@@ -19,8 +19,9 @@ import (
1919 "encoding/json"
2020 "fmt"
2121 "io/ioutil"
22+ "net"
2223 "net/http"
23- osexec "os/exec "
24+ "runtime "
2425 "strconv"
2526 "strings"
2627 "time"
@@ -35,6 +36,7 @@ import (
3536 "github.com/contiv/netplugin/utils"
3637 "github.com/contiv/netplugin/utils/netutils"
3738 "github.com/vishvananda/netlink"
39+ "github.com/vishvananda/netns"
3840)
3941
4042const hostGWIP = "172.20.255.254"
@@ -212,131 +214,170 @@ func nsToPID(ns string) (int, error) {
212214 return strconv .Atoi (elements [2 ])
213215}
214216
215- func moveToNS (pid int , ifname string ) error {
216- // find the link
217- link , err := getLink (ifname )
217+ func setLinkAddress (link netlink.Link , address string ) error {
218+ addr , err := netlink .ParseAddr (address )
218219 if err != nil {
219- log .Errorf ("unable to find link %q. Error %q" , ifname , err )
220- return err
220+ return fmt .Errorf ("failed to parse address %s: %v" , address , err )
221221 }
222222
223- // move to the desired netns
224- err = netlink .LinkSetNsPid (link , pid )
223+ return netlink .AddrAdd (link , addr )
224+ }
225+
226+ func enterPIDNetNS (pid int ) error {
227+ netNS , err := netns .GetFromPid (pid )
225228 if err != nil {
226- log .Errorf ("unable to move interface %s to pid %d. Error: %s" ,
227- ifname , pid , err )
228- return err
229+ return fmt .Errorf ("failed to get the netns of pid %v: %v" , pid , err )
230+ }
231+ defer netNS .Close ()
232+
233+ if err = netns .Set (netNS ); err != nil {
234+ return fmt .Errorf ("failed to enter network namespace of pid %v: %v" , pid , err )
229235 }
230236
231237 return nil
232238}
233239
234240// setIfAttrs sets the required attributes for the container interface
235241func setIfAttrs (pid int , ifname , cidr , newname string ) error {
242+ runtime .LockOSThread ()
243+ defer runtime .UnlockOSThread ()
236244
237- nsenterPath , err := osexec . LookPath ( "nsenter" )
245+ globalNS , err := netns . Get ( )
238246 if err != nil {
239- return err
240- }
241- ipPath , err := osexec .LookPath ("ip" )
242- if err != nil {
243- return err
247+ return fmt .Errorf ("failed to get the global network namespace: %v" , err )
244248 }
245249
250+ defer func () {
251+ netns .Set (globalNS )
252+ globalNS .Close ()
253+ }()
254+
246255 // find the link
247256 link , err := getLink (ifname )
248257 if err != nil {
249- log .Errorf ("unable to find link %q. Error %q" , ifname , err )
250- return err
258+ return fmt .Errorf ("unable to find link %q. Error %q" , ifname , err )
251259 }
252260
253261 // move to the desired netns
254- err = netlink .LinkSetNsPid (link , pid )
255- if err != nil {
256- log .Errorf ("unable to move interface %s to pid %d. Error: %s" ,
262+ if err = netlink .LinkSetNsPid (link , pid ); err != nil {
263+ return fmt .Errorf ("unable to move interface %s to pid %d. Error: %s" ,
257264 ifname , pid , err )
258- return err
259265 }
260266
261- // rename to the desired ifname
262- nsPid := fmt .Sprintf ("%d" , pid )
263- rename , err := osexec .Command (nsenterPath , "-t" , nsPid , "-n" , "-F" , "--" , ipPath , "link" ,
264- "set" , "dev" , ifname , "name" , newname ).CombinedOutput ()
267+ netNS , err := netns .GetFromPid (pid )
265268 if err != nil {
266- log .Errorf ("unable to rename interface %s to %s. Error: %s" ,
267- ifname , newname , err )
268- return nil
269+ return fmt .Errorf ("failed to get the netns of pid %v: %v" , pid , err )
269270 }
270- log .Infof ("Output from rename: %v" , rename )
271271
272- // set the ip address
273- assignIP , err := osexec . Command ( nsenterPath , "-t" , nsPid , "-n" , "-F" , "--" , ipPath ,
274- "address" , "add" , cidr , "dev" , newname ). CombinedOutput ()
272+ if err = netns . Set ( netNS ); err != nil {
273+ return fmt . Errorf ( "failed to enter network namespace of pid %v: %v" , pid , err )
274+ }
275275
276+ link , err = getLink (ifname )
276277 if err != nil {
277- log .Errorf ("unable to assign ip %s to %s. Error: %s" ,
278- cidr , newname , err )
279- return nil
278+ return fmt .Errorf ("unable to find link %q. Error %q" , ifname , err )
280279 }
281- log .Infof ("Output from ip assign: %v" , assignIP )
282280
283- // Finally, mark the link up
284- bringUp , err := osexec .Command (nsenterPath , "-t" , nsPid , "-n" , "-F" , "--" , ipPath ,
285- "link" , "set" , "dev" , newname , "up" ).CombinedOutput ()
281+ // rename the interface from ifname to newname
282+ if err := netlink .LinkSetName (link , newname ); err != nil {
283+ return fmt .Errorf ("failed to rename interface %v to %v: %v" ,
284+ link , newname , err )
285+ }
286286
287- if err != nil {
288- log .Errorf ("unable to assign ip %s to %s. Error: %s" ,
289- cidr , newname , err )
290- return nil
287+ // set the ip address
288+ if err = setLinkAddress (link , cidr ); err != nil {
289+ return fmt .Errorf ("failed to bring up link %v: %v" , newname , err )
290+ }
291+
292+ // set the link up
293+ if err = netlink .LinkSetUp (link ); err != nil {
294+ return fmt .Errorf ("unable to bring up interface %v with address %v: %v" ,
295+ newname , cidr , err )
291296 }
292- log .Debugf ("Output from ip assign: %v" , bringUp )
293- return nil
294297
298+ return nil
295299}
296300
297301func addStaticRoute (pid int , subnet , intfName string ) error {
298- nsenterPath , err := osexec .LookPath ("nsenter" )
302+ runtime .LockOSThread ()
303+ defer runtime .UnlockOSThread ()
304+
305+ globalNS , err := netns .Get ()
299306 if err != nil {
300- return err
307+ return fmt . Errorf ( "failed to get the global network namespace: %v" , err )
301308 }
302309
303- ipPath , err := osexec .LookPath ("ip" )
304- if err != nil {
305- return err
310+ defer func () {
311+ netns .Set (globalNS )
312+ globalNS .Close ()
313+ }()
314+
315+ if err = enterPIDNetNS (pid ); err != nil {
316+ return fmt .Errorf ("failed to enter network namespace of pid %v: %v" , pid , err )
306317 }
307318
308- nsPid := fmt .Sprintf ("%d" , pid )
309- _ , err = osexec .Command (nsenterPath , "-t" , nsPid , "-n" , "-F" , "--" , ipPath ,
310- "route" , "add" , subnet , "dev" , intfName ).CombinedOutput ()
319+ parsedSubnet , err := netlink .ParseIPNet (subnet )
320+ if err != nil {
321+ return fmt .Errorf ("failed to parse subnet %v" , subnet )
322+ }
311323
324+ // find the link
325+ link , err := getLink (intfName )
312326 if err != nil {
313- log .Errorf ("unable to add route %s via %s. Error: %s" ,
314- subnet , intfName , err )
315- return err
327+ return fmt .Errorf ("unable to find link %q. Error %q" , intfName , err )
328+ }
329+
330+ r := netlink.Route {LinkIndex : link .Attrs ().Index ,
331+ Dst : parsedSubnet ,
332+ }
333+
334+ // set static route
335+ if err = netlink .RouteAdd (& r ); err != nil {
336+ return fmt .Errorf ("failed to set default gw %v. Error: %v" , parsedSubnet , err )
316337 }
317338
318339 return nil
319340}
320341
321342// setDefGw sets the default gateway for the container namespace
322343func setDefGw (pid int , gw , intfName string ) error {
323- nsenterPath , err := osexec .LookPath ("nsenter" )
344+ runtime .LockOSThread ()
345+ defer runtime .UnlockOSThread ()
346+
347+ globalNS , err := netns .Get ()
324348 if err != nil {
325- return err
349+ return fmt .Errorf ("failed to get the global network namespace: %v" , err )
350+ }
351+
352+ defer func () {
353+ netns .Set (globalNS )
354+ globalNS .Close ()
355+ }()
356+
357+ if err = enterPIDNetNS (pid ); err != nil {
358+ return fmt .Errorf ("failed to enter network namespace of pid %v: %v" , pid , err )
359+ }
360+
361+ addr := net .ParseIP (gw )
362+ if addr == nil {
363+ return fmt .Errorf ("failed to parse address %v" , gw )
326364 }
327- routePath , err := osexec .LookPath ("route" )
365+
366+ // find the link
367+ link , err := getLink (intfName )
328368 if err != nil {
329- return err
369+ return fmt . Errorf ( "unable to find link %q. Error %q" , intfName , err )
330370 }
371+
372+ r := netlink.Route {LinkIndex : link .Attrs ().Index ,
373+ Gw : addr ,
374+ }
375+
331376 // set default gw
332- nsPid := fmt .Sprintf ("%d" , pid )
333- out , err := osexec .Command (nsenterPath , "-t" , nsPid , "-n" , "-F" , "--" , routePath , "add" ,
334- "default" , "gw" , gw , intfName ).CombinedOutput ()
335- if err != nil {
336- log .Errorf ("unable to set default gw %s. Error: %s - %s" ,
337- gw , err , out )
338- return nil
377+ if err = netlink .RouteAdd (& r ); err != nil {
378+ return fmt .Errorf ("failed to set default gw %v. Error: %v" , gw , err )
339379 }
380+
340381 return nil
341382}
342383
0 commit comments