From a074efe14661ecc547ec0a44a24bba88fd7daf57 Mon Sep 17 00:00:00 2001 From: "Venkatesh, Vemula" Date: Wed, 25 Sep 2024 08:08:12 +0100 Subject: [PATCH 1/6] fix(evpn-bridge): fix for frr to handle vrf setup and teardown Signed-off-by: Venkatesh, Vemula --- pkg/frr/frr.go | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/pkg/frr/frr.go b/pkg/frr/frr.go index 5deeec0..fe25fec 100644 --- a/pkg/frr/frr.go +++ b/pkg/frr/frr.go @@ -271,13 +271,6 @@ func handlevrf(objectData *eventbus.ObjectData) { return } - if len(vrf.Status.Components) != 0 { - for i := 0; i < len(vrf.Status.Components); i++ { - if vrf.Status.Components[i].Name == frrComp { - comp = vrf.Status.Components[i] - } - } - } if objectData.ResourceVersion != vrf.ResourceVersion { log.Printf("FRR: Mismatch in resoruce version %+v\n and vrf resource version %+v\n", objectData.ResourceVersion, vrf.ResourceVersion) comp.Name = frrComp @@ -493,9 +486,9 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { // Configure the vrf in FRR and set up BGP EVPN for it vrfName := fmt.Sprintf("vrf %s", path.Base(vrf.Name)) vniID := fmt.Sprintf("vni %s", strconv.Itoa(int(*vrf.Spec.Vni))) - _, err := Frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit-vrf\n exit", vrfName, vniID)) - // fmt.Printf("FrrZebraCmd: %v:%v", data, err) - if err != nil { + data, err := Frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit-vrf\n exit", vrfName, vniID)) + if err != nil || checkFrrResult(data, false) { + log.Printf("FRR: Error Executing frr config t %s %s exit-vrf exit data %v err is %v data is %v\n", vrfName, vniID, data, err, data) return "", false } err = Frr.Save(ctx) @@ -510,8 +503,9 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { } else { LbiP = fmt.Sprintf("%+v", vrf.Spec.LoopbackIP.IP) } - _, err = Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n router bgp %+v vrf %s\n bgp router-id %s\n no bgp ebgp-requires-policy\n no bgp hard-administrative-reset\n no bgp graceful-restart notification\n address-family ipv4 unicast\n redistribute connected\n redistribute static\n exit-address-family\n address-family l2vpn evpn\n advertise ipv4 unicast\n exit-address-family\n exit", localas, path.Base(vrf.Name), LbiP)) - if err != nil { + data, err = Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n router bgp %+v vrf %s\n bgp router-id %s\n no bgp ebgp-requires-policy\n no bgp hard-administrative-reset\n no bgp graceful-restart notification\n address-family ipv4 unicast\n redistribute connected\n redistribute static\n exit-address-family\n address-family l2vpn evpn\n advertise ipv4 unicast\n exit-address-family\n exit", localas, path.Base(vrf.Name), LbiP)) + if err != nil || checkFrrResult(data, false) { + log.Printf("FRR: Error Executing config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit data %v \n", localas, vrf.Name, LbiP, data) return "", false } err = Frr.Save(ctx) @@ -522,8 +516,8 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { // Update the vrf with attributes from FRR cmd := fmt.Sprintf("show bgp l2vpn evpn vni %d json", *vrf.Spec.Vni) cp, err := Frr.FrrBgpCmd(ctx, cmd) - if err != nil { - log.Printf("error-%v", err) + if err != nil || checkFrrResult(cp, true) { + log.Printf("FRR Error-show bgp l2vpn evpn vni %v cp %v", err, cp) } err = Frr.Save(ctx) if err != nil { @@ -533,8 +527,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { L2vpnCmd := strings.Split(cp, "json") L2vpnCmd = strings.Split(L2vpnCmd[1], hname) cp = L2vpnCmd[0] - // fmt.Printf("FRR_L2vpn[0]: %s\n",cp) - if len(cp) != 7 { + if len(cp) != 7 { // Checking CMD o/p cp = cp[3 : len(cp)-3] } else { log.Printf("FRR: unable to get the command %s\n", cmd) @@ -547,7 +540,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { } cmd = fmt.Sprintf("show bgp vrf %s json", path.Base(vrf.Name)) cp, err = Frr.FrrBgpCmd(ctx, cmd) - if err != nil { + if err != nil || checkFrrResult(cp, true) { log.Printf("error-%v", err) } err = Frr.Save(ctx) @@ -579,7 +572,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { // checkFrrResult checks the vrf result func checkFrrResult(cp string, show bool) bool { - return ((show && reflect.ValueOf(cp).IsZero()) || strings.Contains(cp, "warning") || strings.Contains(cp, "unknown") || strings.Contains(cp, "Unknown") || strings.Contains(cp, "Warning") || strings.Contains(cp, "Ambiguous") || strings.Contains(cp, "specified does not exist")) + return ((show && reflect.ValueOf(cp).IsZero()) || strings.Contains(cp, "warning") || strings.Contains(cp, "unknown") || strings.Contains(cp, "Unknown") || strings.Contains(cp, "Warning") || strings.Contains(cp, "Ambiguous") || strings.Contains(cp, "specified does not exist") || strings.Contains(cp, "Error")) } // setUpSvi sets up the svi @@ -630,6 +623,9 @@ func tearDownSvi(svi *infradb.Svi) bool { bgpVrfName := fmt.Sprintf("router bgp %+v vrf %s", localas, path.Base(svi.Spec.Vrf)) noNeigh := fmt.Sprintf("no neighbor %s peer-group", linkSvi) data, err := Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit", bgpVrfName, noNeigh)) + if strings.Contains(data, "Create the peer-group first") { // Trying to delete non exist peer-group return true + return true + } if err != nil || checkFrrResult(data, false) { log.Printf("FRR: Error in conf Delete vrf/VNI command %s\n", data) return false @@ -668,8 +664,12 @@ func tearDownVrf(vrf *infradb.Vrf) bool { log.Printf("FRR Deleted event") delCmd1 := fmt.Sprintf("no router bgp %+v vrf %s", localas, path.Base(vrf.Name)) delCmd2 := fmt.Sprintf("no vrf %s", path.Base(vrf.Name)) - _, err = Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd1)) - if err != nil { + data, err = Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd1)) + if strings.Contains(data, "Can't find BGP instance") { // Trying to delete non exist VRF return true + return true + } + if err != nil || checkFrrResult(data, false) { + log.Printf("FRR: Error %s\n", data) return false } err = Frr.Save(ctx) @@ -678,6 +678,7 @@ func tearDownVrf(vrf *infradb.Vrf) bool { } _, err = Frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd2)) if err != nil { + return false } err = Frr.Save(ctx) From d2094b1e5078d7e67297455624c860ec06910e8e Mon Sep 17 00:00:00 2001 From: atulpatel261194 Date: Mon, 30 Sep 2024 04:31:24 -0700 Subject: [PATCH 2/6] fix(evpn): report error in comp details Signed-off-by: atulpatel261194 --- pkg/LinuxCIModule/lci.go | 48 ++++++----- pkg/LinuxGeneralModule/lgm.go | 151 ++++++++++++++++++---------------- pkg/frr/frr.go | 72 ++++++++-------- 3 files changed, 145 insertions(+), 126 deletions(-) diff --git a/pkg/LinuxCIModule/lci.go b/pkg/LinuxCIModule/lci.go index f73f964..9607508 100644 --- a/pkg/LinuxCIModule/lci.go +++ b/pkg/LinuxCIModule/lci.go @@ -7,6 +7,7 @@ package linuxcimodule import ( "context" + "fmt" // "io/ioutil" "log" @@ -48,6 +49,7 @@ func handlebp(objectData *eventbus.ObjectData) { log.Printf("LCI : GetBP error: %s\n", err) comp.Name = lciComp comp.CompStatus = common.ComponentStatusError + comp.Details = fmt.Sprintf("LCI : GetBP error: %s\n", err) if comp.Timer == 0 { comp.Timer = 2 * time.Second } else { @@ -63,6 +65,7 @@ func handlebp(objectData *eventbus.ObjectData) { log.Printf("LVM: Mismatch in resoruce version %+v\n and bp resource version %+v\n", objectData.ResourceVersion, BP.ResourceVersion) comp.Name = lciComp comp.CompStatus = common.ComponentStatusError + comp.Details = fmt.Sprintf("LVM: Mismatch in resoruce version %+v\n and bp resource version %+v\n", objectData.ResourceVersion, BP.ResourceVersion) if comp.Timer == 0 { comp.Timer = 2 * time.Second } else { @@ -82,10 +85,10 @@ func handlebp(objectData *eventbus.ObjectData) { } } if BP.Status.BPOperStatus != infradb.BridgePortOperStatusToBeDeleted { - status := setUpBp(BP) + details, status := setUpBp(BP) comp.Name = lciComp + comp.Details = details if status { - comp.Details = "" comp.CompStatus = common.ComponentStatusSuccess comp.Timer = 0 } else { @@ -102,8 +105,9 @@ func handlebp(objectData *eventbus.ObjectData) { log.Printf("error in updating bp status: %s\n", err) } } else { - status := tearDownBp(BP) + details, status := tearDownBp(BP) comp.Name = lciComp + comp.Details = details if status { comp.CompStatus = common.ComponentStatusSuccess comp.Timer = 0 @@ -124,31 +128,31 @@ func handlebp(objectData *eventbus.ObjectData) { } // setUpBp sets up the bridge port -func setUpBp(bp *infradb.BridgePort) bool { +func setUpBp(bp *infradb.BridgePort) (string, bool) { resourceID := path.Base(bp.Name) bridge, err := nlink.LinkByName(ctx, "br-tenant") if err != nil { log.Printf("LCI: Unable to find key br-tenant\n") - return false + return fmt.Sprintf("LCI: Unable to find key br-tenant, %s", err), false } iface, err := nlink.LinkByName(ctx, resourceID) if err != nil { log.Printf("LCI: Unable to find key %s\n", resourceID) - return false + return fmt.Sprintf("LCI: Unable to find key %s\n", resourceID), false } if err := nlink.LinkSetMaster(ctx, iface, bridge); err != nil { log.Printf("LCI: Failed to add iface to bridge: %v", err) - return false + return fmt.Sprintf("LCI: Failed to add iface to bridge: %v", err), false } for _, bridgeRefName := range bp.Spec.LogicalBridges { BrObj, err := infradb.GetLB(bridgeRefName) if err != nil { log.Printf("LCI: unable to find key %s and error is %v", bridgeRefName, err) - return false + return fmt.Sprintf("LCI: unable to find key %s and error is %v", bridgeRefName, err), false } if BrObj.Spec.VlanID > math.MaxUint16 { log.Printf("LVM : VlanID %v value passed in Logical Bridge create is greater than 16 bit value\n", BrObj.Spec.VlanID) - return false + return fmt.Sprintf("LVM : VlanID %v value passed in Logical Bridge create is greater than 16 bit value\n", BrObj.Spec.VlanID), false } //TODO: Update opi-api to change vlanid to int16 in LogiclaBridge "https://linter.aip.dev/141/forbidden-types" vid := uint16(BrObj.Spec.VlanID) @@ -156,60 +160,60 @@ func setUpBp(bp *infradb.BridgePort) bool { case infradb.Access: if err := nlink.BridgeVlanAdd(ctx, iface, vid, true, true, false, false); err != nil { log.Printf("Failed to add vlan to bridge: %v", err) - return false + return fmt.Sprintf("Failed to add vlan to bridge: %v", err), false } case infradb.Trunk: // Example: bridge vlan add dev eth2 vid 20 if err := nlink.BridgeVlanAdd(ctx, iface, vid, false, false, false, false); err != nil { log.Printf("Failed to add vlan to bridge: %v", err) - return false + return fmt.Sprintf("Failed to add vlan to bridge: %v", err), false } default: log.Printf("Only ACCESS or TRUNK supported and not (%d)", bp.Spec.Ptype) - return false + return fmt.Sprintf("Only ACCESS or TRUNK supported and not (%d)", bp.Spec.Ptype), false } } if err := nlink.LinkSetUp(ctx, iface); err != nil { log.Printf("Failed to up iface link: %v", err) - return false + return fmt.Sprintf("Failed to up iface link: %v", err), false } - return true + return "", true } // tearDownBp tears down a bridge port -func tearDownBp(bp *infradb.BridgePort) bool { +func tearDownBp(bp *infradb.BridgePort) (string, bool) { resourceID := path.Base(bp.Name) iface, err := nlink.LinkByName(ctx, resourceID) if err != nil { log.Printf("LCI: Unable to find key %s\n", resourceID) - return false + return fmt.Sprintf("LCI: Unable to find key %s\n", resourceID), false } if err := nlink.LinkSetDown(ctx, iface); err != nil { log.Printf("LCI: Failed to down link: %v", err) - return false + return fmt.Sprintf("LCI: Failed to down link: %v", err), false } for _, bridgeRefName := range bp.Spec.LogicalBridges { BrObj, err := infradb.GetLB(bridgeRefName) if err != nil { log.Printf("LCI: unable to find key %s and error is %v", bridgeRefName, err) - return false + return fmt.Sprintf("LCI: unable to find key %s and error is %v", bridgeRefName, err), false } if BrObj.Spec.VlanID > math.MaxUint16 { log.Printf("LVM : VlanID %v value passed in Logical Bridge create is greater than 16 bit value\n", BrObj.Spec.VlanID) - return false + return fmt.Sprintf("LVM : VlanID %v value passed in Logical Bridge create is greater than 16 bit value\n", BrObj.Spec.VlanID), false } //TODO: Update opi-api to change vlanid to uint16 in LogiclaBridge vid := uint16(BrObj.Spec.VlanID) if err := nlink.BridgeVlanDel(ctx, iface, vid, true, true, false, false); err != nil { log.Printf("LCI: Failed to delete vlan to bridge: %v", err) - return false + return fmt.Sprintf("LCI: Failed to delete vlan to bridge: %v", err), false } } if err := nlink.LinkDel(ctx, iface); err != nil { log.Printf("Failed to delete link: %v", err) - return false + return fmt.Sprintf("Failed to delete link: %v", err), false } - return true + return "", true } var ctx context.Context diff --git a/pkg/LinuxGeneralModule/lgm.go b/pkg/LinuxGeneralModule/lgm.go index 5140bd0..d8fd61b 100644 --- a/pkg/LinuxGeneralModule/lgm.go +++ b/pkg/LinuxGeneralModule/lgm.go @@ -94,6 +94,7 @@ func handleLB(objectData *eventbus.ObjectData) { log.Printf("LGM: GetLB error: %s %s\n", err, objectData.Name) comp.Name = lgmComp comp.CompStatus = common.ComponentStatusError + comp.Details = fmt.Sprintf("LGM: GetLB error: %s %s\n", err, objectData.Name) if comp.Timer == 0 { comp.Timer = 2 * time.Second } else { @@ -109,6 +110,7 @@ func handleLB(objectData *eventbus.ObjectData) { log.Printf("LGM: Mismatch in resoruce version %+v\n and lb resource version %+v\n", objectData.ResourceVersion, lb.ResourceVersion) comp.Name = lgmComp comp.CompStatus = common.ComponentStatusError + comp.Details = fmt.Sprintf("LGM: Mismatch in resoruce version %+v\n and lb resource version %+v\n", objectData.ResourceVersion, lb.ResourceVersion) if comp.Timer == 0 { comp.Timer = 2 * time.Second } else { @@ -128,10 +130,10 @@ func handleLB(objectData *eventbus.ObjectData) { } } if lb.Status.LBOperStatus != infradb.LogicalBridgeOperStatusToBeDeleted { - status := setUpBridge(lb) + details, status := setUpBridge(lb) comp.Name = lgmComp + comp.Details = details if status { - comp.Details = "" comp.CompStatus = common.ComponentStatusSuccess comp.Timer = 0 } else { @@ -148,8 +150,9 @@ func handleLB(objectData *eventbus.ObjectData) { log.Printf("error in updating lb status: %s\n", err) } } else { - status := tearDownBridge(lb) + details, status := tearDownBridge(lb) comp.Name = lgmComp + comp.Details = details if status { comp.CompStatus = common.ComponentStatusSuccess comp.Timer = 0 @@ -194,6 +197,7 @@ func handlesvi(objectData *eventbus.ObjectData) { log.Printf("LGM: Mismatch in resoruce version %+v\n and svi resource version %+v\n", objectData.ResourceVersion, svi.ResourceVersion) comp.Name = lgmComp comp.CompStatus = common.ComponentStatusError + comp.Details = fmt.Sprintf("LGM: Mismatch in resoruce version %+v\n and svi resource version %+v\n", objectData.ResourceVersion, svi.ResourceVersion) if comp.Timer == 0 { comp.Timer = 2 * time.Second } else { @@ -213,8 +217,9 @@ func handlesvi(objectData *eventbus.ObjectData) { } } if svi.Status.SviOperStatus != infradb.SviOperStatusToBeDeleted { - status := setUpSvi(svi) + details, status := setUpSvi(svi) comp.Name = lgmComp + comp.Details = details if status { comp.CompStatus = common.ComponentStatusSuccess comp.Timer = 0 @@ -232,8 +237,9 @@ func handlesvi(objectData *eventbus.ObjectData) { log.Printf("error in updating svi status: %s\n", err) } } else { - status := tearDownSvi(svi) + details, status := tearDownSvi(svi) comp.Name = lgmComp + comp.Details = details if status { comp.CompStatus = common.ComponentStatusSuccess comp.Timer = 0 @@ -263,6 +269,7 @@ func handlevrf(objectData *eventbus.ObjectData) { log.Printf("LGM: GetVRF error: %s %s\n", err, objectData.Name) comp.Name = lgmComp comp.CompStatus = common.ComponentStatusError + comp.Details = fmt.Sprintf("LGM: GetVRF error: %s %s\n", err, objectData.Name) if comp.Timer == 0 { // wait timer is 2 powerof natural numbers ex : 1,2,3... comp.Timer = 2 * time.Second } else { @@ -278,6 +285,7 @@ func handlevrf(objectData *eventbus.ObjectData) { log.Printf("LGM: Mismatch in resoruce version %+v\n and vrf resource version %+v\n", objectData.ResourceVersion, vrf.ResourceVersion) comp.Name = lgmComp comp.CompStatus = common.ComponentStatusError + comp.Details = fmt.Sprintf("LGM: Mismatch in resoruce version %+v\n and vrf resource version %+v\n", objectData.ResourceVersion, vrf.ResourceVersion) if comp.Timer == 0 { // wait timer is 2 powerof natural numbers ex : 1,2,3... comp.Timer = 2 * time.Second } else { @@ -299,8 +307,8 @@ func handlevrf(objectData *eventbus.ObjectData) { if vrf.Status.VrfOperStatus != infradb.VrfOperStatusToBeDeleted { details, status := setUpVrf(vrf) comp.Name = lgmComp + comp.Details = details if status { - comp.Details = details comp.CompStatus = common.ComponentStatusSuccess comp.Timer = 0 } else { @@ -317,8 +325,9 @@ func handlevrf(objectData *eventbus.ObjectData) { log.Printf("error in updating vrf status: %s\n", err) } } else { - status := tearDownVrf(vrf) + details, status := tearDownVrf(vrf) comp.Name = lgmComp + comp.Details = details if status { comp.CompStatus = common.ComponentStatusSuccess comp.Timer = 0 @@ -411,42 +420,42 @@ func routingTableBusy(table uint32) (bool, error) { } // setUpBridge sets up the bridge -func setUpBridge(lb *infradb.LogicalBridge) bool { +func setUpBridge(lb *infradb.LogicalBridge) (string, bool) { link := fmt.Sprintf("vxlan-%+v", lb.Spec.VlanID) if !reflect.ValueOf(lb.Spec.Vni).IsZero() { brIntf, err := nlink.LinkByName(ctx, brTenant) if err != nil { log.Printf("LGM: Failed to get link information for %s: %v\n", brTenant, err) - return false + return fmt.Sprintf("LGM: Failed to get link information for %s: %v\n", brTenant, err), false } vxlan := &netlink.Vxlan{LinkAttrs: netlink.LinkAttrs{Name: link, MTU: ipMtu}, VxlanId: int(*lb.Spec.Vni), Port: 4789, Learning: false, SrcAddr: lb.Spec.VtepIP.IP} if err := nlink.LinkAdd(ctx, vxlan); err != nil { log.Printf("LGM: Failed to create Vxlan linki %s: %v\n", link, err) - return false + return fmt.Sprintf("LGM: Failed to create Vxlan linki %s: %v\n", link, err), false } // Example: ip link set vxlan- master br-tenant addrgenmode none if err = nlink.LinkSetMaster(ctx, vxlan, brIntf); err != nil { log.Printf("LGM: Failed to add Vxlan %s to bridge %s: %v\n", link, brTenant, err) - return false + return fmt.Sprintf("LGM: Failed to add Vxlan %s to bridge %s: %v\n", link, brTenant, err), false } // Example: ip link set vxlan- up if err = nlink.LinkSetUp(ctx, vxlan); err != nil { log.Printf("LGM: Failed to up Vxlan link %s: %v\n", link, err) - return false + return fmt.Sprintf("LGM: Failed to up Vxlan link %s: %v\n", link, err), false } // Example: bridge vlan add dev vxlan- vid pvid untagged if err = nlink.BridgeVlanAdd(ctx, vxlan, uint16(lb.Spec.VlanID), true, true, false, false); err != nil { log.Printf("LGM: Failed to add vlan to bridge %s: %v\n", brTenant, err) - return false + return fmt.Sprintf("LGM: Failed to add vlan to bridge %s: %v\n", brTenant, err), false } if err = nlink.LinkSetBrNeighSuppress(ctx, vxlan, true); err != nil { log.Printf("LGM: Failed to add bridge %v neigh_suppress: %s\n", vxlan, err) - return false + return fmt.Sprintf("LGM: Failed to add bridge %v neigh_suppress: %s\n", vxlan, err), false } - return true + return "", true } - return true + return "", true } // setUpVrf sets up the vrf @@ -470,7 +479,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { isBusy, err := routingTableBusy(routingTable) if err != nil { log.Printf("LGM : Error occurred when checking if routing table %d is busy: %+v\n", routingTable, err) - return "", false + return fmt.Sprintf("LGM : Error occurred when checking if routing table %d is busy: %+v\n", routingTable, err), false } if !isBusy { log.Printf("LGM: Routing Table %d is not busy\n", routingTable) @@ -486,7 +495,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { // Not found similar API in viswananda library so retain the linux commands as it is .. not able to get the route list exact vtip table local if !err { log.Printf(" LGM: VTEP IP not found: %+v\n", vrf.Spec.VtepIP) - return "", false + return fmt.Sprintf(" LGM: VTEP IP not found: %+v\n", vrf.Spec.VtepIP), false } } log.Printf("setUpVrf: %s %d\n", vtip, routingTable) @@ -498,7 +507,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { }) if linkAdderr != nil { log.Printf("LGM: Error in Adding vrf link table %d\n", routingTable) - return "", false + return fmt.Sprintf("LGM: Error in Adding vrf link table %d\n", routingTable), false } log.Printf("LGM: vrf link %s Added with table id %d\n", vrf.Name, routingTable) @@ -506,19 +515,19 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { link, linkErr := nlink.LinkByName(ctx, path.Base(vrf.Name)) if linkErr != nil { log.Printf("LGM : Link %s not found\n", vrf.Name) - return "", false + return fmt.Sprintf("LGM : Link %s not found\n", vrf.Name), false } linkmtuErr := nlink.LinkSetMTU(ctx, link, ipMtu) if linkmtuErr != nil { log.Printf("LGM : Unable to set MTU to link %s \n", vrf.Name) - return "", false + return fmt.Sprintf("LGM : Unable to set MTU to link %s \n", vrf.Name), false } linksetupErr := nlink.LinkSetUp(ctx, link) if linksetupErr != nil { log.Printf("LGM : Unable to set link %s UP \n", vrf.Name) - return "", false + return fmt.Sprintf("LGM : Unable to set link %s UP \n", vrf.Name), false } Lbip := fmt.Sprintf("%+v", vrf.Spec.LoopbackIP.IP) @@ -529,7 +538,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { addrErr := nlink.AddrAdd(ctx, link, Addrs) if addrErr != nil { log.Printf("LGM: Unable to set the loopback ip to vrf link %s \n", vrf.Name) - return "", false + return fmt.Sprintf("LGM: Unable to set the loopback ip to vrf link %s \n", vrf.Name), false } log.Printf("LGM: Added Address %s dev %s\n", Lbip, vrf.Name) @@ -545,7 +554,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { routeaddErr := nlink.RouteAdd(ctx, &route) if routeaddErr != nil { log.Printf("LGM : Failed in adding Route throw default %+v\n", routeaddErr) - return "", false + return fmt.Sprintf("LGM : Failed in adding Route throw default %+v\n", routeaddErr), false } log.Printf("LGM : Added route throw default table %d proto opi_evpn_br metric 9999\n", routingTable) @@ -563,7 +572,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { }) if brErr != nil { log.Printf("LGM : Error in added bridge port\n") - return "", false + return fmt.Sprintf("LGM : Error in added bridge port %v", brErr), false } log.Printf("LGM : Added link br-%s type bridge\n", vrf.Name) @@ -573,36 +582,36 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { linkBr, brErr := nlink.LinkByName(ctx, brStr+path.Base(vrf.Name)) if brErr != nil { log.Printf("LGM : Error in getting the br-%s\n", vrf.Name) - return "", false + return fmt.Sprintf("LGM : Error in getting the br-%s\n", vrf.Name), false } hwErr := nlink.LinkSetHardwareAddr(ctx, linkBr, hw) if hwErr != nil { log.Printf("LGM: Failed in the setting Hardware Address\n") - return "", false + return fmt.Sprintf("LGM: Failed in the setting Hardware Address: %v\n", hwErr), false } linkmtuErr := nlink.LinkSetMTU(ctx, linkBr, ipMtu) if linkmtuErr != nil { log.Printf("LGM : Unable to set MTU to link br-%s \n", vrf.Name) - return "", false + return fmt.Sprintf("LGM : Unable to set MTU to link br-%s \n", vrf.Name), false } linkMaster, errMaster := nlink.LinkByName(ctx, path.Base(vrf.Name)) if errMaster != nil { log.Printf("LGM : Error in getting the %s\n", vrf.Name) - return "", false + return fmt.Sprintf("LGM : Error in getting the %s\n", vrf.Name), false } err := nlink.LinkSetMaster(ctx, linkBr, linkMaster) if err != nil { log.Printf("LGM : Unable to set the master to br-%s link", vrf.Name) - return "", false + return fmt.Sprintf("LGM : Unable to set the master to br-%s link", vrf.Name), false } linksetupErr = nlink.LinkSetUp(ctx, linkBr) if linksetupErr != nil { log.Printf("LGM : Unable to set link %s UP \n", vrf.Name) - return "", false + return fmt.Sprintf("LGM : Unable to set link %s UP \n", vrf.Name), false } log.Printf("LGM: link set br-%s master %s up mtu \n", vrf.Name, IPMtu) @@ -613,7 +622,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { LinkAttrs: netlink.LinkAttrs{Name: vxlanStr + path.Base(vrf.Name), MTU: ipMtu}, VxlanId: int(*vrf.Spec.Vni), SrcAddr: SrcVtep, Learning: false, Proxy: true, Port: 4789}) if vxlanErr != nil { log.Printf("LGM : Error in added vxlan port\n") - return "", false + return fmt.Sprintf("LGM : Error in added vxlan port %v\n", vxlanErr), false } log.Printf("LGM : link added vxlan-%s type vxlan id %d local %s dstport 4789 nolearning proxy\n", vrf.Name, *vrf.Spec.Vni, vtip) @@ -621,13 +630,13 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { linkVxlan, vxlanErr := nlink.LinkByName(ctx, vxlanStr+path.Base(vrf.Name)) if vxlanErr != nil { log.Printf("LGM : Error in getting the %s\n", vxlanStr+vrf.Name) - return "", false + return fmt.Sprintf("LGM : Error in getting the %s\n", vxlanStr+vrf.Name), false } err = nlink.LinkSetMaster(ctx, linkVxlan, linkBr) if err != nil { log.Printf("LGM : Unable to set the master to vxlan-%s link", vrf.Name) - return "", false + return fmt.Sprintf("LGM : Unable to set the master to vxlan-%s link", vrf.Name), false } log.Printf("LGM: vrf Link vxlan setup master\n") @@ -635,7 +644,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { linksetupErr = nlink.LinkSetUp(ctx, linkVxlan) if linksetupErr != nil { log.Printf("LGM : Unable to set link %s UP \n", vrf.Name) - return "", false + return fmt.Sprintf("LGM : Unable to set link %s UP \n", vrf.Name), false } } details := fmt.Sprintf("{\"routingTable\":\"%d\"}", routingTable) @@ -644,58 +653,58 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { } // setUpSvi sets up the svi -func setUpSvi(svi *infradb.Svi) bool { +func setUpSvi(svi *infradb.Svi) (string, bool) { BrObj, err := infradb.GetLB(svi.Spec.LogicalBridge) if err != nil { log.Printf("LGM: unable to find key %s and error is %v", svi.Spec.LogicalBridge, err) - return false + return fmt.Sprintf("LGM: unable to find key %s and error is %v", svi.Spec.LogicalBridge, err), false } linkSvi := fmt.Sprintf("%+v-%+v", path.Base(svi.Spec.Vrf), BrObj.Spec.VlanID) brIntf, err := nlink.LinkByName(ctx, brTenant) if err != nil { log.Printf("LGM : Failed to get link information for %s: %v\n", brTenant, err) - return false + return fmt.Sprintf("LGM : Failed to get link information for %s: %v\n", brTenant, err), false } if BrObj.Spec.VlanID > math.MaxUint16 { log.Printf("LGM : VlanID %v value passed in Logical Bridge create is greater than 16 bit value\n", BrObj.Spec.VlanID) - return false + return fmt.Sprintf("LGM : VlanID %v value passed in Logical Bridge create is greater than 16 bit value\n", BrObj.Spec.VlanID), false } vid := uint16(BrObj.Spec.VlanID) if err = nlink.BridgeVlanAdd(ctx, brIntf, vid, false, false, true, false); err != nil { log.Printf("LGM : Failed to add VLAN %d to bridge interface %s: %v\n", vid, brTenant, err) - return false + return fmt.Sprintf("LGM : Failed to add VLAN %d to bridge interface %s: %v\n", vid, brTenant, err), false } log.Printf("LGM Executed : bridge vlan add dev %s vid %d self\n", brTenant, vid) vlanLink := &netlink.Vlan{LinkAttrs: netlink.LinkAttrs{Name: linkSvi, ParentIndex: brIntf.Attrs().Index}, VlanId: int(BrObj.Spec.VlanID)} if err = nlink.LinkAdd(ctx, vlanLink); err != nil { log.Printf("LGM : Failed to add VLAN sub-interface %s: %v\n", linkSvi, err) - return false + return fmt.Sprintf("LGM : Failed to add VLAN sub-interface %s: %v\n", linkSvi, err), false } log.Printf("LGM Executed : ip link add link %s name %s type vlan id %d\n", brTenant, linkSvi, vid) if err = nlink.LinkSetHardwareAddr(ctx, vlanLink, *svi.Spec.MacAddress); err != nil { log.Printf("LGM : Failed to set link %v: %s\n", vlanLink, err) - return false + return fmt.Sprintf("LGM : Failed to set link %v: %s\n", vlanLink, err), false } log.Printf("LGM Executed : ip link set %s address %s\n", linkSvi, *svi.Spec.MacAddress) vrfIntf, err := nlink.LinkByName(ctx, path.Base(svi.Spec.Vrf)) if err != nil { log.Printf("LGM : Failed to get link information for %s: %v\n", path.Base(svi.Spec.Vrf), err) - return false + return fmt.Sprintf("LGM : Failed to get link information for %s: %v\n", path.Base(svi.Spec.Vrf), err), false } if err = nlink.LinkSetMaster(ctx, vlanLink, vrfIntf); err != nil { log.Printf("LGM : Failed to set master for %v: %s\n", vlanLink, err) - return false + return fmt.Sprintf("LGM : Failed to set master for %v: %s\n", vlanLink, err), false } if err = nlink.LinkSetUp(ctx, vlanLink); err != nil { log.Printf("LGM : Failed to set up link for %v: %s\n", vlanLink, err) - return false + return fmt.Sprintf("LGM : Failed to set up link for %v: %s\n", vlanLink, err), false } if err = nlink.LinkSetMTU(ctx, vlanLink, ipMtu); err != nil { log.Printf("LGM : Failed to set MTU for %v: %s\n", vlanLink, err) - return false + return fmt.Sprintf("LGM : Failed to set MTU for %v: %s\n", vlanLink, err), false } log.Printf("LGM Executed : ip link set %s master %s up mtu %d\n", linkSvi, path.Base(svi.Spec.Vrf), ipMtu) @@ -716,12 +725,12 @@ func setUpSvi(svi *infradb.Svi) bool { } if err := nlink.AddrAdd(ctx, vlanLink, addr); err != nil { log.Printf("LGM: Failed to add ip address %v to %v: %v\n", addr, vlanLink, err) - return false + return fmt.Sprintf("LGM: Failed to add ip address %v to %v: %v\n", addr, vlanLink, err), false } log.Printf("LGM Executed : ip address add %s dev %+v\n", addr, vlanLink) } - return true + return "", true } // GenerateMac Generates the random mac @@ -765,15 +774,15 @@ func NetMaskToInt(mask int) (netmaskint [4]int64) { } // tearDownVrf tears down the vrf -func tearDownVrf(vrf *infradb.Vrf) bool { +func tearDownVrf(vrf *infradb.Vrf) (string, bool) { link, err1 := nlink.LinkByName(ctx, path.Base(vrf.Name)) if err1 != nil { log.Printf("LGM : Link %s not found %+v\n", vrf.Name, err1) - return true + return fmt.Sprintf("LGM : Link %s not found %+v\n", vrf.Name, err1), true } if path.Base(vrf.Name) == "GRD" { - return true + return "", true } routingTable := *vrf.Metadata.RoutingTable[0] // Delete the Linux networking artefacts in reverse order @@ -781,24 +790,24 @@ func tearDownVrf(vrf *infradb.Vrf) bool { linkVxlan, linkErr := nlink.LinkByName(ctx, vxlanStr+path.Base(vrf.Name)) if linkErr != nil { log.Printf("LGM : Link vxlan-%s not found %+v\n", vrf.Name, linkErr) - return false + return fmt.Sprintf("LGM : Link vxlan-%s not found %+v\n", vrf.Name, linkErr), false } delerr := nlink.LinkDel(ctx, linkVxlan) if delerr != nil { log.Printf("LGM: Error in delete vxlan %+v\n", delerr) - return false + return fmt.Sprintf("LGM: Error in delete vxlan %+v\n", delerr), false } log.Printf("LGM : Delete vxlan-%s\n", vrf.Name) linkBr, linkbrErr := nlink.LinkByName(ctx, brStr+path.Base(vrf.Name)) if linkbrErr != nil { log.Printf("LGM : Link br-%s not found %+v\n", vrf.Name, linkbrErr) - return false + return fmt.Sprintf("LGM : Link br-%s not found %+v\n", vrf.Name, linkbrErr), false } delerr = nlink.LinkDel(ctx, linkBr) if delerr != nil { log.Printf("LGM: Error in delete br %+v\n", delerr) - return false + return fmt.Sprintf("LGM: Error in delete br %+v\n", delerr), false } log.Printf("LGM : Delete br-%s\n", vrf.Name) } @@ -806,74 +815,74 @@ func tearDownVrf(vrf *infradb.Vrf) bool { flusherr := nlink.RouteFlushTable(ctx, routeTable) if flusherr != nil { log.Printf("LGM: Error in flush table %+v\n", routeTable) - return false + return fmt.Sprintf("LGM: Error in flush table %+v\n", routeTable), false } log.Printf("LGM Executed : ip route flush table %s\n", routeTable) delerr := nlink.LinkDel(ctx, link) if delerr != nil { log.Printf("LGM: Error in delete br %+v\n", delerr) - return false + return fmt.Sprintf("LGM: Error in delete br %+v\n", delerr), false } log.Printf("LGM :link delete %s\n", vrf.Name) - return true + return "", true } // tearDownSvi tears down the svi -func tearDownSvi(svi *infradb.Svi) bool { +func tearDownSvi(svi *infradb.Svi) (string, bool) { BrObj, err := infradb.GetLB(svi.Spec.LogicalBridge) if err != nil { log.Printf("LGM: unable to find key %s and error is %v", svi.Spec.LogicalBridge, err) - return false + return fmt.Sprintf("LGM: unable to find key %s and error is %v", svi.Spec.LogicalBridge, err), false } brIntf, err := nlink.LinkByName(ctx, brTenant) if err != nil { log.Printf("LGM : Failed to get link information for %s: %v\n", brTenant, err) - return false + return fmt.Sprintf("LGM : Failed to get link information for %s: %v\n", brTenant, err), false } if BrObj.Spec.VlanID > math.MaxUint16 { log.Printf("LGM : VlanID %v value passed in Logical Bridge create is greater than 16 bit value\n", BrObj.Spec.VlanID) - return false + return fmt.Sprintf("LGM : VlanID %v value passed in Logical Bridge create is greater than 16 bit value\n", BrObj.Spec.VlanID), false } vid := uint16(BrObj.Spec.VlanID) if err = nlink.BridgeVlanDel(ctx, brIntf, vid, false, false, true, false); err != nil { log.Printf("LGM : Failed to Del VLAN %d to bridge interface %s: %v\n", vid, brTenant, err) - return false + return fmt.Sprintf("LGM : Failed to Del VLAN %d to bridge interface %s: %v\n", vid, brTenant, err), false } log.Printf("LGM Executed : bridge vlan del dev %s vid %d self\n", brTenant, vid) linkSvi := fmt.Sprintf("%+v-%+v", path.Base(svi.Spec.Vrf), BrObj.Spec.VlanID) Intf, err := nlink.LinkByName(ctx, linkSvi) if err != nil { log.Printf("LGM : Failed to get link %s: %v\n", linkSvi, err) - return true + return fmt.Sprintf("LGM : Failed to get link %s: %v\n", linkSvi, err), true } if err = nlink.LinkDel(ctx, Intf); err != nil { log.Printf("LGM : Failed to delete link %s: %v\n", linkSvi, err) - return false + return fmt.Sprintf("LGM : Failed to delete link %s: %v\n", linkSvi, err), false } log.Printf("LGM: Executed ip link delete %s\n", linkSvi) - return true + return "", true } // tearDownBridge tears down the bridge -func tearDownBridge(lb *infradb.LogicalBridge) bool { +func tearDownBridge(lb *infradb.LogicalBridge) (string, bool) { link := fmt.Sprintf("vxlan-%+v", lb.Spec.VlanID) if !reflect.ValueOf(lb.Spec.Vni).IsZero() { Intf, err := nlink.LinkByName(ctx, link) if err != nil { log.Printf("LGM: Failed to get link %s: %v\n", link, err) - return true + return fmt.Sprintf("LGM: Failed to get link %s: %v\n", link, err), true } if err = nlink.LinkDel(ctx, Intf); err != nil { log.Printf("LGM : Failed to delete link %s: %v\n", link, err) - return false + return fmt.Sprintf("LGM: Failed to delete link %s: %v\n", link, err), false } log.Printf("LGM: Executed ip link delete %s", link) - return true + return "", true } - return true + return "", true } // TearDownTenantBridge tears down the bridge diff --git a/pkg/frr/frr.go b/pkg/frr/frr.go index fe25fec..8fa92b8 100644 --- a/pkg/frr/frr.go +++ b/pkg/frr/frr.go @@ -166,6 +166,7 @@ func handlesvi(objectData *eventbus.ObjectData) { log.Printf("GetSvi error: %s %s\n", err, objectData.Name) comp.Name = frrComp comp.CompStatus = common.ComponentStatusError + comp.Details = fmt.Sprintf("GetSvi error: %s %s\n", err, objectData.Name) if comp.Timer == 0 { comp.Timer = 2 * time.Second } else { @@ -182,6 +183,7 @@ func handlesvi(objectData *eventbus.ObjectData) { log.Printf("FRR: Mismatch in resoruce version %+v\n and svi resource version %+v\n", objectData.ResourceVersion, svi.ResourceVersion) comp.Name = frrComp comp.CompStatus = common.ComponentStatusError + comp.Details = fmt.Sprintf("FRR: Mismatch in resoruce version %+v\n and svi resource version %+v\n", objectData.ResourceVersion, svi.ResourceVersion) if comp.Timer == 0 { comp.Timer = 2 * time.Second } else { @@ -201,8 +203,9 @@ func handlesvi(objectData *eventbus.ObjectData) { } } if svi.Status.SviOperStatus != infradb.SviOperStatusToBeDeleted { - status := setUpSvi(svi) + details, status := setUpSvi(svi) comp.Name = frrComp + comp.Details = details if status { comp.CompStatus = common.ComponentStatusSuccess comp.Timer = 0 @@ -224,8 +227,9 @@ func handlesvi(objectData *eventbus.ObjectData) { log.Printf("error in updating svi status: %s\n", err) } } else { - status := tearDownSvi(svi) + details, status := tearDownSvi(svi) comp.Name = frrComp + comp.Details = details if status { comp.CompStatus = common.ComponentStatusSuccess comp.Timer = 0 @@ -259,6 +263,7 @@ func handlevrf(objectData *eventbus.ObjectData) { log.Printf("GetVRF error: %s %s\n", err, objectData.Name) comp.Name = frrComp comp.CompStatus = common.ComponentStatusError + comp.Details = fmt.Sprintf("GetVRF error: %s %s\n", err, objectData.Name) if comp.Timer == 0 { // wait timer is 2 powerof natural numbers ex : 1,2,3... comp.Timer = 2 * time.Second } else { @@ -275,6 +280,7 @@ func handlevrf(objectData *eventbus.ObjectData) { log.Printf("FRR: Mismatch in resoruce version %+v\n and vrf resource version %+v\n", objectData.ResourceVersion, vrf.ResourceVersion) comp.Name = frrComp comp.CompStatus = common.ComponentStatusError + comp.Details = fmt.Sprintf("FRR: Mismatch in resoruce version %+v\n and vrf resource version %+v\n", objectData.ResourceVersion, vrf.ResourceVersion) if comp.Timer == 0 { // wait timer is 2 powerof natural numbers ex : 1,2,3... comp.Timer = 2 * time.Second } else { @@ -296,8 +302,8 @@ func handlevrf(objectData *eventbus.ObjectData) { if vrf.Status.VrfOperStatus != infradb.VrfOperStatusToBeDeleted { detail, status := setUpVrf(vrf) comp.Name = frrComp + comp.Details = detail if status { - comp.Details = detail comp.CompStatus = common.ComponentStatusSuccess comp.Timer = 0 } else { @@ -318,8 +324,9 @@ func handlevrf(objectData *eventbus.ObjectData) { log.Printf("error in updating vrf status: %s\n", err) } } else { - status := tearDownVrf(vrf) + details, status := tearDownVrf(vrf) comp.Name = frrComp + comp.Details = details if status { comp.CompStatus = common.ComponentStatusSuccess comp.Timer = 0 @@ -477,6 +484,8 @@ type BgpVrfCmd struct { } // setUpVrf sets up the vrf +// +//nolint:funlen,gocognit func setUpVrf(vrf *infradb.Vrf) (string, bool) { // This function must not be executed for the vrf representing the GRD if path.Base(vrf.Name) == "GRD" { @@ -488,8 +497,8 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { vniID := fmt.Sprintf("vni %s", strconv.Itoa(int(*vrf.Spec.Vni))) data, err := Frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit-vrf\n exit", vrfName, vniID)) if err != nil || checkFrrResult(data, false) { - log.Printf("FRR: Error Executing frr config t %s %s exit-vrf exit data %v err is %v data is %v\n", vrfName, vniID, data, err, data) - return "", false + log.Printf("FRR: Error Executing frr config t %s %s exit-vrf exit \n Error: is %v data is %v\n", vrfName, vniID, err.Error(), data) + return fmt.Sprintf("FRR: Error Executing frr config t %s %s exit-vrf exit data %v \n Error: %v Data: %v\n", vrfName, vniID, data, err, data), false } err = Frr.Save(ctx) if err != nil { @@ -506,7 +515,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { data, err = Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n router bgp %+v vrf %s\n bgp router-id %s\n no bgp ebgp-requires-policy\n no bgp hard-administrative-reset\n no bgp graceful-restart notification\n address-family ipv4 unicast\n redistribute connected\n redistribute static\n exit-address-family\n address-family l2vpn evpn\n advertise ipv4 unicast\n exit-address-family\n exit", localas, path.Base(vrf.Name), LbiP)) if err != nil || checkFrrResult(data, false) { log.Printf("FRR: Error Executing config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit data %v \n", localas, vrf.Name, LbiP, data) - return "", false + return fmt.Sprintf("FRR: Error Executing config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit data %v \n", localas, vrf.Name, LbiP, data), false } err = Frr.Save(ctx) if err != nil { @@ -531,7 +540,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { cp = cp[3 : len(cp)-3] } else { log.Printf("FRR: unable to get the command %s\n", cmd) - return "", false + return fmt.Sprintf("FRR: unable to get the command %s\n", cmd), false } var bgpL2vpn BgpL2vpnCmd err1 := json.Unmarshal([]byte(fmt.Sprintf("{%v}", cp)), &bgpL2vpn) @@ -556,7 +565,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { cp = cp[5 : len(cp)-5] } else { log.Printf("FRR: unable to get the command \"%s\"\n", cmd) - return "", false + return fmt.Sprintf("FRR: unable to get the command \"%s\"\n", cmd), false } err1 = json.Unmarshal([]byte(fmt.Sprintf("{%v}", cp)), &bgpVrf) if err1 != nil { @@ -576,11 +585,11 @@ func checkFrrResult(cp string, show bool) bool { } // setUpSvi sets up the svi -func setUpSvi(svi *infradb.Svi) bool { +func setUpSvi(svi *infradb.Svi) (string, bool) { BrObj, err := infradb.GetLB(svi.Spec.LogicalBridge) if err != nil { log.Printf("FRR: unable to find key %s and error is %v", svi.Spec.LogicalBridge, err) - return false + return fmt.Sprintf("FRR: unable to find key %s and error is %v", svi.Spec.LogicalBridge, err), false } linkSvi := fmt.Sprintf("%+v-%+v", path.Base(svi.Spec.Vrf), BrObj.Spec.VlanID) if svi.Spec.EnableBgp && !reflect.ValueOf(svi.Spec.GatewayIPs).IsZero() { @@ -599,24 +608,24 @@ func setUpSvi(svi *infradb.Svi) bool { if err != nil || checkFrrResult(data, false) { log.Printf("FRR: Error in conf svi %s %s command %s\n", svi.Name, path.Base(svi.Spec.Vrf), data) - return false + return fmt.Sprintf("FRR: Error in conf svi %s %s command %s\n", svi.Name, path.Base(svi.Spec.Vrf), data), false } err = Frr.Save(ctx) if err != nil { log.Printf("FRR(setUpSvi): Failed to run save command: %v\n", err) } - return true + return "", true } - return true + return "", true } // tearDownSvi tears down svi -func tearDownSvi(svi *infradb.Svi) bool { +func tearDownSvi(svi *infradb.Svi) (string, bool) { // linkSvi := fmt.Sprintf("%+v-%+v", path.Base(svi.Spec.Vrf), strings.Split(path.Base(svi.Spec.LogicalBridge), "vlan")[1]) BrObj, err := infradb.GetLB(svi.Spec.LogicalBridge) if err != nil { log.Printf("LCI: unable to find key %s and error is %v", svi.Spec.LogicalBridge, err) - return false + return fmt.Sprintf("LCI: unable to find key %s and error is %v", svi.Spec.LogicalBridge, err), false } linkSvi := fmt.Sprintf("%+v-%+v", path.Base(svi.Spec.Vrf), BrObj.Spec.VlanID) if svi.Spec.EnableBgp && !reflect.ValueOf(svi.Spec.GatewayIPs).IsZero() { @@ -624,36 +633,33 @@ func tearDownSvi(svi *infradb.Svi) bool { noNeigh := fmt.Sprintf("no neighbor %s peer-group", linkSvi) data, err := Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit", bgpVrfName, noNeigh)) if strings.Contains(data, "Create the peer-group first") { // Trying to delete non exist peer-group return true - return true + return "", true } if err != nil || checkFrrResult(data, false) { log.Printf("FRR: Error in conf Delete vrf/VNI command %s\n", data) - return false + return fmt.Sprintf("FRR: Error in conf Delete vrf/VNI command %s\n", data), false } err = Frr.Save(ctx) if err != nil { log.Printf("FRR(tearDownSvi): Failed to run save command: %v\n", err) } log.Printf("FRR: Executed vtysh -c conf t -c router bgp %+v vrf %s -c no neighbor %s peer-group -c exit\n", localas, path.Base(svi.Spec.Vrf), linkSvi) - return true + return "", true } - return true + return "", true } // tearDownVrf tears down vrf -func tearDownVrf(vrf *infradb.Vrf) bool { +func tearDownVrf(vrf *infradb.Vrf) (string, bool) { // This function must not be executed for the vrf representing the GRD if path.Base(vrf.Name) == "GRD" { - return true + return "", true } data, err := Frr.FrrZebraCmd(ctx, fmt.Sprintf("show vrf %s vni\n", path.Base(vrf.Name))) - if err != nil { - log.Printf("tearDownVrf : failed to run the command") - } - if checkFrrResult(data, true) { - log.Printf("CP FRR %s\n", data) - return true + if err != nil || checkFrrResult(data, true) { + log.Printf("FRR: Error %s\n", data) + return "", true } err = Frr.Save(ctx) if err != nil { @@ -666,11 +672,11 @@ func tearDownVrf(vrf *infradb.Vrf) bool { delCmd2 := fmt.Sprintf("no vrf %s", path.Base(vrf.Name)) data, err = Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd1)) if strings.Contains(data, "Can't find BGP instance") { // Trying to delete non exist VRF return true - return true + return "", true } if err != nil || checkFrrResult(data, false) { log.Printf("FRR: Error %s\n", data) - return false + return fmt.Sprintf("FRR: Error %s\n", data), false } err = Frr.Save(ctx) if err != nil { @@ -678,8 +684,8 @@ func tearDownVrf(vrf *infradb.Vrf) bool { } _, err = Frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd2)) if err != nil { - - return false + log.Printf("FRR: Error %s\n", data) + return fmt.Sprintf("FRR: Error %s\n", data), false } err = Frr.Save(ctx) if err != nil { @@ -687,5 +693,5 @@ func tearDownVrf(vrf *infradb.Vrf) bool { } log.Printf("FRR: Executed vtysh -c conf t -c %s -c %s -c exit\n", delCmd1, delCmd2) } - return true + return "", true } From 5ae39df12fc6e5838be9885852e17b87e156e72a Mon Sep 17 00:00:00 2001 From: Vemula Venkatesh Date: Mon, 30 Sep 2024 13:23:25 +0100 Subject: [PATCH 3/6] fix(evpn): changed the string length in if condition to string compare Signed-off-by: Vemula Venkatesh --- pkg/frr/frr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/frr/frr.go b/pkg/frr/frr.go index 8fa92b8..0d12baf 100644 --- a/pkg/frr/frr.go +++ b/pkg/frr/frr.go @@ -536,7 +536,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { L2vpnCmd := strings.Split(cp, "json") L2vpnCmd = strings.Split(L2vpnCmd[1], hname) cp = L2vpnCmd[0] - if len(cp) != 7 { // Checking CMD o/p + if strings.Compare(cp, "\r\n{}\r\n{\r\n}\r\n") != 0 { // Checking CMD o/p cp = cp[3 : len(cp)-3] } else { log.Printf("FRR: unable to get the command %s\n", cmd) From 1076f6a49dbf9507fa8be12258d2662b6ebdcc73 Mon Sep 17 00:00:00 2001 From: atulpatel261194 Date: Tue, 1 Oct 2024 10:02:57 -0700 Subject: [PATCH 4/6] fix(evpn): report error in comp details review fixes Signed-off-by: atulpatel261194 --- pkg/frr/frr.go | 48 ++++++++++++++++++++---------------------------- pkg/utils/frr.go | 44 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 58 insertions(+), 34 deletions(-) diff --git a/pkg/frr/frr.go b/pkg/frr/frr.go index 0d12baf..b498d0a 100644 --- a/pkg/frr/frr.go +++ b/pkg/frr/frr.go @@ -495,8 +495,9 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { // Configure the vrf in FRR and set up BGP EVPN for it vrfName := fmt.Sprintf("vrf %s", path.Base(vrf.Name)) vniID := fmt.Sprintf("vni %s", strconv.Itoa(int(*vrf.Spec.Vni))) - data, err := Frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit-vrf\n exit", vrfName, vniID)) - if err != nil || checkFrrResult(data, false) { + + data, err := Frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit-vrf\n exit", vrfName, vniID), false) + if err != nil { log.Printf("FRR: Error Executing frr config t %s %s exit-vrf exit \n Error: is %v data is %v\n", vrfName, vniID, err.Error(), data) return fmt.Sprintf("FRR: Error Executing frr config t %s %s exit-vrf exit data %v \n Error: %v Data: %v\n", vrfName, vniID, data, err, data), false } @@ -512,8 +513,8 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { } else { LbiP = fmt.Sprintf("%+v", vrf.Spec.LoopbackIP.IP) } - data, err = Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n router bgp %+v vrf %s\n bgp router-id %s\n no bgp ebgp-requires-policy\n no bgp hard-administrative-reset\n no bgp graceful-restart notification\n address-family ipv4 unicast\n redistribute connected\n redistribute static\n exit-address-family\n address-family l2vpn evpn\n advertise ipv4 unicast\n exit-address-family\n exit", localas, path.Base(vrf.Name), LbiP)) - if err != nil || checkFrrResult(data, false) { + data, err = Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n router bgp %+v vrf %s\n bgp router-id %s\n no bgp ebgp-requires-policy\n no bgp hard-administrative-reset\n no bgp graceful-restart notification\n address-family ipv4 unicast\n redistribute connected\n redistribute static\n exit-address-family\n address-family l2vpn evpn\n advertise ipv4 unicast\n exit-address-family\n exit", localas, path.Base(vrf.Name), LbiP), false) + if err != nil { log.Printf("FRR: Error Executing config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit data %v \n", localas, vrf.Name, LbiP, data) return fmt.Sprintf("FRR: Error Executing config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit data %v \n", localas, vrf.Name, LbiP, data), false } @@ -524,8 +525,8 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { log.Printf("FRR: Executed config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit\n", localas, vrf.Name, LbiP) // Update the vrf with attributes from FRR cmd := fmt.Sprintf("show bgp l2vpn evpn vni %d json", *vrf.Spec.Vni) - cp, err := Frr.FrrBgpCmd(ctx, cmd) - if err != nil || checkFrrResult(cp, true) { + cp, err := Frr.FrrBgpCmd(ctx, cmd, true) + if err != nil { log.Printf("FRR Error-show bgp l2vpn evpn vni %v cp %v", err, cp) } err = Frr.Save(ctx) @@ -548,8 +549,8 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { log.Printf("error-%v", err) } cmd = fmt.Sprintf("show bgp vrf %s json", path.Base(vrf.Name)) - cp, err = Frr.FrrBgpCmd(ctx, cmd) - if err != nil || checkFrrResult(cp, true) { + cp, err = Frr.FrrBgpCmd(ctx, cmd, true) + if err != nil { log.Printf("error-%v", err) } err = Frr.Save(ctx) @@ -579,11 +580,6 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { return "", true } -// checkFrrResult checks the vrf result -func checkFrrResult(cp string, show bool) bool { - return ((show && reflect.ValueOf(cp).IsZero()) || strings.Contains(cp, "warning") || strings.Contains(cp, "unknown") || strings.Contains(cp, "Unknown") || strings.Contains(cp, "Warning") || strings.Contains(cp, "Ambiguous") || strings.Contains(cp, "specified does not exist") || strings.Contains(cp, "Error")) -} - // setUpSvi sets up the svi func setUpSvi(svi *infradb.Svi) (string, bool) { BrObj, err := infradb.GetLB(svi.Spec.LogicalBridge) @@ -604,9 +600,9 @@ func setUpSvi(svi *infradb.Svi) (string, bool) { neighlinkSr := fmt.Sprintf("neighbor %s soft-reconfiguration inbound\n", linkSvi) bgpListen := fmt.Sprintf(" bgp listen range %s peer-group %s\n", svi.Spec.GatewayIPs[0], linkSvi) - data, err := Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s bgp disable-ebgp-connected-route-check\n %s %s %s %s %s %s exit", bgpVrfName, neighlink, neighlinkRe, neighlinkGw, neighlinkOv, neighlinkSr, bgpListen)) + data, err := Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s bgp disable-ebgp-connected-route-check\n %s %s %s %s %s %s exit", bgpVrfName, neighlink, neighlinkRe, neighlinkGw, neighlinkOv, neighlinkSr, bgpListen), false) - if err != nil || checkFrrResult(data, false) { + if err != nil { log.Printf("FRR: Error in conf svi %s %s command %s\n", svi.Name, path.Base(svi.Spec.Vrf), data) return fmt.Sprintf("FRR: Error in conf svi %s %s command %s\n", svi.Name, path.Base(svi.Spec.Vrf), data), false } @@ -631,11 +627,10 @@ func tearDownSvi(svi *infradb.Svi) (string, bool) { if svi.Spec.EnableBgp && !reflect.ValueOf(svi.Spec.GatewayIPs).IsZero() { bgpVrfName := fmt.Sprintf("router bgp %+v vrf %s", localas, path.Base(svi.Spec.Vrf)) noNeigh := fmt.Sprintf("no neighbor %s peer-group", linkSvi) - data, err := Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit", bgpVrfName, noNeigh)) - if strings.Contains(data, "Create the peer-group first") { // Trying to delete non exist peer-group return true - return "", true - } - if err != nil || checkFrrResult(data, false) { + + data, err := Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit", bgpVrfName, noNeigh), false) + + if err != nil { log.Printf("FRR: Error in conf Delete vrf/VNI command %s\n", data) return fmt.Sprintf("FRR: Error in conf Delete vrf/VNI command %s\n", data), false } @@ -656,8 +651,8 @@ func tearDownVrf(vrf *infradb.Vrf) (string, bool) { return "", true } - data, err := Frr.FrrZebraCmd(ctx, fmt.Sprintf("show vrf %s vni\n", path.Base(vrf.Name))) - if err != nil || checkFrrResult(data, true) { + data, err := Frr.FrrZebraCmd(ctx, fmt.Sprintf("show vrf %s vni\n", path.Base(vrf.Name)), true) + if err != nil { log.Printf("FRR: Error %s\n", data) return "", true } @@ -670,11 +665,8 @@ func tearDownVrf(vrf *infradb.Vrf) (string, bool) { log.Printf("FRR Deleted event") delCmd1 := fmt.Sprintf("no router bgp %+v vrf %s", localas, path.Base(vrf.Name)) delCmd2 := fmt.Sprintf("no vrf %s", path.Base(vrf.Name)) - data, err = Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd1)) - if strings.Contains(data, "Can't find BGP instance") { // Trying to delete non exist VRF return true - return "", true - } - if err != nil || checkFrrResult(data, false) { + data, err = Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd1), false) + if err != nil { log.Printf("FRR: Error %s\n", data) return fmt.Sprintf("FRR: Error %s\n", data), false } @@ -682,7 +674,7 @@ func tearDownVrf(vrf *infradb.Vrf) (string, bool) { if err != nil { log.Printf("FRR(tearDownVrf): Failed to run save command: %v\n", err) } - _, err = Frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd2)) + data, err = Frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd2), false) if err != nil { log.Printf("FRR: Error %s\n", data) return fmt.Sprintf("FRR: Error %s\n", data), false diff --git a/pkg/utils/frr.go b/pkg/utils/frr.go index 9829feb..45dabb3 100644 --- a/pkg/utils/frr.go +++ b/pkg/utils/frr.go @@ -7,6 +7,7 @@ package utils import ( "bufio" "context" + "errors" "fmt" "os/exec" "strings" @@ -51,8 +52,8 @@ const ( // Frr represents limited subset of functions from Frr package type Frr interface { TelnetDialAndCommunicate(ctx context.Context, command string, port int) (string, error) - FrrZebraCmd(ctx context.Context, command string) (string, error) - FrrBgpCmd(ctx context.Context, command string) (string, error) + FrrZebraCmd(ctx context.Context, command string, cmdTypeShow bool) (string, error) + FrrBgpCmd(ctx context.Context, command string, cmdTypeShow bool) (string, error) Save(context.Context) error Password(conn *telnet.Conn, delim string) error EnterPrivileged(conn *telnet.Conn) error @@ -115,16 +116,47 @@ func (n *FrrWrapper) ExitPrivileged(conn *telnet.Conn) error { return conn.SkipUntil(">") } +// checkFrrResult checks the vrf result +func checkFrrResult(data string, show bool) bool { + if show && data == "" { + return true + } + // // Trying to delete non exist VRF || Trying to delete non exist peer-group + if strings.Contains(data, "Can't find BGP instance") || strings.Contains(data, "Create the peer-group first") { + return false + } + patterns := []string{"error", "warning", "unknown", "ambiguous", "specified does not exist"} + lowerStr := strings.ToLower(data) + for _, pattern := range patterns { + if strings.Contains(lowerStr, pattern) { + return true + } + } + return false +} + // FrrZebraCmd connects to Zebra telnet with password and runs command -func (n *FrrWrapper) FrrZebraCmd(ctx context.Context, command string) (string, error) { +func (n *FrrWrapper) FrrZebraCmd(ctx context.Context, command string, cmdTypeShow bool) (string, error) { // ports defined here https://docs.frrouting.org/en/latest/setup.html#services - return n.TelnetDialAndCommunicate(ctx, command, zebra) + cmdOutput, cmdError := n.TelnetDialAndCommunicate(ctx, command, zebra) + if cmdError != nil { + return cmdOutput, cmdError + } else if checkFrrResult(cmdOutput, cmdTypeShow) { + return cmdOutput, errors.New("error while running FrrZebraCmd") + } + return cmdOutput, cmdError } // FrrBgpCmd connects to Bgp telnet with password and runs command -func (n *FrrWrapper) FrrBgpCmd(ctx context.Context, command string) (string, error) { +func (n *FrrWrapper) FrrBgpCmd(ctx context.Context, command string, cmdTypeShow bool) (string, error) { // ports defined here https://docs.frrouting.org/en/latest/setup.html#services - return n.TelnetDialAndCommunicate(ctx, command, bgpd) + cmdOutput, cmdError := n.TelnetDialAndCommunicate(ctx, command, bgpd) + if cmdError != nil { + return cmdOutput, cmdError + } else if checkFrrResult(cmdOutput, cmdTypeShow) { + return cmdOutput, errors.New("error while running FrrBgpCmd") + } + return cmdOutput, cmdError } // Save command save the current config to /etc/frr/frr.conf From 3a22a1633efaaa56a505d9b3dc00be95214835d2 Mon Sep 17 00:00:00 2001 From: Vemula Venkatesh Date: Fri, 25 Oct 2024 12:03:36 +0100 Subject: [PATCH 5/6] fix(evpn): frr bug pr review fixes Signed-off-by: Vemula Venkatesh --- pkg/frr/frr.go | 189 ++++++++++++++++++++++--------------------------- 1 file changed, 84 insertions(+), 105 deletions(-) diff --git a/pkg/frr/frr.go b/pkg/frr/frr.go index b498d0a..cb79854 100644 --- a/pkg/frr/frr.go +++ b/pkg/frr/frr.go @@ -11,12 +11,11 @@ import ( "fmt" "log" - "net" "os" "os/exec" "os/user" "path" - "reflect" + "regexp" "strconv" "strings" "time" @@ -35,8 +34,39 @@ const frrComp string = "frr" // replayThreshold time threshold for replay const replayThreshold = 64 * time.Second -// ModulefrrHandler empty structure -type ModulefrrHandler struct{} +// moduleFrrHandler empty structure +type moduleFrrHandler struct{} + +// bgpl2VpnCmd structure +type bgpl2VpnCmd struct { + Vni int + Type string + InKernel string + Rd string + OriginatorIP string + AdvertiseGatewayMacip string + AdvertiseSviMacIP string + AdvertisePip string + SysIP string + SysMac string + Rmac string + ImportRts []string + ExportRts []string +} + +// route empty structure +type route struct{} + +// bgpVrfCmd structure +type bgpVrfCmd struct { + VrfID int + VrfName string + TableVersion uint + RouterID string + DefaultLocPrf uint + LocalAS int + Routes route +} // ModuleFrrActionHandler empty structure type ModuleFrrActionHandler struct { @@ -67,7 +97,7 @@ func NewModuleFrrActionHandlerWithArgs(runningFrrConfFile, basicFrrConfFile, bac } // HandleEvent handles the events -func (h *ModulefrrHandler) HandleEvent(eventType string, objectData *eventbus.ObjectData) { +func (h *moduleFrrHandler) HandleEvent(eventType string, objectData *eventbus.ObjectData) { switch eventType { case "vrf": // "VRF_added": log.Printf("FRR recevied %s %s\n", eventType, objectData.Name) @@ -381,7 +411,7 @@ func subscribeInfradb(config *config.Config) { for _, subscriberConfig := range config.Subscribers { if subscriberConfig.Name == frrComp { for _, eventType := range subscriberConfig.Events { - eb.StartSubscriber(subscriberConfig.Name, eventType, subscriberConfig.Priority, &ModulefrrHandler{}) + eb.StartSubscriber(subscriberConfig.Name, eventType, subscriberConfig.Priority, &moduleFrrHandler{}) } } } @@ -391,8 +421,8 @@ func subscribeInfradb(config *config.Config) { // ctx variable of type context var ctx context.Context -// Frr variable of type utils wrapper -var Frr utils.Frr +// frr variable of type utils wrapper +var frr utils.Frr // Initialize function handles init functionality func Initialize() { @@ -410,7 +440,7 @@ func Initialize() { subscribeInfradb(&config.GlobalConfig) ctx = context.Background() - Frr = utils.NewFrrWrapperWithArgs("localhost", config.GlobalConfig.Tracer) + frr = utils.NewFrrWrapperWithArgs("localhost", config.GlobalConfig.Tracer) // Make sure IPv4 forwarding is enabled. detail, flag := run([]string{"sysctl", "-w", " net.ipv4.ip_forward=1"}, false) @@ -431,58 +461,6 @@ func DeInitialize() { eb.UnsubscribeModule(frrComp) } -// routingTableBusy function checks the routing table -/*func routingTableBusy(table uint32) bool { - cp, err := run([]string{"ip", "route", "show", "table", strconv.Itoa(int(table))}, false) - if err != 0 { - fmt.Println(cp) - return false - } - // fmt.Printf("route table busy %s %s\n",cp,err) - // Table is busy if it exists and contains some routes - return true // reflect.ValueOf(cp).IsZero() && len(cp)!= 0 -}*/ - -// VRF structure -type VRF struct { - Name string - Vni int - RoutingTables []uint32 - Loopback net.IP - // RoutingTables uint32 -} - -// BgpL2vpnCmd structure -type BgpL2vpnCmd struct { - Vni int - Type string - InKernel string - Rd string - OriginatorIP string - AdvertiseGatewayMacip string - AdvertiseSviMacIP string - AdvertisePip string - SysIP string - SysMac string - Rmac string - ImportRts []string - ExportRts []string -} - -// route empty structure -type route struct{} - -// BgpVrfCmd structure -type BgpVrfCmd struct { - VrfID int - VrfName string - TableVersion uint - RouterID string - DefaultLocPrf uint - LocalAS int - Routes route -} - // setUpVrf sets up the vrf // //nolint:funlen,gocognit @@ -491,77 +469,78 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { if path.Base(vrf.Name) == "GRD" { return "", true } - if !reflect.ValueOf(vrf.Spec.Vni).IsZero() { + if *vrf.Spec.Vni != 0 { // Configure the vrf in FRR and set up BGP EVPN for it vrfName := fmt.Sprintf("vrf %s", path.Base(vrf.Name)) vniID := fmt.Sprintf("vni %s", strconv.Itoa(int(*vrf.Spec.Vni))) - data, err := Frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit-vrf\n exit", vrfName, vniID), false) + data, err := frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit-vrf\n exit", vrfName, vniID), false) if err != nil { log.Printf("FRR: Error Executing frr config t %s %s exit-vrf exit \n Error: is %v data is %v\n", vrfName, vniID, err.Error(), data) return fmt.Sprintf("FRR: Error Executing frr config t %s %s exit-vrf exit data %v \n Error: %v Data: %v\n", vrfName, vniID, data, err, data), false } - err = Frr.Save(ctx) + err = frr.Save(ctx) if err != nil { log.Printf("FRR(setUpVrf): Failed to run save command: %v\n", err) } log.Printf("FRR: Executed frr config t %s %s exit-vrf exit\n", vrfName, vniID) - var LbiP string + var lbIP string - if reflect.ValueOf(vrf.Spec.LoopbackIP).IsZero() { - LbiP = "0.0.0.0" + if vrf.Spec.LoopbackIP != nil { + lbIP = "0.0.0.0" } else { - LbiP = fmt.Sprintf("%+v", vrf.Spec.LoopbackIP.IP) + lbIP = fmt.Sprintf("%+v", vrf.Spec.LoopbackIP.IP) } - data, err = Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n router bgp %+v vrf %s\n bgp router-id %s\n no bgp ebgp-requires-policy\n no bgp hard-administrative-reset\n no bgp graceful-restart notification\n address-family ipv4 unicast\n redistribute connected\n redistribute static\n exit-address-family\n address-family l2vpn evpn\n advertise ipv4 unicast\n exit-address-family\n exit", localas, path.Base(vrf.Name), LbiP), false) + data, err = frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n router bgp %+v vrf %s\n bgp router-id %s\n no bgp ebgp-requires-policy\n no bgp hard-administrative-reset\n no bgp graceful-restart notification\n address-family ipv4 unicast\n redistribute connected\n redistribute static\n exit-address-family\n address-family l2vpn evpn\n advertise ipv4 unicast\n exit-address-family\n exit", localas, path.Base(vrf.Name), lbIP), false) if err != nil { - log.Printf("FRR: Error Executing config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit data %v \n", localas, vrf.Name, LbiP, data) - return fmt.Sprintf("FRR: Error Executing config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit data %v \n", localas, vrf.Name, LbiP, data), false + log.Printf("FRR: Error Executing config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit data %v \n", localas, vrf.Name, lbIP, data) + return fmt.Sprintf("FRR: Error Executing config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit data %v \n", localas, vrf.Name, lbIP, data), false } - err = Frr.Save(ctx) + err = frr.Save(ctx) if err != nil { log.Printf("FRR(setUpVrf): Failed to run save command: %v\n", err) } - log.Printf("FRR: Executed config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit\n", localas, vrf.Name, LbiP) + log.Printf("FRR: Executed config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit\n", localas, vrf.Name, lbIP) // Update the vrf with attributes from FRR cmd := fmt.Sprintf("show bgp l2vpn evpn vni %d json", *vrf.Spec.Vni) - cp, err := Frr.FrrBgpCmd(ctx, cmd, true) + cp, err := frr.FrrBgpCmd(ctx, cmd, true) if err != nil { log.Printf("FRR Error-show bgp l2vpn evpn vni %v cp %v", err, cp) } - err = Frr.Save(ctx) + err = frr.Save(ctx) if err != nil { log.Printf("FRR(setUpVrf): Failed to run save command: %v\n", err) } hname, _ := os.Hostname() - L2vpnCmd := strings.Split(cp, "json") - L2vpnCmd = strings.Split(L2vpnCmd[1], hname) - cp = L2vpnCmd[0] - if strings.Compare(cp, "\r\n{}\r\n{\r\n}\r\n") != 0 { // Checking CMD o/p + l2VpnCmd := strings.Split(cp, "json") + l2VpnCmd = strings.Split(l2VpnCmd[1], hname) + cp = l2VpnCmd[0] + if regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cp) { cp = cp[3 : len(cp)-3] } else { log.Printf("FRR: unable to get the command %s\n", cmd) return fmt.Sprintf("FRR: unable to get the command %s\n", cmd), false } - var bgpL2vpn BgpL2vpnCmd + var bgpL2vpn bgpl2VpnCmd err1 := json.Unmarshal([]byte(fmt.Sprintf("{%v}", cp)), &bgpL2vpn) if err1 != nil { log.Printf("error-%v", err) } cmd = fmt.Sprintf("show bgp vrf %s json", path.Base(vrf.Name)) - cp, err = Frr.FrrBgpCmd(ctx, cmd, true) + cp, err = frr.FrrBgpCmd(ctx, cmd, true) if err != nil { log.Printf("error-%v", err) } - err = Frr.Save(ctx) + err = frr.Save(ctx) if err != nil { log.Printf("FRR(setUpVrf): Failed to run save command: %v\n", err) } - BgpCmd := strings.Split(cp, "json") - BgpCmd = strings.Split(BgpCmd[1], hname) - cp = BgpCmd[0] - var bgpVrf BgpVrfCmd + bgpCmd := strings.Split(cp, "json") + bgpCmd = strings.Split(bgpCmd[1], hname) + cp = bgpCmd[0] + + var bgpVrf bgpVrfCmd if len(cp) != 7 { cp = cp[5 : len(cp)-5] } else { @@ -582,31 +561,31 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { // setUpSvi sets up the svi func setUpSvi(svi *infradb.Svi) (string, bool) { - BrObj, err := infradb.GetLB(svi.Spec.LogicalBridge) + brObj, err := infradb.GetLB(svi.Spec.LogicalBridge) if err != nil { log.Printf("FRR: unable to find key %s and error is %v", svi.Spec.LogicalBridge, err) return fmt.Sprintf("FRR: unable to find key %s and error is %v", svi.Spec.LogicalBridge, err), false } - linkSvi := fmt.Sprintf("%+v-%+v", path.Base(svi.Spec.Vrf), BrObj.Spec.VlanID) - if svi.Spec.EnableBgp && !reflect.ValueOf(svi.Spec.GatewayIPs).IsZero() { + linkSvi := fmt.Sprintf("%+v-%+v", path.Base(svi.Spec.Vrf), brObj.Spec.VlanID) + if svi.Spec.EnableBgp && len(svi.Spec.GatewayIPs) != 0 { // gwIP := fmt.Sprintf("%s", svi.Spec.GatewayIPs[0].IP.To4()) gwIP := string(svi.Spec.GatewayIPs[0].IP.To4()) - RemoteAs := fmt.Sprintf("%d", *svi.Spec.RemoteAs) + remoteAs := fmt.Sprintf("%d", *svi.Spec.RemoteAs) bgpVrfName := fmt.Sprintf("router bgp %+v vrf %s\n", localas, path.Base(svi.Spec.Vrf)) neighlink := fmt.Sprintf("neighbor %s peer-group\n", linkSvi) - neighlinkRe := fmt.Sprintf("neighbor %s remote-as %s\n", linkSvi, RemoteAs) + neighlinkRe := fmt.Sprintf("neighbor %s remote-as %s\n", linkSvi, remoteAs) neighlinkGw := fmt.Sprintf("neighbor %s update-source %s\n", linkSvi, gwIP) neighlinkOv := fmt.Sprintf("neighbor %s as-override\n", linkSvi) neighlinkSr := fmt.Sprintf("neighbor %s soft-reconfiguration inbound\n", linkSvi) bgpListen := fmt.Sprintf(" bgp listen range %s peer-group %s\n", svi.Spec.GatewayIPs[0], linkSvi) - data, err := Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s bgp disable-ebgp-connected-route-check\n %s %s %s %s %s %s exit", bgpVrfName, neighlink, neighlinkRe, neighlinkGw, neighlinkOv, neighlinkSr, bgpListen), false) + data, err := frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s bgp disable-ebgp-connected-route-check\n %s %s %s %s %s %s exit", bgpVrfName, neighlink, neighlinkRe, neighlinkGw, neighlinkOv, neighlinkSr, bgpListen), false) if err != nil { log.Printf("FRR: Error in conf svi %s %s command %s\n", svi.Name, path.Base(svi.Spec.Vrf), data) return fmt.Sprintf("FRR: Error in conf svi %s %s command %s\n", svi.Name, path.Base(svi.Spec.Vrf), data), false } - err = Frr.Save(ctx) + err = frr.Save(ctx) if err != nil { log.Printf("FRR(setUpSvi): Failed to run save command: %v\n", err) } @@ -618,23 +597,23 @@ func setUpSvi(svi *infradb.Svi) (string, bool) { // tearDownSvi tears down svi func tearDownSvi(svi *infradb.Svi) (string, bool) { // linkSvi := fmt.Sprintf("%+v-%+v", path.Base(svi.Spec.Vrf), strings.Split(path.Base(svi.Spec.LogicalBridge), "vlan")[1]) - BrObj, err := infradb.GetLB(svi.Spec.LogicalBridge) + brObj, err := infradb.GetLB(svi.Spec.LogicalBridge) if err != nil { log.Printf("LCI: unable to find key %s and error is %v", svi.Spec.LogicalBridge, err) return fmt.Sprintf("LCI: unable to find key %s and error is %v", svi.Spec.LogicalBridge, err), false } - linkSvi := fmt.Sprintf("%+v-%+v", path.Base(svi.Spec.Vrf), BrObj.Spec.VlanID) - if svi.Spec.EnableBgp && !reflect.ValueOf(svi.Spec.GatewayIPs).IsZero() { + linkSvi := fmt.Sprintf("%+v-%+v", path.Base(svi.Spec.Vrf), brObj.Spec.VlanID) + if svi.Spec.EnableBgp && len(svi.Spec.GatewayIPs) != 0 { bgpVrfName := fmt.Sprintf("router bgp %+v vrf %s", localas, path.Base(svi.Spec.Vrf)) noNeigh := fmt.Sprintf("no neighbor %s peer-group", linkSvi) - data, err := Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit", bgpVrfName, noNeigh), false) + data, err := frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit", bgpVrfName, noNeigh), false) if err != nil { log.Printf("FRR: Error in conf Delete vrf/VNI command %s\n", data) return fmt.Sprintf("FRR: Error in conf Delete vrf/VNI command %s\n", data), false } - err = Frr.Save(ctx) + err = frr.Save(ctx) if err != nil { log.Printf("FRR(tearDownSvi): Failed to run save command: %v\n", err) } @@ -651,35 +630,35 @@ func tearDownVrf(vrf *infradb.Vrf) (string, bool) { return "", true } - data, err := Frr.FrrZebraCmd(ctx, fmt.Sprintf("show vrf %s vni\n", path.Base(vrf.Name)), true) + data, err := frr.FrrZebraCmd(ctx, fmt.Sprintf("show vrf %s vni\n", path.Base(vrf.Name)), true) if err != nil { log.Printf("FRR: Error %s\n", data) return "", true } - err = Frr.Save(ctx) + err = frr.Save(ctx) if err != nil { log.Printf("FRR(tearDownVrf): Failed to run save command: %v\n", err) } // Clean up FRR last - if !reflect.ValueOf(vrf.Spec.Vni).IsZero() { + if *vrf.Spec.Vni != 0 { log.Printf("FRR Deleted event") delCmd1 := fmt.Sprintf("no router bgp %+v vrf %s", localas, path.Base(vrf.Name)) delCmd2 := fmt.Sprintf("no vrf %s", path.Base(vrf.Name)) - data, err = Frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd1), false) + data, err = frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd1), false) if err != nil { log.Printf("FRR: Error %s\n", data) return fmt.Sprintf("FRR: Error %s\n", data), false } - err = Frr.Save(ctx) + err = frr.Save(ctx) if err != nil { log.Printf("FRR(tearDownVrf): Failed to run save command: %v\n", err) } - data, err = Frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd2), false) + data, err = frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd2), false) if err != nil { log.Printf("FRR: Error %s\n", data) return fmt.Sprintf("FRR: Error %s\n", data), false } - err = Frr.Save(ctx) + err = frr.Save(ctx) if err != nil { log.Printf("FRR(tearDownVrf): Failed to run save command: %v\n", err) } From 165664c84a08b37d6c6627ed858ce1fcc9de1b34 Mon Sep 17 00:00:00 2001 From: atulpatel261194 Date: Mon, 28 Oct 2024 00:08:27 -0700 Subject: [PATCH 6/6] fix(evpn): fix error handling in frr utils Signed-off-by: atulpatel261194 --- pkg/frr/frr.go | 40 ++++++++++++++++++++-------------------- pkg/utils/frr.go | 9 ++++----- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/pkg/frr/frr.go b/pkg/frr/frr.go index cb79854..afca340 100644 --- a/pkg/frr/frr.go +++ b/pkg/frr/frr.go @@ -474,10 +474,10 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { vrfName := fmt.Sprintf("vrf %s", path.Base(vrf.Name)) vniID := fmt.Sprintf("vni %s", strconv.Itoa(int(*vrf.Spec.Vni))) - data, err := frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit-vrf\n exit", vrfName, vniID), false) + _, err := frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit-vrf\n exit", vrfName, vniID), false) if err != nil { - log.Printf("FRR: Error Executing frr config t %s %s exit-vrf exit \n Error: is %v data is %v\n", vrfName, vniID, err.Error(), data) - return fmt.Sprintf("FRR: Error Executing frr config t %s %s exit-vrf exit data %v \n Error: %v Data: %v\n", vrfName, vniID, data, err, data), false + log.Printf("FRR: Error Executing frr config t %s %s exit-vrf exit \n Error: is%v\n", vrfName, vniID, err) + return fmt.Sprintf("FRR: Error Executing frr config t %s %s exit-vrf exit \n Error: %v \n", vrfName, vniID, err), false } err = frr.Save(ctx) if err != nil { @@ -491,10 +491,10 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { } else { lbIP = fmt.Sprintf("%+v", vrf.Spec.LoopbackIP.IP) } - data, err = frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n router bgp %+v vrf %s\n bgp router-id %s\n no bgp ebgp-requires-policy\n no bgp hard-administrative-reset\n no bgp graceful-restart notification\n address-family ipv4 unicast\n redistribute connected\n redistribute static\n exit-address-family\n address-family l2vpn evpn\n advertise ipv4 unicast\n exit-address-family\n exit", localas, path.Base(vrf.Name), lbIP), false) + _, err = frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n router bgp %+v vrf %s\n bgp router-id %s\n no bgp ebgp-requires-policy\n no bgp hard-administrative-reset\n no bgp graceful-restart notification\n address-family ipv4 unicast\n redistribute connected\n redistribute static\n exit-address-family\n address-family l2vpn evpn\n advertise ipv4 unicast\n exit-address-family\n exit", localas, path.Base(vrf.Name), lbIP), false) if err != nil { - log.Printf("FRR: Error Executing config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit data %v \n", localas, vrf.Name, lbIP, data) - return fmt.Sprintf("FRR: Error Executing config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit data %v \n", localas, vrf.Name, lbIP, data), false + log.Printf("FRR: Error Executing config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit Error %v \n", localas, vrf.Name, lbIP, err) + return fmt.Sprintf("FRR: Error Executing config t bgpVrfName router bgp %+v vrf %s bgp_route_id %s no bgp ebgp-requires-policy exit-vrf exit Error %v \n", localas, vrf.Name, lbIP, err), false } err = frr.Save(ctx) if err != nil { @@ -579,11 +579,11 @@ func setUpSvi(svi *infradb.Svi) (string, bool) { neighlinkSr := fmt.Sprintf("neighbor %s soft-reconfiguration inbound\n", linkSvi) bgpListen := fmt.Sprintf(" bgp listen range %s peer-group %s\n", svi.Spec.GatewayIPs[0], linkSvi) - data, err := frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s bgp disable-ebgp-connected-route-check\n %s %s %s %s %s %s exit", bgpVrfName, neighlink, neighlinkRe, neighlinkGw, neighlinkOv, neighlinkSr, bgpListen), false) + _, err := frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s bgp disable-ebgp-connected-route-check\n %s %s %s %s %s %s exit", bgpVrfName, neighlink, neighlinkRe, neighlinkGw, neighlinkOv, neighlinkSr, bgpListen), false) if err != nil { - log.Printf("FRR: Error in conf svi %s %s command %s\n", svi.Name, path.Base(svi.Spec.Vrf), data) - return fmt.Sprintf("FRR: Error in conf svi %s %s command %s\n", svi.Name, path.Base(svi.Spec.Vrf), data), false + log.Printf("FRR: Error in conf svi %s %s command %s\n", svi.Name, path.Base(svi.Spec.Vrf), err) + return fmt.Sprintf("FRR: Error in conf svi %s %s command %s\n", svi.Name, path.Base(svi.Spec.Vrf), err), false } err = frr.Save(ctx) if err != nil { @@ -607,11 +607,11 @@ func tearDownSvi(svi *infradb.Svi) (string, bool) { bgpVrfName := fmt.Sprintf("router bgp %+v vrf %s", localas, path.Base(svi.Spec.Vrf)) noNeigh := fmt.Sprintf("no neighbor %s peer-group", linkSvi) - data, err := frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit", bgpVrfName, noNeigh), false) + _, err := frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n %s\n exit", bgpVrfName, noNeigh), false) if err != nil { - log.Printf("FRR: Error in conf Delete vrf/VNI command %s\n", data) - return fmt.Sprintf("FRR: Error in conf Delete vrf/VNI command %s\n", data), false + log.Printf("FRR: Error in conf Delete vrf/VNI command %s\n", err) + return fmt.Sprintf("FRR: Error in conf Delete vrf/VNI command %s\n", err), false } err = frr.Save(ctx) if err != nil { @@ -630,9 +630,9 @@ func tearDownVrf(vrf *infradb.Vrf) (string, bool) { return "", true } - data, err := frr.FrrZebraCmd(ctx, fmt.Sprintf("show vrf %s vni\n", path.Base(vrf.Name)), true) + _, err := frr.FrrZebraCmd(ctx, fmt.Sprintf("show vrf %s vni\n", path.Base(vrf.Name)), true) if err != nil { - log.Printf("FRR: Error %s\n", data) + log.Printf("FRR: Error %s\n", err) return "", true } err = frr.Save(ctx) @@ -644,19 +644,19 @@ func tearDownVrf(vrf *infradb.Vrf) (string, bool) { log.Printf("FRR Deleted event") delCmd1 := fmt.Sprintf("no router bgp %+v vrf %s", localas, path.Base(vrf.Name)) delCmd2 := fmt.Sprintf("no vrf %s", path.Base(vrf.Name)) - data, err = frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd1), false) + _, err = frr.FrrBgpCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd1), false) if err != nil { - log.Printf("FRR: Error %s\n", data) - return fmt.Sprintf("FRR: Error %s\n", data), false + log.Printf("FRR: Error %s\n", err) + return fmt.Sprintf("FRR: Error %s\n", err), false } err = frr.Save(ctx) if err != nil { log.Printf("FRR(tearDownVrf): Failed to run save command: %v\n", err) } - data, err = frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd2), false) + _, err = frr.FrrZebraCmd(ctx, fmt.Sprintf("configure terminal\n %s\n exit\n", delCmd2), false) if err != nil { - log.Printf("FRR: Error %s\n", data) - return fmt.Sprintf("FRR: Error %s\n", data), false + log.Printf("FRR: Error %s\n", err) + return fmt.Sprintf("FRR: Error %s\n", err), false } err = frr.Save(ctx) if err != nil { diff --git a/pkg/utils/frr.go b/pkg/utils/frr.go index 45dabb3..28a3ab5 100644 --- a/pkg/utils/frr.go +++ b/pkg/utils/frr.go @@ -7,7 +7,6 @@ package utils import ( "bufio" "context" - "errors" "fmt" "os/exec" "strings" @@ -140,9 +139,9 @@ func (n *FrrWrapper) FrrZebraCmd(ctx context.Context, command string, cmdTypeSho // ports defined here https://docs.frrouting.org/en/latest/setup.html#services cmdOutput, cmdError := n.TelnetDialAndCommunicate(ctx, command, zebra) if cmdError != nil { - return cmdOutput, cmdError + return "", cmdError } else if checkFrrResult(cmdOutput, cmdTypeShow) { - return cmdOutput, errors.New("error while running FrrZebraCmd") + return "", fmt.Errorf("%s", cmdOutput) } return cmdOutput, cmdError } @@ -152,9 +151,9 @@ func (n *FrrWrapper) FrrBgpCmd(ctx context.Context, command string, cmdTypeShow // ports defined here https://docs.frrouting.org/en/latest/setup.html#services cmdOutput, cmdError := n.TelnetDialAndCommunicate(ctx, command, bgpd) if cmdError != nil { - return cmdOutput, cmdError + return "", cmdError } else if checkFrrResult(cmdOutput, cmdTypeShow) { - return cmdOutput, errors.New("error while running FrrBgpCmd") + return "", fmt.Errorf("%s", cmdOutput) } return cmdOutput, cmdError }