@@ -25,6 +25,36 @@ import (
25
25
var _ stack.LinkEndpoint = (* Endpoint )(nil )
26
26
var _ stack.GSOEndpoint = (* Endpoint )(nil )
27
27
28
+ type veth struct {
29
+ mu sync.RWMutex
30
+ closed bool
31
+ backlogQueue chan vethPacket
32
+ mtu uint32
33
+ endpoints [2 ]Endpoint
34
+ }
35
+
36
+ func (v * veth ) close () {
37
+ v .mu .Lock ()
38
+ closed := v .closed
39
+ v .closed = true
40
+ v .mu .Unlock ()
41
+ if closed {
42
+ return
43
+ }
44
+
45
+ for i := range v .endpoints {
46
+ e := & v .endpoints [i ]
47
+ e .mu .Lock ()
48
+ action := e .onCloseAction
49
+ e .onCloseAction = nil
50
+ e .mu .Unlock ()
51
+ if action != nil {
52
+ action ()
53
+ }
54
+ }
55
+ close (v .backlogQueue )
56
+ }
57
+
28
58
// +stateify savable
29
59
type vethPacket struct {
30
60
e * Endpoint
@@ -38,84 +68,55 @@ const backlogQueueSize = 64
38
68
//
39
69
// +stateify savable
40
70
type Endpoint struct {
41
- pair * Endpoint
71
+ peer * Endpoint
42
72
43
- backlogQueue * chan vethPacket
73
+ veth * veth
44
74
45
75
mu sync.RWMutex `state:"nosave"`
46
76
// +checklocks:mu
47
77
dispatcher stack.NetworkDispatcher
48
-
49
- // +checklocks:mu
50
- stack * stack.Stack
51
- // +checklocks:mu
52
- idx tcpip.NICID
53
78
// linkAddr is the local address of this endpoint.
54
79
//
55
80
// +checklocks:mu
56
81
linkAddr tcpip.LinkAddress
57
82
// +checklocks:mu
58
- mtu uint32
83
+ onCloseAction func ()
59
84
}
60
85
61
86
// NewPair creates a new veth pair.
62
87
func NewPair (mtu uint32 ) (* Endpoint , * Endpoint ) {
63
- backlogQueue := make (chan vethPacket , backlogQueueSize )
64
- a := & Endpoint {
65
- mtu : mtu ,
66
- linkAddr : tcpip .GetRandMacAddr (),
67
- backlogQueue : & backlogQueue ,
68
- }
69
- b := & Endpoint {
88
+ veth := veth {
89
+ backlogQueue : make (chan vethPacket , backlogQueueSize ),
70
90
mtu : mtu ,
71
- pair : a ,
72
- linkAddr : tcpip .GetRandMacAddr (),
73
- backlogQueue : & backlogQueue ,
91
+ endpoints : [2 ]Endpoint {
92
+ Endpoint {
93
+ linkAddr : tcpip .GetRandMacAddr (),
94
+ },
95
+ Endpoint {
96
+ linkAddr : tcpip .GetRandMacAddr (),
97
+ },
98
+ },
74
99
}
75
- a .pair = b
100
+ a := & veth .endpoints [0 ]
101
+ b := & veth .endpoints [1 ]
102
+ a .peer = b
103
+ b .peer = a
104
+ a .veth = & veth
105
+ b .veth = & veth
76
106
go func () {
77
- for t := range backlogQueue {
107
+ for t := range veth . backlogQueue {
78
108
t .e .InjectInbound (t .protocol , t .pkt )
79
109
t .pkt .DecRef ()
80
110
}
111
+
81
112
}()
82
113
return a , b
83
114
}
84
115
85
- // SetStack stores the stack and the device index.
86
- func (e * Endpoint ) SetStack (s * stack.Stack , idx tcpip.NICID ) {
87
- e .mu .Lock ()
88
- defer e .mu .Unlock ()
89
- e .stack = s
90
- e .idx = idx
91
- }
92
-
93
116
// Close closes e. Further packet injections will return an error, and all pending
94
117
// packets are discarded. Close may be called concurrently with WritePackets.
95
118
func (e * Endpoint ) Close () {
96
- e .mu .Lock ()
97
- stack := e .stack
98
- e .stack = nil
99
- e .mu .Unlock ()
100
- if stack == nil {
101
- return
102
- }
103
-
104
- e = e .pair
105
- e .mu .Lock ()
106
- stack = e .stack
107
- idx := e .idx
108
- e .stack = nil
109
- e .mu .Unlock ()
110
- if stack != nil {
111
- // The pair endpoint can live in the current stack or another one.
112
- // RemoveNIC will take the stack lock, so let's run it in another
113
- // goroutine to avoid lock conflicts.
114
- go func () {
115
- stack .RemoveNIC (idx )
116
- }()
117
- }
118
- close (* e .backlogQueue )
119
+ e .veth .close ()
119
120
}
120
121
121
122
// InjectInbound injects an inbound packet. If the endpoint is not attached, the
@@ -146,16 +147,16 @@ func (e *Endpoint) IsAttached() bool {
146
147
147
148
// MTU implements stack.LinkEndpoint.MTU.
148
149
func (e * Endpoint ) MTU () uint32 {
149
- e .mu .RLock ()
150
- defer e .mu .RUnlock ()
151
- return e .mtu
150
+ e .veth . mu .RLock ()
151
+ defer e .veth . mu .RUnlock ()
152
+ return e .veth . mtu
152
153
}
153
154
154
155
// SetMTU implements stack.LinkEndpoint.SetMTU.
155
156
func (e * Endpoint ) SetMTU (mtu uint32 ) {
156
- e .mu .Lock ()
157
- defer e .mu .Unlock ()
158
- e .mtu = mtu
157
+ e .veth . mu .Lock ()
158
+ defer e .veth . mu .Unlock ()
159
+ e .veth . mtu = mtu
159
160
}
160
161
161
162
// Capabilities implements stack.LinkEndpoint.Capabilities.
@@ -204,8 +205,8 @@ func (e *Endpoint) WritePackets(pkts stack.PacketBufferList) (int, tcpip.Error)
204
205
newPkt := stack .NewPacketBuffer (stack.PacketBufferOptions {
205
206
Payload : pkt .ToBuffer (),
206
207
})
207
- (* e .backlogQueue ) <- vethPacket {
208
- e : e .pair ,
208
+ (e . veth .backlogQueue ) <- vethPacket {
209
+ e : e .peer ,
209
210
protocol : pkt .NetworkProtocolNumber ,
210
211
pkt : newPkt ,
211
212
}
@@ -228,3 +229,10 @@ func (e *Endpoint) AddHeader(pkt *stack.PacketBuffer) {}
228
229
229
230
// ParseHeader implements stack.LinkEndpoint.ParseHeader.
230
231
func (e * Endpoint ) ParseHeader (pkt * stack.PacketBuffer ) bool { return true }
232
+
233
+ // SetOnCloseAction implements stack.LinkEndpoint.
234
+ func (e * Endpoint ) SetOnCloseAction (action func ()) {
235
+ e .mu .Lock ()
236
+ defer e .mu .Unlock ()
237
+ e .onCloseAction = action
238
+ }
0 commit comments