Skip to content

Commit

Permalink
Merge pull request #68 from dougbtv/networkstatus-multiple-interface-…
Browse files Browse the repository at this point in the history
…result

Adds CreateNetworkStatuses for CNI results with multiple pod interfaces
  • Loading branch information
dougbtv authored Aug 1, 2024
2 parents e1583b6 + 38ceddc commit ec02fb3
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 0 deletions.
61 changes: 61 additions & 0 deletions pkg/utils/net-attach-def.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,67 @@ func GetNetworkStatus(pod *corev1.Pod) ([]v1.NetworkStatus, error) {
return netStatuses, err
}

// CreateNetworkStatuses creates an array of NetworkStatus from CNI result
// Not to be confused with CreateNetworkStatus (singular)
// This is the preferred method and picks up when CNI ADD results contain multiple container interfaces
func CreateNetworkStatuses(r cnitypes.Result, networkName string, defaultNetwork bool, dev *v1.DeviceInfo) ([]*v1.NetworkStatus, error) {
var networkStatuses []*v1.NetworkStatus
// indexMap is from original CNI result index to networkStatuses index
indexMap := make(map[int]int)

// Convert whatever the IPAM result was into the current Result type
result, err := cni100.NewResultFromResult(r)
if err != nil {
return nil, fmt.Errorf("error converting the type.Result to cni100.Result: %v", err)
}

// Discover default routes upfront and reuse them if necessary.
var useDefaultRoute []string
for _, route := range result.Routes {
if isDefaultRoute(route) {
useDefaultRoute = append(useDefaultRoute, route.GW.String())
}
}

// Same for DNS
v1dns := convertDNS(result.DNS)

// Initialize NetworkStatus for each container interface (e.g. with sandbox present)
indexOfFoundPodInterface := 0
for i, iface := range result.Interfaces {
if iface.Sandbox != "" {
ns := &v1.NetworkStatus{
Name: networkName,
Default: defaultNetwork,
Interface: iface.Name,
Mac: iface.Mac,
Mtu: iface.Mtu,
IPs: []string{},
Gateway: useDefaultRoute,
DeviceInfo: dev,
DNS: *v1dns,
}
networkStatuses = append(networkStatuses, ns)
// Map original index to the new slice index
indexMap[i] = indexOfFoundPodInterface
indexOfFoundPodInterface++
}
}

// Map IPs to network interface based on index
for _, ipConfig := range result.IPs {
if ipConfig.Interface != nil {
originalIndex := *ipConfig.Interface
if newIndex, ok := indexMap[originalIndex]; ok {
ns := networkStatuses[newIndex]
ns.IPs = append(ns.IPs, ipConfig.Address.IP.String())
}
}
}

return networkStatuses, nil
}

// CreateNetworkStatus create NetworkStatus from CNI result
func CreateNetworkStatus(r cnitypes.Result, networkName string, defaultNetwork bool, dev *v1.DeviceInfo) (*v1.NetworkStatus, error) {
netStatus := &v1.NetworkStatus{}
Expand Down
73 changes: 73 additions & 0 deletions pkg/utils/net-attach-def_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,79 @@ var _ = Describe("Netwok Attachment Definition manipulations", func() {
})
})

Context("create network statuses from CNI result with multiple interfaces", func() {
var cniResult *cni100.Result
var networkStatuses []*v1.NetworkStatus

BeforeEach(func() {
cniResult = &cni100.Result{
CNIVersion: "1.1.0",
Interfaces: []*cni100.Interface{
{
Name: "example0",
Mac: "00:AA:BB:CC:DD:01",
Sandbox: "/path/to/network/namespace",
Mtu: 1500,
},
{
Name: "foo",
Mac: "00:AA:BB:CC:DD:33",
},
{
Name: "example1",
Mac: "00:AA:BB:CC:DD:02",
Sandbox: "/path/to/network/namespace",
Mtu: 1500,
},
},
IPs: []*cni100.IPConfig{
{
Address: *EnsureCIDR("192.0.2.1/24"),
Interface: &[]int{0}[0],
},
{
Address: *EnsureCIDR("192.0.2.2/24"),
Interface: &[]int{0}[0],
},
{
Address: *EnsureCIDR("192.0.2.3/24"),
Interface: &[]int{2}[0],
},
},
DNS: cnitypes.DNS{
Nameservers: []string{"8.8.8.8", "8.8.4.4"},
Search: []string{"example.com"},
Options: []string{"ndots:2"},
},
}
var err error
networkStatuses, err = CreateNetworkStatuses(cniResult, "test-multi-net-attach-def", false, nil)
Expect(err).NotTo(HaveOccurred())
})

It("creates network statuses for interfaces with sandbox", func() {
Expect(networkStatuses).To(HaveLen(2))
// Check details for the first returned network status
Expect(networkStatuses[0].Name).To(Equal("test-multi-net-attach-def"))
Expect(networkStatuses[0].Interface).To(Equal("example0"))
Expect(networkStatuses[0].Mtu).To(Equal(1500))
Expect(networkStatuses[0].Mac).To(Equal("00:AA:BB:CC:DD:01"))
Expect(networkStatuses[0].IPs).To(ConsistOf("192.0.2.1", "192.0.2.2"))

// Check details for the second returned network status
Expect(networkStatuses[1].Interface).To(Equal("example1"))
Expect(networkStatuses[1].Mtu).To(Equal(1500))
Expect(networkStatuses[1].Mac).To(Equal("00:AA:BB:CC:DD:02"))
Expect(networkStatuses[1].IPs).To(ConsistOf("192.0.2.3"))
})

It("excludes interfaces without a sandbox", func() {
for _, status := range networkStatuses {
Expect(status.Interface).NotTo(Equal("foo"))
}
})
})

It("parse network selection element in pod", func() {
selectionElement := `
[{
Expand Down

0 comments on commit ec02fb3

Please sign in to comment.