blob: 9305541433e2694b96e206ffcf630e8d8ea01cfd [file] [log] [blame]
sangho80f11cb2015-04-01 13:05:26 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
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;
25import org.onlab.packet.IPv4;
Saurav Das7c305372015-10-28 12:39:42 -070026import org.onlab.packet.Ip4Prefix;
27import org.onlab.packet.VlanId;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070028import org.onlab.util.KryoNamespace;
sangho80f11cb2015-04-01 13:05:26 -070029import org.onosproject.core.ApplicationId;
30import org.onosproject.core.CoreService;
31import org.onosproject.event.Event;
Charles Chan72f556a2015-10-05 17:50:33 -070032import org.onosproject.net.config.ConfigFactory;
33import org.onosproject.net.config.NetworkConfigEvent;
34import org.onosproject.net.config.NetworkConfigRegistry;
35import org.onosproject.net.config.NetworkConfigListener;
36import org.onosproject.net.config.basics.SubjectFactories;
37import org.onosproject.segmentrouting.config.SegmentRoutingConfig;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070038import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
39import org.onosproject.segmentrouting.grouphandler.NeighborSet;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070040import org.onosproject.segmentrouting.grouphandler.NeighborSetNextObjectiveStoreKey;
sangho80f11cb2015-04-01 13:05:26 -070041import org.onosproject.mastership.MastershipService;
42import org.onosproject.net.Device;
43import org.onosproject.net.DeviceId;
44import org.onosproject.net.Link;
sangho80f11cb2015-04-01 13:05:26 -070045import org.onosproject.net.Port;
46import org.onosproject.net.device.DeviceEvent;
47import org.onosproject.net.device.DeviceListener;
48import org.onosproject.net.device.DeviceService;
Srikanth Vavilapalli64505482015-04-21 13:04:13 -070049import org.onosproject.net.flowobjective.FlowObjectiveService;
sangho80f11cb2015-04-01 13:05:26 -070050import org.onosproject.net.host.HostService;
51import org.onosproject.net.intent.IntentService;
52import org.onosproject.net.link.LinkEvent;
53import org.onosproject.net.link.LinkListener;
54import org.onosproject.net.link.LinkService;
55import org.onosproject.net.packet.InboundPacket;
56import org.onosproject.net.packet.PacketContext;
57import org.onosproject.net.packet.PacketProcessor;
58import org.onosproject.net.packet.PacketService;
59import org.onosproject.net.topology.TopologyService;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070060import org.onosproject.store.service.EventuallyConsistentMap;
61import org.onosproject.store.service.EventuallyConsistentMapBuilder;
62import org.onosproject.store.service.StorageService;
63import org.onosproject.store.service.WallClockTimestamp;
sangho80f11cb2015-04-01 13:05:26 -070064import org.slf4j.Logger;
65import org.slf4j.LoggerFactory;
66
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070067import java.net.URI;
Saurav Das7c305372015-10-28 12:39:42 -070068import java.util.Collections;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070069import java.util.HashSet;
sangho27462c62015-05-14 00:39:53 -070070import java.util.List;
sangho80f11cb2015-04-01 13:05:26 -070071import java.util.Map;
Saurav Das7c305372015-10-28 12:39:42 -070072import java.util.Set;
sangho80f11cb2015-04-01 13:05:26 -070073import java.util.concurrent.ConcurrentHashMap;
74import java.util.concurrent.ConcurrentLinkedQueue;
75import java.util.concurrent.Executors;
76import java.util.concurrent.ScheduledExecutorService;
77import java.util.concurrent.ScheduledFuture;
78import java.util.concurrent.TimeUnit;
79
80@SuppressWarnings("ALL")
sangho27462c62015-05-14 00:39:53 -070081@Service
sangho80f11cb2015-04-01 13:05:26 -070082@Component(immediate = true)
sangho27462c62015-05-14 00:39:53 -070083public class SegmentRoutingManager implements SegmentRoutingService {
sangho80f11cb2015-04-01 13:05:26 -070084
Srikanth Vavilapalli64505482015-04-21 13:04:13 -070085 private static Logger log = LoggerFactory
86 .getLogger(SegmentRoutingManager.class);
sangho80f11cb2015-04-01 13:05:26 -070087
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected CoreService coreService;
90
91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 protected TopologyService topologyService;
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected PacketService packetService;
96
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
98 protected IntentService intentService;
99
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected HostService hostService;
102
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 protected DeviceService deviceService;
105
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700107 protected FlowObjectiveService flowObjectiveService;
sangho80f11cb2015-04-01 13:05:26 -0700108
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected LinkService linkService;
111
112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sangho80f11cb2015-04-01 13:05:26 -0700113 protected MastershipService mastershipService;
sangho27462c62015-05-14 00:39:53 -0700114
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700115 protected ArpHandler arpHandler = null;
116 protected IcmpHandler icmpHandler = null;
117 protected IpHandler ipHandler = null;
118 protected RoutingRulePopulator routingRulePopulator = null;
sangho80f11cb2015-04-01 13:05:26 -0700119 protected ApplicationId appId;
sangho9b169e32015-04-14 16:27:13 -0700120 protected DeviceConfiguration deviceConfiguration = null;
sangho80f11cb2015-04-01 13:05:26 -0700121
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700122 private DefaultRoutingHandler defaultRoutingHandler = null;
sangho27462c62015-05-14 00:39:53 -0700123 private TunnelHandler tunnelHandler = null;
124 private PolicyHandler policyHandler = null;
Charles Chan2b078ae2015-10-14 11:24:40 -0700125 private InternalPacketProcessor processor = null;
126 private InternalLinkListener linkListener = null;
127 private InternalDeviceListener deviceListener = null;
sangho80f11cb2015-04-01 13:05:26 -0700128 private InternalEventHandler eventHandler = new InternalEventHandler();
129
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700130 private ScheduledExecutorService executorService = Executors
131 .newScheduledThreadPool(1);
sangho80f11cb2015-04-01 13:05:26 -0700132
133 private static ScheduledFuture<?> eventHandlerFuture = null;
134 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>();
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700135 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap = new ConcurrentHashMap<DeviceId, DefaultGroupHandler>();
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700136 // Per device next objective ID store with (device id + neighbor set) as key
137 private EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
138 Integer> nsNextObjStore = null;
sangho4a5c42a2015-05-20 22:16:38 -0700139 private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
140 private EventuallyConsistentMap<String, Policy> policyStore = null;
Saurav Das7c305372015-10-28 12:39:42 -0700141 // Per device, per-subnet assigned-vlans store, with (device id + subnet
142 // IPv4 prefix) as key
143 private EventuallyConsistentMap<SubnetAssignedVidStoreKey, VlanId>
144 subnetVidStore = null;
sangho4a5c42a2015-05-20 22:16:38 -0700145
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700146 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
147 protected StorageService storageService;
sangho80f11cb2015-04-01 13:05:26 -0700148
Charles Chan72f556a2015-10-05 17:50:33 -0700149 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
150 protected NetworkConfigRegistry cfgService;
151
Charles Chane7c61022015-10-07 14:21:45 -0700152 private final InternalConfigListener cfgListener =
153 new InternalConfigListener(this);
154
Charles Chan72f556a2015-10-05 17:50:33 -0700155 private final ConfigFactory cfgFactory =
156 new ConfigFactory(SubjectFactories.DEVICE_SUBJECT_FACTORY,
157 SegmentRoutingConfig.class,
158 "segmentrouting") {
159 @Override
160 public SegmentRoutingConfig createConfig() {
161 return new SegmentRoutingConfig();
162 }
163 };
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700164
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700165 private Object threadSchedulerLock = new Object();
166 private static int numOfEventsQueued = 0;
167 private static int numOfEventsExecuted = 0;
sangho80f11cb2015-04-01 13:05:26 -0700168 private static int numOfHandlerExecution = 0;
169 private static int numOfHandlerScheduled = 0;
170
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700171 private KryoNamespace.Builder kryoBuilder = null;
172
Saurav Das7c305372015-10-28 12:39:42 -0700173 private static final short ASSIGNED_VLAN_START = 4093;
174 public static final short ASSIGNED_VLAN_NO_SUBNET = 4094;
175
sangho80f11cb2015-04-01 13:05:26 -0700176 @Activate
177 protected void activate() {
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700178 appId = coreService
179 .registerApplication("org.onosproject.segmentrouting");
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700180
181 kryoBuilder = new KryoNamespace.Builder()
182 .register(NeighborSetNextObjectiveStoreKey.class,
sangho4a5c42a2015-05-20 22:16:38 -0700183 NeighborSet.class,
184 DeviceId.class,
185 URI.class,
186 WallClockTimestamp.class,
187 org.onosproject.cluster.NodeId.class,
188 HashSet.class,
189 Tunnel.class,
190 DefaultTunnel.class,
191 Policy.class,
192 TunnelPolicy.class,
Saurav Das7c305372015-10-28 12:39:42 -0700193 Policy.Type.class,
194 SubnetAssignedVidStoreKey.class,
195 VlanId.class
sangho4a5c42a2015-05-20 22:16:38 -0700196 );
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700197
198 log.debug("Creating EC map nsnextobjectivestore");
199 EventuallyConsistentMapBuilder<NeighborSetNextObjectiveStoreKey, Integer>
200 nsNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
201
202 nsNextObjStore = nsNextObjMapBuilder
203 .withName("nsnextobjectivestore")
204 .withSerializer(kryoBuilder)
Madan Jampani675ae202015-06-24 19:05:56 -0700205 .withTimestampProvider((k, v) -> new WallClockTimestamp())
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700206 .build();
207 log.trace("Current size {}", nsNextObjStore.size());
208
sangho4a5c42a2015-05-20 22:16:38 -0700209 EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
210 storageService.eventuallyConsistentMapBuilder();
211
212 tunnelStore = tunnelMapBuilder
213 .withName("tunnelstore")
214 .withSerializer(kryoBuilder)
Madan Jampani675ae202015-06-24 19:05:56 -0700215 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho4a5c42a2015-05-20 22:16:38 -0700216 .build();
217
218 EventuallyConsistentMapBuilder<String, Policy> policyMapBuilder =
219 storageService.eventuallyConsistentMapBuilder();
220
221 policyStore = policyMapBuilder
222 .withName("policystore")
223 .withSerializer(kryoBuilder)
Madan Jampani675ae202015-06-24 19:05:56 -0700224 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho4a5c42a2015-05-20 22:16:38 -0700225 .build();
226
Saurav Das7c305372015-10-28 12:39:42 -0700227 EventuallyConsistentMapBuilder<SubnetAssignedVidStoreKey, VlanId>
228 subnetVidStoreMapBuilder = storageService.eventuallyConsistentMapBuilder();
229
230 subnetVidStore = subnetVidStoreMapBuilder
231 .withName("subnetvidstore")
232 .withSerializer(kryoBuilder)
233 .withTimestampProvider((k, v) -> new WallClockTimestamp())
234 .build();
235
Charles Chan72f556a2015-10-05 17:50:33 -0700236 cfgService.addListener(cfgListener);
237 cfgService.registerConfigFactory(cfgFactory);
Charles Chan72f556a2015-10-05 17:50:33 -0700238
Charles Chan2b078ae2015-10-14 11:24:40 -0700239 processor = new InternalPacketProcessor();
240 linkListener = new InternalLinkListener();
241 deviceListener = new InternalDeviceListener();
242
243 packetService.addProcessor(processor, PacketProcessor.director(2));
244 linkService.addListener(linkListener);
245 deviceService.addListener(deviceListener);
246
247 cfgListener.configureNetwork();
248
sangho80f11cb2015-04-01 13:05:26 -0700249 log.info("Started");
250 }
251
252 @Deactivate
253 protected void deactivate() {
Charles Chan72f556a2015-10-05 17:50:33 -0700254 cfgService.removeListener(cfgListener);
255 cfgService.unregisterConfigFactory(cfgFactory);
256
sangho80f11cb2015-04-01 13:05:26 -0700257 packetService.removeProcessor(processor);
Charles Chan2b078ae2015-10-14 11:24:40 -0700258 linkService.removeListener(linkListener);
259 deviceService.removeListener(deviceListener);
sangho80f11cb2015-04-01 13:05:26 -0700260 processor = null;
Charles Chan2b078ae2015-10-14 11:24:40 -0700261 linkListener = null;
262 deviceService = null;
263
264 groupHandlerMap.clear();
265
sangho80f11cb2015-04-01 13:05:26 -0700266 log.info("Stopped");
267 }
268
sangho27462c62015-05-14 00:39:53 -0700269
270 @Override
271 public List<Tunnel> getTunnels() {
272 return tunnelHandler.getTunnels();
273 }
274
275 @Override
sanghobd812f82015-06-29 14:58:47 -0700276 public TunnelHandler.Result createTunnel(Tunnel tunnel) {
277 return tunnelHandler.createTunnel(tunnel);
sangho27462c62015-05-14 00:39:53 -0700278 }
279
280 @Override
sanghobd812f82015-06-29 14:58:47 -0700281 public TunnelHandler.Result removeTunnel(Tunnel tunnel) {
sangho27462c62015-05-14 00:39:53 -0700282 for (Policy policy: policyHandler.getPolicies()) {
283 if (policy.type() == Policy.Type.TUNNEL_FLOW) {
284 TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
285 if (tunnelPolicy.tunnelId().equals(tunnel.id())) {
286 log.warn("Cannot remove the tunnel used by a policy");
sanghobd812f82015-06-29 14:58:47 -0700287 return TunnelHandler.Result.TUNNEL_IN_USE;
sangho27462c62015-05-14 00:39:53 -0700288 }
289 }
290 }
sanghobd812f82015-06-29 14:58:47 -0700291 return tunnelHandler.removeTunnel(tunnel);
sangho27462c62015-05-14 00:39:53 -0700292 }
293
294 @Override
sanghobd812f82015-06-29 14:58:47 -0700295 public PolicyHandler.Result removePolicy(Policy policy) {
296 return policyHandler.removePolicy(policy);
sangho27462c62015-05-14 00:39:53 -0700297 }
298
299 @Override
sanghobd812f82015-06-29 14:58:47 -0700300 public PolicyHandler.Result createPolicy(Policy policy) {
301 return policyHandler.createPolicy(policy);
sangho27462c62015-05-14 00:39:53 -0700302 }
303
304 @Override
305 public List<Policy> getPolicies() {
306 return policyHandler.getPolicies();
307 }
308
sangho80f1f892015-05-19 11:57:42 -0700309 /**
310 * Returns the tunnel object with the tunnel ID.
311 *
312 * @param tunnelId Tunnel ID
313 * @return Tunnel reference
314 */
sangho27462c62015-05-14 00:39:53 -0700315 public Tunnel getTunnel(String tunnelId) {
316 return tunnelHandler.getTunnel(tunnelId);
317 }
318
sangho80f11cb2015-04-01 13:05:26 -0700319 /**
Saurav Das7c305372015-10-28 12:39:42 -0700320 * Returns the vlan-id assigned to the subnet configured for a device.
321 * If no vlan-id has been assigned, a new one is assigned out of a pool of ids,
322 * if and only if this controller instance is the master for the device.
323 * <p>
324 * USAGE: The assigned vlans are meant to be applied to untagged packets on those
325 * switches/pipelines that need this functionality. These vids are meant
326 * to be used internally within a switch, and thus need to be unique only
327 * on a switch level. Note that packets never go out on the wire with these
328 * vlans. Currently, vlan ids are assigned from value 4093 down.
329 * Vlan id 4094 expected to be used for all ports that are not assigned subnets.
330 * Vlan id 4095 is reserved and unused. Only a single vlan id is assigned
331 * per subnet.
332 * XXX This method should avoid any vlans configured on the ports, but
333 * currently the app works only on untagged packets and as a result
334 * ignores any vlan configuration.
sangho80f11cb2015-04-01 13:05:26 -0700335 *
Saurav Das7c305372015-10-28 12:39:42 -0700336 * @param deviceId switch dpid
337 * @param subnet IPv4 prefix for which assigned vlan is desired
338 * @return VlanId assigned for the subnet on the device, or
339 * null if no vlan assignment was found and this instance is not
340 * the master for the device.
sangho80f11cb2015-04-01 13:05:26 -0700341 */
Saurav Das7c305372015-10-28 12:39:42 -0700342 public VlanId getSubnetAssignedVlanId(DeviceId deviceId, Ip4Prefix subnet) {
343 VlanId assignedVid = subnetVidStore.get(new SubnetAssignedVidStoreKey(
344 deviceId, subnet));
345 if (assignedVid != null) {
346 log.debug("Query for subnet:{} on device:{} returned assigned-vlan "
347 + "{}", subnet, deviceId, assignedVid);
348 return assignedVid;
349 }
350 //check mastership for the right to assign a vlan
351 if (!mastershipService.isLocalMaster(deviceId)) {
352 log.warn("This controller instance is not the master for device {}. "
353 + "Cannot assign vlan-id for subnet {}", deviceId, subnet);
354 return null;
355 }
356 // vlan assignment is expensive but done only once
357 List<Ip4Prefix> configuredSubnets = deviceConfiguration.getSubnets(deviceId);
358 Set<Short> assignedVlans = new HashSet<>();
359 Set<Ip4Prefix> unassignedSubnets = new HashSet<>();
360 for (Ip4Prefix sub : configuredSubnets) {
361 VlanId v = subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId,
362 sub));
363 if (v != null) {
364 assignedVlans.add(v.toShort());
365 } else {
366 unassignedSubnets.add(sub);
367 }
368 }
369 short nextAssignedVlan = ASSIGNED_VLAN_START;
370 if (!assignedVlans.isEmpty()) {
371 nextAssignedVlan = (short) (Collections.min(assignedVlans) - 1);
372 }
373 for (Ip4Prefix unsub : unassignedSubnets) {
374 subnetVidStore.put(new SubnetAssignedVidStoreKey(deviceId, unsub),
375 VlanId.vlanId(nextAssignedVlan--));
376 log.info("Assigned vlan: {} to subnet: {} on device: {}",
377 nextAssignedVlan + 1, unsub, deviceId);
sangho80f11cb2015-04-01 13:05:26 -0700378 }
379
Saurav Das7c305372015-10-28 12:39:42 -0700380 return subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId, subnet));
sangho80f11cb2015-04-01 13:05:26 -0700381 }
382
sangho27462c62015-05-14 00:39:53 -0700383 /**
Saurav Das7c305372015-10-28 12:39:42 -0700384 * Returns the next objective ID for the given NeighborSet.
385 * If the nextObjectiveID does not exist, a new one is created and returned.
sangho27462c62015-05-14 00:39:53 -0700386 *
sangho80f1f892015-05-19 11:57:42 -0700387 * @param deviceId Device ID
388 * @param ns NegighborSet
389 * @return next objective ID
sangho27462c62015-05-14 00:39:53 -0700390 */
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700391 public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns) {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700392 if (groupHandlerMap.get(deviceId) != null) {
393 log.trace("getNextObjectiveId query in device {}", deviceId);
394 return groupHandlerMap
395 .get(deviceId).getNextObjectiveId(ns);
396 } else {
397 log.warn("getNextObjectiveId query in device {} not found", deviceId);
398 return -1;
399 }
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700400 }
401
sangho80f11cb2015-04-01 13:05:26 -0700402 private class InternalPacketProcessor implements PacketProcessor {
sangho80f11cb2015-04-01 13:05:26 -0700403 @Override
404 public void process(PacketContext context) {
405
406 if (context.isHandled()) {
407 return;
408 }
409
410 InboundPacket pkt = context.inPacket();
411 Ethernet ethernet = pkt.parsed();
412
413 if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
414 arpHandler.processPacketIn(pkt);
415 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
416 IPv4 ipPacket = (IPv4) ethernet.getPayload();
417 ipHandler.addToPacketBuffer(ipPacket);
418 if (ipPacket.getProtocol() == IPv4.PROTOCOL_ICMP) {
419 icmpHandler.processPacketIn(pkt);
420 } else {
421 ipHandler.processPacketIn(pkt);
422 }
423 }
424 }
425 }
426
427 private class InternalLinkListener implements LinkListener {
428 @Override
429 public void event(LinkEvent event) {
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700430 if (event.type() == LinkEvent.Type.LINK_ADDED
431 || event.type() == LinkEvent.Type.LINK_REMOVED) {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700432 log.debug("Event {} received from Link Service", event.type());
sangho80f11cb2015-04-01 13:05:26 -0700433 scheduleEventHandlerIfNotScheduled(event);
434 }
435 }
436 }
437
438 private class InternalDeviceListener implements DeviceListener {
sangho80f11cb2015-04-01 13:05:26 -0700439 @Override
440 public void event(DeviceEvent event) {
sangho80f11cb2015-04-01 13:05:26 -0700441 switch (event.type()) {
442 case DEVICE_ADDED:
443 case PORT_REMOVED:
sanghofb7c7292015-04-13 15:15:58 -0700444 case DEVICE_UPDATED:
445 case DEVICE_AVAILABILITY_CHANGED:
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700446 log.debug("Event {} received from Device Service", event.type());
sangho80f11cb2015-04-01 13:05:26 -0700447 scheduleEventHandlerIfNotScheduled(event);
448 break;
449 default:
450 }
451 }
452 }
453
sangho80f11cb2015-04-01 13:05:26 -0700454 private void scheduleEventHandlerIfNotScheduled(Event event) {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700455 synchronized (threadSchedulerLock) {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700456 eventQueue.add(event);
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700457 numOfEventsQueued++;
458
459 if ((numOfHandlerScheduled - numOfHandlerExecution) == 0) {
460 //No pending scheduled event handling threads. So start a new one.
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700461 eventHandlerFuture = executorService
462 .schedule(eventHandler, 100, TimeUnit.MILLISECONDS);
463 numOfHandlerScheduled++;
464 }
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700465 log.trace("numOfEventsQueued {}, numOfEventHanlderScheduled {}",
466 numOfEventsQueued,
467 numOfHandlerScheduled);
sangho80f11cb2015-04-01 13:05:26 -0700468 }
sangho80f11cb2015-04-01 13:05:26 -0700469 }
470
471 private class InternalEventHandler implements Runnable {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700472 @Override
sangho80f11cb2015-04-01 13:05:26 -0700473 public void run() {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700474 try {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700475 while (true) {
476 Event event = null;
477 synchronized (threadSchedulerLock) {
478 if (!eventQueue.isEmpty()) {
479 event = eventQueue.poll();
480 numOfEventsExecuted++;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700481 } else {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700482 numOfHandlerExecution++;
483 log.debug("numOfHandlerExecution {} numOfEventsExecuted {}",
484 numOfHandlerExecution, numOfEventsExecuted);
485 break;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700486 }
sanghofb7c7292015-04-13 15:15:58 -0700487 }
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700488 if (event.type() == LinkEvent.Type.LINK_ADDED) {
489 processLinkAdded((Link) event.subject());
490 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
491 processLinkRemoved((Link) event.subject());
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700492 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
493 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
494 event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
495 if (deviceService.isAvailable(((Device) event.subject()).id())) {
496 processDeviceAdded((Device) event.subject());
497 }
498 } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
499 processPortRemoved((Device) event.subject(),
500 ((DeviceEvent) event).port());
501 } else {
502 log.warn("Unhandled event type: {}", event.type());
503 }
sangho80f11cb2015-04-01 13:05:26 -0700504 }
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700505 } catch (Exception e) {
506 log.error("SegmentRouting event handler "
507 + "thread thrown an exception: {}", e);
sangho80f11cb2015-04-01 13:05:26 -0700508 }
sangho80f11cb2015-04-01 13:05:26 -0700509 }
510 }
511
sangho80f11cb2015-04-01 13:05:26 -0700512 private void processLinkAdded(Link link) {
513 log.debug("A new link {} was added", link.toString());
514
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700515 //Irrespective whether the local is a MASTER or not for this device,
516 //create group handler instance and push default TTP flow rules.
517 //Because in a multi-instance setup, instances can initiate
518 //groups for any devices. Also the default TTP rules are needed
519 //to be pushed before inserting any IP table entries for any device
520 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src()
521 .deviceId());
522 if (groupHandler != null) {
523 groupHandler.linkUp(link);
524 } else {
525 Device device = deviceService.getDevice(link.src().deviceId());
526 if (device != null) {
527 log.warn("processLinkAdded: Link Added "
528 + "Notification without Device Added "
529 + "event, still handling it");
530 processDeviceAdded(device);
531 groupHandler = groupHandlerMap.get(link.src()
532 .deviceId());
sangho80f11cb2015-04-01 13:05:26 -0700533 groupHandler.linkUp(link);
534 }
535 }
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700536
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700537 log.trace("Starting optimized route population process");
538 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null);
539 //log.trace("processLinkAdded: re-starting route population process");
540 //defaultRoutingHandler.startPopulationProcess();
sangho80f11cb2015-04-01 13:05:26 -0700541 }
542
543 private void processLinkRemoved(Link link) {
544 log.debug("A link {} was removed", link.toString());
sangho2165d222015-05-01 09:38:25 -0700545 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
546 if (groupHandler != null) {
547 groupHandler.portDown(link.src().port());
548 }
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700549 log.trace("Starting optimized route population process");
550 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
551 //log.trace("processLinkRemoved: re-starting route population process");
552 //defaultRoutingHandler.startPopulationProcess();
sangho80f11cb2015-04-01 13:05:26 -0700553 }
554
555 private void processDeviceAdded(Device device) {
556 log.debug("A new device with ID {} was added", device.id());
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700557 //Irrespective whether the local is a MASTER or not for this device,
558 //create group handler instance and push default TTP flow rules.
559 //Because in a multi-instance setup, instances can initiate
560 //groups for any devices. Also the default TTP rules are needed
561 //to be pushed before inserting any IP table entries for any device
562 DefaultGroupHandler dgh = DefaultGroupHandler.
563 createGroupHandler(device.id(),
564 appId,
565 deviceConfiguration,
566 linkService,
567 flowObjectiveService,
568 nsNextObjStore);
sangho80f11cb2015-04-01 13:05:26 -0700569 groupHandlerMap.put(device.id(), dgh);
Saurav Das9f1c42e2015-10-23 10:51:11 -0700570 defaultRoutingHandler.populatePortAddressingRules(device.id());
sangho80f11cb2015-04-01 13:05:26 -0700571 }
572
573 private void processPortRemoved(Device device, Port port) {
574 log.debug("Port {} was removed", port.toString());
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700575 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
sangho80f11cb2015-04-01 13:05:26 -0700576 if (groupHandler != null) {
577 groupHandler.portDown(port.number());
578 }
579 }
sangho27462c62015-05-14 00:39:53 -0700580
Charles Chan72f556a2015-10-05 17:50:33 -0700581 private class InternalConfigListener implements NetworkConfigListener {
Charles Chane7c61022015-10-07 14:21:45 -0700582 SegmentRoutingManager segmentRoutingManager;
583
584 public InternalConfigListener(SegmentRoutingManager srMgr) {
585 this.segmentRoutingManager = srMgr;
586 }
587
588 public void configureNetwork() {
589 deviceConfiguration = new DeviceConfiguration(segmentRoutingManager.cfgService);
590
591 arpHandler = new ArpHandler(segmentRoutingManager);
592 icmpHandler = new IcmpHandler(segmentRoutingManager);
593 ipHandler = new IpHandler(segmentRoutingManager);
594 routingRulePopulator = new RoutingRulePopulator(segmentRoutingManager);
595 defaultRoutingHandler = new DefaultRoutingHandler(segmentRoutingManager);
596
597 tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
598 groupHandlerMap, tunnelStore);
599 policyHandler = new PolicyHandler(appId, deviceConfiguration,
600 flowObjectiveService,
601 tunnelHandler, policyStore);
602
Charles Chane7c61022015-10-07 14:21:45 -0700603 for (Device device : deviceService.getDevices()) {
604 //Irrespective whether the local is a MASTER or not for this device,
605 //create group handler instance and push default TTP flow rules.
606 //Because in a multi-instance setup, instances can initiate
607 //groups for any devices. Also the default TTP rules are needed
608 //to be pushed before inserting any IP table entries for any device
609 DefaultGroupHandler groupHandler = DefaultGroupHandler
610 .createGroupHandler(device.id(), appId,
611 deviceConfiguration, linkService,
612 flowObjectiveService,
613 nsNextObjStore);
614 groupHandlerMap.put(device.id(), groupHandler);
Saurav Das9f1c42e2015-10-23 10:51:11 -0700615 defaultRoutingHandler.populatePortAddressingRules(device.id());
Charles Chane7c61022015-10-07 14:21:45 -0700616 }
617
618 defaultRoutingHandler.startPopulationProcess();
619 }
620
Charles Chan72f556a2015-10-05 17:50:33 -0700621 @Override
622 public void event(NetworkConfigEvent event) {
Charles Chan2b078ae2015-10-14 11:24:40 -0700623 if (event.configClass().equals(SegmentRoutingConfig.class)) {
624 if (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED) {
625 log.info("Network configuration added.");
626 configureNetwork();
627 }
628 if (event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) {
629 log.info("Network configuration updated.");
630 // TODO support dynamic configuration
631 }
Charles Chan72f556a2015-10-05 17:50:33 -0700632 }
633 }
634 }
sangho80f11cb2015-04-01 13:05:26 -0700635}