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

kubeovn / kube-ovn / 19917541193

04 Dec 2025 04:19AM UTC coverage: 22.257% (-0.02%) from 22.277%
19917541193

push

github

oilbeater
np: allow icmpv6 to ipv6 ready check

So that we can remove trigger all np updates when subnet gw or uo2ip change.

Signed-off-by: Mengxin Liu <liumengxinfly@gmail.com>

6 of 16 new or added lines in 3 files covered. (37.5%)

6 existing lines in 4 files now uncovered.

11537 of 51836 relevant lines covered (22.26%)

0.26 hits per line

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

0.0
/pkg/controller/network_policy.go
1
package controller
2

3
import (
4
        "fmt"
5
        "maps"
6
        "reflect"
7
        "slices"
8
        "strconv"
9
        "strings"
10
        "unicode"
11

12
        "github.com/scylladb/go-set/strset"
13
        corev1 "k8s.io/api/core/v1"
14
        netv1 "k8s.io/api/networking/v1"
15
        k8serrors "k8s.io/apimachinery/pkg/api/errors"
16
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17
        "k8s.io/apimachinery/pkg/labels"
18
        utilruntime "k8s.io/apimachinery/pkg/util/runtime"
19
        "k8s.io/client-go/tools/cache"
20
        "k8s.io/klog/v2"
21
        "k8s.io/utils/set"
22

23
        kubeovnv1 "github.com/kubeovn/kube-ovn/pkg/apis/kubeovn/v1"
24
        "github.com/kubeovn/kube-ovn/pkg/ovs"
25
        "github.com/kubeovn/kube-ovn/pkg/ovsdb/ovnnb"
26
        "github.com/kubeovn/kube-ovn/pkg/util"
27
)
28

29
const (
30
        NetworkPolicyEnforcementStandard = "standard"
31
        NetworkPolicyEnforcementLax      = "lax"
32
)
33

34
func (c *Controller) enqueueAddNp(obj any) {
×
35
        key := cache.MetaObjectToName(obj.(*netv1.NetworkPolicy)).String()
×
36
        klog.V(3).Infof("enqueue add network policy %s", key)
×
37
        c.updateNpQueue.Add(key)
×
38
}
×
39

40
func (c *Controller) enqueueDeleteNp(obj any) {
×
41
        var np *netv1.NetworkPolicy
×
42
        switch t := obj.(type) {
×
43
        case *netv1.NetworkPolicy:
×
44
                np = t
×
45
        case cache.DeletedFinalStateUnknown:
×
46
                n, ok := t.Obj.(*netv1.NetworkPolicy)
×
47
                if !ok {
×
48
                        klog.Warningf("unexpected object type: %T", t.Obj)
×
49
                        return
×
50
                }
×
51
                np = n
×
52
        default:
×
53
                klog.Warningf("unexpected type: %T", obj)
×
54
                return
×
55
        }
56

57
        key := cache.MetaObjectToName(np).String()
×
58
        klog.V(3).Infof("enqueue delete network policy %s", key)
×
59
        c.deleteNpQueue.Add(key)
×
60
}
61

62
func (c *Controller) enqueueUpdateNp(oldObj, newObj any) {
×
63
        oldNp := oldObj.(*netv1.NetworkPolicy)
×
64
        newNp := newObj.(*netv1.NetworkPolicy)
×
65
        if !reflect.DeepEqual(oldNp.Spec, newNp.Spec) ||
×
66
                !maps.Equal(oldNp.Annotations, newNp.Annotations) {
×
67
                key := cache.MetaObjectToName(newNp).String()
×
68
                klog.V(3).Infof("enqueue update np %s", key)
×
69
                c.updateNpQueue.Add(key)
×
70
        }
×
71
}
72

73
func (c *Controller) createAsForNetpol(ns, name, direction, asName string, addresses []string) error {
×
74
        if err := c.OVNNbClient.CreateAddressSet(asName, map[string]string{
×
75
                networkPolicyKey: fmt.Sprintf("%s/%s/%s", ns, name, direction),
×
76
        }); err != nil {
×
77
                klog.Errorf("failed to create ovn address set %s for np %s/%s: %v", asName, ns, name, err)
×
78
                return err
×
79
        }
×
80

81
        if err := c.OVNNbClient.AddressSetUpdateAddress(asName, addresses...); err != nil {
×
82
                klog.Errorf("failed to set addresses %q to address set %s: %v", strings.Join(addresses, ","), asName, err)
×
83
                return err
×
84
        }
×
85

86
        return nil
×
87
}
88

89
func (c *Controller) handleUpdateNp(key string) error {
×
90
        namespace, name, err := cache.SplitMetaNamespaceKey(key)
×
91
        if err != nil {
×
92
                utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key))
×
93
                return nil
×
94
        }
×
95

96
        c.npKeyMutex.LockKey(key)
×
97
        defer func() { _ = c.npKeyMutex.UnlockKey(key) }()
×
98
        klog.Infof("handle add/update network policy %s", key)
×
99

×
100
        np, err := c.npsLister.NetworkPolicies(namespace).Get(name)
×
101
        if err != nil {
×
102
                if k8serrors.IsNotFound(err) {
×
103
                        return nil
×
104
                }
×
105
                klog.Error(err)
×
106
                return err
×
107
        }
108

