mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-17 10:21:52 +02:00
Group handling changes:
Edge case fix in group store where extraneous group buckets are updated so the group can be reused Bug fix for broadcast group in OF-DPA as there can only be one l2flood group per vlan Group operation failure codes are now reported by the provider to the core Group ids are displayed in hex in a couple of places Change-Id: Ib48d21aa96e0400b77999a1b45839c28f678e524
This commit is contained in:
parent
81a61a1fc4
commit
0fd79d91ea
@ -61,7 +61,7 @@ public class DefaultGroupId implements GroupId {
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("id", id)
|
||||
.add("id", "0x" + Integer.toHexString(id))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
@ -576,7 +576,7 @@ public final class Instructions {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type().toString() + SEPARATOR + Integer.toHexString(groupId.id());
|
||||
return type().toString() + SEPARATOR + "0x" + Integer.toHexString(groupId.id());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -31,6 +31,7 @@ public final class GroupOperation {
|
||||
private final GroupId groupId;
|
||||
private final GroupDescription.Type groupType;
|
||||
private final GroupBuckets buckets;
|
||||
private final GroupMsgErrorCode failureCode;
|
||||
|
||||
public enum Type {
|
||||
/**
|
||||
@ -47,6 +48,28 @@ public final class GroupOperation {
|
||||
DELETE
|
||||
}
|
||||
|
||||
/**
|
||||
* Possible error codes for a failure of a group operation.
|
||||
*
|
||||
*/
|
||||
public enum GroupMsgErrorCode {
|
||||
GROUP_EXISTS,
|
||||
INVALID_GROUP,
|
||||
WEIGHT_UNSUPPORTED,
|
||||
OUT_OF_GROUPS,
|
||||
OUT_OF_BUCKETS,
|
||||
CHAINING_UNSUPPORTED,
|
||||
WATCH_UNSUPPORTED,
|
||||
LOOP,
|
||||
UNKNOWN_GROUP,
|
||||
CHAINED_GROUP,
|
||||
BAD_TYPE,
|
||||
BAD_COMMAND,
|
||||
BAD_BUCKET,
|
||||
BAD_WATCH,
|
||||
EPERM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group operation constructor with the parameters.
|
||||
*
|
||||
@ -63,6 +86,23 @@ public final class GroupOperation {
|
||||
this.groupId = checkNotNull(groupId);
|
||||
this.groupType = checkNotNull(groupType);
|
||||
this.buckets = buckets;
|
||||
this.failureCode = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group operation copy-constructor with additional field to set failure code.
|
||||
* Typically used by provider to return information to the core about
|
||||
* the failure reason for a group operation.
|
||||
*
|
||||
* @param groupOp the original group operation
|
||||
* @param failureCode failure code for a failed group operation
|
||||
*/
|
||||
private GroupOperation(GroupOperation groupOp, GroupMsgErrorCode failureCode) {
|
||||
this.opType = groupOp.opType;
|
||||
this.groupId = groupOp.groupId;
|
||||
this.groupType = groupOp.groupType;
|
||||
this.buckets = groupOp.buckets;
|
||||
this.failureCode = failureCode;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,6 +149,12 @@ public final class GroupOperation {
|
||||
|
||||
}
|
||||
|
||||
public static GroupOperation createFailedGroupOperation(GroupOperation groupOperation,
|
||||
GroupMsgErrorCode failureCode) {
|
||||
checkNotNull(groupOperation);
|
||||
return new GroupOperation(groupOperation, failureCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns group operation type.
|
||||
*
|
||||
@ -145,6 +191,15 @@ public final class GroupOperation {
|
||||
return this.buckets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the failure code representing the failure of a group operation.
|
||||
*
|
||||
* @return error code for failure of group operation
|
||||
*/
|
||||
public GroupMsgErrorCode failureCode() {
|
||||
return failureCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
/*
|
||||
* The deviceId, type and buckets are used for hash.
|
||||
|
@ -88,7 +88,8 @@ import static org.onlab.util.Tools.groupedThreads;
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
/**
|
||||
* Manages inventory of group entries using trivial in-memory implementation.
|
||||
* Manages inventory of group entries using distributed group stores from the
|
||||
* storage service.
|
||||
*/
|
||||
@Component(immediate = true)
|
||||
@Service
|
||||
@ -450,16 +451,18 @@ public class DistributedGroupStore
|
||||
matchingExtraneousGroup = getMatchingExtraneousGroupbyId(
|
||||
groupDesc.deviceId(), groupDesc.givenGroupId());
|
||||
if (matchingExtraneousGroup != null) {
|
||||
log.debug("storeGroupDescriptionInternal: Matching extraneous group found in Device {} for group id {}",
|
||||
log.debug("storeGroupDescriptionInternal: Matching extraneous group "
|
||||
+ "found in Device {} for group id 0x{}",
|
||||
groupDesc.deviceId(),
|
||||
groupDesc.givenGroupId());
|
||||
Integer.toHexString(groupDesc.givenGroupId()));
|
||||
//Check if the group buckets matches with user provided buckets
|
||||
if (matchingExtraneousGroup.buckets().equals(groupDesc.buckets())) {
|
||||
//Group is already existing with the same buckets and Id
|
||||
// Create a group entry object
|
||||
log.debug("storeGroupDescriptionInternal: Buckets also matching in Device {} for group id {}",
|
||||
log.debug("storeGroupDescriptionInternal: Buckets also matching "
|
||||
+ "in Device {} for group id 0x{}",
|
||||
groupDesc.deviceId(),
|
||||
groupDesc.givenGroupId());
|
||||
Integer.toHexString(groupDesc.givenGroupId()));
|
||||
StoredGroupEntry group = new DefaultGroup(
|
||||
matchingExtraneousGroup.id(), groupDesc);
|
||||
// Insert the newly created group entry into key and id maps
|
||||
@ -476,10 +479,27 @@ public class DistributedGroupStore
|
||||
} else {
|
||||
//Group buckets are not matching. Update group
|
||||
//with user provided buckets.
|
||||
//TODO
|
||||
log.debug("storeGroupDescriptionInternal: Buckets are not matching in Device {} for group id {}",
|
||||
log.debug("storeGroupDescriptionInternal: Buckets are not "
|
||||
+ "matching in Device {} for group id 0x{}",
|
||||
groupDesc.deviceId(),
|
||||
groupDesc.givenGroupId());
|
||||
Integer.toHexString(groupDesc.givenGroupId()));
|
||||
StoredGroupEntry modifiedGroup = new DefaultGroup(
|
||||
matchingExtraneousGroup.id(), groupDesc);
|
||||
modifiedGroup.setState(GroupState.PENDING_UPDATE);
|
||||
getGroupStoreKeyMap().
|
||||
put(new GroupStoreKeyMapKey(groupDesc.deviceId(),
|
||||
groupDesc.appCookie()), modifiedGroup);
|
||||
// Ensure it also inserted into group id based table to
|
||||
// avoid any chances of duplication in group id generation
|
||||
getGroupIdTable(groupDesc.deviceId()).
|
||||
put(matchingExtraneousGroup.id(), modifiedGroup);
|
||||
removeExtraneousGroupEntry(matchingExtraneousGroup);
|
||||
log.debug("storeGroupDescriptionInternal: Triggering Group "
|
||||
+ "UPDATE request for {} in device {}",
|
||||
matchingExtraneousGroup.id(),
|
||||
groupDesc.deviceId());
|
||||
notifyDelegate(new GroupEvent(Type.GROUP_UPDATE_REQUESTED, modifiedGroup));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -754,7 +774,7 @@ public class DistributedGroupStore
|
||||
GroupEvent event = null;
|
||||
|
||||
if (existing != null) {
|
||||
log.debug("addOrUpdateGroupEntry: updating group entry {} in device {}",
|
||||
log.trace("addOrUpdateGroupEntry: updating group entry {} in device {}",
|
||||
group.id(),
|
||||
group.deviceId());
|
||||
synchronized (existing) {
|
||||
@ -779,7 +799,7 @@ public class DistributedGroupStore
|
||||
existing.setBytes(group.bytes());
|
||||
if ((existing.state() == GroupState.PENDING_ADD) ||
|
||||
(existing.state() == GroupState.PENDING_ADD_RETRY)) {
|
||||
log.debug("addOrUpdateGroupEntry: group entry {} in device {} moving from {} to ADDED",
|
||||
log.trace("addOrUpdateGroupEntry: group entry {} in device {} moving from {} to ADDED",
|
||||
existing.id(),
|
||||
existing.deviceId(),
|
||||
existing.state());
|
||||
@ -787,7 +807,7 @@ public class DistributedGroupStore
|
||||
existing.setIsGroupStateAddedFirstTime(true);
|
||||
event = new GroupEvent(Type.GROUP_ADDED, existing);
|
||||
} else {
|
||||
log.debug("addOrUpdateGroupEntry: group entry {} in device {} moving from {} to ADDED",
|
||||
log.trace("addOrUpdateGroupEntry: group entry {} in device {} moving from {} to ADDED",
|
||||
existing.id(),
|
||||
existing.deviceId(),
|
||||
GroupState.PENDING_UPDATE);
|
||||
@ -911,18 +931,19 @@ public class DistributedGroupStore
|
||||
}
|
||||
|
||||
log.warn("groupOperationFailed: group operation {} failed"
|
||||
+ "for group {} in device {}",
|
||||
+ "for group {} in device {} with code {}",
|
||||
operation.opType(),
|
||||
existing.id(),
|
||||
existing.deviceId());
|
||||
existing.deviceId(),
|
||||
operation.failureCode());
|
||||
if (operation.failureCode() == GroupOperation.GroupMsgErrorCode.GROUP_EXISTS) {
|
||||
log.warn("Current extraneous groups in device:{} are: {}",
|
||||
deviceId,
|
||||
getExtraneousGroups(deviceId));
|
||||
}
|
||||
switch (operation.opType()) {
|
||||
case ADD:
|
||||
if (existing.state() == GroupState.PENDING_ADD) {
|
||||
//TODO: Need to add support for passing the group
|
||||
//operation failure reason from group provider.
|
||||
//If the error type is anything other than GROUP_EXISTS,
|
||||
//then the GROUP_ADD_FAILED event should be raised even
|
||||
//in PENDING_ADD_RETRY state also.
|
||||
notifyDelegate(new GroupEvent(Type.GROUP_ADD_FAILED, existing));
|
||||
log.warn("groupOperationFailed: cleaningup "
|
||||
+ "group {} from store in device {}....",
|
||||
@ -1220,13 +1241,13 @@ public class DistributedGroupStore
|
||||
for (Group group : extraneousStoredEntries) {
|
||||
// there are groups in the extraneous store that
|
||||
// aren't in the switch
|
||||
log.debug("Group AUDIT: clearing extransoeus group {} from store for device {}",
|
||||
log.debug("Group AUDIT: clearing extraneous group {} from store for device {}",
|
||||
group.id(), deviceId);
|
||||
removeExtraneousGroupEntry(group);
|
||||
}
|
||||
|
||||
if (!deviceInitialAuditStatus) {
|
||||
log.debug("Group AUDIT: Setting device {} initial AUDIT completed",
|
||||
log.info("Group AUDIT: Setting device {} initial AUDIT completed",
|
||||
deviceId);
|
||||
deviceInitialAuditCompleted(deviceId, true);
|
||||
}
|
||||
@ -1266,7 +1287,7 @@ public class DistributedGroupStore
|
||||
}
|
||||
|
||||
private void extraneousGroup(Group group) {
|
||||
log.debug("Group {} is on device {} but not in store.",
|
||||
log.trace("Group {} is on device {} but not in store.",
|
||||
group, group.deviceId());
|
||||
addOrUpdateExtraneousGroupEntry(group);
|
||||
}
|
||||
|
@ -556,7 +556,8 @@ public class OFDPA2GroupHandler {
|
||||
}
|
||||
|
||||
// assemble info for l2 flood group
|
||||
Integer l2floodgroupId = L2_FLOOD_TYPE | (vlanId.toShort() << 16) | nextObj.id();
|
||||
// since there can be only one flood group for a vlan, its index is always the same - 0
|
||||
Integer l2floodgroupId = L2_FLOOD_TYPE | (vlanId.toShort() << 16);
|
||||
int l2floodgk = L2_FLOOD_TYPE | nextObj.id() << 12;
|
||||
final GroupKey l2floodgroupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l2floodgk));
|
||||
// collection of group buckets pointing to all the l2 interface groups
|
||||
@ -1007,7 +1008,7 @@ public class OFDPA2GroupHandler {
|
||||
if (gceSet != null) {
|
||||
for (GroupChainElem gce : gceSet) {
|
||||
log.info("Group service {} group key {} in device {}. "
|
||||
+ "Processing next group in group chain with group id {}",
|
||||
+ "Processing next group in group chain with group id 0x{}",
|
||||
(added) ? "ADDED" : "processed",
|
||||
key, deviceId,
|
||||
Integer.toHexString(gce.groupDescription.givenGroupId()));
|
||||
@ -1020,7 +1021,7 @@ public class OFDPA2GroupHandler {
|
||||
pendingNextObjectives.invalidate(key);
|
||||
nextGrpList.forEach(nextGrp -> {
|
||||
log.info("Group service {} group key {} in device:{}. "
|
||||
+ "Done implementing next objective: {} <<-->> gid:{}",
|
||||
+ "Done implementing next objective: {} <<-->> gid:0x{}",
|
||||
(added) ? "ADDED" : "processed",
|
||||
key, deviceId, nextGrp.nextObjective().id(),
|
||||
Integer.toHexString(groupService.getGroup(deviceId, key)
|
||||
@ -1116,7 +1117,6 @@ public class OFDPA2GroupHandler {
|
||||
this.nextObj = nextObj;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public List<Deque<GroupKey>> groupKey() {
|
||||
return gkeys;
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ import org.onosproject.net.group.Group;
|
||||
import org.onosproject.net.group.GroupBuckets;
|
||||
import org.onosproject.net.group.GroupDescription;
|
||||
import org.onosproject.net.group.GroupOperation;
|
||||
import org.onosproject.net.group.GroupOperation.GroupMsgErrorCode;
|
||||
import org.onosproject.net.group.GroupOperations;
|
||||
import org.onosproject.net.group.GroupProvider;
|
||||
import org.onosproject.net.group.GroupProviderRegistry;
|
||||
@ -56,6 +57,7 @@ import org.projectfloodlight.openflow.protocol.OFErrorType;
|
||||
import org.projectfloodlight.openflow.protocol.OFGroupDescStatsEntry;
|
||||
import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
|
||||
import org.projectfloodlight.openflow.protocol.OFGroupMod;
|
||||
import org.projectfloodlight.openflow.protocol.OFGroupModFailedCode;
|
||||
import org.projectfloodlight.openflow.protocol.OFGroupStatsEntry;
|
||||
import org.projectfloodlight.openflow.protocol.OFGroupStatsReply;
|
||||
import org.projectfloodlight.openflow.protocol.OFGroupType;
|
||||
@ -64,6 +66,7 @@ import org.projectfloodlight.openflow.protocol.OFPortStatus;
|
||||
import org.projectfloodlight.openflow.protocol.OFStatsReply;
|
||||
import org.projectfloodlight.openflow.protocol.OFStatsType;
|
||||
import org.projectfloodlight.openflow.protocol.OFVersion;
|
||||
import org.projectfloodlight.openflow.protocol.errormsg.OFGroupModFailedErrorMsg;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
@ -135,7 +138,6 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv
|
||||
|
||||
@Override
|
||||
public void performGroupOperation(DeviceId deviceId, GroupOperations groupOps) {
|
||||
Map<OFGroupMod, OpenFlowSwitch> mods = Maps.newIdentityHashMap();
|
||||
final Dpid dpid = Dpid.dpid(deviceId.uri());
|
||||
OpenFlowSwitch sw = controller.getSwitch(dpid);
|
||||
for (GroupOperation groupOperation: groupOps.operations()) {
|
||||
@ -329,11 +331,17 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv
|
||||
pendingGroupOperations.get(pendingGroupId);
|
||||
DeviceId deviceId = DeviceId.deviceId(Dpid.uri(dpid));
|
||||
if (operation != null) {
|
||||
OFGroupModFailedCode code =
|
||||
((OFGroupModFailedErrorMsg) errorMsg).getCode();
|
||||
GroupMsgErrorCode failureCode =
|
||||
GroupMsgErrorCode.values()[(code.ordinal())];
|
||||
GroupOperation failedOperation = GroupOperation
|
||||
.createFailedGroupOperation(operation, failureCode);
|
||||
providerService.groupOperationFailed(deviceId,
|
||||
operation);
|
||||
failedOperation);
|
||||
pendingGroupOperations.remove(pendingGroupId);
|
||||
pendingXidMaps.remove(pendingGroupId);
|
||||
log.warn("Received an group mod error {}", msg);
|
||||
log.warn("Received a group mod error {}", msg);
|
||||
} else {
|
||||
log.error("Cannot find pending group operation with group ID: {}",
|
||||
pendingGroupId);
|
||||
|
Loading…
x
Reference in New Issue
Block a user