diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2015-05-01 10:06:42 +0000 |
---|---|---|
committer | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2015-05-01 10:16:09 +0000 |
commit | 232b30117c8eafc5cae7aec81ce9fafe742bdd4b (patch) | |
tree | 235342a7345b6034f02a1864485a4c96e25d3ea2 | |
parent | cea5941db2dd9268ad35b5f494480350d747d404 (diff) |
table: add support for route target constraint nlri
add rtc route
$ gobgp global rib add 65000 77 -a rtc
check it
$ gobgp global rib -a rtc
Network Next Hop AS_PATH Age Attrs
*> 65001:65000:75 0.0.0.0 [65001] 00:15:35 [{Origin: IGP}]
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r-- | config/default.go | 1 | ||||
-rw-r--r-- | gobgp/main.go | 29 | ||||
-rw-r--r-- | server/grpc_server.go | 2 | ||||
-rw-r--r-- | server/peer.go | 27 | ||||
-rw-r--r-- | table/destination.go | 12 | ||||
-rw-r--r-- | table/message.go | 2 | ||||
-rw-r--r-- | table/path.go | 20 | ||||
-rw-r--r-- | table/table.go | 19 | ||||
-rw-r--r-- | table/table_manager.go | 2 |
9 files changed, 113 insertions, 1 deletions
diff --git a/config/default.go b/config/default.go index 2f1bedda..6e08a70e 100644 --- a/config/default.go +++ b/config/default.go @@ -35,6 +35,7 @@ func SetDefaultConfigValues(md toml.MetaData, bt *Bgp) error { AfiSafi{AfiSafiName: "ipv6-unicast"}, AfiSafi{AfiSafiName: "l2vpn-evpn"}, AfiSafi{AfiSafiName: "encap"}, + AfiSafi{AfiSafiName: "rtc"}, } } diff --git a/gobgp/main.go b/gobgp/main.go index 634e95be..80bf6865 100644 --- a/gobgp/main.go +++ b/gobgp/main.go @@ -237,6 +237,8 @@ func checkAddressFamily() (*api.AddressFamily, error) { rf = api.AF_EVPN case "encap": rf = api.AF_ENCAP + case "rtc": + rf = api.AF_RTC case "": e = fmt.Errorf("address family is not specified") default: @@ -409,6 +411,33 @@ func modPath(modtype string, eArgs []string) error { path.Attrs = append(path.Attrs, attr) } + case api.AF_RTC: + if !(len(eArgs) == 3 && eArgs[0] == "default") && len(eArgs) < 4 { + return fmt.Errorf("usage: global rib add <asn> <local admin> -a rtc") + } + var asn, admin int + + if eArgs[0] != "default" { + asn, err = strconv.Atoi(eArgs[0]) + if err != nil { + return fmt.Errorf("invalid asn: %s", eArgs[0]) + } + admin, err = strconv.Atoi(eArgs[1]) + if err != nil { + return fmt.Errorf("invalid local admin: %s", eArgs[1]) + } + } + path.Nlri = &api.Nlri{ + Af: rf, + RtNlri: &api.RTNlri{ + Target: &api.ExtendedCommunity{ + Type: api.EXTENDED_COMMUNITIE_TYPE_TWO_OCTET_AS_SPECIFIC, + Subtype: api.EXTENDED_COMMUNITIE_SUBTYPE_ROUTE_TARGET, + Asn: uint32(asn), + LocalAdmin: uint32(admin), + }, + }, + } } switch modtype { case "add": diff --git a/server/grpc_server.go b/server/grpc_server.go index 01acaf3d..c218a4ac 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -56,6 +56,8 @@ func convertAf2Rf(af *api.AddressFamily) (bgp.RouteFamily, error) { return bgp.RF_EVPN, nil } else if af.Equal(api.AF_ENCAP) { return bgp.RF_ENCAP, nil + } else if af.Equal(api.AF_RTC) { + return bgp.RF_RTC_UC, nil } return bgp.RouteFamily(0), fmt.Errorf("unsupported address family: %v", af) diff --git a/server/peer.go b/server/peer.go index 64235613..7af2653e 100644 --- a/server/peer.go +++ b/server/peer.go @@ -422,6 +422,33 @@ func (peer *Peer) handleGrpc(grpcReq *GrpcRequest) { } }(path.Attrs) + case bgp.RF_RTC_UC: + var ec bgp.ExtendedCommunityInterface + target := path.Nlri.RtNlri.Target + ec_type := target.Type + ec_subtype := target.Subtype + switch ec_type { + case api.EXTENDED_COMMUNITIE_TYPE_TWO_OCTET_AS_SPECIFIC: + if target.Asn == 0 && target.LocalAdmin == 0 { + break + } + ec = &bgp.TwoOctetAsSpecificExtended{ + SubType: bgp.ExtendedCommunityAttrSubType(ec_subtype), + AS: uint16(target.Asn), + LocalAdmin: target.LocalAdmin, + IsTransitive: true, + } + default: + result.ResponseErr = fmt.Errorf("Invalid endpoint ip address: %s", path.Nlri.Prefix) + grpcReq.ResponseCh <- result + close(grpcReq.ResponseCh) + return + } + + nlri = bgp.NewRouteTargetMembershipNLRI(peer.globalConfig.As, ec) + + pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("0.0.0.0", []bgp.AddrPrefixInterface{nlri})) + default: result.ResponseErr = fmt.Errorf("Unsupported address family: %s", rf) grpcReq.ResponseCh <- result diff --git a/table/destination.go b/table/destination.go index bf4afe63..a01c6e04 100644 --- a/table/destination.go +++ b/table/destination.go @@ -1043,3 +1043,15 @@ func NewEncapDestination(nlri bgp.AddrPrefixInterface) *EncapDestination { DestinationDefault: d, } } + +type RouteTargetDestination struct { + *DestinationDefault +} + +func NewRouteTargetDestination(nlri bgp.AddrPrefixInterface) *RouteTargetDestination { + d := NewDestinationDefault(nlri) + d.ROUTE_FAMILY = bgp.RF_RTC_UC + return &RouteTargetDestination{ + DestinationDefault: d, + } +} diff --git a/table/message.go b/table/message.go index 70e2ffcd..5b444ce0 100644 --- a/table/message.go +++ b/table/message.go @@ -155,7 +155,7 @@ func createUpdateMsgFromPath(path Path, msg *bgp.BGPMessage) *bgp.BGPMessage { return bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{}, pathAttrs, []bgp.NLRInfo{*nlri}) } } - } else if rf == bgp.RF_IPv6_UC || rf == bgp.RF_EVPN || rf == bgp.RF_ENCAP { + } else if rf == bgp.RF_IPv6_UC || rf == bgp.RF_EVPN || rf == bgp.RF_ENCAP || rf == bgp.RF_RTC_UC { if path.IsWithdraw() { if msg != nil { idx, _ := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_UNREACH_NLRI) diff --git a/table/path.go b/table/path.go index 88765d44..0d52d343 100644 --- a/table/path.go +++ b/table/path.go @@ -384,6 +384,9 @@ func CreatePath(source *PeerInfo, nlri bgp.AddrPrefixInterface, attrs []bgp.Path case bgp.RF_ENCAP: log.Debugf("CreatePath RouteFamily : %s", bgp.RF_ENCAP.String()) path = NewEncapPath(source, nlri, isWithdraw, attrs, false, now) + case bgp.RF_RTC_UC: + log.Debugf("CreatePath RouteFamily : %s", bgp.RF_RTC_UC) + path = NewRouteTargetPath(source, nlri, isWithdraw, attrs, false, now) default: return path, fmt.Errorf("Unsupported RouteFamily: %s", rf) } @@ -538,3 +541,20 @@ func (p *EncapPath) setPathDefault(pd *PathDefault) { func (p *EncapPath) getPathDefault() *PathDefault { return p.PathDefault } + +type RouteTargetPath struct { + *PathDefault +} + +func NewRouteTargetPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, attrs []bgp.PathAttributeInterface, medSetByTargetNeighbor bool, now time.Time) *RouteTargetPath { + return &RouteTargetPath{ + PathDefault: NewPathDefault(bgp.RF_RTC_UC, source, nlri, isWithdraw, attrs, medSetByTargetNeighbor, now), + } +} + +func (p *RouteTargetPath) setPathDefault(pd *PathDefault) { + p.PathDefault = pd +} +func (p *RouteTargetPath) getPathDefault() *PathDefault { + return p.PathDefault +} diff --git a/table/table.go b/table/table.go index b1434732..22499f5a 100644 --- a/table/table.go +++ b/table/table.go @@ -353,3 +353,22 @@ func (t *EncapTable) createDest(nlri bgp.AddrPrefixInterface) Destination { func (t *EncapTable) tableKey(nlri bgp.AddrPrefixInterface) string { return nlri.String() } + +type RouteTargetTable struct { + *TableDefault +} + +func NewRouteTargetTable() *RouteTargetTable { + routeTargetTable := &RouteTargetTable{} + routeTargetTable.TableDefault = NewTableDefault(0) + routeTargetTable.TableDefault.ROUTE_FAMILY = bgp.RF_RTC_UC + return routeTargetTable +} + +func (t *RouteTargetTable) createDest(nlri bgp.AddrPrefixInterface) Destination { + return Destination(NewRouteTargetDestination(nlri)) +} + +func (t *RouteTargetTable) tableKey(nlri bgp.AddrPrefixInterface) string { + return nlri.String() +} diff --git a/table/table_manager.go b/table/table_manager.go index d4da1735..8d3b18ca 100644 --- a/table/table_manager.go +++ b/table/table_manager.go @@ -131,6 +131,8 @@ func NewTableManager(owner string, rfList []bgp.RouteFamily) *TableManager { t.Tables[bgp.RF_EVPN] = NewEVPNTable(0) case bgp.RF_ENCAP: t.Tables[bgp.RF_ENCAP] = NewEncapTable() + case bgp.RF_RTC_UC: + t.Tables[bgp.RF_RTC_UC] = NewRouteTargetTable() } } t.owner = owner |