use TCP MSS configuration

This commit is contained in:
Maxime Peim
2023-07-06 15:03:56 +00:00
committed by FUJITA Tomonori
parent f617588415
commit e7534de3d2
11 changed files with 132 additions and 7 deletions
+2
View File
@@ -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,
}
@@ -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,
}
+22 -3
View File
@@ -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()
@@ -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
@@ -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)
},
}
@@ -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.
@@ -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 {
+2
View File
@@ -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
@@ -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
+11 -1
View File
@@ -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{
@@ -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
View File
@@ -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
View File
@@ -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)
}
+24 -1
View File
@@ -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 {
@@ -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
+23 -1
View File
@@ -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{
@@ -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
View File
@@ -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")
}
+20 -1
View File
@@ -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 {
@@ -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{
@@ -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
View File
@@ -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))
}