@@ -2,6 +2,7 @@ package network
22
33import (
44 "encoding/json"
5+ "errors"
56 "fmt"
67 "net"
78 "strings"
@@ -16,7 +17,12 @@ import (
1617 cniTypesCurr "github.com/containernetworking/cni/pkg/types/current"
1718)
1819
19- func SetupRoutingForMultitenancy (nwCfg * cni.NetworkConfig , cnsNetworkConfig * cns.GetNetworkContainerResponse , epInfo * network.EndpointInfo , result * cniTypesCurr.Result ) {
20+ func SetupRoutingForMultitenancy (
21+ nwCfg * cni.NetworkConfig ,
22+ cnsNetworkConfig * cns.GetNetworkContainerResponse ,
23+ azIpamResult * cniTypesCurr.Result ,
24+ epInfo * network.EndpointInfo ,
25+ result * cniTypesCurr.Result ) {
2026 // Adding default gateway
2127 if nwCfg .MultiTenancy {
2228 // if snat enabled, add 169.254.0.1 as default gateway
@@ -30,20 +36,34 @@ func SetupRoutingForMultitenancy(nwCfg *cni.NetworkConfig, cnsNetworkConfig *cns
3036 epInfo .Routes = append (epInfo .Routes , network.RouteInfo {Dst : dstIP , Gw : gwIP })
3137 result .Routes = append (result .Routes , & cniTypes.Route {Dst : dstIP , GW : gwIP })
3238 }
39+
40+ setupInfraVnetRoutingForMultitenancy (nwCfg , azIpamResult , epInfo , result )
3341 }
3442}
3543
36- func GetContainerNetworkConfiguration (multiTenancy bool , address string , podName string , podNamespace string ) (* cniTypesCurr.Result , * cns.GetNetworkContainerResponse , net.IPNet , error ) {
37- if multiTenancy {
38- podNameWithoutSuffix := getPodNameWithoutSuffix (podName )
39- log .Printf ("Podname without suffix %v" , podNameWithoutSuffix )
40- return getContainerNetworkConfiguration (address , podNamespace , podNameWithoutSuffix )
44+ func getContainerNetworkConfiguration (
45+ nwCfg * cni.NetworkConfig ,
46+ address string ,
47+ podName string ,
48+ podNamespace string ,
49+ ifName string ) (* cniTypesCurr.Result , * cns.GetNetworkContainerResponse , net.IPNet , error ) {
50+ var podNameWithoutSuffix string
51+
52+ if ! nwCfg .EnableExactMatchForPodName {
53+ podNameWithoutSuffix = getPodNameWithoutSuffix (podName )
54+ } else {
55+ podNameWithoutSuffix = podName
4156 }
4257
43- return nil , nil , net.IPNet {}, nil
58+ log .Printf ("Podname without suffix %v" , podNameWithoutSuffix )
59+ return getContainerNetworkConfigurationInternal (address , podNamespace , podNameWithoutSuffix , ifName )
4460}
4561
46- func getContainerNetworkConfiguration (address string , namespace string , podName string ) (* cniTypesCurr.Result , * cns.GetNetworkContainerResponse , net.IPNet , error ) {
62+ func getContainerNetworkConfigurationInternal (
63+ address string ,
64+ namespace string ,
65+ podName string ,
66+ ifName string ) (* cniTypesCurr.Result , * cns.GetNetworkContainerResponse , net.IPNet , error ) {
4767 cnsClient , err := cnsclient .NewCnsClient (address )
4868 if err != nil {
4969 log .Printf ("Initializing CNS client error %v" , err )
@@ -72,10 +92,10 @@ func getContainerNetworkConfiguration(address string, namespace string, podName
7292 return nil , nil , net.IPNet {}, fmt .Errorf (errBuf )
7393 }
7494
75- return convertToCniResult (networkConfig ), networkConfig , * subnetPrefix , nil
95+ return convertToCniResult (networkConfig , ifName ), networkConfig , * subnetPrefix , nil
7696}
7797
78- func convertToCniResult (networkConfig * cns.GetNetworkContainerResponse ) * cniTypesCurr.Result {
98+ func convertToCniResult (networkConfig * cns.GetNetworkContainerResponse , ifName string ) * cniTypesCurr.Result {
7999 result := & cniTypesCurr.Result {}
80100 resultIpconfig := & cniTypesCurr.IPConfig {}
81101
@@ -109,6 +129,9 @@ func convertToCniResult(networkConfig *cns.GetNetworkContainerResponse) *cniType
109129 result .Routes = append (result .Routes , & cniTypes.Route {Dst : routeIPnet , GW : gwIP })
110130 }
111131
132+ iface := & cniTypesCurr.Interface {Name : ifName }
133+ result .Interfaces = append (result .Interfaces , iface )
134+
112135 return result
113136}
114137
@@ -124,3 +147,117 @@ func getPodNameWithoutSuffix(podName string) string {
124147 log .Printf ("Pod name after splitting based on - : %v" , nameSplit )
125148 return strings .Join (nameSplit , "-" )
126149}
150+
151+ func getInfraVnetIP (
152+ enableInfraVnet bool ,
153+ infraSubnet string ,
154+ nwCfg * cni.NetworkConfig ,
155+ plugin * netPlugin ,
156+ ) (* cniTypesCurr.Result , error ) {
157+
158+ if enableInfraVnet {
159+ _ , ipNet , _ := net .ParseCIDR (infraSubnet )
160+ nwCfg .Ipam .Subnet = ipNet .String ()
161+
162+ log .Printf ("call ipam to allocate ip from subnet %v" , nwCfg .Ipam .Subnet )
163+ azIpamResult , err := plugin .DelegateAdd (nwCfg .Ipam .Type , nwCfg )
164+ if err != nil {
165+ err = plugin .Errorf ("Failed to allocate address: %v" , err )
166+ return nil , err
167+ }
168+
169+ return azIpamResult , nil
170+ }
171+
172+ return nil , nil
173+ }
174+
175+ func cleanupInfraVnetIP (
176+ enableInfraVnet bool ,
177+ infraIPNet * net.IPNet ,
178+ nwCfg * cni.NetworkConfig ,
179+ plugin * netPlugin ) {
180+
181+ log .Printf ("Cleanup infravnet ip" )
182+
183+ if enableInfraVnet {
184+ _ , ipNet , _ := net .ParseCIDR (infraIPNet .String ())
185+ nwCfg .Ipam .Subnet = ipNet .String ()
186+ nwCfg .Ipam .Address = infraIPNet .IP .String ()
187+ plugin .DelegateDel (nwCfg .Ipam .Type , nwCfg )
188+ }
189+ }
190+
191+ func checkIfSubnetOverlaps (enableInfraVnet bool , nwCfg * cni.NetworkConfig , cnsNetworkConfig * cns.GetNetworkContainerResponse ) bool {
192+ if enableInfraVnet {
193+ if cnsNetworkConfig != nil {
194+ _ , infraNet , _ := net .ParseCIDR (nwCfg .InfraVnetAddressSpace )
195+ for _ , cnetSpace := range cnsNetworkConfig .CnetAddressSpace {
196+ cnetSpaceIPNet := & net.IPNet {
197+ IP : net .ParseIP (cnetSpace .IPAddress ),
198+ Mask : net .CIDRMask (int (cnetSpace .PrefixLength ), 32 ),
199+ }
200+
201+ return infraNet .Contains (cnetSpaceIPNet .IP ) || cnetSpaceIPNet .Contains (infraNet .IP )
202+ }
203+ }
204+ }
205+
206+ return false
207+ }
208+
209+ func GetMultiTenancyCNIResult (
210+ enableInfraVnet bool ,
211+ nwCfg * cni.NetworkConfig ,
212+ plugin * netPlugin ,
213+ k8sPodName string ,
214+ k8sNamespace string ,
215+ ifName string ) (* cniTypesCurr.Result , * cns.GetNetworkContainerResponse , net.IPNet , * cniTypesCurr.Result , error ) {
216+
217+ if nwCfg .MultiTenancy {
218+ result , cnsNetworkConfig , subnetPrefix , err := getContainerNetworkConfiguration (nwCfg , "" , k8sPodName , k8sNamespace , ifName )
219+ if err != nil {
220+ log .Printf ("GetContainerNetworkConfiguration failed for podname %v namespace %v with error %v" , k8sPodName , k8sNamespace , err )
221+ return nil , nil , net.IPNet {}, nil , err
222+ }
223+
224+ log .Printf ("PrimaryInterfaceIdentifier :%v" , subnetPrefix .IP .String ())
225+
226+ if checkIfSubnetOverlaps (enableInfraVnet , nwCfg , cnsNetworkConfig ) {
227+ buf := fmt .Sprintf ("InfraVnet %v overlaps with customerVnet %+v" , nwCfg .InfraVnetAddressSpace , cnsNetworkConfig .CnetAddressSpace )
228+ log .Printf (buf )
229+ err = errors .New (buf )
230+ return nil , nil , net.IPNet {}, nil , err
231+ }
232+
233+ if nwCfg .EnableSnatOnHost {
234+ if cnsNetworkConfig .LocalIPConfiguration .IPSubnet .IPAddress == "" {
235+ log .Printf ("Snat IP is not populated. Got empty string" )
236+ return nil , nil , net.IPNet {}, nil , fmt .Errorf ("Snat IP is not populated. Got empty string" )
237+ }
238+ }
239+
240+ if enableInfraVnet {
241+ if nwCfg .InfraVnetAddressSpace == "" {
242+ log .Printf ("InfraVnetAddressSpace is not populated. Got empty string" )
243+ return nil , nil , net.IPNet {}, nil , fmt .Errorf ("InfraVnetAddressSpace is not populated. Got empty string" )
244+ }
245+ }
246+
247+ azIpamResult , err := getInfraVnetIP (enableInfraVnet , subnetPrefix .String (), nwCfg , plugin )
248+ if err != nil {
249+ log .Printf ("GetInfraVnetIP failed with error %v" , err )
250+ return nil , nil , net.IPNet {}, nil , err
251+ }
252+
253+ return result , cnsNetworkConfig , subnetPrefix , azIpamResult , nil
254+ }
255+
256+ return nil , nil , net.IPNet {}, nil , nil
257+ }
258+
259+ func CleanupMultitenancyResources (enableInfraVnet bool , nwCfg * cni.NetworkConfig , azIpamResult * cniTypesCurr.Result , plugin * netPlugin ) {
260+ if nwCfg .MultiTenancy && azIpamResult != nil && azIpamResult .IPs != nil {
261+ cleanupInfraVnetIP (enableInfraVnet , & azIpamResult .IPs [0 ].Address , nwCfg , plugin )
262+ }
263+ }
0 commit comments