109
        defer func() {
×
110
                if err != nil {
×
111
                        c.recorder.Eventf(np, corev1.EventTypeWarning, "CreateACLFailed", err.Error())
×
112
                }
×
113
        }()
114

115
        logEnable := np.Annotations[util.NetworkPolicyLogAnnotation] == "true"
×
116

×
117
        var logActions []string
×
118
        if np.Annotations[util.ACLActionsLogAnnotation] != "" {
×
119
                logActions = strings.Split(np.Annotations[util.ACLActionsLogAnnotation], ",")
×
120
        } else {
×
121
                logActions = []string{ovnnb.ACLActionDrop}
×
122
        }
×
123
        logRate := parseACLLogRate(np.Annotations)
×
124

×
125
        npName := np.Name
×
126
        nameArray := []rune(np.Name)
×
127
        if !unicode.IsLetter(nameArray[0]) {
×
128
                npName = "np" + np.Name
×
129
        }
×
130

131
        // TODO: ovn acl doesn't support address_set name with '-', now we replace '-' by '.'.
132
        // This may cause conflict if two np with name test-np and test.np. Maybe hash is a better solution,
133
        // but we do not want to lost the readability now.
134
        pgName := strings.ReplaceAll(fmt.Sprintf("%s.%s", npName, np.Namespace), "-", ".")
×
135
        ingressAllowAsNamePrefix := strings.ReplaceAll(fmt.Sprintf("%s.%s.ingress.allow", npName, np.Namespace), "-", ".")
×
136
        ingressExceptAsNamePrefix := strings.ReplaceAll(fmt.Sprintf("%s.%s.ingress.except", npName, np.Namespace), "-", ".")
×
137
        egressAllowAsNamePrefix := strings.ReplaceAll(fmt.Sprintf("%s.%s.egress.allow", npName, np.Namespace), "-", ".")
×
138
        egressExceptAsNamePrefix := strings.ReplaceAll(fmt.Sprintf("%s.%s.egress.except", npName, np.Namespace), "-", ".")
×
139

×
140
        if err = c.OVNNbClient.CreatePortGroup(pgName, map[string]string{networkPolicyKey: np.Namespace + "/" + npName}); err != nil {
×
141
                klog.Errorf("create port group for np %s: %v", key, err)
×
142
                return err
×
143
        }
×
144

145
        namedPortMap := c.namedPort.GetNamedPortByNs(np.Namespace)
×
146
        ports, subnetNames, err := c.fetchSelectedPorts(np.Namespace, &np.Spec.PodSelector)
×
147
        if err != nil {
×
148
                klog.Errorf("fetch ports belongs to np %s: %v", key, err)
×
149
                return err
×
150
        }
×
151

152
        protocolSet := strset.NewWithSize(2)
×
153
        for _, subnetName := range subnetNames {
×
154
                subnet, err := c.subnetsLister.Get(subnetName)
×
155
                if err != nil {
×
156
                        klog.Errorf("failed to get pod's subnet %s, %v", subnetName, err)
×
157
                        return err
×
158
                }
×
159

160
                if subnet.Spec.Protocol == kubeovnv1.ProtocolDual {
×
161
                        protocolSet.Add(kubeovnv1.ProtocolIPv4, kubeovnv1.ProtocolIPv6)
×
162
                } else {
×
163
                        protocolSet.Add(subnet.Spec.Protocol)
×
164
                }
×
165
        }
166
        klog.Infof("UpdateNp, related subnets protocols %s", protocolSet.String())
×
167

×
168
        if err = c.OVNNbClient.PortGroupSetPorts(pgName, ports); err != nil {
×
169
                klog.Errorf("failed to set ports of port group %s to %v: %v", pgName, ports, err)
×
170
                return err
×
171
        }
×
172

173
        ingressACLOps, err := c.OVNNbClient.DeleteAclsOps(pgName, portGroupKey, "to-lport", nil)
×
174
        if err != nil {
×
175
                klog.Errorf("generate operations that clear np %s ingress acls: %v", key, err)
×
176
                return err
×
177
        }
×
178

179
        enforcementLax := c.isNetworkPolicyEnforcementLax(np)
