diff options
Diffstat (limited to 'zebra/zebra_evpn_mh.c')
| -rw-r--r-- | zebra/zebra_evpn_mh.c | 312 |
1 files changed, 225 insertions, 87 deletions
diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c index 53412a434e..7e712bf1ee 100644 --- a/zebra/zebra_evpn_mh.c +++ b/zebra/zebra_evpn_mh.c @@ -63,13 +63,14 @@ static void zebra_evpn_es_get_one_base_evpn(void); static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es, zebra_evpn_t *zevpn, bool add); static void zebra_evpn_local_es_del(struct zebra_evpn_es **esp); -static int zebra_evpn_local_es_update(struct zebra_if *zif, uint32_t lid, - struct ethaddr *sysmac); +static int zebra_evpn_local_es_update(struct zebra_if *zif, esi_t *esi); static bool zebra_evpn_es_br_port_dplane_update(struct zebra_evpn_es *es, const char *caller); static void zebra_evpn_mh_uplink_cfg_update(struct zebra_if *zif, bool set); -static void zebra_evpn_mh_update_protodown_es(struct zebra_evpn_es *es); +static void zebra_evpn_mh_update_protodown_es(struct zebra_evpn_es *es, + bool resync_dplane); static void zebra_evpn_mh_clear_protodown_es(struct zebra_evpn_es *es); +static void zebra_evpn_mh_startup_delay_timer_start(const char *rc); esi_t zero_esi_buf, *zero_esi = &zero_esi_buf; @@ -416,15 +417,12 @@ void zebra_evpn_es_evi_show_vni(struct vty *vty, bool uj, vni_t vni, int detail) vty_out(vty, "Type: L local, R remote\n"); vty_out(vty, "%-8s %-30s %-4s\n", "VNI", "ESI", "Type"); } + zebra_evpn_es_evi_show_one_evpn(zevpn, vty, json_array, detail); } else { if (!uj) vty_out(vty, "VNI %d doesn't exist\n", vni); - - return; } - zebra_evpn_es_evi_show_one_evpn(zevpn, vty, json_array, detail); - if (uj) { vty_out(vty, "%s\n", json_object_to_json_string_ext( @@ -935,7 +933,7 @@ void zebra_evpn_if_init(struct zebra_if *zif) /* if an es_id and sysmac are already present against the interface * activate it */ - zebra_evpn_local_es_update(zif, zif->es_info.lid, &zif->es_info.sysmac); + zebra_evpn_local_es_update(zif, &zif->es_info.esi); } /* handle deletion of an access port by removing it from all associated @@ -1469,16 +1467,16 @@ static bool zebra_evpn_es_br_port_dplane_update(struct zebra_evpn_es *es, /* returns TRUE if dplane entry was updated */ 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; old_non_df = !!(es->flags & ZEBRA_EVPNES_NON_DF); if (IS_ZEBRA_DEBUG_EVPN_MH_ES) - zlog_debug("df-change(%s) es %s old %s new %s", caller, - es->esi_str, old_non_df ? "non-df" : "df", - new_non_df ? "non-df" : "df"); + zlog_debug("df-change es %s %s to %s; %s: %s", es->esi_str, + old_non_df ? "non-df" : "df", + new_non_df ? "non-df" : "df", caller, reason); if (old_non_df == new_non_df) return false; @@ -1506,7 +1504,8 @@ static bool zebra_evpn_es_run_df_election(struct zebra_evpn_es *es, */ if (!(es->flags & ZEBRA_EVPNES_LOCAL) || !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 * up again dataplane should block BUM till FRR has had the chance @@ -1514,7 +1513,18 @@ static bool zebra_evpn_es_run_df_election(struct zebra_evpn_es *es, */ if (!(es->flags & ZEBRA_EVPNES_OPER_UP)) { 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)) { @@ -1546,7 +1556,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, @@ -1636,6 +1646,9 @@ static struct zebra_evpn_es *zebra_evpn_es_new(esi_t *esi) { struct zebra_evpn_es *es; + if (!memcmp(esi, zero_esi, sizeof(esi_t))) + return NULL; + es = XCALLOC(MTYPE_ZES, sizeof(struct zebra_evpn_es)); /* fill in ESI */ @@ -1851,6 +1864,8 @@ static void zebra_evpn_es_setup_evis(struct zebra_evpn_es *es) uint16_t vid; struct zebra_evpn_access_bd *acc_bd; + if (!bf_is_inited(zif->vlan_bitmap)) + return; bf_for_each_set_bit(zif->vlan_bitmap, vid, IF_VLAN_BITMAP_MAX) { acc_bd = zebra_evpn_acc_vl_find(vid); @@ -1928,6 +1943,37 @@ static void zebra_evpn_mh_dup_addr_detect_off(void) } } +/* On config of first local-ES turn off advertisement of STALE/DELAY/PROBE + * neighbors + */ +static void zebra_evpn_mh_advertise_reach_neigh_only(void) +{ + if (zmh_info->flags & ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY) + return; + + zmh_info->flags |= ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY; + if (IS_ZEBRA_DEBUG_EVPN_MH_ES) + zlog_debug("evpn-mh: only REACHABLE neigh advertised"); + + /* XXX - if STALE/DELAY/PROBE neighs were previously advertised we + * need to withdraw them + */ +} + +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, struct zebra_if *zif) { @@ -1939,6 +1985,7 @@ static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es, es->nhg_id, zif->ifp->name); zebra_evpn_mh_dup_addr_detect_off(); + zebra_evpn_mh_advertise_reach_neigh_only(); es->flags |= ZEBRA_EVPNES_LOCAL; listnode_init(&es->local_es_listnode, es); @@ -1967,6 +2014,12 @@ static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es, zebra_evpn_es_re_eval_send_to_client(es, 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 */ if (!zebra_evpn_es_run_df_election(es, __func__)) { /* check if the dplane entry needs to be re-programmed as a @@ -1989,7 +2042,7 @@ static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es, false /* force_clear_static */); /* inherit EVPN protodown flags on the access port */ - zebra_evpn_mh_update_protodown_es(es); + zebra_evpn_mh_update_protodown_es(es, true /*resync_dplane*/); } static void zebra_evpn_es_local_info_clear(struct zebra_evpn_es **esp) @@ -2003,6 +2056,8 @@ static void zebra_evpn_es_local_info_clear(struct zebra_evpn_es **esp) es->flags &= ~(ZEBRA_EVPNES_LOCAL | ZEBRA_EVPNES_READY_FOR_BGP); + THREAD_OFF(es->df_delay_timer); + /* remove the DF filter */ dplane_updated = zebra_evpn_es_run_df_election(es, __func__); @@ -2090,17 +2145,50 @@ static void zebra_evpn_es_remote_info_re_eval(struct zebra_evpn_es **esp) /* A new local es is created when a local-es-id and sysmac is configured * against an interface. */ -static int zebra_evpn_local_es_update(struct zebra_if *zif, uint32_t lid, - struct ethaddr *sysmac) +static int zebra_evpn_local_es_update(struct zebra_if *zif, esi_t *esi) { struct zebra_evpn_es *old_es = zif->es_info.es; struct zebra_evpn_es *es; + + memcpy(&zif->es_info.esi, esi, sizeof(*esi)); + if (old_es && !memcmp(&old_es->esi, esi, sizeof(*esi))) + /* dup - nothing to be done */ + return 0; + + /* release the old_es against the zif */ + if (old_es) + zebra_evpn_local_es_del(&old_es); + + es = zebra_evpn_es_find(esi); + if (es) { + /* if it exists against another interface flag an error */ + if (es->zif && es->zif != zif) { + memset(&zif->es_info.esi, 0, sizeof(*esi)); + return -1; + } + } else { + /* create new es */ + es = zebra_evpn_es_new(esi); + } + + if (es) + zebra_evpn_es_local_info_set(es, zif); + + return 0; +} + +static int zebra_evpn_type3_esi_update(struct zebra_if *zif, uint32_t lid, + struct ethaddr *sysmac) +{ + struct zebra_evpn_es *old_es = zif->es_info.es; esi_t esi; int offset = 0; int field_bytes = 0; /* Complete config of the ES-ID bootstraps the ES */ if (!lid || is_zero_mac(sysmac)) { + /* clear old esi */ + memset(&zif->es_info.esi, 0, sizeof(zif->es_info.esi)); /* if in ES is attached to zif delete it */ if (old_es) zebra_evpn_local_es_del(&old_es); @@ -2122,27 +2210,7 @@ static int zebra_evpn_local_es_update(struct zebra_if *zif, uint32_t lid, esi.val[offset++] = (uint8_t)(lid >> 8); esi.val[offset++] = (uint8_t)lid; - if (old_es && !memcmp(&old_es->esi, &esi, sizeof(esi_t))) - /* dup - nothing to be done */ - return 0; - - /* release the old_es against the zif */ - if (old_es) - zebra_evpn_local_es_del(&old_es); - - es = zebra_evpn_es_find(&esi); - if (es) { - /* if it exists against another interface flag an error */ - if (es->zif && es->zif != zif) - return -1; - } else { - /* create new es */ - es = zebra_evpn_es_new(&esi); - } - - zebra_evpn_es_local_info_set(es, zif); - - return 0; + return zebra_evpn_local_es_update(zif, &esi); } static int zebra_evpn_remote_es_del(esi_t *esi, struct in_addr vtep_ip) @@ -2349,7 +2417,7 @@ static int zebra_evpn_es_sys_mac_update(struct zebra_if *zif, { int rv; - rv = zebra_evpn_local_es_update(zif, zif->es_info.lid, sysmac); + rv = zebra_evpn_type3_esi_update(zif, zif->es_info.lid, sysmac); if (!rv) memcpy(&zif->es_info.sysmac, sysmac, sizeof(struct ethaddr)); @@ -2361,13 +2429,29 @@ static int zebra_evpn_es_lid_update(struct zebra_if *zif, uint32_t lid) { int rv; - rv = zebra_evpn_local_es_update(zif, lid, &zif->es_info.sysmac); + rv = zebra_evpn_type3_esi_update(zif, lid, &zif->es_info.sysmac); if (!rv) zif->es_info.lid = lid; return rv; } +/* type-0 esi has changed */ +static int zebra_evpn_es_type0_esi_update(struct zebra_if *zif, esi_t *esi) +{ + int rv; + + rv = zebra_evpn_local_es_update(zif, esi); + + /* clear the old es_lid, es_sysmac - type-0 is being set so old + * type-3 params need to be flushed + */ + memset(&zif->es_info.sysmac, 0, sizeof(struct ethaddr)); + zif->es_info.lid = 0; + + return rv; +} + void zebra_evpn_es_cleanup(void) { struct zebra_evpn_es *es; @@ -2425,10 +2509,10 @@ void zebra_evpn_if_es_print(struct vty *vty, struct zebra_if *zif) char buf[ETHER_ADDR_STRLEN]; char mh_buf[80]; bool vty_print = false; + char esi_buf[ESI_STR_LEN]; mh_buf[0] = '\0'; - snprintf(mh_buf + strlen(mh_buf), sizeof(mh_buf) - strlen(mh_buf), - " EVPN-MH:"); + strlcat(mh_buf, " EVPN-MH:", sizeof(mh_buf)); if (zif->es_info.lid || !is_zero_mac(&zif->es_info.sysmac)) { vty_print = true; snprintf( @@ -2436,17 +2520,21 @@ void zebra_evpn_if_es_print(struct vty *vty, struct zebra_if *zif) sizeof(mh_buf) - strlen(mh_buf), " ES id %u ES sysmac %s", zif->es_info.lid, prefix_mac2str(&zif->es_info.sysmac, buf, sizeof(buf))); + } else if (memcmp(&zif->es_info.esi, zero_esi, sizeof(*zero_esi))) { + vty_print = true; + snprintf(mh_buf + strnlen(mh_buf, sizeof(mh_buf)), + sizeof(mh_buf) - strnlen(mh_buf, sizeof(mh_buf)), + " ES id %s", + esi_to_str(&zif->es_info.esi, esi_buf, + sizeof(esi_buf))); } if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK) { vty_print = true; if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP) - snprintf(mh_buf + strlen(mh_buf), - sizeof(mh_buf) - strlen(mh_buf), " uplink-up"); + strlcat(mh_buf, " uplink (up)", sizeof(mh_buf)); else - snprintf(mh_buf + strlen(mh_buf), - sizeof(mh_buf) - strlen(mh_buf), - " uplink-down"); + strlcat(mh_buf, " uplink (down)", sizeof(mh_buf)); } if (vty_print) @@ -2659,6 +2747,7 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty, char alg_buf[EVPN_DF_ALG_STR_LEN]; struct zebra_evpn_es_vtep *es_vtep; struct listnode *node; + char thread_buf[THREAD_TIMER_STRLEN]; if (json) { json_object *json_vteps; @@ -2695,6 +2784,12 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty, listcount(es->es_evi_list)); json_object_int_add(json, "macCount", listcount(es->mac_list)); 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); if (listcount(es->es_vtep_list)) { json_vteps = json_object_new_array(); @@ -2729,9 +2824,16 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty, "yes" : "no"); 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, " DF: status: %s preference: %u\n", - (es->flags & ZEBRA_EVPNES_NON_DF) ? "non-df" : "df", - es->df_pref); + if (es->flags & ZEBRA_EVPNES_LOCAL) + vty_out(vty, " DF status: %s \n", + (es->flags & ZEBRA_EVPNES_NON_DF) ? "non-df" + : "df"); + if (es->df_delay_timer) + 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, " VTEPs:\n"); for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) { @@ -2833,14 +2935,25 @@ int zebra_evpn_mh_if_write(struct vty *vty, struct interface *ifp) { struct zebra_if *zif = ifp->info; char buf[ETHER_ADDR_STRLEN]; + bool type_3_esi = false; + char esi_buf[ESI_STR_LEN]; - if (zif->es_info.lid) + if (zif->es_info.lid) { vty_out(vty, " evpn mh es-id %u\n", zif->es_info.lid); + type_3_esi = true; + } - if (!is_zero_mac(&zif->es_info.sysmac)) + if (!is_zero_mac(&zif->es_info.sysmac)) { vty_out(vty, " evpn mh es-sys-mac %s\n", prefix_mac2str(&zif->es_info.sysmac, buf, sizeof(buf))); + type_3_esi = true; + } + + if (!type_3_esi + && memcmp(&zif->es_info.esi, zero_esi, sizeof(*zero_esi))) + vty_out(vty, " evpn mh es-id %s\n", + esi_to_str(&zif->es_info.esi, esi_buf, sizeof(esi_buf))); if (zif->es_info.df_pref) vty_out(vty, " evpn mh es-df-pref %u\n", zif->es_info.df_pref); @@ -2929,22 +3042,28 @@ DEFPY(zebra_evpn_es_sys_mac, /* CLI for setting up local-ID part of ESI on an access port */ DEFPY(zebra_evpn_es_id, zebra_evpn_es_id_cmd, - "[no$no] evpn mh es-id [(1-16777215)$es_lid]", + "[no$no] evpn mh es-id [(1-16777215)$es_lid | NAME$esi_str]", NO_STR "EVPN\n" EVPN_MH_VTY_STR - "Ethernet segment local identifier\n" - "ID\n" + "Ethernet segment identifier\n" + "local discriminator\n" + "10-byte ID - 00:AA:BB:CC:DD:EE:FF:GG:HH:II\n" ) { VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif; - int ret; + int ret = 0; + esi_t esi; zif = ifp->info; if (no) { - ret = zebra_evpn_es_lid_update(zif, 0); + if (zif->es_info.lid) + ret = zebra_evpn_es_lid_update(zif, 0); + else if (memcmp(&zif->es_info.esi, zero_esi, sizeof(*zero_esi))) + ret = zebra_evpn_es_type0_esi_update(zif, zero_esi); + if (ret == -1) { vty_out(vty, "%%Failed to clear ES local id\n"); return CMD_WARNING; @@ -2956,14 +3075,23 @@ DEFPY(zebra_evpn_es_id, return CMD_WARNING; } - if (!es_lid) { - vty_out(vty, "%%Specify local ES ID\n"); - return CMD_WARNING; + if (esi_str) { + if (!str_to_esi(esi_str, &esi)) { + vty_out(vty, "%% Malformed ESI\n"); + return CMD_WARNING; + } + ret = zebra_evpn_es_type0_esi_update(zif, &esi); + } else { + if (!es_lid) { + vty_out(vty, "%%Specify local ES ID\n"); + return CMD_WARNING; + } + ret = zebra_evpn_es_lid_update(zif, es_lid); } - ret = zebra_evpn_es_lid_update(zif, es_lid); + if (ret == -1) { vty_out(vty, - "%%ESI already exists on a different interface\n"); + "%%ESI already exists on a different interface\n"); return CMD_WARNING; } } @@ -3029,7 +3157,7 @@ void zebra_evpn_mh_print(struct vty *vty) vty_out(vty, " uplink-cfg-cnt: %u, uplink-active-cnt: %u\n", zmh_info->uplink_cfg_cnt, zmh_info->uplink_oper_up_cnt); if (zmh_info->protodown_rc) - vty_out(vty, " protodown: %s\n", + vty_out(vty, " protodown reasons: %s\n", zebra_protodown_rc_str(zmh_info->protodown_rc, pd_buf, sizeof(pd_buf))); } @@ -3174,16 +3302,14 @@ void zebra_evpn_mh_update_protodown_bond_mbr(struct zebra_if *zif, bool clear, protodown_rc = bond_zif->protodown_rc; } - if (zif->protodown_rc == protodown_rc) - return; - old_protodown = !!(zif->flags & ZIF_FLAG_PROTODOWN); old_protodown_rc = zif->protodown_rc; zif->protodown_rc &= ~ZEBRA_PROTODOWN_EVPN_ALL; zif->protodown_rc |= (protodown_rc & ZEBRA_PROTODOWN_EVPN_ALL); new_protodown = !!zif->protodown_rc; - if (IS_ZEBRA_DEBUG_EVPN_MH_ES) + if (IS_ZEBRA_DEBUG_EVPN_MH_ES + && (zif->protodown_rc != old_protodown_rc)) zlog_debug( "%s bond mbr %s protodown_rc changed; old 0x%x new 0x%x", caller, zif->ifp->name, old_protodown_rc, @@ -3220,14 +3346,20 @@ static void zebra_evpn_mh_update_protodown_bond(struct zebra_if *bond_zif) } /* The global EVPN MH protodown rc is applied to all local ESs */ -static void zebra_evpn_mh_update_protodown_es(struct zebra_evpn_es *es) +static void zebra_evpn_mh_update_protodown_es(struct zebra_evpn_es *es, + bool resync_dplane) { struct zebra_if *zif; enum protodown_reasons old_protodown_rc; zif = es->zif; - if ((zif->protodown_rc & ZEBRA_PROTODOWN_EVPN_ALL) - == (zmh_info->protodown_rc & ZEBRA_PROTODOWN_EVPN_ALL)) + /* if the reason code is the same bail unless it is a new + * ES bond in that case we would need to ensure that the + * dplane is really in sync with zebra + */ + if (!resync_dplane + && (zif->protodown_rc & ZEBRA_PROTODOWN_EVPN_ALL) + == (zmh_info->protodown_rc & ZEBRA_PROTODOWN_EVPN_ALL)) return; old_protodown_rc = zif->protodown_rc; @@ -3235,7 +3367,8 @@ static void zebra_evpn_mh_update_protodown_es(struct zebra_evpn_es *es) zif->protodown_rc |= (zmh_info->protodown_rc & ZEBRA_PROTODOWN_EVPN_ALL); - if (IS_ZEBRA_DEBUG_EVPN_MH_ES) + if (IS_ZEBRA_DEBUG_EVPN_MH_ES + && (old_protodown_rc != zif->protodown_rc)) zlog_debug( "es %s ifp %s protodown_rc changed; old 0x%x new 0x%x", es->esi_str, zif->ifp->name, old_protodown_rc, @@ -3273,7 +3406,7 @@ static void zebra_evpn_mh_update_protodown_es_all(void) struct zebra_evpn_es *es; for (ALL_LIST_ELEMENTS_RO(zmh_info->local_es_list, node, es)) - zebra_evpn_mh_update_protodown_es(es); + zebra_evpn_mh_update_protodown_es(es, false /*resync_dplane*/); } static void zebra_evpn_mh_update_protodown(enum protodown_reasons protodown_rc, @@ -3381,6 +3514,13 @@ void zebra_evpn_mh_uplink_oper_update(struct zebra_if *zif) if (old_protodown == new_protodown) return; + /* if protodown_rc XXX_UPLINK_DOWN is about to be cleared + * fire up the start-up delay timer to allow the EVPN network + * to converge (Type-2 routes need to be advertised and processed) + */ + if (!new_protodown && (zmh_info->uplink_oper_up_cnt == 1)) + zebra_evpn_mh_startup_delay_timer_start("uplink-up"); + zebra_evpn_mh_update_protodown(ZEBRA_PROTODOWN_EVPN_UPLINK_DOWN, new_protodown); } @@ -3396,26 +3536,19 @@ static int zebra_evpn_mh_startup_delay_exp_cb(struct thread *t) return 0; } -static void zebra_evpn_mh_startup_delay_timer_start(bool init) +static void zebra_evpn_mh_startup_delay_timer_start(const char *rc) { - /* 1. This timer can be started during init. - * 2. It can also be restarted if it is alreay running and the - * admin wants to increase or decrease its value - */ - if (!init && !zmh_info->startup_delay_timer) - return; - if (zmh_info->startup_delay_timer) { if (IS_ZEBRA_DEBUG_EVPN_MH_ES) zlog_debug("startup-delay timer cancelled"); - thread_cancel(&zmh_info->startup_delay_timer); - zmh_info->startup_delay_timer = NULL; + THREAD_OFF(zmh_info->startup_delay_timer); } if (zmh_info->startup_delay_time) { if (IS_ZEBRA_DEBUG_EVPN_MH_ES) - zlog_debug("startup-delay timer started for %d sec", - zmh_info->startup_delay_time); + zlog_debug( + "startup-delay timer started for %d sec on %s", + zmh_info->startup_delay_time, rc); thread_add_timer(zrouter.master, zebra_evpn_mh_startup_delay_exp_cb, NULL, zmh_info->startup_delay_time, @@ -3476,7 +3609,12 @@ int zebra_evpn_mh_startup_delay_update(struct vty *vty, uint32_t duration, duration = ZEBRA_EVPN_MH_STARTUP_DELAY_DEF; zmh_info->startup_delay_time = duration; - zebra_evpn_mh_startup_delay_timer_start(false /* init */); + + /* if startup_delay_timer is running allow it to be adjusted + * up or down + */ + if (zmh_info->startup_delay_timer) + zebra_evpn_mh_startup_delay_timer_start("config"); return 0; } @@ -3526,7 +3664,7 @@ void zebra_evpn_mh_init(void) zebra_evpn_acc_vl_cmp, "access VLAN hash table"); zmh_info->startup_delay_time = ZEBRA_EVPN_MH_STARTUP_DELAY_DEF; - zebra_evpn_mh_startup_delay_timer_start(true /*init*/); + zebra_evpn_mh_startup_delay_timer_start("init"); } void zebra_evpn_mh_terminate(void) |
