diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2016-02-04 14:24:18 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-02-04 23:34:24 -0800 |
commit | c9436bc7218800ef6911dab6eed7d7ddf3378e94 (patch) | |
tree | 6001d367aa133e28fddb460647c37e3ac5aef168 /server/server.go | |
parent | 7f6831ce1228e42b717f5bf3e507ddae06483ba1 (diff) |
server: add support specifying addresses to listen
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
Diffstat (limited to 'server/server.go')
-rw-r--r-- | server/server.go | 83 |
1 files changed, 48 insertions, 35 deletions
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) }) |