@@ -16,19 +16,79 @@ package nodes
16
16
17
17
import (
18
18
"errors"
19
- "math"
20
19
"regexp"
20
+ "sort"
21
21
"strconv"
22
22
"strings"
23
23
24
24
"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"
26
26
"github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/pkg/utils"
27
27
28
28
"github.com/vmware/alb-sdk/go/models"
29
29
v1 "k8s.io/api/core/v1"
30
30
)
31
31
32
+ func GetStaticRoutesForOtherNodes (aviVrfNode * AviVrfNode , routeId string ) []* models.StaticRoute {
33
+ var staticRouteCopy []* models.StaticRoute
34
+ nodePrefix := lib .GetClusterName () + "-" + routeId
35
+ for i := 0 ; i < len (aviVrfNode .StaticRoutes ); i ++ {
36
+ if routeId == "" || ! strings .HasPrefix (* aviVrfNode .StaticRoutes [i ].RouteID , nodePrefix ) {
37
+ staticRouteCopy = append (staticRouteCopy , aviVrfNode .StaticRoutes [i ])
38
+ }
39
+ }
40
+ return staticRouteCopy
41
+ }
42
+
43
+ func (o * AviObjectGraph ) CheckAndDeduplicateRecords (key string ) {
44
+ aviVrfNodes := o .GetAviVRF ()
45
+ if len (aviVrfNodes ) == 0 {
46
+ return
47
+ }
48
+ // Each AKO should have single VRF node as it deals with single cluster only.
49
+ aviVrfNode := aviVrfNodes [0 ]
50
+
51
+ podCidrNextHopMap := make (map [string ]string )
52
+ hasDuplicateRecords := false
53
+ // Check if duplicate records for staticroutes exist
54
+ for i := 0 ; i < len (aviVrfNode .StaticRoutes ); i ++ {
55
+ _ , ok := podCidrNextHopMap [* aviVrfNode .StaticRoutes [i ].Prefix .IPAddr .Addr ]
56
+ if ok {
57
+ utils .AviLog .Debug ("VRFContext has duplicate records." )
58
+ hasDuplicateRecords = true
59
+ break
60
+ } else {
61
+ podCidrNextHopMap [* aviVrfNode .StaticRoutes [i ].Prefix .IPAddr .Addr ] = * aviVrfNode .StaticRoutes [i ].NextHop .Addr
62
+ }
63
+ }
64
+ if ! hasDuplicateRecords {
65
+ return
66
+ }
67
+
68
+ utils .AviLog .Debug ("Starting deduplication of records in VRFContext" )
69
+
70
+ o .Lock .Lock ()
71
+ // Clean VRFCache
72
+ aviVrfNode .Nodes = nil
73
+ aviVrfNode .StaticRoutes = nil
74
+ aviVrfNode .NodeStaticRoutes = nil
75
+
76
+ o .Lock .Unlock ()
77
+
78
+ // send sorted list of nodes from here.
79
+ allNodes := objects .SharedNodeLister ().CopyAllObjects ()
80
+ var nodeNames []string
81
+ for k := range allNodes {
82
+ nodeNames = append (nodeNames , k )
83
+ }
84
+ sort .Strings (nodeNames )
85
+ for _ , nodeKey := range nodeNames {
86
+ o .BuildVRFGraph (key , aviVrfNode .Name , nodeKey , false )
87
+ }
88
+
89
+ utils .AviLog .Debug ("Deduplication of records in VRFContext finished" )
90
+ }
91
+
32
92
// BuildVRFGraph : build vrf graph from k8s nodes
33
93
func (o * AviObjectGraph ) BuildVRFGraph (key , vrfName , nodeName string , deleteFlag bool ) error {
34
94
o .Lock .Lock ()
@@ -45,10 +105,8 @@ func (o *AviObjectGraph) BuildVRFGraph(key, vrfName, nodeName string, deleteFlag
45
105
// Each AKO should have single VRF node as it deals with single cluster only.
46
106
aviVrfNode := aviVrfNodes [0 ]
47
107
48
- routeid := 1
49
108
if len (aviVrfNode .StaticRoutes ) == 0 {
50
109
aviVrfNode .NodeStaticRoutes = make (map [string ]StaticRouteDetails )
51
- aviVrfNode .NodeIds = make (map [int ]struct {})
52
110
}
53
111
var nodeRoutes []* models.StaticRoute
54
112
// For new node addition (coming from ingestion layer), nodes static routes will be attahced at the end
@@ -60,19 +118,22 @@ func (o *AviObjectGraph) BuildVRFGraph(key, vrfName, nodeName string, deleteFlag
60
118
node , err := utils .GetInformers ().NodeInformer .Lister ().Get (nodeName )
61
119
if err != nil {
62
120
utils .AviLog .Errorf ("key: %s, Error in fetching node details: %s: %v" , key , nodeName , err )
121
+ aviVrfNode .StaticRoutes = GetStaticRoutesForOtherNodes (aviVrfNode , nodeStaticRouteDetails .RouteIDPrefix )
122
+ processNodeStaticRouteAndNodeDeletion (nodeName , aviVrfNode )
63
123
return err
64
124
}
125
+ var routeIdPrefix string
65
126
if ok {
66
- routeid = nodeStaticRouteDetails .routeID
127
+ routeIdPrefix = nodeStaticRouteDetails .RouteIDPrefix
67
128
} 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 )
129
+ routeIdPrefix = lib .Uuid4 ()
70
130
}
71
- aviVrfNode . NodeIds [ routeid ] = struct {}{}
72
- nodeRoutes , err = o .addRouteForNode (node , vrfName , routeid , aviVrfNode . NodeIds )
131
+
132
+ nodeRoutes , err = o .addRouteForNode (node , vrfName , routeIdPrefix )
73
133
if err != nil {
74
134
utils .AviLog .Errorf ("key: %s, Error Adding vrf for node %s: %v" , key , nodeName , err )
75
- delete (aviVrfNode .NodeIds , routeid )
135
+ aviVrfNode .StaticRoutes = GetStaticRoutesForOtherNodes (aviVrfNode , routeIdPrefix )
136
+ processNodeStaticRouteAndNodeDeletion (nodeName , aviVrfNode )
76
137
return err
77
138
}
78
139
if ! ok {
@@ -81,62 +142,45 @@ func (o *AviObjectGraph) BuildVRFGraph(key, vrfName, nodeName string, deleteFlag
81
142
// node is not present and no overlapping of cidr, append at last
82
143
aviVrfNode .StaticRoutes = append (aviVrfNode .StaticRoutes , nodeRoutes ... )
83
144
nodeStaticRoute := StaticRouteDetails {}
84
- // start index shows at what index of StaticRoutes, nodes routes start (index based zero)
85
- nodeStaticRoute .StartIndex = routeid - 1
86
145
nodeStaticRoute .Count = len (nodeRoutes )
87
- nodeStaticRoute .routeID = routeid
146
+ nodeStaticRoute .RouteIDPrefix = routeIdPrefix
88
147
aviVrfNode .NodeStaticRoutes [nodeName ] = nodeStaticRoute
89
148
aviVrfNode .Nodes = append (aviVrfNode .Nodes , nodeName )
90
149
} else {
91
150
if len (nodeRoutes ) == 0 {
92
- delete (aviVrfNode .NodeIds , routeid )
151
+ //delete all the routes and details of this node
152
+ aviVrfNode .StaticRoutes = GetStaticRoutesForOtherNodes (aviVrfNode , routeIdPrefix )
153
+ processNodeStaticRouteAndNodeDeletion (nodeName , aviVrfNode )
93
154
}
94
155
}
95
156
} else {
96
157
// update case
97
- // Assumption: updated routes (values) for given node will not overlap with other nodes.
158
+ // Assumption: updated routes (values) for given node will not overlap with other nodes
98
159
// So only updating existing routes of that node.
99
160
utils .AviLog .Debugf ("key: %s, StaticRoutes before updation/deletion: [%v]" , key , utils .Stringify (aviVrfNode .StaticRoutes ))
100
- startIndex := nodeStaticRouteDetails .StartIndex
101
161
lenNewNodeRoutes := len (nodeRoutes )
102
162
diff := lenNewNodeRoutes - nodeStaticRouteDetails .Count
103
163
104
- var staticRouteCopy []* models.StaticRoute
105
- copyTill := int (math .Min (float64 (startIndex ), float64 (len (aviVrfNode .StaticRoutes ))))
106
- staticRouteCopy = append (staticRouteCopy , aviVrfNode .StaticRoutes [:copyTill ]... )
107
-
164
+ staticRouteCopy := GetStaticRoutesForOtherNodes (aviVrfNode , routeIdPrefix )
108
165
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
-
113
166
aviVrfNode .StaticRoutes = staticRouteCopy
114
167
115
168
//if diff is 0, there is no change in number of routes previously exist and newly created.
116
169
if diff != 0 {
117
- updateNodeStaticRoutes (aviVrfNode , deleteFlag , nodeName , lenNewNodeRoutes , diff )
170
+ //update all the routes of this node
171
+ updateNodeStaticRoutes (aviVrfNode , deleteFlag , nodeName , lenNewNodeRoutes )
118
172
}
119
173
if lenNewNodeRoutes == 0 {
120
- processNodeStaticRouteAndNodeIdDeletion (nodeName , aviVrfNode )
174
+ //delete all the routes of this node
175
+ processNodeStaticRouteAndNodeDeletion (nodeName , aviVrfNode )
121
176
}
122
177
utils .AviLog .Debugf ("key: %s, StaticRoutes after updation/deletion: [%v]" , key , utils .Stringify (aviVrfNode .StaticRoutes ))
123
178
}
124
179
} else {
125
- //delete case
180
+ //delete flag is turned on and node is deleted
126
181
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 )
182
+ aviVrfNode .StaticRoutes = GetStaticRoutesForOtherNodes (aviVrfNode , nodeStaticRouteDetails .RouteIDPrefix )
183
+ processNodeStaticRouteAndNodeDeletion (nodeName , aviVrfNode )
140
184
utils .AviLog .Debugf ("key: %s, StaticRoutes after deletion: [%v]" , key , utils .Stringify (aviVrfNode .StaticRoutes ))
141
185
}
142
186
aviVrfNode .CalculateCheckSum ()
@@ -145,29 +189,25 @@ func (o *AviObjectGraph) BuildVRFGraph(key, vrfName, nodeName string, deleteFlag
145
189
utils .AviLog .Debugf ("key: %s, vrf node: [%v]" , key , utils .Stringify (aviVrfNode ))
146
190
return nil
147
191
}
148
- func processNodeStaticRouteAndNodeIdDeletion (nodeName string , aviVrfNode * AviVrfNode ) {
192
+ func processNodeStaticRouteAndNodeDeletion (nodeName string , aviVrfNode * AviVrfNode ) {
149
193
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
194
+ nodesCopy := []string {}
195
+ for _ , node := range aviVrfNode .Nodes {
196
+ if node != nodeName {
197
+ nodesCopy = append (nodesCopy , node )
158
198
}
159
199
}
160
- return - 1
200
+ aviVrfNode . Nodes = nodesCopy
161
201
}
162
- func updateNodeStaticRoutes (aviVrfNode * AviVrfNode , isDelete bool , nodeName string , lenNewNodeRoutes , diff int ) {
202
+
203
+ func updateNodeStaticRoutes (aviVrfNode * AviVrfNode , isDelete bool , nodeNameToUpdate string , lenNewNodeRoutes int ) {
163
204
//get index of nodename in node array
164
205
indexOfNodeUnderUpdation := - 1
165
206
166
207
for i := 0 ; i < len (aviVrfNode .Nodes ); i ++ {
167
- if aviVrfNode .Nodes [i ] == nodeName {
208
+ if aviVrfNode .Nodes [i ] == nodeNameToUpdate {
168
209
indexOfNodeUnderUpdation = i
169
210
if ! isDelete {
170
- nodeNameToUpdate := aviVrfNode .Nodes [indexOfNodeUnderUpdation ]
171
211
nodeDetails := aviVrfNode .NodeStaticRoutes [nodeNameToUpdate ]
172
212
nodeDetails .Count = lenNewNodeRoutes
173
213
aviVrfNode .NodeStaticRoutes [nodeNameToUpdate ] = nodeDetails
@@ -176,32 +216,6 @@ func updateNodeStaticRoutes(aviVrfNode *AviVrfNode, isDelete bool, nodeName stri
176
216
}
177
217
}
178
218
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
- }
205
219
// lenNewNodeRoutes will be zero if Node exists without any PodCidr/BloackAffinity attached to it.
206
220
if isDelete || lenNewNodeRoutes == 0 {
207
221
// now remove nodename from Nodes list
@@ -226,7 +240,7 @@ func findRoutePrefix(nodeRoutes, aviRoutes []*models.StaticRoute, key string) bo
226
240
return false
227
241
}
228
242
229
- func (o * AviObjectGraph ) addRouteForNode (node * v1.Node , vrfName string , routeid int , routeIdList map [ int ] struct {} ) ([]* models.StaticRoute , error ) {
243
+ func (o * AviObjectGraph ) addRouteForNode (node * v1.Node , vrfName string , routeIdPrefix string ) ([]* models.StaticRoute , error ) {
230
244
var nodeIP , nodeIP6 string
231
245
var nodeRoutes []* models.StaticRoute
232
246
@@ -243,7 +257,7 @@ func (o *AviObjectGraph) addRouteForNode(node *v1.Node, vrfName string, routeid
243
257
utils .AviLog .Errorf ("Error in fetching Pod CIDR for %v: %s" , node .ObjectMeta .Name , err .Error ())
244
258
return nil , errors .New ("podcidr not found" )
245
259
}
246
- for _ , podCIDR := range podCIDRs {
260
+ for index , podCIDR := range podCIDRs {
247
261
podCIDRAndMask := strings .Split (podCIDR , "/" )
248
262
if len (podCIDRAndMask ) != 2 {
249
263
utils .AviLog .Errorf ("Error in splitting Pod CIDR for %v" , node .ObjectMeta .Name )
@@ -273,7 +287,7 @@ func (o *AviObjectGraph) addRouteForNode(node *v1.Node, vrfName string, routeid
273
287
continue
274
288
}
275
289
mask32 := int32 (mask )
276
- routeIDString := clusterName + "-" + strconv .Itoa (routeid )
290
+ routeIDString := clusterName + "-" + routeIdPrefix + "-" + strconv .Itoa (index )
277
291
nodeRoute := models.StaticRoute {
278
292
RouteID : & routeIDString ,
279
293
Prefix : & models.IPAddrPrefix {
@@ -291,8 +305,6 @@ func (o *AviObjectGraph) addRouteForNode(node *v1.Node, vrfName string, routeid
291
305
}
292
306
293
307
nodeRoutes = append (nodeRoutes , & nodeRoute )
294
- routeIdList [routeid ] = struct {}{}
295
- routeid ++
296
308
}
297
309
return nodeRoutes , nil
298
310
}
0 commit comments