|
|
@@ -157,57 +157,85 @@ func (b *Builder) Build() models.TopologyGraph {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 策略3b: MAC前缀匹配已禁用 - 同品牌设备MAC前缀相同,极易产生误匹配
|
|
|
- // 如果需要连接,请使用精确MAC匹配或确保邻居设备在设备列表中
|
|
|
- if false && targetIP == "" && neighbor.RemoteMAC != "" {
|
|
|
- neighborMACPrefix := getMACPrefix(neighbor.RemoteMAC)
|
|
|
- fmt.Printf(" ⚠ MAC prefix match disabled (too unreliable): %s (prefix: %s)\n", neighbor.RemoteMAC, neighborMACPrefix)
|
|
|
- }
|
|
|
+ // 策略3b: MAC前缀匹配(使用12字符前缀 - 更精确)
|
|
|
+ // 同品牌设备虽然4字符前缀相同,但12字符前缀通常不同
|
|
|
+ if targetIP == "" && neighbor.RemoteMAC != "" {
|
|
|
+ // 使用12字符前缀(例如:642f-c7e0-03)
|
|
|
+ macPrefix := ""
|
|
|
+ if len(neighbor.RemoteMAC) >= 12 {
|
|
|
+ macPrefix = neighbor.RemoteMAC[:12]
|
|
|
+ } else {
|
|
|
+ macPrefix = neighbor.RemoteMAC
|
|
|
+ }
|
|
|
|
|
|
- // 策略3c: LLDP对称性匹配(改进 - 需要双向验证)
|
|
|
- // 设备A的接口X连接到设备B的接口Y
|
|
|
- // 同时设备B的接口Y也应该连接到设备A的接口X
|
|
|
- if targetIP == "" && neighbor.RemoteMAC != "" && neighbor.RemoteInterface != "" {
|
|
|
- fmt.Printf(" Trying LLDP symmetric match: looking for device with interface %s\n", neighbor.RemoteInterface)
|
|
|
+ fmt.Printf(" Trying MAC prefix match (12 chars): %s (prefix: %s)\n", neighbor.RemoteMAC, macPrefix)
|
|
|
+
|
|
|
+ var matchedDevices []string
|
|
|
|
|
|
for _, d := range b.devices {
|
|
|
if d.IP == device.IP {
|
|
|
continue // 跳过自己
|
|
|
}
|
|
|
|
|
|
- // 检查设备d是否有这个接口
|
|
|
- hasInterface := false
|
|
|
- for _, iface := range d.Interfaces {
|
|
|
- if iface.Name == neighbor.RemoteInterface {
|
|
|
- hasInterface = true
|
|
|
- break
|
|
|
+ // 检查设备d的MAC地址是否有匹配的前缀
|
|
|
+ matchingMACs := 0
|
|
|
+ for _, mac := range d.MACAddresses {
|
|
|
+ if len(mac) >= 12 && mac[:12] == macPrefix {
|
|
|
+ matchingMACs++
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if !hasInterface {
|
|
|
- continue
|
|
|
+ if matchingMACs >= 3 {
|
|
|
+ matchedDevices = append(matchedDevices, d.IP)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 只有唯一匹配时才建立连接
|
|
|
+ if len(matchedDevices) == 1 {
|
|
|
+ targetIP = matchedDevices[0]
|
|
|
+ matchMethod = fmt.Sprintf("MAC-prefix-12(%s)", macPrefix)
|
|
|
+ fmt.Printf(" ✓ Matched by MAC prefix-12 (unique): %s -> %s\n", neighbor.RemoteMAC, targetIP)
|
|
|
+ } else if len(matchedDevices) > 1 {
|
|
|
+ fmt.Printf(" ✗ Ambiguous MAC prefix-12 match: %s matched %v\n", macPrefix, matchedDevices)
|
|
|
+ } else {
|
|
|
+ fmt.Printf(" ✗ No device matches MAC prefix-12 %s\n", macPrefix)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 策略3c: LLDP接口匹配(改进 - 单向但要求唯一性)
|
|
|
+ // 如果设备A的LLDP信息显示它连接到接口Y
|
|
|
+ // 而设备B有接口Y,则A连接到B
|
|
|
+ // 但如果有多个设备都有接口Y,则不匹配(避免歧义)
|
|
|
+ if targetIP == "" && neighbor.RemoteMAC != "" && neighbor.RemoteInterface != "" {
|
|
|
+ fmt.Printf(" Trying LLDP interface match: looking for device with interface %s\n", neighbor.RemoteInterface)
|
|
|
+
|
|
|
+ var matchedDevices []string
|
|
|
+
|
|
|
+ for _, d := range b.devices {
|
|
|
+ if d.IP == device.IP {
|
|
|
+ continue // 跳过自己
|
|
|
}
|
|
|
|
|
|
- // 双向验证:检查设备d的邻居信息中,这个接口是否连接回当前设备
|
|
|
- hasReverseLink := false
|
|
|
- for _, dNeighbor := range d.Neighbors {
|
|
|
- if dNeighbor.RemoteInterface == neighbor.LocalInterface && dNeighbor.LocalInterface == neighbor.RemoteInterface {
|
|
|
- hasReverseLink = true
|
|
|
+ // 检查设备d是否有这个接口
|
|
|
+ for _, iface := range d.Interfaces {
|
|
|
+ if iface.Name == neighbor.RemoteInterface {
|
|
|
+ matchedDevices = append(matchedDevices, d.IP)
|
|
|
break
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- if hasReverseLink {
|
|
|
- // 双向验证通过!
|
|
|
- targetIP = d.IP
|
|
|
- matchMethod = fmt.Sprintf("LLDP-symmetric(%s<->%s)", neighbor.LocalInterface, neighbor.RemoteInterface)
|
|
|
- fmt.Printf(" ✓ Matched by LLDP symmetric (bidirectional): %s %s <-> %s %s -> %s\n",
|
|
|
- device.IP, neighbor.LocalInterface, d.IP, neighbor.RemoteInterface, targetIP)
|
|
|
- break
|
|
|
- } else {
|
|
|
- fmt.Printf(" ✗ Device %s has interface %s but no reverse link to %s %s\n",
|
|
|
- d.IP, neighbor.RemoteInterface, device.IP, neighbor.LocalInterface)
|
|
|
- }
|
|
|
+ // 只有唯一匹配时才建立连接
|
|
|
+ if len(matchedDevices) == 1 {
|
|
|
+ targetIP = matchedDevices[0]
|
|
|
+ matchMethod = fmt.Sprintf("LLDP-interface(%s->%s)", neighbor.LocalInterface, neighbor.RemoteInterface)
|
|
|
+ fmt.Printf(" ✓ Matched by LLDP interface (unique): %s %s -> %s %s\n",
|
|
|
+ device.IP, neighbor.LocalInterface, targetIP, neighbor.RemoteInterface)
|
|
|
+ } else if len(matchedDevices) > 1 {
|
|
|
+ fmt.Printf(" ✗ Ambiguous: multiple devices have interface %s: %v\n",
|
|
|
+ neighbor.RemoteInterface, matchedDevices)
|
|
|
+ } else {
|
|
|
+ fmt.Printf(" ✗ No device found with interface %s\n", neighbor.RemoteInterface)
|
|
|
}
|
|
|
}
|
|
|
|