a5c1090ff66276ce1cb891a37e1401af67923c98
[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                                   EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
58                                           Integer> subnetNextObjStore) {
59         super(deviceId, appId, config, linkService, flowObjService,
60               nsNextObjStore, subnetNextObjStore);
61     }
62
63     @Override
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()) {
69             return;
70         }
71
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()) {
79                 continue;
80             }
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);
88                 nsSet.add(ns);
89             }
90         }
91         log.trace("createGroupsAtEdgeRouter: The neighborset "
92                 + "with label for sw {} is {}",
93                 deviceId, nsSet);
94
95         createGroupsFromNeighborsets(nsSet);
96     }
97
98     @Override
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);
110     }
111
112     @Override
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) {
130                 tBuilder.pushMpls()
131                         .setMpls(MplsLabel.
132                                  mplsLabel(ns.getEdgeLabel()));
133             }
134
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);
140
141                 nextObjBuilder.addTreatment(tBuilder.build());
142
143                 NextObjective nextObjective = nextObjBuilder.add();
144                 flowObjectiveService.next(deviceId, nextObjective);
145             }
146         }*/
147     }
148
149     @Override
150     protected Set<NeighborSet> computeImpactedNeighborsetForPortEvent(
151                                             DeviceId impactedNeighbor,
152                                             Set<DeviceId> updatedNeighbors) {
153         Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(updatedNeighbors);
154
155         Set<DeviceId> tmp = new HashSet<>();
156         tmp.addAll(updatedNeighbors);
157         tmp.remove(impactedNeighbor);
158         Set<Set<DeviceId>> tmpPowerSet = getPowerSetOfNeighbors(tmp);
159
160         // Compute the impacted neighbor sets
161         powerSet.removeAll(tmpPowerSet);
162
163         Set<NeighborSet> nsSet = new HashSet<>();
164         for (Set<DeviceId> combo : powerSet) {
165             if (combo.isEmpty()) {
166                 continue;
167             }
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);
175                 nsSet.add(ns);
176             }
177         }
178         log.trace("computeImpactedNeighborsetForPortEvent: The neighborset "
179                 + "with label for sw {} is {}",
180                 deviceId, nsSet);
181         return nsSet;
182     }
183
184 }