Skip to content

Commit 15484f8

Browse files
committed
fix(ui): use source in LLDP neighbor key
1 parent 8957a65 commit 15484f8

File tree

2 files changed

+133
-1
lines changed

2 files changed

+133
-1
lines changed

internal/lldp/tlv.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package lldp
2+
3+
import (
4+
"encoding/binary"
5+
"fmt"
6+
"net"
7+
8+
"github.com/google/gopacket/layers"
9+
)
10+
11+
var (
12+
capabilityMap = map[string]uint16{
13+
"other": layers.LLDPCapsOther,
14+
"repeater": layers.LLDPCapsRepeater,
15+
"bridge": layers.LLDPCapsBridge,
16+
"wlanap": layers.LLDPCapsWLANAP,
17+
"router": layers.LLDPCapsRouter,
18+
"phone": layers.LLDPCapsPhone,
19+
"docsis": layers.LLDPCapsDocSis,
20+
"station_only": layers.LLDPCapsStationOnly,
21+
"cvlan": layers.LLDPCapsCVLAN,
22+
"svlan": layers.LLDPCapsSVLAN,
23+
"tmpr": layers.LLDPCapsTmpr,
24+
}
25+
)
26+
27+
func tlvMgmtAddressToBytes(m *layers.LLDPMgmtAddress) []byte {
28+
var b []byte
29+
b = append(b, byte(len(m.Address))+1) // TLV Length
30+
b = append(b, byte(m.Subtype)) // Address Subtype
31+
b = append(b, m.Address...) // Address
32+
b = append(b, byte(m.InterfaceSubtype)) // Interface Subtype
33+
34+
ifIndex := make([]byte, 4) // 4 bytes for the interface number
35+
binary.BigEndian.PutUint32(ifIndex, m.InterfaceNumber)
36+
b = append(b, ifIndex...)
37+
38+
b = append(b, 0) // OID type
39+
return b
40+
}
41+
42+
func tlvMgmtAddress(m *layers.LLDPMgmtAddress) layers.LinkLayerDiscoveryValue {
43+
return layers.LinkLayerDiscoveryValue{
44+
Type: layers.LLDPTLVMgmtAddress,
45+
Value: tlvMgmtAddressToBytes(m),
46+
Length: uint16(len(tlvMgmtAddressToBytes(m))),
47+
}
48+
}
49+
50+
// if err := checkLLDPTLVLen(v, 9); err != nil {
51+
// return err
52+
// }
53+
// mlen := v.Value[0]
54+
// if err := checkLLDPTLVLen(v, int(mlen+7)); err != nil {
55+
// return err
56+
// }
57+
// info.MgmtAddress.Subtype = IANAAddressFamily(v.Value[1])
58+
// info.MgmtAddress.Address = v.Value[2 : mlen+1]
59+
// info.MgmtAddress.InterfaceSubtype = LLDPInterfaceSubtype(v.Value[mlen+1])
60+
// info.MgmtAddress.InterfaceNumber = binary.BigEndian.Uint32(v.Value[mlen+2 : mlen+6])
61+
// olen := v.Value[mlen+6]
62+
// if err := checkLLDPTLVLen(v, int(mlen+7+olen)); err != nil {
63+
// return err
64+
// }
65+
// info.MgmtAddress.OID = string(v.Value[mlen+7 : mlen+7+olen])
66+
67+
func checkLLDPTLVLen(v layers.LinkLayerDiscoveryValue, l int) (err error) {
68+
if len(v.Value) < l {
69+
err = fmt.Errorf("invalid TLV %v length %d (wanted mimimum %v)", v.Type, len(v.Value), l)
70+
}
71+
return
72+
}
73+
74+
// parseTlvMgmtAddress parses the Management Address TLV and returns the Management Address
75+
// structure.
76+
// we don't parse the OID here, as it's not needed for the neighbor cache
77+
func parseTlvMgmtAddress(v layers.LinkLayerDiscoveryValue) *layers.LLDPMgmtAddress {
78+
if err := checkLLDPTLVLen(v, 9); err != nil {
79+
return nil
80+
}
81+
82+
mlen := v.Value[0]
83+
if err := checkLLDPTLVLen(v, int(mlen+7)); err != nil {
84+
return nil
85+
}
86+
87+
return &layers.LLDPMgmtAddress{
88+
Subtype: layers.IANAAddressFamily(v.Value[1]),
89+
Address: v.Value[2 : mlen+1],
90+
InterfaceSubtype: layers.LLDPInterfaceSubtype(v.Value[mlen+1]),
91+
InterfaceNumber: binary.BigEndian.Uint32(v.Value[mlen+2 : mlen+6]),
92+
}
93+
}
94+
95+
func lldpMgmtAddressToSerializable(m *layers.LLDPMgmtAddress) ManagementAddress {
96+
var addrString string
97+
switch m.Subtype {
98+
case layers.IANAAddressFamilyIPV4:
99+
addrString = net.IP(m.Address).String()
100+
case layers.IANAAddressFamilyIPV6:
101+
addrString = net.IP(m.Address).String()
102+
default:
103+
addrString = string(m.Address)
104+
}
105+
106+
return ManagementAddress{
107+
AddressFamily: m.Subtype.String(),
108+
Address: addrString,
109+
InterfaceSubtype: m.InterfaceSubtype.String(),
110+
InterfaceNumber: m.InterfaceNumber,
111+
}
112+
}
113+
114+
func tlvStringValue(tlvType layers.LLDPTLVType, value string) layers.LinkLayerDiscoveryValue {
115+
return layers.LinkLayerDiscoveryValue{
116+
Type: tlvType,
117+
Value: []byte(value),
118+
Length: uint16(len(value)),
119+
}
120+
}
121+
122+
func toLLDPCapabilitiesBytes(capabilities []string) uint16 {
123+
r := uint16(0)
124+
for _, capability := range capabilities {
125+
mask, ok := capabilityMap[capability]
126+
if ok {
127+
r |= mask
128+
}
129+
}
130+
return r
131+
}

ui/src/components/LLDPNeighborsCard.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ export default function LLDPNeighborsCard({
3737
<div className="space-y-3 pt-2">
3838
{neighbors.map(neighbor => {
3939
const displayName = neighbor.system_name || neighbor.port_description || neighbor.mac;
40-
return <div className="space-y-3" key={neighbor.mac}>
40+
const key = `${neighbor.mac}-${neighbor.source}`;
41+
return <div className="space-y-3" key={key}>
4142
<h4 className="text-sm font-semibold font-mono">{displayName}</h4>
4243
<div
4344
className="rounded-md rounded-l-none border border-slate-500/10 border-l-blue-700/50 bg-white p-4 pl-4 backdrop-blur-sm dark:bg-transparent"

0 commit comments

Comments
 (0)