From 76d07c7aa1b5de666d4a0dc55db3fb5e52b8e23d Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Tue, 19 Mar 2019 11:08:24 -0700 Subject: [PATCH] bgpd: maintain flood mcast group per-l2-vni If PIM-SM if used for BUM flooding the multicast group address can be configured per-vxlan-device. BGP receives this config from zebra via the L2 VNI add/update. Sample output - root@TORS1:~# vtysh -c "show bgp l2vpn evpn vni 1000" |grep Mcast Mcast group: 239.1.1.100 root@TORS1:~# Signed-off-by: Anuradha Karuppiah --- bgpd/bgp_evpn.c | 37 +++++++++++++++++++++++++++++++++---- bgpd/bgp_evpn.h | 3 ++- bgpd/bgp_evpn_private.h | 8 ++++++-- bgpd/bgp_evpn_vty.c | 7 ++++++- bgpd/bgp_zebra.c | 4 +++- 5 files changed, 50 insertions(+), 9 deletions(-) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 732cc6d2bb..66b6ad37e8 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -2296,6 +2296,26 @@ static int delete_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) return delete_all_vni_routes(bgp, vpn); } +/* + * There is a flood mcast IP address change. Update the mcast-grp and + * remove the type-3 route if any. A new type-3 route will be generated + * post tunnel_ip update if the new flood mode is head-end-replication. + */ +static int bgp_evpn_mcast_grp_change(struct bgp *bgp, struct bgpevpn *vpn, + struct in_addr mcast_grp) +{ + struct prefix_evpn p; + + vpn->mcast_grp = mcast_grp; + + if (is_vni_live(vpn)) { + build_evpn_type3_prefix(&p, vpn->originator_ip); + delete_evpn_route(bgp, vpn, &p); + } + + return 0; +} + /* * There is a tunnel endpoint IP address change for this VNI, delete * prior type-3 route (if needed) and update. @@ -5138,8 +5158,9 @@ struct bgpevpn *bgp_evpn_lookup_vni(struct bgp *bgp, vni_t vni) * Create a new vpn - invoked upon configuration or zebra notification. */ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni, - struct in_addr originator_ip, - vrf_id_t tenant_vrf_id) + struct in_addr originator_ip, + vrf_id_t tenant_vrf_id, + struct in_addr mcast_grp) { struct bgpevpn *vpn; @@ -5152,6 +5173,7 @@ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni, vpn->vni = vni; vpn->originator_ip = originator_ip; vpn->tenant_vrf_id = tenant_vrf_id; + vpn->mcast_grp = mcast_grp; /* Initialize route-target import and export lists */ vpn->import_rtl = list_new(); @@ -5650,7 +5672,10 @@ int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni) * about are for the local-tunnel-ip and the (tenant) VRF. */ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni, - struct in_addr originator_ip, vrf_id_t tenant_vrf_id) + struct in_addr originator_ip, + vrf_id_t tenant_vrf_id, + struct in_addr mcast_grp) + { struct bgpevpn *vpn; struct prefix_evpn p; @@ -5661,11 +5686,14 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni, if (is_vni_live(vpn) && IPV4_ADDR_SAME(&vpn->originator_ip, &originator_ip) + && IPV4_ADDR_SAME(&vpn->mcast_grp, &mcast_grp) && vpn->tenant_vrf_id == tenant_vrf_id) /* Probably some other param has changed that we don't * care about. */ return 0; + bgp_evpn_mcast_grp_change(bgp, vpn, mcast_grp); + /* Update tenant_vrf_id if it has changed. */ if (vpn->tenant_vrf_id != tenant_vrf_id) { bgpevpn_unlink_from_l3vni(vpn); @@ -5688,7 +5716,8 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni, /* Create or update as appropriate. */ if (!vpn) { - vpn = bgp_evpn_new(bgp, vni, originator_ip, tenant_vrf_id); + vpn = bgp_evpn_new(bgp, vni, originator_ip, tenant_vrf_id, + mcast_grp); if (!vpn) { flog_err( EC_BGP_VNI, diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index f5802fa894..4ad8e95bee 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -180,7 +180,8 @@ extern int bgp_evpn_local_l3vni_del(vni_t vni, vrf_id_t vrf_id); extern int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni); extern int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni, struct in_addr originator_ip, - vrf_id_t tenant_vrf_id); + vrf_id_t tenant_vrf_id, + struct in_addr mcast_grp); extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi, struct ipaddr *originator_ip); extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi, diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index 785139865e..88b57ff9ea 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -87,6 +87,9 @@ struct bgpevpn { /* Route type 3 field */ struct in_addr originator_ip; + /* PIM-SM MDT group for BUM flooding */ + struct in_addr mcast_grp; + /* Import and Export RTs. */ struct list *import_rtl; struct list *export_rtl; @@ -525,8 +528,9 @@ extern void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn); extern void bgp_evpn_derive_auto_rd_for_vrf(struct bgp *bgp); extern struct bgpevpn *bgp_evpn_lookup_vni(struct bgp *bgp, vni_t vni); extern struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni, - struct in_addr originator_ip, - vrf_id_t tenant_vrf_id); + struct in_addr originator_ip, + vrf_id_t tenant_vrf_id, + struct in_addr mcast_grp); extern void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn); extern struct evpnes *bgp_evpn_lookup_es(struct bgp *bgp, esi_t *esi); extern struct evpnes *bgp_evpn_es_new(struct bgp *bgp, esi_t *esi, diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 28ccaada1c..4dccc89f52 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -473,6 +473,8 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json) prefix_rd2str(&vpn->prd, buf1, sizeof(buf1))); json_object_string_add(json, "originatorIp", inet_ntoa(vpn->originator_ip)); + json_object_string_add(json, "mcastGroup", + inet_ntoa(vpn->mcast_grp)); json_object_string_add(json, "advertiseGatewayMacip", vpn->advertise_gw_macip ? "Yes" : "No"); } else { @@ -488,6 +490,8 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json) prefix_rd2str(&vpn->prd, buf1, sizeof(buf1))); vty_out(vty, " Originator IP: %s\n", inet_ntoa(vpn->originator_ip)); + vty_out(vty, " Mcast group: %s\n", + inet_ntoa(vpn->mcast_grp)); vty_out(vty, " Advertise-gw-macip : %s\n", vpn->advertise_gw_macip ? "Yes" : "No"); vty_out(vty, " Advertise-svi-macip : %s\n", @@ -1897,6 +1901,7 @@ static void evpn_unconfigure_rd(struct bgp *bgp, struct bgpevpn *vpn) static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni) { struct bgpevpn *vpn; + struct in_addr mcast_grp = {INADDR_ANY}; if (!bgp->vnihash) return NULL; @@ -1915,7 +1920,7 @@ static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni) /* tenant vrf will be updated when we get local_vni_add from * zebra */ - vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0); + vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0, mcast_grp); if (!vpn) { flog_err( EC_BGP_VNI, diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 55ecc5f16c..e42d6ee260 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -2553,12 +2553,14 @@ static int bgp_zebra_process_local_vni(int command, struct zclient *zclient, struct bgp *bgp; struct in_addr vtep_ip = {INADDR_ANY}; vrf_id_t tenant_vrf_id = VRF_DEFAULT; + struct in_addr mcast_grp = {INADDR_ANY}; s = zclient->ibuf; vni = stream_getl(s); if (command == ZEBRA_VNI_ADD) { vtep_ip.s_addr = stream_get_ipv4(s); stream_get(&tenant_vrf_id, s, sizeof(vrf_id_t)); + mcast_grp.s_addr = stream_get_ipv4(s); } bgp = bgp_lookup_by_vrf_id(vrf_id); @@ -2574,7 +2576,7 @@ static int bgp_zebra_process_local_vni(int command, struct zclient *zclient, if (command == ZEBRA_VNI_ADD) return bgp_evpn_local_vni_add( bgp, vni, vtep_ip.s_addr ? vtep_ip : bgp->router_id, - tenant_vrf_id); + tenant_vrf_id, mcast_grp); else return bgp_evpn_local_vni_del(bgp, vni); }