diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 70d8ffbcc7..3a3cefda59 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -3390,8 +3390,9 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr); } - if ((afi == AFI_IP || afi == AFI_IP6) && - (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN)) + if (((afi == AFI_IP || afi == AFI_IP6) && + (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN)) || + (afi == AFI_L2VPN && safi == SAFI_EVPN)) { /* Tunnel Encap attribute */ bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP); diff --git a/bgpd/bgp_encap_tlv.c b/bgpd/bgp_encap_tlv.c index 5c18629aa6..8c5ab8d6f6 100644 --- a/bgpd/bgp_encap_tlv.c +++ b/bgpd/bgp_encap_tlv.c @@ -391,8 +391,30 @@ bgp_encap_type_vxlan_to_tlv( struct attr *attr) { struct attr_extra *extra = bgp_attr_extra_get(attr); + struct bgp_attr_encap_subtlv *tlv; + uint32_t vnid; extra->encap_tunneltype = BGP_ENCAP_TYPE_VXLAN; + + if(bet == NULL ||!bet->vnid) + return; + if(extra->encap_subtlvs) + XFREE(MTYPE_ENCAP_TLV, extra->encap_subtlvs); + tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+12); + tlv->type = 1; /* encapsulation type */ + tlv->length = 12; + if(bet->vnid) + { + vnid = htonl(bet->vnid | VXLAN_ENCAP_MASK_VNID_VALID); + memcpy(&tlv->value, &vnid, 4); + } + if(bet->mac_address) + { + char *ptr = (char *)&tlv->value + 4; + memcpy( ptr, bet->mac_address, 6); + } + extra->encap_subtlvs = tlv; + return; } void diff --git a/bgpd/bgp_encap_types.h b/bgpd/bgp_encap_types.h index 0985446ff2..04c0d2f235 100644 --- a/bgpd/bgp_encap_types.h +++ b/bgpd/bgp_encap_types.h @@ -167,10 +167,15 @@ struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode { struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ }; +#define VXLAN_ENCAP_MASK_VNID_VALID 0x80000000 +#define VXLAN_ENCAP_MASK_MAC_VALID 0x40000000 + struct bgp_encap_type_vxlan { uint32_t valid_subtlvs; struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ - /* No subtlvs defined in spec? */ + /* draft-ietf-idr-tunnel-encaps-02 */ + uint32_t vnid; /* does not include V and M bit */ + uint8_t *mac_address; /* optional */ }; struct bgp_encap_type_nvgre { diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f80c24dcba..8487284edb 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -68,8 +68,11 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/rfapi/vnc_import_bgp.h" #include "bgpd/rfapi/vnc_export_bgp.h" #endif +#include "bgpd/bgp_encap_types.h" +#include "bgpd/bgp_encap_tlv.h" #include "bgpd/bgp_evpn.h" + /* Extern from bgp_dump.c */ extern const char *bgp_origin_str[]; extern const char *bgp_origin_long_str[]; @@ -4002,7 +4005,16 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix *p, attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); if(afi == AFI_L2VPN) + { overlay_index_update(&attr, bgp_static->eth_s_id, NULL); + if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) + { + struct bgp_encap_type_vxlan bet; + memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan)); + bet.vnid = p->u.prefix_evpn.eth_tag; + bgp_encap_type_vxlan_to_tlv(&bet, &attr); + } + } /* Apply route-map. */ if (bgp_static->rmap.name) { diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 243c5afb00..20465fbf00 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -207,6 +207,7 @@ struct bgp_static /* EVPN */ struct eth_segment_id *eth_s_id; char *router_mac; + uint16_t encap_tunneltype; }; #define BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen) \