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

Improve error handling with vlanpool #1168

Merged
merged 1 commit into from
Sep 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 17 additions & 7 deletions pkg/controller/fabricvlanpools.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,12 @@ func fabricVlanPoolInit(cont *AciController, stopCh <-chan struct{}) {
cache.WaitForCacheSync(stopCh, cont.fabricVlanPoolInformer.HasSynced)
}

func (cont *AciController) handleFabricVlanPoolUpdate(obj interface{}) bool {
func (cont *AciController) updateFabricVlanPool(obj interface{}) map[string]apicapi.ApicSlice {
progMap := make(map[string]apicapi.ApicSlice)
fabricVlanPoolObj, ok := obj.(*fabattv1.FabricVlanPool)
if !ok {
cont.log.Error("handleFabricVlanPoolUpdate: Bad object type")
return false
return progMap
}
cont.log.Infof("fabricvlanpool update: %s/%s", fabricVlanPoolObj.Namespace, fabricVlanPoolObj.Name)

Expand All @@ -152,8 +153,12 @@ func (cont *AciController) handleFabricVlanPoolUpdate(obj interface{}) bool {
nsVlanPoolMap[fabricVlanPoolObj.Name] = vlanStr
cont.fabricVlanPoolMap[fabricVlanPoolObj.Namespace] = nsVlanPoolMap
encapStr := cont.getGlobalFabricVlanPoolLocked()
progMap := make(map[string]apicapi.ApicSlice)
cont.updateGlobalConfig(encapStr, progMap)
return progMap
}

func (cont *AciController) handleFabricVlanPoolUpdate(obj interface{}) bool {
progMap := cont.updateFabricVlanPool(obj)
for labelKey, apicSlice := range progMap {
if apicSlice == nil {
cont.apicConn.ClearApicObjects(labelKey)
Expand All @@ -164,23 +169,28 @@ func (cont *AciController) handleFabricVlanPoolUpdate(obj interface{}) bool {
return false
}

func (cont *AciController) handleFabricVlanPoolDelete(key string) bool {
func (cont *AciController) deleteFabricVlanPool(key string) map[string]apicapi.ApicSlice {
progMap := make(map[string]apicapi.ApicSlice)
cont.log.Infof("fabricvlanpool delete: %s", key)
fabricVlanPoolElems := strings.Split("/", key)
fabricVlanPoolElems := strings.Split(key, "/")
cont.indexMutex.Lock()
defer cont.indexMutex.Unlock()
nsVlanPoolMap, ok := cont.fabricVlanPoolMap[fabricVlanPoolElems[0]]
if !ok {
return false
return progMap
}
delete(nsVlanPoolMap, fabricVlanPoolElems[1])
cont.fabricVlanPoolMap[fabricVlanPoolElems[0]] = nsVlanPoolMap
if len(nsVlanPoolMap) == 0 {
delete(cont.fabricVlanPoolMap, fabricVlanPoolElems[0])
}
encapStr := cont.getGlobalFabricVlanPoolLocked()
progMap := make(map[string]apicapi.ApicSlice)
cont.updateGlobalConfig(encapStr, progMap)
return progMap
}

func (cont *AciController) handleFabricVlanPoolDelete(key string) bool {
progMap := cont.deleteFabricVlanPool(key)
for labelKey, apicSlice := range progMap {
if apicSlice == nil {
cont.apicConn.ClearApicObjects(labelKey)
Expand Down
7 changes: 4 additions & 3 deletions pkg/controller/nodefabricnetworkattachments.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,12 @@ func (cont *AciController) updateGlobalConfig(encapStr string, progMap map[strin
cont.log.Errorf("Cannot set globalscope objects in per-port vlan mode")
return
}
if cont.globalVlanConfig.SharedPhysDom == nil {
return
}
_, encapBlks, err := cont.parseNodeFabNetAttVlanList(encapStr)
if err != nil {
cont.log.Errorf("Error updating GlobalScopeVlanConfig: %v", err)
return
}
cont.log.Infof("Setting globalvlanpool: %s", encapStr)
apicSlice = cont.updateNodeFabNetAttDom(encapBlks, globalScopeVlanDomPrefix)
labelKey := cont.aciNameForKey("nfna", globalScopeVlanDomPrefix)
progMap[labelKey] = apicSlice
Expand Down Expand Up @@ -282,6 +280,9 @@ func (cont *AciController) populateFabricPaths(epg apicapi.ApicObject, encap int
}

func (cont *AciController) parseNodeFabNetAttVlanList(vlan string) (vlans []int, vlanBlks []string, err error) {
if vlan == "" {
return vlans, vlanBlks, err
}
listContents := vlan
_, after, found := strings.Cut(vlan, "[")
if found {
Expand Down
7 changes: 4 additions & 3 deletions pkg/controller/nodefabricnetworkattachments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,16 +197,17 @@ func NFNACRUDCase(t *testing.T, globalScopeVlan bool, additionalVlans string) {
nfna2 := CreateNFNA("macvlan-net1", "master2.cluster.local", "bond1", "pod2-macvlan-net1",
[]string{"/topology/pod-1/node-101/pathep-[eth1/31]", "/topology/pod-1/node-102/pathep-[eth1/31]"})
fvp := CreateFabricVlanPool("aci-containers-system", "default", additionalVlans)
cont.handleFabricVlanPoolUpdate(fvp)
progMapPool := cont.updateFabricVlanPool(fvp)
progMap := cont.updateNodeFabNetAttObj(nfna1)
var expectedApicSlice1 apicapi.ApicSlice
expectedApicSlice1 = CreateNFNAObjs(nfna1, additionalVlans, cont)
var labelKey string
if globalScopeVlan {
assert.Equal(t, 3, len(progMap), "nfna create apicKey count")
assert.Equal(t, 1, len(progMapPool), "dom count")
assert.Equal(t, 2, len(progMap), "nfna Obj count")
expectedApicSlice1 = CreateNFNADom(nfna1, additionalVlans, cont)
labelKey = cont.aciNameForKey("nfna", "secondary")
assert.Equal(t, expectedApicSlice1, progMap[labelKey], "nfna create global dom")
assert.Equal(t, expectedApicSlice1, progMapPool[labelKey], "nfna create global dom")
var expectedApicSlice2 apicapi.ApicSlice
bd := CreateNFNABD(nfna1, 5, cont)
expectedApicSlice2 = append(expectedApicSlice2, bd)
Expand Down
69 changes: 38 additions & 31 deletions pkg/hostagent/netattachdef.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"github.com/k8snetworkplumbingwg/sriovnet"
fabattv1 "github.com/noironetworks/aci-containers/pkg/fabricattachment/apis/aci.fabricattachment/v1"
md "github.com/noironetworks/aci-containers/pkg/metadata"
"github.com/noironetworks/aci-containers/pkg/util"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -82,7 +83,6 @@ type NetworkAttachmentData struct {
EncapKey string
PluginVlan string
Programmed bool
vlanUnspecified bool
}

type ClientInfo struct {
Expand Down Expand Up @@ -287,9 +287,6 @@ func (agent *HostAgent) LoadCniNetworks() error {
for _, localIface := range netAttData.Ifaces {
agent.netattdefifacemap[localIface] = &netAttData
}
if netAttData.vlanUnspecified {
agent.orphanNadMap[netAttKey] = &netAttData
}
} else {
agent.log.Errorf("Failed to read additional network file %s:%v", path, err2)
return nil
Expand Down Expand Up @@ -408,19 +405,14 @@ func (agent *HostAgent) updateNodeFabricNetworkAttachmentForEncapChangeLocked(na
return
}
if !isDelete {
netAttData.vlanUnspecified = false
vlanList = agent.getAllowedVlansLocked(vlanList, netAttData.Namespace)
netAttData.EncapVlan = vlanList
netAttData.EncapKey = encapKey
agent.log.Debugf("Using nadVlanMap: %s", vlanList)
agent.log.Debugf("Using nadVlanMap allowed list : %s", vlanList)
} else {
vlan, _ := strconv.Atoi(netAttData.PluginVlan)
agent.handlePluginVlan(netAttData, vlan)
}
if netAttData.vlanUnspecified {
agent.orphanNadMap[nadKey] = netAttData
} else {
delete(agent.orphanNadMap, nadKey)
}
fabNetAttName := agent.config.NodeName + "-" + netAttData.Namespace + "-" + netAttData.Name
fabNetAtt, err := agent.fabAttClient.NodeFabricNetworkAttachments(fabNetAttDefNamespace).Get(context.TODO(), fabNetAttName, metav1.GetOptions{})
if err == nil {
Expand All @@ -438,13 +430,9 @@ func (agent *HostAgent) updateNodeFabricNetworkAttachmentForEncapChangeLocked(na
}

func (agent *HostAgent) updateNodeFabricNetworkAttachmentForFabricVlanPoolLocked() {
for _, netAttData := range agent.orphanNadMap {
vlanStr := agent.getFabricVlanPool(netAttData.Namespace, true)
if vlanStr != "" {
netAttData.EncapVlan = vlanStr
} else {
netAttData.EncapVlan = "0"
}
for _, netAttData := range agent.netattdefmap {
vlan, _ := strconv.Atoi(netAttData.PluginVlan)
agent.handlePluginVlan(netAttData, vlan)
fabNetAttName := agent.config.NodeName + "-" + netAttData.Namespace + "-" + netAttData.Name
fabNetAtt, err := agent.fabAttClient.NodeFabricNetworkAttachments(fabNetAttDefNamespace).Get(context.TODO(), fabNetAttName, metav1.GetOptions{})
if err == nil {
Expand Down Expand Up @@ -595,13 +583,42 @@ func validateVlanAnnotation(vlanStr string) (string, error) {
return resultStr, nil
}

func (agent *HostAgent) getAllowedVlansLocked(encapStr string, namespace string) (allowedStr string) {
poolStr := agent.getFabricVlanPool(namespace, true)
poolVlans, _, _, err := util.ParseVlanList([]string{poolStr})
if err != nil {
return ""
}
vlans, _, _, err := util.ParseVlanList([]string{encapStr})
if err != nil {
return ""
}
vlanMap := make(map[int]bool)
for _, elem := range vlans {
vlanMap[elem] = false
}
for _, elem := range poolVlans {
if _, ok := vlanMap[elem]; ok {
if allowedStr == "" {
allowedStr = fmt.Sprintf("[%d", elem)
continue
}
allowedStr += fmt.Sprintf(",%d", elem)
}
}
if len(allowedStr) != 0 {
allowedStr += "]"
}
return allowedStr
}

func (agent *HostAgent) handlePluginVlan(netAttData *NetworkAttachmentData, vlan int) {
netAttData.vlanUnspecified = false
nadKey := netAttData.Namespace + "/" + netAttData.Name
netAttData.PluginVlan = fmt.Sprintf("%d", vlan)
if vlan == 0 {
if val, ok := netAttData.KnownAnnots[vlanAnnot]; ok {
if vlanStr, err := validateVlanAnnotation(val); err == nil {
vlanStr = agent.getAllowedVlansLocked(vlanStr, netAttData.Namespace)
agent.log.Debugf("Using annotation: %s", vlanStr)
netAttData.EncapVlan = vlanStr
netAttData.EncapKey = ""
Expand All @@ -612,19 +629,15 @@ func (agent *HostAgent) handlePluginVlan(netAttData *NetworkAttachmentData, vlan
}
matchingKey, vlanList, match := agent.getNadVlanMapMatchLocked(nadKey)
if match {
vlanList = agent.getAllowedVlansLocked(vlanList, netAttData.Namespace)
agent.log.Debugf("Using nadVlanMap: %s", vlanList)
netAttData.EncapVlan = vlanList
netAttData.EncapKey = matchingKey
return
}
encap := "0"
netAttData.vlanUnspecified = true
vlanStr := agent.getFabricVlanPool(netAttData.Namespace, true)
agent.log.Debugf("Using vlan pool: %s", vlanStr)
if vlanStr != "" {
encap = vlanStr
}
netAttData.EncapVlan = encap
netAttData.EncapVlan = vlanStr
netAttData.EncapKey = ""
return
}
Expand Down Expand Up @@ -774,11 +787,6 @@ func (agent *HostAgent) networkAttDefChanged(ntd *netpolicy.NetworkAttachmentDef
}
}
}
if netattdata.vlanUnspecified {
agent.orphanNadMap[netAttDefKey] = &netattdata
} else {
delete(agent.orphanNadMap, netAttDefKey)
}
if err := agent.updateNodeFabricNetworkAttachmentLocked(&netattdata); err != nil {
agent.log.Errorf("Failed to create/update nodefabricnetworkattachment %s :%v", nodeFabNetAttName, err)
}
Expand Down Expand Up @@ -849,7 +857,6 @@ func (agent *HostAgent) networkAttDefDeleted(obj interface{}) {
delete(agent.netattdefifacemap, iface)
}
}
delete(agent.orphanNadMap, netAttDefKey)
agent.DeleteNetworkMetadata(netattDef)
}
delete(agent.netattdefmap, netAttDefKey)
Expand Down
4 changes: 2 additions & 2 deletions pkg/hostagent/netattachdef_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func TestNADSRIOVCRUD(t *testing.T) {

resourceAnnot := make(map[string]string)
resourceAnnot["k8s.v1.cni.cncf.io/resourceName"] = "openshift.io/enp216s0f0"
resourceAnnot[vlanAnnot] = "[100,101,195-200]"
resourceAnnot[vlanAnnot] = "[100,102,195-200]"
agent := testAgentEnvtest(getChainedModeConfig(nodename), kubeClient, cfg)
configmapData := map[string]string{
nodename: `{"resourceList":[{"resourceName":"enp216s0f0","selectors":{"vendors":["8086"],"devices":["154c"],"pfNames":["enp216s0f0#0-15"],"rootDevices":["0000:d8:00.0"],"IsRdma":false,"NeedVhostNet":false},"SelectorObj":null}]}`,
Expand All @@ -179,7 +179,7 @@ func TestNADSRIOVCRUD(t *testing.T) {
Name: "sriov-net-1",
Namespace: "default",
},
EncapVlan: fabattv1.EncapSource{VlanList: "[100,101,195-200]"},
EncapVlan: fabattv1.EncapSource{VlanList: "[102]"},
AciTopology: map[string]fabattv1.AciNodeLinkAdjacency{
"enp216s0f0": {
FabricLink: []string{
Expand Down