blob: b0fad68a721da91d2ebb8d118714515f5986687e [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
alshabib7911a052014-10-16 17:49:37 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
alshabib7911a052014-10-16 17:49:37 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Ray Milkey957390e2016-02-09 10:02:46 -080016package org.onosproject.provider.lldpcommon;
alshabib7911a052014-10-16 17:49:37 -070017
Ray Milkey1ab441b2018-03-06 15:33:44 -080018import com.google.common.collect.ImmutableMap;
jaegonkimd9119d0d2018-02-06 23:16:52 +090019import com.google.common.collect.Maps;
Yuta HIGUCHI19afc032017-05-20 23:44:17 -070020import io.netty.util.Timeout;
21import io.netty.util.TimerTask;
jaegonkimaaa4f832018-03-11 00:48:36 +090022import io.netty.util.internal.StringUtil;
David K. Bainbridgebbbb9422018-11-05 14:52:38 -080023import org.onlab.packet.ChassisId;
Jonathan Harte8600eb2015-01-12 10:30:45 -080024import org.onlab.packet.Ethernet;
Charles Chan928ff8b2017-05-04 12:22:54 -070025import org.onlab.packet.MacAddress;
Jonathan Harte8600eb2015-01-12 10:30:45 -080026import org.onlab.packet.ONOSLLDP;
27import org.onlab.util.Timer;
DongRyeol Chace65cc02018-07-23 15:02:28 +090028import org.onlab.util.Tools;
29import org.onosproject.net.AnnotationKeys;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.net.ConnectPoint;
DongRyeol Chace65cc02018-07-23 15:02:28 +090031import org.onosproject.net.DefaultAnnotations;
32import org.onosproject.net.DefaultPort;
Brian O'Connorabafb502014-12-02 22:26:20 -080033import org.onosproject.net.Device;
34import org.onosproject.net.DeviceId;
35import org.onosproject.net.Link.Type;
Thomas Vachuska05453c92015-09-09 14:40:49 -070036import org.onosproject.net.LinkKey;
Brian O'Connorabafb502014-12-02 22:26:20 -080037import org.onosproject.net.Port;
38import org.onosproject.net.PortNumber;
DongRyeol Chace65cc02018-07-23 15:02:28 +090039import org.onosproject.net.device.DeviceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.link.DefaultLinkDescription;
41import org.onosproject.net.link.LinkDescription;
Ray Milkey44ba9372018-05-07 09:37:37 -070042import org.onosproject.net.link.ProbedLinkProvider;
Brian O'Connorabafb502014-12-02 22:26:20 -080043import org.onosproject.net.packet.DefaultOutboundPacket;
44import org.onosproject.net.packet.OutboundPacket;
45import org.onosproject.net.packet.PacketContext;
alshabib7911a052014-10-16 17:49:37 -070046import org.slf4j.Logger;
47
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070048import java.nio.ByteBuffer;
Ray Milkey44ba9372018-05-07 09:37:37 -070049import java.util.Map;
Ray Milkeye3c454e2018-11-14 10:47:50 -080050import java.util.Objects;
DongRyeol Chace65cc02018-07-23 15:02:28 +090051import java.util.Optional;
52import java.util.function.Supplier;
53import java.util.stream.Stream;
54import java.util.stream.StreamSupport;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070055
Thomas Vachuska586bc4f2016-08-19 12:44:26 -070056import static com.google.common.base.Strings.isNullOrEmpty;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070057import static java.util.concurrent.TimeUnit.MILLISECONDS;
jaegonkimd9119d0d2018-02-06 23:16:52 +090058import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070059import static org.onosproject.net.PortNumber.portNumber;
60import static org.onosproject.net.flow.DefaultTrafficTreatment.builder;
61import static org.slf4j.LoggerFactory.getLogger;
62
alshabib7911a052014-10-16 17:49:37 -070063/**
64 * Run discovery process from a physical switch. Ports are initially labeled as
65 * slow ports. When an LLDP is successfully received, label the remote port as
66 * fast. Every probeRate milliseconds, loop over all fast ports and send an
67 * LLDP, send an LLDP for a single slow port. Based on FlowVisor topology
68 * discovery implementation.
alshabib7911a052014-10-16 17:49:37 -070069 */
Ray Milkey957390e2016-02-09 10:02:46 -080070public class LinkDiscovery implements TimerTask {
alshabib7911a052014-10-16 17:49:37 -070071
DongRyeol Chace65cc02018-07-23 15:02:28 +090072 private static final String SCHEME_NAME = "linkdiscovery";
73 private static final String ETHERNET = "ETHERNET";
74
alshabib7911a052014-10-16 17:49:37 -070075 private final Logger log = getLogger(getClass());
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070076
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070077 private final Device device;
Ray Milkey957390e2016-02-09 10:02:46 -080078 private final LinkDiscoveryContext context;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070079
alshabib7911a052014-10-16 17:49:37 -070080 private final Ethernet ethPacket;
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070081 private final Ethernet bddpEth;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070082
83 private Timeout timeout;
84 private volatile boolean isStopped;
Thomas Vachuska9280e192018-03-06 11:19:29 -080085
Thomas Vachuska05453c92015-09-09 14:40:49 -070086 // Set of ports to be probed
Ray Milkey44ba9372018-05-07 09:37:37 -070087 private final Map<Long, String> portMap = Maps.newConcurrentMap();
alshabib7911a052014-10-16 17:49:37 -070088 /**
89 * Instantiates discovery manager for the given physical switch. Creates a
90 * generic LLDP packet that will be customized for the port it is sent out on.
91 * Starts the the timer for the discovery process.
Thomas Vachuskae1bcb0b2014-10-27 17:45:10 -070092 *
Thomas Vachuska05453c92015-09-09 14:40:49 -070093 * @param device the physical switch
94 * @param context discovery context
alshabib7911a052014-10-16 17:49:37 -070095 */
Ray Milkey957390e2016-02-09 10:02:46 -080096 public LinkDiscovery(Device device, LinkDiscoveryContext context) {
alshabib7911a052014-10-16 17:49:37 -070097 this.device = device;
Thomas Vachuska05453c92015-09-09 14:40:49 -070098 this.context = context;
alshabib3d643ec2014-10-22 18:33:00 -070099
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700100 ethPacket = new Ethernet();
101 ethPacket.setEtherType(Ethernet.TYPE_LLDP);
Charles Chan928ff8b2017-05-04 12:22:54 -0700102 ethPacket.setDestinationMACAddress(MacAddress.ONOS_LLDP);
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700103 ethPacket.setPad(true);
alshabib7911a052014-10-16 17:49:37 -0700104
Thomas Vachuska05453c92015-09-09 14:40:49 -0700105 bddpEth = new Ethernet();
Thomas Vachuska05453c92015-09-09 14:40:49 -0700106 bddpEth.setEtherType(Ethernet.TYPE_BSN);
Charles Chan928ff8b2017-05-04 12:22:54 -0700107 bddpEth.setDestinationMACAddress(MacAddress.BROADCAST);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700108 bddpEth.setPad(true);
alshabib7911a052014-10-16 17:49:37 -0700109
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700110 isStopped = true;
alshabib7911a052014-10-16 17:49:37 -0700111 start();
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700112 log.debug("Started discovery manager for switch {}", device.id());
alshabib7911a052014-10-16 17:49:37 -0700113
114 }
115
Ray Milkey957390e2016-02-09 10:02:46 -0800116 public synchronized void stop() {
Jon Hall3edc08a2015-09-14 16:59:07 -0700117 if (!isStopped) {
118 isStopped = true;
119 timeout.cancel();
120 } else {
121 log.warn("LinkDiscovery stopped multiple times?");
122 }
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700123 }
124
Ray Milkey957390e2016-02-09 10:02:46 -0800125 public synchronized void start() {
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700126 if (isStopped) {
127 isStopped = false;
Yuta HIGUCHI19afc032017-05-20 23:44:17 -0700128 timeout = Timer.newTimeout(this, 0, MILLISECONDS);
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700129 } else {
130 log.warn("LinkDiscovery started multiple times?");
131 }
132 }
133
Ray Milkey957390e2016-02-09 10:02:46 -0800134 public synchronized boolean isStopped() {
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700135 return isStopped || timeout.isCancelled();
136 }
137
alshabib7911a052014-10-16 17:49:37 -0700138 /**
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700139 * Add physical port to discovery process.
alshabib7911a052014-10-16 17:49:37 -0700140 * Send out initial LLDP and label it as slow port.
141 *
142 * @param port the port
143 */
Ray Milkey957390e2016-02-09 10:02:46 -0800144 public void addPort(Port port) {
jaegonkimd9119d0d2018-02-06 23:16:52 +0900145 Long portNum = port.number().toLong();
146 String portName = port.annotations().value(PORT_NAME);
jaegonkimaaa4f832018-03-11 00:48:36 +0900147 if (portName == null) {
148 portName = StringUtil.EMPTY_STRING;
149 }
jaegonkimd9119d0d2018-02-06 23:16:52 +0900150
You Wang168aa622018-03-08 14:01:37 -0800151 boolean newPort = !containsPort(portNum);
jaegonkimd9119d0d2018-02-06 23:16:52 +0900152 portMap.put(portNum, portName);
153
Thomas Vachuska05453c92015-09-09 14:40:49 -0700154 boolean isMaster = context.mastershipService().isLocalMaster(device.id());
Jonathan Hart45066bc2015-07-28 11:18:34 -0700155 if (newPort && isMaster) {
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700156 log.debug("Sending initial probe to port {}@{}", port.number().toLong(), device.id());
jaegonkimd9119d0d2018-02-06 23:16:52 +0900157 sendProbes(portNum, portName);
alshabib7911a052014-10-16 17:49:37 -0700158 }
alshabib7911a052014-10-16 17:49:37 -0700159 }
160
161 /**
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700162 * removed physical port from discovery process.
163 * @param port the port number
164 */
Ray Milkey957390e2016-02-09 10:02:46 -0800165 public void removePort(PortNumber port) {
jaegonkimd9119d0d2018-02-06 23:16:52 +0900166 portMap.remove(port.toLong());
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700167 }
168
169 /**
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700170 * Handles an incoming LLDP packet. Creates link in topology and adds the
171 * link for staleness tracking.
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700172 *
Thomas Vachuska05453c92015-09-09 14:40:49 -0700173 * @param packetContext packet context
Yuta HIGUCHI5c947272014-11-03 21:39:21 -0800174 * @return true if handled
alshabib7911a052014-10-16 17:49:37 -0700175 */
Ray Milkey957390e2016-02-09 10:02:46 -0800176 public boolean handleLldp(PacketContext packetContext) {
Thomas Vachuska05453c92015-09-09 14:40:49 -0700177 Ethernet eth = packetContext.inPacket().parsed();
Jonathan Harte8600eb2015-01-12 10:30:45 -0800178 if (eth == null) {
179 return false;
180 }
181
DongRyeol Chace65cc02018-07-23 15:02:28 +0900182 if (processOnosLldp(packetContext, eth)) {
183 return true;
184 }
185
186 if (processLldp(packetContext, eth)) {
187 return true;
188 }
189
190 ONOSLLDP lldp = ONOSLLDP.parseLLDP(eth);
191
192 if (lldp == null) {
193 log.debug("Cannot parse the packet. It seems that it is not the lldp or bsn packet.");
194 } else {
195 log.debug("LLDP packet is dropped due to there are no handlers that properly handle this packet: {}",
196 lldp.toString());
197 }
198
199 return false;
200 }
201
202 private boolean processOnosLldp(PacketContext packetContext, Ethernet eth) {
alshabib7911a052014-10-16 17:49:37 -0700203 ONOSLLDP onoslldp = ONOSLLDP.parseONOSLLDP(eth);
204 if (onoslldp != null) {
Ayaka Koshibe48229222016-05-16 18:04:26 -0700205 Type lt;
206 if (notMy(eth.getSourceMAC().toString())) {
207 lt = Type.EDGE;
208 } else {
209 lt = eth.getEtherType() == Ethernet.TYPE_LLDP ?
210 Type.DIRECT : Type.INDIRECT;
Samuel Jero31e16f52018-09-21 10:34:28 -0400211
212 /* Verify MAC in LLDP packets */
213 if (!ONOSLLDP.verify(onoslldp, context.lldpSecret(), context.maxDiscoveryDelay())) {
214 log.warn("LLDP Packet failed to validate!");
215 return true;
216 }
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800217 }
218
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700219 PortNumber srcPort = portNumber(onoslldp.getPort());
Thomas Vachuska05453c92015-09-09 14:40:49 -0700220 PortNumber dstPort = packetContext.inPacket().receivedFrom().port();
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700221
Thomas Vachuska586bc4f2016-08-19 12:44:26 -0700222 String idString = onoslldp.getDeviceString();
223 if (!isNullOrEmpty(idString)) {
Thomas Vachuska586bc4f2016-08-19 12:44:26 -0700224 try {
Ray Milkeyd7ed6972018-11-15 18:24:22 -0800225 DeviceId srcDeviceId = DeviceId.deviceId(idString);
226 DeviceId dstDeviceId = packetContext.inPacket().receivedFrom().deviceId();
227
228 ConnectPoint src = new ConnectPoint(srcDeviceId, srcPort);
229 ConnectPoint dst = new ConnectPoint(dstDeviceId, dstPort);
230
231 LinkDescription ld = new DefaultLinkDescription(src, dst, lt);
Thomas Vachuska586bc4f2016-08-19 12:44:26 -0700232 context.providerService().linkDetected(ld);
233 context.touchLink(LinkKey.linkKey(src, dst));
Ray Milkeyd7ed6972018-11-15 18:24:22 -0800234 } catch (IllegalStateException | IllegalArgumentException e) {
235 log.warn("There is a exception during link creation: {}", e.getMessage());
Thomas Vachuska586bc4f2016-08-19 12:44:26 -0700236 return true;
237 }
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700238 return true;
239 }
alshabib7911a052014-10-16 17:49:37 -0700240 }
241 return false;
242 }
243
DongRyeol Chace65cc02018-07-23 15:02:28 +0900244 private boolean processLldp(PacketContext packetContext, Ethernet eth) {
245 ONOSLLDP onoslldp = ONOSLLDP.parseLLDP(eth);
246 if (onoslldp != null) {
247 Type lt = eth.getEtherType() == Ethernet.TYPE_LLDP ?
248 Type.DIRECT : Type.INDIRECT;
249
250 DeviceService deviceService = context.deviceService();
251 MacAddress srcChassisId = onoslldp.getChassisIdByMac();
252 String srcPortName = onoslldp.getPortNameString();
253 String srcPortDesc = onoslldp.getPortDescString();
254
255 log.debug("srcChassisId:{}, srcPortName:{}, srcPortDesc:{}", srcChassisId, srcPortName, srcPortDesc);
256
257 if (srcChassisId == null && srcPortDesc == null) {
258 log.warn("there are no valid port id");
259 return false;
260 }
261
262 Optional<Device> srcDevice = findSourceDeviceByChassisId(deviceService, srcChassisId);
263
264 if (!srcDevice.isPresent()) {
265 log.warn("source device not found. srcChassisId value: {}", srcChassisId);
266 return false;
267 }
268 Optional<Port> sourcePort = findSourcePortByName(
269 srcPortName == null ? srcPortDesc : srcPortName,
270 deviceService,
271 srcDevice.get());
272
273 if (!sourcePort.isPresent()) {
274 log.warn("source port not found. sourcePort value: {}", sourcePort);
275 return false;
276 }
277
278 PortNumber srcPort = sourcePort.get().number();
279 PortNumber dstPort = packetContext.inPacket().receivedFrom().port();
280
281 DeviceId srcDeviceId = srcDevice.get().id();
282 DeviceId dstDeviceId = packetContext.inPacket().receivedFrom().deviceId();
283
284 ConnectPoint src = new ConnectPoint(srcDeviceId, srcPort);
285 ConnectPoint dst = new ConnectPoint(dstDeviceId, dstPort);
286
287 DefaultAnnotations annotations = DefaultAnnotations.builder()
288 .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
289 .set(AnnotationKeys.LAYER, ETHERNET)
290 .build();
291
292 LinkDescription ld = new DefaultLinkDescription(src, dst, lt, true, annotations);
293 try {
294 context.providerService().linkDetected(ld);
295 context.setTtl(LinkKey.linkKey(src, dst), onoslldp.getTtlBySeconds());
296 } catch (IllegalStateException e) {
297 log.debug("There is a exception during link creation: {}", e);
298 return true;
299 }
300 return true;
301 }
302 return false;
303 }
304
305 private Optional<Device> findSourceDeviceByChassisId(DeviceService deviceService, MacAddress srcChassisId) {
306 Supplier<Stream<Device>> deviceStream = () ->
307 StreamSupport.stream(deviceService.getAvailableDevices().spliterator(), false);
308 Optional<Device> remoteDeviceOptional = deviceStream.get()
309 .filter(device -> device.chassisId() != null
310 && MacAddress.valueOf(device.chassisId().value()).equals(srcChassisId))
311 .findAny();
312
313 if (remoteDeviceOptional.isPresent()) {
314 log.debug("sourceDevice found by chassis id: {}", srcChassisId);
315 return remoteDeviceOptional;
316 } else {
317 remoteDeviceOptional = deviceStream.get().filter(device ->
318 Tools.stream(deviceService.getPorts(device.id()))
319 .anyMatch(port -> port.annotations().keys().contains(AnnotationKeys.PORT_MAC)
320 && MacAddress.valueOf(port.annotations().value(AnnotationKeys.PORT_MAC))
321 .equals(srcChassisId)))
322 .findAny();
323 if (remoteDeviceOptional.isPresent()) {
324 log.debug("sourceDevice found by port mac: {}", srcChassisId);
325 return remoteDeviceOptional;
326 } else {
327 return Optional.empty();
328 }
329 }
330 }
331
332 private Optional<Port> findSourcePortByName(String remotePortName,
333 DeviceService deviceService,
334 Device remoteDevice) {
Ray Milkey208bcb32018-11-15 10:22:44 -0800335 if (remotePortName == null) {
336 return Optional.empty();
337 }
DongRyeol Chace65cc02018-07-23 15:02:28 +0900338 Optional<Port> remotePort = deviceService.getPorts(remoteDevice.id())
Ray Milkeye3c454e2018-11-14 10:47:50 -0800339 .stream().filter(port -> Objects.equals(remotePortName,
340 port.annotations().value(AnnotationKeys.PORT_NAME)))
DongRyeol Chace65cc02018-07-23 15:02:28 +0900341 .findAny();
342
343 if (remotePort.isPresent()) {
344 return remotePort;
345 } else {
346 int portNumber = Integer.parseInt(remotePortName.replaceAll("\\D+", ""));
347 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
348 .set(AnnotationKeys.PORT_NAME, remotePortName);
349
350 return Optional.of(new DefaultPort(remoteDevice, PortNumber.portNumber(portNumber),
351 true,
352 annotations.build()));
353 }
354 }
355
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800356 // true if *NOT* this cluster's own probe.
Ayaka Koshibe48229222016-05-16 18:04:26 -0700357 private boolean notMy(String mac) {
358 // if we are using DEFAULT_MAC, clustering hadn't initialized, so conservative 'yes'
359 String ourMac = context.fingerprint();
360 if (ProbedLinkProvider.defaultMac().equalsIgnoreCase(ourMac)) {
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800361 return true;
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800362 }
Ayaka Koshibe48229222016-05-16 18:04:26 -0700363 return !mac.equalsIgnoreCase(ourMac);
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800364 }
alshabib7911a052014-10-16 17:49:37 -0700365
alshabib7911a052014-10-16 17:49:37 -0700366 /**
367 * Execute this method every t milliseconds. Loops over all ports
368 * labeled as fast and sends out an LLDP. Send out an LLDP on a single slow
369 * port.
370 *
371 * @param t timeout
alshabib7911a052014-10-16 17:49:37 -0700372 */
373 @Override
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700374 public void run(Timeout t) {
Yuta HIGUCHI34198582014-11-10 16:24:58 -0800375 if (isStopped()) {
376 return;
377 }
Thomas Vachuska05453c92015-09-09 14:40:49 -0700378
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700379 if (context.mastershipService().isLocalMaster(device.id())) {
380 log.trace("Sending probes from {}", device.id());
Ray Milkey1ab441b2018-03-06 15:33:44 -0800381 ImmutableMap.copyOf(portMap).forEach(this::sendProbes);
Yuta HIGUCHIf6725882014-10-29 15:25:51 -0700382 }
383
Yuta HIGUCHI32255782014-11-04 22:32:14 -0800384 if (!isStopped()) {
Yuta HIGUCHI19afc032017-05-20 23:44:17 -0700385 timeout = t.timer().newTimeout(this, context.probeRate(), MILLISECONDS);
Yuta HIGUCHI32255782014-11-04 22:32:14 -0800386 }
alshabib7911a052014-10-16 17:49:37 -0700387 }
388
alshabib7911a052014-10-16 17:49:37 -0700389 /**
390 * Creates packet_out LLDP for specified output port.
391 *
jaegonkimd9119d0d2018-02-06 23:16:52 +0900392 * @param portNumber the port
393 * @param portDesc the port description
alshabib7911a052014-10-16 17:49:37 -0700394 * @return Packet_out message with LLDP data
395 */
jaegonkimd9119d0d2018-02-06 23:16:52 +0900396 private OutboundPacket createOutBoundLldp(Long portNumber, String portDesc) {
397 if (portNumber == null) {
alshabib7911a052014-10-16 17:49:37 -0700398 return null;
399 }
David K. Bainbridgebbbb9422018-11-05 14:52:38 -0800400 ONOSLLDP lldp = getLinkProbe(context.deviceService().getDevice(device.id()).chassisId(),
401 portNumber, portDesc);
Ayaka Koshibe48229222016-05-16 18:04:26 -0700402 ethPacket.setSourceMACAddress(context.fingerprint()).setPayload(lldp);
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700403 return new DefaultOutboundPacket(device.id(),
jaegonkimd9119d0d2018-02-06 23:16:52 +0900404 builder().setOutput(portNumber(portNumber)).build(),
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700405 ByteBuffer.wrap(ethPacket.serialize()));
alshabib7911a052014-10-16 17:49:37 -0700406 }
407
408 /**
409 * Creates packet_out BDDP for specified output port.
410 *
jaegonkimd9119d0d2018-02-06 23:16:52 +0900411 * @param portNumber the port
412 * @param portDesc the port description
alshabib7911a052014-10-16 17:49:37 -0700413 * @return Packet_out message with LLDP data
414 */
jaegonkimd9119d0d2018-02-06 23:16:52 +0900415 private OutboundPacket createOutBoundBddp(Long portNumber, String portDesc) {
416 if (portNumber == null) {
alshabib7911a052014-10-16 17:49:37 -0700417 return null;
418 }
David K. Bainbridgebbbb9422018-11-05 14:52:38 -0800419 ONOSLLDP lldp = getLinkProbe(context.deviceService().getDevice(device.id()).chassisId(),
420 portNumber, portDesc);
Ayaka Koshibe48229222016-05-16 18:04:26 -0700421 bddpEth.setSourceMACAddress(context.fingerprint()).setPayload(lldp);
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700422 return new DefaultOutboundPacket(device.id(),
jaegonkimd9119d0d2018-02-06 23:16:52 +0900423 builder().setOutput(portNumber(portNumber)).build(),
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700424 ByteBuffer.wrap(bddpEth.serialize()));
alshabib7911a052014-10-16 17:49:37 -0700425 }
426
David K. Bainbridgebbbb9422018-11-05 14:52:38 -0800427 private ONOSLLDP getLinkProbe(ChassisId chassisId, Long portNumber, String portDesc) {
428 return ONOSLLDP.onosSecureLLDP(device.id().toString(), chassisId, portNumber.intValue(),
Samuel Jero31e16f52018-09-21 10:34:28 -0400429 context.lldpSecret());
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800430 }
431
jaegonkimd9119d0d2018-02-06 23:16:52 +0900432 private void sendProbes(Long portNumber, String portDesc) {
Ray Milkeyd9bbde82016-06-09 11:35:00 -0700433 if (context.packetService() == null) {
434 return;
435 }
Jon Hall274cecb2017-08-09 12:15:48 -0700436 log.trace("Sending probes out of {}@{}", portNumber, device.id());
jaegonkimd9119d0d2018-02-06 23:16:52 +0900437 OutboundPacket pkt = createOutBoundLldp(portNumber, portDesc);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700438 context.packetService().emit(pkt);
Jonathan Hartb35540a2015-11-17 09:30:56 -0800439 if (context.useBddp()) {
jaegonkimd9119d0d2018-02-06 23:16:52 +0900440 OutboundPacket bpkt = createOutBoundBddp(portNumber, portDesc);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700441 context.packetService().emit(bpkt);
Thomas Vachuskae1bcb0b2014-10-27 17:45:10 -0700442 }
alshabib7911a052014-10-16 17:49:37 -0700443 }
444
Ray Milkey957390e2016-02-09 10:02:46 -0800445 public boolean containsPort(long portNumber) {
jaegonkimd9119d0d2018-02-06 23:16:52 +0900446 return portMap.containsKey(portNumber);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700447 }
alshabib7911a052014-10-16 17:49:37 -0700448}