You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
layer2 announcer not work fine When use metallb in k8s ipv6 network.
speaker can announce vip ndp info success when the globalunicat ipv6 address is the first addres of the intreface, if the ipv6 globalunicat ipv6 address is not the first address, speak will get a error: "ipv6-icmp bind: cannot assign requested address" ,because speaker use the link-local address as the source IPv6 address for NDP communications. the os will refuse this op.
finally,the real ipv6 interface can't be the partner of the map “keepNDP“,init failed
of course,there is other problem in internal/layer2/announcer.go
send arp package to interface which only have ipv6 address
send ndp package to interface which only have ipv4 address
To Reproduce
config ipv6 for os
install k8s
install metallb
keep ipv6 address is not the first ipaddress of the interface(The first one from the bottom up)
View the metallb speaker log
Expected Behavior
only announce arp to interface which only have ipv4address
only announce ndp to interface which only have ipv6address
announce arp and ndp to interface which have dualstack address
send ndp package use globalunicat address as the source IPv6 address for NDP communications.
Additional Context
code Analysis
--------------------internal/layer2/announcer.go------
if ifi.Flags&net.FlagBroadcast != 0 { // ---> only use broadcast can't distinguish interface who should use the ARP or NDP
keepARP[ifi.Index] = true
}
for _, a := range addrs {
ipaddr, ok := a.(*net.IPNet)
if !ok {
continue
}
if ipaddr.IP.To4() != nil || !ipaddr.IP.IsLinkLocalUnicast() { // --> Linux usually config a localunicat ipv6 address for interface, so this interface also will be the keepNDP item also it only config a ipv4 address.
continue
}
keepNDP[ifi.Index] = true
break
}
-----------------------internal/layer2/ndp..go----------------------------------------
func newNDPResponder(logger log.Logger, ifi *net.Interface, ann announceFunc) (*ndpResponder, error) {
// Use link-local address as the source IPv6 address for NDP communications.
conn, _, err := ndp.Dial(ifi, ndp.LinkLocal) // ------> LinkLocal raw6 listen op is not allowed by all os.
if err != nil {
return nil, fmt.Errorf("creating NDP responder for %q: %s", ifi.Name, err)
}
ret := &ndpResponder{
logger: logger,
intf: ifi.Name,
hardwareAddr: ifi.HardwareAddr,
conn: conn,
closed: make(chan struct{}),
announce: ann,
solicitedNodeGroups: map[string]int64{},
}
go ret.run()
return ret, nil
MetalLB Version
all
Deployment method
Operator
Main CNI
cilium
Kubernetes Version
v1.28.12
Cluster Distribution
No response
Describe the bug
layer2 announcer not work fine When use metallb in k8s ipv6 network.
speaker can announce vip ndp info success when the globalunicat ipv6 address is the first addres of the intreface, if the ipv6 globalunicat ipv6 address is not the first address, speak will get a error: "ipv6-icmp bind: cannot assign requested address" ,because speaker use the link-local address as the source IPv6 address for NDP communications. the os will refuse this op.
finally,the real ipv6 interface can't be the partner of the map “keepNDP“,init failed
of course,there is other problem in internal/layer2/announcer.go
To Reproduce
Expected Behavior
Additional Context
code Analysis
--------------------internal/layer2/announcer.go------
if ifi.Flags&net.FlagBroadcast != 0 { // ---> only use broadcast can't distinguish interface who should use the ARP or NDP
keepARP[ifi.Index] = true
}
-----------------------internal/layer2/ndp..go----------------------------------------
func newNDPResponder(logger log.Logger, ifi *net.Interface, ann announceFunc) (*ndpResponder, error) {
// Use link-local address as the source IPv6 address for NDP communications.
conn, _, err := ndp.Dial(ifi, ndp.LinkLocal) // ------> LinkLocal raw6 listen op is not allowed by all os.
if err != nil {
return nil, fmt.Errorf("creating NDP responder for %q: %s", ifi.Name, err)
}
}
so, i changed the source code
-------------------internal/layer2/announcer.go------
-----------------------internal/layer2/ndp..go----------------------------------------
func newNDPResponder(logger log.Logger, ifi *net.Interface, ann announceFunc) (*ndpResponder, error) {
// Use link-local address as the source IPv6 address for NDP communications.
conn, _, err := ndp.Dial(ifi, ndp.Global)
........
}
Except the code change,also add a config for the metallb operator values.json to filter some interface.
ps: i can't found this config document in the metallb website ^_^
configInline: |
announcedInterfacesToExclude:
I've read and agree with the following
I've read and agree with the following
The text was updated successfully, but these errors were encountered: