• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kubeovn / kube-ovn / 22605160680

03 Mar 2026 02:14AM UTC coverage: 23.17% (-0.01%) from 23.181%
22605160680

push

github

web-flow
fix: protect ANP/BNP/CNP priority maps from concurrent access (#6373)

The priority maps (anpPrioNameMap, anpNamePrioMap, bnpPrioNameMap,
bnpNamePrioMap) are shared across ANP and CNP handler goroutines
which use different per-key mutexes (anpKeyMutex vs cnpKeyMutex).
This means concurrent map read/write can occur, causing a fatal
runtime panic.

Add a sync.RWMutex (priorityMapMutex) to protect all 4 priority
maps. Write lock is held during validate+write in handleAddAnp,
handleAddCnp, handleDeleteAnp, handleDeleteCnp. Read lock is
held for validation-only access in handleUpdateCnp.

Ref: antrea-io/antrea#7717

Signed-off-by: Mengxin Liu <liumengxinfly@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

0 of 17 new or added lines in 2 files covered. (0.0%)

2 existing lines in 1 file now uncovered.

12616 of 54449 relevant lines covered (23.17%)

0.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

8.5
/pkg/controller/admin_network_policy.go
1
package controller
2

3
import (
4
        "errors"
5
        "fmt"
6
        "net"
7
        "reflect"
8
        "strings"
9
        "unicode"
10

11
        "github.com/scylladb/go-set/strset"
12
        k8serrors "k8s.io/apimachinery/pkg/api/errors"
13
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14
        "k8s.io/apimachinery/pkg/labels"
15
        "k8s.io/client-go/tools/cache"
16
        "k8s.io/klog/v2"
17
        v1alpha1 "sigs.k8s.io/network-policy-api/apis/v1alpha1"
18

19
        kubeovnv1 "github.com/kubeovn/kube-ovn/pkg/apis/kubeovn/v1"
20
        "github.com/kubeovn/kube-ovn/pkg/ovs"
21
        "github.com/kubeovn/kube-ovn/pkg/ovsdb/ovnnb"
22
        "github.com/kubeovn/kube-ovn/pkg/util"
23
)
24

25
type ChangedField string
26

27
const (
28
        ChangedSubject     ChangedField = "Subject"
29
        ChangedIngressRule ChangedField = "IngressRule"
30
        ChangedEgressRule  ChangedField = "EgressRule"
31
)
32

33
type ChangedName struct {
34
        // the rule name can be omitted default, add isMatch to append check for rule update
35
        isMatch     bool
36
        oldRuleName string
37
        curRuleName string
38
}
39

40
type AdminNetworkPolicyChangedDelta struct {
41
        key              string
42
        ruleNames        [util.AnpMaxRules]ChangedName
43
        field            ChangedField
44
        DNSReconcileDone bool
45
}
46

47
func (c *Controller) enqueueAddAnp(obj any) {
×
48
        key := cache.MetaObjectToName(obj.(*v1alpha1.AdminNetworkPolicy)).String()
×
49
        klog.V(3).Infof("enqueue add anp %s", key)
×
50
        c.addAnpQueue.Add(key)
×
51
}
×
52

53
func (c *Controller) enqueueDeleteAnp(obj any) {
×
54
        var anp *v1alpha1.AdminNetworkPolicy
×
55
        switch t := obj.(type) {
×
56
        case *v1alpha1.AdminNetworkPolicy:
×
57
                anp = t
×
58
        case cache.DeletedFinalStateUnknown:
×
59
                a, ok := t.Obj.(*v1alpha1.AdminNetworkPolicy)
×
60
                if !ok {
×
61
                        klog.Warningf("unexpected object type: %T", t.Obj)
×
62
                        return
×
63
                }
×
64
                anp = a
×
65
        default:
×
66
                klog.Warningf("unexpected type: %T", obj)
×
67
                return
×
68
        }
69

70
        klog.V(3).Infof("enqueue delete anp %s", cache.MetaObjectToName(anp).String())
×
71
        c.deleteAnpQueue.Add(anp)
×
72
}
73

74
func (c *Controller) enqueueUpdateAnp(oldObj, newObj any) {
×
75
        oldAnpObj := oldObj.(*v1alpha1.AdminNetworkPolicy)
×
76
        newAnpObj := newObj.(*v1alpha1.AdminNetworkPolicy)
×
77

×
78
        // All the acls should be recreated with the following situations
×
79
        if oldAnpObj.Spec.Priority != newAnpObj.Spec.Priority || len(oldAnpObj.Spec.Ingress) != len(newAnpObj.Spec.Ingress) || len(oldAnpObj.Spec.Egress) != len(newAnpObj.Spec.Egress) {
×
80
                c.addAnpQueue.Add(newAnpObj.Name)
×
81
                return
×
82
        }
×
83

84
        // Acls should be updated when action or ports of ingress/egress rule has been changed
85
        for index, rule := range newAnpObj.Spec.Ingress {
×
86
                oldRule := oldAnpObj.Spec.Ingress[index]
×
87
                if oldRule.Action != rule.Action || !reflect.DeepEqual(oldRule.Ports, rule.Ports) {
×
88
                        // It's difficult to distinguish which rule has changed and update acls for that rule, so go through the anp add process to recreate acls.
×
89
                        // If we want to get fine-grained changes over rule, maybe it's a better way to add a new queue to process the change
×
90
                        c.addAnpQueue.Add(newAnpObj.Name)
×
91
                        return
×
92
                }
×
93
        }
94

95
        for index, rule := range newAnpObj.Spec.Egress {
×
96
                oldRule := oldAnpObj.Spec.Egress[index]
×
97
                if oldRule.Action != rule.Action || !reflect.DeepEqual(oldRule.Ports, rule.Ports) {
×
98
                        c.addAnpQueue.Add(newAnpObj.Name)
×
99
                        return
×
100
                }
×
101
        }
102

103
        if oldAnpObj.Annotations[util.ACLActionsLogAnnotation] != newAnpObj.Annotations[util.ACLActionsLogAnnotation] {
×
104
                c.addAnpQueue.Add(newAnpObj.Name)
×
105
                return
×
106
        }
×
107
        klog.V(3).Infof("enqueue update anp %s", newAnpObj.Name)
×
108

×
109
        // The remaining changes do not affect the acls. The port-group or address-set should be updated.
×
110
        // The port-group for anp should be updated
×
111
        if !reflect.DeepEqual(oldAnpObj.Spec.Subject, newAnpObj.Spec.Subject) {
×
112
                c.updateAnpQueue.Add(&AdminNetworkPolicyChangedDelta{key: newAnpObj.Name, field: ChangedSubject})
×
113
        }
×
114

115
        // Rule name or peer selector in ingress/egress rule has changed, the corresponding address-set need be updated
116
        ruleChanged := false
×
117
        var changedIngressRuleNames, changedEgressRuleNames [util.AnpMaxRules]ChangedName
×
118
        for index, rule := range newAnpObj.Spec.Ingress {
×
119
                oldRule := oldAnpObj.Spec.Ingress[index]
×
120
                if oldRule.Name != rule.Name {
×
121
                        changedIngressRuleNames[index] = ChangedName{oldRuleName: oldRule.Name, curRuleName: rule.Name}
×
122
                        ruleChanged = true
×
123
                }
×
124
                if !reflect.DeepEqual(oldRule.From, rule.From) {
×
125
                        changedIngressRuleNames[index] = ChangedName{curRuleName: rule.Name}
×
126
                        ruleChanged = true
×
127
                }
×
128
        }
129
        if ruleChanged {
×
130
                c.updateAnpQueue.Add(&AdminNetworkPolicyChangedDelta{key: newAnpObj.Name, ruleNames: changedIngressRuleNames, field: ChangedIngressRule})
×
131
        }
×
132

133
        ruleChanged = false
×
134
        for index, rule := range newAnpObj.Spec.Egress {
×
135
                oldRule := oldAnpObj.Spec.Egress[index]
×
136
                if oldRule.Name != rule.Name {
×
137
                        changedEgressRuleNames[index] = ChangedName{oldRuleName: oldRule.Name, curRuleName: rule.Name}
×
138
                        ruleChanged = true
×
139
                }
×
140
                if !reflect.DeepEqual(oldRule.To, rule.To) {
×
141
                        changedEgressRuleNames[index] = ChangedName{curRuleName: rule.Name}
×
142
                        ruleChanged = true
×
143
                }
×
144
        }
145
        if ruleChanged {
×
146
                c.updateAnpQueue.Add(&AdminNetworkPolicyChangedDelta{key: newAnpObj.Name, ruleNames: changedEgressRuleNames, field: ChangedEgressRule})
×
147
        }
×
148
}
149

150
func (c *Controller) handleAddAnp(key string) (err error) {
×
151
        c.anpKeyMutex.LockKey(key)
×
152
        defer func() { _ = c.anpKeyMutex.UnlockKey(key) }()
×
153

154
        cachedAnp, err := c.anpsLister.Get(key)
×
155
        if err != nil {
×
156
                if k8serrors.IsNotFound(err) {
×
157
                        return nil
×
158
                }
×
159
                klog.Error(err)
×
160
                return err
×
161
        }
162
        klog.Infof("handle add anp %s", cachedAnp.Name)
×
163
        anp := cachedAnp.DeepCopy()
×
164

×
NEW
165
        c.priorityMapMutex.Lock()
×
166
        if err := c.validateAnpConfig(anp); err != nil {
×
NEW
167
                c.priorityMapMutex.Unlock()
×
168
                klog.Errorf("failed to validate anp %s: %v", anp.Name, err)
×
169
                return err
×
170
        }
×
171
        if priority, exist := c.anpNamePrioMap[anp.Name]; exist && priority != anp.Spec.Priority {
×
172
                // anp spec's priority has been changed
×
173
                delete(c.anpPrioNameMap, priority)
×
174
        }
×
175
        // record new created anp after validation
176
        c.anpPrioNameMap[anp.Spec.Priority] = anp.Name
×
177
        c.anpNamePrioMap[anp.Name] = anp.Spec.Priority
×
NEW
178
        c.priorityMapMutex.Unlock()
×
179

×
180
        anpName := getAnpName(anp.Name)
×
181
        var logActions []string
×
182
        if anp.Annotations[util.ACLActionsLogAnnotation] != "" {
×
183
                logActions = strings.Split(anp.Annotations[util.ACLActionsLogAnnotation], ",")
×
184
        }
×
185

186
        // ovn portGroup/addressSet doesn't support name with '-', so we replace '-' by '.'.
187
        // This may cause conflict if two anp with name test-anp and test.anp, maybe hash is a better solution, but we do not want to lost the readability now.
188
        // Make sure all create operations are reentrant.
189
        pgName := strings.ReplaceAll(anpName, "-", ".")
×
190
        if err = c.OVNNbClient.CreatePortGroup(pgName, map[string]string{adminNetworkPolicyKey: anpName}); err != nil {
×
191
                klog.Errorf("failed to create port group for anp %s: %v", key, err)
×
192
                return err
×
193
        }
×
194

195
        ports, err := c.fetchSelectedPods(&anp.Spec.Subject)
×
196
        if err != nil {
×
197
                klog.Errorf("failed to fetch ports belongs to anp %s: %v", key, err)
×
198
                return err
×
199
        }
×
200

201
        if err = c.OVNNbClient.PortGroupSetPorts(pgName, ports); err != nil {
×
202
                klog.Errorf("failed to set ports %v to port group %s: %v", ports, pgName, err)
×
203
                return err
×
204
        }
×
205

206
        ingressACLOps, err := c.OVNNbClient.DeleteAclsOps(pgName, portGroupKey, "to-lport", nil)
×
207
        if err != nil {
×
208
                klog.Errorf("failed to generate clear operations for anp %s ingress acls: %v", key, err)
×
209
                return err
×
210
        }
×
211

212
        curIngressAddrSet, curEgressAddrSet, err := c.getCurrentAddrSetByName(anpName, false)
×
213
        if err != nil {
×
214
                klog.Errorf("failed to list address sets for anp %s: %v", key, err)
×
215
                return err
×
216
        }
×
217
        desiredIngressAddrSet := strset.NewWithSize(len(anp.Spec.Ingress) * 2)
×
218
        desiredEgressAddrSet := strset.NewWithSize(len(anp.Spec.Egress) * 2)
×
219

×
220
        // create ingress acl
×
221
        for index, anpr := range anp.Spec.Ingress {
×
222
                // A single address set must contain addresses of the same type and the name must be unique within table, so IPv4 and IPv6 address set should be different
×
223
                ingressAsV4Name, ingressAsV6Name := getAnpAddressSetName(pgName, anpr.Name, index, true)
×
224
                desiredIngressAddrSet.Add(ingressAsV4Name, ingressAsV6Name)
×
225

×
226
                var v4Addrs, v4Addr, v6Addrs, v6Addr []string
×
227
                // This field must be defined and contain at least one item.
×
228
                for _, anprpeer := range anpr.From {
×
229
                        if v4Addr, v6Addr, err = c.fetchIngressSelectedAddresses(&anprpeer); err != nil {
×
230
                                klog.Errorf("failed to fetch admin network policy selected addresses, %v", err)
×
231
                                return err
×
232
                        }
×
233
                        v4Addrs = append(v4Addrs, v4Addr...)
×
234
                        v6Addrs = append(v6Addrs, v6Addr...)
×
235
                }
236
                klog.Infof("anp %s, ingress rule %s, selected v4 address %v, v6 address %v", anpName, anpr.Name, v4Addrs, v6Addrs)
×
237

×
238
                if err = c.createAsForAnpRule(anpName, anpr.Name, "ingress", ingressAsV4Name, v4Addrs, false); err != nil {
×
239
                        klog.Error(err)
×
240
                        return err
×
241
                }
×
242
                if err = c.createAsForAnpRule(anpName, anpr.Name, "ingress", ingressAsV6Name, v6Addrs, false); err != nil {
×
243
                        klog.Error(err)
×
244
                        return err
×
245
                }
×
246

247
                aclPriority := util.AnpACLMaxPriority - int(anp.Spec.Priority*100) - index
×
248
                aclAction := anpACLAction(anpr.Action)
×
249
                rulePorts := []v1alpha1.AdminNetworkPolicyPort{}
×
250
                if anpr.Ports != nil {
×
251
                        rulePorts = *anpr.Ports
×
252
                }
×
253

254
                if len(v4Addrs) != 0 {
×
255
                        aclName := fmt.Sprintf("anp/%s/ingress/%s/%d", anpName, kubeovnv1.ProtocolIPv4, index)
×
256
                        ops, err := c.OVNNbClient.UpdateAnpRuleACLOps(pgName, ingressAsV4Name, kubeovnv1.ProtocolIPv4, aclName, aclPriority, aclAction, logActions, rulePorts, true, false)
×
257
                        if err != nil {
×
258
                                klog.Errorf("failed to add v4 ingress acls for anp %s: %v", key, err)
×
259
                                return err
×
260
                        }
×
261
                        ingressACLOps = append(ingressACLOps, ops...)
×
262
                }
263

264
                if len(v6Addrs) != 0 {
×
265
                        aclName := fmt.Sprintf("anp/%s/ingress/%s/%d", anpName, kubeovnv1.ProtocolIPv6, index)
×
266
                        ops, err := c.OVNNbClient.UpdateAnpRuleACLOps(pgName, ingressAsV6Name, kubeovnv1.ProtocolIPv6, aclName, aclPriority, aclAction, logActions, rulePorts, true, false)
×
267
                        if err != nil {
×
268
                                klog.Errorf("failed to add v6 ingress acls for anp %s: %v", key, err)
×
269
                                return err
×
270
                        }
×
271
                        ingressACLOps = append(ingressACLOps, ops...)
×
272
                }
273
        }
274

275
        if err := c.OVNNbClient.Transact("add-ingress-acls", ingressACLOps); err != nil {
×
276
                return fmt.Errorf("failed to add ingress acls for anp %s: %w", key, err)
×
277
        }
×
278
        if err := c.deleteUnusedAddrSetForAnp(curIngressAddrSet, desiredIngressAddrSet); err != nil {
×
279
                return fmt.Errorf("failed to delete unused ingress address set for anp %s: %w", key, err)
×
280
        }
×
281

282
        egressACLOps, err := c.OVNNbClient.DeleteAclsOps(pgName, portGroupKey, "from-lport", nil)
×
283
        if err != nil {
×
284
                klog.Errorf("failed to generate clear operations for anp %s egress acls: %v", key, err)
×
285
                return err
×
286
        }
×
287

288
        // Reconcile DNSNameResolvers for all collected domain names
289
        if c.config.EnableDNSNameResolver {
×
290
                // Collect all domain names from egress rules
×
291
                var allDomainNames []string
×
292
                for _, anpr := range anp.Spec.Egress {
×
293
                        for _, anprpeer := range anpr.To {
×
294
                                if len(anprpeer.DomainNames) != 0 {
×
295
                                        for _, domainName := range anprpeer.DomainNames {
×
296
                                                allDomainNames = append(allDomainNames, string(domainName))
×
297
                                        }
×
298
                                }
299
                        }
300
                }
301

302
                if err := c.reconcileDNSNameResolversForANP(anpName, allDomainNames); err != nil {
×
303
                        klog.Errorf("failed to reconcile DNSNameResolvers for ANP %s: %v", anpName, err)
×
304
                        return err
×
305
                }
×
306
        }
307

308
        // create egress acl
309
        for index, anpr := range anp.Spec.Egress {
×
310
                // A single address set must contain addresses of the same type and the name must be unique within table, so IPv4 and IPv6 address set should be different
×
311
                egressAsV4Name, egressAsV6Name := getAnpAddressSetName(pgName, anpr.Name, index, false)
×
312
                desiredEgressAddrSet.Add(egressAsV4Name, egressAsV6Name)
×
313

×
314
                var v4Addrs, v4Addr, v6Addrs, v6Addr []string
×
315
                hasDomainNames := false
×
316
                // This field must be defined and contain at least one item.
×
317
                for _, anprpeer := range anpr.To {
×
318
                        if v4Addr, v6Addr, err = c.fetchEgressSelectedAddresses(&anprpeer); err != nil {
×
319
                                klog.Errorf("failed to fetch admin network policy selected addresses, %v", err)
×
320
                                return err
×
321
                        }
×
322
                        v4Addrs = append(v4Addrs, v4Addr...)
×
323
                        v6Addrs = append(v6Addrs, v6Addr...)
×
324

×
325
                        // Check if this peer has domain names
×
326
                        hasDomainNames = hasDomainNames || len(anprpeer.DomainNames) > 0
×
327
                }
328
                klog.Infof("anp %s, egress rule %s, selected v4 address %v, v6 address %v", anpName, anpr.Name, v4Addrs, v6Addrs)
×
329

×
330
                if err = c.createAsForAnpRule(anpName, anpr.Name, "egress", egressAsV4Name, v4Addrs, false); err != nil {
×
331
                        klog.Error(err)
×
332
                        return err
×
333
                }
×
334
                if err = c.createAsForAnpRule(anpName, anpr.Name, "egress", egressAsV6Name, v6Addrs, false); err != nil {
×
335
                        klog.Error(err)
×
336
                        return err
×
337
                }
×
338

339
                aclPriority := util.AnpACLMaxPriority - int(anp.Spec.Priority*100) - index
×
340
                aclAction := anpACLAction(anpr.Action)
×
341
                rulePorts := []v1alpha1.AdminNetworkPolicyPort{}
×
342
                if anpr.Ports != nil {
×
343
                        rulePorts = *anpr.Ports
×
344
                }
×
345

346
                // Create ACL rules if we have IP addresses OR domain names
347
                // Domain names may not be resolved initially but will be updated later
348
                if len(v4Addrs) != 0 || hasDomainNames {
×
349
                        aclName := fmt.Sprintf("anp/%s/egress/%s/%d", anpName, kubeovnv1.ProtocolIPv4, index)
×
350
                        ops, err := c.OVNNbClient.UpdateAnpRuleACLOps(pgName, egressAsV4Name, kubeovnv1.ProtocolIPv4, aclName, aclPriority, aclAction, logActions, rulePorts, false, false)
×
351
                        if err != nil {
×
352
                                klog.Errorf("failed to add v4 egress acls for anp %s: %v", key, err)
×
353
                                return err
×
354
                        }
×
355
                        egressACLOps = append(egressACLOps, ops...)
×
356
                }
357

358
                if len(v6Addrs) != 0 || hasDomainNames {
×
359
                        aclName := fmt.Sprintf("anp/%s/egress/%s/%d", anpName, kubeovnv1.ProtocolIPv6, index)
×
360
                        ops, err := c.OVNNbClient.UpdateAnpRuleACLOps(pgName, egressAsV6Name, kubeovnv1.ProtocolIPv6, aclName, aclPriority, aclAction, logActions, rulePorts, false, false)
×
361
                        if err != nil {
×
362
                                klog.Errorf("failed to add v6 egress acls for anp %s: %v", key, err)
×
363
                                return err
×
364
                        }
×
365
                        egressACLOps = append(egressACLOps, ops...)
×
366
                }
367
        }
368

369
        if err := c.OVNNbClient.Transact("add-egress-acls", egressACLOps); err != nil {
×
370
                return fmt.Errorf("failed to add egress acls for anp %s: %w", key, err)
×
371
        }
×
372
        if err := c.deleteUnusedAddrSetForAnp(curEgressAddrSet, desiredEgressAddrSet); err != nil {
×
373
                return fmt.Errorf("failed to delete unused egress address set for anp %s: %w", key, err)
×
374
        }
×
375

376
        return nil
×
377
}
378

379
func (c *Controller) handleDeleteAnp(anp *v1alpha1.AdminNetworkPolicy) error {
×
380
        c.anpKeyMutex.LockKey(anp.Name)
×
381
        defer func() { _ = c.anpKeyMutex.UnlockKey(anp.Name) }()
×
382

383
        klog.Infof("handle delete admin network policy %s", anp.Name)
×
NEW
384
        c.priorityMapMutex.Lock()
×
385
        delete(c.anpPrioNameMap, anp.Spec.Priority)
×
386
        delete(c.anpNamePrioMap, anp.Name)
×
NEW
387
        c.priorityMapMutex.Unlock()
×
388

×
389
        anpName := getAnpName(anp.Name)
×
390

×
391
        // ACLs related to port_group will be deleted automatically when port_group is deleted
×
392
        pgName := strings.ReplaceAll(anpName, "-", ".")
×
393
        if err := c.OVNNbClient.DeletePortGroup(pgName); err != nil {
×
394
                klog.Errorf("failed to delete port group for anp %s: %v", anpName, err)
×
395
        }
×
396

397
        if err := c.OVNNbClient.DeleteAddressSets(map[string]string{
×
398
                adminNetworkPolicyKey: fmt.Sprintf("%s/%s", anpName, "ingress"),
×
399
        }); err != nil {
×
400
                klog.Errorf("failed to delete ingress address set for anp %s: %v", anpName, err)
×
401
                return err
×
402
        }
×
403

404
        if err := c.OVNNbClient.DeleteAddressSets(map[string]string{
×
405
                adminNetworkPolicyKey: fmt.Sprintf("%s/%s", anpName, "egress"),
×
406
        }); err != nil {
×
407
                klog.Errorf("failed to delete egress address set for anp %s: %v", anpName, err)
×
408
                return err
×
409
        }
×
410

411
        // Delete all DNSNameResolver CRs associated with this ANP
412
        if c.config.EnableDNSNameResolver {
×
413
                if err := c.reconcileDNSNameResolversForANP(anpName, []string{}); err != nil {
×
414
                        klog.Errorf("failed to delete DNSNameResolver CRs for anp %s: %v", anpName, err)
×
415
                        return err
×
416
                }
×
417
        }
418

419
        return nil
×
420
}
421

422
func (c *Controller) handleUpdateAnp(changed *AdminNetworkPolicyChangedDelta) error {
×
423
        // Only handle updates that do not affect acls.
×
424
        c.anpKeyMutex.LockKey(changed.key)
×
425
        defer func() { _ = c.anpKeyMutex.UnlockKey(changed.key) }()
×
426

427
        klog.Infof("handleUpdateAnp: processing ANP %s, field=%s, DNSReconcileDone=%v",
×
428
                changed.key, changed.field, changed.DNSReconcileDone)
×
429

×
430
        cachedAnp, err := c.anpsLister.Get(changed.key)
×
431
        if err != nil {
×
432
                if k8serrors.IsNotFound(err) {
×
433
                        return nil
×
434
                }
×
435
                klog.Error(err)
×
436
                return err
×
437
        }
438
        desiredAnp := cachedAnp.DeepCopy()
×
439
        klog.Infof("handle update admin network policy %s", desiredAnp.Name)
×
440

×
441
        anpName := getAnpName(desiredAnp.Name)
×
442
        pgName := strings.ReplaceAll(anpName, "-", ".")
×
443

×
444
        // The port-group for anp should be updated
×
445
        if changed.field == ChangedSubject {
×
446
                // The port-group must exist when update anp, this check should never be matched.
×
447
                if ok, err := c.OVNNbClient.PortGroupExists(pgName); !ok || err != nil {
×
448
                        klog.Errorf("port-group for anp %s does not exist when update anp", desiredAnp.Name)
×
449
                        return err
×
450
                }
×
451

452
                ports, err := c.fetchSelectedPods(&desiredAnp.Spec.Subject)
×
453
                if err != nil {
×
454
                        klog.Errorf("failed to fetch ports belongs to anp %s: %v", desiredAnp.Name, err)
×
455
                        return err
×
456
                }
×
457

458
                if err = c.OVNNbClient.PortGroupSetPorts(pgName, ports); err != nil {
×
459
                        klog.Errorf("failed to set ports %v to port group %s: %v", ports, pgName, err)
×
460
                        return err
×
461
                }
×
462
        }
463

464
        // Peer selector in ingress/egress rule has changed, so the corresponding address-set need be updated
465
        if changed.field == ChangedIngressRule {
×
466
                for index, rule := range desiredAnp.Spec.Ingress {
×
467
                        // Make sure the rule is changed and go on update
×
468
                        if rule.Name == changed.ruleNames[index].curRuleName || changed.ruleNames[index].isMatch {
×
469
                                if err := c.setAddrSetForAnpRule(anpName, pgName, rule.Name, index, rule.From, []v1alpha1.AdminNetworkPolicyEgressPeer{}, true, false); err != nil {
×
470
                                        klog.Errorf("failed to set ingress address-set for anp rule %s/%s, %v", anpName, rule.Name, err)
×
471
                                        return err
×
472
                                }
×
473

474
                                if changed.ruleNames[index].oldRuleName != "" {
×
475
                                        oldRuleName := changed.ruleNames[index].oldRuleName
×
476
                                        // Normally the name can not be changed, but when the name really changes, the old address set should be deleted
×
477
                                        // There is no description in the Name comments that it cannot be changed
×
478
                                        oldAsV4Name, oldAsV6Name := getAnpAddressSetName(pgName, oldRuleName, index, true)
×
479

×
480
                                        if err := c.OVNNbClient.DeleteAddressSet(oldAsV4Name); err != nil {
×
481
                                                klog.Errorf("failed to delete address set %s, %v", oldAsV4Name, err)
×
482
                                                // just record error log
×
483
                                        }
×
484
                                        if err := c.OVNNbClient.DeleteAddressSet(oldAsV6Name); err != nil {
×
485
                                                klog.Errorf("failed to delete address set %s, %v", oldAsV6Name, err)
×
486
                                        }
×
487
                                }
488
                        }
489
                }
490
        }
491

492
        if changed.field == ChangedEgressRule {
×
493
                for index, rule := range desiredAnp.Spec.Egress {
×
494
                        // Check if we need to update address sets (rule changed or DNS reconciliation needed)
×
495
                        needAddrSetUpdate := rule.Name == changed.ruleNames[index].curRuleName || changed.ruleNames[index].isMatch || changed.DNSReconcileDone
×
496

×
497
                        // Check if we need to reconcile DNS resolvers (DNS feature enabled and not already done)
×
498
                        needDNSReconcile := c.config.EnableDNSNameResolver && !changed.DNSReconcileDone
×
499

×
500
                        if needAddrSetUpdate {
×
501
                                if err := c.setAddrSetForAnpRule(anpName, pgName, rule.Name, index, []v1alpha1.AdminNetworkPolicyIngressPeer{}, rule.To, false, false); err != nil {
×
502
                                        klog.Errorf("failed to set egress address-set for anp rule %s/%s, %v", anpName, rule.Name, err)
×
503
                                        return err
×
504
                                }
×
505

506
                                if needDNSReconcile {
×
507
                                        var currentDomainNames []string
×
508
                                        for _, peer := range rule.To {
×
509
                                                for _, domainName := range peer.DomainNames {
×
510
                                                        currentDomainNames = append(currentDomainNames, string(domainName))
×
511
                                                }
×
512
                                        }
513

514
                                        if err := c.reconcileDNSNameResolversForANP(anpName, currentDomainNames); err != nil {
×
515
                                                klog.Errorf("failed to reconcile DNSNameResolvers for egress rule %s/%s, %v", anpName, rule.Name, err)
×
516
                                                return err
×
517
                                        }
×
518
                                }
519

520
                                if changed.ruleNames[index].oldRuleName != "" {
×
521
                                        oldRuleName := changed.ruleNames[index].oldRuleName
×
522
                                        // Normally the name can not be changed, but when the name really changes, the old address set should be deleted
×
523
                                        // There is no description in the Name comments that it cannot be changed
×
524
                                        oldAsV4Name, oldAsV6Name := getAnpAddressSetName(pgName, oldRuleName, index, false)
×
525

×
526
                                        if err := c.OVNNbClient.DeleteAddressSet(oldAsV4Name); err != nil {
×
527
                                                klog.Errorf("failed to delete address set %s, %v", oldAsV4Name, err)
×
528
                                                // just record error log
×
529
                                        }
×
530
                                        if err := c.OVNNbClient.DeleteAddressSet(oldAsV6Name); err != nil {
×
531
                                                klog.Errorf("failed to delete address set %s, %v", oldAsV6Name, err)
×
532
                                        }
×
533
                                }
534
                        }
535
                }
536
        }
537

538
        return nil
×
539
}
540

541
func (c *Controller) validateAnpConfig(anp *v1alpha1.AdminNetworkPolicy) error {
1✔
542
        // The behavior is undefined if two ANP objects have same priority.
1✔
543
        if anpName, exist := c.anpPrioNameMap[anp.Spec.Priority]; exist && anpName != anp.Name {
2✔
544
                err := fmt.Errorf("can not create anp with same priority %d, exist one is %s, new created is %s", anp.Spec.Priority, anpName, anp.Name)
1✔
545
                klog.Error(err)
1✔
546
                return err
1✔
547
        }
1✔
548

549
        // We have noticed redhat's discussion about ACL priority in https://bugzilla.redhat.com/show_bug.cgi?id=2175752
550
        // After discussion, we decided to use the same range of priorities(20000-30000). Pay tribute to the developers of redhat.
551
        if anp.Spec.Priority > util.AnpMaxPriority {
2✔
552
                err := fmt.Errorf("the priority of anp %s is greater than max value %d", anp.Name, util.AnpMaxPriority)
1✔
553
                klog.Error(err)
1✔
554
                return err
1✔
555
        }
1✔
556

557
        if len(anp.Spec.Ingress) > util.AnpMaxRules || len(anp.Spec.Egress) > util.AnpMaxRules {
1✔
558
                err := fmt.Errorf("at most %d rules can be create in anp ingress/egress, ingress rules num %d and egress rules num %d in anp %s", util.AnpMaxRules, len(anp.Spec.Ingress), len(anp.Spec.Egress), anp.Name)
×
559
                klog.Error(err)
×
560
                return err
×
561
        }
×
562

563
        return nil
1✔
564
}
565

566
func (c *Controller) fetchSelectedPods(anpSubject *v1alpha1.AdminNetworkPolicySubject) ([]string, error) {
×
567
        var ports []string
×
568

×
569
        // Exactly one field must be set.
×
570
        if anpSubject.Namespaces != nil {
×
571
                nsSelector, err := metav1.LabelSelectorAsSelector(anpSubject.Namespaces)
×
572
                if err != nil {
×
573
                        return nil, fmt.Errorf("error creating ns label selector, %w", err)
×
574
                }
×
575

576
                ports, _, _, err = c.fetchPods(nsSelector, labels.Everything())
×
577
                if err != nil {
×
578
                        return nil, fmt.Errorf("failed to fetch pods, %w", err)
×
579
                }
×
580
        } else if anpSubject.Pods != nil {
×
581
                nsSelector, err := metav1.LabelSelectorAsSelector(&anpSubject.Pods.NamespaceSelector)
×
582
                if err != nil {
×
583
                        return nil, fmt.Errorf("error creating ns label selector, %w", err)
×
584
                }
×
585
                podSelector, err := metav1.LabelSelectorAsSelector(&anpSubject.Pods.PodSelector)
×
586
                if err != nil {
×
587
                        return nil, fmt.Errorf("error creating pod label selector, %w", err)
×
588
                }
×
589

590
                ports, _, _, err = c.fetchPods(nsSelector, podSelector)
×
591
                if err != nil {
×
592
                        return nil, fmt.Errorf("failed to fetch pods, %w", err)
×
593
                }
×
594
        }
595
        klog.Infof("get selected ports for subject, %v", ports)
×
596
        return ports, nil
×
597
}
598

599
func (c *Controller) fetchPods(nsSelector, podSelector labels.Selector) ([]string, []string, []string, error) {
×
600
        ports := make([]string, 0, util.AnpMaxRules)
×
601
        v4Addresses := make([]string, 0, util.AnpMaxRules)
×
602
        v6Addresses := make([]string, 0, util.AnpMaxRules)
×
603

×
604
        namespaces, err := c.namespacesLister.List(nsSelector)
×
605
        if err != nil {
×
606
                klog.Errorf("failed to list namespaces: %v", err)
×
607
                return nil, nil, nil, err
×
608
        }
×
609

610
        klog.V(3).Infof("fetch pod ports/addresses, namespace selector is %s, pod selector is %s", nsSelector.String(), podSelector.String())
×
611
        for _, namespace := range namespaces {
×
612
                pods, err := c.podsLister.Pods(namespace.Name).List(podSelector)
×
613
                if err != nil {
×
614
                        return nil, nil, nil, fmt.Errorf("failed to list pods, %w", err)
×
615
                }
×
616

617
                for _, pod := range pods {
×
618
                        if pod.Spec.HostNetwork {
×
619
                                continue
×
620
                        }
621
                        podName := c.getNameByPod(pod)
×
622

×
623
                        podNets, err := c.getPodKubeovnNets(pod)
×
624
                        if err != nil {
×
625
                                return nil, nil, nil, fmt.Errorf("failed to get pod networks, %w", err)
×
626
                        }
×
627

628
                        for _, podNet := range podNets {
×
629
                                if !isOvnSubnet(podNet.Subnet) {
×
630
                                        continue
×
631
                                }
632

633
                                if pod.Annotations[fmt.Sprintf(util.AllocatedAnnotationTemplate, podNet.ProviderName)] == "true" {
×
634
                                        ports = append(ports, ovs.PodNameToPortName(podName, pod.Namespace, podNet.ProviderName))
×
635

×
636
                                        podIPAnnotation := pod.Annotations[fmt.Sprintf(util.IPAddressAnnotationTemplate, podNet.ProviderName)]
×
637
                                        podIPs := strings.SplitSeq(podIPAnnotation, ",")
×
638
                                        for podIP := range podIPs {
×
639
                                                switch util.CheckProtocol(podIP) {
×
640
                                                case kubeovnv1.ProtocolIPv4:
×
641
                                                        v4Addresses = append(v4Addresses, podIP)
×
642
                                                case kubeovnv1.ProtocolIPv6:
×
643
                                                        v6Addresses = append(v6Addresses, podIP)
×
644
                                                }
645
                                        }
646
                                }
647
                        }
648
                }
649
        }
650

651
        return ports, v4Addresses, v6Addresses, nil
×
652
}
653

654
func (c *Controller) fetchIngressSelectedAddresses(ingressPeer *v1alpha1.AdminNetworkPolicyIngressPeer) ([]string, []string, error) {
×
655
        var v4Addresses, v6Addresses []string
×
656

×
657
        // Exactly one of the selector pointers must be set for a given peer.
×
658
        if ingressPeer.Namespaces != nil {
×
659
                nsSelector, err := metav1.LabelSelectorAsSelector(ingressPeer.Namespaces)
×
660
                if err != nil {
×
661
                        return nil, nil, fmt.Errorf("error creating ns label selector, %w", err)
×
662
                }
×
663

664
                _, v4Addresses, v6Addresses, err = c.fetchPods(nsSelector, labels.Everything())
×
665
                if err != nil {
×
666
                        return nil, nil, fmt.Errorf("failed to fetch ingress peer addresses, %w", err)
×
667
                }
×
668
        } else if ingressPeer.Pods != nil {
×
669
                nsSelector, err := metav1.LabelSelectorAsSelector(&ingressPeer.Pods.NamespaceSelector)
×
670
                if err != nil {
×
671
                        return nil, nil, fmt.Errorf("error creating ns label selector, %w", err)
×
672
                }
×
673
                podSelector, err := metav1.LabelSelectorAsSelector(&ingressPeer.Pods.PodSelector)
×
674
                if err != nil {
×
675
                        return nil, nil, fmt.Errorf("error creating pod label selector, %w", err)
×
676
                }
×
677

678
                _, v4Addresses, v6Addresses, err = c.fetchPods(nsSelector, podSelector)
×
679
                if err != nil {
×
680
                        return nil, nil, fmt.Errorf("failed to fetch ingress peer addresses, %w", err)
×
681
                }
×
682
        }
683

684
        return v4Addresses, v6Addresses, nil
×
685
}
686

687
func (c *Controller) fetchEgressSelectedAddresses(egressPeer *v1alpha1.AdminNetworkPolicyEgressPeer) ([]string, []string, error) {
×
688
        return c.fetchEgressSelectedAddressesCommon(egressPeer.Namespaces, egressPeer.Pods, egressPeer.Nodes, egressPeer.Networks, egressPeer.DomainNames)
×
689
}
×
690

691
func (c *Controller) fetchBaselineEgressSelectedAddresses(egressPeer *v1alpha1.BaselineAdminNetworkPolicyEgressPeer) ([]string, []string, error) {
×
692
        return c.fetchEgressSelectedAddressesCommon(egressPeer.Namespaces, egressPeer.Pods, egressPeer.Nodes, egressPeer.Networks, nil)
×
693
}
×
694

695
func (c *Controller) fetchEgressSelectedAddressesCommon(namespaces *metav1.LabelSelector, pods *v1alpha1.NamespacedPod, nodes *metav1.LabelSelector, networks []v1alpha1.CIDR, domainNames []v1alpha1.DomainName) ([]string, []string, error) {
×
696
        var v4Addresses, v6Addresses []string
×
697

×
698
        // Exactly one of the selector pointers must be set for a given peer.
×
699
        switch {
×
700
        case namespaces != nil:
×
701
                nsSelector, err := metav1.LabelSelectorAsSelector(namespaces)
×
702
                if err != nil {
×
703
                        return nil, nil, fmt.Errorf("error creating ns label selector, %w", err)
×
704
                }
×
705

706
                _, v4Addresses, v6Addresses, err = c.fetchPods(nsSelector, labels.Everything())
×
707
                if err != nil {
×
708
                        return nil, nil, fmt.Errorf("failed to fetch egress peer addresses, %w", err)
×
709
                }
×
710
        case pods != nil:
×
711
                nsSelector, err := metav1.LabelSelectorAsSelector(&pods.NamespaceSelector)
×
712
                if err != nil {
×
713
                        return nil, nil, fmt.Errorf("error creating ns label selector, %w", err)
×
714
                }
×
715
                podSelector, err := metav1.LabelSelectorAsSelector(&pods.PodSelector)
×
716
                if err != nil {
×
717
                        return nil, nil, fmt.Errorf("error creating pod label selector, %w", err)
×
718
                }
×
719

720
                _, v4Addresses, v6Addresses, err = c.fetchPods(nsSelector, podSelector)
×
721
                if err != nil {
×
722
                        return nil, nil, fmt.Errorf("failed to fetch egress peer addresses, %w", err)
×
723
                }
×
724
        case nodes != nil:
×
725
                nodesSelector, err := metav1.LabelSelectorAsSelector(nodes)
×
726
                if err != nil {
×
727
                        return nil, nil, fmt.Errorf("error creating nodes label selector, %w", err)
×
728
                }
×
729
                v4Addresses, v6Addresses, err = c.fetchNodesAddrs(nodesSelector)
×
730
                if err != nil {
×
731
                        return nil, nil, fmt.Errorf("failed to fetch egress peer addresses, %w", err)
×
732
                }
×
733
        case len(networks) != 0:
×
734
                v4Addresses, v6Addresses = fetchCIDRAddrs(networks)
×
735
        case len(domainNames) != 0:
×
736
                // DomainNames field is present - resolve addresses from DNSNameResolver
×
737
                if !c.config.EnableDNSNameResolver {
×
738
                        return nil, nil, fmt.Errorf("DNSNameResolver is disabled but domain names are specified: %v", domainNames)
×
739
                }
×
740
                klog.Infof("DomainNames detected in egress peer: %v", domainNames)
×
741
                var err error
×
742
                v4Addresses, v6Addresses, err = c.resolveDomainNames(domainNames)
×
743
                if err != nil {
×
744
                        return nil, nil, fmt.Errorf("failed to resolve domain names: %w", err)
×
745
                }
×
746
        default:
×
747
                return nil, nil, errors.New("at least one egressPeer must be specified")
×
748
        }
749

750
        return v4Addresses, v6Addresses, nil
×
751
}
752

753
// resolveDomainNames resolves domain names to IP addresses using DNSNameResolver lister
754
func (c *Controller) resolveDomainNames(domainNames []v1alpha1.DomainName) ([]string, []string, error) {
×
755
        var allV4Addresses, allV6Addresses []string
×
756

×
757
        for _, domainName := range domainNames {
×
758
                // Find DNSNameResolver for this domain name
×
759
                dnsNameResolvers, err := c.dnsNameResolversLister.List(labels.Everything())
×
760
                if err != nil {
×
761
                        klog.Errorf("Failed to list DNSNameResolvers: %v", err)
×
762
                        continue
×
763
                }
764

765
                var foundResolver *kubeovnv1.DNSNameResolver
×
766
                for _, resolver := range dnsNameResolvers {
×
767
                        if string(resolver.Spec.Name) == string(domainName) {
×
768
                                foundResolver = resolver
×
769
                                break
×
770
                        }
771
                }
772

773
                if foundResolver == nil {
×
774
                        klog.V(3).Infof("No DNSNameResolver found for domain %s, skipping", domainName)
×
775
                        continue
×
776
                }
777

778
                // Get resolved addresses from DNSNameResolver
779
                v4Addresses, v6Addresses, err := getResolvedAddressesFromDNSNameResolver(foundResolver)
×
780
                if err != nil {
×
781
                        klog.Errorf("Failed to get resolved addresses from DNSNameResolver %s: %v", foundResolver.Name, err)
×
782
                        continue
×
783
                }
784

785
                allV4Addresses = append(allV4Addresses, v4Addresses...)
×
786
                allV6Addresses = append(allV6Addresses, v6Addresses...)
×
787
        }
788

789
        return allV4Addresses, allV6Addresses, nil
×
790
}
791

792
func (c *Controller) createAsForAnpRule(anpName, ruleName, direction, asName string, addresses []string, isBanp bool) error {
×
793
        var err error
×
794
        if isBanp {
×
795
                err = c.OVNNbClient.CreateAddressSet(asName, map[string]string{
×
796
                        baselineAdminNetworkPolicyKey: fmt.Sprintf("%s/%s", anpName, direction),
×
797
                })
×
798
        } else {
×
799
                err = c.OVNNbClient.CreateAddressSet(asName, map[string]string{
×
800
                        adminNetworkPolicyKey: fmt.Sprintf("%s/%s", anpName, direction),
×
801
                })
×
802
        }
×
803
        if err != nil {
×
804
                klog.Errorf("failed to create ovn address set %s for anp/banp rule %s/%s: %v", asName, anpName, ruleName, err)
×
805
                return err
×
806
        }
×
807

808
        if err := c.OVNNbClient.AddressSetUpdateAddress(asName, addresses...); err != nil {
×
809
                klog.Errorf("failed to set addresses %q to address set %s: %v", strings.Join(addresses, ","), asName, err)
×
810
                return err
×
811
        }
×
812

813
        return nil
×
814
}
815

816
func (c *Controller) getCurrentAddrSetByName(anpName string, isBanp bool) (*strset.Set, *strset.Set, error) {
×
817
        curIngressAddrSet := strset.New()
×
818
        curEgressAddrSet := strset.New()
×
819
        var ass []ovnnb.AddressSet
×
820
        var err error
×
821

×
822
        // anp and banp can use same name, so depends on the external_ids key field to distinguish
×
823
        if isBanp {
×
824
                ass, err = c.OVNNbClient.ListAddressSets(map[string]string{
×
825
                        baselineAdminNetworkPolicyKey: fmt.Sprintf("%s/%s", anpName, "ingress"),
×
826
                })
×
827
        } else {
×
828
                ass, err = c.OVNNbClient.ListAddressSets(map[string]string{
×
829
                        adminNetworkPolicyKey: fmt.Sprintf("%s/%s", anpName, "ingress"),
×
830
                })
×
831
        }
×
832
        if err != nil {
×
833
                klog.Errorf("failed to list ingress address sets for anp/banp %s: %v", anpName, err)
×
834
                return curIngressAddrSet, curEgressAddrSet, err
×
835
        }
×
836
        for _, as := range ass {
×
837
                curIngressAddrSet.Add(as.Name)
×
838
        }
×
839

840
        if isBanp {
×
841
                ass, err = c.OVNNbClient.ListAddressSets(map[string]string{
×
842
                        baselineAdminNetworkPolicyKey: fmt.Sprintf("%s/%s", anpName, "egress"),
×
843
                })
×
844
        } else {
×
845
                ass, err = c.OVNNbClient.ListAddressSets(map[string]string{
×
846
                        adminNetworkPolicyKey: fmt.Sprintf("%s/%s", anpName, "egress"),
×
847
                })
×
848
        }
×
849
        if err != nil {
×
850
                klog.Errorf("failed to list egress address sets for anp/banp %s: %v", anpName, err)
×
851
                return curIngressAddrSet, curEgressAddrSet, err
×
852
        }
×
853
        for _, as := range ass {
×
854
                curEgressAddrSet.Add(as.Name)
×
855
        }
×
856

857
        return curIngressAddrSet, curEgressAddrSet, nil
×
858
}
859

860
func (c *Controller) deleteUnusedAddrSetForAnp(curAddrSet, desiredAddrSet *strset.Set) error {
×
861
        toDel := strset.Difference(curAddrSet, desiredAddrSet).List()
×
862

×
863
        for _, asName := range toDel {
×
864
                if err := c.OVNNbClient.DeleteAddressSet(asName); err != nil {
×
865
                        klog.Errorf("failed to delete address set %s, %v", asName, err)
×
866
                        return err
×
867
                }
×
868
        }
869

870
        return nil
×
871
}
872

873
func (c *Controller) setAddrSetForAnpRule(anpName, pgName, ruleName string, index int, from []v1alpha1.AdminNetworkPolicyIngressPeer, to []v1alpha1.AdminNetworkPolicyEgressPeer, isIngress, isBanp bool) error {
×
874
        return c.setAddrSetForAnpRuleCommon(anpName, pgName, ruleName, index, from, to, nil, isIngress, isBanp)
×
875
}
×
876

877
func (c *Controller) setAddrSetForBaselineAnpRule(anpName, pgName, ruleName string, index int, from []v1alpha1.AdminNetworkPolicyIngressPeer, to []v1alpha1.BaselineAdminNetworkPolicyEgressPeer, isIngress, isBanp bool) error {
×
878
        return c.setAddrSetForAnpRuleCommon(anpName, pgName, ruleName, index, from, nil, to, isIngress, isBanp)
×
879
}
×
880

881
func (c *Controller) setAddrSetForAnpRuleCommon(anpName, pgName, ruleName string, index int, from []v1alpha1.AdminNetworkPolicyIngressPeer, to []v1alpha1.AdminNetworkPolicyEgressPeer, baselineTo []v1alpha1.BaselineAdminNetworkPolicyEgressPeer, isIngress, isBanp bool) error {
×
882
        // A single address set must contain addresses of the same type and the name must be unique within table, so IPv4 and IPv6 address set should be different
×
883

×
884
        var v4Addrs, v4Addr, v6Addrs, v6Addr []string
×
885
        var err error
×
886
        if isIngress {
×
887
                for _, anprpeer := range from {
×
888
                        if v4Addr, v6Addr, err = c.fetchIngressSelectedAddresses(&anprpeer); err != nil {
×
889
                                klog.Errorf("failed to fetch anp/banp ingress selected addresses, %v", err)
×
890
                                return err
×
891
                        }
×
892
                        v4Addrs = append(v4Addrs, v4Addr...)
×
893
                        v6Addrs = append(v6Addrs, v6Addr...)
×
894
                }
895
                klog.Infof("update anp/banp ingress rule %s, selected v4 address %v, v6 address %v", ruleName, v4Addrs, v6Addrs)
×
896

×
897
                gressAsV4Name, gressAsV6Name := getAnpAddressSetName(pgName, ruleName, index, true)
×
898
                if err = c.createAsForAnpRule(anpName, ruleName, "ingress", gressAsV4Name, v4Addrs, isBanp); err != nil {
×
899
                        klog.Error(err)
×
900
                        return err
×
901
                }
×
902
                if err = c.createAsForAnpRule(anpName, ruleName, "ingress", gressAsV6Name, v6Addrs, isBanp); err != nil {
×
903
                        klog.Error(err)
×
904
                        return err
×
905
                }
×
906
        } else {
×
907
                if to != nil {
×
908
                        for _, anprpeer := range to {
×
909
                                if v4Addr, v6Addr, err = c.fetchEgressSelectedAddresses(&anprpeer); err != nil {
×
910
                                        klog.Errorf("failed to fetch anp/banp egress selected addresses, %v", err)
×
911
                                        return err
×
912
                                }
×
913
                                v4Addrs = append(v4Addrs, v4Addr...)
×
914
                                v6Addrs = append(v6Addrs, v6Addr...)
×
915
                        }
916
                } else {
×
917
                        for _, anprpeer := range baselineTo {
×
918
                                if v4Addr, v6Addr, err = c.fetchBaselineEgressSelectedAddresses(&anprpeer); err != nil {
×
919
                                        klog.Errorf("failed to fetch baseline anp/banp egress selected addresses, %v", err)
×
920
                                        return err
×
921
                                }
×
922
                                v4Addrs = append(v4Addrs, v4Addr...)
×
923
                                v6Addrs = append(v6Addrs, v6Addr...)
×
924
                        }
925
                }
926
                klog.Infof("update anp/banp egress rule %s, selected v4 address %v, v6 address %v", ruleName, v4Addrs, v6Addrs)
×
927

×
928
                gressAsV4Name, gressAsV6Name := getAnpAddressSetName(pgName, ruleName, index, false)
×
929
                if err = c.createAsForAnpRule(anpName, ruleName, "egress", gressAsV4Name, v4Addrs, isBanp); err != nil {
×
930
                        klog.Error(err)
×
931
                        return err
×
932
                }
×
933
                if err = c.createAsForAnpRule(anpName, ruleName, "egress", gressAsV6Name, v6Addrs, isBanp); err != nil {
×
934
                        klog.Error(err)
×
935
                        return err
×
936
                }
×
937
        }
938

939
        return nil
×
940
}
941

942
func (c *Controller) updateAnpsByLabelsMatch(nsLabels, podLabels map[string]string) {
×
943
        anps, _ := c.anpsLister.List(labels.Everything())
×
944
        for _, anp := range anps {
×
945
                changed := &AdminNetworkPolicyChangedDelta{
×
946
                        key: anp.Name,
×
947
                }
×
948

×
949
                if isLabelsMatch(anp.Spec.Subject.Namespaces, anp.Spec.Subject.Pods, nsLabels, podLabels) {
×
950
                        klog.Infof("anp %s, labels matched for anp's subject, nsLabels %s, podLabels %s", anp.Name, labels.Set(nsLabels).String(), labels.Set(podLabels).String())
×
951
                        changed.field = ChangedSubject
×
952
                        c.updateAnpQueue.Add(changed)
×
953
                }
×
954

955
                ingressRuleNames, egressRuleNames := isLabelsMatchAnpRulePeers(anp.Spec.Ingress, anp.Spec.Egress, nsLabels, podLabels)
×
956
                if !isRulesArrayEmpty(ingressRuleNames) {
×
957
                        klog.Infof("anp %s, labels matched for anp's ingress peer, nsLabels %s, podLabels %s", anp.Name, labels.Set(nsLabels).String(), labels.Set(podLabels).String())
×
958
                        changed.ruleNames = ingressRuleNames
×
959
                        changed.field = ChangedIngressRule
×
960
                        c.updateAnpQueue.Add(changed)
×
961
                }
×
962

963
                if !isRulesArrayEmpty(egressRuleNames) {
×
964
                        klog.Infof("anp %s, labels matched for anp's egress peer, nsLabels %s, podLabels %s", anp.Name, labels.Set(nsLabels).String(), labels.Set(podLabels).String())
×
965
                        changed.ruleNames = egressRuleNames
×
966
                        changed.field = ChangedEgressRule
×
967
                        c.updateAnpQueue.Add(changed)
×
968
                }
×
969
        }
970

971
        banps, _ := c.banpsLister.List(labels.Everything())
×
972
        for _, banp := range banps {
×
973
                changed := &AdminNetworkPolicyChangedDelta{
×
974
                        key: banp.Name,
×
975
                }
×
976

×
977
                if isLabelsMatch(banp.Spec.Subject.Namespaces, banp.Spec.Subject.Pods, nsLabels, podLabels) {
×
978
                        klog.Infof("banp %s, labels matched for banp's subject, nsLabels %s, podLabels %s", banp.Name, labels.Set(nsLabels).String(), labels.Set(podLabels).String())
×
979
                        changed.field = ChangedSubject
×
980
                        c.updateBanpQueue.Add(changed)
×
981
                }
×
982

983
                ingressRuleNames, egressRuleNames := isLabelsMatchBanpRulePeers(banp.Spec.Ingress, banp.Spec.Egress, nsLabels, podLabels)
×
984
                if !isRulesArrayEmpty(ingressRuleNames) {
×
985
                        klog.Infof("banp %s, labels matched for banp's ingress peer, nsLabels %s, podLabels %s", banp.Name, labels.Set(nsLabels).String(), labels.Set(podLabels).String())
×
986
                        changed.ruleNames = ingressRuleNames
×
987
                        changed.field = ChangedIngressRule
×
988
                        c.updateBanpQueue.Add(changed)
×
989
                }
×
990

991
                if !isRulesArrayEmpty(egressRuleNames) {
×
992
                        klog.Infof("banp %s, labels matched for banp's egress peer, nsLabels %s, podLabels %s", banp.Name, labels.Set(nsLabels).String(), labels.Set(podLabels).String())
×
993
                        changed.ruleNames = egressRuleNames
×
994
                        changed.field = ChangedEgressRule
×
995
                        c.updateBanpQueue.Add(changed)
×
996
                }
×
997
        }
998
}
999

1000
func isLabelsMatch(namespaces *metav1.LabelSelector, pods *v1alpha1.NamespacedPod, nsLabels, podLabels map[string]string) bool {
1✔
1001
        // Exactly one field of namespaces/pods must be set.
1✔
1002
        if namespaces != nil {
2✔
1003
                nsSelector, _ := metav1.LabelSelectorAsSelector(namespaces)
1✔
1004
                klog.V(3).Infof("namespaces is not nil, nsSelector %s", nsSelector.String())
1✔
1005
                if nsSelector.Matches(labels.Set(nsLabels)) {
2✔
1006
                        return true
1✔
1007
                }
1✔
1008
        } else if pods != nil {
2✔
1009
                nsSelector, _ := metav1.LabelSelectorAsSelector(&pods.NamespaceSelector)
1✔
1010
                podSelector, _ := metav1.LabelSelectorAsSelector(&pods.PodSelector)
1✔
1011
                klog.V(3).Infof("pods is not nil, nsSelector %s, podSelector %s", nsSelector.String(), podSelector.String())
1✔
1012
                if nsSelector.Matches(labels.Set(nsLabels)) && podSelector.Matches(labels.Set(podLabels)) {
2✔
1013
                        return true
1✔
1014
                }
1✔
1015
        }
1016

1017
        return false
1✔
1018
}
1019

1020
func isLabelsMatchRulePeers(from []v1alpha1.AdminNetworkPolicyIngressPeer, to []v1alpha1.AdminNetworkPolicyEgressPeer, nsLabels, podLabels map[string]string) bool {
×
1021
        return isLabelsMatchRulePeersCommon(from, to, nil, nsLabels, podLabels)
×
1022
}
×
1023

1024
func isLabelsMatchBaselineRulePeers(from []v1alpha1.AdminNetworkPolicyIngressPeer, to []v1alpha1.BaselineAdminNetworkPolicyEgressPeer, nsLabels, podLabels map[string]string) bool {
×
1025
        return isLabelsMatchRulePeersCommon(from, nil, to, nsLabels, podLabels)
×
1026
}
×
1027

1028
func isLabelsMatchRulePeersCommon(from []v1alpha1.AdminNetworkPolicyIngressPeer, to []v1alpha1.AdminNetworkPolicyEgressPeer, baselineTo []v1alpha1.BaselineAdminNetworkPolicyEgressPeer, nsLabels, podLabels map[string]string) bool {
×
1029
        for _, ingressPeer := range from {
×
1030
                if isLabelsMatch(ingressPeer.Namespaces, ingressPeer.Pods, nsLabels, podLabels) {
×
1031
                        return true
×
1032
                }
×
1033
        }
1034

1035
        if to != nil {
×
1036
                for _, egressPeer := range to {
×
1037
                        if isLabelsMatch(egressPeer.Namespaces, egressPeer.Pods, nsLabels, podLabels) {
×
1038
                                return true
×
1039
                        }
×
1040
                }
1041
        } else {
×
1042
                for _, egressPeer := range baselineTo {
×
1043
                        if isLabelsMatch(egressPeer.Namespaces, egressPeer.Pods, nsLabels, podLabels) {
×
1044
                                return true
×
1045
                        }
×
1046
                }
1047
        }
1048

1049
        return false
×
1050
}
1051

1052
func isLabelsMatchAnpRulePeers(ingress []v1alpha1.AdminNetworkPolicyIngressRule, egress []v1alpha1.AdminNetworkPolicyEgressRule, nsLabels, podLabels map[string]string) ([util.AnpMaxRules]ChangedName, [util.AnpMaxRules]ChangedName) {
×
1053
        return isLabelsMatchAnpRulePeersCommon(ingress, egress, nil, nsLabels, podLabels)
×
1054
}
×
1055

1056
func isLabelsMatchBaselineAnpRulePeers(_ []v1alpha1.BaselineAdminNetworkPolicyIngressRule, egress []v1alpha1.BaselineAdminNetworkPolicyEgressRule, nsLabels, podLabels map[string]string) ([util.AnpMaxRules]ChangedName, [util.AnpMaxRules]ChangedName) {
×
1057
        return isLabelsMatchAnpRulePeersCommon(nil, nil, egress, nsLabels, podLabels)
×
1058
}
×
1059

1060
func isLabelsMatchAnpRulePeersCommon(ingress []v1alpha1.AdminNetworkPolicyIngressRule, egress []v1alpha1.AdminNetworkPolicyEgressRule, baselineEgress []v1alpha1.BaselineAdminNetworkPolicyEgressRule, nsLabels, podLabels map[string]string) ([util.AnpMaxRules]ChangedName, [util.AnpMaxRules]ChangedName) {
×
1061
        var changedIngressRuleNames, changedEgressRuleNames [util.AnpMaxRules]ChangedName
×
1062

×
1063
        for index, anpr := range ingress {
×
1064
                if isLabelsMatchRulePeers(anpr.From, []v1alpha1.AdminNetworkPolicyEgressPeer{}, nsLabels, podLabels) {
×
1065
                        changedIngressRuleNames[index].isMatch = true
×
1066
                        changedIngressRuleNames[index].curRuleName = anpr.Name
×
1067
                }
×
1068
        }
1069

1070
        if egress != nil {
×
1071
                for index, anpr := range egress {
×
1072
                        if isLabelsMatchRulePeers([]v1alpha1.AdminNetworkPolicyIngressPeer{}, anpr.To, nsLabels, podLabels) {
×
1073
                                changedEgressRuleNames[index].isMatch = true
×
1074
                                changedEgressRuleNames[index].curRuleName = anpr.Name
×
1075
                        }
×
1076
                }
1077
        } else {
×
1078
                for index, banpr := range baselineEgress {
×
1079
                        if isLabelsMatchBaselineRulePeers([]v1alpha1.AdminNetworkPolicyIngressPeer{}, banpr.To, nsLabels, podLabels) {
×
1080
                                changedEgressRuleNames[index].isMatch = true
×
1081
                                changedEgressRuleNames[index].curRuleName = banpr.Name
×
1082
                        }
×
1083
                }
1084
        }
1085

1086
        return changedIngressRuleNames, changedEgressRuleNames
×
1087
}
1088

1089
func isLabelsMatchBanpRulePeers(ingress []v1alpha1.BaselineAdminNetworkPolicyIngressRule, egress []v1alpha1.BaselineAdminNetworkPolicyEgressRule, nsLabels, podLabels map[string]string) ([util.AnpMaxRules]ChangedName, [util.AnpMaxRules]ChangedName) {
×
1090
        return isLabelsMatchBaselineAnpRulePeers(ingress, egress, nsLabels, podLabels)
×
1091
}
×
1092

1093
func getAnpName(name string) string {
1✔
1094
        anpName := name
1✔
1095
        nameArray := []rune(name)
1✔
1096
        if !unicode.IsLetter(nameArray[0]) {
2✔
1097
                anpName = "anp" + name
1✔
1098
        }
1✔
1099
        return anpName
1✔
1100
}
1101

1102
func getAnpAddressSetName(pgName, ruleName string, index int, isIngress bool) (string, string) {
1✔
1103
        var asV4Name, asV6Name string
1✔
1104
        if isIngress {
2✔
1105
                // In case ruleName is omitted, add direction and index to distinguish address-set
1✔
1106
                asV4Name = strings.ReplaceAll(fmt.Sprintf("%s.ingress.%d.%s.%s", pgName, index, ruleName, kubeovnv1.ProtocolIPv4), "-", ".")
1✔
1107
                asV6Name = strings.ReplaceAll(fmt.Sprintf("%s.ingress.%d.%s.%s", pgName, index, ruleName, kubeovnv1.ProtocolIPv6), "-", ".")
1✔
1108
        } else {
2✔
1109
                asV4Name = strings.ReplaceAll(fmt.Sprintf("%s.egress.%d.%s.%s", pgName, index, ruleName, kubeovnv1.ProtocolIPv4), "-", ".")
1✔
1110
                asV6Name = strings.ReplaceAll(fmt.Sprintf("%s.egress.%d.%s.%s", pgName, index, ruleName, kubeovnv1.ProtocolIPv6), "-", ".")
1✔
1111
        }
1✔
1112

1113
        return asV4Name, asV6Name
1✔
1114
}
1115

1116
func anpACLAction(action v1alpha1.AdminNetworkPolicyRuleAction) ovnnb.ACLAction {
1✔
1117
        switch action {
1✔
1118
        case v1alpha1.AdminNetworkPolicyRuleActionAllow:
1✔
1119
                return ovnnb.ACLActionAllowRelated
1✔
1120
        case v1alpha1.AdminNetworkPolicyRuleActionDeny:
1✔
1121
                return ovnnb.ACLActionDrop
1✔
1122
        case v1alpha1.AdminNetworkPolicyRuleActionPass:
1✔
1123
                return ovnnb.ACLActionPass
1✔
1124
        }
1125
        return ovnnb.ACLActionDrop
1✔
1126
}
1127

1128
func isRulesArrayEmpty(ruleNames [util.AnpMaxRules]ChangedName) bool {
1✔
1129
        for _, ruleName := range ruleNames {
2✔
1130
                // The ruleName can be omitted default
1✔
1131
                if ruleName.curRuleName != "" || ruleName.isMatch {
2✔
1132
                        return false
1✔
1133
                }
1✔
1134
        }
1135
        return true
1✔
1136
}
1137

1138
func (c *Controller) fetchNodesAddrs(nodeSelector labels.Selector) ([]string, []string, error) {
×
1139
        nodes, err := c.nodesLister.List(nodeSelector)
×
1140
        if err != nil {
×
1141
                klog.Errorf("failed to list nodes: %v", err)
×
1142
                return nil, nil, err
×
1143
        }
×
1144
        v4Addresses := make([]string, 0, len(nodes))
×
1145
        v6Addresses := make([]string, 0, len(nodes))
×
1146

×
1147
        klog.V(3).Infof("fetch nodes addresses, selector is %s", nodeSelector.String())
×
1148
        for _, node := range nodes {
×
1149
                nodeIPv4, nodeIPv6 := util.GetNodeInternalIP(*node)
×
1150
                if nodeIPv4 != "" {
×
1151
                        v4Addresses = append(v4Addresses, nodeIPv4)
×
1152
                }
×
1153
                if nodeIPv6 != "" {
×
1154
                        v6Addresses = append(v6Addresses, nodeIPv6)
×
1155
                }
×
1156
        }
1157

1158
        return v4Addresses, v6Addresses, nil
×
1159
}
1160

1161
func fetchCIDRAddrs(networks []v1alpha1.CIDR) ([]string, []string) {
1✔
1162
        var v4Addresses, v6Addresses []string
1✔
1163

1✔
1164
        for _, network := range networks {
2✔
1165
                if _, _, err := net.ParseCIDR(string(network)); err != nil {
2✔
1166
                        klog.Errorf("invalid cidr %s", string(network))
1✔
1167
                        continue
1✔
1168
                }
1169
                switch util.CheckProtocol(string(network)) {
1✔
1170
                case kubeovnv1.ProtocolIPv4:
1✔
1171
                        v4Addresses = append(v4Addresses, string(network))
1✔
1172
                case kubeovnv1.ProtocolIPv6:
1✔
1173
                        v6Addresses = append(v6Addresses, string(network))
1✔
1174
                }
1175
        }
1176

1177
        return v4Addresses, v6Addresses
1✔
1178
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc