blob: b956f3a95735aa29340b2a6d200f1c4d541d2239 [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 */
16package org.onosproject.olt;
17
alshabib0ccde6d2015-05-30 18:22:36 -070018import com.google.common.base.Strings;
19import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Modified;
23import org.apache.felix.scr.annotations.Property;
24import 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;
alshabib0ccde6d2015-05-30 18:22:36 -070027import org.onlab.packet.VlanId;
28import org.onlab.util.Tools;
29import org.onosproject.core.ApplicationId;
30import org.onosproject.core.CoreService;
alshabib6b139b42016-01-12 15:55:53 -080031import org.onosproject.event.AbstractListenerManager;
Jonathan Hart3e594642015-10-20 17:31:24 -070032import org.onosproject.net.ConnectPoint;
alshabib0ccde6d2015-05-30 18:22:36 -070033import org.onosproject.net.DeviceId;
34import org.onosproject.net.PortNumber;
Jonathan Hart3e594642015-10-20 17:31:24 -070035import org.onosproject.net.config.ConfigFactory;
36import org.onosproject.net.config.NetworkConfigEvent;
37import org.onosproject.net.config.NetworkConfigListener;
38import org.onosproject.net.config.NetworkConfigRegistry;
39import org.onosproject.net.config.basics.SubjectFactories;
alshabib0ccde6d2015-05-30 18:22:36 -070040import org.onosproject.net.device.DeviceEvent;
41import org.onosproject.net.device.DeviceListener;
42import org.onosproject.net.device.DeviceService;
43import org.onosproject.net.flow.DefaultTrafficSelector;
44import org.onosproject.net.flow.DefaultTrafficTreatment;
45import org.onosproject.net.flow.TrafficSelector;
46import org.onosproject.net.flow.TrafficTreatment;
47import org.onosproject.net.flowobjective.DefaultForwardingObjective;
48import org.onosproject.net.flowobjective.FlowObjectiveService;
49import org.onosproject.net.flowobjective.ForwardingObjective;
alshabib6b139b42016-01-12 15:55:53 -080050import org.onosproject.olt.api.AccessDeviceEvent;
51import org.onosproject.olt.api.AccessDeviceListener;
alshabib0ccde6d2015-05-30 18:22:36 -070052import org.osgi.service.component.ComponentContext;
53import org.slf4j.Logger;
54
55import java.util.Dictionary;
Jonathan Hart3e594642015-10-20 17:31:24 -070056import java.util.Map;
Jonathan Hart48327842015-11-10 16:09:22 -080057import java.util.Optional;
Jonathan Hart3e594642015-10-20 17:31:24 -070058import java.util.concurrent.ConcurrentHashMap;
alshabib0ccde6d2015-05-30 18:22:36 -070059
60import static org.slf4j.LoggerFactory.getLogger;
61
62/**
Jonathan Hart3e594642015-10-20 17:31:24 -070063 * Provisions rules on access devices.
alshabib0ccde6d2015-05-30 18:22:36 -070064 */
Jonathan Hart3e594642015-10-20 17:31:24 -070065@Service
alshabib0ccde6d2015-05-30 18:22:36 -070066@Component(immediate = true)
alshabib6b139b42016-01-12 15:55:53 -080067public class Olt
68 extends AbstractListenerManager<AccessDeviceEvent, AccessDeviceListener>
69 implements AccessDeviceService {
alshabib0ccde6d2015-05-30 18:22:36 -070070 private final Logger log = getLogger(getClass());
71
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected FlowObjectiveService flowObjectiveService;
74
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected DeviceService deviceService;
77
78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 protected CoreService coreService;
80
Jonathan Hart3e594642015-10-20 17:31:24 -070081 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected NetworkConfigRegistry networkConfig;
83
alshabib0ccde6d2015-05-30 18:22:36 -070084 private final DeviceListener deviceListener = new InternalDeviceListener();
85
86 private ApplicationId appId;
87
Jonathan Hart3e594642015-10-20 17:31:24 -070088 private static final VlanId DEFAULT_VLAN = VlanId.vlanId((short) 0);
alshabib17ff25f2015-06-01 10:57:31 -070089 public static final int OFFSET = 200;
90
alshabib0ccde6d2015-05-30 18:22:36 -070091 public static final int UPLINK_PORT = 129;
alshabibb37fd082015-06-05 15:32:15 -070092 public static final int GFAST_UPLINK_PORT = 100;
alshabib0ccde6d2015-05-30 18:22:36 -070093
94 public static final String OLT_DEVICE = "of:90e2ba82f97791e9";
alshabib1af3b712015-06-05 14:55:24 -070095 public static final String GFAST_DEVICE = "of:0011223344551357";
alshabib0ccde6d2015-05-30 18:22:36 -070096
97 @Property(name = "uplinkPort", intValue = UPLINK_PORT,
98 label = "The OLT's uplink port number")
99 private int uplinkPort = UPLINK_PORT;
100
alshabibb37fd082015-06-05 15:32:15 -0700101 @Property(name = "gfastUplink", intValue = GFAST_UPLINK_PORT,
102 label = "The OLT's uplink port number")
103 private int gfastUplink = GFAST_UPLINK_PORT;
104
alshabib6b139b42016-01-12 15:55:53 -0800105 //TODO: replace this information with info comming for net cfg service.
alshabib0ccde6d2015-05-30 18:22:36 -0700106 @Property(name = "oltDevice", value = OLT_DEVICE,
107 label = "The OLT device id")
108 private String oltDevice = OLT_DEVICE;
109
alshabib1af3b712015-06-05 14:55:24 -0700110 @Property(name = "gfastDevice", value = GFAST_DEVICE,
111 label = "The gfast device id")
112 private String gfastDevice = GFAST_DEVICE;
113
Jonathan Hart3e594642015-10-20 17:31:24 -0700114 private Map<DeviceId, AccessDeviceData> oltData = new ConcurrentHashMap<>();
115
116 private InternalNetworkConfigListener configListener =
117 new InternalNetworkConfigListener();
118 private static final Class<AccessDeviceConfig> CONFIG_CLASS =
119 AccessDeviceConfig.class;
120
121 private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
122 new ConfigFactory<DeviceId, AccessDeviceConfig>(
123 SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
124 @Override
125 public AccessDeviceConfig createConfig() {
126 return new AccessDeviceConfig();
127 }
128 };
alshabib0ccde6d2015-05-30 18:22:36 -0700129
130 @Activate
131 public void activate() {
alshabib1af3b712015-06-05 14:55:24 -0700132 appId = coreService.registerApplication("org.onosproject.olt");
alshabibbeb2dc92015-06-05 13:35:13 -0700133
alshabib6b139b42016-01-12 15:55:53 -0800134 eventDispatcher.addSink(AccessDeviceEvent.class, listenerRegistry);
135
Jonathan Hart3e594642015-10-20 17:31:24 -0700136 networkConfig.registerConfigFactory(configFactory);
137 networkConfig.addListener(configListener);
138
139 networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
140 subject -> {
141 AccessDeviceConfig config = networkConfig.getConfig(subject, AccessDeviceConfig.class);
142 if (config != null) {
143 AccessDeviceData data = config.getOlt();
144 oltData.put(data.deviceId(), data);
145 }
146 }
147 );
148
alshabib0ccde6d2015-05-30 18:22:36 -0700149 log.info("Started with Application ID {}", appId.id());
150 }
151
152 @Deactivate
153 public void deactivate() {
Jonathan Hart3e594642015-10-20 17:31:24 -0700154 networkConfig.removeListener(configListener);
155 networkConfig.unregisterConfigFactory(configFactory);
alshabib0ccde6d2015-05-30 18:22:36 -0700156 log.info("Stopped");
157 }
158
159 @Modified
160 public void modified(ComponentContext context) {
161 Dictionary<?, ?> properties = context.getProperties();
162
alshabib0ccde6d2015-05-30 18:22:36 -0700163 String s = Tools.get(properties, "uplinkPort");
164 uplinkPort = Strings.isNullOrEmpty(s) ? UPLINK_PORT : Integer.parseInt(s);
165
166 s = Tools.get(properties, "oltDevice");
167 oltDevice = Strings.isNullOrEmpty(s) ? OLT_DEVICE : s;
alshabib0ccde6d2015-05-30 18:22:36 -0700168 }
169
alshabibbeb2dc92015-06-05 13:35:13 -0700170 private short fetchVlanId(PortNumber port) {
171 long p = port.toLong() + OFFSET;
172 if (p > 4095) {
alshabib0ccde6d2015-05-30 18:22:36 -0700173 log.warn("Port Number {} exceeds vlan max", port);
alshabibbeb2dc92015-06-05 13:35:13 -0700174 return -1;
alshabib0ccde6d2015-05-30 18:22:36 -0700175 }
alshabibbeb2dc92015-06-05 13:35:13 -0700176 return (short) p;
177 }
178
alshabibb37fd082015-06-05 15:32:15 -0700179 private void provisionVlanOnPort(String deviceId, int uplinkPort, PortNumber p, short vlanId) {
alshabibca627502015-06-05 15:19:43 -0700180 DeviceId did = DeviceId.deviceId(deviceId);
alshabib0ccde6d2015-05-30 18:22:36 -0700181
182 TrafficSelector upstream = DefaultTrafficSelector.builder()
alshabibbeb2dc92015-06-05 13:35:13 -0700183 .matchVlanId(VlanId.vlanId(vlanId))
alshabib0ccde6d2015-05-30 18:22:36 -0700184 .matchInPort(p)
185 .build();
186
187 TrafficSelector downStream = DefaultTrafficSelector.builder()
alshabibbeb2dc92015-06-05 13:35:13 -0700188 .matchVlanId(VlanId.vlanId(vlanId))
alshabib0ccde6d2015-05-30 18:22:36 -0700189 .matchInPort(PortNumber.portNumber(uplinkPort))
190 .build();
191
192 TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
193 .setOutput(PortNumber.portNumber(uplinkPort))
194 .build();
195
196 TrafficTreatment downStreamTreatment = DefaultTrafficTreatment.builder()
197 .setOutput(p)
198 .build();
199
200
201 ForwardingObjective upFwd = DefaultForwardingObjective.builder()
202 .withFlag(ForwardingObjective.Flag.VERSATILE)
203 .withPriority(1000)
204 .makePermanent()
205 .withSelector(upstream)
206 .fromApp(appId)
207 .withTreatment(upstreamTreatment)
208 .add();
209
210 ForwardingObjective downFwd = DefaultForwardingObjective.builder()
211 .withFlag(ForwardingObjective.Flag.VERSATILE)
212 .withPriority(1000)
213 .makePermanent()
214 .withSelector(downStream)
215 .fromApp(appId)
216 .withTreatment(downStreamTreatment)
217 .add();
218
alshabibca627502015-06-05 15:19:43 -0700219 flowObjectiveService.forward(did, upFwd);
220 flowObjectiveService.forward(did, downFwd);
Jonathan Hart3e594642015-10-20 17:31:24 -0700221 }
alshabib0ccde6d2015-05-30 18:22:36 -0700222
Jonathan Hart3e594642015-10-20 17:31:24 -0700223 @Override
224 public void provisionSubscriber(ConnectPoint port, VlanId vlan) {
225 AccessDeviceData olt = oltData.get(port.deviceId());
226
227 if (olt == null) {
228 log.warn("No data found for OLT device {}", port.deviceId());
229 return;
230 }
231
Jonathan Hart48327842015-11-10 16:09:22 -0800232 provisionVlans(olt.deviceId(), olt.uplink(), port.port(), vlan, olt.vlan(),
233 olt.defaultVlan());
Jonathan Hart3e594642015-10-20 17:31:24 -0700234 }
235
236 private void provisionVlans(DeviceId deviceId, PortNumber uplinkPort,
237 PortNumber subscriberPort,
Jonathan Hart48327842015-11-10 16:09:22 -0800238 VlanId subscriberVlan, VlanId deviceVlan,
239 Optional<VlanId> defaultVlan) {
Jonathan Hart3e594642015-10-20 17:31:24 -0700240
241 TrafficSelector upstream = DefaultTrafficSelector.builder()
Jonathan Hart48327842015-11-10 16:09:22 -0800242 .matchVlanId((defaultVlan.isPresent()) ? defaultVlan.get() : DEFAULT_VLAN)
Jonathan Hart3e594642015-10-20 17:31:24 -0700243 .matchInPort(subscriberPort)
244 .build();
245
246 TrafficSelector downstream = DefaultTrafficSelector.builder()
247 .matchVlanId(deviceVlan)
248 .matchInPort(uplinkPort)
249 .build();
250
251 TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
252 .setVlanId(subscriberVlan)
253 .pushVlan()
254 .setVlanId(deviceVlan)
255 .setOutput(uplinkPort)
256 .build();
257
258 TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
259 .popVlan()
Jonathan Hart48327842015-11-10 16:09:22 -0800260 .setVlanId((defaultVlan.isPresent()) ? defaultVlan.get() : DEFAULT_VLAN)
Jonathan Hart3e594642015-10-20 17:31:24 -0700261 .setOutput(subscriberPort)
262 .build();
263
264
265 ForwardingObjective upFwd = DefaultForwardingObjective.builder()
266 .withFlag(ForwardingObjective.Flag.VERSATILE)
267 .withPriority(1000)
268 .makePermanent()
269 .withSelector(upstream)
270 .fromApp(appId)
271 .withTreatment(upstreamTreatment)
272 .add();
273
274 ForwardingObjective downFwd = DefaultForwardingObjective.builder()
275 .withFlag(ForwardingObjective.Flag.VERSATILE)
276 .withPriority(1000)
277 .makePermanent()
278 .withSelector(downstream)
279 .fromApp(appId)
280 .withTreatment(downstreamTreatment)
281 .add();
282
283 flowObjectiveService.forward(deviceId, upFwd);
284 flowObjectiveService.forward(deviceId, downFwd);
285 }
286
287 @Override
288 public void removeSubscriber(ConnectPoint port) {
289 throw new UnsupportedOperationException("Not yet implemented");
alshabib0ccde6d2015-05-30 18:22:36 -0700290 }
291
292 private class InternalDeviceListener implements DeviceListener {
293 @Override
294 public void event(DeviceEvent event) {
295 DeviceId devId = DeviceId.deviceId(oltDevice);
alshabib6b139b42016-01-12 15:55:53 -0800296 if (!devId.equals(event.subject().id())) {
297 return;
298 }
alshabib0ccde6d2015-05-30 18:22:36 -0700299 switch (event.type()) {
300 case PORT_ADDED:
301 case PORT_UPDATED:
alshabib6b139b42016-01-12 15:55:53 -0800302 if (event.port().isEnabled()) {
alshabibbeb2dc92015-06-05 13:35:13 -0700303 short vlanId = fetchVlanId(event.port().number());
alshabibb37fd082015-06-05 15:32:15 -0700304 provisionVlanOnPort(gfastDevice, uplinkPort, event.port().number(), vlanId);
alshabib0ccde6d2015-05-30 18:22:36 -0700305 }
306 break;
307 case DEVICE_ADDED:
alshabib6b139b42016-01-12 15:55:53 -0800308 post(new AccessDeviceEvent(
309 AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
310 null, null));
311 break;
alshabib0ccde6d2015-05-30 18:22:36 -0700312 case DEVICE_REMOVED:
alshabib6b139b42016-01-12 15:55:53 -0800313 post(new AccessDeviceEvent(
314 AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
315 null, null));
316 break;
317 case DEVICE_UPDATED:
alshabib0ccde6d2015-05-30 18:22:36 -0700318 case DEVICE_SUSPENDED:
319 case DEVICE_AVAILABILITY_CHANGED:
320 case PORT_REMOVED:
321 case PORT_STATS_UPDATED:
322 default:
323 return;
324 }
325 }
326 }
327
Jonathan Hart3e594642015-10-20 17:31:24 -0700328 private class InternalNetworkConfigListener implements NetworkConfigListener {
329 @Override
330 public void event(NetworkConfigEvent event) {
331 switch (event.type()) {
332
333 case CONFIG_ADDED:
334 case CONFIG_UPDATED:
335 if (event.configClass().equals(CONFIG_CLASS)) {
336 AccessDeviceConfig config =
337 networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
338 if (config != null) {
339 oltData.put(config.getOlt().deviceId(), config.getOlt());
340 }
341 }
342 break;
343 case CONFIG_UNREGISTERED:
344 case CONFIG_REMOVED:
345 default:
346 break;
347 }
348 }
349 }
alshabib0ccde6d2015-05-30 18:22:36 -0700350
351}