blob: 09807ac557f805a346649980975cae6ba369f612 [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;
Jonathan Harte8600eb2015-01-12 10:30:45 -080023import org.onlab.packet.Ethernet;
Charles Chan928ff8b2017-05-04 12:22:54 -070024import org.onlab.packet.MacAddress;
Jonathan Harte8600eb2015-01-12 10:30:45 -080025import org.onlab.packet.ONOSLLDP;
26import org.onlab.util.Timer;
DongRyeol Chace65cc02018-07-23 15:02:28 +090027import org.onlab.util.Tools;
28import org.onosproject.net.AnnotationKeys;
Brian O'Connorabafb502014-12-02 22:26:20 -080029import org.onosproject.net.ConnectPoint;
DongRyeol Chace65cc02018-07-23 15:02:28 +090030import org.onosproject.net.DefaultAnnotations;
31import org.onosproject.net.DefaultPort;
Brian O'Connorabafb502014-12-02 22:26:20 -080032import org.onosproject.net.Device;
33import org.onosproject.net.DeviceId;
34import org.onosproject.net.Link.Type;
Thomas Vachuska05453c92015-09-09 14:40:49 -070035import org.onosproject.net.LinkKey;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.net.Port;
37import org.onosproject.net.PortNumber;
DongRyeol Chace65cc02018-07-23 15:02:28 +090038import org.onosproject.net.device.DeviceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080039import org.onosproject.net.link.DefaultLinkDescription;
40import org.onosproject.net.link.LinkDescription;
Ray Milkey44ba9372018-05-07 09:37:37 -070041import org.onosproject.net.link.ProbedLinkProvider;
Brian O'Connorabafb502014-12-02 22:26:20 -080042import org.onosproject.net.packet.DefaultOutboundPacket;
43import org.onosproject.net.packet.OutboundPacket;
44import org.onosproject.net.packet.PacketContext;
alshabib7911a052014-10-16 17:49:37 -070045import org.slf4j.Logger;
46
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070047import java.nio.ByteBuffer;
Ray Milkey44ba9372018-05-07 09:37:37 -070048import java.util.Map;
Ray Milkeye3c454e2018-11-14 10:47:50 -080049import java.util.Objects;
DongRyeol Chace65cc02018-07-23 15:02:28 +090050import java.util.Optional;
51import java.util.function.Supplier;
52import java.util.stream.Stream;
53import java.util.stream.StreamSupport;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070054
Thomas Vachuska586bc4f2016-08-19 12:44:26 -070055import static com.google.common.base.Strings.isNullOrEmpty;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070056import static java.util.concurrent.TimeUnit.MILLISECONDS;
jaegonkimd9119d0d2018-02-06 23:16:52 +090057import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070058import static org.onosproject.net.PortNumber.portNumber;
59import static org.onosproject.net.flow.DefaultTrafficTreatment.builder;
60import static org.slf4j.LoggerFactory.getLogger;
61
alshabib7911a052014-10-16 17:49:37 -070062/**
63 * Run discovery process from a physical switch. Ports are initially labeled as
64 * slow ports. When an LLDP is successfully received, label the remote port as
65 * fast. Every probeRate milliseconds, loop over all fast ports and send an
66 * LLDP, send an LLDP for a single slow port. Based on FlowVisor topology
67 * discovery implementation.
alshabib7911a052014-10-16 17:49:37 -070068 */
Ray Milkey957390e2016-02-09 10:02:46 -080069public class LinkDiscovery implements TimerTask {
alshabib7911a052014-10-16 17:49:37 -070070
DongRyeol Chace65cc02018-07-23 15:02:28 +090071 private static final String SCHEME_NAME = "linkdiscovery";
72 private static final String ETHERNET = "ETHERNET";
73
alshabib7911a052014-10-16 17:49:37 -070074 private final Logger log = getLogger(getClass());
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070075
DongRyeol Chac80570b2018-11-07 11:55:32 +090076 private final DeviceId deviceId;
Ray Milkey957390e2016-02-09 10:02:46 -080077 private final LinkDiscoveryContext context;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070078
alshabib7911a052014-10-16 17:49:37 -070079 private final Ethernet ethPacket;
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070080 private final Ethernet bddpEth;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070081
82 private Timeout timeout;
83 private volatile boolean isStopped;
Thomas Vachuska9280e192018-03-06 11:19:29 -080084
Thomas Vachuska05453c92015-09-09 14:40:49 -070085 // Set of ports to be probed
Ray Milkey44ba9372018-05-07 09:37:37 -070086 private final Map<Long, String> portMap = Maps.newConcurrentMap();
alshabib7911a052014-10-16 17:49:37 -070087 /**
88 * Instantiates discovery manager for the given physical switch. Creates a
89 * generic LLDP packet that will be customized for the port it is sent out on.
90 * Starts the the timer for the discovery process.
Thomas Vachuskae1bcb0b2014-10-27 17:45:10 -070091 *
DongRyeol Chac80570b2018-11-07 11:55:32 +090092 * @param deviceId the physical switch
Thomas Vachuska05453c92015-09-09 14:40:49 -070093 * @param context discovery context
alshabib7911a052014-10-16 17:49:37 -070094 */
DongRyeol Chac80570b2018-11-07 11:55:32 +090095 public LinkDiscovery(DeviceId deviceId, LinkDiscoveryContext context) {
96 this.deviceId = deviceId;
Thomas Vachuska05453c92015-09-09 14:40:49 -070097 this.context = context;
alshabib3d643ec2014-10-22 18:33:00 -070098
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070099 ethPacket = new Ethernet();
100 ethPacket.setEtherType(Ethernet.TYPE_LLDP);
Charles Chan928ff8b2017-05-04 12:22:54 -0700101 ethPacket.setDestinationMACAddress(MacAddress.ONOS_LLDP);
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700102 ethPacket.setPad(true);
alshabib7911a052014-10-16 17:49:37 -0700103
Thomas Vachuska05453c92015-09-09 14:40:49 -0700104 bddpEth = new Ethernet();
Thomas Vachuska05453c92015-09-09 14:40:49 -0700105 bddpEth.setEtherType(Ethernet.TYPE_BSN);
Charles Chan928ff8b2017-05-04 12:22:54 -0700106 bddpEth.setDestinationMACAddress(MacAddress.BROADCAST);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700107 bddpEth.setPad(true);
alshabib7911a052014-10-16 17:49:37 -0700108
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700109 isStopped = true;
alshabib7911a052014-10-16 17:49:37 -0700110 start();
DongRyeol Chac80570b2018-11-07 11:55:32 +0900111 log.debug("Started discovery manager for switch {}", deviceId);
alshabib7911a052014-10-16 17:49:37 -0700112
113 }
114
Ray Milkey957390e2016-02-09 10:02:46 -0800115 public synchronized void stop() {
Jon Hall3edc08a2015-09-14 16:59:07 -0700116 if (!isStopped) {
117 isStopped = true;
118 timeout.cancel();
119 } else {
120 log.warn("LinkDiscovery stopped multiple times?");
121 }
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700122 }
123
Ray Milkey957390e2016-02-09 10:02:46 -0800124 public synchronized void start() {
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700125 if (isStopped) {
126 isStopped = false;
Yuta HIGUCHI19afc032017-05-20 23:44:17 -0700127 timeout = Timer.newTimeout(this, 0, MILLISECONDS);
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700128 } else {
129 log.warn("LinkDiscovery started multiple times?");
130 }
131 }
132
Ray Milkey957390e2016-02-09 10:02:46 -0800133 public synchronized boolean isStopped() {
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700134 return isStopped || timeout.isCancelled();
135 }
136
alshabib7911a052014-10-16 17:49:37 -0700137 /**
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700138 * Add physical port to discovery process.
alshabib7911a052014-10-16 17:49:37 -0700139 * Send out initial LLDP and label it as slow port.
140 *
141 * @param port the port
142 */
Ray Milkey957390e2016-02-09 10:02:46 -0800143 public void addPort(Port port) {
jaegonkimd9119d0d2018-02-06 23:16:52 +0900144 Long portNum = port.number().toLong();
145 String portName = port.annotations().value(PORT_NAME);
jaegonkimaaa4f832018-03-11 00:48:36 +0900146 if (portName == null) {
147 portName = StringUtil.EMPTY_STRING;
148 }
jaegonkimd9119d0d2018-02-06 23:16:52 +0900149
You Wang168aa622018-03-08 14:01:37 -0800150 boolean newPort = !containsPort(portNum);
jaegonkimd9119d0d2018-02-06 23:16:52 +0900151 portMap.put(portNum, portName);
152
DongRyeol Chac80570b2018-11-07 11:55:32 +0900153 boolean isMaster = context.mastershipService().isLocalMaster(deviceId);
Jonathan Hart45066bc2015-07-28 11:18:34 -0700154 if (newPort && isMaster) {
DongRyeol Chac80570b2018-11-07 11:55:32 +0900155 log.debug("Sending initial probe to port {}@{}", port.number().toLong(), deviceId);
jaegonkimd9119d0d2018-02-06 23:16:52 +0900156 sendProbes(portNum, portName);
alshabib7911a052014-10-16 17:49:37 -0700157 }
alshabib7911a052014-10-16 17:49:37 -0700158 }
159
160 /**
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700161 * removed physical port from discovery process.
162 * @param port the port number
163 */
Ray Milkey957390e2016-02-09 10:02:46 -0800164 public void removePort(PortNumber port) {
jaegonkimd9119d0d2018-02-06 23:16:52 +0900165 portMap.remove(port.toLong());
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700166 }
167
168 /**
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700169 * Handles an incoming LLDP packet. Creates link in topology and adds the
170 * link for staleness tracking.
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700171 *
Thomas Vachuska05453c92015-09-09 14:40:49 -0700172 * @param packetContext packet context
Yuta HIGUCHI5c947272014-11-03 21:39:21 -0800173 * @return true if handled
alshabib7911a052014-10-16 17:49:37 -0700174 */
Ray Milkey957390e2016-02-09 10:02:46 -0800175 public boolean handleLldp(PacketContext packetContext) {
Thomas Vachuska05453c92015-09-09 14:40:49 -0700176 Ethernet eth = packetContext.inPacket().parsed();
Jonathan Harte8600eb2015-01-12 10:30:45 -0800177 if (eth == null) {
178 return false;
179 }
180
DongRyeol Chace65cc02018-07-23 15:02:28 +0900181 if (processOnosLldp(packetContext, eth)) {
182 return true;
183 }
184
185 if (processLldp(packetContext, eth)) {
186 return true;
187 }
188
189 ONOSLLDP lldp = ONOSLLDP.parseLLDP(eth);
190
191 if (lldp == null) {
192 log.debug("Cannot parse the packet. It seems that it is not the lldp or bsn packet.");
193 } else {
194 log.debug("LLDP packet is dropped due to there are no handlers that properly handle this packet: {}",
195 lldp.toString());
196 }
197
198 return false;
199 }
200
201 private boolean processOnosLldp(PacketContext packetContext, Ethernet eth) {
alshabib7911a052014-10-16 17:49:37 -0700202 ONOSLLDP onoslldp = ONOSLLDP.parseONOSLLDP(eth);
203 if (onoslldp != null) {
Ayaka Koshibe48229222016-05-16 18:04:26 -0700204 Type lt;
205 if (notMy(eth.getSourceMAC().toString())) {
206 lt = Type.EDGE;
207 } else {
208 lt = eth.getEtherType() == Ethernet.TYPE_LLDP ?
209 Type.DIRECT : Type.INDIRECT;
Samuel Jero31e16f52018-09-21 10:34:28 -0400210
211 /* Verify MAC in LLDP packets */
212 if (!ONOSLLDP.verify(onoslldp, context.lldpSecret(), context.maxDiscoveryDelay())) {
213 log.warn("LLDP Packet failed to validate!");
214 return true;
215 }
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800216 }
217
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700218 PortNumber srcPort = portNumber(onoslldp.getPort());
Thomas Vachuska05453c92015-09-09 14:40:49 -0700219 PortNumber dstPort = packetContext.inPacket().receivedFrom().port();
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700220
Thomas Vachuska586bc4f2016-08-19 12:44:26 -0700221 String idString = onoslldp.getDeviceString();
222 if (!isNullOrEmpty(idString)) {
Thomas Vachuska586bc4f2016-08-19 12:44:26 -0700223 try {
Ray Milkeyd7ed6972018-11-15 18:24:22 -0800224 DeviceId srcDeviceId = DeviceId.deviceId(idString);
225 DeviceId dstDeviceId = packetContext.inPacket().receivedFrom().deviceId();
226
227 ConnectPoint src = new ConnectPoint(srcDeviceId, srcPort);
228 ConnectPoint dst = new ConnectPoint(dstDeviceId, dstPort);
229
230 LinkDescription ld = new DefaultLinkDescription(src, dst, lt);
Thomas Vachuska586bc4f2016-08-19 12:44:26 -0700231 context.providerService().linkDetected(ld);
232 context.touchLink(LinkKey.linkKey(src, dst));
Ray Milkeyd7ed6972018-11-15 18:24:22 -0800233 } catch (IllegalStateException | IllegalArgumentException e) {
234 log.warn("There is a exception during link creation: {}", e.getMessage());
Thomas Vachuska586bc4f2016-08-19 12:44:26 -0700235 return true;
236 }
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700237 return true;
238 }
alshabib7911a052014-10-16 17:49:37 -0700239 }
240 return false;
241 }
242
DongRyeol Chace65cc02018-07-23 15:02:28 +0900243 private boolean processLldp(PacketContext packetContext, Ethernet eth) {
244 ONOSLLDP onoslldp = ONOSLLDP.parseLLDP(eth);
245 if (onoslldp != null) {
246 Type lt = eth.getEtherType() == Ethernet.TYPE_LLDP ?
247 Type.DIRECT : Type.INDIRECT;
248
249 DeviceService deviceService = context.deviceService();
250 MacAddress srcChassisId = onoslldp.getChassisIdByMac();
251 String srcPortName = onoslldp.getPortNameString();
252 String srcPortDesc = onoslldp.getPortDescString();
253
254 log.debug("srcChassisId:{}, srcPortName:{}, srcPortDesc:{}", srcChassisId, srcPortName, srcPortDesc);
255
256 if (srcChassisId == null && srcPortDesc == null) {
257 log.warn("there are no valid port id");
258 return false;
259 }
260
261 Optional<Device> srcDevice = findSourceDeviceByChassisId(deviceService, srcChassisId);
262
263 if (!srcDevice.isPresent()) {
264 log.warn("source device not found. srcChassisId value: {}", srcChassisId);
265 return false;
266 }
267 Optional<Port> sourcePort = findSourcePortByName(
268 srcPortName == null ? srcPortDesc : srcPortName,
269 deviceService,
270 srcDevice.get());
271
272 if (!sourcePort.isPresent()) {
273 log.warn("source port not found. sourcePort value: {}", sourcePort);
274 return false;
275 }
276
277 PortNumber srcPort = sourcePort.get().number();
278 PortNumber dstPort = packetContext.inPacket().receivedFrom().port();
279
280 DeviceId srcDeviceId = srcDevice.get().id();
281 DeviceId dstDeviceId = packetContext.inPacket().receivedFrom().deviceId();
282
283 ConnectPoint src = new ConnectPoint(srcDeviceId, srcPort);
284 ConnectPoint dst = new ConnectPoint(dstDeviceId, dstPort);
285
286 DefaultAnnotations annotations = DefaultAnnotations.builder()
287 .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
288 .set(AnnotationKeys.LAYER, ETHERNET)
289 .build();
290
291 LinkDescription ld = new DefaultLinkDescription(src, dst, lt, true, annotations);
292 try {
293 context.providerService().linkDetected(ld);
294 context.setTtl(LinkKey.linkKey(src, dst), onoslldp.getTtlBySeconds());
295 } catch (IllegalStateException e) {
296 log.debug("There is a exception during link creation: {}", e);
297 return true;
298 }
299 return true;
300 }
301 return false;
302 }
303
304 private Optional<Device> findSourceDeviceByChassisId(DeviceService deviceService, MacAddress srcChassisId) {
305 Supplier<Stream<Device>> deviceStream = () ->
306 StreamSupport.stream(deviceService.getAvailableDevices().spliterator(), false);
307 Optional<Device> remoteDeviceOptional = deviceStream.get()
308 .filter(device -> device.chassisId() != null
309 && MacAddress.valueOf(device.chassisId().value()).equals(srcChassisId))
310 .findAny();
311
312 if (remoteDeviceOptional.isPresent()) {
313 log.debug("sourceDevice found by chassis id: {}", srcChassisId);
314 return remoteDeviceOptional;
315 } else {
316 remoteDeviceOptional = deviceStream.get().filter(device ->
317 Tools.stream(deviceService.getPorts(device.id()))
318 .anyMatch(port -> port.annotations().keys().contains(AnnotationKeys.PORT_MAC)
319 && MacAddress.valueOf(port.annotations().value(AnnotationKeys.PORT_MAC))
320 .equals(srcChassisId)))
321 .findAny();
322 if (remoteDeviceOptional.isPresent()) {
323 log.debug("sourceDevice found by port mac: {}", srcChassisId);
324 return remoteDeviceOptional;
325 } else {
326 return Optional.empty();
327 }
328 }
329 }
330
331 private Optional<Port> findSourcePortByName(String remotePortName,
332 DeviceService deviceService,
333 Device remoteDevice) {
Ray Milkey208bcb32018-11-15 10:22:44 -0800334 if (remotePortName == null) {
335 return Optional.empty();
336 }
DongRyeol Chace65cc02018-07-23 15:02:28 +0900337 Optional<Port> remotePort = deviceService.getPorts(remoteDevice.id())
Ray Milkeye3c454e2018-11-14 10:47:50 -0800338 .stream().filter(port -> Objects.equals(remotePortName,
339 port.annotations().value(AnnotationKeys.PORT_NAME)))
DongRyeol Chace65cc02018-07-23 15:02:28 +0900340 .findAny();
341
342 if (remotePort.isPresent()) {
343 return remotePort;
344 } else {
345 int portNumber = Integer.parseInt(remotePortName.replaceAll("\\D+", ""));
346 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
347 .set(AnnotationKeys.PORT_NAME, remotePortName);
348
349 return Optional.of(new DefaultPort(remoteDevice, PortNumber.portNumber(portNumber),
350 true,
351 annotations.build()));
352 }
353 }
354
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800355 // true if *NOT* this cluster's own probe.
Ayaka Koshibe48229222016-05-16 18:04:26 -0700356 private boolean notMy(String mac) {
357 // if we are using DEFAULT_MAC, clustering hadn't initialized, so conservative 'yes'
358 String ourMac = context.fingerprint();
359 if (ProbedLinkProvider.defaultMac().equalsIgnoreCase(ourMac)) {
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800360 return true;
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800361 }
Ayaka Koshibe48229222016-05-16 18:04:26 -0700362 return !mac.equalsIgnoreCase(ourMac);
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800363 }
alshabib7911a052014-10-16 17:49:37 -0700364
alshabib7911a052014-10-16 17:49:37 -0700365 /**
366 * Execute this method every t milliseconds. Loops over all ports
367 * labeled as fast and sends out an LLDP. Send out an LLDP on a single slow
368 * port.
369 *
370 * @param t timeout
alshabib7911a052014-10-16 17:49:37 -0700371 */
372 @Override
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700373 public void run(Timeout t) {
Yuta HIGUCHI34198582014-11-10 16:24:58 -0800374 if (isStopped()) {
375 return;
376 }
Thomas Vachuska05453c92015-09-09 14:40:49 -0700377
DongRyeol Chac80570b2018-11-07 11:55:32 +0900378 if (context.mastershipService().isLocalMaster(deviceId)) {
379 log.trace("Sending probes from {}", deviceId);
Ray Milkey1ab441b2018-03-06 15:33:44 -0800380 ImmutableMap.copyOf(portMap).forEach(this::sendProbes);
Yuta HIGUCHIf6725882014-10-29 15:25:51 -0700381 }
382
Yuta HIGUCHI32255782014-11-04 22:32:14 -0800383 if (!isStopped()) {
Yuta HIGUCHI19afc032017-05-20 23:44:17 -0700384 timeout = t.timer().newTimeout(this, context.probeRate(), MILLISECONDS);
Yuta HIGUCHI32255782014-11-04 22:32:14 -0800385 }
alshabib7911a052014-10-16 17:49:37 -0700386 }
387
alshabib7911a052014-10-16 17:49:37 -0700388 /**
389 * Creates packet_out LLDP for specified output port.
390 *
jaegonkimd9119d0d2018-02-06 23:16:52 +0900391 * @param portNumber the port
392 * @param portDesc the port description
alshabib7911a052014-10-16 17:49:37 -0700393 * @return Packet_out message with LLDP data
394 */
jaegonkimd9119d0d2018-02-06 23:16:52 +0900395 private OutboundPacket createOutBoundLldp(Long portNumber, String portDesc) {
396 if (portNumber == null) {
alshabib7911a052014-10-16 17:49:37 -0700397 return null;
398 }
DongRyeol Chac80570b2018-11-07 11:55:32 +0900399 ONOSLLDP lldp = getLinkProbe(portNumber, portDesc);
400 if (lldp == null) {
401 log.warn("Cannot get link probe with portNumber {} and portDesc {} for {} at LLDP packet creation.",
402 portNumber, portDesc, deviceId);
403 return null;
404 }
Ayaka Koshibe48229222016-05-16 18:04:26 -0700405 ethPacket.setSourceMACAddress(context.fingerprint()).setPayload(lldp);
DongRyeol Chac80570b2018-11-07 11:55:32 +0900406 return new DefaultOutboundPacket(deviceId,
jaegonkimd9119d0d2018-02-06 23:16:52 +0900407 builder().setOutput(portNumber(portNumber)).build(),
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700408 ByteBuffer.wrap(ethPacket.serialize()));
alshabib7911a052014-10-16 17:49:37 -0700409 }
410
411 /**
412 * Creates packet_out BDDP for specified output port.
413 *
jaegonkimd9119d0d2018-02-06 23:16:52 +0900414 * @param portNumber the port
415 * @param portDesc the port description
alshabib7911a052014-10-16 17:49:37 -0700416 * @return Packet_out message with LLDP data
417 */
jaegonkimd9119d0d2018-02-06 23:16:52 +0900418 private OutboundPacket createOutBoundBddp(Long portNumber, String portDesc) {
419 if (portNumber == null) {
alshabib7911a052014-10-16 17:49:37 -0700420 return null;
421 }
DongRyeol Chac80570b2018-11-07 11:55:32 +0900422 ONOSLLDP lldp = getLinkProbe(portNumber, portDesc);
423 if (lldp == null) {
424 log.warn("Cannot get link probe with portNumber {} and portDesc {} for {} at BDDP packet creation.",
425 portNumber, portDesc, deviceId);
426 return null;
427 }
Ayaka Koshibe48229222016-05-16 18:04:26 -0700428 bddpEth.setSourceMACAddress(context.fingerprint()).setPayload(lldp);
DongRyeol Chac80570b2018-11-07 11:55:32 +0900429 return new DefaultOutboundPacket(deviceId,
jaegonkimd9119d0d2018-02-06 23:16:52 +0900430 builder().setOutput(portNumber(portNumber)).build(),
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700431 ByteBuffer.wrap(bddpEth.serialize()));
alshabib7911a052014-10-16 17:49:37 -0700432 }
433
DongRyeol Chac80570b2018-11-07 11:55:32 +0900434 private ONOSLLDP getLinkProbe(Long portNumber, String portDesc) {
435 Device device = context.deviceService().getDevice(deviceId);
436 if (device == null) {
437 log.warn("Cannot find the device {}", deviceId);
438 return null;
439 }
440 return ONOSLLDP.onosSecureLLDP(deviceId.toString(), device.chassisId(), portNumber.intValue(), portDesc,
Samuel Jero31e16f52018-09-21 10:34:28 -0400441 context.lldpSecret());
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800442 }
443
jaegonkimd9119d0d2018-02-06 23:16:52 +0900444 private void sendProbes(Long portNumber, String portDesc) {
Ray Milkeyd9bbde82016-06-09 11:35:00 -0700445 if (context.packetService() == null) {
446 return;
447 }
DongRyeol Chac80570b2018-11-07 11:55:32 +0900448 log.trace("Sending probes out of {}@{}", portNumber, deviceId);
jaegonkimd9119d0d2018-02-06 23:16:52 +0900449 OutboundPacket pkt = createOutBoundLldp(portNumber, portDesc);
DongRyeol Chac80570b2018-11-07 11:55:32 +0900450 if (pkt != null) {
451 context.packetService().emit(pkt);
452 } else {
453 log.warn("Cannot send lldp packet due to packet is null {}", deviceId);
454 }
Jonathan Hartb35540a2015-11-17 09:30:56 -0800455 if (context.useBddp()) {
jaegonkimd9119d0d2018-02-06 23:16:52 +0900456 OutboundPacket bpkt = createOutBoundBddp(portNumber, portDesc);
DongRyeol Chac80570b2018-11-07 11:55:32 +0900457 if (bpkt != null) {
458 context.packetService().emit(bpkt);
459 } else {
460 log.warn("Cannot send bddp packet due to packet is null {}", deviceId);
461 }
Thomas Vachuskae1bcb0b2014-10-27 17:45:10 -0700462 }
alshabib7911a052014-10-16 17:49:37 -0700463 }
464
Ray Milkey957390e2016-02-09 10:02:46 -0800465 public boolean containsPort(long portNumber) {
jaegonkimd9119d0d2018-02-06 23:16:52 +0900466 return portMap.containsKey(portNumber);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700467 }
alshabib7911a052014-10-16 17:49:37 -0700468}