Skip to content

Commit 0f5157a

Browse files
committed
Fix delete with prev result logic
1 parent fe35b66 commit 0f5157a

File tree

7 files changed

+93
-72
lines changed

7 files changed

+93
-72
lines changed

cmd/routed-eni-cni-plugin/cni.go

+30-28
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,11 @@ func add(args *skel.CmdArgs, cniTypes typeswrapper.CNITYPES, grpcClient grpcwrap
170170
requiresMultiNICAttachment = true
171171
} else {
172172
log.Debugf("Multi-NIC annotation mismatch: found=%q, required=%q. Falling back to default configuration.",
173-
multiNICAttachment, conf.RuntimeConfig.PodAnnotations[multiNICPodAnnotation])
173+
conf.RuntimeConfig.PodAnnotations[multiNICPodAnnotation], multiNICAttachment)
174174
}
175175
}
176176

177-
log.Debugf("pod requires Multi-NIC attachment: %t", requiresMultiNICAttachment)
177+
log.Debugf("pod requires multi-nic attachment: %t", requiresMultiNICAttachment)
178178

179179
// Set up a connection to the ipamD server.
180180
conn, err := grpcClient.Dial(ipamdAddress, grpc.WithTransportCredentials(insecure.NewCredentials()))
@@ -245,12 +245,11 @@ func add(args *skel.CmdArgs, cniTypes typeswrapper.CNITYPES, grpcClient grpcwrap
245245
HostVethName: hostVethName,
246246
ContainerVethName: containerVethName,
247247
})
248-
249-
// Check if we can use PCIID to store RT-ID ?
250-
// The RT here is the host route table Id not the container
248+
// CNI stores the route table ID in the MAC field of the interface. The Route table ID is on the host side
249+
// and is used during cleanup to remove the ip rules when IPAMD is not reachable.
251250
podInterfaces = append(podInterfaces,
252251
&current.Interface{Name: hostVethName},
253-
&current.Interface{Name: containerVethName, Sandbox: args.Netns, PciID: fmt.Sprint(ip.RouteTableId)},
252+
&current.Interface{Name: containerVethName, Sandbox: args.Netns, Mac: fmt.Sprint(ip.RouteTableId)},
254253
)
255254

256255
// This index always points to the container interface so that we get the IP address corresponding to the interface
@@ -276,7 +275,7 @@ func add(args *skel.CmdArgs, cniTypes typeswrapper.CNITYPES, grpcClient grpcwrap
276275
} else {
277276
err = driverClient.SetupPodNetwork(vethMetadata, args.Netns, mtu, log)
278277
// For non-branch ENI, the pod VLAN ID value of 0 is packed in Interface.Mac, while the interface device number is packed in Interface.Sandbox
279-
dummyInterface = &current.Interface{Name: dummyInterfaceName, Mac: fmt.Sprint(0), Sandbox: fmt.Sprint(vethMetadata[0].DeviceNumber), SocketPath: fmt.Sprint(len(r.IPAddress))}
278+
dummyInterface = &current.Interface{Name: dummyInterfaceName, Mac: fmt.Sprint(0), Sandbox: fmt.Sprint(vethMetadata[0].DeviceNumber)}
280279
}
281280

282281
log.Debugf("Using dummy interface: %v", dummyInterface)
@@ -311,6 +310,8 @@ func add(args *skel.CmdArgs, cniTypes typeswrapper.CNITYPES, grpcClient grpcwrap
311310
}
312311

313312
// dummy interface is appended to PrevResult for use during cleanup
313+
// The interfaces field should only include host,container and dummy interfaces in the list.
314+
// Revisit the prevResult cleanup logic if this changes
314315
result.Interfaces = append(result.Interfaces, dummyInterface)
315316

316317
// Set up a connection to the network policy agent
@@ -348,7 +349,6 @@ func add(args *skel.CmdArgs, cniTypes typeswrapper.CNITYPES, grpcClient grpcwrap
348349
}
349350

350351
log.Debugf("Network Policy agent for EnforceNpToPod returned Success : %v", npr.Success)
351-
352352
return cniTypes.PrintResult(result, conf.CNIVersion)
353353
}
354354

