* 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;
add ? "ADD" : "DEL", vpn->vni);
return -1;
}
+ stream_putl(s, flood_control);
stream_putw_at(s, 0, stream_get_endp(s));
{
int ret;
uint8_t flags;
+ int flood_control;
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
flags = 0;
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;
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;
}
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
*
* 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)
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.
*
* 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 */
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);
*/
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);
}
}
if (addpath_encoded) {
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
addpath_id = ntohl(*((uint32_t *)pnt));
pnt += BGP_ADDPATH_ID_LEN;
/* All EVPN NLRI types start with type and length. */
if (pnt + 2 > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_MISSING_TYPE;
rtype = *pnt++;
psize = *pnt++;
/* When packet overflow occur return immediately. */
if (pnt + psize > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
switch (rtype) {
case BGP_EVPN_MAC_IP_ROUTE:
EC_BGP_EVPN_FAIL,
"%u:%s - Error in processing EVPN type-2 NLRI size %d",
peer->bgp->vrf_id, peer->host, psize);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_TYPE2_SIZE;
}
break;
EC_BGP_PKT_PROCESS,
"%u:%s - Error in processing EVPN type-3 NLRI size %d",
peer->bgp->vrf_id, peer->host, psize);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_TYPE3_SIZE;
}
break;
EC_BGP_PKT_PROCESS,
"%u:%s - Error in processing EVPN type-4 NLRI size %d",
peer->bgp->vrf_id, peer->host, psize);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_TYPE4_SIZE;
}
break;
EC_BGP_PKT_PROCESS,
"%u:%s - Error in processing EVPN type-5 NLRI size %d",
peer->bgp->vrf_id, peer->host, psize);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_TYPE5_SIZE;
}
break;
/* Packet length consistency check. */
if (pnt != lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
- return 0;
+ return BGP_NLRI_PARSE_OK;
}
/*
* 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;
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();
* 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;
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);
/* 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,
*
* 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,
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
next = pi->next;
+
+ /* Unimport EVPN routes from VRFs */
+ if (safi == SAFI_EVPN)
+ bgp_evpn_unimport_route(bgp, AFI_L2VPN,
+ SAFI_EVPN,
+ &rn->p, pi);
+
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
&& pi->type == ZEBRA_ROUTE_BGP
&& (pi->sub_type == BGP_ROUTE_NORMAL
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
addpath_id = ntohl(*((uint32_t *)pnt));
pnt += BGP_ADDPATH_ID_LEN;
EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error (wrong prefix length %d for afi %u)",
peer->host, p.prefixlen, packet->afi);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
}
/* Packet size overflow check. */
EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error (prefix length %d overflows packet)",
peer->host, p.prefixlen);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
}
/* Defensive coding, double-check the psize fits in a struct
EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
peer->host, p.prefixlen, sizeof(p.u));
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
/* Fetch prefix from NLRI packet. */
BGP_ROUTE_NORMAL, NULL, NULL, 0,
NULL);
- /* Address family configuration mismatch or maximum-prefix count
- overflow. */
+ /* Do not send BGP notification twice when maximum-prefix count
+ * overflow. */
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
+ return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
+
+ /* Address family configuration mismatch. */
if (ret < 0)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
}
/* Packet length consistency check. */
EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error (prefix length mismatch with total length)",
peer->host);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
- return 0;
+ return BGP_NLRI_PARSE_OK;
}
static struct bgp_static *bgp_static_new(void)
BGP_AFI_HELP_STR
BGP_SAFI_WITH_LABEL_HELP_STR
"Display routes matching the AS path regular expression\n"
- "A regular-expression to match the BGP AS paths\n")
+ "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
{
afi_t afi = AFI_IP6;
safi_t safi = SAFI_UNICAST;
regex_t *regex;
int rc;
+ if (!config_bgp_aspath_validate(regstr)) {
+ vty_out(vty, "Invalid character in as-path access-list %s\n",
+ regstr);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
regex = bgp_regcomp(regstr);
if (!regex) {
vty_out(vty, "Can't compile regexp %s\n", regstr);