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 static org.opendaylight.openflowplugin.applications.topology.lldp.utils.LLDPDiscoveryUtils.getValueForLLDPPacketIntegrityEnsuring;
12 import static org.opendaylight.openflowplugin.libraries.liblldp.LLDPTLV.CUSTOM_TLV_SUB_TYPE_CUSTOM_SEC;
14 import java.math.BigInteger;
15 import java.security.NoSuchAlgorithmException;
16 import javax.annotation.Nonnull;
17 import org.apache.commons.lang3.StringUtils;
18 import org.opendaylight.openflowplugin.libraries.liblldp.EtherTypes;
19 import org.opendaylight.openflowplugin.libraries.liblldp.Ethernet;
20 import org.opendaylight.openflowplugin.libraries.liblldp.HexEncode;
21 import org.opendaylight.openflowplugin.libraries.liblldp.LLDP;
22 import org.opendaylight.openflowplugin.libraries.liblldp.LLDPTLV;
23 import org.opendaylight.openflowplugin.libraries.liblldp.PacketException;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
31 * Utility class for dealing with LLDP packets.
33 public final class LLDPUtil {
34 private static final Logger LOG = LoggerFactory.getLogger(LLDPUtil.class);
36 private static final String OF_URI_PREFIX = "openflow:";
42 static byte[] buildLldpFrame(final NodeId nodeId, final NodeConnectorId nodeConnectorId, final MacAddress src,
43 final Long outPortNo, final MacAddress destinationAddress)
44 throws NoSuchAlgorithmException, PacketException {
45 // Create discovery pkt
46 LLDP discoveryPkt = new LLDP();
48 // Create LLDP ChassisID TLV
49 BigInteger dataPathId = dataPathIdFromNodeId(nodeId);
50 byte[] cidValue = LLDPTLV.createChassisIDTLVValue(colonize(bigIntegerToPaddedHex(dataPathId)));
51 LLDPTLV chassisIdTlv = new LLDPTLV();
52 chassisIdTlv.setType(LLDPTLV.TLVType.ChassisID.getValue());
53 chassisIdTlv.setType(LLDPTLV.TLVType.ChassisID.getValue()).setLength((short) cidValue.length)
55 discoveryPkt.setChassisId(chassisIdTlv);
57 // Create LLDP PortID TL
58 String hexString = Long.toHexString(outPortNo);
59 byte[] pidValue = LLDPTLV.createPortIDTLVValue(hexString);
60 LLDPTLV portIdTlv = new LLDPTLV();
61 portIdTlv.setType(LLDPTLV.TLVType.PortID.getValue()).setLength((short) pidValue.length).setValue(pidValue);
62 portIdTlv.setType(LLDPTLV.TLVType.PortID.getValue());
63 discoveryPkt.setPortId(portIdTlv);
65 // Create LLDP TTL TLV
66 byte[] ttl = new byte[]{(byte) 0x13, (byte) 0x37};
67 LLDPTLV ttlTlv = new LLDPTLV();
68 ttlTlv.setType(LLDPTLV.TLVType.TTL.getValue()).setLength((short) ttl.length).setValue(ttl);
69 discoveryPkt.setTtl(ttlTlv);
71 // Create LLDP SystemName TLV
72 byte[] snValue = LLDPTLV.createSystemNameTLVValue(nodeId.getValue());
73 LLDPTLV systemNameTlv = new LLDPTLV();
74 systemNameTlv.setType(LLDPTLV.TLVType.SystemName.getValue());
75 systemNameTlv.setType(LLDPTLV.TLVType.SystemName.getValue()).setLength((short) snValue.length)
77 discoveryPkt.setSystemNameId(systemNameTlv);
79 // Create LLDP Custom TLV
80 byte[] customValue = LLDPTLV.createCustomTLVValue(nodeConnectorId.getValue());
81 LLDPTLV customTlv = new LLDPTLV();
82 customTlv.setType(LLDPTLV.TLVType.Custom.getValue()).setLength((short) customValue.length)
83 .setValue(customValue);
84 discoveryPkt.addCustomTLV(customTlv);
86 //Create LLDP CustomSec TLV
87 byte[] pureValue = getValueForLLDPPacketIntegrityEnsuring(nodeConnectorId);
88 byte[] customSecValue = LLDPTLV.createCustomTLVValue(CUSTOM_TLV_SUB_TYPE_CUSTOM_SEC, pureValue);
89 LLDPTLV customSecTlv = new LLDPTLV();
90 customSecTlv.setType(LLDPTLV.TLVType.Custom.getValue()).setLength((short) customSecValue.length)
91 .setValue(customSecValue);
92 discoveryPkt.addCustomTLV(customSecTlv);
94 // Create ethernet pkt
95 byte[] sourceMac = HexEncode.bytesFromHexString(src.getValue());
96 Ethernet ethPkt = new Ethernet();
97 ethPkt.setSourceMACAddress(sourceMac).setEtherType(EtherTypes.LLDP.shortValue()).setPayload(discoveryPkt);
98 if (destinationAddress == null) {
99 ethPkt.setDestinationMACAddress(LLDP.LLDP_MULTICAST_MAC);
101 ethPkt.setDestinationMACAddress(HexEncode.bytesFromHexString(destinationAddress.getValue()));
104 return ethPkt.serialize();
108 static byte[] buildLldpFrame(final NodeId nodeId, final NodeConnectorId nodeConnectorId,
109 final MacAddress srcMacAddress, final Long outputPortNo) throws NoSuchAlgorithmException, PacketException {
110 return buildLldpFrame(nodeId, nodeConnectorId, srcMacAddress, outputPortNo, null);
113 private static String colonize(final String orig) {
114 return orig.replaceAll("(?<=..)(..)", ":$1");
117 private static BigInteger dataPathIdFromNodeId(final NodeId nodeId) {
118 String dpids = nodeId.getValue().replace(OF_URI_PREFIX, "");
119 return new BigInteger(dpids);
122 private static String bigIntegerToPaddedHex(final BigInteger dataPathId) {
123 return StringUtils.leftPad(dataPathId.toString(16), 16, "0");