blob: 02d56646304baf658b482a699d861cf1467e3feb [file] [log] [blame]
cheng fan48e832c2015-05-29 01:54:47 +08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
cheng fan48e832c2015-05-29 01:54:47 +08003 *
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.provider.pcep.topology.impl;
17
cheng fan48e832c2015-05-29 01:54:47 +080018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.onlab.packet.ChassisId;
cheng fan48e832c2015-05-29 01:54:47 +080024import org.onosproject.net.ConnectPoint;
25import org.onosproject.net.DefaultAnnotations;
26import org.onosproject.net.Device;
27import org.onosproject.net.DeviceId;
cheng fan48e832c2015-05-29 01:54:47 +080028import org.onosproject.net.Link.Type;
Andrea Campanella5d73df72017-05-09 14:26:00 -070029import org.onosproject.net.SparseAnnotations;
Avantika-Huaweife44ea62016-05-27 19:21:24 +053030import org.onosproject.net.config.ConfigFactory;
31import org.onosproject.net.config.NetworkConfigRegistry;
32import org.onosproject.net.config.NetworkConfigService;
33import org.onosproject.net.config.basics.SubjectFactories;
cheng fan48e832c2015-05-29 01:54:47 +080034import org.onosproject.net.MastershipRole;
chengfan359abf72015-07-02 23:33:16 +080035import org.onosproject.net.Port;
Saurav Dasa2d37502016-03-25 17:50:40 -070036import org.onosproject.net.PortNumber;
cheng fan48e832c2015-05-29 01:54:47 +080037import org.onosproject.net.device.DefaultDeviceDescription;
38import org.onosproject.net.device.DefaultPortDescription;
39import org.onosproject.net.device.DeviceDescription;
40import org.onosproject.net.device.DeviceProvider;
41import org.onosproject.net.device.DeviceProviderRegistry;
42import org.onosproject.net.device.DeviceProviderService;
43import org.onosproject.net.device.DeviceService;
44import org.onosproject.net.device.PortDescription;
45import org.onosproject.net.link.DefaultLinkDescription;
46import org.onosproject.net.link.LinkDescription;
47import org.onosproject.net.link.LinkProvider;
48import org.onosproject.net.link.LinkProviderRegistry;
49import org.onosproject.net.link.LinkProviderService;
cheng fan48e832c2015-05-29 01:54:47 +080050import org.onosproject.net.provider.AbstractProvider;
51import org.onosproject.net.provider.ProviderId;
Avantika-Huaweife44ea62016-05-27 19:21:24 +053052import org.onosproject.pcep.api.DeviceCapability;
cheng fan48e832c2015-05-29 01:54:47 +080053import org.onosproject.pcep.api.PcepController;
54import org.onosproject.pcep.api.PcepDpid;
55import org.onosproject.pcep.api.PcepLink;
56import org.onosproject.pcep.api.PcepLinkListener;
57import org.onosproject.pcep.api.PcepOperator.OperationType;
58import org.onosproject.pcep.api.PcepSwitch;
59import org.onosproject.pcep.api.PcepSwitchListener;
harikrushna-Huaweia2c7c202017-04-10 18:22:00 +053060import org.onosproject.pcep.server.PccId;
61import org.onosproject.pcep.server.PcepClient;
62import org.onosproject.pcep.server.PcepClientController;
63import org.onosproject.pcep.server.PcepNodeListener;
cheng fan48e832c2015-05-29 01:54:47 +080064import org.slf4j.Logger;
65import org.slf4j.LoggerFactory;
66
chengfan359abf72015-07-02 23:33:16 +080067import java.util.ArrayList;
68import java.util.HashMap;
69import java.util.List;
70
71import static com.google.common.base.Preconditions.checkNotNull;
72import static org.onosproject.net.DeviceId.deviceId;
73import static org.onosproject.pcep.api.PcepDpid.uri;
74
cheng fan48e832c2015-05-29 01:54:47 +080075/**
76 * Provider which uses an PCEP controller to detect network infrastructure
77 * topology.
78 */
79@Component(immediate = true)
80public class PcepTopologyProvider extends AbstractProvider
81 implements LinkProvider, DeviceProvider {
82
Priyanka B9bee0802016-04-27 22:06:02 +053083 /**
84 * Creates instance of PCEP topology provider.
85 */
cheng fan48e832c2015-05-29 01:54:47 +080086 public PcepTopologyProvider() {
Priyanka Bcdf9b102016-06-07 20:01:38 +053087 //In BGP-PCEP app, since both BGP and PCEP topology provider have same scheme
88 //so BGP will be primary and PCEP topology provider will be ancillary.
89 super(new ProviderId("l3", "org.onosproject.provider.pcep", true));
cheng fan48e832c2015-05-29 01:54:47 +080090 }
91
92 private static final Logger log = LoggerFactory
93 .getLogger(PcepTopologyProvider.class);
94
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected LinkProviderRegistry linkProviderRegistry;
97
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected DeviceProviderRegistry deviceProviderRegistry;
100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected PcepController controller;
103
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected DeviceService deviceService;
106
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Priyanka B94395bf2016-05-21 18:39:46 +0530108 protected PcepClientController pcepClientController;
109
Avantika-Huaweife44ea62016-05-27 19:21:24 +0530110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected NetworkConfigRegistry netConfigRegistry;
112
113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
114 protected NetworkConfigService netConfigService;
115
cheng fan48e832c2015-05-29 01:54:47 +0800116 private DeviceProviderService deviceProviderService;
117 private LinkProviderService linkProviderService;
chengfan359abf72015-07-02 23:33:16 +0800118
119 private HashMap<Long, List<PortDescription>> portMap = new HashMap<>();
cheng fan48e832c2015-05-29 01:54:47 +0800120 private InternalLinkProvider listener = new InternalLinkProvider();
121
Avantika-Huaweife44ea62016-05-27 19:21:24 +0530122 private final ConfigFactory<DeviceId, DeviceCapability> configFactory =
123 new ConfigFactory<DeviceId, DeviceCapability>(SubjectFactories.DEVICE_SUBJECT_FACTORY,
Avantika-Huawei3524d852016-06-04 20:44:13 +0530124 DeviceCapability.class, "deviceCapability", false) {
Avantika-Huaweife44ea62016-05-27 19:21:24 +0530125 @Override
126 public DeviceCapability createConfig() {
127 return new DeviceCapability();
128 }
129 };
Priyanka B94395bf2016-05-21 18:39:46 +0530130
cheng fan48e832c2015-05-29 01:54:47 +0800131 @Activate
132 public void activate() {
133 linkProviderService = linkProviderRegistry.register(this);
134 deviceProviderService = deviceProviderRegistry.register(this);
135 controller.addListener(listener);
136 controller.addLinkListener(listener);
Priyanka B94395bf2016-05-21 18:39:46 +0530137 pcepClientController.addNodeListener(listener);
Avantika-Huaweife44ea62016-05-27 19:21:24 +0530138 netConfigRegistry.registerConfigFactory(configFactory);
Priyanka Bcdf9b102016-06-07 20:01:38 +0530139 log.info("Started");
cheng fan48e832c2015-05-29 01:54:47 +0800140 }
141
142 @Deactivate
143 public void deactivate() {
144 linkProviderRegistry.unregister(this);
145 linkProviderService = null;
146 controller.removeListener(listener);
147 controller.removeLinkListener(listener);
Priyanka B94395bf2016-05-21 18:39:46 +0530148 pcepClientController.removeNodeListener(listener);
Avantika-Huaweife44ea62016-05-27 19:21:24 +0530149 netConfigRegistry.unregisterConfigFactory(configFactory);
Priyanka Bcdf9b102016-06-07 20:01:38 +0530150 log.info("Stopped");
cheng fan48e832c2015-05-29 01:54:47 +0800151 }
152
chengfan359abf72015-07-02 23:33:16 +0800153 private List<PortDescription> buildPortDescriptions(PcepDpid dpid,
Andrea Campanella5d73df72017-05-09 14:26:00 -0700154 Port port) {
chengfan359abf72015-07-02 23:33:16 +0800155
156 List<PortDescription> portList;
157
158 if (portMap.containsKey(dpid.value())) {
159 portList = portMap.get(dpid.value());
160 } else {
161 portList = new ArrayList<>();
cheng fan48e832c2015-05-29 01:54:47 +0800162 }
Andrea Campanella5d73df72017-05-09 14:26:00 -0700163 if (port != null) {
164 SparseAnnotations annotations = DefaultAnnotations.builder()
165 .putAll(port.annotations()).build();
166 portList.add(new DefaultPortDescription(port.number(), port.isEnabled(),
167 port.type(), port.portSpeed(),
168 annotations));
chengfan359abf72015-07-02 23:33:16 +0800169 }
170
171 portMap.put(dpid.value(), portList);
172 return portList;
cheng fan48e832c2015-05-29 01:54:47 +0800173 }
174
cheng fan48e832c2015-05-29 01:54:47 +0800175 /**
chengfan3e618792015-06-28 21:42:01 +0800176 * Build a link description from a pcep link.
cheng fan48e832c2015-05-29 01:54:47 +0800177 *
chengfan3e618792015-06-28 21:42:01 +0800178 * @param pceLink pcep link
179 * @return LinkDescription onos link description
cheng fan48e832c2015-05-29 01:54:47 +0800180 */
181 private LinkDescription buildLinkDescription(PcepLink pceLink) {
182 LinkDescription ld;
chengfan359abf72015-07-02 23:33:16 +0800183 checkNotNull(pceLink);
cheng fan48e832c2015-05-29 01:54:47 +0800184 DeviceId srcDeviceID = deviceId(uri(pceLink.linkSrcDeviceID()));
185 DeviceId dstDeviceID = deviceId(uri(pceLink.linkDstDeviceId()));
186
cheng fan48e832c2015-05-29 01:54:47 +0800187 deviceProviderService
188 .updatePorts(srcDeviceID,
chengfan359abf72015-07-02 23:33:16 +0800189 buildPortDescriptions(pceLink.linkSrcDeviceID(),
Andrea Campanella5d73df72017-05-09 14:26:00 -0700190 pceLink.linkSrcPort()));
cheng fan48e832c2015-05-29 01:54:47 +0800191
chengfan359abf72015-07-02 23:33:16 +0800192 deviceProviderService
193 .updatePorts(dstDeviceID,
194 buildPortDescriptions(pceLink.linkDstDeviceId(),
Andrea Campanella5d73df72017-05-09 14:26:00 -0700195 pceLink.linkDstPort()));
cheng fan48e832c2015-05-29 01:54:47 +0800196
chengfan359abf72015-07-02 23:33:16 +0800197 ConnectPoint src = new ConnectPoint(srcDeviceID, pceLink.linkSrcPort().number());
cheng fan48e832c2015-05-29 01:54:47 +0800198
chengfan359abf72015-07-02 23:33:16 +0800199 ConnectPoint dst = new ConnectPoint(dstDeviceID, pceLink.linkDstPort().number());
200
201 DefaultAnnotations extendedAttributes = DefaultAnnotations
202 .builder()
203 .set("subType", String.valueOf(pceLink.linkSubType()))
204 .set("workState", pceLink.linkState())
205 .set("distance", String.valueOf(pceLink.linkDistance()))
206 .set("capType", pceLink.linkCapacityType().toLowerCase())
207 .set("avail_" + pceLink.linkCapacityType().toLowerCase(),
208 String.valueOf(pceLink.linkAvailValue()))
209 .set("max_" + pceLink.linkCapacityType().toLowerCase(),
210 String.valueOf(pceLink.linkMaxValue())).build();
cheng fan48e832c2015-05-29 01:54:47 +0800211 // construct the link
chengfan359abf72015-07-02 23:33:16 +0800212 ld = new DefaultLinkDescription(src, dst, Type.OPTICAL, extendedAttributes);
cheng fan48e832c2015-05-29 01:54:47 +0800213 return ld;
214 }
215
cheng fan48e832c2015-05-29 01:54:47 +0800216 private class InternalLinkProvider
Priyanka B94395bf2016-05-21 18:39:46 +0530217 implements PcepSwitchListener, PcepLinkListener, PcepNodeListener {
cheng fan48e832c2015-05-29 01:54:47 +0800218
219 @Override
220 public void switchAdded(PcepDpid dpid) {
cheng fan48e832c2015-05-29 01:54:47 +0800221 if (deviceProviderService == null) {
222 return;
223 }
chengfan359abf72015-07-02 23:33:16 +0800224 DeviceId deviceId = deviceId(uri(dpid));
cheng fan48e832c2015-05-29 01:54:47 +0800225 PcepSwitch sw = controller.getSwitch(dpid);
226 checkNotNull(sw, "device should not null.");
227 // The default device type is switch.
cheng fan48e832c2015-05-29 01:54:47 +0800228 ChassisId cId = new ChassisId(dpid.value());
chengfan359abf72015-07-02 23:33:16 +0800229 Device.Type deviceType;
cheng fan48e832c2015-05-29 01:54:47 +0800230
cheng fan7716ec92015-05-31 01:53:19 +0800231 switch (sw.getDeviceType()) {
chengfan359abf72015-07-02 23:33:16 +0800232 case ROADM:
233 deviceType = Device.Type.ROADM;
234 break;
235 case OTN:
236 deviceType = Device.Type.SWITCH;
237 break;
238 case ROUTER:
239 deviceType = Device.Type.ROUTER;
240 break;
241 default:
242 deviceType = Device.Type.OTHER;
cheng fan7716ec92015-05-31 01:53:19 +0800243 }
cheng fan48e832c2015-05-29 01:54:47 +0800244
245 DeviceDescription description = new DefaultDeviceDescription(
chengfan359abf72015-07-02 23:33:16 +0800246 deviceId.uri(),
247 deviceType,
248 sw.manufacturerDescription(),
249 sw.hardwareDescription(),
250 sw.softwareDescription(),
251 sw.serialNumber(),
252 cId);
253 deviceProviderService.deviceConnected(deviceId, description);
cheng fan48e832c2015-05-29 01:54:47 +0800254
255 }
256
257 @Override
258 public void switchRemoved(PcepDpid dpid) {
cheng fan48e832c2015-05-29 01:54:47 +0800259 if (deviceProviderService == null || linkProviderService == null) {
260 return;
261 }
262 deviceProviderService.deviceDisconnected(deviceId(uri(dpid)));
263
264 linkProviderService.linksVanished(DeviceId.deviceId(uri(dpid)));
265 }
266
267 @Override
268 public void switchChanged(PcepDpid dpid) {
269 // TODO Auto-generated method stub
270
271 }
272
273 @Override
Jonathan Hart51539b82015-10-29 09:53:04 -0700274 public void handlePceplink(PcepLink link) {
cheng fan48e832c2015-05-29 01:54:47 +0800275
276 OperationType operType = link.getOperationType();
277 LinkDescription ld = buildLinkDescription(link);
278 if (ld == null) {
279 log.error("Invalid link info.");
280 return;
281 }
282 switch (operType) {
chengfan359abf72015-07-02 23:33:16 +0800283 case ADD:
284 case UPDATE:
285 linkProviderService.linkDetected(ld);
286 break;
cheng fan48e832c2015-05-29 01:54:47 +0800287
chengfan359abf72015-07-02 23:33:16 +0800288 case DELETE:
289 linkProviderService.linkVanished(ld);
290 break;
cheng fan48e832c2015-05-29 01:54:47 +0800291
chengfan359abf72015-07-02 23:33:16 +0800292 default:
293 break;
cheng fan48e832c2015-05-29 01:54:47 +0800294
295 }
296 }
297
Priyanka B94395bf2016-05-21 18:39:46 +0530298 @Override
Avantika-Huaweife44ea62016-05-27 19:21:24 +0530299 public void addDevicePcepConfig(PcepClient pc) {
300 if (netConfigRegistry == null) {
301 log.error("Cannot add PCEP device capability as network config service is not available.");
Priyanka B94395bf2016-05-21 18:39:46 +0530302 return;
303 }
Avantika-Huaweife44ea62016-05-27 19:21:24 +0530304 DeviceId pccDeviceId = DeviceId.deviceId(String.valueOf(pc.getPccId().ipAddress()));
305 DeviceCapability deviceCap = netConfigService.addConfig(pccDeviceId, DeviceCapability.class);
306 deviceCap.setLabelStackCap(pc.capability().labelStackCapability())
307 .setLocalLabelCap(pc.capability().pceccCapability())
308 .setSrCap(pc.capability().srCapability())
309 .apply();
Priyanka B94395bf2016-05-21 18:39:46 +0530310 }
311
312 @Override
Avantika-Huaweife44ea62016-05-27 19:21:24 +0530313 public void deleteDevicePcepConfig(PccId pccId) {
314 if (netConfigRegistry == null) {
315 log.error("Cannot remove PCEP device capability as network config service is not available.");
Priyanka B94395bf2016-05-21 18:39:46 +0530316 return;
317 }
Avantika-Huaweife44ea62016-05-27 19:21:24 +0530318 DeviceId pccDeviceId = DeviceId.deviceId(String.valueOf(pccId.ipAddress()));
319 netConfigService.removeConfig(pccDeviceId, DeviceCapability.class);
Priyanka B94395bf2016-05-21 18:39:46 +0530320 }
cheng fan48e832c2015-05-29 01:54:47 +0800321 }
322
323 @Override
324 public void triggerProbe(DeviceId deviceId) {
325 // TODO Auto-generated method stub
cheng fan48e832c2015-05-29 01:54:47 +0800326 }
327
328 @Override
329 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
cheng fan48e832c2015-05-29 01:54:47 +0800330 }
331
332 @Override
333 public boolean isReachable(DeviceId deviceId) {
334 // TODO Auto-generated method stub
cheng fan7716ec92015-05-31 01:53:19 +0800335 return true;
cheng fan48e832c2015-05-29 01:54:47 +0800336 }
Saurav Dasa2d37502016-03-25 17:50:40 -0700337
338 @Override
339 public void changePortState(DeviceId deviceId, PortNumber portNumber,
340 boolean enable) {
341 // TODO Auto-generated method stub
342 }
cheng fan48e832c2015-05-29 01:54:47 +0800343}