2  * Copyright 2015 Open Networking Laboratory
 
   4  * Licensed under the Apache License, Version 2.0 (the "License");
 
   5  * you may not use this file except in compliance with the License.
 
   6  * You may obtain a copy of the License at
 
   8  *     http://www.apache.org/licenses/LICENSE-2.0
 
  10  * Unless required by applicable law or agreed to in writing, software
 
  11  * distributed under the License is distributed on an "AS IS" BASIS,
 
  12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  13  * See the License for the specific language governing permissions and
 
  14  * limitations under the License.
 
  16 package org.onosproject.segmentrouting.grouphandler;
 
  18 import java.util.HashSet;
 
  19 import java.util.List;
 
  22 import org.onosproject.core.ApplicationId;
 
  23 import org.onosproject.net.DeviceId;
 
  24 import org.onosproject.net.Link;
 
  25 import org.onosproject.net.flowobjective.FlowObjectiveService;
 
  26 import org.onosproject.net.link.LinkService;
 
  27 import org.onosproject.store.service.EventuallyConsistentMap;
 
  30  * Default ECMP group handler creation module for an edge device.
 
  31  * This component creates a set of ECMP groups for every neighbor
 
  32  * that this device is connected to.
 
  33  * For example, consider a network of 4 devices: D0 (Segment ID: 100),
 
  34  * D1 (Segment ID: 101), D2 (Segment ID: 102) and D3 (Segment ID: 103),
 
  35  * where D0 and D3 are edge devices and D1 and D2 are transit devices.
 
  36  * Assume device D0 is connected to 2 neighbors (D1 and D2 ).
 
  37  * The following groups will be created in D0:
 
  38  * 1) all ports to D1 + with no label push, // direct attach case, seen
 
  39  * 2) all ports to D1 + with label 102 pushed, // this is not needed
 
  40  * 3) all ports to D1 + with label 103 pushed, // maybe needed, sometimes seen
 
  41  * 4) all ports to D2 + with no label push,
 
  42  * 5) all ports to D2 + with label 101 pushed,
 
  43  * 6) all ports to D2 + with label 103 pushed,
 
  44  * 7) all ports to D1 and D2 + with label 103 pushed // ecmp case
 
  45  * 8) what about ecmp no label case
 
  47 public class DefaultEdgeGroupHandler extends DefaultGroupHandler {
 
  49     protected DefaultEdgeGroupHandler(DeviceId deviceId,
 
  51                                   DeviceProperties config,
 
  52                                   LinkService linkService,
 
  53                                   FlowObjectiveService flowObjService,
 
  54                                   EventuallyConsistentMap<
 
  55                                           NeighborSetNextObjectiveStoreKey,
 
  56                                           Integer> nsNextObjStore,
 
  57                                   EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
 
  58                                           Integer> subnetNextObjStore) {
 
  59         super(deviceId, appId, config, linkService, flowObjService,
 
  60               nsNextObjStore, subnetNextObjStore);
 
  64     public void createGroups() {
 
  65         log.debug("Creating default groups "
 
  66                 + "for edge device {}", deviceId);
 
  67         Set<DeviceId> neighbors = devicePortMap.keySet();
 
  68         if (neighbors == null || neighbors.isEmpty()) {
 
  72         // Create all possible Neighbor sets from this router
 
  73         Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(neighbors);
 
  74         log.trace("createGroupsAtEdgeRouter: The size of neighbor powerset "
 
  75                 + "for sw {} is {}", deviceId, powerSet.size());
 
  76         Set<NeighborSet> nsSet = new HashSet<>();
 
  77         for (Set<DeviceId> combo : powerSet) {
 
  78             if (combo.isEmpty()) {
 
  81             List<Integer> groupSegmentIds =
 
  82                     getSegmentIdsTobePairedWithNeighborSet(combo);
 
  83             for (Integer sId : groupSegmentIds) {
 
  84                 NeighborSet ns = new NeighborSet(combo, sId);
 
  85                 log.trace("createGroupsAtEdgeRouter: sw {} "
 
  86                         + "combo {} sId {} ns {}",
 
  87                         deviceId, combo, sId, ns);
 
  91         log.trace("createGroupsAtEdgeRouter: The neighborset "
 
  92                 + "with label for sw {} is {}",
 
  95         createGroupsFromNeighborsets(nsSet);
 
  99     protected void newNeighbor(Link newNeighborLink) {
 
 100         log.debug("New Neighbor: Updating groups "
 
 101                 + "for edge device {}", deviceId);
 
 102         // Recompute neighbor power set
 
 103         addNeighborAtPort(newNeighborLink.dst().deviceId(),
 
 104                           newNeighborLink.src().port());
 
 105         // Compute new neighbor sets due to the addition of new neighbor
 
 106         Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
 
 107                                              newNeighborLink.dst().deviceId(),
 
 108                                              devicePortMap.keySet());
 
 109         createGroupsFromNeighborsets(nsSet);
 
 113     protected void newPortToExistingNeighbor(Link newNeighborLink) {
 
 114         /*log.debug("New port to existing neighbor: Updating "
 
 115                 + "groups for edge device {}", deviceId);
 
 116         addNeighborAtPort(newNeighborLink.dst().deviceId(),
 
 117                           newNeighborLink.src().port());
 
 118         Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
 
 119                                               newNeighborLink.dst().deviceId(),
 
 120                                               devicePortMap.keySet());
 
 121         for (NeighborSet ns : nsSet) {
 
 122             // Create the new bucket to be updated
 
 123             TrafficTreatment.Builder tBuilder =
 
 124                     DefaultTrafficTreatment.builder();
 
 125             tBuilder.setOutput(newNeighborLink.src().port())
 
 126                     .setEthDst(deviceConfig.getDeviceMac(
 
 127                           newNeighborLink.dst().deviceId()))
 
 128                     .setEthSrc(nodeMacAddr);
 
 129             if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
 
 132                                  mplsLabel(ns.getEdgeLabel()));
 
 135             Integer nextId = deviceNextObjectiveIds.get(ns);
 
 136             if (nextId != null) {
 
 137                 NextObjective.Builder nextObjBuilder = DefaultNextObjective
 
 138                         .builder().withId(nextId)
 
 139                         .withType(NextObjective.Type.HASHED).fromApp(appId);
 
 141                 nextObjBuilder.addTreatment(tBuilder.build());
 
 143                 NextObjective nextObjective = nextObjBuilder.add();
 
 144                 flowObjectiveService.next(deviceId, nextObjective);
 
 150     protected Set<NeighborSet> computeImpactedNeighborsetForPortEvent(
 
 151                                             DeviceId impactedNeighbor,
 
 152                                             Set<DeviceId> updatedNeighbors) {
 
 153         Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(updatedNeighbors);
 
 155         Set<DeviceId> tmp = new HashSet<>();
 
 156         tmp.addAll(updatedNeighbors);
 
 157         tmp.remove(impactedNeighbor);
 
 158         Set<Set<DeviceId>> tmpPowerSet = getPowerSetOfNeighbors(tmp);
 
 160         // Compute the impacted neighbor sets
 
 161         powerSet.removeAll(tmpPowerSet);
 
 163         Set<NeighborSet> nsSet = new HashSet<>();
 
 164         for (Set<DeviceId> combo : powerSet) {
 
 165             if (combo.isEmpty()) {
 
 168             List<Integer> groupSegmentIds =
 
 169                     getSegmentIdsTobePairedWithNeighborSet(combo);
 
 170             for (Integer sId : groupSegmentIds) {
 
 171                 NeighborSet ns = new NeighborSet(combo, sId);
 
 172                 log.trace("computeImpactedNeighborsetForPortEvent: sw {} "
 
 173                         + "combo {} sId {} ns {}",
 
 174                         deviceId, combo, sId, ns);
 
 178         log.trace("computeImpactedNeighborsetForPortEvent: The neighborset "
 
 179                 + "with label for sw {} is {}",