DRA Network Device Discovery Design
Policy-driven network device discovery with DRA compatibility groups, local consumable capacity, and optional shared budgets
DRA Network Device Discovery and ResourceSlice Design
Status: Revised selected design; driver implementation has not started.
Revision: 2026-09-23 — define cold PCI and software-child discovery, effect-specific host-dependency protection, and VLAN/ipvlan/macvlan/macvtap compatibility; align NetworkPlugin capability names and OVN adapter identity; retain the KEP 5963 exclusion model.
Scope: This document defines the proposedDeviceExposurePolicyAPI and its translation into Kubernetes DRA objects. Custom policy fields below are our design, not upstream Kubernetes fields.
Upstream baseline and feature boundaries
The implementation observations in this revision are pinned to Kubernetes commit a255808f6c0deb6e75ce031b5804e722306e46a8, inspected on 2026-09-16. A source-level feature version is not a promise that a particular OpenShift release enables or supports that feature. Validate the actual target distribution before deployment. S1 S2
| Concern | Upstream mechanism | Baseline / dependency |
|---|---|---|
| Device inventory and claims | resource.k8s.io/v1 | Use the current v1 object shape. |
| Counter-set associations | KEP 4815 / DRAPartitionableDevices | Inspected source: beta from 1.36, enabled by default. Do not label this dependency GA in 1.35. |
| Repeated allocations and local limits | KEP 5075 / DRAConsumableCapacity | Inspected source: beta from 1.36, enabled by default. |
| Incompatible network modes | KEP 5963 / DRADeviceCompatibilityGroups | Inspected source: alpha from 1.37, disabled by default; requires partitionable devices. |
supportedNetworkPlugins list attribute | KEP 5491 / DRAListTypeAttributes | Inspected source: alpha from 1.36, disabled by default. List values use strings. |
| Per-allocation shared budgets | KEP 5941 / PR #140084 | Optional follow-on work. Not required for the baseline exclusion design or reference manifests. |
Important implementation caveat: KEP 5963 describes allocation-time group snapshots, but the inspected allocator reconstructs compatibility from live ResourceSlices and allocated device identities. This revision targets that actual behavior. Do not assume claim status already preserves compatibility independently of the inventory. S3 S4
1. Overview and Design Principles
This document specifies how a DRA network driver discovers host network devices and publishes them as ResourceSlices for scheduler-aware allocation.
The Cardinal Rule: The Driver Is Generic
sysfs / netlink observations
|
v
PCI functions + netdevices + typed dependency/ownership graph
|
v
DeviceExposurePolicy selection and validation
|
v
persona entries + scoped compatibility domains + local capacities
|
v
separate counter-bearing and device-bearing ResourceSlicesThe discovery engine starts with PCI functions, including functions already bound to VFIO or unbound at first startup, and joins optional host netdevice, RDMA and controller observations. Software bridges, bonds and VLANs have separate inventory records. An absent host interface is not evidence that a PCI function is absent or free. Section 4.1 defines identity, observation completeness and dependency protection; the engine does not infer NetworkPlugin compatibility from plugin names.
The administrator’s policy declares which devices are exposed, which logical NetworkPlugins can use an entry, how much local capacity each allocation consumes, and which usage modes may coexist. The driver validates and compiles these declarations. The node-side execution path must enforce the compiled compatibility contract and verify the actual device identity before changing networking; being generic does not mean skipping safety checks.
A PF/VF relationship is a discovered topology fact. A declaration that PF passthrough must exclude all child allocations is a policy rule, not a universally assumed consequence of every operation on every PF. In particular, this design does not assert that every PF namespace move destroys its VFs. Independently, the driver must deny any operation whose certified effects can disrupt a protected host dependency. Exposure policy cannot override that safety check.
Other Design Decisions
- Real resources, not synthetic allocation slots. A PCI function, its verified network endpoint or a software interface may have multiple persona entries when it supports different allocation semantics. A persona is an alternative representation, not additional hardware; netdevice absence does not erase a function.
- One winning policy produces one persona.
allowMultipleAllocationsis the single source of truth for sharing that entry. Multiple NetworkPlugin names in one policy are alternatives with identical allocation semantics. - Local capacity limits repeated allocations. A shared persona uses
allowMultipleAllocations: truepluscapacity. The examples reserve one unit per claim allocation, withvalidValues: ["1"]. - Compatibility groups express mode exclusion. Distinct incompatible personas consume from a common counter set and declare disjoint
compatibilityGroups. No local-capacity mirroring and no cross-draining are generated. - Independent constraints use independent domains. Interface mode and PF-family access are separate counter-set associations when both are needed. PF macvlan and child VFs can share a family group while PF macvlan and PF ipvlan remain incompatible in the interface domain.
- Bandwidth is a separate, optional budget. Link speed remains an attribute in the baseline. Do not publish a bandwidth guarantee or an invented fair-share policy just because a speed was discovered.
- Deny-by-default, without forgetting active allocations. Unmatched or excluded devices are not newly exposed. Existing active publication is handled through the drain protocol, not deleted immediately.
- NetworkPlugin selection is explicit. DeviceClasses select the driver and test
supportedNetworkPluginsusing exact list membership. Advertising a NetworkPlugin name is not proof that its invocation and controller integration work. - Stable identities and declarations. Active device names, pool membership, counter-set associations, and groups must survive rescan, policy changes, interface moves, and driver restarts until safely drained.
- Protection is effect-specific. Management, primary-network and external ownership records protect their actual dependency closure. PCI ancestry, PF families, representors, IOMMU groups and reset domains are distinct relationships, not interchangeable exclusion groups.
The upstream API separates compatibility predicates from local and shared capacity accounting. Our policy compiler preserves that separation. S1 S3 S4
2. DeviceExposurePolicy CRD Schema
2.1 Proposed Custom Resource Shape
This is an example custom resource, not an apiextensions.k8s.io/v1 CRD definition. The structural OpenAPI schema, defaults, CEL validation, status schema, and admission integration will be implemented after this design is accepted.
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf0-macvlan
spec:
# Optional; defaults to all nodes.
nodeSelector:
matchLabels:
network.example.com/role: data
# 0-1000, default 100. Used only among expose policies for the same suffix.
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "pf" && device.attributes["dra.networking"].ifName == "enp3s0f0"
action: expose
exposure:
# One policy winner per suffix; no automatic splitting by NetworkPlugin name.
deviceNameSuffix: "-macvlan"
allowMultipleAllocations: true
# Local capacity only. This does not create shared counter capacity.
capacity:
macvlans:
value: "64"
requestPolicy:
default: "1"
validValues: ["1"]
supportedNetworkPlugins:
- name: macvlan
# Compiler validation / topology contract, not a Kubernetes field.
consumePerAllocation:
macvlans: "1"
# Proposed policy API. Each binding compiles to a consumesCounters entry.
compatibility:
- scope: interface
domain: interface-mode
groups: [macvlan]
- scope: sriovFamily
domain: pf-access
groups: [host-retained]
# Selection metadata only; do not override discovered or reserved attributes.
additionalAttributes:
dra.networking/physicalNetworkName: data-network2.2 Field Semantics
| Field | Required / default | Meaning |
|---|---|---|
nodeSelector | Optional; all nodes | Nodes on which the policy participates in resolution. |
priority | Optional; 100 | Highest value wins within the same suffix; range 0-1000. |
selector.cel | Required | Boolean expression against the driver’s normalized discovered attributes. |
action | Optional; expose | expose proposes publication subject to dependency safety; exclude prevents new exposure of the selected inventory resource. An exclusion alone is not an external ownership record. |
exposure.deviceNameSuffix | Optional; empty string | Distinguishes persona policies for one inventory resource. Published identities are pinned after creation. |
exposure.allowMultipleAllocations | Optional; false | Sharing permission for this DRA device entry, not for every alias of the underlying interface. |
exposure.capacity | Required for shared entries in this baseline | Local DeviceCapacity definitions. The compiler qualifies unqualified keys with dra.networking/. |
exposure.supportedNetworkPlugins | Required for expose policies | Non-empty list of logical NetworkPlugin names and optional consumption declarations. All plugins on one entry must have identical allocation semantics. |
consumePerAllocation | Optional; use local defaults | A driver/topology consistency declaration. Baseline amounts must equal requestPolicy.default; the scheduler does not read this custom field. |
exposure.compatibility | Optional unless sharing an exclusion domain | Up to two domain bindings after compilation. Each binding has scope, domain, and non-empty groups. |
compatibility[].scope | Required | interface: the stable endpoint/resource identity, including its function ownership boundary when applicable; it does not require a current ifname. sriovFamily: the PF root’s stable identity, shared with its VFs. |
compatibility[].domain | Required | Administrator-chosen DNS-label name for one independent compatibility constraint. |
compatibility[].groups | Required | One or two unique DNS-label tokens copied into the upstream compatibilityGroups field. |
exposure.additionalAttributes | Optional | Additional scalar selection attributes; string, boolean, or integer. Reserved/discovered keys cannot be overwritten. |
scope and domain resolve a comparison boundary; groups expresses compatibility within that boundary. Group names have no plugin-specific interpretation in the driver.
Each supportedNetworkPlugins[].name identifies a logical plugin in the companion NetworkPlugin registry. It is not a CNI executable name, gRPC socket, deployment artifact or process name. A topology’s pluginRef.name selects that same identity and pins its contract through the immutable revision. A service may implement multiple logical plugins; publish their individual names, not the service name. Discovery capability publication does not replace whole-plan runtime readiness checks.
2.3 Policy Resolution
For each identity-verified inventory resource:
1. Select policies whose nodeSelector applies to this node.
2. Evaluate selector.cel against normalized discovered facts.
3. If any matching policy says exclude: desired exposure is empty.
4. If no expose policy matches: desired exposure is empty.
5. Otherwise group matching expose policies by deviceNameSuffix.
6. Pick highest priority per group; break ties by policy name.
7. Produce exactly one candidate persona per winner.
8. Resolve compatibility bindings against the discovered topology.
9. Validate certified effect footprints against protection/ownership records.
Then validate the complete interface/family publication, including retained entries.
10. Reconcile desired publication with active allocations and the drain state.Exclude priority is irrelevant: an exclusion always takes precedence over exposure. Two policies with different suffixes are not automatically mutually exclusive; their explicit compatibility bindings determine which combinations are allowed.
A selector compilation error rejects the policy. A selector evaluation error makes reconciliation fail closed for the affected inventory evaluation and records a diagnostic; it must not silently skip a potentially applicable exclusion policy. Previously committed active publication remains retained until its lifecycle is resolved.
2.4 Validation and Cross-Policy Checks
These are proposed driver requirements, in addition to upstream API validation:
- An exclusive entry (
allowMultipleAllocations: false) has no local request policy orconsumePerAllocationin the baseline. A shared entry has positive local capacity and an explicit default for each dimension. - Plugin-specific amounts are positive, reference existing capacity keys after qualification, and equal those dimensions’ defaults in the initial implementation. Different plugin costs require different persona policies and suitable compatibility guards; they are not inferred at scheduling time.
- When more than one persona aliases an interface, all aliases must participate in a common interface-scoped domain. Any exclusive persona must be incompatible there with every other alias. The compiler rejects ambiguous aliasing rather than assuming different names imply separate hardware.
- When an exposed PF persona excludes child use, every exposed child and every competing PF persona must participate in the same family-scoped domain. This is configured in policy; topology resolution alone does not invent group membership.
- A
sriovFamilybinding on an interface with no resolvable PF root is invalid. Bridges with indirect PF dependencies are not silently assigned a PF family. - Resolve bindings before enforcing limits: a device may consume from at most two counter sets; a counter-set consumption supports at most two compatibility groups. Reject a third independent domain instead of silently dropping it. S1
- Conflicting domain definitions, duplicate references, invalid names, overriding reserved attributes, or exceeding upstream attribute limits invalidate the affected compilation unit.
supportedNetworkPluginsnames must be nonempty, unique and refer to approved logical plugin contracts. Reject retired capability-field names rather than accepting ambiguous aliases. Advertised support must agree with the inventory and execution contract; the presence of a similarly named CNI binary is insufficient.- All initial counter-set associations generated for exclusion have non-empty groups. An empty list must never be emitted as a wildcard.
- A matching expose policy cannot authorize unsafe effects. Every advertised plugin must pass Section 4.1’s dependency check; an unknown identity, ownership boundary or relevant effect footprint prevents new publication. The compiler rejects that persona with a diagnostic rather than silently dropping a plugin alternative.
Policy admission can validate shape and local consistency. Node reconciliation must validate topology-dependent and cross-policy rules. A future webhook must not claim it can statically validate every node’s current hardware inventory.
3. How Compatibility Domains Work: The Multi-Persona Pattern
The selected pattern remains separate DRA device entries referring to a common resource, but the enforcement mechanism changes to KEP 5963 compatibility groups.
3.1 Three Uses of the Same Compatibility Predicate
| Relationship | Comparison domain | Compatible group assignment |
|---|---|---|
| Macvlan vs ipvlan on one interface | Interface interface-mode | Macvlan: [macvlan]; ipvlan: [ipvlan]. |
| Shared macvlan vs exclusive host-device on one interface | Same interface domain | Macvlan: [macvlan]; passthrough: [passthrough]. |
| PF passthrough vs normal PF/VF use | PF family pf-access | PF passthrough: [pf-passthrough]; retained PF and VFs: [host-retained]. |
PF0 interface-mode: macvlan [macvlan] != passthrough [passthrough]
PF0 family pf-access: macvlan [host-retained]
VF0..VF7 [host-retained]
passthrough [pf-passthrough]This allows PF macvlan and VFs together while excluding PF passthrough. Adding a PF ipvlan persona uses [ipvlan] in the interface domain and [host-retained] in the family domain. It remains compatible with VFs but not with PF macvlan.
A VF’s NetworkPlugin allocation can be exclusive for that VF entry while its family group is host-retained: the group describes access to the parent PF family, not whether that VF is shared.
3.2 Exact Upstream Compatibility Semantics
For each counter set, the scheduler maintains an intersection across the active devices’ group sets. A new candidate is compatible only if including its groups leaves a common group. A candidate associated with two counter sets must pass the predicate on both. Devices associated with different counter sets are not compared through this feature. S1 S3
{macvlan} intersection {macvlan} = {macvlan} -> compatible
{macvlan} intersection {ipvlan} = {} -> incompatiblePairwise overlap is insufficient. {a,b}, {b,c}, and {a,c} intersect pairwise, but the intersection of all three is empty. Empty/unset groups only coexist with other empty/unset groups on the same counter set; they do not mean “compatible with everything”. S3
Do not publish groups: [macvlan, shared] and groups: [ipvlan, shared] when the modes conflict: the common shared token would permit them together.
3.2.1 Upstream Two-Item Limits and Domain Scaling
The pinned Kubernetes API and its generated validation confirm two separate limits:
- One
DeviceCounterConsumptionmay contain at most two uniquecompatibilityGroupsnames. - One device may contain at most two
consumesCountersentries, so it may participate in at most two counter sets and therefore at most two independent compatibility domains.
The API declarations set both maxima to two, and the generated validators call MaxItems(..., 2) for both fields. An API server rejects a third group on one consumption or a third counter-set consumption on one device. S1 S20
These limits constrain different dimensions. A counter set identifies the comparison domain. Its compatibilityGroups are alternative memberships within that domain. The two-group limit does not restrict a domain to two modes: any number of devices or personas may each publish one distinct group, such as macvlan, ipvlan, passthrough, and other mutually exclusive modes. It does restrict a single device that must be compatible through three or more alternative common memberships in the same domain.
The two-consumesCounters limit is more restrictive for this design. A PF persona that consumes from interface-mode and pf-access has used both available domain associations. It cannot also join an independent reset-domain, controller-ownership domain, or other scheduler compatibility domain. Adding that third domain name to the existing compatibilityGroups list is not equivalent: group names in one consumption are OR alternatives inside one domain, while separate counter-set checks are AND constraints. Such flattening may allow an unsafe combination.
Use these workarounds only when their semantics are exact:
- Apply the third domain only to personas that do not already consume from two counter sets. The limit is per device, not a pool-wide limit.
- Merge domains only when they have the same comparison boundary and their conjunction can be encoded losslessly with composite group tokens, with no device requiring more than two tokens. For example, a token may represent the tuple
(interface-mode=macvlan, pf-access=host-retained). Test whole-set intersections for every supported combination; tuple encoding can otherwise reject valid combinations or admit invalid ones. - Put devices in separate pools only when no compatibility comparison is required across those pools. Different pools disable this predicate; pool splitting cannot preserve a required cross-pool exclusion.
- Keep external ownership and operation-safety constraints in Section 4.1’s protection graph. If a third relationship must be enforced by the scheduler between DRA consumers and cannot be encoded exactly, reject that publication profile. A node-side Prepare failure is not a scheduling-time workaround.
- Seek an upstream API extension when a device genuinely needs three or more independent compatibility domains or more than two alternative memberships in one domain. The current API has no general lossless encoding for either case.
3.2.2 Concrete Network Cases That Hit the Limits
The group limit is reachable with the software modes in this document. On one immediate lower, suppose macvlan/macvtap, ipvlan L2, and ipvlan L3 are three mutually incompatible mode families, while a VLAN-creation persona may coexist with any one family. The required sets are:
macvlan/macvtap: {mac-family}
ipvlan L2: {ipvlan-l2}
ipvlan L3: {ipvlan-l3}
VLAN: {mac-family, ipvlan-l2, ipvlan-l3}The VLAN set requires three groups and is rejected by API validation. This cannot be fixed by adding one common vlan-compatible token to the other personas: that token would also make the three conflicting families compatible with each other. More generally, one neutral persona that must intersect three pairwise-disjoint families needs at least three group tokens. Example 10 avoids this limit by approving only ipvlan l2/bridge, leaving two families for the VLAN persona.
The domain limit is reachable when one persona needs three independently scoped scheduler predicates. A multi-function NIC can require all of the following:
- An immediate-lower
interface-modedomain for mac-family, ipvlan and direct handoff. - A PF
pf-accessfamily domain for PF passthrough versus that PF’s VFs. - A separate reset, embedded-switch or controller-mode domain spanning another set of functions or PFs.
The first two consume Example 10’s two entries. A third consumesCounters entry is rejected. Merging the third constraint into pf-access is valid only when both domains have the same members and the combined compatibility relation still needs at most two tokens per persona. Shared reset and controller scopes commonly cross PF-family boundaries, so that equivalence cannot be assumed. If the protection graph can treat the third relationship as an execution-safety boundary, reject unsafe operations there. If simultaneous DRA consumers require scheduling-time exclusion across that third boundary, the current API cannot represent the profile losslessly.
3.3 Local Capacity and the Non-Binding Membership Counter
The upstream field attaches to consumesCounters[]; a compatibility-only relationship still needs a valid counter-set association. This design generates one positive bookkeeping counter named members per compatibility domain. It is not a lock and not a per-Pod quota.
Let N be the number of distinct published persona/device identities referencing a domain, including retained active entries. Publish members = max(1, N) and a fixed consumption of members: "1" for each member. Do not shrink this bookkeeping total during an active drain transition. Normal allocation permits at most one active fixed charge per member identity, so the counter itself does not decide which modes may coexist. Compatibility groups do. S1 S4
For two macvlan/ipvlan personas, members: "2" intentionally leaves enough numerical capacity for both. Their disjoint groups still prevent coexistence.
| Quantity | Role | Consumption |
|---|---|---|
Local capacity.macvlans | Number of macvlan allocation units | Per allocation; examples use one. |
Domain members | Valid counter-set association with non-binding accounting | Fixed charge once per active device identity in the inspected baseline. |
| Optional shared bandwidth | A real shared resource budget | Per allocation only with the separately supported shared-consumable feature. |
A local quota applies to one persona identity. Publishing two compatible aliases with independent local quotas does not create a single aggregate hardware limit. Use one canonical persona for the same allocation contract, explicitly partition the administrator budget, or introduce a genuine shared budget in the follow-on profile. Do not represent the same 64 physical units as two independent 64-unit guarantees.
The old cross-drain model is removed. Local capacity does not automatically decrement a similarly named shared counter. In the old example, allocating macvlan drained the ipvlan mirror but left the macvlan mirror available, so ipvlan could consume that other mirror. Merely charging the fixed amount once did not create mutual exclusion.
3.4 Allocation and Release Lifecycle
With stable publication, the inspected implementation detects that a shared device remains allocated after one of its claims is released. It reconstructs the compatibility baseline using that active device and its live group declarations. The compatibility restriction is not attached to the first claim’s private counter snapshot. S4 S5
| Event | Macvlan allocations | IPvlan result |
|---|---|---|
| Initial | 0 | May allocate. |
| Allocate A | 1 | Blocked. |
| Allocate B on the same macvlan device | 2 | Blocked. |
| Release A; keep B | 1 | Still blocked. |
| Reconstruct scheduler state or restart the driver | 1 | Must remain blocked. |
| Release B and complete cleanup | 0 | May allocate. |
“Allocation released” means the scheduler no longer considers the ResourceClaim allocation active. Pod termination or a driver-local reference count reaching zero is not, by itself, sufficient evidence. One claim may serve multiple Pods; a capacity of 64 means 64 one-unit allocation results, not necessarily 64 Pods. Prefer per-Pod ResourceClaimTemplates where a per-Pod budget is intended. S7
This is not a claim that PR #140084’s static-counter lifetime issue has been fixed. The baseline does not depend on that PR. A combined build must get its own regression tests.
3.5 Feature-Disabled and Unsupported-Cluster Behavior
The baseline requires compatibility support whenever incompatible personas are exposed. Do not remove the group field and publish the same alternatives as a fallback. The API server can strip disabled feature fields; the scheduler can skip slices containing unsupported groups, and a skipped slice can make a pool incomplete. Neither behavior is a substitute for a driver capability contract. S3 S6
Installation must verify the selected API server and scheduler configuration. An explicit deployment capability setting plus API round-trip validation and a controlled scheduler conformance test is preferable to guessing from a version string or OpenAPI schema alone. A schema can describe fields whose feature gates are disabled.
For an unsupported cluster, a separately selected reduced profile may expose only one preselected mode per actual exclusion domain. It must not expose PF passthrough together with active child uses. Node-side checks remain required. This is a deliberate reduced feature profile, not an automatic downgrade of the same policy set.
4. How the Driver Uses Policies
The driver compiles discovered facts and winning policies into a complete desired pool model, validates it, then reconciles it against active allocations.
4.1 Attribute Translation
Discovered facts use the dra.networking domain, except explicitly standardized attributes such as device.k8s.io/pcieRoot. Values below are observations, not inferred NetworkPlugin capabilities. This table defines the supported normalized attribute vocabulary; a ResourceSlice may publish a selection-relevant subset within its attribute limit. Internal inventory retains the complete observation/provenance record, including facts omitted from the illustrative slices.
| Discovered fact | Published attribute | Discovery input |
|---|---|---|
| Interface name, when attached to a verified host endpoint | dra.networking/ifName | Netlink joined to the inventory identity; never synthesized for VFIO/unbound functions. |
| MAC address | dra.networking/mac | Current verified netdevice observation; not a physical identity key. |
| MTU | dra.networking/mtu | Current netdevice observation; omitted when unavailable. |
| Link speed, when known | dra.networking/linkSpeed | Driver/ethtool observation, documented in Mbps. |
| Operational state | dra.networking/operState | Netlink. |
| PCI BDF | dra.networking/pciAddress | PCI enumeration, independent of a host netdevice; a current locator, not replacement-proof identity. |
| NUMA node | dra.networking/numaNode | PCI sysfs topology, when meaningful. |
| PCIe root | device.k8s.io/pcieRoot | PCI topology walk. |
| Vendor and product IDs | dra.networking/vendor, dra.networking/product | PCI identifiers. |
| Bound driver | dra.networking/driver | Sysfs driver association, including approved VFIO drivers; omitted when unbound or unknown. |
| Binding state | dra.networking/bindingState | kernel, vfio, unbound, or unknown; failed reads do not mean unbound. |
| Resource classification | dra.networking/type | Discovered pf/vf/bridge/vlan/bond/nic, or unknown until classification is established; not inferred from interface naming. |
| RDMA association | dra.networking/rdma | Validated netdevice/RDMA relationship. |
| SR-IOV capability and configured VF count | dra.networking/sriovCapable, dra.networking/numVFs | PF sysfs facts. |
| Parent PF and VF index | dra.networking/pfPCIAddress, dra.networking/vfIndex; optional dra.networking/pfName | Reciprocal physfn / virtfnN relationships identify the parent/index; pfName additionally requires a verified host PF endpoint. |
| Bridge facts | dra.networking/bridgeName, bridgeType, vlanFiltering | Supported bridge discovery backend. |
| Master bridge | dra.networking/masterBridge | Master relationship, resolved to a bridge where appropriate. |
Unknown is not zero. Omit unavailable speed, MAC, MTU, NUMA, RDMA, interface-name and parent-name attributes; normalize a reported unknown NUMA value to absence rather than node zero. rdma: false requires an authoritative negative observation, not a failed query. masterBridge: "" means a verified host endpoint has no bridge master; it does not mean no bond, controller or external owner. Omit masterBridge when the endpoint or relationship is unknown. Selectors must guard optional attributes with has(...); a cold VFIO function must not make an unrelated kernel-interface selector fail through an unguarded missing key.
Discovery must not forget a device solely because the driver moved it out of the host network namespace or changed its kernel binding. Preserve an allocation-aware inventory record and reconcile against node execution state.
4.1.1 Cold Inventory and Observation Sources
This is the proposed implementation contract resolving research finding F12. No discovery backend, host ownership adapter or hardware conformance suite is implemented by this document. Inventory visibility and permission to allocate are separate: the initial kernel execution profiles include exclusive VFs and explicitly delegated shared parents; VFIO and unbound functions are discovered but stay unavailable unless a separately certified execution profile accepts them. These hardware/effect boundaries preserve the selected alpha-capability baseline and do not introduce a static/reduced inventory fallback.
The scanner performs read-only discovery. It must not bind a driver, enable VFs, reset hardware, create links or change namespaces to make inventory easier to observe. Linux exposes PCI records independently of network interfaces and exposes PF/VF relationships through PCI sysfs. S13 S14
| Input | Required observation | Completeness rule |
|---|---|---|
/sys/bus/pci/devices | Canonical function path/BDF, IDs/class, driver link, parent PCI topology, available immutable hardware evidence | Enumerate network candidates and all functions needed for dependency boundaries, including non-network peers. A vanished or unreadable entry makes the affected observation incomplete. |
| PCI SR-IOV sysfs | physfn, reciprocal virtfnN, supported/configured VF counts where available | Resolve VF identity without ifName or pfName. A missing/mismatched reciprocal link is unresolved topology, not a standalone free VF. |
| Rtnetlink and netdevice sysfs | Namespaced link identity, kind, lower link, master membership, addresses, routes and rules | Join endpoints to functions using observed device relationships. Distinguish a real VF endpoint from a representor. Dump interruption/event loss invalidates the affected graph until rescan. |
| Devlink and approved driver adapters | Port/controller/function mapping, representors, eswitch ownership and documented operation boundaries | Use supported identifiers and topology, not parsing interface names. Missing adapter support prevents operations requiring those relationships. |
| RDMA observations | Verified device/port-to-function/netdevice mapping | Absence and query failure differ. RDMA execution remains a separate profile. |
| IOMMU and reset evidence | Function group membership and operation-specific reset scope | Record separate typed boundaries. The scanner never discovers a reset footprint by resetting hardware. |
| Protected host configuration and owner adapters | Management/primary-network roots, allocated devices, external ownership and their observed revisions | Required owner coverage must be complete for the candidate’s possible effects. Unsupported/expired ownership information is not “unowned.” |
A FunctionRecord contains a durable physical-resource ID, current locator, identity/presence epoch, classification, binding state and evidence with provenance. It has zero or more EndpointRecord links. An endpoint carries its namespace incarnation, observed link identifier, kind and function/port association; a software interface has its own inventory identity without a fabricated PCI parent. Do not select the first netdevice if a function has several ports or representors. The initial one-endpoint profile rejects that ambiguity; wider profiles must declare the port and function ownership boundaries explicitly.
Each observation records Known, Unknown or Stale, the source and collection revision. A completed scan has an inventoryGeneration and a dependency-graph digest; those are internal driver values, not a kernel-wide atomic snapshot. Reconcile dumps with events and repeat reads when relationships change. Never join observations from different namespace or function incarnations merely because an ifindex or BDF matches. Kernel link/port identifiers aid correlation; they do not certify continuous ownership across disappearance or reboot. S15 S16
4.1.2 Durable Identity and Replacement Uncertainty
The durable resource ID is an opaque, persisted ID scoped to the Kubernetes Node UID and this host installation’s persisted identity. BDF, ifname, ifindex, MAC, VF index, vendor/product IDs and IOMMU group number are locators or observations; none alone proves continuity. Store the evidence used to correlate them and its uncertainty. A boot ID distinguishes observation incarnations; it does not by itself replace the physical-resource ID.
The identity record has a monotonic presenceEpoch, separate from inventoryGeneration, policy revision and ResourceSlice pool generation. Published device/pool names and active claim mappings remain pinned to their committed identity epoch. The following transition rules apply:
- An observed rename or an authorized, journaled namespace move/driver rebind retains the resource ID and epoch when function/endpoint continuity is verified. Update locators; keep the old allocation contract.
- Hardware replacement, a confirmed function removal/recreation, or VF destroy/recreate requires a new epoch. Reusing the same BDF, VF index or ifname never authorizes the new incarnation to satisfy an old allocation. Keep the old record as a tombstone while claims, cleanup or external references remain.
- Reboot, missed events or conflicting evidence produce
IdentityUncertainuntil the approved hardware profile can correlate the device and reconcile outstanding ownership. Matching vendor/product/MAC values alone cannot resolve it. Where reliable continuity evidence is unavailable, require maintenance recovery; do not guess. - On first installation, persist the initial identity before publication, after a complete scan and ownership check. Cold VFIO/unbound discovery must work without a prior execution journal. Their visibility does not authorize rebinding or DMA access. Lost identity storage, a new Node UID or host reinstall does not make previous allocations/reservations disappear: quarantine affected resources until recovery establishes their disposition.
Multiple aliases of one endpoint share its ownership identity. Different endpoints of one function retain a common function boundary for effects such as rebinding. Stable published names use the persisted mapping and collision-checked DNS encoding described in Section 4.3. An uncertain candidate receives no new allocatable entry; an already allocated identity remains represented under the drain contract, with new use blocked and diagnostics attached.
4.1.3 Protection Graph and Authoritative Roots
The driver maintains a typed graph separate from DRA compatibility domains. Its vertices include PCI functions, network endpoints/software links, RDMA resources, controller-managed objects and ownership records. Every edge records provenance, current identity epochs and which effects it can propagate.
Use consumer → dependency direction: a VLAN depends on its lower link; a bridge or bond depends on its member links; an endpoint depends on its PCI function; a VF depends on specified PF services. Master membership also constrains the member: detaching/moving it changes the master’s dependency. Keep representor-to-represented-function and eswitch-control edges distinct from endpoint-to-function edges. A representor is a separate network/control object, not another free alias of the represented VF. Kernel devlink and representor documentation describe this distinction. S16 S17
IOMMU ownership and reset scopes are typed membership boundaries, not directed network-dependency edges. A group may contain non-network functions. IOMMU grouping does not prove the reset footprint, PF family does not prove the IOMMU boundary, and a common PCI root does not make every operation affect every descendant. VFIO requires suitable DMA ownership; reset methods may have different scopes. S18 S19
Protected roots come from all of the following mandatory inputs for the supported host profile:
- Administrator-protected management endpoints and the approved host routing/policy configuration used for control-plane reachability. Observed addresses/routes/rules and current route lookups supplement this configuration; a default-route-only heuristic is insufficient for policy routing, VRFs or multiple management paths.
- Primary CNI/controller ownership, including approved uplinks, bridges, tunnels, representors and externally provisioned interfaces.
br-intor any other naming convention is only a selector convenience, not ownership proof. - Other device plugins/DRA drivers, host bridges/bonds/VMs and approved external managers. Import authoritative ownership or reserve a static hardware partition that excludes their resources. “No ResourceClaim found for this driver” does not establish freedom from other owners.
- This driver’s allocated/prepared/attached/uncertain resources and cleanup debt, including resources no longer visible in the host namespace.
The proposed internal ProtectionRecord contains an owner identity, root resource IDs/epochs, source revision, protected effects, any explicitly delegated operations and its completeness/freshness rule. The node’s administrator-controlled installation configuration must enumerate required sources/adapters and static partitions; tenant exposure policy cannot assert that an unknown owner is absent. Until a required adapter exists, deny the relevant exposure profile. Loss of a source retains prior protection and blocks new dependent operations; it does not expire the protection into permission.
An action: exclude policy only suppresses direct publication. The compiler does not infer that every excluded VF reserves its entire PF family. Protection propagates from actual ownership/dependency records, with the effect rules below. An operator may separately protect a selected resource against specified effects even if it is not currently allocated.
4.1.4 Effect-Specific Safety Evaluation
An approved plugin contract must describe the bounded effects it may perform in Prepare, Connect, Remove and Unprepare, including driver operations and implicit recovery/cleanup effects. A generic plugin name is not that contract. The node implementation maps those effects to a certified hardware/driver profile; unknown or broader-than-declared effects are unsupported.
For a candidate operation, first compute its impact set by following only the relationships relevant to its declared effects. Then compute the protected dependency set from each protection root along consumer → dependency edges for the same effects. Include master-membership changes explicitly. Deny when these sets intersect without an explicit, applicable owner delegation. A blocked dependency path should be reported, for example management VLAN → bond → PF ← requested rebind. Repeat to a fixed point with cycle detection; unresolved relevant edges or cycles whose impact cannot be established are DependencyUnknown, not empty sets.
| Requested effect | Required expansion/check | Policy consequence |
|---|---|---|
| Read-only inspection | Identity and permitted observation scope; no mutation footprint | May inspect protected inventory without publishing or taking ownership. |
| Create/delete an attachment child on a retained parent | Parent’s delegated shared-child contract, namespace/lower relationships, local capacity and incompatible modes; include any parent configuration writes | An approved shared data parent may be usable while retained on host. Management/primary-owned parents are denied unless their owner explicitly delegates these exact effects. |
| Move/detach/delete a netdevice, change its master, or modify parent MTU/MAC/routes | Selected endpoint, its member/master relationship and relevant dependent uppers/owners | A free kernel VF may move; a management uplink or host bridge/bond member may not. Moving one PF netdevice does not automatically equal destroying every VF. |
| Bind/unbind a PCI function | All endpoints/access objects served by the function plus certified driver effects on PF services, VFs and representors | Deny if any affected object is protected, allocated elsewhere or unresolved. A host-owned representor may block VF handoff even when the VF itself has no master. |
| VF create/destroy, PF-wide configuration or eswitch mode change | Applicable PF family and controller/representor dependencies | Deny while any affected child/owner is active or unknown; the driver must not shrink inventory first to make the check pass. |
| VFIO/IOMMU ownership transition | Full DMA ownership boundary and current owners, including non-network members; separately evaluate bind/reset effects | Deny until the certified VFIO profile proves exclusive authorized ownership. IOMMU membership grants no permission to reset the group. |
| Function/slot/bus reset or recovery that can reset | Actual supported reset method and its certified impact set, with dependent owners | Deny unknown scope or overlap. Never substitute “same PF,” “same IOMMU group,” or “same NUMA node” for verified reset scope. |
The initial profile denies reset, VF creation/destruction, arbitrary PCI rebinding and external-controller mutation. Later profiles must supply evidence and owner coordination before advertising them. Host-retained and destructive operations on the same hardware can therefore have different answers. Safety checks do not create scheduler reservations for external owners or extra cross-pool compatibility domains. If simultaneous DRA consumers need a constraint that the two supported scopes cannot express, reject that publication profile instead of depending on late local rejection for normal scheduling.
4.1.5 Publication, Preparation and Changed Dependencies
Before publication, compile every advertised persona/plugin against the complete identity graph, protection records and certified effect profile. Persist its identity epoch and contract fingerprint. Report IdentityUncertain, DependencyUnknown, ProtectedDependency or UnsupportedEffect with the policy, proposed operation and dependency path. The fingerprint records evidence, not a claim that Linux host changes are atomically locked.
Before Prepare and again before every later mutation, resolve the allocated resource through the committed mapping; acquire deterministic resource/domain locks; refresh relevant identity, ownership and effect-boundary observations; and compare with the permitted contract. Safe observation-only changes, such as a verified rename, may update locators. A new protected dependent, changed ownership epoch, vanished peer or unverified replacement blocks the operation before side effects. Revalidate between steps when the preceding step can alter relevant topology.
On a safety-relevant change, block new use of all affected personas, retain allocated declarations and enter PendingDrain/recovery. Do not destroy a live attachment or delete its governing compatibility groups merely because new desired policy excludes it. Cleanup must use the historical operation scope but also verify current identity/ownership; never restore settings onto replacement hardware. If safe reversal cannot be established, retain cleanup debt and quarantine.
Local locks coordinate this driver’s work only. Required host controllers must honor the configured maintenance/ownership handoff; arbitrary privileged host mutations cannot be fenced by a ResourceSlice or a netlink rescan. A deployment that cannot establish disjoint ownership or coordinate a relevant owner must reject that effect profile; it cannot silently remove requested capabilities or exclusion constraints. The separate durable publication-transition work in Section 8 remains required; this contract does not claim to solve scheduler/watch races.
4.2 Policy-Driven Fields
| Output | Source / transformation |
|---|---|
| Device name | Pinned resource/endpoint identity and presence epoch plus winning suffix; never derived solely from a current host ifname. |
allowMultipleAllocations | Copy from policy. |
Local capacity | Policy quantities and request policies; qualify names consistently. |
dra.networking/supportedNetworkPlugins | Names from exposure.supportedNetworkPlugins[].name, serialized as {strings: [...]}. |
| Additional attributes | Validated non-reserved policy metadata, converted to typed attribute values. |
| Counter-set reference | Resolved (pool, scope root, domain) binding. |
compatibilityGroups | Copy the binding’s groups after validation. |
Domain members total | Number of referencing published identities, including retained entries. |
Fixed members consumption | One per referencing identity. |
attributes and capacity are direct fields under a v1 device entry. Do not wrap them in basic. Counter definitions and device entries belong in different ResourceSlice objects. S1
4.3 Topology Resolution and Pool Layout
One PF and its VFs form a pool. Standalone interfaces use standalone pools unless a separately supported topology relationship requires a common pool. Domain comparisons never cross pool boundaries.
For scope: interface, resolve the stable endpoint/resource identity defined in Section 4.1, even when no host ifname exists. For scope: sriovFamily, use the verified parent PF root for both the PF and all of its VFs. The driver discovers these relationships but does not invent mode groups. Profiles with several endpoints sharing a broader function mutation boundary need an explicit supported allocation guard; the initial profile rejects ambiguous multi-port exposure.
A domain key is:
(driver, pool identity, resolved scope-root identity, administrator domain name)The counter-set name is a stable DNS-label encoding of this key within its pool. The implementation must define deterministic normalization, truncation and collision handling, for example a readable prefix with a stable hash suffix. Group names remain opaque; do not append each device’s unique identity to a shared group token.
The examples use short readable names such as pf0-interface-mode and pf0-family-pf-access. Production identity must not depend only on the current interface name or an unstable enumeration order. Persist the mapping used for active allocations under Section 4.1.2’s identity rules. PCI BDF reuse after hardware replacement must not be mistaken for continuity of the old allocated hardware. A protection graph may cross pools even though scheduler compatibility cannot; such a graph is a safety check, not an unsupported cross-pool counter association.
4.4 Translation Algorithm
INPUT:
complete identity-verified inventory and protection graph,
all relevant policies, certified effect profiles, deployment capabilities,
last committed publication, allocated claims, node execution journal
OUTPUT:
validated desired pools, status/diagnostics, staged publication operations
Phase 1 — Resolve policies and personas
Evaluate node and device selectors.
Apply exclude / deny-by-default rules.
Pick one winner per (inventory resource identity, suffix).
Build candidate persona records without publishing them.
Resolve each advertised plugin's bounded effects and required owner coverage.
Phase 2 — Resolve compatibility domains
Resolve each interface or sriovFamily scope root.
Place family members in the same pool.
Resolve each (root, domain) into one counter-set identity.
Copy groups exactly; do not infer them from NetworkPlugin names.
Require complete guards for aliases and any declared family-exclusive mode.
Phase 3 — Merge lifecycle state
Retain active entries missing from desired discovery/policy results.
Pin their identity, associations, groups and relevant allocation contract.
Mark incompatible policy changes or hardware changes as pending drain.
Retain identity-uncertain and newly protected active resources; block new use.
Do not publish replacement identities that can alias still-active hardware.
Phase 4 — Build resource accounting
Copy local capacities; never mirror them for exclusion.
For each domain, publish members >= its distinct retained/current members.
Add fixed members: 1 consumption to every referencing device entry.
Do not add automatic bandwidth or fair-share defaults.
Phase 5 — Validate the entire pool
Check names, field limits, no duplicate device or counter-set identities.
Check one consumption entry per counter set and at most two per device.
Check local quantities, group membership, aliases and feature capabilities.
Check each effect footprint against protected dependencies and owner delegations.
Reject unknown identity, incomplete relevant graph or unsupported effects.
Fail closed on invalid compilation; report the policy and domain involved.
Phase 6 — Pack and publish
Pack counter sets into counter-bearing slices.
Pack devices into device-bearing slices.
Set the same pool name, generation and total resourceSliceCount on all.
Reconcile through the upstream ResourceSlice controller where practical.
Retain old active declarations through transitions; reconcile partial writes.
Phase 7 — Observe and retire
Reconcile allocated claims, host ownership and node execution state continuously.
Remove retired declarations only after the drain/cleanup conditions pass.A pool.generation change allows readers to distinguish pool generations; it is not a multi-object transaction or an instruction to revoke existing claims. Publication must recover from incomplete generations and asynchronous watches. S1 S7
4.5 Optional Follow-On: Shared Bandwidth Budgets
The baseline publishes linkSpeed as a fact and makes no aggregate bandwidth reservation guarantee. The original automatic bandwidth and fair-share logic is removed from the baseline rather than presented as implemented functionality.
If bandwidth reservations are added later, use explicit administrator-supplied budgets and KEP 5941’s request-driven shared consumption. Every traffic consumer intended to participate in that budget must be included: accounting only for VFs while PF macvlan traffic is unaccounted for is not a whole-link reservation model.
The following is an experimental future wire-format fragment, not part of the initial DeviceExposurePolicy schema or baseline manifests. It follows PR #140084 at 51d78febb379ae41f7487a50b9718a4ede0e3f3c; that PR uses valueFrom.capacityName, not capacityKey. S8
# Counter-bearing ResourceSlice.spec fragment, future feature profile.
sharedCounters:
- name: pf0-family-pf-access
counters:
members:
value: "10"
bandwidth:
value: "100000" # Contract: Mbps, explicitly configured by admin.
requestPolicy:
default: "1000"
validRange:
min: "100"
max: "100000"
step: "100"# One member's device fragment, future feature profile.
consumesCounters:
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters:
members:
value: "1"
bandwidth:
valueFrom:
capacityName: dra.networking/bandwidth# ResourceClaim request fragment for that future feature profile.
exactly:
deviceClassName: network-vf-pf0
capacity:
requests:
dra.networking/bandwidth: "2500"Reuse a compatible existing domain counter set where appropriate; do not add a third counter-set association to a device that already uses two. Define one authoritative budget specification and conflict resolution before implementing policy-to-budget translation. Capacity accounting alone also does not configure a hardware rate limit: scheduling reservation and enforcement are separate contracts.
The PR’s fixed-versus-per-share accounting, release behavior, feature transitions and combination with KEP 5963 must be retested on the actual combined code. Do not make baseline mode exclusion depend on a presumed fix in that PR.
4.6 ResourceSlice Packing Rules
In the inspected v1 API: S1
spec.devicesandspec.sharedCountersare mutually exclusive in one object.resourceSliceCountis the total number of ResourceSlices in the pool generation, including both kinds of slices.- A device has at most two
consumesCountersentries, one per referenced counter set; each has at most two compatibility group names. - One counter-bearing slice has at most eight counter sets, each with at most 32 counters.
- Use at most 64 devices per slice when counters, list attributes or other applicable advanced features are used. Validate the target API’s combined attribute/capacity and list-value limits too.
Do not duplicate a counter set in each device slice. Split the inventory into additional slices and update the total count when limits require it.
4.7 Capacity Requests and the Topology Contract
The scheduler does not execute our policies or choose an amount based on a NetworkPlugin name. It reads local requestPolicy and any ResourceClaim capacity requests. Consequently, the baseline fixes each example’s default and allowed amount to one unit and requires all listed NetworkPlugin alternatives to agree with that amount. S1 S7
A request for four units reserves four units; it does not automatically cause the execution engine to create four interfaces. Supporting variable quantities requires an explicit topology/execution contract and generated or user-authored capacity.requests. This is why the examples no longer advertise a one-to-four range while describing exactly one interface per allocation.
DeviceClass selectors select suitable devices but do not create plugin-specific capacity requests. The no-extra-capacity-fields application experience relies on consistent per-device defaults, not hidden scheduler interpretation of consumePerAllocation.
5. Examples
The nine scenarios from the original document are retained. Policy fields are the proposed API in Section 2; ResourceSlice examples use the inspected upstream v1 shape. Examples labelled fragment are not complete Kubernetes objects. Complete objects and every reference VF appear in Section 6.
Interface names, PCI addresses, capacities and speeds are illustrative inventory values from the reference scenario, not discovery defaults or vendor guarantees. The actual driver must use observed identities and administrator-selected limits. The kernel-interface policies guard optional name/master attributes; cold VFIO/unbound inventory needs a separately approved profile and PCI/identity-based selection. ResourceSlice fragments show the allocation layer, not the internal identity, protection or owner records required before publication.
5.1 Example 1: Simple SR-IOV VFs
Scenario: VFs under enp3s0f0 support sriov. Each VF is a normal, exclusively allocated DRA device. Normal use of the family is explicitly labelled host-retained.
DeviceExposurePolicy
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: sriov-vfs-pf0
spec:
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].pfName) &&
device.attributes["dra.networking"].type == "vf" && device.attributes["dra.networking"].pfName == "enp3s0f0"
action: expose
exposure:
allowMultipleAllocations: false
supportedNetworkPlugins:
- name: sriov
compatibility:
- scope: sriovFamily
domain: pf-access
groups:
- host-retainedResulting ResourceSlice Fragments
This scenario exposes eight VFs and no PF persona, so the family domain has eight member identities. A future PF persona must use a compatible family declaration or be drained into a new configuration before publication.
Counter-bearing ResourceSlice.spec fragment:
sharedCounters:
- name: pf0-family-pf-access
counters:
members:
value: '8'Device-bearing ResourceSlice.spec fragment (same pool):
devices:
- name: enp3s0f0v0
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f0v0
dra.networking/pfName:
string: enp3s0f0
dra.networking/vfIndex:
int: 0
dra.networking/pciAddress:
string: '0000:03:00.2'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
consumesCounters:
- counterSet: pf0-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'The remaining seven VF entries use the same family group and each consume one member. VFs are independently allocatable because they are distinct devices with the same group. A VF is exclusive because allowMultipleAllocations is false/omitted, not because its plugin declaration has a custom exclusive flag. There is no automatic numVFs + 1 lock counter.
5.2 Example 2: SR-IOV VFs with Multiple NetworkPlugin Options
Scenario: A VF may be selected for sriov or host-device. The two names are execution alternatives for one exclusive entry, not permission to allocate the VF twice. The scenario assumes the execution path validates each plugin’s configuration requirements.
DeviceExposurePolicy
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf0-vfs
spec:
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].pfName) &&
device.attributes["dra.networking"].type == "vf" && device.attributes["dra.networking"].pfName == "enp3s0f0"
action: expose
exposure:
allowMultipleAllocations: false
supportedNetworkPlugins:
- name: sriov
- name: host-device
compatibility:
- scope: sriovFamily
domain: pf-access
groups:
- host-retainedResulting ResourceSlice Fragments
Counter-bearing ResourceSlice.spec fragment:
sharedCounters:
- name: pf0-family-pf-access
counters:
members:
value: '8'Device-bearing ResourceSlice.spec fragment (same pool):
devices:
- name: enp3s0f0v0
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f0v0
dra.networking/pfName:
string: enp3s0f0
dra.networking/vfIndex:
int: 0
dra.networking/pciAddress:
string: '0000:03:00.2'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
- host-device
consumesCounters:
- counterSet: pf0-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'The supported-NetworkPlugin list is serialized with strings. A generated DeviceClass can use device.attributes["dra.networking"].supportedNetworkPlugins.includes("sriov") or the corresponding host-device selection. .includes() is the DRA list-aware CEL helper; it does not reserve resources or invoke the plugin. S7
5.3 Example 3: PF as Macvlan Parent
Scenario: enp3s0f1 has no exposed VFs or competing persona in this example. It provides 64 one-unit macvlan allocations. This isolated, single-persona case does not need a compatibility domain.
DeviceExposurePolicy
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf1-macvlan-parent
spec:
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "pf" && device.attributes["dra.networking"].ifName == "enp3s0f1"
action: expose
exposure:
allowMultipleAllocations: true
capacity:
macvlans:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'
supportedNetworkPlugins:
- name: macvlan
consumePerAllocation:
macvlans: '1'Resulting Device Entry
name: enp3s0f1
allowMultipleAllocations: true
attributes:
dra.networking/type:
string: pf
dra.networking/ifName:
string: enp3s0f1
dra.networking/pciAddress:
string: '0000:03:00.1'
dra.networking/mac:
string: 04:3f:72:b0:d4:61
dra.networking/mtu:
int: 1500
dra.networking/linkSpeed:
int: 25000
dra.networking/numVFs:
int: 0
dra.networking/rdma:
bool: true
dra.networking/numaNode:
int: 0
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101d
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- macvlan
capacity:
dra.networking/macvlans:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'Each claim allocation consumes one local unit. A 65th one-unit allocation cannot fit. The capacity is an administrator-defined quota, not an automatically discovered macvlan maximum. Adding another persona later requires a common interface domain and a safe migration of any already-active entry; do not silently attach new groups to existing allocations.
5.4 Example 4: Parent-Interface Software Modes
Scenario: The administrator declares macvlan and ipvlan incompatible on enp3s0f1, as motivated by the original document’s receive-handler conflict. The compiler does not contain that plugin-specific rule. Both modes have independent local limits of 64 allocations.
DeviceExposurePolicy — Macvlan Persona
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf1-macvlan
spec:
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "pf" && device.attributes["dra.networking"].ifName == "enp3s0f1"
action: expose
exposure:
deviceNameSuffix: -macvlan
allowMultipleAllocations: true
capacity:
macvlans:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'
supportedNetworkPlugins:
- name: macvlan
consumePerAllocation:
macvlans: '1'
compatibility:
- scope: interface
domain: interface-mode
groups:
- macvlanDeviceExposurePolicy — Ipvlan Persona
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf1-ipvlan
spec:
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "pf" && device.attributes["dra.networking"].ifName == "enp3s0f1"
action: expose
exposure:
deviceNameSuffix: -ipvlan
allowMultipleAllocations: true
capacity:
ipvlans:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'
supportedNetworkPlugins:
- name: ipvlan
consumePerAllocation:
ipvlans: '1'
compatibility:
- scope: interface
domain: interface-mode
groups:
- ipvlanResulting ResourceSlices — Two Objects in One Pool
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: worker-1-pf1-mode-example-counters
spec:
driver: dra.networking
pool:
name: worker-1-pf1-mode-example
generation: 1
resourceSliceCount: 2
nodeName: worker-1
sharedCounters:
- name: pf1-interface-mode
counters:
members:
value: '2'
---
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: worker-1-pf1-mode-example-devices
spec:
driver: dra.networking
pool:
name: worker-1-pf1-mode-example
generation: 1
resourceSliceCount: 2
nodeName: worker-1
devices:
- name: enp3s0f1-macvlan
allowMultipleAllocations: true
attributes:
dra.networking/type:
string: pf
dra.networking/ifName:
string: enp3s0f1
dra.networking/pciAddress:
string: '0000:03:00.1'
dra.networking/mac:
string: 04:3f:72:b0:d4:61
dra.networking/mtu:
int: 1500
dra.networking/linkSpeed:
int: 25000
dra.networking/numVFs:
int: 0
dra.networking/rdma:
bool: true
dra.networking/numaNode:
int: 0
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101d
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- macvlan
capacity:
dra.networking/macvlans:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'
consumesCounters:
- counterSet: pf1-interface-mode
compatibilityGroups:
- macvlan
counters:
members:
value: '1'
- name: enp3s0f1-ipvlan
allowMultipleAllocations: true
attributes:
dra.networking/type:
string: pf
dra.networking/ifName:
string: enp3s0f1
dra.networking/pciAddress:
string: '0000:03:00.1'
dra.networking/mac:
string: 04:3f:72:b0:d4:61
dra.networking/mtu:
int: 1500
dra.networking/linkSpeed:
int: 25000
dra.networking/numVFs:
int: 0
dra.networking/rdma:
bool: true
dra.networking/numaNode:
int: 0
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101d
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- ipvlan
capacity:
dra.networking/ipvlans:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'
consumesCounters:
- counterSet: pf1-interface-mode
compatibilityGroups:
- ipvlan
counters:
members:
value: '1'Walkthrough
| Event | Remaining numerical members | Local macvlan units remaining | Group state / outcome |
|---|---|---|---|
| Initial | 2 | 64 | No active mode. |
| First macvlan claim | 1 | 63 | Active group is macvlan. |
| Second macvlan claim | 1 | 62 | Same device; no new fixed member charge. |
| Try ipvlan | 1 | 62 | Numerical member capacity is sufficient, but groups do not intersect: rejected. |
| Release the first macvlan claim | 1 | 63 | Second claim keeps macvlan active; ipvlan remains rejected. |
| Release the last macvlan claim | 2 | 64 | No active mode; ipvlan can allocate. |
These are expected outcomes from the model, not a report of a cluster test performed for this document. The acceptance suite must verify them across successive allocation cycles and state reconstruction.
5.4.1 Linux Constraints for VLAN, Ipvlan, Macvlan and Macvtap
The NetworkPlugin name alone is not enough to determine compatibility. Compatibility depends on the lower netdevice and the requested mode. For the same immediate lower netdevice, the initial certified profile uses this matrix:
| Active child type | VLAN child | Ipvlan child | Macvlan child | Macvtap child |
|---|---|---|---|---|
| VLAN child | Compatible when (protocol, VLAN ID) ownership does not conflict | Compatible | Compatible | Compatible |
| Ipvlan child | Compatible | Compatible only when all children use the same approved port-wide mode and flags | Incompatible | Incompatible |
| Macvlan child | Compatible | Incompatible | Compatible for approved non-passthru modes and unique MAC addresses | Compatible for approved non-passthru modes and unique MAC addresses |
| Macvtap child | Compatible | Incompatible | Compatible for approved non-passthru modes and unique MAC addresses | Compatible for approved non-passthru modes and unique MAC addresses |
Linux permits only one receive handler on a netdevice. Ipvlan rejects a new port when the selected lower already has a receive handler. Macvlan installs its receive handler on that same lower. Therefore ipvlan cannot share one immediate lower with macvlan or macvtap. Macvtap is implemented through macvlan_common_newlink, so normal macvlan and macvtap children share the macvlan port rather than competing for separate lower-device receive handlers. S21 S22 S23
This compatibility is conditional:
- Ipvlan mode and flags belong to the ipvlan port on the lower device. A profile must pin one combination, such as
l2/bridge, for all concurrent ipvlan children. Separatel2,l3, orl3spersonas on the same lower are mutually exclusive. - Macvlan/macvtap
passthruis an exclusive port mode and must not share the normalmac-familygroup. Publish it as an exclusive persona with a disjoint group. Other mode combinations still require target-kernel tests. - A VLAN child is a stacked netdevice and does not consume the lower’s sole receive-handler slot. Distinct VLAN IDs can coexist, but the plugin must serialize and journal
(lower identity, 802.1Q/802.1ad protocol, VLAN ID)ownership. It must not assume that two requests can independently create the same VLAN link. S24 - NIC unicast-filter limits, switch policy, MTU, offload support, tap-minor availability and administrator quotas remain platform or policy limits. Discovery cannot derive a portable maximum for these child types.
5.4.2 Four Personas on One Discovered PF
Assume discovery observes one verified parent and no pre-existing software children:
FunctionRecord pf1: 0000:03:00.1, mlx5_core, presenceEpoch 7
EndpointRecord: enp3s0f1, ifindex incarnation 12, Ethernet, MTU 1500
Existing uppers: none
Receive-handler owner: noneDiscovery publishes facts about the parent. Policy supplies child-creation permission, approved modes and quotas. It does not discover 64 VLANs, ipvlans, macvlans, or macvtaps from the NIC. The compiler may produce these four persona entries when the execution profile approves VLAN creation, ipvlan l2/bridge, macvlan bridge, and macvtap bridge:
| Persona suffix | Logical plugin | Pinned execution contract | Interface group membership |
|---|---|---|---|
-vlan | vlan | Create an authorized 802.1Q/802.1ad child with journaled protocol and VLAN ID ownership | [mac-family, ipvlan-l2] |
-ipvlan-l2 | ipvlan | l2/bridge on this lower | [ipvlan-l2] |
-macvlan | macvlan | bridge, non-passthru | [mac-family] |
-macvtap | macvtap | bridge, non-passthru, with tap lifecycle management | [mac-family] |
sharedCounters:
- name: pf1-interface-mode
counters:
members:
value: '4'
---
devices:
- name: enp3s0f1-vlan
allowMultipleAllocations: true
attributes:
dra.networking/supportedNetworkPlugins:
strings: [vlan]
capacity:
dra.networking/vlans:
value: '64'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf1-interface-mode
compatibilityGroups: [mac-family, ipvlan-l2]
counters:
members: {value: '1'}
- name: enp3s0f1-ipvlan-l2
allowMultipleAllocations: true
attributes:
dra.networking/supportedNetworkPlugins:
strings: [ipvlan]
dra.networking/ipvlanMode:
string: l2
dra.networking/ipvlanFlags:
string: bridge
capacity:
dra.networking/ipvlans:
value: '64'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf1-interface-mode
compatibilityGroups: [ipvlan-l2]
counters:
members: {value: '1'}
- name: enp3s0f1-macvlan
allowMultipleAllocations: true
attributes:
dra.networking/supportedNetworkPlugins:
strings: [macvlan]
dra.networking/macvlanMode:
string: bridge
capacity:
dra.networking/macvlans:
value: '64'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf1-interface-mode
compatibilityGroups: [mac-family]
counters:
members: {value: '1'}
- name: enp3s0f1-macvtap
allowMultipleAllocations: true
attributes:
dra.networking/supportedNetworkPlugins:
strings: [macvtap]
dra.networking/macvlanMode:
string: bridge
capacity:
dra.networking/macvtaps:
value: '64'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf1-interface-mode
compatibilityGroups: [mac-family]
counters:
members: {value: '1'}ipvlanMode, ipvlanFlags, and macvlanMode in this example are compiled contract-selection attributes. They come from the approved policy/NetworkPlugin revision, not from physical-device discovery. A production schema must reserve and validate these keys before emitting them.
The VLAN persona needs both permitted-family tokens. This uses the upstream maximum of two groups on one counter-set consumption. Resulting intersections are:
| Active set | Common group | Result |
|---|---|---|
| VLAN + ipvlan L2 | ipvlan-l2 | Permit. |
| VLAN + macvlan | mac-family | Permit. |
| VLAN + macvtap | mac-family | Permit. |
| Macvlan + macvtap | mac-family | Permit. |
| Ipvlan + macvlan or macvtap | None | Reject. |
| VLAN + ipvlan + macvlan or macvtap | None | Reject because the child families conflict. |
This encoding stops scaling when the VLAN persona must be neutral across three incompatible child families. It also stops scaling if multiple incompatible ipvlan port modes must coexist as alternatives: VLAN would need mac-family, ipvlan-l2, and ipvlan-l3, exceeding the two-group limit. Select one ipvlan contract per lower, use separate real lower netdevices, or reject the profile. Splitting one physical parent into synthetic DRA names does not remove the kernel conflict.
The four local capacities are independent administrator quotas. They do not prove that the parent supports 256 simultaneous children or impose one aggregate child limit. Use a genuine shared budget when an aggregate limit is required.
5.4.3 Pre-existing VLAN Lowers
Discovery may instead observe two administrator-owned VLAN netdevices:
enp3s0f1 (PF endpoint, 0000:03:00.1)
+-- enp3s0f1.100 (kind vlan, protocol 802.1Q, id 100)
`-- enp3s0f1.200 (kind vlan, protocol 802.1Q, id 200)The inventory creates separate endpoint records for both VLAN devices and dependency edges from each VLAN endpoint to enp3s0f1. A policy may expose macvlan/macvtap personas rooted at VLAN 100 and an ipvlan persona rooted at VLAN 200:
domain(root=enp3s0f1.100, interface-mode): macvlan [mac-family], macvtap [mac-family]
domain(root=enp3s0f1.200, interface-mode): ipvlan-l2 [ipvlan-l2]These children use different immediate lower netdevices, so they do not contend for one receive-handler slot. They need no common interface-mode counter set. They still share the physical PF dependency. Any operation that changes PF MTU, binding, reset state, VLAN offload state, or ownership must pass the protection graph and any required PF-family compatibility domain.
When the driver creates a child after allocation, it records that child in the allocation journal and dependency graph. It does not publish the created child as new free capacity. On restart, discovery correlates the observed child with the journal, allocation identity and lower endpoint before treating it as managed. An unjournaled pre-existing child is external inventory until policy and ownership sources explicitly authorize it.
5.5 Example 5: PF with Macvlan AND Host-Device Passthrough
Scenario: The same interface supports shared macvlan and a normal exclusive passthrough persona. Keep separate entries to make allocation semantics explicit. It is not necessary to claim that capacity can never model a fixed full-capacity request; the selected design simply does not encode mode compatibility through plugin-specific capacity tricks.
DeviceExposurePolicies
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf0-macvlan
spec:
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "pf" && device.attributes["dra.networking"].ifName == "enp3s0f0"
action: expose
exposure:
deviceNameSuffix: -macvlan
allowMultipleAllocations: true
capacity:
macvlans:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'
supportedNetworkPlugins:
- name: macvlan
consumePerAllocation:
macvlans: '1'
compatibility:
- scope: interface
domain: interface-mode
groups:
- macvlan
---
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf0-passthrough
spec:
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "pf" && device.attributes["dra.networking"].ifName == "enp3s0f0"
action: expose
exposure:
deviceNameSuffix: -passthrough
allowMultipleAllocations: false
supportedNetworkPlugins:
- name: host-device
compatibility:
- scope: interface
domain: interface-mode
groups:
- passthroughResulting ResourceSlice Fragments
Counter-bearing ResourceSlice.spec fragment:
sharedCounters:
- name: pf0-interface-mode
counters:
members:
value: '2'Device-bearing ResourceSlice.spec fragment (same pool):
devices:
- name: enp3s0f0-macvlan
allowMultipleAllocations: true
attributes:
dra.networking/type:
string: pf
dra.networking/ifName:
string: enp3s0f0
dra.networking/pciAddress:
string: '0000:03:00.0'
dra.networking/mac:
string: 04:3f:72:b0:d4:60
dra.networking/mtu:
int: 1500
dra.networking/linkSpeed:
int: 100000
dra.networking/numVFs:
int: 0
dra.networking/rdma:
bool: true
dra.networking/numaNode:
int: 0
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101d
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- macvlan
capacity:
dra.networking/macvlans:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'
consumesCounters:
- counterSet: pf0-interface-mode
compatibilityGroups:
- macvlan
counters:
members:
value: '1'
- name: enp3s0f0-passthrough
attributes:
dra.networking/type:
string: pf
dra.networking/ifName:
string: enp3s0f0
dra.networking/pciAddress:
string: '0000:03:00.0'
dra.networking/mac:
string: 04:3f:72:b0:d4:60
dra.networking/mtu:
int: 1500
dra.networking/linkSpeed:
int: 100000
dra.networking/numVFs:
int: 0
dra.networking/rdma:
bool: true
dra.networking/numaNode:
int: 0
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101d
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- host-device
consumesCounters:
- counterSet: pf0-interface-mode
compatibilityGroups:
- passthrough
counters:
members:
value: '1'Macvlan and passthrough use disjoint groups in the same domain. Passthrough does not drain a mirrored macvlan quota. The same exclusion applies in either allocation order. A second allocation of the passthrough entry is rejected by ordinary device exclusivity.
Multiple exclusive aliases are not safe just because each is individually exclusive. They must also be disjoint from each other in the shared interface domain. Prefer one exclusive entry with several valid NetworkPlugin alternatives when the allocation contract is identical.
5.6 Example 6: PF with VFs + Macvlan + Host-Device
Scenario: PF0 has eight VFs. Shared PF macvlan and child VF use are permitted concurrently. PF passthrough is declared incompatible with either. This is a policy assumption for the reference node, not a blanket hardware claim.
DeviceExposurePolicies
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf0-macvlan
spec:
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "pf" && device.attributes["dra.networking"].ifName == "enp3s0f0"
action: expose
exposure:
deviceNameSuffix: -macvlan
allowMultipleAllocations: true
capacity:
macvlans:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'
supportedNetworkPlugins:
- name: macvlan
consumePerAllocation:
macvlans: '1'
compatibility:
- scope: interface
domain: interface-mode
groups:
- macvlan
- scope: sriovFamily
domain: pf-access
groups:
- host-retained
---
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf0-passthrough
spec:
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "pf" && device.attributes["dra.networking"].ifName == "enp3s0f0"
action: expose
exposure:
deviceNameSuffix: -passthrough
allowMultipleAllocations: false
supportedNetworkPlugins:
- name: host-device
compatibility:
- scope: interface
domain: interface-mode
groups:
- passthrough
- scope: sriovFamily
domain: pf-access
groups:
- pf-passthrough
---
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf0-vfs
spec:
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].pfName) &&
device.attributes["dra.networking"].type == "vf" && device.attributes["dra.networking"].pfName == "enp3s0f0"
action: expose
exposure:
allowMultipleAllocations: false
supportedNetworkPlugins:
- name: sriov
- name: host-device
compatibility:
- scope: sriovFamily
domain: pf-access
groups:
- host-retainedResulting ResourceSlice Fragments
PF0 has ten published member identities in the family: two PF personas and eight VFs. Only the two PF personas belong to its interface-mode domain. The following fragment shows both personas and VF0; Section 6 includes all eight VFs in complete objects.
Counter-bearing ResourceSlice.spec fragment:
sharedCounters:
- name: pf0-interface-mode
counters:
members:
value: '2'
- name: pf0-family-pf-access
counters:
members:
value: '10'Device-bearing ResourceSlice.spec fragment (same pool):
devices:
- name: enp3s0f0-macvlan
allowMultipleAllocations: true
attributes:
dra.networking/type:
string: pf
dra.networking/ifName:
string: enp3s0f0
dra.networking/pciAddress:
string: '0000:03:00.0'
dra.networking/mac:
string: 04:3f:72:b0:d4:60
dra.networking/mtu:
int: 1500
dra.networking/linkSpeed:
int: 100000
dra.networking/numVFs:
int: 8
dra.networking/rdma:
bool: true
dra.networking/numaNode:
int: 0
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101d
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- macvlan
capacity:
dra.networking/macvlans:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'
consumesCounters:
- counterSet: pf0-interface-mode
compatibilityGroups:
- macvlan
counters:
members:
value: '1'
- counterSet: pf0-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'
- name: enp3s0f0-passthrough
attributes:
dra.networking/type:
string: pf
dra.networking/ifName:
string: enp3s0f0
dra.networking/pciAddress:
string: '0000:03:00.0'
dra.networking/mac:
string: 04:3f:72:b0:d4:60
dra.networking/mtu:
int: 1500
dra.networking/linkSpeed:
int: 100000
dra.networking/numVFs:
int: 8
dra.networking/rdma:
bool: true
dra.networking/numaNode:
int: 0
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101d
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- host-device
consumesCounters:
- counterSet: pf0-interface-mode
compatibilityGroups:
- passthrough
counters:
members:
value: '1'
- counterSet: pf0-family-pf-access
compatibilityGroups:
- pf-passthrough
counters:
members:
value: '1'
- name: enp3s0f0v0
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f0v0
dra.networking/pfName:
string: enp3s0f0
dra.networking/vfIndex:
int: 0
dra.networking/pciAddress:
string: '0000:03:00.2'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
- host-device
consumesCounters:
- counterSet: pf0-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'Compatibility Matrix
| Candidate combination | Interface-mode result | PF-family result | Allowed? |
|---|---|---|---|
| PF macvlan + another share of PF macvlan | Same persona/group | Host-retained | Yes, within local capacity. |
| PF macvlan + VF0 | VF0 is outside interface domain | Both host-retained | Yes. |
| VF0 + VF1 | Neither uses PF interface domain | Both host-retained | Yes. |
| PF passthrough + PF macvlan | Disjoint | Disjoint | No. |
| PF passthrough + any VF | VF outside interface domain | Disjoint | No. |
| Another allocation of the same VF | Not relevant | Compatible group | No; the VF entry itself is exclusive. |
An optional PF ipvlan persona would use [ipvlan] on pf0-interface-mode and [host-retained] on pf0-family-pf-access. VFs need no extra macvlan/ipvlan token. This two-domain construction avoids treating an empty VF group as a wildcard or forcing every VF to enumerate all PF modes.
All exclusion in this example is group-based. The baseline has no exclusion-slots, no mirrored macvlan capacity and no bandwidth reservation counter. linkSpeed is still published as an attribute.
5.7 Example 7: VF as Bridge Uplink OR SR-IOV
Scenario: A free VF is directly allocatable after ownership and effect checks. A VF pre-enslaved to a host bridge is not directly allocatable; the bridge is the shared device offered to Pods only when its host owner delegates the approved child-port operations. Bridge ownership is host preconfiguration, not a DRA claim for the hidden VF. The required protection record contains bridge → member VF → relevant PF services; the VF’s empty/nonempty masterBridge attribute is a useful selector, not the whole ownership check.
DeviceExposurePolicies
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: free-vfs-sriov
spec:
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].pfName) &&
has(device.attributes["dra.networking"].masterBridge) &&
device.attributes["dra.networking"].type == "vf" && device.attributes["dra.networking"].pfName == "enp3s0f0" && device.attributes["dra.networking"].masterBridge == ""
action: expose
exposure:
allowMultipleAllocations: false
supportedNetworkPlugins:
- name: sriov
- name: host-device
compatibility:
- scope: sriovFamily
domain: pf-access
groups:
- host-retained
---
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: exclude-bridge-slave-vfs
spec:
priority: 900
selector:
cel: >-
has(device.attributes["dra.networking"].masterBridge) &&
device.attributes["dra.networking"].type == "vf" && device.attributes["dra.networking"].masterBridge != ""
action: exclude
---
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: bridge-sriov-data
spec:
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "bridge" && device.attributes["dra.networking"].ifName == "br-sriov-data"
action: expose
exposure:
allowMultipleAllocations: true
capacity:
ports:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'
supportedNetworkPlugins:
- name: bridge
consumePerAllocation:
ports: '1'
---
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: exclude-pf0-host-bridge-uplink
spec:
priority: 900
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "pf" && device.attributes["dra.networking"].ifName == "enp3s0f0"
action: excludeResulting Bridge Entry
name: br-sriov-data
allowMultipleAllocations: true
attributes:
dra.networking/type:
string: bridge
dra.networking/ifName:
string: br-sriov-data
dra.networking/bridgeName:
string: br-sriov-data
dra.networking/bridgeType:
string: linux
dra.networking/mtu:
int: 9000
dra.networking/supportedNetworkPlugins:
strings:
- bridge
capacity:
dra.networking/ports:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'The final policy deliberately excludes every PF0 persona in this conservative bridge profile. Do not combine it with PF passthrough while the host bridge depends on a child VF. Free sibling VFs can still be exposed under the family policy.
For a free sibling VF, the kernel-interface handoff must be certified not to rebind/reset the PF, reconfigure the eswitch or disturb the bridge-owned VF. If that footprint is unknown or broader, deny publication despite the selector match. Conversely, the PF exclusion does not mean every read or every host-retained operation intrinsically destroys VFs; this example chooses a conservative publication profile.
A hidden VF does not contribute a scheduler compatibility group or consume a counter merely because it is busy outside DRA. Removing one from an advertised quota is not a substitute for an active compatibility declaration. This design does not fabricate a DRA allocation for it. Supporting host reservations with simultaneous PF exposure requires a separate, explicit reservation model; it is outside the baseline.
The node execution path must recheck host ownership before a destructive operation using Section 4.1.5. A newly observed bridge dependency blocks further conflicting use and triggers drain/recovery while active declarations remain pinned. Host-network configuration must be coordinated with DRA: an administrator attaching a bridge to hardware already allocated to a workload is outside the scheduler’s view and cannot be made safe by updating a slice after the fact.
5.8 Example 8: Excluding Cluster CNI and Management Interfaces
Scenario: Named cluster-network and management interfaces are excluded from direct workload allocation. Actual protection also requires owner records and the effect-specific dependency check in Section 4.1; these name filters alone do not protect a lower PF or VF.
DeviceExposurePolicies
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: exclude-cluster-cni
spec:
priority: 1000
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].ifName in ["br-int", "ovn-k8s-mp0", "breth0", "ovn-k8s-gw0"]
action: exclude
---
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: exclude-management
spec:
priority: 1000
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].ifName == "eno1"
action: excludeUnallocated matching interfaces are absent from desired publication. Exclusions win regardless of priority. In addition, protect the administrator-approved management/primary-network roots and resolve their dependencies independently of these filters. If management lives on mgmt.100 → bond0 → enp3s0f0, moving the PF or rebinding its function is denied even when only mgmt.100 is named in an exclusion. A primary-CNI-owned representor requires its controller’s ownership record; an unfamiliar name is not free inventory. Missing relevant route/controller coverage makes the candidate unavailable.
If a newly added exclusion or protected dependency affects an already-allocated device, transition it to drain handling and preserve the active declaration; do not interpret the policy as permission to destroy the running workload’s inventory or network state. A verified rename follows the persisted identity so it does not escape protection.
A hard emergency shutdown is an explicit administrative recovery action, not the ordinary reconciliation behavior.
5.9 Example 9: OVN-Kubernetes Networks via the Generic Driver
Scenario retained as a proposed integration, not an established capability. The examples use ovn as the logical NetworkPlugin identity for a proposed gRPC adapter handling an exclusive VF or shared localnet uplink. Advertise that capability only after the adapter implements and validates the required control-plane and execution contract. The existing ovn-k8s-cni-overlay binary is not the identity or protocol of this adapter.
DeviceExposurePolicy — Candidate Accelerated VF Integration
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: ovnk-accelerated-vfs
spec:
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].pfName) &&
device.attributes["dra.networking"].type == "vf" && device.attributes["dra.networking"].pfName == "enp4s0f0"
action: expose
exposure:
allowMultipleAllocations: false
supportedNetworkPlugins:
- name: ovn
compatibility:
- scope: sriovFamily
domain: pf-access
groups:
- host-retainedDeviceExposurePolicy — Candidate Localnet Uplink Integration
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: ovnk-localnet-uplink
spec:
priority: 150
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "pf" && device.attributes["dra.networking"].ifName == "enp6s0f0"
action: expose
exposure:
deviceNameSuffix: -localnet
allowMultipleAllocations: true
capacity:
connections:
value: '128'
requestPolicy:
default: '1'
validValues:
- '1'
supportedNetworkPlugins:
- name: ovn
consumePerAllocation:
connections: '1'
additionalAttributes:
dra.networking/physicalNetworkName: localnet1Resulting Device Fragments
devices:
- name: enp4s0f0v0
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp4s0f0v0
dra.networking/pfName:
string: enp4s0f0
dra.networking/pciAddress:
string: '0000:04:00.2'
dra.networking/numaNode:
int: 0
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- ovn
consumesCounters:
- counterSet: pf4-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'
- name: enp6s0f0-localnet
allowMultipleAllocations: true
attributes:
dra.networking/type:
string: pf
dra.networking/ifName:
string: enp6s0f0
dra.networking/numaNode:
int: 1
dra.networking/physicalNetworkName:
string: localnet1
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- ovn
capacity:
dra.networking/connections:
value: '128'
requestPolicy:
default: '1'
validValues:
- '1'These entries belong in their respective pools. The VF’s pool must also publish the referenced family counter set with a non-binding membership total for its complete inventory; the standalone localnet example has no competing persona and needs no domain.
Network selection metadata such as physicalNetworkName belongs in published attributes. Strict ovn NetworkPlugin configuration and typed inputs belong to the companion NetworkTopology/execution contract. The integration work must separately verify network-controller provisioning, required annotations and identities, representor ownership, VF handoff, namespace timing, input/output types, effect ownership, cleanup and restart behavior. Reusing existing OVN or CNI implementation code does not change the adapter’s public contract.
Until those checks pass, remove claims such as “no separate OVN-K DRA driver is needed” or “our driver invokes it just like any other plugin” from the implementation guarantees. The discovery policy remains generic; external control-plane integration is not automatically generic.
5.10 Example 10: Maximal PF and VF Multi-Persona Pool
Scenario: PF enp3s0f0 has two VFs. The PF supports shared macvlan, ipvlan, vlan, and macvtap child creation, plus exclusive whole-PF passthrough through the logical host-device plugin. Each VF supports exclusive sriov handoff or shared macvlan, ipvlan, vlan, and macvtap child creation. All ipvlan personas use the pinned l2/bridge contract; all macvlan/macvtap personas use non-passthru bridge mode.
This example uses every available domain association on every persona:
- An interface domain protects alternative uses of the immediate lower netdevice.
- One PF-family domain makes PF passthrough incompatible with every host-retained PF or VF persona.
The example models two VFs to keep the complete output reviewable. Additional VFs repeat the five VF policies and device entries with their own interface counter set, while joining the same family counter set.
Discovered Inventory
PF0 enp3s0f0 0000:03:00.0 presenceEpoch 11
+-- VF0 enp3s0f0v0 0000:03:00.2 presenceEpoch 4
`-- VF1 enp3s0f0v1 0000:03:00.3 presenceEpoch 6
Verified relationships:
enp3s0f0v0 -> PF0 family
enp3s0f0v1 -> PF0 family
no existing software uppers
no receive-handler owner on any of the three immediate lowersThe scanner discovers three hardware-backed endpoints and their PF/VF relationship. Policies create fifteen personas; discovery does not mistake those personas for fifteen physical devices.
Complete Policy Set
Five PF policies select type == "pf" && ifName == "enp3s0f0". Five VF policies select type == "vf" && pfName == "enp3s0f0". Each VF policy produces one persona for each matching VF.
The matrix below is normative shorthand for the ten DeviceExposurePolicy objects. All have priority: 200, action: expose, and the selector for their target row. Each shared row sets allowMultipleAllocations: true, the shown capacity with default: "1" and validValues: ["1"], and matching consumePerAllocation: "1". Exclusive rows set allowMultipleAllocations: false and no local capacity. Mode values are validated additionalAttributes tied to the immutable NetworkPlugin revision.
| Target | Suffix / plugin | Sharing and local quota | Interface groups | Family group |
|---|---|---|---|---|
| PF | -vlan / vlan | Shared, 64 | [mac-family, ipvlan-l2] | [host-retained] |
| PF | -ipvlan-l2 / ipvlan | Shared, 64; fixed l2/bridge | [ipvlan-l2] | [host-retained] |
| PF | -macvlan / macvlan | Shared, 64; fixed bridge | [mac-family] | [host-retained] |
| PF | -macvtap / macvtap | Shared, 64; fixed bridge | [mac-family] | [host-retained] |
| PF | -passthrough / host-device | Exclusive | [passthrough] | [pf-passthrough] |
| Each VF | -sriov / sriov | Exclusive | [sriov] | [host-retained] |
| Each VF | -vlan / vlan | Shared, 16 | [mac-family, ipvlan-l2] | [host-retained] |
| Each VF | -ipvlan-l2 / ipvlan | Shared, 16; fixed l2/bridge | [ipvlan-l2] | [host-retained] |
| Each VF | -macvlan / macvlan | Shared, 16; fixed bridge | [mac-family] | [host-retained] |
| Each VF | -macvtap / macvtap | Shared, 16; fixed bridge | [mac-family] | [host-retained] |
PF policies bind scope: interface plus scope: sriovFamily. VF policies do the same: interface resolves to that VF endpoint, while sriovFamily resolves to PF0. Mode attributes shown below come from the approved policy/NetworkPlugin revision.
Complete Resulting ResourceSlices
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: worker-1-pf0-maximal-counters
spec:
driver: dra.networking
pool:
name: worker-1-pf0-maximal
generation: 1
resourceSliceCount: 2
nodeName: worker-1
sharedCounters:
- name: pf0-interface-mode
counters:
members:
value: '5'
- name: pf0vf0-interface-mode
counters:
members:
value: '5'
- name: pf0vf1-interface-mode
counters:
members:
value: '5'
- name: pf0-family-pf-access
counters:
members:
value: '15'
---
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: worker-1-pf0-maximal-devices
spec:
driver: dra.networking
pool:
name: worker-1-pf0-maximal
generation: 1
resourceSliceCount: 2
nodeName: worker-1
devices:
- name: enp3s0f0-vlan
allowMultipleAllocations: true
attributes:
dra.networking/type: {string: pf}
dra.networking/ifName: {string: enp3s0f0}
dra.networking/supportedNetworkPlugins: {strings: [vlan]}
capacity:
dra.networking/vlans:
value: '64'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf0-interface-mode
compatibilityGroups: [mac-family, ipvlan-l2]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters: {members: {value: '1'}}
- name: enp3s0f0-ipvlan-l2
allowMultipleAllocations: true
attributes:
dra.networking/type: {string: pf}
dra.networking/ifName: {string: enp3s0f0}
dra.networking/ipvlanMode: {string: l2}
dra.networking/ipvlanFlags: {string: bridge}
dra.networking/supportedNetworkPlugins: {strings: [ipvlan]}
capacity:
dra.networking/ipvlans:
value: '64'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf0-interface-mode
compatibilityGroups: [ipvlan-l2]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters: {members: {value: '1'}}
- name: enp3s0f0-macvlan
allowMultipleAllocations: true
attributes:
dra.networking/type: {string: pf}
dra.networking/ifName: {string: enp3s0f0}
dra.networking/macvlanMode: {string: bridge}
dra.networking/supportedNetworkPlugins: {strings: [macvlan]}
capacity:
dra.networking/macvlans:
value: '64'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf0-interface-mode
compatibilityGroups: [mac-family]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters: {members: {value: '1'}}
- name: enp3s0f0-macvtap
allowMultipleAllocations: true
attributes:
dra.networking/type: {string: pf}
dra.networking/ifName: {string: enp3s0f0}
dra.networking/macvlanMode: {string: bridge}
dra.networking/supportedNetworkPlugins: {strings: [macvtap]}
capacity:
dra.networking/macvtaps:
value: '64'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf0-interface-mode
compatibilityGroups: [mac-family]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters: {members: {value: '1'}}
- name: enp3s0f0-passthrough
attributes:
dra.networking/type: {string: pf}
dra.networking/ifName: {string: enp3s0f0}
dra.networking/supportedNetworkPlugins: {strings: [host-device]}
consumesCounters:
- counterSet: pf0-interface-mode
compatibilityGroups: [passthrough]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [pf-passthrough]
counters: {members: {value: '1'}}
- name: enp3s0f0v0-sriov
attributes:
dra.networking/type: {string: vf}
dra.networking/ifName: {string: enp3s0f0v0}
dra.networking/pfName: {string: enp3s0f0}
dra.networking/vfIndex: {int: 0}
dra.networking/supportedNetworkPlugins: {strings: [sriov]}
consumesCounters:
- counterSet: pf0vf0-interface-mode
compatibilityGroups: [sriov]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters: {members: {value: '1'}}
- name: enp3s0f0v0-vlan
allowMultipleAllocations: true
attributes:
dra.networking/type: {string: vf}
dra.networking/ifName: {string: enp3s0f0v0}
dra.networking/pfName: {string: enp3s0f0}
dra.networking/vfIndex: {int: 0}
dra.networking/supportedNetworkPlugins: {strings: [vlan]}
capacity:
dra.networking/vlans:
value: '16'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf0vf0-interface-mode
compatibilityGroups: [mac-family, ipvlan-l2]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters: {members: {value: '1'}}
- name: enp3s0f0v0-ipvlan-l2
allowMultipleAllocations: true
attributes:
dra.networking/type: {string: vf}
dra.networking/ifName: {string: enp3s0f0v0}
dra.networking/pfName: {string: enp3s0f0}
dra.networking/vfIndex: {int: 0}
dra.networking/ipvlanMode: {string: l2}
dra.networking/ipvlanFlags: {string: bridge}
dra.networking/supportedNetworkPlugins: {strings: [ipvlan]}
capacity:
dra.networking/ipvlans:
value: '16'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf0vf0-interface-mode
compatibilityGroups: [ipvlan-l2]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters: {members: {value: '1'}}
- name: enp3s0f0v0-macvlan
allowMultipleAllocations: true
attributes:
dra.networking/type: {string: vf}
dra.networking/ifName: {string: enp3s0f0v0}
dra.networking/pfName: {string: enp3s0f0}
dra.networking/vfIndex: {int: 0}
dra.networking/macvlanMode: {string: bridge}
dra.networking/supportedNetworkPlugins: {strings: [macvlan]}
capacity:
dra.networking/macvlans:
value: '16'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf0vf0-interface-mode
compatibilityGroups: [mac-family]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters: {members: {value: '1'}}
- name: enp3s0f0v0-macvtap
allowMultipleAllocations: true
attributes:
dra.networking/type: {string: vf}
dra.networking/ifName: {string: enp3s0f0v0}
dra.networking/pfName: {string: enp3s0f0}
dra.networking/vfIndex: {int: 0}
dra.networking/macvlanMode: {string: bridge}
dra.networking/supportedNetworkPlugins: {strings: [macvtap]}
capacity:
dra.networking/macvtaps:
value: '16'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf0vf0-interface-mode
compatibilityGroups: [mac-family]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters: {members: {value: '1'}}
- name: enp3s0f0v1-sriov
attributes:
dra.networking/type: {string: vf}
dra.networking/ifName: {string: enp3s0f0v1}
dra.networking/pfName: {string: enp3s0f0}
dra.networking/vfIndex: {int: 1}
dra.networking/supportedNetworkPlugins: {strings: [sriov]}
consumesCounters:
- counterSet: pf0vf1-interface-mode
compatibilityGroups: [sriov]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters: {members: {value: '1'}}
- name: enp3s0f0v1-vlan
allowMultipleAllocations: true
attributes:
dra.networking/type: {string: vf}
dra.networking/ifName: {string: enp3s0f0v1}
dra.networking/pfName: {string: enp3s0f0}
dra.networking/vfIndex: {int: 1}
dra.networking/supportedNetworkPlugins: {strings: [vlan]}
capacity:
dra.networking/vlans:
value: '16'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf0vf1-interface-mode
compatibilityGroups: [mac-family, ipvlan-l2]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters: {members: {value: '1'}}
- name: enp3s0f0v1-ipvlan-l2
allowMultipleAllocations: true
attributes:
dra.networking/type: {string: vf}
dra.networking/ifName: {string: enp3s0f0v1}
dra.networking/pfName: {string: enp3s0f0}
dra.networking/vfIndex: {int: 1}
dra.networking/ipvlanMode: {string: l2}
dra.networking/ipvlanFlags: {string: bridge}
dra.networking/supportedNetworkPlugins: {strings: [ipvlan]}
capacity:
dra.networking/ipvlans:
value: '16'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf0vf1-interface-mode
compatibilityGroups: [ipvlan-l2]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters: {members: {value: '1'}}
- name: enp3s0f0v1-macvlan
allowMultipleAllocations: true
attributes:
dra.networking/type: {string: vf}
dra.networking/ifName: {string: enp3s0f0v1}
dra.networking/pfName: {string: enp3s0f0}
dra.networking/vfIndex: {int: 1}
dra.networking/macvlanMode: {string: bridge}
dra.networking/supportedNetworkPlugins: {strings: [macvlan]}
capacity:
dra.networking/macvlans:
value: '16'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf0vf1-interface-mode
compatibilityGroups: [mac-family]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters: {members: {value: '1'}}
- name: enp3s0f0v1-macvtap
allowMultipleAllocations: true
attributes:
dra.networking/type: {string: vf}
dra.networking/ifName: {string: enp3s0f0v1}
dra.networking/pfName: {string: enp3s0f0}
dra.networking/vfIndex: {int: 1}
dra.networking/macvlanMode: {string: bridge}
dra.networking/supportedNetworkPlugins: {strings: [macvtap]}
capacity:
dra.networking/macvtaps:
value: '16'
requestPolicy: {default: '1', validValues: ['1']}
consumesCounters:
- counterSet: pf0vf1-interface-mode
compatibilityGroups: [mac-family]
counters: {members: {value: '1'}}
- counterSet: pf0-family-pf-access
compatibilityGroups: [host-retained]
counters: {members: {value: '1'}}The output stays within the pinned API limits: four shared counter sets in the counter slice, fifteen advanced-feature devices in the device slice, exactly two counter-set consumptions per device, and at most two groups per consumption. The family members: 15 total counts published identities: five PF personas plus five personas for each of two VFs.
Kubernetes 1.37 Feasibility
The manifests fit the Kubernetes 1.37 API limits, but they do not work on an unmodified default 1.37 installation. DRADeviceCompatibilityGroups is alpha and disabled by default. DRAListTypeAttributes, used by supportedNetworkPlugins.strings, is also alpha and disabled by default. DRAPartitionableDevices and DRAConsumableCapacity are beta and enabled by default in 1.37. The API server and scheduler must enable the two alpha gates consistently; the target distribution must expose and support that configuration. S25
| Upstream limit or dependency | Example 10 usage | Result |
|---|---|---|
| Counter sets per counter-bearing slice: 8 | 4 | Fits. |
| Advanced-feature devices per device-bearing slice: 64 | 15 | Fits. |
consumesCounters entries per device: 2 | 2 | Fits exactly; no third independent domain remains. |
compatibilityGroups per consumption: 2 | VLAN personas use 2; all others use 1 | Fits exactly; another neutral compatibility family would not fit. |
| Counters per consumption: 32 | 1 | Fits. |
| Attributes plus capacities per device: 32 | At most 8 in the shown entries | Fits. |
DRADeviceCompatibilityGroups | Required | Alpha, disabled by default. |
DRAListTypeAttributes | Required by the list-valued plugin attribute | Alpha, disabled by default. |
DRAPartitionableDevices | Required by sharedCounters/consumesCounters | Beta, enabled by default. |
DRAConsumableCapacity | Required by shared persona capacity | Beta, enabled by default. |
Example 10 therefore sits on both semantic ceilings without crossing them:
- Every persona already uses both domain entries. Adding a third independent reset/controller/eswitch domain fails validation unless an exact merge removes another domain.
- Every VLAN persona already uses both group tokens. Supporting both ipvlan L2 and ipvlan L3 as separate incompatible alternatives would require a third VLAN token and fails validation.
- Adding more VFs does not consume more domains or groups per device. It does create one extra interface counter set and five extra device identities per VF. For
NVFs this example hasN + 2counter sets and5(N + 1)devices. Once either per-slice limit is exceeded, the driver can shard counter sets and devices across more ResourceSlices in the same pool; that is a packing change, not a semantic workaround.
There is also a current allocator correctness risk outside static API validation. Kubernetes issue #140802 reports that removing an allocated device from a republished pool, or changing its counter associations, can make its counter and compatibility contribution disappear from allocator state. This design’s stable-publication and drain rules avoid that mutation during normal operation, but operational discipline is not proof that the alpha implementation is fixed. Production use requires a Kubernetes build where the issue is resolved or an explicit conformance test showing the selected build fails closed for removal, mutation, restart and partial-generation cases. S26
Therefore the API encoding is feasible, but the complete system is conditional: required gates enabled, no unsupported downstream field stripping, stable publication preserved, the allocator issue addressed or proven contained, and the driver/NetworkPlugin execution paths implemented and tested. Kubernetes only schedules the declared identities; it does not create VLAN, ipvlan, macvlan, macvtap or passthrough links for this custom design.
Compatibility Outcomes
| Active allocation | Candidate | Result and enforcing domain |
|---|---|---|
| PF macvlan | PF macvtap | Permit; both retain mac-family and host-retained. |
| PF macvlan | PF ipvlan | Reject in pf0-interface-mode. |
| PF VLAN | PF macvlan or PF ipvlan | Permit through VLAN’s matching alternative group. |
| VF0 sriov | Any other VF0 persona | Reject in pf0vf0-interface-mode. |
| VF0 macvlan | VF0 macvtap | Permit in VF0 interface domain. |
| VF0 macvlan | VF0 ipvlan | Reject in VF0 interface domain. |
| VF0 macvlan | VF1 ipvlan | Permit; different immediate lowers and interface domains. |
| PF ipvlan | VF0 macvlan and VF1 sriov | Permit; all share host-retained in the family domain. |
| Any PF non-passthru or VF persona | PF passthrough | Reject in pf0-family-pf-access. |
| PF passthrough | Any PF non-passthru persona | Reject in both PF interface and family domains. |
| PF passthrough | Any VF persona | Reject in the family domain. |
The family predicate blocks PF passthrough while any VF persona remains allocated, including a shared child persona with one or more live claims. Releasing one share does not unblock passthrough while another share remains.
Published but idle VF personas do not block PF passthrough: compatibility groups constrain active allocations, not mere inventory. If policy requires PF passthrough to remain unavailable whenever VFs are configured or published, omit the PF passthrough persona or reject it during compilation. Do not rely on compatibility groups for that stronger rule.
Allocation-time compatibility is only the scheduler guard. Before preparing PF passthrough, the execution profile must verify zero active VF/PF-child allocations, complete cleanup, external ownership, configured VF teardown requirements, representors, reset effects and identity continuity. If safe PF takeover cannot be certified, do not publish the passthrough persona.
6. Complete Reference Node
6.1 Node Inventory
Node worker-1 uses the same illustrative inventory as the original design:
| Device | Interface | Type | PCI / topology | Speed | NUMA | Role |
|---|---|---|---|---|---|---|
| PF0 | enp3s0f0 | PF | 0000:03:00.0 | 100 GbE | 0 | Two personas, eight VFs. |
| PF1 | enp3s0f1 | PF | 0000:03:00.1 | 25 GbE | 0 | Passthrough persona, four VFs. |
| PF0 VFs | enp3s0f0v0 through enp3s0f0v7 | VF | Enumerated addresses below | Shared link | 0 | Exclusive sriov/host-device alternatives. |
| PF1 VFs | enp3s0f1v0 through enp3s0f1v3 | VF | Enumerated addresses below | Shared link | 0 | Exclusive sriov/host-device alternatives. |
| Data bridge | br-data | Linux bridge | No PCI identity in this example | Not specified | Not specified | Shared bridge ports. |
| Management | eno1 | NIC | Not exposed | Not relevant | Not specified | Excluded. |
| Cluster networking | br-int, ovn-k8s-mp0 | Infrastructure | Not exposed | Not relevant | Not specified | Excluded. |
Before publishing this reference state, Section 4.1’s ownership sources and effect checks must verify that no protected host dependency intersects the passthrough footprints. A complete graph and explicit data-bridge child-port delegation are prerequisites, not facts established by the sample interface names or YAML. Unknown coverage prevents publication. The host-bridge/VF profile in Example 7 has different ownership/exclusion inputs and must not be blindly merged into this reference profile.
6.2 Complete DeviceExposurePolicy Set
These eight proposed policy resources are scoped to the reference node. The policy API itself must be installed by the future implementation; these are not replacements for a CRD manifest.
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: exclude-cluster-cni
spec:
nodeSelector:
matchLabels:
kubernetes.io/hostname: worker-1
priority: 1000
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].ifName in ["br-int", "ovn-k8s-mp0", "breth0", "ovn-k8s-gw0"]
action: exclude
---
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: exclude-management
spec:
nodeSelector:
matchLabels:
kubernetes.io/hostname: worker-1
priority: 1000
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].ifName == "eno1"
action: exclude
---
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf0-macvlan
spec:
nodeSelector:
matchLabels:
kubernetes.io/hostname: worker-1
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "pf" && device.attributes["dra.networking"].ifName == "enp3s0f0"
action: expose
exposure:
deviceNameSuffix: -macvlan
allowMultipleAllocations: true
capacity:
macvlans:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'
supportedNetworkPlugins:
- name: macvlan
consumePerAllocation:
macvlans: '1'
compatibility:
- scope: interface
domain: interface-mode
groups:
- macvlan
- scope: sriovFamily
domain: pf-access
groups:
- host-retained
---
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf0-passthrough
spec:
nodeSelector:
matchLabels:
kubernetes.io/hostname: worker-1
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "pf" && device.attributes["dra.networking"].ifName == "enp3s0f0"
action: expose
exposure:
deviceNameSuffix: -passthrough
allowMultipleAllocations: false
supportedNetworkPlugins:
- name: host-device
compatibility:
- scope: interface
domain: interface-mode
groups:
- passthrough
- scope: sriovFamily
domain: pf-access
groups:
- pf-passthrough
---
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf0-vfs
spec:
nodeSelector:
matchLabels:
kubernetes.io/hostname: worker-1
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].pfName) &&
device.attributes["dra.networking"].type == "vf" && device.attributes["dra.networking"].pfName == "enp3s0f0"
action: expose
exposure:
allowMultipleAllocations: false
supportedNetworkPlugins:
- name: sriov
- name: host-device
compatibility:
- scope: sriovFamily
domain: pf-access
groups:
- host-retained
---
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf1-passthrough
spec:
nodeSelector:
matchLabels:
kubernetes.io/hostname: worker-1
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "pf" && device.attributes["dra.networking"].ifName == "enp3s0f1"
action: expose
exposure:
allowMultipleAllocations: false
supportedNetworkPlugins:
- name: host-device
compatibility:
- scope: sriovFamily
domain: pf-access
groups:
- pf-passthrough
---
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: pf1-vfs
spec:
nodeSelector:
matchLabels:
kubernetes.io/hostname: worker-1
priority: 200
selector:
cel: >-
has(device.attributes["dra.networking"].pfName) &&
device.attributes["dra.networking"].type == "vf" && device.attributes["dra.networking"].pfName == "enp3s0f1"
action: expose
exposure:
allowMultipleAllocations: false
supportedNetworkPlugins:
- name: sriov
- name: host-device
compatibility:
- scope: sriovFamily
domain: pf-access
groups:
- host-retained
---
apiVersion: networking.dra.io/v1alpha1
kind: DeviceExposurePolicy
metadata:
name: bridge-br-data
spec:
nodeSelector:
matchLabels:
kubernetes.io/hostname: worker-1
priority: 150
selector:
cel: >-
has(device.attributes["dra.networking"].ifName) &&
device.attributes["dra.networking"].type == "bridge" && device.attributes["dra.networking"].ifName == "br-data"
action: expose
exposure:
allowMultipleAllocations: true
capacity:
ports:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'
supportedNetworkPlugins:
- name: bridge
consumePerAllocation:
ports: '1'6.3 Resulting ResourceSlices
There are five ResourceSlice objects, not three. Each PF pool has one counter-bearing slice and one device-bearing slice. The standalone bridge needs only a device-bearing slice. Every VF is included; there are no omitted placeholder devices in this reference output.
PF0 Pool — Counter Slice and Device Slice
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: worker-1-sriov-pf0-counters
spec:
driver: dra.networking
pool:
name: worker-1-sriov-pf0
generation: 1
resourceSliceCount: 2
nodeName: worker-1
sharedCounters:
- name: pf0-interface-mode
counters:
members:
value: '2'
- name: pf0-family-pf-access
counters:
members:
value: '10'
---
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: worker-1-sriov-pf0-devices
spec:
driver: dra.networking
pool:
name: worker-1-sriov-pf0
generation: 1
resourceSliceCount: 2
nodeName: worker-1
devices:
- name: enp3s0f0-macvlan
allowMultipleAllocations: true
attributes:
dra.networking/type:
string: pf
dra.networking/ifName:
string: enp3s0f0
dra.networking/pciAddress:
string: '0000:03:00.0'
dra.networking/mac:
string: 04:3f:72:b0:d4:60
dra.networking/mtu:
int: 1500
dra.networking/linkSpeed:
int: 100000
dra.networking/numVFs:
int: 8
dra.networking/rdma:
bool: true
dra.networking/numaNode:
int: 0
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101d
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- macvlan
capacity:
dra.networking/macvlans:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'
consumesCounters:
- counterSet: pf0-interface-mode
compatibilityGroups:
- macvlan
counters:
members:
value: '1'
- counterSet: pf0-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'
- name: enp3s0f0-passthrough
attributes:
dra.networking/type:
string: pf
dra.networking/ifName:
string: enp3s0f0
dra.networking/pciAddress:
string: '0000:03:00.0'
dra.networking/mac:
string: 04:3f:72:b0:d4:60
dra.networking/mtu:
int: 1500
dra.networking/linkSpeed:
int: 100000
dra.networking/numVFs:
int: 8
dra.networking/rdma:
bool: true
dra.networking/numaNode:
int: 0
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101d
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- host-device
consumesCounters:
- counterSet: pf0-interface-mode
compatibilityGroups:
- passthrough
counters:
members:
value: '1'
- counterSet: pf0-family-pf-access
compatibilityGroups:
- pf-passthrough
counters:
members:
value: '1'
- name: enp3s0f0v0
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f0v0
dra.networking/pfName:
string: enp3s0f0
dra.networking/vfIndex:
int: 0
dra.networking/pciAddress:
string: '0000:03:00.2'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
- host-device
consumesCounters:
- counterSet: pf0-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'
- name: enp3s0f0v1
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f0v1
dra.networking/pfName:
string: enp3s0f0
dra.networking/vfIndex:
int: 1
dra.networking/pciAddress:
string: '0000:03:00.3'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
- host-device
consumesCounters:
- counterSet: pf0-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'
- name: enp3s0f0v2
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f0v2
dra.networking/pfName:
string: enp3s0f0
dra.networking/vfIndex:
int: 2
dra.networking/pciAddress:
string: '0000:03:00.4'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
- host-device
consumesCounters:
- counterSet: pf0-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'
- name: enp3s0f0v3
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f0v3
dra.networking/pfName:
string: enp3s0f0
dra.networking/vfIndex:
int: 3
dra.networking/pciAddress:
string: '0000:03:00.5'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
- host-device
consumesCounters:
- counterSet: pf0-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'
- name: enp3s0f0v4
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f0v4
dra.networking/pfName:
string: enp3s0f0
dra.networking/vfIndex:
int: 4
dra.networking/pciAddress:
string: '0000:03:00.6'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
- host-device
consumesCounters:
- counterSet: pf0-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'
- name: enp3s0f0v5
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f0v5
dra.networking/pfName:
string: enp3s0f0
dra.networking/vfIndex:
int: 5
dra.networking/pciAddress:
string: '0000:03:00.7'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
- host-device
consumesCounters:
- counterSet: pf0-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'
- name: enp3s0f0v6
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f0v6
dra.networking/pfName:
string: enp3s0f0
dra.networking/vfIndex:
int: 6
dra.networking/pciAddress:
string: '0000:03:01.0'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
- host-device
consumesCounters:
- counterSet: pf0-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'
- name: enp3s0f0v7
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f0v7
dra.networking/pfName:
string: enp3s0f0
dra.networking/vfIndex:
int: 7
dra.networking/pciAddress:
string: '0000:03:01.1'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
- host-device
consumesCounters:
- counterSet: pf0-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'PF1 Pool — Counter Slice and Device Slice
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: worker-1-sriov-pf1-counters
spec:
driver: dra.networking
pool:
name: worker-1-sriov-pf1
generation: 1
resourceSliceCount: 2
nodeName: worker-1
sharedCounters:
- name: pf1-family-pf-access
counters:
members:
value: '5'
---
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: worker-1-sriov-pf1-devices
spec:
driver: dra.networking
pool:
name: worker-1-sriov-pf1
generation: 1
resourceSliceCount: 2
nodeName: worker-1
devices:
- name: enp3s0f1
attributes:
dra.networking/type:
string: pf
dra.networking/ifName:
string: enp3s0f1
dra.networking/pciAddress:
string: '0000:03:00.1'
dra.networking/mac:
string: 04:3f:72:b0:d4:61
dra.networking/mtu:
int: 1500
dra.networking/linkSpeed:
int: 25000
dra.networking/numVFs:
int: 4
dra.networking/rdma:
bool: true
dra.networking/numaNode:
int: 0
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101d
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- host-device
consumesCounters:
- counterSet: pf1-family-pf-access
compatibilityGroups:
- pf-passthrough
counters:
members:
value: '1'
- name: enp3s0f1v0
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f1v0
dra.networking/pfName:
string: enp3s0f1
dra.networking/vfIndex:
int: 0
dra.networking/pciAddress:
string: '0000:03:01.2'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
- host-device
consumesCounters:
- counterSet: pf1-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'
- name: enp3s0f1v1
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f1v1
dra.networking/pfName:
string: enp3s0f1
dra.networking/vfIndex:
int: 1
dra.networking/pciAddress:
string: '0000:03:01.3'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
- host-device
consumesCounters:
- counterSet: pf1-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'
- name: enp3s0f1v2
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f1v2
dra.networking/pfName:
string: enp3s0f1
dra.networking/vfIndex:
int: 2
dra.networking/pciAddress:
string: '0000:03:01.4'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
- host-device
consumesCounters:
- counterSet: pf1-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'
- name: enp3s0f1v3
attributes:
dra.networking/type:
string: vf
dra.networking/ifName:
string: enp3s0f1v3
dra.networking/pfName:
string: enp3s0f1
dra.networking/vfIndex:
int: 3
dra.networking/pciAddress:
string: '0000:03:01.5'
dra.networking/numaNode:
int: 0
dra.networking/rdma:
bool: true
dra.networking/vendor:
string: 15b3
dra.networking/product:
string: 101e
dra.networking/driver:
string: mlx5_core
device.k8s.io/pcieRoot:
string: pci0000:00
dra.networking/supportedNetworkPlugins:
strings:
- sriov
- host-device
consumesCounters:
- counterSet: pf1-family-pf-access
compatibilityGroups:
- host-retained
counters:
members:
value: '1'Standalone Bridge Pool
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: worker-1-bridge-br-data
spec:
driver: dra.networking
pool:
name: worker-1-bridge-br-data
generation: 1
resourceSliceCount: 1
nodeName: worker-1
devices:
- name: br-data
allowMultipleAllocations: true
attributes:
dra.networking/type:
string: bridge
dra.networking/ifName:
string: br-data
dra.networking/bridgeName:
string: br-data
dra.networking/bridgeType:
string: linux
dra.networking/mtu:
int: 9000
dra.networking/vlanFiltering:
bool: true
dra.networking/supportedNetworkPlugins:
strings:
- bridge
capacity:
dra.networking/ports:
value: '64'
requestPolicy:
default: '1'
validValues:
- '1'6.4 Summary
| Pool | ResourceSlice objects | Device entries | Compatibility domains |
|---|---|---|---|
worker-1-sriov-pf0 | 2 | 10: two PF personas and eight VFs | pf0-interface-mode has members=2; pf0-family-pf-access has members=10. |
worker-1-sriov-pf1 | 2 | 5: one PF persona and four VFs | pf1-family-pf-access has members=5. |
worker-1-bridge-br-data | 1 | 1 | None. |
| Total | 5 | 16 | Three counter sets across the two PF counter slices. |
Not published: management and cluster-network interfaces selected by exclusion policies. Speeds remain attributes; there is no bandwidth reservation in these baseline manifests.
The numerical member totals accommodate all published identities, including incompatible alternatives. They are deliberately not the source of mutual exclusion.
6.5 App Developer Experience
The platform administers exposure policy and DeviceClasses. Applications reference a class, normally through a ResourceClaimTemplate. The companion NetworkTopology controller may generate those classes, but the discovery implementation does not rely on unverified hidden capacity injection.
The following DeviceClass shows the actual selection logic for the reference PF0 macvlan entry. The VF class is included for the optional bandwidth fragment and future examples. Driver and attribute domains are illustrative; a production project must select its owned driver domain consistently.
apiVersion: resource.k8s.io/v1
kind: DeviceClass
metadata:
name: network-macvlan-pf0
spec:
selectors:
- cel:
expression: device.driver == "dra.networking" && has(device.attributes["dra.networking"].ifName) && device.allowMultipleAllocations == true && device.attributes["dra.networking"].type
== "pf" && device.attributes["dra.networking"].ifName == "enp3s0f0" && device.attributes["dra.networking"].supportedNetworkPlugins.includes("macvlan")
---
apiVersion: resource.k8s.io/v1
kind: DeviceClass
metadata:
name: network-vf-pf0
spec:
selectors:
- cel:
expression: device.driver == "dra.networking" && has(device.attributes["dra.networking"].pfName) && device.allowMultipleAllocations == false && device.attributes["dra.networking"].type
== "vf" && device.attributes["dra.networking"].pfName == "enp3s0f0" && device.attributes["dra.networking"].supportedNetworkPlugins.includes("sriov")
---
apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
name: my-app-network
namespace: default
spec:
spec:
devices:
requests:
- name: net
exactly:
deviceClassName: network-macvlan-pf0
allocationMode: ExactCount
count: 1No explicit capacity request is needed for this baseline: the selected device’s local policy reserves one macvlan unit. Class-origin TopologyRootConfiguration and NetworkPlugin configuration belong to the companion topology integration contract, not new standard fields on a ResourceClaim. The selectors above demonstrate the allocation layer only; they do not provide the complete root bindings or execution configuration from the companion proposal. S7 S9
Claims that combine two VF requests, as in the original bonded-RDMA application example, follow the same class-reference pattern. Their network topology and distinct-device/topology constraints must be generated and tested by the companion controller rather than assumed from request names.
7. Decisions and Remaining Questions
The original consume-once question is no longer a blocker: mode exclusion uses compatibility groups. Remaining implementation choices are recorded separately from resolved API behavior.
| Topic | Decision / remaining work |
|---|---|
| Mode exclusion | Resolved: KEP 5963 with explicit scoped group bindings. No mirrored-capacity cross-drain. |
| PF/VF interaction | Explicit family policy. The reference permits host-retained PF macvlan plus VFs and excludes PF passthrough. Hardware support and cleanup remain platform test requirements. |
| Macvlan/bridge capacity discovery | Administrator supplied. The driver does not invent maximum counts. |
| Default local consumption | Explicit local request policies provide one-unit defaults. Validate round-trip behavior and actual allocator results in tests. |
| Shared-allocation identity | Log the claim’s metadata UID, request, driver/pool/device and result shareID when present. Do not claim that a claim UID is a field inside every AllocationResult. |
| Cross-pool associations | Not supported by this design. A common compatibility domain must be placed in one pool. |
| Dynamic VF count / device disappearance | Needs allocation-aware drain and identity retention. Generation changes alone do not make hardware reconfiguration safe. |
| Bridge creation | Discovery-only in the initial implementation. Host topology changes require coordination. |
| List-attribute fallback | Initial list-based profile requires its feature gate. No substring-based comma-separated fallback. A reduced exact-scalar profile would need a separate schema/selector contract. |
| Policy validation | Local admission validation plus node-level whole-pool checks. Normal exclusive policies without capacity are valid. |
| Shared bandwidth | Follow-on feature requiring an explicit budget policy schema, target PR/version integration and accounting/enforcement tests. |
| OVN-K integration | Proposed example only; requires end-to-end control-plane and execution validation. |
| Cold inventory and identity | Section 4.1 defines PCI-first records, optional endpoints, presence epochs and uncertainty/recovery rules. Implement storage/correlation and collision-checked DNS encoding; hardware continuity is not inferred from BDF/MAC. |
| Protected host dependencies | Section 4.1 defines owner inputs, typed graph direction and effect-specific checks. Implement adapters and certify each profile before publication; incomplete relevant coverage denies new use. |
| Deployment target | Pin Kubernetes/client libraries and determine supported OpenShift feature configuration. Do not infer support from generic Kubernetes version numbers. |
8. Lifecycle, Reconciliation and Safety Contract
8.1 Why Active Publication Must Be Preserved
The inspected KEP 5963 implementation reads groups from live device declarations. Removing an allocated device from the inventory removes its contribution to the compatibility baseline. Changing its groups changes the baseline used for future allocations. These are implementation facts, not behavior this driver should rely on to switch a mode in use. S3 S4
The driver must pin the active publication contract: device and pool identities, domain associations, group tokens, sharing semantics, NetworkPlugin alternatives and relevant execution/capacity configuration. Store enough committed publication and node execution state to recover this contract after restart; a fresh scan of the host namespace is insufficient when devices have been moved.
Policy state is desired state. It is not permission to mutate the meaning of an already allocated device. A new desired contract becomes active only after a safe transition.
8.2 Drain Protocol
A change that removes a persona, changes its groups, switches sharing semantics, changes a scope root, renames an active identity, or replaces physical hardware enters a drain workflow:
- Record the desired change and keep the previous active declaration.
- Prevent new admissions into the affected transition through the deployment’s maintenance/admission mechanism; optionally mark retained devices
NoSchedulewithout evicting running Pods. - Wait for allocated claims, in-flight preparation and node cleanup to reconcile. Recheck before committing a new generation.
- Publish the new complete model and retire the old one only when safe.
A NoSchedule taint can be tolerated by a claim. It is an operational aid, not a security boundary or proof that there are no in-flight allocations. Preventing bypass requires appropriate admission/RBAC policy, and scheduler/watch races still require node-side verification. A poll observing zero claims is not an atomic lock against a concurrent allocator.
For a policy exclusion on an active interface, report PendingDrain rather than immediately deleting the device. For unexpected hardware disappearance, retain the allocation record, fail new preparation clearly, and require recovery; do not expose a replacement under an identity still in use.
8.3 Node-Side Enforcement
The execution path must maintain a persistent, idempotent allocation journal and serialize conflicting work by resolved resource/domain. Acquire multiple locks in deterministic order. Apply Section 4.1.5’s identity-epoch, protection-graph and effect checks before NetworkPlugin or device operations, including the actual networking hook if it occurs after NodePrepareResources. A successful earlier check does not authorize later mutation after ownership or dependency changes.
Preparation, retries, cleanup failures, kubelet reconnect and process restarts must not release a domain prematurely. A local cleanup completion does not remove scheduler allocation state, and scheduler deallocation does not justify forgetting hardware cleanup that is still pending.
The journal must distinguish claim identity, allocation result/share identity and Pod consumers. Count claim allocations separately from Pod references when a claim can be reused. Track external host ownership explicitly where supported; otherwise exclude unsafe exposure profiles, as in Example 7.
8.4 Capability and Authorization Boundaries
The installation profile requires DRAPartitionableDevices, DRAConsumableCapacity, DRADeviceCompatibilityGroups and DRAListTypeAttributes for the full examples. DRASharedConsumableCapacity is not part of the baseline. S2
Use a deployment capability contract and verification, not a fictional generic runtime API for reading all feature-gate values. API write/read tests must detect stripped fields. Scheduler behavior needs its own controlled test. Loss of a required capability must not trigger a fallback that removes exclusion constraints from still-published alternatives.
Restrict writes to driver ResourceSlices, exposure policies and relevant claim status. Compatibility is an allocation predicate, not a tenant authorization system or protection against arbitrary privileged host reconfiguration. Administrative-access claims and custom schedulers require an explicit support policy; the baseline guarantees target normal scheduler-managed allocations.
9. Required Acceptance Tests
The following are implementation acceptance criteria. They have not been run against Kubernetes as part of preparing this document.
| Test | Required result |
|---|---|
| Policy priority and exclusions | One winner per suffix; lexical tie break; any exclusion wins; no match publishes nothing new. |
| Selector failure | Invalid CEL is rejected; runtime evaluation errors fail closed with diagnostics. |
| Policy-to-v1 serialization | No basic, no stringSlice; attributes/capacity at device level; quantities and attribute types preserved. |
| Slice separation and limits | Counter and device objects separated; consistent total count and generation; third consumption or third group rejected. |
| Counter-set resolution | PF/VF members resolve to the same family domain; different interfaces/pools stay independent. |
| Alias coverage | Multiple personas without a common guard rejected; exclusive aliases cannot coexist. |
| Macvlan repeated allocations | A and B on one device both allocate, consuming two local units and one fixed member. |
| Cross-mode rejection | IPvlan rejected while any macvlan claim remains, in either allocation order. |
| First-share release | Release A while B remains; reconstruct allocator state; incompatible mode stays rejected. |
| Last-share release | Release B, reconcile cleanup and allocation state; the alternate mode can allocate. |
| Driver/scheduler state reconstruction | Restarts preserve compatible outcomes and cannot unlock an active mode. |
| Local capacity boundary | 64 one-unit allocations fit; 65th does not. Releasing one restores exactly one unit. |
| Shared versus exclusive | Both orderings blocked; second allocation of a normal exclusive entry rejected. |
| PF family combinations | PF macvlan plus all eligible VFs permitted; PF passthrough rejected until all incompatible family members are released. |
| Independent interface and family domains | Adding PF ipvlan does not block VFs but does block PF macvlan; all two-domain checks apply. |
| Maximal PF/VF persona pool | All fifteen Example 10 identities obey two-domain/two-group limits; PF passthrough conflicts with every active host-retained PF/VF persona. |
| Third independent domain | A persona already in interface and PF-family domains is rejected when a distinct reset/controller domain is required; no association is silently dropped. |
| Neutral VLAN across three families | Mac-family, ipvlan L2 and ipvlan L3 remain mutually incompatible; compilation rejects the VLAN persona because three alternative groups cannot be encoded. |
| Whole-set intersection | Pairwise-overlapping but globally disjoint group sets cannot all allocate. |
| Empty group behavior | Empty only matches empty; missing groups never treated as a wildcard. |
| VLAN/ipvlan/macvlan/macvtap matrix | VLAN coexists with either approved child family; macvlan and macvtap coexist; ipvlan is rejected with either on the same immediate lower. |
| Ipvlan port contract | Concurrent ipvlan allocations use one pinned mode/flag combination; incompatible mode personas cannot overlap. |
| VLAN lower separation | Mac-family children on one VLAN lower and ipvlan children on another do not share an interface domain; PF-wide effects remain guarded. |
| Child recovery | Journaled software children correlate to their allocations after restart; unjournaled children are not published as free capacity. |
| Single allocation search and backtracking | Incompatible requests in one claim/Pod rejected; failed candidates restore group and capacity search state. |
| Policy / identity mutation | Active rename, group change, suffix replacement, sharing change and VF-count shrink require drain; no early retirement. |
| Host namespace move / rebinding | Rescan does not forget a still-allocated device after a supported operation moves or rebinds it. |
| Hidden bridge-owned VF | Exclusion alone creates no reservation; unsafe PF passthrough is unavailable in the selected host-bridge profile. |
| Feature disabled / stripped / skewed | Required fields missing or unenforced prevents unsafe publication; no silent downgrade to unconstrained alternatives. |
| Partial ResourceSlice updates | Incomplete generations and retry/restart converge without exposing conflicting new aliases. |
| Claim reused by Pods | Pod reference changes do not double-charge local capacity or release the claim’s device early. |
| Prepare/unprepare retries and failures | Idempotent journal replay; deterministic domain locking; cleanup failure retains safety state. |
| Optional shared-bandwidth profile | Only on a combined supported build: per-share accounting, release order, defaults, policy changes, feature transitions and compatibility all tested. |
| OVN-K profile | Advertised support is promoted to an implementation guarantee only after provisioning, handoff and cleanup tests pass. |
9.1 Cold Inventory and Dependency Protection Matrix
These cases are the F12 contract acceptance matrix. “Permit” means the identity/protection check passes; normal policy, scheduler allocation, capacity and execution authorization must also pass. They are specified cases, not executed hardware results. Pure graph fixtures can verify traversal and deny decisions; PCI/netlink fixtures and real hardware/controller tests must separately validate the observations and certified effect footprints.
| Case | Observed state and requested action | Required inventory/publication and execution outcome |
|---|---|---|
| F12-01 | First startup; VF already bound to VFIO; no host netdevice or prior journal | Discover the function and PF/index from PCI. Omit unavailable name/MAC/MTU fields. Deny kernel-netdevice publication; only a separately certified VFIO profile may publish after complete ownership checks. No automatic rebind. |
| F12-02 | First startup; unbound network function | Retain a function record with bindingState: unbound. Distinguish unreadable driver link from proven absence. Deny execution in the initial kernel-bound profile. |
| F12-03 | Free, identity-verified kernel VF; complete graph; move its endpoint | Permit when the certified effect set affects only the authorized free resources. An unrelated protected PF on the node does not block it. |
| F12-04 | Authorized rename, namespace move or rebind; stable function continuity | Keep the committed resource ID/epoch and allocation mapping; update verified locators. Rescan cannot republish the same resource as free. |
| F12-05 | VF destroyed/recreated at the same BDF/index, or replacement hardware reuses BDF/MAC | New incarnation cannot satisfy the old allocation. Retain old tombstone/cleanup references, block conflicting new publication and require recovery/drain. |
| F12-06 | Reboot, missed PCI events or lost identity store; continuity cannot be proved | IdentityUncertain; no new preparation or automatic reuse. Recovery reconciles persisted/API/external ownership before accepting the candidate. |
| F12-07 | Management VLAN over bond over PF; move/rebind the PF | Deny with the dependency path even if the PF name matches an expose policy and no PF exclusion exists. Retain active declarations if protection was added later. |
| F12-08 | VF is a host bridge member; direct VF handoff | Deny because the operation removes a protected member. Excluding the bridge from direct allocation is insufficient. |
| F12-09 | Same host bridge uses VF0; free VF1 has a certified isolated endpoint-move operation | Permit VF1 if it changes neither PF/representor service nor bridge-owned resources. A reset/rebind with unknown or overlapping impact is denied. |
| F12-10 | Primary CNI owns a representor; proposed VF/eswitch operation affects it | Deny without the required controller delegation. Never classify the representor as a spare VF by ifname/PCI association alone. |
| F12-11 | Approved shared data parent; one child-creation entitlement; owner delegates exact effects | Permit within the certified shared profile and quota; deletion removes only that attachment’s child. A protected management/primary parent with no such delegation is denied. |
| F12-12 | VFIO transition; IOMMU peer is host-owned/non-network, or peer ownership is unknown | Discover the peer and deny the transition. Absence from network inventory or DRA claims does not make it free. |
| F12-13 | Reset method affects a protected peer outside the PF family/IOMMU group, or scope is unknown | Deny. Reset footprint must be independently established; sharing an IOMMU group neither proves nor authorizes reset scope. |
| F12-14 | Function has several netdevices/ports and a representor; selected endpoint unresolved | Discover all observations but reject ambiguous initial-profile publication. Never choose the first interface or infer ownership from its name. |
| F12-15 | Required controller source stale, netlink dump interrupted, or relevant graph edge unresolved | Retain existing protection; block affected new use with DependencyUnknown. A verified independent inventory component may still reconcile. |
| F12-16 | Ownership/protected dependency changes after publication or Prepare, before Connect | Refresh under local locks, reject mutation, keep active inventory contract and enter drain/recovery. A tolerated scheduling taint cannot bypass this check. |
| F12-17 | Unprepare sees replacement device or a new external owner | Do not restore historical settings onto it. Keep cleanup debt and quarantine pending proven safe recovery. |
| F12-18 | PCI-only candidate evaluated against the kernel-interface example policies | Guarded missing ifName/pfName/masterBridge expressions return non-match, not runtime error. Missing ownership evidence independently blocks unsafe exposure. |
Use both upstream structured-allocator tests with published fixtures and integration/e2e tests exercising real claim transitions. A mathematical model can check desired combinations, but it does not prove the actual scheduler, API server, feature gates or node driver implement them.
10. Implementation Handoff
The first implementation should deliver cold inventory and protection checks for the selected kernel execution profiles, including exclusive VFs and explicitly delegated shared parents, before enabling optional VFIO/rebind/reset profiles. Preserve the full baseline’s declared feature dependencies and exclusion semantics. The policy examples remain target compiler/allocation fixtures, not a claim that every hardware/effect profile is initially supported:
Inventory and protection. Implement Section 4.1’s PCI/function and endpoint records, completeness/provenance tracking, identity persistence and typed graph. Configure authoritative management/primary/external ownership sources. Read VFIO/unbound inventory without rebinding it; reject unsupported effects or missing adapters. Implement F12-01 through F12-18 as source fixtures, graph checks and hardware/controller conformance cases appropriate to each profile.
Policy API and compiler. Implement the proposed schema and admission rules, optional-attribute normalization, guarded selectors, deterministic policy resolution, scoped domain resolution, stable identity mapping, effect-footprint checks and whole-pool validation. Pure compiler tests should use the examples in this document as fixtures and must not treat a policy match as ownership authority.
Publication and allocation-aware state. Integrate the upstream ResourceSlice publishing machinery, correct packing/counts, committed inventory state, allocated-claim observation and drain handling. Add failure/restart tests before allowing automatic destructive transitions.
Node enforcement and topology integration. Implement the journal and resource/domain safety checks, then connect the companion NetworkTopology/NetworkPlugin execution path. Revalidate identity epochs, dependencies and ownership before each mutation and historical cleanup. Keep plugin-specific arguments separate from exposure metadata. Confirm the one-allocation/one-interface baseline contract and claim-sharing behavior.
Target-cluster verification. Run API validation, CEL evaluation and allocator/e2e acceptance on the exact Kubernetes or OpenShift target. Alpha source availability is not production support approval.
Follow-ons. Add an explicit shared-budget policy API and KEP 5941 integration only after the baseline works. Treat OVN-K and host-managed reservations as separately tested integrations, not assumed consequences of the generic discovery engine.
Suggested initial interfaces are conceptual boundaries, not preselected Go APIs: Discover, CorrelateIdentity, BuildProtectionGraph, CheckEffectFootprint, ResolvePolicies, CompilePools, ReconcilePublication, ObserveAllocations, and EnforceDomainContract. Their concrete signatures should be designed against the actual driver repository in the implementation phase.
This revision closes F12’s missing design contract. It does not claim implementation, successful hardware conformance, a complete durable publication fence or a live site update. Unknown reset/representor/external-owner behavior remains an explicit profile blocker until an adapter and its evidence exist.
11. Source Notes
The uploaded design provides the original scope, terminology, nine scenarios and reference inventory. This revision replaces the exclusion model and adds explicitly proposed policy/lifecycle rules. The custom compatibility schema, non-binding members counters, PCI identity records, protection graph and compiler checks are design decisions in this document, not features supplied automatically by Kubernetes or Linux.
Upstream facts were checked against the following primary sources. Prefer the pinned implementation over older prose when the two disagree. Linux source documentation for the F12 revision was checked on 2026-09-23; supported kernels/drivers still require conformance evidence. The OVN integration remains unvalidated.
- S1: Resource API v1: object shapes, quantities, groups and limits
- S2: Feature gates and source-level version/default registration
- S3: Compatibility intersection and feature-disabled slice handling
- S4: Allocator integration and live-slice compatibility baseline
- S5: Allocated-device detection, including shared devices
- S6: API server feature-field stripping
- S7: DRA API concepts: classes, claims and list attributes
- S8: KEP 5941 PR-head API: valueFrom.capacityName and shared consumption
- S9: DeviceClass API and CEL selector environment
- S10: KEP 5963 design text (may differ from implementation)
- S11: Shared consumable capacity PR and review discussion
- S12: KEP 5075 consumable-capacity design
- S13: Linux PCI sysfs inventory
- S14: Linux SR-IOV model and VF enumeration
- S15: Linux netdevice sysfs observations
- S16: Devlink port/controller/function relationships
- S17: Network function representors
- S18: VFIO ownership and IOMMU boundaries
- S19: PCI sysfs ABI: PF/VF links, binding and reset methods
- S20: Generated Kubernetes validation for the two-item limits
- S21: Linux macvlan port and receive-handler implementation
- S22: Linux ipvlan port, mode and receive-handler checks
- S23: Linux macvtap use of the macvlan implementation
- S24: Linux 802.1Q VLAN device registration
- S25: Kubernetes 1.37 feature-gate registration
- S26: Open allocator bug for republished allocated devices