blob: c11570488420a13df8fc6f73eb25408d10b9ee4c [file] [log] [blame]
sanghob35a6192015-04-01 13:05:26 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
sanghob35a6192015-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;
sangho1e575652015-05-14 00:39:53 -070023import org.apache.felix.scr.annotations.Service;
sanghob35a6192015-04-01 13:05:26 -070024import org.onlab.packet.Ethernet;
Charles Chanc42e84e2015-10-20 16:24:19 -070025import org.onlab.packet.IPv4;
Charles Chanc42e84e2015-10-20 16:24:19 -070026import org.onlab.packet.Ip4Prefix;
Charles Chanc42e84e2015-10-20 16:24:19 -070027import org.onlab.packet.IpPrefix;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070028import org.onlab.packet.VlanId;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070029import org.onlab.util.KryoNamespace;
Saurav Das80980c72016-03-23 11:22:49 -070030import org.onosproject.cfg.ComponentConfigService;
sanghob35a6192015-04-01 13:05:26 -070031import org.onosproject.core.ApplicationId;
32import org.onosproject.core.CoreService;
33import org.onosproject.event.Event;
Charles Chand55e84d2016-03-30 17:54:24 -070034import org.onosproject.incubator.net.config.basics.McastConfig;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070035import org.onosproject.mastership.MastershipService;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070036import org.onosproject.net.Device;
37import org.onosproject.net.DeviceId;
38import org.onosproject.net.Link;
39import org.onosproject.net.Port;
Charles Chan68aa62d2015-11-09 16:37:23 -080040import org.onosproject.net.PortNumber;
Charles Chand6832882015-10-05 17:50:33 -070041import org.onosproject.net.config.ConfigFactory;
42import org.onosproject.net.config.NetworkConfigEvent;
Charles Chand6832882015-10-05 17:50:33 -070043import org.onosproject.net.config.NetworkConfigListener;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070044import org.onosproject.net.config.NetworkConfigRegistry;
Charles Chand6832882015-10-05 17:50:33 -070045import org.onosproject.net.config.basics.SubjectFactories;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070046import org.onosproject.net.device.DeviceEvent;
47import org.onosproject.net.device.DeviceListener;
48import org.onosproject.net.device.DeviceService;
Charles Chan68aa62d2015-11-09 16:37:23 -080049import org.onosproject.net.flow.DefaultTrafficSelector;
Charles Chan68aa62d2015-11-09 16:37:23 -080050import org.onosproject.net.flow.TrafficSelector;
51import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070052import org.onosproject.net.flowobjective.FlowObjectiveService;
Charles Chan68aa62d2015-11-09 16:37:23 -080053import org.onosproject.net.host.HostEvent;
54import org.onosproject.net.host.HostListener;
Charles Chand55e84d2016-03-30 17:54:24 -070055import org.onosproject.net.mcast.McastEvent;
56import org.onosproject.net.mcast.McastListener;
57import org.onosproject.net.mcast.MulticastRouteService;
58import org.onosproject.net.packet.PacketPriority;
59import org.onosproject.net.topology.TopologyService;
60import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
61import org.onosproject.segmentrouting.config.DeviceConfiguration;
62import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
63import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
Charles Chanfc5c7802016-05-17 13:13:55 -070064import org.onosproject.segmentrouting.config.XConnectConfig;
Charles Chand55e84d2016-03-30 17:54:24 -070065import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
66import org.onosproject.segmentrouting.grouphandler.NeighborSet;
Charles Chand2990362016-04-18 13:44:03 -070067import org.onosproject.segmentrouting.storekey.NeighborSetNextObjectiveStoreKey;
68import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
sanghob35a6192015-04-01 13:05:26 -070069import org.onosproject.net.host.HostService;
sanghob35a6192015-04-01 13:05:26 -070070import org.onosproject.net.link.LinkEvent;
71import org.onosproject.net.link.LinkListener;
72import org.onosproject.net.link.LinkService;
73import org.onosproject.net.packet.InboundPacket;
74import org.onosproject.net.packet.PacketContext;
75import org.onosproject.net.packet.PacketProcessor;
76import org.onosproject.net.packet.PacketService;
Charles Chand2990362016-04-18 13:44:03 -070077import org.onosproject.segmentrouting.storekey.SubnetAssignedVidStoreKey;
78import org.onosproject.segmentrouting.storekey.SubnetNextObjectiveStoreKey;
Charles Chanfc5c7802016-05-17 13:13:55 -070079import org.onosproject.segmentrouting.storekey.XConnectStoreKey;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070080import org.onosproject.store.serializers.KryoNamespaces;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070081import org.onosproject.store.service.EventuallyConsistentMap;
82import org.onosproject.store.service.EventuallyConsistentMapBuilder;
83import org.onosproject.store.service.StorageService;
84import org.onosproject.store.service.WallClockTimestamp;
Charles Chan35fd1a72016-06-13 18:54:31 -070085import org.opencord.cordconfig.CordConfigEvent;
86import org.opencord.cordconfig.CordConfigListener;
87import org.opencord.cordconfig.CordConfigService;
sanghob35a6192015-04-01 13:05:26 -070088import org.slf4j.Logger;
89import org.slf4j.LoggerFactory;
90
Saurav Das0e99e2b2015-10-28 12:39:42 -070091import java.util.Collections;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070092import java.util.HashSet;
sangho1e575652015-05-14 00:39:53 -070093import java.util.List;
sanghob35a6192015-04-01 13:05:26 -070094import java.util.Map;
Charles Chan188ebf52015-12-23 00:15:11 -080095import java.util.Optional;
Saurav Das0e99e2b2015-10-28 12:39:42 -070096import java.util.Set;
sanghob35a6192015-04-01 13:05:26 -070097import java.util.concurrent.ConcurrentHashMap;
98import java.util.concurrent.ConcurrentLinkedQueue;
99import java.util.concurrent.Executors;
100import java.util.concurrent.ScheduledExecutorService;
101import java.util.concurrent.ScheduledFuture;
102import java.util.concurrent.TimeUnit;
103
Charles Chan3e783d02016-02-26 22:19:52 -0800104import static com.google.common.base.Preconditions.checkState;
105
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700106
Charles Chane849c192016-01-11 18:28:54 -0800107/**
108 * Segment routing manager.
109 */
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700110@Service
111@Component(immediate = true)
sangho1e575652015-05-14 00:39:53 -0700112public class SegmentRoutingManager implements SegmentRoutingService {
sanghob35a6192015-04-01 13:05:26 -0700113
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700114 private static Logger log = LoggerFactory
115 .getLogger(SegmentRoutingManager.class);
sanghob35a6192015-04-01 13:05:26 -0700116
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected CoreService coreService;
119
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sanghob35a6192015-04-01 13:05:26 -0700121 protected PacketService packetService;
122
123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sanghob35a6192015-04-01 13:05:26 -0700124 protected HostService hostService;
125
126 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
127 protected DeviceService deviceService;
128
129 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700130 protected FlowObjectiveService flowObjectiveService;
sanghob35a6192015-04-01 13:05:26 -0700131
132 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
133 protected LinkService linkService;
134
135 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sanghob35a6192015-04-01 13:05:26 -0700136 protected MastershipService mastershipService;
sangho1e575652015-05-14 00:39:53 -0700137
Charles Chan5270ed02016-01-30 23:22:37 -0800138 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
139 protected StorageService storageService;
140
141 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
142 protected NetworkConfigRegistry cfgService;
143
Saurav Das80980c72016-03-23 11:22:49 -0700144 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
145 protected ComponentConfigService compCfgService;
146
Charles Chand55e84d2016-03-30 17:54:24 -0700147 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
148 protected MulticastRouteService multicastRouteService;
149
150 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
151 protected TopologyService topologyService;
152
Charles Chan35fd1a72016-06-13 18:54:31 -0700153 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
154 protected CordConfigService cordConfigService;
155
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700156 protected ArpHandler arpHandler = null;
157 protected IcmpHandler icmpHandler = null;
158 protected IpHandler ipHandler = null;
159 protected RoutingRulePopulator routingRulePopulator = null;
sanghob35a6192015-04-01 13:05:26 -0700160 protected ApplicationId appId;
sangho666cd6d2015-04-14 16:27:13 -0700161 protected DeviceConfiguration deviceConfiguration = null;
sanghob35a6192015-04-01 13:05:26 -0700162
Charles Chan93e71ba2016-04-29 14:38:22 -0700163 protected DefaultRoutingHandler defaultRoutingHandler = null;
sangho1e575652015-05-14 00:39:53 -0700164 private TunnelHandler tunnelHandler = null;
165 private PolicyHandler policyHandler = null;
Charles Chanb8e10c82015-10-14 11:24:40 -0700166 private InternalPacketProcessor processor = null;
167 private InternalLinkListener linkListener = null;
168 private InternalDeviceListener deviceListener = null;
Charles Chanfc5c7802016-05-17 13:13:55 -0700169 private AppConfigHandler appCfgHandler = null;
170 protected XConnectHandler xConnectHandler = null;
Charles Chand2990362016-04-18 13:44:03 -0700171 private McastHandler mcastHandler = null;
Charles Chan35fd1a72016-06-13 18:54:31 -0700172 protected HostHandler hostHandler = null;
173 private CordConfigHandler cordConfigHandler = null;
sanghob35a6192015-04-01 13:05:26 -0700174 private InternalEventHandler eventHandler = new InternalEventHandler();
Charles Chan5270ed02016-01-30 23:22:37 -0800175 private final InternalHostListener hostListener = new InternalHostListener();
Charles Chand55e84d2016-03-30 17:54:24 -0700176 private final InternalConfigListener cfgListener = new InternalConfigListener(this);
177 private final InternalMcastListener mcastListener = new InternalMcastListener();
Charles Chan35fd1a72016-06-13 18:54:31 -0700178 private final InternalCordConfigListener cordConfigListener = new InternalCordConfigListener();
sanghob35a6192015-04-01 13:05:26 -0700179
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700180 private ScheduledExecutorService executorService = Executors
181 .newScheduledThreadPool(1);
sanghob35a6192015-04-01 13:05:26 -0700182
Saurav Das4ce45962015-11-24 23:21:05 -0800183 @SuppressWarnings("unused")
sanghob35a6192015-04-01 13:05:26 -0700184 private static ScheduledFuture<?> eventHandlerFuture = null;
Saurav Das4ce45962015-11-24 23:21:05 -0800185 @SuppressWarnings("rawtypes")
sanghob35a6192015-04-01 13:05:26 -0700186 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>();
Charles Chan68aa62d2015-11-09 16:37:23 -0800187 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
Charles Chane849c192016-01-11 18:28:54 -0800188 new ConcurrentHashMap<>();
189 /**
190 * Per device next objective ID store with (device id + neighbor set) as key.
191 */
192 public EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
Charles Chan68aa62d2015-11-09 16:37:23 -0800193 nsNextObjStore = null;
Charles Chane849c192016-01-11 18:28:54 -0800194 /**
195 * Per device next objective ID store with (device id + subnet) as key.
196 */
197 public EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
Charles Chan68aa62d2015-11-09 16:37:23 -0800198 subnetNextObjStore = null;
Charles Chane849c192016-01-11 18:28:54 -0800199 /**
200 * Per device next objective ID store with (device id + port) as key.
201 */
202 public EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
Saurav Das4ce45962015-11-24 23:21:05 -0800203 portNextObjStore = null;
Saurav Das0e99e2b2015-10-28 12:39:42 -0700204 // Per device, per-subnet assigned-vlans store, with (device id + subnet
205 // IPv4 prefix) as key
206 private EventuallyConsistentMap<SubnetAssignedVidStoreKey, VlanId>
Charles Chane849c192016-01-11 18:28:54 -0800207 subnetVidStore = null;
Saurav Das4ce45962015-11-24 23:21:05 -0800208 private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
209 private EventuallyConsistentMap<String, Policy> policyStore = null;
sangho0b2b6d12015-05-20 22:16:38 -0700210
Charles Chand55e84d2016-03-30 17:54:24 -0700211 private final ConfigFactory<DeviceId, SegmentRoutingDeviceConfig> deviceConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700212 new ConfigFactory<DeviceId, SegmentRoutingDeviceConfig>(
213 SubjectFactories.DEVICE_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700214 SegmentRoutingDeviceConfig.class, "segmentrouting") {
Charles Chand6832882015-10-05 17:50:33 -0700215 @Override
Charles Chan5270ed02016-01-30 23:22:37 -0800216 public SegmentRoutingDeviceConfig createConfig() {
217 return new SegmentRoutingDeviceConfig();
Charles Chand6832882015-10-05 17:50:33 -0700218 }
219 };
Charles Chand55e84d2016-03-30 17:54:24 -0700220 private final ConfigFactory<ApplicationId, SegmentRoutingAppConfig> appConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700221 new ConfigFactory<ApplicationId, SegmentRoutingAppConfig>(
222 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700223 SegmentRoutingAppConfig.class, "segmentrouting") {
Charles Chan5270ed02016-01-30 23:22:37 -0800224 @Override
225 public SegmentRoutingAppConfig createConfig() {
226 return new SegmentRoutingAppConfig();
227 }
228 };
Charles Chanfc5c7802016-05-17 13:13:55 -0700229 private final ConfigFactory<ApplicationId, XConnectConfig> xConnectConfigFactory =
230 new ConfigFactory<ApplicationId, XConnectConfig>(
231 SubjectFactories.APP_SUBJECT_FACTORY,
232 XConnectConfig.class, "xconnect") {
233 @Override
234 public XConnectConfig createConfig() {
235 return new XConnectConfig();
236 }
237 };
Charles Chand55e84d2016-03-30 17:54:24 -0700238 private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700239 new ConfigFactory<ApplicationId, McastConfig>(
240 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700241 McastConfig.class, "multicast") {
242 @Override
243 public McastConfig createConfig() {
244 return new McastConfig();
245 }
246 };
247
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700248 private Object threadSchedulerLock = new Object();
249 private static int numOfEventsQueued = 0;
250 private static int numOfEventsExecuted = 0;
sanghob35a6192015-04-01 13:05:26 -0700251 private static int numOfHandlerExecution = 0;
252 private static int numOfHandlerScheduled = 0;
253
Charles Chan116188d2016-02-18 14:22:42 -0800254 /**
255 * Segment Routing App ID.
256 */
257 public static final String SR_APP_ID = "org.onosproject.segmentrouting";
Charles Chane849c192016-01-11 18:28:54 -0800258 /**
259 * The starting value of per-subnet VLAN ID assignment.
260 */
Saurav Das0e99e2b2015-10-28 12:39:42 -0700261 private static final short ASSIGNED_VLAN_START = 4093;
Charles Chane849c192016-01-11 18:28:54 -0800262 /**
263 * The default VLAN ID assigned to the interfaces without subnet config.
264 */
Saurav Das0e99e2b2015-10-28 12:39:42 -0700265 public static final short ASSIGNED_VLAN_NO_SUBNET = 4094;
266
sanghob35a6192015-04-01 13:05:26 -0700267 @Activate
268 protected void activate() {
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700269 appId = coreService.registerApplication(SR_APP_ID);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700270
271 log.debug("Creating EC map nsnextobjectivestore");
272 EventuallyConsistentMapBuilder<NeighborSetNextObjectiveStoreKey, Integer>
273 nsNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700274 nsNextObjStore = nsNextObjMapBuilder
275 .withName("nsnextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700276 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700277 .withTimestampProvider((k, v) -> new WallClockTimestamp())
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700278 .build();
279 log.trace("Current size {}", nsNextObjStore.size());
280
Charles Chanc42e84e2015-10-20 16:24:19 -0700281 log.debug("Creating EC map subnetnextobjectivestore");
282 EventuallyConsistentMapBuilder<SubnetNextObjectiveStoreKey, Integer>
283 subnetNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
Charles Chanc42e84e2015-10-20 16:24:19 -0700284 subnetNextObjStore = subnetNextObjMapBuilder
285 .withName("subnetnextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700286 .withSerializer(createSerializer())
Charles Chanc42e84e2015-10-20 16:24:19 -0700287 .withTimestampProvider((k, v) -> new WallClockTimestamp())
288 .build();
289
Saurav Das4ce45962015-11-24 23:21:05 -0800290 log.debug("Creating EC map subnetnextobjectivestore");
291 EventuallyConsistentMapBuilder<PortNextObjectiveStoreKey, Integer>
292 portNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
293 portNextObjStore = portNextObjMapBuilder
294 .withName("portnextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700295 .withSerializer(createSerializer())
Saurav Das4ce45962015-11-24 23:21:05 -0800296 .withTimestampProvider((k, v) -> new WallClockTimestamp())
297 .build();
298
sangho0b2b6d12015-05-20 22:16:38 -0700299 EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
300 storageService.eventuallyConsistentMapBuilder();
sangho0b2b6d12015-05-20 22:16:38 -0700301 tunnelStore = tunnelMapBuilder
302 .withName("tunnelstore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700303 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700304 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho0b2b6d12015-05-20 22:16:38 -0700305 .build();
306
307 EventuallyConsistentMapBuilder<String, Policy> policyMapBuilder =
308 storageService.eventuallyConsistentMapBuilder();
sangho0b2b6d12015-05-20 22:16:38 -0700309 policyStore = policyMapBuilder
310 .withName("policystore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700311 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700312 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho0b2b6d12015-05-20 22:16:38 -0700313 .build();
314
Saurav Das0e99e2b2015-10-28 12:39:42 -0700315 EventuallyConsistentMapBuilder<SubnetAssignedVidStoreKey, VlanId>
316 subnetVidStoreMapBuilder = storageService.eventuallyConsistentMapBuilder();
Saurav Das0e99e2b2015-10-28 12:39:42 -0700317 subnetVidStore = subnetVidStoreMapBuilder
318 .withName("subnetvidstore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700319 .withSerializer(createSerializer())
Saurav Das0e99e2b2015-10-28 12:39:42 -0700320 .withTimestampProvider((k, v) -> new WallClockTimestamp())
321 .build();
322
Saurav Das80980c72016-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 Chanb8e10c82015-10-14 11:24:40 -0700328 processor = new InternalPacketProcessor();
329 linkListener = new InternalLinkListener();
330 deviceListener = new InternalDeviceListener();
Charles Chanfc5c7802016-05-17 13:13:55 -0700331 appCfgHandler = new AppConfigHandler(this);
332 xConnectHandler = new XConnectHandler(this);
Charles Chand2990362016-04-18 13:44:03 -0700333 mcastHandler = new McastHandler(this);
334 hostHandler = new HostHandler(this);
Charles Chan35fd1a72016-06-13 18:54:31 -0700335 cordConfigHandler = new CordConfigHandler(this);
Charles Chanb8e10c82015-10-14 11:24:40 -0700336
Charles Chan3e783d02016-02-26 22:19:52 -0800337 cfgService.addListener(cfgListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700338 cfgService.registerConfigFactory(deviceConfigFactory);
339 cfgService.registerConfigFactory(appConfigFactory);
Charles Chanfc5c7802016-05-17 13:13:55 -0700340 cfgService.registerConfigFactory(xConnectConfigFactory);
Charles Chand55e84d2016-03-30 17:54:24 -0700341 cfgService.registerConfigFactory(mcastConfigFactory);
Charles Chan5270ed02016-01-30 23:22:37 -0800342 hostService.addListener(hostListener);
Charles Chanb8e10c82015-10-14 11:24:40 -0700343 packetService.addProcessor(processor, PacketProcessor.director(2));
344 linkService.addListener(linkListener);
345 deviceService.addListener(deviceListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700346 multicastRouteService.addListener(mcastListener);
Charles Chan35fd1a72016-06-13 18:54:31 -0700347 cordConfigService.addListener(cordConfigListener);
Charles Chanb8e10c82015-10-14 11:24:40 -0700348
Charles Chan188ebf52015-12-23 00:15:11 -0800349 // Request ARP packet-in
350 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
351 selector.matchEthType(Ethernet.TYPE_ARP);
352 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId, Optional.empty());
353
Charles Chanb8e10c82015-10-14 11:24:40 -0700354 cfgListener.configureNetwork();
355
sanghob35a6192015-04-01 13:05:26 -0700356 log.info("Started");
357 }
358
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700359 private KryoNamespace.Builder createSerializer() {
360 return new KryoNamespace.Builder()
361 .register(KryoNamespaces.API)
362 .register(NeighborSetNextObjectiveStoreKey.class,
363 SubnetNextObjectiveStoreKey.class,
364 SubnetAssignedVidStoreKey.class,
365 NeighborSet.class,
366 Tunnel.class,
367 DefaultTunnel.class,
368 Policy.class,
369 TunnelPolicy.class,
370 Policy.Type.class,
371 PortNextObjectiveStoreKey.class,
Charles Chanfc5c7802016-05-17 13:13:55 -0700372 XConnectStoreKey.class
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700373 );
374 }
375
sanghob35a6192015-04-01 13:05:26 -0700376 @Deactivate
377 protected void deactivate() {
Charles Chand6832882015-10-05 17:50:33 -0700378 cfgService.removeListener(cfgListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700379 cfgService.unregisterConfigFactory(deviceConfigFactory);
380 cfgService.unregisterConfigFactory(appConfigFactory);
381 cfgService.unregisterConfigFactory(mcastConfigFactory);
Charles Chand6832882015-10-05 17:50:33 -0700382
Charles Chan188ebf52015-12-23 00:15:11 -0800383 // Withdraw ARP packet-in
384 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
385 selector.matchEthType(Ethernet.TYPE_ARP);
386 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId, Optional.empty());
387
sanghob35a6192015-04-01 13:05:26 -0700388 packetService.removeProcessor(processor);
Charles Chanb8e10c82015-10-14 11:24:40 -0700389 linkService.removeListener(linkListener);
390 deviceService.removeListener(deviceListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700391 multicastRouteService.removeListener(mcastListener);
Charles Chan35fd1a72016-06-13 18:54:31 -0700392 cordConfigService.removeListener(cordConfigListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700393
sanghob35a6192015-04-01 13:05:26 -0700394 processor = null;
Charles Chanb8e10c82015-10-14 11:24:40 -0700395 linkListener = null;
Charles Chand55e84d2016-03-30 17:54:24 -0700396 deviceListener = null;
Charles Chanb8e10c82015-10-14 11:24:40 -0700397 groupHandlerMap.clear();
398
Charles Chand55e84d2016-03-30 17:54:24 -0700399 nsNextObjStore.destroy();
400 subnetNextObjStore.destroy();
401 portNextObjStore.destroy();
Charles Chand55e84d2016-03-30 17:54:24 -0700402 tunnelStore.destroy();
403 policyStore.destroy();
404 subnetVidStore.destroy();
sanghob35a6192015-04-01 13:05:26 -0700405 log.info("Stopped");
406 }
407
sangho1e575652015-05-14 00:39:53 -0700408 @Override
409 public List<Tunnel> getTunnels() {
410 return tunnelHandler.getTunnels();
411 }
412
413 @Override
sangho71abe1b2015-06-29 14:58:47 -0700414 public TunnelHandler.Result createTunnel(Tunnel tunnel) {
415 return tunnelHandler.createTunnel(tunnel);
sangho1e575652015-05-14 00:39:53 -0700416 }
417
418 @Override
sangho71abe1b2015-06-29 14:58:47 -0700419 public TunnelHandler.Result removeTunnel(Tunnel tunnel) {
sangho1e575652015-05-14 00:39:53 -0700420 for (Policy policy: policyHandler.getPolicies()) {
421 if (policy.type() == Policy.Type.TUNNEL_FLOW) {
422 TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
423 if (tunnelPolicy.tunnelId().equals(tunnel.id())) {
424 log.warn("Cannot remove the tunnel used by a policy");
sangho71abe1b2015-06-29 14:58:47 -0700425 return TunnelHandler.Result.TUNNEL_IN_USE;
sangho1e575652015-05-14 00:39:53 -0700426 }
427 }
428 }
sangho71abe1b2015-06-29 14:58:47 -0700429 return tunnelHandler.removeTunnel(tunnel);
sangho1e575652015-05-14 00:39:53 -0700430 }
431
432 @Override
sangho71abe1b2015-06-29 14:58:47 -0700433 public PolicyHandler.Result removePolicy(Policy policy) {
434 return policyHandler.removePolicy(policy);
sangho1e575652015-05-14 00:39:53 -0700435 }
436
437 @Override
sangho71abe1b2015-06-29 14:58:47 -0700438 public PolicyHandler.Result createPolicy(Policy policy) {
439 return policyHandler.createPolicy(policy);
sangho1e575652015-05-14 00:39:53 -0700440 }
441
442 @Override
443 public List<Policy> getPolicies() {
444 return policyHandler.getPolicies();
445 }
446
Saurav Das59232cf2016-04-27 18:35:50 -0700447 @Override
448 public void rerouteNetwork() {
449 cfgListener.configureNetwork();
450 for (Device device : deviceService.getDevices()) {
451 defaultRoutingHandler.populatePortAddressingRules(device.id());
452 }
453 defaultRoutingHandler.startPopulationProcess();
454 }
455
sanghof9d0bf12015-05-19 11:57:42 -0700456 /**
457 * Returns the tunnel object with the tunnel ID.
458 *
459 * @param tunnelId Tunnel ID
460 * @return Tunnel reference
461 */
sangho1e575652015-05-14 00:39:53 -0700462 public Tunnel getTunnel(String tunnelId) {
463 return tunnelHandler.getTunnel(tunnelId);
464 }
465
sanghob35a6192015-04-01 13:05:26 -0700466 /**
Saurav Das0e99e2b2015-10-28 12:39:42 -0700467 * Returns the vlan-id assigned to the subnet configured for a device.
468 * If no vlan-id has been assigned, a new one is assigned out of a pool of ids,
469 * if and only if this controller instance is the master for the device.
470 * <p>
471 * USAGE: The assigned vlans are meant to be applied to untagged packets on those
472 * switches/pipelines that need this functionality. These vids are meant
473 * to be used internally within a switch, and thus need to be unique only
474 * on a switch level. Note that packets never go out on the wire with these
475 * vlans. Currently, vlan ids are assigned from value 4093 down.
476 * Vlan id 4094 expected to be used for all ports that are not assigned subnets.
477 * Vlan id 4095 is reserved and unused. Only a single vlan id is assigned
478 * per subnet.
sanghob35a6192015-04-01 13:05:26 -0700479 *
Saurav Das0e99e2b2015-10-28 12:39:42 -0700480 * @param deviceId switch dpid
481 * @param subnet IPv4 prefix for which assigned vlan is desired
482 * @return VlanId assigned for the subnet on the device, or
483 * null if no vlan assignment was found and this instance is not
484 * the master for the device.
sanghob35a6192015-04-01 13:05:26 -0700485 */
Charles Chane849c192016-01-11 18:28:54 -0800486 // TODO: We should avoid assigning VLAN IDs that are used by VLAN cross-connection.
Saurav Das0e99e2b2015-10-28 12:39:42 -0700487 public VlanId getSubnetAssignedVlanId(DeviceId deviceId, Ip4Prefix subnet) {
488 VlanId assignedVid = subnetVidStore.get(new SubnetAssignedVidStoreKey(
489 deviceId, subnet));
490 if (assignedVid != null) {
491 log.debug("Query for subnet:{} on device:{} returned assigned-vlan "
492 + "{}", subnet, deviceId, assignedVid);
493 return assignedVid;
494 }
495 //check mastership for the right to assign a vlan
496 if (!mastershipService.isLocalMaster(deviceId)) {
497 log.warn("This controller instance is not the master for device {}. "
498 + "Cannot assign vlan-id for subnet {}", deviceId, subnet);
499 return null;
500 }
501 // vlan assignment is expensive but done only once
Charles Chan9f676b62015-10-29 14:58:10 -0700502 Set<Ip4Prefix> configuredSubnets = deviceConfiguration.getSubnets(deviceId);
Saurav Das0e99e2b2015-10-28 12:39:42 -0700503 Set<Short> assignedVlans = new HashSet<>();
504 Set<Ip4Prefix> unassignedSubnets = new HashSet<>();
505 for (Ip4Prefix sub : configuredSubnets) {
506 VlanId v = subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId,
507 sub));
508 if (v != null) {
509 assignedVlans.add(v.toShort());
510 } else {
511 unassignedSubnets.add(sub);
512 }
513 }
514 short nextAssignedVlan = ASSIGNED_VLAN_START;
515 if (!assignedVlans.isEmpty()) {
516 nextAssignedVlan = (short) (Collections.min(assignedVlans) - 1);
517 }
518 for (Ip4Prefix unsub : unassignedSubnets) {
Charles Chan5270ed02016-01-30 23:22:37 -0800519 // Special case for default route. Assign default VLAN ID to /32 and /0 subnets
520 if (unsub.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH ||
521 unsub.prefixLength() == 0) {
522 subnetVidStore.put(new SubnetAssignedVidStoreKey(deviceId, unsub),
523 VlanId.vlanId(ASSIGNED_VLAN_NO_SUBNET));
524 } else {
525 subnetVidStore.put(new SubnetAssignedVidStoreKey(deviceId, unsub),
526 VlanId.vlanId(nextAssignedVlan--));
527 log.info("Assigned vlan: {} to subnet: {} on device: {}",
528 nextAssignedVlan + 1, unsub, deviceId);
529 }
sanghob35a6192015-04-01 13:05:26 -0700530 }
531
Saurav Das0e99e2b2015-10-28 12:39:42 -0700532 return subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId, subnet));
sanghob35a6192015-04-01 13:05:26 -0700533 }
534
sangho1e575652015-05-14 00:39:53 -0700535 /**
Saurav Das0e99e2b2015-10-28 12:39:42 -0700536 * Returns the next objective ID for the given NeighborSet.
Saurav Das8a0732e2015-11-20 15:27:53 -0800537 * If the nextObjective does not exist, a new one is created and
Saurav Das4ce45962015-11-24 23:21:05 -0800538 * its id is returned.
sangho1e575652015-05-14 00:39:53 -0700539 *
sanghof9d0bf12015-05-19 11:57:42 -0700540 * @param deviceId Device ID
541 * @param ns NegighborSet
Saurav Das8a0732e2015-11-20 15:27:53 -0800542 * @param meta metadata passed into the creation of a Next Objective
543 * @return next objective ID or -1 if an error was encountered during the
544 * creation of the nextObjective
sangho1e575652015-05-14 00:39:53 -0700545 */
Saurav Das8a0732e2015-11-20 15:27:53 -0800546 public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns,
547 TrafficSelector meta) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700548 if (groupHandlerMap.get(deviceId) != null) {
549 log.trace("getNextObjectiveId query in device {}", deviceId);
550 return groupHandlerMap
Saurav Das8a0732e2015-11-20 15:27:53 -0800551 .get(deviceId).getNextObjectiveId(ns, meta);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700552 } else {
Saurav Das4ce45962015-11-24 23:21:05 -0800553 log.warn("getNextObjectiveId query - groupHandler for device {} "
554 + "not found", deviceId);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700555 return -1;
556 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700557 }
558
Charles Chanc42e84e2015-10-20 16:24:19 -0700559 /**
Saurav Das4ce45962015-11-24 23:21:05 -0800560 * Returns the next objective ID for the given subnet prefix. It is expected
561 * that the next-objective has been pre-created from configuration.
Charles Chanc42e84e2015-10-20 16:24:19 -0700562 *
563 * @param deviceId Device ID
564 * @param prefix Subnet
Saurav Das4ce45962015-11-24 23:21:05 -0800565 * @return next objective ID or -1 if it was not found
Charles Chanc42e84e2015-10-20 16:24:19 -0700566 */
567 public int getSubnetNextObjectiveId(DeviceId deviceId, IpPrefix prefix) {
568 if (groupHandlerMap.get(deviceId) != null) {
569 log.trace("getSubnetNextObjectiveId query in device {}", deviceId);
570 return groupHandlerMap
571 .get(deviceId).getSubnetNextObjectiveId(prefix);
572 } else {
Saurav Das4ce45962015-11-24 23:21:05 -0800573 log.warn("getSubnetNextObjectiveId query - groupHandler for "
574 + "device {} not found", deviceId);
575 return -1;
576 }
577 }
578
579 /**
580 * Returns the next objective ID for the given portNumber, given the treatment.
581 * There could be multiple different treatments to the same outport, which
582 * would result in different objectives. If the next object
583 * does not exist, a new one is created and its id is returned.
584 *
585 * @param deviceId Device ID
586 * @param portNum port number on device for which NextObjective is queried
587 * @param treatment the actions to apply on the packets (should include outport)
588 * @param meta metadata passed into the creation of a Next Objective if necessary
Saurav Das59232cf2016-04-27 18:35:50 -0700589 * @return next objective ID or -1 if an error occurred during retrieval or creation
Saurav Das4ce45962015-11-24 23:21:05 -0800590 */
591 public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
592 TrafficTreatment treatment,
593 TrafficSelector meta) {
594 DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
595 if (ghdlr != null) {
596 return ghdlr.getPortNextObjectiveId(portNum, treatment, meta);
597 } else {
Charles Chane849c192016-01-11 18:28:54 -0800598 log.warn("getPortNextObjectiveId query - groupHandler for device {}"
599 + " not found", deviceId);
600 return -1;
601 }
602 }
603
sanghob35a6192015-04-01 13:05:26 -0700604 private class InternalPacketProcessor implements PacketProcessor {
sanghob35a6192015-04-01 13:05:26 -0700605 @Override
606 public void process(PacketContext context) {
607
608 if (context.isHandled()) {
609 return;
610 }
611
612 InboundPacket pkt = context.inPacket();
613 Ethernet ethernet = pkt.parsed();
Saurav Das4ce45962015-11-24 23:21:05 -0800614 log.trace("Rcvd pktin: {}", ethernet);
sanghob35a6192015-04-01 13:05:26 -0700615 if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
616 arpHandler.processPacketIn(pkt);
617 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
618 IPv4 ipPacket = (IPv4) ethernet.getPayload();
619 ipHandler.addToPacketBuffer(ipPacket);
620 if (ipPacket.getProtocol() == IPv4.PROTOCOL_ICMP) {
621 icmpHandler.processPacketIn(pkt);
622 } else {
623 ipHandler.processPacketIn(pkt);
624 }
625 }
626 }
627 }
628
629 private class InternalLinkListener implements LinkListener {
630 @Override
631 public void event(LinkEvent event) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700632 if (event.type() == LinkEvent.Type.LINK_ADDED
633 || event.type() == LinkEvent.Type.LINK_REMOVED) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700634 log.debug("Event {} received from Link Service", event.type());
sanghob35a6192015-04-01 13:05:26 -0700635 scheduleEventHandlerIfNotScheduled(event);
636 }
637 }
638 }
639
640 private class InternalDeviceListener implements DeviceListener {
sanghob35a6192015-04-01 13:05:26 -0700641 @Override
642 public void event(DeviceEvent event) {
sanghob35a6192015-04-01 13:05:26 -0700643 switch (event.type()) {
644 case DEVICE_ADDED:
645 case PORT_REMOVED:
sangho20eff1d2015-04-13 15:15:58 -0700646 case DEVICE_UPDATED:
647 case DEVICE_AVAILABILITY_CHANGED:
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700648 log.debug("Event {} received from Device Service", event.type());
sanghob35a6192015-04-01 13:05:26 -0700649 scheduleEventHandlerIfNotScheduled(event);
650 break;
651 default:
652 }
653 }
654 }
655
Saurav Das4ce45962015-11-24 23:21:05 -0800656 @SuppressWarnings("rawtypes")
sanghob35a6192015-04-01 13:05:26 -0700657 private void scheduleEventHandlerIfNotScheduled(Event event) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700658 synchronized (threadSchedulerLock) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700659 eventQueue.add(event);
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700660 numOfEventsQueued++;
661
662 if ((numOfHandlerScheduled - numOfHandlerExecution) == 0) {
663 //No pending scheduled event handling threads. So start a new one.
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700664 eventHandlerFuture = executorService
665 .schedule(eventHandler, 100, TimeUnit.MILLISECONDS);
666 numOfHandlerScheduled++;
667 }
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700668 log.trace("numOfEventsQueued {}, numOfEventHandlerScheduled {}",
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700669 numOfEventsQueued,
670 numOfHandlerScheduled);
sanghob35a6192015-04-01 13:05:26 -0700671 }
sanghob35a6192015-04-01 13:05:26 -0700672 }
673
674 private class InternalEventHandler implements Runnable {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700675 @Override
sanghob35a6192015-04-01 13:05:26 -0700676 public void run() {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700677 try {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700678 while (true) {
Saurav Das4ce45962015-11-24 23:21:05 -0800679 @SuppressWarnings("rawtypes")
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700680 Event event = null;
681 synchronized (threadSchedulerLock) {
682 if (!eventQueue.isEmpty()) {
683 event = eventQueue.poll();
684 numOfEventsExecuted++;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700685 } else {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700686 numOfHandlerExecution++;
687 log.debug("numOfHandlerExecution {} numOfEventsExecuted {}",
688 numOfHandlerExecution, numOfEventsExecuted);
689 break;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700690 }
sangho20eff1d2015-04-13 15:15:58 -0700691 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700692 if (event.type() == LinkEvent.Type.LINK_ADDED) {
693 processLinkAdded((Link) event.subject());
694 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
695 processLinkRemoved((Link) event.subject());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700696 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
697 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
698 event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
Saurav Das423fe2b2015-12-04 10:52:59 -0800699 DeviceId deviceId = ((Device) event.subject()).id();
700 if (deviceService.isAvailable(deviceId)) {
Saurav Das837e0bb2015-10-30 17:45:38 -0700701 log.info("Processing device event {} for available device {}",
702 event.type(), ((Device) event.subject()).id());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700703 processDeviceAdded((Device) event.subject());
Saurav Das80980c72016-03-23 11:22:49 -0700704 } else {
705 log.info("Processing device event {} for unavailable device {}",
706 event.type(), ((Device) event.subject()).id());
707 processDeviceRemoved((Device) event.subject());
708 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700709 } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
710 processPortRemoved((Device) event.subject(),
711 ((DeviceEvent) event).port());
Saurav Dasb5c236e2016-06-07 10:08:06 -0700712 } else if (event.type() == DeviceEvent.Type.PORT_ADDED ||
713 event.type() == DeviceEvent.Type.PORT_UPDATED) {
714 log.info("** PORT ADDED OR UPDATED {}/{} -> {}",
715 (Device) event.subject(),
716 ((DeviceEvent) event).port(),
717 event.type());
718 /* XXX create method for single port filtering rules
719 if (defaultRoutingHandler != null) {
720 defaultRoutingHandler.populatePortAddressingRules(
721 ((Device) event.subject()).id());
722 }*/
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700723 } else {
724 log.warn("Unhandled event type: {}", event.type());
725 }
sanghob35a6192015-04-01 13:05:26 -0700726 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700727 } catch (Exception e) {
728 log.error("SegmentRouting event handler "
729 + "thread thrown an exception: {}", e);
sanghob35a6192015-04-01 13:05:26 -0700730 }
sanghob35a6192015-04-01 13:05:26 -0700731 }
732 }
733
sanghob35a6192015-04-01 13:05:26 -0700734 private void processLinkAdded(Link link) {
Saurav Dasb5c236e2016-06-07 10:08:06 -0700735 log.info("** LINK ADDED {}", link.toString());
Charles Chan0b4e6182015-11-03 10:42:14 -0800736 if (!deviceConfiguration.isConfigured(link.src().deviceId())) {
737 log.warn("Source device of this link is not configured.");
738 return;
739 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700740 //Irrespective whether the local is a MASTER or not for this device,
741 //create group handler instance and push default TTP flow rules.
742 //Because in a multi-instance setup, instances can initiate
743 //groups for any devices. Also the default TTP rules are needed
744 //to be pushed before inserting any IP table entries for any device
745 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src()
746 .deviceId());
747 if (groupHandler != null) {
Saurav Das8a0732e2015-11-20 15:27:53 -0800748 groupHandler.linkUp(link, mastershipService.isLocalMaster(
749 link.src().deviceId()));
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700750 } else {
751 Device device = deviceService.getDevice(link.src().deviceId());
752 if (device != null) {
753 log.warn("processLinkAdded: Link Added "
754 + "Notification without Device Added "
755 + "event, still handling it");
756 processDeviceAdded(device);
757 groupHandler = groupHandlerMap.get(link.src()
758 .deviceId());
Saurav Das8a0732e2015-11-20 15:27:53 -0800759 groupHandler.linkUp(link, mastershipService.isLocalMaster(device.id()));
sanghob35a6192015-04-01 13:05:26 -0700760 }
761 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700762
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700763 log.trace("Starting optimized route population process");
764 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null);
765 //log.trace("processLinkAdded: re-starting route population process");
766 //defaultRoutingHandler.startPopulationProcess();
Charles Chan2199c302016-04-23 17:36:10 -0700767
768 mcastHandler.init();
sanghob35a6192015-04-01 13:05:26 -0700769 }
770
771 private void processLinkRemoved(Link link) {
Saurav Dasb5c236e2016-06-07 10:08:06 -0700772 log.info("** LINK REMOVED {}", link.toString());
sangho834e4b02015-05-01 09:38:25 -0700773 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
774 if (groupHandler != null) {
Saurav Das423fe2b2015-12-04 10:52:59 -0800775 groupHandler.portDown(link.src().port(),
776 mastershipService.isLocalMaster(link.src().deviceId()));
sangho834e4b02015-05-01 09:38:25 -0700777 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700778 log.trace("Starting optimized route population process");
779 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
780 //log.trace("processLinkRemoved: re-starting route population process");
781 //defaultRoutingHandler.startPopulationProcess();
Charles Chan2199c302016-04-23 17:36:10 -0700782
783 mcastHandler.processLinkDown(link);
sanghob35a6192015-04-01 13:05:26 -0700784 }
785
786 private void processDeviceAdded(Device device) {
Saurav Dasb5c236e2016-06-07 10:08:06 -0700787 log.info("** DEVICE ADDED with ID {}", device.id());
Charles Chan0b4e6182015-11-03 10:42:14 -0800788 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
Saurav Das2857f382015-11-03 14:39:27 -0800789 log.warn("Device configuration uploading. Device {} will be "
790 + "processed after config completes.", device.id());
791 return;
792 }
Charles Chan2199c302016-04-23 17:36:10 -0700793 processDeviceAddedInternal(device.id());
794 }
795
796 private void processDeviceAddedInternal(DeviceId deviceId) {
Saurav Das837e0bb2015-10-30 17:45:38 -0700797 // Irrespective of whether the local is a MASTER or not for this device,
798 // we need to create a SR-group-handler instance. This is because in a
799 // multi-instance setup, any instance can initiate forwarding/next-objectives
800 // for any switch (even if this instance is a SLAVE or not even connected
801 // to the switch). To handle this, a default-group-handler instance is necessary
802 // per switch.
Charles Chan2199c302016-04-23 17:36:10 -0700803 log.debug("Current groupHandlerMap devs: {}", groupHandlerMap.keySet());
804 if (groupHandlerMap.get(deviceId) == null) {
Charles Chan0b4e6182015-11-03 10:42:14 -0800805 DefaultGroupHandler groupHandler;
806 try {
807 groupHandler = DefaultGroupHandler.
Charles Chan2199c302016-04-23 17:36:10 -0700808 createGroupHandler(deviceId,
809 appId,
810 deviceConfiguration,
811 linkService,
812 flowObjectiveService,
813 this);
Charles Chan0b4e6182015-11-03 10:42:14 -0800814 } catch (DeviceConfigNotFoundException e) {
815 log.warn(e.getMessage() + " Aborting processDeviceAdded.");
816 return;
817 }
Charles Chan2199c302016-04-23 17:36:10 -0700818 log.debug("updating groupHandlerMap with new config for device: {}",
819 deviceId);
820 groupHandlerMap.put(deviceId, groupHandler);
Saurav Das2857f382015-11-03 14:39:27 -0800821 }
Saurav Dasb5c236e2016-06-07 10:08:06 -0700822 // Also, in some cases, drivers may need extra
823 // information to process rules (eg. Router IP/MAC); and so, we send
824 // port addressing rules to the driver as well irrespective of whether
825 // this instance is the master or not.
826 defaultRoutingHandler.populatePortAddressingRules(deviceId);
827
Charles Chan2199c302016-04-23 17:36:10 -0700828 if (mastershipService.isLocalMaster(deviceId)) {
829 hostHandler.readInitialHosts(deviceId);
Charles Chanfc5c7802016-05-17 13:13:55 -0700830 xConnectHandler.init(deviceId);
Charles Chan35fd1a72016-06-13 18:54:31 -0700831 cordConfigHandler.init(deviceId);
Charles Chan2199c302016-04-23 17:36:10 -0700832 DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
Charles Chanc42e84e2015-10-20 16:24:19 -0700833 groupHandler.createGroupsFromSubnetConfig();
Charles Chan2199c302016-04-23 17:36:10 -0700834 routingRulePopulator.populateSubnetBroadcastRule(deviceId);
Charles Chanc42e84e2015-10-20 16:24:19 -0700835 }
Charles Chan5270ed02016-01-30 23:22:37 -0800836
Charles Chanfc5c7802016-05-17 13:13:55 -0700837 appCfgHandler.initVRouters(deviceId);
sanghob35a6192015-04-01 13:05:26 -0700838 }
839
Saurav Das80980c72016-03-23 11:22:49 -0700840 private void processDeviceRemoved(Device device) {
841 nsNextObjStore.entrySet().stream()
842 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
843 .forEach(entry -> {
844 nsNextObjStore.remove(entry.getKey());
845 });
Saurav Das80980c72016-03-23 11:22:49 -0700846 subnetNextObjStore.entrySet().stream()
847 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
848 .forEach(entry -> {
849 subnetNextObjStore.remove(entry.getKey());
850 });
Saurav Das80980c72016-03-23 11:22:49 -0700851 portNextObjStore.entrySet().stream()
852 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
853 .forEach(entry -> {
854 portNextObjStore.remove(entry.getKey());
855 });
Saurav Das80980c72016-03-23 11:22:49 -0700856 subnetVidStore.entrySet().stream()
857 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
858 .forEach(entry -> {
859 subnetVidStore.remove(entry.getKey());
860 });
Saurav Das80980c72016-03-23 11:22:49 -0700861 groupHandlerMap.remove(device.id());
Saurav Das80980c72016-03-23 11:22:49 -0700862 defaultRoutingHandler.purgeEcmpGraph(device.id());
Charles Chan2199c302016-04-23 17:36:10 -0700863 mcastHandler.removeDevice(device.id());
Charles Chanfc5c7802016-05-17 13:13:55 -0700864 xConnectHandler.removeDevice(device.id());
Saurav Das80980c72016-03-23 11:22:49 -0700865 }
866
sanghob35a6192015-04-01 13:05:26 -0700867 private void processPortRemoved(Device device, Port port) {
Saurav Dasb5c236e2016-06-07 10:08:06 -0700868 log.info("Port {} was removed", port.toString());
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700869 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
sanghob35a6192015-04-01 13:05:26 -0700870 if (groupHandler != null) {
Saurav Das423fe2b2015-12-04 10:52:59 -0800871 groupHandler.portDown(port.number(),
872 mastershipService.isLocalMaster(device.id()));
sanghob35a6192015-04-01 13:05:26 -0700873 }
874 }
sangho1e575652015-05-14 00:39:53 -0700875
Charles Chand6832882015-10-05 17:50:33 -0700876 private class InternalConfigListener implements NetworkConfigListener {
Charles Chan4636be02015-10-07 14:21:45 -0700877 SegmentRoutingManager segmentRoutingManager;
878
Charles Chane849c192016-01-11 18:28:54 -0800879 /**
880 * Constructs the internal network config listener.
881 *
882 * @param srMgr segment routing manager
883 */
Charles Chan4636be02015-10-07 14:21:45 -0700884 public InternalConfigListener(SegmentRoutingManager srMgr) {
885 this.segmentRoutingManager = srMgr;
886 }
887
Charles Chane849c192016-01-11 18:28:54 -0800888 /**
889 * Reads network config and initializes related data structure accordingly.
890 */
Charles Chan4636be02015-10-07 14:21:45 -0700891 public void configureNetwork() {
Charles Chanf2565a92016-02-10 20:46:58 -0800892 deviceConfiguration = new DeviceConfiguration(appId,
893 segmentRoutingManager.cfgService);
Charles Chan4636be02015-10-07 14:21:45 -0700894
895 arpHandler = new ArpHandler(segmentRoutingManager);
896 icmpHandler = new IcmpHandler(segmentRoutingManager);
897 ipHandler = new IpHandler(segmentRoutingManager);
898 routingRulePopulator = new RoutingRulePopulator(segmentRoutingManager);
899 defaultRoutingHandler = new DefaultRoutingHandler(segmentRoutingManager);
900
901 tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
902 groupHandlerMap, tunnelStore);
903 policyHandler = new PolicyHandler(appId, deviceConfiguration,
904 flowObjectiveService,
905 tunnelHandler, policyStore);
906
Charles Chan4636be02015-10-07 14:21:45 -0700907 for (Device device : deviceService.getDevices()) {
Charles Chan2199c302016-04-23 17:36:10 -0700908 processDeviceAddedInternal(device.id());
Charles Chan4636be02015-10-07 14:21:45 -0700909 }
910
911 defaultRoutingHandler.startPopulationProcess();
Charles Chan2199c302016-04-23 17:36:10 -0700912 mcastHandler.init();
Charles Chan4636be02015-10-07 14:21:45 -0700913 }
914
Charles Chand6832882015-10-05 17:50:33 -0700915 @Override
916 public void event(NetworkConfigEvent event) {
Charles Chan5270ed02016-01-30 23:22:37 -0800917 // TODO move this part to NetworkConfigEventHandler
918 if (event.configClass().equals(SegmentRoutingDeviceConfig.class)) {
919 switch (event.type()) {
920 case CONFIG_ADDED:
921 log.info("Segment Routing Config added.");
922 configureNetwork();
923 break;
924 case CONFIG_UPDATED:
925 log.info("Segment Routing Config updated.");
926 // TODO support dynamic configuration
927 break;
928 default:
929 break;
Charles Chanb8e10c82015-10-14 11:24:40 -0700930 }
Charles Chan5270ed02016-01-30 23:22:37 -0800931 } else if (event.configClass().equals(SegmentRoutingAppConfig.class)) {
Charles Chanfc5c7802016-05-17 13:13:55 -0700932 checkState(appCfgHandler != null, "NetworkConfigEventHandler is not initialized");
Charles Chan5270ed02016-01-30 23:22:37 -0800933 switch (event.type()) {
934 case CONFIG_ADDED:
Charles Chanfc5c7802016-05-17 13:13:55 -0700935 appCfgHandler.processAppConfigAdded(event);
Charles Chan5270ed02016-01-30 23:22:37 -0800936 break;
937 case CONFIG_UPDATED:
Charles Chanfc5c7802016-05-17 13:13:55 -0700938 appCfgHandler.processAppConfigUpdated(event);
Charles Chan5270ed02016-01-30 23:22:37 -0800939 break;
940 case CONFIG_REMOVED:
Charles Chanfc5c7802016-05-17 13:13:55 -0700941 appCfgHandler.processAppConfigRemoved(event);
942 break;
943 default:
944 break;
945 }
946 } else if (event.configClass().equals(XConnectConfig.class)) {
947 checkState(xConnectHandler != null, "XConnectHandler is not initialized");
948 switch (event.type()) {
949 case CONFIG_ADDED:
950 xConnectHandler.processXConnectConfigAdded(event);
951 break;
952 case CONFIG_UPDATED:
953 xConnectHandler.processXConnectConfigUpdated(event);
954 break;
955 case CONFIG_REMOVED:
956 xConnectHandler.processXConnectConfigRemoved(event);
Charles Chan5270ed02016-01-30 23:22:37 -0800957 break;
958 default:
959 break;
Charles Chanb8e10c82015-10-14 11:24:40 -0700960 }
Charles Chand6832882015-10-05 17:50:33 -0700961 }
962 }
963 }
Charles Chan68aa62d2015-11-09 16:37:23 -0800964
965 private class InternalHostListener implements HostListener {
Charles Chan68aa62d2015-11-09 16:37:23 -0800966 @Override
967 public void event(HostEvent event) {
968 // Do not proceed without mastership
969 DeviceId deviceId = event.subject().location().deviceId();
970 if (!mastershipService.isLocalMaster(deviceId)) {
971 return;
972 }
973
974 switch (event.type()) {
975 case HOST_ADDED:
Charles Chand2990362016-04-18 13:44:03 -0700976 hostHandler.processHostAddedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -0800977 break;
978 case HOST_MOVED:
Charles Chand2990362016-04-18 13:44:03 -0700979 hostHandler.processHostMovedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -0800980 break;
981 case HOST_REMOVED:
Charles Chand2990362016-04-18 13:44:03 -0700982 hostHandler.processHostRemoveEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -0800983 break;
984 case HOST_UPDATED:
Charles Chand2990362016-04-18 13:44:03 -0700985 hostHandler.processHostUpdatedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -0800986 break;
987 default:
988 log.warn("Unsupported host event type: {}", event.type());
989 break;
990 }
991 }
992 }
993
Charles Chand55e84d2016-03-30 17:54:24 -0700994 private class InternalMcastListener implements McastListener {
995 @Override
996 public void event(McastEvent event) {
997 switch (event.type()) {
998 case SOURCE_ADDED:
Charles Chand2990362016-04-18 13:44:03 -0700999 mcastHandler.processSourceAdded(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001000 break;
1001 case SINK_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001002 mcastHandler.processSinkAdded(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001003 break;
1004 case SINK_REMOVED:
Charles Chand2990362016-04-18 13:44:03 -07001005 mcastHandler.processSinkRemoved(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001006 break;
1007 case ROUTE_ADDED:
1008 case ROUTE_REMOVED:
1009 default:
1010 break;
1011 }
1012 }
1013 }
Charles Chan35fd1a72016-06-13 18:54:31 -07001014
1015 private class InternalCordConfigListener implements CordConfigListener {
1016 @Override
1017 public void event(CordConfigEvent event) {
1018 switch (event.type()) {
1019 case ACCESS_AGENT_ADDED:
1020 cordConfigHandler.processAccessAgentAddedEvent(event);
1021 break;
1022 case ACCESS_AGENT_UPDATED:
1023 cordConfigHandler.processAccessAgentUpdatedEvent(event);
1024 break;
1025 case ACCESS_AGENT_REMOVED:
1026 cordConfigHandler.processAccessAgentRemovedEvent(event);
1027 break;
1028 case ACCESS_DEVICE_ADDED:
1029 case ACCESS_DEVICE_UPDATED:
1030 case ACCESS_DEVICE_REMOVED:
1031 default:
1032 break;
1033 }
1034 }
1035 }
sanghob35a6192015-04-01 13:05:26 -07001036}