From d1e684a60b0dd89bde1db6f9c622168460888761 Mon Sep 17 00:00:00 2001 From: dennisafa Date: Thu, 20 May 2021 11:31:37 -0600 Subject: [PATCH] Ability to set multicast attribute on a link --- link.go | 1 + link_linux.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ link_test.go | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) diff --git a/link.go b/link.go index 2e002d69..ca47d05a 100644 --- a/link.go +++ b/link.go @@ -36,6 +36,7 @@ type LinkAttrs struct { Statistics *LinkStatistics Promisc int Allmulti int + Multi int Xdp *LinkXdp EncapType string Protinfo *Protinfo diff --git a/link_linux.go b/link_linux.go index caf30c05..916e7a8b 100644 --- a/link_linux.go +++ b/link_linux.go @@ -182,6 +182,51 @@ func (h *Handle) LinkSetAllmulticastOff(link Link) error { return err } +// LinkSetMulticastOn enables the reception of multicast packets for the link device. +// Equivalent to: `ip link set $link multicast on` +func LinkSetMulticastOn(link Link) error { + return pkgHandle.LinkSetMulticastOn(link) +} + +// LinkSetMulticastOn enables the reception of multicast packets for the link device. +// Equivalent to: `ip link set $link multicast on` +func (h *Handle) LinkSetMulticastOn(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Change = unix.IFF_MULTICAST + msg.Flags = unix.IFF_MULTICAST + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetAllmulticastOff disables the reception of multicast packets for the link device. +// Equivalent to: `ip link set $link multicast off` +func LinkSetMulticastOff(link Link) error { + return pkgHandle.LinkSetMulticastOff(link) +} + +// LinkSetAllmulticastOff disables the reception of multicast packets for the link device. +// Equivalent to: `ip link set $link multicast off` +func (h *Handle) LinkSetMulticastOff(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Change = unix.IFF_MULTICAST + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + func MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error { return pkgHandle.MacvlanMACAddrAdd(link, addr) } @@ -1648,6 +1693,10 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { if msg.Flags&unix.IFF_ALLMULTI != 0 { base.Allmulti = 1 } + if msg.Flags&unix.IFF_MULTICAST != 0 { + base.Multi = 1 + } + var ( link Link stats32 *LinkStatistics32 diff --git a/link_test.go b/link_test.go index 1c9c163b..5c02e107 100644 --- a/link_test.go +++ b/link_test.go @@ -2663,6 +2663,56 @@ func TestLinkSetAllmulticast(t *testing.T) { } } +func TestLinkSetMulticast(t *testing.T) { + tearDown := setUpNetlinkTest(t) + defer tearDown() + + iface := &Veth{LinkAttrs: LinkAttrs{Name: "foo"}, PeerName: "bar"} + if err := LinkAdd(iface); err != nil { + t.Fatal(err) + } + + link, err := LinkByName("foo") + if err != nil { + t.Fatal(err) + } + + if err := LinkSetUp(link); err != nil { + t.Fatal(err) + } + + link, err = LinkByName("foo") + if err != nil { + t.Fatal(err) + } + + if err := LinkSetMulticastOn(link); err != nil { + t.Fatal(err) + } + + link, err = LinkByName("foo") + if err != nil { + t.Fatal(err) + } + + if link.Attrs().Multi != 1 { + t.Fatal("IFF_MULTICAST was not set") + } + + if err := LinkSetMulticastOff(link); err != nil { + t.Fatal(err) + } + + link, err = LinkByName("foo") + if err != nil { + t.Fatal(err) + } + + if link.Attrs().Multi != 0 { + t.Fatal("IFF_MULTICAST is still set") + } +} + func TestLinkSetMacvlanMode(t *testing.T) { tearDown := setUpNetlinkTest(t) defer tearDown()