blob: 9aa8865a8fdb20922c83053d1949491b00e96006 [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 */
16package org.onosproject.olt;
17
alshabibf0e7e702015-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 Harte533a422015-10-20 17:31:24 -070026import org.apache.felix.scr.annotations.Service;
alshabibf0e7e702015-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;
Jonathan Harte533a422015-10-20 17:31:24 -070031import org.onosproject.net.ConnectPoint;
alshabibf0e7e702015-05-30 18:22:36 -070032import org.onosproject.net.DeviceId;
Sho SHIMIZU25005432015-09-02 18:38:12 -070033import org.onosproject.net.Port;
alshabibf0e7e702015-05-30 18:22:36 -070034import org.onosproject.net.PortNumber;
Jonathan Harte533a422015-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;
alshabibf0e7e702015-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;
50import org.osgi.service.component.ComponentContext;
51import org.slf4j.Logger;
52
53import java.util.Dictionary;
Jonathan Harte533a422015-10-20 17:31:24 -070054import java.util.Map;
55import java.util.concurrent.ConcurrentHashMap;
alshabibf0e7e702015-05-30 18:22:36 -070056
57import static org.slf4j.LoggerFactory.getLogger;
58
59/**
Jonathan Harte533a422015-10-20 17:31:24 -070060 * Provisions rules on access devices.
alshabibf0e7e702015-05-30 18:22:36 -070061 */
Jonathan Harte533a422015-10-20 17:31:24 -070062@Service
alshabibf0e7e702015-05-30 18:22:36 -070063@Component(immediate = true)
Jonathan Harte533a422015-10-20 17:31:24 -070064public class OLT implements AccessDeviceService {
alshabibf0e7e702015-05-30 18:22:36 -070065 private final Logger log = getLogger(getClass());
66
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected FlowObjectiveService flowObjectiveService;
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected DeviceService deviceService;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected CoreService coreService;
75
Jonathan Harte533a422015-10-20 17:31:24 -070076 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected NetworkConfigRegistry networkConfig;
78
alshabibf0e7e702015-05-30 18:22:36 -070079 private final DeviceListener deviceListener = new InternalDeviceListener();
80
81 private ApplicationId appId;
82
Jonathan Harte533a422015-10-20 17:31:24 -070083 private static final VlanId DEFAULT_VLAN = VlanId.vlanId((short) 0);
alshabibcf3eb952015-06-01 10:57:31 -070084 public static final int OFFSET = 200;
85
alshabibf0e7e702015-05-30 18:22:36 -070086 public static final int UPLINK_PORT = 129;
alshabib3d581752015-06-05 15:32:15 -070087 public static final int GFAST_UPLINK_PORT = 100;
alshabibf0e7e702015-05-30 18:22:36 -070088
89 public static final String OLT_DEVICE = "of:90e2ba82f97791e9";
alshabib4ae2b402015-06-05 14:55:24 -070090 public static final String GFAST_DEVICE = "of:0011223344551357";
alshabibf0e7e702015-05-30 18:22:36 -070091
92 @Property(name = "uplinkPort", intValue = UPLINK_PORT,
93 label = "The OLT's uplink port number")
94 private int uplinkPort = UPLINK_PORT;
95
alshabib3d581752015-06-05 15:32:15 -070096 @Property(name = "gfastUplink", intValue = GFAST_UPLINK_PORT,
97 label = "The OLT's uplink port number")
98 private int gfastUplink = GFAST_UPLINK_PORT;
99
alshabibf0e7e702015-05-30 18:22:36 -0700100 //TODO: replace this with an annotation lookup
101 @Property(name = "oltDevice", value = OLT_DEVICE,
102 label = "The OLT device id")
103 private String oltDevice = OLT_DEVICE;
104
alshabib4ae2b402015-06-05 14:55:24 -0700105 @Property(name = "gfastDevice", value = GFAST_DEVICE,
106 label = "The gfast device id")
107 private String gfastDevice = GFAST_DEVICE;
108
Jonathan Harte533a422015-10-20 17:31:24 -0700109 private Map<DeviceId, AccessDeviceData> oltData = new ConcurrentHashMap<>();
110
111 private InternalNetworkConfigListener configListener =
112 new InternalNetworkConfigListener();
113 private static final Class<AccessDeviceConfig> CONFIG_CLASS =
114 AccessDeviceConfig.class;
115
116 private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
117 new ConfigFactory<DeviceId, AccessDeviceConfig>(
118 SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
119 @Override
120 public AccessDeviceConfig createConfig() {
121 return new AccessDeviceConfig();
122 }
123 };
alshabibf0e7e702015-05-30 18:22:36 -0700124
125 @Activate
126 public void activate() {
alshabib4ae2b402015-06-05 14:55:24 -0700127 appId = coreService.registerApplication("org.onosproject.olt");
alshabibc4dfe852015-06-05 13:35:13 -0700128
Jonathan Harte533a422015-10-20 17:31:24 -0700129 networkConfig.registerConfigFactory(configFactory);
130 networkConfig.addListener(configListener);
131
132 networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
133 subject -> {
134 AccessDeviceConfig config = networkConfig.getConfig(subject, AccessDeviceConfig.class);
135 if (config != null) {
136 AccessDeviceData data = config.getOlt();
137 oltData.put(data.deviceId(), data);
138 }
139 }
140 );
141
Jonathan Harte78d7772015-07-01 14:49:56 -0700142 /*deviceService.addListener(deviceListener);
Jonathan Hart688c04f2015-06-10 18:19:41 -0700143
alshabibf0e7e702015-05-30 18:22:36 -0700144 deviceService.getPorts(DeviceId.deviceId(oltDevice)).stream().forEach(
145 port -> {
alshabibde5538f92015-06-05 15:19:43 -0700146 if (!port.number().isLogical() && port.isEnabled()) {
alshabibc4dfe852015-06-05 13:35:13 -0700147 short vlanId = fetchVlanId(port.number());
alshabibde5538f92015-06-05 15:19:43 -0700148 if (vlanId > 0) {
alshabib3d581752015-06-05 15:32:15 -0700149 provisionVlanOnPort(oltDevice, uplinkPort, port.number(), (short) 7);
150 provisionVlanOnPort(oltDevice, uplinkPort, port.number(), vlanId);
alshabibde5538f92015-06-05 15:19:43 -0700151 }
alshabibf0e7e702015-05-30 18:22:36 -0700152 }
153 }
Jonathan Harte78d7772015-07-01 14:49:56 -0700154 );*/
alshabib4ae2b402015-06-05 14:55:24 -0700155
156
Sho SHIMIZU25005432015-09-02 18:38:12 -0700157 deviceService.getPorts(DeviceId.deviceId(gfastDevice)).stream()
158 .filter(port -> !port.number().isLogical())
159 .filter(Port::isEnabled)
160 .forEach(port -> {
161 short vlanId = (short) (fetchVlanId(port.number()) + OFFSET);
162 if (vlanId > 0) {
163 provisionVlanOnPort(gfastDevice, gfastUplink, port.number(), vlanId);
164 }
alshabibde5538f92015-06-05 15:19:43 -0700165 }
Sho SHIMIZU25005432015-09-02 18:38:12 -0700166 );
alshabibf0e7e702015-05-30 18:22:36 -0700167 log.info("Started with Application ID {}", appId.id());
168 }
169
170 @Deactivate
171 public void deactivate() {
Jonathan Harte533a422015-10-20 17:31:24 -0700172 networkConfig.removeListener(configListener);
173 networkConfig.unregisterConfigFactory(configFactory);
alshabibf0e7e702015-05-30 18:22:36 -0700174 log.info("Stopped");
175 }
176
177 @Modified
178 public void modified(ComponentContext context) {
179 Dictionary<?, ?> properties = context.getProperties();
180
alshabibf0e7e702015-05-30 18:22:36 -0700181 String s = Tools.get(properties, "uplinkPort");
182 uplinkPort = Strings.isNullOrEmpty(s) ? UPLINK_PORT : Integer.parseInt(s);
183
184 s = Tools.get(properties, "oltDevice");
185 oltDevice = Strings.isNullOrEmpty(s) ? OLT_DEVICE : s;
alshabibf0e7e702015-05-30 18:22:36 -0700186 }
187
alshabibc4dfe852015-06-05 13:35:13 -0700188 private short fetchVlanId(PortNumber port) {
189 long p = port.toLong() + OFFSET;
190 if (p > 4095) {
alshabibf0e7e702015-05-30 18:22:36 -0700191 log.warn("Port Number {} exceeds vlan max", port);
alshabibc4dfe852015-06-05 13:35:13 -0700192 return -1;
alshabibf0e7e702015-05-30 18:22:36 -0700193 }
alshabibc4dfe852015-06-05 13:35:13 -0700194 return (short) p;
195 }
196
alshabib3d581752015-06-05 15:32:15 -0700197 private void provisionVlanOnPort(String deviceId, int uplinkPort, PortNumber p, short vlanId) {
alshabibde5538f92015-06-05 15:19:43 -0700198 DeviceId did = DeviceId.deviceId(deviceId);
alshabibf0e7e702015-05-30 18:22:36 -0700199
200 TrafficSelector upstream = DefaultTrafficSelector.builder()
alshabibc4dfe852015-06-05 13:35:13 -0700201 .matchVlanId(VlanId.vlanId(vlanId))
alshabibf0e7e702015-05-30 18:22:36 -0700202 .matchInPort(p)
203 .build();
204
205 TrafficSelector downStream = DefaultTrafficSelector.builder()
alshabibc4dfe852015-06-05 13:35:13 -0700206 .matchVlanId(VlanId.vlanId(vlanId))
alshabibf0e7e702015-05-30 18:22:36 -0700207 .matchInPort(PortNumber.portNumber(uplinkPort))
208 .build();
209
210 TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
211 .setOutput(PortNumber.portNumber(uplinkPort))
212 .build();
213
214 TrafficTreatment downStreamTreatment = DefaultTrafficTreatment.builder()
215 .setOutput(p)
216 .build();
217
218
219 ForwardingObjective upFwd = DefaultForwardingObjective.builder()
220 .withFlag(ForwardingObjective.Flag.VERSATILE)
221 .withPriority(1000)
222 .makePermanent()
223 .withSelector(upstream)
224 .fromApp(appId)
225 .withTreatment(upstreamTreatment)
226 .add();
227
228 ForwardingObjective downFwd = DefaultForwardingObjective.builder()
229 .withFlag(ForwardingObjective.Flag.VERSATILE)
230 .withPriority(1000)
231 .makePermanent()
232 .withSelector(downStream)
233 .fromApp(appId)
234 .withTreatment(downStreamTreatment)
235 .add();
236
alshabibde5538f92015-06-05 15:19:43 -0700237 flowObjectiveService.forward(did, upFwd);
238 flowObjectiveService.forward(did, downFwd);
Jonathan Harte533a422015-10-20 17:31:24 -0700239 }
alshabibf0e7e702015-05-30 18:22:36 -0700240
Jonathan Harte533a422015-10-20 17:31:24 -0700241 @Override
242 public void provisionSubscriber(ConnectPoint port, VlanId vlan) {
243 AccessDeviceData olt = oltData.get(port.deviceId());
244
245 if (olt == null) {
246 log.warn("No data found for OLT device {}", port.deviceId());
247 return;
248 }
249
250 provisionVlans(olt.deviceId(), olt.uplink(), port.port(), vlan, olt.vlan());
251 }
252
253 private void provisionVlans(DeviceId deviceId, PortNumber uplinkPort,
254 PortNumber subscriberPort,
255 VlanId subscriberVlan, VlanId deviceVlan) {
256
257 TrafficSelector upstream = DefaultTrafficSelector.builder()
258 .matchVlanId(DEFAULT_VLAN)
259 .matchInPort(subscriberPort)
260 .build();
261
262 TrafficSelector downstream = DefaultTrafficSelector.builder()
263 .matchVlanId(deviceVlan)
264 .matchInPort(uplinkPort)
265 .build();
266
267 TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
268 .setVlanId(subscriberVlan)
269 .pushVlan()
270 .setVlanId(deviceVlan)
271 .setOutput(uplinkPort)
272 .build();
273
274 TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
275 .popVlan()
276 .setVlanId(DEFAULT_VLAN)
277 .setOutput(subscriberPort)
278 .build();
279
280
281 ForwardingObjective upFwd = DefaultForwardingObjective.builder()
282 .withFlag(ForwardingObjective.Flag.VERSATILE)
283 .withPriority(1000)
284 .makePermanent()
285 .withSelector(upstream)
286 .fromApp(appId)
287 .withTreatment(upstreamTreatment)
288 .add();
289
290 ForwardingObjective downFwd = DefaultForwardingObjective.builder()
291 .withFlag(ForwardingObjective.Flag.VERSATILE)
292 .withPriority(1000)
293 .makePermanent()
294 .withSelector(downstream)
295 .fromApp(appId)
296 .withTreatment(downstreamTreatment)
297 .add();
298
299 flowObjectiveService.forward(deviceId, upFwd);
300 flowObjectiveService.forward(deviceId, downFwd);
301 }
302
303 @Override
304 public void removeSubscriber(ConnectPoint port) {
305 throw new UnsupportedOperationException("Not yet implemented");
alshabibf0e7e702015-05-30 18:22:36 -0700306 }
307
308 private class InternalDeviceListener implements DeviceListener {
309 @Override
310 public void event(DeviceEvent event) {
311 DeviceId devId = DeviceId.deviceId(oltDevice);
312 switch (event.type()) {
313 case PORT_ADDED:
314 case PORT_UPDATED:
315 if (devId.equals(event.subject().id()) && event.port().isEnabled()) {
alshabibc4dfe852015-06-05 13:35:13 -0700316 short vlanId = fetchVlanId(event.port().number());
alshabib3d581752015-06-05 15:32:15 -0700317 provisionVlanOnPort(gfastDevice, uplinkPort, event.port().number(), vlanId);
alshabibf0e7e702015-05-30 18:22:36 -0700318 }
319 break;
320 case DEVICE_ADDED:
321 case DEVICE_UPDATED:
322 case DEVICE_REMOVED:
323 case DEVICE_SUSPENDED:
324 case DEVICE_AVAILABILITY_CHANGED:
325 case PORT_REMOVED:
326 case PORT_STATS_UPDATED:
327 default:
328 return;
329 }
330 }
331 }
332
Jonathan Harte533a422015-10-20 17:31:24 -0700333 private class InternalNetworkConfigListener implements NetworkConfigListener {
334 @Override
335 public void event(NetworkConfigEvent event) {
336 switch (event.type()) {
337
338 case CONFIG_ADDED:
339 case CONFIG_UPDATED:
340 if (event.configClass().equals(CONFIG_CLASS)) {
341 AccessDeviceConfig config =
342 networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
343 if (config != null) {
344 oltData.put(config.getOlt().deviceId(), config.getOlt());
345 }
346 }
347 break;
348 case CONFIG_UNREGISTERED:
349 case CONFIG_REMOVED:
350 default:
351 break;
352 }
353 }
354 }
alshabibf0e7e702015-05-30 18:22:36 -0700355
356}