@@ -19,8 +19,9 @@ import (
19
19
"encoding/json"
20
20
"fmt"
21
21
"io/ioutil"
22
+ "net"
22
23
"net/http"
23
- osexec "os/exec "
24
+ "runtime "
24
25
"strconv"
25
26
"strings"
26
27
"time"
@@ -35,6 +36,7 @@ import (
35
36
"github.com/contiv/netplugin/utils"
36
37
"github.com/contiv/netplugin/utils/netutils"
37
38
"github.com/vishvananda/netlink"
39
+ "github.com/vishvananda/netns"
38
40
)
39
41
40
42
const hostGWIP = "172.20.255.254"
@@ -212,131 +214,170 @@ func nsToPID(ns string) (int, error) {
212
214
return strconv .Atoi (elements [2 ])
213
215
}
214
216
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 )
218
219
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 )
221
221
}
222
222
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 )
225
228
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 )
229
235
}
230
236
231
237
return nil
232
238
}
233
239
234
240
// setIfAttrs sets the required attributes for the container interface
235
241
func setIfAttrs (pid int , ifname , cidr , newname string ) error {
242
+ runtime .LockOSThread ()
243
+ defer runtime .UnlockOSThread ()
236
244
237
- nsenterPath , err := osexec . LookPath ( "nsenter" )
245
+ globalNS , err := netns . Get ( )
238
246
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 )
244
248
}
245
249
250
+ defer func () {
251
+ netns .Set (globalNS )
252
+ globalNS .Close ()
253
+ }()
254
+
246
255
// find the link
247
256
link , err := getLink (ifname )
248
257
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 )
251
259
}
252
260
253
261
// 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" ,
257
264
ifname , pid , err )
258
- return err
259
265
}
260
266
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 )
265
268
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 )
269
270
}
270
- log .Infof ("Output from rename: %v" , rename )
271
271
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
+ }
275
275
276
+ link , err = getLink (ifname )
276
277
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 )
280
279
}
281
- log .Infof ("Output from ip assign: %v" , assignIP )
282
280
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
+ }
286
286
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 )
291
296
}
292
- log .Debugf ("Output from ip assign: %v" , bringUp )
293
- return nil
294
297
298
+ return nil
295
299
}
296
300
297
301
func 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 ()
299
306
if err != nil {
300
- return err
307
+ return fmt . Errorf ( "failed to get the global network namespace: %v" , err )
301
308
}
302
309
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 )
306
317
}
307
318
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
+ }
311
323
324
+ // find the link
325
+ link , err := getLink (intfName )
312
326
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 )
316
337
}
317
338
318
339
return nil
319
340
}
320
341
321
342
// setDefGw sets the default gateway for the container namespace
322
343
func 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 ()
324
348
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 )
326
364
}
327
- routePath , err := osexec .LookPath ("route" )
365
+
366
+ // find the link
367
+ link , err := getLink (intfName )
328
368
if err != nil {
329
- return err
369
+ return fmt . Errorf ( "unable to find link %q. Error %q" , intfName , err )
330
370
}
371
+
372
+ r := netlink.Route {LinkIndex : link .Attrs ().Index ,
373
+ Gw : addr ,
374
+ }
375
+
331
376
// 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 )
339
379
}
380
+
340
381
return nil
341
382
}
342
383
0 commit comments