blob: e743af566d6b36e8398138d4f0c46fae5ed7b5aa [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;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.net.Device;
32import org.onosproject.net.DeviceId;
33import org.onosproject.net.Link.Type;
Thomas Vachuska05453c92015-09-09 14:40:49 -070034import org.onosproject.net.LinkKey;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.Port;
36import org.onosproject.net.PortNumber;
DongRyeol Chace65cc02018-07-23 15:02:28 +090037import org.onosproject.net.device.DeviceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080038import org.onosproject.net.link.DefaultLinkDescription;
39import org.onosproject.net.link.LinkDescription;
Ray Milkey44ba9372018-05-07 09:37:37 -070040import org.onosproject.net.link.ProbedLinkProvider;
Brian O'Connorabafb502014-12-02 22:26:20 -080041import org.onosproject.net.packet.DefaultOutboundPacket;
42import org.onosproject.net.packet.OutboundPacket;
43import org.onosproject.net.packet.PacketContext;
alshabib7911a052014-10-16 17:49:37 -070044import org.slf4j.Logger;
45
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070046import java.nio.ByteBuffer;
Ray Milkey44ba9372018-05-07 09:37:37 -070047import java.util.Map;
Ray Milkeye3c454e2018-11-14 10:47:50 -080048import java.util.Objects;
DongRyeol Chace65cc02018-07-23 15:02:28 +090049import java.util.Optional;
50import java.util.function.Supplier;
51import java.util.stream.Stream;
52import java.util.stream.StreamSupport;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070053
Thomas Vachuska586bc4f2016-08-19 12:44:26 -070054import static com.google.common.base.Strings.isNullOrEmpty;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070055import static java.util.concurrent.TimeUnit.MILLISECONDS;
jaegonkimd9119d0d2018-02-06 23:16:52 +090056import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070057import static org.onosproject.net.PortNumber.portNumber;
58import static org.onosproject.net.flow.DefaultTrafficTreatment.builder;
59import static org.slf4j.LoggerFactory.getLogger;
60
alshabib7911a052014-10-16 17:49:37 -070061/**
62 * Run discovery process from a physical switch. Ports are initially labeled as
63 * slow ports. When an LLDP is successfully received, label the remote port as
64 * fast. Every probeRate milliseconds, loop over all fast ports and send an
65 * LLDP, send an LLDP for a single slow port. Based on FlowVisor topology
66 * discovery implementation.
alshabib7911a052014-10-16 17:49:37 -070067 */
Ray Milkey957390e2016-02-09 10:02:46 -080068public class LinkDiscovery implements TimerTask {
alshabib7911a052014-10-16 17:49:37 -070069
DongRyeol Chace65cc02018-07-23 15:02:28 +090070 private static final String SCHEME_NAME = "linkdiscovery";
71 private static final String ETHERNET = "ETHERNET";
72
alshabib7911a052014-10-16 17:49:37 -070073 private final Logger log = getLogger(getClass());
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070074
DongRyeol Chac80570b2018-11-07 11:55:32 +090075 private final DeviceId deviceId;
Ray Milkey957390e2016-02-09 10:02:46 -080076 private final LinkDiscoveryContext context;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070077
alshabib7911a052014-10-16 17:49:37 -070078 private final Ethernet ethPacket;
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070079 private final Ethernet bddpEth;
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070080
81 private Timeout timeout;
82 private volatile boolean isStopped;
Thomas Vachuska9280e192018-03-06 11:19:29 -080083
Thomas Vachuska05453c92015-09-09 14:40:49 -070084 // Set of ports to be probed
Ray Milkey44ba9372018-05-07 09:37:37 -070085 private final Map<Long, String> portMap = Maps.newConcurrentMap();
alshabib7911a052014-10-16 17:49:37 -070086 /**
87 * Instantiates discovery manager for the given physical switch. Creates a
88 * generic LLDP packet that will be customized for the port it is sent out on.
89 * Starts the the timer for the discovery process.
Thomas Vachuskae1bcb0b2014-10-27 17:45:10 -070090 *
DongRyeol Chac80570b2018-11-07 11:55:32 +090091 * @param deviceId the physical switch
Thomas Vachuska05453c92015-09-09 14:40:49 -070092 * @param context discovery context
alshabib7911a052014-10-16 17:49:37 -070093 */
DongRyeol Chac80570b2018-11-07 11:55:32 +090094 public LinkDiscovery(DeviceId deviceId, LinkDiscoveryContext context) {
95 this.deviceId = deviceId;
Thomas Vachuska05453c92015-09-09 14:40:49 -070096 this.context = context;
alshabib3d643ec2014-10-22 18:33:00 -070097
Thomas Vachuska96f3ea72015-09-08 13:50:12 -070098 ethPacket = new Ethernet();
99 ethPacket.setEtherType(Ethernet.TYPE_LLDP);
Charles Chan928ff8b2017-05-04 12:22:54 -0700100 ethPacket.setDestinationMACAddress(MacAddress.ONOS_LLDP);
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700101 ethPacket.setPad(true);
alshabib7911a052014-10-16 17:49:37 -0700102
Thomas Vachuska05453c92015-09-09 14:40:49 -0700103 bddpEth = new Ethernet();
Thomas Vachuska05453c92015-09-09 14:40:49 -0700104 bddpEth.setEtherType(Ethernet.TYPE_BSN);
Charles Chan928ff8b2017-05-04 12:22:54 -0700105 bddpEth.setDestinationMACAddress(MacAddress.BROADCAST);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700106 bddpEth.setPad(true);
alshabib7911a052014-10-16 17:49:37 -0700107
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700108 isStopped = true;
alshabib7911a052014-10-16 17:49:37 -0700109 start();
DongRyeol Chac80570b2018-11-07 11:55:32 +0900110 log.debug("Started discovery manager for switch {}", deviceId);
alshabib7911a052014-10-16 17:49:37 -0700111
112 }
113
Ray Milkey957390e2016-02-09 10:02:46 -0800114 public synchronized void stop() {
Jon Hall3edc08a2015-09-14 16:59:07 -0700115 if (!isStopped) {
116 isStopped = true;
117 timeout.cancel();
118 } else {
119 log.warn("LinkDiscovery stopped multiple times?");
120 }
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700121 }
122
Ray Milkey957390e2016-02-09 10:02:46 -0800123 public synchronized void start() {
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700124 if (isStopped) {
125 isStopped = false;
Yuta HIGUCHI19afc032017-05-20 23:44:17 -0700126 timeout = Timer.newTimeout(this, 0, MILLISECONDS);
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700127 } else {
128 log.warn("LinkDiscovery started multiple times?");
129 }
130 }
131
Ray Milkey957390e2016-02-09 10:02:46 -0800132 public synchronized boolean isStopped() {
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700133 return isStopped || timeout.isCancelled();
134 }
135
alshabib7911a052014-10-16 17:49:37 -0700136 /**
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700137 * Add physical port to discovery process.
alshabib7911a052014-10-16 17:49:37 -0700138 * Send out initial LLDP and label it as slow port.
139 *
140 * @param port the port
141 */
Ray Milkey957390e2016-02-09 10:02:46 -0800142 public void addPort(Port port) {
jaegonkimd9119d0d2018-02-06 23:16:52 +0900143 Long portNum = port.number().toLong();
144 String portName = port.annotations().value(PORT_NAME);
jaegonkimaaa4f832018-03-11 00:48:36 +0900145 if (portName == null) {
146 portName = StringUtil.EMPTY_STRING;
147 }
jaegonkimd9119d0d2018-02-06 23:16:52 +0900148
You Wang168aa622018-03-08 14:01:37 -0800149 boolean newPort = !containsPort(portNum);
jaegonkimd9119d0d2018-02-06 23:16:52 +0900150 portMap.put(portNum, portName);
151
DongRyeol Chac80570b2018-11-07 11:55:32 +0900152 boolean isMaster = context.mastershipService().isLocalMaster(deviceId);
Jonathan Hart45066bc2015-07-28 11:18:34 -0700153 if (newPort && isMaster) {
DongRyeol Chac80570b2018-11-07 11:55:32 +0900154 log.debug("Sending initial probe to port {}@{}", port.number().toLong(), deviceId);
jaegonkimd9119d0d2018-02-06 23:16:52 +0900155 sendProbes(portNum, portName);
alshabib7911a052014-10-16 17:49:37 -0700156 }
alshabib7911a052014-10-16 17:49:37 -0700157 }
158
159 /**
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700160 * removed physical port from discovery process.
161 * @param port the port number
162 */
Ray Milkey957390e2016-02-09 10:02:46 -0800163 public void removePort(PortNumber port) {
jaegonkimd9119d0d2018-02-06 23:16:52 +0900164 portMap.remove(port.toLong());
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700165 }
166
167 /**
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700168 * Handles an incoming LLDP packet. Creates link in topology and adds the
169 * link for staleness tracking.
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700170 *
Thomas Vachuska05453c92015-09-09 14:40:49 -0700171 * @param packetContext packet context
Yuta HIGUCHI5c947272014-11-03 21:39:21 -0800172 * @return true if handled
alshabib7911a052014-10-16 17:49:37 -0700173 */
Ray Milkey957390e2016-02-09 10:02:46 -0800174 public boolean handleLldp(PacketContext packetContext) {
Thomas Vachuska05453c92015-09-09 14:40:49 -0700175 Ethernet eth = packetContext.inPacket().parsed();
Jonathan Harte8600eb2015-01-12 10:30:45 -0800176 if (eth == null) {
177 return false;
178 }
179
DongRyeol Chace65cc02018-07-23 15:02:28 +0900180 if (processOnosLldp(packetContext, eth)) {
181 return true;
182 }
183
184 if (processLldp(packetContext, eth)) {
185 return true;
186 }
187
188 ONOSLLDP lldp = ONOSLLDP.parseLLDP(eth);
189
190 if (lldp == null) {
191 log.debug("Cannot parse the packet. It seems that it is not the lldp or bsn packet.");
192 } else {
193 log.debug("LLDP packet is dropped due to there are no handlers that properly handle this packet: {}",
194 lldp.toString());
195 }
196
197 return false;
198 }
199
200 private boolean processOnosLldp(PacketContext packetContext, Ethernet eth) {
alshabib7911a052014-10-16 17:49:37 -0700201 ONOSLLDP onoslldp = ONOSLLDP.parseONOSLLDP(eth);
202 if (onoslldp != null) {
Ayaka Koshibe48229222016-05-16 18:04:26 -0700203 Type lt;
204 if (notMy(eth.getSourceMAC().toString())) {
205 lt = Type.EDGE;
206 } else {
207 lt = eth.getEtherType() == Ethernet.TYPE_LLDP ?
208 Type.DIRECT : Type.INDIRECT;
Samuel Jero31e16f52018-09-21 10:34:28 -0400209
210 /* Verify MAC in LLDP packets */
211 if (!ONOSLLDP.verify(onoslldp, context.lldpSecret(), context.maxDiscoveryDelay())) {
212 log.warn("LLDP Packet failed to validate!");
213 return true;
214 }
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800215 }
216
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700217 PortNumber srcPort = portNumber(onoslldp.getPort());
Thomas Vachuska05453c92015-09-09 14:40:49 -0700218 PortNumber dstPort = packetContext.inPacket().receivedFrom().port();
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700219
Thomas Vachuska586bc4f2016-08-19 12:44:26 -0700220 String idString = onoslldp.getDeviceString();
221 if (!isNullOrEmpty(idString)) {
Thomas Vachuska586bc4f2016-08-19 12:44:26 -0700222 try {
Ray Milkeyd7ed6972018-11-15 18:24:22 -0800223 DeviceId srcDeviceId = DeviceId.deviceId(idString);
224 DeviceId dstDeviceId = packetContext.inPacket().receivedFrom().deviceId();
225
226 ConnectPoint src = new ConnectPoint(srcDeviceId, srcPort);
227 ConnectPoint dst = new ConnectPoint(dstDeviceId, dstPort);
228
229 LinkDescription ld = new DefaultLinkDescription(src, dst, lt);
Thomas Vachuska586bc4f2016-08-19 12:44:26 -0700230 context.providerService().linkDetected(ld);
231 context.touchLink(LinkKey.linkKey(src, dst));
Ray Milkeyd7ed6972018-11-15 18:24:22 -0800232 } catch (IllegalStateException | IllegalArgumentException e) {
233 log.warn("There is a exception during link creation: {}", e.getMessage());
Thomas Vachuska586bc4f2016-08-19 12:44:26 -0700234 return true;
235 }
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700236 return true;
237 }
alshabib7911a052014-10-16 17:49:37 -0700238 }
239 return false;
240 }
241
DongRyeol Chace65cc02018-07-23 15:02:28 +0900242 private boolean processLldp(PacketContext packetContext, Ethernet eth) {
243 ONOSLLDP onoslldp = ONOSLLDP.parseLLDP(eth);
244 if (onoslldp != null) {
245 Type lt = eth.getEtherType() == Ethernet.TYPE_LLDP ?
246 Type.DIRECT : Type.INDIRECT;
247
248 DeviceService deviceService = context.deviceService();
249 MacAddress srcChassisId = onoslldp.getChassisIdByMac();
250 String srcPortName = onoslldp.getPortNameString();
251 String srcPortDesc = onoslldp.getPortDescString();
252
253 log.debug("srcChassisId:{}, srcPortName:{}, srcPortDesc:{}", srcChassisId, srcPortName, srcPortDesc);
254
255 if (srcChassisId == null && srcPortDesc == null) {
256 log.warn("there are no valid port id");
257 return false;
258 }
259
260 Optional<Device> srcDevice = findSourceDeviceByChassisId(deviceService, srcChassisId);
261
262 if (!srcDevice.isPresent()) {
263 log.warn("source device not found. srcChassisId value: {}", srcChassisId);
264 return false;
265 }
266 Optional<Port> sourcePort = findSourcePortByName(
267 srcPortName == null ? srcPortDesc : srcPortName,
268 deviceService,
269 srcDevice.get());
270
271 if (!sourcePort.isPresent()) {
272 log.warn("source port not found. sourcePort value: {}", sourcePort);
273 return false;
274 }
275
276 PortNumber srcPort = sourcePort.get().number();
277 PortNumber dstPort = packetContext.inPacket().receivedFrom().port();
278
279 DeviceId srcDeviceId = srcDevice.get().id();
280 DeviceId dstDeviceId = packetContext.inPacket().receivedFrom().deviceId();
281
DongRyeol Cha81935a62018-11-30 16:51:21 +0900282 if (!sourcePort.get().isEnabled()) {
283 log.debug("Ports are disabled. Cannot create a link between {}/{} and {}/{}",
284 srcDeviceId, sourcePort.get(), dstDeviceId, dstPort);
285 return false;
286 }
287
DongRyeol Chace65cc02018-07-23 15:02:28 +0900288 ConnectPoint src = new ConnectPoint(srcDeviceId, srcPort);
289 ConnectPoint dst = new ConnectPoint(dstDeviceId, dstPort);
290
291 DefaultAnnotations annotations = DefaultAnnotations.builder()
292 .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
293 .set(AnnotationKeys.LAYER, ETHERNET)
294 .build();
295
296 LinkDescription ld = new DefaultLinkDescription(src, dst, lt, true, annotations);
297 try {
298 context.providerService().linkDetected(ld);
299 context.setTtl(LinkKey.linkKey(src, dst), onoslldp.getTtlBySeconds());
300 } catch (IllegalStateException e) {
301 log.debug("There is a exception during link creation: {}", e);
302 return true;
303 }
304 return true;
305 }
306 return false;
307 }
308
309 private Optional<Device> findSourceDeviceByChassisId(DeviceService deviceService, MacAddress srcChassisId) {
310 Supplier<Stream<Device>> deviceStream = () ->
311 StreamSupport.stream(deviceService.getAvailableDevices().spliterator(), false);
312 Optional<Device> remoteDeviceOptional = deviceStream.get()
313 .filter(device -> device.chassisId() != null
314 && MacAddress.valueOf(device.chassisId().value()).equals(srcChassisId))
315 .findAny();
316
317 if (remoteDeviceOptional.isPresent()) {
318 log.debug("sourceDevice found by chassis id: {}", srcChassisId);
319 return remoteDeviceOptional;
320 } else {
321 remoteDeviceOptional = deviceStream.get().filter(device ->
322 Tools.stream(deviceService.getPorts(device.id()))
323 .anyMatch(port -> port.annotations().keys().contains(AnnotationKeys.PORT_MAC)
324 && MacAddress.valueOf(port.annotations().value(AnnotationKeys.PORT_MAC))
325 .equals(srcChassisId)))
326 .findAny();
327 if (remoteDeviceOptional.isPresent()) {
328 log.debug("sourceDevice found by port mac: {}", srcChassisId);
329 return remoteDeviceOptional;
330 } else {
331 return Optional.empty();
332 }
333 }
334 }
335
336 private Optional<Port> findSourcePortByName(String remotePortName,
337 DeviceService deviceService,
338 Device remoteDevice) {
Ray Milkey208bcb32018-11-15 10:22:44 -0800339 if (remotePortName == null) {
340 return Optional.empty();
341 }
DongRyeol Chace65cc02018-07-23 15:02:28 +0900342 Optional<Port> remotePort = deviceService.getPorts(remoteDevice.id())
Ray Milkeye3c454e2018-11-14 10:47:50 -0800343 .stream().filter(port -> Objects.equals(remotePortName,
344 port.annotations().value(AnnotationKeys.PORT_NAME)))
DongRyeol Chace65cc02018-07-23 15:02:28 +0900345 .findAny();
346
347 if (remotePort.isPresent()) {
348 return remotePort;
349 } else {
DongRyeol Cha597315d2018-11-27 10:25:20 +0900350 return Optional.empty();
DongRyeol Chace65cc02018-07-23 15:02:28 +0900351 }
352 }
353
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800354 // true if *NOT* this cluster's own probe.
Ayaka Koshibe48229222016-05-16 18:04:26 -0700355 private boolean notMy(String mac) {
356 // if we are using DEFAULT_MAC, clustering hadn't initialized, so conservative 'yes'
357 String ourMac = context.fingerprint();
358 if (ProbedLinkProvider.defaultMac().equalsIgnoreCase(ourMac)) {
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800359 return true;
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800360 }
Ayaka Koshibe48229222016-05-16 18:04:26 -0700361 return !mac.equalsIgnoreCase(ourMac);
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800362 }
alshabib7911a052014-10-16 17:49:37 -0700363
alshabib7911a052014-10-16 17:49:37 -0700364 /**
365 * Execute this method every t milliseconds. Loops over all ports
366 * labeled as fast and sends out an LLDP. Send out an LLDP on a single slow
367 * port.
368 *
369 * @param t timeout
alshabib7911a052014-10-16 17:49:37 -0700370 */
371 @Override
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700372 public void run(Timeout t) {
Yuta HIGUCHI34198582014-11-10 16:24:58 -0800373 if (isStopped()) {
374 return;
375 }
Thomas Vachuska05453c92015-09-09 14:40:49 -0700376
DongRyeol Chac80570b2018-11-07 11:55:32 +0900377 if (context.mastershipService().isLocalMaster(deviceId)) {
378 log.trace("Sending probes from {}", deviceId);
Ray Milkey1ab441b2018-03-06 15:33:44 -0800379 ImmutableMap.copyOf(portMap).forEach(this::sendProbes);
Yuta HIGUCHIf6725882014-10-29 15:25:51 -0700380 }
381
Yuta HIGUCHI32255782014-11-04 22:32:14 -0800382 if (!isStopped()) {
Yuta HIGUCHI19afc032017-05-20 23:44:17 -0700383 timeout = t.timer().newTimeout(this, context.probeRate(), MILLISECONDS);
Yuta HIGUCHI32255782014-11-04 22:32:14 -0800384 }
alshabib7911a052014-10-16 17:49:37 -0700385 }
386
alshabib7911a052014-10-16 17:49:37 -0700387 /**
388 * Creates packet_out LLDP for specified output port.
389 *
jaegonkimd9119d0d2018-02-06 23:16:52 +0900390 * @param portNumber the port
391 * @param portDesc the port description
alshabib7911a052014-10-16 17:49:37 -0700392 * @return Packet_out message with LLDP data
393 */
jaegonkimd9119d0d2018-02-06 23:16:52 +0900394 private OutboundPacket createOutBoundLldp(Long portNumber, String portDesc) {
395 if (portNumber == null) {
alshabib7911a052014-10-16 17:49:37 -0700396 return null;
397 }
DongRyeol Chac80570b2018-11-07 11:55:32 +0900398 ONOSLLDP lldp = getLinkProbe(portNumber, portDesc);
399 if (lldp == null) {
400 log.warn("Cannot get link probe with portNumber {} and portDesc {} for {} at LLDP packet creation.",
401 portNumber, portDesc, deviceId);
402 return null;
403 }
Ayaka Koshibe48229222016-05-16 18:04:26 -0700404 ethPacket.setSourceMACAddress(context.fingerprint()).setPayload(lldp);
DongRyeol Chac80570b2018-11-07 11:55:32 +0900405 return new DefaultOutboundPacket(deviceId,
jaegonkimd9119d0d2018-02-06 23:16:52 +0900406 builder().setOutput(portNumber(portNumber)).build(),
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700407 ByteBuffer.wrap(ethPacket.serialize()));
alshabib7911a052014-10-16 17:49:37 -0700408 }
409
410 /**
411 * Creates packet_out BDDP for specified output port.
412 *
jaegonkimd9119d0d2018-02-06 23:16:52 +0900413 * @param portNumber the port
414 * @param portDesc the port description
alshabib7911a052014-10-16 17:49:37 -0700415 * @return Packet_out message with LLDP data
416 */
jaegonkimd9119d0d2018-02-06 23:16:52 +0900417 private OutboundPacket createOutBoundBddp(Long portNumber, String portDesc) {
418 if (portNumber == null) {
alshabib7911a052014-10-16 17:49:37 -0700419 return null;
420 }
DongRyeol Chac80570b2018-11-07 11:55:32 +0900421 ONOSLLDP lldp = getLinkProbe(portNumber, portDesc);
422 if (lldp == null) {
423 log.warn("Cannot get link probe with portNumber {} and portDesc {} for {} at BDDP packet creation.",
424 portNumber, portDesc, deviceId);
425 return null;
426 }
Ayaka Koshibe48229222016-05-16 18:04:26 -0700427 bddpEth.setSourceMACAddress(context.fingerprint()).setPayload(lldp);
DongRyeol Chac80570b2018-11-07 11:55:32 +0900428 return new DefaultOutboundPacket(deviceId,
jaegonkimd9119d0d2018-02-06 23:16:52 +0900429 builder().setOutput(portNumber(portNumber)).build(),
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700430 ByteBuffer.wrap(bddpEth.serialize()));
alshabib7911a052014-10-16 17:49:37 -0700431 }
432
DongRyeol Chac80570b2018-11-07 11:55:32 +0900433 private ONOSLLDP getLinkProbe(Long portNumber, String portDesc) {
434 Device device = context.deviceService().getDevice(deviceId);
435 if (device == null) {
436 log.warn("Cannot find the device {}", deviceId);
437 return null;
438 }
439 return ONOSLLDP.onosSecureLLDP(deviceId.toString(), device.chassisId(), portNumber.intValue(), portDesc,
Samuel Jero31e16f52018-09-21 10:34:28 -0400440 context.lldpSecret());
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800441 }
442
jaegonkimd9119d0d2018-02-06 23:16:52 +0900443 private void sendProbes(Long portNumber, String portDesc) {
Ray Milkeyd9bbde82016-06-09 11:35:00 -0700444 if (context.packetService() == null) {
445 return;
446 }
DongRyeol Chac80570b2018-11-07 11:55:32 +0900447 log.trace("Sending probes out of {}@{}", portNumber, deviceId);
jaegonkimd9119d0d2018-02-06 23:16:52 +0900448 OutboundPacket pkt = createOutBoundLldp(portNumber, portDesc);
DongRyeol Chac80570b2018-11-07 11:55:32 +0900449 if (pkt != null) {
450 context.packetService().emit(pkt);
451 } else {
452 log.warn("Cannot send lldp packet due to packet is null {}", deviceId);
453 }
Jonathan Hartb35540a2015-11-17 09:30:56 -0800454 if (context.useBddp()) {
jaegonkimd9119d0d2018-02-06 23:16:52 +0900455 OutboundPacket bpkt = createOutBoundBddp(portNumber, portDesc);
DongRyeol Chac80570b2018-11-07 11:55:32 +0900456 if (bpkt != null) {
457 context.packetService().emit(bpkt);
458 } else {
459 log.warn("Cannot send bddp packet due to packet is null {}", deviceId);
460 }
Thomas Vachuskae1bcb0b2014-10-27 17:45:10 -0700461 }
alshabib7911a052014-10-16 17:49:37 -0700462 }
463
Ray Milkey957390e2016-02-09 10:02:46 -0800464 public boolean containsPort(long portNumber) {
jaegonkimd9119d0d2018-02-06 23:16:52 +0900465 return portMap.containsKey(portNumber);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700466 }
alshabib7911a052014-10-16 17:49:37 -0700467}