99 "github.com/Azure/azure-container-networking/cni"
1010 "github.com/Azure/azure-container-networking/cns"
1111 "github.com/Azure/azure-container-networking/cns/cnsclient"
12+ "github.com/Azure/azure-container-networking/iptables"
1213 "github.com/Azure/azure-container-networking/log"
1314 "github.com/Azure/azure-container-networking/network"
1415 cniTypes "github.com/containernetworking/cni/pkg/types"
@@ -48,7 +49,7 @@ func NewCNSInvoker(podName, namespace string) (*CNSIPAMInvoker, error) {
4849}
4950
5051//Add uses the requestipconfig API in cns, and returns ipv4 and a nil ipv6 as CNS doesn't support IPv6 yet
51- func (invoker * CNSIPAMInvoker ) Add (nwCfg * cni.NetworkConfig , subnetPrefix * net.IPNet , options map [string ]interface {}) (* cniTypesCurr.Result , * cniTypesCurr.Result , error ) {
52+ func (invoker * CNSIPAMInvoker ) Add (nwCfg * cni.NetworkConfig , hostSubnetPrefix * net.IPNet , options map [string ]interface {}) (* cniTypesCurr.Result , * cniTypesCurr.Result , error ) {
5253
5354 // Parse Pod arguments.
5455 podInfo := cns.KubernetesPodInfo {PodName : invoker .podName , PodNamespace : invoker .podNamespace }
@@ -61,7 +62,7 @@ func (invoker *CNSIPAMInvoker) Add(nwCfg *cni.NetworkConfig, subnetPrefix *net.I
6162 return nil , nil , err
6263 }
6364
64- resultIPv4 := IPv4ResultInfo {
65+ info := IPv4ResultInfo {
6566 podIPAddress : response .PodIpInfo .PodIPConfig .IPAddress ,
6667 ncSubnetPrefix : response .PodIpInfo .NetworkContainerPrimaryIPConfig .IPSubnet .PrefixLength ,
6768 ncPrimaryIP : response .PodIpInfo .NetworkContainerPrimaryIPConfig .IPSubnet .IPAddress ,
@@ -71,20 +72,46 @@ func (invoker *CNSIPAMInvoker) Add(nwCfg *cni.NetworkConfig, subnetPrefix *net.I
7172 hostGateway : response .PodIpInfo .HostPrimaryIPInfo .Gateway ,
7273 }
7374
74- ncgw := net .ParseIP (resultIPv4 .ncGatewayIPAddress )
75+ // set the NC Primary IP in options
76+ options [network .SNATIPKey ] = info .ncPrimaryIP
77+
78+ log .Printf ("[cni-invoker-cns] Received info %v for pod %v" , info , podInfo )
79+
80+ ncgw := net .ParseIP (info .ncGatewayIPAddress )
7581 if ncgw == nil {
76- return nil , nil , fmt .Errorf ("Gateway address %v from response is invalid" , resultIPv4 .ncGatewayIPAddress )
82+ return nil , nil , fmt .Errorf ("Gateway address %v from response is invalid" , info .ncGatewayIPAddress )
7783 }
7884
79- // set the NC Primary IP in options
80- options [network .SNATIPKey ] = resultIPv4 .ncPrimaryIP
85+ // set result ipconfig from CNS Response Body
86+ ip , ncipnet , err := net .ParseCIDR (info .podIPAddress + "/" + fmt .Sprint (info .ncSubnetPrefix ))
87+ if ip == nil {
88+ return nil , nil , fmt .Errorf ("Unable to parse IP from response: %v with err %v" , info .podIPAddress , err )
89+ }
8190
82- // set host gateway in options
83- options [network .HostGWKey ] = resultIPv4 .hostGateway
91+ // construct ipnet for result
92+ resultIPnet := net.IPNet {
93+ IP : ip ,
94+ Mask : ncipnet .Mask ,
95+ }
8496
85- log .Printf ("Received result %+v for pod %v" , resultIPv4 , podInfo )
97+ result := & cniTypesCurr.Result {
98+ IPs : []* cniTypesCurr.IPConfig {
99+ {
100+ Version : "4" ,
101+ Address : resultIPnet ,
102+ Gateway : ncgw ,
103+ },
104+ },
105+ Routes : []* cniTypes.Route {
106+ {
107+ Dst : network .Ipv4DefaultRouteDstPrefix ,
108+ GW : ncgw ,
109+ },
110+ },
111+ }
86112
87- result , err := getCNIIPv4Result (resultIPv4 , subnetPrefix )
113+ // set subnet prefix for host vm
114+ err = setHostOptions (nwCfg , hostSubnetPrefix , ncipnet , options , info )
88115 if err != nil {
89116 return nil , nil , err
90117 }
@@ -93,54 +120,44 @@ func (invoker *CNSIPAMInvoker) Add(nwCfg *cni.NetworkConfig, subnetPrefix *net.I
93120 return result , nil , nil
94121}
95122
96- func getCNIIPv4Result ( info IPv4ResultInfo , subnetPrefix * net.IPNet ) ( * cniTypesCurr. Result , error ) {
97-
98- gw := net .ParseIP (info .ncGatewayIPAddress )
99- if gw = = nil {
100- return nil , fmt . Errorf ( "Gateway address %v from response is invalid" , gw )
123+ func setHostOptions ( nwCfg * cni. NetworkConfig , hostSubnetPrefix * net.IPNet , ncSubnetPrefix * net. IPNet , options map [ string ] interface {}, info IPv4ResultInfo ) error {
124+ // get the name of the primary IP address
125+ _ , hostIPNet , err := net .ParseCIDR (info .hostSubnet )
126+ if err ! = nil {
127+ return err
101128 }
102129
130+ * hostSubnetPrefix = * hostIPNet
131+
132+ // get the host ip
103133 hostIP := net .ParseIP (info .hostPrimaryIP )
104134 if hostIP == nil {
105- return nil , fmt .Errorf ("Host IP address %v from response is invalid" , hostIP )
135+ return fmt .Errorf ("Host IP address %v from response is invalid" , info . hostPrimaryIP )
106136 }
107137
108- // set result ipconfig from CNS Response Body
109- ip , ipnet , err := net .ParseCIDR (info .podIPAddress + "/" + fmt . Sprint ( info . ncSubnetPrefix ) )
110- if ip == nil {
111- return nil , fmt .Errorf ("Unable to parse IP from response: %v " , info .podIPAddress )
138+ // get host gateway
139+ hostGateway := net .ParseIP (info .hostGateway )
140+ if hostGateway == nil {
141+ return fmt .Errorf ("Host Gateway %v from response is invalid " , info .hostGateway )
112142 }
113143
114- // get the name of the primary IP address
115- _ , hostIPNet , err := net .ParseCIDR (info .hostSubnet )
116- if err != nil {
117- return nil , err
144+ // this route is needed when the vm on subnet A needs to send traffic to a pod in subnet B on a different vm
145+ options [network .RoutesKey ] = []network.RouteInfo {
146+ {
147+ Dst : * ncSubnetPrefix ,
148+ Gw : hostGateway ,
149+ },
118150 }
119151
120- // set subnet prefix for host vm
121- * subnetPrefix = * hostIPNet
122-
123- // construct ipnet for result
124- resultIPnet := net.IPNet {
125- IP : ip ,
126- Mask : ipnet .Mask ,
152+ azureDNSMatch := fmt .Sprintf (" -m addrtype ! --dst-type local -s %s -d %s -p %s --dport %d" , ncSubnetPrefix .String (), iptables .AzureDNS , iptables .UDP , iptables .DNSPort )
153+ snatPrimaryIPJump := fmt .Sprintf ("%s --to %s" , iptables .Snat , info .ncPrimaryIP )
154+ options [network .IPTablesKey ] = []iptables.IPTableEntry {
155+ iptables .GetCreateChainCmd (iptables .V4 , iptables .Nat , iptables .Swift ),
156+ iptables .GetAppendIptableRuleCmd (iptables .V4 , iptables .Nat , iptables .Postrouting , "" , iptables .Swift ),
157+ iptables .GetInsertIptableRuleCmd (iptables .V4 , iptables .Nat , iptables .Swift , azureDNSMatch , snatPrimaryIPJump ),
127158 }
128159
129- return & cniTypesCurr.Result {
130- IPs : []* cniTypesCurr.IPConfig {
131- {
132- Version : "4" ,
133- Address : resultIPnet ,
134- Gateway : gw ,
135- },
136- },
137- Routes : []* cniTypes.Route {
138- {
139- Dst : network .Ipv4DefaultRouteDstPrefix ,
140- GW : gw ,
141- },
142- },
143- }, nil
160+ return nil
144161}
145162
146163// Delete calls into the releaseipconfiguration API in CNS
0 commit comments