blob: cb58f84c3bd14bf0b6343a256b35593552326e71 [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;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070056import org.onosproject.store.service.EventuallyConsistentMap;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080057import org.slf4j.Logger;
58
59/**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070060 * Default ECMP group handler creation module. This component creates a set of
61 * ECMP groups for every neighbor that this device is connected to based on
62 * whether the current device is an edge device or a transit device.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080063 */
64public class DefaultGroupHandler {
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -070065 protected static final Logger log = getLogger(DefaultGroupHandler.class);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080066
67 protected final DeviceId deviceId;
68 protected final ApplicationId appId;
69 protected final DeviceProperties deviceConfig;
70 protected final List<Integer> allSegmentIds;
Charles Chan0b4e6182015-11-03 10:42:14 -080071 protected int nodeSegmentId = -1;
72 protected boolean isEdgeRouter = false;
73 protected MacAddress nodeMacAddr = null;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080074 protected LinkService linkService;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070075 protected FlowObjectiveService flowObjectiveService;
Saurav Das423fe2b2015-12-04 10:52:59 -080076 // local store for neighbor-device-ids and the set of ports on this device
77 // that connect to the same neighbor
Saurav Das8a0732e2015-11-20 15:27:53 -080078 protected ConcurrentHashMap<DeviceId, Set<PortNumber>> devicePortMap =
79 new ConcurrentHashMap<>();
Saurav Das423fe2b2015-12-04 10:52:59 -080080 //local store for ports on this device connected to neighbor-device-id
Saurav Das8a0732e2015-11-20 15:27:53 -080081 protected ConcurrentHashMap<PortNumber, DeviceId> portDeviceMap =
82 new ConcurrentHashMap<>();
Charles Chane849c192016-01-11 18:28:54 -080083 protected EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
84 nsNextObjStore = null;
85 protected EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
86 subnetNextObjStore = null;
87 protected EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
88 portNextObjStore = null;
89 protected EventuallyConsistentMap<XConnectNextObjectiveStoreKey, Integer>
90 xConnectNextObjStore = null;
Charles Chan188ebf52015-12-23 00:15:11 -080091 private SegmentRoutingManager srManager;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080092
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070093 protected KryoNamespace.Builder kryo = new KryoNamespace.Builder()
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070094 .register(URI.class).register(HashSet.class)
95 .register(DeviceId.class).register(PortNumber.class)
96 .register(NeighborSet.class).register(PolicyGroupIdentifier.class)
97 .register(PolicyGroupParams.class)
98 .register(GroupBucketIdentifier.class)
99 .register(GroupBucketIdentifier.BucketOutputType.class);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800100
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700101 protected DefaultGroupHandler(DeviceId deviceId, ApplicationId appId,
102 DeviceProperties config,
103 LinkService linkService,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700104 FlowObjectiveService flowObjService,
Charles Chan188ebf52015-12-23 00:15:11 -0800105 SegmentRoutingManager srManager) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800106 this.deviceId = checkNotNull(deviceId);
107 this.appId = checkNotNull(appId);
108 this.deviceConfig = checkNotNull(config);
109 this.linkService = checkNotNull(linkService);
Charles Chan0b4e6182015-11-03 10:42:14 -0800110 this.allSegmentIds = checkNotNull(config.getAllDeviceSegmentIds());
111 try {
112 this.nodeSegmentId = config.getSegmentId(deviceId);
113 this.isEdgeRouter = config.isEdgeDevice(deviceId);
114 this.nodeMacAddr = checkNotNull(config.getDeviceMac(deviceId));
115 } catch (DeviceConfigNotFoundException e) {
116 log.warn(e.getMessage()
117 + " Skipping value assignment in DefaultGroupHandler");
118 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700119 this.flowObjectiveService = flowObjService;
Charles Chane849c192016-01-11 18:28:54 -0800120 this.nsNextObjStore = srManager.nsNextObjStore;
121 this.subnetNextObjStore = srManager.subnetNextObjStore;
122 this.portNextObjStore = srManager.portNextObjStore;
123 this.xConnectNextObjStore = srManager.xConnectNextObjStore;
Charles Chan188ebf52015-12-23 00:15:11 -0800124 this.srManager = srManager;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800125
126 populateNeighborMaps();
127 }
128
129 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700130 * Creates a group handler object based on the type of device. If device is
131 * of edge type it returns edge group handler, else it returns transit group
132 * handler.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800133 *
134 * @param deviceId device identifier
135 * @param appId application identifier
136 * @param config interface to retrieve the device properties
137 * @param linkService link service object
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700138 * @param flowObjService flow objective service object
Charles Chane849c192016-01-11 18:28:54 -0800139 * @param srManager segment routing manager
Charles Chan0b4e6182015-11-03 10:42:14 -0800140 * @throws DeviceConfigNotFoundException if the device configuration is not found
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800141 * @return default group handler type
142 */
Saurav Das4ce45962015-11-24 23:21:05 -0800143 public static DefaultGroupHandler createGroupHandler(
144 DeviceId deviceId,
145 ApplicationId appId,
146 DeviceProperties config,
147 LinkService linkService,
148 FlowObjectiveService flowObjService,
Charles Chan188ebf52015-12-23 00:15:11 -0800149 SegmentRoutingManager srManager)
Saurav Das4ce45962015-11-24 23:21:05 -0800150 throws DeviceConfigNotFoundException {
Charles Chan0b4e6182015-11-03 10:42:14 -0800151 // handle possible exception in the caller
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800152 if (config.isEdgeDevice(deviceId)) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700153 return new DefaultEdgeGroupHandler(deviceId, appId, config,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700154 linkService,
155 flowObjService,
Charles Chan188ebf52015-12-23 00:15:11 -0800156 srManager
157 );
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800158 } else {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700159 return new DefaultTransitGroupHandler(deviceId, appId, config,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700160 linkService,
161 flowObjService,
Charles Chan188ebf52015-12-23 00:15:11 -0800162 srManager);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800163 }
164 }
165
166 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700167 * Creates the auto created groups for this device based on the current
168 * snapshot of the topology.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800169 */
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700170 // Empty implementations to be overridden by derived classes
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800171 public void createGroups() {
172 }
173
174 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700175 * Performs group creation or update procedures when a new link is
176 * discovered on this device.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800177 *
178 * @param newLink new neighbor link
Charles Chane849c192016-01-11 18:28:54 -0800179 * @param isMaster true if local instance is the master
180 *
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800181 */
Saurav Das8a0732e2015-11-20 15:27:53 -0800182 public void linkUp(Link newLink, boolean isMaster) {
sanghob35a6192015-04-01 13:05:26 -0700183
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800184 if (newLink.type() != Link.Type.DIRECT) {
185 log.warn("linkUp: unknown link type");
186 return;
187 }
188
189 if (!newLink.src().deviceId().equals(deviceId)) {
190 log.warn("linkUp: deviceId{} doesn't match with link src{}",
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700191 deviceId, newLink.src().deviceId());
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800192 return;
193 }
194
Saurav Das8a0732e2015-11-20 15:27:53 -0800195 log.info("* LinkUP: Device {} linkUp at local port {} to neighbor {}", deviceId,
196 newLink.src().port(), newLink.dst().deviceId());
Charles Chan0b4e6182015-11-03 10:42:14 -0800197 MacAddress dstMac;
198 try {
199 dstMac = deviceConfig.getDeviceMac(newLink.dst().deviceId());
200 } catch (DeviceConfigNotFoundException e) {
201 log.warn(e.getMessage() + " Aborting linkUp.");
202 return;
203 }
204
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700205 addNeighborAtPort(newLink.dst().deviceId(),
206 newLink.src().port());
207 /*if (devicePortMap.get(newLink.dst().deviceId()) == null) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800208 // New Neighbor
209 newNeighbor(newLink);
210 } else {
211 // Old Neighbor
212 newPortToExistingNeighbor(newLink);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700213 }*/
214 Set<NeighborSet> nsSet = nsNextObjStore.keySet()
215 .stream()
216 .filter((nsStoreEntry) -> (nsStoreEntry.deviceId().equals(deviceId)))
217 .map((nsStoreEntry) -> (nsStoreEntry.neighborSet()))
218 .filter((ns) -> (ns.getDeviceIds()
219 .contains(newLink.dst().deviceId())))
220 .collect(Collectors.toSet());
221 log.trace("linkUp: nsNextObjStore contents for device {}:",
sangho0b2b6d12015-05-20 22:16:38 -0700222 deviceId,
223 nsSet);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700224 for (NeighborSet ns : nsSet) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700225 Integer nextId = nsNextObjStore.
226 get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
Saurav Das4ce45962015-11-24 23:21:05 -0800227 if (nextId != null && isMaster) {
Saurav Das423fe2b2015-12-04 10:52:59 -0800228 // Create the new bucket to be updated
229 TrafficTreatment.Builder tBuilder =
230 DefaultTrafficTreatment.builder();
231 tBuilder.setOutput(newLink.src().port())
232 .setEthDst(dstMac)
233 .setEthSrc(nodeMacAddr);
234 if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
235 tBuilder.pushMpls()
236 .copyTtlOut()
237 .setMpls(MplsLabel.mplsLabel(ns.getEdgeLabel()));
238 }
239 // setup metadata to pass to nextObjective - indicate the vlan on egress
240 // if needed by the switch pipeline. Since hashed next-hops are always to
241 // other neighboring routers, there is no subnet assigned on those ports.
242 TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
243 metabuilder.matchVlanId(
244 VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET));
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700245
Saurav Das423fe2b2015-12-04 10:52:59 -0800246 NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder()
247 .withId(nextId)
248 .withType(NextObjective.Type.HASHED)
249 .addTreatment(tBuilder.build())
250 .withMeta(metabuilder.build())
251 .fromApp(appId);
Saurav Das8a0732e2015-11-20 15:27:53 -0800252 log.info("**linkUp in device {}: Adding Bucket "
Saurav Das4ce45962015-11-24 23:21:05 -0800253 + "with Port {} to next object id {}",
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700254 deviceId,
255 newLink.src().port(),
Saurav Das4ce45962015-11-24 23:21:05 -0800256 nextId);
257 NextObjective nextObjective = nextObjBuilder.
258 addToExisting(new SRNextObjectiveContext(deviceId));
259 flowObjectiveService.next(deviceId, nextObjective);
Saurav Das423fe2b2015-12-04 10:52:59 -0800260
261 // the addition of a bucket may actually change the neighborset
262 // update the global store
263 /*
264 Set<DeviceId> neighbors = new HashSet<DeviceId>(ns.getDeviceIds());
265 boolean newadd = neighbors.add(newLink.dst().deviceId());
266 if (newadd) {
267 NeighborSet nsnew = new NeighborSet(neighbors, ns.getEdgeLabel());
268 nsNextObjStore.put(new NeighborSetNextObjectiveStoreKey(deviceId, nsnew),
269 nextId);
270 nsNextObjStore.remove(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
271 }*/
Saurav Das4ce45962015-11-24 23:21:05 -0800272 } else if (isMaster) {
Saurav Das8a0732e2015-11-20 15:27:53 -0800273 log.warn("linkUp in device {}, but global store has no record "
274 + "for neighbor-set {}", deviceId, ns);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700275 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800276 }
277 }
278
279 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700280 * Performs group recovery procedures when a port goes down on this device.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800281 *
282 * @param port port number that has gone down
Charles Chane849c192016-01-11 18:28:54 -0800283 * @param isMaster true if local instance is the master
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800284 */
Saurav Das423fe2b2015-12-04 10:52:59 -0800285 public void portDown(PortNumber port, boolean isMaster) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800286 if (portDeviceMap.get(port) == null) {
287 log.warn("portDown: unknown port");
288 return;
289 }
Charles Chan0b4e6182015-11-03 10:42:14 -0800290
Saurav Das80980c72016-03-23 11:22:49 -0700291 @SuppressWarnings("unused")
Charles Chan0b4e6182015-11-03 10:42:14 -0800292 MacAddress dstMac;
293 try {
294 dstMac = deviceConfig.getDeviceMac(portDeviceMap.get(port));
295 } catch (DeviceConfigNotFoundException e) {
296 log.warn(e.getMessage() + " Aborting portDown.");
297 return;
298 }
299
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700300 log.debug("Device {} portDown {} to neighbor {}", deviceId, port,
301 portDeviceMap.get(port));
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700302 /*Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(portDeviceMap
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700303 .get(port),
304 devicePortMap
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700305 .keySet());*/
306 Set<NeighborSet> nsSet = nsNextObjStore.keySet()
307 .stream()
308 .filter((nsStoreEntry) -> (nsStoreEntry.deviceId().equals(deviceId)))
309 .map((nsStoreEntry) -> (nsStoreEntry.neighborSet()))
310 .filter((ns) -> (ns.getDeviceIds()
311 .contains(portDeviceMap.get(port))))
312 .collect(Collectors.toSet());
Saurav Das423fe2b2015-12-04 10:52:59 -0800313 log.debug("portDown: nsNextObjStore contents for device {}:{}",
314 deviceId, nsSet);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800315 for (NeighborSet ns : nsSet) {
Saurav Das80980c72016-03-23 11:22:49 -0700316 NeighborSetNextObjectiveStoreKey nsStoreKey =
317 new NeighborSetNextObjectiveStoreKey(deviceId, ns);
318 Integer nextId = nsNextObjStore.get(nsStoreKey);
Saurav Das423fe2b2015-12-04 10:52:59 -0800319 if (nextId != null && isMaster) {
Saurav Das80980c72016-03-23 11:22:49 -0700320 // XXX This is a workaround for BUG (CORD-611) in current switches.
321 // Should be temporary because this workaround prevents correct
322 // functionality in LAG recovery.
323 log.info("**portDown port:{} in device {}: Invalidating nextId {}",
324 port, deviceId, nextId);
325 nsNextObjStore.remove(nsStoreKey);
326 /*
Saurav Das8a0732e2015-11-20 15:27:53 -0800327 log.info("**portDown in device {}: Removing Bucket "
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700328 + "with Port {} to next object id {}",
329 deviceId,
330 port,
331 nextId);
Saurav Das423fe2b2015-12-04 10:52:59 -0800332 // Create the bucket to be removed
333 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
334 .builder();
335 tBuilder.setOutput(port)
336 .setEthDst(dstMac)
337 .setEthSrc(nodeMacAddr);
338 if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
339 tBuilder.pushMpls()
340 .copyTtlOut()
341 .setMpls(MplsLabel.mplsLabel(ns.getEdgeLabel()));
342 }
343 NextObjective.Builder nextObjBuilder = DefaultNextObjective
344 .builder()
345 .withType(NextObjective.Type.HASHED) //same as original
346 .withId(nextId)
347 .fromApp(appId)
348 .addTreatment(tBuilder.build());
349 NextObjective nextObjective = nextObjBuilder.
350 removeFromExisting(new SRNextObjectiveContext(deviceId));
sangho834e4b02015-05-01 09:38:25 -0700351
Saurav Das423fe2b2015-12-04 10:52:59 -0800352 flowObjectiveService.next(deviceId, nextObjective);
Saurav Das80980c72016-03-23 11:22:49 -0700353 */
Saurav Das423fe2b2015-12-04 10:52:59 -0800354 // the removal of a bucket may actually change the neighborset
355 // update the global store
356 /*
357 Set<DeviceId> neighbors = new HashSet<DeviceId>(ns.getDeviceIds());
358 boolean removed = neighbors.remove(portDeviceMap.get(port));
359 if (removed) {
360 NeighborSet nsnew = new NeighborSet(neighbors, ns.getEdgeLabel());
361 nsNextObjStore.put(new NeighborSetNextObjectiveStoreKey(deviceId, nsnew),
362 nextId);
363 nsNextObjStore.remove(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
364 }*/
sangho834e4b02015-05-01 09:38:25 -0700365 }
366
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800367 }
368
369 devicePortMap.get(portDeviceMap.get(port)).remove(port);
370 portDeviceMap.remove(port);
371 }
372
373 /**
Saurav Das4ce45962015-11-24 23:21:05 -0800374 * Returns the next objective of type hashed associated with the neighborset.
375 * If there is no next objective for this neighborset, this method
Saurav Das8a0732e2015-11-20 15:27:53 -0800376 * would create a next objective and return. Optionally metadata can be
377 * passed in for the creation of the next objective.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800378 *
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700379 * @param ns neighborset
Saurav Das8a0732e2015-11-20 15:27:53 -0800380 * @param meta metadata passed into the creation of a Next Objective
381 * @return int if found or -1 if there are errors in the creation of the
382 * neighbor set.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800383 */
Saurav Das8a0732e2015-11-20 15:27:53 -0800384 public int getNextObjectiveId(NeighborSet ns, TrafficSelector meta) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700385 Integer nextId = nsNextObjStore.
386 get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700387 if (nextId == null) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700388 log.trace("getNextObjectiveId in device{}: Next objective id "
389 + "not found for {} and creating", deviceId, ns);
390 log.trace("getNextObjectiveId: nsNextObjStore contents for device {}: {}",
391 deviceId,
392 nsNextObjStore.entrySet()
393 .stream()
394 .filter((nsStoreEntry) ->
395 (nsStoreEntry.getKey().deviceId().equals(deviceId)))
396 .collect(Collectors.toList()));
Saurav Das8a0732e2015-11-20 15:27:53 -0800397 createGroupsFromNeighborsets(Collections.singleton(ns), meta);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700398 nextId = nsNextObjStore.
399 get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700400 if (nextId == null) {
401 log.warn("getNextObjectiveId: unable to create next objective");
402 return -1;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700403 } else {
404 log.debug("getNextObjectiveId in device{}: Next objective id {} "
Sho SHIMIZUaf973432015-09-11 14:24:50 -0700405 + "created for {}", deviceId, nextId, ns);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700406 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700407 } else {
408 log.trace("getNextObjectiveId in device{}: Next objective id {} "
Sho SHIMIZUaf973432015-09-11 14:24:50 -0700409 + "found for {}", deviceId, nextId, ns);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700410 }
Sho SHIMIZUaf973432015-09-11 14:24:50 -0700411 return nextId;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800412 }
413
sangho0b2b6d12015-05-20 22:16:38 -0700414 /**
Saurav Das4ce45962015-11-24 23:21:05 -0800415 * Returns the next objective of type broadcast associated with the subnet,
416 * or -1 if no such objective exists. Note that this method does NOT create
417 * the next objective as a side-effect. It is expected that is objective is
418 * created at startup from network configuration.
Charles Chanc42e84e2015-10-20 16:24:19 -0700419 *
420 * @param prefix subnet information
421 * @return int if found or -1
422 */
423 public int getSubnetNextObjectiveId(IpPrefix prefix) {
424 Integer nextId = subnetNextObjStore.
425 get(new SubnetNextObjectiveStoreKey(deviceId, prefix));
Charles Chan9f676b62015-10-29 14:58:10 -0700426
427 return (nextId != null) ? nextId : -1;
Charles Chanc42e84e2015-10-20 16:24:19 -0700428 }
429
430 /**
Saurav Das4ce45962015-11-24 23:21:05 -0800431 * Returns the next objective of type simple associated with the port on the
432 * device, given the treatment. Different treatments to the same port result
433 * in different next objectives. If no such objective exists, this method
434 * creates one and returns the id. Optionally metadata can be passed in for
435 * the creation of the objective.
436 *
437 * @param portNum the port number for the simple next objective
438 * @param treatment the actions to apply on the packets (should include outport)
439 * @param meta optional metadata passed into the creation of the next objective
440 * @return int if found or created, -1 if there are errors during the
441 * creation of the next objective.
442 */
443 public int getPortNextObjectiveId(PortNumber portNum, TrafficTreatment treatment,
444 TrafficSelector meta) {
Charles Chane849c192016-01-11 18:28:54 -0800445 Integer nextId = portNextObjStore
446 .get(new PortNextObjectiveStoreKey(deviceId, portNum, treatment));
Saurav Das4ce45962015-11-24 23:21:05 -0800447 if (nextId == null) {
448 log.trace("getPortNextObjectiveId in device{}: Next objective id "
449 + "not found for {} and {} creating", deviceId, portNum);
450 createGroupFromPort(portNum, treatment, meta);
451 nextId = portNextObjStore.get(
452 new PortNextObjectiveStoreKey(deviceId, portNum, treatment));
453 if (nextId == null) {
454 log.warn("getPortNextObjectiveId: unable to create next obj"
Charles Chane849c192016-01-11 18:28:54 -0800455 + "for dev:{} port:{}", deviceId, portNum);
456 return -1;
457 }
458 }
459 return nextId;
460 }
461
462 /**
463 * Returns the next objective ID of type broadcast associated with the VLAN
464 * cross-connection.
465 *
466 * @param vlanId VLAN ID for the cross-connection
467 * @return int if found or created, -1 if there are errors during the
468 * creation of the next objective
469 */
470 public int getXConnectNextObjectiveId(VlanId vlanId) {
471 Integer nextId = xConnectNextObjStore
472 .get(new XConnectNextObjectiveStoreKey(deviceId, vlanId));
473 if (nextId == null) {
474 log.trace("getXConnectNextObjectiveId: Next objective id "
475 + "not found for device {} and vlan {}. Creating", deviceId, vlanId);
476 createGroupsForXConnect(deviceId);
477 nextId = xConnectNextObjStore.get(
478 new XConnectNextObjectiveStoreKey(deviceId, vlanId));
479 if (nextId == null) {
480 log.warn("getXConnectNextObjectiveId: Next objective id "
481 + "not found for device {} and vlan {}.", deviceId, vlanId);
Saurav Das4ce45962015-11-24 23:21:05 -0800482 return -1;
483 }
484 }
485 return nextId;
486 }
487
488 /**
sangho0b2b6d12015-05-20 22:16:38 -0700489 * Checks if the next objective ID (group) for the neighbor set exists or not.
490 *
491 * @param ns neighbor set to check
492 * @return true if it exists, false otherwise
493 */
494 public boolean hasNextObjectiveId(NeighborSet ns) {
495 Integer nextId = nsNextObjStore.
496 get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
497 if (nextId == null) {
498 return false;
499 }
500
501 return true;
502 }
503
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700504 // Empty implementation
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800505 protected void newNeighbor(Link newLink) {
506 }
507
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700508 // Empty implementation
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800509 protected void newPortToExistingNeighbor(Link newLink) {
510 }
511
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700512 // Empty implementation
513 protected Set<NeighborSet>
514 computeImpactedNeighborsetForPortEvent(DeviceId impactedNeighbor,
515 Set<DeviceId> updatedNeighbors) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800516 return null;
517 }
518
519 private void populateNeighborMaps() {
520 Set<Link> outgoingLinks = linkService.getDeviceEgressLinks(deviceId);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700521 for (Link link : outgoingLinks) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800522 if (link.type() != Link.Type.DIRECT) {
523 continue;
524 }
525 addNeighborAtPort(link.dst().deviceId(), link.src().port());
526 }
527 }
528
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700529 protected void addNeighborAtPort(DeviceId neighborId,
530 PortNumber portToNeighbor) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800531 // Update DeviceToPort database
532 log.debug("Device {} addNeighborAtPort: neighbor {} at port {}",
533 deviceId, neighborId, portToNeighbor);
Saurav Das8a0732e2015-11-20 15:27:53 -0800534 Set<PortNumber> ports = Collections
535 .newSetFromMap(new ConcurrentHashMap<PortNumber, Boolean>());
536 ports.add(portToNeighbor);
537 Set<PortNumber> portnums = devicePortMap.putIfAbsent(neighborId, ports);
538 if (portnums != null) {
539 portnums.add(portToNeighbor);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800540 }
541
542 // Update portToDevice database
Saurav Das8a0732e2015-11-20 15:27:53 -0800543 DeviceId prev = portDeviceMap.putIfAbsent(portToNeighbor, neighborId);
544 if (prev != null) {
545 log.warn("Device: {} port: {} has neighbor: {}. NOT updating "
546 + "to neighbor: {}", deviceId, portToNeighbor, prev, neighborId);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800547 }
548 }
549
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700550 protected Set<Set<DeviceId>> getPowerSetOfNeighbors(Set<DeviceId> neighbors) {
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -0700551 List<DeviceId> list = new ArrayList<>(neighbors);
552 Set<Set<DeviceId>> sets = new HashSet<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800553 // get the number of elements in the neighbors
554 int elements = list.size();
555 // the number of members of a power set is 2^n
556 // including the empty set
557 int powerElements = (1 << elements);
558
559 // run a binary counter for the number of power elements
560 // NOTE: Exclude empty set
561 for (long i = 1; i < powerElements; i++) {
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -0700562 Set<DeviceId> neighborSubSet = new HashSet<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800563 for (int j = 0; j < elements; j++) {
564 if ((i >> j) % 2 == 1) {
565 neighborSubSet.add(list.get(j));
566 }
567 }
568 sets.add(neighborSubSet);
569 }
570 return sets;
571 }
572
573 private boolean isSegmentIdSameAsNodeSegmentId(DeviceId deviceId, int sId) {
Charles Chan0b4e6182015-11-03 10:42:14 -0800574 int segmentId;
575 try {
576 segmentId = deviceConfig.getSegmentId(deviceId);
577 } catch (DeviceConfigNotFoundException e) {
578 log.warn(e.getMessage() + " Aborting isSegmentIdSameAsNodeSegmentId.");
579 return false;
580 }
581
582 return segmentId == sId;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800583 }
584
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700585 protected List<Integer> getSegmentIdsTobePairedWithNeighborSet(Set<DeviceId> neighbors) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800586
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -0700587 List<Integer> nsSegmentIds = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800588
sanghob35a6192015-04-01 13:05:26 -0700589 // Always pair up with no edge label
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700590 // If (neighbors.size() == 1) {
sanghob35a6192015-04-01 13:05:26 -0700591 nsSegmentIds.add(-1);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700592 // }
sanghob35a6192015-04-01 13:05:26 -0700593
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800594 // Filter out SegmentIds matching with the
595 // nodes in the combo
596 for (Integer sId : allSegmentIds) {
597 if (sId.equals(nodeSegmentId)) {
598 continue;
599 }
600 boolean filterOut = false;
601 // Check if the edge label being set is of
602 // any node in the Neighbor set
603 for (DeviceId deviceId : neighbors) {
604 if (isSegmentIdSameAsNodeSegmentId(deviceId, sId)) {
605 filterOut = true;
606 break;
607 }
608 }
609 if (!filterOut) {
610 nsSegmentIds.add(sId);
611 }
612 }
613 return nsSegmentIds;
614 }
615
sangho1e575652015-05-14 00:39:53 -0700616 /**
617 * Creates Groups from a set of NeighborSet given.
618 *
619 * @param nsSet a set of NeighborSet
Saurav Das8a0732e2015-11-20 15:27:53 -0800620 * @param meta metadata passed into the creation of a Next Objective
sangho1e575652015-05-14 00:39:53 -0700621 */
Saurav Das8a0732e2015-11-20 15:27:53 -0800622 public void createGroupsFromNeighborsets(Set<NeighborSet> nsSet,
623 TrafficSelector meta) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800624 for (NeighborSet ns : nsSet) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700625 int nextId = flowObjectiveService.allocateNextId();
626 NextObjective.Builder nextObjBuilder = DefaultNextObjective
627 .builder().withId(nextId)
628 .withType(NextObjective.Type.HASHED).fromApp(appId);
Saurav Das8a0732e2015-11-20 15:27:53 -0800629 for (DeviceId neighborId : ns.getDeviceIds()) {
630 if (devicePortMap.get(neighborId) == null) {
631 log.warn("Neighbor {} is not in the port map yet for dev:{}",
632 neighborId, deviceId);
sangho834e4b02015-05-01 09:38:25 -0700633 return;
Saurav Das8a0732e2015-11-20 15:27:53 -0800634 } else if (devicePortMap.get(neighborId).size() == 0) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700635 log.warn("There are no ports for "
Saurav Das8a0732e2015-11-20 15:27:53 -0800636 + "the Device {} in the port map yet", neighborId);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700637 return;
sangho834e4b02015-05-01 09:38:25 -0700638 }
639
Saurav Das8a0732e2015-11-20 15:27:53 -0800640 MacAddress neighborMac;
Charles Chan0b4e6182015-11-03 10:42:14 -0800641 try {
Saurav Das8a0732e2015-11-20 15:27:53 -0800642 neighborMac = deviceConfig.getDeviceMac(neighborId);
Charles Chan0b4e6182015-11-03 10:42:14 -0800643 } catch (DeviceConfigNotFoundException e) {
644 log.warn(e.getMessage() + " Aborting createGroupsFromNeighborsets.");
645 return;
646 }
647
Saurav Das8a0732e2015-11-20 15:27:53 -0800648 for (PortNumber sp : devicePortMap.get(neighborId)) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700649 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
650 .builder();
Saurav Das8a0732e2015-11-20 15:27:53 -0800651 tBuilder.setEthDst(neighborMac)
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700652 .setEthSrc(nodeMacAddr);
653 if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
Charles Chan68aa62d2015-11-09 16:37:23 -0800654 tBuilder.pushMpls()
655 .copyTtlOut()
656 .setMpls(MplsLabel.mplsLabel(ns.getEdgeLabel()));
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700657 }
Saurav Das8a0732e2015-11-20 15:27:53 -0800658 tBuilder.setOutput(sp);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700659 nextObjBuilder.addTreatment(tBuilder.build());
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800660 }
661 }
Saurav Das8a0732e2015-11-20 15:27:53 -0800662 if (meta != null) {
Saurav Das4ce45962015-11-24 23:21:05 -0800663 nextObjBuilder.withMeta(meta);
Saurav Das8a0732e2015-11-20 15:27:53 -0800664 }
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700665 NextObjective nextObj = nextObjBuilder.
666 add(new SRNextObjectiveContext(deviceId));
Saurav Das8a0732e2015-11-20 15:27:53 -0800667 log.info("**createGroupsFromNeighborsets: Submited "
668 + "next objective {} in device {}",
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700669 nextId, deviceId);
Saurav Das8a0732e2015-11-20 15:27:53 -0800670 flowObjectiveService.next(deviceId, nextObj);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700671 nsNextObjStore.put(new NeighborSetNextObjectiveStoreKey(deviceId, ns),
672 nextId);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800673 }
674 }
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700675
Saurav Das4ce45962015-11-24 23:21:05 -0800676 /**
677 * Creates broadcast groups for all ports in the same configured subnet.
Saurav Das4ce45962015-11-24 23:21:05 -0800678 */
Charles Chanc42e84e2015-10-20 16:24:19 -0700679 public void createGroupsFromSubnetConfig() {
Saurav Das7a1ffca2016-03-28 19:00:18 -0700680 Map<Ip4Prefix, List<PortNumber>> subnetPortMap;
681 try {
682 subnetPortMap = this.deviceConfig.getSubnetPortsMap(this.deviceId);
683 } catch (DeviceConfigNotFoundException e) {
684 log.warn(e.getMessage()
685 + " Not creating broadcast groups for device: " + deviceId);
686 return;
687 }
Charles Chanc42e84e2015-10-20 16:24:19 -0700688 // Construct a broadcast group for each subnet
689 subnetPortMap.forEach((subnet, ports) -> {
Charles Chan9f676b62015-10-29 14:58:10 -0700690 SubnetNextObjectiveStoreKey key =
691 new SubnetNextObjectiveStoreKey(deviceId, subnet);
692
693 if (subnetNextObjStore.containsKey(key)) {
694 log.debug("Broadcast group for device {} and subnet {} exists",
695 deviceId, subnet);
696 return;
697 }
698
Charles Chan188ebf52015-12-23 00:15:11 -0800699 VlanId assignedVlanId =
700 srManager.getSubnetAssignedVlanId(this.deviceId, subnet);
701 TrafficSelector metadata =
702 DefaultTrafficSelector.builder().matchVlanId(assignedVlanId).build();
703
Charles Chanc42e84e2015-10-20 16:24:19 -0700704 int nextId = flowObjectiveService.allocateNextId();
705
706 NextObjective.Builder nextObjBuilder = DefaultNextObjective
707 .builder().withId(nextId)
Charles Chan188ebf52015-12-23 00:15:11 -0800708 .withType(NextObjective.Type.BROADCAST).fromApp(appId)
709 .withMeta(metadata);
Charles Chanc42e84e2015-10-20 16:24:19 -0700710
711 ports.forEach(port -> {
712 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
Saurav Das4f980082015-11-05 13:39:15 -0800713 tBuilder.popVlan();
Charles Chanc42e84e2015-10-20 16:24:19 -0700714 tBuilder.setOutput(port);
715 nextObjBuilder.addTreatment(tBuilder.build());
716 });
717
718 NextObjective nextObj = nextObjBuilder.add();
719 flowObjectiveService.next(deviceId, nextObj);
720 log.debug("createGroupFromSubnetConfig: Submited "
721 + "next objective {} in device {}",
722 nextId, deviceId);
Charles Chan9f676b62015-10-29 14:58:10 -0700723
Charles Chanc42e84e2015-10-20 16:24:19 -0700724 subnetNextObjStore.put(key, nextId);
725 });
726 }
727
Charles Chane849c192016-01-11 18:28:54 -0800728 /**
729 * Creates broadcast groups for VLAN cross-connect ports.
730 *
731 * @param deviceId the DPID of the switch
732 */
733 public void createGroupsForXConnect(DeviceId deviceId) {
734 Map<VlanId, List<ConnectPoint>> xConnectsForDevice = deviceConfig.getXConnects();
735
736 xConnectsForDevice.forEach((vlanId, connectPoints) -> {
737 // Only proceed the xConnect for given device
738 for (ConnectPoint connectPoint : connectPoints) {
739 if (!connectPoint.deviceId().equals(deviceId)) {
740 return;
741 }
742 }
743
744 // Check if the next obj is already in the store
745 XConnectNextObjectiveStoreKey key =
746 new XConnectNextObjectiveStoreKey(deviceId, vlanId);
747 if (xConnectNextObjStore.containsKey(key)) {
748 log.debug("Cross-connect Broadcast group for device {} and vlanId {} exists",
749 deviceId, vlanId);
750 return;
751 }
752
753 TrafficSelector metadata =
754 DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
755 int nextId = flowObjectiveService.allocateNextId();
756
757 NextObjective.Builder nextObjBuilder = DefaultNextObjective
758 .builder().withId(nextId)
759 .withType(NextObjective.Type.BROADCAST).fromApp(appId)
760 .withMeta(metadata);
761
762 connectPoints.forEach(connectPoint -> {
763 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
764 tBuilder.setOutput(connectPoint.port());
765 nextObjBuilder.addTreatment(tBuilder.build());
766 });
767
768 NextObjective nextObj = nextObjBuilder.add();
769 flowObjectiveService.next(deviceId, nextObj);
770 log.debug("createGroupsForXConnect: Submited next objective {} in device {}",
771 nextId, deviceId);
772 xConnectNextObjStore.put(key, nextId);
773 });
774 }
775
Saurav Das4ce45962015-11-24 23:21:05 -0800776
777 /**
778 * Create simple next objective for a single port. The treatments can include
779 * all outgoing actions that need to happen on the packet.
780 *
781 * @param portNum the outgoing port on the device
782 * @param treatment the actions to apply on the packets (should include outport)
783 * @param meta optional data to pass to the driver
784 */
785 public void createGroupFromPort(PortNumber portNum, TrafficTreatment treatment,
786 TrafficSelector meta) {
787 int nextId = flowObjectiveService.allocateNextId();
788 PortNextObjectiveStoreKey key = new PortNextObjectiveStoreKey(
789 deviceId, portNum, treatment);
790
791 NextObjective.Builder nextObjBuilder = DefaultNextObjective
792 .builder().withId(nextId)
793 .withType(NextObjective.Type.SIMPLE)
794 .addTreatment(treatment)
795 .fromApp(appId)
796 .withMeta(meta);
797
798 NextObjective nextObj = nextObjBuilder.add();
799 flowObjectiveService.next(deviceId, nextObj);
800 log.debug("createGroupFromPort: Submited next objective {} in device {} "
801 + "for port {}", nextId, deviceId, portNum);
802
803 portNextObjStore.put(key, nextId);
804 }
805
sangho1e575652015-05-14 00:39:53 -0700806 /**
807 * Removes groups for the next objective ID given.
808 *
809 * @param objectiveId next objective ID to remove
810 * @return true if succeeds, false otherwise
811 */
812 public boolean removeGroup(int objectiveId) {
813
814 if (nsNextObjStore.containsValue(objectiveId)) {
815 NextObjective.Builder nextObjBuilder = DefaultNextObjective
816 .builder().withId(objectiveId)
817 .withType(NextObjective.Type.HASHED).fromApp(appId);
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700818 NextObjective nextObjective = nextObjBuilder.
819 remove(new SRNextObjectiveContext(deviceId));
Saurav Das8a0732e2015-11-20 15:27:53 -0800820 log.info("**removeGroup: Submited "
821 + "next objective {} in device {}",
822 objectiveId, deviceId);
sangho1e575652015-05-14 00:39:53 -0700823 flowObjectiveService.next(deviceId, nextObjective);
824
825 for (Map.Entry<NeighborSetNextObjectiveStoreKey, Integer> entry: nsNextObjStore.entrySet()) {
826 if (entry.getValue().equals(objectiveId)) {
827 nsNextObjStore.remove(entry.getKey());
828 break;
829 }
830 }
sangho0b2b6d12015-05-20 22:16:38 -0700831 return true;
sangho1e575652015-05-14 00:39:53 -0700832 }
833
834 return false;
835 }
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700836
Charles Chane849c192016-01-11 18:28:54 -0800837 /**
838 * Removes all groups from all next objective stores.
839 */
Saurav Das423fe2b2015-12-04 10:52:59 -0800840 public void removeAllGroups() {
841 for (Map.Entry<NeighborSetNextObjectiveStoreKey, Integer> entry:
842 nsNextObjStore.entrySet()) {
843 removeGroup(entry.getValue());
844 }
845 for (Map.Entry<PortNextObjectiveStoreKey, Integer> entry:
846 portNextObjStore.entrySet()) {
847 removeGroup(entry.getValue());
848 }
849 for (Map.Entry<SubnetNextObjectiveStoreKey, Integer> entry:
850 subnetNextObjStore.entrySet()) {
851 removeGroup(entry.getValue());
852 }
853 // should probably clean local stores port-neighbor
854 }
855
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700856 protected static class SRNextObjectiveContext implements ObjectiveContext {
857 final DeviceId deviceId;
858
859 SRNextObjectiveContext(DeviceId deviceId) {
860 this.deviceId = deviceId;
861 }
862 @Override
863 public void onSuccess(Objective objective) {
Saurav Das8a0732e2015-11-20 15:27:53 -0800864 log.info("Next objective {} operation successful in device {}",
865 objective.id(), deviceId);
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700866 }
867
868 @Override
869 public void onError(Objective objective, ObjectiveError error) {
870 log.warn("Next objective {} operation failed with error: {} in device {}",
Saurav Das8a0732e2015-11-20 15:27:53 -0800871 objective.id(), error, deviceId);
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700872 }
873 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800874}