summaryrefslogtreecommitdiff
path: root/bgpd/bgp_evpn.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_evpn.c')
-rw-r--r--bgpd/bgp_evpn.c103
1 files changed, 86 insertions, 17 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 732cc6d2bb..5d191a787c 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -609,7 +609,8 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
* Add (update) or delete remote VTEP from zebra.
*/
static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
- struct prefix_evpn *p, int add)
+ struct prefix_evpn *p,
+ int flood_control, int add)
{
struct stream *s;
@@ -641,6 +642,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
add ? "ADD" : "DEL", vpn->vni);
return -1;
}
+ stream_putl(s, flood_control);
stream_putw_at(s, 0, stream_get_endp(s));
@@ -889,6 +891,7 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
{
int ret;
uint8_t flags;
+ int flood_control;
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
flags = 0;
@@ -903,7 +906,20 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
bgp, vpn, p, pi->attr->nexthop, 1, flags,
mac_mobility_seqnum(pi->attr));
} else {
- ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 1);
+ switch (pi->attr->pmsi_tnl_type) {
+ case PMSI_TNLTYPE_INGR_REPL:
+ flood_control = VXLAN_FLOOD_HEAD_END_REPL;
+ break;
+
+ case PMSI_TNLTYPE_PIM_SM:
+ flood_control = VXLAN_FLOOD_PIM_SM;
+ break;
+
+ default:
+ flood_control = VXLAN_FLOOD_DISABLED;
+ break;
+ }
+ ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, flood_control, 1);
}
return ret;
@@ -920,7 +936,8 @@ static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip,
0, 0, 0);
else
- ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 0);
+ ret = bgp_zebra_send_remote_vtep(bgp, vpn, p,
+ VXLAN_FLOOD_DISABLED, 0);
return ret;
}
@@ -2220,6 +2237,24 @@ static int delete_all_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
return 0;
}
+/* BUM traffic flood mode per-l2-vni */
+static int bgp_evpn_vni_flood_mode_get(struct bgp *bgp,
+ struct bgpevpn *vpn)
+{
+ /* if flooding has been globally disabled per-vni mode is
+ * not relevant
+ */
+ if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
+ return VXLAN_FLOOD_DISABLED;
+
+ /* if mcast group ip has been specified we use a PIM-SM MDT */
+ if (vpn->mcast_grp.s_addr != INADDR_ANY)
+ return VXLAN_FLOOD_PIM_SM;
+
+ /* default is ingress replication */
+ return VXLAN_FLOOD_HEAD_END_REPL;
+}
+
/*
* Update (and advertise) local routes for a VNI. Invoked upon the VNI
* export RT getting modified or change to tunnel IP. Note that these
@@ -2236,7 +2271,8 @@ static int update_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
*
* RT-3 only if doing head-end replication
*/
- if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL) {
+ if (bgp_evpn_vni_flood_mode_get(bgp, vpn)
+ == VXLAN_FLOOD_HEAD_END_REPL) {
build_evpn_type3_prefix(&p, vpn->originator_ip);
ret = update_evpn_route(bgp, vpn, &p, 0, 0);
if (ret)
@@ -2297,6 +2333,26 @@ static int delete_routes_for_vni(struct bgp *bgp, struct bgpevpn *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.
* Note: Route re-advertisement happens elsewhere after other processing
@@ -3538,7 +3594,8 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
*
* RT-3 only if doing head-end replication
*/
- if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL) {
+ if (bgp_evpn_vni_flood_mode_get(bgp, vpn)
+ == VXLAN_FLOOD_HEAD_END_REPL) {
build_evpn_type3_prefix(&p, vpn->originator_ip);
rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
if (!rn) /* unexpected */
@@ -3684,7 +3741,9 @@ static void create_advertise_type3(struct hash_bucket *bucket, void *data)
struct bgp *bgp = data;
struct prefix_evpn p;
- if (!vpn || !is_vni_live(vpn))
+ if (!vpn || !is_vni_live(vpn) ||
+ bgp_evpn_vni_flood_mode_get(bgp, vpn)
+ != VXLAN_FLOOD_HEAD_END_REPL)
return;
build_evpn_type3_prefix(&p, vpn->originator_ip);
@@ -3858,12 +3917,12 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi,
*/
if (attr &&
(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL))) {
- if (attr->pmsi_tnl_type != PMSI_TNLTYPE_INGR_REPL) {
- flog_warn(
- EC_BGP_EVPN_PMSI_PRESENT,
- "%u:%s - Rx EVPN Type-3 NLRI with unsupported PTA %d",
- peer->bgp->vrf_id, peer->host,
- attr->pmsi_tnl_type);
+ if (attr->pmsi_tnl_type != PMSI_TNLTYPE_INGR_REPL &&
+ attr->pmsi_tnl_type != PMSI_TNLTYPE_PIM_SM) {
+ flog_warn(EC_BGP_EVPN_PMSI_PRESENT,
+ "%u:%s - Rx EVPN Type-3 NLRI with unsupported PTA %d",
+ peer->bgp->vrf_id, peer->host,
+ attr->pmsi_tnl_type);
}
}
@@ -5138,8 +5197,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 +5212,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 +5711,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 +5725,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 +5755,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,
@@ -5716,7 +5784,8 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
*
* RT-3 only if doing head-end replication
*/
- if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL) {
+ if (bgp_evpn_vni_flood_mode_get(bgp, vpn)
+ == VXLAN_FLOOD_HEAD_END_REPL) {
build_evpn_type3_prefix(&p, vpn->originator_ip);
if (update_evpn_route(bgp, vpn, &p, 0, 0)) {
flog_err(EC_BGP_EVPN_ROUTE_CREATE,