From 25d662f5becfe34007fbffdc9f737d0db1c9b95b Mon Sep 17 00:00:00 2001 From: Marcelo Guerrero Date: Tue, 30 May 2023 02:27:08 +0200 Subject: [PATCH] Add support for allmulticast flag This allows users to set the allmulticast mode for a VF. Signed-off-by: Marcelo Guerrero --- pkg/config/config.go | 11 +++++++ pkg/config/config_test.go | 38 +++++++++++++++++++++++++ pkg/sriov/sriov.go | 30 ++++++++++++++++++- pkg/sriov/sriov_test.go | 6 ++++ pkg/types/types.go | 12 ++++---- pkg/utils/mocks/netlink_manager_mock.go | 35 +++++++++++++++++++++-- pkg/utils/netlink_manager.go | 12 ++++++++ 7 files changed, 136 insertions(+), 8 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index b2b6f706e..c15a35b58 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -93,6 +93,17 @@ func LoadConf(bytes []byte) (*sriovtypes.NetConf, error) { return nil, fmt.Errorf("LoadConf(): non-zero vlan id must be configured to set vlan QoS to a non-zero value") } + // validate that allMulti is one of supported values + if n.AllMulti != "" && n.AllMulti != "on" && n.AllMulti != "off" { + return nil, fmt.Errorf("LoadConf(): invalid all_multicast value: %s", n.AllMulti) + } + + // validate that both, trust and allMulti are enabled. + // only trusted VFs can enter the all-multicast RX mode. + if n.AllMulti == "on" && n.Trust != "on" { + return nil, fmt.Errorf("LoadConf(): trust must be enabled to set all_multicast: %s", n.AllMulti) + } + // validate that link state is one of supported values if n.LinkState != "" && n.LinkState != "auto" && n.LinkState != "enable" && n.LinkState != "disable" { return nil, fmt.Errorf("LoadConf(): invalid link_state value: %s", n.LinkState) diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 28de55b46..833115b35 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -65,6 +65,44 @@ var _ = Describe("Config", func() { Expect(err).To(HaveOccurred()) }) + It("Assuming correct config file - all multicast", func() { + conf := []byte(`{ + "name": "mynet", + "type": "sriov", + "deviceID": "0000:af:06.1", + "vf": 0, + "all_multicast": "on", + "trust": "on" + }`) + _, err := LoadConf(conf) + Expect(err).ToNot(HaveOccurred()) + }) + + It("Assuming incorrect all_multicast - trust not enabled", func() { + conf := []byte(`{ + "name": "mynet", + "type": "sriov", + "deviceID": "0000:af:06.1", + "vf": 0, + "all_multicast": "on", + "trust": "off" + }`) + _, err := LoadConf(conf) + Expect(err).To(HaveOccurred()) + }) + + It("Assuming incorrect all_multicast - incorrect value", func() { + conf := []byte(`{ + "name": "mynet", + "type": "sriov", + "deviceID": "0000:af:06.1", + "vf": 0, + "all_multicast": "sriov" + }`) + _, err := LoadConf(conf) + Expect(err).To(HaveOccurred()) + }) + It("Assuming device is allocated", func() { conf := []byte(`{ "name": "mynet", diff --git a/pkg/sriov/sriov.go b/pkg/sriov/sriov.go index 90156d46c..edeead0de 100644 --- a/pkg/sriov/sriov.go +++ b/pkg/sriov/sriov.go @@ -68,6 +68,8 @@ func (s *sriovManager) SetupVF(conf *sriovtypes.NetConf, podifName string, netns return "", fmt.Errorf("error getting VF netdevice with name %s", linkName) } + conf.OrigVfState.AllMulti = linkObj.Attrs().Allmulti != 0 + // tempName used as intermediary name to avoid name conflicts tempName := fmt.Sprintf("%s%d", "temp_", linkObj.Attrs().Index) @@ -126,7 +128,20 @@ func (s *sriovManager) SetupVF(conf *sriovtypes.NetConf, podifName string, netns // Error is ignored here because enabling this feature is only a performance enhancement. _ = s.utils.EnableArpAndNdiscNotify(podifName) - // 7. Bring IF up in Pod netns + // 7. Set allmulticast flag + if conf.AllMulti != "" { + if conf.AllMulti == "on" { + if err := s.nLink.LinkSetAllmulticastOn(linkObj); err != nil { + return fmt.Errorf("error setting allmulticast %s: %v", conf.AllMulti, err) + } + } else { + if err := s.nLink.LinkSetAllmulticastOff(linkObj); err != nil { + return fmt.Errorf("error setting allmulticast %s: %v", conf.AllMulti, err) + } + } + } + + // 8. Bring IF up in Pod netns if err := s.nLink.LinkSetUp(linkObj); err != nil { return fmt.Errorf("error bringing interface up in container ns: %q", err) } @@ -181,6 +196,19 @@ func (s *sriovManager) ReleaseVF(conf *sriovtypes.NetConf, podifName string, net } } + // reset allmulticast flag + if conf.AllMulti != "" { + if conf.OrigVfState.AllMulti { + if err := s.nLink.LinkSetAllmulticastOn(linkObj); err != nil { + return fmt.Errorf("error setting allmulticast %s: %v", conf.AllMulti, err) + } + } else { + if err := s.nLink.LinkSetAllmulticastOff(linkObj); err != nil { + return fmt.Errorf("error setting allmulticast %s: %v", conf.AllMulti, err) + } + } + } + // move VF device to init netns if err = s.nLink.LinkSetNsFd(linkObj, int(initns.Fd())); err != nil { return fmt.Errorf("failed to move interface %s to init netns: %v", conf.OrigVfState.HostIFName, err) diff --git a/pkg/sriov/sriov_test.go b/pkg/sriov/sriov_test.go index 4ca960723..fd1653c29 100644 --- a/pkg/sriov/sriov_test.go +++ b/pkg/sriov/sriov_test.go @@ -80,7 +80,11 @@ var _ = Describe("Sriov", func() { HardwareAddr: fakeMac, }} + // Enable allmulticast flag + netconf.AllMulti = "on" + mocked.On("LinkByName", mock.AnythingOfType("string")).Return(fakeLink, nil) + mocked.On("LinkSetAllmulticastOn", mock.Anything).Return(nil) mocked.On("LinkSetDown", fakeLink).Return(nil) mocked.On("LinkSetName", fakeLink, mock.Anything).Return(nil) mocked.On("LinkSetNsFd", fakeLink, mock.AnythingOfType("int")).Return(nil) @@ -190,6 +194,7 @@ var _ = Describe("Sriov", func() { HostIFName: "enp175s6", EffectiveMAC: "c6:c8:7f:1f:21:90", }, + AllMulti: "off", } }) It("Restores Effective MAC address when provided in netconf", func() { @@ -205,6 +210,7 @@ var _ = Describe("Sriov", func() { fakeLink := &FakeLink{netlink.LinkAttrs{Index: 1000, Name: "dummylink"}} mocked.On("LinkByName", netconf.ContIFNames).Return(fakeLink, nil) + mocked.On("LinkSetAllmulticastOff", mock.Anything).Return(nil) mocked.On("LinkSetDown", fakeLink).Return(nil) mocked.On("LinkSetName", fakeLink, netconf.OrigVfState.HostIFName).Return(nil) mocked.On("LinkSetNsFd", fakeLink, mock.AnythingOfType("int")).Return(nil) diff --git a/pkg/types/types.go b/pkg/types/types.go index 75e08845c..6cf5bd9bc 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -17,6 +17,7 @@ type VfState struct { MinTxRate int MaxTxRate int LinkState uint32 + AllMulti bool } // FillFromVfInfo - Fill attributes according to the provided netlink.VfInfo struct @@ -43,11 +44,12 @@ type NetConf struct { DeviceID string `json:"deviceID"` // PCI address of a VF in valid sysfs format VFID int ContIFNames string // VF names after in the container; used during deletion - MinTxRate *int `json:"min_tx_rate"` // Mbps, 0 = disable rate limiting - MaxTxRate *int `json:"max_tx_rate"` // Mbps, 0 = disable rate limiting - SpoofChk string `json:"spoofchk,omitempty"` // on|off - Trust string `json:"trust,omitempty"` // on|off - LinkState string `json:"link_state,omitempty"` // auto|enable|disable + MinTxRate *int `json:"min_tx_rate"` // Mbps, 0 = disable rate limiting + MaxTxRate *int `json:"max_tx_rate"` // Mbps, 0 = disable rate limiting + SpoofChk string `json:"spoofchk,omitempty"` // on|off + Trust string `json:"trust,omitempty"` // on|off + LinkState string `json:"link_state,omitempty"` // auto|enable|disable + AllMulti string `json:"all_multicast,omitempty"` // on|off RuntimeConfig struct { Mac string `json:"mac,omitempty"` } `json:"runtimeConfig,omitempty"` diff --git a/pkg/utils/mocks/netlink_manager_mock.go b/pkg/utils/mocks/netlink_manager_mock.go index 891a4e9d8..363dbf7cb 100644 --- a/pkg/utils/mocks/netlink_manager_mock.go +++ b/pkg/utils/mocks/netlink_manager_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.20.0. DO NOT EDIT. package mocks @@ -20,6 +20,10 @@ func (_m *NetlinkManager) LinkByName(_a0 string) (netlink.Link, error) { ret := _m.Called(_a0) var r0 netlink.Link + var r1 error + if rf, ok := ret.Get(0).(func(string) (netlink.Link, error)); ok { + return rf(_a0) + } if rf, ok := ret.Get(0).(func(string) netlink.Link); ok { r0 = rf(_a0) } else { @@ -28,7 +32,6 @@ func (_m *NetlinkManager) LinkByName(_a0 string) (netlink.Link, error) { } } - var r1 error if rf, ok := ret.Get(1).(func(string) error); ok { r1 = rf(_a0) } else { @@ -38,6 +41,34 @@ func (_m *NetlinkManager) LinkByName(_a0 string) (netlink.Link, error) { return r0, r1 } +// LinkSetAllmulticastOff provides a mock function with given fields: _a0 +func (_m *NetlinkManager) LinkSetAllmulticastOff(_a0 netlink.Link) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(netlink.Link) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// LinkSetAllmulticastOn provides a mock function with given fields: _a0 +func (_m *NetlinkManager) LinkSetAllmulticastOn(_a0 netlink.Link) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(netlink.Link) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // LinkSetDown provides a mock function with given fields: _a0 func (_m *NetlinkManager) LinkSetDown(_a0 netlink.Link) error { ret := _m.Called(_a0) diff --git a/pkg/utils/netlink_manager.go b/pkg/utils/netlink_manager.go index cf681eee0..5db2877cc 100644 --- a/pkg/utils/netlink_manager.go +++ b/pkg/utils/netlink_manager.go @@ -11,6 +11,8 @@ import ( // NetlinkManager is an interface to mock nelink library type NetlinkManager interface { LinkByName(string) (netlink.Link, error) + LinkSetAllmulticastOn(netlink.Link) error + LinkSetAllmulticastOff(netlink.Link) error LinkSetVfVlan(netlink.Link, int, int) error LinkSetVfVlanQos(netlink.Link, int, int, int) error LinkSetVfHardwareAddr(netlink.Link, int, net.HardwareAddr) error @@ -35,6 +37,16 @@ func (n *MyNetlink) LinkByName(name string) (netlink.Link, error) { return netlink.LinkByName(name) } +// LinkSetAllmulticastOn sets allmulticast on +func (n *MyNetlink) LinkSetAllmulticastOn(link netlink.Link) error { + return netlink.LinkSetAllmulticastOn(link) +} + +// LinkSetAllmulticastOff sets allmulticast off +func (n *MyNetlink) LinkSetAllmulticastOff(link netlink.Link) error { + return netlink.LinkSetAllmulticastOff(link) +} + // LinkSetVfVlan using NetlinkManager func (n *MyNetlink) LinkSetVfVlan(link netlink.Link, vf, vlan int) error { return netlink.LinkSetVfVlan(link, vf, vlan)