2 * Copyright (c) 2014 Pacnet and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowplugin.applications.lldpspeaker;
11 import java.math.BigInteger;
12 import java.util.Collections;
13 import java.util.List;
14 import org.apache.commons.lang3.StringUtils;
15 import org.opendaylight.controller.liblldp.EtherTypes;
16 import org.opendaylight.controller.liblldp.Ethernet;
17 import org.opendaylight.controller.liblldp.HexEncode;
18 import org.opendaylight.controller.liblldp.LLDP;
19 import org.opendaylight.controller.liblldp.LLDPTLV;
20 import org.opendaylight.controller.liblldp.PacketException;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * Utility class for dealing with LLDP packets.
30 public final class LLDPUtil {
31 private static final Logger LOG = LoggerFactory.getLogger(LLDPUtil.class);
32 private static final String OF_URI_PREFIX = "openflow:";
34 static byte[] buildLldpFrame(NodeId nodeId, NodeConnectorId nodeConnectorId, MacAddress src, Long outPortNo) {
35 // Create LLDP TTL TLV
36 byte[] ttl = new byte[] { (byte) 0x13, (byte) 0x37 };
37 LLDPTLV ttlTlv = new LLDPTLV();
38 ttlTlv.setType(LLDPTLV.TLVType.TTL.getValue()).setLength((short) ttl.length).setValue(ttl);
40 // Create LLDP ChassisID TLV
41 BigInteger dataPathId = dataPathIdFromNodeId(nodeId);
42 byte[] cidValue = LLDPTLV.createChassisIDTLVValue(
43 colonize(bigIntegerToPaddedHex(dataPathId)));
44 LLDPTLV chassisIdTlv = new LLDPTLV();
45 chassisIdTlv.setType(LLDPTLV.TLVType.ChassisID.getValue());
46 chassisIdTlv.setType(LLDPTLV.TLVType.ChassisID.getValue()).setLength((short) cidValue.length)
49 // Create LLDP SystemName TLV
50 byte[] snValue = LLDPTLV.createSystemNameTLVValue(nodeId.getValue());
51 LLDPTLV systemNameTlv = new LLDPTLV();
52 systemNameTlv.setType(LLDPTLV.TLVType.SystemName.getValue());
53 systemNameTlv.setType(LLDPTLV.TLVType.SystemName.getValue()).setLength((short) snValue.length)
56 // Create LLDP PortID TL
57 String hexString = Long.toHexString(outPortNo);
58 byte[] pidValue = LLDPTLV.createPortIDTLVValue(hexString);
59 LLDPTLV portIdTlv = new LLDPTLV();
60 portIdTlv.setType(LLDPTLV.TLVType.PortID.getValue()).setLength((short) pidValue.length).setValue(pidValue);
61 portIdTlv.setType(LLDPTLV.TLVType.PortID.getValue());
63 // Create LLDP Custom TLV
64 byte[] customValue = LLDPTLV.createCustomTLVValue(nodeConnectorId.getValue());
65 LLDPTLV customTlv = new LLDPTLV();
66 customTlv.setType(LLDPTLV.TLVType.Custom.getValue()).setLength((short) customValue.length)
67 .setValue(customValue);
69 // Create LLDP Custom Option list
70 List<LLDPTLV> customList = Collections.singletonList(customTlv);
72 // Create discovery pkt
73 LLDP discoveryPkt = new LLDP();
74 discoveryPkt.setChassisId(chassisIdTlv).setPortId(portIdTlv).setTtl(ttlTlv).setSystemNameId(systemNameTlv)
75 .setOptionalTLVList(customList);
77 // Create ethernet pkt
78 byte[] sourceMac = HexEncode.bytesFromHexString(src.getValue());
79 Ethernet ethPkt = new Ethernet();
80 ethPkt.setSourceMACAddress(sourceMac).setDestinationMACAddress(LLDP.LLDPMulticastMac)
81 .setEtherType(EtherTypes.LLDP.shortValue()).setPayload(discoveryPkt);
84 return ethPkt.serialize();
85 } catch (PacketException e) {
86 LOG.error("Error creating LLDP packet",e);
91 private static String colonize(String orig) {
92 return orig.replaceAll("(?<=..)(..)", ":$1");
95 private static BigInteger dataPathIdFromNodeId(NodeId nodeId) {
96 String dpids = nodeId.getValue().replace(OF_URI_PREFIX, "");
97 return new BigInteger(dpids);
100 private static String bigIntegerToPaddedHex(BigInteger dataPathId) {
101 return StringUtils.leftPad(dataPathId.toString(16), 16, "0");