diff options
-rw-r--r-- | api/gobgp.pb.go | 10 | ||||
-rw-r--r-- | api/gobgp.proto | 6 | ||||
-rw-r--r-- | gobgp/cmd/global.go | 2 | ||||
-rw-r--r-- | gobgp/cmd/mrt.go | 26 | ||||
-rw-r--r-- | server/server.go | 219 |
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) |