×
180
        if hasIngressRule(np) {
×
181
                if protocolSet.Size() > 0 {
×
182
                        blockACLOps, err := c.OVNNbClient.UpdateDefaultBlockACLOps(key, pgName, ovnnb.ACLDirectionToLport, logEnable, enforcementLax, logRate)
×
183
                        if err != nil {
×
184
                                klog.Errorf("failed to set default ingress block acl: %v", err)
×
185
                                return fmt.Errorf("failed to set default ingress block acl: %w", err)
×
186
                        }
×
187
                        ingressACLOps = append(ingressACLOps, blockACLOps...)
×
188

×
189
                        if enforcementLax {
×
190
                                defaultBlockExceptions, err := c.OVNNbClient.UpdateDefaultBlockExceptionsACLOps(key, pgName, np.Namespace, ovnnb.ACLDirectionToLport)
×
191
                                if err != nil {
×
192
                                        klog.Errorf("failed to set default block exceptions for ingress acl: %v", err)
×
193
                                        return fmt.Errorf("failed to set default block exceptions for ingress acl: %w", err)
×
194
                                }
×
195
                                ingressACLOps = append(ingressACLOps, defaultBlockExceptions...)
×
196
                        }
197
                }
198

199
                for _, protocol := range protocolSet.List() {
×
200
                        for idx, npr := range np.Spec.Ingress {
×
201
                                // 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
×
202
                                ingressAllowAsName := fmt.Sprintf("%s.%s.%d", ingressAllowAsNamePrefix, protocol, idx)
×
203
                                ingressExceptAsName := fmt.Sprintf("%s.%s.%d", ingressExceptAsNamePrefix, protocol, idx)
×
204
                                aclName := fmt.Sprintf("np/%s.%s/ingress/%s/%d", npName, np.Namespace, protocol, idx)
×
205

×
206
                                var allows, excepts []string
×
207
                                if len(npr.From) == 0 {
×
208
                                        if protocol == kubeovnv1.ProtocolIPv4 {
×
209
                                                allows = []string{"0.0.0.0/0"}
×
210
                                        } else {
×
211
                                                allows = []string{"::/0"}
×
212
                                        }
×
213
                                } else {
×
214
                                        var allow, except []string
×
215
                                        for _, npp := range npr.From {
×
216
                                                if allow, except, err = c.fetchPolicySelectedAddresses(np.Namespace, protocol, npp); err != nil {
×
217
                                                        klog.Errorf("failed to fetch policy selected addresses, %v", err)
×
218
                                                        return err
×
219
                                                }
×
220
                                                allows = append(allows, allow...)
×
221
                                                excepts = append(excepts, except...)
×
222
                                        }
223
                                }
224
                                klog.Infof("UpdateNp Ingress, allows is %v, excepts is %v, log %v, protocol %v", allows, excepts, logEnable, protocol)
×
225

×
226
                                if err = c.createAsForNetpol(np.Namespace, npName, "ingress", ingressAllowAsName, allows); err != nil {
×
227
                                        klog.Error(err)
×
228
                                        return err
×
229
                                }
×
230
                                if err = c.createAsForNetpol(np.Namespace, npName, "ingress", ingressExceptAsName, excepts); err != nil {
×
231
                                        klog.Error(err)
×
232
                                        return err
×
233
                                }
×
234

235
                                npp := []netv1.NetworkPolicyPort{}
×
236
                                if len(allows) != 0 || len(excepts) != 0 {
×
237
                                        npp = npr.Ports
×
238
                                }
×
239

240
                                ops, err := c.OVNNbClient.UpdateIngressACLOps(pgName, ingressAllowAsName, ingressExceptAsName, protocol, aclName, npp, logEnable, logActions, logRate, namedPortMap)
×
241
                                if err != nil {
×
242
                                        klog.Errorf("generate operations that add ingress acls to np %s: %v", key, err)
×
243
                                        return err
×
244
                                }
×
245

246
                                ingressACLOps = append(ingressACLOps, ops...)
×
247
                        }
248
                        if len(np.Spec.Ingress) == 0 {
×
249
                                ingressAllowAsName := fmt.Sprintf("%s.%s.all", ingressAllowAsNamePrefix, protocol)
×
250
                                ingressExceptAsName := fmt.Sprintf("%s.%s.all", ingressExceptAsNamePrefix, protocol)
×
251
                                aclName := fmt.Sprintf("np/%s.%s/ingress/%s/all", npName, np.Namespace, protocol)
×
252

×
253
                                if err = c.createAsForNetpol(np.Namespace, npName, "ingress", ingressAllowAsName, nil); err != nil {
×
254
                                        klog.Error(err)
×
255
                                        return err
×
256
                                }
×
257
                                if err = c.createAsForNetpol(np.Namespace, npName, "ingress", ingressExceptAsName, nil); err != nil {
×
258
                                        klog.Error(err)
×
259
                                        return err
×
260
                                }
×
261

262
                                ops, err := c.OVNNbClient.UpdateIngressACLOps(pgName, ingressAllowAsName, ingressExceptAsName, protocol, aclName, nil, logEnable, logActions, logRate, namedPortMap)
×
263
                                if err != nil {
×
264
                                        klog.Errorf("generate operations that add ingress acls to np %s: %v", key, err)
×
265
                                        return err
×
266
                                }
×
267

268
                                ingressACLOps = append(ingressACLOps, ops...)
×
269
                        }
270
                }
271

272
                if err := c.OVNNbClient.Transact("add-ingress-acls", ingressACLOps); err != nil {
×
273
                        return fmt.Errorf("add ingress acls to %s: %w", pgName, err)
×
274
                }
×
275

276
                if err := c.OVNNbClient.SetACLLog(pgName, logEnable, true); err != nil {
×
277
                        // just log and do not return err here
×
278
                        klog.Errorf("failed to set ingress acl log for np %s, %v", key, err)
×
279
                }
×
280

281
                ass, err := c.OVNNbClient.ListAddressSets(map[string]string{
×
282
                        networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, npName, "ingress"),
×
283
                })
×
284
                if err != nil {
×
285
                        klog.Errorf("list np %s address sets: %v", key, err)
×
286
                        return err
×
287
                }
×
288

289
                // The format of asName is like "test.network.policy.test.ingress.except.0" or "test.network.policy.test.ingress.allow.0" for ingress
