diff --git a/link_linux.go b/link_linux.go index e5354b04..202c2b74 100644 --- a/link_linux.go +++ b/link_linux.go @@ -2461,6 +2461,14 @@ func (h *Handle) LinkSetBrProxyArpWiFi(link Link, mode bool) error { return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP_WIFI) } +func LinkSetBrNeighSuppress(link Link, mode bool) error { + return pkgHandle.LinkSetBrNeighSuppress(link, mode) +} + +func (h *Handle) LinkSetBrNeighSuppress(link Link, mode bool) error { + return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_NEIGH_SUPPRESS) +} + func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error { base := link.Attrs() h.ensureIndex(base) diff --git a/protinfo.go b/protinfo.go index 91ea2691..0163cba3 100644 --- a/protinfo.go +++ b/protinfo.go @@ -6,15 +6,16 @@ import ( // Protinfo represents bridge flags from netlink. type Protinfo struct { - Hairpin bool - Guard bool - FastLeave bool - RootBlock bool - Learning bool - Flood bool - ProxyArp bool - ProxyArpWiFi bool - Isolated bool + Hairpin bool + Guard bool + FastLeave bool + RootBlock bool + Learning bool + Flood bool + ProxyArp bool + ProxyArpWiFi bool + Isolated bool + NeighSuppress bool } // String returns a list of enabled flags @@ -51,6 +52,9 @@ func (prot *Protinfo) String() string { if prot.Isolated { boolStrings = append(boolStrings, "Isolated") } + if prot.NeighSuppress { + boolStrings = append(boolStrings, "NeighSuppress") + } return strings.Join(boolStrings, " ") } diff --git a/protinfo_linux.go b/protinfo_linux.go index bfd1b628..1ba25d3c 100644 --- a/protinfo_linux.go +++ b/protinfo_linux.go @@ -70,6 +70,8 @@ func parseProtinfo(infos []syscall.NetlinkRouteAttr) (pi Protinfo) { pi.ProxyArpWiFi = byteToBool(info.Value[0]) case nl.IFLA_BRPORT_ISOLATED: pi.Isolated = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_NEIGH_SUPPRESS: + pi.NeighSuppress = byteToBool(info.Value[0]) } } return diff --git a/protinfo_test.go b/protinfo_test.go index a2909d4f..7e9561c0 100644 --- a/protinfo_test.go +++ b/protinfo_test.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package netlink @@ -83,6 +84,9 @@ func TestProtinfo(t *testing.T) { if pi1.Flood != oldpi1.Flood { t.Fatalf("Flood field was changed for %s but shouldn't", iface1.Name) } + if pi1.NeighSuppress != oldpi1.NeighSuppress { + t.Fatalf("NeighSuppress field was changed for %s but shouldn't", iface1.Name) + } if err := LinkSetGuard(iface2, true); err != nil { t.Fatal(err) @@ -118,6 +122,9 @@ func TestProtinfo(t *testing.T) { if pi2.Flood != oldpi2.Flood { t.Fatalf("Flood field was changed for %s but shouldn't", iface2.Name) } + if pi2.NeighSuppress != oldpi2.NeighSuppress { + t.Fatalf("NeighSuppress field was changed for %s but shouldn't", iface2.Name) + } if err := LinkSetHairpin(iface3, true); err == nil || err.Error() != "operation not supported" { t.Fatalf("Set protinfo attrs for link without master is not supported, but err: %s", err) @@ -162,6 +169,20 @@ func TestProtinfo(t *testing.T) { t.Fatalf("Flood field was changed for %s but shouldn't", iface4.Name) } + // BR_NEIGH_SUPPRESS added on 4.15 + minKernelRequired(t, 4, 15) + + if err := LinkSetBrNeighSuppress(iface1, true); err != nil { + t.Fatal(err) + } + pi1, err = LinkGetProtinfo(iface1) + if err != nil { + t.Fatal(err) + } + if !pi1.NeighSuppress { + t.Fatalf("NeighSuppress is not enabled for %s but should", iface1.Name) + } + // Setting kernel requirement for next tests which require BRPORT_ISOLATED minKernelRequired(t, 4, 18)