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 org.apache.commons.lang3.StringUtils;
17 import org.opendaylight.openflowplugin.libraries.liblldp.EtherTypes;
18 import org.opendaylight.openflowplugin.libraries.liblldp.Ethernet;
19 import org.opendaylight.openflowplugin.libraries.liblldp.HexEncode;
20 import org.opendaylight.openflowplugin.libraries.liblldp.LLDP;
21 import org.opendaylight.openflowplugin.libraries.liblldp.LLDPTLV;
22 import org.opendaylight.openflowplugin.libraries.liblldp.PacketException;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
30 * Utility class for dealing with LLDP packets.
32 public final class LLDPUtil {
33 private static final Logger LOG = LoggerFactory.getLogger(LLDPUtil.class);
35 private static final String OF_URI_PREFIX = "openflow:";
40 static byte[] buildLldpFrame(final NodeId nodeId, final NodeConnectorId nodeConnectorId, final MacAddress src,
41 final Long outPortNo, final MacAddress destinationAddress) {
42 // Create discovery pkt
43 LLDP discoveryPkt = new LLDP();
45 // Create LLDP ChassisID TLV
46 BigInteger dataPathId = dataPathIdFromNodeId(nodeId);
47 byte[] cidValue = LLDPTLV.createChassisIDTLVValue(colonize(bigIntegerToPaddedHex(dataPathId)));
48 LLDPTLV chassisIdTlv = new LLDPTLV();
49 chassisIdTlv.setType(LLDPTLV.TLVType.ChassisID.getValue());
50 chassisIdTlv.setType(LLDPTLV.TLVType.ChassisID.getValue()).setLength((short) cidValue.length)
52 discoveryPkt.setChassisId(chassisIdTlv);
54 // Create LLDP PortID TL
55 String hexString = Long.toHexString(outPortNo);
56 byte[] pidValue = LLDPTLV.createPortIDTLVValue(hexString);
57 LLDPTLV portIdTlv = new LLDPTLV();
58 portIdTlv.setType(LLDPTLV.TLVType.PortID.getValue()).setLength((short) pidValue.length).setValue(pidValue);
59 portIdTlv.setType(LLDPTLV.TLVType.PortID.getValue());
60 discoveryPkt.setPortId(portIdTlv);
62 // Create LLDP TTL TLV
63 byte[] ttl = new byte[]{(byte) 0x13, (byte) 0x37};
64 LLDPTLV ttlTlv = new LLDPTLV();
65 ttlTlv.setType(LLDPTLV.TLVType.TTL.getValue()).setLength((short) ttl.length).setValue(ttl);
66 discoveryPkt.setTtl(ttlTlv);
68 // Create LLDP SystemName TLV
69 byte[] snValue = LLDPTLV.createSystemNameTLVValue(nodeId.getValue());
70 LLDPTLV systemNameTlv = new LLDPTLV();
71 systemNameTlv.setType(LLDPTLV.TLVType.SystemName.getValue());
72 systemNameTlv.setType(LLDPTLV.TLVType.SystemName.getValue()).setLength((short) snValue.length)
74 discoveryPkt.setSystemNameId(systemNameTlv);
76 // Create LLDP Custom TLV
77 byte[] customValue = LLDPTLV.createCustomTLVValue(nodeConnectorId.getValue());
78 LLDPTLV customTlv = new LLDPTLV();
79 customTlv.setType(LLDPTLV.TLVType.Custom.getValue()).setLength((short) customValue.length)
80 .setValue(customValue);
81 discoveryPkt.addCustomTLV(customTlv);
83 //Create LLDP CustomSec TLV
84 byte[] pureValue = new byte[1];
86 pureValue = getValueForLLDPPacketIntegrityEnsuring(nodeConnectorId);
87 byte[] customSecValue = LLDPTLV.createCustomTLVValue(CUSTOM_TLV_SUB_TYPE_CUSTOM_SEC, pureValue);
88 LLDPTLV customSecTlv = new LLDPTLV();
89 customSecTlv.setType(LLDPTLV.TLVType.Custom.getValue()).setLength((short) customSecValue.length)
90 .setValue(customSecValue);
91 discoveryPkt.addCustomTLV(customSecTlv);
92 } catch (NoSuchAlgorithmException e) {
93 LOG.warn("LLDP extra authenticator creation failed.", e);
97 // Create ethernet pkt
98 byte[] sourceMac = HexEncode.bytesFromHexString(src.getValue());
99 Ethernet ethPkt = new Ethernet();
100 ethPkt.setSourceMACAddress(sourceMac).setEtherType(EtherTypes.LLDP.shortValue()).setPayload(discoveryPkt);
101 if (destinationAddress == null) {
102 ethPkt.setDestinationMACAddress(LLDP.LLDP_MULTICAST_MAC);
104 ethPkt.setDestinationMACAddress(HexEncode.bytesFromHexString(destinationAddress.getValue()));
108 return ethPkt.serialize();
109 } catch (PacketException e) {
110 LOG.warn("Error creating LLDP packet.", e);
115 static byte[] buildLldpFrame(final NodeId nodeId, final NodeConnectorId nodeConnectorId,
116 final MacAddress srcMacAddress, final Long outputPortNo) {
117 return buildLldpFrame(nodeId, nodeConnectorId, srcMacAddress, outputPortNo, null);
120 private static String colonize(final String orig) {
121 return orig.replaceAll("(?<=..)(..)", ":$1");
124 private static BigInteger dataPathIdFromNodeId(final NodeId nodeId) {
125 String dpids = nodeId.getValue().replace(OF_URI_PREFIX, "");
126 return new BigInteger(dpids);
129 private static String bigIntegerToPaddedHex(final BigInteger dataPathId) {
130 return StringUtils.leftPad(dataPathId.toString(16), 16, "0");