290
                for _, as := range ass {
×
291
                        values := strings.Split(as.Name, ".")
×
292
                        if len(values) <= 1 {
×
293
                                continue
×
294
                        }
295
                        idxStr := values[len(values)-1]
×
296
                        if idxStr == "all" {
×
297
                                continue
×
298
                        }
299
                        idx, _ := strconv.Atoi(idxStr)
×
300
                        if idx >= len(np.Spec.Ingress) {
×
301
                                if err = c.OVNNbClient.DeleteAddressSet(as.Name); err != nil {
×
302
                                        klog.Errorf("failed to delete np %s address set, %v", key, err)
×
303
                                        return err
×
304
                                }
×
305
                        }
306
                }
307
        } else {
×
308
                if err = c.OVNNbClient.DeleteAcls(pgName, portGroupKey, "to-lport", nil); err != nil {
×
309
                        klog.Errorf("delete np %s ingress acls: %v", key, err)
×
310
                        return err
×
311
                }
×
312

313
                if err := c.OVNNbClient.DeleteAddressSets(map[string]string{
×
314
                        networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, npName, "ingress"),
×
315
                }); err != nil {
×
316
                        klog.Errorf("delete np %s ingress address set: %v", key, err)
×
317
                        return err
×
318
                }
×
319
        }
320

321
        egressACLOps, err := c.OVNNbClient.DeleteAclsOps(pgName, portGroupKey, "from-lport", nil)
×
322
        if err != nil {
×
323
                klog.Errorf("generate operations that clear np %s egress acls: %v", key, err)
×
324
                return err
×
325
        }
×
326

327
        if hasEgressRule(np) {
×
328
                if protocolSet.Size() > 0 {
×
329
                        blockACLOps, err := c.OVNNbClient.UpdateDefaultBlockACLOps(key, pgName, ovnnb.ACLDirectionFromLport, logEnable, enforcementLax, logRate)
×
330
                        if err != nil {
×
331
                                klog.Errorf("failed to set default egress block acl: %v", err)
×
332
                                return fmt.Errorf("failed to set default egress block acl: %w", err)
×
333
                        }
×
334
                        egressACLOps = append(egressACLOps, blockACLOps...)
×
335

×
336
                        if enforcementLax {
×
337
                                defaultBlockExceptions, err := c.OVNNbClient.UpdateDefaultBlockExceptionsACLOps(key, pgName, np.Namespace, ovnnb.ACLDirectionFromLport)
×
338
                                if err != nil {
×
339
                                        klog.Errorf("failed to set default block exceptions for ingress acl: %v", err)
×
340
                                        return fmt.Errorf("failed to set default block exceptions for ingress acl: %w", err)
×
341
                                }
×
342
                                egressACLOps = append(egressACLOps, defaultBlockExceptions...)
×
343
                        }
344
                }
345

346
                for _, protocol := range protocolSet.List() {
×
347
                        for idx, npr := range np.Spec.Egress {
×
348
                                // 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
×
349
                                egressAllowAsName := fmt.Sprintf("%s.%s.%d", egressAllowAsNamePrefix, protocol, idx)
×
350
                                egressExceptAsName := fmt.Sprintf("%s.%s.%d", egressExceptAsNamePrefix, protocol, idx)
×
351
                                aclName := fmt.Sprintf("np/%s.%s/egress/%s/%d", npName, np.Namespace, protocol, idx)
×
352

×
353
                                var allows, excepts []string
×
354
                                if len(npr.To) == 0 {
×
355
                                        if protocol == kubeovnv1.ProtocolIPv4 {
×
356
                                                allows = []string{"0.0.0.0/0"}
×
357
                                        } else {
×
358
                                                allows = []string{"::/0"}
×
359
                                        }
×
360
                                } else {
×
361
                                        var allow, except []string
×
362
                                        for _, npp := range npr.To {
×
363
                                                if allow, except, err = c.fetchPolicySelectedAddresses(np.Namespace, protocol, npp); err != nil {
×
364
                                                        klog.Errorf("failed to fetch policy selected addresses, %v", err)
×
365
                                                        return err
×
366
                                                }
×
367
                                                allows = append(allows, allow...)
×
368
                                                excepts = append(excepts, except...)
×
369
                                        }
370
                                }
371
                                klog.Infof("UpdateNp Egress %s, allows is %v, excepts is %v, log %v", aclName, allows, excepts, logEnable)
×
372

×
373
                                if err = c.createAsForNetpol(np.Namespace, npName, "egress", egressAllowAsName, allows); err != nil {
×
374
                                        klog.Error(err)
×
375
                                        return err
×
376
                                }
×
377
                                if err = c.createAsForNetpol(np.Namespace, npName, "egress", egressExceptAsName, excepts); err != nil {
×
378
                                        klog.Error(err)
×
379
                                        return err
×
380
                                }
×
381

382
                                npp := []netv1.NetworkPolicyPort{}
×
383
                                if len(allows) != 0 || len(excepts) != 0 {
×
384
                                        npp = npr.Ports
×
385
                                }
×
386

387
                                ops, err := c.OVNNbClient.UpdateEgressACLOps(pgName, egressAllowAsName, egressExceptAsName, protocol, aclName, npp, logEnable, logActions, logRate, namedPortMap)
×
388
                                if err != nil {
×
389
                                        klog.Errorf("generate operations that add egress acls to np %s: %v", key, err)
×
390
                                        return err
×
391
                                }
×
392

393
                                egressACLOps = append(egressACLOps, ops...)
×
394
                        }
395
                        if len(np.Spec.Egress) == 0 {
×
396
                                egressAllowAsName := fmt.Sprintf("%s.%s.all", egressAllowAsNamePrefix, protocol)
×
397
                                egressExceptAsName := fmt.Sprintf("%s.%s.all", egressExceptAsNamePrefix, protocol)
×
398
                                aclName := fmt.Sprintf("np/%s.%s/egress/%s/all", npName, np.Namespace, protocol)
×
399

×
400
                                if err = c.createAsForNetpol(np.Namespace, npName, "egress", egressAllowAsName, nil); err != nil {
×
401
                                        klog.Error(err)
×
402
                                        return err
×
403
                                }
×
404
                                if err = c.createAsForNetpol(np.Namespace, npName, "egress", egressExceptAsName, nil); err != nil {
×
405
                                        klog.Error(err)
×
406
                                        return err
×
407
                                }
×
408

409
                                ops, err := c.OVNNbClient.UpdateEgressACLOps(pgName, egressAllowAsName, egressExceptAsName, protocol, aclName, nil, logEnable, logActions, logRate, namedPortMap)
×
410
                                if err != nil {
×
411
                                        klog.Errorf("generate operations that add egress acls to np %s: %v", key, err)
×
412
                                        return err
×
413
                                }
×
414

415
                                egressACLOps = append(egressACLOps, ops...)
×
416
                        }
417
                }
418

419
                if err := c.OVNNbClient.Transact("add-egress-acls", egressACLOps); err != nil {
×
420
                        return fmt.Errorf("add egress acls to %s: %w", pgName, err)
×
421
                }
×
422

423
                if err := c.OVNNbClient.SetACLLog(pgName, logEnable, false); err != nil {
×
424
                        // just log and do not return err here
×
425
                        klog.Errorf("failed to set egress acl log for np %s, %v", key, err)
×
426
                }
×
427

428
                ass, err := c.OVNNbClient.ListAddressSets(map[string]string{
×
429
                        networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, npName, "egress"),
×
430
                })
