mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 18:42:23 +00:00
Merge pull request #3176 from chiragshah6/evpn_dev
zebra: duplicate address detection and dampening
This commit is contained in:
commit
19e5a46591
@ -5802,6 +5802,21 @@ void bgp_evpn_init(struct bgp *bgp)
|
||||
bgp->vrf_export_rtl->del = evpn_xxport_delete_ecomm;
|
||||
bgp->l2vnis = list_new();
|
||||
bgp->l2vnis->cmp = vni_list_cmp;
|
||||
/* By default Duplicate Address Dection is enabled.
|
||||
* Max-moves (N) 5, detection time (M) 180
|
||||
* default action is warning-only
|
||||
* freeze action permanently freezes address,
|
||||
* and freeze time (auto-recovery) is disabled.
|
||||
*/
|
||||
if (bgp->evpn_info) {
|
||||
bgp->evpn_info->dup_addr_detect = true;
|
||||
bgp->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
|
||||
bgp->evpn_info->dad_max_moves = EVPN_DAD_DEFAULT_MAX_MOVES;
|
||||
bgp->evpn_info->dad_freeze = false;
|
||||
bgp->evpn_info->dad_freeze_time = 0;
|
||||
/* Initialize zebra vxlan */
|
||||
bgp_zebra_dup_addr_detection(bgp);
|
||||
}
|
||||
|
||||
/* Default BUM handling is to do head-end replication. */
|
||||
bgp->vxlan_flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
|
||||
|
@ -161,6 +161,24 @@ struct vrf_irt_node {
|
||||
#define RT_TYPE_EXPORT 2
|
||||
#define RT_TYPE_BOTH 3
|
||||
|
||||
#define EVPN_DAD_DEFAULT_TIME 180 /* secs */
|
||||
#define EVPN_DAD_DEFAULT_MAX_MOVES 5 /* default from RFC 7432 */
|
||||
#define EVPN_DAD_DEFAULT_AUTO_RECOVERY_TIME 1800 /* secs */
|
||||
|
||||
struct bgp_evpn_info {
|
||||
/* enable disable dup detect */
|
||||
bool dup_addr_detect;
|
||||
|
||||
/* Detection time(M) */
|
||||
int dad_time;
|
||||
/* Detection max moves(N) */
|
||||
uint32_t dad_max_moves;
|
||||
/* Permanent freeze */
|
||||
bool dad_freeze;
|
||||
/* Recovery time */
|
||||
uint32_t dad_freeze_time;
|
||||
};
|
||||
|
||||
static inline int is_vrf_rd_configured(struct bgp *bgp_vrf)
|
||||
{
|
||||
return (CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD));
|
||||
|
@ -2999,6 +2999,130 @@ DEFUN (no_bgp_evpn_default_originate,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (dup_addr_detection,
|
||||
dup_addr_detection_cmd,
|
||||
"dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
|
||||
"Duplicate address detection\n"
|
||||
"Max allowed moves before address detected as duplicate\n"
|
||||
"Num of max allowed moves (2-1000) default 5\n"
|
||||
"Duplicate address detection time\n"
|
||||
"Time in seconds (2-1800) default 180\n")
|
||||
{
|
||||
struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
|
||||
|
||||
if (!bgp_vrf)
|
||||
return CMD_WARNING;
|
||||
|
||||
bgp_vrf->evpn_info->dup_addr_detect = true;
|
||||
|
||||
if (time_val)
|
||||
bgp_vrf->evpn_info->dad_time = time_val;
|
||||
if (max_moves_val)
|
||||
bgp_vrf->evpn_info->dad_max_moves = max_moves_val;
|
||||
|
||||
bgp_zebra_dup_addr_detection(bgp_vrf);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (dup_addr_detection_auto_recovery,
|
||||
dup_addr_detection_auto_recovery_cmd,
|
||||
"dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
|
||||
"Duplicate address detection\n"
|
||||
"Duplicate address detection freeze\n"
|
||||
"Duplicate address detection permanent freeze\n"
|
||||
"Duplicate address detection freeze time (30-3600)\n")
|
||||
{
|
||||
struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
|
||||
uint32_t freeze_time = freeze_time_val;
|
||||
|
||||
if (!bgp_vrf)
|
||||
return CMD_WARNING;
|
||||
|
||||
bgp_vrf->evpn_info->dup_addr_detect = true;
|
||||
bgp_vrf->evpn_info->dad_freeze = true;
|
||||
bgp_vrf->evpn_info->dad_freeze_time = freeze_time;
|
||||
|
||||
bgp_zebra_dup_addr_detection(bgp_vrf);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (no_dup_addr_detection,
|
||||
no_dup_addr_detection_cmd,
|
||||
"no dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val | freeze <permanent$permanent_val | (30-3600)$freeze_time_val>]",
|
||||
NO_STR
|
||||
"Duplicate address detection\n"
|
||||
"Max allowed moves before address detected as duplicate\n"
|
||||
"Num of max allowed moves (2-1000) default 5\n"
|
||||
"Duplicate address detection time\n"
|
||||
"Time in seconds (2-1800) default 180\n"
|
||||
"Duplicate address detection freeze\n"
|
||||
"Duplicate address detection permanent freeze\n"
|
||||
"Duplicate address detection freeze time (30-3600)\n")
|
||||
{
|
||||
struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
|
||||
uint32_t max_moves = (uint32_t)max_moves_val;
|
||||
uint32_t freeze_time = (uint32_t)freeze_time_val;
|
||||
|
||||
if (!bgp_vrf)
|
||||
return CMD_WARNING;
|
||||
|
||||
if (argc == 2) {
|
||||
if (!bgp_vrf->evpn_info->dup_addr_detect)
|
||||
return CMD_SUCCESS;
|
||||
/* Reset all parameters to default. */
|
||||
bgp_vrf->evpn_info->dup_addr_detect = false;
|
||||
bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
|
||||
bgp_vrf->evpn_info->dad_max_moves = EVPN_DAD_DEFAULT_MAX_MOVES;
|
||||
bgp_vrf->evpn_info->dad_freeze = false;
|
||||
bgp_vrf->evpn_info->dad_freeze_time = 0;
|
||||
} else {
|
||||
if (max_moves) {
|
||||
if (bgp_vrf->evpn_info->dad_max_moves != max_moves) {
|
||||
vty_out(vty,
|
||||
"%% Value does not match with config\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
bgp_vrf->evpn_info->dad_max_moves =
|
||||
EVPN_DAD_DEFAULT_MAX_MOVES;
|
||||
}
|
||||
|
||||
if (time_val) {
|
||||
if (bgp_vrf->evpn_info->dad_time != time_val) {
|
||||
vty_out(vty,
|
||||
"%% Value does not match with config\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
|
||||
}
|
||||
|
||||
if (freeze_time) {
|
||||
if (bgp_vrf->evpn_info->dad_freeze_time
|
||||
!= freeze_time) {
|
||||
vty_out(vty,
|
||||
"%% Value does not match with config\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
bgp_vrf->evpn_info->dad_freeze_time = 0;
|
||||
bgp_vrf->evpn_info->dad_freeze = false;
|
||||
}
|
||||
|
||||
if (permanent_val) {
|
||||
if (bgp_vrf->evpn_info->dad_freeze_time) {
|
||||
vty_out(vty,
|
||||
"%% Value does not match with config\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
bgp_vrf->evpn_info->dad_freeze = false;
|
||||
}
|
||||
}
|
||||
|
||||
bgp_zebra_dup_addr_detection(bgp_vrf);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
|
||||
bgp_evpn_advertise_vni_subnet_cmd,
|
||||
"advertise-subnet",
|
||||
@ -4919,6 +5043,26 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
if (bgp->advertise_gw_macip)
|
||||
vty_out(vty, " advertise-default-gw\n");
|
||||
|
||||
if (!bgp->evpn_info->dup_addr_detect)
|
||||
vty_out(vty, " no dup-addr-detection\n");
|
||||
|
||||
if (bgp->evpn_info->dad_max_moves !=
|
||||
EVPN_DAD_DEFAULT_MAX_MOVES ||
|
||||
bgp->evpn_info->dad_time != EVPN_DAD_DEFAULT_TIME)
|
||||
vty_out(vty, " dup-addr-detection max-moves %u time %u\n",
|
||||
bgp->evpn_info->dad_max_moves,
|
||||
bgp->evpn_info->dad_time);
|
||||
|
||||
if (bgp->evpn_info->dad_freeze) {
|
||||
if (bgp->evpn_info->dad_freeze_time)
|
||||
vty_out(vty,
|
||||
" dup-addr-detection freeze %u\n",
|
||||
bgp->evpn_info->dad_freeze_time);
|
||||
else
|
||||
vty_out(vty,
|
||||
" dup-addr-detection freeze permanent\n");
|
||||
}
|
||||
|
||||
if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
|
||||
vty_out(vty, " flooding disable\n");
|
||||
|
||||
@ -5013,6 +5157,9 @@ void bgp_ethernetvpn_init(void)
|
||||
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
|
||||
install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
|
||||
install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
|
||||
install_element(BGP_EVPN_NODE, &dup_addr_detection_cmd);
|
||||
install_element(BGP_EVPN_NODE, &dup_addr_detection_auto_recovery_cmd);
|
||||
install_element(BGP_EVPN_NODE, &no_dup_addr_detection_cmd);
|
||||
install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
|
||||
|
||||
/* test commands */
|
||||
|
@ -58,6 +58,7 @@
|
||||
#include "bgpd/bgp_mplsvpn.h"
|
||||
#include "bgpd/bgp_labelpool.h"
|
||||
#include "bgpd/bgp_pbr.h"
|
||||
#include "bgpd/bgp_evpn_private.h"
|
||||
|
||||
/* All information about zebra. */
|
||||
struct zclient *zclient = NULL;
|
||||
@ -1999,6 +2000,42 @@ int bgp_zebra_advertise_all_vni(struct bgp *bgp, int advertise)
|
||||
return zclient_send_message(zclient);
|
||||
}
|
||||
|
||||
int bgp_zebra_dup_addr_detection(struct bgp *bgp)
|
||||
{
|
||||
struct stream *s;
|
||||
|
||||
/* 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;
|
||||
|
||||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_debug("dup addr detect %s max_moves %u time %u freeze %s freeze_time %u",
|
||||
bgp->evpn_info->dup_addr_detect ?
|
||||
"enable" : "disable",
|
||||
bgp->evpn_info->dad_max_moves,
|
||||
bgp->evpn_info->dad_time,
|
||||
bgp->evpn_info->dad_freeze ?
|
||||
"enable" : "disable",
|
||||
bgp->evpn_info->dad_freeze_time);
|
||||
|
||||
s = zclient->obuf;
|
||||
stream_reset(s);
|
||||
zclient_create_header(s, ZEBRA_DUPLICATE_ADDR_DETECTION,
|
||||
bgp->vrf_id);
|
||||
stream_putl(s, bgp->evpn_info->dup_addr_detect);
|
||||
stream_putl(s, bgp->evpn_info->dad_time);
|
||||
stream_putl(s, bgp->evpn_info->dad_max_moves);
|
||||
stream_putl(s, bgp->evpn_info->dad_freeze);
|
||||
stream_putl(s, bgp->evpn_info->dad_freeze_time);
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
|
||||
return zclient_send_message(zclient);
|
||||
}
|
||||
|
||||
static int rule_notify_owner(int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id)
|
||||
{
|
||||
|
@ -73,6 +73,7 @@ extern int bgp_zebra_advertise_subnet(struct bgp *bgp, int advertise,
|
||||
vni_t vni);
|
||||
extern int bgp_zebra_advertise_gw_macip(struct bgp *, int, vni_t);
|
||||
extern int bgp_zebra_advertise_all_vni(struct bgp *, int);
|
||||
extern int bgp_zebra_dup_addr_detection(struct bgp *bgp);
|
||||
extern int bgp_zebra_vxlan_flood_control(struct bgp *bgp,
|
||||
enum vxlan_flood_control flood_ctrl);
|
||||
|
||||
|
@ -86,8 +86,10 @@
|
||||
#include "bgpd/bgp_labelpool.h"
|
||||
#include "bgpd/bgp_pbr.h"
|
||||
#include "bgpd/bgp_addpath.h"
|
||||
#include "bgpd/bgp_evpn_private.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)");
|
||||
DEFINE_MTYPE_STATIC(BGPD, BGP_EVPN_INFO, "BGP EVPN instance information");
|
||||
DEFINE_QOBJ_TYPE(bgp_master)
|
||||
DEFINE_QOBJ_TYPE(bgp)
|
||||
DEFINE_QOBJ_TYPE(peer)
|
||||
@ -2982,6 +2984,9 @@ static struct bgp *bgp_create(as_t *as, const char *name,
|
||||
/* assign a unique rd id for auto derivation of vrf's RD */
|
||||
bf_assign_index(bm->rd_idspace, bgp->vrf_rd_id);
|
||||
|
||||
bgp->evpn_info = XCALLOC(MTYPE_BGP_EVPN_INFO,
|
||||
sizeof(struct bgp_evpn_info));
|
||||
|
||||
bgp_evpn_init(bgp);
|
||||
bgp_pbr_init(bgp);
|
||||
return bgp;
|
||||
@ -3373,6 +3378,7 @@ void bgp_free(struct bgp *bgp)
|
||||
|
||||
bgp_evpn_cleanup(bgp);
|
||||
bgp_pbr_cleanup(bgp);
|
||||
XFREE(MTYPE_BGP_EVPN_INFO, bgp->evpn_info);
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||
vpn_policy_direction_t dir;
|
||||
|
@ -482,6 +482,8 @@ struct bgp {
|
||||
/* EVPN enable - advertise local VNIs and their MACs etc. */
|
||||
int advertise_all_vni;
|
||||
|
||||
struct bgp_evpn_info *evpn_info;
|
||||
|
||||
/* EVPN - use RFC 8365 to auto-derive RT */
|
||||
int advertise_autort_rfc8365;
|
||||
|
||||
|
@ -1034,6 +1034,7 @@ static const struct zebra_desc_table command_types[] = {
|
||||
DESC_ENTRY(ZEBRA_IP_PREFIX_ROUTE_DEL),
|
||||
DESC_ENTRY(ZEBRA_REMOTE_MACIP_ADD),
|
||||
DESC_ENTRY(ZEBRA_REMOTE_MACIP_DEL),
|
||||
DESC_ENTRY(ZEBRA_DUPLICATE_ADDR_DETECTION),
|
||||
DESC_ENTRY(ZEBRA_PW_ADD),
|
||||
DESC_ENTRY(ZEBRA_PW_DELETE),
|
||||
DESC_ENTRY(ZEBRA_PW_SET),
|
||||
|
@ -80,4 +80,15 @@ static inline int64_t monotime_until(const struct timeval *ref,
|
||||
return (int64_t)tv.tv_sec * 1000000LL + tv.tv_usec;
|
||||
}
|
||||
|
||||
static inline char *time_to_string(time_t ts)
|
||||
{
|
||||
struct timeval tv;
|
||||
time_t tbuf;
|
||||
|
||||
monotime(&tv);
|
||||
tbuf = time(NULL) - (tv.tv_sec - ts);
|
||||
|
||||
return ctime(&tbuf);
|
||||
}
|
||||
|
||||
#endif /* _FRR_MONOTIME_H */
|
||||
|
@ -135,6 +135,7 @@ typedef enum {
|
||||
ZEBRA_IP_PREFIX_ROUTE_DEL,
|
||||
ZEBRA_REMOTE_MACIP_ADD,
|
||||
ZEBRA_REMOTE_MACIP_DEL,
|
||||
ZEBRA_DUPLICATE_ADDR_DETECTION,
|
||||
ZEBRA_PW_ADD,
|
||||
ZEBRA_PW_DELETE,
|
||||
ZEBRA_PW_SET,
|
||||
|
@ -2443,6 +2443,7 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
|
||||
[ZEBRA_REMOTE_VTEP_DEL] = zebra_vxlan_remote_vtep_del,
|
||||
[ZEBRA_REMOTE_MACIP_ADD] = zebra_vxlan_remote_macip_add,
|
||||
[ZEBRA_REMOTE_MACIP_DEL] = zebra_vxlan_remote_macip_del,
|
||||
[ZEBRA_DUPLICATE_ADDR_DETECTION] = zebra_vxlan_dup_addr_detection,
|
||||
[ZEBRA_INTERFACE_SET_MASTER] = zread_interface_set_master,
|
||||
[ZEBRA_PW_ADD] = zread_pseudowire,
|
||||
[ZEBRA_PW_DELETE] = zread_pseudowire,
|
||||
|
@ -694,6 +694,33 @@ static struct log_ref ferr_zebra_err[] = {
|
||||
.suggestion =
|
||||
"Do not use v6 sourcedest routes, or upgrade your kernel.",
|
||||
},
|
||||
{
|
||||
.code = EC_ZEBRA_DUP_MAC_DETECTED,
|
||||
.title =
|
||||
"EVPN MAC is detected duplicate",
|
||||
.description =
|
||||
"Zebra has hit duplicate address detection threshold which means host MAC is moving.",
|
||||
.suggestion =
|
||||
"Check network topology to detect duplicate host MAC for correctness.",
|
||||
},
|
||||
{
|
||||
.code = EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
|
||||
.title =
|
||||
"EVPN IP is detected duplicate by MAC",
|
||||
.description =
|
||||
"Zebra has hit duplicate address detection threshold which means MAC-IP pair is moving.",
|
||||
.suggestion =
|
||||
"Check network topology to detect duplicate host MAC for correctness.",
|
||||
},
|
||||
{
|
||||
.code = EC_ZEBRA_DUP_IP_DETECTED,
|
||||
.title =
|
||||
"EVPN IP is detected duplicate",
|
||||
.description =
|
||||
"Zebra has hit duplicate address detection threshold which means host IP is moving.",
|
||||
.suggestion =
|
||||
"Check network topology to detect duplicate host IP for correctness.",
|
||||
},
|
||||
{
|
||||
.code = END_FERR,
|
||||
}
|
||||
|
@ -117,6 +117,9 @@ enum zebra_log_refs {
|
||||
EC_ZEBRA_MAX_LABELS_PUSH,
|
||||
EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT,
|
||||
EC_ZEBRA_UNSUPPORTED_V6_SRCDEST,
|
||||
EC_ZEBRA_DUP_MAC_DETECTED,
|
||||
EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
|
||||
EC_ZEBRA_DUP_IP_DETECTED,
|
||||
};
|
||||
|
||||
void zebra_error_init(void);
|
||||
|
@ -125,6 +125,13 @@ struct zebra_vrf {
|
||||
/* l3-vni info */
|
||||
vni_t l3vni;
|
||||
|
||||
bool dup_addr_detect;
|
||||
|
||||
int dad_time;
|
||||
uint32_t dad_max_moves;
|
||||
bool dad_freeze;
|
||||
uint32_t dad_freeze_time;
|
||||
|
||||
/*
|
||||
* Flooding mechanism for BUM packets for VxLAN-EVPN.
|
||||
*/
|
||||
|
@ -1970,7 +1970,7 @@ DEFUN (show_evpn_mac_vni_all,
|
||||
bool uj = use_json(argc, argv);
|
||||
|
||||
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
||||
zebra_vxlan_print_macs_all_vni(vty, zvrf, uj);
|
||||
zebra_vxlan_print_macs_all_vni(vty, zvrf, false, uj);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2059,6 +2059,90 @@ DEFUN (show_evpn_mac_vni_vtep,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (show_evpn_mac_vni_all_dad,
|
||||
show_evpn_mac_vni_all_dad_cmd,
|
||||
"show evpn mac vni all duplicate [json]",
|
||||
SHOW_STR
|
||||
"EVPN\n"
|
||||
"MAC addresses\n"
|
||||
"VxLAN Network Identifier\n"
|
||||
"All VNIs\n"
|
||||
"Duplicate address list\n"
|
||||
JSON_STR)
|
||||
{
|
||||
struct zebra_vrf *zvrf;
|
||||
bool uj = use_json(argc, argv);
|
||||
|
||||
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
||||
zebra_vxlan_print_macs_all_vni(vty, zvrf, true, uj);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DEFPY (show_evpn_mac_vni_dad,
|
||||
show_evpn_mac_vni_dad_cmd,
|
||||
"show evpn mac vni " CMD_VNI_RANGE " duplicate" "[json]",
|
||||
SHOW_STR
|
||||
"EVPN\n"
|
||||
"MAC addresses\n"
|
||||
"VxLAN Network Identifier\n"
|
||||
"VNI number\n"
|
||||
"Duplicate address list\n"
|
||||
JSON_STR)
|
||||
{
|
||||
struct zebra_vrf *zvrf;
|
||||
vni_t vni;
|
||||
bool uj = use_json(argc, argv);
|
||||
|
||||
vni = strtoul(argv[4]->arg, NULL, 10);
|
||||
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
||||
|
||||
zebra_vxlan_print_macs_vni_dad(vty, zvrf, vni, uj);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (show_evpn_neigh_vni_dad,
|
||||
show_evpn_neigh_vni_dad_cmd,
|
||||
"show evpn arp-cache vni " CMD_VNI_RANGE "duplicate" "[json]",
|
||||
SHOW_STR
|
||||
"EVPN\n"
|
||||
"ARP and ND cache\n"
|
||||
"VxLAN Network Identifier\n"
|
||||
"VNI number\n"
|
||||
"Duplicate address list\n"
|
||||
JSON_STR)
|
||||
{
|
||||
struct zebra_vrf *zvrf;
|
||||
vni_t vni;
|
||||
bool uj = use_json(argc, argv);
|
||||
|
||||
vni = strtoul(argv[4]->arg, NULL, 10);
|
||||
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
||||
zebra_vxlan_print_neigh_vni_dad(vty, zvrf, vni, uj);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (show_evpn_neigh_vni_all_dad,
|
||||
show_evpn_neigh_vni_all_dad_cmd,
|
||||
"show evpn arp-cache vni all duplicate [json]",
|
||||
SHOW_STR
|
||||
"EVPN\n"
|
||||
"ARP and ND cache\n"
|
||||
"VxLAN Network Identifier\n"
|
||||
"All VNIs\n"
|
||||
"Duplicate address list\n"
|
||||
JSON_STR)
|
||||
{
|
||||
struct zebra_vrf *zvrf;
|
||||
bool uj = use_json(argc, argv);
|
||||
|
||||
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
||||
zebra_vxlan_print_neigh_all_vni(vty, zvrf, true, uj);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DEFUN (show_evpn_neigh_vni,
|
||||
show_evpn_neigh_vni_cmd,
|
||||
"show evpn arp-cache vni " CMD_VNI_RANGE "[json]",
|
||||
@ -2093,7 +2177,7 @@ DEFUN (show_evpn_neigh_vni_all,
|
||||
bool uj = use_json(argc, argv);
|
||||
|
||||
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
||||
zebra_vxlan_print_neigh_all_vni(vty, zvrf, uj);
|
||||
zebra_vxlan_print_neigh_all_vni(vty, zvrf, false, uj);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2193,6 +2277,55 @@ DEFUN (show_pbr_iptable,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (clear_evpn_dup_addr,
|
||||
clear_evpn_dup_addr_cmd,
|
||||
"clear evpn dup-addr vni <all$vni_all |" CMD_VNI_RANGE"$vni_val [mac M:A:C$mac_val | ip <A.B.C.D|X:X::X:X>]>",
|
||||
CLEAR_STR
|
||||
"EVPN\n"
|
||||
"Duplicate address \n"
|
||||
"VxLAN Network Identifier\n"
|
||||
"VNI number\n"
|
||||
"All VNIs\n"
|
||||
"MAC\n"
|
||||
"MAC address (e.g., 00:e0:ec:20:12:62)\n"
|
||||
"IP\n"
|
||||
"IPv4 address\n"
|
||||
"IPv6 address\n")
|
||||
{
|
||||
struct zebra_vrf *zvrf;
|
||||
vni_t vni = 0;
|
||||
struct ipaddr host_ip = {.ipa_type = IPADDR_NONE };
|
||||
struct ethaddr mac_addr;
|
||||
|
||||
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
||||
if (vni_val) {
|
||||
vni = strtoul(vni_val, NULL, 10);
|
||||
|
||||
if (mac_val) {
|
||||
prefix_str2mac(mac_val, &mac_addr);
|
||||
zebra_vxlan_clear_dup_detect_vni_mac(vty, zvrf, vni,
|
||||
&mac_addr);
|
||||
} else if (ip) {
|
||||
if (sockunion_family(ip) == AF_INET) {
|
||||
host_ip.ipa_type = IPADDR_V4;
|
||||
host_ip.ipaddr_v4.s_addr = sockunion2ip(ip);
|
||||
} else {
|
||||
host_ip.ipa_type = IPADDR_V6;
|
||||
memcpy(&host_ip.ipaddr_v6, &ip->sin6.sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
}
|
||||
zebra_vxlan_clear_dup_detect_vni_ip(vty, zvrf, vni,
|
||||
&host_ip);
|
||||
} else
|
||||
zebra_vxlan_clear_dup_detect_vni(vty, zvrf, vni);
|
||||
|
||||
} else {
|
||||
zebra_vxlan_clear_dup_detect_vni_all(vty, zvrf);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* Static ip route configuration write function. */
|
||||
static int zebra_ip_config(struct vty *vty)
|
||||
{
|
||||
@ -2755,10 +2888,15 @@ void zebra_vty_init(void)
|
||||
install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_mac_vni_dad_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_mac_vni_all_dad_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_neigh_vni_dad_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_neigh_vni_all_dad_cmd);
|
||||
install_element(ENABLE_NODE, &clear_evpn_dup_addr_cmd);
|
||||
|
||||
install_element(VIEW_NODE, &show_pbr_ipset_cmd);
|
||||
install_element(VIEW_NODE, &show_pbr_iptable_cmd);
|
||||
|
1353
zebra/zebra_vxlan.c
1353
zebra/zebra_vxlan.c
File diff suppressed because it is too large
Load Diff
@ -70,6 +70,7 @@ extern void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS);
|
||||
extern void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS);
|
||||
extern void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS);
|
||||
extern void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS);
|
||||
extern void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS);
|
||||
|
||||
extern int is_l3vni_for_prefix_routes_only(vni_t vni);
|
||||
extern ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id);
|
||||
@ -87,6 +88,7 @@ extern void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
|
||||
vni_t vni, bool use_json);
|
||||
extern void zebra_vxlan_print_macs_all_vni(struct vty *vty,
|
||||
struct zebra_vrf *zvrf,
|
||||
bool print_dup,
|
||||
bool use_json);
|
||||
extern void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
|
||||
struct zebra_vrf *zvrf,
|
||||
@ -100,10 +102,14 @@ extern void zebra_vxlan_print_macs_vni_vtep(struct vty *vty,
|
||||
struct zebra_vrf *zvrf, vni_t vni,
|
||||
struct in_addr vtep_ip,
|
||||
bool use_json);
|
||||
extern void zebra_vxlan_print_macs_vni_dad(struct vty *vty,
|
||||
struct zebra_vrf *zvrf, vni_t vni,
|
||||
bool use_json);
|
||||
extern void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
|
||||
vni_t vni, bool use_json);
|
||||
extern void zebra_vxlan_print_neigh_all_vni(struct vty *vty,
|
||||
struct zebra_vrf *zvrf,
|
||||
bool print_dup,
|
||||
bool use_json);
|
||||
extern void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
|
||||
struct zebra_vrf *zvrf,
|
||||
@ -113,6 +119,9 @@ extern void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty,
|
||||
struct zebra_vrf *zvrf, vni_t vni,
|
||||
struct in_addr vtep_ip,
|
||||
bool use_json);
|
||||
extern void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
|
||||
struct zebra_vrf *zvrf, vni_t vni,
|
||||
bool use_json);
|
||||
extern void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf,
|
||||
vni_t vni, bool use_json);
|
||||
extern void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
|
||||
@ -172,5 +181,17 @@ extern void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id,
|
||||
extern void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
|
||||
struct ipaddr *vtep_ip,
|
||||
struct prefix *host_prefix);
|
||||
extern void zebra_vxlan_clear_dup_detect_vni_mac(struct vty *vty,
|
||||
struct zebra_vrf *zvrf,
|
||||
vni_t vni,
|
||||
struct ethaddr *macaddr);
|
||||
extern void zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty,
|
||||
struct zebra_vrf *zvrf,
|
||||
vni_t vni, struct ipaddr *ip);
|
||||
extern void zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty,
|
||||
struct zebra_vrf *zvrf);
|
||||
extern void zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
|
||||
struct zebra_vrf *zvrf,
|
||||
vni_t vni);
|
||||
|
||||
#endif /* _ZEBRA_VXLAN_H */
|
||||
|
@ -249,6 +249,10 @@ struct zebra_mac_t_ {
|
||||
#define ZEBRA_MAC_DEF_GW 0x20
|
||||
/* remote VTEP advertised MAC as default GW */
|
||||
#define ZEBRA_MAC_REMOTE_DEF_GW 0x40
|
||||
#define ZEBRA_MAC_DUPLICATE 0x80
|
||||
|
||||
/* back pointer to zvni */
|
||||
zebra_vni_t *zvni;
|
||||
|
||||
/* Local or remote info. */
|
||||
union {
|
||||
@ -269,6 +273,15 @@ struct zebra_mac_t_ {
|
||||
|
||||
/* list of hosts pointing to this remote RMAC */
|
||||
struct host_rb_tree_entry host_rb;
|
||||
|
||||
/* Duplicate mac detection */
|
||||
uint32_t dad_count;
|
||||
|
||||
struct thread *dad_mac_auto_recovery_timer;
|
||||
|
||||
struct timeval detect_start_time;
|
||||
|
||||
time_t dad_dup_detect_time;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -292,6 +305,7 @@ struct mac_walk_ctx {
|
||||
struct vty *vty; /* Used by VTY handlers */
|
||||
uint32_t count; /* Used by VTY handlers */
|
||||
struct json_object *json; /* Used for JSON Output */
|
||||
bool print_dup; /* Used to print dup addr list */
|
||||
};
|
||||
|
||||
struct rmac_walk_ctx {
|
||||
@ -330,12 +344,15 @@ struct zebra_neigh_t_ {
|
||||
/* Underlying interface. */
|
||||
ifindex_t ifindex;
|
||||
|
||||
zebra_vni_t *zvni;
|
||||
|
||||
uint32_t flags;
|
||||
#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
|
||||
#define ZEBRA_NEIGH_ROUTER_FLAG 0x10
|
||||
#define ZEBRA_NEIGH_DUPLICATE 0x20
|
||||
|
||||
enum zebra_neigh_state state;
|
||||
|
||||
@ -354,6 +371,15 @@ struct zebra_neigh_t_ {
|
||||
|
||||
/* list of hosts pointing to this remote NH entry */
|
||||
struct host_rb_tree_entry host_rb;
|
||||
|
||||
/* Duplicate ip detection */
|
||||
uint32_t dad_count;
|
||||
|
||||
struct thread *dad_ip_auto_recovery_timer;
|
||||
|
||||
struct timeval detect_start_time;
|
||||
|
||||
time_t dad_dup_detect_time;
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user