Skip to content
Open
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
18 changes: 15 additions & 3 deletions pkg/cfn/builder/network_interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,31 @@ func buildNetworkInterfaces(
}

var numEFAs = math.MaxFloat64
var efaStartCard int
for _, it := range info.InstanceTypes {
networkInfo := it.NetworkInfo
numEFAs = math.Min(float64(aws.ToInt32(networkInfo.MaximumNetworkCards)), numEFAs)
if !aws.ToBool(networkInfo.EfaSupported) {
return fmt.Errorf("instance type %s does not support EFA", it.InstanceType)
}
if networkInfo.EfaInfo != nil && networkInfo.EfaInfo.MaximumEfaInterfaces != nil {
maxEfa := aws.ToInt32(networkInfo.EfaInfo.MaximumEfaInterfaces)
numEFAs = math.Min(float64(maxEfa), numEFAs)
// If EFA interfaces < network cards, network card 0 is ENA-only
if maxEfa < aws.ToInt32(networkInfo.MaximumNetworkCards) {
efaStartCard = 1
}
} else {
numEFAs = math.Min(float64(aws.ToInt32(networkInfo.MaximumNetworkCards)), numEFAs)
}
}

firstNI.InterfaceType = gfnt.NewString("efa")
if efaStartCard == 0 {
firstNI.InterfaceType = gfnt.NewString("efa")
}
nis := []gfnec2.LaunchTemplate_NetworkInterface{firstNI}
// The primary network interface (device index 0) must be assigned to network card index 0
// device index 1 for additional cards
for i := 1; i < int(numEFAs); i++ {
for i := 1; i < int(numEFAs)+efaStartCard; i++ {
ni := defaultNetworkInterface(securityGroups, 1, i)
ni.InterfaceType = gfnt.NewString("efa")
nis = append(nis, ni)
Expand Down
62 changes: 59 additions & 3 deletions pkg/cfn/builder/network_interfaces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func TestBuildNetworkInterfaces(t *testing.T) {
mockInstanceTypes []ec2types.InstanceTypeInfo
expectedNetworkInterfaces int
expectedInterfaceType string
expectedFirstNIEfa bool // whether first NI should be EFA
expectedError string
}{
{
Expand Down Expand Up @@ -56,6 +57,7 @@ func TestBuildNetworkInterfaces(t *testing.T) {
},
expectedNetworkInterfaces: 1,
expectedInterfaceType: "efa",
expectedFirstNIEfa: true,
},
{
name: "EFA nodegroup with multiple network cards",
Expand All @@ -76,6 +78,7 @@ func TestBuildNetworkInterfaces(t *testing.T) {
},
expectedNetworkInterfaces: 4,
expectedInterfaceType: "efa",
expectedFirstNIEfa: true,
},
{
name: "EFA nodegroup with mixed instance types",
Expand Down Expand Up @@ -103,6 +106,7 @@ func TestBuildNetworkInterfaces(t *testing.T) {
},
expectedNetworkInterfaces: 1, // Should use minimum across instance types
expectedInterfaceType: "efa",
expectedFirstNIEfa: true,
},
{
name: "EFA nodegroup with non-EFA instance type",
Expand Down Expand Up @@ -141,6 +145,53 @@ func TestBuildNetworkInterfaces(t *testing.T) {
},
expectedNetworkInterfaces: 4,
expectedInterfaceType: "efa",
expectedFirstNIEfa: true,
},
{
name: "EFA nodegroup with MaximumEfaInterfaces less than MaximumNetworkCards",
instanceTypes: []string{"p6-b300.48xlarge"},
efaEnabled: true,
securityGroups: []*gfnt.Value{
gfnt.NewString("sg-12345"),
},
mockInstanceTypes: []ec2types.InstanceTypeInfo{
{
InstanceType: "p6-b300.48xlarge",
NetworkInfo: &ec2types.NetworkInfo{
MaximumNetworkCards: aws.Int32(17),
EfaSupported: aws.Bool(true),
EfaInfo: &ec2types.EfaInfo{
MaximumEfaInterfaces: aws.Int32(16),
},
},
},
},
expectedNetworkInterfaces: 17, // 1 ENA (card 0) + 16 EFA (cards 1-16)
expectedInterfaceType: "efa",

Choose a reason for hiding this comment

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

nit: this is misleading

expectedFirstNIEfa: false, // Network card 0 is ENA-only
},
{
name: "EFA nodegroup with EfaInfo present and matching MaximumNetworkCards",
instanceTypes: []string{"p5.48xlarge"},
efaEnabled: true,
securityGroups: []*gfnt.Value{
gfnt.NewString("sg-12345"),
},
mockInstanceTypes: []ec2types.InstanceTypeInfo{
{
InstanceType: "p5.48xlarge",
NetworkInfo: &ec2types.NetworkInfo{
MaximumNetworkCards: aws.Int32(32),
EfaSupported: aws.Bool(true),
EfaInfo: &ec2types.EfaInfo{
MaximumEfaInterfaces: aws.Int32(32),
},
},
},
},
expectedNetworkInterfaces: 32,
expectedInterfaceType: "efa",
expectedFirstNIEfa: true,
},
{
name: "EFA nodegroup with custom EFA security groups (1.32 scenario)",
Expand All @@ -162,6 +213,7 @@ func TestBuildNetworkInterfaces(t *testing.T) {
},
expectedNetworkInterfaces: 4,
expectedInterfaceType: "efa",
expectedFirstNIEfa: true,
},
}

Expand Down Expand Up @@ -235,9 +287,13 @@ func TestBuildNetworkInterfaces(t *testing.T) {
}

if tt.efaEnabled && tt.expectedError == "" {
// Verify EFA interface type
require.NotNil(t, firstNI.InterfaceType)
assert.Equal(t, gfnt.String(tt.expectedInterfaceType), firstNI.InterfaceType.Raw())
// Verify first NI EFA type
if tt.expectedFirstNIEfa {
require.NotNil(t, firstNI.InterfaceType)
assert.Equal(t, gfnt.String(tt.expectedInterfaceType), firstNI.InterfaceType.Raw())
} else {
assert.Nil(t, firstNI.InterfaceType)
}

// Verify additional network interfaces for multi-card instances
for i := 1; i < tt.expectedNetworkInterfaces; i++ {
Expand Down
Loading