summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2015-08-03 14:04:34 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-08-03 21:59:39 +0900
commit84dd9d6983564b37b7e146264c44da6874a08cf4 (patch)
tree1dcda7f9b8164aec87c0fc6c889f8499c6fd8492
parentd895c87c741084b4469bb260e3ef94f7793a8f92 (diff)
api: use serialized buffer rather than protobuf struct to add paths
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r--api/gobgp.pb.go13
-rw-r--r--api/gobgp.proto4
-rw-r--r--gobgp/global.go254
-rw-r--r--packet/bgp.go36
-rw-r--r--server/grpc_server.go8
-rw-r--r--server/server.go228
6 files changed, 195 insertions, 348 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go
index 901abcad..2f5a50fa 100644
--- a/api/gobgp.pb.go
+++ b/api/gobgp.pb.go
@@ -590,21 +590,16 @@ func (m *Arguments) GetAf() *AddressFamily {
}
type ModPathArguments struct {
- Resource Resource `protobuf:"varint,1,opt,name=resource,enum=api.Resource" json:"resource,omitempty"`
- Path *Path `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"`
+ Resource Resource `protobuf:"varint,1,opt,name=resource,enum=api.Resource" json:"resource,omitempty"`
+ IsWithdraw bool `protobuf:"varint,2,opt,name=is_withdraw" json:"is_withdraw,omitempty"`
+ RawNlri []byte `protobuf:"bytes,3,opt,name=raw_nlri,proto3" json:"raw_nlri,omitempty"`
+ RawPattrs [][]byte `protobuf:"bytes,4,rep,name=raw_pattrs,proto3" json:"raw_pattrs,omitempty"`
}
func (m *ModPathArguments) Reset() { *m = ModPathArguments{} }
func (m *ModPathArguments) String() string { return proto.CompactTextString(m) }
func (*ModPathArguments) ProtoMessage() {}
-func (m *ModPathArguments) GetPath() *Path {
- if m != nil {
- return m.Path
- }
- return nil
-}
-
type PolicyArguments struct {
Resource Resource `protobuf:"varint,1,opt,name=resource,enum=api.Resource" json:"resource,omitempty"`
Operation Operation `protobuf:"varint,2,opt,name=operation,enum=api.Operation" json:"operation,omitempty"`
diff --git a/api/gobgp.proto b/api/gobgp.proto
index e50e3c71..cb85db27 100644
--- a/api/gobgp.proto
+++ b/api/gobgp.proto
@@ -60,7 +60,9 @@ message Arguments {
message ModPathArguments {
Resource resource = 1;
- Path path = 2;
+ bool is_withdraw = 2;
+ bytes raw_nlri = 3;
+ repeated bytes raw_pattrs = 4;
}
message PolicyArguments {
diff --git a/gobgp/global.go b/gobgp/global.go
index 79d91a65..9c272691 100644
--- a/gobgp/global.go
+++ b/gobgp/global.go
@@ -18,12 +18,12 @@ package main
import (
"fmt"
"github.com/osrg/gobgp/api"
+ "github.com/osrg/gobgp/packet"
"github.com/spf13/cobra"
"golang.org/x/net/context"
"net"
"os"
"strconv"
- "strings"
)
func showGlobalRib(args []string) error {
@@ -55,186 +55,178 @@ func modPath(modtype string, args []string) error {
return err
}
- path := &api.Path{}
+ var nlri bgp.AddrPrefixInterface
+ var nexthop string
+
switch rf {
case api.AF_IPV4_UC, api.AF_IPV6_UC:
if len(args) != 1 {
return fmt.Errorf("usage: global rib %s <prefix> -a { ipv4 | ipv6 }", modtype)
}
- prefix := args[0]
- path.Nlri = &api.Nlri{
- Af: rf,
- Prefix: prefix,
+ ip, net, _ := net.ParseCIDR(args[0])
+ if rf == api.AF_IPV4_UC {
+ if ip.To4() == nil {
+ return fmt.Errorf("invalid ipv4 prefix")
+ }
+ nexthop = "0.0.0.0"
+ ones, _ := net.Mask.Size()
+ nlri = bgp.NewNLRInfo(uint8(ones), ip.String())
+ } else {
+ if ip.To16() == nil {
+ return fmt.Errorf("invalid ipv6 prefix")
+ }
+ nexthop = "::"
+ ones, _ := net.Mask.Size()
+ nlri = bgp.NewIPv6AddrPrefix(uint8(ones), ip.String())
}
case api.AF_IPV4_VPN, api.AF_IPV6_VPN:
- if len(args) < 1 {
- return fmt.Errorf("usage: global rib %s <rd>:<prefix> [<rt>...] -a { vpn-ipv4 | vpn-ipv6 }", modtype)
+ if len(args) < 3 || args[1] != "rd" {
+ return fmt.Errorf("usage: global rib %s <prefix> rd <rd> -a { vpn-ipv4 | vpn-ipv6 }", modtype)
}
- elems := strings.SplitN(args[0], ":", 4)
- if len(elems) != 4 {
- return fmt.Errorf("invalid <rd>:<prefix>: %s. hint. <rd> := <type>:<admin>:<assigned>", args[0])
- }
- rd, err := parseRD(elems[:3])
+ ip, net, _ := net.ParseCIDR(args[0])
+ ones, _ := net.Mask.Size()
+
+ rd, err := bgp.ParseRouteDistinguisher(args[2])
if err != nil {
return err
}
- prefix := elems[3]
- elems = strings.Split(prefix, "/")
- if len(elems) != 2 {
- return fmt.Errorf("invalid prefix: %s", prefix)
- }
- masklen, err := strconv.Atoi(elems[1])
- if err != nil {
- return fmt.Errorf("invalid prefix: %s", prefix)
- }
+ mpls := bgp.NewMPLSLabelStack()
- nlri := &api.VPNNlri{
- Rd: rd,
- IpAddr: elems[0],
- IpAddrLen: uint32(masklen),
- }
- path.Nlri = &api.Nlri{
- Af: rf,
- VpnNlri: nlri,
+ if rf == api.AF_IPV4_VPN {
+ if ip.To4() == nil {
+ return fmt.Errorf("invalid ipv4 prefix")
+ }
+ nexthop = "0.0.0.0"
+ nlri = bgp.NewLabeledVPNIPAddrPrefix(uint8(ones), ip.String(), *mpls, rd)
+ } else {
+ if ip.To16() == nil {
+ return fmt.Errorf("invalid ipv6 prefix")
+ }
+ nexthop = "::"
+ nlri = bgp.NewLabeledVPNIPv6AddrPrefix(uint8(ones), ip.String(), *mpls, rd)
}
- case api.AF_EVPN:
- var nlri *api.EVPNNlri
+ case api.AF_EVPN:
if len(args) < 1 {
return fmt.Errorf("usage: global rib %s { macadv | multicast } ... -a evpn", modtype)
}
subtype := args[0]
+ args = args[1:]
switch subtype {
case "macadv":
- if len(args) < 5 {
- return fmt.Errorf("usage: global rib %s macadv <mac address> <ip address> <etag> <label> -a evpn", modtype)
+ if len(args) < 6 || args[4] != "rd" {
+ return fmt.Errorf("usage: global rib %s macadv <mac address> <ip address> <etag> <label> rd <rd> -a evpn", modtype)
}
- macAddr := args[1]
- ipAddr := args[2]
- eTag, err := strconv.Atoi(args[3])
+ mac, err := net.ParseMAC(args[0])
if err != nil {
- return fmt.Errorf("invalid eTag: %s. err: %s", args[3], err)
+ return fmt.Errorf("invalid mac: %s", args[0])
}
- label, err := strconv.Atoi(args[4])
- if err != nil {
- return fmt.Errorf("invalid label: %s. err: %s", args[4], err)
- }
- nlri = &api.EVPNNlri{
- Type: api.EVPN_TYPE_ROUTE_TYPE_MAC_IP_ADVERTISEMENT,
- MacIpAdv: &api.EvpnMacIpAdvertisement{
- MacAddr: macAddr,
- IpAddr: ipAddr,
- Etag: uint32(eTag),
- Labels: []uint32{uint32(label)},
- },
+ var ip net.IP
+ iplen := 0
+ if args[1] != "0.0.0.0" || args[1] != "::" {
+ ip = net.ParseIP(args[1])
+ if ip == nil {
+ return fmt.Errorf("invalid ip prefix: %s", args[1])
+ }
+ iplen = net.IPv4len * 8
+ if ip.To4() == nil {
+ iplen = net.IPv6len * 8
+ }
}
- case "multicast":
- if len(args) < 3 {
- return fmt.Errorf("usage : global rib %s multicast <etag> <label> -a evpn", modtype)
+ eTag, err := strconv.Atoi(args[2])
+ if err != nil {
+ return fmt.Errorf("invalid eTag: %s. err: %s", args[2], err)
}
- eTag, err := strconv.Atoi(args[1])
+ label, err := strconv.Atoi(args[3])
if err != nil {
- return fmt.Errorf("invalid eTag: %s. err: %s", args[1], err)
+ return fmt.Errorf("invalid label: %s. err: %s", args[3], err)
}
- label, err := strconv.Atoi(args[2])
+ rd, err := bgp.ParseRouteDistinguisher(args[5])
if err != nil {
- return fmt.Errorf("invalid label: %s. err: %s", args[2], err)
+ return err
}
- nlri = &api.EVPNNlri{
- Type: api.EVPN_TYPE_INCLUSIVE_MULTICAST_ETHERNET_TAG,
- MulticastEtag: &api.EvpnInclusiveMulticastEthernetTag{
- Etag: uint32(eTag),
+ macIpAdv := &bgp.EVPNMacIPAdvertisementRoute{
+ RD: rd,
+ ESI: bgp.EthernetSegmentIdentifier{
+ Type: bgp.ESI_ARBITRARY,
},
+ MacAddressLength: 48,
+ MacAddress: mac,
+ IPAddressLength: uint8(iplen),
+ IPAddress: ip,
+ Labels: []uint32{uint32(label)},
+ ETag: uint32(eTag),
}
-
- attr := &api.PathAttr{
- Type: api.BGP_ATTR_TYPE_PMSI_TUNNEL,
- PmsiTunnel: &api.PmsiTunnel{
- Type: api.PMSI_TUNNEL_TYPE_INGRESS_REPL,
- Label: uint32(label),
- },
+ nlri = bgp.NewEVPNNLRI(bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT, 0, macIpAdv)
+ case "multicast":
+ if len(args) < 5 || args[2] != "rd" {
+ return fmt.Errorf("usage : global rib %s multicast <ip address> <etag> rd <rd> -a evpn", modtype)
}
- path.Attrs = append(path.Attrs, attr)
- default:
- return fmt.Errorf("usage: global rib add { macadv | multicast | ... -a evpn")
- }
- path.Nlri = &api.Nlri{
- Af: rf,
- EvpnNlri: nlri,
- }
- case api.AF_ENCAP:
- if len(args) < 1 {
- return fmt.Errorf("usage: global rib %s <end point ip address> [<vni>] -a encap", modtype)
- }
- prefix := args[0]
-
- path.Nlri = &api.Nlri{
- Af: rf,
- Prefix: prefix,
- }
+ var ip net.IP
+ iplen := 0
+ if args[0] != "0.0.0.0" || args[0] != "::" {
+ ip = net.ParseIP(args[0])
+ if ip == nil {
+ return fmt.Errorf("invalid ip prefix: %s", args[0])
+ }
+ iplen = net.IPv4len * 8
+ if ip.To4() == nil {
+ iplen = net.IPv6len * 8
+ }
+ }
- if len(args) > 1 {
- vni, err := strconv.Atoi(args[1])
+ eTag, err := strconv.Atoi(args[1])
if err != nil {
- return fmt.Errorf("invalid vni: %s", args[1])
- }
- subTlv := &api.TunnelEncapSubTLV{
- Type: api.ENCAP_SUBTLV_TYPE_COLOR,
- Color: uint32(vni),
- }
- tlv := &api.TunnelEncapTLV{
- Type: api.TUNNEL_TYPE_VXLAN,
- SubTlv: []*api.TunnelEncapSubTLV{subTlv},
- }
- attr := &api.PathAttr{
- Type: api.BGP_ATTR_TYPE_TUNNEL_ENCAP,
- TunnelEncap: []*api.TunnelEncapTLV{tlv},
+ return fmt.Errorf("invalid eTag: %s. err: %s", args[1], err)
}
- path.Attrs = append(path.Attrs, attr)
- }
- case api.AF_RTC:
- if !(len(args) == 3 && args[0] == "default") && len(args) < 4 {
- return fmt.Errorf("usage: global rib add <asn> <local admin> -a rtc")
- }
- var asn, admin int
-
- if args[0] != "default" {
- asn, err = strconv.Atoi(args[0])
+ rd, err := bgp.ParseRouteDistinguisher(args[3])
if err != nil {
- return fmt.Errorf("invalid asn: %s", args[0])
+ return err
}
- admin, err = strconv.Atoi(args[1])
- if err != nil {
- return fmt.Errorf("invalid local admin: %s", args[1])
+
+ multicastEtag := &bgp.EVPNMulticastEthernetTagRoute{
+ RD: rd,
+ IPAddressLength: uint8(iplen),
+ IPAddress: ip,
+ ETag: uint32(eTag),
}
+ nlri = bgp.NewEVPNNLRI(bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG, 0, multicastEtag)
+ default:
+ return fmt.Errorf("usage: global rib add { macadv | multicast | ... -a evpn")
}
- 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),
- },
- },
- }
+ nexthop = "0.0.0.0"
+ default:
+ return fmt.Errorf("Unsupported route family: %s", rf)
}
+
+ arg := &api.ModPathArguments{
+ Resource: api.Resource_GLOBAL,
+ RawPattrs: make([][]byte, 0),
+ }
+
switch modtype {
case CMD_ADD:
- path.IsWithdraw = false
+ arg.IsWithdraw = false
case CMD_DEL:
- path.IsWithdraw = true
+ arg.IsWithdraw = true
}
- arg := &api.ModPathArguments{
- Resource: api.Resource_GLOBAL,
- Path: path,
+ if rf == api.AF_IPV4_UC {
+ arg.RawNlri, _ = nlri.Serialize()
+ n, _ := bgp.NewPathAttributeNextHop(nexthop).Serialize()
+ arg.RawPattrs = append(arg.RawPattrs, n)
+ } else {
+ mpreach, _ := bgp.NewPathAttributeMpReachNLRI(nexthop, []bgp.AddrPrefixInterface{nlri}).Serialize()
+ arg.RawPattrs = append(arg.RawPattrs, mpreach)
}
+
+ origin, _ := bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP).Serialize()
+ arg.RawPattrs = append(arg.RawPattrs, origin)
+
stream, err := client.ModPath(context.Background())
if err != nil {
return err
diff --git a/packet/bgp.go b/packet/bgp.go
index b5bf7924..7fd4f9e6 100644
--- a/packet/bgp.go
+++ b/packet/bgp.go
@@ -24,6 +24,8 @@ import (
"math"
"net"
"reflect"
+ "regexp"
+ "strconv"
"strings"
)
@@ -856,6 +858,40 @@ func getRouteDistinguisher(data []byte) RouteDistinguisherInterface {
return rd
}
+func parseRd(input string) ([]string, error) {
+ exp := regexp.MustCompile("^((\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)|((\\d+)\\.)?(\\d+)):(\\d+)$")
+ group := exp.FindSubmatch([]byte(input))
+ if len(group) != 10 {
+ return nil, fmt.Errorf("failed to parse")
+ }
+ elems := make([]string, 0, len(group))
+ for _, elem := range group {
+ elems = append(elems, string(elem))
+ }
+ return elems, nil
+}
+
+func ParseRouteDistinguisher(rd string) (RouteDistinguisherInterface, error) {
+ elems, err := parseRd(rd)
+ if err != nil {
+ return nil, err
+ }
+ assigned, _ := strconv.Atoi(elems[9])
+ ip := net.ParseIP(elems[1])
+ switch {
+ case ip.To4() != nil:
+ return NewRouteDistinguisherIPAddressAS(elems[1], uint16(assigned)), nil
+ case elems[6] == "" && elems[7] == "":
+ asn, _ := strconv.Atoi(elems[8])
+ return NewRouteDistinguisherTwoOctetAS(uint16(asn), uint32(assigned)), nil
+ default:
+ fst, _ := strconv.Atoi(elems[7])
+ snd, _ := strconv.Atoi(elems[8])
+ asn := fst<<16 | snd
+ return NewRouteDistinguisherFourOctetAS(uint32(asn), uint16(assigned)), nil
+ }
+}
+
//
// RFC3107 Carrying Label Information in BGP-4
//
diff --git a/server/grpc_server.go b/server/grpc_server.go
index 55dd4381..e72b42aa 100644
--- a/server/grpc_server.go
+++ b/server/grpc_server.go
@@ -334,15 +334,11 @@ func (s *Server) ModPath(stream api.Grpc_ModPathServer) error {
}
reqType := REQ_GLOBAL_ADD
- if arg.Path.IsWithdraw {
+ if arg.IsWithdraw {
reqType = REQ_GLOBAL_DELETE
}
- rf, err := convertAf2Rf(arg.Path.Nlri.Af)
- if err != nil {
- return err
- }
- req := NewGrpcRequest(reqType, "", rf, arg.Path)
+ req := NewGrpcRequest(reqType, "", bgp.RouteFamily(0), arg)
s.bgpServerCh <- req
res := <-req.ResponseCh
diff --git a/server/server.go b/server/server.go
index b2ad3764..8eca9d75 100644
--- a/server/server.go
+++ b/server/server.go
@@ -737,15 +737,12 @@ func (server *BgpServer) checkNeighborRequest(grpcReq *GrpcRequest) (*Peer, erro
func handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*table.Path {
var isWithdraw bool
- var p *table.Path
var nlri bgp.AddrPrefixInterface
result := &GrpcResponse{}
pattr := make([]bgp.PathAttributeInterface, 0)
- pattr = append(pattr, bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP))
- rf := grpcReq.RouteFamily
- path, ok := grpcReq.Data.(*api.Path)
+ args, ok := grpcReq.Data.(*api.ModPathArguments)
if !ok {
result.ResponseErr = fmt.Errorf("type assertion failed")
goto ERR
@@ -754,219 +751,48 @@ func handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*t
isWithdraw = true
}
- switch rf {
- case bgp.RF_IPv4_UC:
- ip, net, _ := net.ParseCIDR(path.Nlri.Prefix)
- if ip.To4() == nil {
- result.ResponseErr = fmt.Errorf("Invalid ipv4 prefix: %s", path.Nlri.Prefix)
+ if len(args.RawNlri) > 0 {
+ nlri = &bgp.NLRInfo{}
+ err := nlri.DecodeFromBytes(args.RawNlri)
+ if err != nil {
+ result.ResponseErr = err
goto ERR
}
- ones, _ := net.Mask.Size()
- nlri = &bgp.NLRInfo{
- IPAddrPrefix: *bgp.NewIPAddrPrefix(uint8(ones), ip.String()),
- }
-
- pattr = append(pattr, bgp.NewPathAttributeNextHop("0.0.0.0"))
-
- case bgp.RF_IPv6_UC:
+ }
- ip, net, _ := net.ParseCIDR(path.Nlri.Prefix)
- if ip.To16() == nil {
- result.ResponseErr = fmt.Errorf("Invalid ipv6 prefix: %s", path.Nlri.Prefix)
+ for _, attr := range args.RawPattrs {
+ p, err := bgp.GetPathAttribute(attr)
+ if err != nil {
+ result.ResponseErr = err
goto ERR
}
- ones, _ := net.Mask.Size()
- nlri = bgp.NewIPv6AddrPrefix(uint8(ones), ip.String())
-
- pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("::", []bgp.AddrPrefixInterface{nlri}))
-
- case bgp.RF_IPv4_VPN, bgp.RF_IPv6_VPN:
- var rd bgp.RouteDistinguisherInterface
- switch path.Nlri.VpnNlri.Rd.Type {
- case api.ROUTE_DISTINGUISHER_TYPE_TWO_OCTET_AS:
- a, err := strconv.Atoi(path.Nlri.VpnNlri.Rd.Admin)
- if err != nil {
- result.ResponseErr = fmt.Errorf("Invalid admin value: %s", path.Nlri.VpnNlri.Rd.Admin)
- goto ERR
- }
- rd = bgp.NewRouteDistinguisherTwoOctetAS(uint16(a), path.Nlri.VpnNlri.Rd.Assigned)
- case api.ROUTE_DISTINGUISHER_TYPE_IP4:
- ip := net.ParseIP(path.Nlri.VpnNlri.Rd.Admin)
- if ip.To4() == nil {
- result.ResponseErr = fmt.Errorf("Invalid ipv4 prefix: %s", path.Nlri.VpnNlri.Rd.Admin)
- goto ERR
- }
- assigned := uint16(path.Nlri.VpnNlri.Rd.Assigned)
- rd = bgp.NewRouteDistinguisherIPAddressAS(path.Nlri.VpnNlri.Rd.Admin, assigned)
- case api.ROUTE_DISTINGUISHER_TYPE_FOUR_OCTET_AS:
- a, err := strconv.Atoi(path.Nlri.VpnNlri.Rd.Admin)
- if err != nil {
- result.ResponseErr = fmt.Errorf("Invalid admin value: %s", path.Nlri.VpnNlri.Rd.Admin)
- goto ERR
- }
- admin := uint32(a)
- assigned := uint16(path.Nlri.VpnNlri.Rd.Assigned)
- rd = bgp.NewRouteDistinguisherFourOctetAS(admin, assigned)
- }
-
- mpls := bgp.NewMPLSLabelStack(0)
- if rf == bgp.RF_IPv4_VPN {
- nlri = bgp.NewLabeledVPNIPAddrPrefix(uint8(path.Nlri.VpnNlri.IpAddrLen), path.Nlri.VpnNlri.IpAddr, *mpls, rd)
- pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("0.0.0.0", []bgp.AddrPrefixInterface{nlri}))
- } else {
- nlri = bgp.NewLabeledVPNIPv6AddrPrefix(uint8(path.Nlri.VpnNlri.IpAddrLen), path.Nlri.VpnNlri.IpAddr, *mpls, rd)
- pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("::", []bgp.AddrPrefixInterface{nlri}))
- }
-
- case bgp.RF_EVPN:
- if peerInfo.AS > (1<<16 - 1) {
- result.ResponseErr = fmt.Errorf("evpn path can't be created in 4byte-AS env")
- }
- asn := uint16(peerInfo.AS)
- routerId := peerInfo.LocalID
- var eTag uint32
-
- switch path.Nlri.EvpnNlri.Type {
- case bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT:
- mac, err := net.ParseMAC(path.Nlri.EvpnNlri.MacIpAdv.MacAddr)
- if err != nil {
- result.ResponseErr = fmt.Errorf("Invalid mac: %s", path.Nlri.EvpnNlri.MacIpAdv.MacAddr)
- goto ERR
- }
- var ip net.IP
- iplen := 0
- if path.Nlri.EvpnNlri.MacIpAdv.IpAddr != "0.0.0.0" {
- ip = net.ParseIP(path.Nlri.EvpnNlri.MacIpAdv.IpAddr)
- if ip == nil {
- result.ResponseErr = fmt.Errorf("Invalid ip prefix: %s", path.Nlri.EvpnNlri.MacIpAdv.IpAddr)
- goto ERR
- }
- iplen = net.IPv4len * 8
- if ip.To4() == nil {
- iplen = net.IPv6len * 8
- }
- }
- var labels []uint32
- if len(path.Nlri.EvpnNlri.MacIpAdv.Labels) == 0 {
- labels = []uint32{0}
- } else {
- labels = path.Nlri.EvpnNlri.MacIpAdv.Labels
- }
-
- eTag = path.Nlri.EvpnNlri.MacIpAdv.Etag
- macIpAdv := &bgp.EVPNMacIPAdvertisementRoute{
- RD: bgp.NewRouteDistinguisherIPAddressAS(routerId.String(), 0),
- ESI: bgp.EthernetSegmentIdentifier{
- Type: bgp.ESI_ARBITRARY,
- },
- MacAddressLength: 48,
- MacAddress: mac,
- IPAddressLength: uint8(iplen),
- IPAddress: ip,
- Labels: labels,
- ETag: eTag,
- }
- nlri = bgp.NewEVPNNLRI(bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT, 0, macIpAdv)
- case bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG:
- eTag = path.Nlri.EvpnNlri.MulticastEtag.Etag
- ip := peerInfo.LocalID
- iplen := net.IPv4len * 8
- if ip.To4() == nil {
- iplen = net.IPv6len * 8
- }
- multicastEtag := &bgp.EVPNMulticastEthernetTagRoute{
- RD: bgp.NewRouteDistinguisherIPAddressAS(routerId.String(), 0),
- IPAddressLength: uint8(iplen),
- IPAddress: ip,
- ETag: eTag,
- }
- nlri = bgp.NewEVPNNLRI(bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG, 0, multicastEtag)
- }
- pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("0.0.0.0", []bgp.AddrPrefixInterface{nlri}))
- isTransitive := true
- rt := bgp.NewTwoOctetAsSpecificExtended(asn, eTag, isTransitive)
- encap := &bgp.OpaqueExtended{isTransitive, &bgp.EncapExtended{bgp.TUNNEL_TYPE_VXLAN}}
- pattr = append(pattr, bgp.NewPathAttributeExtendedCommunities([]bgp.ExtendedCommunityInterface{rt, encap}))
- case bgp.RF_ENCAP:
- endpoint := net.ParseIP(path.Nlri.Prefix)
- if endpoint == nil {
- result.ResponseErr = fmt.Errorf("Invalid endpoint ip address: %s", path.Nlri.Prefix)
+ err = p.DecodeFromBytes(attr)
+ if err != nil {
+ result.ResponseErr = err
goto ERR
-
}
- nlri = bgp.NewEncapNLRI(endpoint.String())
- pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("0.0.0.0", []bgp.AddrPrefixInterface{nlri}))
- iterSubTlvs := func(subTlvs []*api.TunnelEncapSubTLV) {
- for _, subTlv := range subTlvs {
- if subTlv.Type == api.ENCAP_SUBTLV_TYPE_COLOR {
- color := subTlv.Color
- subTlv := &bgp.TunnelEncapSubTLV{
- Type: bgp.ENCAP_SUBTLV_TYPE_COLOR,
- Value: &bgp.TunnelEncapSubTLVColor{color},
- }
- tlv := &bgp.TunnelEncapTLV{
- Type: bgp.TUNNEL_TYPE_VXLAN,
- Value: []*bgp.TunnelEncapSubTLV{subTlv},
- }
- attr := bgp.NewPathAttributeTunnelEncap([]*bgp.TunnelEncapTLV{tlv})
- pattr = append(pattr, attr)
- break
- }
- }
- }
-
- iterTlvs := func(tlvs []*api.TunnelEncapTLV) {
- for _, tlv := range tlvs {
- if tlv.Type == api.TUNNEL_TYPE_VXLAN {
- iterSubTlvs(tlv.SubTlv)
- break
- }
- }
- }
-
- func(attrs []*api.PathAttr) {
- for _, attr := range attrs {
- if attr.Type == api.BGP_ATTR_TYPE_TUNNEL_ENCAP {
- iterTlvs(attr.TunnelEncap)
- break
- }
- }
- }(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,
+ switch p.GetType() {
+ case bgp.BGP_ATTR_TYPE_MP_REACH_NLRI:
+ value := p.(*bgp.PathAttributeMpReachNLRI).Value
+ if len(value) != 1 {
+ result.ResponseErr = fmt.Errorf("include only one route in mp_reach_nlri")
+ goto ERR
}
+ nlri = p.(*bgp.PathAttributeMpReachNLRI).Value[0]
+ fallthrough
default:
- result.ResponseErr = fmt.Errorf("Invalid endpoint ip address: %s", path.Nlri.Prefix)
- goto ERR
+ pattr = append(pattr, p)
}
+ }
- nlri = bgp.NewRouteTargetMembershipNLRI(peerInfo.AS, ec)
-
- pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("0.0.0.0", []bgp.AddrPrefixInterface{nlri}))
-
- default:
- result.ResponseErr = fmt.Errorf("Unsupported address family: %s", rf)
+ if nlri == nil {
+ result.ResponseErr = fmt.Errorf("no nlri included")
goto ERR
}
- p = table.NewPath(peerInfo, nlri, isWithdraw, pattr, false, time.Now())
- return []*table.Path{p}
+ return []*table.Path{table.NewPath(peerInfo, nlri, isWithdraw, pattr, false, time.Now())}
ERR:
grpcReq.ResponseCh <- result
close(grpcReq.ResponseCh)