×
431
                if err != nil {
×
432
                        klog.Errorf("list np %s address sets: %v", key, err)
×
433
                        return err
×
434
                }
×
435

436
                // The format of asName is like "test.network.policy.test.egress.except.0" or "test.network.policy.test.egress.allow.0" for egress
437
                for _, as := range ass {
×
438
                        values := strings.Split(as.Name, ".")
×
439
                        if len(values) <= 1 {
×
440
                                continue
×
441
                        }
442
                        idxStr := values[len(values)-1]
×
443
                        if idxStr == "all" {
×
444
                                continue
×
445
                        }
446

447
                        idx, _ := strconv.Atoi(idxStr)
×
448
                        if idx >= len(np.Spec.Egress) {
×
449
                                if err = c.OVNNbClient.DeleteAddressSet(as.Name); err != nil {
×
450
                                        klog.Errorf("delete np %s address set: %v", key, err)
×
451
                                        return err
×
452
                                }
×
453
                        }
454
                }
455
        } else {
×
456
                if err = c.OVNNbClient.DeleteAcls(pgName, portGroupKey, "from-lport", nil); err != nil {
×
457
                        klog.Errorf("delete np %s egress acls: %v", key, err)
×
458
                        return err
×
459
                }
×
460

461
                if err := c.OVNNbClient.DeleteAddressSets(map[string]string{
×
462
                        networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, npName, "egress"),
×
463
                }); err != nil {
×
464
                        klog.Errorf("delete np %s egress address set: %v", key, err)
×
465
                        return err
×
466
                }
×
467
        }
468

NEW
469
        if !enforcementLax && protocolSet.Has(kubeovnv1.ProtocolIPv6) {
×
NEW
470
                if err = c.OVNNbClient.CreateGatewayACL("", pgName); err != nil {
×
NEW
471
                        klog.Errorf("create gateway acl: %v", err)
×
NEW
472
                        return err
×
UNCOV
473
                }
×
474
        }
475
        return nil
×
476
}
477

478
func (c *Controller) handleDeleteNp(key string) error {
×
479
        namespace, name, err := cache.SplitMetaNamespaceKey(key)
×
480
        if err != nil {
×
481
                utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key))
×
482
                return nil
×
483
        }
×
484

485
        c.npKeyMutex.LockKey(key)
×
486
        defer func() { _ = c.npKeyMutex.UnlockKey(key) }()
×
487
        klog.Infof("handle delete network policy %s", key)
×
488

×
489
        npName := name
×
490
        nameArray := []rune(name)
×
491
        if !unicode.IsLetter(nameArray[0]) {
×
492
                npName = "np" + name
×
493
        }
×
494

495
        pgName := strings.ReplaceAll(fmt.Sprintf("%s.%s", npName, namespace), "-", ".")
×
496
        ingressMeterName := fmt.Sprintf("%s_to-lport_meter", pgName)
×
497
        egressMeterName := fmt.Sprintf("%s_from-lport_meter", pgName)
×
498

×
499
        if err := c.OVNNbClient.DeleteMeter(ingressMeterName); err != nil {
×
500
                klog.Errorf("delete ingress meter %s for np %s: %v", ingressMeterName, key, err)
×
501
        }
×
502

503
        if err := c.OVNNbClient.DeleteMeter(egressMeterName); err != nil {
×
504
                klog.Errorf("delete egress meter %s for np %s: %v", egressMeterName, key, err)
×
505
        }
×
506

