Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adding MACAddress to CNS endpoint State and refactoring stateless CNI code #2722

Merged
merged 4 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion cni/windows.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ COPY . .
RUN GOOS=$OS CGO_ENABLED=0 go build -a -o /go/bin/azure-vnet -trimpath -ldflags "-X main.version="$VERSION"" -gcflags="-dwarflocationlists=true" cni/network/plugin/main.go
RUN GOOS=$OS CGO_ENABLED=0 go build -a -o /go/bin/azure-vnet-telemetry -trimpath -ldflags "-X main.version="$VERSION"" -gcflags="-dwarflocationlists=true" cni/telemetry/service/telemetrymain.go
RUN GOOS=$OS CGO_ENABLED=0 go build -a -o /go/bin/azure-vnet-ipam -trimpath -ldflags "-X main.version="$VERSION"" -gcflags="-dwarflocationlists=true" cni/ipam/plugin/main.go
RUN GOOS=$OS CGO_ENABLED=0 go build -a -o /go/bin/azurecni-stateless -trimpath -ldflags "-X main.version="$VERSION"" -gcflags="-dwarflocationlists=true" cni/network/stateless/main.go
RUN GOOS=$OS CGO_ENABLED=0 go build -a -o /go/bin/azure-vnet-stateless -trimpath -ldflags "-X main.version="$VERSION"" -gcflags="-dwarflocationlists=true" cni/network/stateless/main.go

FROM --platform=linux/${ARCH} mcr.microsoft.com/cbl-mariner/base/core:2.0 AS compressor
ARG OS
Expand Down
2 changes: 1 addition & 1 deletion cns/cnireconciler/podinfoprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ func cniStateToCnsEndpointState(state *api.AzureCNIState) map[string]*restserver

