Skip to content

Commit e5e7d62

Browse files
committed
feat: add multi-path routes
Signed-off-by: Sunyanan Choochotkaew <sunyanan.choochotkaew1@ibm.com>
1 parent fe15ab7 commit e5e7d62

File tree

12 files changed

+401
-128
lines changed

12 files changed

+401
-128
lines changed

cni/go.mod

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,37 @@ go 1.22
44

55
require (
66
github.com/Microsoft/hcsshim v0.9.2
7+
github.com/aws/aws-sdk-go v1.43.29
78
github.com/buger/jsonparser v1.1.1
89
github.com/containernetworking/cni v1.2.3
910
github.com/coreos/go-iptables v0.6.0
1011
github.com/gorilla/mux v1.7.3
1112
github.com/onsi/ginkgo v1.16.5
12-
github.com/onsi/gomega v1.19.0
13+
github.com/onsi/gomega v1.33.1
1314
github.com/safchain/ethtool v0.1.0
1415
github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5
15-
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad
16-
github.com/aws/aws-sdk-go v1.43.29
1716
go.uber.org/zap v1.10.0
17+
golang.org/x/sys v0.20.0
1818
gopkg.in/natefinch/lumberjack.v2 v2.0.0
1919
)
20+
21+
require (
22+
github.com/Microsoft/go-winio v0.4.17 // indirect
23+
github.com/containerd/cgroups v1.0.1 // indirect
24+
github.com/fsnotify/fsnotify v1.4.9 // indirect
25+
github.com/gogo/protobuf v1.3.2 // indirect
26+
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
27+
github.com/google/go-cmp v0.6.0 // indirect
28+
github.com/jmespath/go-jmespath v0.4.0 // indirect
29+
github.com/nxadm/tail v1.4.8 // indirect
30+
github.com/pkg/errors v0.9.1 // indirect
31+
github.com/sirupsen/logrus v1.8.1 // indirect
32+
github.com/vishvananda/netns v0.0.4 // indirect
33+
go.opencensus.io v0.22.3 // indirect
34+
go.uber.org/atomic v1.4.0 // indirect
35+
go.uber.org/multierr v1.1.0 // indirect
36+
golang.org/x/net v0.25.0 // indirect
37+
golang.org/x/text v0.15.0 // indirect
38+
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
39+
gopkg.in/yaml.v3 v3.0.1 // indirect
40+
)

cni/plugins/main/multi-nic/aws-ipvlan.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,20 +49,22 @@ type AWSIPVLANNetConf struct {
4949
}
5050

