blob: 96573f2a74066888ddd235c8b0674a78f78c98b8 [file] [log] [blame]
alshabibf0e7e702015-05-30 18:22:36 -07001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Srikanth Vavilapalli2e684912016-01-16 19:21:59 -080016package org.onosproject.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;
alshabibf0e7e702015-05-30 18:22:36 -070030import org.onosproject.core.ApplicationId;
31import org.onosproject.core.CoreService;
alshabib8e4fd2f2016-01-12 15:55:53 -080032import org.onosproject.event.AbstractListenerManager;
Jonathan Harte533a422015-10-20 17:31:24 -070033import org.onosproject.net.ConnectPoint;
alshabibf0e7e702015-05-30 18:22:36 -070034import org.onosproject.net.DeviceId;
alshabibdec2e252016-01-15 12:20:25 -080035import org.onosproject.net.Port;
alshabibf0e7e702015-05-30 18:22:36 -070036import org.onosproject.net.PortNumber;
Jonathan Harte533a422015-10-20 17:31:24 -070037import org.onosproject.net.config.ConfigFactory;
38import org.onosproject.net.config.NetworkConfigEvent;
39import org.onosproject.net.config.NetworkConfigListener;
40import org.onosproject.net.config.NetworkConfigRegistry;
41import org.onosproject.net.config.basics.SubjectFactories;
alshabibf0e7e702015-05-30 18:22:36 -070042import org.onosproject.net.device.DeviceEvent;
43import org.onosproject.net.device.DeviceListener;
44import org.onosproject.net.device.DeviceService;
45import org.onosproject.net.flow.DefaultTrafficSelector;
46import org.onosproject.net.flow.DefaultTrafficTreatment;
47import org.onosproject.net.flow.TrafficSelector;
48import org.onosproject.net.flow.TrafficTreatment;
alshabibdec2e252016-01-15 12:20:25 -080049import org.onosproject.net.flow.criteria.Criteria;
50import org.onosproject.net.flowobjective.DefaultFilteringObjective;
alshabibf0e7e702015-05-30 18:22:36 -070051import org.onosproject.net.flowobjective.DefaultForwardingObjective;
alshabibdec2e252016-01-15 12:20:25 -080052import org.onosproject.net.flowobjective.FilteringObjective;
alshabibf0e7e702015-05-30 18:22:36 -070053import org.onosproject.net.flowobjective.FlowObjectiveService;
54import org.onosproject.net.flowobjective.ForwardingObjective;
alshabib3ea82642016-01-12 18:06:53 -080055import org.onosproject.net.flowobjective.Objective;
56import org.onosproject.net.flowobjective.ObjectiveContext;
57import org.onosproject.net.flowobjective.ObjectiveError;
alshabib000b6fc2016-02-01 17:25:00 -080058import org.onosproject.olt.AccessDeviceConfig;
59import org.onosproject.olt.AccessDeviceData;
Srikanth Vavilapalli2e684912016-01-16 19:21:59 -080060import org.onosproject.olt.AccessDeviceEvent;
61import org.onosproject.olt.AccessDeviceListener;
62import org.onosproject.olt.AccessDeviceService;
alshabib4ceaed32016-03-03 18:00:58 -080063import org.onosproject.store.serializers.KryoNamespaces;
64import org.onosproject.store.service.Serializer;
65import org.onosproject.store.service.StorageService;
alshabibe0559672016-02-21 14:49:51 -080066import org.osgi.service.component.ComponentContext;
alshabibf0e7e702015-05-30 18:22:36 -070067import org.slf4j.Logger;
68
alshabibe0559672016-02-21 14:49:51 -080069import java.util.Dictionary;
alshabibbb83aa22016-02-10 15:08:23 -080070import java.util.List;
Jonathan Harte533a422015-10-20 17:31:24 -070071import java.util.Map;
Jonathan Hart52998382015-11-10 16:09:22 -080072import java.util.Optional;
alshabibe0559672016-02-21 14:49:51 -080073import java.util.Properties;
alshabib3ea82642016-01-12 18:06:53 -080074import java.util.concurrent.CompletableFuture;
Jonathan Harte533a422015-10-20 17:31:24 -070075import java.util.concurrent.ConcurrentHashMap;
alshabib3ea82642016-01-12 18:06:53 -080076import java.util.concurrent.ExecutorService;
77import java.util.concurrent.Executors;
alshabibf0e7e702015-05-30 18:22:36 -070078
alshabibe0559672016-02-21 14:49:51 -080079import static com.google.common.base.Strings.isNullOrEmpty;
80import static org.onlab.util.Tools.get;
alshabib3ea82642016-01-12 18:06:53 -080081import static org.onlab.util.Tools.groupedThreads;
alshabibf0e7e702015-05-30 18:22:36 -070082import static org.slf4j.LoggerFactory.getLogger;
83
84/**
Jonathan Harte533a422015-10-20 17:31:24 -070085 * Provisions rules on access devices.
alshabibf0e7e702015-05-30 18:22:36 -070086 */
Jonathan Harte533a422015-10-20 17:31:24 -070087@Service
alshabibf0e7e702015-05-30 18:22:36 -070088@Component(immediate = true)
alshabib8e4fd2f2016-01-12 15:55:53 -080089public class Olt
90 extends AbstractListenerManager<AccessDeviceEvent, AccessDeviceListener>
91 implements AccessDeviceService {
alshabibe0559672016-02-21 14:49:51 -080092
93 private static final short DEFAULT_VLAN = 0;
alshabib4ceaed32016-03-03 18:00:58 -080094 private static final String SUBSCRIBERS = "existing-subscribers";
alshabibe0559672016-02-21 14:49:51 -080095
alshabibf0e7e702015-05-30 18:22:36 -070096 private final Logger log = getLogger(getClass());
97
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected FlowObjectiveService flowObjectiveService;
100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected DeviceService deviceService;
103
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected CoreService coreService;
106
Jonathan Harte533a422015-10-20 17:31:24 -0700107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected NetworkConfigRegistry networkConfig;
109
alshabibe0559672016-02-21 14:49:51 -0800110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected ComponentConfigService componentConfigService;
112
alshabib4ceaed32016-03-03 18:00:58 -0800113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
114 protected StorageService storageService;
alshabibe0559672016-02-21 14:49:51 -0800115
116 @Property(name = "defaultVlan", intValue = DEFAULT_VLAN,
117 label = "Default VLAN RG<->ONU traffic")
118 private int defaultVlan = DEFAULT_VLAN;
119
alshabibf0e7e702015-05-30 18:22:36 -0700120 private final DeviceListener deviceListener = new InternalDeviceListener();
121
122 private ApplicationId appId;
123
alshabib3ea82642016-01-12 18:06:53 -0800124 private ExecutorService oltInstallers = Executors.newFixedThreadPool(4,
alshabibbf23a1f2016-01-14 17:27:11 -0800125 groupedThreads("onos/olt-service",
126 "olt-installer-%d"));
alshabib4ae2b402015-06-05 14:55:24 -0700127
Jonathan Harte533a422015-10-20 17:31:24 -0700128 private Map<DeviceId, AccessDeviceData> oltData = new ConcurrentHashMap<>();
129
alshabib4ceaed32016-03-03 18:00:58 -0800130 private Map<ConnectPoint, VlanId> subscribers;
alshabibbf23a1f2016-01-14 17:27:11 -0800131
Jonathan Harte533a422015-10-20 17:31:24 -0700132 private InternalNetworkConfigListener configListener =
133 new InternalNetworkConfigListener();
134 private static final Class<AccessDeviceConfig> CONFIG_CLASS =
135 AccessDeviceConfig.class;
136
137 private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
138 new ConfigFactory<DeviceId, AccessDeviceConfig>(
139 SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
alshabibbf23a1f2016-01-14 17:27:11 -0800140 @Override
141 public AccessDeviceConfig createConfig() {
142 return new AccessDeviceConfig();
143 }
144 };
145
alshabibf0e7e702015-05-30 18:22:36 -0700146
147 @Activate
alshabibe0559672016-02-21 14:49:51 -0800148 public void activate(ComponentContext context) {
149 modified(context);
alshabib4ae2b402015-06-05 14:55:24 -0700150 appId = coreService.registerApplication("org.onosproject.olt");
alshabibe0559672016-02-21 14:49:51 -0800151 componentConfigService.registerProperties(getClass());
alshabibc4dfe852015-06-05 13:35:13 -0700152
alshabib8e4fd2f2016-01-12 15:55:53 -0800153 eventDispatcher.addSink(AccessDeviceEvent.class, listenerRegistry);
154
Jonathan Harte533a422015-10-20 17:31:24 -0700155 networkConfig.registerConfigFactory(configFactory);
156 networkConfig.addListener(configListener);
157
alshabibdec2e252016-01-15 12:20:25 -0800158
Jonathan Harte533a422015-10-20 17:31:24 -0700159 networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
160 subject -> {
161 AccessDeviceConfig config = networkConfig.getConfig(subject, AccessDeviceConfig.class);
162 if (config != null) {
163 AccessDeviceData data = config.getOlt();
164 oltData.put(data.deviceId(), data);
165 }
166 }
167 );
168
alshabibdec2e252016-01-15 12:20:25 -0800169 oltData.keySet().stream()
170 .flatMap(did -> deviceService.getPorts(did).stream())
alshabib62e9ce72016-02-11 17:31:36 -0800171 .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
alshabibdec2e252016-01-15 12:20:25 -0800172 .filter(p -> p.isEnabled())
alshabib50d9fc52016-02-12 15:47:20 -0800173 .forEach(p -> processFilteringObjectives((DeviceId) p.element().id(),
174 p.number(), true));
alshabibdec2e252016-01-15 12:20:25 -0800175
alshabib4ceaed32016-03-03 18:00:58 -0800176 subscribers = storageService.<ConnectPoint, VlanId>consistentMapBuilder()
177 .withName(SUBSCRIBERS)
178 .withSerializer(Serializer.using(KryoNamespaces.API))
179 .build().asJavaMap();
180
alshabibba357492016-01-27 13:49:46 -0800181 deviceService.addListener(deviceListener);
182
alshabibf0e7e702015-05-30 18:22:36 -0700183 log.info("Started with Application ID {}", appId.id());
184 }
185
186 @Deactivate
187 public void deactivate() {
alshabibe0559672016-02-21 14:49:51 -0800188 componentConfigService.unregisterProperties(getClass(), false);
alshabib62e9ce72016-02-11 17:31:36 -0800189 deviceService.removeListener(deviceListener);
Jonathan Harte533a422015-10-20 17:31:24 -0700190 networkConfig.removeListener(configListener);
191 networkConfig.unregisterConfigFactory(configFactory);
alshabibf0e7e702015-05-30 18:22:36 -0700192 log.info("Stopped");
193 }
194
alshabibe0559672016-02-21 14:49:51 -0800195 @Modified
196 public void modified(ComponentContext context) {
197 Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
198
199 try {
200 String s = get(properties, "defaultVlan");
201 defaultVlan = isNullOrEmpty(s) ? DEFAULT_VLAN : Integer.parseInt(s.trim());
202 } catch (Exception e) {
203 defaultVlan = DEFAULT_VLAN;
204 }
205 }
206
alshabib32232c82016-02-25 17:57:24 -0500207 @Override
Jonathan Harte533a422015-10-20 17:31:24 -0700208 public void provisionSubscriber(ConnectPoint port, VlanId vlan) {
209 AccessDeviceData olt = oltData.get(port.deviceId());
210
211 if (olt == null) {
212 log.warn("No data found for OLT device {}", port.deviceId());
213 return;
214 }
215
Jonathan Hart52998382015-11-10 16:09:22 -0800216 provisionVlans(olt.deviceId(), olt.uplink(), port.port(), vlan, olt.vlan(),
alshabibb7a9e172016-01-13 11:23:53 -0800217 olt.defaultVlan());
218 }
219
220 @Override
221 public void removeSubscriber(ConnectPoint port) {
alshabibbf23a1f2016-01-14 17:27:11 -0800222 AccessDeviceData olt = oltData.get(port.deviceId());
223
224 if (olt == null) {
225 log.warn("No data found for OLT device {}", port.deviceId());
226 return;
227 }
228
alshabib4ceaed32016-03-03 18:00:58 -0800229 VlanId subscriberVlan = subscribers.remove(port);
230
231 if (subscriberVlan == null) {
232 log.warn("Unknown subscriber at location {}", port);
233 return;
234 }
235
236 unprovisionSubscriber(olt.deviceId(), olt.uplink(), port.port(), subscriberVlan,
237 olt.vlan(), olt.defaultVlan());
alshabibbf23a1f2016-01-14 17:27:11 -0800238
239 }
240
alshabibe0559672016-02-21 14:49:51 -0800241 @Override
242 public Map<DeviceId, AccessDeviceData> fetchOlts() {
243 return Maps.newHashMap(oltData);
244 }
245
alshabibbf23a1f2016-01-14 17:27:11 -0800246 private void unprovisionSubscriber(DeviceId deviceId, PortNumber uplink,
alshabib4ceaed32016-03-03 18:00:58 -0800247 PortNumber subscriberPort, VlanId subscriberVlan,
248 VlanId deviceVlan, Optional<VlanId> defaultVlan) {
alshabibbf23a1f2016-01-14 17:27:11 -0800249
250 CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
251 CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
252
alshabib4ceaed32016-03-03 18:00:58 -0800253 ForwardingObjective.Builder upFwd = upBuilder(uplink, subscriberPort,
254 subscriberVlan, deviceVlan,
255 defaultVlan);
256 ForwardingObjective.Builder downFwd = downBuilder(uplink, subscriberPort,
257 subscriberVlan, deviceVlan,
258 defaultVlan);
alshabibbf23a1f2016-01-14 17:27:11 -0800259
260
alshabib4ceaed32016-03-03 18:00:58 -0800261 flowObjectiveService.forward(deviceId, upFwd.remove(new ObjectiveContext() {
262 @Override
263 public void onSuccess(Objective objective) {
264 upFuture.complete(null);
265 }
alshabibbf23a1f2016-01-14 17:27:11 -0800266
alshabib4ceaed32016-03-03 18:00:58 -0800267 @Override
268 public void onError(Objective objective, ObjectiveError error) {
269 upFuture.complete(error);
270 }
271 }));
272
273 flowObjectiveService.forward(deviceId, downFwd.remove(new ObjectiveContext() {
274 @Override
275 public void onSuccess(Objective objective) {
276 downFuture.complete(null);
277 }
278
279 @Override
280 public void onError(Objective objective, ObjectiveError error) {
281 downFuture.complete(error);
282 }
283 }));
alshabibbf23a1f2016-01-14 17:27:11 -0800284
285 upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
286 if (upStatus == null && downStatus == null) {
287 post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_UNREGISTERED,
288 deviceId,
289 deviceVlan,
290 subscriberVlan));
291 } else if (downStatus != null) {
292 log.error("Subscriber with vlan {} on device {} " +
293 "on port {} failed downstream uninstallation: {}",
294 subscriberVlan, deviceId, subscriberPort, downStatus);
295 } else if (upStatus != null) {
296 log.error("Subscriber with vlan {} on device {} " +
297 "on port {} failed upstream uninstallation: {}",
298 subscriberVlan, deviceId, subscriberPort, upStatus);
299 }
300 }, oltInstallers);
alshabibb7a9e172016-01-13 11:23:53 -0800301
Jonathan Harte533a422015-10-20 17:31:24 -0700302 }
303
304 private void provisionVlans(DeviceId deviceId, PortNumber uplinkPort,
305 PortNumber subscriberPort,
Jonathan Hart52998382015-11-10 16:09:22 -0800306 VlanId subscriberVlan, VlanId deviceVlan,
307 Optional<VlanId> defaultVlan) {
Jonathan Harte533a422015-10-20 17:31:24 -0700308
alshabib3ea82642016-01-12 18:06:53 -0800309 CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
310 CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
311
alshabib4ceaed32016-03-03 18:00:58 -0800312 ForwardingObjective.Builder upFwd = upBuilder(uplinkPort, subscriberPort,
313 subscriberVlan, deviceVlan,
314 defaultVlan);
Jonathan Harte533a422015-10-20 17:31:24 -0700315
316
alshabib4ceaed32016-03-03 18:00:58 -0800317 ForwardingObjective.Builder downFwd = downBuilder(uplinkPort, subscriberPort,
318 subscriberVlan, deviceVlan,
319 defaultVlan);
alshabib3ea82642016-01-12 18:06:53 -0800320
alshabibbf23a1f2016-01-14 17:27:11 -0800321 ConnectPoint cp = new ConnectPoint(deviceId, subscriberPort);
alshabibbf23a1f2016-01-14 17:27:11 -0800322 subscribers.put(cp, subscriberVlan);
alshabibbf23a1f2016-01-14 17:27:11 -0800323
alshabibbf23a1f2016-01-14 17:27:11 -0800324 flowObjectiveService.forward(deviceId, upFwd.add(new ObjectiveContext() {
325 @Override
326 public void onSuccess(Objective objective) {
327 upFuture.complete(null);
328 }
329
330 @Override
331 public void onError(Objective objective, ObjectiveError error) {
332 upFuture.complete(error);
333 }
334 }));
335
alshabibbf23a1f2016-01-14 17:27:11 -0800336 flowObjectiveService.forward(deviceId, downFwd.add(new ObjectiveContext() {
337 @Override
338 public void onSuccess(Objective objective) {
339 downFuture.complete(null);
340 }
341
342 @Override
343 public void onError(Objective objective, ObjectiveError error) {
344 downFuture.complete(error);
345 }
346 }));
alshabib3ea82642016-01-12 18:06:53 -0800347
348 upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
349 if (upStatus == null && downStatus == null) {
350 post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_REGISTERED,
351 deviceId,
352 deviceVlan,
353 subscriberVlan));
alshabib50d9fc52016-02-12 15:47:20 -0800354
alshabib3ea82642016-01-12 18:06:53 -0800355 } else if (downStatus != null) {
356 log.error("Subscriber with vlan {} on device {} " +
357 "on port {} failed downstream installation: {}",
358 subscriberVlan, deviceId, subscriberPort, downStatus);
359 } else if (upStatus != null) {
360 log.error("Subscriber with vlan {} on device {} " +
361 "on port {} failed upstream installation: {}",
362 subscriberVlan, deviceId, subscriberPort, upStatus);
363 }
364 }, oltInstallers);
365
Jonathan Harte533a422015-10-20 17:31:24 -0700366 }
367
alshabib4ceaed32016-03-03 18:00:58 -0800368 private ForwardingObjective.Builder downBuilder(PortNumber uplinkPort,
369 PortNumber subscriberPort,
370 VlanId subscriberVlan,
371 VlanId deviceVlan,
372 Optional<VlanId> defaultVlan) {
373 TrafficSelector downstream = DefaultTrafficSelector.builder()
374 .matchVlanId(deviceVlan)
375 .matchInPort(uplinkPort)
376 .matchInnerVlanId(subscriberVlan)
377 .build();
378
379 TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
380 .popVlan()
381 .setVlanId(defaultVlan.orElse(VlanId.vlanId((short) this.defaultVlan)))
382 .setOutput(subscriberPort)
383 .build();
384
385 return DefaultForwardingObjective.builder()
386 .withFlag(ForwardingObjective.Flag.VERSATILE)
387 .withPriority(1000)
388 .makePermanent()
389 .withSelector(downstream)
390 .fromApp(appId)
391 .withTreatment(downstreamTreatment);
392 }
393
394 private ForwardingObjective.Builder upBuilder(PortNumber uplinkPort,
395 PortNumber subscriberPort,
396 VlanId subscriberVlan,
397 VlanId deviceVlan,
398 Optional<VlanId> defaultVlan) {
399 TrafficSelector upstream = DefaultTrafficSelector.builder()
400 .matchVlanId(defaultVlan.orElse(VlanId.vlanId((short) this.defaultVlan)))
401 .matchInPort(subscriberPort)
402 .build();
403
404
405 TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
406 .pushVlan()
407 .setVlanId(subscriberVlan)
408 .pushVlan()
409 .setVlanId(deviceVlan)
410 .setOutput(uplinkPort)
411 .build();
412
413 return DefaultForwardingObjective.builder()
414 .withFlag(ForwardingObjective.Flag.VERSATILE)
415 .withPriority(1000)
416 .makePermanent()
417 .withSelector(upstream)
418 .fromApp(appId)
419 .withTreatment(upstreamTreatment);
420 }
421
alshabib50d9fc52016-02-12 15:47:20 -0800422 private void processFilteringObjectives(DeviceId devId, PortNumber port, boolean install) {
alshabibbb83aa22016-02-10 15:08:23 -0800423 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
424
425 FilteringObjective eapol = (install ? builder.permit() : builder.deny())
alshabib50d9fc52016-02-12 15:47:20 -0800426 .withKey(Criteria.matchInPort(port))
alshabibdec2e252016-01-15 12:20:25 -0800427 .addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType()))
428 .withMeta(DefaultTrafficTreatment.builder()
429 .setOutput(PortNumber.CONTROLLER).build())
430 .fromApp(appId)
431 .withPriority(1000)
432 .add(new ObjectiveContext() {
433 @Override
434 public void onSuccess(Objective objective) {
435 log.info("Eapol filter for {} on {} installed.",
436 devId, port);
437 }
438
439 @Override
440 public void onError(Objective objective, ObjectiveError error) {
441 log.info("Eapol filter for {} on {} failed because {}",
442 devId, port, error);
443 }
444 });
445
alshabibdec2e252016-01-15 12:20:25 -0800446 flowObjectiveService.filter(devId, eapol);
alshabib000b6fc2016-02-01 17:25:00 -0800447
alshabibdec2e252016-01-15 12:20:25 -0800448 }
449
alshabibf0e7e702015-05-30 18:22:36 -0700450 private class InternalDeviceListener implements DeviceListener {
451 @Override
452 public void event(DeviceEvent event) {
alshabib3ea82642016-01-12 18:06:53 -0800453 DeviceId devId = event.subject().id();
454 if (!oltData.containsKey(devId)) {
455 log.debug("Device {} is not an OLT", devId);
alshabib8e4fd2f2016-01-12 15:55:53 -0800456 return;
457 }
alshabibf0e7e702015-05-30 18:22:36 -0700458 switch (event.type()) {
alshabibdec2e252016-01-15 12:20:25 -0800459 //TODO: Port handling and bookkeeping should be inproved once
460 // olt firmware handles correct behaviour.
alshabibf0e7e702015-05-30 18:22:36 -0700461 case PORT_ADDED:
alshabibbb83aa22016-02-10 15:08:23 -0800462 if (!oltData.get(devId).uplink().equals(event.port().number()) &&
463 event.port().isEnabled()) {
alshabib50d9fc52016-02-12 15:47:20 -0800464 processFilteringObjectives(devId, event.port().number(), true);
alshabibdec2e252016-01-15 12:20:25 -0800465 }
466 break;
467 case PORT_REMOVED:
468 AccessDeviceData olt = oltData.get(devId);
alshabib4ceaed32016-03-03 18:00:58 -0800469 VlanId vlan = subscribers.get(new ConnectPoint(devId,
470 event.port().number()));
alshabibdec2e252016-01-15 12:20:25 -0800471 unprovisionSubscriber(devId, olt.uplink(),
472 event.port().number(),
alshabib4ceaed32016-03-03 18:00:58 -0800473 vlan, olt.vlan(), olt.defaultVlan());
alshabibbb83aa22016-02-10 15:08:23 -0800474 if (!oltData.get(devId).uplink().equals(event.port().number()) &&
475 event.port().isEnabled()) {
alshabib50d9fc52016-02-12 15:47:20 -0800476 processFilteringObjectives(devId, event.port().number(), false);
alshabibbb83aa22016-02-10 15:08:23 -0800477 }
alshabibdec2e252016-01-15 12:20:25 -0800478 break;
alshabibf0e7e702015-05-30 18:22:36 -0700479 case PORT_UPDATED:
alshabibbb83aa22016-02-10 15:08:23 -0800480 if (oltData.get(devId).uplink().equals(event.port().number())) {
481 break;
482 }
483 if (event.port().isEnabled()) {
alshabib50d9fc52016-02-12 15:47:20 -0800484 processFilteringObjectives(devId, event.port().number(), true);
alshabibbb83aa22016-02-10 15:08:23 -0800485 } else {
alshabib50d9fc52016-02-12 15:47:20 -0800486 processFilteringObjectives(devId, event.port().number(), false);
alshabibbb83aa22016-02-10 15:08:23 -0800487 }
alshabibf0e7e702015-05-30 18:22:36 -0700488 break;
489 case DEVICE_ADDED:
alshabib8e4fd2f2016-01-12 15:55:53 -0800490 post(new AccessDeviceEvent(
491 AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
492 null, null));
alshabibe0559672016-02-21 14:49:51 -0800493 provisionDefaultFlows(devId);
alshabib8e4fd2f2016-01-12 15:55:53 -0800494 break;
alshabibf0e7e702015-05-30 18:22:36 -0700495 case DEVICE_REMOVED:
alshabib8e4fd2f2016-01-12 15:55:53 -0800496 post(new AccessDeviceEvent(
497 AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
498 null, null));
499 break;
alshabib7c190012016-02-09 18:22:33 -0800500 case DEVICE_AVAILABILITY_CHANGED:
501 if (deviceService.isAvailable(devId)) {
502 post(new AccessDeviceEvent(
503 AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
504 null, null));
505 } else {
506 post(new AccessDeviceEvent(
507 AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
508 null, null));
509 }
510 break;
alshabib8e4fd2f2016-01-12 15:55:53 -0800511 case DEVICE_UPDATED:
alshabibf0e7e702015-05-30 18:22:36 -0700512 case DEVICE_SUSPENDED:
alshabibf0e7e702015-05-30 18:22:36 -0700513 case PORT_STATS_UPDATED:
514 default:
515 return;
516 }
517 }
518 }
519
Jonathan Harte533a422015-10-20 17:31:24 -0700520 private class InternalNetworkConfigListener implements NetworkConfigListener {
521 @Override
522 public void event(NetworkConfigEvent event) {
523 switch (event.type()) {
524
alshabibbf23a1f2016-01-14 17:27:11 -0800525 case CONFIG_ADDED:
526 case CONFIG_UPDATED:
alshabibe0559672016-02-21 14:49:51 -0800527
528 AccessDeviceConfig config =
529 networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
530 if (config != null) {
531 oltData.put(config.getOlt().deviceId(), config.getOlt());
532 provisionDefaultFlows((DeviceId) event.subject());
Jonathan Harte533a422015-10-20 17:31:24 -0700533 }
alshabibe0559672016-02-21 14:49:51 -0800534
alshabibbf23a1f2016-01-14 17:27:11 -0800535 break;
alshabibe0559672016-02-21 14:49:51 -0800536 case CONFIG_REGISTERED:
alshabibbf23a1f2016-01-14 17:27:11 -0800537 case CONFIG_UNREGISTERED:
alshabibe0559672016-02-21 14:49:51 -0800538 break;
alshabibbf23a1f2016-01-14 17:27:11 -0800539 case CONFIG_REMOVED:
alshabibe0559672016-02-21 14:49:51 -0800540 oltData.remove(event.subject());
alshabibbf23a1f2016-01-14 17:27:11 -0800541 default:
542 break;
Jonathan Harte533a422015-10-20 17:31:24 -0700543 }
544 }
alshabibe0559672016-02-21 14:49:51 -0800545
546 @Override
547 public boolean isRelevant(NetworkConfigEvent event) {
548 return event.configClass().equals(CONFIG_CLASS);
549 }
Jonathan Harte533a422015-10-20 17:31:24 -0700550 }
alshabibf0e7e702015-05-30 18:22:36 -0700551
alshabibbb83aa22016-02-10 15:08:23 -0800552 private void provisionDefaultFlows(DeviceId deviceId) {
553 List<Port> ports = deviceService.getPorts(deviceId);
554
555 ports.stream()
556 .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
557 .filter(p -> p.isEnabled())
alshabib50d9fc52016-02-12 15:47:20 -0800558 .forEach(p -> processFilteringObjectives((DeviceId) p.element().id(),
559 p.number(), true));
alshabibbb83aa22016-02-10 15:08:23 -0800560
561 }
562
alshabibf0e7e702015-05-30 18:22:36 -0700563}