Upgrade ietf-{inet,yang}-types to 2013-07-15
[openflowplugin.git] / applications / lldp-speaker / src / main / java / org / opendaylight / openflowplugin / applications / lldpspeaker / LLDPUtil.java
1 /*
2  * Copyright (c) 2014 Pacnet and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.openflowplugin.applications.lldpspeaker;
10
11 import static org.opendaylight.controller.liblldp.LLDPTLV.CUSTOM_TLV_SUB_TYPE_CUSTOM_SEC;
12 import static org.opendaylight.openflowplugin.applications.topology.lldp.utils.LLDPDiscoveryUtils.getValueForLLDPPacketIntegrityEnsuring;
13 import java.math.BigInteger;
14 import java.security.NoSuchAlgorithmException;
15 import org.apache.commons.lang3.StringUtils;
16 import org.opendaylight.controller.liblldp.EtherTypes;
17 import org.opendaylight.controller.liblldp.Ethernet;
18 import org.opendaylight.controller.liblldp.HexEncode;
19 import org.opendaylight.controller.liblldp.LLDP;
20 import org.opendaylight.controller.liblldp.LLDPTLV;
21 import org.opendaylight.controller.liblldp.PacketException;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29  * Utility class for dealing with LLDP packets.
30  */
31 public final class LLDPUtil {
32     private static final Logger LOG = LoggerFactory.getLogger(LLDPUtil.class);
33     private static final String OF_URI_PREFIX = "openflow:";
34
35     static byte[] buildLldpFrame(final NodeId nodeId,
36             final NodeConnectorId nodeConnectorId, final MacAddress src, final Long outPortNo,
37             final MacAddress destinationAddress) {
38         // Create discovery pkt
39         LLDP discoveryPkt = new LLDP();
40
41         // Create LLDP ChassisID TLV
42         BigInteger dataPathId = dataPathIdFromNodeId(nodeId);
43         byte[] cidValue = LLDPTLV
44                 .createChassisIDTLVValue(colonize(bigIntegerToPaddedHex(dataPathId)));
45         LLDPTLV chassisIdTlv = new LLDPTLV();
46         chassisIdTlv.setType(LLDPTLV.TLVType.ChassisID.getValue());
47         chassisIdTlv.setType(LLDPTLV.TLVType.ChassisID.getValue())
48                 .setLength((short) cidValue.length).setValue(cidValue);
49         discoveryPkt.setChassisId(chassisIdTlv);
50
51         // Create LLDP PortID TL
52         String hexString = Long.toHexString(outPortNo);
53         byte[] pidValue = LLDPTLV.createPortIDTLVValue(hexString);
54         LLDPTLV portIdTlv = new LLDPTLV();
55         portIdTlv.setType(LLDPTLV.TLVType.PortID.getValue())
56                 .setLength((short) pidValue.length).setValue(pidValue);
57         portIdTlv.setType(LLDPTLV.TLVType.PortID.getValue());
58         discoveryPkt.setPortId(portIdTlv);
59
60         // Create LLDP TTL TLV
61         byte[] ttl = new byte[] { (byte) 0x13, (byte) 0x37 };
62         LLDPTLV ttlTlv = new LLDPTLV();
63         ttlTlv.setType(LLDPTLV.TLVType.TTL.getValue())
64                 .setLength((short) ttl.length).setValue(ttl);
65         discoveryPkt.setTtl(ttlTlv);
66
67         // Create LLDP SystemName TLV
68         byte[] snValue = LLDPTLV.createSystemNameTLVValue(nodeId.getValue());
69         LLDPTLV systemNameTlv = new LLDPTLV();
70         systemNameTlv.setType(LLDPTLV.TLVType.SystemName.getValue());
71         systemNameTlv.setType(LLDPTLV.TLVType.SystemName.getValue())
72                 .setLength((short) snValue.length).setValue(snValue);
73         discoveryPkt.setSystemNameId(systemNameTlv);
74
75         // Create LLDP Custom TLV
76         byte[] customValue = LLDPTLV.createCustomTLVValue(nodeConnectorId
77                 .getValue());
78         LLDPTLV customTlv = new LLDPTLV();
79         customTlv.setType(LLDPTLV.TLVType.Custom.getValue())
80                 .setLength((short) customValue.length).setValue(customValue);
81         discoveryPkt.addCustomTLV(customTlv);
82
83         //Create LLDP CustomSec TLV
84         byte[] pureValue = new byte[1];
85         try {
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())
90             .setLength((short)customSecValue.length)
91             .setValue(customSecValue);
92             discoveryPkt.addCustomTLV(customSecTlv);
93         } catch (NoSuchAlgorithmException e1) {
94             LOG.info("LLDP extra authenticator creation failed: {}", e1.getMessage());
95             LOG.debug("Reason why LLDP extra authenticator creation failed: ", e1);
96         }
97
98
99         // Create ethernet pkt
100         byte[] sourceMac = HexEncode.bytesFromHexString(src.getValue());
101         Ethernet ethPkt = new Ethernet();
102         ethPkt.setSourceMACAddress(sourceMac)
103                 .setEtherType(EtherTypes.LLDP.shortValue())
104                 .setPayload(discoveryPkt);
105         if (destinationAddress == null) {
106             ethPkt.setDestinationMACAddress(LLDP.LLDPMulticastMac);
107         } else {
108             ethPkt.setDestinationMACAddress(HexEncode
109                     .bytesFromHexString(destinationAddress.getValue()));
110         }
111
112         try {
113             return ethPkt.serialize();
114         } catch (PacketException e) {
115             LOG.warn("Error creating LLDP packet: {}", e.getMessage());
116             LOG.debug("Error creating LLDP packet.. ", e);
117         }
118         return null;
119     }
120
121     private static String colonize(final String orig) {
122         return orig.replaceAll("(?<=..)(..)", ":$1");
123     }
124
125     private static BigInteger dataPathIdFromNodeId(final NodeId nodeId) {
126         String dpids = nodeId.getValue().replace(OF_URI_PREFIX, "");
127         return new BigInteger(dpids);
128     }
129
130     private static String bigIntegerToPaddedHex(final BigInteger dataPathId) {
131         return StringUtils.leftPad(dataPathId.toString(16), 16, "0");
132     }
133
134     static byte[] buildLldpFrame(final NodeId nodeId,
135             final NodeConnectorId nodeConnectorId, final MacAddress srcMacAddress,
136             final Long outputPortNo) {
137         return buildLldpFrame(nodeId, nodeConnectorId, srcMacAddress,
138                 outputPortNo, null);
139     }
140 }