blob: a43a0f096519fc67518241d4dcc7bf9e71d1fdc0 [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
18import static com.google.common.base.Preconditions.checkNotNull;
19import static org.slf4j.LoggerFactory.getLogger;
20
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070021import java.net.URI;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080022import java.util.ArrayList;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070023import java.util.Collections;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080024import java.util.HashMap;
25import java.util.HashSet;
26import java.util.List;
sangho1e575652015-05-14 00:39:53 -070027import java.util.Map;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070028import java.util.Random;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080029import java.util.Set;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070030import java.util.stream.Collectors;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080031
32import org.onlab.packet.MacAddress;
sangho32a59322015-02-17 12:07:41 -080033import org.onlab.packet.MplsLabel;
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070034import org.onlab.util.KryoNamespace;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080035import org.onosproject.core.ApplicationId;
36import org.onosproject.net.DeviceId;
37import org.onosproject.net.Link;
38import org.onosproject.net.PortNumber;
39import org.onosproject.net.flow.DefaultTrafficTreatment;
40import org.onosproject.net.flow.TrafficTreatment;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070041import org.onosproject.net.flowobjective.DefaultNextObjective;
42import org.onosproject.net.flowobjective.FlowObjectiveService;
43import org.onosproject.net.flowobjective.NextObjective;
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -070044import org.onosproject.net.flowobjective.Objective;
45import org.onosproject.net.flowobjective.ObjectiveContext;
46import org.onosproject.net.flowobjective.ObjectiveError;
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070047import org.onosproject.net.group.DefaultGroupKey;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080048import org.onosproject.net.group.GroupKey;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080049import org.onosproject.net.link.LinkService;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070050import org.onosproject.store.service.EventuallyConsistentMap;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080051import org.slf4j.Logger;
52
53/**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070054 * Default ECMP group handler creation module. This component creates a set of
55 * ECMP groups for every neighbor that this device is connected to based on
56 * whether the current device is an edge device or a transit device.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080057 */
58public class DefaultGroupHandler {
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -070059 protected static final Logger log = getLogger(DefaultGroupHandler.class);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080060
61 protected final DeviceId deviceId;
62 protected final ApplicationId appId;
63 protected final DeviceProperties deviceConfig;
64 protected final List<Integer> allSegmentIds;
65 protected final int nodeSegmentId;
66 protected final boolean isEdgeRouter;
67 protected final MacAddress nodeMacAddr;
68 protected LinkService linkService;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070069 protected FlowObjectiveService flowObjectiveService;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080070
Thomas Vachuska6cdbdd82015-05-15 09:10:58 -070071 protected HashMap<DeviceId, Set<PortNumber>> devicePortMap = new HashMap<>();
72 protected HashMap<PortNumber, DeviceId> portDeviceMap = new HashMap<>();
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070073 //protected HashMap<NeighborSet, Integer> deviceNextObjectiveIds =
74 // new HashMap<NeighborSet, Integer>();
75 protected EventuallyConsistentMap<
76 NeighborSetNextObjectiveStoreKey, Integer> nsNextObjStore = null;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070077 protected Random rand = new Random();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080078
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070079 protected KryoNamespace.Builder kryo = new KryoNamespace.Builder()
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070080 .register(URI.class).register(HashSet.class)
81 .register(DeviceId.class).register(PortNumber.class)
82 .register(NeighborSet.class).register(PolicyGroupIdentifier.class)
83 .register(PolicyGroupParams.class)
84 .register(GroupBucketIdentifier.class)
85 .register(GroupBucketIdentifier.BucketOutputType.class);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080086
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070087 protected DefaultGroupHandler(DeviceId deviceId, ApplicationId appId,
88 DeviceProperties config,
89 LinkService linkService,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070090 FlowObjectiveService flowObjService,
91 EventuallyConsistentMap<
92 NeighborSetNextObjectiveStoreKey,
93 Integer> nsNextObjStore) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080094 this.deviceId = checkNotNull(deviceId);
95 this.appId = checkNotNull(appId);
96 this.deviceConfig = checkNotNull(config);
97 this.linkService = checkNotNull(linkService);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080098 allSegmentIds = checkNotNull(config.getAllDeviceSegmentIds());
99 nodeSegmentId = config.getSegmentId(deviceId);
100 isEdgeRouter = config.isEdgeDevice(deviceId);
101 nodeMacAddr = checkNotNull(config.getDeviceMac(deviceId));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700102 this.flowObjectiveService = flowObjService;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700103 this.nsNextObjStore = nsNextObjStore;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800104
105 populateNeighborMaps();
106 }
107
108 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700109 * Creates a group handler object based on the type of device. If device is
110 * of edge type it returns edge group handler, else it returns transit group
111 * handler.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800112 *
113 * @param deviceId device identifier
114 * @param appId application identifier
115 * @param config interface to retrieve the device properties
116 * @param linkService link service object
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700117 * @param flowObjService flow objective service object
Thomas Vachuska6cdbdd82015-05-15 09:10:58 -0700118 * @param nsNextObjStore next objective store map
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800119 * @return default group handler type
120 */
121 public static DefaultGroupHandler createGroupHandler(DeviceId deviceId,
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700122 ApplicationId appId,
123 DeviceProperties config,
124 LinkService linkService,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700125 FlowObjectiveService flowObjService,
Thomas Vachuska6cdbdd82015-05-15 09:10:58 -0700126 EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
127 Integer> nsNextObjStore) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800128 if (config.isEdgeDevice(deviceId)) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700129 return new DefaultEdgeGroupHandler(deviceId, appId, config,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700130 linkService,
131 flowObjService,
132 nsNextObjStore);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800133 } else {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700134 return new DefaultTransitGroupHandler(deviceId, appId, config,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700135 linkService,
136 flowObjService,
137 nsNextObjStore);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800138 }
139 }
140
141 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700142 * Creates the auto created groups for this device based on the current
143 * snapshot of the topology.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800144 */
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700145 // Empty implementations to be overridden by derived classes
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800146 public void createGroups() {
147 }
148
149 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700150 * Performs group creation or update procedures when a new link is
151 * discovered on this device.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800152 *
153 * @param newLink new neighbor link
154 */
155 public void linkUp(Link newLink) {
sanghob35a6192015-04-01 13:05:26 -0700156
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800157 if (newLink.type() != Link.Type.DIRECT) {
158 log.warn("linkUp: unknown link type");
159 return;
160 }
161
162 if (!newLink.src().deviceId().equals(deviceId)) {
163 log.warn("linkUp: deviceId{} doesn't match with link src{}",
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700164 deviceId, newLink.src().deviceId());
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800165 return;
166 }
167
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700168 log.debug("Device {} linkUp at local port {} to neighbor {}", deviceId,
169 newLink.src().port(), newLink.dst().deviceId());
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700170 addNeighborAtPort(newLink.dst().deviceId(),
171 newLink.src().port());
172 /*if (devicePortMap.get(newLink.dst().deviceId()) == null) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800173 // New Neighbor
174 newNeighbor(newLink);
175 } else {
176 // Old Neighbor
177 newPortToExistingNeighbor(newLink);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700178 }*/
179 Set<NeighborSet> nsSet = nsNextObjStore.keySet()
180 .stream()
181 .filter((nsStoreEntry) -> (nsStoreEntry.deviceId().equals(deviceId)))
182 .map((nsStoreEntry) -> (nsStoreEntry.neighborSet()))
183 .filter((ns) -> (ns.getDeviceIds()
184 .contains(newLink.dst().deviceId())))
185 .collect(Collectors.toSet());
186 log.trace("linkUp: nsNextObjStore contents for device {}:",
sangho0b2b6d12015-05-20 22:16:38 -0700187 deviceId,
188 nsSet);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700189 for (NeighborSet ns : nsSet) {
190 // Create the new bucket to be updated
191 TrafficTreatment.Builder tBuilder =
192 DefaultTrafficTreatment.builder();
193 tBuilder.setOutput(newLink.src().port())
194 .setEthDst(deviceConfig.getDeviceMac(
195 newLink.dst().deviceId()))
196 .setEthSrc(nodeMacAddr);
197 if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
198 tBuilder.pushMpls()
199 .setMpls(MplsLabel.
200 mplsLabel(ns.getEdgeLabel()));
201 }
202
203 Integer nextId = nsNextObjStore.
204 get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
205 if (nextId != null) {
206 NextObjective.Builder nextObjBuilder = DefaultNextObjective
207 .builder().withId(nextId)
208 .withType(NextObjective.Type.HASHED).fromApp(appId);
209
210 nextObjBuilder.addTreatment(tBuilder.build());
211
212 log.debug("linkUp in device {}: Adding Bucket "
213 + "with Port {} to next object id {}",
214 deviceId,
215 newLink.src().port(),
216 nextId);
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700217 NextObjective nextObjective = nextObjBuilder.
218 add(new SRNextObjectiveContext(deviceId));
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700219 flowObjectiveService.next(deviceId, nextObjective);
220 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800221 }
222 }
223
224 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700225 * Performs group recovery procedures when a port goes down on this device.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800226 *
227 * @param port port number that has gone down
228 */
229 public void portDown(PortNumber port) {
230 if (portDeviceMap.get(port) == null) {
231 log.warn("portDown: unknown port");
232 return;
233 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700234 log.debug("Device {} portDown {} to neighbor {}", deviceId, port,
235 portDeviceMap.get(port));
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700236 /*Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(portDeviceMap
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700237 .get(port),
238 devicePortMap
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700239 .keySet());*/
240 Set<NeighborSet> nsSet = nsNextObjStore.keySet()
241 .stream()
242 .filter((nsStoreEntry) -> (nsStoreEntry.deviceId().equals(deviceId)))
243 .map((nsStoreEntry) -> (nsStoreEntry.neighborSet()))
244 .filter((ns) -> (ns.getDeviceIds()
245 .contains(portDeviceMap.get(port))))
246 .collect(Collectors.toSet());
247 log.trace("portDown: nsNextObjStore contents for device {}:",
248 deviceId,
249 nsSet);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800250 for (NeighborSet ns : nsSet) {
251 // Create the bucket to be removed
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700252 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
253 .builder();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800254 tBuilder.setOutput(port)
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700255 .setEthDst(deviceConfig.getDeviceMac(portDeviceMap
256 .get(port))).setEthSrc(nodeMacAddr);
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700257 if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700258 tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns
259 .getEdgeLabel()));
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700260 }
sangho834e4b02015-05-01 09:38:25 -0700261
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700262 Integer nextId = nsNextObjStore.
263 get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
sangho834e4b02015-05-01 09:38:25 -0700264 if (nextId != null) {
265 NextObjective.Builder nextObjBuilder = DefaultNextObjective
266 .builder().withType(NextObjective.Type.SIMPLE).withId(nextId).fromApp(appId);
267
268 nextObjBuilder.addTreatment(tBuilder.build());
269
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700270 log.debug("portDown in device {}: Removing Bucket "
271 + "with Port {} to next object id {}",
272 deviceId,
273 port,
274 nextId);
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700275 NextObjective nextObjective = nextObjBuilder.
276 remove(new SRNextObjectiveContext(deviceId));
sangho834e4b02015-05-01 09:38:25 -0700277
278 flowObjectiveService.next(deviceId, nextObjective);
279 }
280
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800281 }
282
283 devicePortMap.get(portDeviceMap.get(port)).remove(port);
284 portDeviceMap.remove(port);
285 }
286
287 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700288 * Returns the next objective associated with the neighborset.
289 * If there is no next objective for this neighborset, this API
290 * would create a next objective and return.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800291 *
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700292 * @param ns neighborset
293 * @return int if found or -1
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800294 */
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700295 public int getNextObjectiveId(NeighborSet ns) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700296 Integer nextId = nsNextObjStore.
297 get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700298 if (nextId == null) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700299 log.trace("getNextObjectiveId in device{}: Next objective id "
300 + "not found for {} and creating", deviceId, ns);
301 log.trace("getNextObjectiveId: nsNextObjStore contents for device {}: {}",
302 deviceId,
303 nsNextObjStore.entrySet()
304 .stream()
305 .filter((nsStoreEntry) ->
306 (nsStoreEntry.getKey().deviceId().equals(deviceId)))
307 .collect(Collectors.toList()));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700308 createGroupsFromNeighborsets(Collections.singleton(ns));
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700309 nextId = nsNextObjStore.
310 get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700311 if (nextId == null) {
312 log.warn("getNextObjectiveId: unable to create next objective");
313 return -1;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700314 } else {
315 log.debug("getNextObjectiveId in device{}: Next objective id {} "
316 + "created for {}", deviceId, nextId.intValue(), ns);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700317 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700318 } else {
319 log.trace("getNextObjectiveId in device{}: Next objective id {} "
320 + "found for {}", deviceId, nextId.intValue(), ns);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700321 }
322 return nextId.intValue();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800323 }
324
sangho0b2b6d12015-05-20 22:16:38 -0700325 /**
326 * Checks if the next objective ID (group) for the neighbor set exists or not.
327 *
328 * @param ns neighbor set to check
329 * @return true if it exists, false otherwise
330 */
331 public boolean hasNextObjectiveId(NeighborSet ns) {
332 Integer nextId = nsNextObjStore.
333 get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
334 if (nextId == null) {
335 return false;
336 }
337
338 return true;
339 }
340
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700341 // Empty implementation
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800342 protected void newNeighbor(Link newLink) {
343 }
344
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700345 // Empty implementation
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800346 protected void newPortToExistingNeighbor(Link newLink) {
347 }
348
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700349 // Empty implementation
350 protected Set<NeighborSet>
351 computeImpactedNeighborsetForPortEvent(DeviceId impactedNeighbor,
352 Set<DeviceId> updatedNeighbors) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800353 return null;
354 }
355
356 private void populateNeighborMaps() {
357 Set<Link> outgoingLinks = linkService.getDeviceEgressLinks(deviceId);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700358 for (Link link : outgoingLinks) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800359 if (link.type() != Link.Type.DIRECT) {
360 continue;
361 }
362 addNeighborAtPort(link.dst().deviceId(), link.src().port());
363 }
364 }
365
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700366 protected void addNeighborAtPort(DeviceId neighborId,
367 PortNumber portToNeighbor) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800368 // Update DeviceToPort database
369 log.debug("Device {} addNeighborAtPort: neighbor {} at port {}",
370 deviceId, neighborId, portToNeighbor);
371 if (devicePortMap.get(neighborId) != null) {
372 devicePortMap.get(neighborId).add(portToNeighbor);
373 } else {
374 Set<PortNumber> ports = new HashSet<PortNumber>();
375 ports.add(portToNeighbor);
376 devicePortMap.put(neighborId, ports);
377 }
378
379 // Update portToDevice database
380 if (portDeviceMap.get(portToNeighbor) == null) {
381 portDeviceMap.put(portToNeighbor, neighborId);
382 }
383 }
384
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700385 protected Set<Set<DeviceId>> getPowerSetOfNeighbors(Set<DeviceId> neighbors) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800386 List<DeviceId> list = new ArrayList<DeviceId>(neighbors);
387 Set<Set<DeviceId>> sets = new HashSet<Set<DeviceId>>();
388 // get the number of elements in the neighbors
389 int elements = list.size();
390 // the number of members of a power set is 2^n
391 // including the empty set
392 int powerElements = (1 << elements);
393
394 // run a binary counter for the number of power elements
395 // NOTE: Exclude empty set
396 for (long i = 1; i < powerElements; i++) {
397 Set<DeviceId> neighborSubSet = new HashSet<DeviceId>();
398 for (int j = 0; j < elements; j++) {
399 if ((i >> j) % 2 == 1) {
400 neighborSubSet.add(list.get(j));
401 }
402 }
403 sets.add(neighborSubSet);
404 }
405 return sets;
406 }
407
408 private boolean isSegmentIdSameAsNodeSegmentId(DeviceId deviceId, int sId) {
409 return (deviceConfig.getSegmentId(deviceId) == sId);
410 }
411
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700412 protected List<Integer> getSegmentIdsTobePairedWithNeighborSet(Set<DeviceId> neighbors) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800413
414 List<Integer> nsSegmentIds = new ArrayList<Integer>();
415
sanghob35a6192015-04-01 13:05:26 -0700416 // Always pair up with no edge label
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700417 // If (neighbors.size() == 1) {
sanghob35a6192015-04-01 13:05:26 -0700418 nsSegmentIds.add(-1);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700419 // }
sanghob35a6192015-04-01 13:05:26 -0700420
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800421 // Filter out SegmentIds matching with the
422 // nodes in the combo
423 for (Integer sId : allSegmentIds) {
424 if (sId.equals(nodeSegmentId)) {
425 continue;
426 }
427 boolean filterOut = false;
428 // Check if the edge label being set is of
429 // any node in the Neighbor set
430 for (DeviceId deviceId : neighbors) {
431 if (isSegmentIdSameAsNodeSegmentId(deviceId, sId)) {
432 filterOut = true;
433 break;
434 }
435 }
436 if (!filterOut) {
437 nsSegmentIds.add(sId);
438 }
439 }
440 return nsSegmentIds;
441 }
442
sangho1e575652015-05-14 00:39:53 -0700443 /**
444 * Creates Groups from a set of NeighborSet given.
445 *
446 * @param nsSet a set of NeighborSet
447 */
448 public void createGroupsFromNeighborsets(Set<NeighborSet> nsSet) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800449 for (NeighborSet ns : nsSet) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700450 int nextId = flowObjectiveService.allocateNextId();
451 NextObjective.Builder nextObjBuilder = DefaultNextObjective
452 .builder().withId(nextId)
453 .withType(NextObjective.Type.HASHED).fromApp(appId);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800454 for (DeviceId d : ns.getDeviceIds()) {
sangho834e4b02015-05-01 09:38:25 -0700455 if (devicePortMap.get(d) == null) {
456 log.warn("Device {} is not in the port map yet", d);
457 return;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700458 } else if (devicePortMap.get(d).size() == 0) {
459 log.warn("There are no ports for "
460 + "the Device {} in the port map yet", d);
461 return;
sangho834e4b02015-05-01 09:38:25 -0700462 }
463
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800464 for (PortNumber sp : devicePortMap.get(d)) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700465 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
466 .builder();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800467 tBuilder.setOutput(sp)
468 .setEthDst(deviceConfig.getDeviceMac(d))
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700469 .setEthSrc(nodeMacAddr);
470 if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700471 tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns
sangho834e4b02015-05-01 09:38:25 -0700472 .getEdgeLabel()));
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700473 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700474 nextObjBuilder.addTreatment(tBuilder.build());
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800475 }
476 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800477
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700478 NextObjective nextObj = nextObjBuilder.
479 add(new SRNextObjectiveContext(deviceId));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700480 flowObjectiveService.next(deviceId, nextObj);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700481 log.debug("createGroupsFromNeighborsets: Submited "
sangho1e575652015-05-14 00:39:53 -0700482 + "next objective {} in device {}",
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700483 nextId, deviceId);
484 nsNextObjStore.put(new NeighborSetNextObjectiveStoreKey(deviceId, ns),
485 nextId);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800486 }
487 }
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700488
sanghob35a6192015-04-01 13:05:26 -0700489 public GroupKey getGroupKey(Object obj) {
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700490 return new DefaultGroupKey(kryo.build().serialize(obj));
491 }
sanghob35a6192015-04-01 13:05:26 -0700492
sangho1e575652015-05-14 00:39:53 -0700493 /**
494 * Removes groups for the next objective ID given.
495 *
496 * @param objectiveId next objective ID to remove
497 * @return true if succeeds, false otherwise
498 */
499 public boolean removeGroup(int objectiveId) {
500
501 if (nsNextObjStore.containsValue(objectiveId)) {
502 NextObjective.Builder nextObjBuilder = DefaultNextObjective
503 .builder().withId(objectiveId)
504 .withType(NextObjective.Type.HASHED).fromApp(appId);
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700505 NextObjective nextObjective = nextObjBuilder.
506 remove(new SRNextObjectiveContext(deviceId));
sangho1e575652015-05-14 00:39:53 -0700507 flowObjectiveService.next(deviceId, nextObjective);
508
509 for (Map.Entry<NeighborSetNextObjectiveStoreKey, Integer> entry: nsNextObjStore.entrySet()) {
510 if (entry.getValue().equals(objectiveId)) {
511 nsNextObjStore.remove(entry.getKey());
512 break;
513 }
514 }
sangho0b2b6d12015-05-20 22:16:38 -0700515 return true;
sangho1e575652015-05-14 00:39:53 -0700516 }
517
518 return false;
519 }
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700520
521 protected static class SRNextObjectiveContext implements ObjectiveContext {
522 final DeviceId deviceId;
523
524 SRNextObjectiveContext(DeviceId deviceId) {
525 this.deviceId = deviceId;
526 }
527 @Override
528 public void onSuccess(Objective objective) {
529 log.debug("Next objective operation successful in device {}",
530 deviceId);
531 }
532
533 @Override
534 public void onError(Objective objective, ObjectiveError error) {
535 log.warn("Next objective {} operation failed with error: {} in device {}",
536 objective, error, deviceId);
537 }
538 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800539}