Merge pull request #11781 from donaldsharp/ospf_packet_helper

Ospf packet helper
This commit is contained in:
Donatas Abraitis 2022-08-15 20:43:49 +03:00 committed by GitHub
commit 17667be0a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 274 additions and 228 deletions

View File

@ -2086,7 +2086,6 @@ static void ospf6_write(struct thread *thread)
{
struct ospf6 *ospf6 = THREAD_ARG(thread);
struct ospf6_interface *oi;
struct ospf6_interface *last_serviced_oi = NULL;
struct ospf6_header *oh;
struct ospf6_packet *op;
struct listnode *node;
@ -2106,9 +2105,7 @@ static void ospf6_write(struct thread *thread)
assert(node);
oi = listgetdata(node);
while ((pkt_count < ospf6->write_oi_count) && oi
&& (last_serviced_oi != oi)) {
while ((pkt_count < ospf6->write_oi_count) && oi) {
op = ospf6_fifo_head(oi->obuf);
assert(op);
assert(op->length >= OSPF6_HEADER_SIZE);
@ -2221,7 +2218,6 @@ static void ospf6_write(struct thread *thread)
list_delete_node(ospf6->oi_write_q, node);
if (ospf6_fifo_head(oi->obuf) == NULL) {
oi->on_write_q = 0;
last_serviced_oi = NULL;
oi = NULL;
} else {
listnode_add(ospf6->oi_write_q, oi);

View File

@ -638,13 +638,15 @@ int ospf_flood_through_interface(struct ospf_interface *oi,
if (oi->type == OSPF_IFTYPE_NBMA) {
struct ospf_neighbor *nbr;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
if ((nbr = rn->info) != NULL)
if (nbr != oi->nbr_self
&& nbr->state >= NSM_Exchange)
ospf_ls_upd_send_lsa(
nbr, lsa,
OSPF_SEND_PACKET_DIRECT);
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
nbr = rn->info;
if (!nbr)
continue;
if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange)
ospf_ls_upd_send_lsa(nbr, lsa,
OSPF_SEND_PACKET_DIRECT);
}
} else
ospf_ls_upd_send_lsa(oi->nbr_self, lsa,
OSPF_SEND_PACKET_INDIRECT);
@ -991,18 +993,20 @@ static void ospf_ls_retransmit_delete_nbr_if(struct ospf_interface *oi,
struct ospf_lsa *lsr;
if (ospf_if_is_enable(oi))
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
/* If LSA find in LS-retransmit list, then remove it. */
if ((nbr = rn->info) != NULL) {
lsr = ospf_ls_retransmit_lookup(nbr, lsa);
nbr = rn->info;
/* If LSA find in ls-retransmit list, remove it.
*/
if (lsr != NULL
&& lsr->data->ls_seqnum
== lsa->data->ls_seqnum)
ospf_ls_retransmit_delete(nbr, lsr);
}
if (!nbr)
continue;
lsr = ospf_ls_retransmit_lookup(nbr, lsa);
/* If LSA find in ls-retransmit list, remove it. */
if (lsr != NULL &&
lsr->data->ls_seqnum == lsa->data->ls_seqnum)
ospf_ls_retransmit_delete(nbr, lsr);
}
}
void ospf_ls_retransmit_delete_nbr_area(struct ospf_area *area,

View File

@ -66,15 +66,16 @@ int ospf_interface_neighbor_count(struct ospf_interface *oi)
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
nbr = rn->info;
if (nbr) {
/* Do not show myself. */
if (nbr == oi->nbr_self)
continue;
/* Down state is not shown. */
if (nbr->state == NSM_Down)
continue;
count++;
}
if (!nbr)
continue;
/* Do not show myself. */
if (nbr == oi->nbr_self)
continue;
/* Down state is not shown. */
if (nbr->state == NSM_Down)
continue;
count++;
}
return count;
@ -315,10 +316,11 @@ void ospf_if_cleanup(struct ospf_interface *oi)
}
/* send Neighbor event KillNbr to all associated neighbors. */
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
if ((nbr = rn->info) != NULL)
if (nbr != oi->nbr_self)
OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr);
}
/* Cleanup Link State Acknowlegdment list. */
for (ALL_LIST_ELEMENTS(oi->ls_ack, node, nnode, lsa))
@ -492,6 +494,20 @@ struct ospf_interface *ospf_if_lookup_recv_if(struct ospf *ospf,
return match;
}
void ospf_interface_fifo_flush(struct ospf_interface *oi)
{
struct ospf *ospf = oi->ospf;
ospf_fifo_flush(oi->obuf);
if (oi->on_write_q) {
listnode_delete(ospf->oi_write_q, oi);
if (list_isempty(ospf->oi_write_q))
THREAD_OFF(ospf->t_write);
oi->on_write_q = 0;
}
}
static void ospf_if_reset_stats(struct ospf_interface *oi)
{
oi->hello_in = oi->hello_out = 0;
@ -503,19 +519,10 @@ static void ospf_if_reset_stats(struct ospf_interface *oi)
void ospf_if_stream_unset(struct ospf_interface *oi)
{
struct ospf *ospf = oi->ospf;
/* flush the interface packet queue */
ospf_fifo_flush(oi->obuf);
ospf_interface_fifo_flush(oi);
/*reset protocol stats */
ospf_if_reset_stats(oi);
if (oi->on_write_q) {
listnode_delete(ospf->oi_write_q, oi);
if (list_isempty(ospf->oi_write_q))
THREAD_OFF(ospf->t_write);
oi->on_write_q = 0;
}
}

View File

@ -351,6 +351,8 @@ extern void ospf_if_interface(struct interface *ifp);
extern uint32_t ospf_if_count_area_params(struct interface *ifp);
extern void ospf_reset_hello_timer(struct interface *ifp, struct in_addr addr,
bool is_addr);
extern void ospf_interface_fifo_flush(struct ospf_interface *oi);
DECLARE_HOOK(ospf_vl_add, (struct ospf_vl_data * vd), (vd));
DECLARE_HOOK(ospf_vl_delete, (struct ospf_vl_data * vd), (vd));

View File

@ -382,6 +382,10 @@ static void nsm_clear_adj(struct ospf_neighbor *nbr)
static int nsm_kill_nbr(struct ospf_neighbor *nbr)
{
struct ospf_interface *oi = nbr->oi;
struct ospf_neighbor *on;
struct route_node *rn;
/* killing nbr_self is invalid */
if (nbr == nbr->oi->nbr_self) {
assert(nbr != nbr->oi->nbr_self);
@ -407,6 +411,35 @@ static int nsm_kill_nbr(struct ospf_neighbor *nbr)
ospf_get_name(nbr->oi->ospf));
}
/*
* Do we have any neighbors that are also operating
* on this interface?
*/
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
on = rn->info;
if (!on)
continue;
if (on == nbr || on == oi->nbr_self)
continue;
/*
* on is in some state where we might be
* sending packets on this interface
*/
if (on->state > NSM_Down) {
route_unlock_node(rn);
return 0;
}
}
/*
* If we get here we know that this interface
* has no neighbors in a state where we could
* be sending packets. Let's flush anything
* we got.
*/
ospf_interface_fifo_flush(oi);
return 0;
}