5151
// loadAWSCNIConf unmarshal to AWSCNINetConfig and returns list of AWSCNI configs
52-
func loadAWSCNIConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*current.IPConfig) ([][]byte, error) {
53-
confBytesArray := [][]byte{}
52+
func loadAWSCNIConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*current.IPConfig) (confBytesArray [][]byte, multiPathRoutes map[string][]*netlink.NexthopInfo, loadError error) {
53+
confBytesArray = [][]byte{}
5454

5555
configInAWSIPVLAN := &AWSIPVLANNetConfig{}
5656
if err := json.Unmarshal(bytes, configInAWSIPVLAN); err != nil {
57-
return confBytesArray, fmt.Errorf("unmarshal AWSIPVLANNetConfig: %v", err)
57+
loadError = fmt.Errorf("unmarshal AWSIPVLANNetConfig: %v", err)
58+
return
5859
}
5960

6061
// interfaces are orderly assigned from interface set
6162
for index, masterName := range n.Masters {
6263
// add config
6364
singleConfig, err := copyAWSIPVLANConfig(configInAWSIPVLAN.MainPlugin)
6465
if err != nil {
65-
return confBytesArray, fmt.Errorf("copyAWSIPVLANConfig: %v", err)
66+
loadError = fmt.Errorf("copyAWSIPVLANConfig: %v", err)
67+
return
6668
}
6769
if singleConfig.CNIVersion == "" {
6870
singleConfig.CNIVersion = n.CNIVersion
@@ -71,7 +73,8 @@ func loadAWSCNIConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*curren
7173
singleConfig.Master = masterName
7274
confBytes, err := json.Marshal(singleConfig)
7375
if err != nil {
74-
return confBytesArray, fmt.Errorf("Marshal confBytes: %v", err)
76+
loadError = fmt.Errorf("Marshal confBytes: %v", err)
77+
return
7578
}
7679
// add primary IP value
7780
nodeIP := getHostIP(masterName)
@@ -80,7 +83,7 @@ func loadAWSCNIConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*curren
8083
if n.IsMultiNICIPAM {
8184
// multi-NIC IPAM config
8285
if index < len(ipConfigs) {
83-
confBytes = injectMultiNicIPAM(confBytes, ipConfigs, index)
86+
confBytes, multiPathRoutes = injectMultiNicIPAM(confBytes, bytes, ipConfigs, index)
8487
podIP := ipConfigs[index].Address.IP.String()
8588
// add pod IP value
8689
confBytes = injectPodIP(confBytes, podIP)
@@ -89,12 +92,12 @@ func loadAWSCNIConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*curren
8992
utils.Logger.Debug(fmt.Sprintf("index not match config %d, %v", index, ipConfigs))
9093
}
9194
} else {
92-
confBytes = injectSingleNicIPAM(confBytes, bytes)
95+
confBytes, multiPathRoutes = injectSingleNicIPAM(confBytes, bytes)
9396
confBytesArray = append(confBytesArray, confBytes)
9497
// TO-DO: get IP and inject podIP
9598
}
9699
}
97-
return confBytesArray, nil
100+
return
98101
}
99102

100103
func injectPodIP(confBytes []byte, podIP string) []byte {

cni/plugins/main/multi-nic/host-device.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/containernetworking/cni/pkg/types"
1515
current "github.com/containernetworking/cni/pkg/types/100"
1616
"github.com/containernetworking/plugins/pkg/utils"
17+
"github.com/vishvananda/netlink"
1718
)
1819

1920
const (
@@ -42,12 +43,13 @@ type HostDeviceNetConf struct {
4243
}
4344

4445
// loadHostDeviceConf unmarshal to HostDeviceNetConf and returns list of SR-IOV configs
45-
func loadHostDeviceConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*current.IPConfig) ([][]byte, error) {
46-
confBytesArray := [][]byte{}
46+
func loadHostDeviceConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*current.IPConfig) (confBytesArray [][]byte, multiPathRoutes map[string][]*netlink.NexthopInfo, loadError error) {
47+
confBytesArray = [][]byte{}
4748

4849
configInHostDevice := HostDeviceTypeNetConf{}
4950
if err := json.Unmarshal(bytes, &configInHostDevice); err != nil {
50-
return confBytesArray, err
51+
loadError = err
52+
return
5153
}
5254

5355
// interfaces are orderly assigned from interface set
@@ -59,7 +61,8 @@ func loadHostDeviceConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*cu
5961
// add config
6062
singleConfig, err := copyHostDeviceConfig(configInHostDevice.MainPlugin)
6163
if err != nil {
62-
return confBytesArray, err
64+
loadError = err
65+
return
6366
}
6467
if singleConfig.CNIVersion == "" {
6568
singleConfig.CNIVersion = n.CNIVersion
@@ -70,24 +73,25 @@ func loadHostDeviceConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*cu
7073
}
7174
confBytes, err := json.Marshal(singleConfig)
7275
if err != nil {
73-
return confBytesArray, err
76+
loadError = err
77+
return
7478
}
7579
if n.IPAM.Type == HostDeviceIPAMType {
7680
ipConfig := getHostIPConfig(index, n.Masters[index], deviceID)
7781
if ipConfig == nil {
7882
utils.Logger.Debug(fmt.Sprintf("skip %d: no host IP", index))
7983
confBytes = replaceEmptyIPAM(confBytes)
8084
}
81-
confBytes = replaceMultiNicIPAM(confBytes, ipConfig)
85+
confBytes, multiPathRoutes = replaceMultiNicIPAM(confBytes, bytes, ipConfig)
8286
} else if n.IsMultiNICIPAM {
8387
// multi-NIC IPAM config
84-
confBytes = injectMultiNicIPAM(confBytes, ipConfigs, index)
88+
confBytes, multiPathRoutes = injectMultiNicIPAM(confBytes, bytes, ipConfigs, index)
8589
} else {
86-
confBytes = injectSingleNicIPAM(confBytes, bytes)
90+
confBytes, multiPathRoutes = injectSingleNicIPAM(confBytes, bytes)
8791
}
8892
confBytesArray = append(confBytesArray, confBytes)
8993
}
90-
return confBytesArray, nil
94+
return
9195
}
9296