@@ -539,8 +539,13 @@ func getContainerNetworkMetadata(prevResult *current.Result, contVethName string
539539
// returns true if the del request is handled.
540540
func tryDelWithPrevResult(driverClient driver.NetworkAPIs, conf *NetConf, k8sArgs K8sArgs, contVethName string, netNS string, log logger.Logger) (bool, error) {
541541
// prevResult might not be available, if we are still using older cni spec < 0.4.0.
542-
prevResult, ok := conf.PrevResult.(*current.Result)
543-
if !ok {
542+
if conf.PrevResult == nil {
543+
return false, nil
544+
}
545+
546+
prevResult, err := current.NewResultFromResult(conf.PrevResult)
547+
if err != nil {
548+
log.Info("PrevResult not available for pod or parsing failed")
544549
return false, nil
545550
}
546551

@@ -581,8 +586,13 @@ func tryDelWithPrevResult(driverClient driver.NetworkAPIs, conf *NetConf, k8sArg
581586
// Returns true if pod network is torn down
582587
func teardownPodNetworkWithPrevResult(driverClient driver.NetworkAPIs, conf *NetConf, k8sArgs K8sArgs, contVethName string, log logger.Logger) bool {
583588
// For non-branch ENI, prevResult is only available in v1.12.1+
584-
prevResult, ok := conf.PrevResult.(*current.Result)
585-
if !ok {
589+
if conf.PrevResult == nil {
590+
log.Infof("PrevResult not available for pod. Pod may have already been deleted.")
591+
return false
592+
}
593+
594+
prevResult, err := current.NewResultFromResult(conf.PrevResult)
595+
if err != nil {
586596
log.Infof("PrevResult not available for pod. Pod may have already been deleted.")
587597
return false
588598
}
@@ -607,32 +617,24 @@ func teardownPodNetworkWithPrevResult(driverClient driver.NetworkAPIs, conf *Net
607617
// RT ID for NC-0 is also stored in the container interface entry. So we have a path for migration where
608618
// getting the device number from dummy interface can be deprecated entirely. This is currently done to keep it backwards compatible
609619
routeTableId := deviceNumber + 1
610-
611-
var interfacesAttached = 1
612-
if dummyIface.SocketPath != "" {
613-
interfacesAttached, err = strconv.Atoi(dummyIface.SocketPath)
614-
if err != nil {
615-
log.Errorf("error getting number of interfaces attached to the pod: %s", dummyIface.SocketPath)
616-
return false
617-
}
618-
}
619-
620+
// The number of interfaces attached to the pod is taken as the length of the interfaces array - 1 (for dummy interface) divided by 2 (for host and container interface)
621+
var interfacesAttached = (len(prevResult.Interfaces) - 1) / 2
620622
var vethMetadata []driver.VirtualInterfaceMetadata
621623
for v := range interfacesAttached {
622624
containerInterfaceName := networkutils.GenerateContainerVethName(contVethName, containerVethNamePrefix, v)
623625
containerIP, containerInterface, err := getContainerNetworkMetadata(prevResult, containerInterfaceName)
624626
if err != nil {
625-
log.Errorf("Failed to get container IP: %v", err)
626-
return false
627+
log.Errorf("container interface name %s does not exist %v", containerInterfaceName, err)
628+
continue
627629
}
628630

629631
// If this property is set, that means the container metadata has the route table ID which we can use
630632
// If this is not set, it is a pod launched before this change was introduced.
631-
// So it is only managing network card 0 at that time and device number + 1 is the route table ID which we have above
632-
if dummyIface.SocketPath != "" {
633-
routeTableId, err = strconv.Atoi(containerInterface.PciID)
633+
// So it is only managing network card 0 at that time and device number + 1 is the route table ID which we calculate from device number
634+
if containerInterface.Mac != "" {
635+
routeTableId, err = strconv.Atoi(containerInterface.Mac)
634636
if err != nil {
635-
log.Errorf("error getting route table number of the interface %s", containerInterface.PciID)
637+
log.Errorf("error getting route table number of the interface %s", containerInterface.Mac)
636638
return false
637639
}
638640
}

go.sum

+4-4
Original file line numberDiff line numberDiff line change
@@ -329,10 +329,10 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
329329
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
330330
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
331331
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
332-
github.com/onsi/ginkgo/v2 v2.22.1 h1:QW7tbJAUDyVDVOM5dFa7qaybo+CRfR7bemlQUN6Z8aM=
333-
github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM=
334-
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
335-
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
332+
github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
333+
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
334+
github.com/onsi/gomega v1.36.0 h1:Pb12RlruUtj4XUuPUqeEWc6j5DkVVVA49Uf6YLfC95Y=
335+
github.com/onsi/gomega v1.36.0/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
336336
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
337337
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
338338
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=

pkg/awsutils/awsutils.go

+2-5
Original file line numberDiff line numberDiff line change
@@ -918,12 +918,9 @@ func (cache *EC2InstanceMetadataCache) attachENI(eniID string, networkCard int)
918918

919919
// createENITags creates all the tags required to be added to the ENI
920920
//
921-
// Parameters:
922-
// - eniDescription (string):
923-
//
924921
// Returns:
925922
// - []ec2types.TagSpecification: Returns the tags by converting it into AWS SDK class
926-
func (cache *EC2InstanceMetadataCache) createENITags(eniDescription string) []ec2types.TagSpecification {
923+
func (cache *EC2InstanceMetadataCache) createENITags() []ec2types.TagSpecification {
927924

928925
tags := map[string]string{
929926
eniCreatedAtTagKey: time.Now().Format(time.RFC3339),
@@ -966,7 +963,7 @@ func (cache *EC2InstanceMetadataCache) createENIInput(eniDescription string, tag
966963
// return ENI id, error
967964
func (cache *EC2InstanceMetadataCache) createENI(sg []*string, eniCfgSubnet string, numIPs int) (string, error) {
968965
eniDescription := eniDescriptionPrefix + cache.instanceID
969-
tags := cache.createENITags(eniDescription)
966+
tags := cache.createENITags()
970967

971968
var needIPs = numIPs
972969

pkg/ipamd/datastore/data_store.go

+26-15
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ type DataStore struct {
281281
netLink netlinkwrapper.NetLink
282282
isPDEnabled bool
283283
ipCooldownPeriod time.Duration
284+
networkCard int
284285
}
285286

286287
// ENIInfos contains ENI IP information
@@ -294,14 +295,15 @@ type ENIInfos struct {
294295
}
295296

296297
// NewDataStore returns DataStore structure
297-
func NewDataStore(log logger.Logger, backingStore Checkpointer, isPDEnabled bool) *DataStore {
298+
func NewDataStore(log logger.Logger, backingStore Checkpointer, isPDEnabled bool, networkCard int) *DataStore {
298299
return &DataStore{
299300
eniPool: make(ENIPool),
300301
log: log,
301302
backingStore: backingStore,
302303
netLink: netlinkwrapper.NewNetLink(),
303304
isPDEnabled: isPDEnabled,
304305
ipCooldownPeriod: getCooldownPeriod(),
306+
networkCard: networkCard,
305307
}
306308
}
307309

@@ -743,7 +745,7 @@ func (ds *DataStore) AssignPodIPv4Address(ipamKey IPAMKey, ipamMetadata IPAMMeta
743745

744746
// assignPodIPAddressUnsafe mark Address as assigned.
745747
func (ds *DataStore) assignPodIPAddressUnsafe(addr *AddressInfo, ipamKey IPAMKey, ipamMetadata IPAMMetadata, assignedTime time.Time) {
746-
ds.log.Infof("assignPodIPAddressUnsafe: Assign IP %v to sandbox %s with metadata %",
748+
ds.log.Infof("assignPodIPAddressUnsafe: Assign IP %v to sandbox %s with metadata %+v",
747749
addr.Address, ipamKey, ipamMetadata)
748750

749751
if addr.Assigned() {
@@ -1360,6 +1362,10 @@ func (ds *DataStore) getUnusedIP(availableCidr *CidrInfo) (string, error) {
13601362
return "", fmt.Errorf("no free IP available in the prefix - %s/%s", availableCidr.Cidr.IP, availableCidr.Cidr.Mask)
13611363
}
13621364

1365+
func (ds *DataStore) GetNetworkCard() int {
1366+
return ds.networkCard
1367+
}
1368+
13631369
func getNextIPAddr(ip net.IP) {
13641370
for j := len(ip) - 1; j >= 0; j-- {
13651371
ip[j]++
@@ -1547,34 +1553,39 @@ func (ds *DataStore) DeleteFromContainerRule(entry *CheckpointEntry) {
15471553
}
15481554

15491555
type DataStoreAccess struct {
1550-
DataStores map[int]*DataStore
1556+
DataStores []*DataStore
15511557
}
15521558

15531559
func InitializeDataStores(skipNetworkCards []bool, defaultDataStorePath string, enablePD bool, log logger.Logger) *DataStoreAccess {
15541560

1555-
var dsMap = make(map[int]*DataStore, len(skipNetworkCards))
1556-
for i, shouldSkip := range skipNetworkCards {
1557-
if shouldSkip {
1558-
continue
1559-
} else {
1561+
var dsList = make([]*DataStore, 0, len(skipNetworkCards))
1562+
for networkCard, shouldSkip := range skipNetworkCards {
1563+
1564+
if !shouldSkip {
15601565
dsBackingStorePath := defaultDataStorePath
1561-
if i > 0 {
1566+
if networkCard > 0 {
15621567
baseName := strings.TrimSuffix(defaultDataStorePath, ".json")
1563-
dsBackingStorePath = fmt.Sprintf("%s-nic-%d.json", baseName, i)
1568+
dsBackingStorePath = fmt.Sprintf("%s-nic-%d.json", baseName, networkCard)
15641569
}
15651570
checkpointer := NewJSONFile(dsBackingStorePath)
1566-
dsMap[i] = NewDataStore(log, checkpointer, enablePD)
1567-
log.Infof("initialized datastore for network cards index %d", i)
1571+
dsList = append(dsList, NewDataStore(log, checkpointer, enablePD, networkCard))
1572+
log.Infof("initialized datastore for network cards index %d", networkCard)
15681573
}
15691574
}
15701575

15711576
return &DataStoreAccess{
1572-
DataStores: dsMap,
1577+
DataStores: dsList,
15731578
}
15741579
}
15751580

1576-
func (ds *DataStoreAccess) GetDataStore(index int) *DataStore {
1577-
return ds.DataStores[index]
1581+
func (ds *DataStoreAccess) GetDataStore(networkCard int) *DataStore {
1582+
1583+
for index, datastore := range ds.DataStores {
1584+
if datastore.GetNetworkCard() == networkCard {
1585+
return ds.DataStores[index]
1586+
}
1587+
}
1588+
return nil
15781589
}
15791590

15801591
func (ds *DataStoreAccess) ReadAllDataStores(enableIPv6 bool) error {

pkg/ipamd/introspect.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ func (c *IPAMContext) setupIntrospectionServer() *http.Server {
125125
func eniV1RequestHandler(ipam *IPAMContext) func(http.ResponseWriter, *http.Request) {
126126
return func(w http.ResponseWriter, r *http.Request) {
127127
eniInfos := make(map[int]*datastore.ENIInfos, len(ipam.dataStoreAccess.DataStores))
128-
for networkCard, ds := range ipam.dataStoreAccess.DataStores {
129-
eniInfos[networkCard] = ds.GetENIInfos()
128+
for _, ds := range ipam.dataStoreAccess.DataStores {
129+
eniInfos[ds.GetNetworkCard()] = ds.GetENIInfos()
130130
}
131131
responseJSON, err := json.Marshal(eniInfos)
132132
if err != nil {

pkg/ipamd/ipamd.go

+11-8
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,6 @@ var (
216216
// IPAMContext contains node level control information
217217
type IPAMContext struct {
218218
awsClient awsutils.APIs
219-
dataStore []*datastore.DataStore
220219
dataStoreAccess *datastore.DataStoreAccess
221220
k8sClient client.Client
222221
enableIPv4 bool
@@ -964,7 +963,8 @@ func (c *IPAMContext) createSecondaryIPv6ENIs(ctx context.Context) error {
964963

965964
log.Info("Attaching ENIs allowed")
966965

967-
for networkCard, ds := range c.dataStoreAccess.DataStores {
966+
for _, ds := range c.dataStoreAccess.DataStores {
967+
networkCard := ds.GetNetworkCard()
968968
if networkCard == DefaultNetworkCardIndex {
969969
continue
970970
}
@@ -1527,7 +1527,8 @@ func (c *IPAMContext) nodeIPPoolReconcile(ctx context.Context, interval time.Dur
15271527
allManagedAndAttachedENIs := c.filterUnmanagedENIs(allENIs)
15281528
attachedENIsByNetworkCard := c.getENIsByNetworkCard(allManagedAndAttachedENIs)
15291529

1530-
for networkCard, ds := range c.dataStoreAccess.DataStores {
1530+
for _, ds := range c.dataStoreAccess.DataStores {
1531+
networkCard := ds.GetNetworkCard()
15311532
currentENIs := ds.GetENIInfos().ENIs
15321533
attachedENIs := attachedENIsByNetworkCard[networkCard]
15331534
trunkENI := ds.GetTrunkENI()
@@ -2280,7 +2281,7 @@ func (c *IPAMContext) AnnotatePod(podName string, podNamespace string, key strin
22802281
if ok {
22812282
log.Debugf("Existing annotation value: %s", oldVal)
22822283
if oldVal != releasedIP {
2283-
return fmt.Errorf("Released IP %s does not match existing annotation. Not patching pod.", releasedIP)
2284+
return fmt.Errorf("released IP %s does not match existing annotation. Not patching pod", releasedIP)
22842285
}
22852286
newPod.Annotations[key] = ""
22862287
}
@@ -2300,7 +2301,8 @@ func (c *IPAMContext) AnnotatePod(podName string, podNamespace string, key strin
23002301
func (c *IPAMContext) tryUnassignIPsFromENIs() {
23012302
log.Debugf("tryUnassignIPsFromENIs")
23022303
// From all datastores, get ENIInfos and unassign IPs
2303-
for networkCard, ds := range c.dataStoreAccess.DataStores {
2304+
for _, ds := range c.dataStoreAccess.DataStores {
2305+
networkCard := ds.GetNetworkCard()
23042306
eniInfos := ds.GetENIInfos()
23052307
for eniID := range eniInfos.ENIs {
23062308
c.tryUnassignIPFromENI(eniID, networkCard)
@@ -2345,7 +2347,8 @@ func (c *IPAMContext) tryUnassignPrefixesFromENIs() {
23452347
log.Debugf("tryUnassignPrefixesFromENIs")
23462348

23472349
// From all datastores get ENIs and remove prefixes
2348-
for networkCard, ds := range c.dataStoreAccess.DataStores {
2350+
for _, ds := range c.dataStoreAccess.DataStores {
2351+
networkCard := ds.GetNetworkCard()
23492352
eniInfos := ds.GetENIInfos()
23502353
for eniID := range eniInfos.ENIs {
23512354
c.tryUnassignPrefixFromENI(eniID, networkCard)
@@ -2442,8 +2445,8 @@ func (c *IPAMContext) isDatastorePoolTooLow() map[int]Decisions {
24422445
totalIPs = maxIpsPerPrefix
24432446
}
24442447

2445-
for networkCard, ds := range c.dataStoreAccess.DataStores {
2446-
2448+
for _, ds := range c.dataStoreAccess.DataStores {
2449+
networkCard := ds.GetNetworkCard()
24472450
stats := ds.GetIPStats(ipV4AddrFamily)
24482451
// If max pods has been reached, pool is not too low
24492452
if stats.TotalIPs >= c.maxPods {

0 commit comments

Comments
 (0)