blob: 7a1174020c0cb660a3f89cd3b849b009b104193c [file] [log] [blame]
sangho80f11cb2015-04-01 13:05:26 -07001/*
Brian O'Connor43b53542016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
sangho80f11cb2015-04-01 13:05:26 -07003 *
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 */
16package org.onosproject.segmentrouting;
17
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
sangho27462c62015-05-14 00:39:53 -070023import org.apache.felix.scr.annotations.Service;
sangho80f11cb2015-04-01 13:05:26 -070024import org.onlab.packet.Ethernet;
Charles Chan77277672015-10-20 16:24:19 -070025import org.onlab.packet.IPv4;
Charles Chan77277672015-10-20 16:24:19 -070026import org.onlab.packet.Ip4Prefix;
27import org.onlab.packet.IpAddress;
28import org.onlab.packet.IpPrefix;
Jonathan Hart54541d12016-04-12 15:39:44 -070029import org.onlab.packet.MacAddress;
30import org.onlab.packet.VlanId;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070031import org.onlab.util.KryoNamespace;
Saurav Dasc3604f12016-03-23 11:22:49 -070032import org.onosproject.cfg.ComponentConfigService;
sangho80f11cb2015-04-01 13:05:26 -070033import org.onosproject.core.ApplicationId;
34import org.onosproject.core.CoreService;
35import org.onosproject.event.Event;
Charles Chanc91c8782016-03-30 17:54:24 -070036import org.onosproject.incubator.net.config.basics.McastConfig;
Jonathan Hart54541d12016-04-12 15:39:44 -070037import org.onosproject.mastership.MastershipService;
Charles Chan77277672015-10-20 16:24:19 -070038import org.onosproject.net.ConnectPoint;
Jonathan Hart54541d12016-04-12 15:39:44 -070039import org.onosproject.net.Device;
40import org.onosproject.net.DeviceId;
41import org.onosproject.net.Link;
42import org.onosproject.net.Port;
Charles Chanf4586112015-11-09 16:37:23 -080043import org.onosproject.net.PortNumber;
Charles Chan72f556a2015-10-05 17:50:33 -070044import org.onosproject.net.config.ConfigFactory;
45import org.onosproject.net.config.NetworkConfigEvent;
Charles Chan72f556a2015-10-05 17:50:33 -070046import org.onosproject.net.config.NetworkConfigListener;
Jonathan Hart54541d12016-04-12 15:39:44 -070047import org.onosproject.net.config.NetworkConfigRegistry;
Charles Chan72f556a2015-10-05 17:50:33 -070048import org.onosproject.net.config.basics.SubjectFactories;
Jonathan Hart54541d12016-04-12 15:39:44 -070049import org.onosproject.net.device.DeviceEvent;
50import org.onosproject.net.device.DeviceListener;
51import org.onosproject.net.device.DeviceService;
Charles Chanf4586112015-11-09 16:37:23 -080052import org.onosproject.net.flow.DefaultTrafficSelector;
53import org.onosproject.net.flow.DefaultTrafficTreatment;
54import org.onosproject.net.flow.TrafficSelector;
55import org.onosproject.net.flow.TrafficTreatment;
56import org.onosproject.net.flowobjective.DefaultForwardingObjective;
Jonathan Hart54541d12016-04-12 15:39:44 -070057import org.onosproject.net.flowobjective.FlowObjectiveService;
Charles Chanf4586112015-11-09 16:37:23 -080058import org.onosproject.net.flowobjective.ForwardingObjective;
59import org.onosproject.net.flowobjective.Objective;
60import org.onosproject.net.flowobjective.ObjectiveContext;
61import org.onosproject.net.flowobjective.ObjectiveError;
62import org.onosproject.net.host.HostEvent;
63import org.onosproject.net.host.HostListener;
Charles Chanc91c8782016-03-30 17:54:24 -070064import org.onosproject.net.mcast.McastEvent;
65import org.onosproject.net.mcast.McastListener;
66import org.onosproject.net.mcast.MulticastRouteService;
67import org.onosproject.net.packet.PacketPriority;
68import org.onosproject.net.topology.TopologyService;
69import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
70import org.onosproject.segmentrouting.config.DeviceConfiguration;
71import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
72import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
73import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
74import org.onosproject.segmentrouting.grouphandler.NeighborSet;
75import org.onosproject.segmentrouting.grouphandler.NeighborSetNextObjectiveStoreKey;
76import org.onosproject.segmentrouting.grouphandler.PortNextObjectiveStoreKey;
sangho80f11cb2015-04-01 13:05:26 -070077import org.onosproject.net.host.HostService;
sangho80f11cb2015-04-01 13:05:26 -070078import org.onosproject.net.link.LinkEvent;
79import org.onosproject.net.link.LinkListener;
80import org.onosproject.net.link.LinkService;
81import org.onosproject.net.packet.InboundPacket;
82import org.onosproject.net.packet.PacketContext;
83import org.onosproject.net.packet.PacketProcessor;
84import org.onosproject.net.packet.PacketService;
Charles Chan77277672015-10-20 16:24:19 -070085import org.onosproject.segmentrouting.grouphandler.SubnetNextObjectiveStoreKey;
Charles Chanb7f75ac2016-01-11 18:28:54 -080086import org.onosproject.segmentrouting.grouphandler.XConnectNextObjectiveStoreKey;
Jonathan Hart54541d12016-04-12 15:39:44 -070087import org.onosproject.store.serializers.KryoNamespaces;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070088import org.onosproject.store.service.EventuallyConsistentMap;
89import org.onosproject.store.service.EventuallyConsistentMapBuilder;
90import org.onosproject.store.service.StorageService;
91import org.onosproject.store.service.WallClockTimestamp;
sangho80f11cb2015-04-01 13:05:26 -070092import org.slf4j.Logger;
93import org.slf4j.LoggerFactory;
94
Saurav Das7c305372015-10-28 12:39:42 -070095import java.util.Collections;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070096import java.util.HashSet;
sangho27462c62015-05-14 00:39:53 -070097import java.util.List;
sangho80f11cb2015-04-01 13:05:26 -070098import java.util.Map;
Charles Chande6655c2015-12-23 00:15:11 -080099import java.util.Optional;
Saurav Das7c305372015-10-28 12:39:42 -0700100import java.util.Set;
sangho80f11cb2015-04-01 13:05:26 -0700101import java.util.concurrent.ConcurrentHashMap;
102import java.util.concurrent.ConcurrentLinkedQueue;
103import java.util.concurrent.Executors;
104import java.util.concurrent.ScheduledExecutorService;
105import java.util.concurrent.ScheduledFuture;
106import java.util.concurrent.TimeUnit;
107
Charles Chand6d25332016-02-26 22:19:52 -0800108import static com.google.common.base.Preconditions.checkState;
109
Jonathan Hart54541d12016-04-12 15:39:44 -0700110
Charles Chanb7f75ac2016-01-11 18:28:54 -0800111/**
112 * Segment routing manager.
113 */
Jonathan Hart54541d12016-04-12 15:39:44 -0700114@Service
115@Component(immediate = true)
sangho27462c62015-05-14 00:39:53 -0700116public class SegmentRoutingManager implements SegmentRoutingService {
sangho80f11cb2015-04-01 13:05:26 -0700117
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700118 private static Logger log = LoggerFactory
119 .getLogger(SegmentRoutingManager.class);
sangho80f11cb2015-04-01 13:05:26 -0700120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
122 protected CoreService coreService;
123
124 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sangho80f11cb2015-04-01 13:05:26 -0700125 protected PacketService packetService;
126
127 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sangho80f11cb2015-04-01 13:05:26 -0700128 protected HostService hostService;
129
130 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
131 protected DeviceService deviceService;
132
133 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700134 protected FlowObjectiveService flowObjectiveService;
sangho80f11cb2015-04-01 13:05:26 -0700135
136 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
137 protected LinkService linkService;
138
139 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sangho80f11cb2015-04-01 13:05:26 -0700140 protected MastershipService mastershipService;
sangho27462c62015-05-14 00:39:53 -0700141
Charles Chan82ab1932016-01-30 23:22:37 -0800142 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
143 protected StorageService storageService;
144
145 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
146 protected NetworkConfigRegistry cfgService;
147
Saurav Dasc3604f12016-03-23 11:22:49 -0700148 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
149 protected ComponentConfigService compCfgService;
150
Charles Chanc91c8782016-03-30 17:54:24 -0700151 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
152 protected MulticastRouteService multicastRouteService;
153
154 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
155 protected TopologyService topologyService;
156
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700157 protected ArpHandler arpHandler = null;
158 protected IcmpHandler icmpHandler = null;
159 protected IpHandler ipHandler = null;
160 protected RoutingRulePopulator routingRulePopulator = null;
sangho80f11cb2015-04-01 13:05:26 -0700161 protected ApplicationId appId;
sangho9b169e32015-04-14 16:27:13 -0700162 protected DeviceConfiguration deviceConfiguration = null;
sangho80f11cb2015-04-01 13:05:26 -0700163
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700164 private DefaultRoutingHandler defaultRoutingHandler = null;
sangho27462c62015-05-14 00:39:53 -0700165 private TunnelHandler tunnelHandler = null;
166 private PolicyHandler policyHandler = null;
Charles Chan2b078ae2015-10-14 11:24:40 -0700167 private InternalPacketProcessor processor = null;
168 private InternalLinkListener linkListener = null;
169 private InternalDeviceListener deviceListener = null;
Charles Chan82ab1932016-01-30 23:22:37 -0800170 private NetworkConfigEventHandler netcfgHandler = null;
Charles Chanc91c8782016-03-30 17:54:24 -0700171 private McastEventHandler mcastEventHandler = null;
sangho80f11cb2015-04-01 13:05:26 -0700172 private InternalEventHandler eventHandler = new InternalEventHandler();
Charles Chan82ab1932016-01-30 23:22:37 -0800173 private final InternalHostListener hostListener = new InternalHostListener();
Charles Chanc91c8782016-03-30 17:54:24 -0700174 private final InternalConfigListener cfgListener = new InternalConfigListener(this);
175 private final InternalMcastListener mcastListener = new InternalMcastListener();
sangho80f11cb2015-04-01 13:05:26 -0700176
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700177 private ScheduledExecutorService executorService = Executors
178 .newScheduledThreadPool(1);
sangho80f11cb2015-04-01 13:05:26 -0700179
Saurav Das2d94d312015-11-24 23:21:05 -0800180 @SuppressWarnings("unused")
sangho80f11cb2015-04-01 13:05:26 -0700181 private static ScheduledFuture<?> eventHandlerFuture = null;
Saurav Das2d94d312015-11-24 23:21:05 -0800182 @SuppressWarnings("rawtypes")
sangho80f11cb2015-04-01 13:05:26 -0700183 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>();
Charles Chanf4586112015-11-09 16:37:23 -0800184 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
Charles Chanb7f75ac2016-01-11 18:28:54 -0800185 new ConcurrentHashMap<>();
186 /**
187 * Per device next objective ID store with (device id + neighbor set) as key.
188 */
189 public EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
Charles Chanf4586112015-11-09 16:37:23 -0800190 nsNextObjStore = null;
Charles Chanb7f75ac2016-01-11 18:28:54 -0800191 /**
192 * Per device next objective ID store with (device id + subnet) as key.
193 */
194 public EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
Charles Chanf4586112015-11-09 16:37:23 -0800195 subnetNextObjStore = null;
Charles Chanb7f75ac2016-01-11 18:28:54 -0800196 /**
197 * Per device next objective ID store with (device id + port) as key.
198 */
199 public EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
Saurav Das2d94d312015-11-24 23:21:05 -0800200 portNextObjStore = null;
Charles Chanb7f75ac2016-01-11 18:28:54 -0800201 /**
202 * Per cross-connect objective ID store with VLAN ID as key.
203 */
204 public EventuallyConsistentMap<XConnectNextObjectiveStoreKey, Integer>
205 xConnectNextObjStore = null;
Saurav Das7c305372015-10-28 12:39:42 -0700206 // Per device, per-subnet assigned-vlans store, with (device id + subnet
207 // IPv4 prefix) as key
208 private EventuallyConsistentMap<SubnetAssignedVidStoreKey, VlanId>
Charles Chanb7f75ac2016-01-11 18:28:54 -0800209 subnetVidStore = null;
Saurav Das2d94d312015-11-24 23:21:05 -0800210 private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
211 private EventuallyConsistentMap<String, Policy> policyStore = null;
sangho4a5c42a2015-05-20 22:16:38 -0700212
Charles Chanc91c8782016-03-30 17:54:24 -0700213 private final ConfigFactory<DeviceId, SegmentRoutingDeviceConfig> deviceConfigFactory =
Charles Chan82ab1932016-01-30 23:22:37 -0800214 new ConfigFactory<DeviceId, SegmentRoutingDeviceConfig>(SubjectFactories.DEVICE_SUBJECT_FACTORY,
Charles Chanc91c8782016-03-30 17:54:24 -0700215 SegmentRoutingDeviceConfig.class, "segmentrouting") {
Charles Chan72f556a2015-10-05 17:50:33 -0700216 @Override
Charles Chan82ab1932016-01-30 23:22:37 -0800217 public SegmentRoutingDeviceConfig createConfig() {
218 return new SegmentRoutingDeviceConfig();
Charles Chan72f556a2015-10-05 17:50:33 -0700219 }
220 };
Charles Chanc91c8782016-03-30 17:54:24 -0700221 private final ConfigFactory<ApplicationId, SegmentRoutingAppConfig> appConfigFactory =
Charles Chan82ab1932016-01-30 23:22:37 -0800222 new ConfigFactory<ApplicationId, SegmentRoutingAppConfig>(SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chanc91c8782016-03-30 17:54:24 -0700223 SegmentRoutingAppConfig.class, "segmentrouting") {
Charles Chan82ab1932016-01-30 23:22:37 -0800224 @Override
225 public SegmentRoutingAppConfig createConfig() {
226 return new SegmentRoutingAppConfig();
227 }
228 };
Charles Chanf4586112015-11-09 16:37:23 -0800229
Charles Chanc91c8782016-03-30 17:54:24 -0700230 private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory =
231 new ConfigFactory<ApplicationId, McastConfig>(SubjectFactories.APP_SUBJECT_FACTORY,
232 McastConfig.class, "multicast") {
233 @Override
234 public McastConfig createConfig() {
235 return new McastConfig();
236 }
237 };
238
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700239 private Object threadSchedulerLock = new Object();
240 private static int numOfEventsQueued = 0;
241 private static int numOfEventsExecuted = 0;
sangho80f11cb2015-04-01 13:05:26 -0700242 private static int numOfHandlerExecution = 0;
243 private static int numOfHandlerScheduled = 0;
244
Charles Chan1963f4f2016-02-18 14:22:42 -0800245 /**
246 * Segment Routing App ID.
247 */
248 public static final String SR_APP_ID = "org.onosproject.segmentrouting";
Charles Chanb7f75ac2016-01-11 18:28:54 -0800249 /**
250 * The starting value of per-subnet VLAN ID assignment.
251 */
Saurav Das7c305372015-10-28 12:39:42 -0700252 private static final short ASSIGNED_VLAN_START = 4093;
Charles Chanb7f75ac2016-01-11 18:28:54 -0800253 /**
254 * The default VLAN ID assigned to the interfaces without subnet config.
255 */
Saurav Das7c305372015-10-28 12:39:42 -0700256 public static final short ASSIGNED_VLAN_NO_SUBNET = 4094;
257
sangho80f11cb2015-04-01 13:05:26 -0700258 @Activate
259 protected void activate() {
Jonathan Hart54541d12016-04-12 15:39:44 -0700260 appId = coreService.registerApplication(SR_APP_ID);
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700261
262 log.debug("Creating EC map nsnextobjectivestore");
263 EventuallyConsistentMapBuilder<NeighborSetNextObjectiveStoreKey, Integer>
264 nsNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700265 nsNextObjStore = nsNextObjMapBuilder
266 .withName("nsnextobjectivestore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700267 .withSerializer(createSerializer())
Madan Jampani675ae202015-06-24 19:05:56 -0700268 .withTimestampProvider((k, v) -> new WallClockTimestamp())
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700269 .build();
270 log.trace("Current size {}", nsNextObjStore.size());
271
Charles Chan77277672015-10-20 16:24:19 -0700272 log.debug("Creating EC map subnetnextobjectivestore");
273 EventuallyConsistentMapBuilder<SubnetNextObjectiveStoreKey, Integer>
274 subnetNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
Charles Chan77277672015-10-20 16:24:19 -0700275 subnetNextObjStore = subnetNextObjMapBuilder
276 .withName("subnetnextobjectivestore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700277 .withSerializer(createSerializer())
Charles Chan77277672015-10-20 16:24:19 -0700278 .withTimestampProvider((k, v) -> new WallClockTimestamp())
279 .build();
280
Saurav Das2d94d312015-11-24 23:21:05 -0800281 log.debug("Creating EC map subnetnextobjectivestore");
282 EventuallyConsistentMapBuilder<PortNextObjectiveStoreKey, Integer>
283 portNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
284 portNextObjStore = portNextObjMapBuilder
285 .withName("portnextobjectivestore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700286 .withSerializer(createSerializer())
Saurav Das2d94d312015-11-24 23:21:05 -0800287 .withTimestampProvider((k, v) -> new WallClockTimestamp())
288 .build();
289
Charles Chanb7f75ac2016-01-11 18:28:54 -0800290 log.debug("Creating EC map xconnectnextobjectivestore");
291 EventuallyConsistentMapBuilder<XConnectNextObjectiveStoreKey, Integer>
292 xConnectNextObjStoreBuilder = storageService.eventuallyConsistentMapBuilder();
293 xConnectNextObjStore = xConnectNextObjStoreBuilder
294 .withName("xconnectnextobjectivestore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700295 .withSerializer(createSerializer())
Charles Chanb7f75ac2016-01-11 18:28:54 -0800296 .withTimestampProvider((k, v) -> new WallClockTimestamp())
297 .build();
298
sangho4a5c42a2015-05-20 22:16:38 -0700299 EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
300 storageService.eventuallyConsistentMapBuilder();
sangho4a5c42a2015-05-20 22:16:38 -0700301 tunnelStore = tunnelMapBuilder
302 .withName("tunnelstore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700303 .withSerializer(createSerializer())
Madan Jampani675ae202015-06-24 19:05:56 -0700304 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho4a5c42a2015-05-20 22:16:38 -0700305 .build();
306
307 EventuallyConsistentMapBuilder<String, Policy> policyMapBuilder =
308 storageService.eventuallyConsistentMapBuilder();
sangho4a5c42a2015-05-20 22:16:38 -0700309 policyStore = policyMapBuilder
310 .withName("policystore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700311 .withSerializer(createSerializer())
Madan Jampani675ae202015-06-24 19:05:56 -0700312 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho4a5c42a2015-05-20 22:16:38 -0700313 .build();
314
Saurav Das7c305372015-10-28 12:39:42 -0700315 EventuallyConsistentMapBuilder<SubnetAssignedVidStoreKey, VlanId>
316 subnetVidStoreMapBuilder = storageService.eventuallyConsistentMapBuilder();
Saurav Das7c305372015-10-28 12:39:42 -0700317 subnetVidStore = subnetVidStoreMapBuilder
318 .withName("subnetvidstore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700319 .withSerializer(createSerializer())
Saurav Das7c305372015-10-28 12:39:42 -0700320 .withTimestampProvider((k, v) -> new WallClockTimestamp())
321 .build();
322
Saurav Dasc3604f12016-03-23 11:22:49 -0700323 compCfgService.preSetProperty("org.onosproject.net.group.impl.GroupManager",
324 "purgeOnDisconnection", "true");
325 compCfgService.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
326 "purgeOnDisconnection", "true");
327
Charles Chan2b078ae2015-10-14 11:24:40 -0700328 processor = new InternalPacketProcessor();
329 linkListener = new InternalLinkListener();
330 deviceListener = new InternalDeviceListener();
Charles Chan82ab1932016-01-30 23:22:37 -0800331 netcfgHandler = new NetworkConfigEventHandler(this);
Charles Chanc91c8782016-03-30 17:54:24 -0700332 mcastEventHandler = new McastEventHandler(this);
Charles Chan2b078ae2015-10-14 11:24:40 -0700333
Charles Chand6d25332016-02-26 22:19:52 -0800334 cfgService.addListener(cfgListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700335 cfgService.registerConfigFactory(deviceConfigFactory);
336 cfgService.registerConfigFactory(appConfigFactory);
337 cfgService.registerConfigFactory(mcastConfigFactory);
Charles Chan82ab1932016-01-30 23:22:37 -0800338 hostService.addListener(hostListener);
Charles Chan2b078ae2015-10-14 11:24:40 -0700339 packetService.addProcessor(processor, PacketProcessor.director(2));
340 linkService.addListener(linkListener);
341 deviceService.addListener(deviceListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700342 multicastRouteService.addListener(mcastListener);
Charles Chan2b078ae2015-10-14 11:24:40 -0700343
Charles Chande6655c2015-12-23 00:15:11 -0800344 // Request ARP packet-in
345 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
346 selector.matchEthType(Ethernet.TYPE_ARP);
347 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId, Optional.empty());
348
Charles Chan2b078ae2015-10-14 11:24:40 -0700349 cfgListener.configureNetwork();
350
sangho80f11cb2015-04-01 13:05:26 -0700351 log.info("Started");
352 }
353
Jonathan Hart54541d12016-04-12 15:39:44 -0700354 private KryoNamespace.Builder createSerializer() {
355 return new KryoNamespace.Builder()
356 .register(KryoNamespaces.API)
357 .register(NeighborSetNextObjectiveStoreKey.class,
358 SubnetNextObjectiveStoreKey.class,
359 SubnetAssignedVidStoreKey.class,
360 NeighborSet.class,
361 Tunnel.class,
362 DefaultTunnel.class,
363 Policy.class,
364 TunnelPolicy.class,
365 Policy.Type.class,
366 PortNextObjectiveStoreKey.class,
367 XConnectNextObjectiveStoreKey.class
368 );
369 }
370
sangho80f11cb2015-04-01 13:05:26 -0700371 @Deactivate
372 protected void deactivate() {
Charles Chan72f556a2015-10-05 17:50:33 -0700373 cfgService.removeListener(cfgListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700374 cfgService.unregisterConfigFactory(deviceConfigFactory);
375 cfgService.unregisterConfigFactory(appConfigFactory);
376 cfgService.unregisterConfigFactory(mcastConfigFactory);
Charles Chan72f556a2015-10-05 17:50:33 -0700377
Charles Chande6655c2015-12-23 00:15:11 -0800378 // Withdraw ARP packet-in
379 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
380 selector.matchEthType(Ethernet.TYPE_ARP);
381 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId, Optional.empty());
382
sangho80f11cb2015-04-01 13:05:26 -0700383 packetService.removeProcessor(processor);
Charles Chan2b078ae2015-10-14 11:24:40 -0700384 linkService.removeListener(linkListener);
385 deviceService.removeListener(deviceListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700386 multicastRouteService.removeListener(mcastListener);
387
sangho80f11cb2015-04-01 13:05:26 -0700388 processor = null;
Charles Chan2b078ae2015-10-14 11:24:40 -0700389 linkListener = null;
Charles Chanc91c8782016-03-30 17:54:24 -0700390 deviceListener = null;
Charles Chan2b078ae2015-10-14 11:24:40 -0700391 groupHandlerMap.clear();
392
Charles Chanc91c8782016-03-30 17:54:24 -0700393 nsNextObjStore.destroy();
394 subnetNextObjStore.destroy();
395 portNextObjStore.destroy();
396 xConnectNextObjStore.destroy();
397 tunnelStore.destroy();
398 policyStore.destroy();
399 subnetVidStore.destroy();
sangho80f11cb2015-04-01 13:05:26 -0700400 log.info("Stopped");
401 }
402
sangho27462c62015-05-14 00:39:53 -0700403
404 @Override
405 public List<Tunnel> getTunnels() {
406 return tunnelHandler.getTunnels();
407 }
408
409 @Override
sanghobd812f82015-06-29 14:58:47 -0700410 public TunnelHandler.Result createTunnel(Tunnel tunnel) {
411 return tunnelHandler.createTunnel(tunnel);
sangho27462c62015-05-14 00:39:53 -0700412 }
413
414 @Override
sanghobd812f82015-06-29 14:58:47 -0700415 public TunnelHandler.Result removeTunnel(Tunnel tunnel) {
sangho27462c62015-05-14 00:39:53 -0700416 for (Policy policy: policyHandler.getPolicies()) {
417 if (policy.type() == Policy.Type.TUNNEL_FLOW) {
418 TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
419 if (tunnelPolicy.tunnelId().equals(tunnel.id())) {
420 log.warn("Cannot remove the tunnel used by a policy");
sanghobd812f82015-06-29 14:58:47 -0700421 return TunnelHandler.Result.TUNNEL_IN_USE;
sangho27462c62015-05-14 00:39:53 -0700422 }
423 }
424 }
sanghobd812f82015-06-29 14:58:47 -0700425 return tunnelHandler.removeTunnel(tunnel);
sangho27462c62015-05-14 00:39:53 -0700426 }
427
428 @Override
sanghobd812f82015-06-29 14:58:47 -0700429 public PolicyHandler.Result removePolicy(Policy policy) {
430 return policyHandler.removePolicy(policy);
sangho27462c62015-05-14 00:39:53 -0700431 }
432
433 @Override
sanghobd812f82015-06-29 14:58:47 -0700434 public PolicyHandler.Result createPolicy(Policy policy) {
435 return policyHandler.createPolicy(policy);
sangho27462c62015-05-14 00:39:53 -0700436 }
437
438 @Override
439 public List<Policy> getPolicies() {
440 return policyHandler.getPolicies();
441 }
442
sangho80f1f892015-05-19 11:57:42 -0700443 /**
444 * Returns the tunnel object with the tunnel ID.
445 *
446 * @param tunnelId Tunnel ID
447 * @return Tunnel reference
448 */
sangho27462c62015-05-14 00:39:53 -0700449 public Tunnel getTunnel(String tunnelId) {
450 return tunnelHandler.getTunnel(tunnelId);
451 }
452
sangho80f11cb2015-04-01 13:05:26 -0700453 /**
Saurav Das7c305372015-10-28 12:39:42 -0700454 * Returns the vlan-id assigned to the subnet configured for a device.
455 * If no vlan-id has been assigned, a new one is assigned out of a pool of ids,
456 * if and only if this controller instance is the master for the device.
457 * <p>
458 * USAGE: The assigned vlans are meant to be applied to untagged packets on those
459 * switches/pipelines that need this functionality. These vids are meant
460 * to be used internally within a switch, and thus need to be unique only
461 * on a switch level. Note that packets never go out on the wire with these
462 * vlans. Currently, vlan ids are assigned from value 4093 down.
463 * Vlan id 4094 expected to be used for all ports that are not assigned subnets.
464 * Vlan id 4095 is reserved and unused. Only a single vlan id is assigned
465 * per subnet.
sangho80f11cb2015-04-01 13:05:26 -0700466 *
Saurav Das7c305372015-10-28 12:39:42 -0700467 * @param deviceId switch dpid
468 * @param subnet IPv4 prefix for which assigned vlan is desired
469 * @return VlanId assigned for the subnet on the device, or
470 * null if no vlan assignment was found and this instance is not
471 * the master for the device.
sangho80f11cb2015-04-01 13:05:26 -0700472 */
Charles Chanb7f75ac2016-01-11 18:28:54 -0800473 // TODO: We should avoid assigning VLAN IDs that are used by VLAN cross-connection.
Saurav Das7c305372015-10-28 12:39:42 -0700474 public VlanId getSubnetAssignedVlanId(DeviceId deviceId, Ip4Prefix subnet) {
475 VlanId assignedVid = subnetVidStore.get(new SubnetAssignedVidStoreKey(
476 deviceId, subnet));
477 if (assignedVid != null) {
478 log.debug("Query for subnet:{} on device:{} returned assigned-vlan "
479 + "{}", subnet, deviceId, assignedVid);
480 return assignedVid;
481 }
482 //check mastership for the right to assign a vlan
483 if (!mastershipService.isLocalMaster(deviceId)) {
484 log.warn("This controller instance is not the master for device {}. "
485 + "Cannot assign vlan-id for subnet {}", deviceId, subnet);
486 return null;
487 }
488 // vlan assignment is expensive but done only once
Charles Chanc6ad7752015-10-29 14:58:10 -0700489 Set<Ip4Prefix> configuredSubnets = deviceConfiguration.getSubnets(deviceId);
Saurav Das7c305372015-10-28 12:39:42 -0700490 Set<Short> assignedVlans = new HashSet<>();
491 Set<Ip4Prefix> unassignedSubnets = new HashSet<>();
492 for (Ip4Prefix sub : configuredSubnets) {
493 VlanId v = subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId,
494 sub));
495 if (v != null) {
496 assignedVlans.add(v.toShort());
497 } else {
498 unassignedSubnets.add(sub);
499 }
500 }
501 short nextAssignedVlan = ASSIGNED_VLAN_START;
502 if (!assignedVlans.isEmpty()) {
503 nextAssignedVlan = (short) (Collections.min(assignedVlans) - 1);
504 }
505 for (Ip4Prefix unsub : unassignedSubnets) {
Charles Chan82ab1932016-01-30 23:22:37 -0800506 // Special case for default route. Assign default VLAN ID to /32 and /0 subnets
507 if (unsub.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH ||
508 unsub.prefixLength() == 0) {
509 subnetVidStore.put(new SubnetAssignedVidStoreKey(deviceId, unsub),
510 VlanId.vlanId(ASSIGNED_VLAN_NO_SUBNET));
511 } else {
512 subnetVidStore.put(new SubnetAssignedVidStoreKey(deviceId, unsub),
513 VlanId.vlanId(nextAssignedVlan--));
514 log.info("Assigned vlan: {} to subnet: {} on device: {}",
515 nextAssignedVlan + 1, unsub, deviceId);
516 }
sangho80f11cb2015-04-01 13:05:26 -0700517 }
518
Saurav Das7c305372015-10-28 12:39:42 -0700519 return subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId, subnet));
sangho80f11cb2015-04-01 13:05:26 -0700520 }
521
sangho27462c62015-05-14 00:39:53 -0700522 /**
Saurav Das7c305372015-10-28 12:39:42 -0700523 * Returns the next objective ID for the given NeighborSet.
Saurav Das4c35fc42015-11-20 15:27:53 -0800524 * If the nextObjective does not exist, a new one is created and
Saurav Das2d94d312015-11-24 23:21:05 -0800525 * its id is returned.
sangho27462c62015-05-14 00:39:53 -0700526 *
sangho80f1f892015-05-19 11:57:42 -0700527 * @param deviceId Device ID
528 * @param ns NegighborSet
Saurav Das4c35fc42015-11-20 15:27:53 -0800529 * @param meta metadata passed into the creation of a Next Objective
530 * @return next objective ID or -1 if an error was encountered during the
531 * creation of the nextObjective
sangho27462c62015-05-14 00:39:53 -0700532 */
Saurav Das4c35fc42015-11-20 15:27:53 -0800533 public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns,
534 TrafficSelector meta) {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700535 if (groupHandlerMap.get(deviceId) != null) {
536 log.trace("getNextObjectiveId query in device {}", deviceId);
537 return groupHandlerMap
Saurav Das4c35fc42015-11-20 15:27:53 -0800538 .get(deviceId).getNextObjectiveId(ns, meta);
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700539 } else {
Saurav Das2d94d312015-11-24 23:21:05 -0800540 log.warn("getNextObjectiveId query - groupHandler for device {} "
541 + "not found", deviceId);
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700542 return -1;
543 }
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700544 }
545
Charles Chan77277672015-10-20 16:24:19 -0700546 /**
Saurav Das2d94d312015-11-24 23:21:05 -0800547 * Returns the next objective ID for the given subnet prefix. It is expected
548 * that the next-objective has been pre-created from configuration.
Charles Chan77277672015-10-20 16:24:19 -0700549 *
550 * @param deviceId Device ID
551 * @param prefix Subnet
Saurav Das2d94d312015-11-24 23:21:05 -0800552 * @return next objective ID or -1 if it was not found
Charles Chan77277672015-10-20 16:24:19 -0700553 */
554 public int getSubnetNextObjectiveId(DeviceId deviceId, IpPrefix prefix) {
555 if (groupHandlerMap.get(deviceId) != null) {
556 log.trace("getSubnetNextObjectiveId query in device {}", deviceId);
557 return groupHandlerMap
558 .get(deviceId).getSubnetNextObjectiveId(prefix);
559 } else {
Saurav Das2d94d312015-11-24 23:21:05 -0800560 log.warn("getSubnetNextObjectiveId query - groupHandler for "
561 + "device {} not found", deviceId);
562 return -1;
563 }
564 }
565
566 /**
567 * Returns the next objective ID for the given portNumber, given the treatment.
568 * There could be multiple different treatments to the same outport, which
569 * would result in different objectives. If the next object
570 * does not exist, a new one is created and its id is returned.
571 *
572 * @param deviceId Device ID
573 * @param portNum port number on device for which NextObjective is queried
574 * @param treatment the actions to apply on the packets (should include outport)
575 * @param meta metadata passed into the creation of a Next Objective if necessary
576 * @return next objective ID or -1 if it was not found
577 */
578 public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
579 TrafficTreatment treatment,
580 TrafficSelector meta) {
581 DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
582 if (ghdlr != null) {
583 return ghdlr.getPortNextObjectiveId(portNum, treatment, meta);
584 } else {
Charles Chanb7f75ac2016-01-11 18:28:54 -0800585 log.warn("getPortNextObjectiveId query - groupHandler for device {}"
586 + " not found", deviceId);
587 return -1;
588 }
589 }
590
591 /**
592 * Returns the next objective ID of type broadcast associated with the VLAN
593 * cross-connection.
594 *
595 * @param deviceId Device ID for the cross-connection
596 * @param vlanId VLAN ID for the cross-connection
597 * @return next objective ID or -1 if it was not found
598 */
599 public int getXConnectNextObjectiveId(DeviceId deviceId, VlanId vlanId) {
600 DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
601 if (ghdlr != null) {
602 return ghdlr.getXConnectNextObjectiveId(vlanId);
603 } else {
604 log.warn("getPortNextObjectiveId query - groupHandler for device {}"
Saurav Das2d94d312015-11-24 23:21:05 -0800605 + " not found", deviceId);
Charles Chan77277672015-10-20 16:24:19 -0700606 return -1;
607 }
608 }
609
sangho80f11cb2015-04-01 13:05:26 -0700610 private class InternalPacketProcessor implements PacketProcessor {
sangho80f11cb2015-04-01 13:05:26 -0700611 @Override
612 public void process(PacketContext context) {
613
614 if (context.isHandled()) {
615 return;
616 }
617
618 InboundPacket pkt = context.inPacket();
619 Ethernet ethernet = pkt.parsed();
Saurav Das2d94d312015-11-24 23:21:05 -0800620 log.trace("Rcvd pktin: {}", ethernet);
sangho80f11cb2015-04-01 13:05:26 -0700621 if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
622 arpHandler.processPacketIn(pkt);
623 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
624 IPv4 ipPacket = (IPv4) ethernet.getPayload();
625 ipHandler.addToPacketBuffer(ipPacket);
626 if (ipPacket.getProtocol() == IPv4.PROTOCOL_ICMP) {
627 icmpHandler.processPacketIn(pkt);
628 } else {
629 ipHandler.processPacketIn(pkt);
630 }
631 }
632 }
633 }
634
635 private class InternalLinkListener implements LinkListener {
636 @Override
637 public void event(LinkEvent event) {
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700638 if (event.type() == LinkEvent.Type.LINK_ADDED
639 || event.type() == LinkEvent.Type.LINK_REMOVED) {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700640 log.debug("Event {} received from Link Service", event.type());
sangho80f11cb2015-04-01 13:05:26 -0700641 scheduleEventHandlerIfNotScheduled(event);
642 }
643 }
644 }
645
646 private class InternalDeviceListener implements DeviceListener {
sangho80f11cb2015-04-01 13:05:26 -0700647 @Override
648 public void event(DeviceEvent event) {
sangho80f11cb2015-04-01 13:05:26 -0700649 switch (event.type()) {
650 case DEVICE_ADDED:
651 case PORT_REMOVED:
sanghofb7c7292015-04-13 15:15:58 -0700652 case DEVICE_UPDATED:
653 case DEVICE_AVAILABILITY_CHANGED:
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700654 log.debug("Event {} received from Device Service", event.type());
sangho80f11cb2015-04-01 13:05:26 -0700655 scheduleEventHandlerIfNotScheduled(event);
656 break;
657 default:
658 }
659 }
660 }
661
Saurav Das2d94d312015-11-24 23:21:05 -0800662 @SuppressWarnings("rawtypes")
sangho80f11cb2015-04-01 13:05:26 -0700663 private void scheduleEventHandlerIfNotScheduled(Event event) {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700664 synchronized (threadSchedulerLock) {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700665 eventQueue.add(event);
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700666 numOfEventsQueued++;
667
668 if ((numOfHandlerScheduled - numOfHandlerExecution) == 0) {
669 //No pending scheduled event handling threads. So start a new one.
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700670 eventHandlerFuture = executorService
671 .schedule(eventHandler, 100, TimeUnit.MILLISECONDS);
672 numOfHandlerScheduled++;
673 }
Jonathan Hart54541d12016-04-12 15:39:44 -0700674 log.trace("numOfEventsQueued {}, numOfEventHandlerScheduled {}",
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700675 numOfEventsQueued,
676 numOfHandlerScheduled);
sangho80f11cb2015-04-01 13:05:26 -0700677 }
sangho80f11cb2015-04-01 13:05:26 -0700678 }
679
680 private class InternalEventHandler implements Runnable {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700681 @Override
sangho80f11cb2015-04-01 13:05:26 -0700682 public void run() {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700683 try {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700684 while (true) {
Saurav Das2d94d312015-11-24 23:21:05 -0800685 @SuppressWarnings("rawtypes")
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700686 Event event = null;
687 synchronized (threadSchedulerLock) {
688 if (!eventQueue.isEmpty()) {
689 event = eventQueue.poll();
690 numOfEventsExecuted++;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700691 } else {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700692 numOfHandlerExecution++;
693 log.debug("numOfHandlerExecution {} numOfEventsExecuted {}",
694 numOfHandlerExecution, numOfEventsExecuted);
695 break;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700696 }
sanghofb7c7292015-04-13 15:15:58 -0700697 }
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700698 if (event.type() == LinkEvent.Type.LINK_ADDED) {
699 processLinkAdded((Link) event.subject());
700 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
701 processLinkRemoved((Link) event.subject());
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700702 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
703 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
704 event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
Saurav Das62af8802015-12-04 10:52:59 -0800705 DeviceId deviceId = ((Device) event.subject()).id();
706 if (deviceService.isAvailable(deviceId)) {
Saurav Dasc28b3432015-10-30 17:45:38 -0700707 log.info("Processing device event {} for available device {}",
708 event.type(), ((Device) event.subject()).id());
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700709 processDeviceAdded((Device) event.subject());
Saurav Dasc3604f12016-03-23 11:22:49 -0700710 } else {
711 log.info("Processing device event {} for unavailable device {}",
712 event.type(), ((Device) event.subject()).id());
713 processDeviceRemoved((Device) event.subject());
714 }
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700715 } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
716 processPortRemoved((Device) event.subject(),
717 ((DeviceEvent) event).port());
718 } else {
719 log.warn("Unhandled event type: {}", event.type());
720 }
sangho80f11cb2015-04-01 13:05:26 -0700721 }
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700722 } catch (Exception e) {
723 log.error("SegmentRouting event handler "
724 + "thread thrown an exception: {}", e);
sangho80f11cb2015-04-01 13:05:26 -0700725 }
sangho80f11cb2015-04-01 13:05:26 -0700726 }
727 }
728
sangho80f11cb2015-04-01 13:05:26 -0700729 private void processLinkAdded(Link link) {
730 log.debug("A new link {} was added", link.toString());
Charles Chan319d1a22015-11-03 10:42:14 -0800731 if (!deviceConfiguration.isConfigured(link.src().deviceId())) {
732 log.warn("Source device of this link is not configured.");
733 return;
734 }
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700735 //Irrespective whether the local is a MASTER or not for this device,
736 //create group handler instance and push default TTP flow rules.
737 //Because in a multi-instance setup, instances can initiate
738 //groups for any devices. Also the default TTP rules are needed
739 //to be pushed before inserting any IP table entries for any device
740 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src()
741 .deviceId());
742 if (groupHandler != null) {
Saurav Das4c35fc42015-11-20 15:27:53 -0800743 groupHandler.linkUp(link, mastershipService.isLocalMaster(
744 link.src().deviceId()));
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700745 } else {
746 Device device = deviceService.getDevice(link.src().deviceId());
747 if (device != null) {
748 log.warn("processLinkAdded: Link Added "
749 + "Notification without Device Added "
750 + "event, still handling it");
751 processDeviceAdded(device);
752 groupHandler = groupHandlerMap.get(link.src()
753 .deviceId());
Saurav Das4c35fc42015-11-20 15:27:53 -0800754 groupHandler.linkUp(link, mastershipService.isLocalMaster(device.id()));
sangho80f11cb2015-04-01 13:05:26 -0700755 }
756 }
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700757
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700758 log.trace("Starting optimized route population process");
759 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null);
760 //log.trace("processLinkAdded: re-starting route population process");
761 //defaultRoutingHandler.startPopulationProcess();
sangho80f11cb2015-04-01 13:05:26 -0700762 }
763
764 private void processLinkRemoved(Link link) {
765 log.debug("A link {} was removed", link.toString());
sangho2165d222015-05-01 09:38:25 -0700766 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
767 if (groupHandler != null) {
Saurav Das62af8802015-12-04 10:52:59 -0800768 groupHandler.portDown(link.src().port(),
769 mastershipService.isLocalMaster(link.src().deviceId()));
sangho2165d222015-05-01 09:38:25 -0700770 }
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700771 log.trace("Starting optimized route population process");
772 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
773 //log.trace("processLinkRemoved: re-starting route population process");
774 //defaultRoutingHandler.startPopulationProcess();
sangho80f11cb2015-04-01 13:05:26 -0700775 }
776
777 private void processDeviceAdded(Device device) {
778 log.debug("A new device with ID {} was added", device.id());
Charles Chan319d1a22015-11-03 10:42:14 -0800779 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
Saurav Das8ec0ec42015-11-03 14:39:27 -0800780 log.warn("Device configuration uploading. Device {} will be "
781 + "processed after config completes.", device.id());
782 return;
783 }
Saurav Dasc28b3432015-10-30 17:45:38 -0700784 // Irrespective of whether the local is a MASTER or not for this device,
785 // we need to create a SR-group-handler instance. This is because in a
786 // multi-instance setup, any instance can initiate forwarding/next-objectives
787 // for any switch (even if this instance is a SLAVE or not even connected
788 // to the switch). To handle this, a default-group-handler instance is necessary
789 // per switch.
Saurav Das8ec0ec42015-11-03 14:39:27 -0800790 if (groupHandlerMap.get(device.id()) == null) {
Charles Chan319d1a22015-11-03 10:42:14 -0800791 DefaultGroupHandler groupHandler;
792 try {
793 groupHandler = DefaultGroupHandler.
794 createGroupHandler(device.id(),
795 appId,
796 deviceConfiguration,
797 linkService,
798 flowObjectiveService,
Charles Chande6655c2015-12-23 00:15:11 -0800799 this);
Charles Chan319d1a22015-11-03 10:42:14 -0800800 } catch (DeviceConfigNotFoundException e) {
801 log.warn(e.getMessage() + " Aborting processDeviceAdded.");
802 return;
803 }
Saurav Das8ec0ec42015-11-03 14:39:27 -0800804 groupHandlerMap.put(device.id(), groupHandler);
805 // Also, in some cases, drivers may need extra
806 // information to process rules (eg. Router IP/MAC); and so, we send
807 // port addressing rules to the driver as well irrespective of whether
808 // this instance is the master or not.
809 defaultRoutingHandler.populatePortAddressingRules(device.id());
Charles Chand4a99c52015-11-18 16:51:08 -0800810 hostListener.readInitialHosts();
Saurav Das8ec0ec42015-11-03 14:39:27 -0800811 }
Charles Chan77277672015-10-20 16:24:19 -0700812 if (mastershipService.isLocalMaster(device.id())) {
Saurav Das8ec0ec42015-11-03 14:39:27 -0800813 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
Charles Chan77277672015-10-20 16:24:19 -0700814 groupHandler.createGroupsFromSubnetConfig();
Charles Chanf4586112015-11-09 16:37:23 -0800815 routingRulePopulator.populateSubnetBroadcastRule(device.id());
Charles Chanb7f75ac2016-01-11 18:28:54 -0800816 groupHandler.createGroupsForXConnect(device.id());
817 routingRulePopulator.populateXConnectBroadcastRule(device.id());
Charles Chan77277672015-10-20 16:24:19 -0700818 }
Charles Chan82ab1932016-01-30 23:22:37 -0800819
820 netcfgHandler.initVRouters(device.id());
sangho80f11cb2015-04-01 13:05:26 -0700821 }
822
Saurav Dasc3604f12016-03-23 11:22:49 -0700823 private void processDeviceRemoved(Device device) {
824 nsNextObjStore.entrySet().stream()
825 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
826 .forEach(entry -> {
827 nsNextObjStore.remove(entry.getKey());
828 });
829
830 subnetNextObjStore.entrySet().stream()
831 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
832 .forEach(entry -> {
833 subnetNextObjStore.remove(entry.getKey());
834 });
835
836 portNextObjStore.entrySet().stream()
837 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
838 .forEach(entry -> {
839 portNextObjStore.remove(entry.getKey());
840 });
841
842 xConnectNextObjStore.entrySet().stream()
843 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
844 .forEach(entry -> {
845 xConnectNextObjStore.remove(entry.getKey());
846 });
847
848 subnetVidStore.entrySet().stream()
849 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
850 .forEach(entry -> {
851 subnetVidStore.remove(entry.getKey());
852 });
853
854 groupHandlerMap.remove(device.id());
855
856 defaultRoutingHandler.purgeEcmpGraph(device.id());
857 }
858
sangho80f11cb2015-04-01 13:05:26 -0700859 private void processPortRemoved(Device device, Port port) {
860 log.debug("Port {} was removed", port.toString());
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700861 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
sangho80f11cb2015-04-01 13:05:26 -0700862 if (groupHandler != null) {
Saurav Das62af8802015-12-04 10:52:59 -0800863 groupHandler.portDown(port.number(),
864 mastershipService.isLocalMaster(device.id()));
sangho80f11cb2015-04-01 13:05:26 -0700865 }
866 }
sangho27462c62015-05-14 00:39:53 -0700867
Charles Chan72f556a2015-10-05 17:50:33 -0700868 private class InternalConfigListener implements NetworkConfigListener {
Charles Chane7c61022015-10-07 14:21:45 -0700869 SegmentRoutingManager segmentRoutingManager;
870
Charles Chanb7f75ac2016-01-11 18:28:54 -0800871 /**
872 * Constructs the internal network config listener.
873 *
874 * @param srMgr segment routing manager
875 */
Charles Chane7c61022015-10-07 14:21:45 -0700876 public InternalConfigListener(SegmentRoutingManager srMgr) {
877 this.segmentRoutingManager = srMgr;
878 }
879
Charles Chanb7f75ac2016-01-11 18:28:54 -0800880 /**
881 * Reads network config and initializes related data structure accordingly.
882 */
Charles Chane7c61022015-10-07 14:21:45 -0700883 public void configureNetwork() {
Charles Chan43547ca2016-02-10 20:46:58 -0800884 deviceConfiguration = new DeviceConfiguration(appId,
885 segmentRoutingManager.cfgService);
Charles Chane7c61022015-10-07 14:21:45 -0700886
887 arpHandler = new ArpHandler(segmentRoutingManager);
888 icmpHandler = new IcmpHandler(segmentRoutingManager);
889 ipHandler = new IpHandler(segmentRoutingManager);
890 routingRulePopulator = new RoutingRulePopulator(segmentRoutingManager);
891 defaultRoutingHandler = new DefaultRoutingHandler(segmentRoutingManager);
892
893 tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
894 groupHandlerMap, tunnelStore);
895 policyHandler = new PolicyHandler(appId, deviceConfiguration,
896 flowObjectiveService,
897 tunnelHandler, policyStore);
898
Charles Chane7c61022015-10-07 14:21:45 -0700899 for (Device device : deviceService.getDevices()) {
Saurav Dasc28b3432015-10-30 17:45:38 -0700900 // Irrespective of whether the local is a MASTER or not for this device,
901 // we need to create a SR-group-handler instance. This is because in a
902 // multi-instance setup, any instance can initiate forwarding/next-objectives
903 // for any switch (even if this instance is a SLAVE or not even connected
904 // to the switch). To handle this, a default-group-handler instance is necessary
905 // per switch.
Saurav Das8ec0ec42015-11-03 14:39:27 -0800906 if (groupHandlerMap.get(device.id()) == null) {
Charles Chan319d1a22015-11-03 10:42:14 -0800907 DefaultGroupHandler groupHandler;
908 try {
909 groupHandler = DefaultGroupHandler.
910 createGroupHandler(device.id(),
911 appId,
912 deviceConfiguration,
913 linkService,
914 flowObjectiveService,
Charles Chande6655c2015-12-23 00:15:11 -0800915 segmentRoutingManager);
Charles Chan319d1a22015-11-03 10:42:14 -0800916 } catch (DeviceConfigNotFoundException e) {
917 log.warn(e.getMessage() + " Aborting configureNetwork.");
918 return;
919 }
Saurav Das8ec0ec42015-11-03 14:39:27 -0800920 groupHandlerMap.put(device.id(), groupHandler);
Saurav Dasc28b3432015-10-30 17:45:38 -0700921
Saurav Das8ec0ec42015-11-03 14:39:27 -0800922 // Also, in some cases, drivers may need extra
923 // information to process rules (eg. Router IP/MAC); and so, we send
924 // port addressing rules to the driver as well, irrespective of whether
925 // this instance is the master or not.
926 defaultRoutingHandler.populatePortAddressingRules(device.id());
Charles Chand4a99c52015-11-18 16:51:08 -0800927 hostListener.readInitialHosts();
Saurav Das8ec0ec42015-11-03 14:39:27 -0800928 }
Charles Chan77277672015-10-20 16:24:19 -0700929 if (mastershipService.isLocalMaster(device.id())) {
Saurav Das8ec0ec42015-11-03 14:39:27 -0800930 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
Charles Chan77277672015-10-20 16:24:19 -0700931 groupHandler.createGroupsFromSubnetConfig();
Charles Chanf4586112015-11-09 16:37:23 -0800932 routingRulePopulator.populateSubnetBroadcastRule(device.id());
Charles Chanb7f75ac2016-01-11 18:28:54 -0800933 groupHandler.createGroupsForXConnect(device.id());
934 routingRulePopulator.populateXConnectBroadcastRule(device.id());
Charles Chan77277672015-10-20 16:24:19 -0700935 }
Charles Chane7c61022015-10-07 14:21:45 -0700936 }
937
938 defaultRoutingHandler.startPopulationProcess();
939 }
940
Charles Chan72f556a2015-10-05 17:50:33 -0700941 @Override
942 public void event(NetworkConfigEvent event) {
Charles Chan82ab1932016-01-30 23:22:37 -0800943 // TODO move this part to NetworkConfigEventHandler
944 if (event.configClass().equals(SegmentRoutingDeviceConfig.class)) {
945 switch (event.type()) {
946 case CONFIG_ADDED:
947 log.info("Segment Routing Config added.");
948 configureNetwork();
949 break;
950 case CONFIG_UPDATED:
951 log.info("Segment Routing Config updated.");
952 // TODO support dynamic configuration
953 break;
954 default:
955 break;
Charles Chan2b078ae2015-10-14 11:24:40 -0700956 }
Charles Chan82ab1932016-01-30 23:22:37 -0800957 } else if (event.configClass().equals(SegmentRoutingAppConfig.class)) {
Charles Chand6d25332016-02-26 22:19:52 -0800958 checkState(netcfgHandler != null, "NetworkConfigEventHandler is not initialized");
Charles Chan82ab1932016-01-30 23:22:37 -0800959 switch (event.type()) {
960 case CONFIG_ADDED:
961 netcfgHandler.processVRouterConfigAdded(event);
962 break;
963 case CONFIG_UPDATED:
964 netcfgHandler.processVRouterConfigUpdated(event);
965 break;
966 case CONFIG_REMOVED:
967 netcfgHandler.processVRouterConfigRemoved(event);
968 break;
969 default:
970 break;
Charles Chan2b078ae2015-10-14 11:24:40 -0700971 }
Charles Chan72f556a2015-10-05 17:50:33 -0700972 }
973 }
974 }
Charles Chanf4586112015-11-09 16:37:23 -0800975
Charles Chand4a99c52015-11-18 16:51:08 -0800976 // TODO Move bridging table population to a separate class
Charles Chanf4586112015-11-09 16:37:23 -0800977 private class InternalHostListener implements HostListener {
Charles Chand4a99c52015-11-18 16:51:08 -0800978 private void readInitialHosts() {
979 hostService.getHosts().forEach(host -> {
980 MacAddress mac = host.mac();
981 VlanId vlanId = host.vlan();
982 DeviceId deviceId = host.location().deviceId();
983 PortNumber port = host.location().port();
984 Set<IpAddress> ips = host.ipAddresses();
985 log.debug("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port);
986
987 // Populate bridging table entry
988 ForwardingObjective.Builder fob =
Saurav Das2d94d312015-11-24 23:21:05 -0800989 getForwardingObjectiveBuilder(deviceId, mac, vlanId, port);
Charles Chand4a99c52015-11-18 16:51:08 -0800990 flowObjectiveService.forward(deviceId, fob.add(
991 new BridgingTableObjectiveContext(mac, vlanId)
992 ));
993
994 // Populate IP table entry
995 ips.forEach(ip -> {
996 if (ip.isIp4()) {
997 routingRulePopulator.populateIpRuleForHost(
998 deviceId, ip.getIp4Address(), mac, port);
999 }
1000 });
1001 });
1002 }
1003
Charles Chanf4586112015-11-09 16:37:23 -08001004 private ForwardingObjective.Builder getForwardingObjectiveBuilder(
Saurav Das2d94d312015-11-24 23:21:05 -08001005 DeviceId deviceId, MacAddress mac, VlanId vlanId,
1006 PortNumber outport) {
Charles Chande6655c2015-12-23 00:15:11 -08001007 // Get assigned VLAN for the subnet
Saurav Das2d94d312015-11-24 23:21:05 -08001008 VlanId outvlan = null;
1009 Ip4Prefix subnet = deviceConfiguration.getPortSubnet(deviceId, outport);
1010 if (subnet == null) {
1011 outvlan = VlanId.vlanId(ASSIGNED_VLAN_NO_SUBNET);
1012 } else {
1013 outvlan = getSubnetAssignedVlanId(deviceId, subnet);
1014 }
Charles Chande6655c2015-12-23 00:15:11 -08001015
1016 // match rule
1017 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
1018 sbuilder.matchEthDst(mac);
1019 /*
1020 * Note: for untagged packets, match on the assigned VLAN.
1021 * for tagged packets, match on its incoming VLAN.
1022 */
1023 if (vlanId.equals(VlanId.NONE)) {
1024 sbuilder.matchVlanId(outvlan);
1025 } else {
1026 sbuilder.matchVlanId(vlanId);
1027 }
1028
1029 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
1030 tbuilder.immediate().popVlan();
1031 tbuilder.immediate().setOutput(outport);
1032
1033 // for switch pipelines that need it, provide outgoing vlan as metadata
Saurav Das2d94d312015-11-24 23:21:05 -08001034 TrafficSelector meta = DefaultTrafficSelector.builder()
1035 .matchVlanId(outvlan).build();
1036
1037 // All forwarding is via Groups. Drivers can re-purpose to flow-actions if needed.
1038 int portNextObjId = getPortNextObjectiveId(deviceId, outport,
1039 tbuilder.build(),
1040 meta);
Charles Chanf4586112015-11-09 16:37:23 -08001041
1042 return DefaultForwardingObjective.builder()
1043 .withFlag(ForwardingObjective.Flag.SPECIFIC)
1044 .withSelector(sbuilder.build())
Saurav Das2d94d312015-11-24 23:21:05 -08001045 .nextStep(portNextObjId)
Charles Chanf4586112015-11-09 16:37:23 -08001046 .withPriority(100)
1047 .fromApp(appId)
1048 .makePermanent();
1049 }
1050
1051 private void processHostAddedEvent(HostEvent event) {
1052 MacAddress mac = event.subject().mac();
1053 VlanId vlanId = event.subject().vlan();
1054 DeviceId deviceId = event.subject().location().deviceId();
1055 PortNumber port = event.subject().location().port();
1056 Set<IpAddress> ips = event.subject().ipAddresses();
Saurav Das2d94d312015-11-24 23:21:05 -08001057 log.info("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port);
Charles Chanf4586112015-11-09 16:37:23 -08001058
Charles Chan57bd98c2016-02-22 19:27:29 -08001059 if (!deviceConfiguration.suppressHost()
Charles Chan43547ca2016-02-10 20:46:58 -08001060 .contains(new ConnectPoint(deviceId, port))) {
1061 // Populate bridging table entry
1062 log.debug("Populate L2 table entry for host {} at {}:{}",
1063 mac, deviceId, port);
1064 ForwardingObjective.Builder fob =
1065 getForwardingObjectiveBuilder(deviceId, mac, vlanId, port);
1066 flowObjectiveService.forward(deviceId, fob.add(
1067 new BridgingTableObjectiveContext(mac, vlanId)
1068 ));
Charles Chanf4586112015-11-09 16:37:23 -08001069
Charles Chan43547ca2016-02-10 20:46:58 -08001070 // Populate IP table entry
1071 ips.forEach(ip -> {
1072 if (ip.isIp4()) {
1073 routingRulePopulator.populateIpRuleForHost(
1074 deviceId, ip.getIp4Address(), mac, port);
1075 }
1076 });
1077 }
Charles Chanf4586112015-11-09 16:37:23 -08001078 }
1079
1080 private void processHostRemoveEvent(HostEvent event) {
1081 MacAddress mac = event.subject().mac();
1082 VlanId vlanId = event.subject().vlan();
1083 DeviceId deviceId = event.subject().location().deviceId();
1084 PortNumber port = event.subject().location().port();
1085 Set<IpAddress> ips = event.subject().ipAddresses();
1086 log.debug("Host {}/{} is removed from {}:{}", mac, vlanId, deviceId, port);
1087
Charles Chan57bd98c2016-02-22 19:27:29 -08001088 if (!deviceConfiguration.suppressHost()
Charles Chan43547ca2016-02-10 20:46:58 -08001089 .contains(new ConnectPoint(deviceId, port))) {
1090 // Revoke bridging table entry
1091 ForwardingObjective.Builder fob =
1092 getForwardingObjectiveBuilder(deviceId, mac, vlanId, port);
1093 flowObjectiveService.forward(deviceId, fob.remove(
1094 new BridgingTableObjectiveContext(mac, vlanId)
1095 ));
Charles Chanf4586112015-11-09 16:37:23 -08001096
Charles Chan43547ca2016-02-10 20:46:58 -08001097 // Revoke IP table entry
1098 ips.forEach(ip -> {
1099 if (ip.isIp4()) {
1100 routingRulePopulator.revokeIpRuleForHost(
1101 deviceId, ip.getIp4Address(), mac, port);
1102 }
1103 });
1104 }
Charles Chanf4586112015-11-09 16:37:23 -08001105 }
1106
1107 private void processHostMovedEvent(HostEvent event) {
1108 MacAddress mac = event.subject().mac();
1109 VlanId vlanId = event.subject().vlan();
1110 DeviceId prevDeviceId = event.prevSubject().location().deviceId();
1111 PortNumber prevPort = event.prevSubject().location().port();
1112 Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
1113 DeviceId newDeviceId = event.subject().location().deviceId();
1114 PortNumber newPort = event.subject().location().port();
1115 Set<IpAddress> newIps = event.subject().ipAddresses();
1116 log.debug("Host {}/{} is moved from {}:{} to {}:{}",
1117 mac, vlanId, prevDeviceId, prevPort, newDeviceId, newPort);
1118
Charles Chan57bd98c2016-02-22 19:27:29 -08001119 if (!deviceConfiguration.suppressHost()
Charles Chan43547ca2016-02-10 20:46:58 -08001120 .contains(new ConnectPoint(prevDeviceId, prevPort))) {
1121 // Revoke previous bridging table entry
1122 ForwardingObjective.Builder prevFob =
1123 getForwardingObjectiveBuilder(prevDeviceId, mac, vlanId, prevPort);
1124 flowObjectiveService.forward(prevDeviceId, prevFob.remove(
1125 new BridgingTableObjectiveContext(mac, vlanId)
1126 ));
Charles Chanf4586112015-11-09 16:37:23 -08001127
Charles Chan43547ca2016-02-10 20:46:58 -08001128 // Revoke previous IP table entry
1129 prevIps.forEach(ip -> {
1130 if (ip.isIp4()) {
1131 routingRulePopulator.revokeIpRuleForHost(
1132 prevDeviceId, ip.getIp4Address(), mac, prevPort);
1133 }
1134 });
1135 }
Charles Chanf4586112015-11-09 16:37:23 -08001136
Charles Chan57bd98c2016-02-22 19:27:29 -08001137 if (!deviceConfiguration.suppressHost()
Charles Chan43547ca2016-02-10 20:46:58 -08001138 .contains(new ConnectPoint(newDeviceId, newPort))) {
1139 // Populate new bridging table entry
1140 ForwardingObjective.Builder newFob =
1141 getForwardingObjectiveBuilder(newDeviceId, mac, vlanId, newPort);
1142 flowObjectiveService.forward(newDeviceId, newFob.add(
1143 new BridgingTableObjectiveContext(mac, vlanId)
1144 ));
Charles Chanf4586112015-11-09 16:37:23 -08001145
Charles Chan43547ca2016-02-10 20:46:58 -08001146 // Populate new IP table entry
1147 newIps.forEach(ip -> {
1148 if (ip.isIp4()) {
1149 routingRulePopulator.populateIpRuleForHost(
1150 newDeviceId, ip.getIp4Address(), mac, newPort);
1151 }
1152 });
1153 }
Charles Chanf4586112015-11-09 16:37:23 -08001154 }
1155
1156 private void processHostUpdatedEvent(HostEvent event) {
1157 MacAddress mac = event.subject().mac();
1158 VlanId vlanId = event.subject().vlan();
1159 DeviceId prevDeviceId = event.prevSubject().location().deviceId();
1160 PortNumber prevPort = event.prevSubject().location().port();
1161 Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
1162 DeviceId newDeviceId = event.subject().location().deviceId();
1163 PortNumber newPort = event.subject().location().port();
1164 Set<IpAddress> newIps = event.subject().ipAddresses();
1165 log.debug("Host {}/{} is updated", mac, vlanId);
1166
Charles Chan57bd98c2016-02-22 19:27:29 -08001167 if (!deviceConfiguration.suppressHost()
Charles Chan43547ca2016-02-10 20:46:58 -08001168 .contains(new ConnectPoint(prevDeviceId, prevPort))) {
1169 // Revoke previous IP table entry
1170 prevIps.forEach(ip -> {
1171 if (ip.isIp4()) {
1172 routingRulePopulator.revokeIpRuleForHost(
1173 prevDeviceId, ip.getIp4Address(), mac, prevPort);
1174 }
1175 });
1176 }
Charles Chanf4586112015-11-09 16:37:23 -08001177
Charles Chan57bd98c2016-02-22 19:27:29 -08001178 if (!deviceConfiguration.suppressHost()
Charles Chan43547ca2016-02-10 20:46:58 -08001179 .contains(new ConnectPoint(newDeviceId, newPort))) {
1180 // Populate new IP table entry
1181 newIps.forEach(ip -> {
1182 if (ip.isIp4()) {
1183 routingRulePopulator.populateIpRuleForHost(
1184 newDeviceId, ip.getIp4Address(), mac, newPort);
1185 }
1186 });
1187 }
Charles Chanf4586112015-11-09 16:37:23 -08001188 }
1189
1190 @Override
1191 public void event(HostEvent event) {
1192 // Do not proceed without mastership
1193 DeviceId deviceId = event.subject().location().deviceId();
1194 if (!mastershipService.isLocalMaster(deviceId)) {
1195 return;
1196 }
1197
1198 switch (event.type()) {
1199 case HOST_ADDED:
1200 processHostAddedEvent(event);
1201 break;
1202 case HOST_MOVED:
1203 processHostMovedEvent(event);
1204 break;
1205 case HOST_REMOVED:
1206 processHostRemoveEvent(event);
1207 break;
1208 case HOST_UPDATED:
1209 processHostUpdatedEvent(event);
1210 break;
1211 default:
1212 log.warn("Unsupported host event type: {}", event.type());
1213 break;
1214 }
1215 }
1216 }
1217
Charles Chanc91c8782016-03-30 17:54:24 -07001218 private class InternalMcastListener implements McastListener {
1219 @Override
1220 public void event(McastEvent event) {
1221 switch (event.type()) {
1222 case SOURCE_ADDED:
1223 mcastEventHandler.processSourceAdded(event);
1224 break;
1225 case SINK_ADDED:
1226 mcastEventHandler.processSinkAdded(event);
1227 break;
1228 case SINK_REMOVED:
1229 mcastEventHandler.processSinkRemoved(event);
1230 break;
1231 case ROUTE_ADDED:
1232 case ROUTE_REMOVED:
1233 default:
1234 break;
1235 }
1236 }
1237 }
1238
Charles Chanf4586112015-11-09 16:37:23 -08001239 private static class BridgingTableObjectiveContext implements ObjectiveContext {
1240 final MacAddress mac;
1241 final VlanId vlanId;
1242
1243 BridgingTableObjectiveContext(MacAddress mac, VlanId vlanId) {
1244 this.mac = mac;
1245 this.vlanId = vlanId;
1246 }
1247
1248 @Override
1249 public void onSuccess(Objective objective) {
1250 if (objective.op() == Objective.Operation.ADD) {
1251 log.debug("Successfully populate bridging table entry for {}/{}",
1252 mac, vlanId);
1253 } else {
1254 log.debug("Successfully revoke bridging table entry for {}/{}",
1255 mac, vlanId);
1256 }
1257 }
1258
1259 @Override
1260 public void onError(Objective objective, ObjectiveError error) {
1261 if (objective.op() == Objective.Operation.ADD) {
1262 log.debug("Fail to populate bridging table entry for {}/{}. {}",
1263 mac, vlanId, error);
1264 } else {
1265 log.debug("Fail to revoke bridging table entry for {}/{}. {}",
1266 mac, vlanId, error);
1267 }
1268 }
1269 }
sangho80f11cb2015-04-01 13:05:26 -07001270}