mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 16:04:49 +00:00
bgpd/zebra/lib: Add Default Gateway extended community
1. Added default gw extended community 2. code modification to handle sticky-mac/default-gw-mac as they go together 3. show command support for newly added extended community 4. State in zebra to reflect if a mac/neigh is default gateway 5. show command enhancement to refelect the same in zebra commands Ticket: CM-17428 Review: CCR-6580 Testing: Manual Signed-off-by: Mitesh Kanjariya <mitesh@cumulusnetworks.com>
This commit is contained in:
parent
d6fed38109
commit
ead40654de
@ -1876,6 +1876,9 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
|
||||
attr->mm_seqnum = bgp_attr_mac_mobility_seqnum(attr, &sticky);
|
||||
attr->sticky = sticky;
|
||||
|
||||
/* Check if this is a Gateway MAC-IP advertisement */
|
||||
attr->default_gw = bgp_attr_default_gw(attr);
|
||||
|
||||
/* Extract the Rmac, if any */
|
||||
bgp_attr_rmac(attr, &attr->rmac);
|
||||
|
||||
|
@ -162,6 +162,9 @@ struct attr {
|
||||
/* Static MAC for EVPN */
|
||||
u_char sticky;
|
||||
|
||||
/* Flag for default gateway extended community in EVPN */
|
||||
u_char default_gw;
|
||||
|
||||
/* route tag */
|
||||
route_tag_t tag;
|
||||
|
||||
|
@ -134,6 +134,36 @@ void bgp_attr_rmac(struct attr *attr,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* return true if attr contains default gw extended community
|
||||
*/
|
||||
uint8_t bgp_attr_default_gw(struct attr *attr)
|
||||
{
|
||||
struct ecommunity *ecom;
|
||||
int i;
|
||||
|
||||
ecom = attr->ecommunity;
|
||||
if (!ecom || !ecom->size)
|
||||
return 0;
|
||||
|
||||
/* If there is a default gw extendd community return true otherwise
|
||||
* return 0 */
|
||||
for (i = 0; i < ecom->size; i++) {
|
||||
u_char *pnt;
|
||||
u_char type, sub_type;
|
||||
|
||||
pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
|
||||
type = *pnt++;
|
||||
sub_type = *pnt++;
|
||||
|
||||
if ((type == ECOMMUNITY_ENCODE_OPAQUE
|
||||
&& sub_type == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch and return the sequence number from MAC Mobility extended
|
||||
* community, if present, else 0.
|
||||
|
@ -62,5 +62,6 @@ extern int bgp_build_evpn_prefix(int type, uint32_t eth_tag,
|
||||
extern void bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac);
|
||||
extern u_int32_t bgp_attr_mac_mobility_seqnum(struct attr *attr,
|
||||
u_char *sticky);
|
||||
extern uint8_t bgp_attr_default_gw(struct attr *attr);
|
||||
|
||||
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */
|
||||
|
@ -690,6 +690,9 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
|
||||
tunneltype = ntohs(tunneltype);
|
||||
len = sprintf(str_buf + str_pnt, "ET:%d",
|
||||
tunneltype);
|
||||
} else if (*pnt == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW) {
|
||||
len = sprintf(str_buf + str_pnt,
|
||||
"Default Gateway");
|
||||
} else
|
||||
unk_ecom = 1;
|
||||
} else if (type == ECOMMUNITY_ENCODE_EVPN) {
|
||||
|
103
bgpd/bgp_evpn.c
103
bgpd/bgp_evpn.c
@ -506,7 +506,7 @@ static void derive_rd_rt_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
struct prefix_evpn *p,
|
||||
struct in_addr remote_vtep_ip, int add,
|
||||
u_char sticky)
|
||||
u_char flags)
|
||||
{
|
||||
struct stream *s;
|
||||
int ipa_len;
|
||||
@ -541,18 +541,18 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
}
|
||||
stream_put_in_addr(s, &remote_vtep_ip);
|
||||
|
||||
/* TX MAC sticky status */
|
||||
/* TX flags - MAC sticky status and/or gateway mac */
|
||||
if (add)
|
||||
stream_putc(s, sticky);
|
||||
stream_putc(s, flags);
|
||||
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
|
||||
if (bgp_debug_zebra(NULL))
|
||||
zlog_debug("Tx %s MACIP, VNI %u %sMAC %s IP %s remote VTEP %s",
|
||||
zlog_debug("Tx %s MACIP, VNI %u MAC %s IP %s (flags: 0x%x) remote VTEP %s",
|
||||
add ? "ADD" : "DEL", vpn->vni,
|
||||
sticky ? "sticky " : "",
|
||||
prefix_mac2str(&p->prefix.mac, buf1, sizeof(buf1)),
|
||||
ipaddr2str(&p->prefix.ip, buf3, sizeof(buf3)),
|
||||
flags,
|
||||
inet_ntop(AF_INET, &remote_vtep_ip, buf2,
|
||||
sizeof(buf2)));
|
||||
|
||||
@ -662,9 +662,11 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
|
||||
{
|
||||
struct ecommunity ecom_encap;
|
||||
struct ecommunity ecom_sticky;
|
||||
struct ecommunity ecom_default_gw;
|
||||
struct ecommunity ecom_rmac;
|
||||
struct ecommunity_val eval;
|
||||
struct ecommunity_val eval_sticky;
|
||||
struct ecommunity_val eval_default_gw;
|
||||
struct ecommunity_val eval_rmac;
|
||||
bgp_encap_types tnl_type;
|
||||
struct listnode *node, *nnode;
|
||||
@ -719,6 +721,15 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
|
||||
&ecom_rmac);
|
||||
}
|
||||
|
||||
if (attr->default_gw) {
|
||||
memset(&ecom_default_gw, 0, sizeof(ecom_default_gw));
|
||||
encode_default_gw_extcomm(&eval_default_gw);
|
||||
ecom_default_gw.size = 1;
|
||||
ecom_default_gw.val = (uint8_t *)eval_default_gw.val;
|
||||
attr->ecommunity = ecommunity_merge(attr->ecommunity,
|
||||
&ecom_default_gw);
|
||||
}
|
||||
|
||||
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
|
||||
}
|
||||
|
||||
@ -776,13 +787,13 @@ static void add_mac_mobility_to_attr(u_int32_t seq_num, struct attr *attr)
|
||||
/* Install EVPN route into zebra. */
|
||||
static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
struct prefix_evpn *p,
|
||||
struct in_addr remote_vtep_ip, u_char sticky)
|
||||
struct in_addr remote_vtep_ip, u_char flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
|
||||
ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip,
|
||||
1, sticky);
|
||||
1, flags);
|
||||
else
|
||||
ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 1);
|
||||
|
||||
@ -853,6 +864,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
afi_t afi = AFI_L2VPN;
|
||||
safi_t safi = SAFI_EVPN;
|
||||
int ret = 0;
|
||||
u_char flags = 0;
|
||||
|
||||
/* Compute the best path. */
|
||||
bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
|
||||
@ -870,11 +882,16 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
&& !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
|
||||
&& !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED)
|
||||
&& !bgp->addpath_tx_used[afi][safi]) {
|
||||
if (bgp_zebra_has_route_changed(rn, old_select))
|
||||
if (bgp_zebra_has_route_changed(rn, old_select)) {
|
||||
if (old_select->attr->sticky)
|
||||
SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
|
||||
if (old_select->attr->default_gw)
|
||||
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
|
||||
ret = evpn_zebra_install(bgp, vpn,
|
||||
(struct prefix_evpn *)&rn->p,
|
||||
old_select->attr->nexthop,
|
||||
old_select->attr->sticky);
|
||||
flags);
|
||||
}
|
||||
UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG);
|
||||
bgp_zebra_clear_route_change_flags(rn);
|
||||
return ret;
|
||||
@ -899,9 +916,14 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
|
||||
if (new_select && new_select->type == ZEBRA_ROUTE_BGP
|
||||
&& new_select->sub_type == BGP_ROUTE_NORMAL) {
|
||||
flags = 0;
|
||||
if (new_select->attr->sticky)
|
||||
SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
|
||||
if (new_select->attr->default_gw)
|
||||
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
|
||||
ret = evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p,
|
||||
new_select->attr->nexthop,
|
||||
new_select->attr->sticky);
|
||||
flags);
|
||||
/* If an old best existed and it was a "local" route, the only
|
||||
* reason
|
||||
* it would be supplanted is due to MAC mobility procedures. So,
|
||||
@ -931,6 +953,28 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the local ri for this rn is of type gateway mac
|
||||
*/
|
||||
static int evpn_route_is_def_gw(struct bgp *bgp, struct bgp_node *rn)
|
||||
{
|
||||
struct bgp_info *tmp_ri = NULL;
|
||||
struct bgp_info *local_ri = NULL;
|
||||
|
||||
local_ri = NULL;
|
||||
for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) {
|
||||
if (tmp_ri->peer == bgp->peer_self
|
||||
&& tmp_ri->type == ZEBRA_ROUTE_BGP
|
||||
&& tmp_ri->sub_type == BGP_ROUTE_STATIC)
|
||||
local_ri = tmp_ri;
|
||||
}
|
||||
|
||||
if (!local_ri)
|
||||
return 0;
|
||||
|
||||
return local_ri->attr->default_gw;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return true if the local ri for this rn has sticky set
|
||||
@ -1129,7 +1173,7 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
* SVI) advertised in EVPN.
|
||||
* This will ensure that local routes are preferred for g/w macs
|
||||
*/
|
||||
if (remote_ri && !CHECK_FLAG(flags, ZEBRA_MAC_TYPE_GW)) {
|
||||
if (remote_ri && !CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) {
|
||||
u_int32_t cur_seqnum;
|
||||
|
||||
/* Add MM extended community to route. */
|
||||
@ -1206,7 +1250,8 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
attr.mp_nexthop_global_in = vpn->originator_ip;
|
||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
attr.sticky = CHECK_FLAG(flags, ZEBRA_MAC_TYPE_STICKY) ? 1 : 0;
|
||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
|
||||
attr.default_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW) ? 1 : 0;
|
||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
|
||||
bgpevpn_get_rmac(vpn, &attr.rmac);
|
||||
vni2label(vpn->vni, &(attr.label));
|
||||
|
||||
@ -1394,22 +1439,27 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
struct bgp_info *ri;
|
||||
struct attr attr;
|
||||
struct attr attr_sticky;
|
||||
struct attr attr_def_gw;
|
||||
struct attr attr_ip6;
|
||||
struct attr attr_sticky_ip6;
|
||||
struct attr attr_def_gw_ip6;
|
||||
struct attr *attr_new;
|
||||
|
||||
afi = AFI_L2VPN;
|
||||
safi = SAFI_EVPN;
|
||||
memset(&attr, 0, sizeof(struct attr));
|
||||
memset(&attr_sticky, 0, sizeof(struct attr));
|
||||
memset(&attr_def_gw, 0, sizeof(struct attr));
|
||||
memset(&attr_ip6, 0, sizeof(struct attr));
|
||||
memset(&attr_sticky_ip6, 0, sizeof(struct attr));
|
||||
memset(&attr_def_gw_ip6, 0, sizeof(struct attr));
|
||||
|
||||
/* Build path-attribute - all type-2 routes for this VNI will share the
|
||||
* same path attribute.
|
||||
*/
|
||||
bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
|
||||
bgp_attr_default_set(&attr_sticky, BGP_ORIGIN_IGP);
|
||||
bgp_attr_default_set(&attr_def_gw, BGP_ORIGIN_IGP);
|
||||
attr.nexthop = vpn->originator_ip;
|
||||
attr.mp_nexthop_global_in = vpn->originator_ip;
|
||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
@ -1419,6 +1469,11 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
attr_sticky.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
attr_sticky.sticky = 1;
|
||||
bgpevpn_get_rmac(vpn, &attr_sticky.rmac);
|
||||
attr_def_gw.nexthop = vpn->originator_ip;
|
||||
attr_def_gw.mp_nexthop_global_in = vpn->originator_ip;
|
||||
attr_def_gw.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
attr_def_gw.default_gw = 1;
|
||||
bgpevpn_get_rmac(vpn, &attr_def_gw.rmac);
|
||||
bgp_attr_default_set(&attr_ip6, BGP_ORIGIN_IGP);
|
||||
bgp_attr_default_set(&attr_sticky_ip6, BGP_ORIGIN_IGP);
|
||||
attr_ip6.nexthop = vpn->originator_ip;
|
||||
@ -1430,12 +1485,19 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
attr_sticky_ip6.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
attr_sticky_ip6.sticky = 1;
|
||||
bgpevpn_get_rmac(vpn, &attr_sticky_ip6.rmac);
|
||||
attr_def_gw_ip6.nexthop = vpn->originator_ip;
|
||||
attr_def_gw_ip6.mp_nexthop_global_in = vpn->originator_ip;
|
||||
attr_def_gw_ip6.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
attr_def_gw_ip6.default_gw = 1;
|
||||
bgpevpn_get_rmac(vpn, &attr_def_gw_ip6.rmac);
|
||||
|
||||
/* Set up RT, ENCAP and sticky MAC extended community. */
|
||||
build_evpn_route_extcomm(vpn, &attr, AFI_IP);
|
||||
build_evpn_route_extcomm(vpn, &attr_sticky, AFI_IP);
|
||||
build_evpn_route_extcomm(vpn, &attr_def_gw, AFI_IP);
|
||||
build_evpn_route_extcomm(vpn, &attr_ip6, AFI_IP6);
|
||||
build_evpn_route_extcomm(vpn, &attr_sticky_ip6, AFI_IP6);
|
||||
build_evpn_route_extcomm(vpn, &attr_def_gw_ip6, AFI_IP);
|
||||
|
||||
/* Walk this VNI's route table and update local type-2 routes. For any
|
||||
* routes updated, update corresponding entry in the global table too.
|
||||
@ -1454,6 +1516,10 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||
&attr_sticky, 0, 1,
|
||||
&ri, 0);
|
||||
else if (evpn_route_is_def_gw(bgp, rn))
|
||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||
&attr_def_gw, 0, 1,
|
||||
&ri, 0);
|
||||
else
|
||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||
&attr, 0, 1, &ri, 0);
|
||||
@ -1462,6 +1528,10 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||
&attr_sticky_ip6, 0, 1,
|
||||
&ri, 0);
|
||||
else if (evpn_route_is_def_gw(bgp, rn))
|
||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||
&attr_def_gw_ip6, 0, 1,
|
||||
&ri, 0);
|
||||
else
|
||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||
&attr_ip6, 0, 1,
|
||||
@ -1496,7 +1566,11 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
|
||||
/* Unintern temporary. */
|
||||
aspath_unintern(&attr.aspath);
|
||||
aspath_unintern(&attr_ip6.aspath);
|
||||
aspath_unintern(&attr_sticky.aspath);
|
||||
aspath_unintern(&attr_sticky_ip6.aspath);
|
||||
aspath_unintern(&attr_def_gw.aspath);
|
||||
aspath_unintern(&attr_def_gw_ip6.aspath);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -4042,12 +4116,13 @@ int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
|
||||
char buf2[INET6_ADDRSTRLEN];
|
||||
|
||||
zlog_err(
|
||||
"%u:Failed to create Type-2 route, VNI %u %s MAC %s IP %s",
|
||||
"%u:Failed to create Type-2 route, VNI %u %s MAC %s IP %s (flags: 0x%x)",
|
||||
bgp->vrf_id, vpn->vni,
|
||||
CHECK_FLAG(flags, ZEBRA_MAC_TYPE_STICKY) ? "sticky gateway"
|
||||
: "",
|
||||
prefix_mac2str(mac, buf, sizeof(buf)),
|
||||
ipaddr2str(ip, buf2, sizeof(buf2)));
|
||||
ipaddr2str(ip, buf2, sizeof(buf2)),
|
||||
flags);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -257,6 +257,13 @@ static inline void encode_rmac_extcomm(struct ecommunity_val *eval,
|
||||
memcpy(&eval->val[2], rmac, ETH_ALEN);
|
||||
}
|
||||
|
||||
static inline void encode_default_gw_extcomm(struct ecommunity_val *eval)
|
||||
{
|
||||
memset(eval, 0, sizeof(*eval));
|
||||
eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE;
|
||||
eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_DEF_GW;
|
||||
}
|
||||
|
||||
static inline void encode_mac_mobility_extcomm(int static_mac, u_int32_t seq,
|
||||
struct ecommunity_val *eval)
|
||||
{
|
||||
|
@ -343,8 +343,8 @@ enum zapi_route_notify_owner {
|
||||
};
|
||||
|
||||
/* Zebra MAC types */
|
||||
#define ZEBRA_MAC_TYPE_STICKY 0x01 /* Sticky MAC*/
|
||||
#define ZEBRA_MAC_TYPE_GW 0x02 /* gateway (SVI) mac*/
|
||||
#define ZEBRA_MACIP_TYPE_STICKY 0x01 /* Sticky MAC*/
|
||||
#define ZEBRA_MACIP_TYPE_GW 0x02 /* gateway (SVI) mac*/
|
||||
|
||||
struct zclient_options {
|
||||
bool receive_notify;
|
||||
|
@ -286,6 +286,12 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
|
||||
: "Inactive");
|
||||
}
|
||||
}
|
||||
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW)) {
|
||||
if (!json)
|
||||
vty_out(vty, " Default-gateway");
|
||||
else
|
||||
json_object_boolean_true_add(json, "defaultGateway");
|
||||
}
|
||||
if (json == NULL)
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
@ -534,6 +540,12 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt)
|
||||
vty_out(vty, " Auto Mac ");
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
|
||||
vty_out(vty, " Sticky Mac ");
|
||||
|
||||
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
|
||||
vty_out(vty, " Default-gateway Mac ");
|
||||
|
||||
vty_out(vty, "\n");
|
||||
/* print all the associated neigh */
|
||||
vty_out(vty, " Neighbors:\n");
|
||||
@ -1409,7 +1421,7 @@ static void zvni_process_neigh_on_local_mac_add(zebra_vni_t *zvni,
|
||||
|
||||
ZEBRA_NEIGH_SET_ACTIVE(n);
|
||||
zvni_neigh_send_add_to_client(
|
||||
zvni->vni, &n->ip, &n->emac, 0);
|
||||
zvni->vni, &n->ip, &n->emac, n->flags);
|
||||
} else {
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
@ -1519,8 +1531,14 @@ static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t *zvni,
|
||||
*/
|
||||
static int zvni_neigh_send_add_to_client(vni_t vni,
|
||||
struct ipaddr *ip,
|
||||
struct ethaddr *macaddr, u_char flags)
|
||||
struct ethaddr *macaddr,
|
||||
u_char neigh_flags)
|
||||
{
|
||||
u_char flags = 0;
|
||||
|
||||
if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_DEF_GW))
|
||||
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
|
||||
|
||||
return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
|
||||
ZEBRA_MACIP_ADD);
|
||||
}
|
||||
@ -1729,6 +1747,7 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
|
||||
/* Set "local" forwarding info. */
|
||||
SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
|
||||
SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
|
||||
SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
|
||||
memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
|
||||
mac->fwd_info.local.ifindex = ifp->ifindex;
|
||||
mac->fwd_info.local.vid = vxl->access_vlan;
|
||||
@ -1748,9 +1767,14 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
|
||||
|
||||
/* Set "local" forwarding info. */
|
||||
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
|
||||
SET_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW);
|
||||
memcpy(&n->emac, macaddr, ETH_ALEN);
|
||||
n->ifindex = ifp->ifindex;
|
||||
|
||||
/* Only advertise in BGP if the knob is enabled */
|
||||
if (!advertise_gw_macip_enabled(zvni))
|
||||
return 0;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
"SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP",
|
||||
@ -1759,7 +1783,7 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
|
||||
ipaddr2str(ip, buf2, sizeof(buf2)));
|
||||
|
||||
zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr,
|
||||
ZEBRA_MAC_TYPE_GW);
|
||||
n->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1793,16 +1817,21 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
|
||||
if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL))
|
||||
return -1;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
"SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s del to BGP",
|
||||
ifp->name, ifp->ifindex, zvni->vni,
|
||||
prefix_mac2str(&(n->emac), buf1, sizeof(buf1)),
|
||||
ipaddr2str(ip, buf2, sizeof(buf2)));
|
||||
/* only need to delete the entry from bgp if we sent it before */
|
||||
if (advertise_gw_macip_enabled(zvni)) {
|
||||
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(zvni->vni, &n->ip, &n->emac,
|
||||
ZEBRA_MAC_TYPE_GW);
|
||||
/* Remove neighbor from BGP. */
|
||||
zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
|
||||
ZEBRA_MACIP_TYPE_GW);
|
||||
}
|
||||
|
||||
/* Delete this neighbor entry. */
|
||||
zvni_neigh_del(zvni, n);
|
||||
@ -1869,9 +1898,6 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
|
||||
if (!zvni)
|
||||
return;
|
||||
|
||||
if (!advertise_gw_macip_enabled(zvni))
|
||||
return;
|
||||
|
||||
ifp = zvni->vxlan_if;
|
||||
if (!ifp)
|
||||
return;
|
||||
@ -1985,7 +2011,6 @@ static int zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg)
|
||||
{
|
||||
struct mac_walk_ctx *wctx = arg;
|
||||
zebra_mac_t *mac = backet->data;
|
||||
u_char sticky = 0;
|
||||
|
||||
if (((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL))
|
||||
|| ((wctx->flags & DEL_REMOTE_MAC)
|
||||
@ -1995,11 +2020,9 @@ static int zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg)
|
||||
&& IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
|
||||
&wctx->r_vtep_ip))) {
|
||||
if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
|
||||
sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1
|
||||
: 0;
|
||||
zvni_mac_send_del_to_client(
|
||||
wctx->zvni->vni, &mac->macaddr,
|
||||
(sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
|
||||
mac->flags);
|
||||
}
|
||||
|
||||
if (wctx->uninstall)
|
||||
@ -2074,8 +2097,16 @@ static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *mac)
|
||||
* Inform BGP about local MAC addition.
|
||||
*/
|
||||
static int zvni_mac_send_add_to_client(vni_t vni,
|
||||
struct ethaddr *macaddr, u_char flags)
|
||||
struct ethaddr *macaddr,
|
||||
u_char mac_flags)
|
||||
{
|
||||
u_char flags = 0;
|
||||
|
||||
if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY))
|
||||
SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
|
||||
if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW))
|
||||
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
|
||||
|
||||
return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
|
||||
ZEBRA_MACIP_ADD);
|
||||
}
|
||||
@ -2084,8 +2115,16 @@ static int zvni_mac_send_add_to_client(vni_t vni,
|
||||
* Inform BGP about local MAC deletion.
|
||||
*/
|
||||
static int zvni_mac_send_del_to_client(vni_t vni,
|
||||
struct ethaddr *macaddr, u_char flags)
|
||||
struct ethaddr *macaddr,
|
||||
u_char mac_flags)
|
||||
{
|
||||
u_char flags = 0;
|
||||
|
||||
if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY))
|
||||
SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
|
||||
if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW))
|
||||
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
|
||||
|
||||
return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
|
||||
ZEBRA_MACIP_DEL);
|
||||
}
|
||||
@ -2393,15 +2432,13 @@ static void zvni_read_mac_neigh(zebra_vni_t *zvni,
|
||||
vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
|
||||
if (vlan_if) {
|
||||
|
||||
if (advertise_gw_macip_enabled(zvni)) {
|
||||
/* Add SVI MAC-IP */
|
||||
zvni_add_macip_for_intf(vlan_if, 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);
|
||||
}
|
||||
/* 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(zns, vlan_if);
|
||||
}
|
||||
@ -4768,7 +4805,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
|
||||
zvni->vni);
|
||||
ZEBRA_NEIGH_SET_ACTIVE(n);
|
||||
|
||||
return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, 0);
|
||||
return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags);
|
||||
}
|
||||
|
||||
|
||||
@ -4879,6 +4916,17 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length,
|
||||
if (!mac && !n)
|
||||
continue;
|
||||
|
||||
/* Ignore the delete if this mac is a gateway mac-ip */
|
||||
if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) &&
|
||||
CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) {
|
||||
zlog_err("%u: Ignore Del for MAC %s neigh %s on VNI %u as it is configured as a default gateway",
|
||||
zvrf_id(zvrf),
|
||||
prefix_mac2str(&macaddr, buf, sizeof(buf)),
|
||||
ipaddr2str(&ip, buf1, sizeof(buf1)),
|
||||
vni);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Uninstall remote neighbor or MAC. */
|
||||
if (n) {
|
||||
/* When the MAC changes for an IP, it is possible the
|
||||
@ -4936,7 +4984,8 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
|
||||
int update_mac = 0, update_neigh = 0;
|
||||
char buf[ETHER_ADDR_STRLEN];
|
||||
char buf1[INET6_ADDRSTRLEN];
|
||||
u_char sticky;
|
||||
u_char sticky = 0;
|
||||
u_char flags = 0;
|
||||
struct interface *ifp = NULL;
|
||||
struct zebra_if *zif = NULL;
|
||||
|
||||
@ -4973,17 +5022,17 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
|
||||
STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
|
||||
l += IPV4_MAX_BYTELEN;
|
||||
|
||||
/* Get 'sticky' flag. */
|
||||
STREAM_GETC(s, sticky);
|
||||
/* Get flags - sticky mac and/or gateway mac */
|
||||
flags = stream_getc(s);
|
||||
sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
|
||||
l++;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
"Recv MACIP Add %sMAC %s IP %s VNI %u Remote VTEP %s from %s",
|
||||
sticky ? "sticky " : "",
|
||||
"Recv MACIP Add MAC %s IP %s VNI %u Remote VTEP %s with flags 0x%x from %s",
|
||||
prefix_mac2str(&macaddr, buf, sizeof(buf)),
|
||||
ipaddr2str(&ip, buf1, sizeof(buf1)), vni,
|
||||
inet_ntoa(vtep_ip),
|
||||
inet_ntoa(vtep_ip), flags,
|
||||
zebra_route_string(client->proto));
|
||||
|
||||
/* Locate VNI hash entry - expected to exist. */
|
||||
@ -5025,13 +5074,26 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
|
||||
zvni_vtep_install(zvni, &vtep_ip);
|
||||
}
|
||||
|
||||
/* First, check if the remote MAC is unknown or has a change. If
|
||||
* so,
|
||||
* that needs to be updated first. Note that client could
|
||||
* install
|
||||
* MAC and MACIP separately or just install the latter.
|
||||
*/
|
||||
mac = zvni_mac_lookup(zvni, &macaddr);
|
||||
|
||||
/* Ignore the update if the mac is already present
|
||||
as a gateway mac */
|
||||
if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW) &&
|
||||
CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) {
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug("%u:Ignore MAC %s IP %s on VNI %u as MAC is already configured as gateway mac",
|
||||
zvrf_id(zvrf),
|
||||
prefix_mac2str(&macaddr,
|
||||
buf, sizeof(buf)),
|
||||
ipaddr2str(&ip, buf1,
|
||||
sizeof(buf1)), vni);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check if the remote MAC is unknown or has a change.
|
||||
* If so, that needs to be updated first. Note that client could
|
||||
* install MAC and MACIP separately or just install the latter.
|
||||
*/
|
||||
if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
|
||||
|| (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0)
|
||||
!= sticky
|
||||
@ -5146,7 +5208,6 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp,
|
||||
zebra_vni_t *zvni;
|
||||
zebra_mac_t *mac;
|
||||
char buf[ETHER_ADDR_STRLEN];
|
||||
u_char sticky;
|
||||
|
||||
zif = ifp->info;
|
||||
assert(zif);
|
||||
@ -5178,9 +5239,7 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp,
|
||||
ifp->name, ifp->ifindex, vni);
|
||||
|
||||
/* Remove MAC from BGP. */
|
||||
sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
|
||||
zvni_mac_send_del_to_client(zvni->vni, macaddr,
|
||||
(sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
|
||||
zvni_mac_send_del_to_client(zvni->vni, macaddr, mac->flags);
|
||||
|
||||
/*
|
||||
* If there are no neigh associated with the mac delete the mac
|
||||
@ -5253,7 +5312,6 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
|
||||
zebra_vni_t *zvni;
|
||||
zebra_mac_t *mac;
|
||||
char buf[ETHER_ADDR_STRLEN];
|
||||
u_char sticky;
|
||||
|
||||
/* We are interested in MACs only on ports or (port, VLAN) that
|
||||
* map to a VNI.
|
||||
@ -5282,9 +5340,7 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
|
||||
return 0;
|
||||
|
||||
/* Remove MAC from BGP. */
|
||||
sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
|
||||
zvni_mac_send_del_to_client(zvni->vni, macaddr,
|
||||
(sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
|
||||
zvni_mac_send_del_to_client(zvni->vni, macaddr, mac->flags);
|
||||
|
||||
/* Update all the neigh entries associated with this mac */
|
||||
zvni_process_neigh_on_local_mac_del(zvni, mac);
|
||||
@ -5423,7 +5479,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
|
||||
if (add) {
|
||||
zvni_process_neigh_on_local_mac_add(zvni, mac);
|
||||
return zvni_mac_send_add_to_client(zvni->vni, macaddr,
|
||||
sticky);
|
||||
mac->flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -5687,10 +5743,6 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
|
||||
}
|
||||
|
||||
|
||||
/* check if we are advertising gw macip routes */
|
||||
if (!advertise_gw_macip_enabled(zvni))
|
||||
return 0;
|
||||
|
||||
memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
|
||||
|
||||
if (p->family == AF_INET) {
|
||||
|
@ -233,6 +233,7 @@ struct zebra_mac_t_ {
|
||||
#define ZEBRA_MAC_AUTO 0x04 /* Auto created for neighbor. */
|
||||
#define ZEBRA_MAC_STICKY 0x08 /* Static MAC */
|
||||
#define ZEBRA_MAC_REMOTE_RMAC 0x10 /* remote router mac */
|
||||
#define ZEBRA_MAC_DEF_GW 0x20
|
||||
|
||||
/* Local or remote info. */
|
||||
union {
|
||||
@ -314,6 +315,7 @@ struct zebra_neigh_t_ {
|
||||
#define ZEBRA_NEIGH_LOCAL 0x01
|
||||
#define ZEBRA_NEIGH_REMOTE 0x02
|
||||
#define ZEBRA_NEIGH_REMOTE_NH 0x04 /* neigh entry for remote vtep */
|
||||
#define ZEBRA_NEIGH_DEF_GW 0x08
|
||||
|
||||
enum zebra_neigh_state state;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user