blob: 06fa724dbd5974ba3c956e19ad2407893c150eee [file] [log] [blame]
alshabibf0e7e702015-05-30 18:22:36 -07001/*
Brian O'Connord4fbd352016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
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
alshabibbf23a1f2016-01-14 17:27:11 -080018import com.google.common.collect.Maps;
alshabibf0e7e702015-05-30 18:22:36 -070019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
alshabibe0559672016-02-21 14:49:51 -080022import org.apache.felix.scr.annotations.Modified;
23import org.apache.felix.scr.annotations.Property;
alshabibf0e7e702015-05-30 18:22:36 -070024import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Harte533a422015-10-20 17:31:24 -070026import org.apache.felix.scr.annotations.Service;
alshabibdec2e252016-01-15 12:20:25 -080027import org.onlab.packet.EthType;
alshabibf0e7e702015-05-30 18:22:36 -070028import org.onlab.packet.VlanId;
alshabibe0559672016-02-21 14:49:51 -080029import org.onosproject.cfg.ComponentConfigService;
alshabibf3a573e2016-06-01 17:39:10 -070030
alshabibf0e7e702015-05-30 18:22:36 -070031import org.onosproject.core.ApplicationId;
32import org.onosproject.core.CoreService;
alshabib8e4fd2f2016-01-12 15:55:53 -080033import org.onosproject.event.AbstractListenerManager;
alshabib09753b52016-03-04 14:55:19 -080034import org.onosproject.mastership.MastershipService;
Jonathan Harte533a422015-10-20 17:31:24 -070035import org.onosproject.net.ConnectPoint;
alshabibf0e7e702015-05-30 18:22:36 -070036import org.onosproject.net.DeviceId;
alshabibdec2e252016-01-15 12:20:25 -080037import org.onosproject.net.Port;
alshabibf0e7e702015-05-30 18:22:36 -070038import org.onosproject.net.PortNumber;
alshabibf3a573e2016-06-01 17:39:10 -070039
Jonathan Harte533a422015-10-20 17:31:24 -070040import org.onosproject.net.config.ConfigFactory;
41import org.onosproject.net.config.NetworkConfigEvent;
42import org.onosproject.net.config.NetworkConfigListener;
43import org.onosproject.net.config.NetworkConfigRegistry;
44import org.onosproject.net.config.basics.SubjectFactories;
alshabibf0e7e702015-05-30 18:22:36 -070045import org.onosproject.net.device.DeviceEvent;
46import org.onosproject.net.device.DeviceListener;
47import org.onosproject.net.device.DeviceService;
48import org.onosproject.net.flow.DefaultTrafficSelector;
49import org.onosproject.net.flow.DefaultTrafficTreatment;
50import org.onosproject.net.flow.TrafficSelector;
51import org.onosproject.net.flow.TrafficTreatment;
alshabibdec2e252016-01-15 12:20:25 -080052import org.onosproject.net.flow.criteria.Criteria;
53import org.onosproject.net.flowobjective.DefaultFilteringObjective;
alshabibf0e7e702015-05-30 18:22:36 -070054import org.onosproject.net.flowobjective.DefaultForwardingObjective;
alshabibdec2e252016-01-15 12:20:25 -080055import org.onosproject.net.flowobjective.FilteringObjective;
alshabibf0e7e702015-05-30 18:22:36 -070056import org.onosproject.net.flowobjective.FlowObjectiveService;
57import org.onosproject.net.flowobjective.ForwardingObjective;
alshabib3ea82642016-01-12 18:06:53 -080058import org.onosproject.net.flowobjective.Objective;
59import org.onosproject.net.flowobjective.ObjectiveContext;
60import org.onosproject.net.flowobjective.ObjectiveError;
alshabibf3a573e2016-06-01 17:39:10 -070061import org.opencord.cordconfig.access.AccessDeviceConfig;
62import org.opencord.cordconfig.access.AccessDeviceData;
alshabib36a4d732016-06-01 16:03:59 -070063import org.opencord.olt.AccessDeviceEvent;
64import org.opencord.olt.AccessDeviceListener;
65import org.opencord.olt.AccessDeviceService;
alshabib4ceaed32016-03-03 18:00:58 -080066import org.onosproject.store.serializers.KryoNamespaces;
67import org.onosproject.store.service.Serializer;
68import org.onosproject.store.service.StorageService;
alshabibe0559672016-02-21 14:49:51 -080069import org.osgi.service.component.ComponentContext;
alshabibf0e7e702015-05-30 18:22:36 -070070import org.slf4j.Logger;
71
Jonathan Hartfd6c1b32016-03-08 14:09:09 -080072import java.util.Collection;
alshabibe0559672016-02-21 14:49:51 -080073import java.util.Dictionary;
alshabibbb83aa22016-02-10 15:08:23 -080074import java.util.List;
Jonathan Harte533a422015-10-20 17:31:24 -070075import java.util.Map;
Jonathan Hart52998382015-11-10 16:09:22 -080076import java.util.Optional;
alshabibe0559672016-02-21 14:49:51 -080077import java.util.Properties;
alshabib3ea82642016-01-12 18:06:53 -080078import java.util.concurrent.CompletableFuture;
Jonathan Harte533a422015-10-20 17:31:24 -070079import java.util.concurrent.ConcurrentHashMap;
alshabib3ea82642016-01-12 18:06:53 -080080import java.util.concurrent.ExecutorService;
81import java.util.concurrent.Executors;
alshabibf0e7e702015-05-30 18:22:36 -070082
alshabibe0559672016-02-21 14:49:51 -080083import static com.google.common.base.Strings.isNullOrEmpty;
84import static org.onlab.util.Tools.get;
alshabib3ea82642016-01-12 18:06:53 -080085import static org.onlab.util.Tools.groupedThreads;
alshabibf0e7e702015-05-30 18:22:36 -070086import static org.slf4j.LoggerFactory.getLogger;
87
88/**
Jonathan Harte533a422015-10-20 17:31:24 -070089 * Provisions rules on access devices.
alshabibf0e7e702015-05-30 18:22:36 -070090 */
Jonathan Harte533a422015-10-20 17:31:24 -070091@Service
alshabibf0e7e702015-05-30 18:22:36 -070092@Component(immediate = true)
alshabib8e4fd2f2016-01-12 15:55:53 -080093public class Olt
94 extends AbstractListenerManager<AccessDeviceEvent, AccessDeviceListener>
95 implements AccessDeviceService {
alshabibe0559672016-02-21 14:49:51 -080096
97 private static final short DEFAULT_VLAN = 0;
alshabib4ceaed32016-03-03 18:00:58 -080098 private static final String SUBSCRIBERS = "existing-subscribers";
alshabibe0559672016-02-21 14:49:51 -080099
alshabibf0e7e702015-05-30 18:22:36 -0700100 private final Logger log = getLogger(getClass());
101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected FlowObjectiveService flowObjectiveService;
104
105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabib09753b52016-03-04 14:55:19 -0800106 protected MastershipService mastershipService;
107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabibf0e7e702015-05-30 18:22:36 -0700109 protected DeviceService deviceService;
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected CoreService coreService;
113
Jonathan Harte533a422015-10-20 17:31:24 -0700114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 protected NetworkConfigRegistry networkConfig;
116
alshabibe0559672016-02-21 14:49:51 -0800117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected ComponentConfigService componentConfigService;
119
alshabib4ceaed32016-03-03 18:00:58 -0800120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 protected StorageService storageService;
alshabibe0559672016-02-21 14:49:51 -0800122
123 @Property(name = "defaultVlan", intValue = DEFAULT_VLAN,
124 label = "Default VLAN RG<->ONU traffic")
125 private int defaultVlan = DEFAULT_VLAN;
126
alshabibf0e7e702015-05-30 18:22:36 -0700127 private final DeviceListener deviceListener = new InternalDeviceListener();
128
129 private ApplicationId appId;
130
alshabib3ea82642016-01-12 18:06:53 -0800131 private ExecutorService oltInstallers = Executors.newFixedThreadPool(4,
alshabibbf23a1f2016-01-14 17:27:11 -0800132 groupedThreads("onos/olt-service",
133 "olt-installer-%d"));
alshabib4ae2b402015-06-05 14:55:24 -0700134
Jonathan Harte533a422015-10-20 17:31:24 -0700135 private Map<DeviceId, AccessDeviceData> oltData = new ConcurrentHashMap<>();
136
alshabib4ceaed32016-03-03 18:00:58 -0800137 private Map<ConnectPoint, VlanId> subscribers;
alshabibbf23a1f2016-01-14 17:27:11 -0800138
Jonathan Harte533a422015-10-20 17:31:24 -0700139 private InternalNetworkConfigListener configListener =
140 new InternalNetworkConfigListener();
141 private static final Class<AccessDeviceConfig> CONFIG_CLASS =
142 AccessDeviceConfig.class;
143
144 private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
145 new ConfigFactory<DeviceId, AccessDeviceConfig>(
146 SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
alshabibbf23a1f2016-01-14 17:27:11 -0800147 @Override
148 public AccessDeviceConfig createConfig() {
149 return new AccessDeviceConfig();
150 }
151 };
152
alshabibf0e7e702015-05-30 18:22:36 -0700153
154 @Activate
alshabibe0559672016-02-21 14:49:51 -0800155 public void activate(ComponentContext context) {
156 modified(context);
alshabib4ae2b402015-06-05 14:55:24 -0700157 appId = coreService.registerApplication("org.onosproject.olt");
alshabibe0559672016-02-21 14:49:51 -0800158 componentConfigService.registerProperties(getClass());
alshabibc4dfe852015-06-05 13:35:13 -0700159
alshabib8e4fd2f2016-01-12 15:55:53 -0800160 eventDispatcher.addSink(AccessDeviceEvent.class, listenerRegistry);
161
Jonathan Harte533a422015-10-20 17:31:24 -0700162 networkConfig.registerConfigFactory(configFactory);
163 networkConfig.addListener(configListener);
164
alshabibdec2e252016-01-15 12:20:25 -0800165
Jonathan Harte533a422015-10-20 17:31:24 -0700166 networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
167 subject -> {
168 AccessDeviceConfig config = networkConfig.getConfig(subject, AccessDeviceConfig.class);
169 if (config != null) {
170 AccessDeviceData data = config.getOlt();
171 oltData.put(data.deviceId(), data);
172 }
173 }
174 );
175
alshabibdec2e252016-01-15 12:20:25 -0800176 oltData.keySet().stream()
177 .flatMap(did -> deviceService.getPorts(did).stream())
alshabib62e9ce72016-02-11 17:31:36 -0800178 .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
alshabibdec2e252016-01-15 12:20:25 -0800179 .filter(p -> p.isEnabled())
alshabib50d9fc52016-02-12 15:47:20 -0800180 .forEach(p -> processFilteringObjectives((DeviceId) p.element().id(),
181 p.number(), true));
alshabibdec2e252016-01-15 12:20:25 -0800182
alshabib4ceaed32016-03-03 18:00:58 -0800183 subscribers = storageService.<ConnectPoint, VlanId>consistentMapBuilder()
184 .withName(SUBSCRIBERS)
185 .withSerializer(Serializer.using(KryoNamespaces.API))
186 .build().asJavaMap();
187
alshabibba357492016-01-27 13:49:46 -0800188 deviceService.addListener(deviceListener);
189
alshabibf0e7e702015-05-30 18:22:36 -0700190 log.info("Started with Application ID {}", appId.id());
191 }
192
193 @Deactivate
194 public void deactivate() {
alshabibe0559672016-02-21 14:49:51 -0800195 componentConfigService.unregisterProperties(getClass(), false);
alshabib62e9ce72016-02-11 17:31:36 -0800196 deviceService.removeListener(deviceListener);
Jonathan Harte533a422015-10-20 17:31:24 -0700197 networkConfig.removeListener(configListener);
198 networkConfig.unregisterConfigFactory(configFactory);
alshabibf0e7e702015-05-30 18:22:36 -0700199 log.info("Stopped");
200 }
201
alshabibe0559672016-02-21 14:49:51 -0800202 @Modified
203 public void modified(ComponentContext context) {
204 Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
205
206 try {
207 String s = get(properties, "defaultVlan");
208 defaultVlan = isNullOrEmpty(s) ? DEFAULT_VLAN : Integer.parseInt(s.trim());
209 } catch (Exception e) {
210 defaultVlan = DEFAULT_VLAN;
211 }
212 }
213
alshabib32232c82016-02-25 17:57:24 -0500214 @Override
Jonathan Harte533a422015-10-20 17:31:24 -0700215 public void provisionSubscriber(ConnectPoint port, VlanId vlan) {
216 AccessDeviceData olt = oltData.get(port.deviceId());
217
218 if (olt == null) {
219 log.warn("No data found for OLT device {}", port.deviceId());
220 return;
221 }
222
Jonathan Hart52998382015-11-10 16:09:22 -0800223 provisionVlans(olt.deviceId(), olt.uplink(), port.port(), vlan, olt.vlan(),
alshabibb7a9e172016-01-13 11:23:53 -0800224 olt.defaultVlan());
225 }
226
227 @Override
228 public void removeSubscriber(ConnectPoint port) {
alshabibbf23a1f2016-01-14 17:27:11 -0800229 AccessDeviceData olt = oltData.get(port.deviceId());
230
231 if (olt == null) {
232 log.warn("No data found for OLT device {}", port.deviceId());
233 return;
234 }
235
alshabib4ceaed32016-03-03 18:00:58 -0800236 VlanId subscriberVlan = subscribers.remove(port);
237
238 if (subscriberVlan == null) {
239 log.warn("Unknown subscriber at location {}", port);
240 return;
241 }
242
243 unprovisionSubscriber(olt.deviceId(), olt.uplink(), port.port(), subscriberVlan,
244 olt.vlan(), olt.defaultVlan());
alshabibbf23a1f2016-01-14 17:27:11 -0800245
246 }
247
alshabibe0559672016-02-21 14:49:51 -0800248 @Override
Jonathan Hartfd6c1b32016-03-08 14:09:09 -0800249 public Collection<Map.Entry<ConnectPoint, VlanId>> getSubscribers() {
250 return subscribers.entrySet();
251 }
252
253 @Override
alshabibe0559672016-02-21 14:49:51 -0800254 public Map<DeviceId, AccessDeviceData> fetchOlts() {
255 return Maps.newHashMap(oltData);
256 }
257
alshabibbf23a1f2016-01-14 17:27:11 -0800258 private void unprovisionSubscriber(DeviceId deviceId, PortNumber uplink,
alshabib4ceaed32016-03-03 18:00:58 -0800259 PortNumber subscriberPort, VlanId subscriberVlan,
260 VlanId deviceVlan, Optional<VlanId> defaultVlan) {
alshabibbf23a1f2016-01-14 17:27:11 -0800261
262 CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
263 CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
264
alshabib4ceaed32016-03-03 18:00:58 -0800265 ForwardingObjective.Builder upFwd = upBuilder(uplink, subscriberPort,
266 subscriberVlan, deviceVlan,
267 defaultVlan);
268 ForwardingObjective.Builder downFwd = downBuilder(uplink, subscriberPort,
269 subscriberVlan, deviceVlan,
270 defaultVlan);
alshabibbf23a1f2016-01-14 17:27:11 -0800271
272
alshabib4ceaed32016-03-03 18:00:58 -0800273 flowObjectiveService.forward(deviceId, upFwd.remove(new ObjectiveContext() {
274 @Override
275 public void onSuccess(Objective objective) {
276 upFuture.complete(null);
277 }
alshabibbf23a1f2016-01-14 17:27:11 -0800278
alshabib4ceaed32016-03-03 18:00:58 -0800279 @Override
280 public void onError(Objective objective, ObjectiveError error) {
281 upFuture.complete(error);
282 }
283 }));
284
285 flowObjectiveService.forward(deviceId, downFwd.remove(new ObjectiveContext() {
286 @Override
287 public void onSuccess(Objective objective) {
288 downFuture.complete(null);
289 }
290
291 @Override
292 public void onError(Objective objective, ObjectiveError error) {
293 downFuture.complete(error);
294 }
295 }));
alshabibbf23a1f2016-01-14 17:27:11 -0800296
297 upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
298 if (upStatus == null && downStatus == null) {
299 post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_UNREGISTERED,
300 deviceId,
301 deviceVlan,
302 subscriberVlan));
303 } else if (downStatus != null) {
304 log.error("Subscriber with vlan {} on device {} " +
305 "on port {} failed downstream uninstallation: {}",
306 subscriberVlan, deviceId, subscriberPort, downStatus);
307 } else if (upStatus != null) {
308 log.error("Subscriber with vlan {} on device {} " +
309 "on port {} failed upstream uninstallation: {}",
310 subscriberVlan, deviceId, subscriberPort, upStatus);
311 }
312 }, oltInstallers);
alshabibb7a9e172016-01-13 11:23:53 -0800313
Jonathan Harte533a422015-10-20 17:31:24 -0700314 }
315
316 private void provisionVlans(DeviceId deviceId, PortNumber uplinkPort,
317 PortNumber subscriberPort,
Jonathan Hart52998382015-11-10 16:09:22 -0800318 VlanId subscriberVlan, VlanId deviceVlan,
319 Optional<VlanId> defaultVlan) {
Jonathan Harte533a422015-10-20 17:31:24 -0700320
alshabib3ea82642016-01-12 18:06:53 -0800321 CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
322 CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
323
alshabib4ceaed32016-03-03 18:00:58 -0800324 ForwardingObjective.Builder upFwd = upBuilder(uplinkPort, subscriberPort,
325 subscriberVlan, deviceVlan,
326 defaultVlan);
Jonathan Harte533a422015-10-20 17:31:24 -0700327
328
alshabib4ceaed32016-03-03 18:00:58 -0800329 ForwardingObjective.Builder downFwd = downBuilder(uplinkPort, subscriberPort,
330 subscriberVlan, deviceVlan,
331 defaultVlan);
alshabib3ea82642016-01-12 18:06:53 -0800332
alshabibbf23a1f2016-01-14 17:27:11 -0800333 ConnectPoint cp = new ConnectPoint(deviceId, subscriberPort);
alshabibbf23a1f2016-01-14 17:27:11 -0800334 subscribers.put(cp, subscriberVlan);
alshabibbf23a1f2016-01-14 17:27:11 -0800335
alshabibbf23a1f2016-01-14 17:27:11 -0800336 flowObjectiveService.forward(deviceId, upFwd.add(new ObjectiveContext() {
337 @Override
338 public void onSuccess(Objective objective) {
339 upFuture.complete(null);
340 }
341
342 @Override
343 public void onError(Objective objective, ObjectiveError error) {
344 upFuture.complete(error);
345 }
346 }));
347
alshabibbf23a1f2016-01-14 17:27:11 -0800348 flowObjectiveService.forward(deviceId, downFwd.add(new ObjectiveContext() {
349 @Override
350 public void onSuccess(Objective objective) {
351 downFuture.complete(null);
352 }
353
354 @Override
355 public void onError(Objective objective, ObjectiveError error) {
356 downFuture.complete(error);
357 }
358 }));
alshabib3ea82642016-01-12 18:06:53 -0800359
360 upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
361 if (upStatus == null && downStatus == null) {
362 post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_REGISTERED,
363 deviceId,
364 deviceVlan,
365 subscriberVlan));
alshabib50d9fc52016-02-12 15:47:20 -0800366
alshabib3ea82642016-01-12 18:06:53 -0800367 } else if (downStatus != null) {
368 log.error("Subscriber with vlan {} on device {} " +
369 "on port {} failed downstream installation: {}",
370 subscriberVlan, deviceId, subscriberPort, downStatus);
371 } else if (upStatus != null) {
372 log.error("Subscriber with vlan {} on device {} " +
373 "on port {} failed upstream installation: {}",
374 subscriberVlan, deviceId, subscriberPort, upStatus);
375 }
376 }, oltInstallers);
377
Jonathan Harte533a422015-10-20 17:31:24 -0700378 }
379
alshabib4ceaed32016-03-03 18:00:58 -0800380 private ForwardingObjective.Builder downBuilder(PortNumber uplinkPort,
381 PortNumber subscriberPort,
382 VlanId subscriberVlan,
383 VlanId deviceVlan,
384 Optional<VlanId> defaultVlan) {
385 TrafficSelector downstream = DefaultTrafficSelector.builder()
386 .matchVlanId(deviceVlan)
387 .matchInPort(uplinkPort)
388 .matchInnerVlanId(subscriberVlan)
389 .build();
390
391 TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
392 .popVlan()
393 .setVlanId(defaultVlan.orElse(VlanId.vlanId((short) this.defaultVlan)))
394 .setOutput(subscriberPort)
395 .build();
396
397 return DefaultForwardingObjective.builder()
398 .withFlag(ForwardingObjective.Flag.VERSATILE)
399 .withPriority(1000)
400 .makePermanent()
401 .withSelector(downstream)
402 .fromApp(appId)
403 .withTreatment(downstreamTreatment);
404 }
405
406 private ForwardingObjective.Builder upBuilder(PortNumber uplinkPort,
407 PortNumber subscriberPort,
408 VlanId subscriberVlan,
409 VlanId deviceVlan,
410 Optional<VlanId> defaultVlan) {
411 TrafficSelector upstream = DefaultTrafficSelector.builder()
412 .matchVlanId(defaultVlan.orElse(VlanId.vlanId((short) this.defaultVlan)))
413 .matchInPort(subscriberPort)
414 .build();
415
416
417 TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
418 .pushVlan()
419 .setVlanId(subscriberVlan)
420 .pushVlan()
421 .setVlanId(deviceVlan)
422 .setOutput(uplinkPort)
423 .build();
424
425 return DefaultForwardingObjective.builder()
426 .withFlag(ForwardingObjective.Flag.VERSATILE)
427 .withPriority(1000)
428 .makePermanent()
429 .withSelector(upstream)
430 .fromApp(appId)
431 .withTreatment(upstreamTreatment);
432 }
433
alshabib50d9fc52016-02-12 15:47:20 -0800434 private void processFilteringObjectives(DeviceId devId, PortNumber port, boolean install) {
alshabib09753b52016-03-04 14:55:19 -0800435 if (!mastershipService.isLocalMaster(devId)) {
436 return;
437 }
alshabibbb83aa22016-02-10 15:08:23 -0800438 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
439
440 FilteringObjective eapol = (install ? builder.permit() : builder.deny())
alshabib50d9fc52016-02-12 15:47:20 -0800441 .withKey(Criteria.matchInPort(port))
alshabibdec2e252016-01-15 12:20:25 -0800442 .addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType()))
443 .withMeta(DefaultTrafficTreatment.builder()
444 .setOutput(PortNumber.CONTROLLER).build())
445 .fromApp(appId)
446 .withPriority(1000)
447 .add(new ObjectiveContext() {
448 @Override
449 public void onSuccess(Objective objective) {
450 log.info("Eapol filter for {} on {} installed.",
451 devId, port);
452 }
453
454 @Override
455 public void onError(Objective objective, ObjectiveError error) {
456 log.info("Eapol filter for {} on {} failed because {}",
457 devId, port, error);
458 }
459 });
460
alshabibdec2e252016-01-15 12:20:25 -0800461 flowObjectiveService.filter(devId, eapol);
alshabib000b6fc2016-02-01 17:25:00 -0800462
alshabibdec2e252016-01-15 12:20:25 -0800463 }
464
alshabibf0e7e702015-05-30 18:22:36 -0700465 private class InternalDeviceListener implements DeviceListener {
466 @Override
467 public void event(DeviceEvent event) {
alshabib3ea82642016-01-12 18:06:53 -0800468 DeviceId devId = event.subject().id();
469 if (!oltData.containsKey(devId)) {
alshabib8e4fd2f2016-01-12 15:55:53 -0800470 return;
471 }
alshabibf0e7e702015-05-30 18:22:36 -0700472 switch (event.type()) {
Jonathan Hartfd6c1b32016-03-08 14:09:09 -0800473 //TODO: Port handling and bookkeeping should be improved once
alshabibdec2e252016-01-15 12:20:25 -0800474 // olt firmware handles correct behaviour.
alshabibf0e7e702015-05-30 18:22:36 -0700475 case PORT_ADDED:
alshabibbb83aa22016-02-10 15:08:23 -0800476 if (!oltData.get(devId).uplink().equals(event.port().number()) &&
477 event.port().isEnabled()) {
alshabib50d9fc52016-02-12 15:47:20 -0800478 processFilteringObjectives(devId, event.port().number(), true);
alshabibdec2e252016-01-15 12:20:25 -0800479 }
480 break;
481 case PORT_REMOVED:
482 AccessDeviceData olt = oltData.get(devId);
alshabib4ceaed32016-03-03 18:00:58 -0800483 VlanId vlan = subscribers.get(new ConnectPoint(devId,
484 event.port().number()));
alshabibdec2e252016-01-15 12:20:25 -0800485 unprovisionSubscriber(devId, olt.uplink(),
486 event.port().number(),
alshabib4ceaed32016-03-03 18:00:58 -0800487 vlan, olt.vlan(), olt.defaultVlan());
alshabibbb83aa22016-02-10 15:08:23 -0800488 if (!oltData.get(devId).uplink().equals(event.port().number()) &&
489 event.port().isEnabled()) {
alshabib50d9fc52016-02-12 15:47:20 -0800490 processFilteringObjectives(devId, event.port().number(), false);
alshabibbb83aa22016-02-10 15:08:23 -0800491 }
alshabibdec2e252016-01-15 12:20:25 -0800492 break;
alshabibf0e7e702015-05-30 18:22:36 -0700493 case PORT_UPDATED:
alshabibbb83aa22016-02-10 15:08:23 -0800494 if (oltData.get(devId).uplink().equals(event.port().number())) {
495 break;
496 }
497 if (event.port().isEnabled()) {
alshabib50d9fc52016-02-12 15:47:20 -0800498 processFilteringObjectives(devId, event.port().number(), true);
alshabibbb83aa22016-02-10 15:08:23 -0800499 } else {
alshabib50d9fc52016-02-12 15:47:20 -0800500 processFilteringObjectives(devId, event.port().number(), false);
alshabibbb83aa22016-02-10 15:08:23 -0800501 }
alshabibf0e7e702015-05-30 18:22:36 -0700502 break;
503 case DEVICE_ADDED:
alshabib8e4fd2f2016-01-12 15:55:53 -0800504 post(new AccessDeviceEvent(
505 AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
506 null, null));
alshabibe0559672016-02-21 14:49:51 -0800507 provisionDefaultFlows(devId);
alshabib8e4fd2f2016-01-12 15:55:53 -0800508 break;
alshabibf0e7e702015-05-30 18:22:36 -0700509 case DEVICE_REMOVED:
alshabib8e4fd2f2016-01-12 15:55:53 -0800510 post(new AccessDeviceEvent(
511 AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
512 null, null));
513 break;
alshabib7c190012016-02-09 18:22:33 -0800514 case DEVICE_AVAILABILITY_CHANGED:
515 if (deviceService.isAvailable(devId)) {
516 post(new AccessDeviceEvent(
517 AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
518 null, null));
519 } else {
520 post(new AccessDeviceEvent(
521 AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
522 null, null));
523 }
524 break;
alshabib8e4fd2f2016-01-12 15:55:53 -0800525 case DEVICE_UPDATED:
alshabibf0e7e702015-05-30 18:22:36 -0700526 case DEVICE_SUSPENDED:
alshabibf0e7e702015-05-30 18:22:36 -0700527 case PORT_STATS_UPDATED:
528 default:
529 return;
530 }
531 }
532 }
533
Jonathan Harte533a422015-10-20 17:31:24 -0700534 private class InternalNetworkConfigListener implements NetworkConfigListener {
535 @Override
536 public void event(NetworkConfigEvent event) {
537 switch (event.type()) {
538
alshabibbf23a1f2016-01-14 17:27:11 -0800539 case CONFIG_ADDED:
540 case CONFIG_UPDATED:
alshabibe0559672016-02-21 14:49:51 -0800541
542 AccessDeviceConfig config =
543 networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
544 if (config != null) {
545 oltData.put(config.getOlt().deviceId(), config.getOlt());
546 provisionDefaultFlows((DeviceId) event.subject());
Jonathan Harte533a422015-10-20 17:31:24 -0700547 }
alshabibe0559672016-02-21 14:49:51 -0800548
alshabibbf23a1f2016-01-14 17:27:11 -0800549 break;
alshabibe0559672016-02-21 14:49:51 -0800550 case CONFIG_REGISTERED:
alshabibbf23a1f2016-01-14 17:27:11 -0800551 case CONFIG_UNREGISTERED:
alshabibe0559672016-02-21 14:49:51 -0800552 break;
alshabibbf23a1f2016-01-14 17:27:11 -0800553 case CONFIG_REMOVED:
alshabibe0559672016-02-21 14:49:51 -0800554 oltData.remove(event.subject());
alshabibbf23a1f2016-01-14 17:27:11 -0800555 default:
556 break;
Jonathan Harte533a422015-10-20 17:31:24 -0700557 }
558 }
alshabibe0559672016-02-21 14:49:51 -0800559
560 @Override
561 public boolean isRelevant(NetworkConfigEvent event) {
562 return event.configClass().equals(CONFIG_CLASS);
563 }
Jonathan Harte533a422015-10-20 17:31:24 -0700564 }
alshabibf0e7e702015-05-30 18:22:36 -0700565
alshabibbb83aa22016-02-10 15:08:23 -0800566 private void provisionDefaultFlows(DeviceId deviceId) {
alshabib09753b52016-03-04 14:55:19 -0800567 if (!mastershipService.isLocalMaster(deviceId)) {
568 return;
569 }
alshabibbb83aa22016-02-10 15:08:23 -0800570 List<Port> ports = deviceService.getPorts(deviceId);
571
572 ports.stream()
573 .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
574 .filter(p -> p.isEnabled())
alshabib50d9fc52016-02-12 15:47:20 -0800575 .forEach(p -> processFilteringObjectives((DeviceId) p.element().id(),
576 p.number(), true));
alshabibbb83aa22016-02-10 15:08:23 -0800577
578 }
579
alshabibf0e7e702015-05-30 18:22:36 -0700580}