c960adcac3d505cafa09f632d9c9579eb02e87b2
[onosfw.git] /
1 /*
2  * Copyright 2015 Open Networking Laboratory
3  *
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package org.onosproject.segmentrouting.grouphandler;
17
18 import java.util.HashSet;
19 import java.util.List;
20 import java.util.Set;
21
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;
28
29 /**
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
46  */
47 public class DefaultEdgeGroupHandler extends DefaultGroupHandler {
48
49     protected DefaultEdgeGroupHandler(DeviceId deviceId,
50                                   ApplicationId appId,
51                                   DeviceProperties config,
52                                   LinkService linkService,
53                                   FlowObjectiveService flowObjService,
54                                   EventuallyConsistentMap<
55                                   NeighborSetNextObjectiveStoreKey,
56                                   Integer> nsNextObjStore) {
57         super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore);
58     }
59
60     @Override
61     public void createGroups() {
62         log.debug("Creating default groups "
63                 + "for edge device {}", deviceId);
64         Set<DeviceId> neighbors = devicePortMap.keySet();
65         if (neighbors == null || neighbors.isEmpty()) {
66             return;
67         }
68
69         // Create all possible Neighbor sets from this router
70         Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(neighbors);
71         log.trace("createGroupsAtEdgeRouter: The size of neighbor powerset "
72                 + "for sw {} is {}", deviceId, powerSet.size());
73         Set<NeighborSet> nsSet = new HashSet<>();
74         for (Set<DeviceId> combo : powerSet) {
75             if (combo.isEmpty()) {
76                 continue;
77             }
78             List<Integer> groupSegmentIds =
79                     getSegmentIdsTobePairedWithNeighborSet(combo);
80             for (Integer sId : groupSegmentIds) {
81                 NeighborSet ns = new NeighborSet(combo, sId);
82                 log.trace("createGroupsAtEdgeRouter: sw {} "
83                         + "combo {} sId {} ns {}",
84                         deviceId, combo, sId, ns);
85                 nsSet.add(ns);
86             }
87         }
88         log.trace("createGroupsAtEdgeRouter: The neighborset "
89                 + "with label for sw {} is {}",
90                 deviceId, nsSet);
91
92         createGroupsFromNeighborsets(nsSet);
93     }
94
95     @Override
96     protected void newNeighbor(Link newNeighborLink) {
97         log.debug("New Neighbor: Updating groups "
98                 + "for edge device {}", deviceId);
99         // Recompute neighbor power set
100         addNeighborAtPort(newNeighborLink.dst().deviceId(),
101                           newNeighborLink.src().port());
102         // Compute new neighbor sets due to the addition of new neighbor
103         Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
104                                              newNeighborLink.dst().deviceId(),
105                                              devicePortMap.keySet());
106         createGroupsFromNeighborsets(nsSet);
107     }
108
109     @Override
110     protected void newPortToExistingNeighbor(Link newNeighborLink) {
111         /*log.debug("New port to existing neighbor: Updating "
112                 + "groups for edge device {}", deviceId);
113         addNeighborAtPort(newNeighborLink.dst().deviceId(),
114                           newNeighborLink.src().port());
115         Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
116                                               newNeighborLink.dst().deviceId(),
117                                               devicePortMap.keySet());
118         for (NeighborSet ns : nsSet) {
119             // Create the new bucket to be updated
120             TrafficTreatment.Builder tBuilder =
121                     DefaultTrafficTreatment.builder();
122             tBuilder.setOutput(newNeighborLink.src().port())
123                     .setEthDst(deviceConfig.getDeviceMac(
124                           newNeighborLink.dst().deviceId()))
125                     .setEthSrc(nodeMacAddr);
126             if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
127                 tBuilder.pushMpls()
128                         .setMpls(MplsLabel.
129                                  mplsLabel(ns.getEdgeLabel()));
130             }
131
132             Integer nextId = deviceNextObjectiveIds.get(ns);
133             if (nextId != null) {
134                 NextObjective.Builder nextObjBuilder = DefaultNextObjective
135                         .builder().withId(nextId)
136                         .withType(NextObjective.Type.HASHED).fromApp(appId);
137
138                 nextObjBuilder.addTreatment(tBuilder.build());
139
140                 NextObjective nextObjective = nextObjBuilder.add();
141                 flowObjectiveService.next(deviceId, nextObjective);
142             }
143         }*/
144     }
145
146     @Override
147     protected Set<NeighborSet> computeImpactedNeighborsetForPortEvent(
148                                             DeviceId impactedNeighbor,
149                                             Set<DeviceId> updatedNeighbors) {
150         Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(updatedNeighbors);
151
152         Set<DeviceId> tmp = new HashSet<>();
153         tmp.addAll(updatedNeighbors);
154         tmp.remove(impactedNeighbor);
155         Set<Set<DeviceId>> tmpPowerSet = getPowerSetOfNeighbors(tmp);
156
157         // Compute the impacted neighbor sets
158         powerSet.removeAll(tmpPowerSet);
159
160         Set<NeighborSet> nsSet = new HashSet<>();
161         for (Set<DeviceId> combo : powerSet) {
162             if (combo.isEmpty()) {
163                 continue;
164             }
165             List<Integer> groupSegmentIds =
166                     getSegmentIdsTobePairedWithNeighborSet(combo);
167             for (Integer sId : groupSegmentIds) {
168                 NeighborSet ns = new NeighborSet(combo, sId);
169                 log.trace("computeImpactedNeighborsetForPortEvent: sw {} "
170                         + "combo {} sId {} ns {}",
171                         deviceId, combo, sId, ns);
172                 nsSet.add(ns);
173             }
174         }
175         log.trace("computeImpactedNeighborsetForPortEvent: The neighborset "
176                 + "with label for sw {} is {}",
177                 deviceId, nsSet);
178         return nsSet;
179     }
180
181 }