9397
// copyHostDeviceConfig makes a copy of base host-device config

cni/plugins/main/multi-nic/ipvlan.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/containernetworking/cni/pkg/types"
1313
current "github.com/containernetworking/cni/pkg/types/100"
14+
"github.com/vishvananda/netlink"
1415
)
1516

1617
// IPVLANNetConfig defines ipvlan net config
@@ -30,12 +31,13 @@ type IPVLANTypeNetConf struct {
3031
}
3132

3233
// loadIPVANConf unmarshal to IPVLANNetConfig and returns list of IPVLAN configs
33-
func loadIPVANConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*current.IPConfig) ([][]byte, error) {
34-
confBytesArray := [][]byte{}
34+
func loadIPVANConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*current.IPConfig) (confBytesArray [][]byte, multiPathRoutes map[string][]*netlink.NexthopInfo, loadError error) {
35+
confBytesArray = [][]byte{}
3536

3637
configInIPVLAN := &IPVLANNetConfig{}
3738
if err := json.Unmarshal(bytes, configInIPVLAN); err != nil {
38-
return confBytesArray, err
39+
loadError = err
40+
return
3941
}
4042

4143
// interfaces are orderly assigned from interface set
@@ -46,7 +48,8 @@ func loadIPVANConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*current
4648
// add config
4749
singleConfig, err := copyIPVLANConfig(configInIPVLAN.MainPlugin)
4850
if err != nil {
49-
return confBytesArray, err
51+
loadError = err
52+
return
5053
}
5154
if singleConfig.CNIVersion == "" {
5255
singleConfig.CNIVersion = n.CNIVersion
@@ -55,18 +58,19 @@ func loadIPVANConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*current
5558
singleConfig.Master = masterName
5659
confBytes, err := json.Marshal(singleConfig)
5760
if err != nil {
58-
return confBytesArray, err
61+
loadError = err
62+
return
5963
}
6064

6165
if n.IsMultiNICIPAM {
6266
// multi-NIC IPAM config
63-
confBytes = injectMultiNicIPAM(confBytes, ipConfigs, index)
67+
confBytes, multiPathRoutes = injectMultiNicIPAM(confBytes, bytes, ipConfigs, index)
6468
} else {
65-
confBytes = injectSingleNicIPAM(confBytes, bytes)
69+
confBytes, multiPathRoutes = injectSingleNicIPAM(confBytes, bytes)
6670
}
6771
confBytesArray = append(confBytesArray, confBytes)
6872
}
69-
return confBytesArray, nil
73+
return
7074
}
7175

7276
// copyIPVLANConfig makes a copy of base IPVLAN config

cni/plugins/main/multi-nic/macvlan.go

Lines changed: 59 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,78 +6,82 @@
66
package main
77

88
import (
9-
"encoding/json"
10-
"fmt"
9+
"encoding/json"
10+
"fmt"
1111

12-
"github.com/containernetworking/cni/pkg/types"
13-
current "github.com/containernetworking/cni/pkg/types/100"
12+
"github.com/containernetworking/cni/pkg/types"
13+
current "github.com/containernetworking/cni/pkg/types/100"
14+
"github.com/vishvananda/netlink"
1415
)
1516

1617
// MACVLANNetConfig defines macvlan net config
1718
type MACVLANNetConfig struct {
18-
types.NetConf
19-
MainPlugin MACVLANTypeNetConf `json:"plugin"`
19+
types.NetConf
20+
MainPlugin MACVLANTypeNetConf `json:"plugin"`
2021
}
2122

2223
type MACVLANTypeNetConf struct {
23-
types.NetConf
24-
Master string `json:"master"`
25-
Mode string `json:"mode"`
26-
MTU int `json:"mtu"`
24+
types.NetConf
25+
Master string `json:"master"`
26+
Mode string `json:"mode"`
27+
MTU int `json:"mtu"`
2728
}
2829

