blob: 2d4cc451b06bbef3e5af63dc497b4b255924e3e9 [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
Charles Chand7844e52016-10-20 17:02:44 -070018import com.google.common.collect.Maps;
sangho80f11cb2015-04-01 13:05:26 -070019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
sangho27462c62015-05-14 00:39:53 -070024import org.apache.felix.scr.annotations.Service;
sangho80f11cb2015-04-01 13:05:26 -070025import org.onlab.packet.Ethernet;
Pier Ventreb6b81d52016-12-02 08:16:05 -080026import org.onlab.packet.ICMP6;
Charles Chan77277672015-10-20 16:24:19 -070027import org.onlab.packet.IPv4;
Pier Ventreb6a7f342016-11-26 21:05:22 -080028import org.onlab.packet.IPv6;
Charles Chan77277672015-10-20 16:24:19 -070029import org.onlab.packet.Ip4Prefix;
Charles Chan77277672015-10-20 16:24:19 -070030import org.onlab.packet.IpPrefix;
Jonathan Hart54541d12016-04-12 15:39:44 -070031import org.onlab.packet.VlanId;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070032import org.onlab.util.KryoNamespace;
Saurav Dasc3604f12016-03-23 11:22:49 -070033import org.onosproject.cfg.ComponentConfigService;
sangho80f11cb2015-04-01 13:05:26 -070034import org.onosproject.core.ApplicationId;
35import org.onosproject.core.CoreService;
36import org.onosproject.event.Event;
Pier Luigiad0a67f2017-02-03 13:34:21 -080037import org.onosproject.incubator.net.config.basics.ConfigException;
Pier Luigi37a35432017-02-01 13:50:04 -080038import org.onosproject.incubator.net.config.basics.InterfaceConfig;
Charles Chanc91c8782016-03-30 17:54:24 -070039import org.onosproject.incubator.net.config.basics.McastConfig;
Pier Luigiad0a67f2017-02-03 13:34:21 -080040import org.onosproject.incubator.net.intf.Interface;
Charles Chan46fdfaf2016-11-09 20:51:44 -080041import org.onosproject.incubator.net.intf.InterfaceService;
Charles Chandebfea32016-10-24 14:52:01 -070042import org.onosproject.incubator.net.routing.RouteEvent;
43import org.onosproject.incubator.net.routing.RouteListener;
44import org.onosproject.incubator.net.routing.RouteService;
Pier Ventreb6b81d52016-12-02 08:16:05 -080045import org.onosproject.incubator.net.neighbour.NeighbourResolutionService;
Jonathan Hart54541d12016-04-12 15:39:44 -070046import org.onosproject.mastership.MastershipService;
Pier Ventreb6a7f342016-11-26 21:05:22 -080047import org.onosproject.net.ConnectPoint;
Jonathan Hart54541d12016-04-12 15:39:44 -070048import org.onosproject.net.Device;
49import org.onosproject.net.DeviceId;
50import org.onosproject.net.Link;
51import org.onosproject.net.Port;
Charles Chanf4586112015-11-09 16:37:23 -080052import org.onosproject.net.PortNumber;
Charles Chan72f556a2015-10-05 17:50:33 -070053import org.onosproject.net.config.ConfigFactory;
54import org.onosproject.net.config.NetworkConfigEvent;
Charles Chan72f556a2015-10-05 17:50:33 -070055import org.onosproject.net.config.NetworkConfigListener;
Jonathan Hart54541d12016-04-12 15:39:44 -070056import org.onosproject.net.config.NetworkConfigRegistry;
Charles Chan72f556a2015-10-05 17:50:33 -070057import org.onosproject.net.config.basics.SubjectFactories;
Jonathan Hart54541d12016-04-12 15:39:44 -070058import org.onosproject.net.device.DeviceEvent;
59import org.onosproject.net.device.DeviceListener;
60import org.onosproject.net.device.DeviceService;
Charles Chanf4586112015-11-09 16:37:23 -080061import org.onosproject.net.flow.TrafficSelector;
62import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hart54541d12016-04-12 15:39:44 -070063import org.onosproject.net.flowobjective.FlowObjectiveService;
Charles Chanf4586112015-11-09 16:37:23 -080064import org.onosproject.net.host.HostEvent;
65import org.onosproject.net.host.HostListener;
Pier Ventreb6a7f342016-11-26 21:05:22 -080066import org.onosproject.net.host.HostService;
67import org.onosproject.net.link.LinkEvent;
68import org.onosproject.net.link.LinkListener;
69import org.onosproject.net.link.LinkService;
Charles Chanc91c8782016-03-30 17:54:24 -070070import org.onosproject.net.mcast.McastEvent;
71import org.onosproject.net.mcast.McastListener;
72import org.onosproject.net.mcast.MulticastRouteService;
Pier Ventreb6a7f342016-11-26 21:05:22 -080073import org.onosproject.net.packet.InboundPacket;
74import org.onosproject.net.packet.PacketContext;
75import org.onosproject.net.packet.PacketProcessor;
76import org.onosproject.net.packet.PacketService;
Charles Chanc91c8782016-03-30 17:54:24 -070077import org.onosproject.net.topology.TopologyService;
Pier Luigi37a35432017-02-01 13:50:04 -080078import org.onosproject.routing.config.RouterConfig;
Charles Chanc91c8782016-03-30 17:54:24 -070079import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
80import org.onosproject.segmentrouting.config.DeviceConfiguration;
Pier Ventre6b19e482016-11-07 16:21:04 -080081import org.onosproject.segmentrouting.config.PwaasConfig;
Pier Ventreb6a7f342016-11-26 21:05:22 -080082import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
Pier Ventre6b19e482016-11-07 16:21:04 -080083import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
Charles Chan82f19972016-05-17 13:13:55 -070084import org.onosproject.segmentrouting.config.XConnectConfig;
Charles Chanc91c8782016-03-30 17:54:24 -070085import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
86import org.onosproject.segmentrouting.grouphandler.NeighborSet;
Charles Chan1eaf4802016-04-18 13:44:03 -070087import org.onosproject.segmentrouting.storekey.NeighborSetNextObjectiveStoreKey;
88import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
Charles Chan1eaf4802016-04-18 13:44:03 -070089import org.onosproject.segmentrouting.storekey.SubnetAssignedVidStoreKey;
90import org.onosproject.segmentrouting.storekey.SubnetNextObjectiveStoreKey;
Charles Chan82f19972016-05-17 13:13:55 -070091import org.onosproject.segmentrouting.storekey.XConnectStoreKey;
Pier Ventre6b19e482016-11-07 16:21:04 -080092import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
Jonathan Hart54541d12016-04-12 15:39:44 -070093import org.onosproject.store.serializers.KryoNamespaces;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070094import org.onosproject.store.service.EventuallyConsistentMap;
95import org.onosproject.store.service.EventuallyConsistentMapBuilder;
96import org.onosproject.store.service.StorageService;
97import org.onosproject.store.service.WallClockTimestamp;
Charles Chan41f5ec02016-06-13 18:54:31 -070098import org.opencord.cordconfig.CordConfigEvent;
99import org.opencord.cordconfig.CordConfigListener;
100import org.opencord.cordconfig.CordConfigService;
sangho80f11cb2015-04-01 13:05:26 -0700101import org.slf4j.Logger;
102import org.slf4j.LoggerFactory;
103
Saurav Das7c305372015-10-28 12:39:42 -0700104import java.util.Collections;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700105import java.util.HashSet;
sangho27462c62015-05-14 00:39:53 -0700106import java.util.List;
sangho80f11cb2015-04-01 13:05:26 -0700107import java.util.Map;
Saurav Das7c305372015-10-28 12:39:42 -0700108import java.util.Set;
sangho80f11cb2015-04-01 13:05:26 -0700109import java.util.concurrent.ConcurrentHashMap;
110import java.util.concurrent.ConcurrentLinkedQueue;
111import java.util.concurrent.Executors;
112import java.util.concurrent.ScheduledExecutorService;
113import java.util.concurrent.ScheduledFuture;
114import java.util.concurrent.TimeUnit;
Pier Ventreb6a7f342016-11-26 21:05:22 -0800115import java.util.stream.Collectors;
sangho80f11cb2015-04-01 13:05:26 -0700116
Charles Chand6d25332016-02-26 22:19:52 -0800117import static com.google.common.base.Preconditions.checkState;
Pier Ventreadb4ae62016-11-23 09:57:42 -0800118import static org.onlab.packet.Ethernet.TYPE_ARP;
Yuta HIGUCHIebee2f12016-07-21 16:54:33 -0700119import static org.onlab.util.Tools.groupedThreads;
Charles Chand6d25332016-02-26 22:19:52 -0800120
Charles Chanb7f75ac2016-01-11 18:28:54 -0800121/**
122 * Segment routing manager.
123 */
Jonathan Hart54541d12016-04-12 15:39:44 -0700124@Service
125@Component(immediate = true)
sangho27462c62015-05-14 00:39:53 -0700126public class SegmentRoutingManager implements SegmentRoutingService {
sangho80f11cb2015-04-01 13:05:26 -0700127
Charles Chan46fdfaf2016-11-09 20:51:44 -0800128 private static Logger log = LoggerFactory.getLogger(SegmentRoutingManager.class);
sangho80f11cb2015-04-01 13:05:26 -0700129
130 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700131 private ComponentConfigService compCfgService;
sangho80f11cb2015-04-01 13:05:26 -0700132
133 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventreb6a7f342016-11-26 21:05:22 -0800134 private NeighbourResolutionService neighbourResolutionService;
135
136 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700137 CoreService coreService;
sangho80f11cb2015-04-01 13:05:26 -0700138
139 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700140 PacketService packetService;
sangho80f11cb2015-04-01 13:05:26 -0700141
142 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700143 HostService hostService;
sangho80f11cb2015-04-01 13:05:26 -0700144
145 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700146 DeviceService deviceService;
sangho80f11cb2015-04-01 13:05:26 -0700147
148 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700149 FlowObjectiveService flowObjectiveService;
sangho80f11cb2015-04-01 13:05:26 -0700150
151 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700152 LinkService linkService;
sangho27462c62015-05-14 00:39:53 -0700153
Charles Chan82ab1932016-01-30 23:22:37 -0800154 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700155 MastershipService mastershipService;
156
157 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
158 StorageService storageService;
159
160 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
161 MulticastRouteService multicastRouteService;
162
163 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
164 TopologyService topologyService;
165
166 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
167 CordConfigService cordConfigService;
168
169 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
170 RouteService routeService;
Charles Chan82ab1932016-01-30 23:22:37 -0800171
172 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan46fdfaf2016-11-09 20:51:44 -0800173 public NetworkConfigRegistry cfgService;
Charles Chan82ab1932016-01-30 23:22:37 -0800174
Saurav Dasc3604f12016-03-23 11:22:49 -0700175 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan46fdfaf2016-11-09 20:51:44 -0800176 public InterfaceService interfaceService;
177
Charles Chandebfea32016-10-24 14:52:01 -0700178 ArpHandler arpHandler = null;
179 IcmpHandler icmpHandler = null;
180 IpHandler ipHandler = null;
181 RoutingRulePopulator routingRulePopulator = null;
Charles Chan46fdfaf2016-11-09 20:51:44 -0800182 public ApplicationId appId;
sangho9b169e32015-04-14 16:27:13 -0700183 protected DeviceConfiguration deviceConfiguration = null;
sangho80f11cb2015-04-01 13:05:26 -0700184
Charles Chandebfea32016-10-24 14:52:01 -0700185 DefaultRoutingHandler defaultRoutingHandler = null;
sangho27462c62015-05-14 00:39:53 -0700186 private TunnelHandler tunnelHandler = null;
187 private PolicyHandler policyHandler = null;
Charles Chan2b078ae2015-10-14 11:24:40 -0700188 private InternalPacketProcessor processor = null;
189 private InternalLinkListener linkListener = null;
190 private InternalDeviceListener deviceListener = null;
Charles Chan82f19972016-05-17 13:13:55 -0700191 private AppConfigHandler appCfgHandler = null;
Charles Chandebfea32016-10-24 14:52:01 -0700192 XConnectHandler xConnectHandler = null;
Charles Chan1eaf4802016-04-18 13:44:03 -0700193 private McastHandler mcastHandler = null;
Charles Chandebfea32016-10-24 14:52:01 -0700194 HostHandler hostHandler = null;
Charles Chan41f5ec02016-06-13 18:54:31 -0700195 private CordConfigHandler cordConfigHandler = null;
Pier Ventreb6a7f342016-11-26 21:05:22 -0800196 private RouteHandler routeHandler = null;
Pier Ventreb6b81d52016-12-02 08:16:05 -0800197 private SegmentRoutingNeighbourDispatcher neighbourHandler = null;
Pier Ventre6b19e482016-11-07 16:21:04 -0800198 private L2TunnelHandler l2TunnelHandler = null;
sangho80f11cb2015-04-01 13:05:26 -0700199 private InternalEventHandler eventHandler = new InternalEventHandler();
Charles Chan82ab1932016-01-30 23:22:37 -0800200 private final InternalHostListener hostListener = new InternalHostListener();
Charles Chanc91c8782016-03-30 17:54:24 -0700201 private final InternalConfigListener cfgListener = new InternalConfigListener(this);
202 private final InternalMcastListener mcastListener = new InternalMcastListener();
Charles Chan41f5ec02016-06-13 18:54:31 -0700203 private final InternalCordConfigListener cordConfigListener = new InternalCordConfigListener();
Charles Chandebfea32016-10-24 14:52:01 -0700204 private final InternalRouteEventListener routeListener = new InternalRouteEventListener();
sangho80f11cb2015-04-01 13:05:26 -0700205
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700206 private ScheduledExecutorService executorService = Executors
Yuta HIGUCHIebee2f12016-07-21 16:54:33 -0700207 .newScheduledThreadPool(1, groupedThreads("SegmentRoutingManager", "event-%d", log));
sangho80f11cb2015-04-01 13:05:26 -0700208
Saurav Das2d94d312015-11-24 23:21:05 -0800209 @SuppressWarnings("unused")
sangho80f11cb2015-04-01 13:05:26 -0700210 private static ScheduledFuture<?> eventHandlerFuture = null;
Saurav Das2d94d312015-11-24 23:21:05 -0800211 @SuppressWarnings("rawtypes")
Yuta HIGUCHIebee2f12016-07-21 16:54:33 -0700212 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<>();
Charles Chanf4586112015-11-09 16:37:23 -0800213 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
Charles Chanb7f75ac2016-01-11 18:28:54 -0800214 new ConcurrentHashMap<>();
215 /**
216 * Per device next objective ID store with (device id + neighbor set) as key.
217 */
218 public EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
Charles Chanf4586112015-11-09 16:37:23 -0800219 nsNextObjStore = null;
Charles Chanb7f75ac2016-01-11 18:28:54 -0800220 /**
221 * Per device next objective ID store with (device id + subnet) as key.
222 */
223 public EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
Charles Chanf4586112015-11-09 16:37:23 -0800224 subnetNextObjStore = null;
Charles Chanb7f75ac2016-01-11 18:28:54 -0800225 /**
226 * Per device next objective ID store with (device id + port) as key.
227 */
228 public EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
Saurav Das2d94d312015-11-24 23:21:05 -0800229 portNextObjStore = null;
Saurav Das7c305372015-10-28 12:39:42 -0700230 // Per device, per-subnet assigned-vlans store, with (device id + subnet
231 // IPv4 prefix) as key
232 private EventuallyConsistentMap<SubnetAssignedVidStoreKey, VlanId>
Charles Chanb7f75ac2016-01-11 18:28:54 -0800233 subnetVidStore = null;
Saurav Das2d94d312015-11-24 23:21:05 -0800234 private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
235 private EventuallyConsistentMap<String, Policy> policyStore = null;
sangho4a5c42a2015-05-20 22:16:38 -0700236
Charles Chanc91c8782016-03-30 17:54:24 -0700237 private final ConfigFactory<DeviceId, SegmentRoutingDeviceConfig> deviceConfigFactory =
Charles Chan82f19972016-05-17 13:13:55 -0700238 new ConfigFactory<DeviceId, SegmentRoutingDeviceConfig>(
239 SubjectFactories.DEVICE_SUBJECT_FACTORY,
Charles Chanc91c8782016-03-30 17:54:24 -0700240 SegmentRoutingDeviceConfig.class, "segmentrouting") {
Charles Chan72f556a2015-10-05 17:50:33 -0700241 @Override
Charles Chan82ab1932016-01-30 23:22:37 -0800242 public SegmentRoutingDeviceConfig createConfig() {
243 return new SegmentRoutingDeviceConfig();
Charles Chan72f556a2015-10-05 17:50:33 -0700244 }
245 };
Pier Ventre6b19e482016-11-07 16:21:04 -0800246
Charles Chanc91c8782016-03-30 17:54:24 -0700247 private final ConfigFactory<ApplicationId, SegmentRoutingAppConfig> appConfigFactory =
Charles Chan82f19972016-05-17 13:13:55 -0700248 new ConfigFactory<ApplicationId, SegmentRoutingAppConfig>(
249 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chanc91c8782016-03-30 17:54:24 -0700250 SegmentRoutingAppConfig.class, "segmentrouting") {
Charles Chan82ab1932016-01-30 23:22:37 -0800251 @Override
252 public SegmentRoutingAppConfig createConfig() {
253 return new SegmentRoutingAppConfig();
254 }
255 };
Pier Ventre6b19e482016-11-07 16:21:04 -0800256
Charles Chan82f19972016-05-17 13:13:55 -0700257 private final ConfigFactory<ApplicationId, XConnectConfig> xConnectConfigFactory =
258 new ConfigFactory<ApplicationId, XConnectConfig>(
259 SubjectFactories.APP_SUBJECT_FACTORY,
260 XConnectConfig.class, "xconnect") {
261 @Override
262 public XConnectConfig createConfig() {
263 return new XConnectConfig();
264 }
265 };
Pier Ventre6b19e482016-11-07 16:21:04 -0800266
Charles Chanc91c8782016-03-30 17:54:24 -0700267 private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory =
Charles Chan82f19972016-05-17 13:13:55 -0700268 new ConfigFactory<ApplicationId, McastConfig>(
269 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chanc91c8782016-03-30 17:54:24 -0700270 McastConfig.class, "multicast") {
271 @Override
272 public McastConfig createConfig() {
273 return new McastConfig();
274 }
275 };
276
Pier Ventre6b19e482016-11-07 16:21:04 -0800277 private final ConfigFactory<ApplicationId, PwaasConfig> pwaasConfigFactory =
278 new ConfigFactory<ApplicationId, PwaasConfig>(
279 SubjectFactories.APP_SUBJECT_FACTORY,
280 PwaasConfig.class, "pwaas") {
281 @Override
282 public PwaasConfig createConfig() {
283 return new PwaasConfig();
284 }
285 };
286
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700287 private Object threadSchedulerLock = new Object();
288 private static int numOfEventsQueued = 0;
289 private static int numOfEventsExecuted = 0;
sangho80f11cb2015-04-01 13:05:26 -0700290 private static int numOfHandlerExecution = 0;
291 private static int numOfHandlerScheduled = 0;
292
Charles Chan1963f4f2016-02-18 14:22:42 -0800293 /**
294 * Segment Routing App ID.
295 */
Charles Chan46fdfaf2016-11-09 20:51:44 -0800296 public static final String APP_NAME = "org.onosproject.segmentrouting";
Charles Chanb7f75ac2016-01-11 18:28:54 -0800297 /**
298 * The starting value of per-subnet VLAN ID assignment.
299 */
Saurav Das7c305372015-10-28 12:39:42 -0700300 private static final short ASSIGNED_VLAN_START = 4093;
Charles Chanb7f75ac2016-01-11 18:28:54 -0800301 /**
302 * The default VLAN ID assigned to the interfaces without subnet config.
303 */
Saurav Das7c305372015-10-28 12:39:42 -0700304 public static final short ASSIGNED_VLAN_NO_SUBNET = 4094;
305
sangho80f11cb2015-04-01 13:05:26 -0700306 @Activate
307 protected void activate() {
Charles Chan46fdfaf2016-11-09 20:51:44 -0800308 appId = coreService.registerApplication(APP_NAME);
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700309
310 log.debug("Creating EC map nsnextobjectivestore");
311 EventuallyConsistentMapBuilder<NeighborSetNextObjectiveStoreKey, Integer>
312 nsNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700313 nsNextObjStore = nsNextObjMapBuilder
314 .withName("nsnextobjectivestore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700315 .withSerializer(createSerializer())
Madan Jampani675ae202015-06-24 19:05:56 -0700316 .withTimestampProvider((k, v) -> new WallClockTimestamp())
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700317 .build();
318 log.trace("Current size {}", nsNextObjStore.size());
319
Charles Chan77277672015-10-20 16:24:19 -0700320 log.debug("Creating EC map subnetnextobjectivestore");
321 EventuallyConsistentMapBuilder<SubnetNextObjectiveStoreKey, Integer>
322 subnetNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
Charles Chan77277672015-10-20 16:24:19 -0700323 subnetNextObjStore = subnetNextObjMapBuilder
324 .withName("subnetnextobjectivestore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700325 .withSerializer(createSerializer())
Charles Chan77277672015-10-20 16:24:19 -0700326 .withTimestampProvider((k, v) -> new WallClockTimestamp())
327 .build();
328
Saurav Das2d94d312015-11-24 23:21:05 -0800329 log.debug("Creating EC map subnetnextobjectivestore");
330 EventuallyConsistentMapBuilder<PortNextObjectiveStoreKey, Integer>
331 portNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
332 portNextObjStore = portNextObjMapBuilder
333 .withName("portnextobjectivestore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700334 .withSerializer(createSerializer())
Saurav Das2d94d312015-11-24 23:21:05 -0800335 .withTimestampProvider((k, v) -> new WallClockTimestamp())
336 .build();
337
sangho4a5c42a2015-05-20 22:16:38 -0700338 EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
339 storageService.eventuallyConsistentMapBuilder();
sangho4a5c42a2015-05-20 22:16:38 -0700340 tunnelStore = tunnelMapBuilder
341 .withName("tunnelstore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700342 .withSerializer(createSerializer())
Madan Jampani675ae202015-06-24 19:05:56 -0700343 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho4a5c42a2015-05-20 22:16:38 -0700344 .build();
345
346 EventuallyConsistentMapBuilder<String, Policy> policyMapBuilder =
347 storageService.eventuallyConsistentMapBuilder();
sangho4a5c42a2015-05-20 22:16:38 -0700348 policyStore = policyMapBuilder
349 .withName("policystore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700350 .withSerializer(createSerializer())
Madan Jampani675ae202015-06-24 19:05:56 -0700351 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho4a5c42a2015-05-20 22:16:38 -0700352 .build();
353
Saurav Das7c305372015-10-28 12:39:42 -0700354 EventuallyConsistentMapBuilder<SubnetAssignedVidStoreKey, VlanId>
355 subnetVidStoreMapBuilder = storageService.eventuallyConsistentMapBuilder();
Saurav Das7c305372015-10-28 12:39:42 -0700356 subnetVidStore = subnetVidStoreMapBuilder
357 .withName("subnetvidstore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700358 .withSerializer(createSerializer())
Saurav Das7c305372015-10-28 12:39:42 -0700359 .withTimestampProvider((k, v) -> new WallClockTimestamp())
360 .build();
361
Saurav Dasc3604f12016-03-23 11:22:49 -0700362 compCfgService.preSetProperty("org.onosproject.net.group.impl.GroupManager",
Pier Luigib9632ba2017-01-12 18:14:58 -0800363 "purgeOnDisconnection", "true");
Saurav Dasc3604f12016-03-23 11:22:49 -0700364 compCfgService.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
Pier Luigib9632ba2017-01-12 18:14:58 -0800365 "purgeOnDisconnection", "true");
Pier Luigib9632ba2017-01-12 18:14:58 -0800366 compCfgService.preSetProperty("org.onosproject.provider.host.impl.HostLocationProvider",
367 "requestInterceptsEnabled", "false");
Pier Luigibc976df2017-01-12 22:46:39 -0800368 compCfgService.preSetProperty("org.onosproject.incubator.net.neighbour.impl.NeighbourResolutionManager",
369 "requestInterceptsEnabled", "false");
370 compCfgService.preSetProperty("org.onosproject.dhcprelay.DhcpRelay",
371 "arpEnabled", "false");
Pier Luigi0ebeb312017-02-02 22:31:34 -0800372 compCfgService.preSetProperty("org.onosproject.net.host.impl.HostManager",
373 "greedyLearningIpv6", "true");
374
Saurav Dasc3604f12016-03-23 11:22:49 -0700375
Charles Chan2b078ae2015-10-14 11:24:40 -0700376 processor = new InternalPacketProcessor();
377 linkListener = new InternalLinkListener();
378 deviceListener = new InternalDeviceListener();
Charles Chan82f19972016-05-17 13:13:55 -0700379 appCfgHandler = new AppConfigHandler(this);
380 xConnectHandler = new XConnectHandler(this);
Charles Chan1eaf4802016-04-18 13:44:03 -0700381 mcastHandler = new McastHandler(this);
382 hostHandler = new HostHandler(this);
Charles Chan41f5ec02016-06-13 18:54:31 -0700383 cordConfigHandler = new CordConfigHandler(this);
Charles Chandebfea32016-10-24 14:52:01 -0700384 routeHandler = new RouteHandler(this);
Pier Ventreb6b81d52016-12-02 08:16:05 -0800385 neighbourHandler = new SegmentRoutingNeighbourDispatcher(this);
Pier Ventre6b19e482016-11-07 16:21:04 -0800386 l2TunnelHandler = new L2TunnelHandler(this);
Charles Chan2b078ae2015-10-14 11:24:40 -0700387
Charles Chand6d25332016-02-26 22:19:52 -0800388 cfgService.addListener(cfgListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700389 cfgService.registerConfigFactory(deviceConfigFactory);
390 cfgService.registerConfigFactory(appConfigFactory);
Charles Chan82f19972016-05-17 13:13:55 -0700391 cfgService.registerConfigFactory(xConnectConfigFactory);
Charles Chanc91c8782016-03-30 17:54:24 -0700392 cfgService.registerConfigFactory(mcastConfigFactory);
Pier Ventre6b19e482016-11-07 16:21:04 -0800393 cfgService.registerConfigFactory(pwaasConfigFactory);
Charles Chan82ab1932016-01-30 23:22:37 -0800394 hostService.addListener(hostListener);
Charles Chan2b078ae2015-10-14 11:24:40 -0700395 packetService.addProcessor(processor, PacketProcessor.director(2));
396 linkService.addListener(linkListener);
397 deviceService.addListener(deviceListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700398 multicastRouteService.addListener(mcastListener);
Charles Chan41f5ec02016-06-13 18:54:31 -0700399 cordConfigService.addListener(cordConfigListener);
Charles Chan2b078ae2015-10-14 11:24:40 -0700400
401 cfgListener.configureNetwork();
402
Charles Chandebfea32016-10-24 14:52:01 -0700403 routeService.addListener(routeListener);
404
sangho80f11cb2015-04-01 13:05:26 -0700405 log.info("Started");
406 }
407
Jonathan Hart54541d12016-04-12 15:39:44 -0700408 private KryoNamespace.Builder createSerializer() {
409 return new KryoNamespace.Builder()
410 .register(KryoNamespaces.API)
411 .register(NeighborSetNextObjectiveStoreKey.class,
412 SubnetNextObjectiveStoreKey.class,
413 SubnetAssignedVidStoreKey.class,
414 NeighborSet.class,
415 Tunnel.class,
416 DefaultTunnel.class,
417 Policy.class,
418 TunnelPolicy.class,
419 Policy.Type.class,
420 PortNextObjectiveStoreKey.class,
Charles Chan82f19972016-05-17 13:13:55 -0700421 XConnectStoreKey.class
Jonathan Hart54541d12016-04-12 15:39:44 -0700422 );
423 }
424
sangho80f11cb2015-04-01 13:05:26 -0700425 @Deactivate
426 protected void deactivate() {
Charles Chan72f556a2015-10-05 17:50:33 -0700427 cfgService.removeListener(cfgListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700428 cfgService.unregisterConfigFactory(deviceConfigFactory);
429 cfgService.unregisterConfigFactory(appConfigFactory);
Charles Chandebfea32016-10-24 14:52:01 -0700430 cfgService.unregisterConfigFactory(xConnectConfigFactory);
Charles Chanc91c8782016-03-30 17:54:24 -0700431 cfgService.unregisterConfigFactory(mcastConfigFactory);
Pier Ventre6b19e482016-11-07 16:21:04 -0800432 cfgService.unregisterConfigFactory(pwaasConfigFactory);
Charles Chan72f556a2015-10-05 17:50:33 -0700433
sangho80f11cb2015-04-01 13:05:26 -0700434 packetService.removeProcessor(processor);
Charles Chan2b078ae2015-10-14 11:24:40 -0700435 linkService.removeListener(linkListener);
436 deviceService.removeListener(deviceListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700437 multicastRouteService.removeListener(mcastListener);
Charles Chan41f5ec02016-06-13 18:54:31 -0700438 cordConfigService.removeListener(cordConfigListener);
Charles Chandebfea32016-10-24 14:52:01 -0700439 routeService.removeListener(routeListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700440
sangho80f11cb2015-04-01 13:05:26 -0700441 processor = null;
Charles Chan2b078ae2015-10-14 11:24:40 -0700442 linkListener = null;
Charles Chanc91c8782016-03-30 17:54:24 -0700443 deviceListener = null;
Charles Chan2b078ae2015-10-14 11:24:40 -0700444 groupHandlerMap.clear();
445
Charles Chanc91c8782016-03-30 17:54:24 -0700446 nsNextObjStore.destroy();
447 subnetNextObjStore.destroy();
448 portNextObjStore.destroy();
Charles Chanc91c8782016-03-30 17:54:24 -0700449 tunnelStore.destroy();
450 policyStore.destroy();
451 subnetVidStore.destroy();
sangho80f11cb2015-04-01 13:05:26 -0700452 log.info("Stopped");
453 }
454
sangho27462c62015-05-14 00:39:53 -0700455 @Override
456 public List<Tunnel> getTunnels() {
457 return tunnelHandler.getTunnels();
458 }
459
460 @Override
sanghobd812f82015-06-29 14:58:47 -0700461 public TunnelHandler.Result createTunnel(Tunnel tunnel) {
462 return tunnelHandler.createTunnel(tunnel);
sangho27462c62015-05-14 00:39:53 -0700463 }
464
465 @Override
sanghobd812f82015-06-29 14:58:47 -0700466 public TunnelHandler.Result removeTunnel(Tunnel tunnel) {
sangho27462c62015-05-14 00:39:53 -0700467 for (Policy policy: policyHandler.getPolicies()) {
468 if (policy.type() == Policy.Type.TUNNEL_FLOW) {
469 TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
470 if (tunnelPolicy.tunnelId().equals(tunnel.id())) {
471 log.warn("Cannot remove the tunnel used by a policy");
sanghobd812f82015-06-29 14:58:47 -0700472 return TunnelHandler.Result.TUNNEL_IN_USE;
sangho27462c62015-05-14 00:39:53 -0700473 }
474 }
475 }
sanghobd812f82015-06-29 14:58:47 -0700476 return tunnelHandler.removeTunnel(tunnel);
sangho27462c62015-05-14 00:39:53 -0700477 }
478
479 @Override
sanghobd812f82015-06-29 14:58:47 -0700480 public PolicyHandler.Result removePolicy(Policy policy) {
481 return policyHandler.removePolicy(policy);
sangho27462c62015-05-14 00:39:53 -0700482 }
483
484 @Override
sanghobd812f82015-06-29 14:58:47 -0700485 public PolicyHandler.Result createPolicy(Policy policy) {
486 return policyHandler.createPolicy(policy);
sangho27462c62015-05-14 00:39:53 -0700487 }
488
489 @Override
490 public List<Policy> getPolicies() {
491 return policyHandler.getPolicies();
492 }
493
Saurav Das07c74602016-04-27 18:35:50 -0700494 @Override
495 public void rerouteNetwork() {
496 cfgListener.configureNetwork();
497 for (Device device : deviceService.getDevices()) {
498 defaultRoutingHandler.populatePortAddressingRules(device.id());
499 }
500 defaultRoutingHandler.startPopulationProcess();
501 }
502
Charles Chand7844e52016-10-20 17:02:44 -0700503 @Override
Pier Ventreb6a7f342016-11-26 21:05:22 -0800504 public Map<DeviceId, Set<IpPrefix>> getDeviceSubnetMap() {
505 Map<DeviceId, Set<IpPrefix>> deviceSubnetMap = Maps.newHashMap();
Charles Chand7844e52016-10-20 17:02:44 -0700506 deviceService.getAvailableDevices().forEach(device -> {
507 deviceSubnetMap.put(device.id(), deviceConfiguration.getSubnets(device.id()));
508 });
509 return deviceSubnetMap;
510 }
511
sangho80f1f892015-05-19 11:57:42 -0700512 /**
Pier Ventre7a78de22016-10-31 15:00:01 -0700513 * Returns the MPLS-ECMP configuration.
514 *
515 * @return MPLS-ECMP value
516 */
517 public boolean getMplsEcmp() {
518 SegmentRoutingAppConfig segmentRoutingAppConfig = cfgService
519 .getConfig(this.appId, SegmentRoutingAppConfig.class);
520 return segmentRoutingAppConfig != null && segmentRoutingAppConfig.mplsEcmp();
521 }
522
523 /**
sangho80f1f892015-05-19 11:57:42 -0700524 * Returns the tunnel object with the tunnel ID.
525 *
526 * @param tunnelId Tunnel ID
527 * @return Tunnel reference
528 */
sangho27462c62015-05-14 00:39:53 -0700529 public Tunnel getTunnel(String tunnelId) {
530 return tunnelHandler.getTunnel(tunnelId);
531 }
532
sangho80f11cb2015-04-01 13:05:26 -0700533 /**
Saurav Das7c305372015-10-28 12:39:42 -0700534 * Returns the vlan-id assigned to the subnet configured for a device.
535 * If no vlan-id has been assigned, a new one is assigned out of a pool of ids,
536 * if and only if this controller instance is the master for the device.
537 * <p>
538 * USAGE: The assigned vlans are meant to be applied to untagged packets on those
539 * switches/pipelines that need this functionality. These vids are meant
540 * to be used internally within a switch, and thus need to be unique only
541 * on a switch level. Note that packets never go out on the wire with these
542 * vlans. Currently, vlan ids are assigned from value 4093 down.
543 * Vlan id 4094 expected to be used for all ports that are not assigned subnets.
544 * Vlan id 4095 is reserved and unused. Only a single vlan id is assigned
545 * per subnet.
sangho80f11cb2015-04-01 13:05:26 -0700546 *
Saurav Das7c305372015-10-28 12:39:42 -0700547 * @param deviceId switch dpid
Pier Ventre1a655962016-11-28 16:48:06 -0800548 * @param subnet IP prefix for which assigned vlan is desired
Saurav Das7c305372015-10-28 12:39:42 -0700549 * @return VlanId assigned for the subnet on the device, or
550 * null if no vlan assignment was found and this instance is not
551 * the master for the device.
sangho80f11cb2015-04-01 13:05:26 -0700552 */
Charles Chanb7f75ac2016-01-11 18:28:54 -0800553 // TODO: We should avoid assigning VLAN IDs that are used by VLAN cross-connection.
Pier Ventreb6a7f342016-11-26 21:05:22 -0800554 public VlanId getSubnetAssignedVlanId(DeviceId deviceId, IpPrefix subnet) {
Saurav Das7c305372015-10-28 12:39:42 -0700555 VlanId assignedVid = subnetVidStore.get(new SubnetAssignedVidStoreKey(
556 deviceId, subnet));
557 if (assignedVid != null) {
558 log.debug("Query for subnet:{} on device:{} returned assigned-vlan "
559 + "{}", subnet, deviceId, assignedVid);
560 return assignedVid;
561 }
562 //check mastership for the right to assign a vlan
563 if (!mastershipService.isLocalMaster(deviceId)) {
564 log.warn("This controller instance is not the master for device {}. "
565 + "Cannot assign vlan-id for subnet {}", deviceId, subnet);
566 return null;
567 }
568 // vlan assignment is expensive but done only once
Pier Ventreb6a7f342016-11-26 21:05:22 -0800569 // FIXME for now we will do assignment considering only the ipv4 subnet.
570 Set<Ip4Prefix> configuredSubnets = deviceConfiguration.getSubnets(deviceId)
571 .stream()
572 .filter(IpPrefix::isIp4)
573 .map(IpPrefix::getIp4Prefix)
574 .collect(Collectors.toSet());
Saurav Das7c305372015-10-28 12:39:42 -0700575 Set<Short> assignedVlans = new HashSet<>();
576 Set<Ip4Prefix> unassignedSubnets = new HashSet<>();
577 for (Ip4Prefix sub : configuredSubnets) {
578 VlanId v = subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId,
579 sub));
580 if (v != null) {
581 assignedVlans.add(v.toShort());
582 } else {
583 unassignedSubnets.add(sub);
584 }
585 }
586 short nextAssignedVlan = ASSIGNED_VLAN_START;
587 if (!assignedVlans.isEmpty()) {
588 nextAssignedVlan = (short) (Collections.min(assignedVlans) - 1);
589 }
590 for (Ip4Prefix unsub : unassignedSubnets) {
Pier Ventre1a655962016-11-28 16:48:06 -0800591 subnetVidStore.put(new SubnetAssignedVidStoreKey(deviceId, unsub),
592 VlanId.vlanId(nextAssignedVlan--));
593 log.info("Assigned vlan: {} to subnet: {} on device: {}",
594 nextAssignedVlan + 1, unsub, deviceId);
sangho80f11cb2015-04-01 13:05:26 -0700595 }
Saurav Das7c305372015-10-28 12:39:42 -0700596 return subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId, subnet));
sangho80f11cb2015-04-01 13:05:26 -0700597 }
598
sangho27462c62015-05-14 00:39:53 -0700599 /**
Saurav Das7c305372015-10-28 12:39:42 -0700600 * Returns the next objective ID for the given NeighborSet.
Saurav Das4c35fc42015-11-20 15:27:53 -0800601 * If the nextObjective does not exist, a new one is created and
Saurav Das2d94d312015-11-24 23:21:05 -0800602 * its id is returned.
sangho27462c62015-05-14 00:39:53 -0700603 *
sangho80f1f892015-05-19 11:57:42 -0700604 * @param deviceId Device ID
605 * @param ns NegighborSet
Saurav Das4c35fc42015-11-20 15:27:53 -0800606 * @param meta metadata passed into the creation of a Next Objective
Pier Ventre229fd0b2016-10-31 16:49:19 -0700607 * @param isBos indicates if it is BoS or not
Saurav Das4c35fc42015-11-20 15:27:53 -0800608 * @return next objective ID or -1 if an error was encountered during the
609 * creation of the nextObjective
sangho27462c62015-05-14 00:39:53 -0700610 */
Saurav Das4c35fc42015-11-20 15:27:53 -0800611 public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns,
Pier Ventre229fd0b2016-10-31 16:49:19 -0700612 TrafficSelector meta, boolean isBos) {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700613 if (groupHandlerMap.get(deviceId) != null) {
614 log.trace("getNextObjectiveId query in device {}", deviceId);
615 return groupHandlerMap
Pier Ventre229fd0b2016-10-31 16:49:19 -0700616 .get(deviceId).getNextObjectiveId(ns, meta, isBos);
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700617 } else {
Saurav Das2d94d312015-11-24 23:21:05 -0800618 log.warn("getNextObjectiveId query - groupHandler for device {} "
619 + "not found", deviceId);
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700620 return -1;
621 }
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700622 }
623
Charles Chan77277672015-10-20 16:24:19 -0700624 /**
Pier Ventre229fd0b2016-10-31 16:49:19 -0700625 * Returns the next objective ID for the given NeighborSet.
626 * If the nextObjective does not exist, a new one is created and
627 * its id is returned.
628 *
629 * @param deviceId Device ID
630 * @param ns NegighborSet
631 * @param meta metadata passed into the creation of a Next Objective
632 * @return next objective ID or -1 if an error was encountered during the
633 * creation of the nextObjective
634 */
635 public int getNextObjectiveId(DeviceId deviceId,
636 NeighborSet ns,
637 TrafficSelector meta) {
638 return this.getNextObjectiveId(deviceId, ns, meta, true);
639 }
640
641 /**
Saurav Das2d94d312015-11-24 23:21:05 -0800642 * Returns the next objective ID for the given subnet prefix. It is expected
643 * that the next-objective has been pre-created from configuration.
Charles Chan77277672015-10-20 16:24:19 -0700644 *
645 * @param deviceId Device ID
646 * @param prefix Subnet
Saurav Das2d94d312015-11-24 23:21:05 -0800647 * @return next objective ID or -1 if it was not found
Charles Chan77277672015-10-20 16:24:19 -0700648 */
649 public int getSubnetNextObjectiveId(DeviceId deviceId, IpPrefix prefix) {
650 if (groupHandlerMap.get(deviceId) != null) {
651 log.trace("getSubnetNextObjectiveId query in device {}", deviceId);
652 return groupHandlerMap
653 .get(deviceId).getSubnetNextObjectiveId(prefix);
654 } else {
Saurav Das2d94d312015-11-24 23:21:05 -0800655 log.warn("getSubnetNextObjectiveId query - groupHandler for "
656 + "device {} not found", deviceId);
657 return -1;
658 }
659 }
660
661 /**
662 * Returns the next objective ID for the given portNumber, given the treatment.
663 * There could be multiple different treatments to the same outport, which
664 * would result in different objectives. If the next object
665 * does not exist, a new one is created and its id is returned.
666 *
667 * @param deviceId Device ID
668 * @param portNum port number on device for which NextObjective is queried
669 * @param treatment the actions to apply on the packets (should include outport)
670 * @param meta metadata passed into the creation of a Next Objective if necessary
Saurav Das07c74602016-04-27 18:35:50 -0700671 * @return next objective ID or -1 if an error occurred during retrieval or creation
Saurav Das2d94d312015-11-24 23:21:05 -0800672 */
673 public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
674 TrafficTreatment treatment,
675 TrafficSelector meta) {
676 DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
677 if (ghdlr != null) {
678 return ghdlr.getPortNextObjectiveId(portNum, treatment, meta);
679 } else {
Charles Chanb7f75ac2016-01-11 18:28:54 -0800680 log.warn("getPortNextObjectiveId query - groupHandler for device {}"
681 + " not found", deviceId);
682 return -1;
683 }
684 }
685
sangho80f11cb2015-04-01 13:05:26 -0700686 private class InternalPacketProcessor implements PacketProcessor {
sangho80f11cb2015-04-01 13:05:26 -0700687 @Override
688 public void process(PacketContext context) {
689
690 if (context.isHandled()) {
691 return;
692 }
693
694 InboundPacket pkt = context.inPacket();
695 Ethernet ethernet = pkt.parsed();
Pier Luigi37a35432017-02-01 13:50:04 -0800696
697 if (ethernet == null) {
698 return;
699 }
700
Saurav Das2d94d312015-11-24 23:21:05 -0800701 log.trace("Rcvd pktin: {}", ethernet);
Pier Ventreadb4ae62016-11-23 09:57:42 -0800702 if (ethernet.getEtherType() == TYPE_ARP) {
Pier Ventreb6a7f342016-11-26 21:05:22 -0800703 log.warn("{} - we are still receiving ARP packets from {}",
704 context.inPacket().receivedFrom());
705 log.debug("{}", ethernet);
Pier Ventre6b2c1b32016-12-09 17:26:04 -0800706 return;
sangho80f11cb2015-04-01 13:05:26 -0700707 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
Pier Ventreb6b81d52016-12-02 08:16:05 -0800708 IPv4 ipv4Packet = (IPv4) ethernet.getPayload();
709 //ipHandler.addToPacketBuffer(ipv4Packet);
710 if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_ICMP) {
711 icmpHandler.processIcmp(ethernet, pkt.receivedFrom());
sangho80f11cb2015-04-01 13:05:26 -0700712 } else {
Charles Chand041ad82017-01-13 17:20:44 -0800713 // NOTE: We don't support IP learning at this moment so this
714 // is not necessary. Also it causes duplication of DHCP packets.
Pier Ventre6b2c1b32016-12-09 17:26:04 -0800715 // ipHandler.processPacketIn(ipv4Packet, pkt.receivedFrom());
sangho80f11cb2015-04-01 13:05:26 -0700716 }
Pier Ventreb6a7f342016-11-26 21:05:22 -0800717 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV6) {
718 IPv6 ipv6Packet = (IPv6) ethernet.getPayload();
Pier Ventreb6b81d52016-12-02 08:16:05 -0800719 //ipHandler.addToPacketBuffer(ipv6Packet);
Pier Luigi37a35432017-02-01 13:50:04 -0800720 // We deal with the packet only if the packet is a ICMP6 ECHO/REPLY
Pier Ventreb6b81d52016-12-02 08:16:05 -0800721 if (ipv6Packet.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
722 ICMP6 icmp6Packet = (ICMP6) ipv6Packet.getPayload();
723 if (icmp6Packet.getIcmpType() == ICMP6.ECHO_REQUEST ||
724 icmp6Packet.getIcmpType() == ICMP6.ECHO_REPLY) {
725 icmpHandler.processIcmpv6(ethernet, pkt.receivedFrom());
726 } else {
Pier Luigi37a35432017-02-01 13:50:04 -0800727 // XXX Neigbour hacking, to handle the ICMPv6 packet
728 // not under our control
729 if (icmpHandler.handleUPstreamPackets(context)) {
730 log.debug("Rcvd pktin from UpStream: {}", ipv6Packet);
731 } else {
732 log.debug("Received ICMPv6 0x{} - not handled",
733 Integer.toHexString(icmp6Packet.getIcmpType() & 0xff));
734 }
Pier Ventreb6b81d52016-12-02 08:16:05 -0800735 }
736 } else {
737 // NOTE: We don't support IP learning at this moment so this
738 // is not necessary. Also it causes duplication of DHCPv6 packets.
739 // ipHandler.processPacketIn(ipv6Packet, pkt.receivedFrom());
740 }
sangho80f11cb2015-04-01 13:05:26 -0700741 }
742 }
743 }
744
745 private class InternalLinkListener implements LinkListener {
746 @Override
747 public void event(LinkEvent event) {
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700748 if (event.type() == LinkEvent.Type.LINK_ADDED
749 || event.type() == LinkEvent.Type.LINK_REMOVED) {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700750 log.debug("Event {} received from Link Service", event.type());
sangho80f11cb2015-04-01 13:05:26 -0700751 scheduleEventHandlerIfNotScheduled(event);
752 }
753 }
754 }
755
756 private class InternalDeviceListener implements DeviceListener {
sangho80f11cb2015-04-01 13:05:26 -0700757 @Override
758 public void event(DeviceEvent event) {
sangho80f11cb2015-04-01 13:05:26 -0700759 switch (event.type()) {
760 case DEVICE_ADDED:
Saurav Dasf0f592d2016-11-18 15:21:57 -0800761 case PORT_UPDATED:
762 case PORT_ADDED:
sanghofb7c7292015-04-13 15:15:58 -0700763 case DEVICE_UPDATED:
764 case DEVICE_AVAILABILITY_CHANGED:
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700765 log.debug("Event {} received from Device Service", event.type());
sangho80f11cb2015-04-01 13:05:26 -0700766 scheduleEventHandlerIfNotScheduled(event);
767 break;
768 default:
769 }
770 }
771 }
772
Saurav Das2d94d312015-11-24 23:21:05 -0800773 @SuppressWarnings("rawtypes")
sangho80f11cb2015-04-01 13:05:26 -0700774 private void scheduleEventHandlerIfNotScheduled(Event event) {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700775 synchronized (threadSchedulerLock) {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700776 eventQueue.add(event);
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700777 numOfEventsQueued++;
778
779 if ((numOfHandlerScheduled - numOfHandlerExecution) == 0) {
780 //No pending scheduled event handling threads. So start a new one.
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700781 eventHandlerFuture = executorService
782 .schedule(eventHandler, 100, TimeUnit.MILLISECONDS);
783 numOfHandlerScheduled++;
784 }
Jonathan Hart54541d12016-04-12 15:39:44 -0700785 log.trace("numOfEventsQueued {}, numOfEventHandlerScheduled {}",
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700786 numOfEventsQueued,
787 numOfHandlerScheduled);
sangho80f11cb2015-04-01 13:05:26 -0700788 }
sangho80f11cb2015-04-01 13:05:26 -0700789 }
790
791 private class InternalEventHandler implements Runnable {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700792 @Override
sangho80f11cb2015-04-01 13:05:26 -0700793 public void run() {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700794 try {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700795 while (true) {
Saurav Das2d94d312015-11-24 23:21:05 -0800796 @SuppressWarnings("rawtypes")
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700797 Event event = null;
798 synchronized (threadSchedulerLock) {
799 if (!eventQueue.isEmpty()) {
800 event = eventQueue.poll();
801 numOfEventsExecuted++;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700802 } else {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700803 numOfHandlerExecution++;
804 log.debug("numOfHandlerExecution {} numOfEventsExecuted {}",
805 numOfHandlerExecution, numOfEventsExecuted);
806 break;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700807 }
sanghofb7c7292015-04-13 15:15:58 -0700808 }
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700809 if (event.type() == LinkEvent.Type.LINK_ADDED) {
810 processLinkAdded((Link) event.subject());
811 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
Pier Ventre6d593892016-09-13 21:33:40 -0700812 Link linkRemoved = (Link) event.subject();
813 if (linkRemoved.src().elementId() instanceof DeviceId &&
814 !deviceService.isAvailable(linkRemoved.src().deviceId())) {
815 continue;
816 }
817 if (linkRemoved.dst().elementId() instanceof DeviceId &&
818 !deviceService.isAvailable(linkRemoved.dst().deviceId())) {
819 continue;
820 }
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700821 processLinkRemoved((Link) event.subject());
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700822 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
823 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
824 event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
Saurav Das62af8802015-12-04 10:52:59 -0800825 DeviceId deviceId = ((Device) event.subject()).id();
826 if (deviceService.isAvailable(deviceId)) {
Saurav Dasc28b3432015-10-30 17:45:38 -0700827 log.info("Processing device event {} for available device {}",
828 event.type(), ((Device) event.subject()).id());
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700829 processDeviceAdded((Device) event.subject());
Saurav Dasc3604f12016-03-23 11:22:49 -0700830 } else {
831 log.info("Processing device event {} for unavailable device {}",
832 event.type(), ((Device) event.subject()).id());
833 processDeviceRemoved((Device) event.subject());
834 }
Saurav Dasf0f592d2016-11-18 15:21:57 -0800835 } else if (event.type() == DeviceEvent.Type.PORT_ADDED) {
Saurav Dasd1872b02016-12-02 15:43:47 -0800836 // typically these calls come when device is added first time
837 // so port filtering rules are handled at the device_added event.
838 // port added calls represent all ports on the device,
839 // enabled or not.
Saurav Dasf0f592d2016-11-18 15:21:57 -0800840 log.debug("** PORT ADDED {}/{} -> {}",
Saurav Dasd1872b02016-12-02 15:43:47 -0800841 ((DeviceEvent) event).subject().id(),
842 ((DeviceEvent) event).port().number(),
843 event.type());
Saurav Dasf0f592d2016-11-18 15:21:57 -0800844 } else if (event.type() == DeviceEvent.Type.PORT_UPDATED) {
Saurav Dasd1872b02016-12-02 15:43:47 -0800845 // these calls happen for every subsequent event
846 // ports enabled, disabled, switch goes away, comes back
Saurav Dasf0f592d2016-11-18 15:21:57 -0800847 log.info("** PORT UPDATED {}/{} -> {}",
848 event.subject(),
849 ((DeviceEvent) event).port(),
850 event.type());
851 processPortUpdated(((Device) event.subject()),
852 ((DeviceEvent) event).port());
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700853 } else {
854 log.warn("Unhandled event type: {}", event.type());
855 }
sangho80f11cb2015-04-01 13:05:26 -0700856 }
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700857 } catch (Exception e) {
858 log.error("SegmentRouting event handler "
859 + "thread thrown an exception: {}", e);
sangho80f11cb2015-04-01 13:05:26 -0700860 }
sangho80f11cb2015-04-01 13:05:26 -0700861 }
862 }
863
sangho80f11cb2015-04-01 13:05:26 -0700864 private void processLinkAdded(Link link) {
Saurav Dasb149be12016-06-07 10:08:06 -0700865 log.info("** LINK ADDED {}", link.toString());
Charles Chan319d1a22015-11-03 10:42:14 -0800866 if (!deviceConfiguration.isConfigured(link.src().deviceId())) {
867 log.warn("Source device of this link is not configured.");
868 return;
869 }
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700870 //Irrespective whether the local is a MASTER or not for this device,
871 //create group handler instance and push default TTP flow rules.
872 //Because in a multi-instance setup, instances can initiate
873 //groups for any devices. Also the default TTP rules are needed
874 //to be pushed before inserting any IP table entries for any device
875 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src()
876 .deviceId());
877 if (groupHandler != null) {
Saurav Das4c35fc42015-11-20 15:27:53 -0800878 groupHandler.linkUp(link, mastershipService.isLocalMaster(
879 link.src().deviceId()));
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700880 } else {
881 Device device = deviceService.getDevice(link.src().deviceId());
882 if (device != null) {
883 log.warn("processLinkAdded: Link Added "
884 + "Notification without Device Added "
885 + "event, still handling it");
886 processDeviceAdded(device);
887 groupHandler = groupHandlerMap.get(link.src()
888 .deviceId());
Saurav Das4c35fc42015-11-20 15:27:53 -0800889 groupHandler.linkUp(link, mastershipService.isLocalMaster(device.id()));
sangho80f11cb2015-04-01 13:05:26 -0700890 }
891 }
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700892
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700893 log.trace("Starting optimized route population process");
894 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null);
895 //log.trace("processLinkAdded: re-starting route population process");
896 //defaultRoutingHandler.startPopulationProcess();
Charles Chan72779502016-04-23 17:36:10 -0700897
898 mcastHandler.init();
sangho80f11cb2015-04-01 13:05:26 -0700899 }
900
901 private void processLinkRemoved(Link link) {
Saurav Dasb149be12016-06-07 10:08:06 -0700902 log.info("** LINK REMOVED {}", link.toString());
sangho2165d222015-05-01 09:38:25 -0700903 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
904 if (groupHandler != null) {
Saurav Das62af8802015-12-04 10:52:59 -0800905 groupHandler.portDown(link.src().port(),
906 mastershipService.isLocalMaster(link.src().deviceId()));
sangho2165d222015-05-01 09:38:25 -0700907 }
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700908 log.trace("Starting optimized route population process");
909 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
910 //log.trace("processLinkRemoved: re-starting route population process");
911 //defaultRoutingHandler.startPopulationProcess();
Charles Chan72779502016-04-23 17:36:10 -0700912
913 mcastHandler.processLinkDown(link);
sangho80f11cb2015-04-01 13:05:26 -0700914 }
915
916 private void processDeviceAdded(Device device) {
Saurav Dasb149be12016-06-07 10:08:06 -0700917 log.info("** DEVICE ADDED with ID {}", device.id());
Charles Chan319d1a22015-11-03 10:42:14 -0800918 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
Saurav Das8ec0ec42015-11-03 14:39:27 -0800919 log.warn("Device configuration uploading. Device {} will be "
920 + "processed after config completes.", device.id());
921 return;
922 }
Charles Chan72779502016-04-23 17:36:10 -0700923 processDeviceAddedInternal(device.id());
924 }
925
926 private void processDeviceAddedInternal(DeviceId deviceId) {
Saurav Dasc28b3432015-10-30 17:45:38 -0700927 // Irrespective of whether the local is a MASTER or not for this device,
928 // we need to create a SR-group-handler instance. This is because in a
929 // multi-instance setup, any instance can initiate forwarding/next-objectives
930 // for any switch (even if this instance is a SLAVE or not even connected
931 // to the switch). To handle this, a default-group-handler instance is necessary
932 // per switch.
Charles Chan72779502016-04-23 17:36:10 -0700933 log.debug("Current groupHandlerMap devs: {}", groupHandlerMap.keySet());
934 if (groupHandlerMap.get(deviceId) == null) {
Charles Chan319d1a22015-11-03 10:42:14 -0800935 DefaultGroupHandler groupHandler;
936 try {
937 groupHandler = DefaultGroupHandler.
Charles Chan72779502016-04-23 17:36:10 -0700938 createGroupHandler(deviceId,
939 appId,
940 deviceConfiguration,
941 linkService,
942 flowObjectiveService,
943 this);
Charles Chan319d1a22015-11-03 10:42:14 -0800944 } catch (DeviceConfigNotFoundException e) {
945 log.warn(e.getMessage() + " Aborting processDeviceAdded.");
946 return;
947 }
Charles Chan72779502016-04-23 17:36:10 -0700948 log.debug("updating groupHandlerMap with new config for device: {}",
949 deviceId);
950 groupHandlerMap.put(deviceId, groupHandler);
Saurav Das8ec0ec42015-11-03 14:39:27 -0800951 }
Saurav Dasb149be12016-06-07 10:08:06 -0700952 // Also, in some cases, drivers may need extra
953 // information to process rules (eg. Router IP/MAC); and so, we send
954 // port addressing rules to the driver as well irrespective of whether
955 // this instance is the master or not.
956 defaultRoutingHandler.populatePortAddressingRules(deviceId);
957
Charles Chan72779502016-04-23 17:36:10 -0700958 if (mastershipService.isLocalMaster(deviceId)) {
Charles Chandebfea32016-10-24 14:52:01 -0700959 hostHandler.init(deviceId);
Charles Chan82f19972016-05-17 13:13:55 -0700960 xConnectHandler.init(deviceId);
Charles Chan41f5ec02016-06-13 18:54:31 -0700961 cordConfigHandler.init(deviceId);
Charles Chan72779502016-04-23 17:36:10 -0700962 DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
Charles Chan77277672015-10-20 16:24:19 -0700963 groupHandler.createGroupsFromSubnetConfig();
Charles Chan72779502016-04-23 17:36:10 -0700964 routingRulePopulator.populateSubnetBroadcastRule(deviceId);
Charles Chan77277672015-10-20 16:24:19 -0700965 }
Charles Chan82ab1932016-01-30 23:22:37 -0800966
Charles Chandebfea32016-10-24 14:52:01 -0700967 appCfgHandler.init(deviceId);
968 routeHandler.init(deviceId);
sangho80f11cb2015-04-01 13:05:26 -0700969 }
970
Saurav Dasc3604f12016-03-23 11:22:49 -0700971 private void processDeviceRemoved(Device device) {
972 nsNextObjStore.entrySet().stream()
973 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
974 .forEach(entry -> {
975 nsNextObjStore.remove(entry.getKey());
976 });
Saurav Dasc3604f12016-03-23 11:22:49 -0700977 subnetNextObjStore.entrySet().stream()
978 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
979 .forEach(entry -> {
980 subnetNextObjStore.remove(entry.getKey());
981 });
Saurav Dasc3604f12016-03-23 11:22:49 -0700982 portNextObjStore.entrySet().stream()
983 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
984 .forEach(entry -> {
985 portNextObjStore.remove(entry.getKey());
986 });
Saurav Dasc3604f12016-03-23 11:22:49 -0700987 subnetVidStore.entrySet().stream()
988 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
989 .forEach(entry -> {
990 subnetVidStore.remove(entry.getKey());
991 });
Saurav Dasc3604f12016-03-23 11:22:49 -0700992 groupHandlerMap.remove(device.id());
Saurav Dasc3604f12016-03-23 11:22:49 -0700993 defaultRoutingHandler.purgeEcmpGraph(device.id());
Charles Chan72779502016-04-23 17:36:10 -0700994 mcastHandler.removeDevice(device.id());
Charles Chan82f19972016-05-17 13:13:55 -0700995 xConnectHandler.removeDevice(device.id());
Saurav Dasc3604f12016-03-23 11:22:49 -0700996 }
997
Saurav Dasf0f592d2016-11-18 15:21:57 -0800998 private void processPortUpdated(Device device, Port port) {
999 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
1000 log.warn("Device configuration uploading. Not handling port event for"
1001 + "dev: {} port: {}", device.id(), port.number());
1002 return;
1003 }
1004 /* XXX create method for single port filtering rules which are needed
1005 for both switch-to-switch ports and edge ports
1006 if (defaultRoutingHandler != null) {
1007 defaultRoutingHandler.populatePortAddressingRules(
1008 ((Device) event.subject()).id());
1009 }*/
1010
1011 // portUpdated calls are for ports that have gone down or up. For switch
1012 // to switch ports, link-events should take care of any re-routing or
1013 // group editing necessary for port up/down. Here we only process edge ports
1014 // that are already configured.
Pier Ventreb6a7f342016-11-26 21:05:22 -08001015 Ip4Prefix configuredSubnet = deviceConfiguration.getPortIPv4Subnet(device.id(),
Saurav Dasf0f592d2016-11-18 15:21:57 -08001016 port.number());
1017 if (configuredSubnet == null) {
1018 log.debug("Not handling port updated event for unconfigured port "
1019 + "dev/port: {}/{}", device.id(), port.number());
1020 return;
1021 }
1022 processEdgePort(device, port, configuredSubnet);
1023 }
1024
1025 private void processEdgePort(Device device, Port port, Ip4Prefix subnet) {
1026 boolean portUp = port.isEnabled();
1027 if (portUp) {
1028 log.info("Device:EdgePort {}:{} is enabled in subnet: {}", device.id(),
1029 port.number(), subnet);
1030 } else {
1031 log.info("Device:EdgePort {}:{} is disabled in subnet: {}", device.id(),
1032 port.number(), subnet);
1033 }
1034
Srikanth Vavilapalli64505482015-04-21 13:04:13 -07001035 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
sangho80f11cb2015-04-01 13:05:26 -07001036 if (groupHandler != null) {
Saurav Dasf0f592d2016-11-18 15:21:57 -08001037 groupHandler.processEdgePort(port.number(), subnet, portUp,
Saurav Das62af8802015-12-04 10:52:59 -08001038 mastershipService.isLocalMaster(device.id()));
Saurav Dasf0f592d2016-11-18 15:21:57 -08001039 } else {
1040 log.warn("Group handler not found for dev:{}. Not handling edge port"
1041 + " {} event for port:{}", device.id(),
1042 (portUp) ? "UP" : "DOWN", port.number());
sangho80f11cb2015-04-01 13:05:26 -07001043 }
1044 }
sangho27462c62015-05-14 00:39:53 -07001045
Pier Ventreb6a7f342016-11-26 21:05:22 -08001046 /**
1047 * Registers the given connect point with the NRS, this is necessary
1048 * to receive the NDP and ARP packets from the NRS.
1049 *
1050 * @param portToRegister connect point to register
1051 */
1052 public void registerConnectPoint(ConnectPoint portToRegister) {
Pier Ventreb6a7f342016-11-26 21:05:22 -08001053 this.neighbourResolutionService.registerNeighbourHandler(
1054 portToRegister,
1055 neighbourHandler,
1056 appId
1057 );
1058 }
1059
Charles Chan72f556a2015-10-05 17:50:33 -07001060 private class InternalConfigListener implements NetworkConfigListener {
Charles Chan46fdfaf2016-11-09 20:51:44 -08001061 SegmentRoutingManager srManager;
Charles Chane7c61022015-10-07 14:21:45 -07001062
Charles Chanb7f75ac2016-01-11 18:28:54 -08001063 /**
1064 * Constructs the internal network config listener.
1065 *
Charles Chan46fdfaf2016-11-09 20:51:44 -08001066 * @param srManager segment routing manager
Charles Chanb7f75ac2016-01-11 18:28:54 -08001067 */
Charles Chan46fdfaf2016-11-09 20:51:44 -08001068 public InternalConfigListener(SegmentRoutingManager srManager) {
1069 this.srManager = srManager;
Charles Chane7c61022015-10-07 14:21:45 -07001070 }
1071
Charles Chanb7f75ac2016-01-11 18:28:54 -08001072 /**
1073 * Reads network config and initializes related data structure accordingly.
1074 */
Charles Chane7c61022015-10-07 14:21:45 -07001075 public void configureNetwork() {
Pier Ventreb6a7f342016-11-26 21:05:22 -08001076
Charles Chan46fdfaf2016-11-09 20:51:44 -08001077 deviceConfiguration = new DeviceConfiguration(srManager);
Charles Chane7c61022015-10-07 14:21:45 -07001078
Charles Chan46fdfaf2016-11-09 20:51:44 -08001079 arpHandler = new ArpHandler(srManager);
1080 icmpHandler = new IcmpHandler(srManager);
1081 ipHandler = new IpHandler(srManager);
1082 routingRulePopulator = new RoutingRulePopulator(srManager);
1083 defaultRoutingHandler = new DefaultRoutingHandler(srManager);
Charles Chane7c61022015-10-07 14:21:45 -07001084
1085 tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
1086 groupHandlerMap, tunnelStore);
1087 policyHandler = new PolicyHandler(appId, deviceConfiguration,
1088 flowObjectiveService,
1089 tunnelHandler, policyStore);
1090
Charles Chane7c61022015-10-07 14:21:45 -07001091 for (Device device : deviceService.getDevices()) {
Charles Chan72779502016-04-23 17:36:10 -07001092 processDeviceAddedInternal(device.id());
Charles Chane7c61022015-10-07 14:21:45 -07001093 }
1094
1095 defaultRoutingHandler.startPopulationProcess();
Charles Chan72779502016-04-23 17:36:10 -07001096 mcastHandler.init();
Charles Chane7c61022015-10-07 14:21:45 -07001097 }
1098
Charles Chan72f556a2015-10-05 17:50:33 -07001099 @Override
1100 public void event(NetworkConfigEvent event) {
Charles Chan82ab1932016-01-30 23:22:37 -08001101 // TODO move this part to NetworkConfigEventHandler
1102 if (event.configClass().equals(SegmentRoutingDeviceConfig.class)) {
1103 switch (event.type()) {
1104 case CONFIG_ADDED:
1105 log.info("Segment Routing Config added.");
1106 configureNetwork();
1107 break;
1108 case CONFIG_UPDATED:
1109 log.info("Segment Routing Config updated.");
1110 // TODO support dynamic configuration
1111 break;
1112 default:
1113 break;
Charles Chan2b078ae2015-10-14 11:24:40 -07001114 }
Charles Chan82ab1932016-01-30 23:22:37 -08001115 } else if (event.configClass().equals(SegmentRoutingAppConfig.class)) {
Charles Chan82f19972016-05-17 13:13:55 -07001116 checkState(appCfgHandler != null, "NetworkConfigEventHandler is not initialized");
Charles Chan82ab1932016-01-30 23:22:37 -08001117 switch (event.type()) {
1118 case CONFIG_ADDED:
Charles Chan82f19972016-05-17 13:13:55 -07001119 appCfgHandler.processAppConfigAdded(event);
Charles Chan82ab1932016-01-30 23:22:37 -08001120 break;
1121 case CONFIG_UPDATED:
Charles Chan82f19972016-05-17 13:13:55 -07001122 appCfgHandler.processAppConfigUpdated(event);
Charles Chan82ab1932016-01-30 23:22:37 -08001123 break;
1124 case CONFIG_REMOVED:
Charles Chan82f19972016-05-17 13:13:55 -07001125 appCfgHandler.processAppConfigRemoved(event);
1126 break;
1127 default:
1128 break;
1129 }
Charles Chandebfea32016-10-24 14:52:01 -07001130 configureNetwork();
Charles Chan82f19972016-05-17 13:13:55 -07001131 } else if (event.configClass().equals(XConnectConfig.class)) {
1132 checkState(xConnectHandler != null, "XConnectHandler is not initialized");
1133 switch (event.type()) {
1134 case CONFIG_ADDED:
1135 xConnectHandler.processXConnectConfigAdded(event);
1136 break;
1137 case CONFIG_UPDATED:
1138 xConnectHandler.processXConnectConfigUpdated(event);
1139 break;
1140 case CONFIG_REMOVED:
1141 xConnectHandler.processXConnectConfigRemoved(event);
Charles Chan82ab1932016-01-30 23:22:37 -08001142 break;
1143 default:
1144 break;
Charles Chan2b078ae2015-10-14 11:24:40 -07001145 }
Pier Luigi37a35432017-02-01 13:50:04 -08001146 // XXX Neighbour hacking. This method is looking for
1147 // the Internet-Router interface. In order to retrieve
1148 // the upstream port.
1149 } else if (event.configClass().equals(InterfaceConfig.class)) {
1150 switch (event.type()) {
1151 case CONFIG_ADDED:
1152 case CONFIG_UPDATED:
Pier Luigiad0a67f2017-02-03 13:34:21 -08001153 updateUPstreamCP();
Pier Luigi37a35432017-02-01 13:50:04 -08001154 case CONFIG_REGISTERED:
1155 case CONFIG_UNREGISTERED:
1156 case CONFIG_REMOVED:
1157 break;
1158 default:
1159 break;
1160 }
1161 // XXX Neighbour hacking. This method is looking for
1162 // the vrouter port.
1163 } else if (event.configClass().equals(RouterConfig.class)) {
1164 switch (event.type()) {
1165 case CONFIG_ADDED:
1166 case CONFIG_UPDATED:
Pier Luigiad0a67f2017-02-03 13:34:21 -08001167 updateVRouterCP(event);
Pier Luigi37a35432017-02-01 13:50:04 -08001168 case CONFIG_REGISTERED:
1169 case CONFIG_UNREGISTERED:
1170 case CONFIG_REMOVED:
1171 break;
1172 default:
1173 break;
1174 }
Pier Ventre6b19e482016-11-07 16:21:04 -08001175 } else if (event.configClass().equals(PwaasConfig.class)) {
1176 checkState(l2TunnelHandler != null, "L2TunnelHandler is not initialized");
1177 switch (event.type()) {
1178 case CONFIG_ADDED:
1179 l2TunnelHandler.processPwaasConfigAdded(event);
1180 break;
1181 case CONFIG_UPDATED:
1182 l2TunnelHandler.processPwaasConfigUpdated(event);
1183 break;
1184 case CONFIG_REMOVED:
1185 l2TunnelHandler.processPwaasConfigRemoved(event);
1186 break;
1187 default:
1188 break;
1189 }
Charles Chan72f556a2015-10-05 17:50:33 -07001190 }
1191 }
1192 }
Charles Chanf4586112015-11-09 16:37:23 -08001193
Pier Luigiad0a67f2017-02-03 13:34:21 -08001194 /////////////////////////////////////////////////////////////////
1195 // XXX Neighbour hacking, temporary workaround will be //
1196 // removed as soon as possible, when the bridging will //
1197 // be implemented. For now, it's fine to leave this //
1198 /////////////////////////////////////////////////////////////////
1199
1200 // XXX Neighbour hacking. To store upstream connect
1201 // point and vRouter connect point
1202 ConnectPoint upstreamCP = null;
1203 ConnectPoint vRouterCP = null;
1204
1205 // XXX Neighbour hacking. To update the Upstream CP
1206 public void updateUPstreamCP() {
1207 Set<ConnectPoint> portSubjects = cfgService.getSubjects(ConnectPoint.class, InterfaceConfig.class);
1208 upstreamCP = null;
1209 portSubjects.stream().forEach(subject -> {
1210 InterfaceConfig config = cfgService.getConfig(subject, InterfaceConfig.class);
1211 Set<Interface> networkInterfaces;
1212 try {
1213 networkInterfaces = config.getInterfaces();
1214 } catch (ConfigException e) {
1215 log.error("Error loading port configuration");
1216 return;
1217 }
1218 networkInterfaces.forEach(networkInterface -> {
1219 if (networkInterface.name().equals("internet-router")) {
1220 upstreamCP = subject;
1221 }
1222 });
1223 });
1224
1225 }
1226
1227 // XXX Neighbour hacking. To update the Upstream CP
1228 public void updateVRouterCP(NetworkConfigEvent event) {
1229 RouterConfig config = (RouterConfig) event.config().get();
1230 if (config == null) {
1231 log.warn("Router config not available");
1232 vRouterCP = null;
1233 return;
1234 }
1235 vRouterCP = config.getControlPlaneConnectPoint();
1236 }
1237
Charles Chanf4586112015-11-09 16:37:23 -08001238 private class InternalHostListener implements HostListener {
Charles Chanf4586112015-11-09 16:37:23 -08001239 @Override
1240 public void event(HostEvent event) {
1241 // Do not proceed without mastership
1242 DeviceId deviceId = event.subject().location().deviceId();
1243 if (!mastershipService.isLocalMaster(deviceId)) {
1244 return;
1245 }
1246
1247 switch (event.type()) {
1248 case HOST_ADDED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001249 hostHandler.processHostAddedEvent(event);
Charles Chanf4586112015-11-09 16:37:23 -08001250 break;
1251 case HOST_MOVED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001252 hostHandler.processHostMovedEvent(event);
Charles Chanf4586112015-11-09 16:37:23 -08001253 break;
1254 case HOST_REMOVED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001255 hostHandler.processHostRemoveEvent(event);
Charles Chanf4586112015-11-09 16:37:23 -08001256 break;
1257 case HOST_UPDATED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001258 hostHandler.processHostUpdatedEvent(event);
Charles Chanf4586112015-11-09 16:37:23 -08001259 break;
1260 default:
1261 log.warn("Unsupported host event type: {}", event.type());
1262 break;
1263 }
1264 }
1265 }
1266
Charles Chanc91c8782016-03-30 17:54:24 -07001267 private class InternalMcastListener implements McastListener {
1268 @Override
1269 public void event(McastEvent event) {
1270 switch (event.type()) {
1271 case SOURCE_ADDED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001272 mcastHandler.processSourceAdded(event);
Charles Chanc91c8782016-03-30 17:54:24 -07001273 break;
1274 case SINK_ADDED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001275 mcastHandler.processSinkAdded(event);
Charles Chanc91c8782016-03-30 17:54:24 -07001276 break;
1277 case SINK_REMOVED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001278 mcastHandler.processSinkRemoved(event);
Charles Chanc91c8782016-03-30 17:54:24 -07001279 break;
1280 case ROUTE_ADDED:
1281 case ROUTE_REMOVED:
1282 default:
1283 break;
1284 }
1285 }
1286 }
Charles Chan41f5ec02016-06-13 18:54:31 -07001287
1288 private class InternalCordConfigListener implements CordConfigListener {
1289 @Override
1290 public void event(CordConfigEvent event) {
1291 switch (event.type()) {
1292 case ACCESS_AGENT_ADDED:
1293 cordConfigHandler.processAccessAgentAddedEvent(event);
1294 break;
1295 case ACCESS_AGENT_UPDATED:
1296 cordConfigHandler.processAccessAgentUpdatedEvent(event);
1297 break;
1298 case ACCESS_AGENT_REMOVED:
1299 cordConfigHandler.processAccessAgentRemovedEvent(event);
1300 break;
1301 case ACCESS_DEVICE_ADDED:
1302 case ACCESS_DEVICE_UPDATED:
1303 case ACCESS_DEVICE_REMOVED:
1304 default:
1305 break;
1306 }
1307 }
1308 }
Charles Chandebfea32016-10-24 14:52:01 -07001309
1310 private class InternalRouteEventListener implements RouteListener {
1311 @Override
1312 public void event(RouteEvent event) {
1313 switch (event.type()) {
1314 case ROUTE_ADDED:
1315 routeHandler.processRouteAdded(event);
1316 break;
1317 case ROUTE_UPDATED:
1318 routeHandler.processRouteUpdated(event);
1319 break;
1320 case ROUTE_REMOVED:
1321 routeHandler.processRouteRemoved(event);
1322 break;
1323 default:
1324 break;
1325 }
1326 }
1327 }
sangho80f11cb2015-04-01 13:05:26 -07001328}