summaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2015-07-31 18:51:05 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-08-08 20:56:46 +0900
commitbf9e135ba85cad641c3812abace9221cbf5a2615 (patch)
tree435728bd72e93ddfea7a3c02d78cfb1a9c65f16f /server
parentecd079e318e1c5d5aa2d2f1348a4ad1a37daec37 (diff)
server: support vrf
to add/delete vrf $ gobgp vrf [add|del] <vrf-name> rd <rd> rt [import|export|both] <rt>... show vrf $ gobgp vrf to add/delete a path to a specific vrf $ gobgp vrf <vrf-name> rib [add|del] <prefix> -a <address-family> show paths contained in a specific vrf $ gobgp vrf <vrf-name> rib -a <address-family> Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
Diffstat (limited to 'server')
-rw-r--r--server/grpc_server.go63
-rw-r--r--server/server.go209
2 files changed, 237 insertions, 35 deletions
diff --git a/server/grpc_server.go b/server/grpc_server.go
index 17fb6c87..041f0659 100644
--- a/server/grpc_server.go
+++ b/server/grpc_server.go
@@ -48,8 +48,6 @@ const (
REQ_NEIGHBOR_POLICY_DEL_EXPORT
REQ_NEIGHBOR_POLICY_DEL_DISTRIBUTE
REQ_GLOBAL_RIB
- REQ_GLOBAL_ADD
- REQ_GLOBAL_DELETE
REQ_POLICY_PREFIX
REQ_POLICY_PREFIXES
REQ_POLICY_PREFIX_ADD
@@ -85,6 +83,10 @@ const (
REQ_MRT_GLOBAL_RIB
REQ_MRT_LOCAL_RIB
REQ_RPKI
+ REQ_VRF
+ REQ_VRFS
+ REQ_VRF_MOD
+ REQ_MOD_PATH
)
const GRPC_PORT = 8080
@@ -329,16 +331,11 @@ func (s *Server) ModPath(stream api.Grpc_ModPathServer) error {
return err
}
- if arg.Resource != api.Resource_GLOBAL {
+ if arg.Resource != api.Resource_GLOBAL && arg.Resource != api.Resource_VRF {
return fmt.Errorf("unsupported resource: %s", arg.Resource)
}
- reqType := REQ_GLOBAL_ADD
- if arg.IsWithdraw {
- reqType = REQ_GLOBAL_DELETE
- }
-
- req := NewGrpcRequest(reqType, "", bgp.RouteFamily(0), arg)
+ req := NewGrpcRequest(REQ_MOD_PATH, arg.Name, bgp.RouteFamily(0), arg)
s.bgpServerCh <- req
res := <-req.ResponseCh
@@ -641,6 +638,54 @@ func (s *Server) GetRPKI(arg *api.Arguments, stream api.Grpc_GetRPKIServer) erro
return nil
}
+func (s *Server) GetVrf(arg *api.Arguments, stream api.Grpc_GetVrfServer) error {
+ rf, err := convertAf2Rf(arg.Af)
+ if err != nil {
+ return err
+ }
+ req := NewGrpcRequest(REQ_VRF, "", rf, arg)
+ s.bgpServerCh <- req
+
+ for res := range req.ResponseCh {
+ if err := res.Err(); err != nil {
+ log.Debug(err.Error())
+ return err
+ }
+ if err := stream.Send(res.Data.(*api.Path)); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (s *Server) GetVrfs(arg *api.Arguments, stream api.Grpc_GetVrfsServer) error {
+ req := NewGrpcRequest(REQ_VRFS, "", bgp.RouteFamily(0), nil)
+ s.bgpServerCh <- req
+
+ for res := range req.ResponseCh {
+ if err := res.Err(); err != nil {
+ log.Debug(err.Error())
+ return err
+ }
+ if err := stream.Send(res.Data.(*api.Vrf)); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (s *Server) ModVrf(ctx context.Context, arg *api.ModVrfArguments) (*api.Error, error) {
+ none := &api.Error{}
+ req := NewGrpcRequest(REQ_VRF_MOD, "", bgp.RouteFamily(0), arg)
+ s.bgpServerCh <- req
+
+ res := <-req.ResponseCh
+ if err := res.Err(); err != nil {
+ return none, err
+ }
+ return none, nil
+}
+
type GrpcRequest struct {
RequestType int
RemoteAddr string
diff --git a/server/server.go b/server/server.go
index 4cabc7b9..56ef8c68 100644
--- a/server/server.go
+++ b/server/server.go
@@ -831,33 +831,31 @@ func getMacMobilityExtendedCommunity(etag uint32, mac net.HardwareAddr, evpnPath
return nil
}
-func (server *BgpServer) handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*table.Path {
- var isWithdraw bool
+func (server *BgpServer) handleModPathRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*table.Path {
var nlri bgp.AddrPrefixInterface
result := &GrpcResponse{}
pattr := make([]bgp.PathAttributeInterface, 0)
extcomms := make([]bgp.ExtendedCommunityInterface, 0)
+ var nexthop string
+ var rf bgp.RouteFamily
- args, ok := grpcReq.Data.(*api.ModPathArguments)
+ arg, ok := grpcReq.Data.(*api.ModPathArguments)
if !ok {
result.ResponseErr = fmt.Errorf("type assertion failed")
goto ERR
}
- if grpcReq.RequestType == REQ_GLOBAL_DELETE {
- isWithdraw = true
- }
- if len(args.RawNlri) > 0 {
+ if len(arg.RawNlri) > 0 {
nlri = &bgp.NLRInfo{}
- err := nlri.DecodeFromBytes(args.RawNlri)
+ err := nlri.DecodeFromBytes(arg.RawNlri)
if err != nil {
result.ResponseErr = err
goto ERR
}
}
- for _, attr := range args.RawPattrs {
+ for _, attr := range arg.RawPattrs {
p, err := bgp.GetPathAttribute(attr)
if err != nil {
result.ResponseErr = err
@@ -871,30 +869,70 @@ func (server *BgpServer) handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *
}
switch p.GetType() {
+ case bgp.BGP_ATTR_TYPE_NEXT_HOP:
+ nexthop = p.(*bgp.PathAttributeNextHop).Value.String()
case bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES:
value := p.(*bgp.PathAttributeExtendedCommunities).Value
if len(value) > 0 {
extcomms = append(extcomms, value...)
}
case bgp.BGP_ATTR_TYPE_MP_REACH_NLRI:
- value := p.(*bgp.PathAttributeMpReachNLRI).Value
- if len(value) != 1 {
+ mpreach := p.(*bgp.PathAttributeMpReachNLRI)
+ if len(mpreach.Value) != 1 {
result.ResponseErr = fmt.Errorf("include only one route in mp_reach_nlri")
goto ERR
}
- nlri = p.(*bgp.PathAttributeMpReachNLRI).Value[0]
- fallthrough
+ nlri = mpreach.Value[0]
+ nexthop = mpreach.Nexthop.String()
default:
pattr = append(pattr, p)
}
}
- if nlri == nil {
- result.ResponseErr = fmt.Errorf("no nlri included")
+ if nlri == nil || nexthop == "" {
+ result.ResponseErr = fmt.Errorf("not found nlri or nexthop")
goto ERR
}
- if bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI()) == bgp.RF_EVPN {
+ rf = bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI())
+
+ if arg.Resource == api.Resource_VRF {
+ vrfs := server.localRibMap[GLOBAL_RIB_NAME].rib.Vrfs
+ if _, ok := vrfs[arg.Name]; !ok {
+ result.ResponseErr = fmt.Errorf("vrf %s not found", arg.Name)
+ goto ERR
+ }
+ vrf := vrfs[arg.Name]
+
+ switch rf {
+ case bgp.RF_IPv4_UC:
+ n := nlri.(*bgp.NLRInfo)
+ nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(), vrf.Rd)
+ case bgp.RF_IPv6_UC:
+ n := nlri.(*bgp.IPv6AddrPrefix)
+ nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(), vrf.Rd)
+ case bgp.RF_EVPN:
+ n := nlri.(*bgp.EVPNNLRI)
+ switch n.RouteType {
+ case bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT:
+ n.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute).RD = vrf.Rd
+ case bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG:
+ n.RouteTypeData.(*bgp.EVPNMulticastEthernetTagRoute).RD = vrf.Rd
+ }
+ default:
+ result.ResponseErr = fmt.Errorf("unsupported route family for vrf: %s", rf)
+ goto ERR
+ }
+ extcomms = append(extcomms, vrf.ExportRt...)
+ }
+
+ if arg.Resource != api.Resource_VRF && rf == bgp.RF_IPv4_UC {
+ pattr = append(pattr, bgp.NewPathAttributeNextHop(nexthop))
+ } else {
+ pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI(nexthop, []bgp.AddrPrefixInterface{nlri}))
+ }
+
+ if rf == bgp.RF_EVPN {
evpnNlri := nlri.(*bgp.EVPNNLRI)
if evpnNlri.RouteType == bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
macIpAdv := evpnNlri.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute)
@@ -911,7 +949,7 @@ func (server *BgpServer) handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *
pattr = append(pattr, bgp.NewPathAttributeExtendedCommunities(extcomms))
}
- return []*table.Path{table.NewPath(peerInfo, nlri, isWithdraw, pattr, false, time.Now(), args.NoImplicitWithdraw)}
+ return []*table.Path{table.NewPath(peerInfo, nlri, arg.IsWithdraw, pattr, false, time.Now(), arg.NoImplicitWithdraw)}
ERR:
grpcReq.ResponseCh <- result
close(grpcReq.ResponseCh)
@@ -919,8 +957,123 @@ ERR:
}
+func (server *BgpServer) handleVrfMod(arg *api.ModVrfArguments) error {
+ vrfs := server.localRibMap[GLOBAL_RIB_NAME].rib.Vrfs
+ switch arg.Operation {
+ case api.Operation_ADD:
+ if _, ok := vrfs[arg.Vrf.Name]; ok {
+ return fmt.Errorf("vrf %s already exists", arg.Vrf.Name)
+ }
+ rd := bgp.GetRouteDistinguisher(arg.Vrf.Rd)
+ f := func(bufs [][]byte) ([]bgp.ExtendedCommunityInterface, error) {
+ ret := make([]bgp.ExtendedCommunityInterface, 0, len(bufs))
+ for _, rt := range bufs {
+ r, err := bgp.ParseExtended(rt)
+ if err != nil {
+ return nil, err
+ }
+ ret = append(ret, r)
+ }
+ return ret, nil
+ }
+ importRt, err := f(arg.Vrf.ImportRt)
+ if err != nil {
+ return err
+ }
+ exportRt, err := f(arg.Vrf.ImportRt)
+ if err != nil {
+ return err
+ }
+ log.WithFields(log.Fields{
+ "Topic": "Vrf",
+ "Key": arg.Vrf.Name,
+ "Rd": rd,
+ "ImportRt": importRt,
+ "ExportRt": exportRt,
+ }).Debugf("add vrf")
+ vrfs[arg.Vrf.Name] = &table.Vrf{
+ Name: arg.Vrf.Name,
+ Rd: rd,
+ ImportRt: importRt,
+ ExportRt: exportRt,
+ }
+ case api.Operation_DEL:
+ if _, ok := vrfs[arg.Vrf.Name]; !ok {
+ return fmt.Errorf("vrf %s not found", arg.Vrf.Name)
+ }
+ vrf := vrfs[arg.Vrf.Name]
+ log.WithFields(log.Fields{
+ "Topic": "Vrf",
+ "Key": vrf.Name,
+ "Rd": vrf.Rd,
+ "ImportRt": vrf.ImportRt,
+ "ExportRt": vrf.ExportRt,
+ }).Debugf("delete vrf")
+ delete(vrfs, arg.Vrf.Name)
+ default:
+ return fmt.Errorf("unknown operation:", arg.Operation)
+ }
+ return nil
+}
+
+func (server *BgpServer) handleVrfRequest(req *GrpcRequest) []*table.Path {
+ var msgs []*table.Path
+ result := &GrpcResponse{}
+
+ switch req.RequestType {
+ case REQ_VRF:
+ arg := req.Data.(*api.Arguments)
+ rib := server.localRibMap[GLOBAL_RIB_NAME].rib
+ vrfs := rib.Vrfs
+ if _, ok := vrfs[arg.Name]; !ok {
+ result.ResponseErr = fmt.Errorf("vrf %s not found", arg.Name)
+ break
+ }
+ var rf bgp.RouteFamily
+ switch req.RouteFamily {
+ case bgp.RF_IPv4_UC:
+ rf = bgp.RF_IPv4_VPN
+ case bgp.RF_IPv6_UC:
+ rf = bgp.RF_IPv6_VPN
+ case bgp.RF_EVPN:
+ rf = bgp.RF_EVPN
+ default:
+ result.ResponseErr = fmt.Errorf("unsupported route family: %s", req.RouteFamily)
+ break
+ }
+ for _, path := range rib.GetPathList(rf) {
+ ok := policy.CanImportToVrf(vrfs[arg.Name], path)
+ if !ok {
+ continue
+ }
+ req.ResponseCh <- &GrpcResponse{
+ Data: path.ToApiStruct(),
+ }
+ }
+ goto END
+ case REQ_VRFS:
+ vrfs := server.localRibMap[GLOBAL_RIB_NAME].rib.Vrfs
+ for _, vrf := range vrfs {
+ req.ResponseCh <- &GrpcResponse{
+ Data: vrf.ToApiStruct(),
+ }
+ }
+ goto END
+ case REQ_VRF_MOD:
+ arg := req.Data.(*api.ModVrfArguments)
+ result.ResponseErr = server.handleVrfMod(arg)
+ default:
+ result.ResponseErr = fmt.Errorf("unknown request type:", req.RequestType)
+ }
+
+ req.ResponseCh <- result
+END:
+ close(req.ResponseCh)
+ return msgs
+}
+
func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg {
- msgs := make([]*SenderMsg, 0)
+ var msgs []*SenderMsg
switch grpcReq.RequestType {
case REQ_GLOBAL_RIB:
@@ -933,14 +1086,14 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg {
}
close(grpcReq.ResponseCh)
- case REQ_GLOBAL_ADD, REQ_GLOBAL_DELETE:
+ case REQ_MOD_PATH:
pi := &table.PeerInfo{
AS: server.bgpConfig.Global.GlobalConfig.As,
LocalID: server.bgpConfig.Global.GlobalConfig.RouterId,
}
- pathList := server.handleGlobalRibRequest(grpcReq, pi)
+ pathList := server.handleModPathRequest(grpcReq, pi)
if len(pathList) > 0 {
- msgs = append(msgs, server.propagateUpdate("", false, pathList)...)
+ msgs = server.propagateUpdate("", false, pathList)
grpcReq.ResponseCh <- &GrpcResponse{}
close(grpcReq.ResponseCh)
}
@@ -1011,7 +1164,7 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg {
break
}
m := bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN, nil)
- msgs = append(msgs, newSenderMsg(peer, []*bgp.BGPMessage{m}))
+ msgs = []*SenderMsg{newSenderMsg(peer, []*bgp.BGPMessage{m})}
grpcReq.ResponseCh <- &GrpcResponse{}
close(grpcReq.ResponseCh)
@@ -1022,7 +1175,7 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg {
}
peer.fsm.idleHoldTime = peer.conf.Timers.TimersConfig.IdleHoldTimeAfterReset
m := bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_RESET, nil)
- msgs = append(msgs, newSenderMsg(peer, []*bgp.BGPMessage{m}))
+ msgs = []*SenderMsg{newSenderMsg(peer, []*bgp.BGPMessage{m})}
grpcReq.ResponseCh <- &GrpcResponse{}
close(grpcReq.ResponseCh)
@@ -1032,8 +1185,7 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg {
break
}
pathList := peer.adjRib.GetInPathList(grpcReq.RouteFamily)
- msgs = append(msgs, server.propagateUpdate(peer.conf.NeighborConfig.NeighborAddress.String(),
- peer.isRouteServerClient(), pathList)...)
+ msgs = server.propagateUpdate(peer.conf.NeighborConfig.NeighborAddress.String(), peer.isRouteServerClient(), pathList)
if grpcReq.RequestType == REQ_NEIGHBOR_SOFT_RESET_IN {
grpcReq.ResponseCh <- &GrpcResponse{}
@@ -1048,7 +1200,7 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg {
}
pathList := peer.adjRib.GetOutPathList(grpcReq.RouteFamily)
msgList := table.CreateUpdateMsgFromPaths(pathList)
- msgs = append(msgs, newSenderMsg(peer, msgList))
+ msgs = []*SenderMsg{newSenderMsg(peer, msgList)}
grpcReq.ResponseCh <- &GrpcResponse{}
close(grpcReq.ResponseCh)
@@ -1239,6 +1391,11 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg {
server.handleMrt(grpcReq)
case REQ_RPKI:
server.roaClient.handleGRPC(grpcReq)
+ case REQ_VRF, REQ_VRFS, REQ_VRF_MOD:
+ pathList := server.handleVrfRequest(grpcReq)
+ if len(pathList) > 0 {
+ msgs = server.propagateUpdate("", false, pathList)
+ }
default:
errmsg := fmt.Errorf("Unknown request type: %v", grpcReq.RequestType)
result := &GrpcResponse{