diff options
-rw-r--r-- | pkg/tcpip/link/fdbased/endpoint.go | 57 | ||||
-rw-r--r-- | pkg/tcpip/link/fdbased/endpoint_test.go | 6 | ||||
-rw-r--r-- | pkg/tcpip/sample/tun_tcp_connect/main.go | 5 | ||||
-rw-r--r-- | pkg/tcpip/sample/tun_tcp_echo/main.go | 5 | ||||
-rw-r--r-- | runsc/boot/network.go | 5 |
5 files changed, 48 insertions, 30 deletions
diff --git a/pkg/tcpip/link/fdbased/endpoint.go b/pkg/tcpip/link/fdbased/endpoint.go index 84439a9ed..6354688e2 100644 --- a/pkg/tcpip/link/fdbased/endpoint.go +++ b/pkg/tcpip/link/fdbased/endpoint.go @@ -136,10 +136,9 @@ type Options struct { // // Makes fd non-blocking, but does not take ownership of fd, which must remain // open for the lifetime of the returned endpoint. -func New(opts *Options) tcpip.LinkEndpointID { +func New(opts *Options) (tcpip.LinkEndpointID, error) { if err := syscall.SetNonblock(opts.FD, true); err != nil { - // TODO : replace panic with an error return. - panic(fmt.Sprintf("syscall.SetNonblock(%v) failed: %v", opts.FD, err)) + return 0, fmt.Errorf("syscall.SetNonblock(%v) failed: %v", opts.FD, err) } caps := stack.LinkEndpointCapabilities(0) @@ -175,27 +174,34 @@ func New(opts *Options) tcpip.LinkEndpointID { packetDispatchMode: opts.PacketDispatchMode, } - if opts.GSOMaxSize != 0 && isSocketFD(opts.FD) { - e.caps |= stack.CapabilityGSO - e.gsoMaxSize = opts.GSOMaxSize + // For non-socket FDs we read one packet a time (e.g. TAP devices). + msgsPerRecv := 1 + e.inboundDispatcher = e.dispatch + + isSocket, err := isSocketFD(opts.FD) + if err != nil { + return 0, err } - if isSocketFD(opts.FD) && e.packetDispatchMode == PacketMMap { - if err := e.setupPacketRXRing(); err != nil { - // TODO: replace panic with an error return. - panic(fmt.Sprintf("e.setupPacketRXRing failed: %v", err)) + if isSocket { + if opts.GSOMaxSize != 0 { + e.caps |= stack.CapabilityGSO + e.gsoMaxSize = opts.GSOMaxSize } - e.inboundDispatcher = e.packetMMapDispatch - return stack.RegisterLinkEndpoint(e) - } - // For non-socket FDs we read one packet a time (e.g. TAP devices) - msgsPerRecv := 1 - e.inboundDispatcher = e.dispatch - // If the provided FD is a socket then we optimize packet reads by - // using recvmmsg() instead of read() to read packets in a batch. - if isSocketFD(opts.FD) && e.packetDispatchMode == RecvMMsg { - e.inboundDispatcher = e.recvMMsgDispatch - msgsPerRecv = MaxMsgsPerRecv + switch e.packetDispatchMode { + case PacketMMap: + if err := e.setupPacketRXRing(); err != nil { + return 0, fmt.Errorf("e.setupPacketRXRing failed: %v", err) + } + e.inboundDispatcher = e.packetMMapDispatch + return stack.RegisterLinkEndpoint(e), nil + + case RecvMMsg: + // If the provided FD is a socket then we optimize packet reads by + // using recvmmsg() instead of read() to read packets in a batch. + e.inboundDispatcher = e.recvMMsgDispatch + msgsPerRecv = MaxMsgsPerRecv + } } e.views = make([][]buffer.View, msgsPerRecv) @@ -217,16 +223,15 @@ func New(opts *Options) tcpip.LinkEndpointID { e.msgHdrs[i].Msg.Iovlen = uint64(iovLen) } - return stack.RegisterLinkEndpoint(e) + return stack.RegisterLinkEndpoint(e), nil } -func isSocketFD(fd int) bool { +func isSocketFD(fd int) (bool, error) { var stat syscall.Stat_t if err := syscall.Fstat(fd, &stat); err != nil { - // TODO : replace panic with an error return. - panic(fmt.Sprintf("syscall.Fstat(%v,...) failed: %v", fd, err)) + return false, fmt.Errorf("syscall.Fstat(%v,...) failed: %v", fd, err) } - return (stat.Mode & syscall.S_IFSOCK) == syscall.S_IFSOCK + return (stat.Mode & syscall.S_IFSOCK) == syscall.S_IFSOCK, nil } // Attach launches the goroutine that reads packets from the file descriptor and diff --git a/pkg/tcpip/link/fdbased/endpoint_test.go b/pkg/tcpip/link/fdbased/endpoint_test.go index ecc5b73f3..5a06c6387 100644 --- a/pkg/tcpip/link/fdbased/endpoint_test.go +++ b/pkg/tcpip/link/fdbased/endpoint_test.go @@ -68,7 +68,11 @@ func newContext(t *testing.T, opt *Options) *context { } opt.FD = fds[1] - ep := stack.FindLinkEndpoint(New(opt)).(*endpoint) + epID, err := New(opt) + if err != nil { + t.Fatalf("Failed to create FD endpoint: %v", err) + } + ep := stack.FindLinkEndpoint(epID).(*endpoint) c := &context{ t: t, diff --git a/pkg/tcpip/sample/tun_tcp_connect/main.go b/pkg/tcpip/sample/tun_tcp_connect/main.go index 327a79f48..cf8900c4d 100644 --- a/pkg/tcpip/sample/tun_tcp_connect/main.go +++ b/pkg/tcpip/sample/tun_tcp_connect/main.go @@ -137,7 +137,10 @@ func main() { log.Fatal(err) } - linkID := fdbased.New(&fdbased.Options{FD: fd, MTU: mtu}) + linkID, err := fdbased.New(&fdbased.Options{FD: fd, MTU: mtu}) + if err != nil { + log.Fatal(err) + } if err := s.CreateNIC(1, sniffer.New(linkID)); err != nil { log.Fatal(err) } diff --git a/pkg/tcpip/sample/tun_tcp_echo/main.go b/pkg/tcpip/sample/tun_tcp_echo/main.go index b23dc13e7..da6202f97 100644 --- a/pkg/tcpip/sample/tun_tcp_echo/main.go +++ b/pkg/tcpip/sample/tun_tcp_echo/main.go @@ -128,12 +128,15 @@ func main() { log.Fatal(err) } - linkID := fdbased.New(&fdbased.Options{ + linkID, err := fdbased.New(&fdbased.Options{ FD: fd, MTU: mtu, EthernetHeader: *tap, Address: tcpip.LinkAddress(maddr), }) + if err != nil { + log.Fatal(err) + } if err := s.CreateNIC(1, linkID); err != nil { log.Fatal(err) } diff --git a/runsc/boot/network.go b/runsc/boot/network.go index 3915a021f..ceb00a858 100644 --- a/runsc/boot/network.go +++ b/runsc/boot/network.go @@ -135,7 +135,7 @@ func (n *Network) CreateLinksAndRoutes(args *CreateLinksAndRoutesArgs, _ *struct } mac := tcpip.LinkAddress(generateRndMac()) - linkEP := fdbased.New(&fdbased.Options{ + linkEP, err := fdbased.New(&fdbased.Options{ FD: newFD, MTU: uint32(link.MTU), EthernetHeader: true, @@ -144,6 +144,9 @@ func (n *Network) CreateLinksAndRoutes(args *CreateLinksAndRoutesArgs, _ *struct GSOMaxSize: link.GSOMaxSize, RXChecksumOffload: true, }) + if err != nil { + return err + } log.Infof("Enabling interface %q with id %d on addresses %+v (%v)", link.Name, nicID, link.Addresses, mac) if err := n.createNICWithAddrs(nicID, link.Name, linkEP, link.Addresses, false /* loopback */); err != nil { |