// Test initial AUDIT process with pending group requests private void testInitialAuditWithPendingGroupRequests(DeviceId deviceId) { PortNumber[] ports1 = {PortNumber.portNumber(31), PortNumber.portNumber(32)}; PortNumber[] ports2 = {PortNumber.portNumber(41), PortNumber.portNumber(42)}; GroupId gId1 = new DefaultGroupId(1); Group group1 = createSouthboundGroupEntry(gId1, Arrays.asList(ports1), 0, deviceId); GroupId gId2 = new DefaultGroupId(2); // Non zero reference count will make the group manager to queue // the extraneous groups until reference count is zero. Group group2 = createSouthboundGroupEntry(gId2, Arrays.asList(ports2), 2, deviceId); List<Group> groupEntries = Arrays.asList(group1, group2); providerService.pushGroupMetrics(deviceId, groupEntries); // First group metrics would trigger the device audit completion // post which all pending group requests are also executed. GroupKey key = new DefaultGroupKey("group1BeforeAudit".getBytes()); Group createdGroup = groupService.getGroup(deviceId, key); int createdGroupId = createdGroup.id().id(); assertNotEquals(gId1.id(), createdGroupId); assertNotEquals(gId2.id(), createdGroupId); List<GroupOperation> expectedGroupOps = Arrays.asList( GroupOperation.createDeleteGroupOperation(gId1, Group.Type.SELECT), GroupOperation.createAddGroupOperation( createdGroup.id(), Group.Type.SELECT, createdGroup.buckets())); if (deviceId.equals(DID)) { internalProvider.validate(deviceId, expectedGroupOps); } else { this.validate(deviceId, expectedGroupOps); } }
// Test AUDIT with confirmed groups private void testAuditWithConfirmedGroups(DeviceId deviceId) { GroupKey key = new DefaultGroupKey("group1BeforeAudit".getBytes()); Group createdGroup = groupService.getGroup(deviceId, key); createdGroup = new DefaultGroup(createdGroup.id(), deviceId, Group.Type.SELECT, createdGroup.buckets()); List<Group> groupEntries = Collections.singletonList(createdGroup); providerService.pushGroupMetrics(deviceId, groupEntries); internalListener.validateEvent(Collections.singletonList(GroupEvent.Type.GROUP_ADDED)); }
// Test group remove operations private void testRemoveGroup(DeviceId deviceId) { GroupKey currKey = new DefaultGroupKey("group1RemoveBuckets".getBytes()); Group existingGroup = groupService.getGroup(deviceId, currKey); groupService.removeGroup(deviceId, currKey, appId); List<GroupOperation> expectedGroupOps = Collections.singletonList( GroupOperation.createDeleteGroupOperation(existingGroup.id(), Group.Type.SELECT)); if (deviceId.equals(DID)) { internalProvider.validate(deviceId, expectedGroupOps); } else { this.validate(deviceId, expectedGroupOps); } List<Group> groupEntries = Collections.emptyList(); providerService.pushGroupMetrics(deviceId, groupEntries); internalListener.validateEvent(Collections.singletonList(GroupEvent.Type.GROUP_REMOVED)); }
private void processMulticastRule(ForwardingObjective fwd) { if (fwd.nextId() == null) { log.error("Multicast objective does not have a next id"); fail(fwd, ObjectiveError.BADPARAMS); } OLTPipelineGroup next = getGroupForNextObjective(fwd.nextId()); if (next == null) { log.error("Group for forwarding objective missing: {}", fwd); fail(fwd, ObjectiveError.GROUPMISSING); } Group group = groupService.getGroup(deviceId, next.key()); TrafficTreatment treatment = buildTreatment(Instructions.createGroup(group.id())); FlowRule rule = DefaultFlowRule.builder() .forDevice(deviceId) .forTable(0) .fromApp(fwd.appId()) .makePermanent() .withPriority(fwd.priority()) .withSelector(fwd.selector()) .withTreatment(treatment) .build(); FlowRuleOperations.Builder builder = FlowRuleOperations.builder(); switch (fwd.op()) { case ADD: builder.add(rule); break; case REMOVE: builder.remove(rule); break; case ADD_TO_EXISTING: case REMOVE_FROM_EXISTING: break; default: log.warn("Unknown forwarding operation: {}", fwd.op()); } applyFlowRules(builder, fwd); }
// Test group add bucket operations private void testAddBuckets(DeviceId deviceId) { GroupKey addKey = new DefaultGroupKey("group1AddBuckets".getBytes()); GroupKey prevKey = new DefaultGroupKey("group1BeforeAudit".getBytes()); Group createdGroup = groupService.getGroup(deviceId, prevKey); List<GroupBucket> buckets = new ArrayList<>(); buckets.addAll(createdGroup.buckets().buckets()); PortNumber[] addPorts = {PortNumber.portNumber(51), PortNumber.portNumber(52)}; List<PortNumber> outPorts; outPorts = new ArrayList<>(); outPorts.addAll(Arrays.asList(addPorts)); List<GroupBucket> addBuckets; addBuckets = new ArrayList<>(); for (PortNumber portNumber : outPorts) { TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); tBuilder .setOutput(portNumber) .setEthDst(MacAddress.valueOf("00:00:00:00:00:02")) .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01")) .pushMpls() .setMpls(MplsLabel.mplsLabel(106)); addBuckets.add(DefaultGroupBucket.createSelectGroupBucket(tBuilder.build())); buckets.add(DefaultGroupBucket.createSelectGroupBucket(tBuilder.build())); } GroupBuckets groupAddBuckets = new GroupBuckets(addBuckets); groupService.addBucketsToGroup(deviceId, prevKey, groupAddBuckets, addKey, appId); GroupBuckets updatedBuckets = new GroupBuckets(buckets); List<GroupOperation> expectedGroupOps = Collections.singletonList( GroupOperation.createModifyGroupOperation( createdGroup.id(), Group.Type.SELECT, updatedBuckets)); if (deviceId.equals(DID)) { internalProvider.validate(deviceId, expectedGroupOps); } else { this.validate(deviceId, expectedGroupOps); } Group existingGroup = groupService.getGroup(deviceId, addKey); List<Group> groupEntries = Collections.singletonList(existingGroup); providerService.pushGroupMetrics(deviceId, groupEntries); internalListener.validateEvent(Collections.singletonList(GroupEvent.Type.GROUP_UPDATED)); }
// Test AUDIT process with extraneous groups and missing groups private void testAuditWithExtraneousMissingGroups(DeviceId deviceId) { PortNumber[] ports1 = {PortNumber.portNumber(31), PortNumber.portNumber(32)}; PortNumber[] ports2 = {PortNumber.portNumber(41), PortNumber.portNumber(42)}; GroupId gId1 = new DefaultGroupId(1); Group group1 = createSouthboundGroupEntry(gId1, Arrays.asList(ports1), 0, deviceId); GroupId gId2 = new DefaultGroupId(2); Group group2 = createSouthboundGroupEntry(gId2, Arrays.asList(ports2), 0, deviceId); List<Group> groupEntries = Arrays.asList(group1, group2); providerService.pushGroupMetrics(deviceId, groupEntries); GroupKey key = new DefaultGroupKey("group1BeforeAudit".getBytes()); Group createdGroup = groupService.getGroup(deviceId, key); List<GroupOperation> expectedGroupOps = Arrays.asList( GroupOperation.createDeleteGroupOperation(gId1, Group.Type.SELECT), GroupOperation.createDeleteGroupOperation(gId2, Group.Type.SELECT), GroupOperation.createAddGroupOperation( createdGroup.id(), Group.Type.SELECT, createdGroup.buckets())); if (deviceId.equals(DID)) { internalProvider.validate(deviceId, expectedGroupOps); } else { this.validate(deviceId, expectedGroupOps); } }
@Override // Dell switches need ETH_DST based match condition in all IP table entries. // So this method overrides the default spring-open behavior and adds // ETH_DST match condition while pushing IP table flow rules protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) { log.debug("Processing specific"); TrafficSelector selector = fwd.selector(); EthTypeCriterion ethType = (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); if ((ethType == null) || ((((short) ethType.ethType()) != Ethernet.TYPE_IPV4) && (((short) ethType.ethType()) != Ethernet.MPLS_UNICAST))) { log.debug("processSpecific: Unsupported " + "forwarding objective criteraia"); fail(fwd, ObjectiveError.UNSUPPORTED); return Collections.emptySet(); } TrafficSelector.Builder filteredSelectorBuilder = DefaultTrafficSelector.builder(); int forTableId = -1; if (((short) ethType.ethType()) == Ethernet.TYPE_IPV4) { if (deviceTMac == null) { log.debug( "processSpecific: ETH_DST filtering " + "objective is not set which is required " + "before sending a IPv4 forwarding objective"); // TODO: Map the error to more appropriate error code. fail(fwd, ObjectiveError.DEVICEMISSING); return Collections.emptySet(); } filteredSelectorBuilder = filteredSelectorBuilder .matchEthType(Ethernet.TYPE_IPV4) .matchEthDst(deviceTMac) .matchIPDst(((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip()); forTableId = ipv4UnicastTableId; log.debug("processing IPv4 specific forwarding objective"); } else { filteredSelectorBuilder = filteredSelectorBuilder .matchEthType(Ethernet.MPLS_UNICAST) .matchMplsLabel( ((MplsCriterion) selector.getCriterion(Criterion.Type.MPLS_LABEL)).label()); // TODO: Add Match for BoS // if (selector.getCriterion(Criterion.Type.MPLS_BOS) != null) { // } forTableId = mplsTableId; log.debug("processing MPLS specific forwarding objective"); } TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder(); if (fwd.treatment() != null) { for (Instruction i : fwd.treatment().allInstructions()) { treatmentBuilder.add(i); } } if (fwd.nextId() != null) { NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); if (next != null) { GroupKey key = appKryo.deserialize(next.data()); Group group = groupService.getGroup(deviceId, key); if (group == null) { log.warn("The group left!"); fail(fwd, ObjectiveError.GROUPMISSING); return Collections.emptySet(); } treatmentBuilder.group(group.id()); log.debug("Adding OUTGROUP action"); } else { log.warn("processSpecific: No associated next objective object"); fail(fwd, ObjectiveError.GROUPMISSING); return Collections.emptySet(); } } TrafficSelector filteredSelector = filteredSelectorBuilder.build(); TrafficTreatment treatment = treatmentBuilder.transition(aclTableId).build(); FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() .fromApp(fwd.appId()) .withPriority(fwd.priority()) .forDevice(deviceId) .withSelector(filteredSelector) .withTreatment(treatment); if (fwd.permanent()) { ruleBuilder.makePermanent(); } else { ruleBuilder.makeTemporary(fwd.timeout()); } ruleBuilder.forTable(forTableId); return Collections.singletonList(ruleBuilder.build()); }
@Override public int compare(Group g1, Group g2) { return Long.valueOf(g1.id().id()).compareTo(Long.valueOf(g2.id().id())); }
private void groupOperationFaliure(DeviceId deviceId) { PortNumber[] ports1 = {PortNumber.portNumber(31), PortNumber.portNumber(32)}; PortNumber[] ports2 = {PortNumber.portNumber(41), PortNumber.portNumber(42)}; // Test Group creation before AUDIT process GroupKey key = new DefaultGroupKey("group1BeforeAudit".getBytes()); List<GroupBucket> buckets = new ArrayList<>(); List<PortNumber> outPorts = new ArrayList<>(); outPorts.addAll(Arrays.asList(ports1)); outPorts.addAll(Arrays.asList(ports2)); for (PortNumber portNumber : outPorts) { TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); tBuilder .setOutput(portNumber) .setEthDst(MacAddress.valueOf("00:00:00:00:00:02")) .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01")) .pushMpls() .setMpls(MplsLabel.mplsLabel(106)); buckets.add(DefaultGroupBucket.createSelectGroupBucket(tBuilder.build())); } GroupBuckets groupBuckets = new GroupBuckets(buckets); GroupDescription newGroupDesc = new DefaultGroupDescription(deviceId, Group.Type.SELECT, groupBuckets, key, null, appId); groupService.addGroup(newGroupDesc); // Test initial group audit process GroupId gId1 = new DefaultGroupId(1); Group group1 = createSouthboundGroupEntry(gId1, Arrays.asList(ports1), 0, deviceId); GroupId gId2 = new DefaultGroupId(2); // Non zero reference count will make the group manager to queue // the extraneous groups until reference count is zero. Group group2 = createSouthboundGroupEntry(gId2, Arrays.asList(ports2), 2, deviceId); List<Group> groupEntries = Arrays.asList(group1, group2); providerService.pushGroupMetrics(deviceId, groupEntries); Group createdGroup = groupService.getGroup(deviceId, key); // Group Add failure test GroupOperation groupAddOp = GroupOperation.createAddGroupOperation( createdGroup.id(), createdGroup.type(), createdGroup.buckets()); providerService.groupOperationFailed(deviceId, groupAddOp); internalListener.validateEvent(Collections.singletonList(GroupEvent.Type.GROUP_ADD_FAILED)); // Group Mod failure test groupService.addGroup(newGroupDesc); createdGroup = groupService.getGroup(deviceId, key); assertNotNull(createdGroup); GroupOperation groupModOp = GroupOperation.createModifyGroupOperation( createdGroup.id(), createdGroup.type(), createdGroup.buckets()); providerService.groupOperationFailed(deviceId, groupModOp); internalListener.validateEvent(Collections.singletonList(GroupEvent.Type.GROUP_UPDATE_FAILED)); // Group Delete failure test groupService.addGroup(newGroupDesc); createdGroup = groupService.getGroup(deviceId, key); assertNotNull(createdGroup); GroupOperation groupDelOp = GroupOperation.createDeleteGroupOperation(createdGroup.id(), createdGroup.type()); providerService.groupOperationFailed(deviceId, groupDelOp); internalListener.validateEvent(Collections.singletonList(GroupEvent.Type.GROUP_REMOVE_FAILED)); }
@Override public void notify(GroupEvent event) { final Group group = event.subject(); GroupProvider groupProvider = getProvider(group.deviceId()); GroupOperations groupOps = null; switch (event.type()) { case GROUP_ADD_REQUESTED: log.debug("GROUP_ADD_REQUESTED for Group {} on device {}", group.id(), group.deviceId()); GroupOperation groupAddOp = GroupOperation.createAddGroupOperation(group.id(), group.type(), group.buckets()); groupOps = new GroupOperations(Collections.singletonList(groupAddOp)); groupProvider.performGroupOperation(group.deviceId(), groupOps); break; case GROUP_UPDATE_REQUESTED: log.debug( "GROUP_UPDATE_REQUESTED for Group {} on device {}", group.id(), group.deviceId()); GroupOperation groupModifyOp = GroupOperation.createModifyGroupOperation(group.id(), group.type(), group.buckets()); groupOps = new GroupOperations(Collections.singletonList(groupModifyOp)); groupProvider.performGroupOperation(group.deviceId(), groupOps); break; case GROUP_REMOVE_REQUESTED: log.debug( "GROUP_REMOVE_REQUESTED for Group {} on device {}", group.id(), group.deviceId()); GroupOperation groupDeleteOp = GroupOperation.createDeleteGroupOperation(group.id(), group.type()); groupOps = new GroupOperations(Collections.singletonList(groupDeleteOp)); groupProvider.performGroupOperation(group.deviceId(), groupOps); break; case GROUP_ADDED: case GROUP_UPDATED: case GROUP_REMOVED: case GROUP_ADD_FAILED: case GROUP_UPDATE_FAILED: case GROUP_REMOVE_FAILED: post(event); break; default: break; } }