diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-12-17 18:44:13 -0800 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-12-17 18:44:13 -0800 |
commit | 52ce66ef711d4f2cd356ec654e57ad6e2732981d (patch) | |
tree | 15079ebb80b686fb0210d291fdd5607fccc32385 | |
parent | 1b5d53c411f71209263b8f590ca317802f89621f (diff) |
rpki: support reset/softreset/enable operation
gobgp rpki server <ip address> reset|softreset|enable
reset: close a tcp conneciton and retry to connect and send ResetQuery
softreset: send ResetQuery
enable: send SerialQuery
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | gobgp/cmd/rpki.go | 62 | ||||
-rw-r--r-- | server/rpki.go | 78 | ||||
-rw-r--r-- | server/server.go | 18 |
3 files changed, 92 insertions, 66 deletions
diff --git a/gobgp/cmd/rpki.go b/gobgp/cmd/rpki.go index 7d37acd6..200b7b1d 100644 --- a/gobgp/cmd/rpki.go +++ b/gobgp/cmd/rpki.go @@ -105,55 +105,47 @@ func NewRPKICmd() *cobra.Command { Use: CMD_RPKI, } - modRPKI := func(op api.Operation, address string) { + modRPKI := func(op api.Operation, address string) error { arg := &api.ModRpkiArguments{ Operation: op, Address: address, Port: 323, } - client.ModRPKI(context.Background(), arg) + _, err := client.ModRPKI(context.Background(), arg) + return err } - enableCmd := &cobra.Command{ - Use: CMD_ENABLE, + serverCmd := &cobra.Command{ + Use: CMD_RPKI_SERVER, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 1 { - fmt.Println("usage: gobgp rpki enable <ip address>") + if len(args) == 0 { + showRPKIServer(args) + return + } else if len(args) != 2 { + fmt.Println("usage: gobgp rpki server <ip address> [reset|softreset|enable]") os.Exit(1) } - modRPKI(api.Operation_ENABLE, args[0]) - }, - } - rpkiCmd.AddCommand(enableCmd) - - resetCmd := &cobra.Command{ - Use: CMD_RESET, - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 1 { - fmt.Println("usage: gobgp rpki reset <ip address>") + addr := net.ParseIP(args[0]) + if addr == nil { + fmt.Println("invalid ip address:", args[0]) os.Exit(1) } - modRPKI(api.Operation_RESET, args[0]) - }, - } - rpkiCmd.AddCommand(resetCmd) - - softResetCmd := &cobra.Command{ - Use: CMD_SOFT_RESET, - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 1 { - fmt.Println("usage: gobgp rpki softreset <ip address>") + var op api.Operation + switch args[1] { + case "reset": + op = api.Operation_RESET + case "softreset": + op = api.Operation_SOFTRESET + case "enable": + op = api.Operation_ENABLE + default: + fmt.Println("unknown operation:", args[1]) os.Exit(1) } - modRPKI(api.Operation_SOFTRESET, args[0]) - }, - } - rpkiCmd.AddCommand(softResetCmd) - - serverCmd := &cobra.Command{ - Use: CMD_RPKI_SERVER, - Run: func(cmd *cobra.Command, args []string) { - showRPKIServer(args) + err := modRPKI(op, addr.String()) + if err != nil { + fmt.Println(err) + } }, } diff --git a/server/rpki.go b/server/rpki.go index 326203ec..1864fa25 100644 --- a/server/rpki.go +++ b/server/rpki.go @@ -80,7 +80,6 @@ func newROAManager(as uint32, conf config.RpkiServers) (*roaManager, error) { client := &roaClient{ host: net.JoinHostPort(c.Address.String(), strconv.Itoa(int(c.Port))), eventCh: m.eventCh, - state: &entry.RpkiServerState, } m.clientMap[client.host] = client client.t.Go(client.tryConnect) @@ -89,6 +88,25 @@ func newROAManager(as uint32, conf config.RpkiServers) (*roaManager, error) { return m, nil } +func (m *roaManager) operate(op api.Operation, address string) error { + for network, client := range m.clientMap { + add, _ := splitHostPort(network) + if add == address { + switch op { + case api.Operation_ENABLE: + client.enable() + case api.Operation_DISABLE: + case api.Operation_RESET: + client.reset() + case api.Operation_SOFTRESET: + client.softReset() + } + return nil + } + } + return fmt.Errorf("roa server not found %s", address) +} + func (c *roaManager) recieveROA() chan *roaClientEvent { return c.eventCh } @@ -108,7 +126,6 @@ func (m *roaManager) handleROAEvent(ev *roaClientEvent) { client.state.Downtime = time.Now().Unix() // clear state client.state.RpkiMessages = config.RpkiMessages{} - client.conn.Close() client.conn = nil client.t = tomb.Tomb{} client.t.Go(client.tryConnect) @@ -119,7 +136,7 @@ func (m *roaManager) handleROAEvent(ev *roaClientEvent) { client.t = tomb.Tomb{} client.t.Go(client.established) case RTR: - m.handleRTRMsg(ev.src, client.state, ev.data) + m.handleRTRMsg(client, &client.state, ev.data) } } @@ -166,13 +183,16 @@ func addROA(host string, tree *radix.Tree, as uint32, prefix []byte, prefixLen, } } -func (c *roaManager) handleRTRMsg(host string, state *config.RpkiServerState, buf []byte) { +func (c *roaManager) handleRTRMsg(client *roaClient, state *config.RpkiServerState, buf []byte) { received := &state.RpkiMessages.RpkiReceived m, _ := bgp.ParseRTR(buf) if m != nil { + switch msg := m.(type) { case *bgp.RTRSerialNotify: + client.sessionID = msg.RTRCommon.SessionID + client.serialNumber = msg.RTRCommon.SerialNumber received.SerialNotify++ case *bgp.RTRSerialQuery: case *bgp.RTRResetQuery: @@ -187,9 +207,11 @@ func (c *roaManager) handleRTRMsg(host string, state *config.RpkiServerState, bu received.Ipv6Prefix++ tree = c.roas[bgp.RF_IPv6_UC] } - addROA(host, tree, msg.AS, msg.Prefix, msg.PrefixLen, msg.MaxLen) + addROA(client.host, tree, msg.AS, msg.Prefix, msg.PrefixLen, msg.MaxLen) case *bgp.RTREndOfData: received.EndOfData++ + client.sessionID = msg.RTRCommon.SessionID + client.serialNumber = msg.RTRCommon.SerialNumber case *bgp.RTRCacheReset: received.CacheReset++ case *bgp.RTRErrorReport: @@ -342,14 +364,42 @@ func (c *roaManager) validate(pathList []*table.Path) { } type roaClient struct { - t tomb.Tomb - host string - conn *net.TCPConn - state *config.RpkiServerState - eventCh chan *roaClientEvent + t tomb.Tomb + host string + conn *net.TCPConn + state config.RpkiServerState + eventCh chan *roaClientEvent + sessionID uint16 + serialNumber uint32 +} + +func (c *roaClient) enable() error { + if c.conn != nil { + r := bgp.NewRTRSerialQuery(c.sessionID, c.serialNumber) + data, _ := r.Serialize() + _, err := c.conn.Write(data) + if err != nil { + return err + } + c.state.RpkiMessages.RpkiSent.SerialQuery++ + } + return nil } -func (c *roaClient) kill() { +func (c *roaClient) softReset() error { + if c.conn != nil { + r := bgp.NewRTRResetQuery() + data, _ := r.Serialize() + _, err := c.conn.Write(data) + if err != nil { + return err + } + c.state.RpkiMessages.RpkiSent.ResetQuery++ + } + return nil +} + +func (c *roaClient) reset() { c.t.Kill(nil) if c.conn != nil { c.conn.Close() @@ -383,16 +433,12 @@ func (c *roaClient) established() error { } } - r := bgp.NewRTRResetQuery() - data, _ := r.Serialize() - _, err := c.conn.Write(data) + err := c.softReset() if err != nil { disconnected() return nil } - c.state.RpkiMessages.RpkiSent.ResetQuery++ - reader := bufio.NewReader(c.conn) scanner := bufio.NewScanner(reader) scanner.Split(bgp.SplitRTR) diff --git a/server/server.go b/server/server.go index c5875299..a72c9d1d 100644 --- a/server/server.go +++ b/server/server.go @@ -2375,22 +2375,7 @@ func (server *BgpServer) handleModMrt(grpcReq *GrpcRequest) { func (server *BgpServer) handleModRpki(grpcReq *GrpcRequest) { arg := grpcReq.Data.(*api.ModRpkiArguments) - configured := false - if len(server.bgpConfig.RpkiServers.RpkiServerList) > 0 { - configured = true - } - if arg.Operation == api.Operation_ADD { - if configured { - grpcDone(grpcReq, fmt.Errorf("already enabled")) - return - } - } else { - if !configured { - grpcDone(grpcReq, fmt.Errorf("not enabled yet")) - return - } - } switch arg.Operation { case api.Operation_ADD: r := config.RpkiServer{} @@ -2400,6 +2385,9 @@ func (server *BgpServer) handleModRpki(grpcReq *GrpcRequest) { server.roaManager, _ = newROAManager(server.bgpConfig.Global.GlobalConfig.As, server.bgpConfig.RpkiServers) grpcDone(grpcReq, nil) return + case api.Operation_ENABLE, api.Operation_DISABLE, api.Operation_RESET, api.Operation_SOFTRESET: + grpcDone(grpcReq, server.roaManager.operate(arg.Operation, arg.Address)) + return } grpcDone(grpcReq, fmt.Errorf("not supported yet")) } |