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