{"record":{"id":"2fb1c0cfb0f4b77e","repo":"cilium/cilium","slug":"device-is-not-a-vf","errorCode":null,"errorMessage":"device is not a vf","messagePattern":"device is not a vf","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/networkdriver/sriov/sriov.go","lineNumber":35,"sourceCode":"\t\"strings\"\n\n\t\"github.com/vishvananda/netlink\"\n\tresourceapi \"k8s.io/api/resource/v1\"\n\t\"k8s.io/utils/ptr\"\n\n\t\"github.com/cilium/cilium/pkg/datapath/linux/safenetlink\"\n\t\"github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1\"\n\t\"github.com/cilium/cilium/pkg/logging/logfields\"\n\t\"github.com/cilium/cilium/pkg/networkdriver/types\"\n)\n\nconst (\n\tdefaultSysfsPath = \"/host/sys\"\n\tpciDevicesPath   = \"bus/pci/devices\"\n)\n\nvar (\n\terrNotAVF            = errors.New(\"device is not a vf\")\n\terrTooManyVFs        = errors.New(\"too many vfs\")\n\terrInterfaceNotFound = errors.New(\"interface not found\")\n\terrVFIDNotFound      = errors.New(\"could not find VF ID\")\n)\n\ntype PCIAddr string\ntype KernelIfName string\n\n// netlinkOps abstracts the netlink calls used by SRIOVManager and PciDevice.\n// The real implementation delegates to safenetlink/netlink; tests inject a fake.\ntype netlinkOps interface {\n\t// LinkList returns all netlink links on the system.\n\tLinkList() ([]netlink.Link, error)\n\t// LinkByName returns the link with the given interface name.\n\tLinkByName(name string) (netlink.Link, error)\n\t// LinkSetVfVlan sets the VLAN for a VF on a PF link.\n\tLinkSetVfVlan(link netlink.Link, vf, vlan int) error\n}","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/pkg/networkdriver/sriov/sriov.go#L17-L53","documentation":"errNotAVF (\"device is not a vf\") is returned by the SR-IOV PciDevice Setup and Free methods (pkg/networkdriver/sriov/sriov.go:120-152) when d.PFName is empty, i.e. the device being set up or freed has no Physical Function parent recorded. parseDevice also yields this condition when a discovered PCI device cannot be attributed to a PF, meaning it is not usable as an SR-IOV virtual function.","triggerScenarios":"Setup(config) or Free(config) is called on a PciDevice whose PFName field is empty — the wrapped error includes the device's pci-style ifname and kernel ifname. This happens when parseDevice discovered a PCI network device that is not an SR-IOV VF (no PF link in sysfs).","commonSituations":"Pool filters (driver/vendor/device-id) accidentally match physical function or non-SR-IOV NICs, so a non-VF device enters the pool; sysfs PF symlinks (virtfnN) missing because SR-IOV is disabled on the PF; bonding/team devices or unusual NIC firmware that breaks PF-VF attribution.","solutions":["Check the pool config filters so only actual VFs match — add explicit pciAddrs or ifNames rather than broad driver/vendor filters.","Verify SR-IOV is enabled and VFs are created on the PF: cat /sys/bus/pci/devices/<PF>/sriov_numvfs.","Confirm /host/sys is mounted into the container (defaultSysfsPath is /host/sys) so PF-VF relationships are visible.","If the device is a PF intentionally, remove it from the pool and select its VFs instead."],"exampleFix":"// before: broad filter matches the PF itself\n// filter: {drivers: [\"mlx5_core\"]}\n// after: restrict to the VF pci addresses\n// filter: {pciAddrs: [\"0000:3b:02.5\", \"0000:3b:02.6\"]}","handlingStrategy":"validation","validationCode":"func isSRIOVVF(pciAddr string) (bool, error) {\n\tpath := filepath.Join(\"/host/sys/bus/pci/devices\", pciAddr)\n\tphysFn, err := os.Readlink(filepath.Join(path, \"physfn\"))\n\tif os.IsNotExist(err) {\n\t\treturn false, nil // no PF parent: not a VF\n\t}\n\treturn err == nil, err\n}","typeGuard":"func IsNotAVF(err error) bool {\n\treturn errors.Is(err, sriov.ErrNotAVF)\n}","tryCatchPattern":"if err := dev.Setup(cfg); err != nil {\n\tif errors.Is(err, errNotAVF) {\n\t\t// skip non-VF device and mark it ineligible instead of failing the allocation\n\t\treturn skipDevice(dev, err)\n\t}\n\treturn err\n}","preventionTips":["Scope pool filters with explicit pciAddrs/ifNames so physical functions and non-SR-IOV NICs cannot match.","Verify sriov_numvfs > 0 on the PF before declaring VFs available to the pool.","Ensure /host/sys is mounted at the expected path in the driver container.","Check the physfn symlink exists for each candidate PCI address before adding it to a pool."],"tags":["sriov","network","pci","sysfs","kubernetes"],"backgroundTag":"device-not-a-vf","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}