summaryrefslogtreecommitdiffhomepage
path: root/pkg/server
diff options
context:
space:
mode:
authorHitoshi Irino <irino@sfc.wide.ad.jp>2019-06-24 00:39:22 +0900
committerFUJITA Tomonori <fujita.tomonori@gmail.com>2019-07-02 11:40:22 +0900
commit2f5a4d59cb8d494bcf1a64d45d84bcd8fd4a7f06 (patch)
tree130afc174fe85d32abe3ad4994aecec3461ffcc4 /pkg/server
parent9f936065a907639661eca3924f0a8f09d94abbfe (diff)
BGP connection on a speecified interface (including which is associated VRF) using syscall SO_BINDTODEVICE
Diffstat (limited to 'pkg/server')
-rw-r--r--pkg/server/fsm.go6
-rw-r--r--pkg/server/grpc_server.go1
-rw-r--r--pkg/server/server.go4
-rw-r--r--pkg/server/sockopt.go2
-rw-r--r--pkg/server/sockopt_linux.go12
-rw-r--r--pkg/server/sockopt_openbsd.go2
6 files changed, 20 insertions, 7 deletions
diff --git a/pkg/server/fsm.go b/pkg/server/fsm.go
index ae102812..b06ddd5d 100644
--- a/pkg/server/fsm.go
+++ b/pkg/server/fsm.go
@@ -491,7 +491,7 @@ func (h *fsmHandler) connectLoop(ctx context.Context, wg *sync.WaitGroup) {
defer wg.Done()
fsm := h.fsm
- retry, addr, port, password, ttl, ttlMin, localAddress := func() (int, string, int, string, uint8, uint8, string) {
+ retry, addr, port, password, ttl, ttlMin, localAddress, bindInterface := func() (int, string, int, string, uint8, uint8, string, string) {
fsm.lock.RLock()
defer fsm.lock.RUnlock()
@@ -518,7 +518,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
+ return tick, addr, port, password, ttl, ttlMin, fsm.pConf.Transport.Config.LocalAddress, fsm.pConf.Transport.Config.BindInterface
}()
tick := minConnectRetryInterval
@@ -553,7 +553,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(network, address, c, ttl, ttlMin, password)
+ return dialerControl(network, address, c, ttl, ttlMin, password, bindInterface)
},
}
diff --git a/pkg/server/grpc_server.go b/pkg/server/grpc_server.go
index 0d6f7d9c..2540e685 100644
--- a/pkg/server/grpc_server.go
+++ b/pkg/server/grpc_server.go
@@ -655,6 +655,7 @@ func newNeighborFromAPIStruct(a *api.Peer) (*config.Neighbor, 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.BindInterface = a.Transport.BindInterface
}
if a.EbgpMultihop != nil {
pconf.EbgpMultihop.Config.Enabled = a.EbgpMultihop.Enabled
diff --git a/pkg/server/server.go b/pkg/server/server.go
index 82efeb6a..d77512f5 100644
--- a/pkg/server/server.go
+++ b/pkg/server/server.go
@@ -250,6 +250,7 @@ func (s *BgpServer) passConnToPeer(conn *net.TCPConn) {
}
peer.fsm.lock.RLock()
localAddr := peer.fsm.pConf.Transport.Config.LocalAddress
+ bindInterface := peer.fsm.pConf.Transport.Config.BindInterface
peer.fsm.lock.RUnlock()
localAddrValid := func(laddr string) bool {
if laddr == "0.0.0.0" || laddr == "::" {
@@ -262,12 +263,13 @@ func (s *BgpServer) passConnToPeer(conn *net.TCPConn) {
}
host, _, _ := net.SplitHostPort(l.String())
- if host != laddr {
+ if host != laddr && bindInterface == "" {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": remoteAddr,
"Configured addr": laddr,
"Addr": host,
+ "BindInterface": bindInterface,
}).Info("Mismatched local address")
return false
}
diff --git a/pkg/server/sockopt.go b/pkg/server/sockopt.go
index e2b1c086..0aab0ba9 100644
--- a/pkg/server/sockopt.go
+++ b/pkg/server/sockopt.go
@@ -39,7 +39,7 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
return setTcpMinTTLSockopt(conn, ttl)
}
-func dialerControl(network, address string, c syscall.RawConn, ttl, ttlMin uint8, password string) error {
+func dialerControl(network, address string, c syscall.RawConn, ttl, ttlMin uint8, password string, bindInterface string) error {
if password != "" {
log.WithFields(log.Fields{
"Topic": "Peer",
diff --git a/pkg/server/sockopt_linux.go b/pkg/server/sockopt_linux.go
index 31df8397..203087ab 100644
--- a/pkg/server/sockopt_linux.go
+++ b/pkg/server/sockopt_linux.go
@@ -103,7 +103,7 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
return setsockOptInt(sc, level, name, ttl)
}
-func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8, password string) error {
+func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8, password string, bindInterface string) error {
family := syscall.AF_INET
raddr, _ := net.ResolveTCPAddr("tcp", address)
if raddr.IP.To4() == nil {
@@ -161,5 +161,15 @@ func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8
return sockerr
}
}
+ if bindInterface != "" {
+ if err := c.Control(func(fd uintptr) {
+ sockerr = os.NewSyscallError("setsockopt", syscall.SetsockoptString(int(fd), syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, bindInterface))
+ }); err != nil {
+ return err
+ }
+ if sockerr != nil {
+ return sockerr
+ }
+ }
return nil
}
diff --git a/pkg/server/sockopt_openbsd.go b/pkg/server/sockopt_openbsd.go
index e65aabe0..3d6825e2 100644
--- a/pkg/server/sockopt_openbsd.go
+++ b/pkg/server/sockopt_openbsd.go
@@ -403,7 +403,7 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
return setsockOptInt(sc, level, name, ttl)
}
-func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8, password string) error {
+func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8, password string, bindInterface string) error {
if password != "" {
log.WithFields(log.Fields{
"Topic": "Peer",