mirror of
https://github.com/osrg/gobgp.git
synced 2024-05-11 05:55:10 +00:00
api: add reset and shutdown support
Signed-off-by: FUJITA Tomonori <[email protected]>
This commit is contained in:
+35
-16
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -30,16 +31,17 @@ const (
|
||||
REQ_ADJ_RIB_IN
|
||||
REQ_ADJ_RIB_OUT
|
||||
REQ_LOCAL_RIB
|
||||
REQ_NEIGHBOR_SHUTDOWN
|
||||
REQ_NEIGHBOR_RESET
|
||||
REQ_NEIGHBOR_SOFT_RESET
|
||||
REQ_NEIGHBOR_SOFT_RESET_IN
|
||||
REQ_NEIGHBOR_SOFT_RESET_OUT
|
||||
)
|
||||
|
||||
const (
|
||||
BASE_VERSION = "/v1"
|
||||
NEIGHBOR = "/bgp/neighbor"
|
||||
NEIGHBORS = "/bgp/neighbors"
|
||||
ADJ_RIB_IN = "/bgp/adj-rib-in"
|
||||
ADJ_RIB_OUT = "/bgp/adj-rib-out"
|
||||
ADJ_RIB_LOCAL = "/bgp/adj-rib-local"
|
||||
ADJ_RIB_LOCAL_BEST = "/bgp/adj-rib-local/best"
|
||||
BASE_VERSION = "/v1"
|
||||
NEIGHBOR = "/bgp/neighbor"
|
||||
NEIGHBORS = "/bgp/neighbors"
|
||||
|
||||
PARAM_REMOTE_PEER_ADDR = "remotePeerAddr"
|
||||
STATS = "/stats"
|
||||
@@ -102,18 +104,19 @@ func NewRestServer(port int, bgpServerCh chan *RestRequest) *RestServer {
|
||||
func (rs *RestServer) Serve() {
|
||||
neighbor := BASE_VERSION + NEIGHBOR
|
||||
neighbors := BASE_VERSION + NEIGHBORS
|
||||
// adjRibIn := BASE_VERSION + ADJ_RIB_IN
|
||||
// adjRibOut := BASE_VERSION + ADJ_RIB_OUT
|
||||
// adjRibLocal := BASE_VERSION + ADJ_RIB_LOCAL
|
||||
// adjRibLocalBest := BASE_VERSION + ADJ_RIB_LOCAL_BEST
|
||||
|
||||
r := mux.NewRouter()
|
||||
// set URLs
|
||||
|
||||
perPeerURL := "/{" + PARAM_REMOTE_PEER_ADDR + "}"
|
||||
r.HandleFunc(neighbors, rs.Neighbors).Methods("GET")
|
||||
r.HandleFunc(neighbor+"/{"+PARAM_REMOTE_PEER_ADDR+"}", rs.Neighbor).Methods("GET")
|
||||
// r.HandleFunc(adjRibIn+"/{"+PARAM_REMOTE_PEER_ADDR+"}", rs.AdjRibIn).Methods("GET")
|
||||
// r.HandleFunc(adjRibOut+"/{"+PARAM_REMOTE_PEER_ADDR+"}", rs.AdjRibOut).Methods("GET")
|
||||
r.HandleFunc(neighbor+"/{"+PARAM_REMOTE_PEER_ADDR+"}/"+"local-rib", rs.NeighborLocalRib).Methods("GET")
|
||||
r.HandleFunc(neighbor+perPeerURL, rs.Neighbor).Methods("GET")
|
||||
r.HandleFunc(neighbor+perPeerURL+"/"+"local-rib", rs.NeighborLocalRib).Methods("GET")
|
||||
r.HandleFunc(neighbor+perPeerURL+"/"+"shutdown", rs.NeighborPostHandler).Methods("POST")
|
||||
r.HandleFunc(neighbor+perPeerURL+"/"+"reset", rs.NeighborPostHandler).Methods("POST")
|
||||
r.HandleFunc(neighbor+perPeerURL+"/"+"softreset", rs.NeighborPostHandler).Methods("POST")
|
||||
r.HandleFunc(neighbor+perPeerURL+"/"+"softresetin", rs.NeighborPostHandler).Methods("POST")
|
||||
r.HandleFunc(neighbor+perPeerURL+"/"+"softresetout", rs.NeighborPostHandler).Methods("POST")
|
||||
|
||||
// stats
|
||||
r.HandleFunc(STATS, stats_api.Handler).Methods("GET")
|
||||
|
||||
@@ -154,6 +157,22 @@ func (rs *RestServer) neighbor(w http.ResponseWriter, r *http.Request, reqType i
|
||||
w.Write(res.Data)
|
||||
}
|
||||
|
||||
func (rs *RestServer) NeighborPostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
action := strings.Split(r.URL.Path, "/")
|
||||
switch action[len(action)-1] {
|
||||
case "shutdown":
|
||||
rs.neighbor(w, r, REQ_NEIGHBOR_SHUTDOWN)
|
||||
case "reset":
|
||||
rs.neighbor(w, r, REQ_NEIGHBOR_RESET)
|
||||
case "softreset":
|
||||
rs.neighbor(w, r, REQ_NEIGHBOR_SOFT_RESET)
|
||||
case "softresetin":
|
||||
rs.neighbor(w, r, REQ_NEIGHBOR_SOFT_RESET_IN)
|
||||
case "softresetout":
|
||||
rs.neighbor(w, r, REQ_NEIGHBOR_SOFT_RESET_OUT)
|
||||
}
|
||||
}
|
||||
|
||||
func (rs *RestServer) Neighbor(w http.ResponseWriter, r *http.Request) {
|
||||
rs.neighbor(w, r, REQ_NEIGHBOR)
|
||||
}
|
||||
|
||||
+30
-3
@@ -24,6 +24,14 @@
|
||||
# $ gobgpcli show neighbor 10.0.0.2
|
||||
# - get the local rib of a neighbor
|
||||
# $ gobgpcli show neighbor 10.0.0.2 local
|
||||
# - reset
|
||||
# $ gobgpcli reset neighbor 10.0.0.2
|
||||
# - softresetin
|
||||
# $ gobgpcli softresetin neighbor 10.0.0.2
|
||||
# - softresetout
|
||||
# $ gobgpcli softresetout neighbor 10.0.0.2
|
||||
# - shutdown
|
||||
# $ gobgpcli shutdown neighbor 10.0.0.2
|
||||
|
||||
from optparse import OptionParser
|
||||
import requests
|
||||
@@ -33,8 +41,27 @@ import json
|
||||
from datetime import timedelta
|
||||
|
||||
|
||||
class Action(object):
|
||||
def __init__(self, command, options, args):
|
||||
super(Action, self).__init__()
|
||||
self.command = command
|
||||
self.options = options
|
||||
self.args = args
|
||||
self.base_url = self.options.url + ":" + str(self.options.port) + "/v1/bgp"
|
||||
|
||||
def __call__(self):
|
||||
if len(self.args) != 1:
|
||||
return 1
|
||||
r = requests.post(self.base_url + "/neighbor/" + self.args[0] + "/" + self.command)
|
||||
if r.status_code == requests.codes.ok:
|
||||
print "Succeed"
|
||||
else:
|
||||
print "Failed"
|
||||
return 0
|
||||
|
||||
|
||||
class Show(object):
|
||||
def __init__(self, options, args):
|
||||
def __init__(self, _command, options, args):
|
||||
super(Show, self).__init__()
|
||||
self.options = options
|
||||
self.args = args
|
||||
@@ -194,7 +221,7 @@ def main():
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
commands = {"show": Show}
|
||||
commands = {"show": Show, "reset": Action, "shutdown": Action, "softreset": Action, "softresetin": Action, "softresetout": Action}
|
||||
|
||||
if len(args) == 0:
|
||||
parser.print_help()
|
||||
@@ -204,7 +231,7 @@ def main():
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
ret = commands[args[0]](options, args[1:])()
|
||||
ret = commands[args[0]](args[0], options, args[1:])()
|
||||
if ret != 0:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
+11
-6
@@ -122,7 +122,7 @@ type FSMHandler struct {
|
||||
func NewFSMHandler(fsm *FSM) *FSMHandler {
|
||||
f := &FSMHandler{
|
||||
fsm: fsm,
|
||||
errorCh: make(chan bool),
|
||||
errorCh: make(chan bool, 2),
|
||||
}
|
||||
f.t.Go(f.loop)
|
||||
return f
|
||||
@@ -281,7 +281,11 @@ func (h *FSMHandler) opensent() bgp.FSMState {
|
||||
case *bgp.MessageError:
|
||||
err := e.MsgData.(*bgp.MessageError)
|
||||
m := bgp.NewBGPNotificationMessage(err.TypeCode, err.SubTypeCode, err.Data)
|
||||
h.fsm.outgoing <- m
|
||||
b, _ := m.Serialize()
|
||||
fsm.passiveConn.Write(b)
|
||||
fsm.bgpMessageStateUpdate(m.Header.Type, false)
|
||||
h.conn.Close()
|
||||
nextState = bgp.BGP_FSM_IDLE
|
||||
default:
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Peer",
|
||||
@@ -330,10 +334,11 @@ func (h *FSMHandler) openconfirm() bgp.FSMState {
|
||||
case *bgp.MessageError:
|
||||
err := e.MsgData.(*bgp.MessageError)
|
||||
m := bgp.NewBGPNotificationMessage(err.TypeCode, err.SubTypeCode, err.Data)
|
||||
h.fsm.outgoing <- m
|
||||
// tx goroutine will close the tcp
|
||||
// connection and state will be
|
||||
// changed. so no need to change here.
|
||||
b, _ := m.Serialize()
|
||||
fsm.passiveConn.Write(b)
|
||||
fsm.bgpMessageStateUpdate(m.Header.Type, false)
|
||||
h.conn.Close()
|
||||
return bgp.BGP_FSM_IDLE
|
||||
default:
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Peer",
|
||||
|
||||
+18
-2
@@ -168,8 +168,24 @@ func (peer *Peer) sendMessages(msgs []*bgp.BGPMessage) {
|
||||
|
||||
func (peer *Peer) handleREST(restReq *api.RestRequest) {
|
||||
result := &api.RestResponse{}
|
||||
j, _ := json.Marshal(peer.rib.Tables[peer.rf])
|
||||
result.Data = j
|
||||
switch restReq.RequestType {
|
||||
case api.REQ_LOCAL_RIB:
|
||||
j, _ := json.Marshal(peer.rib.Tables[peer.rf])
|
||||
result.Data = j
|
||||
case api.REQ_NEIGHBOR_SHUTDOWN:
|
||||
peer.fsm.outgoing <- bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN, nil)
|
||||
case api.REQ_NEIGHBOR_RESET:
|
||||
peer.fsm.outgoing <- bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_RESET, nil)
|
||||
case api.REQ_NEIGHBOR_SOFT_RESET:
|
||||
case api.REQ_NEIGHBOR_SOFT_RESET_IN:
|
||||
// check capability
|
||||
// drop allIn and other peers?
|
||||
// peer.adjRib.DropAllIn(peer.rf)
|
||||
peer.fsm.outgoing <- bgp.NewBGPRouteRefreshMessage(uint16(int(peer.rf)>>16), 0, uint8(int(peer.rf)&0xff))
|
||||
case api.REQ_NEIGHBOR_SOFT_RESET_OUT:
|
||||
pathList := peer.adjRib.GetOutPathList(peer.rf)
|
||||
peer.sendMessages(table.CreateUpdateMsgFromPaths(pathList))
|
||||
}
|
||||
restReq.ResponseCh <- result
|
||||
close(restReq.ResponseCh)
|
||||
}
|
||||
|
||||
+2
-2
@@ -228,7 +228,7 @@ func (server *BgpServer) handleRest(restReq *api.RestRequest) {
|
||||
restReq.ResponseCh <- result
|
||||
close(restReq.ResponseCh)
|
||||
|
||||
case api.REQ_NEIGHBOR: // get neighbor state
|
||||
case api.REQ_NEIGHBOR:
|
||||
|
||||
remoteAddr := restReq.RemoteAddr
|
||||
result := &api.RestResponse{}
|
||||
@@ -241,7 +241,7 @@ func (server *BgpServer) handleRest(restReq *api.RestRequest) {
|
||||
}
|
||||
restReq.ResponseCh <- result
|
||||
close(restReq.ResponseCh)
|
||||
case api.REQ_LOCAL_RIB:
|
||||
case api.REQ_LOCAL_RIB, api.REQ_NEIGHBOR_SHUTDOWN, api.REQ_NEIGHBOR_RESET, api.REQ_NEIGHBOR_SOFT_RESET_IN, api.REQ_NEIGHBOR_SOFT_RESET_OUT:
|
||||
remoteAddr := restReq.RemoteAddr
|
||||
result := &api.RestResponse{}
|
||||
info, found := server.peerMap[remoteAddr]
|
||||
|
||||
Reference in New Issue
Block a user