mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 20:34:33 +00:00
bgpd/zebra/lib: EVPN support for asymmetric VxLan routing
1. Advertise gateway mac-ip in EVPN 2. Advertise VRR mac-ip in EVPN 3. Ignore gateway mac-ip advertisements in case of distributed gateway 4. Config knob to enable/disable gateway mac-ip advertisements Ticket: CM-16456, CM-16543, CM-16555, CM-16778 Review: CCR-6283 Unit-test: Manual Signed-off-by: Mitesh Kanjariya <mitesh@cumulusnetworks.com>
This commit is contained in:
parent
8f4b98eedb
commit
1a98c08704
@ -704,7 +704,7 @@ static int evpn_route_is_sticky(struct bgp *bgp, struct bgp_node *rn)
|
|||||||
static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
|
static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
|
||||||
afi_t afi, safi_t safi, struct bgp_node *rn,
|
afi_t afi, safi_t safi, struct bgp_node *rn,
|
||||||
struct attr *attr, int add, int vni_table,
|
struct attr *attr, int add, int vni_table,
|
||||||
struct bgp_info **ri)
|
struct bgp_info **ri, u_char flags)
|
||||||
{
|
{
|
||||||
struct bgp_info *tmp_ri;
|
struct bgp_info *tmp_ri;
|
||||||
struct bgp_info *local_ri, *remote_ri;
|
struct bgp_info *local_ri, *remote_ri;
|
||||||
@ -751,8 +751,11 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
|
|||||||
* remote, we have to initiate appropriate MAC mobility steps.
|
* remote, we have to initiate appropriate MAC mobility steps.
|
||||||
* This
|
* This
|
||||||
* is applicable when updating the VNI routing table.
|
* is applicable when updating the VNI routing table.
|
||||||
|
* We need to skip mobility steps for g/w macs (local mac on g/w
|
||||||
|
* SVI) advertised in EVPN.
|
||||||
|
* This will ensure that local routes are preferred for g/w macs
|
||||||
*/
|
*/
|
||||||
if (remote_ri) {
|
if (remote_ri && !CHECK_FLAG(flags, ZEBRA_MAC_TYPE_GW)) {
|
||||||
u_int32_t cur_seqnum;
|
u_int32_t cur_seqnum;
|
||||||
|
|
||||||
/* Add MM extended community to route. */
|
/* Add MM extended community to route. */
|
||||||
@ -811,7 +814,7 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
|
|||||||
* and schedule for processing.
|
* and schedule for processing.
|
||||||
*/
|
*/
|
||||||
static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
|
static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
|
||||||
struct prefix_evpn *p, u_char sticky)
|
struct prefix_evpn *p, u_char flags)
|
||||||
{
|
{
|
||||||
struct bgp_node *rn;
|
struct bgp_node *rn;
|
||||||
struct attr attr;
|
struct attr attr;
|
||||||
@ -828,7 +831,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
|
|||||||
attr.nexthop = vpn->originator_ip;
|
attr.nexthop = vpn->originator_ip;
|
||||||
attr.mp_nexthop_global_in = vpn->originator_ip;
|
attr.mp_nexthop_global_in = vpn->originator_ip;
|
||||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||||
attr.sticky = sticky;
|
attr.sticky = CHECK_FLAG(flags, ZEBRA_MAC_TYPE_STICKY) ? 1 : 0;
|
||||||
|
|
||||||
/* Set up RT and ENCAP extended community. */
|
/* Set up RT and ENCAP extended community. */
|
||||||
build_evpn_route_extcomm(vpn, &attr);
|
build_evpn_route_extcomm(vpn, &attr);
|
||||||
@ -839,7 +842,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
|
|||||||
|
|
||||||
/* Create or update route entry. */
|
/* Create or update route entry. */
|
||||||
route_change = update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr,
|
route_change = update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr,
|
||||||
1, 1, &ri);
|
1, 1, &ri, flags);
|
||||||
assert(ri);
|
assert(ri);
|
||||||
attr_new = ri->attr;
|
attr_new = ri->attr;
|
||||||
|
|
||||||
@ -860,7 +863,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
|
|||||||
rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
|
rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
|
||||||
(struct prefix *)p, &vpn->prd);
|
(struct prefix *)p, &vpn->prd);
|
||||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn, attr_new, 1, 0,
|
update_evpn_route_entry(bgp, vpn, afi, safi, rn, attr_new, 1, 0,
|
||||||
&global_ri);
|
&global_ri, flags);
|
||||||
|
|
||||||
/* Schedule for processing and unlock node. */
|
/* Schedule for processing and unlock node. */
|
||||||
bgp_process(bgp, rn, afi, safi);
|
bgp_process(bgp, rn, afi, safi);
|
||||||
@ -998,10 +1001,10 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
|||||||
|
|
||||||
if (evpn_route_is_sticky(bgp, rn))
|
if (evpn_route_is_sticky(bgp, rn))
|
||||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||||
&attr_sticky, 0, 1, &ri);
|
&attr_sticky, 0, 1, &ri, 0);
|
||||||
else
|
else
|
||||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr,
|
update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr,
|
||||||
0, 1, &ri);
|
0, 1, &ri, 0);
|
||||||
|
|
||||||
/* If a local route exists for this prefix, we need to update
|
/* If a local route exists for this prefix, we need to update
|
||||||
* the global routing table too.
|
* the global routing table too.
|
||||||
@ -1022,7 +1025,7 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
|||||||
(struct prefix *)evp, &vpn->prd);
|
(struct prefix *)evp, &vpn->prd);
|
||||||
assert(rd_rn);
|
assert(rd_rn);
|
||||||
update_evpn_route_entry(bgp, vpn, afi, safi, rd_rn, attr_new, 0,
|
update_evpn_route_entry(bgp, vpn, afi, safi, rd_rn, attr_new, 0,
|
||||||
0, &global_ri);
|
0, &global_ri, 0);
|
||||||
|
|
||||||
/* Schedule for processing and unlock node. */
|
/* Schedule for processing and unlock node. */
|
||||||
bgp_process(bgp, rd_rn, afi, safi);
|
bgp_process(bgp, rd_rn, afi, safi);
|
||||||
@ -1631,8 +1634,8 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
|||||||
|
|
||||||
global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
|
global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
|
||||||
(struct prefix *)&p, &vpn->prd);
|
(struct prefix *)&p, &vpn->prd);
|
||||||
update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, 0,
|
update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, 0, &ri,
|
||||||
&ri);
|
0);
|
||||||
|
|
||||||
/* Schedule for processing and unlock node. */
|
/* Schedule for processing and unlock node. */
|
||||||
bgp_process(bgp, global_rn, afi, safi);
|
bgp_process(bgp, global_rn, afi, safi);
|
||||||
@ -1665,7 +1668,7 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
|||||||
(struct prefix *)evp, &vpn->prd);
|
(struct prefix *)evp, &vpn->prd);
|
||||||
assert(global_rn);
|
assert(global_rn);
|
||||||
update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1,
|
update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1,
|
||||||
0, &global_ri);
|
0, &global_ri, 0);
|
||||||
|
|
||||||
/* Schedule for processing and unlock node. */
|
/* Schedule for processing and unlock node. */
|
||||||
bgp_process(bgp, global_rn, afi, safi);
|
bgp_process(bgp, global_rn, afi, safi);
|
||||||
@ -2586,7 +2589,7 @@ int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
|
|||||||
* Handle add of a local MACIP.
|
* Handle add of a local MACIP.
|
||||||
*/
|
*/
|
||||||
int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
|
int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
|
||||||
struct ipaddr *ip, u_char sticky)
|
struct ipaddr *ip, u_char flags)
|
||||||
{
|
{
|
||||||
struct bgpevpn *vpn;
|
struct bgpevpn *vpn;
|
||||||
struct prefix_evpn p;
|
struct prefix_evpn p;
|
||||||
@ -2606,13 +2609,17 @@ int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
|
|||||||
|
|
||||||
/* Create EVPN type-2 route and schedule for processing. */
|
/* Create EVPN type-2 route and schedule for processing. */
|
||||||
build_evpn_type2_prefix(&p, mac, ip);
|
build_evpn_type2_prefix(&p, mac, ip);
|
||||||
if (update_evpn_route(bgp, vpn, &p, sticky)) {
|
if (update_evpn_route(bgp, vpn, &p, flags)) {
|
||||||
char buf[ETHER_ADDR_STRLEN];
|
char buf[ETHER_ADDR_STRLEN];
|
||||||
char buf2[INET6_ADDRSTRLEN];
|
char buf2[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
zlog_err(
|
zlog_err(
|
||||||
"%u:Failed to create Type-2 route, VNI %u %sMAC %s IP %s",
|
"%u:Failed to create Type-2 route, VNI %u %s %s MAC %s IP %s",
|
||||||
bgp->vrf_id, vpn->vni, sticky ? "sticky" : "",
|
bgp->vrf_id, vpn->vni,
|
||||||
|
CHECK_FLAG(flags, ZEBRA_MAC_TYPE_STICKY) ? "sticky "
|
||||||
|
: "",
|
||||||
|
CHECK_FLAG(flags, ZEBRA_MAC_TYPE_STICKY) ? "gateway "
|
||||||
|
: "",
|
||||||
prefix_mac2str(mac, buf, sizeof(buf)),
|
prefix_mac2str(mac, buf, sizeof(buf)),
|
||||||
ipaddr2str(ip, buf2, sizeof(buf2)));
|
ipaddr2str(ip, buf2, sizeof(buf2)));
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -42,7 +42,7 @@ extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni,
|
|||||||
struct ethaddr *mac, struct ipaddr *ip);
|
struct ethaddr *mac, struct ipaddr *ip);
|
||||||
extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni,
|
extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni,
|
||||||
struct ethaddr *mac, struct ipaddr *ip,
|
struct ethaddr *mac, struct ipaddr *ip,
|
||||||
u_char sticky);
|
u_char flags);
|
||||||
extern int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni);
|
extern int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni);
|
||||||
extern int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
|
extern int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
|
||||||
struct in_addr originator_ip);
|
struct in_addr originator_ip);
|
||||||
|
@ -58,6 +58,9 @@ struct bgpevpn {
|
|||||||
#define VNI_FLAG_IMPRT_CFGD 0x8 /* Import RT is user configured */
|
#define VNI_FLAG_IMPRT_CFGD 0x8 /* Import RT is user configured */
|
||||||
#define VNI_FLAG_EXPRT_CFGD 0x10 /* Export RT is user configured */
|
#define VNI_FLAG_EXPRT_CFGD 0x10 /* Export RT is user configured */
|
||||||
|
|
||||||
|
/* Flag to indicate if we are advertising the g/w mac ip for this VNI*/
|
||||||
|
u_int8_t advertise_gw_macip;
|
||||||
|
|
||||||
/* Id for deriving the RD automatically for this VNI */
|
/* Id for deriving the RD automatically for this VNI */
|
||||||
u_int16_t rd_id;
|
u_int16_t rd_id;
|
||||||
|
|
||||||
|
@ -1641,6 +1641,51 @@ static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp)
|
|||||||
vty);
|
vty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* evpn - enable advertisement of default g/w
|
||||||
|
*/
|
||||||
|
static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
|
||||||
|
{
|
||||||
|
if (!vpn) {
|
||||||
|
if (bgp->advertise_gw_macip)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bgp->advertise_gw_macip = 1;
|
||||||
|
bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
|
||||||
|
} else {
|
||||||
|
if (vpn->advertise_gw_macip)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vpn->advertise_gw_macip = 1;
|
||||||
|
bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
|
||||||
|
vpn->vni);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* evpn - disable advertisement of default g/w
|
||||||
|
*/
|
||||||
|
static void evpn_unset_advertise_default_gw(struct bgp *bgp,
|
||||||
|
struct bgpevpn *vpn)
|
||||||
|
{
|
||||||
|
if (!vpn) {
|
||||||
|
if (!bgp->advertise_gw_macip)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bgp->advertise_gw_macip = 0;
|
||||||
|
bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
|
||||||
|
} else {
|
||||||
|
if (!vpn->advertise_gw_macip)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vpn->advertise_gw_macip = 0;
|
||||||
|
bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
|
||||||
|
vpn->vni);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* EVPN (VNI advertisement) enabled. Register with zebra.
|
* EVPN (VNI advertisement) enabled. Register with zebra.
|
||||||
*/
|
*/
|
||||||
@ -1694,12 +1739,15 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn, int *write)
|
|||||||
ecom)) {
|
ecom)) {
|
||||||
ecom_str = ecommunity_ecom2str(
|
ecom_str = ecommunity_ecom2str(
|
||||||
ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||||
vty_out(vty, " route-target export %s\n",
|
vty_out(vty, " route-target export %s\n",
|
||||||
ecom_str);
|
ecom_str);
|
||||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vpn->advertise_gw_macip)
|
||||||
|
vty_out(vty, " advertise-default-gw\n");
|
||||||
|
|
||||||
vty_out(vty, " exit-vni\n");
|
vty_out(vty, " exit-vni\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1712,6 +1760,77 @@ static void write_vni_config_for_entry(struct hash_backet *backet,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_CUMULUS)
|
#if defined(HAVE_CUMULUS)
|
||||||
|
DEFUN (bgp_evpn_advertise_default_gw_vni,
|
||||||
|
bgp_evpn_advertise_default_gw_vni_cmd,
|
||||||
|
"advertise-default-gw",
|
||||||
|
"Advertise defualt g/w mac-ip routes in EVPN for a VNI\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_set_advertise_default_gw(bgp, vpn);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (no_bgp_evpn_advertise_default_vni_gw,
|
||||||
|
no_bgp_evpn_advertise_default_gw_vni_cmd,
|
||||||
|
"no advertise-default-gw",
|
||||||
|
NO_STR
|
||||||
|
"Withdraw default g/w mac-ip routes from EVPN for a VNI\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_default_gw(bgp, vpn);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DEFUN (bgp_evpn_advertise_default_gw,
|
||||||
|
bgp_evpn_advertise_default_gw_cmd,
|
||||||
|
"advertise-default-gw",
|
||||||
|
"Advertise All defualt g/w mac-ip routes in EVPN\n")
|
||||||
|
{
|
||||||
|
struct bgp *bgp = VTY_GET_CONTEXT(bgp);
|
||||||
|
|
||||||
|
if (!bgp)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
evpn_set_advertise_default_gw(bgp, NULL);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (no_bgp_evpn_advertise_default_gw,
|
||||||
|
no_bgp_evpn_advertise_default_gw_cmd,
|
||||||
|
"no advertise-default-gw",
|
||||||
|
NO_STR
|
||||||
|
"Withdraw All default g/w mac-ip routes from EVPN\n")
|
||||||
|
{
|
||||||
|
struct bgp *bgp = VTY_GET_CONTEXT(bgp);
|
||||||
|
|
||||||
|
if (!bgp)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
evpn_unset_advertise_default_gw(bgp, NULL);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
DEFUN (bgp_evpn_advertise_all_vni,
|
DEFUN (bgp_evpn_advertise_all_vni,
|
||||||
bgp_evpn_advertise_all_vni_cmd,
|
bgp_evpn_advertise_all_vni_cmd,
|
||||||
"advertise-all-vni",
|
"advertise-all-vni",
|
||||||
@ -1764,6 +1883,9 @@ DEFUN (show_bgp_l2vpn_evpn_vni,
|
|||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
|
|
||||||
if (argc == ((idx + 1) + 1)) {
|
if (argc == ((idx + 1) + 1)) {
|
||||||
|
vty_out(vty, "Advertise gateway macip flag: %s\n",
|
||||||
|
bgp->advertise_gw_macip ? "Enabled" : "Disabled");
|
||||||
|
|
||||||
/* Display all VNIs */
|
/* Display all VNIs */
|
||||||
vty_out(vty, "Advertise All VNI flag: %s\n",
|
vty_out(vty, "Advertise All VNI flag: %s\n",
|
||||||
bgp->advertise_all_vni ? "Enabled" : "Disabled");
|
bgp->advertise_all_vni ? "Enabled" : "Disabled");
|
||||||
@ -2544,6 +2666,11 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
|
|||||||
bgp_config_write_family_header(vty, afi, safi, write);
|
bgp_config_write_family_header(vty, afi, safi, write);
|
||||||
vty_out(vty, " advertise-all-vni\n");
|
vty_out(vty, " advertise-all-vni\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bgp->advertise_gw_macip) {
|
||||||
|
bgp_config_write_family_header(vty, afi, safi, write);
|
||||||
|
vty_out(vty, " advertise-default-gw\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bgp_ethernetvpn_init(void)
|
void bgp_ethernetvpn_init(void)
|
||||||
@ -2569,6 +2696,8 @@ void bgp_ethernetvpn_init(void)
|
|||||||
#if defined(HAVE_CUMULUS)
|
#if defined(HAVE_CUMULUS)
|
||||||
install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
|
install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
|
||||||
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
|
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
|
||||||
|
install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
|
||||||
|
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
|
||||||
|
|
||||||
/* "show bgp l2vpn evpn" commands. */
|
/* "show bgp l2vpn evpn" commands. */
|
||||||
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
|
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
|
||||||
@ -2592,5 +2721,9 @@ void bgp_ethernetvpn_init(void)
|
|||||||
install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
|
install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
|
||||||
install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
|
install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
|
||||||
install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
|
install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
|
||||||
|
install_element(BGP_EVPN_VNI_NODE,
|
||||||
|
&bgp_evpn_advertise_default_gw_vni_cmd);
|
||||||
|
install_element(BGP_EVPN_VNI_NODE,
|
||||||
|
&no_bgp_evpn_advertise_default_gw_vni_cmd);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -2034,6 +2034,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);
|
zclient_send_interface_radv_req(zclient, bgp->vrf_id, peer->ifp, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bgp_zebra_advertise_gw_macip(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_DEFAULT_GW, 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_all_vni(struct bgp *bgp, int advertise)
|
int bgp_zebra_advertise_all_vni(struct bgp *bgp, int advertise)
|
||||||
{
|
{
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
@ -2120,7 +2143,7 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient,
|
|||||||
int ipa_len;
|
int ipa_len;
|
||||||
char buf[ETHER_ADDR_STRLEN];
|
char buf[ETHER_ADDR_STRLEN];
|
||||||
char buf1[INET6_ADDRSTRLEN];
|
char buf1[INET6_ADDRSTRLEN];
|
||||||
u_char sticky;
|
u_char flags;
|
||||||
|
|
||||||
memset(&ip, 0, sizeof(ip));
|
memset(&ip, 0, sizeof(ip));
|
||||||
s = zclient->ibuf;
|
s = zclient->ibuf;
|
||||||
@ -2140,21 +2163,20 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient,
|
|||||||
(ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4 : IPADDR_V6;
|
(ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4 : IPADDR_V6;
|
||||||
stream_get(&ip.ip.addr, s, ipa_len);
|
stream_get(&ip.ip.addr, s, ipa_len);
|
||||||
}
|
}
|
||||||
sticky = stream_getc(s);
|
flags = stream_getc(s);
|
||||||
|
|
||||||
bgp = bgp_lookup_by_vrf_id(vrf_id);
|
bgp = bgp_lookup_by_vrf_id(vrf_id);
|
||||||
if (!bgp)
|
if (!bgp)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (BGP_DEBUG(zebra, ZEBRA))
|
if (BGP_DEBUG(zebra, ZEBRA))
|
||||||
zlog_debug("%u:Recv MACIP %s %sMAC %s IP %s VNI %u", vrf_id,
|
zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u",
|
||||||
(command == ZEBRA_MACIP_ADD) ? "Add" : "Del",
|
vrf_id, (command == ZEBRA_MACIP_ADD) ? "Add" : "Del",
|
||||||
sticky ? "sticky " : "",
|
flags, prefix_mac2str(&mac, buf, sizeof(buf)),
|
||||||
prefix_mac2str(&mac, buf, sizeof(buf)),
|
|
||||||
ipaddr2str(&ip, buf1, sizeof(buf1)), vni);
|
ipaddr2str(&ip, buf1, sizeof(buf1)), vni);
|
||||||
|
|
||||||
if (command == ZEBRA_MACIP_ADD)
|
if (command == ZEBRA_MACIP_ADD)
|
||||||
return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, sticky);
|
return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, flags);
|
||||||
else
|
else
|
||||||
return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip);
|
return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip);
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
#ifndef _QUAGGA_BGP_ZEBRA_H
|
#ifndef _QUAGGA_BGP_ZEBRA_H
|
||||||
#define _QUAGGA_BGP_ZEBRA_H
|
#define _QUAGGA_BGP_ZEBRA_H
|
||||||
|
|
||||||
|
#include "vxlan.h"
|
||||||
|
|
||||||
extern void bgp_zebra_init(struct thread_master *master);
|
extern void bgp_zebra_init(struct thread_master *master);
|
||||||
extern void bgp_zebra_destroy(void);
|
extern void bgp_zebra_destroy(void);
|
||||||
extern int bgp_if_update_all(void);
|
extern int bgp_if_update_all(void);
|
||||||
@ -57,6 +59,7 @@ extern struct interface *if_lookup_by_ipv6(struct in6_addr *, ifindex_t,
|
|||||||
extern struct interface *if_lookup_by_ipv6_exact(struct in6_addr *, ifindex_t,
|
extern struct interface *if_lookup_by_ipv6_exact(struct in6_addr *, ifindex_t,
|
||||||
vrf_id_t);
|
vrf_id_t);
|
||||||
|
|
||||||
|
extern int bgp_zebra_advertise_gw_macip(struct bgp *, int, vni_t);
|
||||||
extern int bgp_zebra_advertise_all_vni(struct bgp *, int);
|
extern int bgp_zebra_advertise_all_vni(struct bgp *, int);
|
||||||
|
|
||||||
extern int bgp_zebra_num_connects(void);
|
extern int bgp_zebra_num_connects(void);
|
||||||
|
@ -380,6 +380,9 @@ struct bgp {
|
|||||||
/* EVI hash table */
|
/* EVI hash table */
|
||||||
struct hash *vnihash;
|
struct hash *vnihash;
|
||||||
|
|
||||||
|
/* EVPN enable - advertise gateway macip routes */
|
||||||
|
int advertise_gw_macip;
|
||||||
|
|
||||||
/* EVPN enable - advertise local VNIs and their MACs etc. */
|
/* EVPN enable - advertise local VNIs and their MACs etc. */
|
||||||
int advertise_all_vni;
|
int advertise_all_vni;
|
||||||
|
|
||||||
|
@ -908,6 +908,7 @@ static const struct zebra_desc_table command_types[] = {
|
|||||||
DESC_ENTRY(ZEBRA_GET_LABEL_CHUNK),
|
DESC_ENTRY(ZEBRA_GET_LABEL_CHUNK),
|
||||||
DESC_ENTRY(ZEBRA_RELEASE_LABEL_CHUNK),
|
DESC_ENTRY(ZEBRA_RELEASE_LABEL_CHUNK),
|
||||||
DESC_ENTRY(ZEBRA_ADVERTISE_ALL_VNI),
|
DESC_ENTRY(ZEBRA_ADVERTISE_ALL_VNI),
|
||||||
|
DESC_ENTRY(ZEBRA_ADVERTISE_DEFAULT_GW),
|
||||||
DESC_ENTRY(ZEBRA_VNI_ADD),
|
DESC_ENTRY(ZEBRA_VNI_ADD),
|
||||||
DESC_ENTRY(ZEBRA_VNI_DEL),
|
DESC_ENTRY(ZEBRA_VNI_DEL),
|
||||||
DESC_ENTRY(ZEBRA_REMOTE_VTEP_ADD),
|
DESC_ENTRY(ZEBRA_REMOTE_VTEP_ADD),
|
||||||
|
@ -97,6 +97,7 @@ typedef enum {
|
|||||||
ZEBRA_FEC_REGISTER,
|
ZEBRA_FEC_REGISTER,
|
||||||
ZEBRA_FEC_UNREGISTER,
|
ZEBRA_FEC_UNREGISTER,
|
||||||
ZEBRA_FEC_UPDATE,
|
ZEBRA_FEC_UPDATE,
|
||||||
|
ZEBRA_ADVERTISE_DEFAULT_GW,
|
||||||
ZEBRA_ADVERTISE_ALL_VNI,
|
ZEBRA_ADVERTISE_ALL_VNI,
|
||||||
ZEBRA_VNI_ADD,
|
ZEBRA_VNI_ADD,
|
||||||
ZEBRA_VNI_DEL,
|
ZEBRA_VNI_DEL,
|
||||||
@ -266,6 +267,10 @@ struct zapi_ipv4 {
|
|||||||
vrf_id_t vrf_id;
|
vrf_id_t vrf_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Zebra MAC types */
|
||||||
|
#define ZEBRA_MAC_TYPE_STICKY 0x01 /* Sticky MAC*/
|
||||||
|
#define ZEBRA_MAC_TYPE_GW 0x02 /* gateway (SVI) mac*/
|
||||||
|
|
||||||
/* Prototypes of zebra client service functions. */
|
/* Prototypes of zebra client service functions. */
|
||||||
extern struct zclient *zclient_new(struct thread_master *);
|
extern struct zclient *zclient_new(struct thread_master *);
|
||||||
extern void zclient_init(struct zclient *, int, u_short);
|
extern void zclient_init(struct zclient *, int, u_short);
|
||||||
|
@ -251,6 +251,8 @@ static void netlink_determine_zebra_iftype(char *kind, zebra_iftype_t *zif_type)
|
|||||||
*zif_type = ZEBRA_IF_VLAN;
|
*zif_type = ZEBRA_IF_VLAN;
|
||||||
else if (strcmp(kind, "vxlan") == 0)
|
else if (strcmp(kind, "vxlan") == 0)
|
||||||
*zif_type = ZEBRA_IF_VXLAN;
|
*zif_type = ZEBRA_IF_VXLAN;
|
||||||
|
else if (strcmp(kind, "macvlan") == 0)
|
||||||
|
*zif_type = ZEBRA_IF_MACVLAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporary Assignments to compile on older platforms.
|
// Temporary Assignments to compile on older platforms.
|
||||||
|
@ -186,11 +186,12 @@ struct rtadvconf {
|
|||||||
|
|
||||||
/* Zebra interface type - ones of interest. */
|
/* Zebra interface type - ones of interest. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ZEBRA_IF_VXLAN, /* VxLAN interface */
|
ZEBRA_IF_VXLAN, /* VxLAN interface */
|
||||||
ZEBRA_IF_VRF, /* VRF device */
|
ZEBRA_IF_VRF, /* VRF device */
|
||||||
ZEBRA_IF_BRIDGE, /* bridge device */
|
ZEBRA_IF_BRIDGE, /* bridge device */
|
||||||
ZEBRA_IF_VLAN, /* VLAN sub-interface */
|
ZEBRA_IF_VLAN, /* VLAN sub-interface */
|
||||||
ZEBRA_IF_OTHER, /* Anything else */
|
ZEBRA_IF_MACVLAN, /* MAC VLAN interface*/
|
||||||
|
ZEBRA_IF_OTHER, /* Anything else */
|
||||||
} zebra_iftype_t;
|
} zebra_iftype_t;
|
||||||
|
|
||||||
/* Zebra "slave" interface type */
|
/* Zebra "slave" interface type */
|
||||||
@ -295,6 +296,9 @@ static inline void zebra_if_set_ziftype(struct interface *ifp,
|
|||||||
#define IS_ZEBRA_IF_VXLAN(ifp) \
|
#define IS_ZEBRA_IF_VXLAN(ifp) \
|
||||||
(((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VXLAN)
|
(((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VXLAN)
|
||||||
|
|
||||||
|
#define IS_ZEBRA_IF_MACVLAN(ifp) \
|
||||||
|
(((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_MACVLAN)
|
||||||
|
|
||||||
#define IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) \
|
#define IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) \
|
||||||
(((struct zebra_if *)(ifp->info))->zif_slave_type \
|
(((struct zebra_if *)(ifp->info))->zif_slave_type \
|
||||||
== ZEBRA_IF_SLAVE_BRIDGE)
|
== ZEBRA_IF_SLAVE_BRIDGE)
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "zebra/debug.h"
|
#include "zebra/debug.h"
|
||||||
#include "zebra/router-id.h"
|
#include "zebra/router-id.h"
|
||||||
#include "zebra/zebra_memory.h"
|
#include "zebra/zebra_memory.h"
|
||||||
|
#include "zebra/zebra_vxlan.h"
|
||||||
|
|
||||||
#define ZEBRA_PTM_SUPPORT
|
#define ZEBRA_PTM_SUPPORT
|
||||||
|
|
||||||
@ -402,6 +403,8 @@ void zebra_interface_address_add_update(struct interface *ifp,
|
|||||||
zlog_warn(
|
zlog_warn(
|
||||||
"WARNING: advertising address to clients that is not yet usable.");
|
"WARNING: advertising address to clients that is not yet usable.");
|
||||||
|
|
||||||
|
zebra_vxlan_add_del_gw_macip(ifp, ifc->address, 1);
|
||||||
|
|
||||||
router_id_add_address(ifc);
|
router_id_add_address(ifc);
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
|
for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
|
||||||
@ -428,6 +431,8 @@ void zebra_interface_address_delete_update(struct interface *ifp,
|
|||||||
prefix2str(p, buf, sizeof(buf)), ifc->ifp->name);
|
prefix2str(p, buf, sizeof(buf)), ifc->ifp->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zebra_vxlan_add_del_gw_macip(ifp, ifc->address, 0);
|
||||||
|
|
||||||
router_id_del_address(ifc);
|
router_id_del_address(ifc);
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
|
for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
|
||||||
|
@ -102,6 +102,11 @@ struct zebra_vrf {
|
|||||||
*/
|
*/
|
||||||
int advertise_all_vni;
|
int advertise_all_vni;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whether we are advertising g/w macip in EVPN or not.
|
||||||
|
*/
|
||||||
|
int advertise_gw_macip;
|
||||||
|
|
||||||
/* Route Installs */
|
/* Route Installs */
|
||||||
uint64_t installs;
|
uint64_t installs;
|
||||||
uint64_t removals;
|
uint64_t removals;
|
||||||
|
@ -68,7 +68,7 @@ static void zvni_print_hash(struct hash_backet *backet, void *ctxt);
|
|||||||
|
|
||||||
static int zvni_macip_send_msg_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
static int zvni_macip_send_msg_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
||||||
struct ethaddr *macaddr,
|
struct ethaddr *macaddr,
|
||||||
struct ipaddr *ip, u_char sticky,
|
struct ipaddr *ip, u_char flags,
|
||||||
u_int16_t cmd);
|
u_int16_t cmd);
|
||||||
static unsigned int neigh_hash_keymake(void *p);
|
static unsigned int neigh_hash_keymake(void *p);
|
||||||
static int neigh_cmp(const void *p1, const void *p2);
|
static int neigh_cmp(const void *p1, const void *p2);
|
||||||
@ -83,10 +83,10 @@ static void zvni_neigh_del_all(struct zebra_vrf *zvrf, zebra_vni_t *zvni,
|
|||||||
static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip);
|
static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip);
|
||||||
static int zvni_neigh_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
static int zvni_neigh_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
||||||
struct ipaddr *ip,
|
struct ipaddr *ip,
|
||||||
struct ethaddr *macaddr);
|
struct ethaddr *macaddr, u_char flags);
|
||||||
static int zvni_neigh_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
static int zvni_neigh_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
||||||
struct ipaddr *ip,
|
struct ipaddr *ip,
|
||||||
struct ethaddr *macaddr);
|
struct ethaddr *macaddr, u_char flags);
|
||||||
static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n);
|
static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n);
|
||||||
static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n);
|
static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n);
|
||||||
static zebra_vni_t *zvni_map_svi(struct interface *ifp,
|
static zebra_vni_t *zvni_map_svi(struct interface *ifp,
|
||||||
@ -106,9 +106,9 @@ static void zvni_mac_del_all(struct zebra_vrf *zvrf, zebra_vni_t *zvni,
|
|||||||
int uninstall, int upd_client, u_int32_t flags);
|
int uninstall, int upd_client, u_int32_t flags);
|
||||||
static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *macaddr);
|
static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *macaddr);
|
||||||
static int zvni_mac_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
static int zvni_mac_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
||||||
struct ethaddr *macaddr, u_char sticky);
|
struct ethaddr *macaddr, u_char flags);
|
||||||
static int zvni_mac_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
static int zvni_mac_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
||||||
struct ethaddr *macaddr, u_char sticky);
|
struct ethaddr *macaddr, u_char flags);
|
||||||
static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
|
static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
|
||||||
struct interface *br_if, vlanid_t vid);
|
struct interface *br_if, vlanid_t vid);
|
||||||
static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac);
|
static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac);
|
||||||
@ -131,10 +131,31 @@ static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep);
|
|||||||
static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall);
|
static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall);
|
||||||
static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip);
|
static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip);
|
||||||
static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip);
|
static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip);
|
||||||
|
static int zvni_del_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni);
|
||||||
|
static int zvni_add_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni);
|
||||||
|
static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
|
||||||
|
struct ethaddr *macaddr, struct ipaddr *ip);
|
||||||
|
static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
|
||||||
|
struct ipaddr *ip);
|
||||||
|
struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp);
|
||||||
|
static int advertise_gw_macip_enabled(struct zebra_vrf *zvrf,
|
||||||
|
zebra_vni_t *zvni);
|
||||||
|
static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac,
|
||||||
|
int uninstall);
|
||||||
|
|
||||||
/* Private functions */
|
/* Private functions */
|
||||||
|
|
||||||
|
static int advertise_gw_macip_enabled(struct zebra_vrf *zvrf, zebra_vni_t *zvni)
|
||||||
|
{
|
||||||
|
if (zvrf && zvrf->advertise_gw_macip)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (zvni && zvni->advertise_gw_macip)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper function to determine maximum width of neighbor IP address for
|
* Helper function to determine maximum width of neighbor IP address for
|
||||||
* display - just because we're dealing with IPv6 addresses that can
|
* display - just because we're dealing with IPv6 addresses that can
|
||||||
@ -450,7 +471,7 @@ static void zvni_print_hash(struct hash_backet *backet, void *ctxt)
|
|||||||
*/
|
*/
|
||||||
static int zvni_macip_send_msg_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
static int zvni_macip_send_msg_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
||||||
struct ethaddr *macaddr,
|
struct ethaddr *macaddr,
|
||||||
struct ipaddr *ip, u_char sticky,
|
struct ipaddr *ip, u_char flags,
|
||||||
u_int16_t cmd)
|
u_int16_t cmd)
|
||||||
{
|
{
|
||||||
struct zserv *client;
|
struct zserv *client;
|
||||||
@ -483,19 +504,18 @@ static int zvni_macip_send_msg_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
|||||||
} else
|
} else
|
||||||
stream_putl(s, 0); /* Just MAC. */
|
stream_putl(s, 0); /* Just MAC. */
|
||||||
|
|
||||||
stream_putc(s, sticky); /* Sticky MAC? */
|
stream_putc(s, flags); /* sticky mac/gateway mac */
|
||||||
|
|
||||||
/* Write packet size. */
|
/* Write packet size. */
|
||||||
stream_putw_at(s, 0, stream_get_endp(s));
|
stream_putw_at(s, 0, stream_get_endp(s));
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||||
zlog_debug("%u:Send MACIP %s %sMAC %s IP %s VNI %u to %s",
|
zlog_debug(
|
||||||
zvrf_id(zvrf),
|
"%u:Send MACIP %s flags 0x%x MAC %s IP %s VNI %u to %s",
|
||||||
(cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del",
|
zvrf_id(zvrf), (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del",
|
||||||
sticky ? "sticky " : "",
|
flags, prefix_mac2str(macaddr, buf, sizeof(buf)),
|
||||||
prefix_mac2str(macaddr, buf, sizeof(buf)),
|
ipaddr2str(ip, buf2, sizeof(buf2)), vni,
|
||||||
ipaddr2str(ip, buf2, sizeof(buf2)), vni,
|
zebra_route_string(client->proto));
|
||||||
zebra_route_string(client->proto));
|
|
||||||
|
|
||||||
if (cmd == ZEBRA_MACIP_ADD)
|
if (cmd == ZEBRA_MACIP_ADD)
|
||||||
client->macipadd_cnt++;
|
client->macipadd_cnt++;
|
||||||
@ -597,8 +617,9 @@ static int zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg)
|
|||||||
&& (n->flags & ZEBRA_NEIGH_REMOTE)
|
&& (n->flags & ZEBRA_NEIGH_REMOTE)
|
||||||
&& IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) {
|
&& IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) {
|
||||||
if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL))
|
if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL))
|
||||||
zvni_neigh_send_del_to_client(
|
zvni_neigh_send_del_to_client(wctx->zvrf,
|
||||||
wctx->zvrf, wctx->zvni->vni, &n->ip, &n->emac);
|
wctx->zvni->vni, &n->ip,
|
||||||
|
&n->emac, 0);
|
||||||
|
|
||||||
if (wctx->uninstall)
|
if (wctx->uninstall)
|
||||||
zvni_neigh_uninstall(wctx->zvni, n);
|
zvni_neigh_uninstall(wctx->zvni, n);
|
||||||
@ -676,9 +697,9 @@ static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip)
|
|||||||
*/
|
*/
|
||||||
static int zvni_neigh_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
static int zvni_neigh_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
||||||
struct ipaddr *ip,
|
struct ipaddr *ip,
|
||||||
struct ethaddr *macaddr)
|
struct ethaddr *macaddr, u_char flags)
|
||||||
{
|
{
|
||||||
return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, ip, 0,
|
return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, ip, flags,
|
||||||
ZEBRA_MACIP_ADD);
|
ZEBRA_MACIP_ADD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -687,9 +708,9 @@ static int zvni_neigh_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
|||||||
*/
|
*/
|
||||||
static int zvni_neigh_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
static int zvni_neigh_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
||||||
struct ipaddr *ip,
|
struct ipaddr *ip,
|
||||||
struct ethaddr *macaddr)
|
struct ethaddr *macaddr, u_char flags)
|
||||||
{
|
{
|
||||||
return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, ip, 0,
|
return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, ip, flags,
|
||||||
ZEBRA_MACIP_DEL);
|
ZEBRA_MACIP_DEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -770,6 +791,309 @@ static void zvni_install_neigh_hash(struct hash_backet *backet, void *ctxt)
|
|||||||
zvni_neigh_install(wctx->zvni, n);
|
zvni_neigh_install(wctx->zvni, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the VRR interface for SVI if any */
|
||||||
|
struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp)
|
||||||
|
{
|
||||||
|
struct zebra_vrf *zvrf = NULL;
|
||||||
|
struct interface *tmp_if = NULL;
|
||||||
|
struct zebra_if *zif = NULL;
|
||||||
|
struct listnode *node;
|
||||||
|
|
||||||
|
zvrf = vrf_info_lookup(ifp->vrf_id);
|
||||||
|
assert(zvrf);
|
||||||
|
|
||||||
|
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, tmp_if)) {
|
||||||
|
zif = tmp_if->info;
|
||||||
|
if (!zif)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!IS_ZEBRA_IF_MACVLAN(tmp_if))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (zif->link == ifp)
|
||||||
|
return tmp_if;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int zvni_del_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni)
|
||||||
|
{
|
||||||
|
struct zebra_vrf *zvrf = NULL;
|
||||||
|
struct listnode *cnode = NULL, *cnnode = NULL;
|
||||||
|
struct connected *c = NULL;
|
||||||
|
struct ethaddr macaddr;
|
||||||
|
|
||||||
|
zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
|
||||||
|
if (!zvrf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
|
||||||
|
|
||||||
|
for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
|
||||||
|
struct ipaddr ip;
|
||||||
|
|
||||||
|
memset(&ip, 0, sizeof(struct ipaddr));
|
||||||
|
if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (c->address->family == AF_INET) {
|
||||||
|
ip.ipa_type = IPADDR_V4;
|
||||||
|
memcpy(&(ip.ipaddr_v4), &(c->address->u.prefix4),
|
||||||
|
sizeof(struct in_addr));
|
||||||
|
} else if (c->address->family == AF_INET6) {
|
||||||
|
ip.ipa_type = IPADDR_V6;
|
||||||
|
memcpy(&(ip.ipaddr_v6), &(c->address->u.prefix6),
|
||||||
|
sizeof(struct in6_addr));
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
zvni_gw_macip_del(ifp, zvni, &ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int zvni_add_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni)
|
||||||
|
{
|
||||||
|
struct zebra_vrf *zvrf = NULL;
|
||||||
|
struct listnode *cnode = NULL, *cnnode = NULL;
|
||||||
|
struct connected *c = NULL;
|
||||||
|
struct ethaddr macaddr;
|
||||||
|
|
||||||
|
zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
|
||||||
|
if (!zvrf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
|
||||||
|
|
||||||
|
for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
|
||||||
|
struct ipaddr ip;
|
||||||
|
|
||||||
|
memset(&ip, 0, sizeof(struct ipaddr));
|
||||||
|
if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (c->address->family == AF_INET) {
|
||||||
|
ip.ipa_type = IPADDR_V4;
|
||||||
|
memcpy(&(ip.ipaddr_v4), &(c->address->u.prefix4),
|
||||||
|
sizeof(struct in_addr));
|
||||||
|
} else if (c->address->family == AF_INET6) {
|
||||||
|
ip.ipa_type = IPADDR_V6;
|
||||||
|
memcpy(&(ip.ipaddr_v6), &(c->address->u.prefix6),
|
||||||
|
sizeof(struct in6_addr));
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* zvni_gw_macip_add_to_client
|
||||||
|
*/
|
||||||
|
static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
|
||||||
|
struct ethaddr *macaddr, struct ipaddr *ip)
|
||||||
|
{
|
||||||
|
struct zebra_vrf *zvrf = NULL;
|
||||||
|
struct zebra_if *zif = NULL;
|
||||||
|
struct zebra_l2info_vxlan *vxl = NULL;
|
||||||
|
zebra_neigh_t *n = NULL;
|
||||||
|
zebra_mac_t *mac = NULL;
|
||||||
|
char buf[ETHER_ADDR_STRLEN];
|
||||||
|
char buf2[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
|
||||||
|
if (!zvrf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
zif = zvni->vxlan_if->info;
|
||||||
|
if (!zif)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
vxl = &zif->l2info.vxl;
|
||||||
|
|
||||||
|
mac = zvni_mac_lookup(zvni, macaddr);
|
||||||
|
if (!mac) {
|
||||||
|
mac = zvni_mac_add(zvni, macaddr);
|
||||||
|
if (!mac) {
|
||||||
|
zlog_err("%u:Failed to add MAC %s intf %s(%u) VID %u",
|
||||||
|
ifp->vrf_id,
|
||||||
|
prefix_mac2str(macaddr, buf, sizeof(buf)),
|
||||||
|
ifp->name, ifp->ifindex, vxl->access_vlan);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set "local" forwarding info. */
|
||||||
|
SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
|
||||||
|
SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
|
||||||
|
memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
|
||||||
|
mac->fwd_info.local.ifindex = ifp->ifindex;
|
||||||
|
mac->fwd_info.local.vid = vxl->access_vlan;
|
||||||
|
|
||||||
|
n = zvni_neigh_lookup(zvni, ip);
|
||||||
|
if (!n) {
|
||||||
|
n = zvni_neigh_add(zvni, ip);
|
||||||
|
if (!n) {
|
||||||
|
zlog_err(
|
||||||
|
"%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
|
||||||
|
ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
|
||||||
|
prefix_mac2str(macaddr, NULL,
|
||||||
|
ETHER_ADDR_STRLEN),
|
||||||
|
ifp->name, ifp->ifindex, zvni->vni);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set "local" forwarding info. */
|
||||||
|
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
|
||||||
|
memcpy(&n->emac, macaddr, ETH_ALEN);
|
||||||
|
n->ifindex = ifp->ifindex;
|
||||||
|
|
||||||
|
/* We have a neigh associated to mac increment the refcnt*/
|
||||||
|
mac->neigh_refcnt++;
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||||
|
zlog_debug(
|
||||||
|
"%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s add to BGP",
|
||||||
|
ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni,
|
||||||
|
prefix_mac2str(macaddr, NULL, ETHER_ADDR_STRLEN),
|
||||||
|
ipaddr2str(ip, buf2, sizeof(buf2)));
|
||||||
|
|
||||||
|
zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip, macaddr,
|
||||||
|
ZEBRA_MAC_TYPE_GW);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* zvni_gw_macip_del_from_client
|
||||||
|
*/
|
||||||
|
static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
|
||||||
|
struct ipaddr *ip)
|
||||||
|
{
|
||||||
|
struct zebra_vrf *zvrf = NULL;
|
||||||
|
zebra_neigh_t *n = NULL;
|
||||||
|
zebra_mac_t *mac = NULL;
|
||||||
|
char buf2[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
|
||||||
|
if (!zvrf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* If the neigh entry is not present nothing to do*/
|
||||||
|
n = zvni_neigh_lookup(zvni, ip);
|
||||||
|
if (!n)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* mac entry should be present */
|
||||||
|
mac = zvni_mac_lookup(zvni, &n->emac);
|
||||||
|
if (!mac)
|
||||||
|
zlog_err("%u: MAC %s doesnt exsists for neigh %s on VNI %u",
|
||||||
|
ifp->vrf_id,
|
||||||
|
prefix_mac2str(&n->emac, NULL, ETHER_ADDR_STRLEN),
|
||||||
|
ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
|
||||||
|
|
||||||
|
/* If the entry is not local nothing to do*/
|
||||||
|
if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||||
|
zlog_debug(
|
||||||
|
"%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
|
||||||
|
ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni,
|
||||||
|
prefix_mac2str(&(n->emac), NULL, ETHER_ADDR_STRLEN),
|
||||||
|
ipaddr2str(ip, buf2, sizeof(buf2)));
|
||||||
|
|
||||||
|
/* Remove neighbor from BGP. */
|
||||||
|
zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac,
|
||||||
|
ZEBRA_MAC_TYPE_GW);
|
||||||
|
|
||||||
|
/* Delete this neighbor entry. */
|
||||||
|
zvni_neigh_del(zvni, n);
|
||||||
|
|
||||||
|
/* see if the mac needs to be deleted as well*/
|
||||||
|
zvni_deref_ip2mac(zvni, mac, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void zvni_gw_macip_del_for_vni_hash(struct hash_backet *backet,
|
||||||
|
void *zvrf)
|
||||||
|
{
|
||||||
|
zebra_vni_t *zvni = NULL;
|
||||||
|
struct zebra_if *zif = NULL;
|
||||||
|
struct zebra_l2info_vxlan zl2_info;
|
||||||
|
struct interface *vlan_if = NULL;
|
||||||
|
struct interface *vrr_if = NULL;
|
||||||
|
|
||||||
|
/* Add primary SVI MAC*/
|
||||||
|
zvni = (zebra_vni_t *)backet->data;
|
||||||
|
if (!zvni)
|
||||||
|
return;
|
||||||
|
|
||||||
|
zif = zvni->vxlan_if->info;
|
||||||
|
zl2_info = zif->l2info.vxl;
|
||||||
|
|
||||||
|
vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan,
|
||||||
|
zif->brslave_info.br_if);
|
||||||
|
if (!vlan_if)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Del primary MAC-IP */
|
||||||
|
zvni_del_macip_for_intf(vlan_if, zvni);
|
||||||
|
|
||||||
|
/* Del VRR MAC-IP - if any*/
|
||||||
|
vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
|
||||||
|
if (vrr_if)
|
||||||
|
zvni_del_macip_for_intf(vrr_if, zvni);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
|
||||||
|
void *zvrf)
|
||||||
|
{
|
||||||
|
zebra_vni_t *zvni = NULL;
|
||||||
|
struct zebra_if *zif = NULL;
|
||||||
|
struct zebra_l2info_vxlan zl2_info;
|
||||||
|
struct interface *vlan_if = NULL;
|
||||||
|
struct interface *vrr_if = NULL;
|
||||||
|
|
||||||
|
zvni = (zebra_vni_t *)backet->data;
|
||||||
|
if (!zvni)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!advertise_gw_macip_enabled(zvrf, zvni))
|
||||||
|
return;
|
||||||
|
|
||||||
|
zif = zvni->vxlan_if->info;
|
||||||
|
zl2_info = zif->l2info.vxl;
|
||||||
|
|
||||||
|
vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan,
|
||||||
|
zif->brslave_info.br_if);
|
||||||
|
if (!vlan_if)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!advertise_gw_macip_enabled(zvrf, zvni))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Add primary SVI MAC-IP */
|
||||||
|
zvni_add_macip_for_intf(vlan_if, zvni);
|
||||||
|
|
||||||
|
/* Add VRR MAC-IP - if any*/
|
||||||
|
vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
|
||||||
|
if (vrr_if)
|
||||||
|
zvni_add_macip_for_intf(vrr_if, zvni);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make hash key for MAC.
|
* Make hash key for MAC.
|
||||||
*/
|
*/
|
||||||
@ -864,8 +1188,9 @@ static int zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg)
|
|||||||
if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
|
if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
|
||||||
sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1
|
sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1
|
||||||
: 0;
|
: 0;
|
||||||
zvni_mac_send_del_to_client(wctx->zvrf, wctx->zvni->vni,
|
zvni_mac_send_del_to_client(
|
||||||
&mac->macaddr, sticky);
|
wctx->zvrf, wctx->zvni->vni, &mac->macaddr,
|
||||||
|
(sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wctx->uninstall)
|
if (wctx->uninstall)
|
||||||
@ -941,9 +1266,9 @@ static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *mac)
|
|||||||
* Inform BGP about local MAC addition.
|
* Inform BGP about local MAC addition.
|
||||||
*/
|
*/
|
||||||
static int zvni_mac_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
static int zvni_mac_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
||||||
struct ethaddr *macaddr, u_char sticky)
|
struct ethaddr *macaddr, u_char flags)
|
||||||
{
|
{
|
||||||
return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, NULL, sticky,
|
return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, NULL, flags,
|
||||||
ZEBRA_MACIP_ADD);
|
ZEBRA_MACIP_ADD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -951,9 +1276,9 @@ static int zvni_mac_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
|||||||
* Inform BGP about local MAC deletion.
|
* Inform BGP about local MAC deletion.
|
||||||
*/
|
*/
|
||||||
static int zvni_mac_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
static int zvni_mac_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni,
|
||||||
struct ethaddr *macaddr, u_char sticky)
|
struct ethaddr *macaddr, u_char flags)
|
||||||
{
|
{
|
||||||
return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, NULL, sticky,
|
return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, NULL, flags,
|
||||||
ZEBRA_MACIP_DEL);
|
ZEBRA_MACIP_DEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1234,6 +1559,7 @@ static void zvni_read_mac_neigh(struct zebra_vrf *zvrf, zebra_vni_t *zvni,
|
|||||||
struct zebra_if *zif;
|
struct zebra_if *zif;
|
||||||
struct interface *vlan_if;
|
struct interface *vlan_if;
|
||||||
struct zebra_l2info_vxlan *vxl;
|
struct zebra_l2info_vxlan *vxl;
|
||||||
|
struct interface *vrr_if;
|
||||||
|
|
||||||
zif = ifp->info;
|
zif = ifp->info;
|
||||||
vxl = &zif->l2info.vxl;
|
vxl = &zif->l2info.vxl;
|
||||||
@ -1247,8 +1573,20 @@ static void zvni_read_mac_neigh(struct zebra_vrf *zvrf, zebra_vni_t *zvni,
|
|||||||
macfdb_read_for_bridge(zvrf->zns, ifp, zif->brslave_info.br_if);
|
macfdb_read_for_bridge(zvrf->zns, ifp, zif->brslave_info.br_if);
|
||||||
vlan_if = zvni_map_to_svi(zvrf, vxl->access_vlan,
|
vlan_if = zvni_map_to_svi(zvrf, vxl->access_vlan,
|
||||||
zif->brslave_info.br_if);
|
zif->brslave_info.br_if);
|
||||||
if (vlan_if)
|
if (vlan_if) {
|
||||||
|
|
||||||
|
if (advertise_gw_macip_enabled(zvrf, zvni)) {
|
||||||
|
/* Add SVI MAC-IP */
|
||||||
|
zvni_add_macip_for_intf(vlan_if, zvni);
|
||||||
|
|
||||||
|
/* Add VRR MAC-IP - if any*/
|
||||||
|
vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
|
||||||
|
if (vrr_if)
|
||||||
|
zvni_add_macip_for_intf(vrr_if, zvni);
|
||||||
|
}
|
||||||
|
|
||||||
neigh_read_for_vlan(zvrf->zns, vlan_if);
|
neigh_read_for_vlan(zvrf->zns, vlan_if);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1915,7 +2253,7 @@ int zebra_vxlan_local_neigh_del(struct interface *ifp,
|
|||||||
assert(zvrf);
|
assert(zvrf);
|
||||||
|
|
||||||
/* Remove neighbor from BGP. */
|
/* Remove neighbor from BGP. */
|
||||||
zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac);
|
zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac, 0);
|
||||||
|
|
||||||
/* Delete this neighbor entry. */
|
/* Delete this neighbor entry. */
|
||||||
zvni_neigh_del(zvni, n);
|
zvni_neigh_del(zvni, n);
|
||||||
@ -2008,8 +2346,8 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
|
|||||||
|
|
||||||
/* Issue delete for older info, if needed. */
|
/* Issue delete for older info, if needed. */
|
||||||
if (send_del)
|
if (send_del)
|
||||||
zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip,
|
zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac,
|
||||||
&n->emac);
|
0);
|
||||||
|
|
||||||
/* Set "local" forwarding info. */
|
/* Set "local" forwarding info. */
|
||||||
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
|
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
|
||||||
@ -2019,7 +2357,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
|
|||||||
/* Inform BGP if required. */
|
/* Inform BGP if required. */
|
||||||
if (send_upd)
|
if (send_upd)
|
||||||
return zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip,
|
return zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip,
|
||||||
macaddr);
|
macaddr, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2419,7 +2757,8 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp,
|
|||||||
|
|
||||||
/* Remove MAC from BGP. */
|
/* Remove MAC from BGP. */
|
||||||
sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
|
sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
|
||||||
zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr, sticky);
|
zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr,
|
||||||
|
(sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
|
||||||
|
|
||||||
/* Delete this MAC entry. */
|
/* Delete this MAC entry. */
|
||||||
zvni_mac_del(zvni, mac);
|
zvni_mac_del(zvni, mac);
|
||||||
@ -2526,7 +2865,8 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
|
|||||||
|
|
||||||
/* Remove MAC from BGP. */
|
/* Remove MAC from BGP. */
|
||||||
sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
|
sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
|
||||||
zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr, sticky);
|
zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr,
|
||||||
|
(sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
|
||||||
|
|
||||||
/* Delete this MAC entry. */
|
/* Delete this MAC entry. */
|
||||||
zvni_mac_del(zvni, mac);
|
zvni_mac_del(zvni, mac);
|
||||||
@ -2656,8 +2996,9 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
|
|||||||
|
|
||||||
/* Inform BGP if required. */
|
/* Inform BGP if required. */
|
||||||
if (add)
|
if (add)
|
||||||
return zvni_mac_send_add_to_client(zvrf, zvni->vni, macaddr,
|
return zvni_mac_send_add_to_client(
|
||||||
sticky);
|
zvrf, zvni->vni, macaddr,
|
||||||
|
(sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2788,6 +3129,100 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add/Del gateway macip to evpn
|
||||||
|
* g/w can be:
|
||||||
|
* 1. SVI interface on a vlan aware bridge
|
||||||
|
* 2. SVI interface on a vlan unaware bridge
|
||||||
|
* 3. vrr interface (MACVLAN) associated to a SVI
|
||||||
|
* We advertise macip routes for an interface if it is associated to VxLan vlan
|
||||||
|
*/
|
||||||
|
int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
|
||||||
|
int add)
|
||||||
|
{
|
||||||
|
struct ipaddr ip;
|
||||||
|
struct ethaddr macaddr;
|
||||||
|
zebra_vni_t *zvni = NULL;
|
||||||
|
struct zebra_vrf *zvrf = NULL;
|
||||||
|
|
||||||
|
memset(&ip, 0, sizeof(struct ipaddr));
|
||||||
|
memset(&macaddr, 0, sizeof(struct ethaddr));
|
||||||
|
|
||||||
|
if (IS_ZEBRA_IF_MACVLAN(ifp)) {
|
||||||
|
struct interface *svi_if =
|
||||||
|
NULL; /* SVI corresponding to the MACVLAN */
|
||||||
|
struct zebra_if *ifp_zif =
|
||||||
|
NULL; /* Zebra daemon specific info for MACVLAN */
|
||||||
|
struct zebra_if *svi_if_zif =
|
||||||
|
NULL; /* Zebra daemon specific info for SVI*/
|
||||||
|
|
||||||
|
ifp_zif = ifp->info;
|
||||||
|
if (!ifp_zif)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
svi_if = ifp_zif->link;
|
||||||
|
if (!svi_if) {
|
||||||
|
zlog_err("%u:MACVLAN %s(%u) without link information",
|
||||||
|
ifp->vrf_id, ifp->name, ifp->ifindex);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ZEBRA_IF_VLAN(svi_if)) {
|
||||||
|
svi_if_zif = svi_if->info;
|
||||||
|
if (svi_if_zif)
|
||||||
|
zvni = zvni_map_svi(svi_if, svi_if_zif->link);
|
||||||
|
} else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
|
||||||
|
zvni = zvni_map_svi(svi_if, svi_if);
|
||||||
|
}
|
||||||
|
} else if (IS_ZEBRA_IF_VLAN(ifp)) {
|
||||||
|
struct zebra_if *svi_if_zif =
|
||||||
|
NULL; /* Zebra daemon specific info for SVI*/
|
||||||
|
|
||||||
|
svi_if_zif = ifp->info;
|
||||||
|
if (svi_if_zif)
|
||||||
|
zvni = zvni_map_svi(ifp, svi_if_zif->link);
|
||||||
|
} else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
|
||||||
|
zvni = zvni_map_svi(ifp, ifp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!zvni)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!zvni->vxlan_if) {
|
||||||
|
zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
|
||||||
|
zvni->vni, zvni);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
|
||||||
|
if (!zvrf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* check if we are advertising gw macip routes */
|
||||||
|
if (!advertise_gw_macip_enabled(zvrf, zvni))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
|
||||||
|
|
||||||
|
if (p->family == AF_INET) {
|
||||||
|
ip.ipa_type = IPADDR_V4;
|
||||||
|
memcpy(&(ip.ipaddr_v4), &(p->u.prefix4),
|
||||||
|
sizeof(struct in_addr));
|
||||||
|
} else if (p->family == AF_INET6) {
|
||||||
|
ip.ipa_type = IPADDR_V6;
|
||||||
|
memcpy(&(ip.ipaddr_v6), &(p->u.prefix6),
|
||||||
|
sizeof(struct in6_addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (add)
|
||||||
|
zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
|
||||||
|
else
|
||||||
|
zvni_gw_macip_del(ifp, zvni, &ip);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle SVI interface going down. At this point, this is a NOP since
|
* Handle SVI interface going down. At this point, this is a NOP since
|
||||||
* the kernel deletes the neighbor entries on this SVI (if any).
|
* the kernel deletes the neighbor entries on this SVI (if any).
|
||||||
@ -3146,6 +3581,98 @@ int zebra_vxlan_if_add(struct interface *ifp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle message from client to enable/disable advertisement of g/w macip
|
||||||
|
* routes
|
||||||
|
*/
|
||||||
|
int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock,
|
||||||
|
u_short length, struct zebra_vrf *zvrf)
|
||||||
|
{
|
||||||
|
struct stream *s;
|
||||||
|
int advertise;
|
||||||
|
vni_t vni = 0;
|
||||||
|
zebra_vni_t *zvni = NULL;
|
||||||
|
|
||||||
|
s = client->ibuf;
|
||||||
|
advertise = stream_getc(s);
|
||||||
|
vni = stream_get3(s);
|
||||||
|
|
||||||
|
if (!vni) {
|
||||||
|
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||||
|
zlog_debug("%u:EVPN gateway macip Adv %s, currently %s",
|
||||||
|
zvrf_id(zvrf),
|
||||||
|
advertise ? "enabled" : "disabled",
|
||||||
|
advertise_gw_macip_enabled(zvrf, NULL)
|
||||||
|
? "enabled"
|
||||||
|
: "disabled");
|
||||||
|
|
||||||
|
if (zvrf->advertise_gw_macip == advertise)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
zvrf->advertise_gw_macip = advertise;
|
||||||
|
|
||||||
|
if (advertise_gw_macip_enabled(zvrf, zvni))
|
||||||
|
hash_iterate(zvrf->vni_table,
|
||||||
|
zvni_gw_macip_add_for_vni_hash, zvrf);
|
||||||
|
else
|
||||||
|
hash_iterate(zvrf->vni_table,
|
||||||
|
zvni_gw_macip_del_for_vni_hash, zvrf);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
struct zebra_if *zif = NULL;
|
||||||
|
struct zebra_l2info_vxlan zl2_info;
|
||||||
|
struct interface *vlan_if = NULL;
|
||||||
|
struct interface *vrr_if = NULL;
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||||
|
zlog_debug(
|
||||||
|
"%u:EVPN gateway macip Adv %s on VNI %d , currently %s",
|
||||||
|
zvrf_id(zvrf),
|
||||||
|
advertise ? "enabled" : "disabled", vni,
|
||||||
|
advertise_gw_macip_enabled(zvrf, zvni)
|
||||||
|
? "enabled"
|
||||||
|
: "disabled");
|
||||||
|
|
||||||
|
zvni = zvni_lookup(zvrf, vni);
|
||||||
|
if (!zvni)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (zvni->advertise_gw_macip == advertise)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
zvni->advertise_gw_macip = advertise;
|
||||||
|
|
||||||
|
zif = zvni->vxlan_if->info;
|
||||||
|
zl2_info = zif->l2info.vxl;
|
||||||
|
|
||||||
|
vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan,
|
||||||
|
zif->brslave_info.br_if);
|
||||||
|
if (!vlan_if)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (advertise_gw_macip_enabled(zvrf, zvni)) {
|
||||||
|
/* Add primary SVI MAC-IP */
|
||||||
|
zvni_add_macip_for_intf(vlan_if, zvni);
|
||||||
|
|
||||||
|
/* Add VRR MAC-IP - if any*/
|
||||||
|
vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
|
||||||
|
if (vrr_if)
|
||||||
|
zvni_add_macip_for_intf(vrr_if, zvni);
|
||||||
|
} else {
|
||||||
|
/* Del primary MAC-IP */
|
||||||
|
zvni_del_macip_for_intf(vlan_if, zvni);
|
||||||
|
|
||||||
|
/* Del VRR MAC-IP - if any*/
|
||||||
|
vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
|
||||||
|
if (vrr_if)
|
||||||
|
zvni_del_macip_for_intf(vrr_if, zvni);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle message from client to learn (or stop learning) about VNIs and MACs.
|
* Handle message from client to learn (or stop learning) about VNIs and MACs.
|
||||||
* When enabled, the VNI hash table will be built and MAC FDB table read;
|
* When enabled, the VNI hash table will be built and MAC FDB table read;
|
||||||
@ -3174,6 +3701,10 @@ int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock,
|
|||||||
/* Build VNI hash table and inform BGP. */
|
/* Build VNI hash table and inform BGP. */
|
||||||
zvni_build_hash_table(zvrf);
|
zvni_build_hash_table(zvrf);
|
||||||
|
|
||||||
|
/* Add all SVI (L3 GW) MACs to BGP*/
|
||||||
|
hash_iterate(zvrf->vni_table, zvni_gw_macip_add_for_vni_hash,
|
||||||
|
zvrf);
|
||||||
|
|
||||||
/* Read the MAC FDB */
|
/* Read the MAC FDB */
|
||||||
macfdb_read(zvrf->zns);
|
macfdb_read(zvrf->zns);
|
||||||
|
|
||||||
|
@ -68,6 +68,8 @@ extern void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf,
|
|||||||
vni_t vni);
|
vni_t vni);
|
||||||
extern void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf);
|
extern void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf);
|
||||||
|
|
||||||
|
extern int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
|
||||||
|
int add);
|
||||||
extern int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if);
|
extern int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if);
|
||||||
extern int zebra_vxlan_svi_down(struct interface *ifp,
|
extern int zebra_vxlan_svi_down(struct interface *ifp,
|
||||||
struct interface *link_if);
|
struct interface *link_if);
|
||||||
@ -104,6 +106,9 @@ extern int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock,
|
|||||||
u_short length, struct zebra_vrf *zvrf);
|
u_short length, struct zebra_vrf *zvrf);
|
||||||
extern int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock,
|
extern int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock,
|
||||||
u_short length, struct zebra_vrf *zvrf);
|
u_short length, struct zebra_vrf *zvrf);
|
||||||
|
extern int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock,
|
||||||
|
u_short length,
|
||||||
|
struct zebra_vrf *zvrf);
|
||||||
extern int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock,
|
extern int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock,
|
||||||
u_short length,
|
u_short length,
|
||||||
struct zebra_vrf *zvrf);
|
struct zebra_vrf *zvrf);
|
||||||
|
@ -63,6 +63,9 @@ struct zebra_vni_t_ {
|
|||||||
/* VNI - key */
|
/* VNI - key */
|
||||||
vni_t vni;
|
vni_t vni;
|
||||||
|
|
||||||
|
/* Flag for advertising gw macip */
|
||||||
|
u_int8_t advertise_gw_macip;
|
||||||
|
|
||||||
/* Corresponding VxLAN interface. */
|
/* Corresponding VxLAN interface. */
|
||||||
struct interface *vxlan_if;
|
struct interface *vxlan_if;
|
||||||
|
|
||||||
|
@ -2418,6 +2418,9 @@ static int zebra_client_read(struct thread *thread)
|
|||||||
case ZEBRA_FEC_UNREGISTER:
|
case ZEBRA_FEC_UNREGISTER:
|
||||||
zserv_fec_unregister(client, sock, length);
|
zserv_fec_unregister(client, sock, length);
|
||||||
break;
|
break;
|
||||||
|
case ZEBRA_ADVERTISE_DEFAULT_GW:
|
||||||
|
zebra_vxlan_advertise_gw_macip(client, sock, length, zvrf);
|
||||||
|
break;
|
||||||
case ZEBRA_ADVERTISE_ALL_VNI:
|
case ZEBRA_ADVERTISE_ALL_VNI:
|
||||||
zebra_vxlan_advertise_all_vni(client, sock, length, zvrf);
|
zebra_vxlan_advertise_all_vni(client, sock, length, zvrf);
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user