507
        if err = c.OVNNbClient.DeletePortGroup(pgName); err != nil {
×
508
                klog.Errorf("delete np %s port group: %v", key, err)
×
509
        }
×
510

511
        if err := c.OVNNbClient.DeleteAddressSets(map[string]string{
×
512
                networkPolicyKey: fmt.Sprintf("%s/%s/%s", namespace, npName, "service"),
×
513
        }); err != nil {
×
514
                klog.Errorf("delete np %s service address set: %v", key, err)
×
515
                return err
×
516
        }
×
517

518
        if err := c.OVNNbClient.DeleteAddressSets(map[string]string{
×
519
                networkPolicyKey: fmt.Sprintf("%s/%s/%s", namespace, npName, "ingress"),
×
520
        }); err != nil {
×
521
                klog.Errorf("delete np %s ingress address set: %v", key, err)
×
522
                return err
×
523
        }
×
524

525
        if err := c.OVNNbClient.DeleteAddressSets(map[string]string{
×
526
                networkPolicyKey: fmt.Sprintf("%s/%s/%s", namespace, npName, "egress"),
×
527
        }); err != nil {
×
528
                klog.Errorf("delete np %s egress address set: %v", key, err)
×
529
                return err
×
530
        }
×
531

532
        return nil
×
533
}
534

535
func (c *Controller) fetchSelectedPorts(namespace string, selector *metav1.LabelSelector) ([]string, []string, error) {
×
536
        var subnets []string
×
537
        sel, err := metav1.LabelSelectorAsSelector(selector)
×
538
        if err != nil {
×
539
                return nil, nil, fmt.Errorf("error creating label selector, %w", err)
×
540
        }
×
541
        pods, err := c.podsLister.Pods(namespace).List(sel)
×
542
        if err != nil {
×
543
                return nil, nil, fmt.Errorf("failed to list pods, %w", err)
×
544
        }
×
545

546
        ports := make([]string, 0, len(pods))
×
547
        for _, pod := range pods {
×
548
                if pod.Spec.HostNetwork {
×
549
                        continue
×
550
                }
551
                podName := c.getNameByPod(pod)
×
552
                podNets, err := c.getPodKubeovnNets(pod)
×
553
                if err != nil {
×
554
                        return nil, nil, fmt.Errorf("failed to get pod networks, %w", err)
×
555
                }
×
556

557
                for _, podNet := range podNets {
×
558
                        if !isOvnSubnet(podNet.Subnet) {
×
559
                                continue
×
560
                        }
561

562
                        if pod.Annotations[fmt.Sprintf(util.AllocatedAnnotationTemplate, podNet.ProviderName)] == "true" {
×
563
                                ports = append(ports, ovs.PodNameToPortName(podName, pod.Namespace, podNet.ProviderName))
×
564
                                // Pod selected by networkpolicy has its own subnet which is not the default subnet
×
565
                                subnets = append(subnets, podNet.Subnet.Name)
×
566
                        }
×
567
                }
568
        }
569
        subnets = slices.Compact(subnets)
×
570
        return ports, subnets, nil
×
571
}
572

573
func hasIngressRule(np *netv1.NetworkPolicy) bool {
×
574
        for _, pt := range np.Spec.PolicyTypes {
×
575
                if strings.Contains(string(pt), string(netv1.PolicyTypeIngress)) {
×
576
                        return true
×
577
                }
×
578
        }
579
        return np.Spec.Ingress != nil
×
580
}
581

582
func hasEgressRule(np *netv1.NetworkPolicy) bool {
×
583
        for _, pt := range np.Spec.PolicyTypes {
×
584
                if strings.Contains(string(pt), string(netv1.PolicyTypeEgress)) {
×
585
                        return true
×
586
                }
×
587
        }
588
        return np.Spec.Egress != nil
×
589
}
590

