diff options
author | Ian Gudger <igudger@google.com> | 2019-03-12 14:36:58 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2019-03-12 14:37:56 -0700 |
commit | a16f6e50c5a6465b94f367d62c7a46b34ef15f66 (patch) | |
tree | 6ad6ab66e1ed0c8da218f3db0afe47fc74452e06 | |
parent | 8930e79ebf72a0cc69e9b81af37bcbb57b115543 (diff) |
Make HandleLocal apply to all non-loopback interfaces.
HandleLocal is very similar conceptually to MULTICAST_LOOP, so we can unify
the implementations. This has the benefit of making HandleLocal apply even when
the fdbased link endpoint isn't in use.
In addition, move looping logic to route creation so that it doesn't need to be
run for each packet. This should improve performance.
PiperOrigin-RevId: 238099480
Change-Id: I72839f16f25310471453bc9d3fb8544815b25c23
-rw-r--r-- | pkg/tcpip/link/fdbased/endpoint.go | 15 | ||||
-rw-r--r-- | pkg/tcpip/stack/nic.go | 4 | ||||
-rw-r--r-- | pkg/tcpip/stack/route.go | 21 | ||||
-rw-r--r-- | pkg/tcpip/stack/stack.go | 13 | ||||
-rw-r--r-- | runsc/boot/loader.go | 5 | ||||
-rw-r--r-- | runsc/boot/network.go | 1 |
6 files changed, 28 insertions, 31 deletions
diff --git a/pkg/tcpip/link/fdbased/endpoint.go b/pkg/tcpip/link/fdbased/endpoint.go index fa980716d..d726551b0 100644 --- a/pkg/tcpip/link/fdbased/endpoint.go +++ b/pkg/tcpip/link/fdbased/endpoint.go @@ -100,11 +100,6 @@ type endpoint struct { inboundDispatcher linkDispatcher 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 - // packetDispatchMode controls the packet dispatcher used by this // endpoint. packetDispatchMode PacketDispatchMode @@ -128,7 +123,6 @@ type Options struct { Address tcpip.LinkAddress SaveRestore bool DisconnectOk bool - HandleLocal bool PacketDispatchMode PacketDispatchMode } @@ -168,7 +162,6 @@ func New(opts *Options) tcpip.LinkEndpointID { closed: opts.ClosedFunc, addr: opts.Address, hdrSize: hdrSize, - handleLocal: opts.HandleLocal, packetDispatchMode: opts.PacketDispatchMode, } @@ -256,14 +249,6 @@ 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.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { - if e.handleLocal && r.LocalAddress != "" && r.LocalAddress == r.RemoteAddress { - views := make([]buffer.View, 1, 1+len(payload.Views())) - views[0] = hdr.View() - views = append(views, payload.Views()...) - vv := buffer.NewVectorisedView(len(views[0])+payload.Size(), views) - e.dispatcher.DeliverNetworkPacket(e, r.RemoteLinkAddress, r.LocalLinkAddress, protocol, vv) - return nil - } if e.hdrSize > 0 { // Add ethernet header if needed. eth := header.Ethernet(hdr.Prepend(header.EthernetMinimumSize)) diff --git a/pkg/tcpip/stack/nic.go b/pkg/tcpip/stack/nic.go index 14267bb48..defa8102a 100644 --- a/pkg/tcpip/stack/nic.go +++ b/pkg/tcpip/stack/nic.go @@ -409,7 +409,7 @@ func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remote, _ tcpip.LinkAddr n.mu.RLock() for _, ref := range n.endpoints { if ref.protocol == header.IPv4ProtocolNumber && ref.tryIncRef() { - r := makeRoute(protocol, dst, src, linkEP.LinkAddress(), ref, false /* multicastLoop */) + r := makeRoute(protocol, dst, src, linkEP.LinkAddress(), ref, false /* handleLocal */, false /* multicastLoop */) r.RemoteLinkAddress = remote ref.ep.HandlePacket(&r, vv) ref.decRef() @@ -420,7 +420,7 @@ func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remote, _ tcpip.LinkAddr } if ref := n.getRef(protocol, dst); ref != nil { - r := makeRoute(protocol, dst, src, linkEP.LinkAddress(), ref, false /* multicastLoop */) + r := makeRoute(protocol, dst, src, linkEP.LinkAddress(), ref, false /* handleLocal */, false /* multicastLoop */) r.RemoteLinkAddress = remote ref.ep.HandlePacket(&r, vv) ref.decRef() diff --git a/pkg/tcpip/stack/route.go b/pkg/tcpip/stack/route.go index c9603ad5e..86fb728b2 100644 --- a/pkg/tcpip/stack/route.go +++ b/pkg/tcpip/stack/route.go @@ -47,19 +47,27 @@ type Route struct { // starts. ref *referencedNetworkEndpoint - multicastLoop bool + // loop controls where WritePacket should send packets. + loop PacketLooping } // makeRoute initializes a new route. It takes ownership of the provided // reference to a network endpoint. -func makeRoute(netProto tcpip.NetworkProtocolNumber, localAddr, remoteAddr tcpip.Address, localLinkAddr tcpip.LinkAddress, ref *referencedNetworkEndpoint, multicastLoop bool) Route { +func makeRoute(netProto tcpip.NetworkProtocolNumber, localAddr, remoteAddr tcpip.Address, localLinkAddr tcpip.LinkAddress, ref *referencedNetworkEndpoint, handleLocal, multicastLoop bool) Route { + loop := PacketOut + if handleLocal && localAddr != "" && remoteAddr == localAddr { + loop = PacketLoop + } else if multicastLoop && (header.IsV4MulticastAddress(remoteAddr) || header.IsV6MulticastAddress(remoteAddr)) { + loop |= PacketLoop + } + return Route{ NetProto: netProto, LocalAddress: localAddr, LocalLinkAddress: localLinkAddr, RemoteAddress: remoteAddr, ref: ref, - multicastLoop: multicastLoop, + loop: loop, } } @@ -137,12 +145,7 @@ func (r *Route) IsResolutionRequired() bool { // WritePacket writes the packet through the given route. func (r *Route) WritePacket(hdr buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.TransportProtocolNumber, ttl uint8) *tcpip.Error { - loop := PacketOut - if r.multicastLoop && (header.IsV4MulticastAddress(r.RemoteAddress) || header.IsV6MulticastAddress(r.RemoteAddress)) { - loop |= PacketLoop - } - - err := r.ref.ep.WritePacket(r, hdr, payload, protocol, ttl, loop) + err := r.ref.ep.WritePacket(r, hdr, payload, protocol, ttl, r.loop) if err == tcpip.ErrNoRoute { r.Stats().IP.OutgoingPacketErrors.Increment() } diff --git a/pkg/tcpip/stack/stack.go b/pkg/tcpip/stack/stack.go index 047b704e0..cbfe5c3c7 100644 --- a/pkg/tcpip/stack/stack.go +++ b/pkg/tcpip/stack/stack.go @@ -308,6 +308,9 @@ type Stack struct { // clock is used to generate user-visible times. clock tcpip.Clock + + // handleLocal allows non-loopback interfaces to loop packets. + handleLocal bool } // Options contains optional Stack configuration. @@ -319,6 +322,11 @@ type Options struct { // Stats are optional statistic counters. Stats tcpip.Stats + + // HandleLocal indicates whether packets destined to their source + // should be handled by the stack internally (true) or outside the + // stack (false). + HandleLocal bool } // New allocates a new networking stack with only the requested networking and @@ -343,6 +351,7 @@ func New(network []string, transport []string, opts Options) *Stack { PortManager: ports.NewPortManager(), clock: clock, stats: opts.Stats.FillIn(), + handleLocal: opts.HandleLocal, } // Add specified network protocols. @@ -764,7 +773,7 @@ func (s *Stack) FindRoute(id tcpip.NICID, localAddr, remoteAddr tcpip.Address, n if id != 0 && !needRoute { if nic, ok := s.nics[id]; ok { if ref := s.getRefEP(nic, localAddr, netProto); ref != nil { - return makeRoute(netProto, ref.ep.ID().LocalAddress, remoteAddr, nic.linkEP.LinkAddress(), ref, multicastLoop && !nic.loopback), nil + return makeRoute(netProto, ref.ep.ID().LocalAddress, remoteAddr, nic.linkEP.LinkAddress(), ref, s.handleLocal && !nic.loopback, multicastLoop && !nic.loopback), nil } } } else { @@ -780,7 +789,7 @@ func (s *Stack) FindRoute(id tcpip.NICID, localAddr, remoteAddr tcpip.Address, n remoteAddr = ref.ep.ID().LocalAddress } - r := makeRoute(netProto, ref.ep.ID().LocalAddress, remoteAddr, nic.linkEP.LinkAddress(), ref, multicastLoop && !nic.loopback) + r := makeRoute(netProto, ref.ep.ID().LocalAddress, remoteAddr, nic.linkEP.LinkAddress(), ref, s.handleLocal && !nic.loopback, multicastLoop && !nic.loopback) if needRoute { r.NextHop = route.Gateway } diff --git a/runsc/boot/loader.go b/runsc/boot/loader.go index 4c7e6abfc..9ebe64dce 100644 --- a/runsc/boot/loader.go +++ b/runsc/boot/loader.go @@ -769,8 +769,9 @@ func newEmptyNetworkStack(conf *Config, clock tcpip.Clock) (inet.Stack, error) { netProtos := []string{ipv4.ProtocolName, ipv6.ProtocolName, arp.ProtocolName} protoNames := []string{tcp.ProtocolName, udp.ProtocolName, icmp.ProtocolName4} s := epsocket.Stack{stack.New(netProtos, protoNames, stack.Options{ - Clock: clock, - Stats: epsocket.Metrics, + Clock: clock, + Stats: epsocket.Metrics, + HandleLocal: true, })} if err := s.Stack.SetTransportProtocolOption(tcp.ProtocolNumber, tcp.SACKEnabled(true)); err != nil { return nil, fmt.Errorf("failed to enable SACK: %v", err) diff --git a/runsc/boot/network.go b/runsc/boot/network.go index 40bc147ca..f025a42f1 100644 --- a/runsc/boot/network.go +++ b/runsc/boot/network.go @@ -138,7 +138,6 @@ func (n *Network) CreateLinksAndRoutes(args *CreateLinksAndRoutesArgs, _ *struct FD: newFD, MTU: uint32(link.MTU), EthernetHeader: true, - HandleLocal: true, Address: mac, PacketDispatchMode: fdbased.PacketMMap, }) |