summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/link
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/tcpip/link')
-rw-r--r--pkg/tcpip/link/fdbased/endpoint.go52
1 files changed, 32 insertions, 20 deletions
diff --git a/pkg/tcpip/link/fdbased/endpoint.go b/pkg/tcpip/link/fdbased/endpoint.go
index 4e20cfbf8..152d8f0b2 100644
--- a/pkg/tcpip/link/fdbased/endpoint.go
+++ b/pkg/tcpip/link/fdbased/endpoint.go
@@ -55,10 +55,15 @@ type endpoint struct {
// its end of the communication pipe.
closed func(*tcpip.Error)
- vv *buffer.VectorisedView
- iovecs []syscall.Iovec
- views []buffer.View
- attached bool
+ vv *buffer.VectorisedView
+ iovecs []syscall.Iovec
+ views []buffer.View
+ dispatcher stack.NetworkDispatcher
+
+ // handleLocal indicates whether packets destined to itself should be
+ // handled by the netstack internally (true) or be forwarded to the FD
+ // endpoint (false).
+ handleLocal bool
}
// Options specify the details about the fd-based endpoint to be created.
@@ -71,6 +76,7 @@ type Options struct {
Address tcpip.LinkAddress
SaveRestore bool
DisconnectOk bool
+ HandleLocal bool
}
// New creates a new fd-based endpoint.
@@ -100,14 +106,15 @@ func New(opts *Options) tcpip.LinkEndpointID {
}
e := &endpoint{
- fd: opts.FD,
- mtu: opts.MTU,
- caps: caps,
- closed: opts.ClosedFunc,
- addr: opts.Address,
- hdrSize: hdrSize,
- views: make([]buffer.View, len(BufConfig)),
- iovecs: make([]syscall.Iovec, len(BufConfig)),
+ fd: opts.FD,
+ mtu: opts.MTU,
+ caps: caps,
+ closed: opts.ClosedFunc,
+ addr: opts.Address,
+ hdrSize: hdrSize,
+ views: make([]buffer.View, len(BufConfig)),
+ iovecs: make([]syscall.Iovec, len(BufConfig)),
+ handleLocal: opts.HandleLocal,
}
vv := buffer.NewVectorisedView(0, e.views)
e.vv = &vv
@@ -117,16 +124,16 @@ func New(opts *Options) tcpip.LinkEndpointID {
// Attach launches the goroutine that reads packets from the file descriptor and
// dispatches them via the provided dispatcher.
func (e *endpoint) Attach(dispatcher stack.NetworkDispatcher) {
- e.attached = true
+ e.dispatcher = dispatcher
// Link endpoints are not savable. When transportation endpoints are
// saved, they stop sending outgoing packets and all incoming packets
// are rejected.
- go e.dispatchLoop(dispatcher) // S/R-SAFE: See above.
+ go e.dispatchLoop() // S/R-SAFE: See above.
}
// IsAttached implements stack.LinkEndpoint.IsAttached.
func (e *endpoint) IsAttached() bool {
- return e.attached
+ return e.dispatcher != nil
}
// MTU implements stack.LinkEndpoint.MTU. It returns the value initialized
@@ -153,6 +160,12 @@ func (e *endpoint) LinkAddress() tcpip.LinkAddress {
// WritePacket writes outbound packets to the file descriptor. If it is not
// currently writable, the packet is dropped.
func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.NetworkProtocolNumber) *tcpip.Error {
+ if e.handleLocal && r.LocalAddress != "" && r.LocalAddress == r.RemoteAddress {
+ hdrView := hdr.View()
+ vv := buffer.NewVectorisedView(len(hdrView)+len(payload), []buffer.View{hdrView, payload})
+ e.dispatcher.DeliverNetworkPacket(e, r.RemoteLinkAddress, protocol, &vv)
+ return nil
+ }
if e.hdrSize > 0 {
// Add ethernet header if needed.
eth := header.Ethernet(hdr.Prepend(header.EthernetMinimumSize))
@@ -165,7 +178,6 @@ func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload
if len(payload) == 0 {
return rawfile.NonBlockingWrite(e.fd, hdr.UsedBytes())
-
}
return rawfile.NonBlockingWrite2(e.fd, hdr.UsedBytes(), payload)
@@ -198,7 +210,7 @@ func (e *endpoint) allocateViews(bufConfig []int) {
}
// dispatch reads one packet from the file descriptor and dispatches it.
-func (e *endpoint) dispatch(d stack.NetworkDispatcher, largeV buffer.View) (bool, *tcpip.Error) {
+func (e *endpoint) dispatch(largeV buffer.View) (bool, *tcpip.Error) {
e.allocateViews(BufConfig)
n, err := rawfile.BlockingReadv(e.fd, e.iovecs)
@@ -234,7 +246,7 @@ func (e *endpoint) dispatch(d stack.NetworkDispatcher, largeV buffer.View) (bool
e.vv.SetSize(n)
e.vv.TrimFront(e.hdrSize)
- d.DeliverNetworkPacket(e, addr, p, e.vv)
+ e.dispatcher.DeliverNetworkPacket(e, addr, p, e.vv)
// Prepare e.views for another packet: release used views.
for i := 0; i < used; i++ {
@@ -246,10 +258,10 @@ func (e *endpoint) dispatch(d stack.NetworkDispatcher, largeV buffer.View) (bool
// dispatchLoop reads packets from the file descriptor in a loop and dispatches
// them to the network stack.
-func (e *endpoint) dispatchLoop(d stack.NetworkDispatcher) *tcpip.Error {
+func (e *endpoint) dispatchLoop() *tcpip.Error {
v := buffer.NewView(header.MaxIPPacketSize)
for {
- cont, err := e.dispatch(d, v)
+ cont, err := e.dispatch(v)
if err != nil || !cont {
if e.closed != nil {
e.closed(err)