diff options
Diffstat (limited to 'server/peer.go')
-rw-r--r-- | server/peer.go | 243 |
1 files changed, 124 insertions, 119 deletions
diff --git a/server/peer.go b/server/peer.go index 8c62d105..194998fb 100644 --- a/server/peer.go +++ b/server/peer.go @@ -288,79 +288,93 @@ func (peer *Peer) sendMessages(msgs []*bgp.BGPMessage) { } } -func (peer *Peer) handleREST(restReq *api.RestRequest) { - result := &api.RestResponse{} - switch restReq.RequestType { +func (peer *Peer) handleGrpc(grpcReq *api.GrpcRequest) { + result := &api.GrpcResponse{} + switch grpcReq.RequestType { case api.REQ_GLOBAL_ADD, api.REQ_GLOBAL_DELETE: - rf := restReq.RouteFamily - prefixes := restReq.Data["prefix"].([]string) + rf := grpcReq.RouteFamily + prefix := grpcReq.Data["prefix"].(string) var isWithdraw bool - if restReq.RequestType == api.REQ_GLOBAL_DELETE { + if grpcReq.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()), - } + 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})) - 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()) + if rf == bgp.RF_IPv4_UC { + ip, net, _ := net.ParseCIDR(prefix) + if ip.To4() == nil { + result.ResponseErr = fmt.Errorf("Invalid ipv4 prefix: %s", prefix) + grpcReq.ResponseCh <- result + close(grpcReq.ResponseCh) + return + } + ones, _ := net.Mask.Size() + nlri = &bgp.NLRInfo{ + IPAddrPrefix: *bgp.NewIPAddrPrefix(uint8(ones), ip.String()), + } - pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("::", []bgp.AddrPrefixInterface{nlri})) + pattr = append(pattr, bgp.NewPathAttributeNextHop("0.0.0.0")) - } else { - result.ResponseErr = fmt.Errorf("Unsupported address family: %s", rf) - restReq.ResponseCh <- result - close(restReq.ResponseCh) + } 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) + grpcReq.ResponseCh <- result + close(grpcReq.ResponseCh) return } + ones, _ := net.Mask.Size() + nlri = bgp.NewIPv6AddrPrefix(uint8(ones), ip.String()) - p := table.CreatePath(peer.peerInfo, nlri, pattr, isWithdraw, time.Now()) - pList = append(pList, p) + pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("::", []bgp.AddrPrefixInterface{nlri})) + + } else { + result.ResponseErr = fmt.Errorf("Unsupported address family: %s", rf) + grpcReq.ResponseCh <- result + close(grpcReq.ResponseCh) + return } + p := table.CreatePath(peer.peerInfo, nlri, pattr, isWithdraw, time.Now()) + pm := &peerMsg{ msgType: PEER_MSG_PATH, - msgData: pList, + msgData: []table.Path{p}, } 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)) - if peer.fsm.adminState != ADMIN_STATE_DOWN { - if t, ok := peer.rib.Tables[restReq.RouteFamily]; ok { - j, _ = json.Marshal(t) + if peer.fsm.adminState == ADMIN_STATE_DOWN { + close(grpcReq.ResponseCh) + return + } + if t, ok := peer.rib.Tables[grpcReq.RouteFamily]; ok { + type table struct { + Destinations []*api.Destination + } + var tt table + j, _ := json.Marshal(t) + err := json.Unmarshal(j, &tt) + if err != nil { + result := &api.GrpcResponse{} + result.ResponseErr = err + grpcReq.ResponseCh <- result + close(grpcReq.ResponseCh) + return + } + for _, dst := range tt.Destinations { + result := &api.GrpcResponse{} + result.Data = dst + grpcReq.ResponseCh <- result } + close(grpcReq.ResponseCh) + return } - result.Data = j case api.REQ_NEIGHBOR_SHUTDOWN: peer.outgoing <- bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN, nil) case api.REQ_NEIGHBOR_RESET: @@ -368,40 +382,55 @@ func (peer *Peer) handleREST(restReq *api.RestRequest) { peer.outgoing <- bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_RESET, nil) case api.REQ_NEIGHBOR_SOFT_RESET, api.REQ_NEIGHBOR_SOFT_RESET_IN: // soft-reconfiguration inbound - peer.sendPathsToSiblings(peer.adjRib.GetInPathList(restReq.RouteFamily)) - if restReq.RequestType == api.REQ_NEIGHBOR_SOFT_RESET_IN { + peer.sendPathsToSiblings(peer.adjRib.GetInPathList(grpcReq.RouteFamily)) + if grpcReq.RequestType == api.REQ_NEIGHBOR_SOFT_RESET_IN { break } fallthrough case api.REQ_NEIGHBOR_SOFT_RESET_OUT: - pathList := peer.adjRib.GetOutPathList(restReq.RouteFamily) + pathList := peer.adjRib.GetOutPathList(grpcReq.RouteFamily) peer.sendMessages(table.CreateUpdateMsgFromPaths(pathList)) case api.REQ_ADJ_RIB_IN, api.REQ_ADJ_RIB_OUT: - rf := restReq.RouteFamily - if restReq.RequestType == api.REQ_ADJ_RIB_IN { - paths := peer.adjRib.GetInPathList(rf) - j, _ := json.Marshal(paths) - result.Data = j + rf := grpcReq.RouteFamily + var paths []table.Path + + if grpcReq.RequestType == api.REQ_ADJ_RIB_IN { + paths = peer.adjRib.GetInPathList(rf) log.Debugf("RouteFamily=%v adj-rib-in found : %d", rf.String(), len(paths)) } else { - paths := peer.adjRib.GetOutPathList(rf) - j, _ := json.Marshal(paths) - result.Data = j + paths = peer.adjRib.GetOutPathList(rf) log.Debugf("RouteFamily=%v adj-rib-out found : %d", rf.String(), len(paths)) } + + for _, p := range paths { + result := &api.GrpcResponse{} + path := &api.Path{} + j, _ := json.Marshal(p) + err := json.Unmarshal(j, path) + if err != nil { + result.ResponseErr = err + } else { + result.Data = path + } + grpcReq.ResponseCh <- result + } + close(grpcReq.ResponseCh) + return case api.REQ_NEIGHBOR_ENABLE, api.REQ_NEIGHBOR_DISABLE: - r := make(map[string]string) - if restReq.RequestType == api.REQ_NEIGHBOR_ENABLE { + var err api.Error + if grpcReq.RequestType == api.REQ_NEIGHBOR_ENABLE { select { case peer.fsm.adminStateCh <- ADMIN_STATE_UP: log.WithFields(log.Fields{ "Topic": "Peer", "Key": peer.peerConfig.NeighborAddress, }).Debug("ADMIN_STATE_UP requested") - r["result"] = "ADMIN_STATE_UP" + err.Code = api.Error_SUCCESS + err.Msg = "ADMIN_STATE_UP" default: log.Warning("previous request is still remaining. : ", peer.peerConfig.NeighborAddress) - r["result"] = "previous request is still remaining" + err.Code = api.Error_FAIL + err.Msg = "previous request is still remaining" } } else { select { @@ -410,17 +439,18 @@ func (peer *Peer) handleREST(restReq *api.RestRequest) { "Topic": "Peer", "Key": peer.peerConfig.NeighborAddress, }).Debug("ADMIN_STATE_DOWN requested") - r["result"] = "ADMIN_STATE_DOWN" + err.Code = api.Error_SUCCESS + err.Msg = "ADMIN_STATE_DOWN" default: log.Warning("previous request is still remaining. : ", peer.peerConfig.NeighborAddress) - r["result"] = "previous request is still remaining" + err.Code = api.Error_FAIL + err.Msg = "previous request is still remaining" } } - j, _ := json.Marshal(r) - result.Data = j + result.Data = err } - restReq.ResponseCh <- result - close(restReq.ResponseCh) + grpcReq.ResponseCh <- result + close(grpcReq.ResponseCh) } func (peer *Peer) sendUpdateMsgFromPaths(pList []table.Path) { @@ -626,7 +656,7 @@ func (peer *Peer) handleServerMsg(m *serverMsg) { log.Warning("can not find peer: ", d.Address.String()) } case SRV_MSG_API: - peer.handleREST(m.msgData.(*api.RestRequest)) + peer.handleGrpc(m.msgData.(*api.GrpcRequest)) case SRV_MSG_POLICY_UPDATED: log.Debug("policy updated") d := m.msgData.(map[string]*policy.Policy) @@ -797,30 +827,29 @@ func (peer *Peer) PassConn(conn *net.TCPConn) { } func (peer *Peer) MarshalJSON() ([]byte, error) { + p, err := peer.ToGrpc() + if err != nil { + return nil, err + } + return json.Marshal(p) +} + +func (peer *Peer) ToGrpc() (*api.Peer, error) { f := peer.fsm c := f.peerConfig - p := make(map[string]interface{}) - capList := make([]int, 0) + capList := make([]int32, 0, len(peer.capMap)) for k, _ := range peer.capMap { - capList = append(capList, int(k)) + capList = append(capList, int32(k)) } - p["conf"] = struct { - RemoteIP string `json:"remote_ip"` - Id string `json:"id"` - RemoteAS uint32 `json:"remote_as"` - CapRefresh bool `json:"cap_refresh"` - CapEnhancedRefresh bool `json:"cap_enhanced_refresh"` - RemoteCap []int - LocalCap []int - }{ - RemoteIP: c.NeighborAddress.String(), + conf := &api.PeerConf{ + RemoteIp: c.NeighborAddress.String(), Id: peer.peerInfo.ID.To4().String(), - RemoteAS: c.PeerAs, + RemoteAs: c.PeerAs, RemoteCap: capList, - LocalCap: []int{int(bgp.BGP_CAP_MULTIPROTOCOL), int(bgp.BGP_CAP_ROUTE_REFRESH), int(bgp.BGP_CAP_FOUR_OCTET_AS_NUMBER)}, + LocalCap: []int32{int32(bgp.BGP_CAP_MULTIPROTOCOL), int32(bgp.BGP_CAP_ROUTE_REFRESH), int32(bgp.BGP_CAP_FOUR_OCTET_AS_NUMBER)}, } s := c.BgpNeighborCommonState @@ -845,34 +874,7 @@ func (peer *Peer) MarshalJSON() ([]byte, error) { } } - p["info"] = struct { - BgpState string `json:"bgp_state"` - AdminState string - FsmEstablishedTransitions uint32 `json:"fsm_established_transitions"` - TotalMessageOut uint32 `json:"total_message_out"` - TotalMessageIn uint32 `json:"total_message_in"` - UpdateMessageOut uint32 `json:"update_message_out"` - UpdateMessageIn uint32 `json:"update_message_in"` - KeepAliveMessageOut uint32 `json:"keepalive_message_out"` - KeepAliveMessageIn uint32 `json:"keepalive_message_in"` - OpenMessageOut uint32 `json:"open_message_out"` - OpenMessageIn uint32 `json:"open_message_in"` - NotificationOut uint32 `json:"notification_out"` - NotificationIn uint32 `json:"notification_in"` - RefreshMessageOut uint32 `json:"refresh_message_out"` - RefreshMessageIn uint32 `json:"refresh_message_in"` - DiscardedOut uint32 - DiscardedIn uint32 - Uptime int64 `json:"uptime"` - Downtime int64 `json:"downtime"` - LastError string `json:"last_error"` - Received uint32 - Accepted uint32 - Advertized uint32 - OutQ int - Flops uint32 - }{ - + info := &api.PeerInfo{ BgpState: f.state.String(), AdminState: f.adminState.String(), FsmEstablishedTransitions: s.EstablishedCount, @@ -895,9 +897,12 @@ func (peer *Peer) MarshalJSON() ([]byte, error) { Received: received, Accepted: accepted, Advertized: advertized, - OutQ: len(peer.outgoing), + OutQ: uint32(len(peer.outgoing)), Flops: s.Flops, } - return json.Marshal(p) + return &api.Peer{ + Conf: conf, + Info: info, + }, nil } |