blob: 976fcaa03b8e327cd549f920626e324547505b7e [file] [log] [blame]
alshabib0ccde6d2015-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 Vavilapalli0d21dd12016-01-16 19:21:59 -080016package org.onosproject.olt.impl;
alshabib0ccde6d2015-05-30 18:22:36 -070017
alshabib02cbe6a2016-01-14 17:27:11 -080018import com.google.common.collect.Maps;
alshabib0ccde6d2015-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;
alshabibf544c012016-02-21 14:49:51 -080022import org.apache.felix.scr.annotations.Modified;
23import org.apache.felix.scr.annotations.Property;
alshabib0ccde6d2015-05-30 18:22:36 -070024import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Hart3e594642015-10-20 17:31:24 -070026import org.apache.felix.scr.annotations.Service;
alshabibbb424232016-01-15 12:20:25 -080027import org.onlab.packet.EthType;
alshabib0ccde6d2015-05-30 18:22:36 -070028import org.onlab.packet.VlanId;
alshabibf544c012016-02-21 14:49:51 -080029import org.onosproject.cfg.ComponentConfigService;
alshabib0ccde6d2015-05-30 18:22:36 -070030import org.onosproject.core.ApplicationId;
31import org.onosproject.core.CoreService;
alshabib6b139b42016-01-12 15:55:53 -080032import org.onosproject.event.AbstractListenerManager;
alshabibfe1ffee2016-03-04 14:55:19 -080033import org.onosproject.mastership.MastershipService;
Jonathan Hart3e594642015-10-20 17:31:24 -070034import org.onosproject.net.ConnectPoint;
alshabib0ccde6d2015-05-30 18:22:36 -070035import org.onosproject.net.DeviceId;
alshabibbb424232016-01-15 12:20:25 -080036import org.onosproject.net.Port;
alshabib0ccde6d2015-05-30 18:22:36 -070037import org.onosproject.net.PortNumber;
Jonathan Hart3e594642015-10-20 17:31:24 -070038import org.onosproject.net.config.ConfigFactory;
39import org.onosproject.net.config.NetworkConfigEvent;
40import org.onosproject.net.config.NetworkConfigListener;
41import org.onosproject.net.config.NetworkConfigRegistry;
42import org.onosproject.net.config.basics.SubjectFactories;
alshabib0ccde6d2015-05-30 18:22:36 -070043import org.onosproject.net.device.DeviceEvent;
44import org.onosproject.net.device.DeviceListener;
45import org.onosproject.net.device.DeviceService;
46import org.onosproject.net.flow.DefaultTrafficSelector;
47import org.onosproject.net.flow.DefaultTrafficTreatment;
48import org.onosproject.net.flow.TrafficSelector;
49import org.onosproject.net.flow.TrafficTreatment;
alshabibbb424232016-01-15 12:20:25 -080050import org.onosproject.net.flow.criteria.Criteria;
51import org.onosproject.net.flowobjective.DefaultFilteringObjective;
alshabib0ccde6d2015-05-30 18:22:36 -070052import org.onosproject.net.flowobjective.DefaultForwardingObjective;
alshabibbb424232016-01-15 12:20:25 -080053import org.onosproject.net.flowobjective.FilteringObjective;
alshabib0ccde6d2015-05-30 18:22:36 -070054import org.onosproject.net.flowobjective.FlowObjectiveService;
55import org.onosproject.net.flowobjective.ForwardingObjective;
alshabib49cadbd2016-01-12 18:06:53 -080056import org.onosproject.net.flowobjective.Objective;
57import org.onosproject.net.flowobjective.ObjectiveContext;
58import org.onosproject.net.flowobjective.ObjectiveError;
alshabib03adb492016-02-01 17:25:00 -080059import org.onosproject.olt.AccessDeviceConfig;
60import org.onosproject.olt.AccessDeviceData;
Srikanth Vavilapalli0d21dd12016-01-16 19:21:59 -080061import org.onosproject.olt.AccessDeviceEvent;
62import org.onosproject.olt.AccessDeviceListener;
63import org.onosproject.olt.AccessDeviceService;
alshabib6cb86362016-03-03 18:00:58 -080064import org.onosproject.store.serializers.KryoNamespaces;
65import org.onosproject.store.service.Serializer;
66import org.onosproject.store.service.StorageService;
alshabibf544c012016-02-21 14:49:51 -080067import org.osgi.service.component.ComponentContext;
alshabib0ccde6d2015-05-30 18:22:36 -070068import org.slf4j.Logger;
69
alshabibf544c012016-02-21 14:49:51 -080070import java.util.Dictionary;
alshabib8f8060d2016-02-10 15:08:23 -080071import java.util.List;
Jonathan Hart3e594642015-10-20 17:31:24 -070072import java.util.Map;
Jonathan Hart48327842015-11-10 16:09:22 -080073import java.util.Optional;
alshabibf544c012016-02-21 14:49:51 -080074import java.util.Properties;
alshabib49cadbd2016-01-12 18:06:53 -080075import java.util.concurrent.CompletableFuture;
Jonathan Hart3e594642015-10-20 17:31:24 -070076import java.util.concurrent.ConcurrentHashMap;
alshabib49cadbd2016-01-12 18:06:53 -080077import java.util.concurrent.ExecutorService;
78import java.util.concurrent.Executors;
alshabib0ccde6d2015-05-30 18:22:36 -070079
alshabibf544c012016-02-21 14:49:51 -080080import static com.google.common.base.Strings.isNullOrEmpty;
81import static org.onlab.util.Tools.get;
alshabib49cadbd2016-01-12 18:06:53 -080082import static org.onlab.util.Tools.groupedThreads;
alshabib0ccde6d2015-05-30 18:22:36 -070083import static org.slf4j.LoggerFactory.getLogger;
84
85/**
Jonathan Hart3e594642015-10-20 17:31:24 -070086 * Provisions rules on access devices.
alshabib0ccde6d2015-05-30 18:22:36 -070087 */
Jonathan Hart3e594642015-10-20 17:31:24 -070088@Service
alshabib0ccde6d2015-05-30 18:22:36 -070089@Component(immediate = true)
alshabib6b139b42016-01-12 15:55:53 -080090public class Olt
91 extends AbstractListenerManager<AccessDeviceEvent, AccessDeviceListener>
92 implements AccessDeviceService {
alshabibf544c012016-02-21 14:49:51 -080093
94 private static final short DEFAULT_VLAN = 0;
alshabib6cb86362016-03-03 18:00:58 -080095 private static final String SUBSCRIBERS = "existing-subscribers";
alshabibf544c012016-02-21 14:49:51 -080096
alshabib0ccde6d2015-05-30 18:22:36 -070097 private final Logger log = getLogger(getClass());
98
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected FlowObjectiveService flowObjectiveService;
101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabibfe1ffee2016-03-04 14:55:19 -0800103 protected MastershipService mastershipService;
104
105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabib0ccde6d2015-05-30 18:22:36 -0700106 protected DeviceService deviceService;
107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected CoreService coreService;
110
Jonathan Hart3e594642015-10-20 17:31:24 -0700111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected NetworkConfigRegistry networkConfig;
113
alshabibf544c012016-02-21 14:49:51 -0800114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 protected ComponentConfigService componentConfigService;
116
alshabib6cb86362016-03-03 18:00:58 -0800117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected StorageService storageService;
alshabibf544c012016-02-21 14:49:51 -0800119
120 @Property(name = "defaultVlan", intValue = DEFAULT_VLAN,
121 label = "Default VLAN RG<->ONU traffic")
122 private int defaultVlan = DEFAULT_VLAN;
123
alshabib0ccde6d2015-05-30 18:22:36 -0700124 private final DeviceListener deviceListener = new InternalDeviceListener();
125
126 private ApplicationId appId;
127
alshabib49cadbd2016-01-12 18:06:53 -0800128 private ExecutorService oltInstallers = Executors.newFixedThreadPool(4,
alshabib02cbe6a2016-01-14 17:27:11 -0800129 groupedThreads("onos/olt-service",
130 "olt-installer-%d"));
alshabib1af3b712015-06-05 14:55:24 -0700131
Jonathan Hart3e594642015-10-20 17:31:24 -0700132 private Map<DeviceId, AccessDeviceData> oltData = new ConcurrentHashMap<>();
133
alshabib6cb86362016-03-03 18:00:58 -0800134 private Map<ConnectPoint, VlanId> subscribers;
alshabib02cbe6a2016-01-14 17:27:11 -0800135
Jonathan Hart3e594642015-10-20 17:31:24 -0700136 private InternalNetworkConfigListener configListener =
137 new InternalNetworkConfigListener();
138 private static final Class<AccessDeviceConfig> CONFIG_CLASS =
139 AccessDeviceConfig.class;
140
141 private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
142 new ConfigFactory<DeviceId, AccessDeviceConfig>(
143 SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
alshabib02cbe6a2016-01-14 17:27:11 -0800144 @Override
145 public AccessDeviceConfig createConfig() {
146 return new AccessDeviceConfig();
147 }
148 };
149
alshabib0ccde6d2015-05-30 18:22:36 -0700150
151 @Activate
alshabibf544c012016-02-21 14:49:51 -0800152 public void activate(ComponentContext context) {
153 modified(context);
alshabib1af3b712015-06-05 14:55:24 -0700154 appId = coreService.registerApplication("org.onosproject.olt");
alshabibf544c012016-02-21 14:49:51 -0800155 componentConfigService.registerProperties(getClass());
alshabibbeb2dc92015-06-05 13:35:13 -0700156
alshabib6b139b42016-01-12 15:55:53 -0800157 eventDispatcher.addSink(AccessDeviceEvent.class, listenerRegistry);
158
Jonathan Hart3e594642015-10-20 17:31:24 -0700159 networkConfig.registerConfigFactory(configFactory);
160 networkConfig.addListener(configListener);
161
alshabibbb424232016-01-15 12:20:25 -0800162
Jonathan Hart3e594642015-10-20 17:31:24 -0700163 networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
164 subject -> {
165 AccessDeviceConfig config = networkConfig.getConfig(subject, AccessDeviceConfig.class);
166 if (config != null) {
167 AccessDeviceData data = config.getOlt();
168 oltData.put(data.deviceId(), data);
169 }
170 }
171 );
172
alshabibbb424232016-01-15 12:20:25 -0800173 oltData.keySet().stream()
174 .flatMap(did -> deviceService.getPorts(did).stream())
alshabibfe69e9a2016-02-11 17:31:36 -0800175 .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
alshabibbb424232016-01-15 12:20:25 -0800176 .filter(p -> p.isEnabled())
alshabibea9eed92016-02-12 15:47:20 -0800177 .forEach(p -> processFilteringObjectives((DeviceId) p.element().id(),
178 p.number(), true));
alshabibbb424232016-01-15 12:20:25 -0800179
alshabib6cb86362016-03-03 18:00:58 -0800180 subscribers = storageService.<ConnectPoint, VlanId>consistentMapBuilder()
181 .withName(SUBSCRIBERS)
182 .withSerializer(Serializer.using(KryoNamespaces.API))
183 .build().asJavaMap();
184
alshabib87f90e42016-01-27 13:49:46 -0800185 deviceService.addListener(deviceListener);
186
alshabib0ccde6d2015-05-30 18:22:36 -0700187 log.info("Started with Application ID {}", appId.id());
188 }
189
190 @Deactivate
191 public void deactivate() {
alshabibf544c012016-02-21 14:49:51 -0800192 componentConfigService.unregisterProperties(getClass(), false);
alshabibfe69e9a2016-02-11 17:31:36 -0800193 deviceService.removeListener(deviceListener);
Jonathan Hart3e594642015-10-20 17:31:24 -0700194 networkConfig.removeListener(configListener);
195 networkConfig.unregisterConfigFactory(configFactory);
alshabib0ccde6d2015-05-30 18:22:36 -0700196 log.info("Stopped");
197 }
198
alshabibf544c012016-02-21 14:49:51 -0800199 @Modified
200 public void modified(ComponentContext context) {
201 Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
202
203 try {
204 String s = get(properties, "defaultVlan");
205 defaultVlan = isNullOrEmpty(s) ? DEFAULT_VLAN : Integer.parseInt(s.trim());
206 } catch (Exception e) {
207 defaultVlan = DEFAULT_VLAN;
208 }
209 }
210
alshabib56efe432016-02-25 17:57:24 -0500211 @Override
Jonathan Hart3e594642015-10-20 17:31:24 -0700212 public void provisionSubscriber(ConnectPoint port, VlanId vlan) {
213 AccessDeviceData olt = oltData.get(port.deviceId());
214
215 if (olt == null) {
216 log.warn("No data found for OLT device {}", port.deviceId());
217 return;
218 }
219
Jonathan Hart48327842015-11-10 16:09:22 -0800220 provisionVlans(olt.deviceId(), olt.uplink(), port.port(), vlan, olt.vlan(),
alshabibfa0dc662016-01-13 11:23:53 -0800221 olt.defaultVlan());
222 }
223
224 @Override
225 public void removeSubscriber(ConnectPoint port) {
alshabib02cbe6a2016-01-14 17:27:11 -0800226 AccessDeviceData olt = oltData.get(port.deviceId());
227
228 if (olt == null) {
229 log.warn("No data found for OLT device {}", port.deviceId());
230 return;
231 }
232
alshabib6cb86362016-03-03 18:00:58 -0800233 VlanId subscriberVlan = subscribers.remove(port);
234
235 if (subscriberVlan == null) {
236 log.warn("Unknown subscriber at location {}", port);
237 return;
238 }
239
240 unprovisionSubscriber(olt.deviceId(), olt.uplink(), port.port(), subscriberVlan,
241 olt.vlan(), olt.defaultVlan());
alshabib02cbe6a2016-01-14 17:27:11 -0800242
243 }
244
alshabibf544c012016-02-21 14:49:51 -0800245 @Override
246 public Map<DeviceId, AccessDeviceData> fetchOlts() {
247 return Maps.newHashMap(oltData);
248 }
249
alshabib02cbe6a2016-01-14 17:27:11 -0800250 private void unprovisionSubscriber(DeviceId deviceId, PortNumber uplink,
alshabib6cb86362016-03-03 18:00:58 -0800251 PortNumber subscriberPort, VlanId subscriberVlan,
252 VlanId deviceVlan, Optional<VlanId> defaultVlan) {
alshabib02cbe6a2016-01-14 17:27:11 -0800253
254 CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
255 CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
256
alshabib6cb86362016-03-03 18:00:58 -0800257 ForwardingObjective.Builder upFwd = upBuilder(uplink, subscriberPort,
258 subscriberVlan, deviceVlan,
259 defaultVlan);
260 ForwardingObjective.Builder downFwd = downBuilder(uplink, subscriberPort,
261 subscriberVlan, deviceVlan,
262 defaultVlan);
alshabib02cbe6a2016-01-14 17:27:11 -0800263
264
alshabib6cb86362016-03-03 18:00:58 -0800265 flowObjectiveService.forward(deviceId, upFwd.remove(new ObjectiveContext() {
266 @Override
267 public void onSuccess(Objective objective) {
268 upFuture.complete(null);
269 }
alshabib02cbe6a2016-01-14 17:27:11 -0800270
alshabib6cb86362016-03-03 18:00:58 -0800271 @Override
272 public void onError(Objective objective, ObjectiveError error) {
273 upFuture.complete(error);
274 }
275 }));
276
277 flowObjectiveService.forward(deviceId, downFwd.remove(new ObjectiveContext() {
278 @Override
279 public void onSuccess(Objective objective) {
280 downFuture.complete(null);
281 }
282
283 @Override
284 public void onError(Objective objective, ObjectiveError error) {
285 downFuture.complete(error);
286 }
287 }));
alshabib02cbe6a2016-01-14 17:27:11 -0800288
289 upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
290 if (upStatus == null && downStatus == null) {
291 post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_UNREGISTERED,
292 deviceId,
293 deviceVlan,
294 subscriberVlan));
295 } else if (downStatus != null) {
296 log.error("Subscriber with vlan {} on device {} " +
297 "on port {} failed downstream uninstallation: {}",
298 subscriberVlan, deviceId, subscriberPort, downStatus);
299 } else if (upStatus != null) {
300 log.error("Subscriber with vlan {} on device {} " +
301 "on port {} failed upstream uninstallation: {}",
302 subscriberVlan, deviceId, subscriberPort, upStatus);
303 }
304 }, oltInstallers);
alshabibfa0dc662016-01-13 11:23:53 -0800305
Jonathan Hart3e594642015-10-20 17:31:24 -0700306 }
307
308 private void provisionVlans(DeviceId deviceId, PortNumber uplinkPort,
309 PortNumber subscriberPort,
Jonathan Hart48327842015-11-10 16:09:22 -0800310 VlanId subscriberVlan, VlanId deviceVlan,
311 Optional<VlanId> defaultVlan) {
Jonathan Hart3e594642015-10-20 17:31:24 -0700312
alshabib49cadbd2016-01-12 18:06:53 -0800313 CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
314 CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
315
alshabib6cb86362016-03-03 18:00:58 -0800316 ForwardingObjective.Builder upFwd = upBuilder(uplinkPort, subscriberPort,
317 subscriberVlan, deviceVlan,
318 defaultVlan);
Jonathan Hart3e594642015-10-20 17:31:24 -0700319
320
alshabib6cb86362016-03-03 18:00:58 -0800321 ForwardingObjective.Builder downFwd = downBuilder(uplinkPort, subscriberPort,
322 subscriberVlan, deviceVlan,
323 defaultVlan);
alshabib49cadbd2016-01-12 18:06:53 -0800324
alshabib02cbe6a2016-01-14 17:27:11 -0800325 ConnectPoint cp = new ConnectPoint(deviceId, subscriberPort);
alshabib02cbe6a2016-01-14 17:27:11 -0800326 subscribers.put(cp, subscriberVlan);
alshabib02cbe6a2016-01-14 17:27:11 -0800327
alshabib02cbe6a2016-01-14 17:27:11 -0800328 flowObjectiveService.forward(deviceId, upFwd.add(new ObjectiveContext() {
329 @Override
330 public void onSuccess(Objective objective) {
331 upFuture.complete(null);
332 }
333
334 @Override
335 public void onError(Objective objective, ObjectiveError error) {
336 upFuture.complete(error);
337 }
338 }));
339
alshabib02cbe6a2016-01-14 17:27:11 -0800340 flowObjectiveService.forward(deviceId, downFwd.add(new ObjectiveContext() {
341 @Override
342 public void onSuccess(Objective objective) {
343 downFuture.complete(null);
344 }
345
346 @Override
347 public void onError(Objective objective, ObjectiveError error) {
348 downFuture.complete(error);
349 }
350 }));
alshabib49cadbd2016-01-12 18:06:53 -0800351
352 upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
353 if (upStatus == null && downStatus == null) {
354 post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_REGISTERED,
355 deviceId,
356 deviceVlan,
357 subscriberVlan));
alshabibea9eed92016-02-12 15:47:20 -0800358
alshabib49cadbd2016-01-12 18:06:53 -0800359 } else if (downStatus != null) {
360 log.error("Subscriber with vlan {} on device {} " +
361 "on port {} failed downstream installation: {}",
362 subscriberVlan, deviceId, subscriberPort, downStatus);
363 } else if (upStatus != null) {
364 log.error("Subscriber with vlan {} on device {} " +
365 "on port {} failed upstream installation: {}",
366 subscriberVlan, deviceId, subscriberPort, upStatus);
367 }
368 }, oltInstallers);
369
Jonathan Hart3e594642015-10-20 17:31:24 -0700370 }
371
alshabib6cb86362016-03-03 18:00:58 -0800372 private ForwardingObjective.Builder downBuilder(PortNumber uplinkPort,
373 PortNumber subscriberPort,
374 VlanId subscriberVlan,
375 VlanId deviceVlan,
376 Optional<VlanId> defaultVlan) {
377 TrafficSelector downstream = DefaultTrafficSelector.builder()
378 .matchVlanId(deviceVlan)
379 .matchInPort(uplinkPort)
380 .matchInnerVlanId(subscriberVlan)
381 .build();
382
383 TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
384 .popVlan()
385 .setVlanId(defaultVlan.orElse(VlanId.vlanId((short) this.defaultVlan)))
386 .setOutput(subscriberPort)
387 .build();
388
389 return DefaultForwardingObjective.builder()
390 .withFlag(ForwardingObjective.Flag.VERSATILE)
391 .withPriority(1000)
392 .makePermanent()
393 .withSelector(downstream)
394 .fromApp(appId)
395 .withTreatment(downstreamTreatment);
396 }
397
398 private ForwardingObjective.Builder upBuilder(PortNumber uplinkPort,
399 PortNumber subscriberPort,
400 VlanId subscriberVlan,
401 VlanId deviceVlan,
402 Optional<VlanId> defaultVlan) {
403 TrafficSelector upstream = DefaultTrafficSelector.builder()
404 .matchVlanId(defaultVlan.orElse(VlanId.vlanId((short) this.defaultVlan)))
405 .matchInPort(subscriberPort)
406 .build();
407
408
409 TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
410 .pushVlan()
411 .setVlanId(subscriberVlan)
412 .pushVlan()
413 .setVlanId(deviceVlan)
414 .setOutput(uplinkPort)
415 .build();
416
417 return DefaultForwardingObjective.builder()
418 .withFlag(ForwardingObjective.Flag.VERSATILE)
419 .withPriority(1000)
420 .makePermanent()
421 .withSelector(upstream)
422 .fromApp(appId)
423 .withTreatment(upstreamTreatment);
424 }
425
alshabibea9eed92016-02-12 15:47:20 -0800426 private void processFilteringObjectives(DeviceId devId, PortNumber port, boolean install) {
alshabibfe1ffee2016-03-04 14:55:19 -0800427 if (!mastershipService.isLocalMaster(devId)) {
428 return;
429 }
alshabib8f8060d2016-02-10 15:08:23 -0800430 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
431
432 FilteringObjective eapol = (install ? builder.permit() : builder.deny())
alshabibea9eed92016-02-12 15:47:20 -0800433 .withKey(Criteria.matchInPort(port))
alshabibbb424232016-01-15 12:20:25 -0800434 .addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType()))
435 .withMeta(DefaultTrafficTreatment.builder()
436 .setOutput(PortNumber.CONTROLLER).build())
437 .fromApp(appId)
438 .withPriority(1000)
439 .add(new ObjectiveContext() {
440 @Override
441 public void onSuccess(Objective objective) {
442 log.info("Eapol filter for {} on {} installed.",
443 devId, port);
444 }
445
446 @Override
447 public void onError(Objective objective, ObjectiveError error) {
448 log.info("Eapol filter for {} on {} failed because {}",
449 devId, port, error);
450 }
451 });
452
alshabibbb424232016-01-15 12:20:25 -0800453 flowObjectiveService.filter(devId, eapol);
alshabib03adb492016-02-01 17:25:00 -0800454
alshabibbb424232016-01-15 12:20:25 -0800455 }
456
alshabib0ccde6d2015-05-30 18:22:36 -0700457 private class InternalDeviceListener implements DeviceListener {
458 @Override
459 public void event(DeviceEvent event) {
alshabib49cadbd2016-01-12 18:06:53 -0800460 DeviceId devId = event.subject().id();
461 if (!oltData.containsKey(devId)) {
462 log.debug("Device {} is not an OLT", devId);
alshabib6b139b42016-01-12 15:55:53 -0800463 return;
464 }
alshabib0ccde6d2015-05-30 18:22:36 -0700465 switch (event.type()) {
alshabibbb424232016-01-15 12:20:25 -0800466 //TODO: Port handling and bookkeeping should be inproved once
467 // olt firmware handles correct behaviour.
alshabib0ccde6d2015-05-30 18:22:36 -0700468 case PORT_ADDED:
alshabib8f8060d2016-02-10 15:08:23 -0800469 if (!oltData.get(devId).uplink().equals(event.port().number()) &&
470 event.port().isEnabled()) {
alshabibea9eed92016-02-12 15:47:20 -0800471 processFilteringObjectives(devId, event.port().number(), true);
alshabibbb424232016-01-15 12:20:25 -0800472 }
473 break;
474 case PORT_REMOVED:
475 AccessDeviceData olt = oltData.get(devId);
alshabib6cb86362016-03-03 18:00:58 -0800476 VlanId vlan = subscribers.get(new ConnectPoint(devId,
477 event.port().number()));
alshabibbb424232016-01-15 12:20:25 -0800478 unprovisionSubscriber(devId, olt.uplink(),
479 event.port().number(),
alshabib6cb86362016-03-03 18:00:58 -0800480 vlan, olt.vlan(), olt.defaultVlan());
alshabib8f8060d2016-02-10 15:08:23 -0800481 if (!oltData.get(devId).uplink().equals(event.port().number()) &&
482 event.port().isEnabled()) {
alshabibea9eed92016-02-12 15:47:20 -0800483 processFilteringObjectives(devId, event.port().number(), false);
alshabib8f8060d2016-02-10 15:08:23 -0800484 }
alshabibbb424232016-01-15 12:20:25 -0800485 break;
alshabib0ccde6d2015-05-30 18:22:36 -0700486 case PORT_UPDATED:
alshabib8f8060d2016-02-10 15:08:23 -0800487 if (oltData.get(devId).uplink().equals(event.port().number())) {
488 break;
489 }
490 if (event.port().isEnabled()) {
alshabibea9eed92016-02-12 15:47:20 -0800491 processFilteringObjectives(devId, event.port().number(), true);
alshabib8f8060d2016-02-10 15:08:23 -0800492 } else {
alshabibea9eed92016-02-12 15:47:20 -0800493 processFilteringObjectives(devId, event.port().number(), false);
alshabib8f8060d2016-02-10 15:08:23 -0800494 }
alshabib0ccde6d2015-05-30 18:22:36 -0700495 break;
496 case DEVICE_ADDED:
alshabib6b139b42016-01-12 15:55:53 -0800497 post(new AccessDeviceEvent(
498 AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
499 null, null));
alshabibf544c012016-02-21 14:49:51 -0800500 provisionDefaultFlows(devId);
alshabib6b139b42016-01-12 15:55:53 -0800501 break;
alshabib0ccde6d2015-05-30 18:22:36 -0700502 case DEVICE_REMOVED:
alshabib6b139b42016-01-12 15:55:53 -0800503 post(new AccessDeviceEvent(
504 AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
505 null, null));
506 break;
alshabibe5ec2402016-02-09 18:22:33 -0800507 case DEVICE_AVAILABILITY_CHANGED:
508 if (deviceService.isAvailable(devId)) {
509 post(new AccessDeviceEvent(
510 AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
511 null, null));
512 } else {
513 post(new AccessDeviceEvent(
514 AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
515 null, null));
516 }
517 break;
alshabib6b139b42016-01-12 15:55:53 -0800518 case DEVICE_UPDATED:
alshabib0ccde6d2015-05-30 18:22:36 -0700519 case DEVICE_SUSPENDED:
alshabib0ccde6d2015-05-30 18:22:36 -0700520 case PORT_STATS_UPDATED:
521 default:
522 return;
523 }
524 }
525 }
526
Jonathan Hart3e594642015-10-20 17:31:24 -0700527 private class InternalNetworkConfigListener implements NetworkConfigListener {
528 @Override
529 public void event(NetworkConfigEvent event) {
530 switch (event.type()) {
531
alshabib02cbe6a2016-01-14 17:27:11 -0800532 case CONFIG_ADDED:
533 case CONFIG_UPDATED:
alshabibf544c012016-02-21 14:49:51 -0800534
535 AccessDeviceConfig config =
536 networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
537 if (config != null) {
538 oltData.put(config.getOlt().deviceId(), config.getOlt());
539 provisionDefaultFlows((DeviceId) event.subject());
Jonathan Hart3e594642015-10-20 17:31:24 -0700540 }
alshabibf544c012016-02-21 14:49:51 -0800541
alshabib02cbe6a2016-01-14 17:27:11 -0800542 break;
alshabibf544c012016-02-21 14:49:51 -0800543 case CONFIG_REGISTERED:
alshabib02cbe6a2016-01-14 17:27:11 -0800544 case CONFIG_UNREGISTERED:
alshabibf544c012016-02-21 14:49:51 -0800545 break;
alshabib02cbe6a2016-01-14 17:27:11 -0800546 case CONFIG_REMOVED:
alshabibf544c012016-02-21 14:49:51 -0800547 oltData.remove(event.subject());
alshabib02cbe6a2016-01-14 17:27:11 -0800548 default:
549 break;
Jonathan Hart3e594642015-10-20 17:31:24 -0700550 }
551 }
alshabibf544c012016-02-21 14:49:51 -0800552
553 @Override
554 public boolean isRelevant(NetworkConfigEvent event) {
555 return event.configClass().equals(CONFIG_CLASS);
556 }
Jonathan Hart3e594642015-10-20 17:31:24 -0700557 }
alshabib0ccde6d2015-05-30 18:22:36 -0700558
alshabib8f8060d2016-02-10 15:08:23 -0800559 private void provisionDefaultFlows(DeviceId deviceId) {
alshabibfe1ffee2016-03-04 14:55:19 -0800560 if (!mastershipService.isLocalMaster(deviceId)) {
561 return;
562 }
alshabib8f8060d2016-02-10 15:08:23 -0800563 List<Port> ports = deviceService.getPorts(deviceId);
564
565 ports.stream()
566 .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
567 .filter(p -> p.isEnabled())
alshabibea9eed92016-02-12 15:47:20 -0800568 .forEach(p -> processFilteringObjectives((DeviceId) p.element().id(),
569 p.number(), true));
alshabib8f8060d2016-02-10 15:08:23 -0800570
571 }
572
alshabib0ccde6d2015-05-30 18:22:36 -0700573}