diff options
| -rw-r--r-- | bgpd/bgp_evpn_vty.c | 4 | ||||
| -rw-r--r-- | doc/developer/cli.rst | 10 | ||||
| -rw-r--r-- | doc/developer/workflow.rst | 11 | ||||
| -rw-r--r-- | doc/user/basic.rst | 5 | ||||
| -rw-r--r-- | doc/user/zebra.rst | 5 | ||||
| -rw-r--r-- | lib/thread.c | 58 | ||||
| -rw-r--r-- | pimd/pim_igmp.c | 11 | ||||
| -rw-r--r-- | pimd/pim_nht.c | 3 | ||||
| -rw-r--r-- | pimd/pim_rpf.c | 38 | ||||
| -rw-r--r-- | snapcraft/snapcraft.yaml.in | 1 | ||||
| -rw-r--r-- | tools/etc/frr/support_bundle_commands.conf | 1 | ||||
| -rw-r--r-- | vtysh/vtysh.c | 21 | ||||
| -rw-r--r-- | zebra/interface.c | 26 | ||||
| -rw-r--r-- | zebra/interface.h | 1 | ||||
| -rw-r--r-- | zebra/kernel_socket.c | 19 | ||||
| -rw-r--r-- | zebra/zebra_nhg.c | 2 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 6 |
17 files changed, 171 insertions, 51 deletions
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 4c7d9845e9..7ddf159844 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -3515,8 +3515,8 @@ DEFUN (bgp_evpn_advertise_all_vni, bgp_evpn = bgp_get_evpn(); if (bgp_evpn && bgp_evpn != bgp) { - vty_out(vty, "%% Please unconfigure EVPN in VRF %s\n", - bgp_evpn->name); + vty_out(vty, "%% Please unconfigure EVPN in %s\n", + bgp_evpn->name_pretty); return CMD_WARNING_CONFIG_FAILED; } diff --git a/doc/developer/cli.rst b/doc/developer/cli.rst index 9254eb4739..ff6c4f6e16 100644 --- a/doc/developer/cli.rst +++ b/doc/developer/cli.rst @@ -48,6 +48,16 @@ a node and returns the parent of the node. This interface causes all manner of insidious problems, even for experienced developers, and needs to be fixed at some point in the future. +Deprecation of old style of commands +------------------------------------ + +There are currently 2 styles of defining commands within a FRR source file. +``DEFUN`` and ``DEFPY``. ``DEFPY`` should be used for all new commands that +a developer is writing. This is because it allows for much better handling +of command line arguments as well as ensuring that input is correct. ``DEFUN`` +is listed here for historical reasons as well as for ensuring that existing +code can be understood by new developers. + Defining Commands ----------------- All definitions for the CLI system are exposed in ``lib/command.h``. In this diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst index 45bee17b71..af8756a909 100644 --- a/doc/developer/workflow.rst +++ b/doc/developer/workflow.rst @@ -346,6 +346,13 @@ Pre-submission Checklist the new feature within our existing CI infrastructure. Also the addition of automated testing to cover any pull request is encouraged. +- All new code must use the current latest version of acceptable code. + + - If a daemon is converted to YANG, then new code must use YANG. + - DEFPY's must be used for new cli + - Typesafe lists must be used + - printf formatting changes must be used + .. _signing-off: Signing Off @@ -1250,8 +1257,8 @@ CLI changes ----------- CLI's are a complicated ugly beast. Additions or changes to the CLI should use -a DEFUN to encapsulate one setting as much as is possible. Additionally as new -DEFUN's are added to the system, documentation should be provided for the new +a DEFPY to encapsulate one setting as much as is possible. Additionally as new +DEFPY's are added to the system, documentation should be provided for the new commands. Backwards Compatibility diff --git a/doc/user/basic.rst b/doc/user/basic.rst index 21432039c1..4c196cfcfe 100644 --- a/doc/user/basic.rst +++ b/doc/user/basic.rst @@ -673,6 +673,11 @@ Terminal Mode Commands we are setting each individual fd for the poll command at that point in time. +.. clicmd:: show thread timers + + This command displays FRR's timer data for timers that will pop in + the future. + .. _common-invocation-options: Common Invocation Options diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index 058987acf1..15c6088b7a 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -29,6 +29,9 @@ Besides the common invocation options (:ref:`common-invocation-options`), the Zebra, when started, will read in routes. Those routes that Zebra identifies that it was the originator of will be swept in TIME seconds. If no time is specified then we will sweep those routes immediately. + Under the *BSD's, there is no way to properly store the originating + route and the route types in this case will show up as a static route + with an admin distance of 255. .. option:: -r, --retain @@ -81,7 +84,7 @@ Besides the common invocation options (:ref:`common-invocation-options`), the .. option:: -s <SIZE>, --nl-bufsize <SIZE> Allow zebra to modify the default receive buffer size to SIZE - in bytes. Under *BSD only the -s option is available. + in bytes. Under \*BSD only the -s option is available. .. _interface-commands: diff --git a/lib/thread.c b/lib/thread.c index bc3bfe89d4..90074b3d89 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -498,6 +498,41 @@ DEFUN (clear_thread_cpu, return CMD_SUCCESS; } +static void show_thread_timers_helper(struct vty *vty, struct thread_master *m) +{ + const char *name = m->name ? m->name : "main"; + char underline[strlen(name) + 1]; + struct thread *thread; + + memset(underline, '-', sizeof(underline)); + underline[sizeof(underline) - 1] = '\0'; + + vty_out(vty, "\nShowing timers for %s\n", name); + vty_out(vty, "-------------------%s\n", underline); + + frr_each (thread_timer_list, &m->timer, thread) { + vty_out(vty, " %-50s%pTH\n", thread->hist->funcname, thread); + } +} + +DEFPY_NOSH (show_thread_timers, + show_thread_timers_cmd, + "show thread timers", + SHOW_STR + "Thread information\n" + "Show all timers and how long they have in the system\n") +{ + struct listnode *node; + struct thread_master *m; + + frr_with_mutex (&masters_mtx) { + for (ALL_LIST_ELEMENTS_RO(masters, node, m)) + show_thread_timers_helper(vty, m); + } + + return CMD_SUCCESS; +} + void thread_cmd_init(void) { install_element(VIEW_NODE, &show_thread_cpu_cmd); @@ -509,6 +544,8 @@ void thread_cmd_init(void) install_element(CONFIG_NODE, &no_service_cputime_warning_cmd); install_element(CONFIG_NODE, &service_walltime_warning_cmd); install_element(CONFIG_NODE, &no_service_walltime_warning_cmd); + + install_element(VIEW_NODE, &show_thread_timers_cmd); } /* CLI end ------------------------------------------------------------------ */ @@ -1847,6 +1884,27 @@ unsigned long thread_consumed_time(RUSAGE_T *now, RUSAGE_T *start, unsigned long *cputime) { #ifdef HAVE_CLOCK_THREAD_CPUTIME_ID + +#ifdef __FreeBSD__ + /* + * FreeBSD appears to have an issue when calling clock_gettime + * with CLOCK_THREAD_CPUTIME_ID really close to each other + * occassionally the now time will be before the start time. + * This is not good and FRR is ending up with CPU HOG's + * when the subtraction wraps to very large numbers + * + * What we are going to do here is cheat a little bit + * and notice that this is a problem and just correct + * it so that it is impossible to happen + */ + if (start->cpu.tv_sec == now->cpu.tv_sec && + start->cpu.tv_nsec > now->cpu.tv_nsec) + now->cpu.tv_nsec = start->cpu.tv_nsec + 1; + else if (start->cpu.tv_sec > now->cpu.tv_sec) { + now->cpu.tv_sec = start->cpu.tv_sec; + now->cpu.tv_nsec = start->cpu.tv_nsec + 1; + } +#endif *cputime = (now->cpu.tv_sec - start->cpu.tv_sec) * TIMER_SECOND_MICRO + (now->cpu.tv_nsec - start->cpu.tv_nsec) / 1000; #else diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 34268ecf90..5cdefd2828 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -526,17 +526,6 @@ bool pim_igmp_verify_header(struct ip *ip_hdr, size_t len, size_t *hlen) } } - if ((msg_type == PIM_IGMP_V3_MEMBERSHIP_REPORT) - || ((msg_type == PIM_IGMP_MEMBERSHIP_QUERY) - && (igmp_msg_len >= IGMP_V3_SOURCES_OFFSET))) { - /* All IGMPv3 messages must be received with TOS set to 0xC0*/ - if (ip_hdr->ip_tos != IPTOS_PREC_INTERNETCONTROL) { - zlog_warn("Received IGMP Packet with invalid TOS %u", - ip_hdr->ip_tos); - return false; - } - } - return true; } diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index 78f074510b..ce5298e5b0 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -1030,8 +1030,7 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim, nexthop_tab[i].protocol_distance; nexthop->mrib_route_metric = nexthop_tab[i].route_metric; - memcpy(&(nexthop->last_lookup), &(src_addr), - sizeof(pim_addr)); + nexthop->last_lookup = src_addr; nexthop->last_lookup_time = pim_time_monotonic_usec(); nexthop->nbr = nbr; found = 1; diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index d971cef24b..c62a06f85c 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -169,11 +169,13 @@ bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop, static int nexthop_mismatch(const struct pim_nexthop *nh1, const struct pim_nexthop *nh2) { - return (nh1->interface != nh2->interface) - || (nh1->mrib_nexthop_addr.u.prefix4.s_addr - != nh2->mrib_nexthop_addr.u.prefix4.s_addr) - || (nh1->mrib_metric_preference != nh2->mrib_metric_preference) - || (nh1->mrib_route_metric != nh2->mrib_route_metric); + pim_addr nh_addr1 = pim_addr_from_prefix(&nh1->mrib_nexthop_addr); + pim_addr nh_addr2 = pim_addr_from_prefix(&nh2->mrib_nexthop_addr); + + return (nh1->interface != nh2->interface) || + (pim_addr_cmp(nh_addr1, nh_addr2)) || + (nh1->mrib_metric_preference != nh2->mrib_metric_preference) || + (nh1->mrib_route_metric != nh2->mrib_route_metric); } static void pim_rpf_cost_change(struct pim_instance *pim, @@ -213,6 +215,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim, bool neigh_needed = true; uint32_t saved_mrib_route_metric; pim_addr rpf_addr; + pim_addr saved_rpf_addr; if (PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags)) return PIM_RPF_OK; @@ -297,9 +300,11 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim, } /* detect change in RPF'(S,G) */ - if (saved.rpf_addr.u.prefix4.s_addr != rpf->rpf_addr.u.prefix4.s_addr - || saved.source_nexthop - .interface != rpf->source_nexthop.interface) { + + saved_rpf_addr = pim_addr_from_prefix(&saved.rpf_addr); + + if (pim_addr_cmp(saved_rpf_addr, rpf_addr) || + saved.source_nexthop.interface != rpf->source_nexthop.interface) { pim_rpf_cost_change(pim, up, saved_mrib_route_metric); return PIM_RPF_CHANGED; } @@ -327,13 +332,13 @@ void pim_upstream_rpf_clear(struct pim_instance *pim, if (up->rpf.source_nexthop.interface) { pim_upstream_switch(pim, up, PIM_UPSTREAM_NOTJOINED); up->rpf.source_nexthop.interface = NULL; - up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr = - PIM_NET_INADDR_ANY; + pim_addr_to_prefix(&up->rpf.source_nexthop.mrib_nexthop_addr, + PIMADDR_ANY); up->rpf.source_nexthop.mrib_metric_preference = router->infinite_assert_metric.metric_preference; up->rpf.source_nexthop.mrib_route_metric = router->infinite_assert_metric.route_metric; - up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; + pim_addr_to_prefix(&up->rpf.rpf_addr, PIMADDR_ANY); pim_upstream_mroute_iif_update(up->channel_oil, __func__); } } @@ -403,12 +408,12 @@ int pim_rpf_addr_is_inaddr_none(struct pim_rpf *rpf) int pim_rpf_addr_is_inaddr_any(struct pim_rpf *rpf) { + pim_addr rpf_addr = pim_addr_from_prefix(&rpf->rpf_addr); + switch (rpf->rpf_addr.family) { case AF_INET: - return rpf->rpf_addr.u.prefix4.s_addr == INADDR_ANY; case AF_INET6: - zlog_warn("%s: v6 Unimplmented", __func__); - return 1; + return pim_addr_is_any(rpf_addr); default: return 0; } @@ -426,7 +431,12 @@ unsigned int pim_rpf_hash_key(const void *arg) { const struct pim_nexthop_cache *r = arg; +#if PIM_IPV == 4 || !defined(PIM_V6_TEMP_BREAK) return jhash_1word(r->rpf.rpf_addr.u.prefix4.s_addr, 0); +#else + return jhash2(r->rpf.rpf_addr.u.prefix6.s6_addr32, + array_size(r->rpf.rpf_addr.u.prefix6.s6_addr32), 0); +#endif } bool pim_rpf_equal(const void *arg1, const void *arg2) diff --git a/snapcraft/snapcraft.yaml.in b/snapcraft/snapcraft.yaml.in index 51252ede0c..01033d0413 100644 --- a/snapcraft/snapcraft.yaml.in +++ b/snapcraft/snapcraft.yaml.in @@ -306,6 +306,7 @@ parts: - make - gawk - libreadline-dev + - libelf-dev - texinfo - libncurses5-dev - texlive-latex-base diff --git a/tools/etc/frr/support_bundle_commands.conf b/tools/etc/frr/support_bundle_commands.conf index e223eb2743..46e0625d8c 100644 --- a/tools/etc/frr/support_bundle_commands.conf +++ b/tools/etc/frr/support_bundle_commands.conf @@ -78,6 +78,7 @@ show debugging hashtable show running-config show thread cpu show thread poll +show thread timers show daemons show version CMD_LIST_END diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index e209cea690..f8c6a1fc1d 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -218,9 +218,9 @@ static ssize_t vtysh_client_receive(struct vtysh_client *vclient, char *buf, do { ret = recvmsg(vclient->fd, &mh, 0); - if (ret < 0 && (errno == EINTR || errno == EAGAIN)) - continue; - } while (false); + if (ret >= 0 || (errno != EINTR && errno != EAGAIN)) + break; + } while (true); if (cmh->cmsg_len == CMSG_LEN(sizeof(int))) { int fd; @@ -2774,6 +2774,16 @@ static int show_one_daemon(struct vty *vty, struct cmd_token **argv, int argc, return ret; } +DEFUN (vtysh_show_thread_timer, + vtysh_show_thread_timer_cmd, + "show thread timers", + SHOW_STR + "Thread information\n" + "Show all timers and how long they have in the system\n") +{ + return show_per_daemon(vty, argv, argc, "Thread timers for %s:\n"); +} + DEFUN (vtysh_show_poll, vtysh_show_poll_cmd, "show thread poll", @@ -3582,7 +3592,7 @@ static void vtysh_log_print(struct vtysh_client *vclient, struct tm tm; char ts_buf[32]; - if (hdr->prio > array_size(visual_prios)) + if (hdr->prio >= array_size(visual_prios)) vis = &visual_prios[LOG_CRIT]; else vis = &visual_prios[hdr->prio]; @@ -3647,6 +3657,8 @@ static void vtysh_log_read(struct thread *thread) if (ret <= 0) { struct timespec ts; + buf.text[0] = '\0'; /* coverity */ + if (ret != 0) snprintfrr(buf.text, sizeof(buf.text), "log monitor connection error: %m"); @@ -4858,6 +4870,7 @@ void vtysh_init_vty(void) install_element(VIEW_NODE, &vtysh_show_work_queues_daemon_cmd); install_element(VIEW_NODE, &vtysh_show_thread_cmd); install_element(VIEW_NODE, &vtysh_show_poll_cmd); + install_element(VIEW_NODE, &vtysh_show_thread_timer_cmd); /* Logging */ install_element(VIEW_NODE, &vtysh_show_logging_cmd); diff --git a/zebra/interface.c b/zebra/interface.c index c30f43456c..fbd2aac005 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -72,8 +72,6 @@ static void if_zebra_speed_update(struct thread *thread) bool changed = false; int error = 0; - zif->speed_update = NULL; - new_speed = kernel_get_speed(ifp, &error); /* error may indicate vrf not available or @@ -92,8 +90,27 @@ static void if_zebra_speed_update(struct thread *thread) } if (changed || new_speed == UINT32_MAX) { - thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 5, - &zif->speed_update); +#define SPEED_UPDATE_SLEEP_TIME 5 +#define SPEED_UPDATE_COUNT_MAX (4 * 60 / SPEED_UPDATE_SLEEP_TIME) + /* + * Some interfaces never actually have an associated speed + * with them ( I am looking at you bridges ). + * So instead of iterating forever, let's give the + * system 4 minutes to try to figure out the speed + * if after that it it's probably never going to become + * useful. + * Since I don't know all the wonderful types of interfaces + * that may come into existence in the future I am going + * to not update the system to keep track of that. This + * is far simpler to just stop trying after 4 minutes + */ + if (new_speed == UINT32_MAX && + zif->speed_update_count == SPEED_UPDATE_COUNT_MAX) + return; + + zif->speed_update_count++; + thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, + SPEED_UPDATE_SLEEP_TIME, &zif->speed_update); thread_ignore_late_timer(zif->speed_update); } } @@ -196,6 +213,7 @@ static int if_zebra_new_hook(struct interface *ifp) * of seconds and ask again. Hopefully it's all settled * down upon startup. */ + zebra_if->speed_update_count = 0; thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 15, &zebra_if->speed_update); thread_ignore_late_timer(zebra_if->speed_update); diff --git a/zebra/interface.h b/zebra/interface.h index 85617961af..c19e494860 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -412,6 +412,7 @@ struct zebra_if { ifindex_t link_ifindex; struct interface *link; + uint8_t speed_update_count; struct thread *speed_update; /* diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index d812094848..ce1f17111b 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -1011,6 +1011,8 @@ void rtm_read(struct rt_msghdr *rtm) ifindex_t ifindex = 0; afi_t afi; char fbuf[64]; + int32_t proto = ZEBRA_ROUTE_KERNEL; + uint8_t distance = 0; zebra_flags = 0; @@ -1042,8 +1044,11 @@ void rtm_read(struct rt_msghdr *rtm) if (!(flags & RTF_GATEWAY)) return; - if (flags & RTF_PROTO1) + if (flags & RTF_PROTO1) { SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE); + proto = ZEBRA_ROUTE_STATIC; + distance = 255; + } memset(&nh, 0, sizeof(nh)); @@ -1111,13 +1116,13 @@ void rtm_read(struct rt_msghdr *rtm) 0, true); if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) - rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, - zebra_flags, &p, NULL, &nh, 0, RT_TABLE_MAIN, - 0, 0, 0, 0, false); + rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, proto, 0, zebra_flags, + &p, NULL, &nh, 0, RT_TABLE_MAIN, 0, 0, distance, 0, + false); else - rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, NULL, &nh, 0, RT_TABLE_MAIN, 0, - 0, true); + rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, proto, 0, + zebra_flags, &p, NULL, &nh, 0, RT_TABLE_MAIN, 0, + distance, true); } /* Interface function for the kernel routing table updates. Support diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 858309f3e7..e1d28e1534 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -2475,7 +2475,7 @@ skip_check: memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr)); - zvrf = zebra_vrf_lookup_by_id(nexthop->vrf_id); + zvrf = zebra_vrf_lookup_by_id(re->vrf_id); if (!zvrf) { if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug(" %s: zvrf is NULL", __func__); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index af159da3cc..e376d4b2af 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -116,6 +116,7 @@ static const struct { [ZEBRA_ROUTE_OPENFABRIC] = {ZEBRA_ROUTE_OPENFABRIC, 115, 5}, [ZEBRA_ROUTE_VRRP] = {ZEBRA_ROUTE_VRRP, 255, 7}, [ZEBRA_ROUTE_SRTE] = {ZEBRA_ROUTE_SRTE, 255, 7}, + [ZEBRA_ROUTE_ALL] = {ZEBRA_ROUTE_ALL, 255, 7}, /* Any new route type added to zebra, should be mirrored here */ /* no entry/default: 150 */ @@ -4386,9 +4387,8 @@ static void check_route_info(void) * ZEBRA_ROUTE_ALL is also ignored. */ for (int i = 0; i < len; i++) { - if (i == ZEBRA_ROUTE_SYSTEM || i == ZEBRA_ROUTE_ALL) - continue; - assert(route_info[i].key); + assert(route_info[i].key >= ZEBRA_ROUTE_SYSTEM && + route_info[i].key < ZEBRA_ROUTE_MAX); assert(route_info[i].meta_q_map < MQ_SIZE); } } |
