Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use TCP MSS configuration #2671

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions internal/pkg/config/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,7 @@ func NewPeerFromConfigStruct(pconf *Neighbor) *api.Peer {
LocalAddress: localAddress,
PassiveMode: pconf.Transport.Config.PassiveMode,
BindInterface: pconf.Transport.Config.BindInterface,
TcpMss: uint32(pconf.Transport.Config.TcpMss),
},
AfiSafis: afiSafis,
}
Expand Down Expand Up @@ -640,6 +641,7 @@ func NewPeerGroupFromConfigStruct(pconf *PeerGroup) *api.PeerGroup {
RemotePort: uint32(pconf.Transport.Config.RemotePort),
LocalAddress: pconf.Transport.Config.LocalAddress,
PassiveMode: pconf.Transport.Config.PassiveMode,
TcpMss: uint32(pconf.Transport.Config.TcpMss),
},
AfiSafis: afiSafis,
}
Expand Down
25 changes: 22 additions & 3 deletions pkg/server/fsm.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ func (h *fsmHandler) connectLoop(ctx context.Context, wg *sync.WaitGroup) {
defer wg.Done()
fsm := h.fsm

retry, addr, port, password, ttl, ttlMin, localAddress, localPort, bindInterface := func() (int, string, int, string, uint8, uint8, string, int, string) {
retry, addr, port, password, ttl, ttlMin, mss, localAddress, localPort, bindInterface := func() (int, string, int, string, uint8, uint8, uint16, string, int, string) {
fsm.lock.RLock()
defer fsm.lock.RUnlock()

Expand All @@ -521,7 +521,7 @@ func (h *fsmHandler) connectLoop(ctx context.Context, wg *sync.WaitGroup) {
ttl = fsm.pConf.EbgpMultihop.Config.MultihopTtl
}
}
return tick, addr, port, password, ttl, ttlMin, fsm.pConf.Transport.Config.LocalAddress, int(fsm.pConf.Transport.Config.LocalPort), fsm.pConf.Transport.Config.BindInterface
return tick, addr, port, password, ttl, ttlMin, fsm.pConf.Transport.Config.TcpMss, fsm.pConf.Transport.Config.LocalAddress, int(fsm.pConf.Transport.Config.LocalPort), fsm.pConf.Transport.Config.BindInterface
}()

tick := minConnectRetryInterval
Expand Down Expand Up @@ -556,7 +556,7 @@ func (h *fsmHandler) connectLoop(ctx context.Context, wg *sync.WaitGroup) {
LocalAddr: laddr,
Timeout: time.Duration(tick-1) * time.Second,
Control: func(network, address string, c syscall.RawConn) error {
return dialerControl(fsm.logger, network, address, c, ttl, ttlMin, password, bindInterface)
return dialerControl(fsm.logger, network, address, c, ttl, ttlMin, mss, password, bindInterface)
},
}

Expand Down Expand Up @@ -634,6 +634,14 @@ func (h *fsmHandler) active(ctx context.Context) (bgp.FSMState, *fsmStateReason)
"State": fsm.state.String(),
"Error": err})
}
if err := setPeerConnMSS(fsm); err != nil {
fsm.logger.Warn("cannot set MSS for peer",
log.Fields{
"Topic": "Peer",
"Key": fsm.pConf.Config.NeighborAddress,
"State": fsm.state.String(),
"Error": err})
}
fsm.lock.RUnlock()
// we don't implement delayed open timer so move to opensent right
// away.
Expand Down Expand Up @@ -705,6 +713,17 @@ func setPeerConnTTL(fsm *fsm) error {
return nil
}

func setPeerConnMSS(fsm *fsm) error {
mss := fsm.pConf.Transport.Config.TcpMss
if mss == 0 {
return nil
}
if err := setTCPMSSSockopt(fsm.conn.(*net.TCPConn), mss); err != nil {
return fmt.Errorf("failed to set MSS %d: %w", mss, err)
}
return nil
}

