// 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);
   }
 }
Exemple #7
0
    @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;
      }
    }
  @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));
  }