Merge "BUG-86: Fixed echo response processing"
[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.openflowplugin.applications.topology.lldp.utils.LLDPDiscoveryUtils.getValueForLLDPPacketIntegrityEnsuring;
12 import static org.opendaylight.openflowplugin.libraries.liblldp.LLDPTLV.CUSTOM_TLV_SUB_TYPE_CUSTOM_SEC;
13
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;
28
29 /**
30  * Utility class for dealing with LLDP packets.
31  */
32 public final class LLDPUtil {
33     private static final Logger LOG = LoggerFactory.getLogger(LLDPUtil.class);
34
35     private static final String OF_URI_PREFIX = "openflow:";
36
37     private LLDPUtil() {
38     }
39
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();
44
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)
51                 .setValue(cidValue);
52         discoveryPkt.setChassisId(chassisIdTlv);
53
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);
61
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);
67
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)
73                 .setValue(snValue);
74         discoveryPkt.setSystemNameId(systemNameTlv);
75
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);
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()).setLength((short) customSecValue.length)
90                     .setValue(customSecValue);
91             discoveryPkt.addCustomTLV(customSecTlv);
92         } catch (NoSuchAlgorithmException e) {
93             LOG.warn("LLDP extra authenticator creation failed.", e);
94         }
95
96
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);
103         } else {
104             ethPkt.setDestinationMACAddress(HexEncode.bytesFromHexString(destinationAddress.getValue()));
105         }
106
107         try {
108             return ethPkt.serialize();
109         } catch (PacketException e) {
110             LOG.warn("Error creating LLDP packet.", e);
111         }
112         return null;
113     }
114
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);
118     }
119
120     private static String colonize(final String orig) {
121         return orig.replaceAll("(?<=..)(..)", ":$1");
122     }
123
124     private static BigInteger dataPathIdFromNodeId(final NodeId nodeId) {
125         String dpids = nodeId.getValue().replace(OF_URI_PREFIX, "");
126         return new BigInteger(dpids);
127     }
128
129     private static String bigIntegerToPaddedHex(final BigInteger dataPathId) {
130         return StringUtils.leftPad(dataPathId.toString(16), 16, "0");
131     }
132 }