blob: e1d1dac9be44ea5878fa7cfce78f5b984f44e38b [file] [log] [blame]
alshabibf0e7e702015-05-30 18:22:36 -07001/*
Brian O'Connord6a135a2017-08-03 22:46:05 -07002 * Copyright 2016-present Open Networking Foundation
alshabibf0e7e702015-05-30 18:22:36 -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 */
alshabib36a4d732016-06-01 16:03:59 -070016package org.opencord.olt.impl;
alshabibf0e7e702015-05-30 18:22:36 -070017
Saurav Das82b8e6d2018-10-04 15:25:12 -070018import static com.google.common.base.Preconditions.checkNotNull;
19import static com.google.common.base.Strings.isNullOrEmpty;
20import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
21import static org.onlab.util.Tools.get;
22import static org.onlab.util.Tools.groupedThreads;
23import static org.slf4j.LoggerFactory.getLogger;
24
25import java.util.AbstractMap;
26import java.util.ArrayList;
27import java.util.Collection;
28import java.util.Dictionary;
29import java.util.List;
30import java.util.Map;
31import java.util.Optional;
32import java.util.Properties;
33import java.util.concurrent.CompletableFuture;
34import java.util.concurrent.ExecutorService;
35import java.util.concurrent.Executors;
36
alshabibf0e7e702015-05-30 18:22:36 -070037import org.apache.felix.scr.annotations.Activate;
38import org.apache.felix.scr.annotations.Component;
39import org.apache.felix.scr.annotations.Deactivate;
alshabibe0559672016-02-21 14:49:51 -080040import org.apache.felix.scr.annotations.Modified;
41import org.apache.felix.scr.annotations.Property;
alshabibf0e7e702015-05-30 18:22:36 -070042import org.apache.felix.scr.annotations.Reference;
43import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Harte533a422015-10-20 17:31:24 -070044import org.apache.felix.scr.annotations.Service;
alshabibdec2e252016-01-15 12:20:25 -080045import org.onlab.packet.EthType;
Amit Ghosh95e2f652017-08-23 12:49:46 +010046import org.onlab.packet.IPv4;
47import org.onlab.packet.TpPort;
alshabibf0e7e702015-05-30 18:22:36 -070048import org.onlab.packet.VlanId;
Amit Ghosh95e2f652017-08-23 12:49:46 +010049import org.onlab.util.Tools;
alshabibe0559672016-02-21 14:49:51 -080050import org.onosproject.cfg.ComponentConfigService;
alshabibf0e7e702015-05-30 18:22:36 -070051import org.onosproject.core.ApplicationId;
52import org.onosproject.core.CoreService;
alshabib8e4fd2f2016-01-12 15:55:53 -080053import org.onosproject.event.AbstractListenerManager;
alshabib09753b52016-03-04 14:55:19 -080054import org.onosproject.mastership.MastershipService;
Amit Ghosh1ed9aef2018-07-17 17:08:16 +010055import org.onosproject.net.AnnotationKeys;
Jonathan Harte533a422015-10-20 17:31:24 -070056import org.onosproject.net.ConnectPoint;
Amit Ghosh1ed9aef2018-07-17 17:08:16 +010057import org.onosproject.net.Device;
alshabibf0e7e702015-05-30 18:22:36 -070058import org.onosproject.net.DeviceId;
alshabibdec2e252016-01-15 12:20:25 -080059import org.onosproject.net.Port;
alshabibf0e7e702015-05-30 18:22:36 -070060import org.onosproject.net.PortNumber;
61import org.onosproject.net.device.DeviceEvent;
62import org.onosproject.net.device.DeviceListener;
63import org.onosproject.net.device.DeviceService;
64import org.onosproject.net.flow.DefaultTrafficSelector;
65import org.onosproject.net.flow.DefaultTrafficTreatment;
66import org.onosproject.net.flow.TrafficSelector;
67import org.onosproject.net.flow.TrafficTreatment;
alshabibdec2e252016-01-15 12:20:25 -080068import org.onosproject.net.flow.criteria.Criteria;
69import org.onosproject.net.flowobjective.DefaultFilteringObjective;
alshabibf0e7e702015-05-30 18:22:36 -070070import org.onosproject.net.flowobjective.DefaultForwardingObjective;
alshabibdec2e252016-01-15 12:20:25 -080071import org.onosproject.net.flowobjective.FilteringObjective;
alshabibf0e7e702015-05-30 18:22:36 -070072import org.onosproject.net.flowobjective.FlowObjectiveService;
73import org.onosproject.net.flowobjective.ForwardingObjective;
alshabib3ea82642016-01-12 18:06:53 -080074import org.onosproject.net.flowobjective.Objective;
75import org.onosproject.net.flowobjective.ObjectiveContext;
76import org.onosproject.net.flowobjective.ObjectiveError;
alshabib36a4d732016-06-01 16:03:59 -070077import org.opencord.olt.AccessDeviceEvent;
78import org.opencord.olt.AccessDeviceListener;
79import org.opencord.olt.AccessDeviceService;
Amit Ghosh31939522018-08-16 13:28:21 +010080import org.opencord.olt.AccessSubscriberId;
Amit Ghosh1ed9aef2018-07-17 17:08:16 +010081import org.opencord.sadis.SubscriberAndDeviceInformation;
82import org.opencord.sadis.SubscriberAndDeviceInformationService;
alshabibe0559672016-02-21 14:49:51 -080083import org.osgi.service.component.ComponentContext;
alshabibf0e7e702015-05-30 18:22:36 -070084import org.slf4j.Logger;
85
Saurav Das82b8e6d2018-10-04 15:25:12 -070086import com.google.common.collect.ImmutableMap;
87import com.google.common.collect.Maps;
alshabibf0e7e702015-05-30 18:22:36 -070088
89/**
Jonathan Harte533a422015-10-20 17:31:24 -070090 * Provisions rules on access devices.
alshabibf0e7e702015-05-30 18:22:36 -070091 */
Jonathan Harte533a422015-10-20 17:31:24 -070092@Service
alshabibf0e7e702015-05-30 18:22:36 -070093@Component(immediate = true)
alshabib8e4fd2f2016-01-12 15:55:53 -080094public class Olt
95 extends AbstractListenerManager<AccessDeviceEvent, AccessDeviceListener>
96 implements AccessDeviceService {
Charles Chan54f110f2017-01-20 11:22:42 -080097 private static final String APP_NAME = "org.opencord.olt";
alshabibe0559672016-02-21 14:49:51 -080098
99 private static final short DEFAULT_VLAN = 0;
100
alshabibf0e7e702015-05-30 18:22:36 -0700101 private final Logger log = getLogger(getClass());
102
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 protected FlowObjectiveService flowObjectiveService;
105
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabib09753b52016-03-04 14:55:19 -0800107 protected MastershipService mastershipService;
108
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabibf0e7e702015-05-30 18:22:36 -0700110 protected DeviceService deviceService;
111
112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 protected CoreService coreService;
114
Jonathan Harte533a422015-10-20 17:31:24 -0700115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabibe0559672016-02-21 14:49:51 -0800116 protected ComponentConfigService componentConfigService;
117
alshabib4ceaed32016-03-03 18:00:58 -0800118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100119 protected SubscriberAndDeviceInformationService subsService;
alshabibe0559672016-02-21 14:49:51 -0800120
121 @Property(name = "defaultVlan", intValue = DEFAULT_VLAN,
122 label = "Default VLAN RG<->ONU traffic")
123 private int defaultVlan = DEFAULT_VLAN;
124
Matt Jeanneret3f579262018-06-14 17:16:23 -0400125 @Property(name = "enableDhcpOnProvisioning", boolValue = true,
126 label = "Create the DHCP Flow rules when a subscriber is provisioned")
127 protected boolean enableDhcpOnProvisioning = false;
128
129 @Property(name = "enableIgmpOnProvisioning", boolValue = false,
130 label = "Create IGMP Flow rules when a subscriber is provisioned")
131 protected boolean enableIgmpOnProvisioning = false;
Amit Ghosh95e2f652017-08-23 12:49:46 +0100132
alshabibf0e7e702015-05-30 18:22:36 -0700133 private final DeviceListener deviceListener = new InternalDeviceListener();
134
135 private ApplicationId appId;
136
Saurav Das82b8e6d2018-10-04 15:25:12 -0700137 private ExecutorService oltInstallers = Executors
138 .newFixedThreadPool(4, groupedThreads("onos/olt-service",
139 "olt-installer-%d"));
alshabibf0e7e702015-05-30 18:22:36 -0700140
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700141 protected ExecutorService eventExecutor;
142
Saurav Das82b8e6d2018-10-04 15:25:12 -0700143 private Map<ConnectPoint, SubscriberAndDeviceInformation> programmedSubs;
144
alshabibf0e7e702015-05-30 18:22:36 -0700145 @Activate
alshabibe0559672016-02-21 14:49:51 -0800146 public void activate(ComponentContext context) {
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700147 eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/olt", "events-%d", log));
alshabibe0559672016-02-21 14:49:51 -0800148 modified(context);
Charles Chan54f110f2017-01-20 11:22:42 -0800149 appId = coreService.registerApplication(APP_NAME);
alshabibe0559672016-02-21 14:49:51 -0800150 componentConfigService.registerProperties(getClass());
Saurav Das82b8e6d2018-10-04 15:25:12 -0700151 programmedSubs = Maps.newConcurrentMap();
alshabibc4dfe852015-06-05 13:35:13 -0700152
alshabib8e4fd2f2016-01-12 15:55:53 -0800153 eventDispatcher.addSink(AccessDeviceEvent.class, listenerRegistry);
154
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100155 // look for all provisioned devices in Sadis and create EAPOL flows for the
156 // UNI ports
157 Iterable<Device> devices = deviceService.getDevices();
158 for (Device d : devices) {
Jonathan Hart403372d2018-08-22 11:44:13 -0700159 checkAndCreateDeviceFlows(d);
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100160 }
alshabib4ceaed32016-03-03 18:00:58 -0800161
alshabibba357492016-01-27 13:49:46 -0800162 deviceService.addListener(deviceListener);
163
alshabibf0e7e702015-05-30 18:22:36 -0700164 log.info("Started with Application ID {}", appId.id());
165 }
166
167 @Deactivate
168 public void deactivate() {
alshabibe0559672016-02-21 14:49:51 -0800169 componentConfigService.unregisterProperties(getClass(), false);
alshabib62e9ce72016-02-11 17:31:36 -0800170 deviceService.removeListener(deviceListener);
Jonathan Hart5f1c8142018-07-24 17:31:59 -0700171 eventDispatcher.removeSink(AccessDeviceEvent.class);
alshabibf0e7e702015-05-30 18:22:36 -0700172 log.info("Stopped");
173 }
174
alshabibe0559672016-02-21 14:49:51 -0800175 @Modified
176 public void modified(ComponentContext context) {
177 Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
178
179 try {
180 String s = get(properties, "defaultVlan");
181 defaultVlan = isNullOrEmpty(s) ? DEFAULT_VLAN : Integer.parseInt(s.trim());
Amit Ghosh95e2f652017-08-23 12:49:46 +0100182
Matt Jeanneret3f579262018-06-14 17:16:23 -0400183 Boolean o = Tools.isPropertyEnabled(properties, "enableDhcpOnProvisioning");
Amit Ghosh95e2f652017-08-23 12:49:46 +0100184 if (o != null) {
Matt Jeanneret3f579262018-06-14 17:16:23 -0400185 enableDhcpOnProvisioning = o;
Amit Ghosh95e2f652017-08-23 12:49:46 +0100186 }
Matt Jeanneret3f579262018-06-14 17:16:23 -0400187
188 Boolean p = Tools.isPropertyEnabled(properties, "enableIgmpOnProvisioning");
189 if (p != null) {
190 enableIgmpOnProvisioning = p;
191 }
192
alshabibe0559672016-02-21 14:49:51 -0800193 } catch (Exception e) {
194 defaultVlan = DEFAULT_VLAN;
195 }
196 }
197
alshabib32232c82016-02-25 17:57:24 -0500198 @Override
Amit Ghosh31939522018-08-16 13:28:21 +0100199 public boolean provisionSubscriber(ConnectPoint port) {
Jonathan Hart94b90492018-04-24 14:02:25 -0700200 checkNotNull(deviceService.getPort(port.deviceId(), port.port()),
201 "Invalid connect point");
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100202 // Find the subscriber on this connect point
203 SubscriberAndDeviceInformation sub = getSubscriber(port);
204 if (sub == null) {
205 log.warn("No subscriber found for {}", port);
Amit Ghosh31939522018-08-16 13:28:21 +0100206 return false;
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100207 }
Jonathan Harte533a422015-10-20 17:31:24 -0700208
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100209 // Get the uplink port
210 Port uplinkPort = getUplinkPort(deviceService.getDevice(port.deviceId()));
211 if (uplinkPort == null) {
212 log.warn("No uplink port found for OLT device {}", port.deviceId());
Amit Ghosh31939522018-08-16 13:28:21 +0100213 return false;
Jonathan Harte533a422015-10-20 17:31:24 -0700214 }
215
Matt Jeanneret3f579262018-06-14 17:16:23 -0400216 if (enableDhcpOnProvisioning) {
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100217 processDhcpFilteringObjectives(port.deviceId(), port.port(), true);
Amit Ghosh95e2f652017-08-23 12:49:46 +0100218 }
Saurav Das82b8e6d2018-10-04 15:25:12 -0700219 log.info("Programming vlans for subscriber: {}", sub);
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100220 Optional<VlanId> defaultVlan = Optional.empty();
Saurav Das82b8e6d2018-10-04 15:25:12 -0700221 provisionVlans(port.deviceId(), uplinkPort.number(), port.port(),
222 sub.cTag(), sub.sTag(), defaultVlan);
Amit Ghosh95e2f652017-08-23 12:49:46 +0100223
Matt Jeanneret3f579262018-06-14 17:16:23 -0400224 if (enableIgmpOnProvisioning) {
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100225 processIgmpFilteringObjectives(port.deviceId(), port.port(), true);
Amit Ghosh95e2f652017-08-23 12:49:46 +0100226 }
Saurav Das82b8e6d2018-10-04 15:25:12 -0700227 // cache subscriber info
228 programmedSubs.put(port, sub);
Amit Ghosh31939522018-08-16 13:28:21 +0100229 return true;
alshabibb7a9e172016-01-13 11:23:53 -0800230 }
231
232 @Override
Amit Ghosh31939522018-08-16 13:28:21 +0100233 public boolean removeSubscriber(ConnectPoint port) {
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100234 // Get the subscriber connected to this port from Sadis
235 SubscriberAndDeviceInformation subscriber = getSubscriber(port);
236 if (subscriber == null) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700237 log.warn("Subscriber on port {} not found in sadis .. checking "
238 + "local cache", port);
239 subscriber = programmedSubs.get(port);
240 if (subscriber == null) {
241 log.warn("Subscriber on port {} was not previously programmed", port);
242 return false;
243 }
alshabibbf23a1f2016-01-14 17:27:11 -0800244 }
245
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100246 // Get the uplink port
247 Port uplinkPort = getUplinkPort(deviceService.getDevice(port.deviceId()));
248 if (uplinkPort == null) {
249 log.warn("No uplink port found for OLT device {}", port.deviceId());
Amit Ghosh31939522018-08-16 13:28:21 +0100250 return false;
alshabib4ceaed32016-03-03 18:00:58 -0800251 }
252
Matt Jeanneret3f579262018-06-14 17:16:23 -0400253 if (enableDhcpOnProvisioning) {
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100254 processDhcpFilteringObjectives(port.deviceId(), port.port(), false);
Amit Ghosh95e2f652017-08-23 12:49:46 +0100255 }
256
Saurav Das82b8e6d2018-10-04 15:25:12 -0700257 log.info("Removing programmed vlans for subscriber: {}", subscriber);
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100258 Optional<VlanId> defaultVlan = Optional.empty();
Saurav Das82b8e6d2018-10-04 15:25:12 -0700259 unprovisionSubscriber(port.deviceId(), uplinkPort.number(), port.port(),
260 subscriber.cTag(), subscriber.sTag(), defaultVlan);
alshabibbf23a1f2016-01-14 17:27:11 -0800261
Matt Jeanneret3f579262018-06-14 17:16:23 -0400262 if (enableIgmpOnProvisioning) {
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100263 processIgmpFilteringObjectives(port.deviceId(), port.port(), false);
Amit Ghosh95e2f652017-08-23 12:49:46 +0100264 }
Saurav Das82b8e6d2018-10-04 15:25:12 -0700265 programmedSubs.remove(port);
Amit Ghosh31939522018-08-16 13:28:21 +0100266 return true;
alshabibbf23a1f2016-01-14 17:27:11 -0800267 }
268
Amit Ghosh31939522018-08-16 13:28:21 +0100269 @Override
270 public boolean provisionSubscriber(AccessSubscriberId subscriberId) {
271 // Check if we can find the connect point to which this subscriber is connected
272 ConnectPoint subsPort = findSubscriberConnectPoint(subscriberId.toString());
273 if (subsPort == null) {
274 log.warn("ConnectPoint for {} not found", subscriberId);
275 return false;
276 }
277
278 return provisionSubscriber(subsPort);
279 }
Amit Ghosh95e2f652017-08-23 12:49:46 +0100280
alshabibe0559672016-02-21 14:49:51 -0800281 @Override
Amit Ghosh31939522018-08-16 13:28:21 +0100282 public boolean removeSubscriber(AccessSubscriberId subscriberId) {
283 // Check if we can find the connect point to which this subscriber is connected
284 ConnectPoint subsPort = findSubscriberConnectPoint(subscriberId.toString());
285 if (subsPort == null) {
286 log.warn("ConnectPoint for {} not found", subscriberId);
287 return false;
288 }
289
290 return removeSubscriber(subsPort);
291 }
292
293 @Override
294 public Collection<Map.Entry<ConnectPoint, Map.Entry<VlanId, VlanId>>> getSubscribers() {
295 ArrayList<Map.Entry<ConnectPoint, Map.Entry<VlanId, VlanId>>> subs = new ArrayList<>();
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100296
Saurav Das82b8e6d2018-10-04 15:25:12 -0700297 // Get the subscribers for all the devices configured in sadis
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100298 // If the port is UNI, is enabled and exists in Sadis then copy it
299 for (Device d : deviceService.getDevices()) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700300 if (getOltInfo(d) == null) {
301 continue; // not an olt, or not configured in sadis
302 }
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100303 for (Port p: deviceService.getPorts(d.id())) {
304 if (isUniPort(d, p) && p.isEnabled()) {
305 ConnectPoint cp = new ConnectPoint(d.id(), p.number());
306
307 SubscriberAndDeviceInformation sub = getSubscriber(cp);
308 if (sub != null) {
Amit Ghosh31939522018-08-16 13:28:21 +0100309 Map.Entry<VlanId, VlanId> vlans = new AbstractMap.SimpleEntry(sub.sTag(), sub.cTag());
310 subs.add(new AbstractMap.SimpleEntry(cp, vlans));
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100311 }
312 }
313 }
314 }
315
316 return subs;
Jonathan Hartfd6c1b32016-03-08 14:09:09 -0800317 }
318
319 @Override
Saurav Das82b8e6d2018-10-04 15:25:12 -0700320 public ImmutableMap<ConnectPoint, SubscriberAndDeviceInformation> getProgSubs() {
321 return ImmutableMap.copyOf(programmedSubs);
322 }
323
324 @Override
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100325 public List<DeviceId> fetchOlts() {
326 // look through all the devices and find the ones that are OLTs as per Sadis
327 List<DeviceId> olts = new ArrayList<>();
328 Iterable<Device> devices = deviceService.getDevices();
329 for (Device d : devices) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700330 if (getOltInfo(d) != null) {
331 // So this is indeed an OLT device
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100332 olts.add(d.id());
333 }
334 }
335 return olts;
alshabibe0559672016-02-21 14:49:51 -0800336 }
337
Amit Ghosh31939522018-08-16 13:28:21 +0100338 /**
339 * Finds the connect point to which a subscriber is connected.
340 *
341 * @param id The id of the subscriber, this is the same ID as in Sadis
342 * @return Subscribers ConnectPoint if found else null
343 */
344 private ConnectPoint findSubscriberConnectPoint(String id) {
345
346 Iterable<Device> devices = deviceService.getDevices();
347 for (Device d : devices) {
348 for (Port p : deviceService.getPorts(d.id())) {
349 log.trace("Comparing {} with {}", p.annotations().value(AnnotationKeys.PORT_NAME), id);
350 if (p.annotations().value(AnnotationKeys.PORT_NAME).equals(id)) {
351 log.debug("Found on device {} port {}", d.id(), p.number());
352 return new ConnectPoint(d.id(), p.number());
353 }
354 }
355 }
356 return null;
357 }
358
alshabibbf23a1f2016-01-14 17:27:11 -0800359 private void unprovisionSubscriber(DeviceId deviceId, PortNumber uplink,
Saurav Das82b8e6d2018-10-04 15:25:12 -0700360 PortNumber subscriberPort, VlanId cVlan,
361 VlanId sVlan, Optional<VlanId> defaultVlan) {
alshabibbf23a1f2016-01-14 17:27:11 -0800362
363 CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
364 CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
365
alshabib4ceaed32016-03-03 18:00:58 -0800366 ForwardingObjective.Builder upFwd = upBuilder(uplink, subscriberPort,
Saurav Das82b8e6d2018-10-04 15:25:12 -0700367 cVlan, sVlan,
alshabib4ceaed32016-03-03 18:00:58 -0800368 defaultVlan);
369 ForwardingObjective.Builder downFwd = downBuilder(uplink, subscriberPort,
Saurav Das82b8e6d2018-10-04 15:25:12 -0700370 cVlan, sVlan,
alshabib4ceaed32016-03-03 18:00:58 -0800371 defaultVlan);
alshabibbf23a1f2016-01-14 17:27:11 -0800372
alshabib4ceaed32016-03-03 18:00:58 -0800373 flowObjectiveService.forward(deviceId, upFwd.remove(new ObjectiveContext() {
374 @Override
375 public void onSuccess(Objective objective) {
376 upFuture.complete(null);
377 }
alshabibbf23a1f2016-01-14 17:27:11 -0800378
alshabib4ceaed32016-03-03 18:00:58 -0800379 @Override
380 public void onError(Objective objective, ObjectiveError error) {
381 upFuture.complete(error);
382 }
383 }));
384
385 flowObjectiveService.forward(deviceId, downFwd.remove(new ObjectiveContext() {
386 @Override
387 public void onSuccess(Objective objective) {
388 downFuture.complete(null);
389 }
390
391 @Override
392 public void onError(Objective objective, ObjectiveError error) {
393 downFuture.complete(error);
394 }
395 }));
alshabibbf23a1f2016-01-14 17:27:11 -0800396
397 upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
398 if (upStatus == null && downStatus == null) {
399 post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_UNREGISTERED,
400 deviceId,
Saurav Das82b8e6d2018-10-04 15:25:12 -0700401 sVlan,
402 cVlan));
alshabibbf23a1f2016-01-14 17:27:11 -0800403 } else if (downStatus != null) {
404 log.error("Subscriber with vlan {} on device {} " +
405 "on port {} failed downstream uninstallation: {}",
Saurav Das82b8e6d2018-10-04 15:25:12 -0700406 cVlan, deviceId, subscriberPort, downStatus);
alshabibbf23a1f2016-01-14 17:27:11 -0800407 } else if (upStatus != null) {
408 log.error("Subscriber with vlan {} on device {} " +
409 "on port {} failed upstream uninstallation: {}",
Saurav Das82b8e6d2018-10-04 15:25:12 -0700410 cVlan, deviceId, subscriberPort, upStatus);
alshabibbf23a1f2016-01-14 17:27:11 -0800411 }
412 }, oltInstallers);
alshabibb7a9e172016-01-13 11:23:53 -0800413
Jonathan Harte533a422015-10-20 17:31:24 -0700414 }
415
416 private void provisionVlans(DeviceId deviceId, PortNumber uplinkPort,
417 PortNumber subscriberPort,
Jonathan Hart52998382015-11-10 16:09:22 -0800418 VlanId subscriberVlan, VlanId deviceVlan,
419 Optional<VlanId> defaultVlan) {
Jonathan Harte533a422015-10-20 17:31:24 -0700420
alshabib3ea82642016-01-12 18:06:53 -0800421 CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
422 CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
423
alshabib4ceaed32016-03-03 18:00:58 -0800424 ForwardingObjective.Builder upFwd = upBuilder(uplinkPort, subscriberPort,
425 subscriberVlan, deviceVlan,
426 defaultVlan);
Jonathan Harte533a422015-10-20 17:31:24 -0700427
428
alshabib4ceaed32016-03-03 18:00:58 -0800429 ForwardingObjective.Builder downFwd = downBuilder(uplinkPort, subscriberPort,
430 subscriberVlan, deviceVlan,
431 defaultVlan);
alshabib3ea82642016-01-12 18:06:53 -0800432
alshabibbf23a1f2016-01-14 17:27:11 -0800433 flowObjectiveService.forward(deviceId, upFwd.add(new ObjectiveContext() {
434 @Override
435 public void onSuccess(Objective objective) {
436 upFuture.complete(null);
437 }
438
439 @Override
440 public void onError(Objective objective, ObjectiveError error) {
441 upFuture.complete(error);
442 }
443 }));
444
alshabibbf23a1f2016-01-14 17:27:11 -0800445 flowObjectiveService.forward(deviceId, downFwd.add(new ObjectiveContext() {
446 @Override
447 public void onSuccess(Objective objective) {
448 downFuture.complete(null);
449 }
450
451 @Override
452 public void onError(Objective objective, ObjectiveError error) {
453 downFuture.complete(error);
454 }
455 }));
alshabib3ea82642016-01-12 18:06:53 -0800456
457 upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
458 if (upStatus == null && downStatus == null) {
459 post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_REGISTERED,
460 deviceId,
461 deviceVlan,
462 subscriberVlan));
alshabib50d9fc52016-02-12 15:47:20 -0800463
alshabib3ea82642016-01-12 18:06:53 -0800464 } else if (downStatus != null) {
465 log.error("Subscriber with vlan {} on device {} " +
466 "on port {} failed downstream installation: {}",
467 subscriberVlan, deviceId, subscriberPort, downStatus);
468 } else if (upStatus != null) {
469 log.error("Subscriber with vlan {} on device {} " +
470 "on port {} failed upstream installation: {}",
471 subscriberVlan, deviceId, subscriberPort, upStatus);
472 }
473 }, oltInstallers);
474
Jonathan Harte533a422015-10-20 17:31:24 -0700475 }
476
alshabib4ceaed32016-03-03 18:00:58 -0800477 private ForwardingObjective.Builder downBuilder(PortNumber uplinkPort,
478 PortNumber subscriberPort,
479 VlanId subscriberVlan,
480 VlanId deviceVlan,
481 Optional<VlanId> defaultVlan) {
482 TrafficSelector downstream = DefaultTrafficSelector.builder()
483 .matchVlanId(deviceVlan)
484 .matchInPort(uplinkPort)
485 .matchInnerVlanId(subscriberVlan)
486 .build();
487
488 TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
489 .popVlan()
490 .setVlanId(defaultVlan.orElse(VlanId.vlanId((short) this.defaultVlan)))
491 .setOutput(subscriberPort)
492 .build();
493
494 return DefaultForwardingObjective.builder()
495 .withFlag(ForwardingObjective.Flag.VERSATILE)
496 .withPriority(1000)
497 .makePermanent()
498 .withSelector(downstream)
499 .fromApp(appId)
500 .withTreatment(downstreamTreatment);
501 }
502
503 private ForwardingObjective.Builder upBuilder(PortNumber uplinkPort,
504 PortNumber subscriberPort,
505 VlanId subscriberVlan,
506 VlanId deviceVlan,
507 Optional<VlanId> defaultVlan) {
508 TrafficSelector upstream = DefaultTrafficSelector.builder()
509 .matchVlanId(defaultVlan.orElse(VlanId.vlanId((short) this.defaultVlan)))
510 .matchInPort(subscriberPort)
511 .build();
512
513
514 TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
515 .pushVlan()
516 .setVlanId(subscriberVlan)
517 .pushVlan()
518 .setVlanId(deviceVlan)
519 .setOutput(uplinkPort)
520 .build();
521
522 return DefaultForwardingObjective.builder()
523 .withFlag(ForwardingObjective.Flag.VERSATILE)
524 .withPriority(1000)
525 .makePermanent()
526 .withSelector(upstream)
527 .fromApp(appId)
528 .withTreatment(upstreamTreatment);
529 }
530
Saurav Das82b8e6d2018-10-04 15:25:12 -0700531 private void processEapolFilteringObjectives(DeviceId devId, PortNumber port, boolean install) {
alshabib09753b52016-03-04 14:55:19 -0800532 if (!mastershipService.isLocalMaster(devId)) {
533 return;
534 }
alshabibbb83aa22016-02-10 15:08:23 -0800535 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
536
537 FilteringObjective eapol = (install ? builder.permit() : builder.deny())
alshabib50d9fc52016-02-12 15:47:20 -0800538 .withKey(Criteria.matchInPort(port))
alshabibdec2e252016-01-15 12:20:25 -0800539 .addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType()))
540 .withMeta(DefaultTrafficTreatment.builder()
541 .setOutput(PortNumber.CONTROLLER).build())
542 .fromApp(appId)
Matt Jeanneret3f579262018-06-14 17:16:23 -0400543 .withPriority(10000)
alshabibdec2e252016-01-15 12:20:25 -0800544 .add(new ObjectiveContext() {
545 @Override
546 public void onSuccess(Objective objective) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700547 log.info("Eapol filter for {} on {} {}.",
548 devId, port, (install) ? "installed" : "removed");
alshabibdec2e252016-01-15 12:20:25 -0800549 }
550
551 @Override
552 public void onError(Objective objective, ObjectiveError error) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700553 log.info("Eapol filter for {} on {} failed {} because {}",
554 devId, port, (install) ? "installation" : "removal",
555 error);
alshabibdec2e252016-01-15 12:20:25 -0800556 }
557 });
558
alshabibdec2e252016-01-15 12:20:25 -0800559 flowObjectiveService.filter(devId, eapol);
alshabib000b6fc2016-02-01 17:25:00 -0800560
alshabibdec2e252016-01-15 12:20:25 -0800561 }
562
Jonathan Hart403372d2018-08-22 11:44:13 -0700563 /**
564 * Installs trap filtering objectives for particular traffic types on an
565 * NNI port.
566 *
567 * @param devId device ID
568 * @param port port number
569 * @param install true to install, false to remove
570 */
571 private void processNniFilteringObjectives(DeviceId devId, PortNumber port, boolean install) {
572 processLldpFilteringObjective(devId, port, install);
573 processDhcpFilteringObjectives(devId, port, install);
574 }
575
576 private void processLldpFilteringObjective(DeviceId devId, PortNumber port, boolean install) {
577 if (!mastershipService.isLocalMaster(devId)) {
578 return;
579 }
580 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
581
582 FilteringObjective lldp = (install ? builder.permit() : builder.deny())
583 .withKey(Criteria.matchInPort(port))
584 .addCondition(Criteria.matchEthType(EthType.EtherType.LLDP.ethType()))
585 .withMeta(DefaultTrafficTreatment.builder()
586 .setOutput(PortNumber.CONTROLLER).build())
587 .fromApp(appId)
588 .withPriority(10000)
589 .add(new ObjectiveContext() {
590 @Override
591 public void onSuccess(Objective objective) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700592 log.info("LLDP filter for {} on {} {}.",
593 devId, port, (install) ? "installed" : "removed");
Jonathan Hart403372d2018-08-22 11:44:13 -0700594 }
595
596 @Override
597 public void onError(Objective objective, ObjectiveError error) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700598 log.info("LLDP filter for {} on {} failed {} because {}",
599 devId, port, (install) ? "installation" : "removal",
600 error);
Jonathan Hart403372d2018-08-22 11:44:13 -0700601 }
602 });
603
604 flowObjectiveService.filter(devId, lldp);
605
606 }
607
Amit Ghosh95e2f652017-08-23 12:49:46 +0100608 private void processDhcpFilteringObjectives(DeviceId devId, PortNumber port, boolean install) {
609 if (!mastershipService.isLocalMaster(devId)) {
610 return;
611 }
612 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
613
614 FilteringObjective dhcpUpstream = (install ? builder.permit() : builder.deny())
615 .withKey(Criteria.matchInPort(port))
616 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
617 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP))
618 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(68)))
619 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(67)))
620 .withMeta(DefaultTrafficTreatment.builder()
621 .setOutput(PortNumber.CONTROLLER).build())
622 .fromApp(appId)
Matt Jeanneret3f579262018-06-14 17:16:23 -0400623 .withPriority(10000)
Amit Ghosh95e2f652017-08-23 12:49:46 +0100624 .add(new ObjectiveContext() {
625 @Override
626 public void onSuccess(Objective objective) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700627 log.info("DHCP filter for {} on {} {}.",
628 devId, port, (install) ? "installed" : "removed");
Amit Ghosh95e2f652017-08-23 12:49:46 +0100629 }
630
631 @Override
632 public void onError(Objective objective, ObjectiveError error) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700633 log.info("DHCP filter for {} on {} failed {} because {}",
634 devId, port, (install) ? "installation" : "removal",
635 error);
Amit Ghosh95e2f652017-08-23 12:49:46 +0100636 }
637 });
638
639 flowObjectiveService.filter(devId, dhcpUpstream);
640 }
641
642 private void processIgmpFilteringObjectives(DeviceId devId, PortNumber port, boolean install) {
643 if (!mastershipService.isLocalMaster(devId)) {
644 return;
645 }
646
647 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
648
649 builder = install ? builder.permit() : builder.deny();
650
651 FilteringObjective igmp = builder
652 .withKey(Criteria.matchInPort(port))
653 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
654 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_IGMP))
655 .withMeta(DefaultTrafficTreatment.builder()
656 .setOutput(PortNumber.CONTROLLER).build())
657 .fromApp(appId)
658 .withPriority(10000)
659 .add(new ObjectiveContext() {
660 @Override
661 public void onSuccess(Objective objective) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700662 log.info("Igmp filter for {} on {} {}.",
663 devId, port, (install) ? "installed" : "removed");
Amit Ghosh95e2f652017-08-23 12:49:46 +0100664 }
665
666 @Override
667 public void onError(Objective objective, ObjectiveError error) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700668 log.info("Igmp filter for {} on {} failed {} because {}.",
669 devId, port, (install) ? "installation" : "removal",
670 error);
Amit Ghosh95e2f652017-08-23 12:49:46 +0100671 }
672 });
673
674 flowObjectiveService.filter(devId, igmp);
675 }
676
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100677 /**
Jonathan Hart403372d2018-08-22 11:44:13 -0700678 * Creates trap flows for device, including DHCP and LLDP trap on NNI and
679 * EAPOL trap on the UNIs, if device is present in Sadis config.
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100680 *
681 * @param dev Device to look for
682 */
Jonathan Hart403372d2018-08-22 11:44:13 -0700683 private void checkAndCreateDeviceFlows(Device dev) {
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100684 // we create only for the ones we are master of
685 if (!mastershipService.isLocalMaster(dev.id())) {
686 return;
687 }
688 // check if this device is provisioned in Sadis
689 String devSerialNo = dev.serialNumber();
690 SubscriberAndDeviceInformation deviceInfo = subsService.get(devSerialNo);
Jonathan Hart403372d2018-08-22 11:44:13 -0700691 log.debug("checkAndCreateDeviceFlows: deviceInfo {}", deviceInfo);
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100692
693 if (deviceInfo != null) {
Jonathan Hart403372d2018-08-22 11:44:13 -0700694 // This is an OLT device as per Sadis, we create flows for UNI and NNI ports
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100695 for (Port p : deviceService.getPorts(dev.id())) {
696 if (isUniPort(dev, p)) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700697 processEapolFilteringObjectives(dev.id(), p.number(), true);
Jonathan Hart403372d2018-08-22 11:44:13 -0700698 } else {
699 processNniFilteringObjectives(dev.id(), p.number(), true);
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100700 }
701 }
702 }
703 }
704
Jonathan Hart403372d2018-08-22 11:44:13 -0700705
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100706 /**
707 * Get the uplink for of the OLT device.
708 *
709 * This assumes that the OLT has a single uplink port. When more uplink ports need to be supported
710 * this logic needs to be changed
711 *
712 * @param dev Device to look for
713 * @return The uplink Port of the OLT
714 */
715 private Port getUplinkPort(Device dev) {
716 // check if this device is provisioned in Sadis
717 String devSerialNo = dev.serialNumber();
718 SubscriberAndDeviceInformation deviceInfo = subsService.get(devSerialNo);
719 log.debug("getUplinkPort: deviceInfo {}", deviceInfo);
Saurav Das82b8e6d2018-10-04 15:25:12 -0700720 if (deviceInfo == null) {
721 log.warn("Device {} is not configured in SADIS .. cannot fetch device"
722 + " info", dev.id());
723 return null;
724 }
725 // Return the port that has been configured as the uplink port of this OLT in Sadis
726 for (Port p: deviceService.getPorts(dev.id())) {
727 if (p.number().toLong() == deviceInfo.uplinkPort()) {
728 log.debug("getUplinkPort: Found port {}", p);
729 return p;
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100730 }
731 }
732
Saurav Das82b8e6d2018-10-04 15:25:12 -0700733 log.debug("getUplinkPort: No uplink port found for OLT {}", dev.id());
Amit Ghosh1ed9aef2018-07-17 17:08:16 +0100734 return null;
735 }
736
737 /**
738 * Return the subscriber on a port.
739 *
740 * @param port On which to find the subscriber
741 * @return subscriber if found else null
742 */
743 private SubscriberAndDeviceInformation getSubscriber(ConnectPoint port) {
744 String portName = deviceService.getPort(port).annotations()
745 .value(AnnotationKeys.PORT_NAME);
746
747 return subsService.get(portName);
748 }
749
750 private boolean isUniPort(Device d, Port p) {
751 Port ulPort = getUplinkPort(d);
752 if (ulPort != null) {
753 return (ulPort.number().toLong() != p.number().toLong());
754 }
755 return false;
Jonathan Hart1d34c8b2018-05-05 15:37:28 -0700756 }
757
Jonathan Hart4c538002018-08-23 10:11:54 -0700758 private SubscriberAndDeviceInformation getOltInfo(Device dev) {
759 String devSerialNo = dev.serialNumber();
760 SubscriberAndDeviceInformation deviceInfo = subsService.get(devSerialNo);
761 return deviceInfo;
762 }
763
alshabibf0e7e702015-05-30 18:22:36 -0700764 private class InternalDeviceListener implements DeviceListener {
765 @Override
766 public void event(DeviceEvent event) {
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700767 eventExecutor.execute(() -> {
768 DeviceId devId = event.subject().id();
769 Device dev = event.subject();
Jonathan Hart4c538002018-08-23 10:11:54 -0700770
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700771 if (event.type() == DeviceEvent.Type.PORT_STATS_UPDATED) {
772 return;
773 }
Jonathan Hart4c538002018-08-23 10:11:54 -0700774
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700775 if (getOltInfo(dev) == null) {
776 log.debug("No device info found, this is not an OLT");
777 return;
778 }
Jonathan Hart4c538002018-08-23 10:11:54 -0700779
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700780 log.debug("OLT got {} event for {}", event.type(), event.subject());
Jonathan Hart4c538002018-08-23 10:11:54 -0700781
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700782 switch (event.type()) {
783 //TODO: Port handling and bookkeeping should be improved once
784 // olt firmware handles correct behaviour.
785 case PORT_ADDED:
786 if (isUniPort(dev, event.port())) {
787 post(new AccessDeviceEvent(AccessDeviceEvent.Type.UNI_ADDED, devId, event.port()));
Jonathan Hart4c538002018-08-23 10:11:54 -0700788
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700789 if (event.port().isEnabled()) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700790 processEapolFilteringObjectives(devId, event.port().number(), true);
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700791 }
792 } else {
793 checkAndCreateDeviceFlows(dev);
794 }
795 break;
796 case PORT_REMOVED:
797 if (isUniPort(dev, event.port())) {
798 if (event.port().isEnabled()) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700799 processEapolFilteringObjectives(devId, event.port().number(), false);
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700800 removeSubscriber(new ConnectPoint(devId, event.port().number()));
801 }
802
803 post(new AccessDeviceEvent(AccessDeviceEvent.Type.UNI_REMOVED, devId, event.port()));
804 }
805
806 break;
807 case PORT_UPDATED:
808 if (!isUniPort(dev, event.port())) {
809 break;
810 }
Jonathan Hart1d34c8b2018-05-05 15:37:28 -0700811
812 if (event.port().isEnabled()) {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700813 processEapolFilteringObjectives(devId, event.port().number(), true);
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700814 post(new AccessDeviceEvent(AccessDeviceEvent.Type.UNI_ADDED, devId, event.port()));
815 } else {
Saurav Das82b8e6d2018-10-04 15:25:12 -0700816 processEapolFilteringObjectives(devId, event.port().number(), false);
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700817 post(new AccessDeviceEvent(AccessDeviceEvent.Type.UNI_REMOVED, devId, event.port()));
Jonathan Hart1d34c8b2018-05-05 15:37:28 -0700818 }
alshabibbb83aa22016-02-10 15:08:23 -0800819 break;
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700820 case DEVICE_ADDED:
alshabib7c190012016-02-09 18:22:33 -0800821 post(new AccessDeviceEvent(
822 AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
823 null, null));
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700824
825 // Send UNI_ADDED events for all existing ports
826 deviceService.getPorts(devId).stream()
827 .filter(p -> isUniPort(dev, p))
828 .filter(Port::isEnabled)
829 .forEach(p -> post(new AccessDeviceEvent(
830 AccessDeviceEvent.Type.UNI_ADDED, devId, p)));
831
Jonathan Hart403372d2018-08-22 11:44:13 -0700832 checkAndCreateDeviceFlows(dev);
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700833 break;
834 case DEVICE_REMOVED:
835 deviceService.getPorts(devId).stream()
836 .filter(p -> isUniPort(dev, p))
837 .forEach(p -> post(new AccessDeviceEvent(
838 AccessDeviceEvent.Type.UNI_REMOVED, devId, p)));
839
alshabib7c190012016-02-09 18:22:33 -0800840 post(new AccessDeviceEvent(
841 AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
842 null, null));
Matteo Scandolo632f0fc2018-09-07 12:21:45 -0700843 break;
844 case DEVICE_AVAILABILITY_CHANGED:
845 if (deviceService.isAvailable(devId)) {
846 post(new AccessDeviceEvent(
847 AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
848 null, null));
849 checkAndCreateDeviceFlows(dev);
850 } else {
851 post(new AccessDeviceEvent(
852 AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
853 null, null));
854 }
855 break;
856 case DEVICE_UPDATED:
857 case DEVICE_SUSPENDED:
858 case PORT_STATS_UPDATED:
859 default:
860 return;
861 }
862 });
alshabibf0e7e702015-05-30 18:22:36 -0700863 }
864 }
alshabibf0e7e702015-05-30 18:22:36 -0700865}