@@ -15,14 +15,13 @@ import (
1515 "gvisor.dev/gvisor/pkg/tcpip/stack"
1616)
1717
18- // SnapLen is the maximum bytes of a packet to be saved. Packets with a length
19- // less than or equal to snapLen will be saved in their entirety. Longer
20- // packets will be truncated to snapLen.
21- const SnapLen uint32 = 2048 // in bytes; some sufficient value
18+ // Clearing endpoint on Dispose will result in all stack.Linkpoint APIs
19+ // returning zero values (which may trip netstack?)
20+ const clearEndpointOnDispose = false
2221
2322type FdSwapper interface {
2423 // Swap closes existing FDs; uses new fd.
25- Swap (fd int ) error
24+ Swap (fd , mtu int ) error
2625 // Dispose closes all existing FDs.
2726 Dispose () error
2827 // Stat returns EpStat (fd, age, read, written, lastRead, lastWrite).
@@ -76,6 +75,8 @@ var _ stack.NetworkDispatcher = (*magiclink)(nil)
7675var _ stack.GSOEndpoint = (* magiclink )(nil )
7776var _ SeamlessEndpoint = (* magiclink )(nil )
7877
78+ var errMissingSink = errors .New ("magic: pcap sink is nil" )
79+
7980// ref: github.com/google/gvisor/blob/91f58d2cc/pkg/tcpip/sample/tun_tcp_echo/main.go#L102
8081func NewEndpoint (dev , mtu int , sink io.WriteCloser ) (ep SeamlessEndpoint , err error ) {
8182 defer func () {
@@ -85,6 +86,10 @@ func NewEndpoint(dev, mtu int, sink io.WriteCloser) (ep SeamlessEndpoint, err er
8586 log .I ("netstack: new endpoint(fd:%d / mtu:%d); err? %v" , dev , mtu , err )
8687 }()
8788
89+ if sink == nil {
90+ return nil , errMissingSink
91+ }
92+
8893 umtu := uint32 (mtu )
8994 opt := Options {
9095 FDs : []int {dev },
@@ -95,39 +100,27 @@ func NewEndpoint(dev, mtu int, sink io.WriteCloser) (ep SeamlessEndpoint, err er
95100 return nil , err
96101 }
97102 // ref: github.com/google/gvisor/blob/aeabb785278/pkg/tcpip/link/sniffer/sniffer.go#L111-L131
98- return snoop (ep , sink )
99- }
100-
101- func snoop (ep SeamlessEndpoint , sink io.WriteCloser ) (SeamlessEndpoint , error ) {
102- if sink == nil {
103- return ep , nil
104- }
105- // TODO: MTU instead of SnapLen? Must match pcapsink.begin()
106- link , err := newSnoopyEndpoint (ep , sink , true /*write header*/ )
107- if err != nil {
108- return nil , err
109- }
110-
111- v := core.NewVolatile [SeamlessEndpoint ](link )
103+ v := core.NewVolatile [SeamlessEndpoint ](ep )
112104 d := core .NewZeroVolatile [stack.NetworkDispatcher ]()
113- return & magiclink {v , d , sink }, nil
105+
106+ return & magiclink {v , d /*nil*/ , sink }, nil
114107}
115108
116109func Pcap2Stdout (y bool ) (ok bool ) {
117110 if y {
118- ok = LogPackets .CompareAndSwap (0 , 1 )
111+ ok = logPackets .CompareAndSwap (0 , 1 )
119112 } else {
120- ok = LogPackets .CompareAndSwap (1 , 0 )
113+ ok = logPackets .CompareAndSwap (1 , 0 )
121114 }
122115 log .I ("netstack: pcap stdout(%t): done?(%t)" , y , ok )
123116 return
124117}
125118
126119func Pcap2File (y bool ) (ok bool ) {
127120 if y {
128- ok = WritePCAP .CompareAndSwap (0 , 1 )
121+ ok = writePCAP .CompareAndSwap (0 , 1 )
129122 } else {
130- ok = WritePCAP .CompareAndSwap (1 , 0 )
123+ ok = writePCAP .CompareAndSwap (1 , 0 )
131124 }
132125 log .I ("netstack: pcap file(%t): done?(%t)" , y , ok )
133126 return
@@ -139,10 +132,10 @@ func Pcap2File(y bool) (ok bool) {
139132// - none: no packets are logged
140133func PcapModes () string {
141134 var modes []string
142- if LogPackets .Load () == 1 {
135+ if logPackets .Load () == 1 {
143136 modes = append (modes , "stdout" )
144137 }
145- if WritePCAP .Load () == 1 {
138+ if writePCAP .Load () == 1 {
146139 modes = append (modes , "file" )
147140 }
148141 if len (modes ) == 0 {
@@ -152,12 +145,12 @@ func PcapModes() string {
152145}
153146
154147// Swap implements SeamlessEndpoint.
155- func (l * magiclink ) Swap (fd int ) (err error ) {
148+ func (l * magiclink ) Swap (fd , mtu int ) (err error ) {
156149 e := l .e .Load ()
157150 hasSwappedFd := false
158151 needsNewEndpoint := e == nil
159152 if e != nil {
160- err = e .Swap (fd )
153+ err = e .Swap (fd , mtu )
161154 hasSwappedFd = err == nil
162155 needsNewEndpoint = errors .Is (err , errNeedsNewEndpoint )
163156 }
@@ -168,46 +161,45 @@ func (l *magiclink) Swap(fd int) (err error) {
168161 return err
169162 }
170163
171- if needsNewEndpoint {
172- umtu := uint32 (l .MTU ())
173- opt := Options {
174- FDs : []int {fd },
175- MTU : umtu ,
176- }
177-
178- ep , err := newFdbasedInjectableEndpoint (& opt )
179- if err != nil {
180- log .E ("netstack: magic(%d); swap: err %v" , fd , err )
181- return err
182- }
164+ umtu := uint32 (mtu )
165+ opt := Options {
166+ FDs : []int {fd },
167+ MTU : umtu ,
168+ }
183169
184- link , err := newSnoopyEndpoint ( ep , l . s , false /*write header*/ )
185- if err != nil {
186- log .E ("netstack: magic(%d); swap: err %v" , fd , err )
187- return err
188- }
170+ ep , err := newFdbasedInjectableEndpoint ( & opt )
171+ if err != nil {
172+ log .E ("netstack: magic(%d); swap: err %v" , fd , err )
173+ return err
174+ }
189175
190- if old := l .e .Swap (link ); old != nil {
191- core .Go ("magic." + strconv .Itoa (fd ), old .Close )
192- }
176+ if old := l .e .Swap (ep ); old != nil {
177+ core .Go ("magic." + strconv .Itoa (fd ), old .Close )
178+ }
193179
194- d := l .d .Load ()
195- if d == nil {
196- ep .Attach (nil ) // attach the new endpoint to the dispatcher
197- } else {
198- ep .Attach (l ) // attach the new endpoint to the existing dispatcher
199- }
200- logei (d == nil )("netstack: magic(%d) mtu: %d; swap: new ep... dispatch? %t" ,
201- fd , umtu , d != nil )
180+ d := l .d .Load ()
181+ if d == nil {
182+ ep .Attach (nil ) // attach the new endpoint to the dispatcher
183+ } else {
184+ ep .Attach (l ) // attach the new endpoint to the existing dispatcher
202185 }
186+ logei (d == nil )("netstack: magic(%d) mtu: %d; swap: new ep... dispatch? %t" ,
187+ fd , umtu , d != nil )
203188
204189 return nil
205190}
206191
207192// Dispose implements SeamlessEndpoint.
208193func (l * magiclink ) Dispose () error {
209194 if e := l .e .Load (); e != nil {
210- l .e .Store (nil ) // clear the endpoint
195+ if clearEndpointOnDispose {
196+ // will result in stack.LinkEndpoint impls return zero values
197+ // unsure if this will trip netstack in to thinking if this
198+ // endpoint is kaput, when in reality, this endpoint can swap
199+ // in a healthy endpoint at a later point in time, which then
200+ // we'd expect netstack to use as expected.
201+ l .e .Store (nil )
202+ }
211203 return e .Dispose ()
212204 }
213205 log .W ("netstack: magic: dispose; no endpoint" )
@@ -271,6 +263,7 @@ func (l *magiclink) Attach(dispatcher stack.NetworkDispatcher) {
271263 e .Attach (l )
272264 }
273265 }
266+ log .I ("netstack: magic: attach dispatcher? %t" , dispatcher == nil )
274267}
275268
276269func (l * magiclink ) IsAttached () bool {
@@ -281,6 +274,7 @@ func (l *magiclink) IsAttached() bool {
281274}
282275
283276func (l * magiclink ) DeliverNetworkPacket (protocol tcpip.NetworkProtocolNumber , pkt * stack.PacketBuffer ) {
277+ l .DumpPacket (DirectionRecv , protocol , pkt )
284278 if d := l .d .Load (); d != nil {
285279 d .DeliverNetworkPacket (protocol , pkt )
286280 }
@@ -293,9 +287,17 @@ func (l *magiclink) DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt
293287}
294288
295289func (l * magiclink ) WritePackets (pkts stack.PacketBufferList ) (int , tcpip.Error ) {
290+ if l .doPCAP () {
291+ for _ , pkt := range pkts .AsSlice () {
292+ if pkt != nil { // nilaway
293+ l .DumpPacket (DirectionSend , pkt .NetworkProtocolNumber , pkt )
294+ }
295+ }
296+ }
296297 if e := l .e .Load (); e != nil {
297298 return e .WritePackets (pkts )
298299 }
300+ log .E ("netstack: magic: write packets; no endpoint" )
299301 return 0 , & tcpip.ErrInvalidEndpointState {}
300302}
301303
0 commit comments