Skip to content

Commit 008dadc

Browse files
authored
feat: Modifying stateless CNI state to account for swift 2.0 changes. (#2523)
* Modyfying stateless CNI state to account for swift 2.0 changes * Removing SecondaryNICInfor fro EPInfo. * removing SecondaryNic from the epInfo. * Make change to UpdateEndpointState API to support SwiftV2 for Stateless CNI * updating Makefile to include azure CNI binary.
1 parent 3783c0c commit 008dadc

File tree

7 files changed

+125
-54
lines changed

7 files changed

+125
-54
lines changed

Makefile

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ AZURE_IPAM_DIR = $(REPO_ROOT)/azure-ipam
4747
CNM_DIR = $(REPO_ROOT)/cnm/plugin
4848
CNI_NET_DIR = $(REPO_ROOT)/cni/network/plugin
4949
CNI_IPAM_DIR = $(REPO_ROOT)/cni/ipam/plugin
50+
STATELESS_CNI_NET_DIR = $(REPO_ROOT)/cni/network/stateless
5051
CNI_IPAMV6_DIR = $(REPO_ROOT)/cni/ipam/pluginv6
5152
CNI_TELEMETRY_DIR = $(REPO_ROOT)/cni/telemetry/service
5253
ACNCLI_DIR = $(REPO_ROOT)/tools/acncli
@@ -59,10 +60,13 @@ IMAGE_DIR = $(OUTPUT_DIR)/images
5960
CNM_BUILD_DIR = $(BUILD_DIR)/cnm
6061
CNI_BUILD_DIR = $(BUILD_DIR)/cni
6162
ACNCLI_BUILD_DIR = $(BUILD_DIR)/acncli
63+
STATELESS_CNI_BUILD_DIR = $(CNI_BUILD_DIR)/stateless
6264
CNI_MULTITENANCY_BUILD_DIR = $(BUILD_DIR)/cni-multitenancy
6365
CNI_MULTITENANCY_TRANSPARENT_VLAN_BUILD_DIR = $(BUILD_DIR)/cni-multitenancy-transparent-vlan
6466
CNI_SWIFT_BUILD_DIR = $(BUILD_DIR)/cni-swift
6567
CNI_OVERLAY_BUILD_DIR = $(BUILD_DIR)/cni-overlay
68+
STATELESS_CNI_OVERLAY_BUILD_DIR = $(CNI_OVERLAY_BUILD_DIR)/stateless
69+
STATELESS_CNI_SWIFT_BUILD_DIR = $(CNI_SWIFT_BUILD_DIR)/stateless
6670
CNI_BAREMETAL_BUILD_DIR = $(BUILD_DIR)/cni-baremetal
6771
CNI_DUALSTACK_BUILD_DIR = $(BUILD_DIR)/cni-dualstack
6872
CNS_BUILD_DIR = $(BUILD_DIR)/cns
@@ -130,7 +134,7 @@ endif
130134

131135
# Shorthand target names for convenience.
132136
azure-cnm-plugin: cnm-binary cnm-archive
133-
azure-cni-plugin: azure-vnet-binary azure-vnet-ipam-binary azure-vnet-ipamv6-binary azure-vnet-telemetry-binary cni-archive
137+
azure-cni-plugin: azure-vnet-binary azure-vnet-stateless-binary azure-vnet-ipam-binary azure-vnet-ipamv6-binary azure-vnet-telemetry-binary cni-archive
134138
azure-cns: azure-cns-binary cns-archive
135139
acncli: acncli-binary acncli-archive
136140
azure-npm: azure-npm-binary npm-archive
@@ -179,6 +183,10 @@ cnm-binary:
179183
azure-vnet-binary:
180184
cd $(CNI_NET_DIR) && CGO_ENABLED=0 go build -v -o $(CNI_BUILD_DIR)/azure-vnet$(EXE_EXT) -ldflags "-X main.version=$(CNI_VERSION)" -gcflags="-dwarflocationlists=true"
181185

186+
# Build the Azure CNI stateless network binary
187+
azure-vnet-stateless-binary:
188+
cd $(STATELESS_CNI_NET_DIR) && CGO_ENABLED=0 go build -v -o $(STATELESS_CNI_BUILD_DIR)/azure-vnet$(EXE_EXT) -ldflags "-X main.version=$(CNI_VERSION)" -gcflags="-dwarflocationlists=true"
189+
182190
# Build the Azure CNI IPAM binary.
183191
azure-vnet-ipam-binary:
184192
cd $(CNI_IPAM_DIR) && CGO_ENABLED=0 go build -v -o $(CNI_BUILD_DIR)/azure-vnet-ipam$(EXE_EXT) -ldflags "-X main.version=$(CNI_VERSION)" -gcflags="-dwarflocationlists=true"
@@ -674,12 +682,16 @@ endif
674682
cp cni/azure-$(GOOS)-swift.conflist $(CNI_SWIFT_BUILD_DIR)/10-azure.conflist
675683
cp telemetry/azure-vnet-telemetry.config $(CNI_SWIFT_BUILD_DIR)/azure-vnet-telemetry.config
676684
cp $(CNI_BUILD_DIR)/azure-vnet$(EXE_EXT) $(CNI_BUILD_DIR)/azure-vnet-ipam$(EXE_EXT) $(CNI_BUILD_DIR)/azure-vnet-telemetry$(EXE_EXT) $(CNI_SWIFT_BUILD_DIR)
685+
$(MKDIR) $(STATELESS_CNI_SWIFT_BUILD_DIR)
686+
cp $(STATELESS_CNI_BUILD_DIR)/azure-vnet$(EXE_EXT) $(STATELESS_CNI_SWIFT_BUILD_DIR)
677687
cd $(CNI_SWIFT_BUILD_DIR) && $(ARCHIVE_CMD) $(CNI_SWIFT_ARCHIVE_NAME) azure-vnet$(EXE_EXT) azure-vnet-ipam$(EXE_EXT) azure-vnet-telemetry$(EXE_EXT) 10-azure.conflist azure-vnet-telemetry.config
678688

679689
$(MKDIR) $(CNI_OVERLAY_BUILD_DIR)
680690
cp cni/azure-$(GOOS)-swift-overlay.conflist $(CNI_OVERLAY_BUILD_DIR)/10-azure.conflist
681691
cp telemetry/azure-vnet-telemetry.config $(CNI_OVERLAY_BUILD_DIR)/azure-vnet-telemetry.config
682692
cp $(CNI_BUILD_DIR)/azure-vnet$(EXE_EXT) $(CNI_BUILD_DIR)/azure-vnet-ipam$(EXE_EXT) $(CNI_BUILD_DIR)/azure-vnet-telemetry$(EXE_EXT) $(CNI_OVERLAY_BUILD_DIR)
693+
$(MKDIR) $(STATELESS_CNI_OVERLAY_BUILD_DIR)
694+
cp $(STATELESS_CNI_BUILD_DIR)/azure-vnet$(EXE_EXT) $(STATELESS_CNI_OVERLAY_BUILD_DIR)
683695
cd $(CNI_OVERLAY_BUILD_DIR) && $(ARCHIVE_CMD) $(CNI_OVERLAY_ARCHIVE_NAME) azure-vnet$(EXE_EXT) azure-vnet-ipam$(EXE_EXT) azure-vnet-telemetry$(EXE_EXT) 10-azure.conflist azure-vnet-telemetry.config
684696

685697
$(MKDIR) $(CNI_DUALSTACK_BUILD_DIR)

cns/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,4 +363,5 @@ type GetHomeAzResponse struct {
363363
type EndpointRequest struct {
364364
HnsEndpointID string `json:"hnsEndpointID"`
365365
HostVethName string `json:"hostVethName"`
366+
InterfaceName string `json:"InterfaceName"`
366367
}

cns/client/client.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,15 +1059,11 @@ func (c *Client) GetEndpoint(ctx context.Context, endpointID string) (*restserve
10591059

10601060
// UpdateEndpoint calls the EndpointHandlerAPI in CNS
10611061
// to update the state of a given EndpointID with either HNSEndpointID or HostVethName
1062-
func (c *Client) UpdateEndpoint(ctx context.Context, endpointID, hnsID, vethName string) (*cns.Response, error) {
1062+
func (c *Client) UpdateEndpoint(ctx context.Context, endpointID string, ipInfo map[string]*restserver.IPInfo) (*cns.Response, error) {
10631063
// build the request
1064-
updateEndpoint := cns.EndpointRequest{
1065-
HnsEndpointID: hnsID,
1066-
HostVethName: vethName,
1067-
}
10681064
var body bytes.Buffer
10691065

1070-
if err := json.NewEncoder(&body).Encode(updateEndpoint); err != nil {
1066+
if err := json.NewEncoder(&body).Encode(ipInfo); err != nil {
10711067
return nil, errors.Wrap(err, "failed to encode updateEndpoint")
10721068
}
10731069

cns/client/client_test.go

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2710,15 +2710,17 @@ func TestUpdateEndpoint(t *testing.T) {
27102710
containerID string
27112711
hnsID string
27122712
vethName string
2713+
ifName string
27132714
response *RequestCapture
2714-
expReq *cns.EndpointRequest
2715+
expReq map[string]*restserver.IPInfo
27152716
shouldErr bool
27162717
}{
27172718
{
27182719
"empty",
27192720
"",
27202721
"",
27212722
"",
2723+
"",
27222724
&RequestCapture{
27232725
Next: &mockdo{},
27242726
},
@@ -2730,13 +2732,17 @@ func TestUpdateEndpoint(t *testing.T) {
27302732
"foo",
27312733
"bar",
27322734
"",
2735+
"eth0",
27332736
&RequestCapture{
27342737
Next: &mockdo{
27352738
httpStatusCodeToReturn: http.StatusOK,
27362739
},
27372740
},
2738-
&cns.EndpointRequest{
2739-
HnsEndpointID: "bar",
2741+
map[string]*restserver.IPInfo{
2742+
"eth0": {
2743+
HnsEndpointID: "bar",
2744+
NICType: cns.InfraNIC,
2745+
},
27402746
},
27412747
false,
27422748
},
@@ -2745,13 +2751,17 @@ func TestUpdateEndpoint(t *testing.T) {
27452751
"foo",
27462752
"",
27472753
"bar",
2754+
"eth0",
27482755
&RequestCapture{
27492756
Next: &mockdo{
27502757
httpStatusCodeToReturn: http.StatusOK,
27512758
},
27522759
},
2753-
&cns.EndpointRequest{
2754-
HostVethName: "bar",
2760+
map[string]*restserver.IPInfo{
2761+
"eth0": {
2762+
HostVethName: "bar",
2763+
NICType: cns.InfraNIC,
2764+
},
27552765
},
27562766
false,
27572767
},
@@ -2760,13 +2770,17 @@ func TestUpdateEndpoint(t *testing.T) {
27602770
"foo",
27612771
"",
27622772
"bar",
2773+
"eth0",
27632774
&RequestCapture{
27642775
Next: &mockdo{
27652776
httpStatusCodeToReturn: http.StatusBadRequest,
27662777
},
27672778
},
2768-
&cns.EndpointRequest{
2769-
HostVethName: "bar",
2779+
map[string]*restserver.IPInfo{
2780+
"eth0": {
2781+
HostVethName: "bar",
2782+
NICType: cns.InfraNIC,
2783+
},
27702784
},
27712785
true,
27722786
},
@@ -2784,7 +2798,7 @@ func TestUpdateEndpoint(t *testing.T) {
27842798
}
27852799

27862800
// execute the method under test
2787-
res, err := client.UpdateEndpoint(context.TODO(), test.containerID, test.hnsID, test.vethName)
2801+
res, err := client.UpdateEndpoint(context.TODO(), test.containerID, test.expReq)
27882802
if err != nil && !test.shouldErr {
27892803
t.Fatal("unexpected error: err: ", err, res.Message)
27902804
}
@@ -2801,7 +2815,7 @@ func TestUpdateEndpoint(t *testing.T) {
28012815
// if a request was expected to be sent, decode it and ensure that it
28022816
// matches expectations
28032817
if test.expReq != nil {
2804-
var gotReq cns.EndpointRequest
2818+
var gotReq map[string]*restserver.IPInfo
28052819
err = json.NewDecoder(test.response.Request.Body).Decode(&gotReq)
28062820
if err != nil {
28072821
t.Fatal("error decoding the received request: err:", err)
@@ -2810,7 +2824,7 @@ func TestUpdateEndpoint(t *testing.T) {
28102824
// a nil expReq is semantically meaningful (i.e. "no request"), but in
28112825
// order for cmp to work properly, the outer types should be identical.
28122826
// Thus we have to dereference it explicitly:
2813-
expReq := *test.expReq
2827+
expReq := test.expReq
28142828

28152829
// ensure that the received request is what was expected
28162830
if !cmp.Equal(gotReq, expReq) {

cns/restserver/ipam.go

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,7 +1083,7 @@ func (service *HTTPRestService) GetEndpointHelper(endpointID string) (*EndpointI
10831083
func (service *HTTPRestService) UpdateEndpointHandler(w http.ResponseWriter, r *http.Request) {
10841084
logger.Printf("[updateEndpoint] updateEndpoint for %s", r.URL.Path)
10851085

1086-
var req cns.EndpointRequest
1086+
var req map[string]*IPInfo
10871087
err := service.Listener.Decode(w, r, &req)
10881088
endpointID := strings.TrimPrefix(r.URL.Path, cns.EndpointPath)
10891089
logger.Request(service.Name, &req, err)
@@ -1098,11 +1098,10 @@ func (service *HTTPRestService) UpdateEndpointHandler(w http.ResponseWriter, r *
10981098
logger.Response(service.Name, response, response.ReturnCode, err)
10991099
return
11001100
}
1101-
if req.HostVethName == "" && req.HnsEndpointID == "" {
1102-
logger.Warnf("[updateEndpoint] No HnsEndpointID or HostVethName has been provided")
1101+
if err = verifyUpdateEndpointStateRequest(req); err != nil {
11031102
response := cns.Response{
11041103
ReturnCode: types.InvalidRequest,
1105-
Message: "[updateEndpoint] No HnsEndpointID or HostVethName has been provided",
1104+
Message: err.Error(),
11061105
}
11071106
w.Header().Set(cnsReturnCode, response.ReturnCode.String())
11081107
err = service.Listener.Encode(w, &response)
@@ -1131,22 +1130,27 @@ func (service *HTTPRestService) UpdateEndpointHandler(w http.ResponseWriter, r *
11311130
}
11321131

11331132
// UpdateEndpointHelper updates the state of the given endpointId with HNSId or VethName
1134-
func (service *HTTPRestService) UpdateEndpointHelper(endpointID string, req cns.EndpointRequest) error {
1133+
func (service *HTTPRestService) UpdateEndpointHelper(endpointID string, req map[string]*IPInfo) error {
11351134
if service.EndpointStateStore == nil {
11361135
return ErrStoreEmpty
11371136
}
11381137
logger.Printf("[updateEndpoint] Updating endpoint state for infra container %s", endpointID)
11391138
if endpointInfo, ok := service.EndpointState[endpointID]; ok {
1140-
logger.Printf("[updateEndpoint] Found existing endpoint state for infra container %s", endpointID)
1141-
if req.HnsEndpointID != "" {
1142-
service.EndpointState[endpointID].HnsEndpointID = req.HnsEndpointID
1143-
logger.Printf("[updateEndpoint] update the endpoint %s with HNSID %s", endpointID, req.HnsEndpointID)
1144-
}
1145-
if req.HostVethName != "" {
1146-
service.EndpointState[endpointID].HostVethName = req.HostVethName
1147-
logger.Printf("[updateEndpoint] update the endpoint %s with vethName %s", endpointID, req.HostVethName)
1139+
for ifName, InterfaceInfo := range req {
1140+
logger.Printf("[updateEndpoint] Found existing endpoint state for infra container %s", endpointID)
1141+
if InterfaceInfo.HnsEndpointID != "" {
1142+
service.EndpointState[endpointID].IfnameToIPMap[ifName].HnsEndpointID = InterfaceInfo.HnsEndpointID
1143+
logger.Printf("[updateEndpoint] update the endpoint %s with HNSID %s", endpointID, InterfaceInfo.HnsEndpointID)
1144+
}
1145+
if InterfaceInfo.HostVethName != "" {
1146+
service.EndpointState[endpointID].IfnameToIPMap[ifName].HostVethName = InterfaceInfo.HostVethName
1147+
logger.Printf("[updateEndpoint] update the endpoint %s with vethName %s", endpointID, InterfaceInfo.HostVethName)
1148+
}
1149+
if InterfaceInfo.NICType != "" {
1150+
service.EndpointState[endpointID].IfnameToIPMap[ifName].NICType = InterfaceInfo.NICType
1151+
logger.Printf("[updateEndpoint] update the endpoint %s with NICType %s", endpointID, InterfaceInfo.NICType)
1152+
}
11481153
}
1149-
11501154
err := service.EndpointStateStore.Write(EndpointStoreKey, service.EndpointState)
11511155
if err != nil {
11521156
return fmt.Errorf("[updateEndpoint] failed to write endpoint state to store for pod %s : %w", endpointInfo.PodName, err)
@@ -1155,3 +1159,16 @@ func (service *HTTPRestService) UpdateEndpointHelper(endpointID string, req cns.
11551159
}
11561160
return errors.New("[updateEndpoint] endpoint could not be found in the statefile")
11571161
}
1162+
1163+
// verifyUpdateEndpointStateRequest verify the CNI request body for the UpdateENdpointState API
1164+
func verifyUpdateEndpointStateRequest(req map[string]*IPInfo) error {
1165+
for ifName, InterfaceInfo := range req {
1166+
if InterfaceInfo.HostVethName == "" && InterfaceInfo.HnsEndpointID == "" && InterfaceInfo.NICType == "" {
1167+
return errors.New("[updateEndpoint] No NicType, HnsEndpointID or HostVethName has been provided")
1168+
}
1169+
if ifName == "" {
1170+
return errors.New("[updateEndpoint] No Interface has been provided")
1171+
}
1172+
}
1173+
return nil
1174+
}

cns/restserver/restserver.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,14 @@ type EndpointInfo struct {
9393
PodName string
9494
PodNamespace string
9595
IfnameToIPMap map[string]*IPInfo // key : interface name, value : IPInfo
96-
HnsEndpointID string
97-
HostVethName string
9896
}
9997

10098
type IPInfo struct {
101-
IPv4 []net.IPNet
102-
IPv6 []net.IPNet
99+
IPv4 []net.IPNet
100+
IPv6 []net.IPNet `json:",omitempty"`
101+
HnsEndpointID string `json:",omitempty"`
102+
HostVethName string `json:",omitempty"`
103+
NICType cns.NICType
103104
}
104105

105106
type GetHTTPServiceDataResponse struct {

0 commit comments

Comments
 (0)