diff options
-rw-r--r-- | config/bgp_configs.go | 2 | ||||
-rw-r--r-- | docs/sources/configuration.md | 8 | ||||
-rw-r--r-- | server/server.go | 83 | ||||
-rw-r--r-- | tools/pyang_plugins/gobgp.yang | 3 |
4 files changed, 61 insertions, 35 deletions
diff --git a/config/bgp_configs.go b/config/bgp_configs.go index c6a3e53e..4191bbd2 100644 --- a/config/bgp_configs.go +++ b/config/bgp_configs.go @@ -1448,6 +1448,8 @@ type Neighbor struct { type ListenConfig struct { // original -> gobgp:port Port int32 `mapstructure:"port"` + // original -> gobgp:local-address + LocalAddressList []string `mapstructure:"local-address-list"` } //struct for container gobgp:mpls-label-range diff --git a/docs/sources/configuration.md b/docs/sources/configuration.md index abe04d32..4866d950 100644 --- a/docs/sources/configuration.md +++ b/docs/sources/configuration.md @@ -22,6 +22,14 @@ [global.mpls-label-range] min-label = 1000 max-label = 2000 + [global.listen-config] + # listen port (by default 179) + port = 1790 + # to disable listening + # port = -1 + + # listen address list (by default "0.0.0.0" and "::") + local-address-list = ["192.168.10.1", "2001:db8::1"] [[rpki-servers]] [rpki-servers.config] diff --git a/server/server.go b/server/server.go index 25ccb9e5..a6d663a7 100644 --- a/server/server.go +++ b/server/server.go @@ -102,7 +102,7 @@ type BgpServer struct { policy *table.RoutingPolicy broadcastReqs []*GrpcRequest broadcastMsgs []broadcastMsg - listenerMap map[string]*net.TCPListener + listeners []*net.TCPListener neighborMap map[string]*Peer globalRib *table.TableManager zclient *zebra.Client @@ -128,13 +128,21 @@ func NewBgpServer() *BgpServer { } // avoid mapped IPv6 address -func listenAndAccept(proto string, port uint32, ch chan *net.TCPConn) (*net.TCPListener, error) { - service := ":" + strconv.Itoa(int(port)) - addr, _ := net.ResolveTCPAddr(proto, service) +func listenAndAccept(address string, port uint32, ch chan *net.TCPConn) (*net.TCPListener, error) { + proto := "tcp4" + if ip := net.ParseIP(address); ip == nil { + return nil, fmt.Errorf("can't listen on %s", address) + } else if strings.Contains(address, ":") { + address = fmt.Sprintf("[%s]", address) + proto = "tcp6" + } + addr, err := net.ResolveTCPAddr(proto, fmt.Sprintf("%s:%d", address, port)) + if err != nil { + return nil, err + } l, err := net.ListenTCP(proto, addr) if err != nil { - log.Info(err) return nil, err } go func() { @@ -163,6 +171,18 @@ func (server *BgpServer) notify2watchers(typ watcherEventType, ev watcherEvent) return nil } +func (server *BgpServer) Listeners(addr string) []*net.TCPListener { + list := make([]*net.TCPListener, 0, len(server.listeners)) + rhs := net.ParseIP(addr).To4() != nil + for _, l := range server.listeners { + lhs := net.ParseIP(l.Addr().String()).To4() != nil + if lhs == rhs { + list = append(list, l) + } + } + return list +} + func (server *BgpServer) Serve() { var g config.Global for { @@ -256,27 +276,21 @@ func (server *BgpServer) Serve() { rfs, _ := config.AfiSafis(g.AfiSafis).ToRfList() server.globalRib = table.NewTableManager(rfs, g.MplsLabelRange.MinLabel, g.MplsLabelRange.MaxLabel) - server.listenerMap = make(map[string]*net.TCPListener) + server.listeners = make([]*net.TCPListener, 0, 2) acceptCh := make(chan *net.TCPConn, 4096) if g.ListenConfig.Port > 0 { - l4, err1 := listenAndAccept("tcp4", uint32(g.ListenConfig.Port), acceptCh) - server.listenerMap["tcp4"] = l4 - l6, err2 := listenAndAccept("tcp6", uint32(g.ListenConfig.Port), acceptCh) - server.listenerMap["tcp6"] = l6 - if err1 != nil && err2 != nil { - log.Fatal("can't listen either v4 and v6") - os.Exit(1) + list := []string{"0.0.0.0", "::"} + if len(g.ListenConfig.LocalAddressList) > 0 { + list = g.ListenConfig.LocalAddressList } - } - - listener := func(addr string) *net.TCPListener { - var l *net.TCPListener - if net.ParseIP(addr).To4() != nil { - l = server.listenerMap["tcp4"] - } else { - l = server.listenerMap["tcp6"] + for _, addr := range list { + l, err := listenAndAccept(addr, uint32(g.ListenConfig.Port), acceptCh) + if err != nil { + log.Fatal(err) + os.Exit(1) + } + server.listeners = append(server.listeners, l) } - return l } server.fsmincomingCh = make(chan *FsmMsg, 4096) @@ -393,7 +407,9 @@ func (server *BgpServer) Serve() { continue } if g.ListenConfig.Port > 0 { - SetTcpMD5SigSockopts(listener(addr), addr, config.Config.AuthPassword) + for _, l := range server.Listeners(addr) { + SetTcpMD5SigSockopts(l, addr, config.Config.AuthPassword) + } } peer := NewPeer(g, config, server.globalRib, server.policy) server.setPolicyByConfig(peer.ID(), config.ApplyPolicy) @@ -416,7 +432,9 @@ func (server *BgpServer) Serve() { server.broadcastPeerState(peer, bgp.BGP_FSM_IDLE) case config := <-server.deletedPeerCh: addr := config.Config.NeighborAddress - SetTcpMD5SigSockopts(listener(addr), addr, "") + for _, l := range server.Listeners(addr) { + SetTcpMD5SigSockopts(l, addr, "") + } peer, found := server.neighborMap[addr] if found { log.Info("Delete a peer configuration for ", addr) @@ -2118,15 +2136,6 @@ func (server *BgpServer) handleGrpcModNeighbor(grpcReq *GrpcRequest) (sMsgs []*S if arg.Operation != api.Operation_ADD && !ok { return nil, fmt.Errorf("not found neighbor %s", addr) } - listener := func(addr net.IP) *net.TCPListener { - var l *net.TCPListener - if addr.To4() != nil { - l = server.listenerMap["tcp4"] - } else { - l = server.listenerMap["tcp6"] - } - return l - } switch arg.Operation { case api.Operation_ADD: @@ -2136,7 +2145,9 @@ func (server *BgpServer) handleGrpcModNeighbor(grpcReq *GrpcRequest) (sMsgs []*S log.Infof("Peer %s is added", addr) } if server.bgpConfig.Global.ListenConfig.Port > 0 { - SetTcpMD5SigSockopts(listener(net.ParseIP(addr)), addr, arg.Peer.Conf.AuthPassword) + for _, l := range server.Listeners(addr) { + SetTcpMD5SigSockopts(l, addr, arg.Peer.Conf.AuthPassword) + } } apitoConfig := func(a *api.Peer) (config.Neighbor, error) { var pconf config.Neighbor @@ -2245,7 +2256,9 @@ func (server *BgpServer) handleGrpcModNeighbor(grpcReq *GrpcRequest) (sMsgs []*S peer.startFSMHandler(server.fsmincomingCh, server.fsmStateCh) server.broadcastPeerState(peer, bgp.BGP_FSM_IDLE) case api.Operation_DEL: - SetTcpMD5SigSockopts(listener(net.ParseIP(addr)), addr, "") + for _, l := range server.Listeners(addr) { + SetTcpMD5SigSockopts(l, addr, "") + } log.Info("Delete a peer configuration for ", addr) go func(addr string) { t := time.AfterFunc(time.Minute*5, func() { log.Fatal("failed to free the fsm.h.t for ", addr) }) diff --git a/tools/pyang_plugins/gobgp.yang b/tools/pyang_plugins/gobgp.yang index 29e3342d..0a60ac6f 100644 --- a/tools/pyang_plugins/gobgp.yang +++ b/tools/pyang_plugins/gobgp.yang @@ -726,6 +726,9 @@ module gobgp { leaf port { type int32; } + leaf-list local-address { + type string; + } } } } |