From d4f72cd350793b2af068189482f010866210894c Mon Sep 17 00:00:00 2001 From: netixx Date: Mon, 15 Apr 2024 16:05:15 +0200 Subject: [PATCH 1/2] Enable SO_REUSEPORT Signed-off-by: netixx --- net/tcp/listen.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/tcp/listen.go b/net/tcp/listen.go index 45efc19c..2e281a84 100644 --- a/net/tcp/listen.go +++ b/net/tcp/listen.go @@ -60,6 +60,12 @@ func (lf *ListenerFactory) NewListener(v *vrf.VRF, laddr *net.TCPAddr, ttl uint8 return nil, fmt.Errorf("unable to get SO_REUSEADDR %w", err) } + err = unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEPORT, 1) + if err != nil { + unix.Close(fd) + return nil, fmt.Errorf("unable to get SO_REUSEPORT %w", err) + } + if ttl != 0 { err = unix.SetsockoptInt(fd, SOL_IP, unix.IP_TTL, int(ttl)) if err != nil { From e3dea281d94fa7e5401d12a0d797a99fe4877945 Mon Sep 17 00:00:00 2001 From: netixx Date: Thu, 18 Apr 2024 14:10:21 +0200 Subject: [PATCH 2/2] Make reuseport optional --- net/tcp/listen.go | 17 +++++++++-------- net/tcp/listener_manager.go | 6 ++++-- protocols/bgp/server/server.go | 3 ++- tests/bgp_integration_test.go | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/net/tcp/listen.go b/net/tcp/listen.go index 2e281a84..45a217e3 100644 --- a/net/tcp/listen.go +++ b/net/tcp/listen.go @@ -9,7 +9,7 @@ import ( ) type ListenerFactoryI interface { - NewListener(v *vrf.VRF, laddr *net.TCPAddr, ttl uint8) (ListenerI, error) + NewListener(v *vrf.VRF, laddr *net.TCPAddr, ttl uint8, reuseport bool) (ListenerI, error) } type ListenerFactory struct{} @@ -30,7 +30,7 @@ type Listener struct { } // NewListener starts a TCPListener -func (lf *ListenerFactory) NewListener(v *vrf.VRF, laddr *net.TCPAddr, ttl uint8) (ListenerI, error) { +func (lf *ListenerFactory) NewListener(v *vrf.VRF, laddr *net.TCPAddr, ttl uint8, reuseport bool) (ListenerI, error) { l := &Listener{ laddr: laddr, } @@ -57,13 +57,14 @@ func (lf *ListenerFactory) NewListener(v *vrf.VRF, laddr *net.TCPAddr, ttl uint8 err = unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1) if err != nil { unix.Close(fd) - return nil, fmt.Errorf("unable to get SO_REUSEADDR %w", err) + return nil, fmt.Errorf("unable to set SO_REUSEADDR %w", err) } - err = unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEPORT, 1) - if err != nil { - unix.Close(fd) - return nil, fmt.Errorf("unable to get SO_REUSEPORT %w", err) + if reuseport { + if err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil { + unix.Close(fd) + return nil, fmt.Errorf("unable to set SO_REUSEPORT %w", err) + } } if ttl != 0 { @@ -153,7 +154,7 @@ type MockListener struct { connCh chan *MockConn } -func (lf *MockListenerFactory) NewListener(v *vrf.VRF, laddr *net.TCPAddr, ttl uint8) (ListenerI, error) { +func (lf *MockListenerFactory) NewListener(v *vrf.VRF, laddr *net.TCPAddr, ttl uint8, reusePort bool) (ListenerI, error) { return &MockListener{ localAddr: laddr.IP, localPort: uint16(laddr.Port), diff --git a/net/tcp/listener_manager.go b/net/tcp/listener_manager.go index 102d0423..c5a05842 100644 --- a/net/tcp/listener_manager.go +++ b/net/tcp/listener_manager.go @@ -27,14 +27,16 @@ type ListenerManager struct { listenersByVRFmu sync.RWMutex acceptCh chan ConnWithVRF listenerFactory ListenerFactoryI + reusePort bool } -func NewListenerManager(listenAddrsByVRF map[string][]string) *ListenerManager { +func NewListenerManager(listenAddrsByVRF map[string][]string, reusePort bool) *ListenerManager { return &ListenerManager{ listenAddrsByVRF: listenAddrsByVRF, listenersByVRF: make(map[string][]ListenerI), listenerFactory: NewListenerFactory(), acceptCh: make(chan ConnWithVRF), + reusePort: reusePort, } } @@ -93,7 +95,7 @@ func (lm *ListenerManager) _addListener(vrf *vrf.VRF, addr string, ch chan ConnW } log.Infof("Listener manager: Starting TCP listener on %s in VRF %s", addr, vrf.Name()) - l, err := lm.listenerFactory.NewListener(vrf, tcpaddr, 255) + l, err := lm.listenerFactory.NewListener(vrf, tcpaddr, 255, lm.reusePort) if err != nil { return err } diff --git a/protocols/bgp/server/server.go b/protocols/bgp/server/server.go index 1bba09ff..fc065e7c 100644 --- a/protocols/bgp/server/server.go +++ b/protocols/bgp/server/server.go @@ -29,6 +29,7 @@ type BGPServerConfig struct { // Optional attributes DefaultLocalPreference *uint32 + ReusePort bool } type bgpServer struct { @@ -68,7 +69,7 @@ func newBGPServer(config BGPServerConfig) *bgpServer { server := &bgpServer{ config: config, peers: newPeerManager(), - listenerManager: tcp.NewListenerManager(config.ListenAddrsByVRF), + listenerManager: tcp.NewListenerManager(config.ListenAddrsByVRF, config.ReusePort), } server.metrics = &metricsService{server} diff --git a/tests/bgp_integration_test.go b/tests/bgp_integration_test.go index 6356ddcf..27e7a09d 100644 --- a/tests/bgp_integration_test.go +++ b/tests/bgp_integration_test.go @@ -28,7 +28,7 @@ func TestBGP(t *testing.T) { "main": { "0.0.0.0:179", }, - }) + }, false) lm.SetListenerFactory(tcp.NewMockListenerFactory()) b.SetListenerManager(lm)