mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-31 10:13:14 -04:00 
			
		
		
		
	create pkg/reuseport (#3455)
* create pkg/reuseport Move the core server listening functions to a new package so plugins can use them. Also make *all* servers use the functions here; as only the udp/tcp listeners where using SO_REUSEPORT (if available). This is the only actual change in this PR; in it's core it's just a move of 2 files. This can also be used to cleanup the dance we're doing now for re-acquiring the sockets in e.g. the metrics plugins and the ready plugin. Signed-off-by: Miek Gieben <miek@miek.nl> * Also push a small doc update Signed-off-by: Miek Gieben <miek@miek.nl>
This commit is contained in:
		| @@ -1,33 +0,0 @@ | |||||||
| // +build go1.11 |  | ||||||
| // +build aix darwin dragonfly freebsd linux netbsd openbsd |  | ||||||
|  |  | ||||||
| package dnsserver |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"context" |  | ||||||
| 	"net" |  | ||||||
| 	"syscall" |  | ||||||
|  |  | ||||||
| 	"github.com/coredns/coredns/plugin/pkg/log" |  | ||||||
|  |  | ||||||
| 	"golang.org/x/sys/unix" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func reuseportControl(network, address string, c syscall.RawConn) error { |  | ||||||
| 	c.Control(func(fd uintptr) { |  | ||||||
| 		if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil { |  | ||||||
| 			log.Warningf("Failed to set SO_REUSEPORT on socket: %s", err) |  | ||||||
| 		} |  | ||||||
| 	}) |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func listen(network, addr string) (net.Listener, error) { |  | ||||||
| 	lc := net.ListenConfig{Control: reuseportControl} |  | ||||||
| 	return lc.Listen(context.Background(), network, addr) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func listenPacket(network, addr string) (net.PacketConn, error) { |  | ||||||
| 	lc := net.ListenConfig{Control: reuseportControl} |  | ||||||
| 	return lc.ListenPacket(context.Background(), network, addr) |  | ||||||
| } |  | ||||||
| @@ -1,11 +0,0 @@ | |||||||
| // +build !go1.11 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd |  | ||||||
|  |  | ||||||
| package dnsserver |  | ||||||
|  |  | ||||||
| import "net" |  | ||||||
|  |  | ||||||
| func listen(network, addr string) (net.Listener, error) { return net.Listen(network, addr) } |  | ||||||
|  |  | ||||||
| func listenPacket(network, addr string) (net.PacketConn, error) { |  | ||||||
| 	return net.ListenPacket(network, addr) |  | ||||||
| } |  | ||||||
| @@ -15,6 +15,7 @@ import ( | |||||||
| 	"github.com/coredns/coredns/plugin/pkg/edns" | 	"github.com/coredns/coredns/plugin/pkg/edns" | ||||||
| 	"github.com/coredns/coredns/plugin/pkg/log" | 	"github.com/coredns/coredns/plugin/pkg/log" | ||||||
| 	"github.com/coredns/coredns/plugin/pkg/rcode" | 	"github.com/coredns/coredns/plugin/pkg/rcode" | ||||||
|  | 	"github.com/coredns/coredns/plugin/pkg/reuseport" | ||||||
| 	"github.com/coredns/coredns/plugin/pkg/trace" | 	"github.com/coredns/coredns/plugin/pkg/trace" | ||||||
| 	"github.com/coredns/coredns/plugin/pkg/transport" | 	"github.com/coredns/coredns/plugin/pkg/transport" | ||||||
| 	"github.com/coredns/coredns/request" | 	"github.com/coredns/coredns/request" | ||||||
| @@ -126,7 +127,7 @@ func (s *Server) ServePacket(p net.PacketConn) error { | |||||||
|  |  | ||||||
| // Listen implements caddy.TCPServer interface. | // Listen implements caddy.TCPServer interface. | ||||||
| func (s *Server) Listen() (net.Listener, error) { | func (s *Server) Listen() (net.Listener, error) { | ||||||
| 	l, err := listen("tcp", s.Addr[len(transport.DNS+"://"):]) | 	l, err := reuseport.Listen("tcp", s.Addr[len(transport.DNS+"://"):]) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| @@ -140,7 +141,7 @@ func (s *Server) WrapListener(ln net.Listener) net.Listener { | |||||||
|  |  | ||||||
| // ListenPacket implements caddy.UDPServer interface. | // ListenPacket implements caddy.UDPServer interface. | ||||||
| func (s *Server) ListenPacket() (net.PacketConn, error) { | func (s *Server) ListenPacket() (net.PacketConn, error) { | ||||||
| 	p, err := listenPacket("udp", s.Addr[len(transport.DNS+"://"):]) | 	p, err := reuseport.ListenPacket("udp", s.Addr[len(transport.DNS+"://"):]) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ import ( | |||||||
| 	"net" | 	"net" | ||||||
|  |  | ||||||
| 	"github.com/coredns/coredns/pb" | 	"github.com/coredns/coredns/pb" | ||||||
|  | 	"github.com/coredns/coredns/plugin/pkg/reuseport" | ||||||
| 	"github.com/coredns/coredns/plugin/pkg/transport" | 	"github.com/coredns/coredns/plugin/pkg/transport" | ||||||
|  |  | ||||||
| 	"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc" | 	"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc" | ||||||
| @@ -72,7 +73,7 @@ func (s *ServergRPC) ServePacket(p net.PacketConn) error { return nil } | |||||||
| // Listen implements caddy.TCPServer interface. | // Listen implements caddy.TCPServer interface. | ||||||
| func (s *ServergRPC) Listen() (net.Listener, error) { | func (s *ServergRPC) Listen() (net.Listener, error) { | ||||||
|  |  | ||||||
| 	l, err := net.Listen("tcp", s.Addr[len(transport.GRPC+"://"):]) | 	l, err := reuseport.Listen("tcp", s.Addr[len(transport.GRPC+"://"):]) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ import ( | |||||||
| 	"github.com/coredns/coredns/plugin/pkg/dnsutil" | 	"github.com/coredns/coredns/plugin/pkg/dnsutil" | ||||||
| 	"github.com/coredns/coredns/plugin/pkg/doh" | 	"github.com/coredns/coredns/plugin/pkg/doh" | ||||||
| 	"github.com/coredns/coredns/plugin/pkg/response" | 	"github.com/coredns/coredns/plugin/pkg/response" | ||||||
|  | 	"github.com/coredns/coredns/plugin/pkg/reuseport" | ||||||
| 	"github.com/coredns/coredns/plugin/pkg/transport" | 	"github.com/coredns/coredns/plugin/pkg/transport" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -61,7 +62,7 @@ func (s *ServerHTTPS) ServePacket(p net.PacketConn) error { return nil } | |||||||
| // Listen implements caddy.TCPServer interface. | // Listen implements caddy.TCPServer interface. | ||||||
| func (s *ServerHTTPS) Listen() (net.Listener, error) { | func (s *ServerHTTPS) Listen() (net.Listener, error) { | ||||||
|  |  | ||||||
| 	l, err := net.Listen("tcp", s.Addr[len(transport.HTTPS+"://"):]) | 	l, err := reuseport.Listen("tcp", s.Addr[len(transport.HTTPS+"://"):]) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net" | 	"net" | ||||||
|  |  | ||||||
|  | 	"github.com/coredns/coredns/plugin/pkg/reuseport" | ||||||
| 	"github.com/coredns/coredns/plugin/pkg/transport" | 	"github.com/coredns/coredns/plugin/pkg/transport" | ||||||
|  |  | ||||||
| 	"github.com/miekg/dns" | 	"github.com/miekg/dns" | ||||||
| @@ -57,7 +58,7 @@ func (s *ServerTLS) ServePacket(p net.PacketConn) error { return nil } | |||||||
|  |  | ||||||
| // Listen implements caddy.TCPServer interface. | // Listen implements caddy.TCPServer interface. | ||||||
| func (s *ServerTLS) Listen() (net.Listener, error) { | func (s *ServerTLS) Listen() (net.Listener, error) { | ||||||
| 	l, err := net.Listen("tcp", s.Addr[len(transport.TLS+"://"):]) | 	l, err := reuseport.Listen("tcp", s.Addr[len(transport.TLS+"://"):]) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -64,6 +64,11 @@ a *Metrics* section detailing the metrics. | |||||||
| If the plugin supports signalling readiness it should have a *Ready* section detailing how it | If the plugin supports signalling readiness it should have a *Ready* section detailing how it | ||||||
| works, and implement the `ready.Readiness` interface. | works, and implement the `ready.Readiness` interface. | ||||||
|  |  | ||||||
|  | ## Opening Sockets | ||||||
|  |  | ||||||
|  | See the plugin/pkg/reuseport for `Listen` and `ListenPacket` functions. Using these functions makes | ||||||
|  | you plugin handle reload events better. | ||||||
|  |  | ||||||
| ## Documentation | ## Documentation | ||||||
|  |  | ||||||
| Each plugin should have a README.md explaining what the plugin does and how it is configured. The | Each plugin should have a README.md explaining what the plugin does and how it is configured. The | ||||||
|   | |||||||
							
								
								
									
										37
									
								
								plugin/pkg/reuseport/listen_go111.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								plugin/pkg/reuseport/listen_go111.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | // +build go1.11 | ||||||
|  | // +build aix darwin dragonfly freebsd linux netbsd openbsd | ||||||
|  |  | ||||||
|  | package reuseport | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"net" | ||||||
|  | 	"syscall" | ||||||
|  |  | ||||||
|  | 	"github.com/coredns/coredns/plugin/pkg/log" | ||||||
|  |  | ||||||
|  | 	"golang.org/x/sys/unix" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func control(network, address string, c syscall.RawConn) error { | ||||||
|  | 	c.Control(func(fd uintptr) { | ||||||
|  | 		if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil { | ||||||
|  | 			log.Warningf("Failed to set SO_REUSEPORT on socket: %s", err) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Listen announces on the local network address. See net.Listen for more information. | ||||||
|  | // If SO_REUSEPORT is available it will be set on the socket. | ||||||
|  | func Listen(network, addr string) (net.Listener, error) { | ||||||
|  | 	lc := net.ListenConfig{Control: control} | ||||||
|  | 	return lc.Listen(context.Background(), network, addr) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ListenPacket announces on the local network address. See net.ListenPacket for more information. | ||||||
|  | // If SO_REUSEPORT is available it will be set on the socket. | ||||||
|  | func ListenPacket(network, addr string) (net.PacketConn, error) { | ||||||
|  | 	lc := net.ListenConfig{Control: control} | ||||||
|  | 	return lc.ListenPacket(context.Background(), network, addr) | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								plugin/pkg/reuseport/listen_go_not111.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								plugin/pkg/reuseport/listen_go_not111.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | // +build !go1.11 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd | ||||||
|  |  | ||||||
|  | package reuseport | ||||||
|  |  | ||||||
|  | import "net" | ||||||
|  |  | ||||||
|  | // Listen is a wrapper around net.Listen. | ||||||
|  | func Listen(network, addr string) (net.Listener, error) { return net.Listen(network, addr) } | ||||||
|  |  | ||||||
|  | // ListenPacket is a wrapper around net.ListenPacket. | ||||||
|  | func ListenPacket(network, addr string) (net.PacketConn, error) { | ||||||
|  | 	return net.ListenPacket(network, addr) | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user