feat: 优化拓扑匹配策略,使用12字符MAC前缀提高匹配精度
This commit is contained in:
@@ -157,18 +157,59 @@ func (b *Builder) Build() models.TopologyGraph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 策略3b: MAC前缀匹配已禁用 - 同品牌设备MAC前缀相同,极易产生误匹配
|
// 策略3b: MAC前缀匹配(使用12字符前缀 - 更精确)
|
||||||
// 如果需要连接,请使用精确MAC匹配或确保邻居设备在设备列表中
|
// 同品牌设备虽然4字符前缀相同,但12字符前缀通常不同
|
||||||
if false && targetIP == "" && neighbor.RemoteMAC != "" {
|
if targetIP == "" && neighbor.RemoteMAC != "" {
|
||||||
neighborMACPrefix := getMACPrefix(neighbor.RemoteMAC)
|
// 使用12字符前缀(例如:642f-c7e0-03)
|
||||||
fmt.Printf(" ⚠ MAC prefix match disabled (too unreliable): %s (prefix: %s)\n", neighbor.RemoteMAC, neighborMACPrefix)
|
macPrefix := ""
|
||||||
|
if len(neighbor.RemoteMAC) >= 12 {
|
||||||
|
macPrefix = neighbor.RemoteMAC[:12]
|
||||||
|
} else {
|
||||||
|
macPrefix = neighbor.RemoteMAC
|
||||||
}
|
}
|
||||||
|
|
||||||
// 策略3c: LLDP对称性匹配(改进 - 需要双向验证)
|
fmt.Printf(" Trying MAC prefix match (12 chars): %s (prefix: %s)\n", neighbor.RemoteMAC, macPrefix)
|
||||||
// 设备A的接口X连接到设备B的接口Y
|
|
||||||
// 同时设备B的接口Y也应该连接到设备A的接口X
|
var matchedDevices []string
|
||||||
|
|
||||||
|
for _, d := range b.devices {
|
||||||
|
if d.IP == device.IP {
|
||||||
|
continue // 跳过自己
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查设备d的MAC地址是否有匹配的前缀
|
||||||
|
matchingMACs := 0
|
||||||
|
for _, mac := range d.MACAddresses {
|
||||||
|
if len(mac) >= 12 && mac[:12] == macPrefix {
|
||||||
|
matchingMACs++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 != "" {
|
if targetIP == "" && neighbor.RemoteMAC != "" && neighbor.RemoteInterface != "" {
|
||||||
fmt.Printf(" Trying LLDP symmetric match: looking for device with interface %s\n", 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 {
|
for _, d := range b.devices {
|
||||||
if d.IP == device.IP {
|
if d.IP == device.IP {
|
||||||
@@ -176,38 +217,25 @@ func (b *Builder) Build() models.TopologyGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查设备d是否有这个接口
|
// 检查设备d是否有这个接口
|
||||||
hasInterface := false
|
|
||||||
for _, iface := range d.Interfaces {
|
for _, iface := range d.Interfaces {
|
||||||
if iface.Name == neighbor.RemoteInterface {
|
if iface.Name == neighbor.RemoteInterface {
|
||||||
hasInterface = true
|
matchedDevices = append(matchedDevices, d.IP)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hasInterface {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 双向验证:检查设备d的邻居信息中,这个接口是否连接回当前设备
|
// 只有唯一匹配时才建立连接
|
||||||
hasReverseLink := false
|
if len(matchedDevices) == 1 {
|
||||||
for _, dNeighbor := range d.Neighbors {
|
targetIP = matchedDevices[0]
|
||||||
if dNeighbor.RemoteInterface == neighbor.LocalInterface && dNeighbor.LocalInterface == neighbor.RemoteInterface {
|
matchMethod = fmt.Sprintf("LLDP-interface(%s->%s)", neighbor.LocalInterface, neighbor.RemoteInterface)
|
||||||
hasReverseLink = true
|
fmt.Printf(" ✓ Matched by LLDP interface (unique): %s %s -> %s %s\n",
|
||||||
break
|
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)
|
||||||
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 {
|
} else {
|
||||||
fmt.Printf(" ✗ Device %s has interface %s but no reverse link to %s %s\n",
|
fmt.Printf(" ✗ No device found with interface %s\n", neighbor.RemoteInterface)
|
||||||
d.IP, neighbor.RemoteInterface, device.IP, neighbor.LocalInterface)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user