BUG-2242: LLDP speaker as separate application.
[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 java.math.BigInteger;
12 import java.util.Collections;
13 import java.util.List;
14 import org.apache.commons.lang3.StringUtils;
15 import org.opendaylight.controller.liblldp.EtherTypes;
16 import org.opendaylight.controller.liblldp.Ethernet;
17 import org.opendaylight.controller.liblldp.HexEncode;
18 import org.opendaylight.controller.liblldp.LLDP;
19 import org.opendaylight.controller.liblldp.LLDPTLV;
20 import org.opendaylight.controller.liblldp.PacketException;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 /**
28  * Utility class for dealing with LLDP packets.
29  */
30 public final class LLDPUtil {
31     private static final Logger LOG = LoggerFactory.getLogger(LLDPUtil.class);
32     private static final String OF_URI_PREFIX = "openflow:";
33
34     static byte[] buildLldpFrame(NodeId nodeId, NodeConnectorId nodeConnectorId, MacAddress src, Long outPortNo) {
35         // Create LLDP TTL TLV
36         byte[] ttl = new byte[] { (byte) 0x13, (byte) 0x37 };
37         LLDPTLV ttlTlv = new LLDPTLV();
38         ttlTlv.setType(LLDPTLV.TLVType.TTL.getValue()).setLength((short) ttl.length).setValue(ttl);
39
40         // Create LLDP ChassisID TLV
41         BigInteger dataPathId = dataPathIdFromNodeId(nodeId);
42         byte[] cidValue = LLDPTLV.createChassisIDTLVValue(
43                 colonize(bigIntegerToPaddedHex(dataPathId)));
44         LLDPTLV chassisIdTlv = new LLDPTLV();
45         chassisIdTlv.setType(LLDPTLV.TLVType.ChassisID.getValue());
46         chassisIdTlv.setType(LLDPTLV.TLVType.ChassisID.getValue()).setLength((short) cidValue.length)
47                 .setValue(cidValue);
48
49         // Create LLDP SystemName TLV
50         byte[] snValue = LLDPTLV.createSystemNameTLVValue(nodeId.getValue());
51         LLDPTLV systemNameTlv = new LLDPTLV();
52         systemNameTlv.setType(LLDPTLV.TLVType.SystemName.getValue());
53         systemNameTlv.setType(LLDPTLV.TLVType.SystemName.getValue()).setLength((short) snValue.length)
54                 .setValue(snValue);
55
56         // Create LLDP PortID TL
57         String hexString = Long.toHexString(outPortNo);
58         byte[] pidValue = LLDPTLV.createPortIDTLVValue(hexString);
59         LLDPTLV portIdTlv = new LLDPTLV();
60         portIdTlv.setType(LLDPTLV.TLVType.PortID.getValue()).setLength((short) pidValue.length).setValue(pidValue);
61         portIdTlv.setType(LLDPTLV.TLVType.PortID.getValue());
62
63         // Create LLDP Custom TLV
64         byte[] customValue = LLDPTLV.createCustomTLVValue(nodeConnectorId.getValue());
65         LLDPTLV customTlv = new LLDPTLV();
66         customTlv.setType(LLDPTLV.TLVType.Custom.getValue()).setLength((short) customValue.length)
67                 .setValue(customValue);
68
69         // Create LLDP Custom Option list
70         List<LLDPTLV> customList = Collections.singletonList(customTlv);
71
72         // Create discovery pkt
73         LLDP discoveryPkt = new LLDP();
74         discoveryPkt.setChassisId(chassisIdTlv).setPortId(portIdTlv).setTtl(ttlTlv).setSystemNameId(systemNameTlv)
75                 .setOptionalTLVList(customList);
76
77         // Create ethernet pkt
78         byte[] sourceMac = HexEncode.bytesFromHexString(src.getValue());
79         Ethernet ethPkt = new Ethernet();
80         ethPkt.setSourceMACAddress(sourceMac).setDestinationMACAddress(LLDP.LLDPMulticastMac)
81                 .setEtherType(EtherTypes.LLDP.shortValue()).setPayload(discoveryPkt);
82
83         try {
84             return ethPkt.serialize();
85         } catch (PacketException e) {
86             LOG.error("Error creating LLDP packet",e);
87         }
88         return null;
89     }
90
91     private static String colonize(String orig) {
92         return orig.replaceAll("(?<=..)(..)", ":$1");
93     }
94
95     private static BigInteger dataPathIdFromNodeId(NodeId nodeId) {
96         String dpids = nodeId.getValue().replace(OF_URI_PREFIX, "");
97         return new BigInteger(dpids);
98     }
99
100     private static String bigIntegerToPaddedHex(BigInteger dataPathId) {
101         return StringUtils.leftPad(dataPathId.toString(16), 16, "0");
102     }
103 }