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.segmentrouting.config.DeviceProperties;
28 import org.onosproject.store.service.EventuallyConsistentMap;
31 * Default ECMP group handler creation module for an edge device.
32 * This component creates a set of ECMP groups for every neighbor
33 * that this device is connected to.
34 * For example, consider a network of 4 devices: D0 (Segment ID: 100),
35 * D1 (Segment ID: 101), D2 (Segment ID: 102) and D3 (Segment ID: 103),
36 * where D0 and D3 are edge devices and D1 and D2 are transit devices.
37 * Assume device D0 is connected to 2 neighbors (D1 and D2 ).
38 * The following groups will be created in D0:
39 * 1) all ports to D1 + with no label push, // direct attach case, seen
40 * 2) all ports to D1 + with label 102 pushed, // this is not needed
41 * 3) all ports to D1 + with label 103 pushed, // maybe needed, sometimes seen
42 * 4) all ports to D2 + with no label push,
43 * 5) all ports to D2 + with label 101 pushed,
44 * 6) all ports to D2 + with label 103 pushed,
45 * 7) all ports to D1 and D2 + with label 103 pushed // ecmp case
46 * 8) what about ecmp no label case
48 public class DefaultEdgeGroupHandler extends DefaultGroupHandler {
50 protected DefaultEdgeGroupHandler(DeviceId deviceId,
52 DeviceProperties config,
53 LinkService linkService,
54 FlowObjectiveService flowObjService,
55 EventuallyConsistentMap<
56 NeighborSetNextObjectiveStoreKey,
57 Integer> nsNextObjStore,
58 EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
59 Integer> subnetNextObjStore) {
60 super(deviceId, appId, config, linkService, flowObjService,
61 nsNextObjStore, subnetNextObjStore);
65 public void createGroups() {
66 log.debug("Creating default groups "
67 + "for edge device {}", deviceId);
68 Set<DeviceId> neighbors = devicePortMap.keySet();
69 if (neighbors == null || neighbors.isEmpty()) {
73 // Create all possible Neighbor sets from this router
74 Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(neighbors);
75 log.trace("createGroupsAtEdgeRouter: The size of neighbor powerset "
76 + "for sw {} is {}", deviceId, powerSet.size());
77 Set<NeighborSet> nsSet = new HashSet<>();
78 for (Set<DeviceId> combo : powerSet) {
79 if (combo.isEmpty()) {
82 List<Integer> groupSegmentIds =
83 getSegmentIdsTobePairedWithNeighborSet(combo);
84 for (Integer sId : groupSegmentIds) {
85 NeighborSet ns = new NeighborSet(combo, sId);
86 log.trace("createGroupsAtEdgeRouter: sw {} "
87 + "combo {} sId {} ns {}",
88 deviceId, combo, sId, ns);
92 log.trace("createGroupsAtEdgeRouter: The neighborset "
93 + "with label for sw {} is {}",
96 //createGroupsFromNeighborsets(nsSet);
100 protected void newNeighbor(Link newNeighborLink) {
101 log.debug("New Neighbor: Updating groups "
102 + "for edge device {}", deviceId);
103 // Recompute neighbor power set
104 addNeighborAtPort(newNeighborLink.dst().deviceId(),
105 newNeighborLink.src().port());
106 // Compute new neighbor sets due to the addition of new neighbor
107 Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
108 newNeighborLink.dst().deviceId(),
109 devicePortMap.keySet());
110 //createGroupsFromNeighborsets(nsSet);
114 protected void newPortToExistingNeighbor(Link newNeighborLink) {
115 /*log.debug("New port to existing neighbor: Updating "
116 + "groups for edge device {}", deviceId);
117 addNeighborAtPort(newNeighborLink.dst().deviceId(),
118 newNeighborLink.src().port());
119 Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
120 newNeighborLink.dst().deviceId(),
121 devicePortMap.keySet());
122 for (NeighborSet ns : nsSet) {
123 // Create the new bucket to be updated
124 TrafficTreatment.Builder tBuilder =
125 DefaultTrafficTreatment.builder();
126 tBuilder.setOutput(newNeighborLink.src().port())
127 .setEthDst(deviceConfig.getDeviceMac(
128 newNeighborLink.dst().deviceId()))
129 .setEthSrc(nodeMacAddr);
130 if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
133 mplsLabel(ns.getEdgeLabel()));
136 Integer nextId = deviceNextObjectiveIds.get(ns);
137 if (nextId != null) {
138 NextObjective.Builder nextObjBuilder = DefaultNextObjective
139 .builder().withId(nextId)
140 .withType(NextObjective.Type.HASHED).fromApp(appId);
142 nextObjBuilder.addTreatment(tBuilder.build());
144 NextObjective nextObjective = nextObjBuilder.add();
145 flowObjectiveService.next(deviceId, nextObjective);
151 protected Set<NeighborSet> computeImpactedNeighborsetForPortEvent(
152 DeviceId impactedNeighbor,
153 Set<DeviceId> updatedNeighbors) {
154 Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(updatedNeighbors);
156 Set<DeviceId> tmp = new HashSet<>();
157 tmp.addAll(updatedNeighbors);
158 tmp.remove(impactedNeighbor);
159 Set<Set<DeviceId>> tmpPowerSet = getPowerSetOfNeighbors(tmp);
161 // Compute the impacted neighbor sets
162 powerSet.removeAll(tmpPowerSet);
164 Set<NeighborSet> nsSet = new HashSet<>();
165 for (Set<DeviceId> combo : powerSet) {
166 if (combo.isEmpty()) {
169 List<Integer> groupSegmentIds =
170 getSegmentIdsTobePairedWithNeighborSet(combo);
171 for (Integer sId : groupSegmentIds) {
172 NeighborSet ns = new NeighborSet(combo, sId);
173 log.trace("computeImpactedNeighborsetForPortEvent: sw {} "
174 + "combo {} sId {} ns {}",
175 deviceId, combo, sId, ns);
179 log.trace("computeImpactedNeighborsetForPortEvent: The neighborset "
180 + "with label for sw {} is {}",