Skip to content

Commit 1bb877c

Browse files
committed
AV-232614 Static Route related fixes
1 parent eda0175 commit 1bb877c

File tree

5 files changed

+147
-151
lines changed

5 files changed

+147
-151
lines changed

Diff for: internal/lib/utils.go

+11
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@ import (
1818
"context"
1919
"encoding/json"
2020
"fmt"
21+
"log"
2122
"regexp"
2223
"strings"
2324
"sync"
2425

26+
"github.com/google/uuid"
27+
2528
routev1 "github.com/openshift/api/route/v1"
2629
corev1 "k8s.io/api/core/v1"
2730
networkingv1 "k8s.io/api/networking/v1"
@@ -594,3 +597,11 @@ func (s *LockSet) Unlock(lockName string) {
594597
func GetLockSet() *LockSet {
595598
return &lockSet
596599
}
600+
601+
func Uuid4() string {
602+
id, err := uuid.NewRandom()
603+
if err != nil {
604+
log.Fatal(err)
605+
}
606+
return id.String()
607+
}

Diff for: internal/nodes/avi_model_nodes.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -323,17 +323,15 @@ func (o *AviObjectGraph) GetOrderedNodes() []AviModelNode {
323323
}
324324

325325
type StaticRouteDetails struct {
326-
StartIndex int
327-
Count int
328-
routeID int
326+
Count int
327+
RouteIDPrefix string
329328
}
330329
type AviVrfNode struct {
331330
Name string
332331
StaticRoutes []*avimodels.StaticRoute
333332
CloudConfigCksum uint32
334333
NodeStaticRoutes map[string]StaticRouteDetails
335334
Nodes []string
336-
NodeIds map[int]struct{}
337335
}
338336

339337
func (v *AviVrfNode) GetCheckSum() uint32 {

Diff for: internal/nodes/avi_vrf_translator.go

+83-85
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,64 @@ package nodes
1616

1717
import (
1818
"errors"
19-
"math"
2019
"regexp"
20+
"sort"
2121
"strconv"
2222
"strings"
2323

2424
"github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/internal/lib"
25-
25+
"github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/internal/objects"
2626
"github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/pkg/utils"
2727

2828
"github.com/vmware/alb-sdk/go/models"
2929
v1 "k8s.io/api/core/v1"
3030
)
3131

32+
func GetStaticRoutesForOtherNodes(aviVrfNode *AviVrfNode, nodePrefix string) []*models.StaticRoute {
33+
var staticRouteCopy []*models.StaticRoute
34+
for i := 0; i < len(aviVrfNode.StaticRoutes); i++ {
35+
if *aviVrfNode.StaticRoutes[i].RouteID != "" || !strings.HasPrefix(*aviVrfNode.StaticRoutes[i].RouteID, nodePrefix) {
36+
staticRouteCopy = append(staticRouteCopy, aviVrfNode.StaticRoutes[i])
37+
}
38+
}
39+
return staticRouteCopy
40+
}
41+
42+
func (o *AviObjectGraph) CheckAndDeduplicateRecords(key string, aviVrfNode *AviVrfNode) {
43+
podCidrNextHopMap := make(map[string]string)
44+
hasDuplicateRecords := false
45+
for i := 0; i < len(aviVrfNode.StaticRoutes); i++ {
46+
_, ok := podCidrNextHopMap[*aviVrfNode.StaticRoutes[i].Prefix.IPAddr.Addr]
47+
if ok {
48+
hasDuplicateRecords = true
49+
break
50+
} else {
51+
podCidrNextHopMap[*aviVrfNode.StaticRoutes[i].Prefix.IPAddr.Addr] = *aviVrfNode.StaticRoutes[i].NextHop.Addr
52+
}
53+
}
54+
if !hasDuplicateRecords {
55+
return
56+
}
57+
58+
// Clean VRFCache
59+
aviVrfNode.Nodes = nil
60+
aviVrfNode.StaticRoutes = nil
61+
aviVrfNode.NodeStaticRoutes = nil
62+
63+
// send sorted list of nodes from here.
64+
allNodes := objects.SharedNodeLister().CopyAllObjects()
65+
var nodeKeys []string
66+
for k := range allNodes {
67+
nodeKeys = append(nodeKeys, k)
68+
}
69+
sort.Strings(nodeKeys)
70+
for _, nodeKey := range nodeKeys {
71+
o.BuildVRFGraph(key, aviVrfNode.Name, nodeKey, false, false)
72+
}
73+
}
74+
3275
// BuildVRFGraph : build vrf graph from k8s nodes
33-
func (o *AviObjectGraph) BuildVRFGraph(key, vrfName, nodeName string, deleteFlag bool) error {
76+
func (o *AviObjectGraph) BuildVRFGraph(key, vrfName, nodeName string, deleteFlag bool, deDuplicateRecords bool) error {
3477
o.Lock.Lock()
3578
defer o.Lock.Unlock()
3679
//fetch vrf Node
@@ -45,10 +88,8 @@ func (o *AviObjectGraph) BuildVRFGraph(key, vrfName, nodeName string, deleteFlag
4588
// Each AKO should have single VRF node as it deals with single cluster only.
4689
aviVrfNode := aviVrfNodes[0]
4790

48-
routeid := 1
4991
if len(aviVrfNode.StaticRoutes) == 0 {
5092
aviVrfNode.NodeStaticRoutes = make(map[string]StaticRouteDetails)
51-
aviVrfNode.NodeIds = make(map[int]struct{})
5293
}
5394
var nodeRoutes []*models.StaticRoute
5495
// For new node addition (coming from ingestion layer), nodes static routes will be attahced at the end
@@ -60,19 +101,22 @@ func (o *AviObjectGraph) BuildVRFGraph(key, vrfName, nodeName string, deleteFlag
60101
node, err := utils.GetInformers().NodeInformer.Lister().Get(nodeName)
61102
if err != nil {
62103
utils.AviLog.Errorf("key: %s, Error in fetching node details: %s: %v", key, nodeName, err)
104+
aviVrfNode.StaticRoutes = GetStaticRoutesForOtherNodes(aviVrfNode, lib.GetClusterName()+"-"+nodeStaticRouteDetails.RouteIDPrefix)
105+
processNodeStaticRouteAndNodeDeletion(nodeName, aviVrfNode)
63106
return err
64107
}
108+
var routeIdPrefix string
65109
if ok {
66-
routeid = nodeStaticRouteDetails.routeID
110+
routeIdPrefix = nodeStaticRouteDetails.RouteIDPrefix
67111
} else {
68-
//O(n) for each node. But it will re-use previous index. So used instead of always incrementing index.
69-
routeid = findFreeRouteId(aviVrfNode.NodeIds)
112+
routeIdPrefix = lib.Uuid4()
70113
}
71-
aviVrfNode.NodeIds[routeid] = struct{}{}
72-
nodeRoutes, err = o.addRouteForNode(node, vrfName, routeid, aviVrfNode.NodeIds)
114+
115+
nodeRoutes, err = o.addRouteForNode(node, vrfName, routeIdPrefix)
73116
if err != nil {
74117
utils.AviLog.Errorf("key: %s, Error Adding vrf for node %s: %v", key, nodeName, err)
75-
delete(aviVrfNode.NodeIds, routeid)
118+
aviVrfNode.StaticRoutes = GetStaticRoutesForOtherNodes(aviVrfNode, lib.GetClusterName()+"-"+routeIdPrefix)
119+
processNodeStaticRouteAndNodeDeletion(nodeName, aviVrfNode)
76120
return err
77121
}
78122
if !ok {
@@ -81,93 +125,75 @@ func (o *AviObjectGraph) BuildVRFGraph(key, vrfName, nodeName string, deleteFlag
81125
// node is not present and no overlapping of cidr, append at last
82126
aviVrfNode.StaticRoutes = append(aviVrfNode.StaticRoutes, nodeRoutes...)
83127
nodeStaticRoute := StaticRouteDetails{}
84-
// start index shows at what index of StaticRoutes, nodes routes start (index based zero)
85-
nodeStaticRoute.StartIndex = routeid - 1
86128
nodeStaticRoute.Count = len(nodeRoutes)
87-
nodeStaticRoute.routeID = routeid
129+
nodeStaticRoute.RouteIDPrefix = routeIdPrefix
88130
aviVrfNode.NodeStaticRoutes[nodeName] = nodeStaticRoute
89131
aviVrfNode.Nodes = append(aviVrfNode.Nodes, nodeName)
90132
} else {
91133
if len(nodeRoutes) == 0 {
92-
delete(aviVrfNode.NodeIds, routeid)
134+
//delete all the routes and details of this node
135+
aviVrfNode.StaticRoutes = GetStaticRoutesForOtherNodes(aviVrfNode, lib.GetClusterName()+"-"+routeIdPrefix)
136+
processNodeStaticRouteAndNodeDeletion(nodeName, aviVrfNode)
93137
}
94138
}
95139
} else {
96140
// update case
97-
// Assumption: updated routes (values) for given node will not overlap with other nodes.
141+
// Assumption: updated routes (values) for given node will not overlap with other nodes
98142
// So only updating existing routes of that node.
99143
utils.AviLog.Debugf("key: %s, StaticRoutes before updation/deletion: [%v]", key, utils.Stringify(aviVrfNode.StaticRoutes))
100-
startIndex := nodeStaticRouteDetails.StartIndex
101144
lenNewNodeRoutes := len(nodeRoutes)
102145
diff := lenNewNodeRoutes - nodeStaticRouteDetails.Count
103146

104-
var staticRouteCopy []*models.StaticRoute
105-
copyTill := int(math.Min(float64(startIndex), float64(len(aviVrfNode.StaticRoutes))))
106-
staticRouteCopy = append(staticRouteCopy, aviVrfNode.StaticRoutes[:copyTill]...)
107-
147+
staticRouteCopy := GetStaticRoutesForOtherNodes(aviVrfNode, lib.GetClusterName()+"-"+routeIdPrefix)
108148
staticRouteCopy = append(staticRouteCopy, nodeRoutes...)
109-
110-
copyFrom := int(math.Min(float64(startIndex+nodeStaticRouteDetails.Count), float64(len(aviVrfNode.StaticRoutes))))
111-
staticRouteCopy = append(staticRouteCopy, aviVrfNode.StaticRoutes[copyFrom:]...)
112-
113149
aviVrfNode.StaticRoutes = staticRouteCopy
114150

115151
//if diff is 0, there is no change in number of routes previously exist and newly created.
116152
if diff != 0 {
117-
updateNodeStaticRoutes(aviVrfNode, deleteFlag, nodeName, lenNewNodeRoutes, diff)
153+
//update all the routes of this node
154+
updateNodeStaticRoutes(aviVrfNode, deleteFlag, nodeName, lenNewNodeRoutes)
118155
}
119156
if lenNewNodeRoutes == 0 {
120-
processNodeStaticRouteAndNodeIdDeletion(nodeName, aviVrfNode)
157+
//delete all the routes of this node
158+
processNodeStaticRouteAndNodeDeletion(nodeName, aviVrfNode)
121159
}
122160
utils.AviLog.Debugf("key: %s, StaticRoutes after updation/deletion: [%v]", key, utils.Stringify(aviVrfNode.StaticRoutes))
123161
}
124162
} else {
125-
//delete case
163+
//delete flag is turned on and node is deleted
126164
utils.AviLog.Debugf("key: %s, StaticRoutes before deletion: [%v]", key, utils.Stringify(aviVrfNode.StaticRoutes))
127-
startIndex := nodeStaticRouteDetails.StartIndex
128-
count := nodeStaticRouteDetails.Count
129-
var staticRouteCopy []*models.StaticRoute
130-
updateNodeStaticRoutes(aviVrfNode, deleteFlag, nodeName, 0, -count)
131-
132-
copyTill := int(math.Min(float64(startIndex), float64(len(aviVrfNode.StaticRoutes))))
133-
staticRouteCopy = append(staticRouteCopy, aviVrfNode.StaticRoutes[:copyTill]...)
134-
135-
copyFrom := int(math.Min(float64(startIndex+nodeStaticRouteDetails.Count), float64(len(aviVrfNode.StaticRoutes))))
136-
staticRouteCopy = append(staticRouteCopy, aviVrfNode.StaticRoutes[copyFrom:]...)
137-
138-
aviVrfNode.StaticRoutes = staticRouteCopy
139-
processNodeStaticRouteAndNodeIdDeletion(nodeName, aviVrfNode)
165+
aviVrfNode.StaticRoutes = GetStaticRoutesForOtherNodes(aviVrfNode, lib.GetClusterName()+"-"+nodeStaticRouteDetails.RouteIDPrefix)
166+
processNodeStaticRouteAndNodeDeletion(nodeName, aviVrfNode)
140167
utils.AviLog.Debugf("key: %s, StaticRoutes after deletion: [%v]", key, utils.Stringify(aviVrfNode.StaticRoutes))
141168
}
169+
if deDuplicateRecords {
170+
o.CheckAndDeduplicateRecords(key, aviVrfNode)
171+
}
142172
aviVrfNode.CalculateCheckSum()
143173
utils.AviLog.Infof("key: %s, Added vrf node %s", key, vrfName)
144174
utils.AviLog.Infof("key: %s, Number of static routes %v", key, len(aviVrfNode.StaticRoutes))
145175
utils.AviLog.Debugf("key: %s, vrf node: [%v]", key, utils.Stringify(aviVrfNode))
146176
return nil
147177
}
148-
func processNodeStaticRouteAndNodeIdDeletion(nodeName string, aviVrfNode *AviVrfNode) {
178+
func processNodeStaticRouteAndNodeDeletion(nodeName string, aviVrfNode *AviVrfNode) {
149179
delete(aviVrfNode.NodeStaticRoutes, nodeName)
150-
for nodeId := len(aviVrfNode.NodeIds); nodeId > len(aviVrfNode.StaticRoutes); nodeId-- {
151-
delete(aviVrfNode.NodeIds, nodeId)
152-
}
153-
}
154-
func findFreeRouteId(routeIdList map[int]struct{}) int {
155-
for i := 1; i < math.MaxInt32; i++ {
156-
if _, ok := routeIdList[i]; !ok {
157-
return i
180+
nodesCopy := []string{}
181+
for _, node := range aviVrfNode.Nodes {
182+
if node != nodeName {
183+
nodesCopy = append(nodesCopy, node)
158184
}
159185
}
160-
return -1
186+
aviVrfNode.Nodes = nodesCopy
161187
}
162-
func updateNodeStaticRoutes(aviVrfNode *AviVrfNode, isDelete bool, nodeName string, lenNewNodeRoutes, diff int) {
188+
189+
func updateNodeStaticRoutes(aviVrfNode *AviVrfNode, isDelete bool, nodeNameToUpdate string, lenNewNodeRoutes int) {
163190
//get index of nodename in node array
164191
indexOfNodeUnderUpdation := -1
165192

166193
for i := 0; i < len(aviVrfNode.Nodes); i++ {
167-
if aviVrfNode.Nodes[i] == nodeName {
194+
if aviVrfNode.Nodes[i] == nodeNameToUpdate {
168195
indexOfNodeUnderUpdation = i
169196
if !isDelete {
170-
nodeNameToUpdate := aviVrfNode.Nodes[indexOfNodeUnderUpdation]
171197
nodeDetails := aviVrfNode.NodeStaticRoutes[nodeNameToUpdate]
172198
nodeDetails.Count = lenNewNodeRoutes
173199
aviVrfNode.NodeStaticRoutes[nodeNameToUpdate] = nodeDetails
@@ -176,32 +202,6 @@ func updateNodeStaticRoutes(aviVrfNode *AviVrfNode, isDelete bool, nodeName stri
176202
}
177203
}
178204
if indexOfNodeUnderUpdation != -1 {
179-
clusterName := lib.GetClusterName()
180-
//Change nodemap entries till index
181-
for nodeIndex := len(aviVrfNode.Nodes) - 1; nodeIndex > indexOfNodeUnderUpdation; nodeIndex-- {
182-
nodeNameToUpdate := aviVrfNode.Nodes[nodeIndex]
183-
nodeDetails := aviVrfNode.NodeStaticRoutes[nodeNameToUpdate]
184-
oldStartIndex := nodeDetails.StartIndex
185-
nodeDetails.StartIndex = nodeDetails.StartIndex + diff
186-
nodeDetails.routeID = nodeDetails.StartIndex + 1
187-
aviVrfNode.NodeStaticRoutes[nodeNameToUpdate] = nodeDetails
188-
newRouteId := nodeDetails.routeID
189-
var tempStartIndex int
190-
if isDelete {
191-
tempStartIndex = oldStartIndex
192-
} else {
193-
tempStartIndex = nodeDetails.StartIndex
194-
}
195-
for staticRouteIndex := tempStartIndex; staticRouteIndex < nodeDetails.Count+tempStartIndex; staticRouteIndex++ {
196-
newRouteName := clusterName + "-" + strconv.Itoa(newRouteId)
197-
if staticRouteIndex > (len(aviVrfNode.StaticRoutes)-1) || staticRouteIndex < 0 {
198-
utils.AviLog.Warnf("Some StaticRoutes could not be updated.")
199-
continue
200-
}
201-
aviVrfNode.StaticRoutes[staticRouteIndex].RouteID = &newRouteName
202-
newRouteId++
203-
}
204-
}
205205
// lenNewNodeRoutes will be zero if Node exists without any PodCidr/BloackAffinity attached to it.
206206
if isDelete || lenNewNodeRoutes == 0 {
207207
// now remove nodename from Nodes list
@@ -226,7 +226,7 @@ func findRoutePrefix(nodeRoutes, aviRoutes []*models.StaticRoute, key string) bo
226226
return false
227227
}
228228

229-
func (o *AviObjectGraph) addRouteForNode(node *v1.Node, vrfName string, routeid int, routeIdList map[int]struct{}) ([]*models.StaticRoute, error) {
229+
func (o *AviObjectGraph) addRouteForNode(node *v1.Node, vrfName string, routeIdPrefix string) ([]*models.StaticRoute, error) {
230230
var nodeIP, nodeIP6 string
231231
var nodeRoutes []*models.StaticRoute
232232

@@ -243,7 +243,7 @@ func (o *AviObjectGraph) addRouteForNode(node *v1.Node, vrfName string, routeid
243243
utils.AviLog.Errorf("Error in fetching Pod CIDR for %v: %s", node.ObjectMeta.Name, err.Error())
244244
return nil, errors.New("podcidr not found")
245245
}
246-
for _, podCIDR := range podCIDRs {
246+
for index, podCIDR := range podCIDRs {
247247
podCIDRAndMask := strings.Split(podCIDR, "/")
248248
if len(podCIDRAndMask) != 2 {
249249
utils.AviLog.Errorf("Error in splitting Pod CIDR for %v", node.ObjectMeta.Name)
@@ -273,7 +273,7 @@ func (o *AviObjectGraph) addRouteForNode(node *v1.Node, vrfName string, routeid
273273
continue
274274
}
275275
mask32 := int32(mask)
276-
routeIDString := clusterName + "-" + strconv.Itoa(routeid)
276+
routeIDString := clusterName + "-" + routeIdPrefix + "-" + strconv.Itoa(index)
277277
nodeRoute := models.StaticRoute{
278278
RouteID: &routeIDString,
279279
Prefix: &models.IPAddrPrefix{
@@ -291,8 +291,6 @@ func (o *AviObjectGraph) addRouteForNode(node *v1.Node, vrfName string, routeid
291291
}
292292

293293
nodeRoutes = append(nodeRoutes, &nodeRoute)
294-
routeIdList[routeid] = struct{}{}
295-
routeid++
296294
}
297295
return nodeRoutes, nil
298296
}

Diff for: internal/nodes/dequeue_ingestion.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ func processNodeObj(key, nodename string, sharedQueue *utils.WorkerQueue, fullsy
884884
}
885885
aviModelGraph := aviModel.(*AviObjectGraph)
886886
aviModelGraph.IsVrf = true
887-
err = aviModelGraph.BuildVRFGraph(key, vrfcontext, nodename, deleteFlag)
887+
err = aviModelGraph.BuildVRFGraph(key, vrfcontext, nodename, deleteFlag, true)
888888
if err != nil {
889889
utils.AviLog.Errorf("key: %s, msg: Error creating vrf graph: %v", key, err)
890890
return

0 commit comments

Comments
 (0)