summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--api/rest.go51
-rwxr-xr-xcli/gobgpcli33
-rw-r--r--server/fsm.go17
-rw-r--r--server/peer.go20
-rw-r--r--server/server.go4
5 files changed, 96 insertions, 29 deletions
diff --git a/api/rest.go b/api/rest.go
index 2fba4496..404a6bb5 100644
--- a/api/rest.go
+++ b/api/rest.go
@@ -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)
}
diff --git a/cli/gobgpcli b/cli/gobgpcli
index 70e70e78..55d9b379 100755
--- a/cli/gobgpcli
+++ b/cli/gobgpcli
@@ -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)
diff --git a/server/fsm.go b/server/fsm.go
index d57a6f42..81050b31 100644
--- a/server/fsm.go
+++ b/server/fsm.go
@@ -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",
diff --git a/server/peer.go b/server/peer.go
index 4e6f2ff3..6f0d2f6b 100644
--- a/server/peer.go
+++ b/server/peer.go
@@ -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)
}
diff --git a/server/server.go b/server/server.go
index bc4274de..cbd67732 100644
--- a/server/server.go
+++ b/server/server.go
@@ -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]