// extractEndpointInfo extract Interface Name and endpointID for each endpoint based the CNI state
func extractEndpointInfo(epID, containerID string) (endpointID, interfaceName string) {
ifName := restserver.InterfaceName
ifName := restserver.InfraInterfaceName
if strings.Contains(epID, "-eth") {
ifName = epID[len(epID)-4:]
}
Expand Down
50 changes: 34 additions & 16 deletions cns/restserver/ipam.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ var (
)

const (
ContainerIDLength = 8
InterfaceName = "eth0"
ContainerIDLength = 8
InfraInterfaceName = "eth0"
)

// requestIPConfigHandlerHelper validates the request, assign IPs and return the IPConfigs
Expand Down Expand Up @@ -1071,7 +1071,7 @@ func (service *HTTPRestService) GetEndpointHelper(endpointID string) (*EndpointI
// This part is a temprory fix if we have endpoint states belong to CNI version 1.4.X on Windows since the states don't have the containerID
// In case there was no endpoint founded with ContainerID as the key,
// then [First 8 character of containerid]-eth0 will be tried
legacyEndpointID := endpointID[:ContainerIDLength] + "-" + InterfaceName
legacyEndpointID := endpointID[:ContainerIDLength] + "-" + InfraInterfaceName
if endpointInfo, ok := service.EndpointState[legacyEndpointID]; ok {
logger.Warnf("[GetEndpointState] Found existing endpoint state for container %s", legacyEndpointID)
return endpointInfo, nil
Expand Down Expand Up @@ -1136,25 +1136,43 @@ func (service *HTTPRestService) UpdateEndpointHelper(endpointID string, req map[
}
logger.Printf("[updateEndpoint] Updating endpoint state for infra container %s", endpointID)
if endpointInfo, ok := service.EndpointState[endpointID]; ok {
for ifName, InterfaceInfo := range req {
logger.Printf("[updateEndpoint] Found existing endpoint state for infra container %s", endpointID)
if InterfaceInfo.HnsEndpointID != "" {
service.EndpointState[endpointID].IfnameToIPMap[ifName].HnsEndpointID = InterfaceInfo.HnsEndpointID
logger.Printf("[updateEndpoint] update the endpoint %s with HNSID %s", endpointID, InterfaceInfo.HnsEndpointID)
for ifName, interfaceInfo := range req {
// This codition will create a map for SecodaryNIC and also also creates MAP entry for InfraNic in case that the initial goalState is using empty InterfaceName
if _, keyExist := service.EndpointState[endpointID].IfnameToIPMap[ifName]; !keyExist {
service.EndpointState[endpointID].IfnameToIPMap[ifName] = &IPInfo{}
if val, emptyKeyExist := service.EndpointState[endpointID].IfnameToIPMap[""]; emptyKeyExist && ifName == InfraInterfaceName {
service.EndpointState[endpointID].IfnameToIPMap[ifName].IPv4 = val.IPv4
service.EndpointState[endpointID].IfnameToIPMap[ifName].IPv6 = val.IPv6
delete(service.EndpointState[endpointID].IfnameToIPMap, "")
}
}
logger.Printf("[updateEndpoint] Found existing endpoint state for infra container %s with %s , [%+v]", endpointID, ifName, interfaceInfo)
if interfaceInfo.HnsEndpointID != "" {
service.EndpointState[endpointID].IfnameToIPMap[ifName].HnsEndpointID = interfaceInfo.HnsEndpointID
logger.Printf("[updateEndpoint] update the endpoint %s with HNSID %s", endpointID, interfaceInfo.HnsEndpointID)
}
if interfaceInfo.HnsNetworkID != "" {
service.EndpointState[endpointID].IfnameToIPMap[ifName].HnsNetworkID = interfaceInfo.HnsNetworkID
logger.Printf("[updateEndpoint] update the endpoint %s with HnsNetworkID %s", endpointID, interfaceInfo.HnsEndpointID)
}
if interfaceInfo.HostVethName != "" {
service.EndpointState[endpointID].IfnameToIPMap[ifName].HostVethName = interfaceInfo.HostVethName
logger.Printf("[updateEndpoint] update the endpoint %s with vethName %s", endpointID, interfaceInfo.HostVethName)
}
if InterfaceInfo.HostVethName != "" {
service.EndpointState[endpointID].IfnameToIPMap[ifName].HostVethName = InterfaceInfo.HostVethName
logger.Printf("[updateEndpoint] update the endpoint %s with vethName %s", endpointID, InterfaceInfo.HostVethName)
if interfaceInfo.NICType != "" {
service.EndpointState[endpointID].IfnameToIPMap[ifName].NICType = interfaceInfo.NICType
logger.Printf("[updateEndpoint] update the endpoint %s with NICType %s", endpointID, interfaceInfo.NICType)
}
if InterfaceInfo.NICType != "" {
service.EndpointState[endpointID].IfnameToIPMap[ifName].NICType = InterfaceInfo.NICType
logger.Printf("[updateEndpoint] update the endpoint %s with NICType %s", endpointID, InterfaceInfo.NICType)
if interfaceInfo.MacAddress != "" {
service.EndpointState[endpointID].IfnameToIPMap[ifName].MacAddress = interfaceInfo.MacAddress
logger.Printf("[updateEndpoint] update the endpoint %s with MacAddress %s", endpointID, interfaceInfo.MacAddress)
}
}
err := service.EndpointStateStore.Write(EndpointStoreKey, service.EndpointState)
if err != nil {
return fmt.Errorf("[updateEndpoint] failed to write endpoint state to store for pod %s : %w", endpointInfo.PodName, err)
}
logger.Printf("[updateEndpoint] successfully write the state to the file %s", endpointID)
return nil
}
return errors.New("[updateEndpoint] endpoint could not be found in the statefile")
Expand All @@ -1163,8 +1181,8 @@ func (service *HTTPRestService) UpdateEndpointHelper(endpointID string, req map[
// verifyUpdateEndpointStateRequest verify the CNI request body for the UpdateENdpointState API
func verifyUpdateEndpointStateRequest(req map[string]*IPInfo) error {
for ifName, InterfaceInfo := range req {
if InterfaceInfo.HostVethName == "" && InterfaceInfo.HnsEndpointID == "" && InterfaceInfo.NICType == "" {
return errors.New("[updateEndpoint] No NicType, HnsEndpointID or HostVethName has been provided")
if InterfaceInfo.HostVethName == "" && InterfaceInfo.HnsEndpointID == "" && InterfaceInfo.NICType == "" && InterfaceInfo.MacAddress == "" {
return errors.New("[updateEndpoint] No NicType, MacAddress, HnsEndpointID or HostVethName has been provided")
}
if ifName == "" {
return errors.New("[updateEndpoint] No Interface has been provided")
Expand Down
2 changes: 2 additions & 0 deletions cns/restserver/restserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ type IPInfo struct {
IPv4 []net.IPNet
IPv6 []net.IPNet `json:",omitempty"`
HnsEndpointID string `json:",omitempty"`
HnsNetworkID string `json:",omitempty"`
HostVethName string `json:",omitempty"`
MacAddress string `json:",omitempty"`
NICType cns.NICType
}

Expand Down
2 changes: 2 additions & 0 deletions network/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type AzureHNSEndpoint struct{}
type endpoint struct {
Id string
HnsId string `json:",omitempty"`
HNSNetworkID string `json:",omitempty"`
SandboxKey string
IfName string
HostIfName string
Expand Down Expand Up @@ -92,6 +93,7 @@ type EndpointInfo struct {
NICType cns.NICType
SkipDefaultRoutes bool
HNSEndpointID string
HNSNetworkID string
HostIfName string
}

Expand Down
20 changes: 11 additions & 9 deletions network/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ func (nm *networkManager) CreateEndpoint(cli apipaClient, networkID string, epIn
func (nm *networkManager) UpdateEndpointState(ep *endpoint) error {
ifnameToIPInfoMap := generateCNSIPInfoMap(ep) // key : interface name, value : IPInfo
logger.Info("Calling cns updateEndpoint API with ", zap.String("containerID: ", ep.ContainerID), zap.String("HnsId: ", ep.HnsId), zap.String("HostIfName: ", ep.HostIfName))
logger.Info("ifnameToIPInfoMap:", zap.Any("ifnameToIPInfoMap", ifnameToIPInfoMap))
response, err := nm.CnsClient.UpdateEndpoint(context.TODO(), ep.ContainerID, ifnameToIPInfoMap)
if err != nil {
return errors.Wrapf(err, "Update endpoint API returend with error")
Expand Down Expand Up @@ -689,6 +690,7 @@ func (nm *networkManager) GetEndpointID(containerID, ifName string) string {
return containerID + "-" + ifName
}

// cnsEndpointInfotoCNIEpInfo convert a CNS endpoint state to CNI EndpointInfo
func cnsEndpointInfotoCNIEpInfo(endpointInfo restserver.EndpointInfo, endpointID string) *EndpointInfo {
epInfo := &EndpointInfo{
Id: endpointID,
Expand All @@ -710,21 +712,21 @@ func cnsEndpointInfotoCNIEpInfo(endpointInfo restserver.EndpointInfo, endpointID
epInfo.IfName = ifName
epInfo.HostIfName = ipInfo.HostVethName
epInfo.HNSEndpointID = ipInfo.HnsEndpointID
epInfo.HNSNetworkID = ipInfo.HnsNetworkID
epInfo.MacAddress = net.HardwareAddr(ipInfo.MacAddress)
}
return epInfo
}

// generateCNSIPInfoMap generates a CNS ifNametoIPInfoMap structure based on CNI endpoint
func generateCNSIPInfoMap(ep *endpoint) map[string]*restserver.IPInfo {
ifNametoIPInfoMap := make(map[string]*restserver.IPInfo) // key : interface name, value : IPInfo
if ep.IfName != "" {
ifNametoIPInfoMap[ep.IfName].NICType = cns.InfraNIC
ifNametoIPInfoMap[ep.IfName].HnsEndpointID = ep.HnsId
ifNametoIPInfoMap[ep.IfName].HostVethName = ep.HostIfName
}
if ep.SecondaryInterfaces != nil {
for ifName, InterfaceInfo := range ep.SecondaryInterfaces {
ifNametoIPInfoMap[ifName].NICType = InterfaceInfo.NICType
}
ifNametoIPInfoMap[ep.IfName] = &restserver.IPInfo{
NICType: cns.InfraNIC,
HnsEndpointID: ep.HnsId,
HnsNetworkID: ep.HNSNetworkID,
HostVethName: ep.HostIfName,
MacAddress: ep.MacAddress.String(),
}
return ifNametoIPInfoMap
}
Loading