summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--api/rest.go212
-rw-r--r--bgpd.go5
-rw-r--r--server/server.go26
3 files changed, 243 insertions, 0 deletions
diff --git a/api/rest.go b/api/rest.go
new file mode 100644
index 00000000..f75b989d
--- /dev/null
+++ b/api/rest.go
@@ -0,0 +1,212 @@
+// Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package api
+
+import (
+ "encoding/json"
+ "fmt"
+ log "github.com/Sirupsen/logrus"
+ "github.com/gorilla/mux"
+ "net/http"
+ "os"
+ "strconv"
+)
+
+var logger *log.Logger = &log.Logger{
+ Out: os.Stderr,
+ Formatter: new(log.JSONFormatter),
+ Hooks: make(map[log.Level][]log.Hook),
+ Level: log.InfoLevel,
+}
+
+const (
+ _ = iota
+ REQ_NEIGHBOR
+ REQ_NEIGHBORS
+ REQ_ADJ_RIB_IN
+ REQ_ADJ_RIB_OUT
+ REQ_ADJ_RIB_LOCAL
+ REQ_ADJ_RIB_LOCAL_BEST
+)
+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"
+
+ PARAM_REMOTE_PEER_ADDR = "remotePeerAddr"
+)
+
+const REST_PORT = 8080
+
+const (
+ _ = iota
+ JSON_FORMATTED
+ JSON_UN_FORMATTED
+)
+
+var JsonFormat int = JSON_FORMATTED
+
+// trigger struct for exchanging information in the rest and peer.
+// rest and peer operated at different thread.
+
+type RestRequest struct {
+ RequestType int
+ RemoteAddr string
+ ResponseCh chan RestResponse
+ Err error
+}
+
+func NewRestRequest(reqType int, remoteAddr string) *RestRequest {
+ r := &RestRequest{
+ RequestType: reqType,
+ RemoteAddr: remoteAddr,
+ ResponseCh: make(chan RestResponse),
+ }
+ return r
+}
+
+type RestResponse interface {
+ Err() error
+}
+
+type RestResponseDefault struct {
+ ResponseErr error
+}
+
+func (r *RestResponseDefault) Err() error {
+ return r.ResponseErr
+}
+
+// Response struct for Neighbor
+type RestResponseNeighbor struct {
+ RestResponseDefault
+ RemoteAddr string
+ RemoteAs uint32
+ NeighborState uint32
+ UpdateCount int
+}
+
+// Response struct for Rib
+type RestResponseRib struct {
+ RestResponseDefault
+ RemoteAddr string
+ RemoteAs uint32
+ RibInfo []string
+}
+
+type RestServer struct {
+ port int
+ bgpServerCh chan *RestRequest
+}
+
+func NewRestServer(port int, bgpServerCh chan *RestRequest) *RestServer {
+ rs := &RestServer{
+ port: port,
+ bgpServerCh: bgpServerCh}
+ return rs
+}
+
+// Main thread of rest service.
+// URL than can receive.
+// get state of neighbor.
+// -- curt -i -X GET http://<ownIP>:3000/v1/bgp/neighbor/<remote address of target neighbor>
+// get state of neighbors.
+// -- curt -i -X GET http://<ownIP>:3000/v1/bgp/neighbors
+// get adj-rib-in of each neighbor.
+// -- curt -i -X GET http://<ownIP>:3000/v1/bgp/adj-rib-in/<remote address of target neighbor>
+// get adj-rib-out of each neighbor.
+// -- curt -i -X GET http://<ownIP>:3000/v1/bgp/adj-rib-out/<remote address of target neighbor>
+// get adj-rib-local of each neighbor.
+// -- curt -i -X GET http://<ownIP>:3000/v1/bgp/adj-rib-local/<remote address of target neighbor>
+// get only best path of adj-rib-local of each neighbor.
+// -- curt -i -X GET http://<ownIP>:3000/v1/bgp/adj-rib-local/best/<remote address of target neighbor>
+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
+ r.HandleFunc(neighbor+"/{"+PARAM_REMOTE_PEER_ADDR+"}", rs.Neighbor).Methods("GET")
+ // r.HandleFunc(neighbors, rs.Neighbors).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(adjRibLocal+"/{"+PARAM_REMOTE_PEER_ADDR+"}", rs.AdjRibLocal).Methods("GET")
+ // r.HandleFunc(adjRibLocalBest+"/{"+PARAM_REMOTE_PEER_ADDR+"}", rs.AdjRibLocalBest).Methods("GET")
+
+ // Handler when not found url
+ r.NotFoundHandler = http.HandlerFunc(NotFoundHandler)
+ http.Handle("/", r)
+
+ http.ListenAndServe(":"+strconv.Itoa(rs.port), nil)
+
+}
+
+// Http request of curl, return the json format infomation of neibor state.
+func (rs *RestServer) Neighbor(w http.ResponseWriter, r *http.Request) {
+ // remotePeerAddr := mux.Vars(r)[PARAM_REMOTE_PEER_ADDR]
+
+ params := mux.Vars(r)
+ remoteAddr, found := params[PARAM_REMOTE_PEER_ADDR]
+ if !found {
+ errStr := "neighbor address is not specified"
+ logger.Debug(errStr)
+ http.Error(w, errStr, http.StatusInternalServerError)
+ }
+
+ logger.Debugf("Look up neighbor with the remote address : %v", remoteAddr)
+
+ //Send channel of request parameter.
+ req := NewRestRequest(REQ_NEIGHBOR, remoteAddr)
+ rs.bgpServerCh <- req
+
+ //Wait response
+ resInf := <-req.ResponseCh
+ if e := resInf.Err(); e != nil {
+ logger.Debug(e.Error())
+ http.Error(w, e.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ res := resInf.(*RestResponseNeighbor)
+
+ var jns []byte
+ var err error
+ switch JsonFormat {
+ case JSON_FORMATTED:
+ jns, err = json.MarshalIndent(res, "", " ") // formatted json
+ case JSON_UN_FORMATTED:
+ jns, err = json.Marshal(res) // Unformatted json
+ }
+ if err != nil {
+ errStr := fmt.Sprintf("Failed to perth json of neighbor state", remoteAddr)
+ logger.Error(errStr)
+ http.Error(w, errStr, http.StatusInternalServerError)
+ return
+ }
+ w.Write(jns)
+}
+
+func NotFoundHandler(w http.ResponseWriter, r *http.Request) {
+ http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
+}
diff --git a/bgpd.go b/bgpd.go
index 277349a7..1ba04fbc 100644
--- a/bgpd.go
+++ b/bgpd.go
@@ -18,6 +18,7 @@ package main
import (
"fmt"
"github.com/jessevdk/go-flags"
+ "github.com/osrg/gobgp/api"
"github.com/osrg/gobgp/config"
"github.com/osrg/gobgp/packet"
"github.com/osrg/gobgp/server"
@@ -54,6 +55,10 @@ func main() {
bgpServer := server.NewBgpServer(bgp.BGP_PORT)
go bgpServer.Serve()
+ // start Rest Server
+ restServer := api.NewRestServer(api.REST_PORT, bgpServer.RestReqCh)
+ go restServer.Serve()
+
var bgpConfig *config.BgpType = nil
for {
select {
diff --git a/server/server.go b/server/server.go
index 54644560..bca36afa 100644
--- a/server/server.go
+++ b/server/server.go
@@ -17,6 +17,7 @@ package server
import (
"fmt"
+ "github.com/osrg/gobgp/api"
"github.com/osrg/gobgp/config"
"net"
"os"
@@ -43,6 +44,7 @@ type BgpServer struct {
globalTypeCh chan config.GlobalType
addedPeerCh chan config.NeighborType
deletedPeerCh chan config.NeighborType
+ RestReqCh chan *api.RestRequest
listenPort int
peerMap map[string]*Peer
}
@@ -52,6 +54,7 @@ func NewBgpServer(port int) *BgpServer {
b.globalTypeCh = make(chan config.GlobalType)
b.addedPeerCh = make(chan config.NeighborType)
b.deletedPeerCh = make(chan config.NeighborType)
+ b.RestReqCh = make(chan *api.RestRequest, 1)
b.listenPort = port
return &b
}
@@ -114,6 +117,9 @@ func (server *BgpServer) Serve() {
} else {
fmt.Println("can't found neighbor", addr)
}
+ case restReq := <-server.RestReqCh:
+ server.handleRest(restReq)
+
case msg := <-broadcastCh:
server.broadcast(msg)
}
@@ -143,3 +149,23 @@ func (server *BgpServer) broadcast(msg *message) {
}
}
}
+
+func (server *BgpServer) handleRest(restReq *api.RestRequest) {
+ defer close(restReq.ResponseCh)
+ switch restReq.RequestType {
+ case api.REQ_NEIGHBOR: // get neighbor state
+
+ remoteAddr := restReq.RemoteAddr
+ result := &api.RestResponseNeighbor{}
+ peer, found := server.peerMap[remoteAddr]
+ if found {
+ c := peer.peerConfig
+ result.NeighborState = c.BgpNeighborCommonState.State
+ result.RemoteAddr = c.NeighborAddress.String()
+ result.RemoteAs = c.PeerAs
+ } else {
+ result.ResponseErr = fmt.Errorf("Neighbor that has %v does not exist.", remoteAddr)
+ }
+ restReq.ResponseCh <- result
+ }
+}