Skip to content

Commit 36bf02d

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

File tree

4 files changed

+126
-145
lines changed

4 files changed

+126
-145
lines changed

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+
}

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 {

internal/nodes/avi_vrf_translator.go

+63-80
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,11 @@ package nodes
1616

1717
import (
1818
"errors"
19-
"math"
2019
"regexp"
2120
"strconv"
2221
"strings"
2322

2423
"github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/internal/lib"
25-
2624
"github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/pkg/utils"
2725

2826
"github.com/vmware/alb-sdk/go/models"
@@ -45,10 +43,8 @@ func (o *AviObjectGraph) BuildVRFGraph(key, vrfName, nodeName string, deleteFlag
4543
// Each AKO should have single VRF node as it deals with single cluster only.
4644
aviVrfNode := aviVrfNodes[0]
4745

48-
routeid := 1
4946
if len(aviVrfNode.StaticRoutes) == 0 {
5047
aviVrfNode.NodeStaticRoutes = make(map[string]StaticRouteDetails)
51-
aviVrfNode.NodeIds = make(map[int]struct{})
5248
}
5349
var nodeRoutes []*models.StaticRoute
5450
// For new node addition (coming from ingestion layer), nodes static routes will be attahced at the end
@@ -60,19 +56,36 @@ func (o *AviObjectGraph) BuildVRFGraph(key, vrfName, nodeName string, deleteFlag
6056
node, err := utils.GetInformers().NodeInformer.Lister().Get(nodeName)
6157
if err != nil {
6258
utils.AviLog.Errorf("key: %s, Error in fetching node details: %s: %v", key, nodeName, err)
59+
var staticRouteCopy []*models.StaticRoute
60+
for i := 0; i < len(aviVrfNode.StaticRoutes); i++ {
61+
if !strings.HasPrefix(*aviVrfNode.StaticRoutes[i].RouteID, nodeStaticRouteDetails.RouteIDPrefix) {
62+
staticRouteCopy = append(staticRouteCopy, aviVrfNode.StaticRoutes[i])
63+
}
64+
}
65+
aviVrfNode.StaticRoutes = staticRouteCopy
66+
processNodeStaticRouteAndNodeDeletion(nodeName, aviVrfNode)
6367
return err
6468
}
69+
var routeIdPrefix string
6570
if ok {
66-
routeid = nodeStaticRouteDetails.routeID
71+
routeIdPrefix = nodeStaticRouteDetails.RouteIDPrefix
6772
} 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)
73+
routeIdPrefix = lib.Uuid4()
7074
}
71-
aviVrfNode.NodeIds[routeid] = struct{}{}
72-
nodeRoutes, err = o.addRouteForNode(node, vrfName, routeid, aviVrfNode.NodeIds)
75+
76+
nodeRoutes, err = o.addRouteForNode(node, vrfName, routeIdPrefix)
7377
if err != nil {
7478
utils.AviLog.Errorf("key: %s, Error Adding vrf for node %s: %v", key, nodeName, err)
75-
delete(aviVrfNode.NodeIds, routeid)
79+
80+
//delete all the routes of this node
81+
var staticRouteCopy []*models.StaticRoute
82+
for i := 0; i < len(aviVrfNode.StaticRoutes); i++ {
83+
if !strings.HasPrefix(*aviVrfNode.StaticRoutes[i].RouteID, lib.GetClusterName() + "-" +routeIdPrefix) {
84+
staticRouteCopy = append(staticRouteCopy, aviVrfNode.StaticRoutes[i])
85+
}
86+
}
87+
aviVrfNode.StaticRoutes = staticRouteCopy
88+
processNodeStaticRouteAndNodeDeletion(nodeName, aviVrfNode)
7689
return err
7790
}
7891
if !ok {
@@ -81,62 +94,64 @@ func (o *AviObjectGraph) BuildVRFGraph(key, vrfName, nodeName string, deleteFlag
8194
// node is not present and no overlapping of cidr, append at last
8295
aviVrfNode.StaticRoutes = append(aviVrfNode.StaticRoutes, nodeRoutes...)
8396
nodeStaticRoute := StaticRouteDetails{}
84-
// start index shows at what index of StaticRoutes, nodes routes start (index based zero)
85-
nodeStaticRoute.StartIndex = routeid - 1
8697
nodeStaticRoute.Count = len(nodeRoutes)
87-
nodeStaticRoute.routeID = routeid
98+
nodeStaticRoute.RouteIDPrefix = routeIdPrefix
8899
aviVrfNode.NodeStaticRoutes[nodeName] = nodeStaticRoute
89100
aviVrfNode.Nodes = append(aviVrfNode.Nodes, nodeName)
90101
} else {
91102
if len(nodeRoutes) == 0 {
92-
delete(aviVrfNode.NodeIds, routeid)
103+
//delete all the routes and details of this node
104+
var staticRouteCopy []*models.StaticRoute
105+
for i := 0; i < len(aviVrfNode.StaticRoutes); i++ {
106+
if !strings.HasPrefix(*aviVrfNode.StaticRoutes[i].RouteID, lib.GetClusterName() + "-" + routeIdPrefix) {
107+
staticRouteCopy = append(staticRouteCopy, aviVrfNode.StaticRoutes[i])
108+
}
109+
}
110+
aviVrfNode.StaticRoutes = staticRouteCopy
111+
processNodeStaticRouteAndNodeDeletion(nodeName, aviVrfNode)
93112
}
94113
}
95114
} else {
96115
// update case
97-
// Assumption: updated routes (values) for given node will not overlap with other nodes.
116+
// Assumption: updated routes (values) for given node will not overlap with other nodes
98117
// So only updating existing routes of that node.
99118
utils.AviLog.Debugf("key: %s, StaticRoutes before updation/deletion: [%v]", key, utils.Stringify(aviVrfNode.StaticRoutes))
100-
startIndex := nodeStaticRouteDetails.StartIndex
101119
lenNewNodeRoutes := len(nodeRoutes)
102120
diff := lenNewNodeRoutes - nodeStaticRouteDetails.Count
103121

104122
var staticRouteCopy []*models.StaticRoute
105-
copyTill := int(math.Min(float64(startIndex), float64(len(aviVrfNode.StaticRoutes))))
106-
staticRouteCopy = append(staticRouteCopy, aviVrfNode.StaticRoutes[:copyTill]...)
123+
for i := 0; i < len(aviVrfNode.StaticRoutes); i++ {
124+
if !strings.HasPrefix(*aviVrfNode.StaticRoutes[i].RouteID, lib.GetClusterName() + "-" + routeIdPrefix) {
125+
staticRouteCopy = append(staticRouteCopy, aviVrfNode.StaticRoutes[i])
126+
}
127+
}
107128

108129
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-
113130
aviVrfNode.StaticRoutes = staticRouteCopy
114131

115132
//if diff is 0, there is no change in number of routes previously exist and newly created.
116133
if diff != 0 {
117-
updateNodeStaticRoutes(aviVrfNode, deleteFlag, nodeName, lenNewNodeRoutes, diff)
134+
//update all the routes of this node
135+
updateNodeStaticRoutes(aviVrfNode, deleteFlag, nodeName, lenNewNodeRoutes)
118136
}
119137
if lenNewNodeRoutes == 0 {
120-
processNodeStaticRouteAndNodeIdDeletion(nodeName, aviVrfNode)
138+
//delete all the routes of this node
139+
processNodeStaticRouteAndNodeDeletion(nodeName, aviVrfNode)
121140
}
122141
utils.AviLog.Debugf("key: %s, StaticRoutes after updation/deletion: [%v]", key, utils.Stringify(aviVrfNode.StaticRoutes))
123142
}
124143
} else {
125-
//delete case
144+
//delete flag is turned on and node is deleted
126145
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:]...)
137146

