static void delete_withdraw_vrf_routes(struct bgp *bgp_vrf)
{
/* delete all ipv4 routes and withdraw from peers */
- bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST);
+ if (advertise_type5_routes(bgp_vrf, AFI_IP))
+ bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST);
/* delete all ipv6 routes and withdraw from peers */
- bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST);
+ if (advertise_type5_routes(bgp_vrf, AFI_IP6))
+ bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST);
}
/* update and advertise all ipv4 and ipv6 routes in thr vrf table as type-5
static void update_advertise_vrf_routes(struct bgp *bgp_vrf)
{
/* update all ipv4 routes */
- bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST);
+ if (advertise_type5_routes(bgp_vrf, AFI_IP))
+ bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST);
/* update all ipv6 routes */
- bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST);
+ if (advertise_type5_routes(bgp_vrf, AFI_IP6))
+ bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST);
}
/*
struct prefix_evpn evp;
char buf[PREFIX_STRLEN];
- /* NOTE: Check needed as this is called per-route also. */
- if (!advertise_type5_routes(bgp_vrf, afi))
- return;
-
build_type5_prefix_from_ip_prefix(&evp, p);
ret = delete_evpn_type5_route(bgp_vrf, &evp);
if (ret) {
struct bgp_node *rn = NULL;
struct bgp_info *ri;
- /* Bail out early if we don't have to advertise type-5 routes. */
- if (!advertise_type5_routes(bgp_vrf, afi))
- return;
-
table = bgp_vrf->rib[afi][safi];
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
/* Only care about "selected" routes - non-imported. */
int ret = 0;
struct prefix_evpn evp;
char buf[PREFIX_STRLEN];
-
- /* NOTE: Check needed as this is called per-route also. */
- if (!advertise_type5_routes(bgp_vrf, afi))
- return;
-
+
build_type5_prefix_from_ip_prefix(&evp, p);
ret = update_evpn_type5_route(bgp_vrf, &evp, src_attr);
if (ret)
struct bgp_node *rn = NULL;
struct bgp_info *ri;
- /* Bail out early if we don't have to advertise type-5 routes. */
- if (!advertise_type5_routes(bgp_vrf, afi))
- return;
-
table = bgp_vrf->rib[afi][safi];
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
/* Need to identify the "selected" route entry to use its
return vni;
}
+static inline int advertise_type5_routes(struct bgp *bgp_vrf,
+ afi_t afi)
+{
+ if (!bgp_vrf->l3vni)
+ return 0;
+
+ if (afi == AFI_IP &&
+ CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
+ return 1;
+
+ if (afi == AFI_IP6 &&
+ CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
+ return 1;
+
+ return 0;
+}
+
extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf,
struct prefix *p,
struct attr *src_attr,
}
}
+static inline int is_evpn_prefix_default(struct prefix *evp)
+{
+ if (evp->family != AF_EVPN)
+ return 0;
+
+ return ((evp->u.prefix_evpn.ip_prefix_length == 0) ? 1 : 0);
+}
+
static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp,
struct prefix *ip)
{
p->prefix.ip.ipaddr_v4 = originator_ip;
}
-static inline int advertise_type5_routes(struct bgp *bgp_vrf,
- afi_t afi)
+static inline int evpn_default_originate_set(struct bgp *bgp, afi_t afi,
+ safi_t safi)
{
- if (!bgp_vrf->l3vni)
- return 0;
-
if (afi == AFI_IP &&
- CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN))
+ CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
return 1;
-
- if (afi == AFI_IP6 &&
- CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN))
+ else if (afi == AFI_IP6 &&
+ CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
return 1;
-
return 0;
}
return;
}
+/*
+ * evpn - enable advertisement of default g/w
+ */
+static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
+ afi_t afi, int add)
+{
+ struct prefix ip_prefix;
+ safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
+
+ /* form the default prefix 0.0.0.0/0 */
+ memset(&ip_prefix, 0, sizeof(struct prefix));
+ ip_prefix.family = afi2family(afi);
+ ip_prefix.prefixlen = 0;
+
+ if (add) {
+ /* bail if we are already advertising default route */
+ if (evpn_default_originate_set(bgp_vrf, afi, safi))
+ return;
+
+ if (afi == AFI_IP)
+ SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
+ else if (afi == AFI_IP6)
+ SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
+ bgp_evpn_advertise_type5_route(bgp_vrf, &ip_prefix,
+ NULL, afi, safi);
+ } else {
+ /* bail out if we havent advertised the default route */
+ if (!evpn_default_originate_set(bgp_vrf, afi, safi))
+ return;
+ if (afi == AFI_IP)
+ UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
+ else if (afi == AFI_IP6)
+ UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
+ bgp_evpn_withdraw_type5_route(bgp_vrf, &ip_prefix,
+ afi, safi);
+ }
+}
+
/*
* evpn - enable advertisement of default g/w
*/
return CMD_SUCCESS;
}
+DEFUN (bgp_evpn_default_originate,
+ bgp_evpn_default_originate_cmd,
+ "default-originate <ipv4 | ipv6>",
+ "originate a default route\n"
+ "ipv4 address family\n"
+ "ipv6 address family\n")
+{
+ afi_t afi = 0;
+ int idx_afi = 0;
+ struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
+
+ if (!bgp_vrf)
+ return CMD_WARNING;
+ argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
+ evpn_process_default_originate_cmd(bgp_vrf, afi, 1);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_evpn_default_originate,
+ no_bgp_evpn_default_originate_cmd,
+ "no default-originate <ipv4 | ipv6>",
+ NO_STR
+ "withdraw a default route\n"
+ "ipv4 address family\n"
+ "ipv6 address family\n")
+{
+ afi_t afi = 0;
+ int idx_afi = 0;
+ struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
+
+ if (!bgp_vrf)
+ return CMD_WARNING;
+ argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
+ evpn_process_default_originate_cmd(bgp_vrf, afi, 0);
+ return CMD_SUCCESS;
+}
+
DEFUN (bgp_evpn_advertise_vni_subnet,
bgp_evpn_advertise_vni_subnet_cmd,
"advertise-subnet",
if (!bgp_vrf)
return CMD_WARNING;
- if (!(advertise_type5_routes(bgp_vrf, AFI_IP) ||
- advertise_type5_routes(bgp_vrf, AFI_IP6))) {
- vty_out(vty,
- "%%Please enable ip prefix advertisement under l2vpn evpn in %s",
- vrf_id_to_name(bgp_vrf->vrf_id));
- return CMD_WARNING;
- }
-
evpn_set_advertise_subnet(bgp, vpn);
return CMD_SUCCESS;
}
/* if we are already advertising ipv4 prefix as type-5
* nothing to do
*/
- if (!rmap_changed && CHECK_FLAG(bgp_vrf->vrf_flags,
- BGP_VRF_ADVERTISE_IPV4_IN_EVPN))
+ if (!rmap_changed &&
+ CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
return CMD_WARNING;
- SET_FLAG(bgp_vrf->vrf_flags,
- BGP_VRF_ADVERTISE_IPV4_IN_EVPN);
+ SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
} else {
/* if we are already advertising ipv6 prefix as type-5
* nothing to do
*/
- if (!rmap_changed && CHECK_FLAG(bgp_vrf->vrf_flags,
- BGP_VRF_ADVERTISE_IPV6_IN_EVPN))
+ if (!rmap_changed &&
+ CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
return CMD_WARNING;
- SET_FLAG(bgp_vrf->vrf_flags,
- BGP_VRF_ADVERTISE_IPV6_IN_EVPN);
+ SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
}
if (rmap_changed) {
if (afi == AFI_IP) {
- /* if we are already advertising ipv4 prefix as type-5
+ /* if we are not advertising ipv4 prefix as type-5
* nothing to do
*/
- if (CHECK_FLAG(bgp_vrf->vrf_flags,
- BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) {
+ if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
- UNSET_FLAG(bgp_vrf->vrf_flags,
- BGP_VRF_ADVERTISE_IPV4_IN_EVPN);
+ UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
}
} else {
- /* if we are already advertising ipv6 prefix as type-5
+ /* if we are not advertising ipv6 prefix as type-5
* nothing to do
*/
- if (CHECK_FLAG(bgp_vrf->vrf_flags,
- BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) {
+ if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
UNSET_FLAG(bgp_vrf->vrf_flags,
- BGP_VRF_ADVERTISE_IPV6_IN_EVPN);
+ BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
}
}
if (bgp->advertise_gw_macip)
vty_out(vty, " advertise-default-gw\n");
- if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN))
+ if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
vty_out(vty, " advertise ipv4 unicast\n");
- if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN))
+ if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
vty_out(vty, " advertise ipv6 unicast\n");
+ if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
+ vty_out(vty, " default-originate ipv4\n");
+
+ if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
+ vty_out(vty, " default-originate ipv6\n");
+
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
vty_out(vty, " rd %s\n",
prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
+ install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
+ install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
/* "show bgp l2vpn evpn" commands. */
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
/* advertise/withdraw type-5 routes */
if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
- if (new_select &&
+ if (advertise_type5_routes(bgp, afi) && new_select &&
(!new_select->extra || !new_select->extra->parent))
bgp_evpn_advertise_type5_route(bgp, &rn->p,
new_select->attr,
afi, safi);
- else if (old_select &&
+ else if (advertise_type5_routes(bgp, afi) && old_select &&
(!old_select->extra || !old_select->extra->parent))
bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
}
route_match_ip_route_source_prefix_list_compile,
route_match_ip_route_source_prefix_list_free};
+/* `match evpn default-route' */
+
+/* Match function should return 1 if match is success else 0 */
+static route_map_result_t route_match_evpn_default_route(void *rule,
+ struct prefix *p,
+ route_map_object_t
+ type, void *object)
+{
+ if (type == RMAP_BGP && is_evpn_prefix_default(p))
+ return RMAP_MATCH;
+
+ return RMAP_NOMATCH;
+}
+
+/* Route map commands for default-route matching. */
+struct route_map_rule_cmd route_match_evpn_default_route_cmd = {
+ "evpn default-route", route_match_evpn_default_route, NULL, NULL};
+
/* `match mac address MAC_ACCESS_LIST' */
/* Match function should return 1 if match is success else return
RMAP_EVENT_MATCH_DELETED);
}
+DEFUN (match_evpn_default_route,
+ match_evpn_default_route_cmd,
+ "match evpn default-route",
+ MATCH_STR
+ EVPN_HELP_STR
+ "default EVPN type-5 route\n")
+{
+ return bgp_route_match_add(vty, "evpn default-route", NULL,
+ RMAP_EVENT_MATCH_ADDED);
+}
+
+DEFUN (no_match_evpn_default_route,
+ no_match_evpn_default_route_cmd,
+ "no match evpn default-route",
+ NO_STR
+ MATCH_STR
+ EVPN_HELP_STR
+ "default EVPN type-5 route\n")
+{
+ return bgp_route_match_delete(vty, "evpn default-route", NULL,
+ RMAP_EVENT_MATCH_DELETED);
+}
+
DEFUN (match_peer,
match_peer_cmd,
"match peer <A.B.C.D|X:X::X:X|WORD>",
route_map_install_match(&route_match_mac_address_cmd);
route_map_install_match(&route_match_evpn_vni_cmd);
route_map_install_match(&route_match_evpn_route_type_cmd);
+ route_map_install_match(&route_match_evpn_default_route_cmd);
route_map_install_set(&route_set_ip_nexthop_cmd);
route_map_install_set(&route_set_local_pref_cmd);
install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
install_element(RMAP_NODE, &match_evpn_route_type_cmd);
install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
+ install_element(RMAP_NODE, &match_evpn_default_route_cmd);
+ install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
install_element(RMAP_NODE, &match_aspath_cmd);
install_element(RMAP_NODE, &no_match_aspath_cmd);
u_int16_t af_flags[AFI_MAX][SAFI_MAX];
#define BGP_CONFIG_DAMPENING (1 << 0)
+/* l2vpn evpn flags - 1 << 0 is used for DAMPENNG */
+#define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST (1 << 1)
+#define BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST (1 << 2)
+#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4 (1 << 3)
+#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6 (1 << 4)
+
+
/* Route table for next-hop lookup cache. */
struct bgp_table *nexthop_cache_table[AFI_MAX];
/* vrf flags */
uint32_t vrf_flags;
#define BGP_VRF_AUTO (1 << 0)
-#define BGP_VRF_ADVERTISE_IPV4_IN_EVPN (1 << 1)
-#define BGP_VRF_ADVERTISE_IPV6_IN_EVPN (1 << 2)
-#define BGP_VRF_IMPORT_RT_CFGD (1 << 3)
-#define BGP_VRF_EXPORT_RT_CFGD (1 << 4)
-#define BGP_VRF_RD_CFGD (1 << 5)
-#define BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY (1 << 6)
+#define BGP_VRF_IMPORT_RT_CFGD (1 << 1)
+#define BGP_VRF_EXPORT_RT_CFGD (1 << 2)
+#define BGP_VRF_RD_CFGD (1 << 3)
+#define BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY (1 << 4)
+
/* unique ID for auto derivation of RD for this vrf */
uint16_t vrf_rd_id;