2930
// loadMACVLANConf unmarshals to MACVLANNetConfig and returns a list of MACVLAN configs
30-
func loadMACVLANConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*current.IPConfig) ([][]byte, error) {
31-
confBytesArray := [][]byte{}
31+
func loadMACVLANConf(bytes []byte, ifName string, n *NetConf, ipConfigs []*current.IPConfig) (confBytesArray [][]byte, multiPathRoutes map[string][]*netlink.NexthopInfo, loadError error) {
32+
confBytesArray = [][]byte{}
3233

33-
configInMACVLAN := &MACVLANNetConfig{}
34-
if err := json.Unmarshal(bytes, configInMACVLAN); err != nil {
35-
return confBytesArray, err
36-
}
34+
configInMACVLAN := &MACVLANNetConfig{}
35+
if err := json.Unmarshal(bytes, configInMACVLAN); err != nil {
36+
loadError = err
37+
return
38+
}
3739

38-
// Interfaces are orderly assigned from the interface set
39-
for index, masterName := range n.Masters {
40-
if masterName == "" {
41-
continue
42-
}
40+
// Interfaces are orderly assigned from the interface set
41+
for index, masterName := range n.Masters {
42+
if masterName == "" {
43+
continue
44+
}
4345

44-
// Add config
45-
singleConfig, err := copyMACVLANConfig(configInMACVLAN.MainPlugin)
46-
if err != nil {
47-
return confBytesArray, err
48-
}
49-
if singleConfig.CNIVersion == "" {
50-
singleConfig.CNIVersion = n.CNIVersion
51-
}
52-
singleConfig.Name = fmt.Sprintf("%s-%d", ifName, index)
53-
singleConfig.Master = masterName
54-
confBytes, err := json.Marshal(singleConfig)
55-
if err != nil {
56-
return confBytesArray, err
57-
}
46+
// Add config
47+
singleConfig, err := copyMACVLANConfig(configInMACVLAN.MainPlugin)
48+
if err != nil {
49+
loadError = err
50+
return
51+
}
52+
if singleConfig.CNIVersion == "" {
53+
singleConfig.CNIVersion = n.CNIVersion
54+
}
55+
singleConfig.Name = fmt.Sprintf("%s-%d", ifName, index)
56+
singleConfig.Master = masterName
57+
confBytes, err := json.Marshal(singleConfig)
58+
if err != nil {
59+
loadError = err
60+
return
61+
}
5862

59-
if n.IsMultiNICIPAM {
60-
// Multi-NIC IPAM config
61-
confBytes = injectMultiNicIPAM(confBytes, ipConfigs, index)
62-
} else {
63-
// Single-NIC IPAM config
64-
confBytes = injectSingleNicIPAM(confBytes, bytes)
65-
}
66-
confBytesArray = append(confBytesArray, confBytes)
67-
}
68-
return confBytesArray, nil
63+
if n.IsMultiNICIPAM {
64+
// Multi-NIC IPAM config
65+
confBytes, multiPathRoutes = injectMultiNicIPAM(confBytes, bytes, ipConfigs, index)
66+
} else {
67+
// Single-NIC IPAM config
68+
confBytes, multiPathRoutes = injectSingleNicIPAM(confBytes, bytes)
69+
}
70+
confBytesArray = append(confBytesArray, confBytes)
71+
}
72+
return
6973
}
7074

7175
// copyMACVLANConfig makes a copy of the base MACVLAN config
7276
func copyMACVLANConfig(original MACVLANTypeNetConf) (*MACVLANTypeNetConf, error) {
73-
copiedObject := &MACVLANTypeNetConf{}
74-
byteObject, err := json.Marshal(original)
75-
if err != nil {
76-
return copiedObject, err
77-
}
78-
err = json.Unmarshal(byteObject, copiedObject)
79-
if err != nil {
80-
return copiedObject, err
81-
}
82-
return copiedObject, nil
77+
copiedObject := &MACVLANTypeNetConf{}
78+
byteObject, err := json.Marshal(original)
79+
if err != nil {
80+
return copiedObject, err
81+
}
82+
err = json.Unmarshal(byteObject, copiedObject)
83+
if err != nil {
84+
return copiedObject, err
85+
}
86+
return copiedObject, nil
8387
}

0 commit comments

Comments
 (0)