blob: 6e944af3ea9be673bd0185dddf35118aca9021bc [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
HIGUCHI Yutab7a15d72015-12-15 09:54:40 -080018import com.google.common.collect.ImmutableSet;
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -080019import com.google.common.collect.Lists;
Sho SHIMIZU44f37612015-11-25 16:23:22 -080020import org.onlab.packet.MplsLabel;
21import org.onlab.packet.VlanId;
22import org.onlab.util.ItemNotFoundException;
Marc De Leenheer2c305302015-12-07 21:37:44 -080023import org.onosproject.net.DefaultOchSignalComparator;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070024import org.onosproject.net.Device;
Sho SHIMIZU44f37612015-11-25 16:23:22 -080025import org.onosproject.net.DeviceId;
Sho SHIMIZU08fdbd22015-08-19 16:59:35 -070026import org.onosproject.net.Port;
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +020027import org.onosproject.net.OchPort;
HIGUCHI Yutad39e3762015-12-04 09:43:16 -080028import org.onosproject.net.OchSignal;
Sho SHIMIZU44f37612015-11-25 16:23:22 -080029import org.onosproject.net.PortNumber;
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +020030import org.onosproject.net.TributarySlot;
31import org.onosproject.net.OduSignalType;
HIGUCHI Yutad39e3762015-12-04 09:43:16 -080032import org.onosproject.net.behaviour.LambdaQuery;
Sho SHIMIZU44f37612015-11-25 16:23:22 -080033import org.onosproject.net.behaviour.MplsQuery;
34import org.onosproject.net.behaviour.VlanQuery;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070035import org.onosproject.net.device.DeviceEvent;
36import org.onosproject.net.device.DeviceListener;
HIGUCHI Yuta11d16092015-12-04 23:35:43 -080037import org.onosproject.net.device.DeviceService;
38import org.onosproject.net.driver.Driver;
Sho SHIMIZU44f37612015-11-25 16:23:22 -080039import org.onosproject.net.driver.DriverHandler;
40import org.onosproject.net.driver.DriverService;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070041import org.onosproject.net.newresource.ResourceAdminService;
42import org.onosproject.net.newresource.ResourcePath;
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +020043import org.slf4j.Logger;
44import org.slf4j.LoggerFactory;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070045
HIGUCHI Yutad39e3762015-12-04 09:43:16 -080046import java.util.Collections;
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +020047import java.util.List;
HIGUCHI Yutab7a15d72015-12-15 09:54:40 -080048import java.util.Set;
HIGUCHI Yutad39e3762015-12-04 09:43:16 -080049import java.util.SortedSet;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070050import java.util.concurrent.ExecutorService;
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +020051import java.util.stream.Collectors;
52import java.util.stream.IntStream;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070053
54import static com.google.common.base.Preconditions.checkNotNull;
55
56/**
57 * An implementation of DeviceListener registering devices as resources.
58 */
59final class ResourceDeviceListener implements DeviceListener {
60
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +020061 private static final Logger log = LoggerFactory.getLogger(ResourceDeviceListener.class);
62
63 private static final int TOTAL_ODU2_TRIBUTARY_SLOTS = 8;
64 private static final int TOTAL_ODU4_TRIBUTARY_SLOTS = 80;
65 private static final List<TributarySlot> ENTIRE_ODU2_TRIBUTARY_SLOTS = getEntireOdu2TributarySlots();
66 private static final List<TributarySlot> ENTIRE_ODU4_TRIBUTARY_SLOTS = getEntireOdu4TributarySlots();
67
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070068 private final ResourceAdminService adminService;
HIGUCHI Yuta11d16092015-12-04 23:35:43 -080069 private final DeviceService deviceService;
Sho SHIMIZU44f37612015-11-25 16:23:22 -080070 private final DriverService driverService;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070071 private final ExecutorService executor;
72
HIGUCHI Yuta11d16092015-12-04 23:35:43 -080073
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070074 /**
75 * Creates an instance with the specified ResourceAdminService and ExecutorService.
76 *
77 * @param adminService instance invoked to register resources
HIGUCHI Yuta11d16092015-12-04 23:35:43 -080078 * @param deviceService {@link DeviceService} to be used.
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070079 * @param executor executor used for processing resource registration
80 */
HIGUCHI Yuta11d16092015-12-04 23:35:43 -080081 ResourceDeviceListener(ResourceAdminService adminService, DeviceService deviceService, DriverService driverService,
Sho SHIMIZU44f37612015-11-25 16:23:22 -080082 ExecutorService executor) {
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070083 this.adminService = checkNotNull(adminService);
HIGUCHI Yuta11d16092015-12-04 23:35:43 -080084 this.deviceService = checkNotNull(deviceService);
Sho SHIMIZU44f37612015-11-25 16:23:22 -080085 this.driverService = checkNotNull(driverService);
Sho SHIMIZUd97a9502015-08-18 10:02:30 -070086 this.executor = checkNotNull(executor);
87 }
88
89 @Override
90 public void event(DeviceEvent event) {
91 Device device = event.subject();
92 switch (event.type()) {
93 case DEVICE_ADDED:
94 registerDeviceResource(device);
95 break;
Sho SHIMIZUe60a5ab2015-08-20 11:51:49 -070096 case DEVICE_REMOVED:
97 unregisterDeviceResource(device);
98 break;
HIGUCHI Yuta11d16092015-12-04 23:35:43 -080099 case DEVICE_AVAILABILITY_CHANGED:
100 if (deviceService.isAvailable(device.id())) {
101 registerDeviceResource(device);
102 // TODO: do we need to walk the ports?
103 } else {
104 unregisterDeviceResource(device);
105 }
106 break;
Sho SHIMIZU08fdbd22015-08-19 16:59:35 -0700107 case PORT_ADDED:
HIGUCHI Yuta11d16092015-12-04 23:35:43 -0800108 case PORT_UPDATED:
109 if (event.port().isEnabled()) {
110 registerPortResource(device, event.port());
111 } else {
112 unregisterPortResource(device, event.port());
113 }
Sho SHIMIZUc2ddedd2015-08-20 11:54:29 -0700114 break;
Sho SHIMIZUe2292842015-08-20 11:59:23 -0700115 case PORT_REMOVED:
116 unregisterPortResource(device, event.port());
117 break;
Sho SHIMIZUd97a9502015-08-18 10:02:30 -0700118 default:
119 break;
120 }
121 }
122
123 private void registerDeviceResource(Device device) {
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -0800124 executor.submit(() -> adminService.registerResources(ResourcePath.discrete(device.id())));
Sho SHIMIZUd97a9502015-08-18 10:02:30 -0700125 }
Sho SHIMIZU08fdbd22015-08-19 16:59:35 -0700126
Sho SHIMIZUe60a5ab2015-08-20 11:51:49 -0700127 private void unregisterDeviceResource(Device device) {
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -0800128 executor.submit(() -> adminService.unregisterResources(ResourcePath.discrete(device.id())));
Sho SHIMIZUe60a5ab2015-08-20 11:51:49 -0700129 }
130
Sho SHIMIZU08fdbd22015-08-19 16:59:35 -0700131 private void registerPortResource(Device device, Port port) {
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200132 ResourcePath portPath = ResourcePath.discrete(device.id(), port.number());
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -0800133 executor.submit(() -> {
134 adminService.registerResources(portPath);
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200135
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800136 // for VLAN IDs
HIGUCHI Yutab7a15d72015-12-15 09:54:40 -0800137 Set<VlanId> vlans = queryVlanIds(device.id(), port.number());
138 if (!vlans.isEmpty()) {
139 adminService.registerResources(vlans.stream()
140 .map(portPath::child)
141 .collect(Collectors.toList()));
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800142 }
143
144 // for MPLS labels
HIGUCHI Yutab7a15d72015-12-15 09:54:40 -0800145 Set<MplsLabel> mplsLabels = queryMplsLabels(device.id(), port.number());
146 if (!mplsLabels.isEmpty()) {
147 adminService.registerResources(mplsLabels.stream()
148 .map(portPath::child)
149 .collect(Collectors.toList()));
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800150 }
151
HIGUCHI Yutad39e3762015-12-04 09:43:16 -0800152 // for Lambdas
153 SortedSet<OchSignal> lambdas = queryLambdas(device.id(), port.number());
154 if (!lambdas.isEmpty()) {
155 adminService.registerResources(lambdas.stream()
156 .map(portPath::child)
157 .collect(Collectors.toList()));
158 }
159
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800160 // for Tributary slots
161 // TODO: need to define Behaviour to make a query about OCh port
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -0800162 switch (port.type()) {
163 case OCH:
164 // register ODU TributarySlots against the OCH port
165 registerTributarySlotsResources(((OchPort) port).signalType(), portPath);
166 break;
167 default:
168 break;
169 }
170 });
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200171 }
172
173 private void registerTributarySlotsResources(OduSignalType oduSignalType, ResourcePath portPath) {
174 switch (oduSignalType) {
175 case ODU2:
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -0800176 adminService.registerResources(Lists.transform(ENTIRE_ODU2_TRIBUTARY_SLOTS, portPath::child));
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200177 break;
178 case ODU4:
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -0800179 adminService.registerResources(Lists.transform(ENTIRE_ODU4_TRIBUTARY_SLOTS, portPath::child));
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200180 break;
181 default:
182 break;
183 }
Sho SHIMIZU08fdbd22015-08-19 16:59:35 -0700184 }
Sho SHIMIZUe2292842015-08-20 11:59:23 -0700185
186 private void unregisterPortResource(Device device, Port port) {
Sho SHIMIZU2c7cecf2015-11-11 14:16:14 -0800187 ResourcePath resource = ResourcePath.discrete(device.id(), port.number());
188 executor.submit(() -> adminService.unregisterResources(resource));
Sho SHIMIZUe2292842015-08-20 11:59:23 -0700189 }
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200190
HIGUCHI Yutad39e3762015-12-04 09:43:16 -0800191 private SortedSet<OchSignal> queryLambdas(DeviceId did, PortNumber port) {
192 try {
HIGUCHI Yuta11d16092015-12-04 23:35:43 -0800193 // DriverHandler does not provide a way to check if a
194 // behaviour is supported.
195 Driver driver = driverService.getDriver(did);
196 if (driver == null || !driver.hasBehaviour(LambdaQuery.class)) {
197 return Collections.emptySortedSet();
198 }
HIGUCHI Yutad39e3762015-12-04 09:43:16 -0800199 DriverHandler handler = driverService.createHandler(did);
200 if (handler == null) {
201 return Collections.emptySortedSet();
202 }
203 LambdaQuery query = handler.behaviour(LambdaQuery.class);
HIGUCHI Yuta11d16092015-12-04 23:35:43 -0800204 if (query != null) {
Marc De Leenheer2c305302015-12-07 21:37:44 -0800205 return query.queryLambdas(port).stream()
206 .flatMap(x -> OchSignal.toFlexGrid(x).stream())
Marc De Leenheercef45552015-12-14 19:59:59 -0800207 .collect(Collectors.toCollection(DefaultOchSignalComparator::newOchSignalTreeSet));
HIGUCHI Yuta11d16092015-12-04 23:35:43 -0800208 } else {
209 return Collections.emptySortedSet();
210 }
HIGUCHI Yutad39e3762015-12-04 09:43:16 -0800211 } catch (ItemNotFoundException e) {
212 return Collections.emptySortedSet();
213 }
214 }
215
HIGUCHI Yutab7a15d72015-12-15 09:54:40 -0800216 private Set<VlanId> queryVlanIds(DeviceId device, PortNumber port) {
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800217 try {
HIGUCHI Yuta11d16092015-12-04 23:35:43 -0800218 // DriverHandler does not provide a way to check if a
219 // behaviour is supported.
220 Driver driver = driverService.getDriver(device);
221 if (driver == null || !driver.hasBehaviour(VlanQuery.class)) {
222 // device does not support this
HIGUCHI Yutab7a15d72015-12-15 09:54:40 -0800223 return ImmutableSet.of();
HIGUCHI Yuta11d16092015-12-04 23:35:43 -0800224 }
225
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800226 DriverHandler handler = driverService.createHandler(device);
227 if (handler == null) {
HIGUCHI Yutab7a15d72015-12-15 09:54:40 -0800228 return ImmutableSet.of();
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800229 }
230
231 VlanQuery query = handler.behaviour(VlanQuery.class);
HIGUCHI Yutab7a15d72015-12-15 09:54:40 -0800232 if (query == null) {
233 return ImmutableSet.of();
234 }
235 return query.queryVlanIds(port);
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800236 } catch (ItemNotFoundException e) {
HIGUCHI Yutab7a15d72015-12-15 09:54:40 -0800237 return ImmutableSet.of();
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800238 }
239 }
240
HIGUCHI Yutab7a15d72015-12-15 09:54:40 -0800241 private Set<MplsLabel> queryMplsLabels(DeviceId device, PortNumber port) {
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800242 try {
HIGUCHI Yuta11d16092015-12-04 23:35:43 -0800243 // DriverHandler does not provide a way to check if a
244 // behaviour is supported.
245 Driver driver = driverService.getDriver(device);
246 if (driver == null || !driver.hasBehaviour(MplsQuery.class)) {
247 // device does not support this
HIGUCHI Yutab7a15d72015-12-15 09:54:40 -0800248 return ImmutableSet.of();
HIGUCHI Yuta11d16092015-12-04 23:35:43 -0800249 }
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800250 DriverHandler handler = driverService.createHandler(device);
251 if (handler == null) {
HIGUCHI Yutab7a15d72015-12-15 09:54:40 -0800252 return ImmutableSet.of();
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800253 }
254
255 MplsQuery query = handler.behaviour(MplsQuery.class);
HIGUCHI Yutab7a15d72015-12-15 09:54:40 -0800256 if (query == null) {
257 return ImmutableSet.of();
258 }
259 return query.queryMplsLabels(port);
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800260 } catch (ItemNotFoundException e) {
HIGUCHI Yutab7a15d72015-12-15 09:54:40 -0800261 return ImmutableSet.of();
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800262 }
263 }
264
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200265 private static List<TributarySlot> getEntireOdu2TributarySlots() {
266 return IntStream.rangeClosed(1, TOTAL_ODU2_TRIBUTARY_SLOTS)
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800267 .mapToObj(TributarySlot::of)
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200268 .collect(Collectors.toList());
269 }
270 private static List<TributarySlot> getEntireOdu4TributarySlots() {
271 return IntStream.rangeClosed(1, TOTAL_ODU4_TRIBUTARY_SLOTS)
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800272 .mapToObj(TributarySlot::of)
Rimon Ashkenazye2410ff2015-11-10 14:11:08 +0200273 .collect(Collectors.toList());
274 }
Sho SHIMIZUd97a9502015-08-18 10:02:30 -0700275}