summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--api/gobgp.pb.go10
-rw-r--r--api/gobgp.proto6
-rw-r--r--gobgp/cmd/global.go2
-rw-r--r--gobgp/cmd/mrt.go26
-rw-r--r--server/server.go219
5 files changed, 139 insertions, 124 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go
index 550863dc..5f6ae14b 100644
--- a/api/gobgp.pb.go
+++ b/api/gobgp.pb.go
@@ -170,18 +170,16 @@ func (*Arguments) ProtoMessage() {}
type ModPathArguments struct {
Resource Resource `protobuf:"varint,1,opt,name=resource,enum=api.Resource" json:"resource,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
- Path *Path `protobuf:"bytes,3,opt,name=path" json:"path,omitempty"`
- Asn uint32 `protobuf:"varint,4,opt,name=asn" json:"asn,omitempty"`
- Id string `protobuf:"bytes,5,opt,name=id" json:"id,omitempty"`
+ Paths []*Path `protobuf:"bytes,3,rep,name=paths" json:"paths,omitempty"`
}
func (m *ModPathArguments) Reset() { *m = ModPathArguments{} }
func (m *ModPathArguments) String() string { return proto.CompactTextString(m) }
func (*ModPathArguments) ProtoMessage() {}
-func (m *ModPathArguments) GetPath() *Path {
+func (m *ModPathArguments) GetPaths() []*Path {
if m != nil {
- return m.Path
+ return m.Paths
}
return nil
}
@@ -249,6 +247,8 @@ type Path struct {
Validation int32 `protobuf:"varint,6,opt,name=validation" json:"validation,omitempty"`
NoImplicitWithdraw bool `protobuf:"varint,7,opt,name=no_implicit_withdraw" json:"no_implicit_withdraw,omitempty"`
Rf uint32 `protobuf:"varint,8,opt,name=rf" json:"rf,omitempty"`
+ SourceAsn uint32 `protobuf:"varint,9,opt,name=source_asn" json:"source_asn,omitempty"`
+ SourceId string `protobuf:"bytes,10,opt,name=source_id" json:"source_id,omitempty"`
}
func (m *Path) Reset() { *m = Path{} }
diff --git a/api/gobgp.proto b/api/gobgp.proto
index ba39250c..6d3f6f74 100644
--- a/api/gobgp.proto
+++ b/api/gobgp.proto
@@ -63,9 +63,7 @@ message Arguments {
message ModPathArguments {
Resource resource = 1;
string name = 2;
- Path path = 3;
- uint32 asn = 4;
- string id = 5;
+ repeated Path paths = 3;
}
message PolicyArguments {
@@ -118,6 +116,8 @@ message Path {
int32 validation = 6;
bool no_implicit_withdraw = 7;
uint32 rf = 8;
+ uint32 source_asn = 9;
+ string source_id = 10;
}
message Destination {
diff --git a/gobgp/cmd/global.go b/gobgp/cmd/global.go
index d351148d..bebe6358 100644
--- a/gobgp/cmd/global.go
+++ b/gobgp/cmd/global.go
@@ -547,7 +547,7 @@ func modPath(resource api.Resource, name, modtype string, args []string) error {
arg := &api.ModPathArguments{
Resource: resource,
Name: name,
- Path: path,
+ Paths: []*api.Path{path},
}
stream, err := client.ModPath(context.Background())
diff --git a/gobgp/cmd/mrt.go b/gobgp/cmd/mrt.go
index fd598aa4..ef99eaba 100644
--- a/gobgp/cmd/mrt.go
+++ b/gobgp/cmd/mrt.go
@@ -270,17 +270,21 @@ func injectMrt(r string, filename string, count int) error {
rib := msg.Body.(*bgp.Rib)
nlri := rib.Prefix
- for _, e := range rib.Entries {
- path := &api.Path{
- Pattrs: make([][]byte, 0),
- NoImplicitWithdraw: true,
- }
+ paths := make([]*api.Path, 0, len(rib.Entries))
+ for _, e := range rib.Entries {
if len(peers) < int(e.PeerIndex) {
fmt.Printf("invalid peer index: %d (PEER_INDEX_TABLE has only %d peers)\n", e.PeerIndex, len(peers))
os.Exit(1)
}
+ path := &api.Path{
+ Pattrs: make([][]byte, 0),
+ NoImplicitWithdraw: true,
+ SourceAsn: peers[e.PeerIndex].AS,
+ SourceId: peers[e.PeerIndex].BgpId.String(),
+ }
+
if rf == bgp.RF_IPv4_UC {
path.Nlri, _ = nlri.Serialize()
}
@@ -293,12 +297,12 @@ func injectMrt(r string, filename string, count int) error {
path.Pattrs = append(path.Pattrs, b)
}
- ch <- &api.ModPathArguments{
- Resource: resource,
- Path: path,
- Asn: peers[e.PeerIndex].AS,
- Id: peers[e.PeerIndex].BgpId.String(),
- }
+ paths = append(paths, path)
+ }
+
+ ch <- &api.ModPathArguments{
+ Resource: resource,
+ Paths: paths,
}
idx += 1
diff --git a/server/server.go b/server/server.go
index c1ba5206..1699a5cb 100644
--- a/server/server.go
+++ b/server/server.go
@@ -966,142 +966,153 @@ func (server *BgpServer) handleModPathRequest(grpcReq *GrpcRequest) []*table.Pat
var nlri bgp.AddrPrefixInterface
result := &GrpcResponse{}
- pattr := make([]bgp.PathAttributeInterface, 0)
- extcomms := make([]bgp.ExtendedCommunityInterface, 0)
+ var pattr []bgp.PathAttributeInterface
+ var extcomms []bgp.ExtendedCommunityInterface
var nexthop string
var rf bgp.RouteFamily
+ var paths []*table.Path
var path *api.Path
- seen := make(map[bgp.BGPAttrType]bool)
var pi *table.PeerInfo
-
arg, ok := grpcReq.Data.(*api.ModPathArguments)
if !ok {
result.ResponseErr = fmt.Errorf("type assertion failed")
goto ERR
}
- if arg.Asn != 0 {
- pi = &table.PeerInfo{
- AS: arg.Asn,
- LocalID: net.ParseIP(arg.Id),
- }
- } else {
- pi = &table.PeerInfo{
- AS: server.bgpConfig.Global.GlobalConfig.As,
- LocalID: server.bgpConfig.Global.GlobalConfig.RouterId,
- }
- }
- path = arg.Path
- if len(path.Nlri) > 0 {
- nlri = &bgp.IPAddrPrefix{}
- err := nlri.DecodeFromBytes(path.Nlri)
- if err != nil {
- result.ResponseErr = err
- goto ERR
- }
- }
+ paths = make([]*table.Path, 0, len(arg.Paths))
- for _, attr := range path.Pattrs {
- p, err := bgp.GetPathAttribute(attr)
- if err != nil {
- result.ResponseErr = err
- goto ERR
- }
+ for _, path = range arg.Paths {
+ seen := make(map[bgp.BGPAttrType]bool)
- err = p.DecodeFromBytes(attr)
- if err != nil {
- result.ResponseErr = err
- goto ERR
- }
+ pattr = make([]bgp.PathAttributeInterface, 0)
+ extcomms = make([]bgp.ExtendedCommunityInterface, 0)
- if _, ok := seen[p.GetType()]; !ok {
- seen[p.GetType()] = true
+ if path.SourceAsn != 0 {
+ pi = &table.PeerInfo{
+ AS: path.SourceAsn,
+ LocalID: net.ParseIP(path.SourceId),
+ }
} else {
- result.ResponseErr = fmt.Errorf("the path attribute apears twice. Type : " + strconv.Itoa(int(p.GetType())))
- goto ERR
+ pi = &table.PeerInfo{
+ AS: server.bgpConfig.Global.GlobalConfig.As,
+ LocalID: server.bgpConfig.Global.GlobalConfig.RouterId,
+ }
}
- 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:
- mpreach := p.(*bgp.PathAttributeMpReachNLRI)
- if len(mpreach.Value) != 1 {
- result.ResponseErr = fmt.Errorf("include only one route in mp_reach_nlri")
+
+ if len(path.Nlri) > 0 {
+ nlri = &bgp.IPAddrPrefix{}
+ err := nlri.DecodeFromBytes(path.Nlri)
+ if err != nil {
+ result.ResponseErr = err
goto ERR
}
- nlri = mpreach.Value[0]
- nexthop = mpreach.Nexthop.String()
- default:
- pattr = append(pattr, p)
}
- }
- if nlri == nil || nexthop == "" {
- result.ResponseErr = fmt.Errorf("not found nlri or nexthop")
- goto ERR
- }
+ for _, attr := range path.Pattrs {
+ p, err := bgp.GetPathAttribute(attr)
+ if err != nil {
+ result.ResponseErr = err
+ goto ERR
+ }
+
+ err = p.DecodeFromBytes(attr)
+ if err != nil {
+ result.ResponseErr = err
+ goto ERR
+ }
- rf = bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI())
+ if _, ok := seen[p.GetType()]; !ok {
+ seen[p.GetType()] = true
+ } else {
+ result.ResponseErr = fmt.Errorf("the path attribute apears twice. Type : " + strconv.Itoa(int(p.GetType())))
+ goto ERR
+ }
+ 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:
+ mpreach := p.(*bgp.PathAttributeMpReachNLRI)
+ if len(mpreach.Value) != 1 {
+ result.ResponseErr = fmt.Errorf("include only one route in mp_reach_nlri")
+ goto ERR
+ }
+ nlri = mpreach.Value[0]
+ nexthop = mpreach.Nexthop.String()
+ default:
+ pattr = append(pattr, p)
+ }
+ }
- 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)
+ if nlri == nil || nexthop == "" {
+ result.ResponseErr = fmt.Errorf("not found nlri or nexthop")
goto ERR
}
- vrf := vrfs[arg.Name]
- switch rf {
- case bgp.RF_IPv4_UC:
- n := nlri.(*bgp.IPAddrPrefix)
- 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
+ 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
}
- default:
- result.ResponseErr = fmt.Errorf("unsupported route family for vrf: %s", rf)
- goto ERR
+ vrf := vrfs[arg.Name]
+
+ switch rf {
+ case bgp.RF_IPv4_UC:
+ n := nlri.(*bgp.IPAddrPrefix)
+ 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...)
}
- 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)
- etag := macIpAdv.ETag
- mac := macIpAdv.MacAddress
- paths := server.localRibMap[GLOBAL_RIB_NAME].rib.GetBestPathList(bgp.RF_EVPN)
- if m := getMacMobilityExtendedCommunity(etag, mac, paths); m != nil {
- extcomms = append(extcomms, m)
+ 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)
+ etag := macIpAdv.ETag
+ mac := macIpAdv.MacAddress
+ paths := server.localRibMap[GLOBAL_RIB_NAME].rib.GetBestPathList(bgp.RF_EVPN)
+ if m := getMacMobilityExtendedCommunity(etag, mac, paths); m != nil {
+ extcomms = append(extcomms, m)
+ }
}
}
- }
- if len(extcomms) > 0 {
- pattr = append(pattr, bgp.NewPathAttributeExtendedCommunities(extcomms))
+ if len(extcomms) > 0 {
+ pattr = append(pattr, bgp.NewPathAttributeExtendedCommunities(extcomms))
+ }
+
+ paths = append(paths, table.NewPath(pi, nlri, path.IsWithdraw, pattr, false, time.Now(), path.NoImplicitWithdraw))
+
}
- return []*table.Path{table.NewPath(pi, nlri, path.IsWithdraw, pattr, false, time.Now(), path.NoImplicitWithdraw)}
+ return paths
ERR:
grpcReq.ResponseCh <- result
close(grpcReq.ResponseCh)