9
9
"os"
10
10
"path/filepath"
11
11
"slices"
12
+ "strings"
12
13
"time"
13
14
14
15
"github.com/blang/semver"
@@ -25,6 +26,8 @@ import (
25
26
"github.com/threefoldtech/zos/pkg/netlight/namespace"
26
27
"github.com/threefoldtech/zos/pkg/netlight/options"
27
28
"github.com/threefoldtech/zos/pkg/netlight/resource"
29
+ "github.com/threefoldtech/zos/pkg/netlight/wireguard"
30
+ "github.com/threefoldtech/zos/pkg/set"
28
31
"github.com/threefoldtech/zos/pkg/versioned"
29
32
"github.com/vishvananda/netlink"
30
33
)
@@ -38,18 +41,17 @@ const (
38
41
networkDir = "networks"
39
42
)
40
43
41
- var (
42
- NDMZGwIP = & net.IPNet {
43
- IP : net .ParseIP ("100.127.0.1" ),
44
- Mask : net .CIDRMask (16 , 32 ),
45
- }
46
- )
44
+ var NDMZGwIP = & net.IPNet {
45
+ IP : net .ParseIP ("100.127.0.1" ),
46
+ Mask : net .CIDRMask (16 , 32 ),
47
+ }
47
48
48
49
var NetworkSchemaLatestVersion = semver .MustParse ("0.1.0" )
49
50
50
51
type networker struct {
51
52
ipamLease string
52
53
networkDir string
54
+ portSet * set.UIntSet
53
55
}
54
56
55
57
var _ pkg.NetworkerLight = (* networker )(nil )
@@ -63,13 +65,20 @@ func NewNetworker() (pkg.NetworkerLight, error) {
63
65
ipamLease := filepath .Join (vd , ipamLeaseDir )
64
66
runtimeDir := filepath .Join (vd , networkDir )
65
67
66
- return & networker {
68
+ nw := networker {
67
69
ipamLease : ipamLease ,
68
70
networkDir : runtimeDir ,
69
- }, nil
71
+ portSet : set .NewInt (),
72
+ }
73
+
74
+ if err := nw .syncWGPorts (); err != nil {
75
+ return nil , err
76
+ }
77
+ return & nw , nil
70
78
}
71
79
72
- func (n * networker ) Create (name string , privateNet net.IPNet , seed []byte ) error {
80
+ // func (n *networker) Create(name string, privateNet net.IPNet, seed []byte, twinID uint32, wgListenPort uint16, wgPrivateKey string, ipRange net.IPNet, nr pkg.Network) error {
81
+ func (n * networker ) Create (name string , net zos.NetworkLight ) error {
73
82
b , err := bridge .Get (NDMZBridge )
74
83
if err != nil {
75
84
return err
@@ -79,7 +88,67 @@ func (n *networker) Create(name string, privateNet net.IPNet, seed []byte) error
79
88
return err
80
89
}
81
90
82
- _ , err = resource .Create (name , b , ip , NDMZGwIP , & privateNet , seed )
91
+ storedNR , err := n .networkOf (zos .NetID (name ))
92
+ if err != nil && ! os .IsNotExist (err ) {
93
+ return errors .Wrap (err , "failed to load previous network setup" )
94
+ }
95
+
96
+ if err == nil {
97
+ if err := n .releasePort (storedNR .WGListenPort ); err != nil {
98
+ return err
99
+ }
100
+ }
101
+
102
+ if err := n .reservePort (net .WGListenPort ); err != nil {
103
+ return err
104
+ }
105
+
106
+ netr , err := resource .Create (name , b , ip , NDMZGwIP , & net .Subnet .IPNet , net .Mycelium .Key , net .NetworkIPRange .IPNet , net )
107
+ if err != nil {
108
+ return err
109
+ }
110
+
111
+ cleanup := func () {
112
+ log .Error ().Msg ("clean up network resource" )
113
+ if err := resource .Delete (name ); err != nil {
114
+ log .Error ().Err (err ).Msg ("error during deletion of network resource after failed deployment" )
115
+ }
116
+ if err := n .releasePort (net .WGListenPort ); err != nil {
117
+ log .Error ().Err (err ).Msg ("release wireguard port failed" )
118
+ }
119
+ }
120
+
121
+ defer func () {
122
+ if err != nil {
123
+ cleanup ()
124
+ }
125
+ }()
126
+
127
+ wgName , err := netr .WGName ()
128
+ if err != nil {
129
+ return errors .Wrap (err , "failed to get wg interface name for network resource" )
130
+ }
131
+
132
+ exists , err := netr .HasWireguard ()
133
+ if err != nil {
134
+ return errors .Wrap (err , "failed to check if network resource has wireguard setup" )
135
+ }
136
+
137
+ if ! exists {
138
+ var wg * wireguard.Wireguard
139
+ wg , err = wireguard .New (wgName )
140
+ if err != nil {
141
+ return errors .Wrapf (err , "failed to create wg interface for network resource '%s'" , name )
142
+ }
143
+ if err = netr .SetWireguard (wg ); err != nil {
144
+ return errors .Wrap (err , "failed to setup wireguard interface for network resource" )
145
+ }
146
+ }
147
+
148
+ if err = netr .ConfigureWG (net .WGPrivateKey ); err != nil {
149
+ return errors .Wrap (err , "failed to configure network resource" )
150
+ }
151
+
83
152
return err
84
153
}
85
154
@@ -89,7 +158,6 @@ func (n *networker) Delete(name string) error {
89
158
}
90
159
91
160
return resource .Delete (name )
92
-
93
161
}
94
162
95
163
func (n * networker ) AttachPrivate (name , id string , vmIp net.IP ) (device pkg.TapDevice , err error ) {
@@ -391,10 +459,14 @@ func (n *networker) Interfaces(iface string, netns string) (pkg.Interfaces, erro
391
459
}
392
460
393
461
func CreateNDMZBridge () (* netlink.Bridge , error ) {
394
- return createNDMZBridge (NDMZBridge , NDMZGw )
462
+ return createNDMZBridge (NDMZBridge )
395
463
}
396
464
397
- func createNDMZBridge (name string , gw string ) (* netlink.Bridge , error ) {
465
+ func (n * networker ) WireguardPorts () ([]uint , error ) {
466
+ return n .portSet .List ()
467
+ }
468
+
469
+ func createNDMZBridge (name string ) (* netlink.Bridge , error ) {
398
470
if ! bridge .Exists (name ) {
399
471
if _ , err := bridge .New (name ); err != nil {
400
472
return nil , errors .Wrapf (err , "couldn't create bridge %s" , name )
@@ -424,3 +496,68 @@ func createNDMZBridge(name string, gw string) (*netlink.Bridge, error) {
424
496
425
497
return link .(* netlink.Bridge ), nil
426
498
}
499
+
500
+ func (n * networker ) reservePort (port uint16 ) error {
501
+ log .Debug ().Uint16 ("port" , port ).Msg ("reserve wireguard port" )
502
+ err := n .portSet .Add (uint (port ))
503
+ if err != nil {
504
+ return errors .Wrap (err , "wireguard listen port already in use, pick another one" )
505
+ }
506
+
507
+ return nil
508
+ }
509
+
510
+ func (n * networker ) releasePort (port uint16 ) error {
511
+ log .Debug ().Uint16 ("port" , port ).Msg ("release wireguard port" )
512
+ n .portSet .Remove (uint (port ))
513
+ return nil
514
+ }
515
+
516
+ func (n * networker ) syncWGPorts () error {
517
+ names , err := namespace .List ("n-" )
518
+ if err != nil {
519
+ return err
520
+ }
521
+
522
+ readPort := func (name string ) (int , error ) {
523
+ netNS , err := namespace .GetByName (name )
524
+ if err != nil {
525
+ return 0 , err
526
+ }
527
+ defer netNS .Close ()
528
+
529
+ ifaceName := strings .Replace (name , "n-" , "w-" , 1 )
530
+
531
+ var port int
532
+ err = netNS .Do (func (_ ns.NetNS ) error {
533
+ link , err := wireguard .GetByName (ifaceName )
534
+ if err != nil {
535
+ return err
536
+ }
537
+ d , err := link .Device ()
538
+ if err != nil {
539
+ return err
540
+ }
541
+
542
+ port = d .ListenPort
543
+ return nil
544
+ })
545
+ if err != nil {
546
+ return 0 , err
547
+ }
548
+
549
+ return port , nil
550
+ }
551
+
552
+ for _ , name := range names {
553
+ port , err := readPort (name )
554
+ if err != nil {
555
+ log .Error ().Err (err ).Str ("namespace" , name ).Msgf ("failed to read port for network namespace" )
556
+ continue
557
+ }
558
+ // skip error cause we don't care if there are some duplicate at this point
559
+ _ = n .portSet .Add (uint (port ))
560
+ }
561
+
562
+ return nil
563
+ }
0 commit comments