Skip to content
This repository was archived by the owner on May 6, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pkg/apis/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ type InterfaceConfig struct {
// to be assigned to the interface.
Addresses []string `json:"addresses,omitempty"`

// DHCP, if true, indicates that the interface should be configured via DHCP.
// This is mutually exclusive with the 'addresses' field.
DHCP *bool `json:"dhcp,omitempty"`

// MTU is the Maximum Transmission Unit for the interface.
MTU *int32 `json:"mtu,omitempty"`

Expand Down
4 changes: 4 additions & 0 deletions pkg/apis/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ func validateInterfaceConfig(cfg *InterfaceConfig, fieldPath string) (allErrors
}
}

if cfg.DHCP != nil && *cfg.DHCP && len(cfg.Addresses) > 0 {
allErrors = append(allErrors, fmt.Errorf("%s: dhcp and addresses are mutually exclusive", fieldPath))
}

if cfg.MTU != nil {
if *cfg.MTU < MinMTU {
allErrors = append(allErrors, fmt.Errorf("%s.mtu: must be at least %d, got %d", fieldPath, MinMTU, *cfg.MTU))
Expand Down
19 changes: 19 additions & 0 deletions pkg/apis/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,25 @@ func TestValidateInterfaceConfig(t *testing.T) {
expectErr: true,
errCount: 1,
},
{
name: "valid with dhcp",
cfg: &InterfaceConfig{Name: "eth0", DHCP: ptr.To(true)},
fieldPath: "iface",
expectErr: false,
},
{
name: "invalid with dhcp and addresses",
cfg: &InterfaceConfig{Name: "eth0", DHCP: ptr.To(true), Addresses: []string{"10.0.0.1/24"}},
fieldPath: "iface",
expectErr: true,
errCount: 1,
},
{
name: "valid with dhcp false and addresses",
cfg: &InterfaceConfig{Name: "eth0", DHCP: ptr.To(false), Addresses: []string{"10.0.0.1/24"}},
fieldPath: "iface",
expectErr: false,
},
{
name: "multiple errors",
cfg: &InterfaceConfig{Name: "eth/0", Addresses: []string{"badip"}, MTU: ptr.To[int32](0)},
Expand Down
4 changes: 2 additions & 2 deletions pkg/driver/dhcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"github.com/vishvananda/netlink"
)

func getDHCP(ifName string) (ip string, routes []apis.RouteConfig, err error) {
func getDHCP(ctx context.Context, ifName string) (ip string, routes []apis.RouteConfig, err error) {
link, err := netlink.LinkByName(ifName)
if err != nil {
return "", nil, err
Expand All @@ -43,7 +43,7 @@ func getDHCP(ifName string) (ip string, routes []apis.RouteConfig, err error) {
}
defer dhclient.Close()

lease, err := dhclient.Request(context.Background())
lease, err := dhclient.Request(ctx)
if err != nil {
return "", nil, fmt.Errorf("fail to obtain DHCP lease on interface %s up: %v", ifName, err)
}
Expand Down
34 changes: 16 additions & 18 deletions pkg/driver/dra_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,25 @@ func (np *NetworkDriver) prepareResourceClaim(ctx context.Context, claim *resour
podCfg.Network.Interface.Name = ifName
}

// If there is no custom addresses then use the existing ones
if len(podCfg.Network.Interface.Addresses) == 0 {
// If DHCP is requested, do a DHCP request to gather the network parameters (IPs and Routes)
// ... but we DO NOT apply them in the root namespace
Copy link

Copilot AI Jun 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider adding a small inline comment or refactoring the conditional block to clarify that the DHCP configuration is opt-in and bypasses the default address acquisition to improve code readability in the future.

Suggested change
// ... but we DO NOT apply them in the root namespace
// ... but we DO NOT apply them in the root namespace
// Note: DHCP configuration is opt-in and bypasses the default address acquisition logic below.

Copilot uses AI. Check for mistakes.
if podCfg.Network.Interface.DHCP != nil && *podCfg.Network.Interface.DHCP {
klog.V(2).Infof("trying to get network configuration via DHCP")
contextCancel, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
ip, routes, err := getDHCP(contextCancel, ifName)
if err != nil {
errorList = append(errorList, fmt.Errorf("fail to get configuration via DHCP for %s: %w", ifName, err))
} else {
podCfg.Network.Interface.Addresses = []string{ip}
podCfg.Network.Routes = append(podCfg.Network.Routes, routes...)
}
} else if len(podCfg.Network.Interface.Addresses) == 0 {
// If there is no custom addresses and no DHCP, then use the existing ones
// get the existing IP addresses
nlAddresses, err := nlHandle.AddrList(link, netlink.FAMILY_ALL)
if err != nil && !errors.Is(err, netlink.ErrDumpInterrupted) {
klog.Infof("fail to get ip addresses for interface %s : %v", ifName, err)
errorList = append(errorList, fmt.Errorf("fail to get ip addresses for interface %s : %w", ifName, err))
} else {
for _, address := range nlAddresses {
// Only move IP addresses with global scope because those are not host-specific, auto-configured,
Expand All @@ -185,21 +198,6 @@ func (np *NetworkDriver) prepareResourceClaim(ctx context.Context, claim *resour
}
}

// If there are no addresses configured on the interface and the user is not setting them
// this may be an interface that uses DHCP, so we bring it up if necessary and do a DHCP
// request to gather the network parameters (IPs and Routes) ... but we DO NOT apply them
// in the root namespace
if len(podCfg.Network.Interface.Addresses) == 0 {
klog.V(2).Infof("trying to get network configuration via DHCP")
ip, routes, err := getDHCP(ifName)
if err != nil {
klog.Infof("fail to get configuration via DHCP: %v", err)
} else {
podCfg.Network.Interface.Addresses = []string{ip}
podCfg.Network.Routes = append(podCfg.Network.Routes, routes...)
}
}

// Obtain the existing supported ethtool features and validate the config
if podCfg.Network.Ethtool != nil {
client, err := newEthtoolClient(0)
Expand Down
Loading