summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2015-04-04 14:02:46 +0000
committerISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2015-04-04 14:02:46 +0000
commit01a0fc94cc86a536544ab641bbaf9f54aad1593c (patch)
tree141716b2b98da6bad1a59a2500c2601ddf82c11f
parent6d2fec2f4f86edc29a058b4971553fe48b1a7c7c (diff)
api/server: add apis to add/delete routes to/from global rib
add: curl -X POST -d prefix=10.0.0.0/24 http://localhost:8080/v1/bgp/global/ipv4 delete: curl -X DELETE -d prefix=10.0.0.0/24 http://localhost:8080/v1/bgp/global/ipv4 Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r--api/rest.go59
-rw-r--r--server/peer.go65
-rw-r--r--server/peer_test.go18
-rw-r--r--server/server.go3
4 files changed, 133 insertions, 12 deletions
diff --git a/api/rest.go b/api/rest.go
index 1201abea..fd57253d 100644
--- a/api/rest.go
+++ b/api/rest.go
@@ -16,11 +16,13 @@
package api
import (
+ "bytes"
log "github.com/Sirupsen/logrus"
"github.com/fukata/golang-stats-api-handler"
"github.com/gorilla/mux"
"github.com/osrg/gobgp/packet"
"net/http"
+ "net/url"
"strconv"
)
@@ -39,6 +41,8 @@ const (
REQ_NEIGHBOR_ENABLE
REQ_NEIGHBOR_DISABLE
REQ_GLOBAL_RIB
+ REQ_GLOBAL_ADD
+ REQ_GLOBAL_DELETE
)
const (
@@ -66,14 +70,16 @@ type RestRequest struct {
RouteFamily bgp.RouteFamily
ResponseCh chan *RestResponse
Err error
+ Data map[string]interface{}
}
-func NewRestRequest(reqType int, remoteAddr string, rf bgp.RouteFamily) *RestRequest {
+func NewRestRequest(reqType int, remoteAddr string, rf bgp.RouteFamily, d map[string]interface{}) *RestRequest {
r := &RestRequest{
RequestType: reqType,
RouteFamily: rf,
RemoteAddr: remoteAddr,
ResponseCh: make(chan *RestResponse),
+ Data: d,
}
return r
}
@@ -122,6 +128,8 @@ func (rs *RestServer) Serve() {
operationURL := "/{" + PARAM_OPERATION + "}"
routeFamilyURL := "/{" + PARAM_ROUTE_FAMILY + "}"
r.HandleFunc(global+showObjectURL+routeFamilyURL, rs.GlobalGET).Methods("GET")
+ r.HandleFunc(global+routeFamilyURL, rs.GlobalPOST).Methods("POST")
+ r.HandleFunc(global+routeFamilyURL, rs.GlobalDELETE).Methods("DELETE")
r.HandleFunc(neighbors, rs.NeighborGET).Methods("GET")
r.HandleFunc(neighbor+perPeerURL, rs.NeighborGET).Methods("GET")
r.HandleFunc(neighbor+perPeerURL+showObjectURL+routeFamilyURL, rs.NeighborGET).Methods("GET")
@@ -160,7 +168,7 @@ func (rs *RestServer) neighbor(w http.ResponseWriter, r *http.Request, reqType i
}
//Send channel of request parameter.
- req := NewRestRequest(reqType, remoteAddr, rf)
+ req := NewRestRequest(reqType, remoteAddr, rf, nil)
rs.bgpServerCh <- req
//Wait response
@@ -233,6 +241,53 @@ func (rs *RestServer) GlobalGET(w http.ResponseWriter, r *http.Request) {
}
+func (rs *RestServer) global(w http.ResponseWriter, r *http.Request, reqType int) {
+ params := mux.Vars(r)
+ var rf bgp.RouteFamily
+ routeFamily, ok := params[PARAM_ROUTE_FAMILY]
+ if ok {
+ switch routeFamily {
+ case "ipv4":
+ rf = bgp.RF_IPv4_UC
+ case "ipv6":
+ rf = bgp.RF_IPv6_UC
+ case "evpn":
+ rf = bgp.RF_EVPN
+ default:
+ NotFoundHandler(w, r)
+ return
+ }
+ }
+ var buf bytes.Buffer
+ buf.ReadFrom(r.Body)
+ query, _ := url.ParseQuery(buf.String())
+ d := make(map[string]interface{})
+ for k, v := range query {
+ d[k] = v
+ }
+ req := NewRestRequest(reqType, "", rf, d)
+ rs.bgpServerCh <- req
+
+ //Wait response
+ res := <-req.ResponseCh
+ if e := res.Err(); e != nil {
+ log.Debug(e.Error())
+ http.Error(w, e.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/json; charset=utf-8")
+ w.Write(res.Data)
+}
+
+func (rs *RestServer) GlobalPOST(w http.ResponseWriter, r *http.Request) {
+ rs.global(w, r, REQ_GLOBAL_ADD)
+}
+
+func (rs *RestServer) GlobalDELETE(w http.ResponseWriter, r *http.Request) {
+ rs.global(w, r, REQ_GLOBAL_DELETE)
+}
+
func NotFoundHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
}
diff --git a/server/peer.go b/server/peer.go
index 362482a7..8c62d105 100644
--- a/server/peer.go
+++ b/server/peer.go
@@ -17,6 +17,7 @@ package server
import (
"encoding/json"
+ "fmt"
log "github.com/Sirupsen/logrus"
"github.com/osrg/gobgp/api"
"github.com/osrg/gobgp/config"
@@ -101,6 +102,9 @@ func NewPeer(g config.Global, peer config.Neighbor, serverMsgCh chan *serverMsg,
LocalID: g.RouterId,
Address: peer.NeighborAddress,
}
+ if isGlobalRib {
+ p.peerInfo.ID = g.RouterId
+ }
rfList := p.configuredRFlist()
p.adjRib = table.NewAdjRib(rfList)
p.rib = table.NewTableManager(p.peerConfig.NeighborAddress.String(), rfList)
@@ -287,6 +291,67 @@ func (peer *Peer) sendMessages(msgs []*bgp.BGPMessage) {
func (peer *Peer) handleREST(restReq *api.RestRequest) {
result := &api.RestResponse{}
switch restReq.RequestType {
+ case api.REQ_GLOBAL_ADD, api.REQ_GLOBAL_DELETE:
+ rf := restReq.RouteFamily
+ prefixes := restReq.Data["prefix"].([]string)
+ var isWithdraw bool
+ if restReq.RequestType == api.REQ_GLOBAL_DELETE {
+ isWithdraw = true
+ }
+
+ pList := make([]table.Path, 0, len(prefixes))
+ for _, prefix := range prefixes {
+ var nlri bgp.AddrPrefixInterface
+ pattr := make([]bgp.PathAttributeInterface, 0)
+ pattr = append(pattr, bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP))
+ asparam := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{peer.peerInfo.AS})
+ pattr = append(pattr, bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{asparam}))
+
+ if rf == bgp.RF_IPv4_UC {
+ ip, net, _ := net.ParseCIDR(prefix)
+ if ip.To4() == nil {
+ result.ResponseErr = fmt.Errorf("Invalid ipv4 prefix: %s", prefix)
+ restReq.ResponseCh <- result
+ close(restReq.ResponseCh)
+ return
+ }
+ ones, _ := net.Mask.Size()
+ nlri = &bgp.NLRInfo{
+ IPAddrPrefix: *bgp.NewIPAddrPrefix(uint8(ones), ip.String()),
+ }
+
+ pattr = append(pattr, bgp.NewPathAttributeNextHop("0.0.0.0"))
+
+ } else if rf == bgp.RF_IPv6_UC {
+ ip, net, _ := net.ParseCIDR(prefix)
+ if ip.To16() == nil {
+ result.ResponseErr = fmt.Errorf("Invalid ipv6 prefix: %s", prefix)
+ restReq.ResponseCh <- result
+ close(restReq.ResponseCh)
+ return
+ }
+ ones, _ := net.Mask.Size()
+ nlri = bgp.NewIPv6AddrPrefix(uint8(ones), ip.String())
+
+ pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("::", []bgp.AddrPrefixInterface{nlri}))
+
+ } else {
+ result.ResponseErr = fmt.Errorf("Unsupported address family: %s", rf)
+ restReq.ResponseCh <- result
+ close(restReq.ResponseCh)
+ return
+ }
+
+ p := table.CreatePath(peer.peerInfo, nlri, pattr, isWithdraw, time.Now())
+ pList = append(pList, p)
+ }
+
+ pm := &peerMsg{
+ msgType: PEER_MSG_PATH,
+ msgData: pList,
+ }
+ peer.peerMsgCh <- pm
+
case api.REQ_LOCAL_RIB, api.REQ_GLOBAL_RIB:
// just empty so we use ipv4 for any route family
j, _ := json.Marshal(table.NewIPv4Table(0))
diff --git a/server/peer_test.go b/server/peer_test.go
index 23588fdc..90c64960 100644
--- a/server/peer_test.go
+++ b/server/peer_test.go
@@ -123,7 +123,7 @@ func TestPeerAdminShutdownWhileEstablished(t *testing.T) {
peer.connCh <- m
waitUntil(assert, bgp.BGP_FSM_ESTABLISHED, peer, 1000)
- restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC)
+ restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg := &serverMsg{
msgType: SRV_MSG_API,
msgData: restReq,
@@ -166,7 +166,7 @@ func TestPeerAdminShutdownWhileIdle(t *testing.T) {
waitUntil(assert, bgp.BGP_FSM_IDLE, peer, 1000)
- restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC)
+ restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg := &serverMsg{
msgType: SRV_MSG_API,
msgData: restReq,
@@ -201,7 +201,7 @@ func TestPeerAdminShutdownWhileActive(t *testing.T) {
waitUntil(assert, bgp.BGP_FSM_ACTIVE, peer, 1000)
- restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC)
+ restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg := &serverMsg{
msgType: SRV_MSG_API,
msgData: restReq,
@@ -238,7 +238,7 @@ func TestPeerAdminShutdownWhileOpensent(t *testing.T) {
peer.connCh <- m
waitUntil(assert, bgp.BGP_FSM_OPENSENT, peer, 1000)
- restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC)
+ restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg := &serverMsg{
msgType: SRV_MSG_API,
msgData: restReq,
@@ -283,7 +283,7 @@ func TestPeerAdminShutdownWhileOpenconfirm(t *testing.T) {
peer.connCh <- m
waitUntil(assert, bgp.BGP_FSM_OPENCONFIRM, peer, 1000)
- restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC)
+ restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg := &serverMsg{
msgType: SRV_MSG_API,
msgData: restReq,
@@ -334,7 +334,7 @@ func TestPeerAdminEnable(t *testing.T) {
waitUntil(assert, bgp.BGP_FSM_ESTABLISHED, peer, 1000)
// shutdown peer at first
- restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC)
+ restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg := &serverMsg{
msgType: SRV_MSG_API,
msgData: restReq,
@@ -350,7 +350,7 @@ func TestPeerAdminEnable(t *testing.T) {
assert.Equal(ADMIN_STATE_DOWN, peer.fsm.adminState)
// enable peer
- restReq = api.NewRestRequest(api.REQ_NEIGHBOR_ENABLE, "0.0.0.0", bgp.RF_IPv4_UC)
+ restReq = api.NewRestRequest(api.REQ_NEIGHBOR_ENABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg = &serverMsg{
msgType: SRV_MSG_API,
msgData: restReq,
@@ -397,7 +397,7 @@ func TestPeerAdminShutdownReject(t *testing.T) {
peer.connCh <- m
waitUntil(assert, bgp.BGP_FSM_OPENSENT, peer, 1000)
- restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC)
+ restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg := &serverMsg{
msgType: SRV_MSG_API,
msgData: restReq,
@@ -411,7 +411,7 @@ func TestPeerAdminShutdownReject(t *testing.T) {
json.Unmarshal(result.Data, &res)
assert.Equal("previous request is still remaining", res["result"])
- restReq = api.NewRestRequest(api.REQ_NEIGHBOR_ENABLE, "0.0.0.0", bgp.RF_IPv4_UC)
+ restReq = api.NewRestRequest(api.REQ_NEIGHBOR_ENABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg = &serverMsg{
msgType: SRV_MSG_API,
msgData: restReq,
diff --git a/server/server.go b/server/server.go
index ebb7a611..a47f9177 100644
--- a/server/server.go
+++ b/server/server.go
@@ -116,6 +116,7 @@ func (server *BgpServer) Serve() {
neighConf := config.Neighbor{
NeighborAddress: g.RouterId,
AfiSafiList: g.AfiSafiList,
+ PeerAs: g.As,
}
server.globalRib = NewPeer(g, neighConf, globalSch, globalPch, nil, true, make(map[string]*policy.Policy))
@@ -320,7 +321,7 @@ func (server *BgpServer) handleRest(restReq *api.RestRequest) {
}
restReq.ResponseCh <- result
close(restReq.ResponseCh)
- case api.REQ_GLOBAL_RIB:
+ case api.REQ_GLOBAL_RIB, api.REQ_GLOBAL_ADD, api.REQ_GLOBAL_DELETE:
msg := &serverMsg{
msgType: SRV_MSG_API,
msgData: restReq,