591
func (c *Controller) fetchPolicySelectedAddresses(namespace, protocol string, npp netv1.NetworkPolicyPeer) ([]string, []string, error) {
×
592
        selectedAddresses := []string{}
×
593
        exceptAddresses := []string{}
×
594

×
595
        // ingress.from.ipblock or egress.to.ipblock
×
596
        if npp.IPBlock != nil && util.CheckProtocol(npp.IPBlock.CIDR) == protocol {
×
597
                selectedAddresses = append(selectedAddresses, npp.IPBlock.CIDR)
×
598
                if npp.IPBlock.Except != nil {
×
599
                        exceptAddresses = append(exceptAddresses, npp.IPBlock.Except...)
×
600
                }
×
601
        }
602
        if npp.NamespaceSelector == nil && npp.PodSelector == nil {
×
603
                return selectedAddresses, exceptAddresses, nil
×
604
        }
×
605

606
        selectedNs := []string{}
×
607
        if npp.NamespaceSelector == nil {
×
608
                selectedNs = append(selectedNs, namespace)
×
609
        } else {
×
610
                sel, err := metav1.LabelSelectorAsSelector(npp.NamespaceSelector)
×
611
                if err != nil {
×
612
                        return nil, nil, fmt.Errorf("error creating label selector, %w", err)
×
613
                }
×
614
                nss, err := c.namespacesLister.List(sel)
×
615
                if err != nil {
×
616
                        return nil, nil, fmt.Errorf("failed to list ns, %w", err)
×
617
                }
×
618
                for _, ns := range nss {
×
619
                        selectedNs = append(selectedNs, ns.Name)
×
620
                }
×
621
        }
622

623
        var sel labels.Selector
×
624
        if npp.PodSelector == nil {
×
625
                sel = labels.Everything()
×
626
        } else {
×
627
                sel, _ = metav1.LabelSelectorAsSelector(npp.PodSelector)
×
628
        }
×
629

630
        for _, ns := range selectedNs {
×
631
                pods, err := c.podsLister.Pods(ns).List(sel)
×
632
                if err != nil {
×
633
                        return nil, nil, fmt.Errorf("failed to list pod, %w", err)
×
634
                }
×
635
                svcs, err := c.servicesLister.Services(ns).List(labels.Everything())
×
636
                if err != nil {
×
637
                        klog.Errorf("failed to list svc, %v", err)
×
638
                        return nil, nil, fmt.Errorf("failed to list svc, %w", err)
×
639
                }
×
640

641
                for _, pod := range pods {
×
642
                        podNets, err := c.getPodKubeovnNets(pod)
×
643
                        if err != nil {
×
644
                                klog.Errorf("failed to get pod nets %v", err)
×
645
                                return nil, nil, err
×
646
                        }
×
647
                        for _, podNet := range podNets {
×
648
                                podIPAnnotation := pod.Annotations[fmt.Sprintf(util.IPAddressAnnotationTemplate, podNet.ProviderName)]
×
649
                                podIPs := strings.SplitSeq(podIPAnnotation, ",")
×
650
                                for podIP := range podIPs {
×
651
                                        if podIP != "" && util.CheckProtocol(podIP) == protocol {
×
652
                                                selectedAddresses = append(selectedAddresses, podIP)
×
653
                                        }
×
654
                                }
655
                                if len(svcs) == 0 {
×
656
                                        continue
×
657
                                }
658

659
                                svcIPs, err := svcMatchPods(svcs, pod, protocol)
×
660
                                if err != nil {
×
661
                                        return nil, nil, err
×
662
                                }
×
663
                                selectedAddresses = append(selectedAddresses, svcIPs...)
×
664
                        }
665
                }
666
        }
667
        return selectedAddresses, exceptAddresses, nil
×
668
}
669

670
func svcMatchPods(svcs []*corev1.Service, pod *corev1.Pod, protocol string) ([]string, error) {
×
671
        matchSvcs := []string{}
×
672
        // find svc ip by pod's info
×
673
        for _, svc := range svcs {
×
674
                if isSvcMatchPod(svc, pod) {
×
675
                        clusterIPs := util.ServiceClusterIPs(*svc)
×
676
                        protocolClusterIPs := getProtocolSvcIP(clusterIPs, protocol)
×
677
                        if len(protocolClusterIPs) != 0 {
×
678
                                matchSvcs = append(matchSvcs, protocolClusterIPs...)
×
679
                        }
×
680
                }
681
        }
682
        return matchSvcs, nil
×
683
}
684

685
func getProtocolSvcIP(clusterIPs []string, protocol string) []string {
×
686
        protocolClusterIPs := []string{}
×
687
        for _, clusterIP := range clusterIPs {
×
688
                if clusterIP != "" && clusterIP != corev1.ClusterIPNone && util.CheckProtocol(clusterIP) == protocol {
×
689
                        protocolClusterIPs = append(protocolClusterIPs, clusterIP)
×
690
                }
×
691
        }
692
        return protocolClusterIPs
×
693
}
694

695
func isSvcMatchPod(svc *corev1.Service, pod *corev1.Pod) bool {
×
696
        return labels.Set(svc.Spec.Selector).AsSelector().Matches(labels.Set(pod.Labels))
×
697
}
×
698

699
func (c *Controller) podMatchNetworkPolicies(pod *corev1.Pod) []string {
×
700
        podNs, err := c.namespacesLister.Get(pod.Namespace)
×
701
        if err != nil {
×
702
                klog.Errorf("failed to get namespace %s: %v", pod.Namespace, err)
×
703
                utilruntime.HandleError(err)
×
704
                return nil
×
705
        }
×
706

707
        nps, err := c.npsLister.NetworkPolicies(corev1.NamespaceAll).List(labels.Everything())
×
708
        if err != nil {
×
709
                klog.Errorf("failed to list network policies: %v", err)
×
710
                utilruntime.HandleError(err)
×
711
                return nil
×
712
        }
×
713

714
        match := []string{}
×
715
        for _, np := range nps {
×
716
                if isPodMatchNetworkPolicy(pod, podNs, np, np.Namespace) {
×
717
                        match = append(match, cache.MetaObjectToName(np).String())
×
718
                }
×
719
        }
720
        return match
×
721
}
722

723
func (c *Controller) svcMatchNetworkPolicies(svc *corev1.Service) ([]string, error) {
×
724
        // find all match pod
×
725
        sel := labels.Set(svc.Spec.Selector).AsSelector()
×
726
        pods, err := c.podsLister.Pods(svc.Namespace).List(sel)
×
727
        if err != nil {
×
728
                return nil, fmt.Errorf("failed to list pods, %w", err)
×
729
        }
×
730

731
        // find all match netpol
732
        nps, err := c.npsLister.NetworkPolicies(corev1.NamespaceAll).List(labels.Everything())
×
733
        if err != nil {
×
734
                return nil, fmt.Errorf("failed to list netpols, %w", err)
×
735
        }
×
736
        match := set.New[string]()
×
737
        ns, _ := c.namespacesLister.Get(svc.Namespace)
×
738
        for _, pod := range pods {
×
739
                for _, np := range nps {
×
740
                        key := cache.MetaObjectToName(np).String()
×
741
                        if match.Has(key) {
×
742
                                continue
×
743
                        }
744
                        if isPodMatchNetworkPolicy(pod, ns, np, np.Namespace) {
×
745
                                match.Insert(key)
×
746
                                klog.V(3).Infof("svc %s/%s match np %s", svc.Namespace, svc.Name, key)
×
747
                        }
×
748
                }
749
        }
750
        return match.UnsortedList(), nil
×
751
}
752

