blob: 752ee2d705f63ab09e60bfb24d5155250844fee4 [file] [log] [blame]
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -08001/*
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 */
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070016package org.onosproject.segmentrouting.grouphandler;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080017
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080018import java.util.HashSet;
19import java.util.Set;
20
sangho32a59322015-02-17 12:07:41 -080021import org.onlab.packet.MplsLabel;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080022import org.onosproject.core.ApplicationId;
23import org.onosproject.net.DeviceId;
24import org.onosproject.net.Link;
25import org.onosproject.net.flow.DefaultTrafficTreatment;
26import org.onosproject.net.flow.TrafficTreatment;
sangho834e4b02015-05-01 09:38:25 -070027import org.onosproject.net.flowobjective.DefaultNextObjective;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070028import org.onosproject.net.flowobjective.FlowObjectiveService;
sangho834e4b02015-05-01 09:38:25 -070029import org.onosproject.net.flowobjective.NextObjective;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080030import org.onosproject.net.link.LinkService;
31
32/**
33 * Default ECMP group handler creation module for a transit device.
34 * This component creates a set of ECMP groups for every neighbor
35 * that this device is connected to.
36 * For example, consider a network of 4 devices: D0 (Segment ID: 100),
37 * D1 (Segment ID: 101), D2 (Segment ID: 102) and D3 (Segment ID: 103),
38 * where D0 and D3 are edge devices and D1 and D2 are transit devices.
39 * Assume transit device D1 is connected to 2 neighbors (D0 and D3 ).
40 * The following groups will be created in D1:
41 * 1) all ports to D0 + with no label push,
42 * 2) all ports to D3 + with no label push,
43 */
44public class DefaultTransitGroupHandler extends DefaultGroupHandler {
45
46 protected DefaultTransitGroupHandler(DeviceId deviceId,
47 ApplicationId appId,
48 DeviceProperties config,
49 LinkService linkService,
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070050 FlowObjectiveService flowObjService) {
51 super(deviceId, appId, config, linkService, flowObjService);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080052 }
53
54 @Override
55 public void createGroups() {
56 Set<DeviceId> neighbors = devicePortMap.keySet();
57 if (neighbors == null || neighbors.isEmpty()) {
58 return;
59 }
60
61 // Create all possible Neighbor sets from this router
62 // NOTE: Avoid any pairings of edge routers only
63 Set<Set<DeviceId>> sets = getPowerSetOfNeighbors(neighbors);
64 sets = filterEdgeRouterOnlyPairings(sets);
65 log.debug("createGroupsAtTransitRouter: The size of neighbor powerset "
66 + "for sw {} is {}", deviceId, sets.size());
67 Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
68 for (Set<DeviceId> combo : sets) {
69 if (combo.isEmpty()) {
70 continue;
71 }
72 NeighborSet ns = new NeighborSet(combo);
73 log.debug("createGroupsAtTransitRouter: sw {} combo {} ns {}",
74 deviceId, combo, ns);
75 nsSet.add(ns);
76 }
77 log.debug("createGroupsAtTransitRouter: The neighborset with label "
78 + "for sw {} is {}", deviceId, nsSet);
79
80 createGroupsFromNeighborsets(nsSet);
81 }
82
83 @Override
84 protected void newNeighbor(Link newNeighborLink) {
85 log.debug("New Neighbor: Updating groups for "
86 + "transit device {}", deviceId);
87 // Recompute neighbor power set
88 addNeighborAtPort(newNeighborLink.dst().deviceId(),
89 newNeighborLink.src().port());
90 // Compute new neighbor sets due to the addition of new neighbor
91 Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
92 newNeighborLink.dst().deviceId(),
93 devicePortMap.keySet());
94 createGroupsFromNeighborsets(nsSet);
95 }
96
97 @Override
98 protected void newPortToExistingNeighbor(Link newNeighborLink) {
99 log.debug("New port to existing neighbor: Updating "
100 + "groups for transit device {}", deviceId);
101 addNeighborAtPort(newNeighborLink.dst().deviceId(),
102 newNeighborLink.src().port());
103 Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
104 newNeighborLink.dst().deviceId(),
105 devicePortMap.keySet());
106 for (NeighborSet ns : nsSet) {
107 // Create the new bucket to be updated
108 TrafficTreatment.Builder tBuilder =
109 DefaultTrafficTreatment.builder();
110 tBuilder.setOutput(newNeighborLink.src().port())
111 .setEthDst(deviceConfig.getDeviceMac(
112 newNeighborLink.dst().deviceId()))
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700113 .setEthSrc(nodeMacAddr);
114 if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
115 tBuilder.pushMpls()
116 .setMpls(MplsLabel.
117 mplsLabel(ns.getEdgeLabel()));
118 }
sangho834e4b02015-05-01 09:38:25 -0700119
120
121 Integer nextId = deviceNextObjectiveIds.get(getGroupKey(ns));
122 if (nextId != null) {
123 NextObjective.Builder nextObjBuilder = DefaultNextObjective
124 .builder().withId(nextId)
125 .withType(NextObjective.Type.HASHED).fromApp(appId);
126
127 nextObjBuilder.addTreatment(tBuilder.build());
128
129 NextObjective nextObjective = nextObjBuilder.add();
130 flowObjectiveService.next(deviceId, nextObjective);
131 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800132 }
133 }
134
135 @Override
136 protected Set<NeighborSet> computeImpactedNeighborsetForPortEvent(
137 DeviceId impactedNeighbor,
138 Set<DeviceId> updatedNeighbors) {
139 Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(updatedNeighbors);
140
sanghob35a6192015-04-01 13:05:26 -0700141 Set<DeviceId> tmp = new HashSet<DeviceId>();
142 tmp.addAll(updatedNeighbors);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800143 tmp.remove(impactedNeighbor);
144 Set<Set<DeviceId>> tmpPowerSet = getPowerSetOfNeighbors(tmp);
145
146 // Compute the impacted neighbor sets
147 powerSet.removeAll(tmpPowerSet);
148
149 powerSet = filterEdgeRouterOnlyPairings(powerSet);
150 Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
151 for (Set<DeviceId> combo : powerSet) {
152 if (combo.isEmpty()) {
153 continue;
154 }
155 NeighborSet ns = new NeighborSet(combo);
156 log.debug("createGroupsAtTransitRouter: sw {} combo {} ns {}",
157 deviceId, combo, ns);
158 nsSet.add(ns);
159 }
160 log.debug("computeImpactedNeighborsetForPortEvent: The neighborset with label "
161 + "for sw {} is {}", deviceId, nsSet);
162
163 return nsSet;
164 }
165
166 private Set<Set<DeviceId>> filterEdgeRouterOnlyPairings(Set<Set<DeviceId>> sets) {
167 Set<Set<DeviceId>> fiteredSets = new HashSet<Set<DeviceId>>();
168 for (Set<DeviceId> deviceSubSet : sets) {
169 if (deviceSubSet.size() > 1) {
170 boolean avoidEdgeRouterPairing = true;
171 for (DeviceId device : deviceSubSet) {
172 if (!deviceConfig.isEdgeDevice(device)) {
173 avoidEdgeRouterPairing = false;
174 break;
175 }
176 }
177 if (!avoidEdgeRouterPairing) {
178 fiteredSets.add(deviceSubSet);
179 }
180 } else {
181 fiteredSets.add(deviceSubSet);
182 }
183 }
184 return fiteredSets;
185 }
186}