Skip to content

Commit

Permalink
Fix fetching enimetadata for efa-only enis
Browse files Browse the repository at this point in the history
  • Loading branch information
Pavani-Panakanti committed Sep 23, 2024
1 parent 5c471fe commit cc6f1c0
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 65 deletions.
143 changes: 78 additions & 65 deletions pkg/awsutils/awsutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,12 @@ func (cache *EC2InstanceMetadataCache) getENIMetadata(eniMAC string) (ENIMetadat
return ENIMetadata{}, err
}

networkCard, err := cache.imds.GetNetworkCard(ctx, eniMAC)
if err != nil {
awsAPIErrInc("GetNetworkCard", err)
return ENIMetadata{}, err
}

deviceNum, err = cache.imds.GetDeviceNumber(ctx, eniMAC)
if err != nil {
awsAPIErrInc("GetDeviceNumber", err)
Expand All @@ -602,90 +608,97 @@ func (cache *EC2InstanceMetadataCache) getENIMetadata(eniMAC string) (ENIMetadat
deviceNum = 0
}

log.Debugf("Found ENI: %s, MAC %s, device %d", eniID, eniMAC, deviceNum)

// Get IPv4 and IPv6 addresses assigned to interface
cidr, err := cache.imds.GetSubnetIPv4CIDRBlock(ctx, eniMAC)
if err != nil {
awsAPIErrInc("GetSubnetIPv4CIDRBlock", err)
return ENIMetadata{}, err
}

imdsIPv4s, err := cache.imds.GetLocalIPv4s(ctx, eniMAC)
if err != nil {
awsAPIErrInc("GetLocalIPv4s", err)
return ENIMetadata{}, err
}

ec2ip4s := make([]*ec2.NetworkInterfacePrivateIpAddress, len(imdsIPv4s))
for i, ip4 := range imdsIPv4s {
ec2ip4s[i] = &ec2.NetworkInterfacePrivateIpAddress{
Primary: aws.Bool(i == 0),
PrivateIpAddress: aws.String(ip4.String()),
}
}
log.Debugf("Found ENI: %s, MAC %s, device %d, network card %d", eniID, eniMAC, deviceNum, networkCard)

var subnetV4Cidr string
var ec2ip4s []*ec2.NetworkInterfacePrivateIpAddress
var ec2ip6s []*ec2.NetworkInterfaceIpv6Address
var subnetV6Cidr string
if cache.v6Enabled {
// For IPv6 ENIs, do not error on missing IPv6 information
v6cidr, err := cache.imds.GetSubnetIPv6CIDRBlocks(ctx, eniMAC)
if err != nil {
awsAPIErrInc("GetSubnetIPv6CIDRBlocks", err)
} else {
subnetV6Cidr = v6cidr.String()
}
var ec2ipv4Prefixes []*ec2.Ipv4PrefixSpecification
var ec2ipv6Prefixes []*ec2.Ipv6PrefixSpecification

imdsIPv6s, err := cache.imds.GetIPv6s(ctx, eniMAC)
if networkCard == 0 {
// Get IPv4 and IPv6 addresses assigned to interface
cidr, err := cache.imds.GetSubnetIPv4CIDRBlock(ctx, eniMAC)
if err != nil {
awsAPIErrInc("GetIPv6s", err)
awsAPIErrInc("GetSubnetIPv4CIDRBlock", err)
return ENIMetadata{}, err
} else {
ec2ip6s = make([]*ec2.NetworkInterfaceIpv6Address, len(imdsIPv6s))
for i, ip6 := range imdsIPv6s {
ec2ip6s[i] = &ec2.NetworkInterfaceIpv6Address{
Ipv6Address: aws.String(ip6.String()),
}
}
subnetV4Cidr = cidr.String()
}
}

var ec2ipv4Prefixes []*ec2.Ipv4PrefixSpecification
var ec2ipv6Prefixes []*ec2.Ipv6PrefixSpecification

// If IPv6 is enabled, get attached v6 prefixes.
if cache.v6Enabled {
imdsIPv6Prefixes, err := cache.imds.GetIPv6Prefixes(ctx, eniMAC)
imdsIPv4s, err := cache.imds.GetLocalIPv4s(ctx, eniMAC)
if err != nil {
awsAPIErrInc("GetIPv6Prefixes", err)
awsAPIErrInc("GetLocalIPv4s", err)
return ENIMetadata{}, err
}
for _, ipv6prefix := range imdsIPv6Prefixes {
ec2ipv6Prefixes = append(ec2ipv6Prefixes, &ec2.Ipv6PrefixSpecification{
Ipv6Prefix: aws.String(ipv6prefix.String()),
})

ec2ip4s = make([]*ec2.NetworkInterfacePrivateIpAddress, len(imdsIPv4s))
for i, ip4 := range imdsIPv4s {
ec2ip4s[i] = &ec2.NetworkInterfacePrivateIpAddress{
Primary: aws.Bool(i == 0),
PrivateIpAddress: aws.String(ip4.String()),
}
}
} else if cache.v4Enabled && ((eniMAC == primaryMAC && !cache.useCustomNetworking) || (eniMAC != primaryMAC)) {
// Get prefix on primary ENI when custom networking is enabled is not needed.
// If primary ENI has prefixes attached and then we move to custom networking, we don't need to fetch
// the prefix since recommendation is to terminate the nodes and that would have deleted the prefix on the
// primary ENI.
imdsIPv4Prefixes, err := cache.imds.GetIPv4Prefixes(ctx, eniMAC)
if err != nil {
awsAPIErrInc("GetIPv4Prefixes", err)
return ENIMetadata{}, err


if cache.v6Enabled {
// For IPv6 ENIs, do not error on missing IPv6 information
v6cidr, err := cache.imds.GetSubnetIPv6CIDRBlocks(ctx, eniMAC)
if err != nil {
awsAPIErrInc("GetSubnetIPv6CIDRBlocks", err)
} else {
subnetV6Cidr = v6cidr.String()
}

imdsIPv6s, err := cache.imds.GetIPv6s(ctx, eniMAC)
if err != nil {
awsAPIErrInc("GetIPv6s", err)
} else {
ec2ip6s = make([]*ec2.NetworkInterfaceIpv6Address, len(imdsIPv6s))
for i, ip6 := range imdsIPv6s {
ec2ip6s[i] = &ec2.NetworkInterfaceIpv6Address{
Ipv6Address: aws.String(ip6.String()),
}
}
}
}
for _, ipv4prefix := range imdsIPv4Prefixes {
ec2ipv4Prefixes = append(ec2ipv4Prefixes, &ec2.Ipv4PrefixSpecification{
Ipv4Prefix: aws.String(ipv4prefix.String()),
})

// If IPv6 is enabled, get attached v6 prefixes.
if cache.v6Enabled {
imdsIPv6Prefixes, err := cache.imds.GetIPv6Prefixes(ctx, eniMAC)
if err != nil {
awsAPIErrInc("GetIPv6Prefixes", err)
return ENIMetadata{}, err
}
for _, ipv6prefix := range imdsIPv6Prefixes {
ec2ipv6Prefixes = append(ec2ipv6Prefixes, &ec2.Ipv6PrefixSpecification{
Ipv6Prefix: aws.String(ipv6prefix.String()),
})
}
} else if cache.v4Enabled && ((eniMAC == primaryMAC && !cache.useCustomNetworking) || (eniMAC != primaryMAC)) {
// Get prefix on primary ENI when custom networking is enabled is not needed.
// If primary ENI has prefixes attached and then we move to custom networking, we don't need to fetch
// the prefix since recommendation is to terminate the nodes and that would have deleted the prefix on the
// primary ENI.
imdsIPv4Prefixes, err := cache.imds.GetIPv4Prefixes(ctx, eniMAC)
if err != nil {
awsAPIErrInc("GetIPv4Prefixes", err)
return ENIMetadata{}, err
}
for _, ipv4prefix := range imdsIPv4Prefixes {
ec2ipv4Prefixes = append(ec2ipv4Prefixes, &ec2.Ipv4PrefixSpecification{
Ipv4Prefix: aws.String(ipv4prefix.String()),
})
}
}
}

return ENIMetadata{
ENIID: eniID,
MAC: eniMAC,
DeviceNumber: deviceNum,
SubnetIPv4CIDR: cidr.String(),
SubnetIPv4CIDR: subnetV4Cidr,
IPv4Addresses: ec2ip4s,
IPv4Prefixes: ec2ipv4Prefixes,
SubnetIPv6CIDR: subnetV6Cidr,
Expand Down Expand Up @@ -1356,7 +1369,7 @@ func (cache *EC2InstanceMetadataCache) DescribeAllENIs() (DescribeAllENIsResult,
if interfaceType == "trunk" {
trunkENI = eniID
}
if interfaceType == "efa" {
if interfaceType == "efa" || interfaceType == "efa-only" {
efaENIs[eniID] = true
}
// Check IPv4 addresses
Expand Down
6 changes: 6 additions & 0 deletions pkg/awsutils/imds.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ func (imds TypedIMDS) getInt(ctx context.Context, key string) (int, error) {
return dataInt, err
}

// GetNetworkCard returns the unique network card number associated with an interface.
func (imds TypedIMDS) GetNetworkCard(ctx context.Context, mac string) (int, error) {
key := fmt.Sprintf("network/interfaces/macs/%s/network-card", mac)
return imds.getInt(ctx, key)
}

// GetDeviceNumber returns the unique device number associated with an interface. The primary interface is 0.
func (imds TypedIMDS) GetDeviceNumber(ctx context.Context, mac string) (int, error) {
key := fmt.Sprintf("network/interfaces/macs/%s/device-number", mac)
Expand Down

0 comments on commit cc6f1c0

Please sign in to comment.