mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 10:37:29 +00:00
zebra: add support for DF delay timer
When a new ES is created it is held in a non-DF state for 3 seconds as specified by RFC7432. This allows the switch time to import the Type-4 routes from the peers. And the peers time to rx the new Type-4 route. root@torm-11:mgmt:~# vtysh -c "show evpn es 03:44:38:39:ff:ff:01:00:00:01"|grep DF DF status: non-df DF delay: 00:00:01 DF preference: 50000 root@torm-11:mgmt:~# vtysh -c "show evpn es 03:44:38:39:ff:ff:01:00:00:01"|grep DF DF status: df DF preference: 50000 root@torm-11:mgmt:~# Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
This commit is contained in:
parent
0109f42f86
commit
35f5c31b0e
@ -1470,16 +1470,16 @@ static bool zebra_evpn_es_br_port_dplane_update(struct zebra_evpn_es *es,
|
|||||||
|
|
||||||
/* returns TRUE if dplane entry was updated */
|
/* returns TRUE if dplane entry was updated */
|
||||||
static bool zebra_evpn_es_df_change(struct zebra_evpn_es *es, bool new_non_df,
|
static bool zebra_evpn_es_df_change(struct zebra_evpn_es *es, bool new_non_df,
|
||||||
const char *caller)
|
const char *caller, const char *reason)
|
||||||
{
|
{
|
||||||
bool old_non_df;
|
bool old_non_df;
|
||||||
|
|
||||||
old_non_df = !!(es->flags & ZEBRA_EVPNES_NON_DF);
|
old_non_df = !!(es->flags & ZEBRA_EVPNES_NON_DF);
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
|
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
|
||||||
zlog_debug("df-change(%s) es %s old %s new %s", caller,
|
zlog_debug("df-change es %s %s to %s; %s: %s", es->esi_str,
|
||||||
es->esi_str, old_non_df ? "non-df" : "df",
|
old_non_df ? "non-df" : "df",
|
||||||
new_non_df ? "non-df" : "df");
|
new_non_df ? "non-df" : "df", caller, reason);
|
||||||
|
|
||||||
if (old_non_df == new_non_df)
|
if (old_non_df == new_non_df)
|
||||||
return false;
|
return false;
|
||||||
@ -1507,7 +1507,8 @@ static bool zebra_evpn_es_run_df_election(struct zebra_evpn_es *es,
|
|||||||
*/
|
*/
|
||||||
if (!(es->flags & ZEBRA_EVPNES_LOCAL)
|
if (!(es->flags & ZEBRA_EVPNES_LOCAL)
|
||||||
|| !zmh_info->es_originator_ip.s_addr)
|
|| !zmh_info->es_originator_ip.s_addr)
|
||||||
return zebra_evpn_es_df_change(es, new_non_df, caller);
|
return zebra_evpn_es_df_change(es, new_non_df, caller,
|
||||||
|
"not-ready");
|
||||||
|
|
||||||
/* if oper-state is down DF filtering must be on. when the link comes
|
/* if oper-state is down DF filtering must be on. when the link comes
|
||||||
* up again dataplane should block BUM till FRR has had the chance
|
* up again dataplane should block BUM till FRR has had the chance
|
||||||
@ -1515,7 +1516,18 @@ static bool zebra_evpn_es_run_df_election(struct zebra_evpn_es *es,
|
|||||||
*/
|
*/
|
||||||
if (!(es->flags & ZEBRA_EVPNES_OPER_UP)) {
|
if (!(es->flags & ZEBRA_EVPNES_OPER_UP)) {
|
||||||
new_non_df = true;
|
new_non_df = true;
|
||||||
return zebra_evpn_es_df_change(es, new_non_df, caller);
|
return zebra_evpn_es_df_change(es, new_non_df, caller,
|
||||||
|
"oper-down");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ES was just created; we need to wait for the peers to rx the
|
||||||
|
* our Type-4 routes and for the switch to import the peers' Type-4
|
||||||
|
* routes
|
||||||
|
*/
|
||||||
|
if (es->df_delay_timer) {
|
||||||
|
new_non_df = true;
|
||||||
|
return zebra_evpn_es_df_change(es, new_non_df, caller,
|
||||||
|
"df-delay");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
|
for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
|
||||||
@ -1547,7 +1559,7 @@ static bool zebra_evpn_es_run_df_election(struct zebra_evpn_es *es,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return zebra_evpn_es_df_change(es, new_non_df, caller);
|
return zebra_evpn_es_df_change(es, new_non_df, caller, "elected");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void zebra_evpn_es_vtep_add(struct zebra_evpn_es *es,
|
static void zebra_evpn_es_vtep_add(struct zebra_evpn_es *es,
|
||||||
@ -1932,6 +1944,20 @@ static void zebra_evpn_mh_dup_addr_detect_off(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int zebra_evpn_es_df_delay_exp_cb(struct thread *t)
|
||||||
|
{
|
||||||
|
struct zebra_evpn_es *es;
|
||||||
|
|
||||||
|
es = THREAD_ARG(t);
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
|
||||||
|
zlog_debug("es %s df-delay expired", es->esi_str);
|
||||||
|
|
||||||
|
zebra_evpn_es_run_df_election(es, __func__);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es,
|
static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es,
|
||||||
struct zebra_if *zif)
|
struct zebra_if *zif)
|
||||||
{
|
{
|
||||||
@ -1971,6 +1997,12 @@ static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es,
|
|||||||
zebra_evpn_es_re_eval_send_to_client(es,
|
zebra_evpn_es_re_eval_send_to_client(es,
|
||||||
false /* es_evi_re_reval */);
|
false /* es_evi_re_reval */);
|
||||||
|
|
||||||
|
/* Start the DF delay timer on the local ES */
|
||||||
|
if (!es->df_delay_timer)
|
||||||
|
thread_add_timer(zrouter.master, zebra_evpn_es_df_delay_exp_cb,
|
||||||
|
es, ZEBRA_EVPN_MH_DF_DELAY_TIME,
|
||||||
|
&es->df_delay_timer);
|
||||||
|
|
||||||
/* See if the local VTEP can function as DF on the ES */
|
/* See if the local VTEP can function as DF on the ES */
|
||||||
if (!zebra_evpn_es_run_df_election(es, __func__)) {
|
if (!zebra_evpn_es_run_df_election(es, __func__)) {
|
||||||
/* check if the dplane entry needs to be re-programmed as a
|
/* check if the dplane entry needs to be re-programmed as a
|
||||||
@ -2007,6 +2039,8 @@ static void zebra_evpn_es_local_info_clear(struct zebra_evpn_es **esp)
|
|||||||
|
|
||||||
es->flags &= ~(ZEBRA_EVPNES_LOCAL | ZEBRA_EVPNES_READY_FOR_BGP);
|
es->flags &= ~(ZEBRA_EVPNES_LOCAL | ZEBRA_EVPNES_READY_FOR_BGP);
|
||||||
|
|
||||||
|
THREAD_OFF(es->df_delay_timer);
|
||||||
|
|
||||||
/* remove the DF filter */
|
/* remove the DF filter */
|
||||||
dplane_updated = zebra_evpn_es_run_df_election(es, __func__);
|
dplane_updated = zebra_evpn_es_run_df_election(es, __func__);
|
||||||
|
|
||||||
@ -2696,6 +2730,7 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty,
|
|||||||
char alg_buf[EVPN_DF_ALG_STR_LEN];
|
char alg_buf[EVPN_DF_ALG_STR_LEN];
|
||||||
struct zebra_evpn_es_vtep *es_vtep;
|
struct zebra_evpn_es_vtep *es_vtep;
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
|
char thread_buf[THREAD_TIMER_STRLEN];
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
json_object *json_vteps;
|
json_object *json_vteps;
|
||||||
@ -2732,6 +2767,12 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty,
|
|||||||
listcount(es->es_evi_list));
|
listcount(es->es_evi_list));
|
||||||
json_object_int_add(json, "macCount", listcount(es->mac_list));
|
json_object_int_add(json, "macCount", listcount(es->mac_list));
|
||||||
json_object_int_add(json, "dfPreference", es->df_pref);
|
json_object_int_add(json, "dfPreference", es->df_pref);
|
||||||
|
if (es->df_delay_timer)
|
||||||
|
json_object_string_add(
|
||||||
|
json, "dfDelayTimer",
|
||||||
|
thread_timer_to_hhmmss(thread_buf,
|
||||||
|
sizeof(thread_buf),
|
||||||
|
es->df_delay_timer));
|
||||||
json_object_int_add(json, "nexthopGroup", es->nhg_id);
|
json_object_int_add(json, "nexthopGroup", es->nhg_id);
|
||||||
if (listcount(es->es_vtep_list)) {
|
if (listcount(es->es_vtep_list)) {
|
||||||
json_vteps = json_object_new_array();
|
json_vteps = json_object_new_array();
|
||||||
@ -2766,12 +2807,16 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty,
|
|||||||
"yes" : "no");
|
"yes" : "no");
|
||||||
vty_out(vty, " VNI Count: %d\n", listcount(es->es_evi_list));
|
vty_out(vty, " VNI Count: %d\n", listcount(es->es_evi_list));
|
||||||
vty_out(vty, " MAC Count: %d\n", listcount(es->mac_list));
|
vty_out(vty, " MAC Count: %d\n", listcount(es->mac_list));
|
||||||
vty_out(vty, " DF: status: %s preference: %u\n",
|
if (es->flags & ZEBRA_EVPNES_LOCAL)
|
||||||
!(es->flags & ZEBRA_EVPNES_LOCAL)
|
vty_out(vty, " DF status: %s \n",
|
||||||
? "-"
|
(es->flags & ZEBRA_EVPNES_NON_DF) ? "non-df"
|
||||||
: ((es->flags & ZEBRA_EVPNES_NON_DF) ? "non-df"
|
: "df");
|
||||||
: "df"),
|
if (es->df_delay_timer)
|
||||||
es->df_pref);
|
vty_out(vty, " DF delay: %s\n",
|
||||||
|
thread_timer_to_hhmmss(thread_buf,
|
||||||
|
sizeof(thread_buf),
|
||||||
|
es->df_delay_timer));
|
||||||
|
vty_out(vty, " DF preference: %u\n", es->df_pref);
|
||||||
vty_out(vty, " Nexthop group: %u\n", es->nhg_id);
|
vty_out(vty, " Nexthop group: %u\n", es->nhg_id);
|
||||||
vty_out(vty, " VTEPs:\n");
|
vty_out(vty, " VTEPs:\n");
|
||||||
for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
|
for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
|
||||||
@ -3479,8 +3524,7 @@ static void zebra_evpn_mh_startup_delay_timer_start(const char *rc)
|
|||||||
if (zmh_info->startup_delay_timer) {
|
if (zmh_info->startup_delay_timer) {
|
||||||
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
|
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
|
||||||
zlog_debug("startup-delay timer cancelled");
|
zlog_debug("startup-delay timer cancelled");
|
||||||
thread_cancel(&zmh_info->startup_delay_timer);
|
THREAD_OFF(zmh_info->startup_delay_timer);
|
||||||
zmh_info->startup_delay_timer = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zmh_info->startup_delay_time) {
|
if (zmh_info->startup_delay_time) {
|
||||||
|
@ -88,6 +88,13 @@ struct zebra_evpn_es {
|
|||||||
* advertised via the ESR
|
* advertised via the ESR
|
||||||
*/
|
*/
|
||||||
uint16_t df_pref;
|
uint16_t df_pref;
|
||||||
|
|
||||||
|
/* When a new ES is configured it is held in a non-DF state
|
||||||
|
* for 3 seconds. This allows the peer Type-4 routes to be
|
||||||
|
* imported before running the DF election.
|
||||||
|
*/
|
||||||
|
#define ZEBRA_EVPN_MH_DF_DELAY_TIME 3 /* seconds */
|
||||||
|
struct thread *df_delay_timer;
|
||||||
};
|
};
|
||||||
RB_HEAD(zebra_es_rb_head, zebra_evpn_es);
|
RB_HEAD(zebra_es_rb_head, zebra_evpn_es);
|
||||||
RB_PROTOTYPE(zebra_es_rb_head, zebra_evpn_es, rb_node, zebra_es_rb_cmp);
|
RB_PROTOTYPE(zebra_es_rb_head, zebra_evpn_es, rb_node, zebra_es_rb_cmp);
|
||||||
|
Loading…
Reference in New Issue
Block a user