@@ -2,10 +2,10 @@ package netstack
22
33import (
44 "errors"
5+ "fmt"
56 "io"
67 "strconv"
78 "strings"
8- "sync"
99 "syscall"
1010
1111 "github.com/celzero/firestack/intra/core"
@@ -21,15 +21,64 @@ import (
2121const SnapLen uint32 = 2048 // in bytes; some sufficient value
2222
2323var (
24- errNoFdSwapper = errors .New ("linkFdSwap : no FdSwapper" )
24+ errNoFdSwapper = errors .New ("magiclink : no FdSwapper" )
2525)
2626
27- type linkSwap struct {
28- sync.Mutex
29- e stack.LinkEndpoint
27+ type FdSwapper interface {
28+ // Swap closes existing FDs; uses new fd.
29+ Swap (fd int ) error
30+ // Dispose closes all existing FDs.
31+ Dispose () error
32+ // Stat returns EpStat (fd, age, read, written, lastRead, lastWrite).
33+ Stat () EpStat
34+ }
35+
36+ type EpStat struct {
37+ // Fd is the file descriptor of the endpoint.
38+ Fd int
39+ // Alive indicates whether the endpoint is alive.
40+ Alive bool
41+ // Age is the age of the endpoint.
42+ Age string
43+ // Read is the number of bytes read from the endpoint.
44+ Read string
45+ // Written is the number of bytes written to the endpoint.
46+ Written string
47+ // LastRead is the last time the endpoint was read from.
48+ LastRead string
49+ // LastWrite is the last time the endpoint was written to.
50+ LastWrite string
51+ }
52+
53+ func (s EpStat ) String () string {
54+ if s .Fd == 0 {
55+ return "<nil>"
56+ }
57+ return fmt .Sprintf ("Fd: %d,Alive: %t,Age: %s,R: %s,W: %s,LastRead: %s,LastWrite: %s" ,
58+ s .Fd ,
59+ s .Alive ,
60+ s .Age ,
61+ s .Read ,
62+ s .Written ,
63+ s .LastRead ,
64+ s .LastWrite )
65+ }
66+
67+ type SeamlessEndpoint interface {
68+ stack.LinkEndpoint
3069 FdSwapper
3170}
3271
72+ type magiclink struct {
73+ e * core.Volatile [stack.LinkEndpoint ]
74+ d * core.Volatile [stack.NetworkDispatcher ]
75+ FdSwapper
76+ }
77+
78+ var _ stack.LinkEndpoint = (* magiclink )(nil )
79+ var _ stack.NetworkDispatcher = (* magiclink )(nil )
80+ var _ FdSwapper = (* magiclink )(nil )
81+
3382// ref: github.com/google/gvisor/blob/91f58d2cc/pkg/tcpip/sample/tun_tcp_echo/main.go#L102
3483func NewEndpoint (dev , mtu int , sink io.WriteCloser ) (ep SeamlessEndpoint , err error ) {
3584 defer func () {
@@ -60,7 +109,9 @@ func snoop(ep SeamlessEndpoint, sink io.WriteCloser) (SeamlessEndpoint, error) {
60109 if link , err := NewSnoopyEndpoint (ep , sink ); err != nil {
61110 return nil , err
62111 } else {
63- return & linkSwap {sync.Mutex {}, link , ep }, nil
112+ v := core.NewVolatile [stack.LinkEndpoint ](link )
113+ d := core .NewZeroVolatile [stack.NetworkDispatcher ]()
114+ return & magiclink {v , d , ep }, nil
64115 }
65116}
66117
@@ -103,7 +154,7 @@ func PcapModes() string {
103154}
104155
105156// Swap implements FdSwapper.
106- func (l * linkSwap ) Swap (fd int ) error {
157+ func (l * magiclink ) Swap (fd int ) error {
107158 if l .FdSwapper == nil {
108159 return errNoFdSwapper
109160 }
@@ -116,120 +167,136 @@ func (l *linkSwap) Swap(fd int) error {
116167 MTU : umtu ,
117168 }
118169 if ep , err := newFdbasedInjectableEndpoint (& opt ); err == nil {
119- l .Lock ()
120- core .Go ("linkFdSwap." + strconv .Itoa (fd ), l .e .Close )
121- l .e = ep
122- l .Unlock ()
170+ if old := l .e .Swap (ep ); old != nil {
171+ core .Go ("magic." + strconv .Itoa (fd ), old .Close )
172+ }
173+ if l .d .Load () == nil {
174+ log .W ("netstack: %d magic(mtu: %d); new ep but no dispatcher" , fd , umtu )
175+ ep .Attach (nil ) // attach the new endpoint to the dispatcher
176+ } else {
177+ log .I ("netstack: %d magic(mtu: %d); new ep, attaching dispatcher" , fd , umtu )
178+ ep .Attach (l ) // attach the new endpoint to the existing dispatcher
179+ }
123180 } else {
124- log .E ("netstack: linkFdSwap (%d); err %v" , fd , err )
181+ log .E ("netstack: magic (%d); err %v" , fd , err )
125182 return err
126183 }
127184 }
128185
129186 return err
130187}
131188
132- func (l * linkSwap ) MTU () uint32 {
133- l .Lock ()
134- e := l .e
135- l .Unlock ()
136- return e .MTU ()
189+ func (l * magiclink ) MTU () uint32 {
190+ if e := l .e .Load (); e != nil {
191+ return e .MTU ()
192+ }
193+ return 0
194+ }
195+
196+ func (l * magiclink ) SetMTU (mtu uint32 ) {
197+ if e := l .e .Load (); e != nil {
198+ e .SetMTU (mtu )
199+ }
200+ }
201+
202+ func (l * magiclink ) MaxHeaderLength () uint16 {
203+ if e := l .e .Load (); e != nil {
204+ return e .MaxHeaderLength ()
205+ }
206+ return 0
137207}
138208
139- func (l * linkSwap ) SetMTU ( mtu uint32 ) {
140- l . Lock ()
141- e := l . e
142- l . Unlock ()
143- e . SetMTU ( mtu )
209+ func (l * magiclink ) LinkAddress () tcpip. LinkAddress {
210+ if e := l . e . Load (); e != nil {
211+ return e . LinkAddress ()
212+ }
213+ return ""
144214}
145215
146- func (l * linkSwap ) MaxHeaderLength () uint16 {
147- l .Lock ()
148- e := l .e
149- l .Unlock ()
150- return e .MaxHeaderLength ()
216+ func (l * magiclink ) SetLinkAddress (addr tcpip.LinkAddress ) {
217+ if e := l .e .Load (); e != nil {
218+ e .SetLinkAddress (addr )
219+ }
151220}
152221
153- func (l * linkSwap ) LinkAddress () tcpip. LinkAddress {
154- l . Lock ()
155- e := l . e
156- l . Unlock ()
157- return e . LinkAddress ()
222+ func (l * magiclink ) Capabilities () stack. LinkEndpointCapabilities {
223+ if e := l . e . Load (); e != nil {
224+ return e . Capabilities ()
225+ }
226+ return 0
158227}
159228
160- func (l * linkSwap ) SetLinkAddress (addr tcpip.LinkAddress ) {
161- l .Lock ()
162- e := l .e
163- l .Unlock ()
164- e .SetLinkAddress (addr )
229+ func (l * magiclink ) Attach (dispatcher stack.NetworkDispatcher ) {
230+ l .d .Store (dispatcher ) // update the dispatcher
231+ if e := l .e .Load (); e != nil {
232+ if dispatcher == nil {
233+ e .Attach (nil ) // detach
234+ } else {
235+ e .Attach (l )
236+ }
237+ }
165238}
166239
167- func (l * linkSwap ) Capabilities () stack. LinkEndpointCapabilities {
168- l . Lock ()
169- e := l . e
170- l . Unlock ()
171- return e . Capabilities ()
240+ func (l * magiclink ) IsAttached () bool {
241+ if e := l . e . Load (); e != nil {
242+ return e . IsAttached ()
243+ }
244+ return false
172245}
173246
174- func (l * linkSwap ) Attach (dispatcher stack.NetworkDispatcher ) {
175- l .Lock ()
176- e := l .e
177- l .Unlock ()
178- e .Attach (dispatcher )
247+ func (l * magiclink ) DeliverNetworkPacket (protocol tcpip.NetworkProtocolNumber , pkt * stack.PacketBuffer ) {
248+ if d := l .d .Load (); d != nil {
249+ d .DeliverNetworkPacket (protocol , pkt )
250+ }
179251}
180252
181- func (l * linkSwap ) IsAttached () bool {
182- l .Lock ()
183- e := l .e
184- l .Unlock ()
185- return e .IsAttached ()
253+ func (l * magiclink ) DeliverLinkPacket (protocol tcpip.NetworkProtocolNumber , pkt * stack.PacketBuffer ) {
254+ if d := l .d .Load (); d != nil {
255+ d .DeliverLinkPacket (protocol , pkt )
256+ }
186257}
187258
188- func (l * linkSwap ) WritePackets (pkts stack.PacketBufferList ) (int , tcpip.Error ) {
189- l . Lock ()
190- e := l . e
191- l . Unlock ()
192- return e . WritePackets ( pkts )
259+ func (l * magiclink ) WritePackets (pkts stack.PacketBufferList ) (int , tcpip.Error ) {
260+ if e := l . e . Load (); e != nil {
261+ return e . WritePackets ( pkts )
262+ }
263+ return 0 , & tcpip. ErrInvalidEndpointState {}
193264}
194265
195- func (l * linkSwap ) Wait () {
196- l .Lock ()
197- e := l .e
198- l .Unlock ()
199- e .Wait ()
266+ func (l * magiclink ) Wait () {
267+ if e := l .e .Load (); e != nil {
268+ e .Wait ()
269+ }
200270}
201271
202- func (l * linkSwap ) ARPHardwareType () header.ARPHardwareType {
203- l . Lock ()
204- e := l . e
205- l . Unlock ()
206- return e . ARPHardwareType ()
272+ func (l * magiclink ) ARPHardwareType () header.ARPHardwareType {
273+ if e := l . e . Load (); e != nil {
274+ return e . ARPHardwareType ()
275+ }
276+ return 0
207277}
208278
209- func (l * linkSwap ) AddHeader (pkt * stack.PacketBuffer ) {
210- l .Lock ()
211- e := l .e
212- l .Unlock ()
213- e .AddHeader (pkt )
279+ func (l * magiclink ) AddHeader (pkt * stack.PacketBuffer ) {
280+ if e := l .e .Load (); e != nil {
281+ e .AddHeader (pkt )
282+ }
214283}
215284
216- func (l * linkSwap ) ParseHeader (pkt * stack.PacketBuffer ) bool {
217- l . Lock ()
218- e := l . e
219- l . Unlock ()
220- return e . ParseHeader ( pkt )
285+ func (l * magiclink ) ParseHeader (pkt * stack.PacketBuffer ) bool {
286+ if e := l . e . Load (); e != nil {
287+ return e . ParseHeader ( pkt )
288+ }
289+ return false
221290}
222291
223- func (l * linkSwap ) Close () {
224- l .Lock ()
225- e := l .e
226- l .Unlock ()
227- e .Close ()
292+ func (l * magiclink ) Close () {
293+ if e := l .e .Load (); e != nil {
294+ e .Close ()
295+ }
228296}
229297
230- func (l * linkSwap ) SetOnCloseAction (f func ()) {
231- l .Lock ()
232- e := l .e
233- l .Unlock ()
234- e .SetOnCloseAction (f )
298+ func (l * magiclink ) SetOnCloseAction (f func ()) {
299+ if e := l .e .Load (); e != nil {
300+ e .SetOnCloseAction (f )
301+ }
235302}
0 commit comments