@@ -3,32 +3,53 @@ package dataplane
33import (
44 "fmt"
55
6- "github.com/Azure/azure-container-networking/npm"
76 "github.com/Azure/azure-container-networking/npm/pkg/dataplane/ipsets"
87 "github.com/Azure/azure-container-networking/npm/pkg/dataplane/policies"
8+ npmerrors "github.com/Azure/azure-container-networking/npm/util/errors"
9+ "k8s.io/klog"
10+ )
11+
12+ const (
13+ // AzureNetworkName is default network Azure CNI creates
14+ AzureNetworkName = "azure"
915)
1016
1117type DataPlane struct {
1218 policyMgr * policies.PolicyManager
1319 ipsetMgr * ipsets.IPSetManager
1420 networkID string
21+ nodeName string
1522 // key is PodKey
1623 endpointCache map [string ]* NPMEndpoint
1724}
1825
1926type NPMEndpoint struct {
2027 Name string
2128 ID string
29+ IP string
2230 // Map with Key as Network Policy name to to emulate set
2331 // and value as struct{} for minimal memory consumption
2432 NetPolReference map [string ]struct {}
2533}
2634
27- func NewDataPlane () * DataPlane {
35+ // UpdateNPMPod pod controller will populate and send this datastructure to dataplane
36+ // to update the dataplane with the latest pod information
37+ // this helps in calculating if any update needs to have policies applied or removed
38+ type UpdateNPMPod struct {
39+ Name string
40+ Namespace string
41+ PodIP string
42+ NodeName string
43+ IPSetsToAdd []string
44+ IPSetsToRemove []string
45+ }
46+
47+ func NewDataPlane (nodeName string ) * DataPlane {
2848 return & DataPlane {
2949 policyMgr : policies .NewPolicyManager (),
30- ipsetMgr : ipsets .NewIPSetManager (),
50+ ipsetMgr : ipsets .NewIPSetManager (AzureNetworkName ),
3151 endpointCache : make (map [string ]* NPMEndpoint ),
52+ nodeName : nodeName ,
3253 }
3354}
3455
@@ -44,22 +65,14 @@ func (dp *DataPlane) ResetDataPlane() error {
4465}
4566
4667// CreateIPSet takes in a set object and updates local cache with this set
47- func (dp * DataPlane ) CreateIPSet (setName string , setType ipsets.SetType ) error {
48- err := dp .ipsetMgr .CreateIPSet (setName , setType )
49- if err != nil {
50- return fmt .Errorf ("[DataPlane] error while creating set: %w" , err )
51- }
52- return nil
68+ func (dp * DataPlane ) CreateIPSet (setName string , setType ipsets.SetType ) {
69+ dp .ipsetMgr .CreateIPSet (setName , setType )
5370}
5471
5572// DeleteSet checks for members and references of the given "set" type ipset
5673// if not used then will delete it from cache
57- func (dp * DataPlane ) DeleteIPSet (name string ) error {
58- err := dp .ipsetMgr .DeleteIPSet (name )
59- if err != nil {
60- return fmt .Errorf ("[DataPlane] error while deleting set: %w" , err )
61- }
62- return nil
74+ func (dp * DataPlane ) DeleteIPSet (name string ) {
75+ dp .ipsetMgr .DeleteIPSet (name )
6376}
6477
6578// AddToSet takes in a list of IPSet names along with IP member
@@ -102,8 +115,14 @@ func (dp *DataPlane) RemoveFromList(listName string, setNames []string) error {
102115 return nil
103116}
104117
118+ // ShouldUpdatePod will let controller know if its needs to aggregate pod data for update pod call.
119+ func (dp * DataPlane ) ShouldUpdatePod () bool {
120+ return dp .shouldUpdatePod ()
121+ }
122+
105123// UpdatePod is to be called by pod_controller ONLY when a new pod is CREATED.
106- func (dp * DataPlane ) UpdatePod (pod * npm.NpmPod ) error {
124+ func (dp * DataPlane ) UpdatePod (pod * UpdateNPMPod ) error {
125+ // TODO check pod is in this Node if yes continue
107126 err := dp .updatePod (pod )
108127 if err != nil {
109128 return fmt .Errorf ("[DataPlane] error while updating pod: %w" , err )
@@ -125,8 +144,34 @@ func (dp *DataPlane) ApplyDataPlane() error {
125144}
126145
127146// AddPolicy takes in a translated NPMNetworkPolicy object and applies on dataplane
128- func (dp * DataPlane ) AddPolicy (policies * policies.NPMNetworkPolicy ) error {
129- err := dp .policyMgr .AddPolicy (policies )
147+ func (dp * DataPlane ) AddPolicy (policy * policies.NPMNetworkPolicy ) error {
148+ klog .Infof ("[DataPlane] Add Policy called for %s" , policy .Name )
149+ // Create and add references for Selector IPSets first
150+ err := dp .addIPSetReferences (policy .PodSelectorIPSets , policy .Name , ipsets .SelectorType )
151+ if err != nil {
152+ klog .Infof ("[DataPlane] error while adding Selector IPSet references: %s" , err .Error ())
153+ return fmt .Errorf ("[DataPlane] error while adding Selector IPSet references: %w" , err )
154+ }
155+
156+ // Create and add references for Rule IPSets
157+ err = dp .addIPSetReferences (policy .RuleIPSets , policy .Name , ipsets .NetPolType )
158+ if err != nil {
159+ klog .Infof ("[DataPlane] error while adding Rule IPSet references: %s" , err .Error ())
160+ return fmt .Errorf ("[DataPlane] error while adding Rule IPSet references: %w" , err )
161+ }
162+
163+ err = dp .ApplyDataPlane ()
164+ if err != nil {
165+ return fmt .Errorf ("[DataPlane] error while applying dataplane: %w" , err )
166+ }
167+ // TODO calculate endpoints to apply policy on
168+ endpointList , err := dp .getEndpointsToApplyPolicy (policy )
169+ if err != nil {
170+ return err
171+ }
172+
173+ policy .PodEndpoints = endpointList
174+ err = dp .policyMgr .AddPolicy (policy , nil )
130175 if err != nil {
131176 return fmt .Errorf ("[DataPlane] error while adding policy: %w" , err )
132177 }
@@ -135,19 +180,147 @@ func (dp *DataPlane) AddPolicy(policies *policies.NPMNetworkPolicy) error {
135180
136181// RemovePolicy takes in network policy name and removes it from dataplane and cache
137182func (dp * DataPlane ) RemovePolicy (policyName string ) error {
138- err := dp .policyMgr .RemovePolicy (policyName )
183+ klog .Infof ("[DataPlane] Remove Policy called for %s" , policyName )
184+ // because policy Manager will remove from policy from cache
185+ // keep a local copy to remove references for ipsets
186+ policy , ok := dp .policyMgr .GetPolicy (policyName )
187+ if ! ok {
188+ klog .Infof ("[DataPlane] Policy %s is not found. Might been deleted already" , policyName )
189+ return nil
190+ }
191+ // Use the endpoint list saved in cache for this network policy to remove
192+ err := dp .policyMgr .RemovePolicy (policy .Name , nil )
139193 if err != nil {
140194 return fmt .Errorf ("[DataPlane] error while removing policy: %w" , err )
141195 }
196+ // Remove references for Rule IPSets first
197+ err = dp .deleteIPSetReferences (policy .RuleIPSets , policy .Name , ipsets .NetPolType )
198+ if err != nil {
199+ return err
200+ }
201+
202+ // Remove references for Selector IPSets
203+ err = dp .deleteIPSetReferences (policy .PodSelectorIPSets , policy .Name , ipsets .SelectorType )
204+ if err != nil {
205+ return err
206+ }
207+
208+ err = dp .ApplyDataPlane ()
209+ if err != nil {
210+ return fmt .Errorf ("[DataPlane] error while applying dataplane: %w" , err )
211+ }
212+
142213 return nil
143214}
144215
145216// UpdatePolicy takes in updated policy object, calculates the delta and applies changes
146217// onto dataplane accordingly
147- func (dp * DataPlane ) UpdatePolicy (policies * policies.NPMNetworkPolicy ) error {
148- err := dp .policyMgr .UpdatePolicy (policies )
218+ func (dp * DataPlane ) UpdatePolicy (policy * policies.NPMNetworkPolicy ) error {
219+ klog .Infof ("[DataPlane] Update Policy called for %s" , policy .Name )
220+ ok := dp .policyMgr .PolicyExists (policy .Name )
221+ if ! ok {
222+ klog .Infof ("[DataPlane] Policy %s is not found. Might been deleted already" , policy .Name )
223+ return dp .AddPolicy (policy )
224+ }
225+
226+ // TODO it would be ideal to calculate a diff of policies
227+ // and remove/apply only the delta of IPSets and policies
228+
229+ // Taking the easy route here, delete existing policy
230+ err := dp .policyMgr .RemovePolicy (policy .Name , nil )
149231 if err != nil {
150232 return fmt .Errorf ("[DataPlane] error while updating policy: %w" , err )
151233 }
234+ // and add the new updated policy
235+ err = dp .policyMgr .AddPolicy (policy , nil )
236+ if err != nil {
237+ return fmt .Errorf ("[DataPlane] error while updating policy: %w" , err )
238+ }
239+ return nil
240+ }
241+
242+ func (dp * DataPlane ) addIPSetReferences (sets map [string ]* ipsets.IPSet , netpolName string , referenceType ipsets.ReferenceType ) error {
243+ // Create IPSets first along with reference updates
244+ for _ , set := range sets {
245+ dp .ipsetMgr .CreateIPSet (set .Name , set .Type )
246+ err := dp .ipsetMgr .AddReference (set .Name , netpolName , referenceType )
247+ if err != nil {
248+ npmErrorString := npmerrors .AddSelectorReference
249+ if referenceType == ipsets .NetPolType {
250+ npmErrorString = npmerrors .AddNetPolReference
251+ }
252+ return npmerrors .Errorf (npmErrorString , false , fmt .Sprintf ("[dataplane] failed to add reference with err: %s" , err .Error ()))
253+ }
254+ }
255+
256+ // TODO is there a possibility for a list set of selector referencing rule ipset?
257+ // if so this below addition would throw an error because rule ipsets are not created
258+ // Check if any list sets are provided with members to add
259+ for _ , set := range sets {
260+ // Check if any 2nd level IPSets are generated by Controller with members
261+ // Apply members to the list set
262+ if set .Kind == ipsets .ListSet {
263+ if len (set .MemberIPSets ) > 0 {
264+ memberList := []string {}
265+ for _ , memberSet := range set .MemberIPSets {
266+ memberList = append (memberList , memberSet .Name )
267+ }
268+ err := dp .ipsetMgr .AddToList (set .Name , memberList )
269+ if err != nil {
270+ npmErrorString := npmerrors .AddSelectorReference
271+ if referenceType == ipsets .NetPolType {
272+ npmErrorString = npmerrors .AddNetPolReference
273+ }
274+ return npmerrors .Errorf (npmErrorString , false , fmt .Sprintf ("[dataplane] failed to AddToList in addIPSetReferences with err: %s" , err .Error ()))
275+
276+ }
277+ }
278+ }
279+ }
280+
281+ return nil
282+ }
283+
284+ func (dp * DataPlane ) deleteIPSetReferences (sets map [string ]* ipsets.IPSet , netpolName string , referenceType ipsets.ReferenceType ) error {
285+ for _ , set := range sets {
286+ // TODO ignore set does not exist error
287+ // TODO add delete ipset after removing members
288+ err := dp .ipsetMgr .DeleteReference (set .Name , netpolName , referenceType )
289+ if err != nil {
290+ npmErrorString := npmerrors .DeleteSelectorReference
291+ if referenceType == ipsets .NetPolType {
292+ npmErrorString = npmerrors .DeleteNetPolReference
293+ }
294+ return npmerrors .Errorf (npmErrorString , false , fmt .Sprintf ("[dataplane] failed to deleteIPSetReferences with err: %s" , err .Error ()))
295+ }
296+ }
297+
298+ // Check if any list sets are provided with members to add
299+ // TODO for nested IPsets check if we are safe to remove members
300+ // if k1:v0:v1 is created by two network policies
301+ // and both have same members
302+ // then we should not delete k1:v0:v1 members ( special case for nested ipsets )
303+ for _ , set := range sets {
304+ // Delete if any 2nd level IPSets are generated by Controller with members
305+ if set .Kind == ipsets .ListSet {
306+ if len (set .MemberIPSets ) > 0 {
307+ memberList := []string {}
308+ for _ , memberSet := range set .MemberIPSets {
309+ memberList = append (memberList , memberSet .Name )
310+ }
311+ err := dp .ipsetMgr .RemoveFromList (set .Name , memberList )
312+ if err != nil {
313+ npmErrorString := npmerrors .DeleteSelectorReference
314+ if referenceType == ipsets .NetPolType {
315+ npmErrorString = npmerrors .DeleteNetPolReference
316+ }
317+ return npmerrors .Errorf (npmErrorString , false , fmt .Sprintf ("[dataplane] failed to RemoveFromList in deleteIPSetReferences with err: %s" , err .Error ()))
318+ }
319+ }
320+ }
321+
322+ // Try to delete these IPSets
323+ dp .ipsetMgr .DeleteIPSet (set .Name )
324+ }
152325 return nil
153326}
0 commit comments