github.com/gopacket/gopacket@v1.1.0/layers/lldp.go (about)

     1  // Copyright 2012 Google, Inc. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style license
     4  // that can be found in the LICENSE file in the root of the source
     5  // tree.
     6  
     7  package layers
     8  
     9  import (
    10  	"encoding/binary"
    11  	"errors"
    12  	"fmt"
    13  
    14  	"github.com/gopacket/gopacket"
    15  )
    16  
    17  // LLDPTLVType is the type of each TLV value in a LinkLayerDiscovery packet.
    18  type LLDPTLVType byte
    19  
    20  const (
    21  	LLDPTLVEnd             LLDPTLVType = 0
    22  	LLDPTLVChassisID       LLDPTLVType = 1
    23  	LLDPTLVPortID          LLDPTLVType = 2
    24  	LLDPTLVTTL             LLDPTLVType = 3
    25  	LLDPTLVPortDescription LLDPTLVType = 4
    26  	LLDPTLVSysName         LLDPTLVType = 5
    27  	LLDPTLVSysDescription  LLDPTLVType = 6
    28  	LLDPTLVSysCapabilities LLDPTLVType = 7
    29  	LLDPTLVMgmtAddress     LLDPTLVType = 8
    30  	LLDPTLVOrgSpecific     LLDPTLVType = 127
    31  )
    32  
    33  // LinkLayerDiscoveryValue is a TLV value inside a LinkLayerDiscovery packet layer.
    34  type LinkLayerDiscoveryValue struct {
    35  	Type   LLDPTLVType
    36  	Length uint16
    37  	Value  []byte
    38  }
    39  
    40  func (c *LinkLayerDiscoveryValue) len() int {
    41  	return 0
    42  }
    43  
    44  // LLDPChassisIDSubType specifies the value type for a single LLDPChassisID.ID
    45  type LLDPChassisIDSubType byte
    46  
    47  // LLDP Chassis Types
    48  const (
    49  	LLDPChassisIDSubTypeReserved    LLDPChassisIDSubType = 0
    50  	LLDPChassisIDSubTypeChassisComp LLDPChassisIDSubType = 1
    51  	LLDPChassisIDSubtypeIfaceAlias  LLDPChassisIDSubType = 2
    52  	LLDPChassisIDSubTypePortComp    LLDPChassisIDSubType = 3
    53  	LLDPChassisIDSubTypeMACAddr     LLDPChassisIDSubType = 4
    54  	LLDPChassisIDSubTypeNetworkAddr LLDPChassisIDSubType = 5
    55  	LLDPChassisIDSubtypeIfaceName   LLDPChassisIDSubType = 6
    56  	LLDPChassisIDSubTypeLocal       LLDPChassisIDSubType = 7
    57  )
    58  
    59  type LLDPChassisID struct {
    60  	Subtype LLDPChassisIDSubType
    61  	ID      []byte
    62  }
    63  
    64  func (c *LLDPChassisID) serialize() []byte {
    65  
    66  	var buf = make([]byte, c.serializedLen())
    67  	idLen := uint16(LLDPTLVChassisID)<<9 | uint16(len(c.ID)+1) //id should take 7 bits, length should take 9 bits, +1 for subtype
    68  	binary.BigEndian.PutUint16(buf[0:2], idLen)
    69  	buf[2] = byte(c.Subtype)
    70  	copy(buf[3:], c.ID)
    71  	return buf
    72  }
    73  
    74  func (c *LLDPChassisID) serializedLen() int {
    75  	return len(c.ID) + 3 // +2 for id and length, +1 for subtype
    76  }
    77  
    78  // LLDPPortIDSubType specifies the value type for a single LLDPPortID.ID
    79  type LLDPPortIDSubType byte
    80  
    81  // LLDP PortID types
    82  const (
    83  	LLDPPortIDSubtypeReserved       LLDPPortIDSubType = 0
    84  	LLDPPortIDSubtypeIfaceAlias     LLDPPortIDSubType = 1
    85  	LLDPPortIDSubtypePortComp       LLDPPortIDSubType = 2
    86  	LLDPPortIDSubtypeMACAddr        LLDPPortIDSubType = 3
    87  	LLDPPortIDSubtypeNetworkAddr    LLDPPortIDSubType = 4
    88  	LLDPPortIDSubtypeIfaceName      LLDPPortIDSubType = 5
    89  	LLDPPortIDSubtypeAgentCircuitID LLDPPortIDSubType = 6
    90  	LLDPPortIDSubtypeLocal          LLDPPortIDSubType = 7
    91  )
    92  
    93  type LLDPPortID struct {
    94  	Subtype LLDPPortIDSubType
    95  	ID      []byte
    96  }
    97  
    98  func (c *LLDPPortID) serialize() []byte {
    99  
   100  	var buf = make([]byte, c.serializedLen())
   101  	idLen := uint16(LLDPTLVPortID)<<9 | uint16(len(c.ID)+1) //id should take 7 bits, length should take 9 bits, +1 for subtype
   102  	binary.BigEndian.PutUint16(buf[0:2], idLen)
   103  	buf[2] = byte(c.Subtype)
   104  	copy(buf[3:], c.ID)
   105  	return buf
   106  }
   107  
   108  func (c *LLDPPortID) serializedLen() int {
   109  	return len(c.ID) + 3 // +2 for id and length, +1 for subtype
   110  }
   111  
   112  // LinkLayerDiscovery is a packet layer containing the LinkLayer Discovery Protocol.
   113  // See http:http://standards.ieee.org/getieee802/download/802.1AB-2009.pdf
   114  // ChassisID, PortID and TTL are mandatory TLV's. Other values can be decoded
   115  // with DecodeValues()
   116  type LinkLayerDiscovery struct {
   117  	BaseLayer
   118  	ChassisID LLDPChassisID
   119  	PortID    LLDPPortID
   120  	TTL       uint16
   121  	Values    []LinkLayerDiscoveryValue
   122  }
   123  
   124  type IEEEOUI uint32
   125  
   126  // http://standards.ieee.org/develop/regauth/oui/oui.txt
   127  const (
   128  	IEEEOUI8021     IEEEOUI = 0x0080c2
   129  	IEEEOUI8023     IEEEOUI = 0x00120f
   130  	IEEEOUI80211    IEEEOUI = 0x000fac
   131  	IEEEOUI8021Qbg  IEEEOUI = 0x0013BF
   132  	IEEEOUICisco2   IEEEOUI = 0x000142
   133  	IEEEOUIMedia    IEEEOUI = 0x0012bb // TR-41
   134  	IEEEOUIProfinet IEEEOUI = 0x000ecf
   135  	IEEEOUIDCBX     IEEEOUI = 0x001b21
   136  )
   137  
   138  // LLDPOrgSpecificTLV is an Organisation-specific TLV
   139  type LLDPOrgSpecificTLV struct {
   140  	OUI     IEEEOUI
   141  	SubType uint8
   142  	Info    []byte
   143  }
   144  
   145  // LLDPCapabilities Types
   146  const (
   147  	LLDPCapsOther       uint16 = 1 << 0
   148  	LLDPCapsRepeater    uint16 = 1 << 1
   149  	LLDPCapsBridge      uint16 = 1 << 2
   150  	LLDPCapsWLANAP      uint16 = 1 << 3
   151  	LLDPCapsRouter      uint16 = 1 << 4
   152  	LLDPCapsPhone       uint16 = 1 << 5
   153  	LLDPCapsDocSis      uint16 = 1 << 6
   154  	LLDPCapsStationOnly uint16 = 1 << 7
   155  	LLDPCapsCVLAN       uint16 = 1 << 8
   156  	LLDPCapsSVLAN       uint16 = 1 << 9
   157  	LLDPCapsTmpr        uint16 = 1 << 10
   158  )
   159  
   160  // LLDPCapabilities represents the capabilities of a device
   161  type LLDPCapabilities struct {
   162  	Other       bool
   163  	Repeater    bool
   164  	Bridge      bool
   165  	WLANAP      bool
   166  	Router      bool
   167  	Phone       bool
   168  	DocSis      bool
   169  	StationOnly bool
   170  	CVLAN       bool
   171  	SVLAN       bool
   172  	TMPR        bool
   173  }
   174  
   175  type LLDPSysCapabilities struct {
   176  	SystemCap  LLDPCapabilities
   177  	EnabledCap LLDPCapabilities
   178  }
   179  
   180  type IANAAddressFamily byte
   181  
   182  // LLDP Management Address Subtypes
   183  // http://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml
   184  const (
   185  	IANAAddressFamilyReserved IANAAddressFamily = 0
   186  	IANAAddressFamilyIPV4     IANAAddressFamily = 1
   187  	IANAAddressFamilyIPV6     IANAAddressFamily = 2
   188  	IANAAddressFamilyNSAP     IANAAddressFamily = 3
   189  	IANAAddressFamilyHDLC     IANAAddressFamily = 4
   190  	IANAAddressFamilyBBN1822  IANAAddressFamily = 5
   191  	IANAAddressFamily802      IANAAddressFamily = 6
   192  	IANAAddressFamilyE163     IANAAddressFamily = 7
   193  	IANAAddressFamilyE164     IANAAddressFamily = 8
   194  	IANAAddressFamilyF69      IANAAddressFamily = 9
   195  	IANAAddressFamilyX121     IANAAddressFamily = 10
   196  	IANAAddressFamilyIPX      IANAAddressFamily = 11
   197  	IANAAddressFamilyAtalk    IANAAddressFamily = 12
   198  	IANAAddressFamilyDecnet   IANAAddressFamily = 13
   199  	IANAAddressFamilyBanyan   IANAAddressFamily = 14
   200  	IANAAddressFamilyE164NSAP IANAAddressFamily = 15
   201  	IANAAddressFamilyDNS      IANAAddressFamily = 16
   202  	IANAAddressFamilyDistname IANAAddressFamily = 17
   203  	IANAAddressFamilyASNumber IANAAddressFamily = 18
   204  	IANAAddressFamilyXTPIPV4  IANAAddressFamily = 19
   205  	IANAAddressFamilyXTPIPV6  IANAAddressFamily = 20
   206  	IANAAddressFamilyXTP      IANAAddressFamily = 21
   207  	IANAAddressFamilyFcWWPN   IANAAddressFamily = 22
   208  	IANAAddressFamilyFcWWNN   IANAAddressFamily = 23
   209  	IANAAddressFamilyGWID     IANAAddressFamily = 24
   210  	IANAAddressFamilyL2VPN    IANAAddressFamily = 25
   211  )
   212  
   213  type LLDPInterfaceSubtype byte
   214  
   215  // LLDP Interface Subtypes
   216  const (
   217  	LLDPInterfaceSubtypeUnknown LLDPInterfaceSubtype = 1
   218  	LLDPInterfaceSubtypeifIndex LLDPInterfaceSubtype = 2
   219  	LLDPInterfaceSubtypeSysPort LLDPInterfaceSubtype = 3
   220  )
   221  
   222  type LLDPMgmtAddress struct {
   223  	Subtype          IANAAddressFamily
   224  	Address          []byte
   225  	InterfaceSubtype LLDPInterfaceSubtype
   226  	InterfaceNumber  uint32
   227  	OID              string
   228  }
   229  
   230  // LinkLayerDiscoveryInfo represents the decoded details for a set of LinkLayerDiscoveryValues
   231  // Organisation-specific TLV's can be decoded using the various Decode() methods
   232  type LinkLayerDiscoveryInfo struct {
   233  	BaseLayer
   234  	PortDescription string
   235  	SysName         string
   236  	SysDescription  string
   237  	SysCapabilities LLDPSysCapabilities
   238  	MgmtAddress     LLDPMgmtAddress
   239  	OrgTLVs         []LLDPOrgSpecificTLV      // Private TLVs
   240  	Unknown         []LinkLayerDiscoveryValue // undecoded TLVs
   241  }
   242  
   243  // / IEEE 802.1 TLV Subtypes
   244  const (
   245  	LLDP8021SubtypePortVLANID       uint8 = 1
   246  	LLDP8021SubtypeProtocolVLANID   uint8 = 2
   247  	LLDP8021SubtypeVLANName         uint8 = 3
   248  	LLDP8021SubtypeProtocolIdentity uint8 = 4
   249  	LLDP8021SubtypeVDIUsageDigest   uint8 = 5
   250  	LLDP8021SubtypeManagementVID    uint8 = 6
   251  	LLDP8021SubtypeLinkAggregation  uint8 = 7
   252  )
   253  
   254  // VLAN Port Protocol ID options
   255  const (
   256  	LLDPProtocolVLANIDCapability byte = 1 << 1
   257  	LLDPProtocolVLANIDStatus     byte = 1 << 2
   258  )
   259  
   260  type PortProtocolVLANID struct {
   261  	Supported bool
   262  	Enabled   bool
   263  	ID        uint16
   264  }
   265  
   266  type VLANName struct {
   267  	ID   uint16
   268  	Name string
   269  }
   270  
   271  type ProtocolIdentity []byte
   272  
   273  // LACP options
   274  const (
   275  	LLDPAggregationCapability byte = 1 << 0
   276  	LLDPAggregationStatus     byte = 1 << 1
   277  )
   278  
   279  // IEEE 802 Link Aggregation parameters
   280  type LLDPLinkAggregation struct {
   281  	Supported bool
   282  	Enabled   bool
   283  	PortID    uint32
   284  }
   285  
   286  // LLDPInfo8021 represents the information carried in 802.1 Org-specific TLVs
   287  type LLDPInfo8021 struct {
   288  	PVID               uint16
   289  	PPVIDs             []PortProtocolVLANID
   290  	VLANNames          []VLANName
   291  	ProtocolIdentities []ProtocolIdentity
   292  	VIDUsageDigest     uint32
   293  	ManagementVID      uint16
   294  	LinkAggregation    LLDPLinkAggregation
   295  }
   296  
   297  // IEEE 802.3 TLV Subtypes
   298  const (
   299  	LLDP8023SubtypeMACPHY          uint8 = 1
   300  	LLDP8023SubtypeMDIPower        uint8 = 2
   301  	LLDP8023SubtypeLinkAggregation uint8 = 3
   302  	LLDP8023SubtypeMTU             uint8 = 4
   303  )
   304  
   305  // MACPHY options
   306  const (
   307  	LLDPMACPHYCapability byte = 1 << 0
   308  	LLDPMACPHYStatus     byte = 1 << 1
   309  )
   310  
   311  // From IANA-MAU-MIB (introduced by RFC 4836) - dot3MauType
   312  const (
   313  	LLDPMAUTypeUnknown         uint16 = 0
   314  	LLDPMAUTypeAUI             uint16 = 1
   315  	LLDPMAUType10Base5         uint16 = 2
   316  	LLDPMAUTypeFOIRL           uint16 = 3
   317  	LLDPMAUType10Base2         uint16 = 4
   318  	LLDPMAUType10BaseT         uint16 = 5
   319  	LLDPMAUType10BaseFP        uint16 = 6
   320  	LLDPMAUType10BaseFB        uint16 = 7
   321  	LLDPMAUType10BaseFL        uint16 = 8
   322  	LLDPMAUType10BROAD36       uint16 = 9
   323  	LLDPMAUType10BaseT_HD      uint16 = 10
   324  	LLDPMAUType10BaseT_FD      uint16 = 11
   325  	LLDPMAUType10BaseFL_HD     uint16 = 12
   326  	LLDPMAUType10BaseFL_FD     uint16 = 13
   327  	LLDPMAUType100BaseT4       uint16 = 14
   328  	LLDPMAUType100BaseTX_HD    uint16 = 15
   329  	LLDPMAUType100BaseTX_FD    uint16 = 16
   330  	LLDPMAUType100BaseFX_HD    uint16 = 17
   331  	LLDPMAUType100BaseFX_FD    uint16 = 18
   332  	LLDPMAUType100BaseT2_HD    uint16 = 19
   333  	LLDPMAUType100BaseT2_FD    uint16 = 20
   334  	LLDPMAUType1000BaseX_HD    uint16 = 21
   335  	LLDPMAUType1000BaseX_FD    uint16 = 22
   336  	LLDPMAUType1000BaseLX_HD   uint16 = 23
   337  	LLDPMAUType1000BaseLX_FD   uint16 = 24
   338  	LLDPMAUType1000BaseSX_HD   uint16 = 25
   339  	LLDPMAUType1000BaseSX_FD   uint16 = 26
   340  	LLDPMAUType1000BaseCX_HD   uint16 = 27
   341  	LLDPMAUType1000BaseCX_FD   uint16 = 28
   342  	LLDPMAUType1000BaseT_HD    uint16 = 29
   343  	LLDPMAUType1000BaseT_FD    uint16 = 30
   344  	LLDPMAUType10GBaseX        uint16 = 31
   345  	LLDPMAUType10GBaseLX4      uint16 = 32
   346  	LLDPMAUType10GBaseR        uint16 = 33
   347  	LLDPMAUType10GBaseER       uint16 = 34
   348  	LLDPMAUType10GBaseLR       uint16 = 35
   349  	LLDPMAUType10GBaseSR       uint16 = 36
   350  	LLDPMAUType10GBaseW        uint16 = 37
   351  	LLDPMAUType10GBaseEW       uint16 = 38
   352  	LLDPMAUType10GBaseLW       uint16 = 39
   353  	LLDPMAUType10GBaseSW       uint16 = 40
   354  	LLDPMAUType10GBaseCX4      uint16 = 41
   355  	LLDPMAUType2BaseTL         uint16 = 42
   356  	LLDPMAUType10PASS_TS       uint16 = 43
   357  	LLDPMAUType100BaseBX10D    uint16 = 44
   358  	LLDPMAUType100BaseBX10U    uint16 = 45
   359  	LLDPMAUType100BaseLX10     uint16 = 46
   360  	LLDPMAUType1000BaseBX10D   uint16 = 47
   361  	LLDPMAUType1000BaseBX10U   uint16 = 48
   362  	LLDPMAUType1000BaseLX10    uint16 = 49
   363  	LLDPMAUType1000BasePX10D   uint16 = 50
   364  	LLDPMAUType1000BasePX10U   uint16 = 51
   365  	LLDPMAUType1000BasePX20D   uint16 = 52
   366  	LLDPMAUType1000BasePX20U   uint16 = 53
   367  	LLDPMAUType10GBaseT        uint16 = 54
   368  	LLDPMAUType10GBaseLRM      uint16 = 55
   369  	LLDPMAUType1000BaseKX      uint16 = 56
   370  	LLDPMAUType10GBaseKX4      uint16 = 57
   371  	LLDPMAUType10GBaseKR       uint16 = 58
   372  	LLDPMAUType10_1GBasePRX_D1 uint16 = 59
   373  	LLDPMAUType10_1GBasePRX_D2 uint16 = 60
   374  	LLDPMAUType10_1GBasePRX_D3 uint16 = 61
   375  	LLDPMAUType10_1GBasePRX_U1 uint16 = 62
   376  	LLDPMAUType10_1GBasePRX_U2 uint16 = 63
   377  	LLDPMAUType10_1GBasePRX_U3 uint16 = 64
   378  	LLDPMAUType10GBasePR_D1    uint16 = 65
   379  	LLDPMAUType10GBasePR_D2    uint16 = 66
   380  	LLDPMAUType10GBasePR_D3    uint16 = 67
   381  	LLDPMAUType10GBasePR_U1    uint16 = 68
   382  	LLDPMAUType10GBasePR_U3    uint16 = 69
   383  )
   384  
   385  // From RFC 3636 - ifMauAutoNegCapAdvertisedBits
   386  const (
   387  	LLDPMAUPMDOther        uint16 = 1 << 15
   388  	LLDPMAUPMD10BaseT      uint16 = 1 << 14
   389  	LLDPMAUPMD10BaseT_FD   uint16 = 1 << 13
   390  	LLDPMAUPMD100BaseT4    uint16 = 1 << 12
   391  	LLDPMAUPMD100BaseTX    uint16 = 1 << 11
   392  	LLDPMAUPMD100BaseTX_FD uint16 = 1 << 10
   393  	LLDPMAUPMD100BaseT2    uint16 = 1 << 9
   394  	LLDPMAUPMD100BaseT2_FD uint16 = 1 << 8
   395  	LLDPMAUPMDFDXPAUSE     uint16 = 1 << 7
   396  	LLDPMAUPMDFDXAPAUSE    uint16 = 1 << 6
   397  	LLDPMAUPMDFDXSPAUSE    uint16 = 1 << 5
   398  	LLDPMAUPMDFDXBPAUSE    uint16 = 1 << 4
   399  	LLDPMAUPMD1000BaseX    uint16 = 1 << 3
   400  	LLDPMAUPMD1000BaseX_FD uint16 = 1 << 2
   401  	LLDPMAUPMD1000BaseT    uint16 = 1 << 1
   402  	LLDPMAUPMD1000BaseT_FD uint16 = 1 << 0
   403  )
   404  
   405  // Inverted ifMauAutoNegCapAdvertisedBits if required
   406  // (Some manufacturers misinterpreted the spec -
   407  // see https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=1455)
   408  const (
   409  	LLDPMAUPMDOtherInv        uint16 = 1 << 0
   410  	LLDPMAUPMD10BaseTInv      uint16 = 1 << 1
   411  	LLDPMAUPMD10BaseT_FDInv   uint16 = 1 << 2
   412  	LLDPMAUPMD100BaseT4Inv    uint16 = 1 << 3
   413  	LLDPMAUPMD100BaseTXInv    uint16 = 1 << 4
   414  	LLDPMAUPMD100BaseTX_FDInv uint16 = 1 << 5
   415  	LLDPMAUPMD100BaseT2Inv    uint16 = 1 << 6
   416  	LLDPMAUPMD100BaseT2_FDInv uint16 = 1 << 7
   417  	LLDPMAUPMDFDXPAUSEInv     uint16 = 1 << 8
   418  	LLDPMAUPMDFDXAPAUSEInv    uint16 = 1 << 9
   419  	LLDPMAUPMDFDXSPAUSEInv    uint16 = 1 << 10
   420  	LLDPMAUPMDFDXBPAUSEInv    uint16 = 1 << 11
   421  	LLDPMAUPMD1000BaseXInv    uint16 = 1 << 12
   422  	LLDPMAUPMD1000BaseX_FDInv uint16 = 1 << 13
   423  	LLDPMAUPMD1000BaseTInv    uint16 = 1 << 14
   424  	LLDPMAUPMD1000BaseT_FDInv uint16 = 1 << 15
   425  )
   426  
   427  type LLDPMACPHYConfigStatus struct {
   428  	AutoNegSupported  bool
   429  	AutoNegEnabled    bool
   430  	AutoNegCapability uint16
   431  	MAUType           uint16
   432  }
   433  
   434  // MDI Power options
   435  const (
   436  	LLDPMDIPowerPortClass    byte = 1 << 0
   437  	LLDPMDIPowerCapability   byte = 1 << 1
   438  	LLDPMDIPowerStatus       byte = 1 << 2
   439  	LLDPMDIPowerPairsAbility byte = 1 << 3
   440  )
   441  
   442  type LLDPPowerType byte
   443  
   444  type LLDPPowerSource byte
   445  
   446  type LLDPPowerPriority byte
   447  
   448  const (
   449  	LLDPPowerPriorityUnknown LLDPPowerPriority = 0
   450  	LLDPPowerPriorityMedium  LLDPPowerPriority = 1
   451  	LLDPPowerPriorityHigh    LLDPPowerPriority = 2
   452  	LLDPPowerPriorityLow     LLDPPowerPriority = 3
   453  )
   454  
   455  type LLDPPowerViaMDI8023 struct {
   456  	PortClassPSE    bool // false = PD
   457  	PSESupported    bool
   458  	PSEEnabled      bool
   459  	PSEPairsAbility bool
   460  	PSEPowerPair    uint8
   461  	PSEClass        uint8
   462  	Type            LLDPPowerType
   463  	Source          LLDPPowerSource
   464  	Priority        LLDPPowerPriority
   465  	Requested       uint16 // 1-510 Watts
   466  	Allocated       uint16 // 1-510 Watts
   467  }
   468  
   469  // LLDPInfo8023 represents the information carried in 802.3 Org-specific TLVs
   470  type LLDPInfo8023 struct {
   471  	MACPHYConfigStatus LLDPMACPHYConfigStatus
   472  	PowerViaMDI        LLDPPowerViaMDI8023
   473  	LinkAggregation    LLDPLinkAggregation
   474  	MTU                uint16
   475  }
   476  
   477  // IEEE 802.1Qbg TLV Subtypes
   478  const (
   479  	LLDP8021QbgEVB   uint8 = 0
   480  	LLDP8021QbgCDCP  uint8 = 1
   481  	LLDP8021QbgVDP   uint8 = 2
   482  	LLDP8021QbgEVB22 uint8 = 13
   483  )
   484  
   485  // LLDPEVBCapabilities Types
   486  const (
   487  	LLDPEVBCapsSTD uint16 = 1 << 7
   488  	LLDPEVBCapsRR  uint16 = 1 << 6
   489  	LLDPEVBCapsRTE uint16 = 1 << 2
   490  	LLDPEVBCapsECP uint16 = 1 << 1
   491  	LLDPEVBCapsVDP uint16 = 1 << 0
   492  )
   493  
   494  // LLDPEVBCapabilities represents the EVB capabilities of a device
   495  type LLDPEVBCapabilities struct {
   496  	StandardBridging            bool
   497  	ReflectiveRelay             bool
   498  	RetransmissionTimerExponent bool
   499  	EdgeControlProtocol         bool
   500  	VSIDiscoveryProtocol        bool
   501  }
   502  
   503  type LLDPEVBSettings struct {
   504  	Supported      LLDPEVBCapabilities
   505  	Enabled        LLDPEVBCapabilities
   506  	SupportedVSIs  uint16
   507  	ConfiguredVSIs uint16
   508  	RTEExponent    uint8
   509  }
   510  
   511  // LLDPInfo8021Qbg represents the information carried in 802.1Qbg Org-specific TLVs
   512  type LLDPInfo8021Qbg struct {
   513  	EVBSettings LLDPEVBSettings
   514  }
   515  
   516  type LLDPMediaSubtype uint8
   517  
   518  // Media TLV Subtypes
   519  const (
   520  	LLDPMediaTypeCapabilities LLDPMediaSubtype = 1
   521  	LLDPMediaTypeNetwork      LLDPMediaSubtype = 2
   522  	LLDPMediaTypeLocation     LLDPMediaSubtype = 3
   523  	LLDPMediaTypePower        LLDPMediaSubtype = 4
   524  	LLDPMediaTypeHardware     LLDPMediaSubtype = 5
   525  	LLDPMediaTypeFirmware     LLDPMediaSubtype = 6
   526  	LLDPMediaTypeSoftware     LLDPMediaSubtype = 7
   527  	LLDPMediaTypeSerial       LLDPMediaSubtype = 8
   528  	LLDPMediaTypeManufacturer LLDPMediaSubtype = 9
   529  	LLDPMediaTypeModel        LLDPMediaSubtype = 10
   530  	LLDPMediaTypeAssetID      LLDPMediaSubtype = 11
   531  )
   532  
   533  type LLDPMediaClass uint8
   534  
   535  // Media Class Values
   536  const (
   537  	LLDPMediaClassUndefined   LLDPMediaClass = 0
   538  	LLDPMediaClassEndpointI   LLDPMediaClass = 1
   539  	LLDPMediaClassEndpointII  LLDPMediaClass = 2
   540  	LLDPMediaClassEndpointIII LLDPMediaClass = 3
   541  	LLDPMediaClassNetwork     LLDPMediaClass = 4
   542  )
   543  
   544  // LLDPMediaCapabilities Types
   545  const (
   546  	LLDPMediaCapsLLDP      uint16 = 1 << 0
   547  	LLDPMediaCapsNetwork   uint16 = 1 << 1
   548  	LLDPMediaCapsLocation  uint16 = 1 << 2
   549  	LLDPMediaCapsPowerPSE  uint16 = 1 << 3
   550  	LLDPMediaCapsPowerPD   uint16 = 1 << 4
   551  	LLDPMediaCapsInventory uint16 = 1 << 5
   552  )
   553  
   554  // LLDPMediaCapabilities represents the LLDP Media capabilities of a device
   555  type LLDPMediaCapabilities struct {
   556  	Capabilities  bool
   557  	NetworkPolicy bool
   558  	Location      bool
   559  	PowerPSE      bool
   560  	PowerPD       bool
   561  	Inventory     bool
   562  	Class         LLDPMediaClass
   563  }
   564  
   565  type LLDPApplicationType uint8
   566  
   567  const (
   568  	LLDPAppTypeReserved            LLDPApplicationType = 0
   569  	LLDPAppTypeVoice               LLDPApplicationType = 1
   570  	LLDPappTypeVoiceSignaling      LLDPApplicationType = 2
   571  	LLDPappTypeGuestVoice          LLDPApplicationType = 3
   572  	LLDPappTypeGuestVoiceSignaling LLDPApplicationType = 4
   573  	LLDPappTypeSoftphoneVoice      LLDPApplicationType = 5
   574  	LLDPappTypeVideoConferencing   LLDPApplicationType = 6
   575  	LLDPappTypeStreamingVideo      LLDPApplicationType = 7
   576  	LLDPappTypeVideoSignaling      LLDPApplicationType = 8
   577  )
   578  
   579  type LLDPNetworkPolicy struct {
   580  	ApplicationType LLDPApplicationType
   581  	Defined         bool
   582  	Tagged          bool
   583  	VLANId          uint16
   584  	L2Priority      uint16
   585  	DSCPValue       uint8
   586  }
   587  
   588  type LLDPLocationFormat uint8
   589  
   590  const (
   591  	LLDPLocationFormatInvalid    LLDPLocationFormat = 0
   592  	LLDPLocationFormatCoordinate LLDPLocationFormat = 1
   593  	LLDPLocationFormatAddress    LLDPLocationFormat = 2
   594  	LLDPLocationFormatECS        LLDPLocationFormat = 3
   595  )
   596  
   597  type LLDPLocationAddressWhat uint8
   598  
   599  const (
   600  	LLDPLocationAddressWhatDHCP    LLDPLocationAddressWhat = 0
   601  	LLDPLocationAddressWhatNetwork LLDPLocationAddressWhat = 1
   602  	LLDPLocationAddressWhatClient  LLDPLocationAddressWhat = 2
   603  )
   604  
   605  type LLDPLocationAddressType uint8
   606  
   607  const (
   608  	LLDPLocationAddressTypeLanguage       LLDPLocationAddressType = 0
   609  	LLDPLocationAddressTypeNational       LLDPLocationAddressType = 1
   610  	LLDPLocationAddressTypeCounty         LLDPLocationAddressType = 2
   611  	LLDPLocationAddressTypeCity           LLDPLocationAddressType = 3
   612  	LLDPLocationAddressTypeCityDivision   LLDPLocationAddressType = 4
   613  	LLDPLocationAddressTypeNeighborhood   LLDPLocationAddressType = 5
   614  	LLDPLocationAddressTypeStreet         LLDPLocationAddressType = 6
   615  	LLDPLocationAddressTypeLeadingStreet  LLDPLocationAddressType = 16
   616  	LLDPLocationAddressTypeTrailingStreet LLDPLocationAddressType = 17
   617  	LLDPLocationAddressTypeStreetSuffix   LLDPLocationAddressType = 18
   618  	LLDPLocationAddressTypeHouseNum       LLDPLocationAddressType = 19
   619  	LLDPLocationAddressTypeHouseSuffix    LLDPLocationAddressType = 20
   620  	LLDPLocationAddressTypeLandmark       LLDPLocationAddressType = 21
   621  	LLDPLocationAddressTypeAdditional     LLDPLocationAddressType = 22
   622  	LLDPLocationAddressTypeName           LLDPLocationAddressType = 23
   623  	LLDPLocationAddressTypePostal         LLDPLocationAddressType = 24
   624  	LLDPLocationAddressTypeBuilding       LLDPLocationAddressType = 25
   625  	LLDPLocationAddressTypeUnit           LLDPLocationAddressType = 26
   626  	LLDPLocationAddressTypeFloor          LLDPLocationAddressType = 27
   627  	LLDPLocationAddressTypeRoom           LLDPLocationAddressType = 28
   628  	LLDPLocationAddressTypePlace          LLDPLocationAddressType = 29
   629  	LLDPLocationAddressTypeScript         LLDPLocationAddressType = 128
   630  )
   631  
   632  type LLDPLocationCoordinate struct {
   633  	LatitudeResolution  uint8
   634  	Latitude            uint64
   635  	LongitudeResolution uint8
   636  	Longitude           uint64
   637  	AltitudeType        uint8
   638  	AltitudeResolution  uint16
   639  	Altitude            uint32
   640  	Datum               uint8
   641  }
   642  
   643  type LLDPLocationAddressLine struct {
   644  	Type  LLDPLocationAddressType
   645  	Value string
   646  }
   647  
   648  type LLDPLocationAddress struct {
   649  	What         LLDPLocationAddressWhat
   650  	CountryCode  string
   651  	AddressLines []LLDPLocationAddressLine
   652  }
   653  
   654  type LLDPLocationECS struct {
   655  	ELIN string
   656  }
   657  
   658  // LLDP represents a physical location.
   659  // Only one of the embedded types will contain values, depending on Format.
   660  type LLDPLocation struct {
   661  	Format     LLDPLocationFormat
   662  	Coordinate LLDPLocationCoordinate
   663  	Address    LLDPLocationAddress
   664  	ECS        LLDPLocationECS
   665  }
   666  
   667  type LLDPPowerViaMDI struct {
   668  	Type     LLDPPowerType
   669  	Source   LLDPPowerSource
   670  	Priority LLDPPowerPriority
   671  	Value    uint16
   672  }
   673  
   674  // LLDPInfoMedia represents the information carried in TR-41 Org-specific TLVs
   675  type LLDPInfoMedia struct {
   676  	MediaCapabilities LLDPMediaCapabilities
   677  	NetworkPolicy     LLDPNetworkPolicy
   678  	Location          LLDPLocation
   679  	PowerViaMDI       LLDPPowerViaMDI
   680  	HardwareRevision  string
   681  	FirmwareRevision  string
   682  	SoftwareRevision  string
   683  	SerialNumber      string
   684  	Manufacturer      string
   685  	Model             string
   686  	AssetID           string
   687  }
   688  
   689  type LLDPCisco2Subtype uint8
   690  
   691  // Cisco2 TLV Subtypes
   692  const (
   693  	LLDPCisco2PowerViaMDI LLDPCisco2Subtype = 1
   694  )
   695  
   696  const (
   697  	LLDPCiscoPSESupport   uint8 = 1 << 0
   698  	LLDPCiscoArchShared   uint8 = 1 << 1
   699  	LLDPCiscoPDSparePair  uint8 = 1 << 2
   700  	LLDPCiscoPSESparePair uint8 = 1 << 3
   701  )
   702  
   703  // LLDPInfoCisco2 represents the information carried in Cisco Org-specific TLVs
   704  type LLDPInfoCisco2 struct {
   705  	PSEFourWirePoESupported       bool
   706  	PDSparePairArchitectureShared bool
   707  	PDRequestSparePairPoEOn       bool
   708  	PSESparePairPoEOn             bool
   709  }
   710  
   711  // Profinet Subtypes
   712  type LLDPProfinetSubtype uint8
   713  
   714  const (
   715  	LLDPProfinetPNIODelay         LLDPProfinetSubtype = 1
   716  	LLDPProfinetPNIOPortStatus    LLDPProfinetSubtype = 2
   717  	LLDPProfinetPNIOMRPPortStatus LLDPProfinetSubtype = 4
   718  	LLDPProfinetPNIOChassisMAC    LLDPProfinetSubtype = 5
   719  	LLDPProfinetPNIOPTCPStatus    LLDPProfinetSubtype = 6
   720  )
   721  
   722  type LLDPPNIODelay struct {
   723  	RXLocal    uint32
   724  	RXRemote   uint32
   725  	TXLocal    uint32
   726  	TXRemote   uint32
   727  	CableLocal uint32
   728  }
   729  
   730  type LLDPPNIOPortStatus struct {
   731  	Class2 uint16
   732  	Class3 uint16
   733  }
   734  
   735  type LLDPPNIOMRPPortStatus struct {
   736  	UUID   []byte
   737  	Status uint16
   738  }
   739  
   740  type LLDPPNIOPTCPStatus struct {
   741  	MasterAddress     []byte
   742  	SubdomainUUID     []byte
   743  	IRDataUUID        []byte
   744  	PeriodValid       bool
   745  	PeriodLength      uint32
   746  	RedPeriodValid    bool
   747  	RedPeriodBegin    uint32
   748  	OrangePeriodValid bool
   749  	OrangePeriodBegin uint32
   750  	GreenPeriodValid  bool
   751  	GreenPeriodBegin  uint32
   752  }
   753  
   754  // LLDPInfoProfinet represents the information carried in Profinet Org-specific TLVs
   755  type LLDPInfoProfinet struct {
   756  	PNIODelay         LLDPPNIODelay
   757  	PNIOPortStatus    LLDPPNIOPortStatus
   758  	PNIOMRPPortStatus LLDPPNIOMRPPortStatus
   759  	ChassisMAC        []byte
   760  	PNIOPTCPStatus    LLDPPNIOPTCPStatus
   761  }
   762  
   763  // LayerType returns gopacket.LayerTypeLinkLayerDiscovery.
   764  func (c *LinkLayerDiscovery) LayerType() gopacket.LayerType {
   765  	return LayerTypeLinkLayerDiscovery
   766  }
   767  
   768  // SerializeTo serializes LLDP packet to bytes and writes on SerializeBuffer.
   769  func (c *LinkLayerDiscovery) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   770  	chassIDLen := c.ChassisID.serializedLen()
   771  	portIDLen := c.PortID.serializedLen()
   772  	vb, err := b.AppendBytes(chassIDLen + portIDLen + 4) // +4 for TTL
   773  	if err != nil {
   774  		return err
   775  	}
   776  	copy(vb[:chassIDLen], c.ChassisID.serialize())
   777  	copy(vb[chassIDLen:], c.PortID.serialize())
   778  	ttlIDLen := uint16(LLDPTLVTTL)<<9 | uint16(2)
   779  	binary.BigEndian.PutUint16(vb[chassIDLen+portIDLen:], ttlIDLen)
   780  	binary.BigEndian.PutUint16(vb[chassIDLen+portIDLen+2:], c.TTL)
   781  
   782  	for _, v := range c.Values {
   783  		vb, err := b.AppendBytes(int(v.Length) + 2) // +2 for TLV type and length; 1 byte for subtype is included in v.Value
   784  		if err != nil {
   785  			return err
   786  		}
   787  		idLen := ((uint16(v.Type) << 9) | v.Length)
   788  		binary.BigEndian.PutUint16(vb[0:2], idLen)
   789  		copy(vb[2:], v.Value)
   790  	}
   791  
   792  	vb, err = b.AppendBytes(2) // End Tlv, 2 bytes
   793  	if err != nil {
   794  		return err
   795  	}
   796  	binary.BigEndian.PutUint16(vb[len(vb)-2:], uint16(0)) //End tlv, 2 bytes, all zero
   797  	return nil
   798  
   799  }
   800  
   801  func decodeLinkLayerDiscovery(data []byte, p gopacket.PacketBuilder) error {
   802  	var vals []LinkLayerDiscoveryValue
   803  	vData := data[0:]
   804  	for len(vData) > 0 {
   805  		if len(vData) < 2 {
   806  			p.SetTruncated()
   807  			return errors.New("LLDP vdata < 2 bytes")
   808  		}
   809  		nbit := vData[0] & 0x01
   810  		t := LLDPTLVType(vData[0] >> 1)
   811  		val := LinkLayerDiscoveryValue{Type: t, Length: uint16(nbit)<<8 + uint16(vData[1])}
   812  		if val.Length > 0 {
   813  			if len(vData) < int(val.Length+2) {
   814  				p.SetTruncated()
   815  				return fmt.Errorf("LLDP VData < %d bytes", val.Length+2)
   816  			}
   817  			val.Value = vData[2 : val.Length+2]
   818  		}
   819  		vals = append(vals, val)
   820  		if t == LLDPTLVEnd {
   821  			break
   822  		}
   823  		if len(vData) < int(2+val.Length) {
   824  			return errors.New("Malformed LinkLayerDiscovery Header")
   825  		}
   826  		vData = vData[2+val.Length:]
   827  	}
   828  	if len(vals) < 4 {
   829  		return errors.New("Missing mandatory LinkLayerDiscovery TLV")
   830  	}
   831  	c := &LinkLayerDiscovery{}
   832  	gotEnd := false
   833  	for _, v := range vals {
   834  		switch v.Type {
   835  		case LLDPTLVEnd:
   836  			gotEnd = true
   837  		case LLDPTLVChassisID:
   838  			if len(v.Value) < 2 {
   839  				return errors.New("Malformed LinkLayerDiscovery ChassisID TLV")
   840  			}
   841  			c.ChassisID.Subtype = LLDPChassisIDSubType(v.Value[0])
   842  			c.ChassisID.ID = v.Value[1:]
   843  		case LLDPTLVPortID:
   844  			if len(v.Value) < 2 {
   845  				return errors.New("Malformed LinkLayerDiscovery PortID TLV")
   846  			}
   847  			c.PortID.Subtype = LLDPPortIDSubType(v.Value[0])
   848  			c.PortID.ID = v.Value[1:]
   849  		case LLDPTLVTTL:
   850  			if len(v.Value) < 2 {
   851  				return errors.New("Malformed LinkLayerDiscovery TTL TLV")
   852  			}
   853  			c.TTL = binary.BigEndian.Uint16(v.Value[0:2])
   854  		default:
   855  			c.Values = append(c.Values, v)
   856  		}
   857  	}
   858  	if c.ChassisID.Subtype == 0 || c.PortID.Subtype == 0 || !gotEnd {
   859  		return errors.New("Missing mandatory LinkLayerDiscovery TLV")
   860  	}
   861  	c.Contents = data
   862  	p.AddLayer(c)
   863  
   864  	info := &LinkLayerDiscoveryInfo{}
   865  	p.AddLayer(info)
   866  	for _, v := range c.Values {
   867  		switch v.Type {
   868  		case LLDPTLVPortDescription:
   869  			info.PortDescription = string(v.Value)
   870  		case LLDPTLVSysName:
   871  			info.SysName = string(v.Value)
   872  		case LLDPTLVSysDescription:
   873  			info.SysDescription = string(v.Value)
   874  		case LLDPTLVSysCapabilities:
   875  			if err := checkLLDPTLVLen(v, 4); err != nil {
   876  				return err
   877  			}
   878  			info.SysCapabilities.SystemCap = getCapabilities(binary.BigEndian.Uint16(v.Value[0:2]))
   879  			info.SysCapabilities.EnabledCap = getCapabilities(binary.BigEndian.Uint16(v.Value[2:4]))
   880  		case LLDPTLVMgmtAddress:
   881  			if err := checkLLDPTLVLen(v, 9); err != nil {
   882  				return err
   883  			}
   884  			mlen := v.Value[0]
   885  			if err := checkLLDPTLVLen(v, int(mlen+7)); err != nil {
   886  				return err
   887  			}
   888  			info.MgmtAddress.Subtype = IANAAddressFamily(v.Value[1])
   889  			info.MgmtAddress.Address = v.Value[2 : mlen+1]
   890  			info.MgmtAddress.InterfaceSubtype = LLDPInterfaceSubtype(v.Value[mlen+1])
   891  			info.MgmtAddress.InterfaceNumber = binary.BigEndian.Uint32(v.Value[mlen+2 : mlen+6])
   892  			olen := v.Value[mlen+6]
   893  			if err := checkLLDPTLVLen(v, int(mlen+7+olen)); err != nil {
   894  				return err
   895  			}
   896  			info.MgmtAddress.OID = string(v.Value[mlen+7 : mlen+7+olen])
   897  		case LLDPTLVOrgSpecific:
   898  			if err := checkLLDPTLVLen(v, 4); err != nil {
   899  				return err
   900  			}
   901  			info.OrgTLVs = append(info.OrgTLVs, LLDPOrgSpecificTLV{IEEEOUI(binary.BigEndian.Uint32(append([]byte{byte(0)}, v.Value[0:3]...))), uint8(v.Value[3]), v.Value[4:]})
   902  		}
   903  	}
   904  	return nil
   905  }
   906  
   907  func (l *LinkLayerDiscoveryInfo) Decode8021() (info LLDPInfo8021, err error) {
   908  	for _, o := range l.OrgTLVs {
   909  		if o.OUI != IEEEOUI8021 {
   910  			continue
   911  		}
   912  		switch o.SubType {
   913  		case LLDP8021SubtypePortVLANID:
   914  			if err = checkLLDPOrgSpecificLen(o, 2); err != nil {
   915  				return
   916  			}
   917  			info.PVID = binary.BigEndian.Uint16(o.Info[0:2])
   918  		case LLDP8021SubtypeProtocolVLANID:
   919  			if err = checkLLDPOrgSpecificLen(o, 3); err != nil {
   920  				return
   921  			}
   922  			sup := (o.Info[0]&LLDPProtocolVLANIDCapability > 0)
   923  			en := (o.Info[0]&LLDPProtocolVLANIDStatus > 0)
   924  			id := binary.BigEndian.Uint16(o.Info[1:3])
   925  			info.PPVIDs = append(info.PPVIDs, PortProtocolVLANID{sup, en, id})
   926  		case LLDP8021SubtypeVLANName:
   927  			if err = checkLLDPOrgSpecificLen(o, 2); err != nil {
   928  				return
   929  			}
   930  			id := binary.BigEndian.Uint16(o.Info[0:2])
   931  			info.VLANNames = append(info.VLANNames, VLANName{id, string(o.Info[3:])})
   932  		case LLDP8021SubtypeProtocolIdentity:
   933  			if err = checkLLDPOrgSpecificLen(o, 1); err != nil {
   934  				return
   935  			}
   936  			l := int(o.Info[0])
   937  			if l > 0 {
   938  				info.ProtocolIdentities = append(info.ProtocolIdentities, o.Info[1:1+l])
   939  			}
   940  		case LLDP8021SubtypeVDIUsageDigest:
   941  			if err = checkLLDPOrgSpecificLen(o, 4); err != nil {
   942  				return
   943  			}
   944  			info.VIDUsageDigest = binary.BigEndian.Uint32(o.Info[0:4])
   945  		case LLDP8021SubtypeManagementVID:
   946  			if err = checkLLDPOrgSpecificLen(o, 2); err != nil {
   947  				return
   948  			}
   949  			info.ManagementVID = binary.BigEndian.Uint16(o.Info[0:2])
   950  		case LLDP8021SubtypeLinkAggregation:
   951  			if err = checkLLDPOrgSpecificLen(o, 5); err != nil {
   952  				return
   953  			}
   954  			sup := (o.Info[0]&LLDPAggregationCapability > 0)
   955  			en := (o.Info[0]&LLDPAggregationStatus > 0)
   956  			info.LinkAggregation = LLDPLinkAggregation{sup, en, binary.BigEndian.Uint32(o.Info[1:5])}
   957  		}
   958  	}
   959  	return
   960  }
   961  
   962  func (l *LinkLayerDiscoveryInfo) Decode8023() (info LLDPInfo8023, err error) {
   963  	for _, o := range l.OrgTLVs {
   964  		if o.OUI != IEEEOUI8023 {
   965  			continue
   966  		}
   967  		switch o.SubType {
   968  		case LLDP8023SubtypeMACPHY:
   969  			if err = checkLLDPOrgSpecificLen(o, 5); err != nil {
   970  				return
   971  			}
   972  			sup := (o.Info[0]&LLDPMACPHYCapability > 0)
   973  			en := (o.Info[0]&LLDPMACPHYStatus > 0)
   974  			ca := binary.BigEndian.Uint16(o.Info[1:3])
   975  			mau := binary.BigEndian.Uint16(o.Info[3:5])
   976  			info.MACPHYConfigStatus = LLDPMACPHYConfigStatus{sup, en, ca, mau}
   977  		case LLDP8023SubtypeMDIPower:
   978  			if err = checkLLDPOrgSpecificLen(o, 3); err != nil {
   979  				return
   980  			}
   981  			info.PowerViaMDI.PortClassPSE = (o.Info[0]&LLDPMDIPowerPortClass > 0)
   982  			info.PowerViaMDI.PSESupported = (o.Info[0]&LLDPMDIPowerCapability > 0)
   983  			info.PowerViaMDI.PSEEnabled = (o.Info[0]&LLDPMDIPowerStatus > 0)
   984  			info.PowerViaMDI.PSEPairsAbility = (o.Info[0]&LLDPMDIPowerPairsAbility > 0)
   985  			info.PowerViaMDI.PSEPowerPair = uint8(o.Info[1])
   986  			info.PowerViaMDI.PSEClass = uint8(o.Info[2])
   987  			if len(o.Info) >= 7 {
   988  				info.PowerViaMDI.Type = LLDPPowerType((o.Info[3] & 0xc0) >> 6)
   989  				info.PowerViaMDI.Source = LLDPPowerSource((o.Info[3] & 0x30) >> 4)
   990  				if info.PowerViaMDI.Type == 1 || info.PowerViaMDI.Type == 3 {
   991  					info.PowerViaMDI.Source += 128 // For Stringify purposes
   992  				}
   993  				info.PowerViaMDI.Priority = LLDPPowerPriority(o.Info[3] & 0x0f)
   994  				info.PowerViaMDI.Requested = binary.BigEndian.Uint16(o.Info[4:6])
   995  				info.PowerViaMDI.Allocated = binary.BigEndian.Uint16(o.Info[6:8])
   996  			}
   997  		case LLDP8023SubtypeLinkAggregation:
   998  			if err = checkLLDPOrgSpecificLen(o, 5); err != nil {
   999  				return
  1000  			}
  1001  			sup := (o.Info[0]&LLDPAggregationCapability > 0)
  1002  			en := (o.Info[0]&LLDPAggregationStatus > 0)
  1003  			info.LinkAggregation = LLDPLinkAggregation{sup, en, binary.BigEndian.Uint32(o.Info[1:5])}
  1004  		case LLDP8023SubtypeMTU:
  1005  			if err = checkLLDPOrgSpecificLen(o, 2); err != nil {
  1006  				return
  1007  			}
  1008  			info.MTU = binary.BigEndian.Uint16(o.Info[0:2])
  1009  		}
  1010  	}
  1011  	return
  1012  }
  1013  
  1014  func (l *LinkLayerDiscoveryInfo) Decode8021Qbg() (info LLDPInfo8021Qbg, err error) {
  1015  	for _, o := range l.OrgTLVs {
  1016  		if o.OUI != IEEEOUI8021Qbg {
  1017  			continue
  1018  		}
  1019  		switch o.SubType {
  1020  		case LLDP8021QbgEVB:
  1021  			if err = checkLLDPOrgSpecificLen(o, 9); err != nil {
  1022  				return
  1023  			}
  1024  			info.EVBSettings.Supported = getEVBCapabilities(binary.BigEndian.Uint16(o.Info[0:2]))
  1025  			info.EVBSettings.Enabled = getEVBCapabilities(binary.BigEndian.Uint16(o.Info[2:4]))
  1026  			info.EVBSettings.SupportedVSIs = binary.BigEndian.Uint16(o.Info[4:6])
  1027  			info.EVBSettings.ConfiguredVSIs = binary.BigEndian.Uint16(o.Info[6:8])
  1028  			info.EVBSettings.RTEExponent = uint8(o.Info[8])
  1029  		}
  1030  	}
  1031  	return
  1032  }
  1033  
  1034  func (l *LinkLayerDiscoveryInfo) DecodeMedia() (info LLDPInfoMedia, err error) {
  1035  	for _, o := range l.OrgTLVs {
  1036  		if o.OUI != IEEEOUIMedia {
  1037  			continue
  1038  		}
  1039  		switch LLDPMediaSubtype(o.SubType) {
  1040  		case LLDPMediaTypeCapabilities:
  1041  			if err = checkLLDPOrgSpecificLen(o, 3); err != nil {
  1042  				return
  1043  			}
  1044  			b := binary.BigEndian.Uint16(o.Info[0:2])
  1045  			info.MediaCapabilities.Capabilities = (b & LLDPMediaCapsLLDP) > 0
  1046  			info.MediaCapabilities.NetworkPolicy = (b & LLDPMediaCapsNetwork) > 0
  1047  			info.MediaCapabilities.Location = (b & LLDPMediaCapsLocation) > 0
  1048  			info.MediaCapabilities.PowerPSE = (b & LLDPMediaCapsPowerPSE) > 0
  1049  			info.MediaCapabilities.PowerPD = (b & LLDPMediaCapsPowerPD) > 0
  1050  			info.MediaCapabilities.Inventory = (b & LLDPMediaCapsInventory) > 0
  1051  			info.MediaCapabilities.Class = LLDPMediaClass(o.Info[2])
  1052  		case LLDPMediaTypeNetwork:
  1053  			if err = checkLLDPOrgSpecificLen(o, 4); err != nil {
  1054  				return
  1055  			}
  1056  			info.NetworkPolicy.ApplicationType = LLDPApplicationType(o.Info[0])
  1057  			b := binary.BigEndian.Uint16(o.Info[1:3])
  1058  			info.NetworkPolicy.Defined = (b & 0x8000) == 0
  1059  			info.NetworkPolicy.Tagged = (b & 0x4000) > 0
  1060  			info.NetworkPolicy.VLANId = (b & 0x1ffe) >> 1
  1061  			b = binary.BigEndian.Uint16(o.Info[2:4])
  1062  			info.NetworkPolicy.L2Priority = (b & 0x01c0) >> 6
  1063  			info.NetworkPolicy.DSCPValue = uint8(o.Info[3] & 0x3f)
  1064  		case LLDPMediaTypeLocation:
  1065  			if err = checkLLDPOrgSpecificLen(o, 1); err != nil {
  1066  				return
  1067  			}
  1068  			info.Location.Format = LLDPLocationFormat(o.Info[0])
  1069  			o.Info = o.Info[1:]
  1070  			switch info.Location.Format {
  1071  			case LLDPLocationFormatCoordinate:
  1072  				if err = checkLLDPOrgSpecificLen(o, 16); err != nil {
  1073  					return
  1074  				}
  1075  				info.Location.Coordinate.LatitudeResolution = uint8(o.Info[0]&0xfc) >> 2
  1076  				b := binary.BigEndian.Uint64(o.Info[0:8])
  1077  				info.Location.Coordinate.Latitude = (b & 0x03ffffffff000000) >> 24
  1078  				info.Location.Coordinate.LongitudeResolution = uint8(o.Info[5]&0xfc) >> 2
  1079  				b = binary.BigEndian.Uint64(o.Info[5:13])
  1080  				info.Location.Coordinate.Longitude = (b & 0x03ffffffff000000) >> 24
  1081  				info.Location.Coordinate.AltitudeType = uint8((o.Info[10] & 0x30) >> 4)
  1082  				b1 := binary.BigEndian.Uint16(o.Info[10:12])
  1083  				info.Location.Coordinate.AltitudeResolution = (b1 & 0xfc0) >> 6
  1084  				b2 := binary.BigEndian.Uint32(o.Info[11:15])
  1085  				info.Location.Coordinate.Altitude = b2 & 0x3fffffff
  1086  				info.Location.Coordinate.Datum = uint8(o.Info[15])
  1087  			case LLDPLocationFormatAddress:
  1088  				if err = checkLLDPOrgSpecificLen(o, 3); err != nil {
  1089  					return
  1090  				}
  1091  				//ll := uint8(o.Info[0])
  1092  				info.Location.Address.What = LLDPLocationAddressWhat(o.Info[1])
  1093  				info.Location.Address.CountryCode = string(o.Info[2:4])
  1094  				data := o.Info[4:]
  1095  				for len(data) > 1 {
  1096  					aType := LLDPLocationAddressType(data[0])
  1097  					aLen := int(data[1])
  1098  					if len(data) >= aLen+2 {
  1099  						info.Location.Address.AddressLines = append(info.Location.Address.AddressLines, LLDPLocationAddressLine{aType, string(data[2 : aLen+2])})
  1100  						data = data[aLen+2:]
  1101  					} else {
  1102  						break
  1103  					}
  1104  				}
  1105  			case LLDPLocationFormatECS:
  1106  				info.Location.ECS.ELIN = string(o.Info)
  1107  			}
  1108  		case LLDPMediaTypePower:
  1109  			if err = checkLLDPOrgSpecificLen(o, 3); err != nil {
  1110  				return
  1111  			}
  1112  			info.PowerViaMDI.Type = LLDPPowerType((o.Info[0] & 0xc0) >> 6)
  1113  			info.PowerViaMDI.Source = LLDPPowerSource((o.Info[0] & 0x30) >> 4)
  1114  			if info.PowerViaMDI.Type == 1 || info.PowerViaMDI.Type == 3 {
  1115  				info.PowerViaMDI.Source += 128 // For Stringify purposes
  1116  			}
  1117  			info.PowerViaMDI.Priority = LLDPPowerPriority(o.Info[0] & 0x0f)
  1118  			info.PowerViaMDI.Value = binary.BigEndian.Uint16(o.Info[1:3]) * 100 // 0 to 102.3 w, 0.1W increments
  1119  		case LLDPMediaTypeHardware:
  1120  			info.HardwareRevision = string(o.Info)
  1121  		case LLDPMediaTypeFirmware:
  1122  			info.FirmwareRevision = string(o.Info)
  1123  		case LLDPMediaTypeSoftware:
  1124  			info.SoftwareRevision = string(o.Info)
  1125  		case LLDPMediaTypeSerial:
  1126  			info.SerialNumber = string(o.Info)
  1127  		case LLDPMediaTypeManufacturer:
  1128  			info.Manufacturer = string(o.Info)
  1129  		case LLDPMediaTypeModel:
  1130  			info.Model = string(o.Info)
  1131  		case LLDPMediaTypeAssetID:
  1132  			info.AssetID = string(o.Info)
  1133  		}
  1134  	}
  1135  	return
  1136  }
  1137  
  1138  func (l *LinkLayerDiscoveryInfo) DecodeCisco2() (info LLDPInfoCisco2, err error) {
  1139  	for _, o := range l.OrgTLVs {
  1140  		if o.OUI != IEEEOUICisco2 {
  1141  			continue
  1142  		}
  1143  		switch LLDPCisco2Subtype(o.SubType) {
  1144  		case LLDPCisco2PowerViaMDI:
  1145  			if err = checkLLDPOrgSpecificLen(o, 1); err != nil {
  1146  				return
  1147  			}
  1148  			info.PSEFourWirePoESupported = (o.Info[0] & LLDPCiscoPSESupport) > 0
  1149  			info.PDSparePairArchitectureShared = (o.Info[0] & LLDPCiscoArchShared) > 0
  1150  			info.PDRequestSparePairPoEOn = (o.Info[0] & LLDPCiscoPDSparePair) > 0
  1151  			info.PSESparePairPoEOn = (o.Info[0] & LLDPCiscoPSESparePair) > 0
  1152  		}
  1153  	}
  1154  	return
  1155  }
  1156  
  1157  func (l *LinkLayerDiscoveryInfo) DecodeProfinet() (info LLDPInfoProfinet, err error) {
  1158  	for _, o := range l.OrgTLVs {
  1159  		if o.OUI != IEEEOUIProfinet {
  1160  			continue
  1161  		}
  1162  		switch LLDPProfinetSubtype(o.SubType) {
  1163  		case LLDPProfinetPNIODelay:
  1164  			if err = checkLLDPOrgSpecificLen(o, 20); err != nil {
  1165  				return
  1166  			}
  1167  			info.PNIODelay.RXLocal = binary.BigEndian.Uint32(o.Info[0:4])
  1168  			info.PNIODelay.RXRemote = binary.BigEndian.Uint32(o.Info[4:8])
  1169  			info.PNIODelay.TXLocal = binary.BigEndian.Uint32(o.Info[8:12])
  1170  			info.PNIODelay.TXRemote = binary.BigEndian.Uint32(o.Info[12:16])
  1171  			info.PNIODelay.CableLocal = binary.BigEndian.Uint32(o.Info[16:20])
  1172  		case LLDPProfinetPNIOPortStatus:
  1173  			if err = checkLLDPOrgSpecificLen(o, 4); err != nil {
  1174  				return
  1175  			}
  1176  			info.PNIOPortStatus.Class2 = binary.BigEndian.Uint16(o.Info[0:2])
  1177  			info.PNIOPortStatus.Class3 = binary.BigEndian.Uint16(o.Info[2:4])
  1178  		case LLDPProfinetPNIOMRPPortStatus:
  1179  			if err = checkLLDPOrgSpecificLen(o, 18); err != nil {
  1180  				return
  1181  			}
  1182  			info.PNIOMRPPortStatus.UUID = o.Info[0:16]
  1183  			info.PNIOMRPPortStatus.Status = binary.BigEndian.Uint16(o.Info[16:18])
  1184  		case LLDPProfinetPNIOChassisMAC:
  1185  			if err = checkLLDPOrgSpecificLen(o, 6); err != nil {
  1186  				return
  1187  			}
  1188  			info.ChassisMAC = o.Info[0:6]
  1189  		case LLDPProfinetPNIOPTCPStatus:
  1190  			if err = checkLLDPOrgSpecificLen(o, 54); err != nil {
  1191  				return
  1192  			}
  1193  			info.PNIOPTCPStatus.MasterAddress = o.Info[0:6]
  1194  			info.PNIOPTCPStatus.SubdomainUUID = o.Info[6:22]
  1195  			info.PNIOPTCPStatus.IRDataUUID = o.Info[22:38]
  1196  			b := binary.BigEndian.Uint32(o.Info[38:42])
  1197  			info.PNIOPTCPStatus.PeriodValid = (b & 0x80000000) > 0
  1198  			info.PNIOPTCPStatus.PeriodLength = b & 0x7fffffff
  1199  			b = binary.BigEndian.Uint32(o.Info[42:46])
  1200  			info.PNIOPTCPStatus.RedPeriodValid = (b & 0x80000000) > 0
  1201  			info.PNIOPTCPStatus.RedPeriodBegin = b & 0x7fffffff
  1202  			b = binary.BigEndian.Uint32(o.Info[46:50])
  1203  			info.PNIOPTCPStatus.OrangePeriodValid = (b & 0x80000000) > 0
  1204  			info.PNIOPTCPStatus.OrangePeriodBegin = b & 0x7fffffff
  1205  			b = binary.BigEndian.Uint32(o.Info[50:54])
  1206  			info.PNIOPTCPStatus.GreenPeriodValid = (b & 0x80000000) > 0
  1207  			info.PNIOPTCPStatus.GreenPeriodBegin = b & 0x7fffffff
  1208  		}
  1209  	}
  1210  	return
  1211  }
  1212  
  1213  // LayerType returns gopacket.LayerTypeLinkLayerDiscoveryInfo.
  1214  func (c *LinkLayerDiscoveryInfo) LayerType() gopacket.LayerType {
  1215  	return LayerTypeLinkLayerDiscoveryInfo
  1216  }
  1217  
  1218  func getCapabilities(v uint16) (c LLDPCapabilities) {
  1219  	c.Other = (v&LLDPCapsOther > 0)
  1220  	c.Repeater = (v&LLDPCapsRepeater > 0)
  1221  	c.Bridge = (v&LLDPCapsBridge > 0)
  1222  	c.WLANAP = (v&LLDPCapsWLANAP > 0)
  1223  	c.Router = (v&LLDPCapsRouter > 0)
  1224  	c.Phone = (v&LLDPCapsPhone > 0)
  1225  	c.DocSis = (v&LLDPCapsDocSis > 0)
  1226  	c.StationOnly = (v&LLDPCapsStationOnly > 0)
  1227  	c.CVLAN = (v&LLDPCapsCVLAN > 0)
  1228  	c.SVLAN = (v&LLDPCapsSVLAN > 0)
  1229  	c.TMPR = (v&LLDPCapsTmpr > 0)
  1230  	return
  1231  }
  1232  
  1233  func getEVBCapabilities(v uint16) (c LLDPEVBCapabilities) {
  1234  	c.StandardBridging = (v & LLDPEVBCapsSTD) > 0
  1235  	c.StandardBridging = (v & LLDPEVBCapsSTD) > 0
  1236  	c.ReflectiveRelay = (v & LLDPEVBCapsRR) > 0
  1237  	c.RetransmissionTimerExponent = (v & LLDPEVBCapsRTE) > 0
  1238  	c.EdgeControlProtocol = (v & LLDPEVBCapsECP) > 0
  1239  	c.VSIDiscoveryProtocol = (v & LLDPEVBCapsVDP) > 0
  1240  	return
  1241  }
  1242  
  1243  func (t LLDPTLVType) String() (s string) {
  1244  	switch t {
  1245  	case LLDPTLVEnd:
  1246  		s = "TLV End"
  1247  	case LLDPTLVChassisID:
  1248  		s = "Chassis ID"
  1249  	case LLDPTLVPortID:
  1250  		s = "Port ID"
  1251  	case LLDPTLVTTL:
  1252  		s = "TTL"
  1253  	case LLDPTLVPortDescription:
  1254  		s = "Port Description"
  1255  	case LLDPTLVSysName:
  1256  		s = "System Name"
  1257  	case LLDPTLVSysDescription:
  1258  		s = "System Description"
  1259  	case LLDPTLVSysCapabilities:
  1260  		s = "System Capabilities"
  1261  	case LLDPTLVMgmtAddress:
  1262  		s = "Management Address"
  1263  	case LLDPTLVOrgSpecific:
  1264  		s = "Organisation Specific"
  1265  	default:
  1266  		s = "Unknown"
  1267  	}
  1268  	return
  1269  }
  1270  
  1271  func (t LLDPChassisIDSubType) String() (s string) {
  1272  	switch t {
  1273  	case LLDPChassisIDSubTypeReserved:
  1274  		s = "Reserved"
  1275  	case LLDPChassisIDSubTypeChassisComp:
  1276  		s = "Chassis Component"
  1277  	case LLDPChassisIDSubtypeIfaceAlias:
  1278  		s = "Interface Alias"
  1279  	case LLDPChassisIDSubTypePortComp:
  1280  		s = "Port Component"
  1281  	case LLDPChassisIDSubTypeMACAddr:
  1282  		s = "MAC Address"
  1283  	case LLDPChassisIDSubTypeNetworkAddr:
  1284  		s = "Network Address"
  1285  	case LLDPChassisIDSubtypeIfaceName:
  1286  		s = "Interface Name"
  1287  	case LLDPChassisIDSubTypeLocal:
  1288  		s = "Local"
  1289  	default:
  1290  		s = "Unknown"
  1291  	}
  1292  	return
  1293  }
  1294  
  1295  func (t LLDPPortIDSubType) String() (s string) {
  1296  	switch t {
  1297  	case LLDPPortIDSubtypeReserved:
  1298  		s = "Reserved"
  1299  	case LLDPPortIDSubtypeIfaceAlias:
  1300  		s = "Interface Alias"
  1301  	case LLDPPortIDSubtypePortComp:
  1302  		s = "Port Component"
  1303  	case LLDPPortIDSubtypeMACAddr:
  1304  		s = "MAC Address"
  1305  	case LLDPPortIDSubtypeNetworkAddr:
  1306  		s = "Network Address"
  1307  	case LLDPPortIDSubtypeIfaceName:
  1308  		s = "Interface Name"
  1309  	case LLDPPortIDSubtypeAgentCircuitID:
  1310  		s = "Agent Circuit ID"
  1311  	case LLDPPortIDSubtypeLocal:
  1312  		s = "Local"
  1313  	default:
  1314  		s = "Unknown"
  1315  	}
  1316  	return
  1317  }
  1318  
  1319  func (t IANAAddressFamily) String() (s string) {
  1320  	switch t {
  1321  	case IANAAddressFamilyReserved:
  1322  		s = "Reserved"
  1323  	case IANAAddressFamilyIPV4:
  1324  		s = "IPv4"
  1325  	case IANAAddressFamilyIPV6:
  1326  		s = "IPv6"
  1327  	case IANAAddressFamilyNSAP:
  1328  		s = "NSAP"
  1329  	case IANAAddressFamilyHDLC:
  1330  		s = "HDLC"
  1331  	case IANAAddressFamilyBBN1822:
  1332  		s = "BBN 1822"
  1333  	case IANAAddressFamily802:
  1334  		s = "802 media plus Ethernet 'canonical format'"
  1335  	case IANAAddressFamilyE163:
  1336  		s = "E.163"
  1337  	case IANAAddressFamilyE164:
  1338  		s = "E.164 (SMDS, Frame Relay, ATM)"
  1339  	case IANAAddressFamilyF69:
  1340  		s = "F.69 (Telex)"
  1341  	case IANAAddressFamilyX121:
  1342  		s = "X.121, X.25, Frame Relay"
  1343  	case IANAAddressFamilyIPX:
  1344  		s = "IPX"
  1345  	case IANAAddressFamilyAtalk:
  1346  		s = "Appletalk"
  1347  	case IANAAddressFamilyDecnet:
  1348  		s = "Decnet IV"
  1349  	case IANAAddressFamilyBanyan:
  1350  		s = "Banyan Vines"
  1351  	case IANAAddressFamilyE164NSAP:
  1352  		s = "E.164 with NSAP format subaddress"
  1353  	case IANAAddressFamilyDNS:
  1354  		s = "DNS"
  1355  	case IANAAddressFamilyDistname:
  1356  		s = "Distinguished Name"
  1357  	case IANAAddressFamilyASNumber:
  1358  		s = "AS Number"
  1359  	case IANAAddressFamilyXTPIPV4:
  1360  		s = "XTP over IP version 4"
  1361  	case IANAAddressFamilyXTPIPV6:
  1362  		s = "XTP over IP version 6"
  1363  	case IANAAddressFamilyXTP:
  1364  		s = "XTP native mode XTP"
  1365  	case IANAAddressFamilyFcWWPN:
  1366  		s = "Fibre Channel World-Wide Port Name"
  1367  	case IANAAddressFamilyFcWWNN:
  1368  		s = "Fibre Channel World-Wide Node Name"
  1369  	case IANAAddressFamilyGWID:
  1370  		s = "GWID"
  1371  	case IANAAddressFamilyL2VPN:
  1372  		s = "AFI for Layer 2 VPN"
  1373  	default:
  1374  		s = "Unknown"
  1375  	}
  1376  	return
  1377  }
  1378  
  1379  func (t LLDPInterfaceSubtype) String() (s string) {
  1380  	switch t {
  1381  	case LLDPInterfaceSubtypeUnknown:
  1382  		s = "Unknown"
  1383  	case LLDPInterfaceSubtypeifIndex:
  1384  		s = "IfIndex"
  1385  	case LLDPInterfaceSubtypeSysPort:
  1386  		s = "System Port Number"
  1387  	default:
  1388  		s = "Unknown"
  1389  	}
  1390  	return
  1391  }
  1392  
  1393  func (t LLDPPowerType) String() (s string) {
  1394  	switch t {
  1395  	case 0:
  1396  		s = "Type 2 PSE Device"
  1397  	case 1:
  1398  		s = "Type 2 PD Device"
  1399  	case 2:
  1400  		s = "Type 1 PSE Device"
  1401  	case 3:
  1402  		s = "Type 1 PD Device"
  1403  	default:
  1404  		s = "Unknown"
  1405  	}
  1406  	return
  1407  }
  1408  
  1409  func (t LLDPPowerSource) String() (s string) {
  1410  	switch t {
  1411  	// PD Device
  1412  	case 0:
  1413  		s = "Unknown"
  1414  	case 1:
  1415  		s = "PSE"
  1416  	case 2:
  1417  		s = "Local"
  1418  	case 3:
  1419  		s = "PSE and Local"
  1420  	// PSE Device  (Actual value  + 128)
  1421  	case 128:
  1422  		s = "Unknown"
  1423  	case 129:
  1424  		s = "Primary Power Source"
  1425  	case 130:
  1426  		s = "Backup Power Source"
  1427  	default:
  1428  		s = "Unknown"
  1429  	}
  1430  	return
  1431  }
  1432  
  1433  func (t LLDPPowerPriority) String() (s string) {
  1434  	switch t {
  1435  	case 0:
  1436  		s = "Unknown"
  1437  	case 1:
  1438  		s = "Critical"
  1439  	case 2:
  1440  		s = "High"
  1441  	case 3:
  1442  		s = "Low"
  1443  	default:
  1444  		s = "Unknown"
  1445  	}
  1446  	return
  1447  }
  1448  
  1449  func (t LLDPMediaSubtype) String() (s string) {
  1450  	switch t {
  1451  	case LLDPMediaTypeCapabilities:
  1452  		s = "Media Capabilities"
  1453  	case LLDPMediaTypeNetwork:
  1454  		s = "Network Policy"
  1455  	case LLDPMediaTypeLocation:
  1456  		s = "Location Identification"
  1457  	case LLDPMediaTypePower:
  1458  		s = "Extended Power-via-MDI"
  1459  	case LLDPMediaTypeHardware:
  1460  		s = "Hardware Revision"
  1461  	case LLDPMediaTypeFirmware:
  1462  		s = "Firmware Revision"
  1463  	case LLDPMediaTypeSoftware:
  1464  		s = "Software Revision"
  1465  	case LLDPMediaTypeSerial:
  1466  		s = "Serial Number"
  1467  	case LLDPMediaTypeManufacturer:
  1468  		s = "Manufacturer"
  1469  	case LLDPMediaTypeModel:
  1470  		s = "Model"
  1471  	case LLDPMediaTypeAssetID:
  1472  		s = "Asset ID"
  1473  	default:
  1474  		s = "Unknown"
  1475  	}
  1476  	return
  1477  }
  1478  
  1479  func (t LLDPMediaClass) String() (s string) {
  1480  	switch t {
  1481  	case LLDPMediaClassUndefined:
  1482  		s = "Undefined"
  1483  	case LLDPMediaClassEndpointI:
  1484  		s = "Endpoint Class I"
  1485  	case LLDPMediaClassEndpointII:
  1486  		s = "Endpoint Class II"
  1487  	case LLDPMediaClassEndpointIII:
  1488  		s = "Endpoint Class III"
  1489  	case LLDPMediaClassNetwork:
  1490  		s = "Network Connectivity"
  1491  	default:
  1492  		s = "Unknown"
  1493  	}
  1494  	return
  1495  }
  1496  
  1497  func (t LLDPApplicationType) String() (s string) {
  1498  	switch t {
  1499  	case LLDPAppTypeReserved:
  1500  		s = "Reserved"
  1501  	case LLDPAppTypeVoice:
  1502  		s = "Voice"
  1503  	case LLDPappTypeVoiceSignaling:
  1504  		s = "Voice Signaling"
  1505  	case LLDPappTypeGuestVoice:
  1506  		s = "Guest Voice"
  1507  	case LLDPappTypeGuestVoiceSignaling:
  1508  		s = "Guest Voice Signaling"
  1509  	case LLDPappTypeSoftphoneVoice:
  1510  		s = "Softphone Voice"
  1511  	case LLDPappTypeVideoConferencing:
  1512  		s = "Video Conferencing"
  1513  	case LLDPappTypeStreamingVideo:
  1514  		s = "Streaming Video"
  1515  	case LLDPappTypeVideoSignaling:
  1516  		s = "Video Signaling"
  1517  	default:
  1518  		s = "Unknown"
  1519  	}
  1520  	return
  1521  }
  1522  
  1523  func (t LLDPLocationFormat) String() (s string) {
  1524  	switch t {
  1525  	case LLDPLocationFormatInvalid:
  1526  		s = "Invalid"
  1527  	case LLDPLocationFormatCoordinate:
  1528  		s = "Coordinate-based LCI"
  1529  	case LLDPLocationFormatAddress:
  1530  		s = "Address-based LCO"
  1531  	case LLDPLocationFormatECS:
  1532  		s = "ECS ELIN"
  1533  	default:
  1534  		s = "Unknown"
  1535  	}
  1536  	return
  1537  }
  1538  
  1539  func (t LLDPLocationAddressType) String() (s string) {
  1540  	switch t {
  1541  	case LLDPLocationAddressTypeLanguage:
  1542  		s = "Language"
  1543  	case LLDPLocationAddressTypeNational:
  1544  		s = "National subdivisions (province, state, etc)"
  1545  	case LLDPLocationAddressTypeCounty:
  1546  		s = "County, parish, district"
  1547  	case LLDPLocationAddressTypeCity:
  1548  		s = "City, township"
  1549  	case LLDPLocationAddressTypeCityDivision:
  1550  		s = "City division, borough, ward"
  1551  	case LLDPLocationAddressTypeNeighborhood:
  1552  		s = "Neighborhood, block"
  1553  	case LLDPLocationAddressTypeStreet:
  1554  		s = "Street"
  1555  	case LLDPLocationAddressTypeLeadingStreet:
  1556  		s = "Leading street direction"
  1557  	case LLDPLocationAddressTypeTrailingStreet:
  1558  		s = "Trailing street suffix"
  1559  	case LLDPLocationAddressTypeStreetSuffix:
  1560  		s = "Street suffix"
  1561  	case LLDPLocationAddressTypeHouseNum:
  1562  		s = "House number"
  1563  	case LLDPLocationAddressTypeHouseSuffix:
  1564  		s = "House number suffix"
  1565  	case LLDPLocationAddressTypeLandmark:
  1566  		s = "Landmark or vanity address"
  1567  	case LLDPLocationAddressTypeAdditional:
  1568  		s = "Additional location information"
  1569  	case LLDPLocationAddressTypeName:
  1570  		s = "Name"
  1571  	case LLDPLocationAddressTypePostal:
  1572  		s = "Postal/ZIP code"
  1573  	case LLDPLocationAddressTypeBuilding:
  1574  		s = "Building"
  1575  	case LLDPLocationAddressTypeUnit:
  1576  		s = "Unit"
  1577  	case LLDPLocationAddressTypeFloor:
  1578  		s = "Floor"
  1579  	case LLDPLocationAddressTypeRoom:
  1580  		s = "Room number"
  1581  	case LLDPLocationAddressTypePlace:
  1582  		s = "Place type"
  1583  	case LLDPLocationAddressTypeScript:
  1584  		s = "Script"
  1585  	default:
  1586  		s = "Unknown"
  1587  	}
  1588  	return
  1589  }
  1590  
  1591  func checkLLDPTLVLen(v LinkLayerDiscoveryValue, l int) (err error) {
  1592  	if len(v.Value) < l {
  1593  		err = fmt.Errorf("Invalid TLV %v length %d (wanted mimimum %v", v.Type, len(v.Value), l)
  1594  	}
  1595  	return
  1596  }
  1597  
  1598  func checkLLDPOrgSpecificLen(o LLDPOrgSpecificTLV, l int) (err error) {
  1599  	if len(o.Info) < l {
  1600  		err = fmt.Errorf("Invalid Org Specific TLV %v length %d (wanted minimum %v)", o.SubType, len(o.Info), l)
  1601  	}
  1602  	return
  1603  }