summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--api/gobgp.pb.go22
-rw-r--r--api/gobgp.proto9
-rw-r--r--gobgp/global.go83
-rw-r--r--packet/bgp.go11
-rw-r--r--server/server.go140
5 files changed, 195 insertions, 70 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go
index e0cde493..bc1cad51 100644
--- a/api/gobgp.pb.go
+++ b/api/gobgp.pb.go
@@ -21,6 +21,7 @@ It has these top-level messages:
ExtendedCommunity
EVPNNlri
EvpnMacIpAdvertisement
+ EvpnInclusiveMulticastEthernetTag
RTNlri
Nlri
TunnelEncapSubTLV
@@ -690,7 +691,8 @@ func (*ExtendedCommunity) ProtoMessage() {}
type EVPNNlri struct {
Type EVPN_TYPE `protobuf:"varint,1,opt,name=type,enum=api.EVPN_TYPE" json:"type,omitempty"`
// EvpnAutoDiscoveryRoute = 2;
- MacIpAdv *EvpnMacIpAdvertisement `protobuf:"bytes,3,opt,name=mac_ip_adv" json:"mac_ip_adv,omitempty"`
+ MacIpAdv *EvpnMacIpAdvertisement `protobuf:"bytes,3,opt,name=mac_ip_adv" json:"mac_ip_adv,omitempty"`
+ MulticastEtag *EvpnInclusiveMulticastEthernetTag `protobuf:"bytes,4,opt,name=multicast_etag" json:"multicast_etag,omitempty"`
}
func (m *EVPNNlri) Reset() { *m = EVPNNlri{} }
@@ -704,6 +706,13 @@ func (m *EVPNNlri) GetMacIpAdv() *EvpnMacIpAdvertisement {
return nil
}
+func (m *EVPNNlri) GetMulticastEtag() *EvpnInclusiveMulticastEthernetTag {
+ if m != nil {
+ return m.MulticastEtag
+ }
+ return nil
+}
+
type EvpnMacIpAdvertisement struct {
MacAddr string `protobuf:"bytes,1,opt,name=mac_addr" json:"mac_addr,omitempty"`
MacAddrLen uint32 `protobuf:"varint,2,opt,name=mac_addr_len" json:"mac_addr_len,omitempty"`
@@ -719,6 +728,17 @@ func (m *EvpnMacIpAdvertisement) Reset() { *m = EvpnMacIpAdvertisement{}
func (m *EvpnMacIpAdvertisement) String() string { return proto.CompactTextString(m) }
func (*EvpnMacIpAdvertisement) ProtoMessage() {}
+type EvpnInclusiveMulticastEthernetTag struct {
+ Rd string `protobuf:"bytes,1,opt,name=rd" json:"rd,omitempty"`
+ Etag uint32 `protobuf:"varint,2,opt,name=etag" json:"etag,omitempty"`
+ IpAddr string `protobuf:"bytes,3,opt,name=ip_addr" json:"ip_addr,omitempty"`
+ IpAddrLen uint32 `protobuf:"varint,4,opt,name=ip_addr_len" json:"ip_addr_len,omitempty"`
+}
+
+func (m *EvpnInclusiveMulticastEthernetTag) Reset() { *m = EvpnInclusiveMulticastEthernetTag{} }
+func (m *EvpnInclusiveMulticastEthernetTag) String() string { return proto.CompactTextString(m) }
+func (*EvpnInclusiveMulticastEthernetTag) ProtoMessage() {}
+
type RTNlri struct {
Asn uint32 `protobuf:"varint,1,opt,name=asn" json:"asn,omitempty"`
Target *ExtendedCommunity `protobuf:"bytes,2,opt,name=target" json:"target,omitempty"`
diff --git a/api/gobgp.proto b/api/gobgp.proto
index 1467ab51..1e789502 100644
--- a/api/gobgp.proto
+++ b/api/gobgp.proto
@@ -210,7 +210,7 @@ message EVPNNlri {
EVPN_TYPE type = 1;
// EvpnAutoDiscoveryRoute = 2;
EvpnMacIpAdvertisement mac_ip_adv = 3;
-// EvpnInclusiveMulticastEthernetTag = 4;
+ EvpnInclusiveMulticastEthernetTag multicast_etag = 4;
// EvpnEthernetSegmentRoute = 5;
}
@@ -225,6 +225,13 @@ message EvpnMacIpAdvertisement {
repeated uint32 labels = 8;
}
+message EvpnInclusiveMulticastEthernetTag {
+ string rd = 1;
+ uint32 etag = 2;
+ string ip_addr = 3;
+ uint32 ip_addr_len = 4;
+}
+
message RTNlri {
uint32 asn = 1;
ExtendedCommunity target = 2;
diff --git a/gobgp/global.go b/gobgp/global.go
index 00b0da6c..8744449f 100644
--- a/gobgp/global.go
+++ b/gobgp/global.go
@@ -21,6 +21,7 @@ import (
"github.com/spf13/cobra"
"golang.org/x/net/context"
"net"
+ "os"
"strconv"
)
@@ -36,7 +37,7 @@ func modPath(modtype string, eArgs []string) error {
}
path := &api.Path{}
- var prefix, macAddr, ipAddr string
+ var prefix string
switch rf {
case api.AF_IPV4_UC, api.AF_IPV6_UC:
if len(eArgs) == 1 || len(eArgs) == 3 {
@@ -49,21 +50,71 @@ func modPath(modtype string, eArgs []string) error {
Prefix: prefix,
}
case api.AF_EVPN:
- if len(eArgs) == 4 {
- macAddr = eArgs[0]
- ipAddr = eArgs[1]
- } else {
- return fmt.Errorf("usage: global rib %s <mac address> <ip address> -a evpn", modtype)
+ var nlri *api.EVPNNlri
+
+ if len(eArgs) < 1 {
+ return fmt.Errorf("usage: global rib %s { macadv | multicast } ... -a evpn", modtype)
}
- path.Nlri = &api.Nlri{
- Af: rf,
- EvpnNlri: &api.EVPNNlri{
+ subtype := eArgs[0]
+
+ switch subtype {
+ case "macadv":
+ if len(eArgs) < 5 {
+ return fmt.Errorf("usage: global rib %s macadv <mac address> <ip address> <etag> <label> -a evpn", modtype)
+ }
+ macAddr := eArgs[1]
+ ipAddr := eArgs[2]
+ eTag, err := strconv.Atoi(eArgs[3])
+ if err != nil {
+ return fmt.Errorf("invalid eTag: %s. err: %s", eArgs[3], err)
+ }
+ label, err := strconv.Atoi(eArgs[4])
+ if err != nil {
+ return fmt.Errorf("invalid label: %s. err: %s", eArgs[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)},
},
- },
+ }
+ case "multicast":
+ if len(eArgs) < 3 {
+ return fmt.Errorf("usage : global rib %s multicast <etag> <label> -a evpn", modtype)
+ }
+ eTag, err := strconv.Atoi(eArgs[1])
+ if err != nil {
+ return fmt.Errorf("invalid eTag: %s. err: %s", eArgs[1], err)
+ }
+ label, err := strconv.Atoi(eArgs[2])
+ if err != nil {
+ return fmt.Errorf("invalid label: %s. err: %s", eArgs[2], err)
+ }
+ nlri = &api.EVPNNlri{
+ Type: api.EVPN_TYPE_INCLUSIVE_MULTICAST_ETHERNET_TAG,
+ MulticastEtag: &api.EvpnInclusiveMulticastEthernetTag{
+ 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),
+ },
+ }
+
+ 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(eArgs) < 3 {
@@ -172,14 +223,22 @@ func NewGlobalCmd() *cobra.Command {
addCmd := &cobra.Command{
Use: CMD_ADD,
Run: func(cmd *cobra.Command, args []string) {
- modPath(CMD_ADD, args)
+ err := modPath(CMD_ADD, args)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
},
}
delCmd := &cobra.Command{
Use: CMD_DEL,
Run: func(cmd *cobra.Command, args []string) {
- modPath(CMD_DEL, args)
+ err := modPath(CMD_DEL, args)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
},
}
diff --git a/packet/bgp.go b/packet/bgp.go
index 4301d7c1..bdd07911 100644
--- a/packet/bgp.go
+++ b/packet/bgp.go
@@ -797,7 +797,7 @@ func NewRouteDistinguisherIPAddressAS(admin string, assigned uint16) *RouteDisti
DefaultRouteDistinguisher: DefaultRouteDistinguisher{
Type: BGP_RD_IPV4_ADDRESS,
},
- Admin: net.ParseIP(admin),
+ Admin: net.ParseIP(admin).To4(),
Assigned: assigned,
}
}
@@ -3037,6 +3037,15 @@ func (e *TwoOctetAsSpecificExtended) ToApiStruct() *api.ExtendedCommunity {
}
}
+func NewTwoOctetAsSpecificExtended(as uint16, rt uint32, isTransitive bool) *TwoOctetAsSpecificExtended {
+ return &TwoOctetAsSpecificExtended{
+ SubType: ExtendedCommunityAttrSubType(EC_SUBTYPE_ROUTE_TARGET),
+ AS: as,
+ LocalAdmin: rt,
+ IsTransitive: isTransitive,
+ }
+}
+
type IPv4AddressSpecificExtended struct {
SubType ExtendedCommunityAttrSubType
IPv4 net.IP
diff --git a/server/server.go b/server/server.go
index 29f3a1fd..437e90da 100644
--- a/server/server.go
+++ b/server/server.go
@@ -668,36 +668,32 @@ func (server *BgpServer) checkNeighborRequest(grpcReq *GrpcRequest) (*Peer, erro
}
func handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*table.Path {
- pathList := []*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))
+ asparam := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{peerInfo.AS})
+ pattr = append(pattr, bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{asparam}))
+
rf := grpcReq.RouteFamily
path, ok := grpcReq.Data.(*api.Path)
if !ok {
result.ResponseErr = fmt.Errorf("type assertion failed")
- grpcReq.ResponseCh <- result
- close(grpcReq.ResponseCh)
- return pathList
+ goto ERR
}
- var isWithdraw bool
if grpcReq.RequestType == REQ_GLOBAL_DELETE {
isWithdraw = true
}
- 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{peerInfo.AS})
- pattr = append(pattr, bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{asparam}))
-
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)
- grpcReq.ResponseCh <- result
- close(grpcReq.ResponseCh)
- return pathList
+ goto ERR
}
ones, _ := net.Mask.Size()
nlri = &bgp.NLRInfo{
@@ -711,9 +707,7 @@ func handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*t
ip, net, _ := net.ParseCIDR(path.Nlri.Prefix)
if ip.To16() == nil {
result.ResponseErr = fmt.Errorf("Invalid ipv6 prefix: %s", path.Nlri.Prefix)
- grpcReq.ResponseCh <- result
- close(grpcReq.ResponseCh)
- return pathList
+ goto ERR
}
ones, _ := net.Mask.Size()
nlri = bgp.NewIPv6AddrPrefix(uint8(ones), ip.String())
@@ -721,45 +715,80 @@ func handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*t
pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("::", []bgp.AddrPrefixInterface{nlri}))
case bgp.RF_EVPN:
- mac, err := net.ParseMAC(path.Nlri.EvpnNlri.MacIpAdv.MacAddr)
- if err != nil {
- result.ResponseErr = fmt.Errorf("Invalid mac: %s", path.Nlri.EvpnNlri.MacIpAdv.MacAddr)
- grpcReq.ResponseCh <- result
- close(grpcReq.ResponseCh)
- return pathList
- }
- ip := net.ParseIP(path.Nlri.EvpnNlri.MacIpAdv.IpAddr)
- if ip == nil {
- result.ResponseErr = fmt.Errorf("Invalid ip prefix: %s", path.Nlri.EvpnNlri.MacIpAdv.IpAddr)
- grpcReq.ResponseCh <- result
- close(grpcReq.ResponseCh)
- return pathList
- }
- iplen := net.IPv4len * 8
- if ip.To4() == nil {
- iplen = net.IPv6len * 8
+ 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
- macIpAdv := &bgp.EVPNMacIPAdvertisementRoute{
- RD: bgp.NewRouteDistinguisherTwoOctetAS(0, 0),
- ESI: bgp.EthernetSegmentIdentifier{
- Type: bgp.ESI_ARBITRARY,
- },
- MacAddressLength: 48,
- MacAddress: mac,
- IPAddressLength: uint8(iplen),
- IPAddress: ip,
- Labels: []uint32{0},
+ 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)
}
- nlri = bgp.NewEVPNNLRI(bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT, 0, macIpAdv)
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)
- grpcReq.ResponseCh <- result
- close(grpcReq.ResponseCh)
- return pathList
+ goto ERR
}
nlri = bgp.NewEncapNLRI(endpoint.String())
@@ -820,9 +849,7 @@ func handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*t
}
default:
result.ResponseErr = fmt.Errorf("Invalid endpoint ip address: %s", path.Nlri.Prefix)
- grpcReq.ResponseCh <- result
- close(grpcReq.ResponseCh)
- return pathList
+ goto ERR
}
nlri = bgp.NewRouteTargetMembershipNLRI(peerInfo.AS, ec)
@@ -831,13 +858,16 @@ func handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*t
default:
result.ResponseErr = fmt.Errorf("Unsupported address family: %s", rf)
- grpcReq.ResponseCh <- result
- close(grpcReq.ResponseCh)
- return pathList
+ goto ERR
}
- p := table.NewPath(peerInfo, nlri, isWithdraw, pattr, false, time.Now())
+ p = table.NewPath(peerInfo, nlri, isWithdraw, pattr, false, time.Now())
return []*table.Path{p}
+ERR:
+ grpcReq.ResponseCh <- result
+ close(grpcReq.ResponseCh)
+ return []*table.Path{}
+
}
func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg {