blob: 457be6d4f8c54587f19fe9d2498180cbb742bd34 [file] [log] [blame]
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -08003 *
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.HashSet;
25import java.util.List;
sangho1e575652015-05-14 00:39:53 -070026import java.util.Map;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080027import java.util.Set;
Saurav Das8a0732e2015-11-20 15:27:53 -080028import java.util.concurrent.ConcurrentHashMap;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070029import java.util.stream.Collectors;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080030
Charles Chanc42e84e2015-10-20 16:24:19 -070031import org.onlab.packet.Ip4Prefix;
32import org.onlab.packet.IpPrefix;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080033import org.onlab.packet.MacAddress;
sangho32a59322015-02-17 12:07:41 -080034import org.onlab.packet.MplsLabel;
Saurav Das423fe2b2015-12-04 10:52:59 -080035import org.onlab.packet.VlanId;
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070036import org.onlab.util.KryoNamespace;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080037import org.onosproject.core.ApplicationId;
Charles Chane849c192016-01-11 18:28:54 -080038import org.onosproject.net.ConnectPoint;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080039import org.onosproject.net.DeviceId;
40import org.onosproject.net.Link;
41import org.onosproject.net.PortNumber;
Saurav Das423fe2b2015-12-04 10:52:59 -080042import org.onosproject.net.flow.DefaultTrafficSelector;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080043import org.onosproject.net.flow.DefaultTrafficTreatment;
Saurav Das8a0732e2015-11-20 15:27:53 -080044import org.onosproject.net.flow.TrafficSelector;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080045import org.onosproject.net.flow.TrafficTreatment;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070046import org.onosproject.net.flowobjective.DefaultNextObjective;
47import org.onosproject.net.flowobjective.FlowObjectiveService;
48import org.onosproject.net.flowobjective.NextObjective;
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -070049import org.onosproject.net.flowobjective.Objective;
50import org.onosproject.net.flowobjective.ObjectiveContext;
51import org.onosproject.net.flowobjective.ObjectiveError;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080052import org.onosproject.net.link.LinkService;
Saurav Das423fe2b2015-12-04 10:52:59 -080053import org.onosproject.segmentrouting.SegmentRoutingManager;
Charles Chan0b4e6182015-11-03 10:42:14 -080054import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
55import org.onosproject.segmentrouting.config.DeviceProperties;
Charles Chand2990362016-04-18 13:44:03 -070056import org.onosproject.segmentrouting.storekey.NeighborSetNextObjectiveStoreKey;
57import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
58import org.onosproject.segmentrouting.storekey.SubnetNextObjectiveStoreKey;
59import org.onosproject.segmentrouting.storekey.XConnectNextObjectiveStoreKey;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070060import org.onosproject.store.service.EventuallyConsistentMap;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080061import org.slf4j.Logger;
62
63/**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070064 * Default ECMP group handler creation module. This component creates a set of
65 * ECMP groups for every neighbor that this device is connected to based on
66 * whether the current device is an edge device or a transit device.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080067 */
68public class DefaultGroupHandler {
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -070069 protected static final Logger log = getLogger(DefaultGroupHandler.class);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080070
71 protected final DeviceId deviceId;
72 protected final ApplicationId appId;
73 protected final DeviceProperties deviceConfig;
74 protected final List<Integer> allSegmentIds;
Charles Chan0b4e6182015-11-03 10:42:14 -080075 protected int nodeSegmentId = -1;
76 protected boolean isEdgeRouter = false;
77 protected MacAddress nodeMacAddr = null;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080078 protected LinkService linkService;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070079 protected FlowObjectiveService flowObjectiveService;
Saurav Das423fe2b2015-12-04 10:52:59 -080080 // local store for neighbor-device-ids and the set of ports on this device
81 // that connect to the same neighbor
Saurav Das8a0732e2015-11-20 15:27:53 -080082 protected ConcurrentHashMap<DeviceId, Set<PortNumber>> devicePortMap =
83 new ConcurrentHashMap<>();
Saurav Das423fe2b2015-12-04 10:52:59 -080084 //local store for ports on this device connected to neighbor-device-id
Saurav Das8a0732e2015-11-20 15:27:53 -080085 protected ConcurrentHashMap<PortNumber, DeviceId> portDeviceMap =
86 new ConcurrentHashMap<>();
Charles Chane849c192016-01-11 18:28:54 -080087 protected EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
88 nsNextObjStore = null;
89 protected EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
90 subnetNextObjStore = null;
91 protected EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
92 portNextObjStore = null;
93 protected EventuallyConsistentMap<XConnectNextObjectiveStoreKey, Integer>
94 xConnectNextObjStore = null;
Charles Chan188ebf52015-12-23 00:15:11 -080095 private SegmentRoutingManager srManager;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080096
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070097 protected KryoNamespace.Builder kryo = new KryoNamespace.Builder()
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070098 .register(URI.class).register(HashSet.class)
99 .register(DeviceId.class).register(PortNumber.class)
100 .register(NeighborSet.class).register(PolicyGroupIdentifier.class)
101 .register(PolicyGroupParams.class)
102 .register(GroupBucketIdentifier.class)
103 .register(GroupBucketIdentifier.BucketOutputType.class);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800104
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700105 protected DefaultGroupHandler(DeviceId deviceId, ApplicationId appId,
106 DeviceProperties config,
107 LinkService linkService,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700108 FlowObjectiveService flowObjService,
Charles Chan188ebf52015-12-23 00:15:11 -0800109 SegmentRoutingManager srManager) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800110 this.deviceId = checkNotNull(deviceId);
111 this.appId = checkNotNull(appId);
112 this.deviceConfig = checkNotNull(config);
113 this.linkService = checkNotNull(linkService);
Charles Chan0b4e6182015-11-03 10:42:14 -0800114 this.allSegmentIds = checkNotNull(config.getAllDeviceSegmentIds());
115 try {
116 this.nodeSegmentId = config.getSegmentId(deviceId);
117 this.isEdgeRouter = config.isEdgeDevice(deviceId);
118 this.nodeMacAddr = checkNotNull(config.getDeviceMac(deviceId));
119 } catch (DeviceConfigNotFoundException e) {
120 log.warn(e.getMessage()
121 + " Skipping value assignment in DefaultGroupHandler");
122 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700123 this.flowObjectiveService = flowObjService;
Charles Chane849c192016-01-11 18:28:54 -0800124 this.nsNextObjStore = srManager.nsNextObjStore;
125 this.subnetNextObjStore = srManager.subnetNextObjStore;
126 this.portNextObjStore = srManager.portNextObjStore;
127 this.xConnectNextObjStore = srManager.xConnectNextObjStore;
Charles Chan188ebf52015-12-23 00:15:11 -0800128 this.srManager = srManager;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800129
130 populateNeighborMaps();
131 }
132
133 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700134 * Creates a group handler object based on the type of device. If device is
135 * of edge type it returns edge group handler, else it returns transit group
136 * handler.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800137 *
138 * @param deviceId device identifier
139 * @param appId application identifier
140 * @param config interface to retrieve the device properties
141 * @param linkService link service object
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700142 * @param flowObjService flow objective service object
Charles Chane849c192016-01-11 18:28:54 -0800143 * @param srManager segment routing manager
Charles Chan0b4e6182015-11-03 10:42:14 -0800144 * @throws DeviceConfigNotFoundException if the device configuration is not found
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800145 * @return default group handler type
146 */
Saurav Das4ce45962015-11-24 23:21:05 -0800147 public static DefaultGroupHandler createGroupHandler(
148 DeviceId deviceId,
149 ApplicationId appId,
150 DeviceProperties config,
151 LinkService linkService,
152 FlowObjectiveService flowObjService,
Charles Chan188ebf52015-12-23 00:15:11 -0800153 SegmentRoutingManager srManager)
Saurav Das4ce45962015-11-24 23:21:05 -0800154 throws DeviceConfigNotFoundException {
Charles Chan0b4e6182015-11-03 10:42:14 -0800155 // handle possible exception in the caller
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800156 if (config.isEdgeDevice(deviceId)) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700157 return new DefaultEdgeGroupHandler(deviceId, appId, config,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700158 linkService,
159 flowObjService,
Charles Chan188ebf52015-12-23 00:15:11 -0800160 srManager
161 );
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800162 } else {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700163 return new DefaultTransitGroupHandler(deviceId, appId, config,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700164 linkService,
165 flowObjService,
Charles Chan188ebf52015-12-23 00:15:11 -0800166 srManager);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800167 }
168 }
169
170 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700171 * Creates the auto created groups for this device based on the current
172 * snapshot of the topology.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800173 */
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700174 // Empty implementations to be overridden by derived classes
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800175 public void createGroups() {
176 }
177
178 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700179 * Performs group creation or update procedures when a new link is
180 * discovered on this device.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800181 *
182 * @param newLink new neighbor link
Charles Chane849c192016-01-11 18:28:54 -0800183 * @param isMaster true if local instance is the master
184 *
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800185 */
Saurav Das8a0732e2015-11-20 15:27:53 -0800186 public void linkUp(Link newLink, boolean isMaster) {
sanghob35a6192015-04-01 13:05:26 -0700187
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800188 if (newLink.type() != Link.Type.DIRECT) {
189 log.warn("linkUp: unknown link type");
190 return;
191 }
192
193 if (!newLink.src().deviceId().equals(deviceId)) {
194 log.warn("linkUp: deviceId{} doesn't match with link src{}",
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700195 deviceId, newLink.src().deviceId());
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800196 return;
197 }
198
Saurav Das8a0732e2015-11-20 15:27:53 -0800199 log.info("* LinkUP: Device {} linkUp at local port {} to neighbor {}", deviceId,
200 newLink.src().port(), newLink.dst().deviceId());
Charles Chan0b4e6182015-11-03 10:42:14 -0800201 MacAddress dstMac;
202 try {
203 dstMac = deviceConfig.getDeviceMac(newLink.dst().deviceId());
204 } catch (DeviceConfigNotFoundException e) {
205 log.warn(e.getMessage() + " Aborting linkUp.");
206 return;
207 }
208
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700209 addNeighborAtPort(newLink.dst().deviceId(),
210 newLink.src().port());
211 /*if (devicePortMap.get(newLink.dst().deviceId()) == null) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800212 // New Neighbor
213 newNeighbor(newLink);
214 } else {
215 // Old Neighbor
216 newPortToExistingNeighbor(newLink);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700217 }*/
218 Set<NeighborSet> nsSet = nsNextObjStore.keySet()
219 .stream()
220 .filter((nsStoreEntry) -> (nsStoreEntry.deviceId().equals(deviceId)))
221 .map((nsStoreEntry) -> (nsStoreEntry.neighborSet()))
222 .filter((ns) -> (ns.getDeviceIds()
223 .contains(newLink.dst().deviceId())))
224 .collect(Collectors.toSet());
225 log.trace("linkUp: nsNextObjStore contents for device {}:",
sangho0b2b6d12015-05-20 22:16:38 -0700226 deviceId,
227 nsSet);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700228 for (NeighborSet ns : nsSet) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700229 Integer nextId = nsNextObjStore.
230 get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
Saurav Das4ce45962015-11-24 23:21:05 -0800231 if (nextId != null && isMaster) {
Saurav Das423fe2b2015-12-04 10:52:59 -0800232 // Create the new bucket to be updated
233 TrafficTreatment.Builder tBuilder =
234 DefaultTrafficTreatment.builder();
235 tBuilder.setOutput(newLink.src().port())
236 .setEthDst(dstMac)
237 .setEthSrc(nodeMacAddr);
238 if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
239 tBuilder.pushMpls()
240 .copyTtlOut()
241 .setMpls(MplsLabel.mplsLabel(ns.getEdgeLabel()));
242 }
243 // setup metadata to pass to nextObjective - indicate the vlan on egress
244 // if needed by the switch pipeline. Since hashed next-hops are always to
245 // other neighboring routers, there is no subnet assigned on those ports.
246 TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
247 metabuilder.matchVlanId(
248 VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET));
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700249
Saurav Das423fe2b2015-12-04 10:52:59 -0800250 NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder()
251 .withId(nextId)
252 .withType(NextObjective.Type.HASHED)
253 .addTreatment(tBuilder.build())
254 .withMeta(metabuilder.build())
255 .fromApp(appId);
Saurav Das8a0732e2015-11-20 15:27:53 -0800256 log.info("**linkUp in device {}: Adding Bucket "
Saurav Das4ce45962015-11-24 23:21:05 -0800257 + "with Port {} to next object id {}",
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700258 deviceId,
259 newLink.src().port(),
Saurav Das4ce45962015-11-24 23:21:05 -0800260 nextId);
261 NextObjective nextObjective = nextObjBuilder.
262 addToExisting(new SRNextObjectiveContext(deviceId));
263 flowObjectiveService.next(deviceId, nextObjective);
Saurav Das423fe2b2015-12-04 10:52:59 -0800264
265 // the addition of a bucket may actually change the neighborset
266 // update the global store
267 /*
268 Set<DeviceId> neighbors = new HashSet<DeviceId>(ns.getDeviceIds());
269 boolean newadd = neighbors.add(newLink.dst().deviceId());
270 if (newadd) {
271 NeighborSet nsnew = new NeighborSet(neighbors, ns.getEdgeLabel());
272 nsNextObjStore.put(new NeighborSetNextObjectiveStoreKey(deviceId, nsnew),
273 nextId);
274 nsNextObjStore.remove(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
275 }*/
Saurav Das4ce45962015-11-24 23:21:05 -0800276 } else if (isMaster) {
Saurav Das8a0732e2015-11-20 15:27:53 -0800277 log.warn("linkUp in device {}, but global store has no record "
278 + "for neighbor-set {}", deviceId, ns);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700279 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800280 }
281 }
282
283 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700284 * Performs group recovery procedures when a port goes down on this device.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800285 *
286 * @param port port number that has gone down
Charles Chane849c192016-01-11 18:28:54 -0800287 * @param isMaster true if local instance is the master
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800288 */
Saurav Das423fe2b2015-12-04 10:52:59 -0800289 public void portDown(PortNumber port, boolean isMaster) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800290 if (portDeviceMap.get(port) == null) {
291 log.warn("portDown: unknown port");
292 return;
293 }
Charles Chan0b4e6182015-11-03 10:42:14 -0800294
Saurav Das80980c72016-03-23 11:22:49 -0700295 @SuppressWarnings("unused")
Charles Chan0b4e6182015-11-03 10:42:14 -0800296 MacAddress dstMac;
297 try {
298 dstMac = deviceConfig.getDeviceMac(portDeviceMap.get(port));
299 } catch (DeviceConfigNotFoundException e) {
300 log.warn(e.getMessage() + " Aborting portDown.");
301 return;
302 }
303
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700304 log.debug("Device {} portDown {} to neighbor {}", deviceId, port,
305 portDeviceMap.get(port));
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700306 /*Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(portDeviceMap
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700307 .get(port),
308 devicePortMap
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700309 .keySet());*/
310 Set<NeighborSet> nsSet = nsNextObjStore.keySet()
311 .stream()
312 .filter((nsStoreEntry) -> (nsStoreEntry.deviceId().equals(deviceId)))
313 .map((nsStoreEntry) -> (nsStoreEntry.neighborSet()))
314 .filter((ns) -> (ns.getDeviceIds()
315 .contains(portDeviceMap.get(port))))
316 .collect(Collectors.toSet());
Saurav Das423fe2b2015-12-04 10:52:59 -0800317 log.debug("portDown: nsNextObjStore contents for device {}:{}",
318 deviceId, nsSet);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800319 for (NeighborSet ns : nsSet) {
Saurav Das80980c72016-03-23 11:22:49 -0700320 NeighborSetNextObjectiveStoreKey nsStoreKey =
321 new NeighborSetNextObjectiveStoreKey(deviceId, ns);
322 Integer nextId = nsNextObjStore.get(nsStoreKey);
Saurav Das423fe2b2015-12-04 10:52:59 -0800323 if (nextId != null && isMaster) {
Saurav Das80980c72016-03-23 11:22:49 -0700324 // XXX This is a workaround for BUG (CORD-611) in current switches.
325 // Should be temporary because this workaround prevents correct
326 // functionality in LAG recovery.
327 log.info("**portDown port:{} in device {}: Invalidating nextId {}",
328 port, deviceId, nextId);
329 nsNextObjStore.remove(nsStoreKey);
330 /*
Saurav Das8a0732e2015-11-20 15:27:53 -0800331 log.info("**portDown in device {}: Removing Bucket "
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700332 + "with Port {} to next object id {}",
333 deviceId,
334 port,
335 nextId);
Saurav Das423fe2b2015-12-04 10:52:59 -0800336 // Create the bucket to be removed
337 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
338 .builder();
339 tBuilder.setOutput(port)
340 .setEthDst(dstMac)
341 .setEthSrc(nodeMacAddr);
342 if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
343 tBuilder.pushMpls()
344 .copyTtlOut()
345 .setMpls(MplsLabel.mplsLabel(ns.getEdgeLabel()));
346 }
347 NextObjective.Builder nextObjBuilder = DefaultNextObjective
348 .builder()
349 .withType(NextObjective.Type.HASHED) //same as original
350 .withId(nextId)
351 .fromApp(appId)
352 .addTreatment(tBuilder.build());
353 NextObjective nextObjective = nextObjBuilder.
354 removeFromExisting(new SRNextObjectiveContext(deviceId));
sangho834e4b02015-05-01 09:38:25 -0700355
Saurav Das423fe2b2015-12-04 10:52:59 -0800356 flowObjectiveService.next(deviceId, nextObjective);
Saurav Das80980c72016-03-23 11:22:49 -0700357 */
Saurav Das423fe2b2015-12-04 10:52:59 -0800358 // the removal of a bucket may actually change the neighborset
359 // update the global store
360 /*
361 Set<DeviceId> neighbors = new HashSet<DeviceId>(ns.getDeviceIds());
362 boolean removed = neighbors.remove(portDeviceMap.get(port));
363 if (removed) {
364 NeighborSet nsnew = new NeighborSet(neighbors, ns.getEdgeLabel());
365 nsNextObjStore.put(new NeighborSetNextObjectiveStoreKey(deviceId, nsnew),
366 nextId);
367 nsNextObjStore.remove(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
368 }*/
sangho834e4b02015-05-01 09:38:25 -0700369 }
370
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800371 }
372
373 devicePortMap.get(portDeviceMap.get(port)).remove(port);
374 portDeviceMap.remove(port);
375 }
376
377 /**
Saurav Das4ce45962015-11-24 23:21:05 -0800378 * Returns the next objective of type hashed associated with the neighborset.
379 * If there is no next objective for this neighborset, this method
Saurav Das8a0732e2015-11-20 15:27:53 -0800380 * would create a next objective and return. Optionally metadata can be
381 * passed in for the creation of the next objective.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800382 *
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700383 * @param ns neighborset
Saurav Das8a0732e2015-11-20 15:27:53 -0800384 * @param meta metadata passed into the creation of a Next Objective
385 * @return int if found or -1 if there are errors in the creation of the
386 * neighbor set.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800387 */
Saurav Das8a0732e2015-11-20 15:27:53 -0800388 public int getNextObjectiveId(NeighborSet ns, TrafficSelector meta) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700389 Integer nextId = nsNextObjStore.
390 get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700391 if (nextId == null) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700392 log.trace("getNextObjectiveId in device{}: Next objective id "
393 + "not found for {} and creating", deviceId, ns);
394 log.trace("getNextObjectiveId: nsNextObjStore contents for device {}: {}",
395 deviceId,
396 nsNextObjStore.entrySet()
397 .stream()
398 .filter((nsStoreEntry) ->
399 (nsStoreEntry.getKey().deviceId().equals(deviceId)))
400 .collect(Collectors.toList()));
Saurav Das8a0732e2015-11-20 15:27:53 -0800401 createGroupsFromNeighborsets(Collections.singleton(ns), meta);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700402 nextId = nsNextObjStore.
403 get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700404 if (nextId == null) {
405 log.warn("getNextObjectiveId: unable to create next objective");
406 return -1;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700407 } else {
408 log.debug("getNextObjectiveId in device{}: Next objective id {} "
Sho SHIMIZUaf973432015-09-11 14:24:50 -0700409 + "created for {}", deviceId, nextId, ns);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700410 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700411 } else {
412 log.trace("getNextObjectiveId in device{}: Next objective id {} "
Sho SHIMIZUaf973432015-09-11 14:24:50 -0700413 + "found for {}", deviceId, nextId, ns);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700414 }
Sho SHIMIZUaf973432015-09-11 14:24:50 -0700415 return nextId;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800416 }
417
sangho0b2b6d12015-05-20 22:16:38 -0700418 /**
Saurav Das4ce45962015-11-24 23:21:05 -0800419 * Returns the next objective of type broadcast associated with the subnet,
420 * or -1 if no such objective exists. Note that this method does NOT create
421 * the next objective as a side-effect. It is expected that is objective is
422 * created at startup from network configuration.
Charles Chanc42e84e2015-10-20 16:24:19 -0700423 *
424 * @param prefix subnet information
425 * @return int if found or -1
426 */
427 public int getSubnetNextObjectiveId(IpPrefix prefix) {
428 Integer nextId = subnetNextObjStore.
429 get(new SubnetNextObjectiveStoreKey(deviceId, prefix));
Charles Chan9f676b62015-10-29 14:58:10 -0700430
431 return (nextId != null) ? nextId : -1;
Charles Chanc42e84e2015-10-20 16:24:19 -0700432 }
433
434 /**
Saurav Das4ce45962015-11-24 23:21:05 -0800435 * Returns the next objective of type simple associated with the port on the
436 * device, given the treatment. Different treatments to the same port result
437 * in different next objectives. If no such objective exists, this method
438 * creates one and returns the id. Optionally metadata can be passed in for
439 * the creation of the objective.
440 *
441 * @param portNum the port number for the simple next objective
442 * @param treatment the actions to apply on the packets (should include outport)
443 * @param meta optional metadata passed into the creation of the next objective
444 * @return int if found or created, -1 if there are errors during the
445 * creation of the next objective.
446 */
447 public int getPortNextObjectiveId(PortNumber portNum, TrafficTreatment treatment,
448 TrafficSelector meta) {
Charles Chane849c192016-01-11 18:28:54 -0800449 Integer nextId = portNextObjStore
450 .get(new PortNextObjectiveStoreKey(deviceId, portNum, treatment));
Saurav Das4ce45962015-11-24 23:21:05 -0800451 if (nextId == null) {
452 log.trace("getPortNextObjectiveId in device{}: Next objective id "
453 + "not found for {} and {} creating", deviceId, portNum);
454 createGroupFromPort(portNum, treatment, meta);
455 nextId = portNextObjStore.get(
456 new PortNextObjectiveStoreKey(deviceId, portNum, treatment));
457 if (nextId == null) {
458 log.warn("getPortNextObjectiveId: unable to create next obj"
Charles Chane849c192016-01-11 18:28:54 -0800459 + "for dev:{} port:{}", deviceId, portNum);
460 return -1;
461 }
462 }
463 return nextId;
464 }
465
466 /**
467 * Returns the next objective ID of type broadcast associated with the VLAN
468 * cross-connection.
469 *
470 * @param vlanId VLAN ID for the cross-connection
471 * @return int if found or created, -1 if there are errors during the
472 * creation of the next objective
473 */
474 public int getXConnectNextObjectiveId(VlanId vlanId) {
475 Integer nextId = xConnectNextObjStore
476 .get(new XConnectNextObjectiveStoreKey(deviceId, vlanId));
477 if (nextId == null) {
478 log.trace("getXConnectNextObjectiveId: Next objective id "
479 + "not found for device {} and vlan {}. Creating", deviceId, vlanId);
480 createGroupsForXConnect(deviceId);
481 nextId = xConnectNextObjStore.get(
482 new XConnectNextObjectiveStoreKey(deviceId, vlanId));
483 if (nextId == null) {
484 log.warn("getXConnectNextObjectiveId: Next objective id "
485 + "not found for device {} and vlan {}.", deviceId, vlanId);
Saurav Das4ce45962015-11-24 23:21:05 -0800486 return -1;
487 }
488 }
489 return nextId;
490 }
491
492 /**
sangho0b2b6d12015-05-20 22:16:38 -0700493 * Checks if the next objective ID (group) for the neighbor set exists or not.
494 *
495 * @param ns neighbor set to check
496 * @return true if it exists, false otherwise
497 */
498 public boolean hasNextObjectiveId(NeighborSet ns) {
499 Integer nextId = nsNextObjStore.
500 get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
501 if (nextId == null) {
502 return false;
503 }
504
505 return true;
506 }
507
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700508 // Empty implementation
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800509 protected void newNeighbor(Link newLink) {
510 }
511
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700512 // Empty implementation
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800513 protected void newPortToExistingNeighbor(Link newLink) {
514 }
515
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700516 // Empty implementation
517 protected Set<NeighborSet>
518 computeImpactedNeighborsetForPortEvent(DeviceId impactedNeighbor,
519 Set<DeviceId> updatedNeighbors) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800520 return null;
521 }
522
523 private void populateNeighborMaps() {
524 Set<Link> outgoingLinks = linkService.getDeviceEgressLinks(deviceId);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700525 for (Link link : outgoingLinks) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800526 if (link.type() != Link.Type.DIRECT) {
527 continue;
528 }
529 addNeighborAtPort(link.dst().deviceId(), link.src().port());
530 }
531 }
532
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700533 protected void addNeighborAtPort(DeviceId neighborId,
534 PortNumber portToNeighbor) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800535 // Update DeviceToPort database
536 log.debug("Device {} addNeighborAtPort: neighbor {} at port {}",
537 deviceId, neighborId, portToNeighbor);
Saurav Das8a0732e2015-11-20 15:27:53 -0800538 Set<PortNumber> ports = Collections
539 .newSetFromMap(new ConcurrentHashMap<PortNumber, Boolean>());
540 ports.add(portToNeighbor);
541 Set<PortNumber> portnums = devicePortMap.putIfAbsent(neighborId, ports);
542 if (portnums != null) {
543 portnums.add(portToNeighbor);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800544 }
545
546 // Update portToDevice database
Saurav Das8a0732e2015-11-20 15:27:53 -0800547 DeviceId prev = portDeviceMap.putIfAbsent(portToNeighbor, neighborId);
548 if (prev != null) {
549 log.warn("Device: {} port: {} has neighbor: {}. NOT updating "
550 + "to neighbor: {}", deviceId, portToNeighbor, prev, neighborId);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800551 }
552 }
553
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700554 protected Set<Set<DeviceId>> getPowerSetOfNeighbors(Set<DeviceId> neighbors) {
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -0700555 List<DeviceId> list = new ArrayList<>(neighbors);
556 Set<Set<DeviceId>> sets = new HashSet<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800557 // get the number of elements in the neighbors
558 int elements = list.size();
559 // the number of members of a power set is 2^n
560 // including the empty set
561 int powerElements = (1 << elements);
562
563 // run a binary counter for the number of power elements
564 // NOTE: Exclude empty set
565 for (long i = 1; i < powerElements; i++) {
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -0700566 Set<DeviceId> neighborSubSet = new HashSet<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800567 for (int j = 0; j < elements; j++) {
568 if ((i >> j) % 2 == 1) {
569 neighborSubSet.add(list.get(j));
570 }
571 }
572 sets.add(neighborSubSet);
573 }
574 return sets;
575 }
576
577 private boolean isSegmentIdSameAsNodeSegmentId(DeviceId deviceId, int sId) {
Charles Chan0b4e6182015-11-03 10:42:14 -0800578 int segmentId;
579 try {
580 segmentId = deviceConfig.getSegmentId(deviceId);
581 } catch (DeviceConfigNotFoundException e) {
582 log.warn(e.getMessage() + " Aborting isSegmentIdSameAsNodeSegmentId.");
583 return false;
584 }
585
586 return segmentId == sId;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800587 }
588
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700589 protected List<Integer> getSegmentIdsTobePairedWithNeighborSet(Set<DeviceId> neighbors) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800590
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -0700591 List<Integer> nsSegmentIds = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800592
sanghob35a6192015-04-01 13:05:26 -0700593 // Always pair up with no edge label
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700594 // If (neighbors.size() == 1) {
sanghob35a6192015-04-01 13:05:26 -0700595 nsSegmentIds.add(-1);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700596 // }
sanghob35a6192015-04-01 13:05:26 -0700597
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800598 // Filter out SegmentIds matching with the
599 // nodes in the combo
600 for (Integer sId : allSegmentIds) {
601 if (sId.equals(nodeSegmentId)) {
602 continue;
603 }
604 boolean filterOut = false;
605 // Check if the edge label being set is of
606 // any node in the Neighbor set
607 for (DeviceId deviceId : neighbors) {
608 if (isSegmentIdSameAsNodeSegmentId(deviceId, sId)) {
609 filterOut = true;
610 break;
611 }
612 }
613 if (!filterOut) {
614 nsSegmentIds.add(sId);
615 }
616 }
617 return nsSegmentIds;
618 }
619
sangho1e575652015-05-14 00:39:53 -0700620 /**
621 * Creates Groups from a set of NeighborSet given.
622 *
623 * @param nsSet a set of NeighborSet
Saurav Das8a0732e2015-11-20 15:27:53 -0800624 * @param meta metadata passed into the creation of a Next Objective
sangho1e575652015-05-14 00:39:53 -0700625 */
Saurav Das8a0732e2015-11-20 15:27:53 -0800626 public void createGroupsFromNeighborsets(Set<NeighborSet> nsSet,
627 TrafficSelector meta) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800628 for (NeighborSet ns : nsSet) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700629 int nextId = flowObjectiveService.allocateNextId();
630 NextObjective.Builder nextObjBuilder = DefaultNextObjective
631 .builder().withId(nextId)
632 .withType(NextObjective.Type.HASHED).fromApp(appId);
Saurav Das8a0732e2015-11-20 15:27:53 -0800633 for (DeviceId neighborId : ns.getDeviceIds()) {
634 if (devicePortMap.get(neighborId) == null) {
635 log.warn("Neighbor {} is not in the port map yet for dev:{}",
636 neighborId, deviceId);
sangho834e4b02015-05-01 09:38:25 -0700637 return;
Saurav Das8a0732e2015-11-20 15:27:53 -0800638 } else if (devicePortMap.get(neighborId).size() == 0) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700639 log.warn("There are no ports for "
Saurav Das8a0732e2015-11-20 15:27:53 -0800640 + "the Device {} in the port map yet", neighborId);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700641 return;
sangho834e4b02015-05-01 09:38:25 -0700642 }
643
Saurav Das8a0732e2015-11-20 15:27:53 -0800644 MacAddress neighborMac;
Charles Chan0b4e6182015-11-03 10:42:14 -0800645 try {
Saurav Das8a0732e2015-11-20 15:27:53 -0800646 neighborMac = deviceConfig.getDeviceMac(neighborId);
Charles Chan0b4e6182015-11-03 10:42:14 -0800647 } catch (DeviceConfigNotFoundException e) {
648 log.warn(e.getMessage() + " Aborting createGroupsFromNeighborsets.");
649 return;
650 }
651
Saurav Das8a0732e2015-11-20 15:27:53 -0800652 for (PortNumber sp : devicePortMap.get(neighborId)) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700653 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
654 .builder();
Saurav Das8a0732e2015-11-20 15:27:53 -0800655 tBuilder.setEthDst(neighborMac)
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700656 .setEthSrc(nodeMacAddr);
657 if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
Charles Chan68aa62d2015-11-09 16:37:23 -0800658 tBuilder.pushMpls()
659 .copyTtlOut()
660 .setMpls(MplsLabel.mplsLabel(ns.getEdgeLabel()));
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700661 }
Saurav Das8a0732e2015-11-20 15:27:53 -0800662 tBuilder.setOutput(sp);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700663 nextObjBuilder.addTreatment(tBuilder.build());
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800664 }
665 }
Saurav Das8a0732e2015-11-20 15:27:53 -0800666 if (meta != null) {
Saurav Das4ce45962015-11-24 23:21:05 -0800667 nextObjBuilder.withMeta(meta);
Saurav Das8a0732e2015-11-20 15:27:53 -0800668 }
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700669 NextObjective nextObj = nextObjBuilder.
670 add(new SRNextObjectiveContext(deviceId));
Saurav Das8a0732e2015-11-20 15:27:53 -0800671 log.info("**createGroupsFromNeighborsets: Submited "
672 + "next objective {} in device {}",
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700673 nextId, deviceId);
Saurav Das8a0732e2015-11-20 15:27:53 -0800674 flowObjectiveService.next(deviceId, nextObj);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700675 nsNextObjStore.put(new NeighborSetNextObjectiveStoreKey(deviceId, ns),
676 nextId);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800677 }
678 }
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700679
Saurav Das4ce45962015-11-24 23:21:05 -0800680 /**
681 * Creates broadcast groups for all ports in the same configured subnet.
Saurav Das4ce45962015-11-24 23:21:05 -0800682 */
Charles Chanc42e84e2015-10-20 16:24:19 -0700683 public void createGroupsFromSubnetConfig() {
Saurav Das7a1ffca2016-03-28 19:00:18 -0700684 Map<Ip4Prefix, List<PortNumber>> subnetPortMap;
685 try {
686 subnetPortMap = this.deviceConfig.getSubnetPortsMap(this.deviceId);
687 } catch (DeviceConfigNotFoundException e) {
688 log.warn(e.getMessage()
689 + " Not creating broadcast groups for device: " + deviceId);
690 return;
691 }
Charles Chanc42e84e2015-10-20 16:24:19 -0700692 // Construct a broadcast group for each subnet
693 subnetPortMap.forEach((subnet, ports) -> {
Charles Chan9f676b62015-10-29 14:58:10 -0700694 SubnetNextObjectiveStoreKey key =
695 new SubnetNextObjectiveStoreKey(deviceId, subnet);
696
697 if (subnetNextObjStore.containsKey(key)) {
698 log.debug("Broadcast group for device {} and subnet {} exists",
699 deviceId, subnet);
700 return;
701 }
702
Charles Chan188ebf52015-12-23 00:15:11 -0800703 VlanId assignedVlanId =
704 srManager.getSubnetAssignedVlanId(this.deviceId, subnet);
705 TrafficSelector metadata =
706 DefaultTrafficSelector.builder().matchVlanId(assignedVlanId).build();
707
Charles Chanc42e84e2015-10-20 16:24:19 -0700708 int nextId = flowObjectiveService.allocateNextId();
709
710 NextObjective.Builder nextObjBuilder = DefaultNextObjective
711 .builder().withId(nextId)
Charles Chan188ebf52015-12-23 00:15:11 -0800712 .withType(NextObjective.Type.BROADCAST).fromApp(appId)
713 .withMeta(metadata);
Charles Chanc42e84e2015-10-20 16:24:19 -0700714
715 ports.forEach(port -> {
716 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
Saurav Das4f980082015-11-05 13:39:15 -0800717 tBuilder.popVlan();
Charles Chanc42e84e2015-10-20 16:24:19 -0700718 tBuilder.setOutput(port);
719 nextObjBuilder.addTreatment(tBuilder.build());
720 });
721
722 NextObjective nextObj = nextObjBuilder.add();
723 flowObjectiveService.next(deviceId, nextObj);
724 log.debug("createGroupFromSubnetConfig: Submited "
725 + "next objective {} in device {}",
726 nextId, deviceId);
Charles Chan9f676b62015-10-29 14:58:10 -0700727
Charles Chanc42e84e2015-10-20 16:24:19 -0700728 subnetNextObjStore.put(key, nextId);
729 });
730 }
731
Charles Chane849c192016-01-11 18:28:54 -0800732 /**
733 * Creates broadcast groups for VLAN cross-connect ports.
734 *
735 * @param deviceId the DPID of the switch
736 */
737 public void createGroupsForXConnect(DeviceId deviceId) {
738 Map<VlanId, List<ConnectPoint>> xConnectsForDevice = deviceConfig.getXConnects();
739
740 xConnectsForDevice.forEach((vlanId, connectPoints) -> {
741 // Only proceed the xConnect for given device
742 for (ConnectPoint connectPoint : connectPoints) {
743 if (!connectPoint.deviceId().equals(deviceId)) {
744 return;
745 }
746 }
747
748 // Check if the next obj is already in the store
749 XConnectNextObjectiveStoreKey key =
750 new XConnectNextObjectiveStoreKey(deviceId, vlanId);
751 if (xConnectNextObjStore.containsKey(key)) {
752 log.debug("Cross-connect Broadcast group for device {} and vlanId {} exists",
753 deviceId, vlanId);
754 return;
755 }
756
757 TrafficSelector metadata =
758 DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
759 int nextId = flowObjectiveService.allocateNextId();
760
761 NextObjective.Builder nextObjBuilder = DefaultNextObjective
762 .builder().withId(nextId)
763 .withType(NextObjective.Type.BROADCAST).fromApp(appId)
764 .withMeta(metadata);
765
766 connectPoints.forEach(connectPoint -> {
767 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
768 tBuilder.setOutput(connectPoint.port());
769 nextObjBuilder.addTreatment(tBuilder.build());
770 });
771
772 NextObjective nextObj = nextObjBuilder.add();
773 flowObjectiveService.next(deviceId, nextObj);
774 log.debug("createGroupsForXConnect: Submited next objective {} in device {}",
775 nextId, deviceId);
776 xConnectNextObjStore.put(key, nextId);
777 });
778 }
779
Saurav Das4ce45962015-11-24 23:21:05 -0800780
781 /**
782 * Create simple next objective for a single port. The treatments can include
783 * all outgoing actions that need to happen on the packet.
784 *
785 * @param portNum the outgoing port on the device
786 * @param treatment the actions to apply on the packets (should include outport)
787 * @param meta optional data to pass to the driver
788 */
789 public void createGroupFromPort(PortNumber portNum, TrafficTreatment treatment,
790 TrafficSelector meta) {
791 int nextId = flowObjectiveService.allocateNextId();
792 PortNextObjectiveStoreKey key = new PortNextObjectiveStoreKey(
793 deviceId, portNum, treatment);
794
795 NextObjective.Builder nextObjBuilder = DefaultNextObjective
796 .builder().withId(nextId)
797 .withType(NextObjective.Type.SIMPLE)
798 .addTreatment(treatment)
799 .fromApp(appId)
800 .withMeta(meta);
801
802 NextObjective nextObj = nextObjBuilder.add();
803 flowObjectiveService.next(deviceId, nextObj);
804 log.debug("createGroupFromPort: Submited next objective {} in device {} "
805 + "for port {}", nextId, deviceId, portNum);
806
807 portNextObjStore.put(key, nextId);
808 }
809
sangho1e575652015-05-14 00:39:53 -0700810 /**
811 * Removes groups for the next objective ID given.
812 *
813 * @param objectiveId next objective ID to remove
814 * @return true if succeeds, false otherwise
815 */
816 public boolean removeGroup(int objectiveId) {
817
818 if (nsNextObjStore.containsValue(objectiveId)) {
819 NextObjective.Builder nextObjBuilder = DefaultNextObjective
820 .builder().withId(objectiveId)
821 .withType(NextObjective.Type.HASHED).fromApp(appId);
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700822 NextObjective nextObjective = nextObjBuilder.
823 remove(new SRNextObjectiveContext(deviceId));
Saurav Das8a0732e2015-11-20 15:27:53 -0800824 log.info("**removeGroup: Submited "
825 + "next objective {} in device {}",
826 objectiveId, deviceId);
sangho1e575652015-05-14 00:39:53 -0700827 flowObjectiveService.next(deviceId, nextObjective);
828
829 for (Map.Entry<NeighborSetNextObjectiveStoreKey, Integer> entry: nsNextObjStore.entrySet()) {
830 if (entry.getValue().equals(objectiveId)) {
831 nsNextObjStore.remove(entry.getKey());
832 break;
833 }
834 }
sangho0b2b6d12015-05-20 22:16:38 -0700835 return true;
sangho1e575652015-05-14 00:39:53 -0700836 }
837
838 return false;
839 }
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700840
Charles Chane849c192016-01-11 18:28:54 -0800841 /**
842 * Removes all groups from all next objective stores.
843 */
Saurav Das423fe2b2015-12-04 10:52:59 -0800844 public void removeAllGroups() {
845 for (Map.Entry<NeighborSetNextObjectiveStoreKey, Integer> entry:
846 nsNextObjStore.entrySet()) {
847 removeGroup(entry.getValue());
848 }
849 for (Map.Entry<PortNextObjectiveStoreKey, Integer> entry:
850 portNextObjStore.entrySet()) {
851 removeGroup(entry.getValue());
852 }
853 for (Map.Entry<SubnetNextObjectiveStoreKey, Integer> entry:
854 subnetNextObjStore.entrySet()) {
855 removeGroup(entry.getValue());
856 }
857 // should probably clean local stores port-neighbor
858 }
859
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700860 protected static class SRNextObjectiveContext implements ObjectiveContext {
861 final DeviceId deviceId;
862
863 SRNextObjectiveContext(DeviceId deviceId) {
864 this.deviceId = deviceId;
865 }
866 @Override
867 public void onSuccess(Objective objective) {
Saurav Das8a0732e2015-11-20 15:27:53 -0800868 log.info("Next objective {} operation successful in device {}",
869 objective.id(), deviceId);
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700870 }
871
872 @Override
873 public void onError(Objective objective, ObjectiveError error) {
874 log.warn("Next objective {} operation failed with error: {} in device {}",
Saurav Das8a0732e2015-11-20 15:27:53 -0800875 objective.id(), error, deviceId);
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700876 }
877 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800878}