@@ -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
4042// epSpec contains the spec of the Endpoint to be created
@@ -210,131 +212,170 @@ func nsToPID(ns string) (int, error) {
210212 return strconv .Atoi (elements [2 ])
211213}
212214
213- func moveToNS (pid int , ifname string ) error {
214- // find the link
215- link , err := getLink (ifname )
215+ func setLinkAddress (link netlink.Link , address string ) error {
216+ addr , err := netlink .ParseAddr (address )
216217 if err != nil {
217- log .Errorf ("unable to find link %q. Error %q" , ifname , err )
218- return err
218+ return fmt .Errorf ("failed to parse address %s: %v" , address , err )
219219 }
220220
221- // move to the desired netns
222- err = netlink .LinkSetNsPid (link , pid )
221+ return netlink .AddrAdd (link , addr )
222+ }
223+
224+ func enterPIDNetNS (pid int ) error {
225+ netNS , err := netns .GetFromPid (pid )
223226 if err != nil {
224- log .Errorf ("unable to move interface %s to pid %d. Error: %s" ,
225- ifname , pid , err )
226- return err
227+ return fmt .Errorf ("failed to get the netns of pid %v: %v" , pid , err )
228+ }
229+ defer netNS .Close ()
230+
231+ if err = netns .Set (netNS ); err != nil {
232+ return fmt .Errorf ("failed to enter network namespace of pid %v: %v" , pid , err )
227233 }
228234
229235 return nil
230236}
231237
232238// setIfAttrs sets the required attributes for the container interface
233239func setIfAttrs (pid int , ifname , cidr , newname string ) error {
240+ runtime .LockOSThread ()
241+ defer runtime .UnlockOSThread ()
234242
235- nsenterPath , err := osexec . LookPath ( "nsenter" )
243+ globalNS , err := netns . Get ( )
236244 if err != nil {
237- return err
238- }
239- ipPath , err := osexec .LookPath ("ip" )
240- if err != nil {
241- return err
245+ return fmt .Errorf ("failed to get the global network namespace: %v" , err )
242246 }
243247
248+ defer func () {
249+ netns .Set (globalNS )
250+ globalNS .Close ()
251+ }()
252+
244253 // find the link
245254 link , err := getLink (ifname )
246255 if err != nil {
247- log .Errorf ("unable to find link %q. Error %q" , ifname , err )
248- return err
256+ return fmt .Errorf ("unable to find link %q. Error %q" , ifname , err )
249257 }
250258
251259 // move to the desired netns
252- err = netlink .LinkSetNsPid (link , pid )
253- if err != nil {
254- log .Errorf ("unable to move interface %s to pid %d. Error: %s" ,
260+ if err = netlink .LinkSetNsPid (link , pid ); err != nil {
261+ return fmt .Errorf ("unable to move interface %s to pid %d. Error: %s" ,
255262 ifname , pid , err )
256- return err
257263 }
258264
259- // rename to the desired ifname
260- nsPid := fmt .Sprintf ("%d" , pid )
261- rename , err := osexec .Command (nsenterPath , "-t" , nsPid , "-n" , "-F" , "--" , ipPath , "link" ,
262- "set" , "dev" , ifname , "name" , newname ).CombinedOutput ()
265+ netNS , err := netns .GetFromPid (pid )
263266 if err != nil {
264- log .Errorf ("unable to rename interface %s to %s. Error: %s" ,
265- ifname , newname , err )
266- return nil
267+ return fmt .Errorf ("failed to get the netns of pid %v: %v" , pid , err )
267268 }
268- log .Infof ("Output from rename: %v" , rename )
269269
270- // set the ip address
271- assignIP , err := osexec . Command ( nsenterPath , "-t" , nsPid , "-n" , "-F" , "--" , ipPath ,
272- "address" , "add" , cidr , "dev" , newname ). CombinedOutput ()
270+ if err = netns . Set ( netNS ); err != nil {
271+ return fmt . Errorf ( "failed to enter network namespace of pid %v: %v" , pid , err )
272+ }
273273
274+ link , err = getLink (ifname )
274275 if err != nil {
275- log .Errorf ("unable to assign ip %s to %s. Error: %s" ,
276- cidr , newname , err )
277- return nil
276+ return fmt .Errorf ("unable to find link %q. Error %q" , ifname , err )
278277 }
279- log .Infof ("Output from ip assign: %v" , assignIP )
280278
281- // Finally, mark the link up
282- bringUp , err := osexec .Command (nsenterPath , "-t" , nsPid , "-n" , "-F" , "--" , ipPath ,
283- "link" , "set" , "dev" , newname , "up" ).CombinedOutput ()
279+ // rename the interface from ifname to newname
280+ if err := netlink .LinkSetName (link , newname ); err != nil {
281+ return fmt .Errorf ("failed to rename interface %v to %v: %v" ,
282+ link , newname , err )
283+ }
284284
285- if err != nil {
286- log .Errorf ("unable to assign ip %s to %s. Error: %s" ,
287- cidr , newname , err )
288- return nil
285+ // set the ip address
286+ if err = setLinkAddress (link , cidr ); err != nil {
287+ return fmt .Errorf ("failed to bring up link %v: %v" , newname , err )
288+ }
289+
290+ // set the link up
291+ if err = netlink .LinkSetUp (link ); err != nil {
292+ return fmt .Errorf ("unable to bring up interface %v with address %v: %v" ,
293+ newname , cidr , err )
289294 }
290- log .Debugf ("Output from ip assign: %v" , bringUp )
291- return nil
292295
296+ return nil
293297}
294298
295299func addStaticRoute (pid int , subnet , intfName string ) error {
296- nsenterPath , err := osexec .LookPath ("nsenter" )
300+ runtime .LockOSThread ()
301+ defer runtime .UnlockOSThread ()
302+
303+ globalNS , err := netns .Get ()
297304 if err != nil {
298- return err
305+ return fmt . Errorf ( "failed to get the global network namespace: %v" , err )
299306 }
300307
301- ipPath , err := osexec .LookPath ("ip" )
302- if err != nil {
303- return err
308+ defer func () {
309+ netns .Set (globalNS )
310+ globalNS .Close ()
311+ }()
312+
313+ if err = enterPIDNetNS (pid ); err != nil {
314+ return fmt .Errorf ("failed to enter network namespace of pid %v: %v" , pid , err )
304315 }
305316
306- nsPid := fmt .Sprintf ("%d" , pid )
307- _ , err = osexec .Command (nsenterPath , "-t" , nsPid , "-n" , "-F" , "--" , ipPath ,
308- "route" , "add" , subnet , "dev" , intfName ).CombinedOutput ()
317+ parsedSubnet , err := netlink .ParseIPNet (subnet )
318+ if err != nil {
319+ return fmt .Errorf ("failed to parse subnet %v" , subnet )
320+ }
309321
322+ // find the link
323+ link , err := getLink (intfName )
310324 if err != nil {
311- log .Errorf ("unable to add route %s via %s. Error: %s" ,
312- subnet , intfName , err )
313- return err
325+ return fmt .Errorf ("unable to find link %q. Error %q" , intfName , err )
326+ }
327+
328+ r := netlink.Route {LinkIndex : link .Attrs ().Index ,
329+ Dst : parsedSubnet ,
330+ }
331+
332+ // set static route
333+ if err = netlink .RouteAdd (& r ); err != nil {
334+ return fmt .Errorf ("failed to set default gw %v. Error: %v" , parsedSubnet , err )
314335 }
315336
316337 return nil
317338}
318339
319340// setDefGw sets the default gateway for the container namespace
320341func setDefGw (pid int , gw , intfName string ) error {
321- nsenterPath , err := osexec .LookPath ("nsenter" )
342+ runtime .LockOSThread ()
343+ defer runtime .UnlockOSThread ()
344+
345+ globalNS , err := netns .Get ()
322346 if err != nil {
323- return err
347+ return fmt .Errorf ("failed to get the global network namespace: %v" , err )
348+ }
349+
350+ defer func () {
351+ netns .Set (globalNS )
352+ globalNS .Close ()
353+ }()
354+
355+ if err = enterPIDNetNS (pid ); err != nil {
356+ return fmt .Errorf ("failed to enter network namespace of pid %v: %v" , pid , err )
357+ }
358+
359+ addr := net .ParseIP (gw )
360+ if addr == nil {
361+ return fmt .Errorf ("failed to parse address %v" , gw )
324362 }
325- routePath , err := osexec .LookPath ("route" )
363+
364+ // find the link
365+ link , err := getLink (intfName )
326366 if err != nil {
327- return err
367+ return fmt . Errorf ( "unable to find link %q. Error %q" , intfName , err )
328368 }
369+
370+ r := netlink.Route {LinkIndex : link .Attrs ().Index ,
371+ Gw : addr ,
372+ }
373+
329374 // set default gw
330- nsPid := fmt .Sprintf ("%d" , pid )
331- out , err := osexec .Command (nsenterPath , "-t" , nsPid , "-n" , "-F" , "--" , routePath , "add" ,
332- "default" , "gw" , gw , intfName ).CombinedOutput ()
333- if err != nil {
334- log .Errorf ("unable to set default gw %s. Error: %s - %s" ,
335- gw , err , out )
336- return nil
375+ if err = netlink .RouteAdd (& r ); err != nil {
376+ return fmt .Errorf ("failed to set default gw %v. Error: %v" , gw , err )
337377 }
378+
338379 return nil
339380}
340381
0 commit comments