blob: 0ac494c9e8f264efae195eaf300c30ff83a37f53 [file] [log] [blame]
Shashikanth VH1ca26ce2015-11-20 23:19:49 +05301/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Shashikanth VH1ca26ce2015-11-20 23:19:49 +05303 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 * the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 * specific language governing permissions and limitations under the License.
12 */
13
14package org.onosproject.provider.bgp.topology.impl;
15
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053016import static org.onosproject.bgp.controller.BgpDpid.uri;
17import static org.onosproject.net.DeviceId.deviceId;
Priyanka Bfc51c952016-03-26 14:30:33 +053018import static org.onosproject.net.Device.Type.ROUTER;
19import static org.onosproject.net.Device.Type.VIRTUAL;
20
21import java.util.List;
22import java.util.Set;
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053023
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053024import org.onlab.packet.ChassisId;
25import org.apache.felix.scr.annotations.Activate;
26import org.apache.felix.scr.annotations.Component;
27import org.apache.felix.scr.annotations.Deactivate;
28import org.apache.felix.scr.annotations.Reference;
29import org.apache.felix.scr.annotations.ReferenceCardinality;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053030import org.onosproject.bgp.controller.BgpController;
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053031import org.onosproject.bgp.controller.BgpDpid;
Priyanka Bfc51c952016-03-26 14:30:33 +053032import org.onosproject.bgp.controller.BgpLinkListener;
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053033import org.onosproject.bgp.controller.BgpNodeListener;
Priyanka Bfc51c952016-03-26 14:30:33 +053034import org.onosproject.bgpio.exceptions.BgpParseException;
35import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier;
36import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
37import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053038import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
Priyanka Bfc51c952016-03-26 14:30:33 +053039import org.onosproject.bgpio.protocol.linkstate.NodeDescriptors;
40import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
41import org.onosproject.bgpio.types.AutonomousSystemTlv;
42import org.onosproject.bgpio.types.BgpLSIdentifierTlv;
43import org.onosproject.bgpio.types.BgpValueType;
44import org.onosproject.bgpio.types.IPv4AddressTlv;
45import org.onosproject.bgpio.types.IsIsNonPseudonode;
46import org.onosproject.bgpio.types.IsIsPseudonode;
47import org.onosproject.bgpio.types.LinkLocalRemoteIdentifiersTlv;
48import org.onosproject.bgpio.types.OspfNonPseudonode;
49import org.onosproject.bgpio.types.OspfPseudonode;
50import org.onosproject.core.CoreService;
51import org.onosproject.net.AnnotationKeys;
52import org.onosproject.net.ConnectPoint;
53import org.onosproject.net.DefaultAnnotations;
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053054import org.onosproject.net.Device;
55import org.onosproject.net.DeviceId;
Priyanka Bfc51c952016-03-26 14:30:33 +053056import org.onosproject.net.Link;
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053057import org.onosproject.net.MastershipRole;
Saurav Dasa2d37502016-03-25 17:50:40 -070058import org.onosproject.net.PortNumber;
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053059import org.onosproject.net.device.DefaultDeviceDescription;
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053060import org.onosproject.net.device.DeviceDescription;
61import org.onosproject.net.device.DeviceProvider;
62import org.onosproject.net.device.DeviceProviderRegistry;
63import org.onosproject.net.device.DeviceProviderService;
Priyanka Bfc51c952016-03-26 14:30:33 +053064import org.onosproject.net.device.DeviceService;
65import org.onosproject.net.link.DefaultLinkDescription;
66import org.onosproject.net.link.LinkDescription;
67import org.onosproject.net.link.LinkProvider;
68import org.onosproject.net.link.LinkProviderRegistry;
69import org.onosproject.net.link.LinkProviderService;
70import org.onosproject.net.link.LinkService;
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053071import org.onosproject.net.provider.AbstractProvider;
72import org.onosproject.net.provider.ProviderId;
73import org.slf4j.Logger;
74import org.slf4j.LoggerFactory;
75
76/**
77 * Provider which uses an BGP controller to detect network infrastructure topology.
78 */
79@Component(immediate = true)
Priyanka Bfc51c952016-03-26 14:30:33 +053080public class BgpTopologyProvider extends AbstractProvider implements DeviceProvider, LinkProvider {
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053081
Priyanka B9bee0802016-04-27 22:06:02 +053082 /**
83 * Creates an instance of BGP topology provider.
84 */
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053085 public BgpTopologyProvider() {
Priyanka B9bee0802016-04-27 22:06:02 +053086 super(new ProviderId("l3", "org.onosproject.provider.bgp"));
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053087 }
88
89 private static final Logger log = LoggerFactory.getLogger(BgpTopologyProvider.class);
90
91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053092 protected DeviceProviderRegistry deviceProviderRegistry;
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Priyanka Bfc51c952016-03-26 14:30:33 +053095 protected LinkProviderRegistry linkProviderRegistry;
96
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053098 protected BgpController controller;
Shashikanth VH1ca26ce2015-11-20 23:19:49 +053099
Priyanka Bfc51c952016-03-26 14:30:33 +0530100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected LinkService linkService;
102
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 protected DeviceService deviceService;
105
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected CoreService coreService;
108
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530109 private DeviceProviderService deviceProviderService;
Priyanka Bfc51c952016-03-26 14:30:33 +0530110 private LinkProviderService linkProviderService;
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530111
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530112 private InternalBgpProvider listener = new InternalBgpProvider();
113 private static final String UNKNOWN = "unknown";
Priyanka Bfc51c952016-03-26 14:30:33 +0530114 public static final long IDENTIFIER_SET = 0x100000000L;
115 public static final String AS_NUMBER = "asNumber";
116 public static final String DOMAIN_IDENTIFIER = "domainIdentifier";
117 public static final String ROUTING_UNIVERSE = "routingUniverse";
118 public static final long PSEUDO_PORT = 0xffffffff;
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530119
120 @Activate
121 public void activate() {
Priyanka Bfc51c952016-03-26 14:30:33 +0530122 log.debug("BgpTopologyProvider activate");
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530123 deviceProviderService = deviceProviderRegistry.register(this);
Priyanka Bfc51c952016-03-26 14:30:33 +0530124 linkProviderService = linkProviderRegistry.register(this);
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530125 controller.addListener(listener);
Priyanka Bfc51c952016-03-26 14:30:33 +0530126 controller.addLinkListener(listener);
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530127 }
128
129 @Deactivate
130 public void deactivate() {
Priyanka Bfc51c952016-03-26 14:30:33 +0530131 log.debug("BgpTopologyProvider deactivate");
132 deviceProviderRegistry.unregister(this);
133 deviceProviderService = null;
134 linkProviderRegistry.unregister(this);
135 linkProviderService = null;
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530136 controller.removeListener(listener);
Priyanka Bfc51c952016-03-26 14:30:33 +0530137 controller.removeLinkListener(listener);
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530138 }
139
140 /*
141 * Implements device and link update.
142 */
Priyanka Bfc51c952016-03-26 14:30:33 +0530143 private class InternalBgpProvider implements BgpNodeListener, BgpLinkListener {
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530144
145 @Override
Priyanka Bfc51c952016-03-26 14:30:33 +0530146 public void addNode(BgpNodeLSNlriVer4 nodeNlri, PathAttrNlriDetails details) {
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530147 log.debug("Add node {}", nodeNlri.toString());
148
149 if (deviceProviderService == null) {
150 return;
151 }
Priyanka Bfc51c952016-03-26 14:30:33 +0530152 Device.Type deviceType = ROUTER;
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530153 BgpDpid nodeUri = new BgpDpid(nodeNlri);
154 DeviceId deviceId = deviceId(uri(nodeUri.toString()));
155 ChassisId cId = new ChassisId();
156
Priyanka Bfc51c952016-03-26 14:30:33 +0530157 DefaultAnnotations.Builder newBuilder = DefaultAnnotations.builder();
158
159 newBuilder.set(AnnotationKeys.TYPE, "L3");
160 newBuilder.set(ROUTING_UNIVERSE, Long.toString(nodeNlri.getIdentifier()));
161
162 List<BgpValueType> tlvs = nodeNlri.getLocalNodeDescriptors().getNodedescriptors().getSubTlvs();
163 for (BgpValueType tlv : tlvs) {
164 if (tlv instanceof AutonomousSystemTlv) {
165 newBuilder.set(AS_NUMBER, Integer.toString(((AutonomousSystemTlv) tlv).getAsNum()));
166 } else if (tlv instanceof BgpLSIdentifierTlv) {
167 newBuilder.set(DOMAIN_IDENTIFIER,
168 Integer.toString(((BgpLSIdentifierTlv) tlv).getBgpLsIdentifier()));
169 }
170 if (tlv.getType() == NodeDescriptors.IGP_ROUTERID_TYPE) {
171 if (tlv instanceof IsIsPseudonode) {
172 deviceType = VIRTUAL;
173 newBuilder.set(AnnotationKeys.ROUTER_ID, new String(((IsIsPseudonode) tlv).getIsoNodeId()));
174 } else if (tlv instanceof OspfPseudonode) {
175 deviceType = VIRTUAL;
176 newBuilder
177 .set(AnnotationKeys.ROUTER_ID, Integer.toString(((OspfPseudonode) tlv).getrouterID()));
178 } else if (tlv instanceof IsIsNonPseudonode) {
179 newBuilder.set(AnnotationKeys.ROUTER_ID, new String(((IsIsNonPseudonode) tlv).getIsoNodeId()));
180 } else if (tlv instanceof OspfNonPseudonode) {
181 newBuilder.set(AnnotationKeys.ROUTER_ID,
182 Integer.toString(((OspfNonPseudonode) tlv).getrouterID()));
183 }
184 }
185 }
186
187 DeviceDescription description = new DefaultDeviceDescription(uri(nodeUri.toString()), deviceType, UNKNOWN,
188 UNKNOWN, UNKNOWN, UNKNOWN, cId, newBuilder.build());
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530189 deviceProviderService.deviceConnected(deviceId, description);
190
191 }
192
193 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530194 public void deleteNode(BgpNodeLSNlriVer4 nodeNlri) {
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530195 log.debug("Delete node {}", nodeNlri.toString());
196
197 if (deviceProviderService == null) {
198 return;
199 }
200
Priyanka Bfc51c952016-03-26 14:30:33 +0530201 BgpDpid deviceUri = new BgpDpid(nodeNlri);
202 DeviceId deviceId = deviceId(uri(deviceUri.toString()));
203 deviceProviderService.deviceDisconnected(deviceId);
204 }
205
206 @Override
207 public void addLink(BgpLinkLsNlriVer4 linkNlri, PathAttrNlriDetails details) throws BgpParseException {
208 log.debug("Addlink {}", linkNlri.toString());
209
210 if (linkProviderService == null) {
211 return;
212 }
213 LinkDescription linkDes = buildLinkDes(linkNlri, details, true);
214 linkProviderService.linkDetected(linkDes);
215 }
216
217 //Build link description.
218 private LinkDescription buildLinkDes(BgpLinkLsNlriVer4 linkNlri, PathAttrNlriDetails details, boolean isAddLink)
219 throws BgpParseException {
220 long srcAddress = 0;
221 long dstAddress = 0;
222 boolean localPseduo = false;
223 boolean remotePseduo = false;
224
225 List<BgpValueType> localTlvs = linkNlri.getLinkIdentifier().localNodeDescriptors().getSubTlvs();
226 for (BgpValueType localTlv : localTlvs) {
227 if (localTlv instanceof IsIsPseudonode || localTlv instanceof OspfPseudonode) {
228 localPseduo = true;
229 }
230 }
231 List<BgpValueType> remoteTlvs = linkNlri.getLinkIdentifier().remoteNodeDescriptors().getSubTlvs();
232 for (BgpValueType remoteTlv : remoteTlvs) {
233 if (remoteTlv instanceof IsIsPseudonode || remoteTlv instanceof OspfPseudonode) {
234 remotePseduo = true;
235 }
236 }
237
238 List<BgpValueType> tlvs = linkNlri.getLinkIdentifier().linkDescriptors();
239 for (BgpValueType tlv : tlvs) {
240 if (tlv instanceof LinkLocalRemoteIdentifiersTlv) {
241 srcAddress = ((LinkLocalRemoteIdentifiersTlv) tlv).getLinkLocalIdentifier();
242 //Set 32nd bit.
243 srcAddress = srcAddress | IDENTIFIER_SET;
244 dstAddress = ((LinkLocalRemoteIdentifiersTlv) tlv).getLinkRemoteIdentifier();
245 dstAddress = dstAddress | IDENTIFIER_SET;
246 } else if (tlv instanceof IPv4AddressTlv) {
247 if (tlv.getType() == BgpLinkLSIdentifier.IPV4_INTERFACE_ADDRESS_TYPE) {
248 srcAddress = ((IPv4AddressTlv) tlv).address().toInt();
249 } else {
250 dstAddress = ((IPv4AddressTlv) tlv).address().toInt();
251 }
252 }
253 }
254
255 DeviceId srcId = deviceId(uri(new BgpDpid(linkNlri, BgpDpid.NODE_DESCRIPTOR_LOCAL).toString()));
256 DeviceId dstId = deviceId(uri(new BgpDpid(linkNlri, BgpDpid.NODE_DESCRIPTOR_REMOTE).toString()));
257
258 if (localPseduo && srcAddress == 0) {
259 srcAddress = PSEUDO_PORT;
260 } else if (remotePseduo && dstAddress == 0) {
261 dstAddress = PSEUDO_PORT;
262 }
263
264 ConnectPoint src = new ConnectPoint(srcId, PortNumber.portNumber(srcAddress));
265 ConnectPoint dst = new ConnectPoint(dstId, PortNumber.portNumber(dstAddress));
266 BgpNodeLSNlriVer4 srcNodeNlri = new BgpNodeLSNlriVer4(linkNlri.getIdentifier(), linkNlri.getProtocolId()
267 .getType(), new BgpNodeLSIdentifier(linkNlri.getLinkIdentifier().localNodeDescriptors()), false,
268 linkNlri.getRouteDistinguisher());
269
270 BgpNodeLSNlriVer4 dstNodeNlri = new BgpNodeLSNlriVer4(linkNlri.getIdentifier(), linkNlri.getProtocolId()
271 .getType(), new BgpNodeLSIdentifier(linkNlri.getLinkIdentifier().remoteNodeDescriptors()), false,
272 linkNlri.getRouteDistinguisher());
273
274 addOrDeletePseudoNode(isAddLink, localPseduo, remotePseduo, srcNodeNlri,
275 dstNodeNlri, srcId, dstId, details);
276 return new DefaultLinkDescription(src, dst, Link.Type.DIRECT, false);
277 }
278
279 private void addOrDeletePseudoNode(boolean isAddLink, boolean localPseduo, boolean remotePseduo,
280 BgpNodeLSNlriVer4 srcNodeNlri, BgpNodeLSNlriVer4 dstNodeNlri, DeviceId srcId, DeviceId dstId,
281 PathAttrNlriDetails details) {
282 if (isAddLink) {
283 if (localPseduo) {
284 if (deviceService.getDevice(srcId) == null) {
285 for (BgpNodeListener l : controller.listener()) {
286 l.addNode(srcNodeNlri, details);
287 }
288 }
289 } else if (remotePseduo) {
290 if (deviceService.getDevice(dstId) == null) {
291 for (BgpNodeListener l : controller.listener()) {
292 l.addNode(dstNodeNlri, details);
293 }
294 }
295 }
296 } else {
297 if (localPseduo) {
298 Set<Link> links = linkService.getDeviceLinks(srcId);
299 if (links == null || links.isEmpty()) {
300 for (BgpNodeListener l : controller.listener()) {
301 l.deleteNode(srcNodeNlri);
302 }
303 }
304 } else if (remotePseduo) {
305 log.info("Remote pseudo delete link ");
306 Set<Link> links = linkService.getDeviceLinks(dstId);
307 if (links == null || links.isEmpty()) {
308 for (BgpNodeListener l : controller.listener()) {
309 l.deleteNode(dstNodeNlri);
310 }
311 }
312 }
313 }
314 }
315
316 @Override
317 public void deleteLink(BgpLinkLsNlriVer4 linkNlri) throws BgpParseException {
318 log.debug("Delete link {}", linkNlri.toString());
319
320 if (linkProviderService == null) {
321 return;
322 }
323
324 LinkDescription linkDes = buildLinkDes(linkNlri, null, false);
325 linkProviderService.linkVanished(linkDes);
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530326 }
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530327 }
328
329 @Override
330 public void triggerProbe(DeviceId deviceId) {
331 // TODO Auto-generated method stub
332 }
333
334 @Override
335 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
336 }
337
338 @Override
339 public boolean isReachable(DeviceId deviceId) {
340 // TODO Auto-generated method stub
341 return true;
342 }
Saurav Dasa2d37502016-03-25 17:50:40 -0700343
344 @Override
345 public void changePortState(DeviceId deviceId, PortNumber portNumber,
346 boolean enable) {
347 }
Shashikanth VH1ca26ce2015-11-20 23:19:49 +0530348}