blob: 46aeeb0a7029d580fc0daba7e0e01f7f98c3dd36 [file] [log] [blame]
Sho SHIMIZUd97a9502015-08-18 10:02:30 -07001/*
2 * Copyright 2015 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.net.newresource.impl;
17
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -080018import com.google.common.collect.Lists;
Sho SHIMIZU44f37612015-11-25 16:23:22 -080019import org.onlab.packet.MplsLabel;
20import org.onlab.packet.VlanId;
21import org.onlab.util.ItemNotFoundException;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070022import org.onosproject.net.Device;
Sho SHIMIZU44f37612015-11-25 16:23:22 -080023import org.onosproject.net.DeviceId;
Sho SHIMIZU08fdbd22015-08-19 16:59:35 -070024import org.onosproject.net.Port;
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +020025import org.onosproject.net.OchPort;
HIGUCHI Yutad39e3762015-12-04 09:43:16 -080026import org.onosproject.net.OchSignal;
Sho SHIMIZU44f37612015-11-25 16:23:22 -080027import org.onosproject.net.PortNumber;
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +020028import org.onosproject.net.TributarySlot;
29import org.onosproject.net.OduSignalType;
HIGUCHI Yutad39e3762015-12-04 09:43:16 -080030import org.onosproject.net.behaviour.LambdaQuery;
Sho SHIMIZU44f37612015-11-25 16:23:22 -080031import org.onosproject.net.behaviour.MplsQuery;
32import org.onosproject.net.behaviour.VlanQuery;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070033import org.onosproject.net.device.DeviceEvent;
34import org.onosproject.net.device.DeviceListener;
HIGUCHI Yuta11d16092015-12-04 23:35:43 -080035import org.onosproject.net.device.DeviceService;
36import org.onosproject.net.driver.Driver;
Sho SHIMIZU44f37612015-11-25 16:23:22 -080037import org.onosproject.net.driver.DriverHandler;
38import org.onosproject.net.driver.DriverService;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070039import org.onosproject.net.newresource.ResourceAdminService;
40import org.onosproject.net.newresource.ResourcePath;
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +020041import org.slf4j.Logger;
42import org.slf4j.LoggerFactory;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070043
HIGUCHI Yutad39e3762015-12-04 09:43:16 -080044import java.util.Collections;
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +020045import java.util.List;
HIGUCHI Yutad39e3762015-12-04 09:43:16 -080046import java.util.SortedSet;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070047import java.util.concurrent.ExecutorService;
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +020048import java.util.stream.Collectors;
49import java.util.stream.IntStream;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070050
51import static com.google.common.base.Preconditions.checkNotNull;
52
53/**
54 * An implementation of DeviceListener registering devices as resources.
55 */
56final class ResourceDeviceListener implements DeviceListener {
57
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +020058 private static final Logger log = LoggerFactory.getLogger(ResourceDeviceListener.class);
59
Sho SHIMIZU44f37612015-11-25 16:23:22 -080060 private static final int MAX_VLAN_ID = VlanId.MAX_VLAN;
61 private static final List<VlanId> ENTIRE_VLAN_IDS = getEntireVlans();
62
63 private static final int MAX_MPLS_LABEL = 1048576;
64 private static final List<MplsLabel> ENTIRE_MPLS_LABELS = getEntireMplsLabels();
65
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +020066 private static final int TOTAL_ODU2_TRIBUTARY_SLOTS = 8;
67 private static final int TOTAL_ODU4_TRIBUTARY_SLOTS = 80;
68 private static final List<TributarySlot> ENTIRE_ODU2_TRIBUTARY_SLOTS = getEntireOdu2TributarySlots();
69 private static final List<TributarySlot> ENTIRE_ODU4_TRIBUTARY_SLOTS = getEntireOdu4TributarySlots();
70
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070071 private final ResourceAdminService adminService;
HIGUCHI Yuta11d16092015-12-04 23:35:43 -080072 private final DeviceService deviceService;
Sho SHIMIZU44f37612015-11-25 16:23:22 -080073 private final DriverService driverService;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070074 private final ExecutorService executor;
75
HIGUCHI Yuta11d16092015-12-04 23:35:43 -080076
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070077 /**
78 * Creates an instance with the specified ResourceAdminService and ExecutorService.
79 *
80 * @param adminService instance invoked to register resources
HIGUCHI Yuta11d16092015-12-04 23:35:43 -080081 * @param deviceService {@link DeviceService} to be used.
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070082 * @param executor executor used for processing resource registration
83 */
HIGUCHI Yuta11d16092015-12-04 23:35:43 -080084 ResourceDeviceListener(ResourceAdminService adminService, DeviceService deviceService, DriverService driverService,
Sho SHIMIZU44f37612015-11-25 16:23:22 -080085 ExecutorService executor) {
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070086 this.adminService = checkNotNull(adminService);
HIGUCHI Yuta11d16092015-12-04 23:35:43 -080087 this.deviceService = checkNotNull(deviceService);
Sho SHIMIZU44f37612015-11-25 16:23:22 -080088 this.driverService = checkNotNull(driverService);
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070089 this.executor = checkNotNull(executor);
90 }
91
92 @Override
93 public void event(DeviceEvent event) {
94 Device device = event.subject();
95 switch (event.type()) {
96 case DEVICE_ADDED:
97 registerDeviceResource(device);
98 break;
Sho SHIMIZUe60a5ab2015-08-20 11:51:49 -070099 case DEVICE_REMOVED:
100 unregisterDeviceResource(device);
101 break;
HIGUCHI Yuta11d16092015-12-04 23:35:43 -0800102 case DEVICE_AVAILABILITY_CHANGED:
103 if (deviceService.isAvailable(device.id())) {
104 registerDeviceResource(device);
105 // TODO: do we need to walk the ports?
106 } else {
107 unregisterDeviceResource(device);
108 }
109 break;
Sho SHIMIZU08fdbd22015-08-19 16:59:35 -0700110 case PORT_ADDED:
HIGUCHI Yuta11d16092015-12-04 23:35:43 -0800111 case PORT_UPDATED:
112 if (event.port().isEnabled()) {
113 registerPortResource(device, event.port());
114 } else {
115 unregisterPortResource(device, event.port());
116 }
Sho SHIMIZUc2ddedd2015-08-20 11:54:29 -0700117 break;
Sho SHIMIZUe2292842015-08-20 11:59:23 -0700118 case PORT_REMOVED:
119 unregisterPortResource(device, event.port());
120 break;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -0700121 default:
122 break;
123 }
124 }
125
126 private void registerDeviceResource(Device device) {
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -0800127 executor.submit(() -> adminService.registerResources(ResourcePath.discrete(device.id())));
Sho SHIMIZUd97a9502015-08-18 10:02:30 -0700128 }
Sho SHIMIZU08fdbd22015-08-19 16:59:35 -0700129
Sho SHIMIZUe60a5ab2015-08-20 11:51:49 -0700130 private void unregisterDeviceResource(Device device) {
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -0800131 executor.submit(() -> adminService.unregisterResources(ResourcePath.discrete(device.id())));
Sho SHIMIZUe60a5ab2015-08-20 11:51:49 -0700132 }
133
Sho SHIMIZU08fdbd22015-08-19 16:59:35 -0700134 private void registerPortResource(Device device, Port port) {
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200135 ResourcePath portPath = ResourcePath.discrete(device.id(), port.number());
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -0800136 executor.submit(() -> {
137 adminService.registerResources(portPath);
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200138
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800139 // for VLAN IDs
140 if (isVlanEnabled(device.id(), port.number())) {
141 adminService.registerResources(Lists.transform(ENTIRE_VLAN_IDS, portPath::child));
142 }
143
144 // for MPLS labels
145 if (isMplsEnabled(device.id(), port.number())) {
146 adminService.registerResources(Lists.transform(ENTIRE_MPLS_LABELS, portPath::child));
147 }
148
HIGUCHI Yutad39e3762015-12-04 09:43:16 -0800149 // for Lambdas
150 SortedSet<OchSignal> lambdas = queryLambdas(device.id(), port.number());
151 if (!lambdas.isEmpty()) {
152 adminService.registerResources(lambdas.stream()
153 .map(portPath::child)
154 .collect(Collectors.toList()));
155 }
156
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800157 // for Tributary slots
158 // TODO: need to define Behaviour to make a query about OCh port
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -0800159 switch (port.type()) {
160 case OCH:
161 // register ODU TributarySlots against the OCH port
162 registerTributarySlotsResources(((OchPort) port).signalType(), portPath);
163 break;
164 default:
165 break;
166 }
167 });
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200168 }
169
170 private void registerTributarySlotsResources(OduSignalType oduSignalType, ResourcePath portPath) {
171 switch (oduSignalType) {
172 case ODU2:
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -0800173 adminService.registerResources(Lists.transform(ENTIRE_ODU2_TRIBUTARY_SLOTS, portPath::child));
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200174 break;
175 case ODU4:
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -0800176 adminService.registerResources(Lists.transform(ENTIRE_ODU4_TRIBUTARY_SLOTS, portPath::child));
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200177 break;
178 default:
179 break;
180 }
Sho SHIMIZU08fdbd22015-08-19 16:59:35 -0700181 }
Sho SHIMIZUe2292842015-08-20 11:59:23 -0700182
183 private void unregisterPortResource(Device device, Port port) {
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -0800184 ResourcePath resource = ResourcePath.discrete(device.id(), port.number());
185 executor.submit(() -> adminService.unregisterResources(resource));
Sho SHIMIZUe2292842015-08-20 11:59:23 -0700186 }
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200187
HIGUCHI Yutad39e3762015-12-04 09:43:16 -0800188 private SortedSet<OchSignal> queryLambdas(DeviceId did, PortNumber port) {
189 try {
HIGUCHI Yuta11d16092015-12-04 23:35:43 -0800190 // DriverHandler does not provide a way to check if a
191 // behaviour is supported.
192 Driver driver = driverService.getDriver(did);
193 if (driver == null || !driver.hasBehaviour(LambdaQuery.class)) {
194 return Collections.emptySortedSet();
195 }
HIGUCHI Yutad39e3762015-12-04 09:43:16 -0800196 DriverHandler handler = driverService.createHandler(did);
197 if (handler == null) {
198 return Collections.emptySortedSet();
199 }
200 LambdaQuery query = handler.behaviour(LambdaQuery.class);
HIGUCHI Yuta11d16092015-12-04 23:35:43 -0800201 if (query != null) {
202 return query.queryLambdas(port);
203 } else {
204 return Collections.emptySortedSet();
205 }
HIGUCHI Yutad39e3762015-12-04 09:43:16 -0800206 } catch (ItemNotFoundException e) {
207 return Collections.emptySortedSet();
208 }
209 }
210
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800211 private boolean isVlanEnabled(DeviceId device, PortNumber port) {
212 try {
HIGUCHI Yuta11d16092015-12-04 23:35:43 -0800213 // DriverHandler does not provide a way to check if a
214 // behaviour is supported.
215 Driver driver = driverService.getDriver(device);
216 if (driver == null || !driver.hasBehaviour(VlanQuery.class)) {
217 // device does not support this
218 return false;
219 }
220
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800221 DriverHandler handler = driverService.createHandler(device);
222 if (handler == null) {
223 return false;
224 }
225
226 VlanQuery query = handler.behaviour(VlanQuery.class);
227 return query != null && query.isEnabled(port);
228 } catch (ItemNotFoundException e) {
229 return false;
230 }
231 }
232
233 private boolean isMplsEnabled(DeviceId device, PortNumber port) {
234 try {
HIGUCHI Yuta11d16092015-12-04 23:35:43 -0800235 // DriverHandler does not provide a way to check if a
236 // behaviour is supported.
237 Driver driver = driverService.getDriver(device);
238 if (driver == null || !driver.hasBehaviour(MplsQuery.class)) {
239 // device does not support this
240 return false;
241 }
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800242 DriverHandler handler = driverService.createHandler(device);
243 if (handler == null) {
244 return false;
245 }
246
247 MplsQuery query = handler.behaviour(MplsQuery.class);
248 return query != null && query.isEnabled(port);
249 } catch (ItemNotFoundException e) {
250 return false;
251 }
252 }
253
254 private static List<VlanId> getEntireVlans() {
255 return IntStream.range(0, MAX_VLAN_ID)
256 .mapToObj(x -> VlanId.vlanId((short) x))
257 .collect(Collectors.toList());
258 }
259
260 private static List<MplsLabel> getEntireMplsLabels() {
261 // potentially many objects are created
262 return IntStream.range(0, MAX_MPLS_LABEL)
263 .mapToObj(MplsLabel::mplsLabel)
264 .collect(Collectors.toList());
265 }
266
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200267 private static List<TributarySlot> getEntireOdu2TributarySlots() {
268 return IntStream.rangeClosed(1, TOTAL_ODU2_TRIBUTARY_SLOTS)
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800269 .mapToObj(TributarySlot::of)
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200270 .collect(Collectors.toList());
271 }
272 private static List<TributarySlot> getEntireOdu4TributarySlots() {
273 return IntStream.rangeClosed(1, TOTAL_ODU4_TRIBUTARY_SLOTS)
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800274 .mapToObj(TributarySlot::of)
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200275 .collect(Collectors.toList());
276 }
Sho SHIMIZUd97a9502015-08-18 10:02:30 -0700277}