753
func isPodMatchNetworkPolicy(pod *corev1.Pod, podNs *corev1.Namespace, policy *netv1.NetworkPolicy, policyNs string) bool {
×
754
        sel, _ := metav1.LabelSelectorAsSelector(&policy.Spec.PodSelector)
×
755
        if podNs.Name == policyNs && sel.Matches(labels.Set(pod.Labels)) {
×
756
                return true
×
757
        }
×
758
        for _, npr := range policy.Spec.Ingress {
×
759
                for _, npp := range npr.From {
×
760
                        if isPodMatchPolicyPeer(pod, podNs, npp, policyNs) {
×
761
                                return true
×
762
                        }
×
763
                }
764
        }
765
        for _, npr := range policy.Spec.Egress {
×
766
                for _, npp := range npr.To {
×
767
                        if isPodMatchPolicyPeer(pod, podNs, npp, policyNs) {
×
768
                                return true
×
769
                        }
×
770
                }
771
        }
772
        return false
×
773
}
774

775
func isPodMatchPolicyPeer(pod *corev1.Pod, podNs *corev1.Namespace, policyPeer netv1.NetworkPolicyPeer, policyNs string) bool {
×
776
        if policyPeer.IPBlock != nil {
×
777
                return false
×
778
        }
×
779
        if policyPeer.NamespaceSelector == nil {
×
780
                if policyNs != podNs.Name {
×
781
                        return false
×
782
                }
×
783
        } else if !util.ObjectMatchesLabelSelector(podNs, policyPeer.NamespaceSelector) {
×
784
                return false
×
785
        }
×
786

787
        return policyPeer.PodSelector == nil || util.ObjectMatchesLabelSelector(pod, policyPeer.PodSelector)
×
788
}
789

790
func (c *Controller) namespaceMatchNetworkPolicies(ns *corev1.Namespace) []string {
×
791
        nps, _ := c.npsLister.NetworkPolicies(corev1.NamespaceAll).List(labels.Everything())
×
792
        match := make([]string, 0, len(nps))
×
793
        for _, np := range nps {
×
794
                if isNamespaceMatchNetworkPolicy(ns, np) {
×
795
                        match = append(match, cache.MetaObjectToName(np).String())
×
796
                }
×
797
        }
798
        return match
×
799
}
800

801
func isNamespaceMatchNetworkPolicy(ns *corev1.Namespace, policy *netv1.NetworkPolicy) bool {
×
802
        for _, npr := range policy.Spec.Ingress {
×
803
                for _, npp := range npr.From {
×
804
                        if npp.NamespaceSelector != nil {
×
805
                                nsSel, _ := metav1.LabelSelectorAsSelector(npp.NamespaceSelector)
×
806
                                if ns.Labels == nil {
×
807
                                        ns.Labels = map[string]string{}
×
808
                                }
×
809
                                if nsSel.Matches(labels.Set(ns.Labels)) {
×
810
                                        return true
×
811
                                }
×
812
                        }
813
                }
814
        }
815

816
        for _, npr := range policy.Spec.Egress {
×
817
                for _, npp := range npr.To {
×
818
                        if npp.NamespaceSelector != nil {
×
819
                                nsSel, _ := metav1.LabelSelectorAsSelector(npp.NamespaceSelector)
×
820
                                if ns.Labels == nil {
×
821
                                        ns.Labels = map[string]string{}
×
822
                                }
×
823
                                if nsSel.Matches(labels.Set(ns.Labels)) {
×
824
                                        return true
×
825
                                }
×
826
                        }
827
                }
828
        }
829
        return false
×
830
}
831

832
func (c *Controller) isNetworkPolicyEnforcementLax(policy *netv1.NetworkPolicy) bool {
×
833
        // User provided a custom enforcement through annotations
×
834
        if value, ok := policy.Annotations[util.NetworkPolicyEnforcementAnnotation]; ok {
×
835
                return value == NetworkPolicyEnforcementLax
×
836
        }
×
837

838
        // Fallback to the configuration of the controller
839
        return c.config.NetworkPolicyEnforcement == NetworkPolicyEnforcementLax
×
840
}
841

842
func parseACLLogRate(annotations map[string]string) int {
×
843
        val := strings.TrimSpace(annotations[util.ACLLogMeterAnnotation])
×
844
        if val == "" {
×
845
                return 0
×
846
        }
×
847
        rate, err := strconv.Atoi(val)
×
848
        if err != nil || rate <= 0 {
×
849
                if val != "" {
×
850
                        klog.Warningf("invalid acl_log_meter value %q, should be positive integer", val)
×
851
                }
×
852
                return 0
×
853
        }
854
        return rate
×
855
}
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