From 31310b25f20260b66ab7a4ce726f57d815424867 Mon Sep 17 00:00:00 2001 From: Mitesh Kanjariya Date: Sun, 19 Nov 2017 21:47:04 -0800 Subject: [PATCH] bgpd: advertise VNI subnet In EVPN symmetric routing, not all subnets are presents everywhere. We have multiple scenarios where a host might not get learned locally. 1. GARP miss 2. SVI down/up 3. Silent host We need a mechanism to resolve such hosts. In order to achieve this, we will be advertising a subnet route from a box and that box will help in resolving the ARP to such hosts. Signed-off-by: Mitesh Kanjariya --- bgpd/bgp_evpn.c | 27 +++---- bgpd/bgp_evpn.h | 4 +- bgpd/bgp_evpn_private.h | 3 + bgpd/bgp_evpn_vty.c | 82 +++++++++++++++++++++ bgpd/bgp_route.c | 4 +- bgpd/bgp_zebra.c | 72 +++++++++++++++++++ bgpd/bgp_zebra.h | 3 +- lib/log.c | 3 + lib/zclient.c | 10 +++ lib/zclient.h | 5 ++ zebra/zebra_vxlan.c | 137 ++++++++++++++++++++++++++++++++++++ zebra/zebra_vxlan.h | 2 + zebra/zebra_vxlan_private.h | 3 + zebra/zserv.c | 3 + zebra/zserv.h | 2 + 15 files changed, 342 insertions(+), 18 deletions(-) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index b20076d471..1a9b26764c 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -3188,20 +3188,20 @@ static void bgp_evpn_handle_export_rt_change_for_vrf(struct bgp *bgp_vrf) */ /* withdraw type-5 route corresponding to ip prefix */ -void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, struct bgp_node *rn, +void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, struct prefix *p, afi_t afi, safi_t safi) { int ret = 0; struct prefix_evpn evp; char buf[PREFIX_STRLEN]; - build_type5_prefix_from_ip_prefix(&evp, &rn->p); + build_type5_prefix_from_ip_prefix(&evp, p); ret = delete_evpn_type5_route(bgp_vrf, &evp); if (ret) { zlog_err( "%u failed to delete type-5 route for prefix %s in vrf %s", bgp_vrf->vrf_id, - prefix2str(&rn->p, buf, sizeof(buf)), + prefix2str(p, buf, sizeof(buf)), vrf_id_to_name(bgp_vrf->vrf_id)); } } @@ -3218,12 +3218,12 @@ void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, table = bgp_vrf->rib[afi][safi]; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) - bgp_evpn_withdraw_type5_route(bgp_vrf, rn, afi, safi); + bgp_evpn_withdraw_type5_route(bgp_vrf, &rn->p, afi, safi); } /* advertise ip prefix as type-5 route*/ -void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct bgp_node *rn, +void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct prefix *p, afi_t afi, safi_t safi) { int ret = 0; @@ -3233,20 +3233,17 @@ void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct bgp_node *rn, if (!advertise_type5_routes(bgp_vrf, afi)) return; - if (!rn->info) - return; - /* only advertise subnet routes as type-5 */ - if (is_host_route(&rn->p)) + if (is_host_route(p)) return; - build_type5_prefix_from_ip_prefix(&evp, &rn->p); + build_type5_prefix_from_ip_prefix(&evp, p); ret = update_evpn_type5_route(bgp_vrf, &evp); if (ret) { zlog_err( "%u failed to create type-5 route for prefix %s in vrf %s", bgp_vrf->vrf_id, - prefix2str(&rn->p, buf, sizeof(buf)), + prefix2str(p, buf, sizeof(buf)), vrf_id_to_name(bgp_vrf->vrf_id)); } } @@ -3259,8 +3256,12 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, struct bgp_node *rn = NULL; table = bgp_vrf->rib[afi][safi]; - for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) - bgp_evpn_advertise_type5_route(bgp_vrf, rn, afi, safi); + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + + if (!rn->info) + continue; + bgp_evpn_advertise_type5_route(bgp_vrf, &rn->p, afi, safi); + } } void evpn_rt_delete_auto(struct bgp *bgp, vni_t vni, diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index b3b61db141..cff9d65468 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -56,10 +56,10 @@ static inline vni_t label2vni(mpls_label_t *label) } extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, - struct bgp_node *rn, + struct prefix *p, afi_t afi, safi_t safi); extern void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, - struct bgp_node *rn, + struct prefix *p, afi_t afi, safi_t safi); extern void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, afi_t afi, safi_t safi); diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index 6003e03f35..cc0ec82344 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -65,6 +65,9 @@ struct bgpevpn { /* Flag to indicate if we are advertising the g/w mac ip for this VNI*/ u_int8_t advertise_gw_macip; + /* Flag to indicate if we are advertising subnet for this VNI */ + u_int8_t advertise_subnet; + /* Id for deriving the RD automatically for this VNI */ u_int16_t rd_id; diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index b463896c49..932046f7e0 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -2271,6 +2271,32 @@ static void evpn_unset_advertise_default_gw(struct bgp *bgp, return; } +/* + * evpn - enable advertisement of default g/w + */ +static void evpn_set_advertise_subnet(struct bgp *bgp, + struct bgpevpn *vpn) +{ + if (vpn->advertise_subnet) + return; + + vpn->advertise_subnet = 1; + bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni); +} + +/* + * evpn - disable advertisement of default g/w + */ +static void evpn_unset_advertise_subnet(struct bgp *bgp, + struct bgpevpn *vpn) +{ + if (!vpn->advertise_subnet) + return; + + vpn->advertise_subnet = 0; + bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni); +} + /* * EVPN (VNI advertisement) enabled. Register with zebra. */ @@ -2330,6 +2356,9 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn) if (vpn->advertise_gw_macip) vty_out(vty, " advertise-default-gw\n"); + if (vpn->advertise_subnet) + vty_out(vty, " advertise-subnet\n"); + vty_out(vty, " exit-vni\n"); } } @@ -2440,6 +2469,56 @@ DEFUN (no_bgp_evpn_advertise_all_vni, return CMD_SUCCESS; } +DEFUN (bgp_evpn_advertise_vni_subnet, + bgp_evpn_advertise_vni_subnet_cmd, + "advertise-subnet", + "Advertise the subnet corresponding to VNI\n") +{ + struct bgp *bgp_vrf = NULL; + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn); + + if (!bgp) + return CMD_WARNING; + + if (!vpn) + return CMD_WARNING; + + bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id); + 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; +} + +DEFUN (no_bgp_evpn_advertise_vni_subnet, + no_bgp_evpn_advertise_vni_subnet_cmd, + "no advertise-subnet", + NO_STR + "Advertise All local VNIs\n") +{ + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn); + + if (!bgp) + return CMD_WARNING; + + if (!vpn) + return CMD_WARNING; + + evpn_unset_advertise_subnet(bgp, vpn); + return CMD_SUCCESS; +} + DEFUN (bgp_evpn_advertise_type5, bgp_evpn_advertise_type5_cmd, "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR, @@ -4118,5 +4197,8 @@ void bgp_ethernetvpn_init(void) &bgp_evpn_advertise_default_gw_vni_cmd); install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_advertise_default_gw_vni_cmd); + install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd); + install_element(BGP_EVPN_VNI_NODE, + &no_bgp_evpn_advertise_vni_subnet_cmd); #endif } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 234bde418b..7ee84c3531 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2226,9 +2226,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, /* advertise/withdraw type-5 routes */ if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { if (new_select) - bgp_evpn_advertise_type5_route(bgp, rn, afi, safi); + bgp_evpn_advertise_type5_route(bgp, &rn->p, afi, safi); else if (old_select) - bgp_evpn_withdraw_type5_route(bgp, rn, afi, safi); + bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi); } /* Clear any route change flags. */ diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 2a35645ee8..970b3eefbf 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1635,6 +1635,29 @@ void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer) zclient_send_interface_radv_req(zclient, bgp->vrf_id, peer->ifp, 0, 0); } +int bgp_zebra_advertise_subnet(struct bgp *bgp, int advertise, vni_t vni) +{ + struct stream *s = NULL; + + /* Check socket. */ + if (!zclient || zclient->sock < 0) + return 0; + + /* Don't try to register if Zebra doesn't know of this instance. */ + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + return 0; + + s = zclient->obuf; + stream_reset(s); + + zclient_create_header(s, ZEBRA_ADVERTISE_SUBNET, bgp->vrf_id); + stream_putc(s, advertise); + stream_put3(s, vni); + stream_putw_at(s, 0, stream_get_endp(s)); + + return zclient_send_message(zclient); +} + int bgp_zebra_advertise_gw_macip(struct bgp *bgp, int advertise, vni_t vni) { struct stream *s = NULL; @@ -1821,6 +1844,53 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient, return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip); } +static void bgp_zebra_process_local_ip_prefix(int cmd, + struct zclient *zclient, + zebra_size_t length, + vrf_id_t vrf_id) +{ + struct stream *s = NULL; + struct bgp *bgp_vrf = NULL; + struct prefix p; + char buf[PREFIX_STRLEN]; + + memset(&p, 0, sizeof(struct prefix)); + s = zclient->ibuf; + stream_get(&p, s, sizeof(struct prefix)); + + bgp_vrf = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp_vrf) + return; + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Recv prefix %s %s on vrf %s", + prefix2str(&p, buf, sizeof(buf)), + (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) ? "ADD" : "DEL", + vrf_id_to_name(vrf_id)); + + if (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) { + + if (p.family == AF_INET) + return bgp_evpn_advertise_type5_route(bgp_vrf, &p, + AFI_IP, + SAFI_UNICAST); + else + return bgp_evpn_advertise_type5_route(bgp_vrf, &p, + AFI_IP6, + SAFI_UNICAST); + + } else { + if (p.family == AF_INET) + return bgp_evpn_withdraw_type5_route(bgp_vrf, &p, + AFI_IP, + SAFI_UNICAST); + else + return bgp_evpn_withdraw_type5_route(bgp_vrf, &p, + AFI_IP6, + SAFI_UNICAST); + } +} + extern struct zebra_privs_t bgpd_privs; void bgp_zebra_init(struct thread_master *master) @@ -1853,6 +1923,8 @@ void bgp_zebra_init(struct thread_master *master) zclient->local_macip_del = bgp_zebra_process_local_macip; zclient->local_l3vni_add = bgp_zebra_process_local_l3vni; zclient->local_l3vni_del = bgp_zebra_process_local_l3vni; + zclient->local_ip_prefix_add = bgp_zebra_process_local_ip_prefix; + zclient->local_ip_prefix_del = bgp_zebra_process_local_ip_prefix; } void bgp_zebra_destroy(void) diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index 7d37864f44..da5160bc16 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -58,7 +58,8 @@ extern struct interface *if_lookup_by_ipv6(struct in6_addr *, ifindex_t, vrf_id_t); extern struct interface *if_lookup_by_ipv6_exact(struct in6_addr *, ifindex_t, vrf_id_t); - +extern int bgp_zebra_advertise_subnet(struct bgp *bgp, int advertise, + vni_t vni); extern int bgp_zebra_advertise_gw_macip(struct bgp *, int, vni_t); extern int bgp_zebra_advertise_all_vni(struct bgp *, int); diff --git a/lib/log.c b/lib/log.c index bf65ac7c7d..66be533e84 100644 --- a/lib/log.c +++ b/lib/log.c @@ -943,6 +943,7 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_RELEASE_LABEL_CHUNK), DESC_ENTRY(ZEBRA_ADVERTISE_ALL_VNI), DESC_ENTRY(ZEBRA_ADVERTISE_DEFAULT_GW), + DESC_ENTRY(ZEBRA_ADVERTISE_SUBNET), DESC_ENTRY(ZEBRA_VNI_ADD), DESC_ENTRY(ZEBRA_VNI_DEL), DESC_ENTRY(ZEBRA_L3VNI_ADD), @@ -951,6 +952,8 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_REMOTE_VTEP_DEL), DESC_ENTRY(ZEBRA_MACIP_ADD), DESC_ENTRY(ZEBRA_MACIP_DEL), + DESC_ENTRY(ZEBRA_IP_PREFIX_ROUTE_ADD), + DESC_ENTRY(ZEBRA_IP_PREFIX_ROUTE_DEL), DESC_ENTRY(ZEBRA_REMOTE_MACIP_ADD), DESC_ENTRY(ZEBRA_REMOTE_MACIP_DEL), DESC_ENTRY(ZEBRA_PW_ADD), diff --git a/lib/zclient.c b/lib/zclient.c index a4bd2bda32..a4fa0966a7 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -2234,6 +2234,16 @@ static int zclient_read(struct thread *thread) (*zclient->local_macip_del)(command, zclient, length, vrf_id); break; + case ZEBRA_IP_PREFIX_ROUTE_ADD: + if (zclient->local_ip_prefix_add) + (*zclient->local_ip_prefix_add)(command, zclient, + length, vrf_id); + break; + case ZEBRA_IP_PREFIX_ROUTE_DEL: + if (zclient->local_ip_prefix_del) + (*zclient->local_ip_prefix_del)(command, zclient, + length, vrf_id); + break; case ZEBRA_PW_STATUS_UPDATE: if (zclient->pw_status_update) (*zclient->pw_status_update)(command, zclient, length, diff --git a/lib/zclient.h b/lib/zclient.h index 892e0ea994..8554f3e39d 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -109,6 +109,7 @@ typedef enum { ZEBRA_FEC_UNREGISTER, ZEBRA_FEC_UPDATE, ZEBRA_ADVERTISE_DEFAULT_GW, + ZEBRA_ADVERTISE_SUBNET, ZEBRA_ADVERTISE_ALL_VNI, ZEBRA_VNI_ADD, ZEBRA_VNI_DEL, @@ -118,6 +119,8 @@ typedef enum { ZEBRA_REMOTE_VTEP_DEL, ZEBRA_MACIP_ADD, ZEBRA_MACIP_DEL, + ZEBRA_IP_PREFIX_ROUTE_ADD, + ZEBRA_IP_PREFIX_ROUTE_DEL, ZEBRA_REMOTE_MACIP_ADD, ZEBRA_REMOTE_MACIP_DEL, ZEBRA_PW_ADD, @@ -204,6 +207,8 @@ struct zclient { int (*local_vni_del)(int, struct zclient *, uint16_t, vrf_id_t); int (*local_l3vni_add)(int, struct zclient *, uint16_t, vrf_id_t); int (*local_l3vni_del)(int, struct zclient *, uint16_t, vrf_id_t); + void (*local_ip_prefix_add)(int, struct zclient *, uint16_t, vrf_id_t); + void (*local_ip_prefix_del)(int, struct zclient *, uint16_t, vrf_id_t); int (*local_macip_add)(int, struct zclient *, uint16_t, vrf_id_t); int (*local_macip_del)(int, struct zclient *, uint16_t, vrf_id_t); int (*pw_status_update)(int, struct zclient *, uint16_t, vrf_id_t); diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 1d70e970ec..6b92d80953 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -59,6 +59,9 @@ DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "VNI Neighbor"); /* static function declarations */ +static int ip_prefix_send_to_client(vrf_id_t vrf_id, + struct prefix *p, + uint16_t cmd); static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json); static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt); static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet, @@ -1710,7 +1713,37 @@ static int zvni_add_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni) zvni_gw_macip_add(ifp, zvni, &macaddr, &ip); } + return 0; +} + + +static int zvni_advertise_subnet(zebra_vni_t *zvni, + struct interface *ifp, + int advertise) +{ + struct listnode *cnode = NULL, *cnnode = NULL; + struct connected *c = NULL; + struct ethaddr macaddr; + + memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN); + + for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) { + struct prefix p; + memcpy(&p, c->address, sizeof(struct prefix)); + + /* skip link local address */ + if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) + continue; + + apply_mask(&p); + if (advertise) + ip_prefix_send_to_client(ifp->vrf_id, &p, + ZEBRA_IP_PREFIX_ROUTE_ADD); + else + ip_prefix_send_to_client(ifp->vrf_id, &p, + ZEBRA_IP_PREFIX_ROUTE_DEL); + } return 0; } @@ -3749,6 +3782,43 @@ static void zl3vni_del_nh_hash_entry(struct hash_backet *backet, zl3vni_nh_del(zl3vni, n); } +static int ip_prefix_send_to_client(vrf_id_t vrf_id, + struct prefix *p, + uint16_t cmd) +{ + struct zserv *client = NULL; + struct stream *s = NULL; + char buf[PREFIX_STRLEN]; + + client = zebra_find_client(ZEBRA_ROUTE_BGP); + /* BGP may not be running. */ + if (!client) + return 0; + + s = client->obuf; + stream_reset(s); + + zserv_create_header(s, cmd, vrf_id); + stream_put(s, p, sizeof(struct prefix)); + + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "Send ip prefix %s %s on vrf %s", + prefix2str(p, buf, sizeof(buf)), + (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) ? "ADD" : "DEL", + vrf_id_to_name(vrf_id)); + + if (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) + client->prefixadd_cnt++; + else + client->prefixdel_cnt++; + + return zebra_server_send_message(client); +} + /* Public functions */ /* handle evpn route in vrf table */ @@ -6461,6 +6531,73 @@ int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf) return 0; } +/* + * Handle message from client to enable/disable advertisement of g/w macip + * routes + */ +int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) +{ + struct stream *s; + int advertise; + vni_t vni = 0; + zebra_vni_t *zvni = NULL; + struct interface *ifp = NULL; + struct zebra_if *zif = NULL; + struct zebra_l2info_vxlan zl2_info; + struct interface *vlan_if = NULL; + + if (zvrf_id(zvrf) != VRF_DEFAULT) { + zlog_err("EVPN GW-MACIP Adv for non-default VRF %u", + zvrf_id(zvrf)); + return -1; + } + + s = client->ibuf; + advertise = stream_getc(s); + vni = stream_get3(s); + + zvni = zvni_lookup(vni); + if (!zvni) + return 0; + + if (zvni->advertise_subnet == advertise) + return 0; + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "EVPN subnet Adv %s on VNI %d , currently %s", + advertise ? "enabled" : "disabled", vni, + zvni->advertise_subnet ? "enabled" : "disabled"); + + + zvni->advertise_subnet = advertise; + + ifp = zvni->vxlan_if; + if (!ifp) + return 0; + + zif = ifp->info; + + /* If down or not mapped to a bridge, we're done. */ + if (!if_is_operative(ifp) || !zif->brslave_info.br_if) + return 0; + + zl2_info = zif->l2info.vxl; + + vlan_if = zvni_map_to_svi(zl2_info.access_vlan, + zif->brslave_info.br_if); + if (!vlan_if) + return 0; + + if (zvni->advertise_subnet) + zvni_advertise_subnet(zvni, vlan_if, 1); + else + zvni_advertise_subnet(zvni, vlan_if, 0); + + return 0; +} + /* * Handle message from client to enable/disable advertisement of g/w macip * routes diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index b7def6acf8..4e1eedd0dc 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -140,6 +140,8 @@ extern int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, struct zebra_vrf *zvrf); extern int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, struct zebra_vrf *zvrf); +extern int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length, + struct zebra_vrf *zvrf); extern int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, struct zebra_vrf *zvrf); diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h index ecbdbfd835..8d34b3e2f1 100644 --- a/zebra/zebra_vxlan_private.h +++ b/zebra/zebra_vxlan_private.h @@ -70,6 +70,9 @@ struct zebra_vni_t_ { /* Flag for advertising gw macip */ u_int8_t advertise_gw_macip; + /* Flag for advertising gw macip */ + u_int8_t advertise_subnet; + /* Corresponding VxLAN interface. */ struct interface *vxlan_if; diff --git a/zebra/zserv.c b/zebra/zserv.c index 3ee2bb59ec..71437bab15 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -2603,6 +2603,9 @@ static inline void zserv_handle_commands(struct zserv *client, case ZEBRA_ADVERTISE_DEFAULT_GW: zebra_vxlan_advertise_gw_macip(client, length, zvrf); break; + case ZEBRA_ADVERTISE_SUBNET: + zebra_vxlan_advertise_subnet(client, length, zvrf); + break; case ZEBRA_ADVERTISE_ALL_VNI: zebra_vxlan_advertise_all_vni(client, length, zvrf); break; diff --git a/zebra/zserv.h b/zebra/zserv.h index 4b3b0041b8..7d5f6b4543 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -114,6 +114,8 @@ struct zserv { u_int32_t l3vnidel_cnt; u_int32_t macipadd_cnt; u_int32_t macipdel_cnt; + u_int32_t prefixadd_cnt; + u_int32_t prefixdel_cnt; time_t connect_time; time_t last_read_time; -- 2.39.5