mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 18:42:23 +00:00
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 <mitesh@cumulusnetworks.com>
This commit is contained in:
parent
b57ba6d2a8
commit
31310b25f2
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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. */
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user