Skip to content

Commit 3179b1f

Browse files
committed
added logic to bypass ipsets for /32 cidrs with npm lite
1 parent 6c232c8 commit 3179b1f

File tree

5 files changed

+80
-180
lines changed

5 files changed

+80
-180
lines changed

npm/pkg/controlplane/translation/translatePolicy.go

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package translation
33
import (
44
"errors"
55
"fmt"
6+
"strings"
67

78
"github.com/Azure/azure-container-networking/npm/pkg/dataplane/ipsets"
89
"github.com/Azure/azure-container-networking/npm/pkg/dataplane/policies"
@@ -362,6 +363,53 @@ func peerAndPortRule(npmNetPol *policies.NPMNetworkPolicy, direction policies.Di
362363
return nil
363364
}
364365

366+
func directPeerAndPortRule(npmNetPol *policies.NPMNetworkPolicy, direction policies.Direction, ports []networkingv1.NetworkPolicyPort, cidr string, npmLiteToggle bool) error {
367+
ip := strings.TrimSuffix(cidr, "/32")
368+
if len(ports) == 0 {
369+
acl := policies.NewACLPolicy(policies.Allowed, direction)
370+
// bypasses ipset creation for /32 cidrs and directly creates an acl with the cidr
371+
if direction == policies.Ingress {
372+
acl.SrcDirectIPs = []string{ip}
373+
} else {
374+
acl.DstDirectIPs = []string{ip}
375+
}
376+
npmNetPol.ACLs = append(npmNetPol.ACLs, acl)
377+
return nil
378+
} else {
379+
// handle each port separately
380+
for i := range ports {
381+
portKind, err := portType(ports[i])
382+
if err != nil {
383+
return err
384+
}
385+
386+
err = checkForNamedPortType(portKind, npmLiteToggle)
387+
if err != nil {
388+
return err
389+
}
390+
391+
acl := policies.NewACLPolicy(policies.Allowed, direction)
392+
393+
// Set direct IP based on direction
394+
if direction == policies.Ingress {
395+
acl.SrcDirectIPs = []string{ip}
396+
} else {
397+
acl.DstDirectIPs = []string{ip}
398+
}
399+
400+
// Handle ports
401+
if portKind == numericPortType {
402+
portInfo, protocol := numericPortRule(&ports[i])
403+
acl.DstPorts = portInfo
404+
acl.Protocol = policies.Protocol(protocol)
405+
}
406+
npmNetPol.ACLs = append(npmNetPol.ACLs, acl)
407+
408+
}
409+
}
410+
return nil
411+
}
412+
365413
// translateRule translates ingress or egress rules and update npmNetPol object.
366414
func translateRule(npmNetPol *policies.NPMNetworkPolicy,
367415
netPolName string,
@@ -405,6 +453,16 @@ func translateRule(npmNetPol *policies.NPMNetworkPolicy,
405453
// #2.1 Handle IPBlock and port if exist
406454
if peer.IPBlock != nil {
407455
if len(peer.IPBlock.CIDR) > 0 {
456+
// add logic that if the peer is only IPBlock and npm lite is enabled and is a /32 cidr block
457+
// then skip creating IpBlockIPSet
458+
if npmLiteToggle && util.IsCIDR32(peer.IPBlock.CIDR) {
459+
err = directPeerAndPortRule(npmNetPol, direction, ports, peer.IPBlock.CIDR, npmLiteToggle)
460+
if err != nil {
461+
return err
462+
}
463+
continue
464+
}
465+
408466
ipBlockIPSet, ipBlockSetInfo, err := ipBlockRule(netPolName, npmNetPol.Namespace, direction, matchType, ruleIndex, peerIdx, peer.IPBlock)
409467
if err != nil {
410468
return err
@@ -417,12 +475,6 @@ func translateRule(npmNetPol *policies.NPMNetworkPolicy,
417475
}
418476
}
419477

420-
// if npm lite is configured, check network policy only consists of CIDR blocks
421-
err := npmLiteValidPolicy(peer, npmLiteToggle)
422-
if err != nil {
423-
return err
424-
}
425-
426478
// Do not need to run below code to translate PodSelector and NamespaceSelector
427479
// since IPBlock field is exclusive in NetworkPolicyPeer (i.e., peer in this code).
428480

@@ -642,14 +694,6 @@ func TranslatePolicy(npObj *networkingv1.NetworkPolicy, npmLiteToggle bool) (*po
642694
return npmNetPol, nil
643695
}
644696

645-
// validates only CIDR based peer is present + no combination of CIDR with pod/namespace selectors are present
646-
func npmLiteValidPolicy(peer networkingv1.NetworkPolicyPeer, npmLiteEnabled bool) error {
647-
if npmLiteEnabled && (peer.PodSelector != nil || peer.NamespaceSelector != nil) {
648-
return ErrUnsupportedNonCIDR
649-
}
650-
return nil
651-
}
652-
653697
func checkForNamedPortType(portKind netpolPortType, npmLiteToggle bool) error {
654698
if npmLiteToggle && portKind == namedPortType {
655699
return ErrUnsupportedNonCIDR

npm/pkg/controlplane/translation/translatePolicy_test.go

Lines changed: 0 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -2921,169 +2921,6 @@ func TestEgressPolicy(t *testing.T) {
29212921
}
29222922
}
29232923

2924-
func TestNpmLiteCidrPolicy(t *testing.T) {
2925-
// Test 1) Npm lite enabled, CIDR + Namespace label Peers, returns error
2926-
// Test 2) NPM lite disabled, CIDR + Namespace label Peers, returns no error
2927-
// Test 3) Npm Lite enabled, CIDR Peers , returns no error
2928-
// Test 4) NPM Lite enabled, Combination of CIDR + Label in same peer, returns an error
2929-
// test 5) NPM Lite enabled, no peer, returns no error
2930-
// test 6) NPM Lite enabled, no cidr, no peer, only ports + protocol
2931-
2932-
port8000 := intstr.FromInt(8000)
2933-
tcp := v1.ProtocolTCP
2934-
tests := []struct {
2935-
name string
2936-
targetSelector *metav1.LabelSelector
2937-
ports []networkingv1.NetworkPolicyPort
2938-
peersFrom []networkingv1.NetworkPolicyPeer
2939-
peersTo []networkingv1.NetworkPolicyPeer
2940-
npmLiteEnabled bool
2941-
wantErr bool
2942-
}{
2943-
{
2944-
name: "CIDR + port + namespace",
2945-
targetSelector: nil,
2946-
ports: []networkingv1.NetworkPolicyPort{
2947-
{
2948-
Protocol: &tcp,
2949-
Port: &port8000,
2950-
},
2951-
},
2952-
peersFrom: []networkingv1.NetworkPolicyPeer{
2953-
{
2954-
NamespaceSelector: &metav1.LabelSelector{
2955-
MatchLabels: map[string]string{
2956-
"peer-nsselector-kay": "peer-nsselector-value",
2957-
},
2958-
},
2959-
},
2960-
{
2961-
IPBlock: &networkingv1.IPBlock{
2962-
CIDR: "172.17.0.0/16",
2963-
Except: []string{"172.17.1.0/24", "172.17.2.0/24"},
2964-
},
2965-
},
2966-
{
2967-
IPBlock: &networkingv1.IPBlock{
2968-
CIDR: "172.17.0.0/16",
2969-
},
2970-
},
2971-
},
2972-
peersTo: []networkingv1.NetworkPolicyPeer{},
2973-
npmLiteEnabled: true,
2974-
wantErr: true,
2975-
},
2976-
{
2977-
name: "cidr + namespace label + disabledLite ",
2978-
targetSelector: nil,
2979-
peersFrom: []networkingv1.NetworkPolicyPeer{
2980-
{
2981-
NamespaceSelector: &metav1.LabelSelector{
2982-
MatchLabels: map[string]string{
2983-
"peer-nsselector-kay": "peer-nsselector-value",
2984-
},
2985-
},
2986-
},
2987-
{
2988-
IPBlock: &networkingv1.IPBlock{
2989-
CIDR: "172.17.0.0/16",
2990-
Except: []string{"172.17.1.0/24", "172.17.2.0/24"},
2991-
},
2992-
},
2993-
{
2994-
IPBlock: &networkingv1.IPBlock{
2995-
CIDR: "172.17.0.0/16",
2996-
},
2997-
},
2998-
},
2999-
peersTo: []networkingv1.NetworkPolicyPeer{},
3000-
npmLiteEnabled: false,
3001-
wantErr: false,
3002-
},
3003-
{
3004-
name: "CIDR Only",
3005-
targetSelector: nil,
3006-
peersFrom: []networkingv1.NetworkPolicyPeer{
3007-
{
3008-
IPBlock: &networkingv1.IPBlock{
3009-
CIDR: "172.17.0.0/16",
3010-
Except: []string{"172.17.1.0/24", "172.17.2.0/24"},
3011-
},
3012-
},
3013-
{
3014-
IPBlock: &networkingv1.IPBlock{
3015-
CIDR: "172.17.0.0/16",
3016-
},
3017-
},
3018-
},
3019-
peersTo: []networkingv1.NetworkPolicyPeer{},
3020-
npmLiteEnabled: true,
3021-
wantErr: false,
3022-
},
3023-
{
3024-
name: "CIDR + namespace labels",
3025-
targetSelector: nil,
3026-
peersFrom: []networkingv1.NetworkPolicyPeer{
3027-
{
3028-
IPBlock: &networkingv1.IPBlock{
3029-
CIDR: "172.17.0.0/17",
3030-
Except: []string{"172.17.1.0/24", "172.17.2.0/24"},
3031-
},
3032-
NamespaceSelector: &metav1.LabelSelector{
3033-
MatchLabels: map[string]string{
3034-
"peer-nsselector-kay": "peer-nsselector-value",
3035-
},
3036-
},
3037-
},
3038-
},
3039-
peersTo: []networkingv1.NetworkPolicyPeer{},
3040-
npmLiteEnabled: true,
3041-
wantErr: true,
3042-
},
3043-
{
3044-
name: "no peers",
3045-
targetSelector: nil,
3046-
peersFrom: []networkingv1.NetworkPolicyPeer{},
3047-
peersTo: []networkingv1.NetworkPolicyPeer{},
3048-
npmLiteEnabled: true,
3049-
wantErr: false,
3050-
},
3051-
{
3052-
name: "port only",
3053-
targetSelector: nil,
3054-
ports: []networkingv1.NetworkPolicyPort{
3055-
{
3056-
Protocol: &tcp,
3057-
Port: &port8000,
3058-
},
3059-
},
3060-
peersFrom: []networkingv1.NetworkPolicyPeer{},
3061-
peersTo: []networkingv1.NetworkPolicyPeer{},
3062-
npmLiteEnabled: true,
3063-
wantErr: false,
3064-
},
3065-
}
3066-
3067-
for _, tt := range tests {
3068-
tt := tt
3069-
t.Run(tt.name, func(t *testing.T) {
3070-
// run the function passing in peers and a flag indicating whether npm lite is enabled
3071-
var err error
3072-
for _, peer := range tt.peersFrom {
3073-
err = npmLiteValidPolicy(peer, tt.npmLiteEnabled)
3074-
if err != nil {
3075-
break
3076-
}
3077-
}
3078-
if tt.wantErr {
3079-
require.Error(t, err)
3080-
} else {
3081-
require.NoError(t, err)
3082-
}
3083-
})
3084-
}
3085-
}
3086-
30872924
func TestCheckForNamedPortType(t *testing.T) {
30882925
port8000 := intstr.FromInt(8000)
30892926
namedPort := intstr.FromString("namedPort")

npm/pkg/dataplane/policies/policy.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ type ACLPolicy struct {
114114
SrcList []SetInfo
115115
// DstList destination IPSets condition setinfos
116116
DstList []SetInfo
117+
// SrcDirectIPs holds direct IPs for source matching (used for /32 CIDRs on Windows with npm lite enabled)
118+
SrcDirectIPs []string
119+
// DstDirectIPs holds direct IPs for destination matching (used for /32 CIDRs on Windows with npm lite enabled)
120+
DstDirectIPs []string
117121
// Target defines a target in iptables for linux. i,e, Mark, Accept, Drop
118122
// in windows, this is either ALLOW or DENY
119123
Target Verdict
@@ -282,7 +286,9 @@ func translatedIPSetsToString(items []*ipsets.TranslatedIPSet) string {
282286
// Included is false when match set have "!".
283287
// MatchType captures match direction flags.
284288
// For example match set in linux:
285-
// ! azure-npm-123 src
289+
//
290+
// ! azure-npm-123 src
291+
//
286292
// "!" this indicates a negative match (Included is false) of an azure-npm-123
287293
// MatchType is "src"
288294
type SetInfo struct {

npm/pkg/dataplane/policies/policy_windows.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package policies
33
import (
44
"errors"
55
"fmt"
6+
"strings"
67

78
"github.com/Azure/azure-container-networking/npm/pkg/dataplane/ipsets"
89
"github.com/Microsoft/hcsshim/hcn"
@@ -101,8 +102,16 @@ func (acl *ACLPolicy) convertToAclSettings(aclID string) (*NPMACLPolSettings, er
101102
// policySettings.RuleType = hcn.RuleTypeSwitch
102103

103104
// ACLPolicy settings uses ID field of SetPolicy in LocalAddresses or RemoteAddresses
104-
srcListStr := getAddrListFromSetInfo(acl.SrcList)
105-
dstListStr := getAddrListFromSetInfo(acl.DstList)
105+
var srcListStr, dstListStr string
106+
// Check if we have direct IPs (NPM Lite /32 bypass)
107+
if len(acl.SrcDirectIPs) > 0 || len(acl.DstDirectIPs) > 0 {
108+
srcListStr = strings.Join(acl.SrcDirectIPs, ",")
109+
dstListStr = strings.Join(acl.DstDirectIPs, ",")
110+
} else {
111+
// Original IPSet-based approach
112+
srcListStr = getAddrListFromSetInfo(acl.SrcList)
113+
dstListStr = getAddrListFromSetInfo(acl.DstList)
114+
}
106115
dstPortStr := getPortStrFromPorts(acl.DstPorts)
107116

108117
// HNS has confusing Local and Remote address defintions

npm/util/util.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,3 +359,7 @@ func NodeIP() (string, error) {
359359

360360
return nodeIP, nil
361361
}
362+
363+
func IsCIDR32(cidr string) bool {
364+
return strings.HasSuffix(cidr, "/32")
365+
}

0 commit comments

Comments
 (0)