99 "os"
1010 "path/filepath"
1111 "slices"
12+ "strings"
1213 "time"
1314
1415 "github.com/blang/semver"
@@ -20,13 +21,15 @@ import (
2021 localPkg "github.com/threefoldtech/zosbase/pkg"
2122 "github.com/threefoldtech/zosbase/pkg/cache"
2223 "github.com/threefoldtech/zosbase/pkg/gridtypes/zos"
24+ "github.com/threefoldtech/zosbase/pkg/netbase/wireguard"
2325 "github.com/threefoldtech/zosbase/pkg/netlight/bridge"
2426 "github.com/threefoldtech/zosbase/pkg/netlight/ifaceutil"
2527 "github.com/threefoldtech/zosbase/pkg/netlight/ipam"
2628 "github.com/threefoldtech/zosbase/pkg/netlight/namespace"
2729 "github.com/threefoldtech/zosbase/pkg/netlight/options"
2830 "github.com/threefoldtech/zosbase/pkg/netlight/public"
2931 "github.com/threefoldtech/zosbase/pkg/netlight/resource"
32+ "github.com/threefoldtech/zosbase/pkg/set"
3033 "github.com/threefoldtech/zosbase/pkg/versioned"
3134 "github.com/vishvananda/netlink"
3235)
@@ -50,6 +53,7 @@ var NetworkSchemaLatestVersion = semver.MustParse("0.1.0")
5053type networker struct {
5154 ipamLease string
5255 networkDir string
56+ portSet * set.UIntSet
5357}
5458
5559var _ localPkg.NetworkerLight = (* networker )(nil )
@@ -63,13 +67,19 @@ func NewNetworker() (localPkg.NetworkerLight, error) {
6367 ipamLease := filepath .Join (vd , ipamLeaseDir )
6468 runtimeDir := filepath .Join (vd , networkDir )
6569
66- return & networker {
70+ n := networker {
6771 ipamLease : ipamLease ,
6872 networkDir : runtimeDir ,
69- }, nil
73+ portSet : set .NewInt (),
74+ }
75+
76+ if err := n .syncWGPorts (); err != nil {
77+ return nil , err
78+ }
79+ return & n , nil
7080}
7181
72- func (n * networker ) Create (name string , privateNet net. IPNet , seed []byte ) error {
82+ func (n * networker ) Create (name string , net zos. NetworkLight , seed []byte ) error {
7383 b , err := bridge .Get (NDMZBridge )
7484 if err != nil {
7585 return err
@@ -79,7 +89,68 @@ func (n *networker) Create(name string, privateNet net.IPNet, seed []byte) error
7989 return err
8090 }
8191
82- _ , err = resource .Create (name , b , ip , NDMZGwIP , & privateNet , seed )
92+ storedNR , err := n .networkOf (zos .NetID (name ))
93+ if err != nil && ! os .IsNotExist (err ) {
94+ return errors .Wrap (err , "failed to load previous network setup" )
95+ }
96+
97+ if err == nil {
98+ if err := n .releasePort (storedNR .WGListenPort ); err != nil {
99+ return err
100+ }
101+ }
102+
103+ if err := n .reservePort (net .WGListenPort ); err != nil {
104+ return err
105+ }
106+
107+ // _, err = resource.Create(name, b, ip, NDMZGwIP, &privateNet, seed)
108+ netr , err := resource .Create (name , b , ip , NDMZGwIP , & net .Subnet .IPNet , seed , net )
109+ // netr, err := resource.Create(name, b, ip, NDMZGwIP, &net.Subnet.IPNet, net.Mycelium.Key, net.NetworkIPRange.IPNet, net)
110+ if err != nil {
111+ return err
112+ }
113+
114+ cleanup := func () {
115+ log .Error ().Msg ("clean up network resource" )
116+ if err := resource .Delete (name ); err != nil {
117+ log .Error ().Err (err ).Msg ("error during deletion of network resource after failed deployment" )
118+ }
119+ if err := n .releasePort (net .WGListenPort ); err != nil {
120+ log .Error ().Err (err ).Msg ("release wireguard port failed" )
121+ }
122+ }
123+
124+ defer func () {
125+ if err != nil {
126+ cleanup ()
127+ }
128+ }()
129+
130+ wgName , err := netr .WGName ()
131+ if err != nil {
132+ return errors .Wrap (err , "failed to get wg interface name for network resource" )
133+ }
134+
135+ exists , err := netr .HasWireguard ()
136+ if err != nil {
137+ return errors .Wrap (err , "failed to check if network resource has wireguard setup" )
138+ }
139+
140+ if ! exists {
141+ var wg * wireguard.Wireguard
142+ wg , err = wireguard .New (wgName )
143+ if err != nil {
144+ return errors .Wrapf (err , "failed to create wg interface for network resource '%s'" , name )
145+ }
146+ if err = netr .SetWireguard (wg ); err != nil {
147+ return errors .Wrap (err , "failed to setup wireguard interface for network resource" )
148+ }
149+ }
150+
151+ if err = netr .ConfigureWG (net .WGPrivateKey ); err != nil {
152+ return errors .Wrap (err , "failed to configure network resource" )
153+ }
83154 return err
84155}
85156
@@ -462,3 +533,72 @@ func createNDMZBridge(name string, gw string) (*netlink.Bridge, error) {
462533
463534 return link .(* netlink.Bridge ), nil
464535}
536+
537+ func (n * networker ) WireguardPorts () ([]uint , error ) {
538+ return n .portSet .List ()
539+ }
540+
541+ func (n * networker ) syncWGPorts () error {
542+ names , err := namespace .List ("n-" )
543+ if err != nil {
544+ return err
545+ }
546+
547+ readPort := func (name string ) (int , error ) {
548+ netNS , err := namespace .GetByName (name )
549+ if err != nil {
550+ return 0 , err
551+ }
552+ defer netNS .Close ()
553+
554+ ifaceName := strings .Replace (name , "n-" , "w-" , 1 )
555+
556+ var port int
557+ err = netNS .Do (func (_ ns.NetNS ) error {
558+ link , err := wireguard .GetByName (ifaceName )
559+ if err != nil {
560+ return err
561+ }
562+ d , err := link .Device ()
563+ if err != nil {
564+ return err
565+ }
566+
567+ port = d .ListenPort
568+ return nil
569+ })
570+ if err != nil {
571+ return 0 , err
572+ }
573+
574+ return port , nil
575+ }
576+
577+ for _ , name := range names {
578+ port , err := readPort (name )
579+ if err != nil {
580+ log .Error ().Err (err ).Str ("namespace" , name ).Msgf ("failed to read port for network namespace" )
581+ continue
582+ }
583+ // skip error cause we don't care if there are some duplicate at this point
584+ _ = n .portSet .Add (uint (port ))
585+ }
586+
587+ return nil
588+ }
589+
590+ func (n * networker ) reservePort (port uint16 ) error {
591+ log .Debug ().Uint16 ("port" , port ).Msg ("reserve wireguard port" )
592+ err := n .portSet .Add (uint (port ))
593+ if err != nil {
594+ return errors .Wrap (err , "wireguard listen port already in use, pick another one" )
595+ }
596+
597+ return nil
598+ }
599+
600+ func (n * networker ) releasePort (port uint16 ) error {
601+ log .Debug ().Uint16 ("port" , port ).Msg ("release wireguard port" )
602+ n .portSet .Remove (uint (port ))
603+ return nil
604+ }
0 commit comments