View File

@ -623,7 +623,6 @@ static void ospf_write(struct thread *thread)
{
struct ospf *ospf = THREAD_ARG(thread);
struct ospf_interface *oi;
struct ospf_interface *last_serviced_oi = NULL;
struct ospf_packet *op;
struct sockaddr_in sa_dst;
struct ip iph;
@ -664,13 +663,7 @@ static void ospf_write(struct thread *thread)
ipid = (time(NULL) & 0xffff);
#endif /* WANT_OSPF_WRITE_FRAGMENT */
while ((pkt_count < ospf->write_oi_count) && oi
&& (last_serviced_oi != oi)) {
/* If there is only packet in the queue, the oi is removed from
write-q, so fix up the last interface that was serviced */
if (last_serviced_oi == NULL) {
last_serviced_oi = oi;
}
while ((pkt_count < ospf->write_oi_count) && oi) {
pkt_count++;
#ifdef WANT_OSPF_WRITE_FRAGMENT
/* convenience - max OSPF data per packet */
@ -853,11 +846,9 @@ static void ospf_write(struct thread *thread)
list_delete_node(ospf->oi_write_q, node);
if (ospf_fifo_head(oi->obuf) == NULL) {
oi->on_write_q = 0;
last_serviced_oi = NULL;
oi = NULL;
} else {
} else
listnode_add(ospf->oi_write_q, oi);
}
/* Setup to service from the head of the queue again */
if (!list_isempty(ospf->oi_write_q)) {
@ -3358,49 +3349,44 @@ static int ospf_make_hello(struct ospf_interface *oi, struct stream *s)
stream_put_ipv4(s, BDR(oi).s_addr);
/* Add neighbor seen. */
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
if ((nbr = rn->info))
if (nbr->router_id.s_addr
!= INADDR_ANY) /* Ignore 0.0.0.0 node. */
if (nbr->state
!= NSM_Attempt) /* Ignore Down neighbor. */
if (nbr->state
!= NSM_Down) /* This is myself for
DR election. */
if (!IPV4_ADDR_SAME(
&nbr->router_id,
&oi->ospf->router_id)) {
/* Check neighbor is
* sane? */
if (nbr->d_router.s_addr
!= INADDR_ANY
&& IPV4_ADDR_SAME(
&nbr->d_router,
&oi->address
->u
.prefix4)
&& IPV4_ADDR_SAME(
&nbr->bd_router,
&oi->address
->u
.prefix4))
flag = 1;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
nbr = rn->info;
/* Hello packet overflows interface MTU. */
if (length + sizeof(uint32_t)
> ospf_packet_max(oi)) {
flog_err(
EC_OSPF_LARGE_HELLO,
"Oversized Hello packet! Larger than MTU. Not sending it out");
return 0;
}
if (!nbr)
continue;
stream_put_ipv4(
s,
nbr->router_id
.s_addr);
length += 4;
}
/* Ignore the 0.0.0.0 node */
if (nbr->router_id.s_addr == INADDR_ANY)
continue;
/* Ignore Down neighbor */
if (nbr->state == NSM_Attempt)
continue;
/* This is myself for DR election */
if (nbr->state == NSM_Down)
continue;
if (IPV4_ADDR_SAME(&nbr->router_id, &oi->ospf->router_id))
continue;
/* Check neighbor is sane? */
if (nbr->d_router.s_addr != INADDR_ANY &&
IPV4_ADDR_SAME(&nbr->d_router, &oi->address->u.prefix4) &&
IPV4_ADDR_SAME(&nbr->bd_router, &oi->address->u.prefix4))
flag = 1;
/* Hello packet overflows interface MTU.
*/
if (length + sizeof(uint32_t) > ospf_packet_max(oi)) {
flog_err(
EC_OSPF_LARGE_HELLO,
"Oversized Hello packet! Larger than MTU. Not sending it out");
return 0;
}
stream_put_ipv4(s, nbr->router_id.s_addr);
length += 4;
}
/* Let neighbor generate BackupSeen. */
if (flag == 1)
@ -3781,54 +3767,44 @@ void ospf_hello_send(struct ospf_interface *oi)
struct ospf_neighbor *nbr;
struct route_node *rn;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
if ((nbr = rn->info))
if (nbr != oi->nbr_self)
if (nbr->state != NSM_Down) {
/* RFC 2328 Section 9.5.1
If the router is not
eligible to become Designated
Router,
it must periodically send
Hello Packets to both the
Designated Router and the
Backup Designated Router (if
they
exist). */
if (PRIORITY(oi) == 0
&& IPV4_ADDR_CMP(
&DR(oi),
&nbr->address.u
.prefix4)
&& IPV4_ADDR_CMP(
&BDR(oi),
&nbr->address.u
.prefix4))
continue;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
nbr = rn->info;
if (!nbr)
continue;
/* If the router is eligible to
become Designated Router, it
must periodically send Hello
Packets to all neighbors that
are also eligible. In
addition, if the router is
itself the
Designated Router or Backup
Designated Router, it must
also
send periodic Hello Packets
to all other neighbors. */
if (nbr == oi->nbr_self)
continue;
if (nbr->priority == 0
&& oi->state == ISM_DROther)
continue;
/* if oi->state == Waiting, send
* hello to all neighbors */
ospf_hello_send_sub(
oi,
nbr->address.u.prefix4
.s_addr);
}
if (nbr->state == NSM_Down)
continue;
/*
* RFC 2328 Section 9.5.1
* If the router is not eligible to become Designated
* Router, it must periodically send Hello Packets to
* both the Designated Router and the Backup
* Designated Router (if they exist).
*/
if (PRIORITY(oi) == 0 &&
IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) &&
IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4))
continue;
/*
* If the router is eligible to become Designated
* Router, it must periodically send Hello Packets to
* all neighbors that are also eligible. In addition,
* if the router is itself the Designated Router or
* Backup Designated Router, it must also send periodic
* Hello Packets to all other neighbors.
*/
if (nbr->priority == 0 && oi->state == ISM_DROther)
continue;
/* if oi->state == Waiting, send
* hello to all neighbors */
ospf_hello_send_sub(oi, nbr->address.u.prefix4.s_addr);
}
} else {
/* Decide destination address. */
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
@ -4300,14 +4276,18 @@ void ospf_ls_ack_send_delayed(struct ospf_interface *oi)
struct ospf_neighbor *nbr;
struct route_node *rn;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
if ((nbr = rn->info) != NULL)
if (nbr != oi->nbr_self
&& nbr->state >= NSM_Exchange)
while (listcount(oi->ls_ack))
ospf_ls_ack_send_list(
oi, oi->ls_ack,
nbr->address.u.prefix4);
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
nbr = rn->info;
if (!nbr)
continue;
if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange)
while (listcount(oi->ls_ack))
ospf_ls_ack_send_list(
oi, oi->ls_ack,
nbr->address.u.prefix4);
}
return;
}
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)