func capAddPathFromConfig(pConf *config.Neighbor) bgp.ParameterCapabilityInterface {
tuples := make([]*bgp.CapAddPathTuple, 0, len(pConf.AfiSafis))
for _, af := range pConf.AfiSafis {
Expand Down
2 changes: 2 additions & 0 deletions pkg/server/grpc_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,7 @@ func newNeighborFromAPIStruct(a *api.Peer) (*config.Neighbor, error) {
pconf.Transport.Config.RemotePort = uint16(a.Transport.RemotePort)
pconf.Transport.Config.LocalPort = uint16(a.Transport.LocalPort)
pconf.Transport.Config.BindInterface = a.Transport.BindInterface
pconf.Transport.Config.TcpMss = uint16(a.Transport.TcpMss)
}
if a.EbgpMultihop != nil {
pconf.EbgpMultihop.Config.Enabled = a.EbgpMultihop.Enabled
Expand Down Expand Up @@ -836,6 +837,7 @@ func newPeerGroupFromAPIStruct(a *api.PeerGroup) (*config.PeerGroup, error) {
pconf.Transport.Config.LocalAddress = a.Transport.LocalAddress
pconf.Transport.Config.PassiveMode = a.Transport.PassiveMode
pconf.Transport.Config.RemotePort = uint16(a.Transport.RemotePort)
pconf.Transport.Config.TcpMss = uint16(a.Transport.TcpMss)
}
if a.EbgpMultihop != nil {
pconf.EbgpMultihop.Config.Enabled = a.EbgpMultihop.Enabled
Expand Down
12 changes: 11 additions & 1 deletion pkg/server/sockopt.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ func setBindToDevSockopt(sc syscall.RawConn, device string) error {
return fmt.Errorf("binding connection to a device is not supported")
}

func dialerControl(logger log.Logger, network, address string, c syscall.RawConn, ttl, minTtl uint8, password string, bindInterface string) error {
func setTCPMSSSockopt(conn *net.TCPConn, mss uint16) error {
return setTcpMSSSockopt(conn, mss)
}

func dialerControl(logger log.Logger, network, address string, c syscall.RawConn, ttl, minTtl uint8, mss uint16, password string, bindInterface string) error {
if password != "" {
logger.Warn("setting md5 for active connection is not supported",
log.Fields{
Expand All @@ -60,5 +64,11 @@ func dialerControl(logger log.Logger, network, address string, c syscall.RawConn
"Topic": "Peer",
"Key": address})
}
if mss != 0 {
logger.Warn("setting MSS for active connection is not supported",
log.Fields{
"Topic": "Peer",
"Key": address})
}
return nil
}
9 changes: 9 additions & 0 deletions pkg/server/sockopt_bsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,12 @@ func setTcpMinTTLSockopt(conn *net.TCPConn, ttl int) error {
}
return setsockOptInt(sc, level, name, ttl)
}

func setTcpMSSSockopt(conn *net.TCPConn, mss uint16) error {
family := extractFamilyFromTCPConn(conn)
sc, err := conn.SyscallConn()
if err != nil {
return err
}
return setsockoptTcpMss(sc, family, mss)
}
9 changes: 9 additions & 0 deletions pkg/server/sockopt_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,12 @@ func setTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
func setTcpMinTTLSockopt(conn *net.TCPConn, ttl int) error {
return fmt.Errorf("setting min ttl is not supported")
}

func setTcpMSSSockopt(conn *net.TCPConn, mss uint16) error {
family := extractFamilyFromTCPConn(conn)
sc, err := conn.SyscallConn()
if err != nil {
return err
}
return setsockoptTcpMss(sc, family, mss)
}
25 changes: 24 additions & 1 deletion pkg/server/sockopt_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,16 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
return setsockOptInt(sc, level, name, ttl)
}

func dialerControl(logger log.Logger, network, address string, c syscall.RawConn, ttl, minTtl uint8, password string, bindInterface string) error {
func setTCPMSSSockopt(conn *net.TCPConn, mss uint16) error {
family := extractFamilyFromTCPConn(conn)
sc, err := conn.SyscallConn()
if err != nil {
return err
}
return setsockoptTcpMss(sc, family, mss)
}

func dialerControl(logger log.Logger, network, address string, c syscall.RawConn, ttl, minTtl uint8, mss uint16, password string, bindInterface string) error {
family := syscall.AF_INET
raddr, _ := net.ResolveTCPAddr("tcp", address)
if raddr.IP.To4() == nil {
Expand Down Expand Up @@ -146,6 +155,20 @@ func dialerControl(logger log.Logger, network, address string, c syscall.RawConn
return sockerr
}
}

if mss != 0 {
if err := c.Control(func(fd uintptr) {
level := syscall.IPPROTO_TCP
name := syscall.TCP_MAXSEG
sockerr = os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fd), level, name, int(mss)))
}); err != nil {
return err
}
if sockerr != nil {
return sockerr
}
}

if bindInterface != "" {
if err := setBindToDevSockopt(c, bindInterface); err != nil {
return err
Expand Down
24 changes: 23 additions & 1 deletion pkg/server/sockopt_openbsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,11 +384,20 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
return setsockOptInt(sc, level, name, ttl)
}

func setTCPMSSSockopt(conn *net.TCPConn, mss uint16) error {
family := extractFamilyFromTCPConn(conn)
sc, err := conn.SyscallConn()
if err != nil {
return err
}
return setsockoptTcpMss(sc, family, mss)
}

func setBindToDevSockopt(sc syscall.RawConn, device string) error {
return fmt.Errorf("binding connection to a device is not supported")
}

func dialerControl(logger log.Logger, network, address string, c syscall.RawConn, ttl, minTtl uint8, password string, bindInterface string) error {
func dialerControl(logger log.Logger, network, address string, c syscall.RawConn, ttl, minTtl uint8, mss uint16, password string, bindInterface string) error {
if password != "" {
logger.Warn("setting md5 for active connection is not supported",
log.Fields{
Expand All @@ -407,5 +416,18 @@ func dialerControl(logger log.Logger, network, address string, c syscall.RawConn
"Topic": "Peer",
"Key": address})
}
var sockerr error
if mss != 0 {
if err := c.Control(func(fd uintptr) {
level := syscall.IPPROTO_TCP
name := syscall.TCP_MAXSEG
sockerr = os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fd), level, name, int(mss)))
}); err != nil {
return err
}
if sockerr != nil {
return sockerr
}
}
return nil
}
4 changes: 4 additions & 0 deletions pkg/server/sockopt_stub.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ func setTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
func setTcpMinTTLSockopt(conn *net.TCPConn, ttl int) error {
return fmt.Errorf("setting min ttl is not supported")
}

func setTcpMSSSockopt(conn *net.TCPConn, mss uint16) error {
return fmt.Errorf("setting min ttl is not supported")
}
21 changes: 20 additions & 1 deletion pkg/server/sockopt_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const (
tcpMD5SIG = 14 // TCP MD5 Signature (RFC2385)
ipv6MinHopCount = 73 // Generalized TTL Security Mechanism (RFC5082)
IP_MINTTL = 0x15 // pulled from https://golang.org/pkg/syscall/?GOOS=linux#IP_MINTTL
TCP_MAXSEG = 0x2 // pulled from https://pkg.go.dev/syscall?GOOS=linux#TCP_MAXSEG
)

func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error {
Expand Down Expand Up @@ -63,7 +64,19 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
return setsockOptInt(sc, level, name, ttl)
}

func dialerControl(logger log.Logger, network, address string, c syscall.RawConn, ttl, ttlMin uint8, password string, bindInterface string) error {
func setTCPMSSSockopt(conn *net.TCPConn, mss uint16) error {
// TCP_MAXSEG syscall option exists only from Windows 10
// https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-getsockopt
sc, err := conn.SyscallConn()
if err != nil {
return err
}
level := syscall.IPPROTO_TCP
name := TCP_MAXSEG
return setsockOptInt(sc, level, name, int(mss))
}

func dialerControl(logger log.Logger, network, address string, c syscall.RawConn, ttl, ttlMin uint8, mss uint16, password string, bindInterface string) error {
if password != "" {
logger.Warn("setting md5 for active connection is not supported",
log.Fields{
Expand All @@ -82,5 +95,11 @@ func dialerControl(logger log.Logger, network, address string, c syscall.RawConn
"Topic": "Peer",
"Key": address})
}
if mss != 0 {
logger.Warn("setting MSS for active connection is not supported",
log.Fields{
"Topic": "Peer",
"Key": address})
}
return nil
}
6 changes: 6 additions & 0 deletions pkg/server/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,9 @@ func setsockoptIpTtl(sc syscall.RawConn, family int, value int) error {
}
return setsockOptInt(sc, level, name, value)
}

func setsockoptTcpMss(sc syscall.RawConn, family int, value uint16) error {
level := syscall.IPPROTO_TCP
name := syscall.TCP_MAXSEG
return setsockOptInt(sc, level, name, int(value))
}