Skip to content

Commit

Permalink
Add support for AllocateDefaultGateway Feature
Browse files Browse the repository at this point in the history
add `allocateDefaultGateway` flag to cni-args that
activates the special behaviour.
When CNI is called with this flag, the plugin
will try to allocate IP address of the pool's
default gateway  as interface IP for the cotnainer.
  • Loading branch information
ykulazhenkov committed Jun 13, 2024
1 parent fb98825 commit 3917ecc
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 118 deletions.
302 changes: 191 additions & 111 deletions api/grpc/nvidia/ipam/node/v1/node.pb.go

Large diffs are not rendered by default.

12 changes: 10 additions & 2 deletions api/grpc/proto/nvidia/ipam/node/v1/node.proto
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,12 @@ message IPAMParameters {
string cni_ifname = 3;
// required, additional metadata to identify IP allocation
IPAMMetadata metadata = 4;
// type of the pool which is refered by the name in the pools field
// optional, type of the pool which is refered by the name in the pools field
PoolType pool_type = 5;
// conatins IP that were statically requested
// optional, conatins IP that were statically requested
repeated string requested_ips = 6;
// optional, conatins extra features requested for the allocation
IPAMFeatures features = 7;
}

// IPAMMetadata contains metadata for IPAM calls
Expand All @@ -89,6 +91,12 @@ message IPAMMetadata {
string device_id = 4;
}

// IPAMFeatures contains extra features requested for the IPAM call
message IPAMFeatures {
// optional, request IP of the default gateway from the pool be allocated for container
bool allocate_default_gateway = 1;
}

// IsAllocatedRequest contains parameters for IsAllocated rpc call
message IsAllocatedRequest {
// required, IPAMParameters contains parameters IPAM parameters related to the request
Expand Down
3 changes: 3 additions & 0 deletions pkg/cni/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ func cniConfToGRPCReq(conf *types.NetConf, args *skel.CmdArgs) *nodev1.IPAMParam
DeviceId: conf.DeviceID,
},
RequestedIps: requestedIPs,
Features: &nodev1.IPAMFeatures{
AllocateDefaultGateway: conf.IPAM.Features.AllocateDefaultGateway,
},
}
if req.Metadata.K8SPodUid == "" {
log.Warningf("K8S_POD_UID is not provided by container runtime")
Expand Down
1 change: 1 addition & 0 deletions pkg/cni/plugin/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ var _ = Describe("plugin tests", func() {
K8SPodNamespace: "test",
},
RequestedIps: []string{},
Features: &nodev1.IPAMFeatures{},
}}).Return(&nodev1.AllocateResponse{
Allocations: []*nodev1.AllocationInfo{{
Pool: "my-pool",
Expand Down
23 changes: 20 additions & 3 deletions pkg/cni/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ type IPAMConf struct {
} `json:"-"`
// requested IPs from CNI_ARGS, args and capabilities
RequestedIPs []net.IP `json:"-"`
// internal representation of the requested features
Features struct {
// request to allocate pool's default gateway as
// interface IP address for the container
AllocateDefaultGateway bool
} `json:"-"`
}

// NetConf is CNI network config
Expand All @@ -95,9 +101,10 @@ type NetConf struct {

// IPAMArgs holds arguments from stdin args["cni"]
type IPAMArgs struct {
IPs []string `json:"ips"`
PoolNames []string `json:"poolNames"`
PoolType string `json:"poolType"`
IPs []string `json:"ips"`
PoolNames []string `json:"poolNames"`
PoolType string `json:"poolType"`
AllocateDefaultGateway bool `json:"allocateDefaultGateway"`
}

// IPAMEnvArgs holds arguments from CNI_ARGS env variable
Expand Down Expand Up @@ -173,6 +180,16 @@ func (cl *confLoader) LoadConf(args *skel.CmdArgs) (*NetConf, error) {
return nil, err
}

if n.Args != nil && n.Args.ArgsCNI != nil {
n.IPAM.Features.AllocateDefaultGateway = n.Args.ArgsCNI.AllocateDefaultGateway
}

if n.IPAM.Features.AllocateDefaultGateway {
if len(n.IPAM.RequestedIPs) > 0 {
return nil, fmt.Errorf("allocatedDefaultGateway can't be used together with static IP request")
}
}

n.IPAM.Pools, err = getPools(n)
if err != nil {
return nil, err
Expand Down
20 changes: 18 additions & 2 deletions pkg/ipam-node/handlers/allocate.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,12 @@ func (h *Handlers) allocateInPool(poolName string, reqLog logr.Logger,
if err != nil || subnet == nil || subnet.IP == nil || subnet.Mask == nil {
return PoolAlloc{}, poolCfgError(poolLog, poolName, poolType, "invalid subnet")
}
gateway := net.ParseIP(poolCfg.Gateway)
rangeSet := &allocator.RangeSet{allocator.Range{
RangeStart: rangeStart,
RangeEnd: rangeEnd,
Subnet: cniTypes.IPNet(*subnet),
Gateway: net.ParseIP(poolCfg.Gateway),
Gateway: gateway,
}}
if err := rangeSet.Canonicalize(); err != nil {
return PoolAlloc{}, poolCfgError(poolLog, poolName, poolType,
Expand All @@ -152,6 +153,16 @@ func (h *Handlers) allocateInPool(poolName string, reqLog logr.Logger,
break
}
}

if params.Features != nil && params.Features.AllocateDefaultGateway {
if gateway == nil {
return PoolAlloc{}, status.Errorf(codes.InvalidArgument,
"pool without gateway can't be used with allocate_default_gateway feature,"+
"pool \"%s\", poolType \"%s\"", poolName, poolType)
}
selectedStaticIP = gateway
}

exclusionRangeSet := make(allocator.RangeSet, 0, len(poolCfg.Exclusions))
for _, e := range poolCfg.Exclusions {
exclusionRangeSet = append(exclusionRangeSet, allocator.Range{
Expand Down Expand Up @@ -197,8 +208,13 @@ func (h *Handlers) allocateInPool(poolName string, reqLog logr.Logger,
return PoolAlloc{}, status.Errorf(codes.Internal,
"failed to allocate IP address in pool \"%s\", poolType \"%s\"", poolName, poolType)
}
poolLog.Info("IP address allocated", "allocation", result.String())
if params.Features != nil && params.Features.AllocateDefaultGateway {
// TODO (ykulazhenkov): do we want to keep gateway in this case?
// if we will return gateway here, the container will have same IP as interface address and as gateway
result.Gateway = nil
}

poolLog.Info("IP address allocated", "allocation", result.String())
return PoolAlloc{
Pool: poolName,
IPConfig: result,
Expand Down
4 changes: 4 additions & 0 deletions pkg/ipam-node/handlers/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ func validateReq(req paramsGetter) error {
return fieldsIsInvalidError(fmt.Sprintf("parameters.requested_ips[%d]", i))
}
}
if params.Features != nil && params.Features.AllocateDefaultGateway && len(params.RequestedIps) > 0 {
return status.Errorf(codes.InvalidArgument,
"parameters.features.allocate_default_gateway can't be used together with static IPs")
}
return nil
}

Expand Down

0 comments on commit 3917ecc

Please sign in to comment.