View File

@ -756,13 +756,14 @@ static struct ospf_neighbor *get_neighbor_by_addr(struct ospf *top,
for (ALL_LIST_ELEMENTS_RO(top->oiflist, node, oi))
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
nbr = rn->info;
if (nbr)
if (IPV4_ADDR_SAME(&nbr->address.u.prefix4,
&addr)
|| IPV4_ADDR_SAME(&nbr->router_id, &addr)) {
route_unlock_node(rn);
return nbr;
}
if (!nbr)
continue;
if (IPV4_ADDR_SAME(&nbr->address.u.prefix4, &addr) ||
IPV4_ADDR_SAME(&nbr->router_id, &addr)) {
route_unlock_node(rn);
return nbr;
}
}
return NULL;
}

View File

@ -4008,13 +4008,15 @@ static void show_ip_ospf_interface_traffic_sub(struct vty *vty,
oi->ls_ack_in);
json_object_int_add(json_interface_sub, "lsAckOut",
oi->ls_ack_out);
json_object_int_add(json_interface_sub, "packetsQueued",
listcount(oi->obuf));
} else {
vty_out(vty,
"%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
"%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %12lu\n",
oi->ifp->name, oi->hello_in, oi->hello_out,
oi->db_desc_in, oi->db_desc_out, oi->ls_req_in,
oi->ls_req_out, oi->ls_upd_in, oi->ls_upd_out,
oi->ls_ack_in, oi->ls_ack_out);
oi->ls_ack_in, oi->ls_ack_out, listcount(oi->obuf));
}
}
@ -4030,14 +4032,14 @@ static int show_ip_ospf_interface_traffic_common(
if (!use_json && !display_once) {
vty_out(vty, "\n");
vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s\n", "Interface",
" HELLO", " DB-Desc", " LS-Req", " LS-Update",
" LS-Ack");
vty_out(vty, "%-10s%-18s%-18s%-17s%-17s%-17s\n", "",
vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n",
"Interface", " HELLO", " DB-Desc", " LS-Req",
" LS-Update", " LS-Ack", " Packets");
vty_out(vty, "%-10s%-18s%-18s%-17s%-17s%-17s%-17s\n", "",
" Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
" Rx/Tx");
" Rx/Tx", " Queued");
vty_out(vty,
"--------------------------------------------------------------------------------------------\n");
"-------------------------------------------------------------------------------------------------------------\n");
} else if (use_json) {
if (use_vrf)
json_vrf = json_object_new_object();
@ -4476,19 +4478,22 @@ static void show_ip_ospf_neighbor_sub(struct vty *vty,
struct ospf_neighbor *nbr, *prev_nbr = NULL;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
if ((nbr = rn->info)) {
/* Do not show myself. */
if (nbr == oi->nbr_self)
continue;
/* Down state is not shown. */
if (nbr->state == NSM_Down)
continue;
nbr = rn->info;
prev_nbr = nbr;
if (!nbr)
continue;
show_ip_ospf_neighbour_brief(vty, nbr, prev_nbr, json,
use_json);
}
/* Do not show myself. */
if (nbr == oi->nbr_self)
continue;
/* Down state is not shown. */
if (nbr->state == NSM_Down)
continue;
prev_nbr = nbr;
show_ip_ospf_neighbour_brief(vty, nbr, prev_nbr, json,
use_json);
}
}
@ -5402,14 +5407,17 @@ static int show_ip_ospf_neighbor_id_common(struct vty *vty, struct ospf *ospf,
ospf_show_vrf_name(ospf, vty, json, use_vrf);
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
if ((nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, router_id))) {
if (is_detail)
show_ip_ospf_neighbor_detail_sub(
vty, oi, nbr, NULL, json, use_json);
else
show_ip_ospf_neighbour_brief(vty, nbr, NULL,
json, use_json);
}
nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, router_id);
if (!nbr)
continue;
if (is_detail)
show_ip_ospf_neighbor_detail_sub(vty, oi, nbr, NULL,
json, use_json);
else
show_ip_ospf_neighbour_brief(vty, nbr, NULL, json,
use_json);
}
if (use_json)
@ -5498,16 +5506,19 @@ static int show_ip_ospf_neighbor_detail_common(struct vty *vty,
struct ospf_neighbor *nbr, *prev_nbr = NULL;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
if ((nbr = rn->info)) {
if (nbr != oi->nbr_self) {
if (nbr->state != NSM_Down) {
show_ip_ospf_neighbor_detail_sub(
vty, oi, nbr, prev_nbr,
json_nbr_sub, use_json);
}
nbr = rn->info;
if (!nbr)
continue;
if (nbr != oi->nbr_self) {
if (nbr->state != NSM_Down) {
show_ip_ospf_neighbor_detail_sub(
vty, oi, nbr, prev_nbr,
json_nbr_sub, use_json);
}
prev_nbr = nbr;
}
prev_nbr = nbr;
}
}
@ -5668,27 +5679,29 @@ static int show_ip_ospf_neighbor_detail_all_common(struct vty *vty,
struct ospf_nbr_nbma *nbr_nbma;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
if ((nbr = rn->info)) {
if (nbr != oi->nbr_self)
if (nbr->state != NSM_Down)
show_ip_ospf_neighbor_detail_sub(
vty, oi, rn->info,
prev_nbr,
json_vrf, use_json);
prev_nbr = nbr;
}
nbr = rn->info;
if (!nbr)
continue;
if (nbr != oi->nbr_self)
if (nbr->state != NSM_Down)
show_ip_ospf_neighbor_detail_sub(
vty, oi, rn->info, prev_nbr,
json_vrf, use_json);
prev_nbr = nbr;
}
if (oi->type == OSPF_IFTYPE_NBMA) {
struct listnode *nd;
if (oi->type != OSPF_IFTYPE_NBMA)
continue;
for (ALL_LIST_ELEMENTS_RO(oi->nbr_nbma, nd, nbr_nbma)) {
if (nbr_nbma->nbr == NULL
|| nbr_nbma->nbr->state == NSM_Down)
show_ip_ospf_nbr_nbma_detail_sub(
vty, oi, nbr_nbma, use_json,
json_vrf);
}
struct listnode *nd;
for (ALL_LIST_ELEMENTS_RO(oi->nbr_nbma, nd, nbr_nbma)) {
if (nbr_nbma->nbr == NULL ||
nbr_nbma->nbr->state == NSM_Down)
show_ip_ospf_nbr_nbma_detail_sub(
vty, oi, nbr_nbma, use_json, json_vrf);
}
}
@ -5853,19 +5866,25 @@ static int show_ip_ospf_neighbor_int_detail_common(struct vty *vty,
}
for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
if ((oi = rn->info)) {
for (nrn = route_top(oi->nbrs); nrn;
nrn = route_next(nrn)) {
if ((nbr = nrn->info)) {
if (nbr != oi->nbr_self) {
if (nbr->state != NSM_Down)
show_ip_ospf_neighbor_detail_sub(
vty, oi, nbr,
NULL,
json, use_json);
}
}
}
oi = rn->info;
if (!oi)
continue;
for (nrn = route_top(oi->nbrs); nrn; nrn = route_next(nrn)) {
nbr = nrn->info;
if (!nbr)
continue;
if (nbr == oi->nbr_self)
continue;
if (nbr->state == NSM_Down)
continue;
show_ip_ospf_neighbor_detail_sub(vty, oi, nbr, NULL,
json, use_json);
}
}
@ -8019,13 +8038,17 @@ static void ospf_nbr_timer_update(struct ospf_interface *oi)
struct route_node *rn;
struct ospf_neighbor *nbr;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
if ((nbr = rn->info)) {
nbr->v_inactivity = OSPF_IF_PARAM(oi, v_wait);
nbr->v_db_desc = OSPF_IF_PARAM(oi, retransmit_interval);
nbr->v_ls_req = OSPF_IF_PARAM(oi, retransmit_interval);
nbr->v_ls_upd = OSPF_IF_PARAM(oi, retransmit_interval);
}
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
nbr = rn->info;
if (!nbr)
continue;
nbr->v_inactivity = OSPF_IF_PARAM(oi, v_wait);
nbr->v_db_desc = OSPF_IF_PARAM(oi, retransmit_interval);
nbr->v_ls_req = OSPF_IF_PARAM(oi, retransmit_interval);
nbr->v_ls_upd = OSPF_IF_PARAM(oi, retransmit_interval);
}
}
static int ospf_vty_dead_interval_set(struct vty *vty, const char *interval_str,