Skip to content

Commit

Permalink
Add udev rule to keep PF name stable
Browse files Browse the repository at this point in the history
This rule is required for some
kernels to keep PF name same
after switching to switchdev mode

Signed-off-by: Yury Kulazhenkov <[email protected]>
  • Loading branch information
ykulazhenkov committed Mar 20, 2024
1 parent 68ef448 commit b7fb8ce
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 48 deletions.
2 changes: 2 additions & 0 deletions pkg/consts/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ const (
UdevDisableNM = "/bindata/scripts/udev-find-sriov-pf.sh"
UdevRepName = "/bindata/scripts/switchdev-vf-link-name.sh"
// nolint:goconst
PFNameUdevRule = `SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", KERNELS=="%s", NAME="%s"`
// nolint:goconst
NMUdevRule = `SUBSYSTEM=="net", ` +
`ACTION=="add|change|move", ` +
`ATTRS{device}=="%s", ` +
Expand Down
24 changes: 12 additions & 12 deletions pkg/helper/mock/mock_helper.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pkg/host/internal/sriov/sriov.go
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,7 @@ func (s *sriov) encapTypeToLinkType(encapType string) string {
func (s *sriov) addUdevRules(iface *sriovnetworkv1.Interface) error {
log.Log.V(2).Info("addUdevRules(): add udev rules for device",
"device", iface.PciAddress)
if err := s.udevHelper.AddUdevRule(iface.PciAddress); err != nil {
if err := s.udevHelper.AddUdevRules(iface.PciAddress, iface.Name); err != nil {
return err
}
if sriovnetworkv1.GetEswitchModeFromSpec(iface) == sriovnetworkv1.ESwithModeSwitchDev {
Expand All @@ -917,7 +917,7 @@ func (s *sriov) addUdevRules(iface *sriovnetworkv1.Interface) error {
func (s *sriov) removeUdevRules(pciAddress string) error {
log.Log.V(2).Info("removeUdevRules(): remove udev rules for device",
"device", pciAddress)
if err := s.udevHelper.RemoveUdevRule(pciAddress); err != nil {
if err := s.udevHelper.RemoveUdevRules(pciAddress); err != nil {
return err
}
return s.udevHelper.RemoveVfRepresentorUdevRule(pciAddress)
Expand Down
10 changes: 5 additions & 5 deletions pkg/host/internal/sriov/sriov_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ var _ = Describe("SRIOV", func() {
dputilsLibMock.EXPECT().GetVFconfigured("0000:d8:00.0").Return(0)
netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(&netlink.DevlinkDevice{
Attrs: netlink.DevlinkDevAttrs{Eswitch: netlink.DevlinkDevEswitchAttr{Mode: "legacy"}}}, nil)
hostMock.EXPECT().AddUdevRule("0000:d8:00.0").Return(nil)
hostMock.EXPECT().AddUdevRules("0000:d8:00.0", "enp216s0f0np0").Return(nil)
dputilsLibMock.EXPECT().GetVFList("0000:d8:00.0").Return([]string{"0000:d8:00.2", "0000:d8:00.3"}, nil)
pfLinkMock := netlinkMockPkg.NewMockLink(testCtrl)
netlinkLibMock.EXPECT().LinkByName("enp216s0f0np0").Return(pfLinkMock, nil).Times(3)
Expand Down Expand Up @@ -179,7 +179,7 @@ var _ = Describe("SRIOV", func() {
dputilsLibMock.EXPECT().GetVFconfigured("0000:d8:00.0").Return(0)
netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(&netlink.DevlinkDevice{
Attrs: netlink.DevlinkDevAttrs{Eswitch: netlink.DevlinkDevEswitchAttr{Mode: "legacy"}}}, nil)
hostMock.EXPECT().AddUdevRule("0000:d8:00.0").Return(nil)
hostMock.EXPECT().AddUdevRules("0000:d8:00.0", "enp216s0f0np0").Return(nil)
dputilsLibMock.EXPECT().GetVFList("0000:d8:00.0").Return([]string{"0000:d8:00.2"}, nil)
pfLinkMock := netlinkMockPkg.NewMockLink(testCtrl)
netlinkLibMock.EXPECT().LinkByName("enp216s0f0np0").Return(pfLinkMock, nil).Times(2)
Expand Down Expand Up @@ -227,7 +227,7 @@ var _ = Describe("SRIOV", func() {
hostMock.EXPECT().IsKernelLockdownMode().Return(false)
dputilsLibMock.EXPECT().GetSriovVFcapacity("0000:d8:00.0").Return(1)
dputilsLibMock.EXPECT().GetVFconfigured("0000:d8:00.0").Return(0)
hostMock.EXPECT().AddUdevRule("0000:d8:00.0").Return(nil)
hostMock.EXPECT().AddUdevRules("0000:d8:00.0", "enp216s0f0np0").Return(nil)
hostMock.EXPECT().EnableHwTcOffload("enp216s0f0np0").Return(nil)
hostMock.EXPECT().GetDevlinkDeviceParam("0000:d8:00.0", "flow_steering_mode").Return("", syscall.EINVAL)
dputilsLibMock.EXPECT().GetVFList("0000:d8:00.0").Return([]string{"0000:d8:00.2"}, nil).Times(2)
Expand Down Expand Up @@ -345,7 +345,7 @@ var _ = Describe("SRIOV", func() {
netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(
&netlink.DevlinkDevice{Attrs: netlink.DevlinkDevAttrs{Eswitch: netlink.DevlinkDevEswitchAttr{Mode: "legacy"}}},
nil)
hostMock.EXPECT().RemoveUdevRule("0000:d8:00.0").Return(nil)
hostMock.EXPECT().RemoveUdevRules("0000:d8:00.0").Return(nil)
hostMock.EXPECT().RemoveVfRepresentorUdevRule("0000:d8:00.0").Return(nil)
hostMock.EXPECT().SetNetdevMTU("0000:d8:00.0", 1500).Return(nil)

Expand Down Expand Up @@ -391,7 +391,7 @@ var _ = Describe("SRIOV", func() {
netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(
&netlink.DevlinkDevice{Attrs: netlink.DevlinkDevAttrs{Eswitch: netlink.DevlinkDevEswitchAttr{Mode: "legacy"}}},
nil)
hostMock.EXPECT().AddUdevRule("0000:d8:00.0").Return(nil)
hostMock.EXPECT().AddUdevRules("0000:d8:00.0", "enp216s0f0np0").Return(nil)
dputilsLibMock.EXPECT().GetVFList("0000:d8:00.0").Return([]string{"0000:d8:00.2", "0000:d8:00.3"}, nil)
hostMock.EXPECT().Unbind("0000:d8:00.2").Return(nil)
hostMock.EXPECT().Unbind("0000:d8:00.3").Return(nil)
Expand Down
29 changes: 20 additions & 9 deletions pkg/host/internal/udev/udev.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,28 @@ func (u *udev) PrepareVFRepUdevRule() error {
return nil
}

// AddUdevRule adds a udev rule that disables network-manager for VFs on the concrete PF
func (u *udev) AddUdevRule(pfPciAddress string) error {
log.Log.V(2).Info("AddUdevRule()", "device", pfPciAddress)
udevRuleContent := fmt.Sprintf(consts.NMUdevRule, strings.Join(vars.SupportedVfIds, "|"), pfPciAddress)
return u.addUdevRule(pfPciAddress, "10-nm-disable", udevRuleContent)
// AddUdevRules adds two udev rules for PF:
// 1. the rule that disables NetworkManager for all VFs on PF
// 2. the rule that configure PF to always use name provided in pfName arg
func (u *udev) AddUdevRules(pfPciAddress, pfName string) error {
log.Log.V(2).Info("AddUdevRules()", "device", pfPciAddress)
nmRuleContent := fmt.Sprintf(consts.NMUdevRule, strings.Join(vars.SupportedVfIds, "|"), pfPciAddress)
if err := u.addUdevRule(pfPciAddress, "10-nm-disable", nmRuleContent); err != nil {
return err
}
pfNameRuleContent := fmt.Sprintf(consts.PFNameUdevRule, pfPciAddress, pfName)
return u.addUdevRule(pfPciAddress, "10-pf-name", pfNameRuleContent)
}

// RemoveUdevRule removes a udev rule that disables network-manager for VFs on the concrete PF
func (u *udev) RemoveUdevRule(pfPciAddress string) error {
log.Log.V(2).Info("RemoveUdevRule()", "device", pfPciAddress)
return u.removeUdevRule(pfPciAddress, "10-nm-disable")
// RemoveUdevRules removes following udev rules for PF:
// 1. the rule that disables NetworkManager for all VFs on PF
// 2. the rule that configure PF to always use name provided in pfName arg
func (u *udev) RemoveUdevRules(pfPciAddress string) error {
log.Log.V(2).Info("RemoveUdevRules()", "device", pfPciAddress)
if err := u.removeUdevRule(pfPciAddress, "10-nm-disable"); err != nil {
return err
}
return u.removeUdevRule(pfPciAddress, "10-pf-name")
}

// AddVfRepresentorUdevRule adds udev rule that renames VF representors on the concrete PF
Expand Down
19 changes: 15 additions & 4 deletions pkg/host/internal/udev/udev_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
)

const (
testExpectedPFUdevRule = `SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", KERNELS=="0000:d8:00.0", NAME="enp129"`
testExpectedNMUdevRule = `SUBSYSTEM=="net", ACTION=="add|change|move", ` +
`ATTRS{device}=="0x1017|0x1018", ` +
`IMPORT{program}="/etc/udev/disable-nm-sriov.sh $env{INTERFACE} 0000:d8:00.0"`
Expand All @@ -33,10 +34,13 @@ var _ = Describe("UDEV", func() {
Context("AddUdevRule", func() {
It("Created", func() {
helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{})
Expect(s.AddUdevRule("0000:d8:00.0")).To(BeNil())
Expect(s.AddUdevRules("0000:d8:00.0", "enp129")).To(BeNil())
helpers.GinkgoAssertFileContentsEquals(
"/etc/udev/rules.d/10-nm-disable-0000:d8:00.0.rules",
testExpectedNMUdevRule)
helpers.GinkgoAssertFileContentsEquals(
"/etc/udev/rules.d/10-pf-name-0000:d8:00.0.rules",
testExpectedPFUdevRule)
})
It("Overwrite", func() {
helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{
Expand All @@ -45,10 +49,13 @@ var _ = Describe("UDEV", func() {
"/etc/udev/rules.d/10-nm-disable-0000:d8:00.0.rules": []byte("something"),
},
})
Expect(s.AddUdevRule("0000:d8:00.0")).To(BeNil())
Expect(s.AddUdevRules("0000:d8:00.0", "enp129")).To(BeNil())
helpers.GinkgoAssertFileContentsEquals(
"/etc/udev/rules.d/10-nm-disable-0000:d8:00.0.rules",
testExpectedNMUdevRule)
helpers.GinkgoAssertFileContentsEquals(
"/etc/udev/rules.d/10-pf-name-0000:d8:00.0.rules",
testExpectedPFUdevRule)
})
})
Context("RemoveUdevRule", func() {
Expand All @@ -57,18 +64,22 @@ var _ = Describe("UDEV", func() {
Dirs: []string{"/etc/udev/rules.d"},
Files: map[string][]byte{
"/etc/udev/rules.d/10-nm-disable-0000:d8:00.0.rules": []byte(testExpectedNMUdevRule),
"/etc/udev/rules.d/10-pf-name-0000:d8:00.0.rules": []byte(testExpectedPFUdevRule),
},
})
Expect(s.RemoveUdevRule("0000:d8:00.0")).To(BeNil())
Expect(s.RemoveUdevRules("0000:d8:00.0")).To(BeNil())
_, err := os.Stat(filepath.Join(vars.FilesystemRoot,
"/etc/udev/rules.d/10-nm-disable-0000:d8:00.0.rules"))
Expect(os.IsNotExist(err)).To(BeTrue())
_, err = os.Stat(filepath.Join(vars.FilesystemRoot,
"/etc/udev/rules.d/10-pf-name-0000:d8:00.0.rules"))
Expect(os.IsNotExist(err)).To(BeTrue())
})
It("Not found", func() {
helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{
Dirs: []string{"/etc/udev/rules.d"},
})
Expect(s.RemoveUdevRule("0000:d8:00.0")).To(BeNil())
Expect(s.RemoveUdevRules("0000:d8:00.0")).To(BeNil())
})
})
Context("AddVfRepresentorUdevRule", func() {
Expand Down
24 changes: 12 additions & 12 deletions pkg/host/mock/mock_host.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 8 additions & 4 deletions pkg/host/types/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,14 @@ type UdevInterface interface {
PrepareNMUdevRule(supportedVfIds []string) error
// PrepareVFRepUdevRule creates a script which helps to configure representor name for the VF
PrepareVFRepUdevRule() error
// AddUdevRule adds a udev rule that disables network-manager for VFs on the concrete PF
AddUdevRule(pfPciAddress string) error
// RemoveUdevRule removes a udev rule that disables network-manager for VFs on the concrete PF
RemoveUdevRule(pfPciAddress string) error
// AddUdevRules adds two udev rules for PF:
// 1. the rule that disables NetworkManager for all VFs on PF
// 2. the rule that configure PF to always use name provided in pfName arg
AddUdevRules(pfPciAddress, pfName string) error
// RemoveUdevRules removes following udev rules for PF:
// 1. the rule that disables NetworkManager for all VFs on PF
// 2. the rule that configure PF to always use name provided in pfName arg
RemoveUdevRules(pfPciAddress string) error
// AddVfRepresentorUdevRule adds udev rule that renames VF representors on the concrete PF
AddVfRepresentorUdevRule(pfPciAddress, pfName, pfSwitchID, pfSwitchPort string) error
// RemoveVfRepresentorUdevRule removes udev rule that renames VF representors on the concrete PF
Expand Down

0 comments on commit b7fb8ce

Please sign in to comment.