blob: a62b11575a675b32c26db1a81dd31c9bd4678370 [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
Jonathan Hart913e9e12016-03-08 14:09:09 -080070import java.util.Collection;
alshabibf544c012016-02-21 14:49:51 -080071import java.util.Dictionary;
alshabib8f8060d2016-02-10 15:08:23 -080072import java.util.List;
Jonathan Hart3e594642015-10-20 17:31:24 -070073import java.util.Map;
Jonathan Hart48327842015-11-10 16:09:22 -080074import java.util.Optional;
alshabibf544c012016-02-21 14:49:51 -080075import java.util.Properties;
alshabib49cadbd2016-01-12 18:06:53 -080076import java.util.concurrent.CompletableFuture;
Jonathan Hart3e594642015-10-20 17:31:24 -070077import java.util.concurrent.ConcurrentHashMap;
alshabib49cadbd2016-01-12 18:06:53 -080078import java.util.concurrent.ExecutorService;
79import java.util.concurrent.Executors;
alshabib0ccde6d2015-05-30 18:22:36 -070080
alshabibf544c012016-02-21 14:49:51 -080081import static com.google.common.base.Strings.isNullOrEmpty;
82import static org.onlab.util.Tools.get;
alshabib49cadbd2016-01-12 18:06:53 -080083import static org.onlab.util.Tools.groupedThreads;
alshabib0ccde6d2015-05-30 18:22:36 -070084import static org.slf4j.LoggerFactory.getLogger;
85
86/**
Jonathan Hart3e594642015-10-20 17:31:24 -070087 * Provisions rules on access devices.
alshabib0ccde6d2015-05-30 18:22:36 -070088 */
Jonathan Hart3e594642015-10-20 17:31:24 -070089@Service
alshabib0ccde6d2015-05-30 18:22:36 -070090@Component(immediate = true)
alshabib6b139b42016-01-12 15:55:53 -080091public class Olt
92 extends AbstractListenerManager<AccessDeviceEvent, AccessDeviceListener>
93 implements AccessDeviceService {
alshabibf544c012016-02-21 14:49:51 -080094
95 private static final short DEFAULT_VLAN = 0;
alshabib6cb86362016-03-03 18:00:58 -080096 private static final String SUBSCRIBERS = "existing-subscribers";
alshabibf544c012016-02-21 14:49:51 -080097
alshabib0ccde6d2015-05-30 18:22:36 -070098 private final Logger log = getLogger(getClass());
99
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected FlowObjectiveService flowObjectiveService;
102
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabibfe1ffee2016-03-04 14:55:19 -0800104 protected MastershipService mastershipService;
105
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabib0ccde6d2015-05-30 18:22:36 -0700107 protected DeviceService deviceService;
108
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected CoreService coreService;
111
Jonathan Hart3e594642015-10-20 17:31:24 -0700112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 protected NetworkConfigRegistry networkConfig;
114
alshabibf544c012016-02-21 14:49:51 -0800115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 protected ComponentConfigService componentConfigService;
117
alshabib6cb86362016-03-03 18:00:58 -0800118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 protected StorageService storageService;
alshabibf544c012016-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
alshabib0ccde6d2015-05-30 18:22:36 -0700125 private final DeviceListener deviceListener = new InternalDeviceListener();
126
127 private ApplicationId appId;
128
alshabib49cadbd2016-01-12 18:06:53 -0800129 private ExecutorService oltInstallers = Executors.newFixedThreadPool(4,
alshabib02cbe6a2016-01-14 17:27:11 -0800130 groupedThreads("onos/olt-service",
131 "olt-installer-%d"));
alshabib1af3b712015-06-05 14:55:24 -0700132
Jonathan Hart3e594642015-10-20 17:31:24 -0700133 private Map<DeviceId, AccessDeviceData> oltData = new ConcurrentHashMap<>();
134
alshabib6cb86362016-03-03 18:00:58 -0800135 private Map<ConnectPoint, VlanId> subscribers;
alshabib02cbe6a2016-01-14 17:27:11 -0800136
Jonathan Hart3e594642015-10-20 17:31:24 -0700137 private InternalNetworkConfigListener configListener =
138 new InternalNetworkConfigListener();
139 private static final Class<AccessDeviceConfig> CONFIG_CLASS =
140 AccessDeviceConfig.class;
141
142 private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
143 new ConfigFactory<DeviceId, AccessDeviceConfig>(
144 SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
alshabib02cbe6a2016-01-14 17:27:11 -0800145 @Override
146 public AccessDeviceConfig createConfig() {
147 return new AccessDeviceConfig();
148 }
149 };
150
alshabib0ccde6d2015-05-30 18:22:36 -0700151
152 @Activate
alshabibf544c012016-02-21 14:49:51 -0800153 public void activate(ComponentContext context) {
154 modified(context);
alshabib1af3b712015-06-05 14:55:24 -0700155 appId = coreService.registerApplication("org.onosproject.olt");
alshabibf544c012016-02-21 14:49:51 -0800156 componentConfigService.registerProperties(getClass());
alshabibbeb2dc92015-06-05 13:35:13 -0700157
alshabib6b139b42016-01-12 15:55:53 -0800158 eventDispatcher.addSink(AccessDeviceEvent.class, listenerRegistry);
159
Jonathan Hart3e594642015-10-20 17:31:24 -0700160 networkConfig.registerConfigFactory(configFactory);
161 networkConfig.addListener(configListener);
162
alshabibbb424232016-01-15 12:20:25 -0800163
Jonathan Hart3e594642015-10-20 17:31:24 -0700164 networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
165 subject -> {
166 AccessDeviceConfig config = networkConfig.getConfig(subject, AccessDeviceConfig.class);
167 if (config != null) {
168 AccessDeviceData data = config.getOlt();
169 oltData.put(data.deviceId(), data);
170 }
171 }
172 );
173
alshabibbb424232016-01-15 12:20:25 -0800174 oltData.keySet().stream()
175 .flatMap(did -> deviceService.getPorts(did).stream())
alshabibfe69e9a2016-02-11 17:31:36 -0800176 .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
alshabibbb424232016-01-15 12:20:25 -0800177 .filter(p -> p.isEnabled())
alshabibea9eed92016-02-12 15:47:20 -0800178 .forEach(p -> processFilteringObjectives((DeviceId) p.element().id(),
179 p.number(), true));
alshabibbb424232016-01-15 12:20:25 -0800180
alshabib6cb86362016-03-03 18:00:58 -0800181 subscribers = storageService.<ConnectPoint, VlanId>consistentMapBuilder()
182 .withName(SUBSCRIBERS)
183 .withSerializer(Serializer.using(KryoNamespaces.API))
184 .build().asJavaMap();
185
alshabib87f90e42016-01-27 13:49:46 -0800186 deviceService.addListener(deviceListener);
187
alshabib0ccde6d2015-05-30 18:22:36 -0700188 log.info("Started with Application ID {}", appId.id());
189 }
190
191 @Deactivate
192 public void deactivate() {
alshabibf544c012016-02-21 14:49:51 -0800193 componentConfigService.unregisterProperties(getClass(), false);
alshabibfe69e9a2016-02-11 17:31:36 -0800194 deviceService.removeListener(deviceListener);
Jonathan Hart3e594642015-10-20 17:31:24 -0700195 networkConfig.removeListener(configListener);
196 networkConfig.unregisterConfigFactory(configFactory);
alshabib0ccde6d2015-05-30 18:22:36 -0700197 log.info("Stopped");
198 }
199
alshabibf544c012016-02-21 14:49:51 -0800200 @Modified
201 public void modified(ComponentContext context) {
202 Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
203
204 try {
205 String s = get(properties, "defaultVlan");
206 defaultVlan = isNullOrEmpty(s) ? DEFAULT_VLAN : Integer.parseInt(s.trim());
207 } catch (Exception e) {
208 defaultVlan = DEFAULT_VLAN;
209 }
210 }
211
alshabib56efe432016-02-25 17:57:24 -0500212 @Override
Jonathan Hart3e594642015-10-20 17:31:24 -0700213 public void provisionSubscriber(ConnectPoint port, VlanId vlan) {
214 AccessDeviceData olt = oltData.get(port.deviceId());
215
216 if (olt == null) {
217 log.warn("No data found for OLT device {}", port.deviceId());
218 return;
219 }
220
Jonathan Hart48327842015-11-10 16:09:22 -0800221 provisionVlans(olt.deviceId(), olt.uplink(), port.port(), vlan, olt.vlan(),
alshabibfa0dc662016-01-13 11:23:53 -0800222 olt.defaultVlan());
223 }
224
225 @Override
226 public void removeSubscriber(ConnectPoint port) {
alshabib02cbe6a2016-01-14 17:27:11 -0800227 AccessDeviceData olt = oltData.get(port.deviceId());
228
229 if (olt == null) {
230 log.warn("No data found for OLT device {}", port.deviceId());
231 return;
232 }
233
alshabib6cb86362016-03-03 18:00:58 -0800234 VlanId subscriberVlan = subscribers.remove(port);
235
236 if (subscriberVlan == null) {
237 log.warn("Unknown subscriber at location {}", port);
238 return;
239 }
240
241 unprovisionSubscriber(olt.deviceId(), olt.uplink(), port.port(), subscriberVlan,
242 olt.vlan(), olt.defaultVlan());
alshabib02cbe6a2016-01-14 17:27:11 -0800243
244 }
245
alshabibf544c012016-02-21 14:49:51 -0800246 @Override
Jonathan Hart913e9e12016-03-08 14:09:09 -0800247 public Collection<Map.Entry<ConnectPoint, VlanId>> getSubscribers() {
248 return subscribers.entrySet();
249 }
250
251 @Override
alshabibf544c012016-02-21 14:49:51 -0800252 public Map<DeviceId, AccessDeviceData> fetchOlts() {
253 return Maps.newHashMap(oltData);
254 }
255
alshabib02cbe6a2016-01-14 17:27:11 -0800256 private void unprovisionSubscriber(DeviceId deviceId, PortNumber uplink,
alshabib6cb86362016-03-03 18:00:58 -0800257 PortNumber subscriberPort, VlanId subscriberVlan,
258 VlanId deviceVlan, Optional<VlanId> defaultVlan) {
alshabib02cbe6a2016-01-14 17:27:11 -0800259
260 CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
261 CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
262
alshabib6cb86362016-03-03 18:00:58 -0800263 ForwardingObjective.Builder upFwd = upBuilder(uplink, subscriberPort,
264 subscriberVlan, deviceVlan,
265 defaultVlan);
266 ForwardingObjective.Builder downFwd = downBuilder(uplink, subscriberPort,
267 subscriberVlan, deviceVlan,
268 defaultVlan);
alshabib02cbe6a2016-01-14 17:27:11 -0800269
270
alshabib6cb86362016-03-03 18:00:58 -0800271 flowObjectiveService.forward(deviceId, upFwd.remove(new ObjectiveContext() {
272 @Override
273 public void onSuccess(Objective objective) {
274 upFuture.complete(null);
275 }
alshabib02cbe6a2016-01-14 17:27:11 -0800276
alshabib6cb86362016-03-03 18:00:58 -0800277 @Override
278 public void onError(Objective objective, ObjectiveError error) {
279 upFuture.complete(error);
280 }
281 }));
282
283 flowObjectiveService.forward(deviceId, downFwd.remove(new ObjectiveContext() {
284 @Override
285 public void onSuccess(Objective objective) {
286 downFuture.complete(null);
287 }
288
289 @Override
290 public void onError(Objective objective, ObjectiveError error) {
291 downFuture.complete(error);
292 }
293 }));
alshabib02cbe6a2016-01-14 17:27:11 -0800294
295 upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
296 if (upStatus == null && downStatus == null) {
297 post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_UNREGISTERED,
298 deviceId,
299 deviceVlan,
300 subscriberVlan));
301 } else if (downStatus != null) {
302 log.error("Subscriber with vlan {} on device {} " +
303 "on port {} failed downstream uninstallation: {}",
304 subscriberVlan, deviceId, subscriberPort, downStatus);
305 } else if (upStatus != null) {
306 log.error("Subscriber with vlan {} on device {} " +
307 "on port {} failed upstream uninstallation: {}",
308 subscriberVlan, deviceId, subscriberPort, upStatus);
309 }
310 }, oltInstallers);
alshabibfa0dc662016-01-13 11:23:53 -0800311
Jonathan Hart3e594642015-10-20 17:31:24 -0700312 }
313
314 private void provisionVlans(DeviceId deviceId, PortNumber uplinkPort,
315 PortNumber subscriberPort,
Jonathan Hart48327842015-11-10 16:09:22 -0800316 VlanId subscriberVlan, VlanId deviceVlan,
317 Optional<VlanId> defaultVlan) {
Jonathan Hart3e594642015-10-20 17:31:24 -0700318
alshabib49cadbd2016-01-12 18:06:53 -0800319 CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
320 CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
321
alshabib6cb86362016-03-03 18:00:58 -0800322 ForwardingObjective.Builder upFwd = upBuilder(uplinkPort, subscriberPort,
323 subscriberVlan, deviceVlan,
324 defaultVlan);
Jonathan Hart3e594642015-10-20 17:31:24 -0700325
326
alshabib6cb86362016-03-03 18:00:58 -0800327 ForwardingObjective.Builder downFwd = downBuilder(uplinkPort, subscriberPort,
328 subscriberVlan, deviceVlan,
329 defaultVlan);
alshabib49cadbd2016-01-12 18:06:53 -0800330
alshabib02cbe6a2016-01-14 17:27:11 -0800331 ConnectPoint cp = new ConnectPoint(deviceId, subscriberPort);
alshabib02cbe6a2016-01-14 17:27:11 -0800332 subscribers.put(cp, subscriberVlan);
alshabib02cbe6a2016-01-14 17:27:11 -0800333
alshabib02cbe6a2016-01-14 17:27:11 -0800334 flowObjectiveService.forward(deviceId, upFwd.add(new ObjectiveContext() {
335 @Override
336 public void onSuccess(Objective objective) {
337 upFuture.complete(null);
338 }
339
340 @Override
341 public void onError(Objective objective, ObjectiveError error) {
342 upFuture.complete(error);
343 }
344 }));
345
alshabib02cbe6a2016-01-14 17:27:11 -0800346 flowObjectiveService.forward(deviceId, downFwd.add(new ObjectiveContext() {
347 @Override
348 public void onSuccess(Objective objective) {
349 downFuture.complete(null);
350 }
351
352 @Override
353 public void onError(Objective objective, ObjectiveError error) {
354 downFuture.complete(error);
355 }
356 }));
alshabib49cadbd2016-01-12 18:06:53 -0800357
358 upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
359 if (upStatus == null && downStatus == null) {
360 post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_REGISTERED,
361 deviceId,
362 deviceVlan,
363 subscriberVlan));
alshabibea9eed92016-02-12 15:47:20 -0800364
alshabib49cadbd2016-01-12 18:06:53 -0800365 } else if (downStatus != null) {
366 log.error("Subscriber with vlan {} on device {} " +
367 "on port {} failed downstream installation: {}",
368 subscriberVlan, deviceId, subscriberPort, downStatus);
369 } else if (upStatus != null) {
370 log.error("Subscriber with vlan {} on device {} " +
371 "on port {} failed upstream installation: {}",
372 subscriberVlan, deviceId, subscriberPort, upStatus);
373 }
374 }, oltInstallers);
375
Jonathan Hart3e594642015-10-20 17:31:24 -0700376 }
377
alshabib6cb86362016-03-03 18:00:58 -0800378 private ForwardingObjective.Builder downBuilder(PortNumber uplinkPort,
379 PortNumber subscriberPort,
380 VlanId subscriberVlan,
381 VlanId deviceVlan,
382 Optional<VlanId> defaultVlan) {
383 TrafficSelector downstream = DefaultTrafficSelector.builder()
384 .matchVlanId(deviceVlan)
385 .matchInPort(uplinkPort)
386 .matchInnerVlanId(subscriberVlan)
387 .build();
388
389 TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
390 .popVlan()
391 .setVlanId(defaultVlan.orElse(VlanId.vlanId((short) this.defaultVlan)))
392 .setOutput(subscriberPort)
393 .build();
394
395 return DefaultForwardingObjective.builder()
396 .withFlag(ForwardingObjective.Flag.VERSATILE)
397 .withPriority(1000)
398 .makePermanent()
399 .withSelector(downstream)
400 .fromApp(appId)
401 .withTreatment(downstreamTreatment);
402 }
403
404 private ForwardingObjective.Builder upBuilder(PortNumber uplinkPort,
405 PortNumber subscriberPort,
406 VlanId subscriberVlan,
407 VlanId deviceVlan,
408 Optional<VlanId> defaultVlan) {
409 TrafficSelector upstream = DefaultTrafficSelector.builder()
410 .matchVlanId(defaultVlan.orElse(VlanId.vlanId((short) this.defaultVlan)))
411 .matchInPort(subscriberPort)
412 .build();
413
414
415 TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
416 .pushVlan()
417 .setVlanId(subscriberVlan)
418 .pushVlan()
419 .setVlanId(deviceVlan)
420 .setOutput(uplinkPort)
421 .build();
422
423 return DefaultForwardingObjective.builder()
424 .withFlag(ForwardingObjective.Flag.VERSATILE)
425 .withPriority(1000)
426 .makePermanent()
427 .withSelector(upstream)
428 .fromApp(appId)
429 .withTreatment(upstreamTreatment);
430 }
431
alshabibea9eed92016-02-12 15:47:20 -0800432 private void processFilteringObjectives(DeviceId devId, PortNumber port, boolean install) {
alshabibfe1ffee2016-03-04 14:55:19 -0800433 if (!mastershipService.isLocalMaster(devId)) {
434 return;
435 }
alshabib8f8060d2016-02-10 15:08:23 -0800436 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
437
438 FilteringObjective eapol = (install ? builder.permit() : builder.deny())
alshabibea9eed92016-02-12 15:47:20 -0800439 .withKey(Criteria.matchInPort(port))
alshabibbb424232016-01-15 12:20:25 -0800440 .addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType()))
441 .withMeta(DefaultTrafficTreatment.builder()
442 .setOutput(PortNumber.CONTROLLER).build())
443 .fromApp(appId)
444 .withPriority(1000)
445 .add(new ObjectiveContext() {
446 @Override
447 public void onSuccess(Objective objective) {
448 log.info("Eapol filter for {} on {} installed.",
449 devId, port);
450 }
451
452 @Override
453 public void onError(Objective objective, ObjectiveError error) {
454 log.info("Eapol filter for {} on {} failed because {}",
455 devId, port, error);
456 }
457 });
458
alshabibbb424232016-01-15 12:20:25 -0800459 flowObjectiveService.filter(devId, eapol);
alshabib03adb492016-02-01 17:25:00 -0800460
alshabibbb424232016-01-15 12:20:25 -0800461 }
462
alshabib0ccde6d2015-05-30 18:22:36 -0700463 private class InternalDeviceListener implements DeviceListener {
464 @Override
465 public void event(DeviceEvent event) {
alshabib49cadbd2016-01-12 18:06:53 -0800466 DeviceId devId = event.subject().id();
467 if (!oltData.containsKey(devId)) {
alshabib6b139b42016-01-12 15:55:53 -0800468 return;
469 }
alshabib0ccde6d2015-05-30 18:22:36 -0700470 switch (event.type()) {
Jonathan Hart913e9e12016-03-08 14:09:09 -0800471 //TODO: Port handling and bookkeeping should be improved once
alshabibbb424232016-01-15 12:20:25 -0800472 // olt firmware handles correct behaviour.
alshabib0ccde6d2015-05-30 18:22:36 -0700473 case PORT_ADDED:
alshabib8f8060d2016-02-10 15:08:23 -0800474 if (!oltData.get(devId).uplink().equals(event.port().number()) &&
475 event.port().isEnabled()) {
alshabibea9eed92016-02-12 15:47:20 -0800476 processFilteringObjectives(devId, event.port().number(), true);
alshabibbb424232016-01-15 12:20:25 -0800477 }
478 break;
479 case PORT_REMOVED:
480 AccessDeviceData olt = oltData.get(devId);
alshabib6cb86362016-03-03 18:00:58 -0800481 VlanId vlan = subscribers.get(new ConnectPoint(devId,
482 event.port().number()));
alshabibbb424232016-01-15 12:20:25 -0800483 unprovisionSubscriber(devId, olt.uplink(),
484 event.port().number(),
alshabib6cb86362016-03-03 18:00:58 -0800485 vlan, olt.vlan(), olt.defaultVlan());
alshabib8f8060d2016-02-10 15:08:23 -0800486 if (!oltData.get(devId).uplink().equals(event.port().number()) &&
487 event.port().isEnabled()) {
alshabibea9eed92016-02-12 15:47:20 -0800488 processFilteringObjectives(devId, event.port().number(), false);
alshabib8f8060d2016-02-10 15:08:23 -0800489 }
alshabibbb424232016-01-15 12:20:25 -0800490 break;
alshabib0ccde6d2015-05-30 18:22:36 -0700491 case PORT_UPDATED:
alshabib8f8060d2016-02-10 15:08:23 -0800492 if (oltData.get(devId).uplink().equals(event.port().number())) {
493 break;
494 }
495 if (event.port().isEnabled()) {
alshabibea9eed92016-02-12 15:47:20 -0800496 processFilteringObjectives(devId, event.port().number(), true);
alshabib8f8060d2016-02-10 15:08:23 -0800497 } else {
alshabibea9eed92016-02-12 15:47:20 -0800498 processFilteringObjectives(devId, event.port().number(), false);
alshabib8f8060d2016-02-10 15:08:23 -0800499 }
alshabib0ccde6d2015-05-30 18:22:36 -0700500 break;
501 case DEVICE_ADDED:
alshabib6b139b42016-01-12 15:55:53 -0800502 post(new AccessDeviceEvent(
503 AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
504 null, null));
alshabibf544c012016-02-21 14:49:51 -0800505 provisionDefaultFlows(devId);
alshabib6b139b42016-01-12 15:55:53 -0800506 break;
alshabib0ccde6d2015-05-30 18:22:36 -0700507 case DEVICE_REMOVED:
alshabib6b139b42016-01-12 15:55:53 -0800508 post(new AccessDeviceEvent(
509 AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
510 null, null));
511 break;
alshabibe5ec2402016-02-09 18:22:33 -0800512 case DEVICE_AVAILABILITY_CHANGED:
513 if (deviceService.isAvailable(devId)) {
514 post(new AccessDeviceEvent(
515 AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
516 null, null));
517 } else {
518 post(new AccessDeviceEvent(
519 AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
520 null, null));
521 }
522 break;
alshabib6b139b42016-01-12 15:55:53 -0800523 case DEVICE_UPDATED:
alshabib0ccde6d2015-05-30 18:22:36 -0700524 case DEVICE_SUSPENDED:
alshabib0ccde6d2015-05-30 18:22:36 -0700525 case PORT_STATS_UPDATED:
526 default:
527 return;
528 }
529 }
530 }
531
Jonathan Hart3e594642015-10-20 17:31:24 -0700532 private class InternalNetworkConfigListener implements NetworkConfigListener {
533 @Override
534 public void event(NetworkConfigEvent event) {
535 switch (event.type()) {
536
alshabib02cbe6a2016-01-14 17:27:11 -0800537 case CONFIG_ADDED:
538 case CONFIG_UPDATED:
alshabibf544c012016-02-21 14:49:51 -0800539
540 AccessDeviceConfig config =
541 networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
542 if (config != null) {
543 oltData.put(config.getOlt().deviceId(), config.getOlt());
544 provisionDefaultFlows((DeviceId) event.subject());
Jonathan Hart3e594642015-10-20 17:31:24 -0700545 }
alshabibf544c012016-02-21 14:49:51 -0800546
alshabib02cbe6a2016-01-14 17:27:11 -0800547 break;
alshabibf544c012016-02-21 14:49:51 -0800548 case CONFIG_REGISTERED:
alshabib02cbe6a2016-01-14 17:27:11 -0800549 case CONFIG_UNREGISTERED:
alshabibf544c012016-02-21 14:49:51 -0800550 break;
alshabib02cbe6a2016-01-14 17:27:11 -0800551 case CONFIG_REMOVED:
alshabibf544c012016-02-21 14:49:51 -0800552 oltData.remove(event.subject());
alshabib02cbe6a2016-01-14 17:27:11 -0800553 default:
554 break;
Jonathan Hart3e594642015-10-20 17:31:24 -0700555 }
556 }
alshabibf544c012016-02-21 14:49:51 -0800557
558 @Override
559 public boolean isRelevant(NetworkConfigEvent event) {
560 return event.configClass().equals(CONFIG_CLASS);
561 }
Jonathan Hart3e594642015-10-20 17:31:24 -0700562 }
alshabib0ccde6d2015-05-30 18:22:36 -0700563
alshabib8f8060d2016-02-10 15:08:23 -0800564 private void provisionDefaultFlows(DeviceId deviceId) {
alshabibfe1ffee2016-03-04 14:55:19 -0800565 if (!mastershipService.isLocalMaster(deviceId)) {
566 return;
567 }
alshabib8f8060d2016-02-10 15:08:23 -0800568 List<Port> ports = deviceService.getPorts(deviceId);
569
570 ports.stream()
571 .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
572 .filter(p -> p.isEnabled())
alshabibea9eed92016-02-12 15:47:20 -0800573 .forEach(p -> processFilteringObjectives((DeviceId) p.element().id(),
574 p.number(), true));
alshabib8f8060d2016-02-10 15:08:23 -0800575
576 }
577
alshabib0ccde6d2015-05-30 18:22:36 -0700578}