diff --git a/link.go b/link.go index 260542e7..f820cdb6 100644 --- a/link.go +++ b/link.go @@ -318,6 +318,9 @@ type Macvlan struct { // MACAddrs is only populated for Macvlan SOURCE links MACAddrs []net.HardwareAddr + + BCQueueLen uint32 + UsedBCQueueLen uint32 } func (macvlan *Macvlan) Attrs() *LinkAttrs { diff --git a/link_linux.go b/link_linux.go index f4ced224..d713612a 100644 --- a/link_linux.go +++ b/link_linux.go @@ -1733,15 +1733,9 @@ func (h *Handle) linkModify(link Link, flags int) error { data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode))) data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag))) case *Macvlan: - if link.Mode != MACVLAN_MODE_DEFAULT { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode])) - } + addMacvlanAttrs(link, linkInfo) case *Macvtap: - if link.Mode != MACVLAN_MODE_DEFAULT { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode])) - } + addMacvtapAttrs(link, linkInfo) case *Geneve: addGeneveAttrs(link, linkInfo) case *Gretap: @@ -2953,11 +2947,30 @@ func parseIPVtapData(link Link, data []syscall.NetlinkRouteAttr) { } } +func addMacvtapAttrs(macvtap *Macvtap, linkInfo *nl.RtAttr) { + addMacvlanAttrs(&macvtap.Macvlan, linkInfo) +} + func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) { macv := link.(*Macvtap) parseMacvlanData(&macv.Macvlan, data) } +func addMacvlanAttrs(macvlan *Macvlan, linkInfo *nl.RtAttr) { + var data *nl.RtAttr + + if macvlan.Mode != MACVLAN_MODE_DEFAULT || macvlan.BCQueueLen > 0 { + data = linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + } + + if macvlan.Mode != MACVLAN_MODE_DEFAULT { + data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[macvlan.Mode])) + } + if macvlan.BCQueueLen > 0 { + data.AddRtAttr(nl.IFLA_MACVLAN_BC_QUEUE_LEN, nl.Uint32Attr(macvlan.BCQueueLen)) + } +} + func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) { macv := link.(*Macvlan) for _, datum := range data { @@ -2985,6 +2998,10 @@ func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) { for _, macDatum := range macs { macv.MACAddrs = append(macv.MACAddrs, net.HardwareAddr(macDatum.Value[0:6])) } + case nl.IFLA_MACVLAN_BC_QUEUE_LEN: + macv.BCQueueLen = native.Uint32(datum.Value[0:4]) + case nl.IFLA_MACVLAN_BC_QUEUE_LEN_USED: + macv.UsedBCQueueLen = native.Uint32(datum.Value[0:4]) } } } diff --git a/link_test.go b/link_test.go index df09d17e..eb7bd228 100644 --- a/link_test.go +++ b/link_test.go @@ -201,6 +201,16 @@ func testLinkAddDel(t *testing.T, link Link) { if macv.Mode != other.Mode { t.Fatalf("Got unexpected mode: %d, expected: %d", other.Mode, macv.Mode) } + if other.BCQueueLen > 0 || other.UsedBCQueueLen > 0 { + if other.UsedBCQueueLen < other.BCQueueLen { + t.Fatalf("UsedBCQueueLen (%d) is smaller than BCQueueLen (%d)", other.UsedBCQueueLen, other.BCQueueLen) + } + } + if macv.BCQueueLen > 0 { + if macv.BCQueueLen != other.BCQueueLen { + t.Fatalf("BCQueueLen not set correctly: %d, expected: %d", other.BCQueueLen, macv.BCQueueLen) + } + } } if macv, ok := link.(*Macvtap); ok { @@ -211,6 +221,16 @@ func testLinkAddDel(t *testing.T, link Link) { if macv.Mode != other.Mode { t.Fatalf("Got unexpected mode: %d, expected: %d", other.Mode, macv.Mode) } + if other.BCQueueLen > 0 || other.UsedBCQueueLen > 0 { + if other.UsedBCQueueLen < other.BCQueueLen { + t.Fatalf("UsedBCQueueLen (%d) is smaller than BCQueueLen (%d)", other.UsedBCQueueLen, other.BCQueueLen) + } + } + if macv.BCQueueLen > 0 { + if macv.BCQueueLen != other.BCQueueLen { + t.Fatalf("BCQueueLen not set correctly: %d, expected: %d", other.BCQueueLen, macv.BCQueueLen) + } + } } if _, ok := link.(*Vti); ok { @@ -916,6 +936,36 @@ func TestLinkAddDelMacvtap(t *testing.T) { } } +func TestLinkMacvBCQueueLen(t *testing.T) { + minKernelRequired(t, 5, 11) + + tearDown := setUpNetlinkTest(t) + defer tearDown() + + parent := &Dummy{LinkAttrs{Name: "foo"}} + if err := LinkAdd(parent); err != nil { + t.Fatal(err) + } + + testLinkAddDel(t, &Macvlan{ + LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index}, + Mode: MACVLAN_MODE_PRIVATE, + BCQueueLen: 10000, + }) + + testLinkAddDel(t, &Macvtap{ + Macvlan: Macvlan{ + LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index}, + Mode: MACVLAN_MODE_PRIVATE, + BCQueueLen: 10000, + }, + }) + + if err := LinkDel(parent); err != nil { + t.Fatal(err) + } +} + func TestNetkitPeerNs(t *testing.T) { minKernelRequired(t, 6, 7) tearDown := setUpNetlinkTest(t) diff --git a/nl/link_linux.go b/nl/link_linux.go index 744f4137..0b5be470 100644 --- a/nl/link_linux.go +++ b/nl/link_linux.go @@ -144,7 +144,9 @@ const ( IFLA_MACVLAN_MACADDR IFLA_MACVLAN_MACADDR_DATA IFLA_MACVLAN_MACADDR_COUNT - IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS + IFLA_MACVLAN_BC_QUEUE_LEN + IFLA_MACVLAN_BC_QUEUE_LEN_USED + IFLA_MACVLAN_MAX = IFLA_MACVLAN_BC_QUEUE_LEN_USED ) const (