147+
var staticRouteCopy []*models.StaticRoute
148+
for i := 0; i < len(aviVrfNode.StaticRoutes); i++ {
149+
if !ok || !strings.HasPrefix(*aviVrfNode.StaticRoutes[i].RouteID, lib.GetClusterName() + "-" + nodeStaticRouteDetails.RouteIDPrefix) {
150+
staticRouteCopy = append(staticRouteCopy, aviVrfNode.StaticRoutes[i])
151+
}
152+
}
138153
aviVrfNode.StaticRoutes = staticRouteCopy
139-
processNodeStaticRouteAndNodeIdDeletion(nodeName, aviVrfNode)
154+
processNodeStaticRouteAndNodeDeletion(nodeName, aviVrfNode)
140155
utils.AviLog.Debugf("key: %s, StaticRoutes after deletion: [%v]", key, utils.Stringify(aviVrfNode.StaticRoutes))
141156
}
142157
aviVrfNode.CalculateCheckSum()
@@ -145,29 +160,25 @@ func (o *AviObjectGraph) BuildVRFGraph(key, vrfName, nodeName string, deleteFlag
145160
utils.AviLog.Debugf("key: %s, vrf node: [%v]", key, utils.Stringify(aviVrfNode))
146161
return nil
147162
}
148-
func processNodeStaticRouteAndNodeIdDeletion(nodeName string, aviVrfNode *AviVrfNode) {
163+
func processNodeStaticRouteAndNodeDeletion(nodeName string, aviVrfNode *AviVrfNode) {
149164
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
165+
nodesCopy := []string{}
166+
for _, node := range aviVrfNode.Nodes {
167+
if node != nodeName {
168+
nodesCopy = append(nodesCopy, node)
158169
}
159170
}
160-
return -1
171+
aviVrfNode.Nodes = nodesCopy
161172
}
162-
func updateNodeStaticRoutes(aviVrfNode *AviVrfNode, isDelete bool, nodeName string, lenNewNodeRoutes, diff int) {
173+
174+
func updateNodeStaticRoutes(aviVrfNode *AviVrfNode, isDelete bool, nodeNameToUpdate string, lenNewNodeRoutes int) {
163175
//get index of nodename in node array
164176
indexOfNodeUnderUpdation := -1
165177

166178
for i := 0; i < len(aviVrfNode.Nodes); i++ {
167-
if aviVrfNode.Nodes[i] == nodeName {
179+
if aviVrfNode.Nodes[i] == nodeNameToUpdate {
168180
indexOfNodeUnderUpdation = i
169181
if !isDelete {
170-
nodeNameToUpdate := aviVrfNode.Nodes[indexOfNodeUnderUpdation]
171182
nodeDetails := aviVrfNode.NodeStaticRoutes[nodeNameToUpdate]
172183
nodeDetails.Count = lenNewNodeRoutes
173184
aviVrfNode.NodeStaticRoutes[nodeNameToUpdate] = nodeDetails
@@ -176,32 +187,6 @@ func updateNodeStaticRoutes(aviVrfNode *AviVrfNode, isDelete bool, nodeName stri
176187
}
177188
}
178189
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-
}
205190
// lenNewNodeRoutes will be zero if Node exists without any PodCidr/BloackAffinity attached to it.
206191
if isDelete || lenNewNodeRoutes == 0 {
207192
// now remove nodename from Nodes list
@@ -226,7 +211,7 @@ func findRoutePrefix(nodeRoutes, aviRoutes []*models.StaticRoute, key string) bo
226211
return false
227212
}
228213

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

@@ -243,7 +228,7 @@ func (o *AviObjectGraph) addRouteForNode(node *v1.Node, vrfName string, routeid
243228
utils.AviLog.Errorf("Error in fetching Pod CIDR for %v: %s", node.ObjectMeta.Name, err.Error())
244229
return nil, errors.New("podcidr not found")
245230
}
246-
for _, podCIDR := range podCIDRs {
231+
for index, podCIDR := range podCIDRs {
247232
podCIDRAndMask := strings.Split(podCIDR, "/")
248233
if len(podCIDRAndMask) != 2 {
249234
utils.AviLog.Errorf("Error in splitting Pod CIDR for %v", node.ObjectMeta.Name)
@@ -273,7 +258,7 @@ func (o *AviObjectGraph) addRouteForNode(node *v1.Node, vrfName string, routeid
273258
continue
274259
}
275260
mask32 := int32(mask)
276-
routeIDString := clusterName + "-" + strconv.Itoa(routeid)
261+
routeIDString := clusterName + "-" + routeIdPrefix + "-" + strconv.Itoa(index)
277262
nodeRoute := models.StaticRoute{
278263
RouteID: &routeIDString,
279264
Prefix: &models.IPAddrPrefix{
@@ -291,8 +276,6 @@ func (o *AviObjectGraph) addRouteForNode(node *v1.Node, vrfName string, routeid
291276
}
292277

293278
nodeRoutes = append(nodeRoutes, &nodeRoute)
294-
routeIdList[routeid] = struct{}{}
295-
routeid++
296279
}
297280
return nodeRoutes, nil
298281
}

0 commit comments

Comments
 (0)