diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/agentx.c | 7 | ||||
| -rw-r--r-- | lib/command.c | 32 | ||||
| -rw-r--r-- | lib/filter.c | 33 | ||||
| -rw-r--r-- | lib/frr_pthread.c | 5 | ||||
| -rw-r--r-- | lib/frr_zmq.c | 22 | ||||
| -rw-r--r-- | lib/hash.c | 14 | ||||
| -rw-r--r-- | lib/if.c | 7 | ||||
| -rw-r--r-- | lib/ldp_sync.c | 2 | ||||
| -rw-r--r-- | lib/libfrr_trace.c | 4 | ||||
| -rw-r--r-- | lib/libfrr_trace.h | 240 | ||||
| -rw-r--r-- | lib/linklist.c | 9 | ||||
| -rw-r--r-- | lib/memory.c | 5 | ||||
| -rw-r--r-- | lib/nexthop.c | 8 | ||||
| -rw-r--r-- | lib/nexthop_group.c | 20 | ||||
| -rw-r--r-- | lib/northbound.c | 58 | ||||
| -rw-r--r-- | lib/northbound.h | 23 | ||||
| -rw-r--r-- | lib/northbound_cli.c | 8 | ||||
| -rw-r--r-- | lib/northbound_confd.c | 12 | ||||
| -rw-r--r-- | lib/northbound_sysrepo.c | 12 | ||||
| -rw-r--r-- | lib/sockunion.c | 12 | ||||
| -rw-r--r-- | lib/spf_backoff.c | 9 | ||||
| -rw-r--r-- | lib/subdir.am | 8 | ||||
| -rw-r--r-- | lib/table.c | 7 | ||||
| -rw-r--r-- | lib/thread.c | 49 | ||||
| -rw-r--r-- | lib/thread.h | 19 | ||||
| -rw-r--r-- | lib/trace.h | 80 | ||||
| -rw-r--r-- | lib/workqueue.c | 4 | ||||
| -rw-r--r-- | lib/yang.c | 40 | ||||
| -rw-r--r-- | lib/yang.h | 28 | ||||
| -rw-r--r-- | lib/yang_translator.c | 22 | ||||
| -rw-r--r-- | lib/zassert.h | 2 | ||||
| -rw-r--r-- | lib/zlog.c | 29 |
32 files changed, 641 insertions, 189 deletions
diff --git a/lib/agentx.c b/lib/agentx.c index 7c4bdcbe27..603d8d6172 100644 --- a/lib/agentx.c +++ b/lib/agentx.c @@ -107,7 +107,7 @@ static void agentx_events_update(void) struct thread *thr; int fd, thr_fd; - THREAD_OFF(timeout_thr); + thread_cancel(&timeout_thr); FD_ZERO(&fds); snmp_select_info(&maxfd, &fds, &timeout, &block); @@ -130,7 +130,7 @@ static void agentx_events_update(void) if (thr_fd == fd) { struct listnode *nextln = listnextnode(ln); if (!FD_ISSET(fd, &fds)) { - thread_cancel(thr); + thread_cancel(&thr); list_delete_node(events, ln); } ln = nextln; @@ -151,7 +151,8 @@ static void agentx_events_update(void) */ while (ln) { struct listnode *nextln = listnextnode(ln); - thread_cancel(listgetdata(ln)); + thr = listgetdata(ln); + thread_cancel(&thr); list_delete_node(events, ln); ln = nextln; } diff --git a/lib/command.c b/lib/command.c index 1e950fe483..7d335e1c36 100644 --- a/lib/command.c +++ b/lib/command.c @@ -139,6 +139,27 @@ static struct cmd_node config_node = { .node_exit = vty_config_node_exit, }; +static bool vty_check_node_for_xpath_decrement(enum node_type target_node, + enum node_type node) +{ + /* bgp afi-safi (`address-family <afi> <safi>`) node + * does not increment xpath_index. + * In order to use (`router bgp`) BGP_NODE's xpath as a base, + * retain xpath_index as 1 upon exiting from + * afi-safi node. + */ + + if (target_node == BGP_NODE + && (node == BGP_IPV4_NODE || node == BGP_IPV6_NODE + || node == BGP_IPV4M_NODE || node == BGP_IPV6M_NODE + || node == BGP_VPNV4_NODE || node == BGP_VPNV6_NODE + || node == BGP_EVPN_NODE || node == BGP_IPV4L_NODE + || node == BGP_IPV6L_NODE )) + return false; + + return true; +} + /* This is called from main when a daemon is invoked with -v or --version. */ void print_version(const char *progname) { @@ -985,7 +1006,9 @@ int cmd_execute_command(vector vline, struct vty *vty, while (vty->node > CONFIG_NODE) { try_node = node_parent(try_node); vty->node = try_node; - if (vty->xpath_index > 0) + if (vty->xpath_index > 0 + && vty_check_node_for_xpath_decrement(try_node, + onode)) vty->xpath_index--; ret = cmd_execute_command_real(vline, FILTER_RELAXED, vty, cmd); @@ -1194,7 +1217,9 @@ int command_config_read_one_line(struct vty *vty, && ret != CMD_SUCCESS && ret != CMD_WARNING && vty->node > CONFIG_NODE) { vty->node = node_parent(vty->node); - if (vty->xpath_index > 0) + if (vty->xpath_index > 0 + && vty_check_node_for_xpath_decrement(vty->node, + saved_node)) vty->xpath_index--; ret = cmd_execute_command_strict(vline, vty, cmd); } @@ -1316,7 +1341,8 @@ void cmd_exit(struct vty *vty) } if (cnode->parent_node) vty->node = cnode->parent_node; - if (vty->xpath_index > 0) + if (vty->xpath_index > 0 + && vty_check_node_for_xpath_decrement(vty->node, cnode->node)) vty->xpath_index--; } diff --git a/lib/filter.c b/lib/filter.c index e6add0462b..f5ae9ee2b7 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -576,14 +576,12 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi) if (filter->addr_mask.s_addr == 0xffffffff) vty_out(vty, " any\n"); else { - vty_out(vty, " %s", - inet_ntoa(filter->addr)); + vty_out(vty, " %pI4", &filter->addr); if (filter->addr_mask.s_addr != INADDR_ANY) vty_out(vty, - ", wildcard bits %s", - inet_ntoa( - filter->addr_mask)); + ", wildcard bits %pI4", + &filter->addr_mask); vty_out(vty, "\n"); } } @@ -625,14 +623,12 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi) if (filter->addr_mask.s_addr == 0xffffffff) vty_out(vty, " any\n"); else { - vty_out(vty, " %s", - inet_ntoa(filter->addr)); + vty_out(vty, " %pI4", &filter->addr); if (filter->addr_mask.s_addr != INADDR_ANY) vty_out(vty, - ", wildcard bits %s", - inet_ntoa( - filter->addr_mask)); + ", wildcard bits %pI4", + &filter->addr_mask); vty_out(vty, "\n"); } } @@ -722,29 +718,28 @@ static void config_write_access_cisco(struct vty *vty, struct filter *mfilter) if (filter->addr_mask.s_addr == 0xffffffff) vty_out(vty, " any"); else if (filter->addr_mask.s_addr == INADDR_ANY) - vty_out(vty, " host %s", inet_ntoa(filter->addr)); + vty_out(vty, " host %pI4", &filter->addr); else { - vty_out(vty, " %s", inet_ntoa(filter->addr)); - vty_out(vty, " %s", inet_ntoa(filter->addr_mask)); + vty_out(vty, " %pI4", &filter->addr); + vty_out(vty, " %pI4", &filter->addr_mask); } if (filter->mask_mask.s_addr == 0xffffffff) vty_out(vty, " any"); else if (filter->mask_mask.s_addr == INADDR_ANY) - vty_out(vty, " host %s", inet_ntoa(filter->mask)); + vty_out(vty, " host %pI4", &filter->mask); else { - vty_out(vty, " %s", inet_ntoa(filter->mask)); - vty_out(vty, " %s", inet_ntoa(filter->mask_mask)); + vty_out(vty, " %pI4", &filter->mask); + vty_out(vty, " %pI4", &filter->mask_mask); } vty_out(vty, "\n"); } else { if (filter->addr_mask.s_addr == 0xffffffff) vty_out(vty, " any\n"); else { - vty_out(vty, " %s", inet_ntoa(filter->addr)); + vty_out(vty, " %pI4", &filter->addr); if (filter->addr_mask.s_addr != INADDR_ANY) - vty_out(vty, " %s", - inet_ntoa(filter->addr_mask)); + vty_out(vty, " %pI4", &filter->addr_mask); vty_out(vty, "\n"); } } diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c index da9594ed80..3f0179fbc1 100644 --- a/lib/frr_pthread.c +++ b/lib/frr_pthread.c @@ -28,6 +28,7 @@ #include "memory.h" #include "linklist.h" #include "zlog.h" +#include "libfrr_trace.h" DEFINE_MTYPE_STATIC(LIB, FRR_PTHREAD, "FRR POSIX Thread") DEFINE_MTYPE_STATIC(LIB, PTHREAD_PRIM, "POSIX sync primitives") @@ -167,6 +168,8 @@ int frr_pthread_run(struct frr_pthread *fpt, const pthread_attr_t *attr) sigfillset(&blocksigs); pthread_sigmask(SIG_BLOCK, &blocksigs, &oldsigs); + frrtrace(1, frr_libfrr, frr_pthread_run, fpt->name); + fpt->rcu_thread = rcu_thread_prepare(); ret = pthread_create(&fpt->thread, attr, frr_pthread_inner, fpt); @@ -204,6 +207,8 @@ void frr_pthread_notify_running(struct frr_pthread *fpt) int frr_pthread_stop(struct frr_pthread *fpt, void **result) { + frrtrace(1, frr_libfrr, frr_pthread_stop, fpt->name); + int ret = (*fpt->attr.stop)(fpt, result); memset(&fpt->thread, 0x00, sizeof(fpt->thread)); return ret; diff --git a/lib/frr_zmq.c b/lib/frr_zmq.c index 565936a410..cc11d76700 100644 --- a/lib/frr_zmq.c +++ b/lib/frr_zmq.c @@ -190,10 +190,8 @@ int funcname_frrzmq_thread_add_read(struct thread_master *master, cb->read.cancelled = false; if (events & ZMQ_POLLIN) { - if (cb->read.thread) { - thread_cancel(cb->read.thread); - cb->read.thread = NULL; - } + thread_cancel(&cb->read.thread); + funcname_thread_add_event(master, frrzmq_read_msg, cbp, fd, &cb->read.thread, funcname, schedfrom, fromln); @@ -298,10 +296,8 @@ int funcname_frrzmq_thread_add_write(struct thread_master *master, cb->write.cancelled = false; if (events & ZMQ_POLLOUT) { - if (cb->write.thread) { - thread_cancel(cb->write.thread); - cb->write.thread = NULL; - } + thread_cancel(&cb->write.thread); + funcname_thread_add_event(master, frrzmq_write_msg, cbp, fd, &cb->write.thread, funcname, schedfrom, fromln); @@ -317,10 +313,8 @@ void frrzmq_thread_cancel(struct frrzmq_cb **cb, struct cb_core *core) if (!cb || !*cb) return; core->cancelled = true; - if (core->thread) { - thread_cancel(core->thread); - core->thread = NULL; - } + thread_cancel(&core->thread); + if ((*cb)->read.cancelled && !(*cb)->read.thread && (*cb)->write.cancelled && (*cb)->write.thread) XFREE(MTYPE_ZEROMQ_CB, *cb); @@ -344,8 +338,8 @@ void frrzmq_check_events(struct frrzmq_cb **cbp, struct cb_core *core, return; if (events & event && core->thread && !core->cancelled) { struct thread_master *tm = core->thread->master; - thread_cancel(core->thread); - core->thread = NULL; + thread_cancel(&core->thread); + thread_add_event(tm, (event == ZMQ_POLLIN ? frrzmq_read_msg : frrzmq_write_msg), cbp, cb->fd, &core->thread); diff --git a/lib/hash.c b/lib/hash.c index 85982774ac..ed429b77d0 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -29,6 +29,7 @@ #include "command.h" #include "libfrr.h" #include "frr_pthread.h" +#include "libfrr_trace.h" DEFINE_MTYPE_STATIC(LIB, HASH, "Hash") DEFINE_MTYPE_STATIC(LIB, HASH_BACKET, "Hash Bucket") @@ -138,6 +139,8 @@ static void hash_expand(struct hash *hash) void *hash_get(struct hash *hash, void *data, void *(*alloc_func)(void *)) { + frrtrace(2, frr_libfrr, hash_get, hash, data); + unsigned int key; unsigned int index; void *newdata; @@ -172,6 +175,8 @@ void *hash_get(struct hash *hash, void *data, void *(*alloc_func)(void *)) hash->index[index] = bucket; hash->count++; + frrtrace(3, frr_libfrr, hash_insert, hash, data, key); + int oldlen = bucket->next ? bucket->next->len : 0; int newlen = oldlen + 1; @@ -206,7 +211,7 @@ unsigned int string_hash_make(const char *str) void *hash_release(struct hash *hash, void *data) { - void *ret; + void *ret = NULL; unsigned int key; unsigned int index; struct hash_bucket *bucket; @@ -236,11 +241,14 @@ void *hash_release(struct hash *hash, void *data) ret = bucket->data; XFREE(MTYPE_HASH_BACKET, bucket); hash->count--; - return ret; + break; } pp = bucket; } - return NULL; + + frrtrace(3, frr_libfrr, hash_release, hash, data, ret); + + return ret; } void hash_iterate(struct hash *hash, void (*func)(struct hash_bucket *, void *), @@ -1106,8 +1106,8 @@ ifaddr_ipv4_add (struct in_addr *ifaddr, struct interface *ifp) if (rn) { route_unlock_node (rn); - zlog_info ("ifaddr_ipv4_add(): address %s is already added", - inet_ntoa (*ifaddr)); + zlog_info("ifaddr_ipv4_add(): address %pI4 is already added", + ifaddr); return; } rn->info = ifp; @@ -1126,8 +1126,7 @@ ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp) rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p); if (! rn) { - zlog_info ("ifaddr_ipv4_delete(): can't find address %s", - inet_ntoa (*ifaddr)); + zlog_info("%s: can't find address %pI4", __func__, ifaddr); return; } rn->info = NULL; diff --git a/lib/ldp_sync.c b/lib/ldp_sync.c index 9657f0b1df..c9d7eb37cf 100644 --- a/lib/ldp_sync.c +++ b/lib/ldp_sync.c @@ -79,7 +79,7 @@ bool ldp_sync_if_down(struct ldp_sync_info *ldp_sync_info) * update state */ if (ldp_sync_info && ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED) { - THREAD_TIMER_OFF(ldp_sync_info->t_holddown); + THREAD_OFF(ldp_sync_info->t_holddown); if (ldp_sync_info->state == LDP_IGP_SYNC_STATE_REQUIRED_UP) ldp_sync_info->state = diff --git a/lib/libfrr_trace.c b/lib/libfrr_trace.c new file mode 100644 index 0000000000..2f300e6ee1 --- /dev/null +++ b/lib/libfrr_trace.c @@ -0,0 +1,4 @@ +#define TRACEPOINT_CREATE_PROBES +#define TRACEPOINT_DEFINE + +#include "libfrr_trace.h" diff --git a/lib/libfrr_trace.h b/lib/libfrr_trace.h new file mode 100644 index 0000000000..7215007ffb --- /dev/null +++ b/lib/libfrr_trace.h @@ -0,0 +1,240 @@ +/* Tracing + * + * Copyright (C) 2020 NVIDIA Corporation + * Quentin Young + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if !defined(_LIBFRR_TRACE_H_) || defined(TRACEPOINT_HEADER_MULTI_READ) +#define _LIBFRR_TRACE_H_ + +#include "trace.h" + +#ifdef HAVE_LTTNG + +#undef TRACEPOINT_PROVIDER +#define TRACEPOINT_PROVIDER frr_libfrr + +#undef TRACEPOINT_INCLUDE +#define TRACEPOINT_INCLUDE "./libfrr_trace.h" + +#include <lttng/tracepoint.h> + +#include "hash.h" +#include "thread.h" +#include "memory.h" +#include "linklist.h" +#include "table.h" + +/* clang-format off */ + +TRACEPOINT_EVENT( + frr_libfrr, + hash_get, + TP_ARGS(struct hash *, hash, void *, data), + TP_FIELDS( + ctf_string(name, hash->name ? hash->name : "(unnamed)") + ctf_integer(unsigned int, index_size, hash->size) + ctf_integer(unsigned long, item_count, hash->count) + ctf_integer_hex(intptr_t, data_ptr, data) + ) +) + +TRACEPOINT_LOGLEVEL(frr_libfrr, hash_get, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_libfrr, + hash_insert, + TP_ARGS(struct hash *, hash, void *, data, unsigned int, key), + TP_FIELDS( + ctf_string(name, hash->name ? hash->name : "(unnamed)") + ctf_integer(unsigned int, key, hash->size) + ctf_integer(unsigned int, index_size, hash->size) + ctf_integer(unsigned long, item_count, hash->count) + ctf_integer_hex(intptr_t, data_ptr, data) + ) +) + +TRACEPOINT_LOGLEVEL(frr_libfrr, hash_insert, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_libfrr, + hash_release, + TP_ARGS(struct hash *, hash, void *, data, void *, released_item), + TP_FIELDS( + ctf_string(name, hash->name ? hash->name : "(unnamed)") + ctf_integer(unsigned int, index_size, hash->size) + ctf_integer(unsigned long, item_count, hash->count) + ctf_integer_hex(intptr_t, data_ptr, data) + ctf_integer_hex(intptr_t, released_item, data) + ) +) + +TRACEPOINT_LOGLEVEL(frr_libfrr, hash_release, TRACE_INFO) + +#define THREAD_SCHEDULE_ARGS \ + TP_ARGS(struct thread_master *, master, const char *, funcname, \ + const char *, schedfrom, int, fromln, struct thread **, \ + thread_ptr, int, fd, int, val, void *, arg, long, time) + +TRACEPOINT_EVENT_CLASS( + frr_libfrr, + thread_operation, + THREAD_SCHEDULE_ARGS, + TP_FIELDS( + ctf_string(threadmaster_name, master->name) + ctf_string(function_name, funcname ? funcname : "(unknown function)") + ctf_string(scheduled_from, schedfrom ? schedfrom : "(unknown file)") + ctf_integer(int, scheduled_on_line, fromln) + ctf_integer_hex(intptr_t, thread_addr, thread_ptr ? *thread_ptr : NULL) + ctf_integer(int, file_descriptor, fd) + ctf_integer(int, event_value, val) + ctf_integer_hex(intptr_t, argument_ptr, arg) + ctf_integer(long, timer, time) + ) +) + +#define THREAD_OPERATION_TRACEPOINT_INSTANCE(name) \ + TRACEPOINT_EVENT_INSTANCE(frr_libfrr, thread_operation, name, \ + THREAD_SCHEDULE_ARGS) \ + TRACEPOINT_LOGLEVEL(frr_libfrr, name, TRACE_INFO) + +THREAD_OPERATION_TRACEPOINT_INSTANCE(schedule_timer) +THREAD_OPERATION_TRACEPOINT_INSTANCE(schedule_event) +THREAD_OPERATION_TRACEPOINT_INSTANCE(schedule_read) +THREAD_OPERATION_TRACEPOINT_INSTANCE(schedule_write) +THREAD_OPERATION_TRACEPOINT_INSTANCE(thread_cancel) +THREAD_OPERATION_TRACEPOINT_INSTANCE(thread_cancel_async) +THREAD_OPERATION_TRACEPOINT_INSTANCE(thread_call) + +TRACEPOINT_EVENT( + frr_libfrr, + frr_pthread_run, + TP_ARGS( + char *, name + ), + TP_FIELDS( + ctf_string(frr_pthread_name, name) + ) +) + +TRACEPOINT_EVENT( + frr_libfrr, + frr_pthread_stop, + TP_ARGS( + char *, name + ), + TP_FIELDS( + ctf_string(frr_pthread_name, name) + ) +) + +TRACEPOINT_EVENT( + frr_libfrr, + memalloc, + TP_ARGS( + struct memtype *, mt, void *, ptr, size_t, size + ), + TP_FIELDS( + ctf_string(memtype, mt->name) + ctf_integer(size_t, size, size) + ctf_integer_hex(intptr_t, ptr, ptr) + ) +) + +TRACEPOINT_EVENT( + frr_libfrr, + memfree, + TP_ARGS( + struct memtype *, mt, void *, ptr + ), + TP_FIELDS( + ctf_string(memtype, mt->name) + ctf_integer_hex(intptr_t, ptr, ptr) + ) +) + +TRACEPOINT_EVENT( + frr_libfrr, + list_add, + TP_ARGS( + struct list *, list, const void *, ptr + ), + TP_FIELDS( + ctf_integer_hex(intptr_t, list, list) + ctf_integer(unsigned int, count, list->count) + ctf_integer_hex(intptr_t, ptr, ptr) + ) +) + +TRACEPOINT_EVENT( + frr_libfrr, + list_remove, + TP_ARGS( + struct list *, list, const void *, ptr + ), + TP_FIELDS( + ctf_integer_hex(intptr_t, list, list) + ctf_integer(unsigned int, count, list->count) + ctf_integer_hex(intptr_t, ptr, ptr) + ) +) + +TRACEPOINT_EVENT( + frr_libfrr, + list_delete_node, + TP_ARGS( + struct list *, list, const void *, node + ), + TP_FIELDS( + ctf_integer_hex(intptr_t, list, list) + ctf_integer(unsigned int, count, list->count) + ctf_integer_hex(intptr_t, node, node) + ) +) + +TRACEPOINT_EVENT( + frr_libfrr, + list_sort, + TP_ARGS( + struct list *, list + ), + TP_FIELDS( + ctf_integer_hex(intptr_t, list, list) + ctf_integer(unsigned int, count, list->count) + ) +) + +TRACEPOINT_EVENT( + frr_libfrr, + route_node_get, + TP_ARGS( + struct route_table *, table, char *, prefix + ), + TP_FIELDS( + ctf_integer_hex(intptr_t, table, table) + ctf_string(prefix, prefix) + ) +) + +/* clang-format on */ + +#include <lttng/tracepoint-event.h> +#include <lttng/tracelog.h> + +#endif /* HAVE_LTTNG */ + +#endif /* _LIBFRR_TRACE_H_ */ diff --git a/lib/linklist.c b/lib/linklist.c index 84dc6e1419..43c2002231 100644 --- a/lib/linklist.c +++ b/lib/linklist.c @@ -23,6 +23,7 @@ #include "linklist.h" #include "memory.h" +#include "libfrr_trace.h" DEFINE_MTYPE_STATIC(LIB, LINK_LIST, "Link List") DEFINE_MTYPE_STATIC(LIB, LINK_NODE, "Link Node") @@ -66,6 +67,8 @@ static void listnode_free(struct list *list, struct listnode *node) struct listnode *listnode_add(struct list *list, void *val) { + frrtrace(2, frr_libfrr, list_add, list, val); + struct listnode *node; assert(val != NULL); @@ -281,6 +284,8 @@ void listnode_move_to_tail(struct list *l, struct listnode *n) void listnode_delete(struct list *list, const void *val) { + frrtrace(2, frr_libfrr, list_remove, list, val); + struct listnode *node = listnode_lookup(list, val); if (node) @@ -360,6 +365,8 @@ struct listnode *listnode_lookup_nocheck(struct list *list, void *data) void list_delete_node(struct list *list, struct listnode *node) { + frrtrace(2, frr_libfrr, list_delete_node, list, node); + if (node->prev) node->prev->next = node->next; else @@ -374,6 +381,8 @@ void list_delete_node(struct list *list, struct listnode *node) void list_sort(struct list *list, int (*cmp)(const void **, const void **)) { + frrtrace(1, frr_libfrr, list_sort, list); + struct listnode *ln, *nn; int i = -1; void *data; diff --git a/lib/memory.c b/lib/memory.c index 2c902d123b..f715044ea3 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -29,6 +29,7 @@ #include "memory.h" #include "log.h" +#include "libfrr_trace.h" static struct memgroup *mg_first = NULL; struct memgroup **mg_insert = &mg_first; @@ -77,6 +78,8 @@ static inline void mt_count_alloc(struct memtype *mt, size_t size, void *ptr) static inline void mt_count_free(struct memtype *mt, void *ptr) { + frrtrace(2, frr_libfrr, memfree, mt, ptr); + assert(mt->n_alloc); atomic_fetch_sub_explicit(&mt->n_alloc, 1, memory_order_relaxed); @@ -89,6 +92,8 @@ static inline void mt_count_free(struct memtype *mt, void *ptr) static inline void *mt_checkalloc(struct memtype *mt, void *ptr, size_t size) { + frrtrace(3, frr_libfrr, memalloc, mt, ptr, size); + if (__builtin_expect(ptr == NULL, 0)) { if (size) { /* malloc(0) is allowed to return NULL */ diff --git a/lib/nexthop.c b/lib/nexthop.c index f1575649b1..b2fa945690 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -431,13 +431,13 @@ const char *nexthop2str(const struct nexthop *nexthop, char *str, int size) break; case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: - snprintf(str, size, "%s if %u", inet_ntoa(nexthop->gate.ipv4), - nexthop->ifindex); + snprintfrr(str, size, "%pI4 if %u", &nexthop->gate.ipv4, + nexthop->ifindex); break; case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: - snprintf(str, size, "%s if %u", inet6_ntoa(nexthop->gate.ipv6), - nexthop->ifindex); + snprintfrr(str, size, "%pI6 if %u", &nexthop->gate.ipv6, + nexthop->ifindex); break; case NEXTHOP_TYPE_BLACKHOLE: snprintf(str, size, "blackhole"); diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c index 4afb1d642a..dee98ad8d7 100644 --- a/lib/nexthop_group.c +++ b/lib/nexthop_group.c @@ -975,7 +975,6 @@ void nexthop_group_write_nexthop_simple(struct vty *vty, const struct nexthop *nh, char *altifname) { - char buf[100]; char *ifname; vty_out(vty, "nexthop "); @@ -990,19 +989,16 @@ void nexthop_group_write_nexthop_simple(struct vty *vty, vty_out(vty, "%s", ifname); break; case NEXTHOP_TYPE_IPV4: - vty_out(vty, "%s", inet_ntoa(nh->gate.ipv4)); + vty_out(vty, "%pI4", &nh->gate.ipv4); break; case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out(vty, "%s %s", inet_ntoa(nh->gate.ipv4), ifname); + vty_out(vty, "%pI4 %s", &nh->gate.ipv4, ifname); break; case NEXTHOP_TYPE_IPV6: - vty_out(vty, "%s", - inet_ntop(AF_INET6, &nh->gate.ipv6, buf, sizeof(buf))); + vty_out(vty, "%pI6", &nh->gate.ipv6); break; case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out(vty, "%s %s", - inet_ntop(AF_INET6, &nh->gate.ipv6, buf, sizeof(buf)), - ifname); + vty_out(vty, "%pI6 %s", &nh->gate.ipv6, ifname); break; case NEXTHOP_TYPE_BLACKHOLE: break; @@ -1056,10 +1052,14 @@ void nexthop_group_json_nexthop(json_object *j, const struct nexthop *nh) ifindex2ifname(nh->ifindex, nh->vrf_id)); break; case NEXTHOP_TYPE_IPV4: - json_object_string_add(j, "nexthop", inet_ntoa(nh->gate.ipv4)); + json_object_string_add( + j, "nexthop", + inet_ntop(AF_INET, &nh->gate.ipv4, buf, sizeof(buf))); break; case NEXTHOP_TYPE_IPV4_IFINDEX: - json_object_string_add(j, "nexthop", inet_ntoa(nh->gate.ipv4)); + json_object_string_add( + j, "nexthop", + inet_ntop(AF_INET, &nh->gate.ipv4, buf, sizeof(buf))); json_object_string_add(j, "vrfId", ifindex2ifname(nh->ifindex, nh->vrf_id)); break; diff --git a/lib/northbound.c b/lib/northbound.c index c99f993ea5..ecfa2c9d11 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -152,20 +152,22 @@ static int nb_node_del_cb(const struct lys_node *snode, void *arg) struct nb_node *nb_node; nb_node = snode->priv; - lys_set_private(snode, NULL); - XFREE(MTYPE_NB_NODE, nb_node); + if (nb_node) { + lys_set_private(snode, NULL); + XFREE(MTYPE_NB_NODE, nb_node); + } return YANG_ITER_CONTINUE; } void nb_nodes_create(void) { - yang_snodes_iterate_all(nb_node_new_cb, 0, NULL); + yang_snodes_iterate(NULL, nb_node_new_cb, 0, NULL); } void nb_nodes_delete(void) { - yang_snodes_iterate_all(nb_node_del_cb, 0, NULL); + yang_snodes_iterate(NULL, nb_node_del_cb, 0, NULL); } struct nb_node *nb_node_find(const char *xpath) @@ -273,8 +275,10 @@ static int nb_node_validate(const struct lys_node *snode, void *arg) unsigned int *errors = arg; /* Validate callbacks and priority. */ - *errors += nb_node_validate_cbs(nb_node); - *errors += nb_node_validate_priority(nb_node); + if (nb_node) { + *errors += nb_node_validate_cbs(nb_node); + *errors += nb_node_validate_priority(nb_node); + } return YANG_ITER_CONTINUE; } @@ -2232,25 +2236,11 @@ static void nb_load_callbacks(const struct frr_yang_module_info *module) } } -void nb_init(struct thread_master *tm, - const struct frr_yang_module_info *const modules[], - size_t nmodules, bool db_enabled) +void nb_validate_callbacks(void) { unsigned int errors = 0; - /* Load YANG modules. */ - for (size_t i = 0; i < nmodules; i++) - yang_module_load(modules[i]->name); - - /* Create a nb_node for all YANG schema nodes. */ - nb_nodes_create(); - - /* Load northbound callbacks. */ - for (size_t i = 0; i < nmodules; i++) - nb_load_callbacks(modules[i]); - - /* Validate northbound callbacks. */ - yang_snodes_iterate_all(nb_node_validate, 0, &errors); + yang_snodes_iterate(NULL, nb_node_validate, 0, &errors); if (errors > 0) { flog_err( EC_LIB_NB_CBS_VALIDATION, @@ -2258,9 +2248,33 @@ void nb_init(struct thread_master *tm, __func__, errors); exit(1); } +} +void nb_load_module(const struct frr_yang_module_info *module_info) +{ + struct yang_module *module; + + DEBUGD(&nb_dbg_events, "northbound: loading %s.yang", + module_info->name); + + module = yang_module_load(module_info->name); + yang_snodes_iterate(module->info, nb_node_new_cb, 0, NULL); + nb_load_callbacks(module_info); +} + +void nb_init(struct thread_master *tm, + const struct frr_yang_module_info *const modules[], + size_t nmodules, bool db_enabled) +{ nb_db_enabled = db_enabled; + /* Load YANG modules and their corresponding northbound callbacks. */ + for (size_t i = 0; i < nmodules; i++) + nb_load_module(modules[i]); + + /* Validate northbound callbacks. */ + nb_validate_callbacks(); + /* Create an empty running configuration. */ running_config = nb_config_new(NULL); running_config_entries = hash_create(running_config_entry_key_make, diff --git a/lib/northbound.h b/lib/northbound.h index 16f19b3d5b..3f6e4dc46e 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -1238,6 +1238,29 @@ extern const char *nb_err_name(enum nb_error error); extern const char *nb_client_name(enum nb_client client); /* + * Validate all northbound callbacks. + * + * Some errors, like missing callbacks or invalid priorities, are fatal and + * can't be recovered from. Other errors, like unneeded callbacks, are logged + * but otherwise ignored. + * + * Whenever a YANG module is loaded after startup, *all* northbound callbacks + * need to be validated and not only the callbacks from the newly loaded module. + * This is because augmentations can change the properties of the augmented + * module, making mandatory the implementation of additional callbacks. + */ +void nb_validate_callbacks(void); + +/* + * Load a YANG module with its corresponding northbound callbacks. + * + * module_info + * Pointer to structure containing the module name and its northbound + * callbacks. + */ +void nb_load_module(const struct frr_yang_module_info *module_info); + +/* * Initialize the northbound layer. Should be called only once during the * daemon initialization process. * diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c index a7f3a1b305..7048df99fb 100644 --- a/lib/northbound_cli.c +++ b/lib/northbound_cli.c @@ -89,7 +89,7 @@ static int nb_cli_classic_commit(struct vty *vty) static void nb_cli_pending_commit_clear(struct vty *vty) { - THREAD_TIMER_OFF(vty->t_pending_commit); + THREAD_OFF(vty->t_pending_commit); vty->backoff_cmd_count = 0; XFREE(MTYPE_TMP, vty->pending_cmds_buf); vty->pending_cmds_buflen = 0; @@ -154,7 +154,7 @@ static int nb_cli_schedule_command(struct vty *vty) vty->pending_cmds_buflen); /* Schedule the commit operation. */ - THREAD_TIMER_OFF(vty->t_pending_commit); + THREAD_OFF(vty->t_pending_commit); thread_add_timer_msec(master, nb_cli_pending_commit_cb, vty, 100, &vty->t_pending_commit); @@ -312,7 +312,7 @@ int nb_cli_rpc(struct vty *vty, const char *xpath, struct list *input, void nb_cli_confirmed_commit_clean(struct vty *vty) { - THREAD_TIMER_OFF(vty->t_confirmed_commit_timeout); + thread_cancel(&vty->t_confirmed_commit_timeout); nb_config_free(vty->confirmed_commit_rollback); vty->confirmed_commit_rollback = NULL; } @@ -377,7 +377,7 @@ static int nb_cli_commit(struct vty *vty, bool force, "%% Resetting confirmed-commit timeout to %u minute(s)\n\n", confirmed_timeout); - THREAD_TIMER_OFF(vty->t_confirmed_commit_timeout); + thread_cancel(&vty->t_confirmed_commit_timeout); thread_add_timer(master, nb_cli_confirmed_commit_timeout, vty, confirmed_timeout * 60, diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c index c1cb0fc11d..8acba9fd2b 100644 --- a/lib/northbound_confd.c +++ b/lib/northbound_confd.c @@ -550,6 +550,9 @@ static int frr_confd_init_cdb(void) continue; nb_node = snode->priv; + if (!nb_node) + continue; + DEBUGD(&nb_dbg_client_confd, "%s: subscribing to '%s'", __func__, nb_node->xpath); @@ -1189,7 +1192,7 @@ static int frr_confd_subscribe_state(const struct lys_node *snode, void *arg) struct nb_node *nb_node = snode->priv; struct confd_data_cbs *data_cbs = arg; - if (!CHECK_FLAG(snode->flags, LYS_CONFIG_R)) + if (!nb_node || !CHECK_FLAG(snode->flags, LYS_CONFIG_R)) return YANG_ITER_CONTINUE; /* We only need to subscribe to the root of the state subtrees. */ if (snode->parent && CHECK_FLAG(snode->parent->flags, LYS_CONFIG_R)) @@ -1276,7 +1279,7 @@ static int frr_confd_init_dp(const char *program_name) * Iterate over all loaded YANG modules and subscribe to the paths * referent to state data. */ - yang_snodes_iterate_all(frr_confd_subscribe_state, 0, &data_cbs); + yang_snodes_iterate(NULL, frr_confd_subscribe_state, 0, &data_cbs); /* Register notification stream. */ memset(&ncbs, 0, sizeof(ncbs)); @@ -1393,7 +1396,8 @@ static int frr_confd_calculate_snode_hash(const struct lys_node *snode, { struct nb_node *nb_node = snode->priv; - nb_node->confd_hash = confd_str2hash(snode->name); + if (nb_node) + nb_node->confd_hash = confd_str2hash(snode->name); return YANG_ITER_CONTINUE; } @@ -1426,7 +1430,7 @@ static int frr_confd_init(const char *program_name) goto error; } - yang_snodes_iterate_all(frr_confd_calculate_snode_hash, 0, NULL); + yang_snodes_iterate(NULL, frr_confd_calculate_snode_hash, 0, NULL); hook_register(nb_notification_send, frr_confd_notification_send); diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c index 3cd310c5a7..c027f4de72 100644 --- a/lib/northbound_sysrepo.c +++ b/lib/northbound_sysrepo.c @@ -575,6 +575,8 @@ static int frr_sr_subscribe_state(const struct lys_node *snode, void *arg) return YANG_ITER_CONTINUE; nb_node = snode->priv; + if (!nb_node) + return YANG_ITER_CONTINUE; DEBUGD(&nb_dbg_client_sysrepo, "sysrepo: providing data to '%s'", nb_node->xpath); @@ -599,6 +601,8 @@ static int frr_sr_subscribe_rpc(const struct lys_node *snode, void *arg) return YANG_ITER_CONTINUE; nb_node = snode->priv; + if (!nb_node) + return YANG_ITER_CONTINUE; DEBUGD(&nb_dbg_client_sysrepo, "sysrepo: providing RPC to '%s'", nb_node->xpath); @@ -686,10 +690,10 @@ static int frr_sr_init(void) int event_pipe; frr_sr_subscribe_config(module); - yang_snodes_iterate_module(module->info, frr_sr_subscribe_state, - 0, module); - yang_snodes_iterate_module(module->info, frr_sr_subscribe_rpc, - 0, module); + yang_snodes_iterate(module->info, frr_sr_subscribe_state, 0, + module); + yang_snodes_iterate(module->info, frr_sr_subscribe_rpc, 0, + module); /* Watch subscriptions. */ ret = sr_get_event_pipe(module->sr_subscription, &event_pipe); diff --git a/lib/sockunion.c b/lib/sockunion.c index d77229797c..c999845659 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -587,15 +587,11 @@ static void __attribute__((unused)) sockunion_print(const union sockunion *su) switch (su->sa.sa_family) { case AF_INET: - printf("%s\n", inet_ntoa(su->sin.sin_addr)); + printf("%pI4\n", &su->sin.sin_addr); + break; + case AF_INET6: + printf("%pI6\n", &su->sin6.sin6_addr); break; - case AF_INET6: { - char buf[SU_ADDRSTRLEN]; - - printf("%s\n", inet_ntop(AF_INET6, &(su->sin6.sin6_addr), buf, - sizeof(buf))); - } break; - #ifdef AF_LINK case AF_LINK: { struct sockaddr_dl *sdl; diff --git a/lib/spf_backoff.c b/lib/spf_backoff.c index acb208e5e7..ac6dd29f06 100644 --- a/lib/spf_backoff.c +++ b/lib/spf_backoff.c @@ -110,8 +110,8 @@ void spf_backoff_free(struct spf_backoff *backoff) if (!backoff) return; - THREAD_TIMER_OFF(backoff->t_holddown); - THREAD_TIMER_OFF(backoff->t_timetolearn); + thread_cancel(&backoff->t_holddown); + thread_cancel(&backoff->t_timetolearn); XFREE(MTYPE_SPF_BACKOFF_NAME, backoff->name); XFREE(MTYPE_SPF_BACKOFF, backoff); @@ -121,7 +121,6 @@ static int spf_backoff_timetolearn_elapsed(struct thread *thread) { struct spf_backoff *backoff = THREAD_ARG(thread); - backoff->t_timetolearn = NULL; backoff->state = SPF_BACKOFF_LONG_WAIT; backoff_debug("SPF Back-off(%s) TIMETOLEARN elapsed, move to state %s", backoff->name, spf_backoff_state2str(backoff->state)); @@ -132,7 +131,7 @@ static int spf_backoff_holddown_elapsed(struct thread *thread) { struct spf_backoff *backoff = THREAD_ARG(thread); - THREAD_TIMER_OFF(backoff->t_timetolearn); + THREAD_OFF(backoff->t_timetolearn); timerclear(&backoff->first_event_time); backoff->state = SPF_BACKOFF_QUIET; backoff_debug("SPF Back-off(%s) HOLDDOWN elapsed, move to state %s", @@ -166,7 +165,7 @@ long spf_backoff_schedule(struct spf_backoff *backoff) break; case SPF_BACKOFF_SHORT_WAIT: case SPF_BACKOFF_LONG_WAIT: - THREAD_TIMER_OFF(backoff->t_holddown); + thread_cancel(&backoff->t_holddown); thread_add_timer_msec(backoff->m, spf_backoff_holddown_elapsed, backoff, backoff->holddown, &backoff->t_holddown); diff --git a/lib/subdir.am b/lib/subdir.am index 55f127b019..ed3c30799d 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -3,7 +3,7 @@ # lib_LTLIBRARIES += lib/libfrr.la lib_libfrr_la_LDFLAGS = -version-info 0:0:0 -Xlinker -e_libfrr_version -lib_libfrr_la_LIBADD = $(LIBCAP) $(UNWIND_LIBS) $(LIBYANG_LIBS) $(LUA_LIB) $(LIBM) +lib_libfrr_la_LIBADD = $(LIBCAP) $(UNWIND_LIBS) $(LIBYANG_LIBS) $(LUA_LIB) $(UST_LIBS) $(LIBM) lib_libfrr_la_SOURCES = \ lib/agg_table.c \ @@ -46,6 +46,7 @@ lib_libfrr_la_SOURCES = \ lib/lib_errors.c \ lib/lib_vty.c \ lib/libfrr.c \ + lib/libfrr_trace.c \ lib/linklist.c \ lib/log.c \ lib/log_filter.c \ @@ -204,6 +205,7 @@ pkginclude_HEADERS += \ lib/lib_errors.h \ lib/lib_vty.h \ lib/libfrr.h \ + lib/libfrr_trace.h \ lib/libospf.h \ lib/linklist.h \ lib/log.h \ @@ -251,6 +253,7 @@ pkginclude_HEADERS += \ lib/table.h \ lib/termtable.h \ lib/thread.h \ + lib/trace.h \ lib/typerb.h \ lib/typesafe.h \ lib/vector.h \ @@ -401,7 +404,7 @@ lib_grammar_sandbox_LDADD = \ lib_clippy_CPPFLAGS = $(AM_CPPFLAGS) -D_GNU_SOURCE -DBUILDING_CLIPPY lib_clippy_CFLAGS = $(PYTHON_CFLAGS) -lib_clippy_LDADD = $(PYTHON_LIBS) +lib_clippy_LDADD = $(PYTHON_LIBS) $(UST_LIBS) lib_clippy_LDFLAGS = -export-dynamic lib_clippy_SOURCES = \ lib/clippy.c \ @@ -411,6 +414,7 @@ lib_clippy_SOURCES = \ lib/command_py.c \ lib/defun_lex.l \ lib/graph.c \ + lib/libfrr_trace.c \ lib/memory.c \ lib/vector.c \ # end diff --git a/lib/table.c b/lib/table.c index b315637f19..89e32182b5 100644 --- a/lib/table.c +++ b/lib/table.c @@ -27,6 +27,7 @@ #include "table.h" #include "memory.h" #include "sockunion.h" +#include "libfrr_trace.h" DEFINE_MTYPE_STATIC(LIB, ROUTE_TABLE, "Route table") DEFINE_MTYPE(LIB, ROUTE_NODE, "Route node") @@ -276,6 +277,12 @@ struct route_node *route_node_lookup_maynull(struct route_table *table, struct route_node *route_node_get(struct route_table *table, union prefixconstptr pu) { + if (frrtrace_enabled(frr_libfrr, route_node_get)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(pu, buf, sizeof(buf)); + frrtrace(2, frr_libfrr, route_node_get, table, buf); + } + struct route_node search; struct prefix *p = &search.p; diff --git a/lib/thread.c b/lib/thread.c index db35a3f031..1765de9573 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -35,6 +35,7 @@ #include "frratomic.h" #include "frr_pthread.h" #include "lib_errors.h" +#include "libfrr_trace.h" DEFINE_MTYPE_STATIC(LIB, THREAD, "Thread") DEFINE_MTYPE_STATIC(LIB, THREAD_MASTER, "Thread master") @@ -787,6 +788,13 @@ struct thread *funcname_thread_add_read_write(int dir, struct thread_master *m, struct thread *thread = NULL; struct thread **thread_array; + if (dir == THREAD_READ) + frrtrace(9, frr_libfrr, schedule_read, m, funcname, schedfrom, + fromln, t_ptr, fd, 0, arg, 0); + else + frrtrace(9, frr_libfrr, schedule_write, m, funcname, schedfrom, + fromln, t_ptr, fd, 0, arg, 0); + assert(fd >= 0 && fd < m->fd_limit); frr_with_mutex(&m->mtx) { if (t_ptr && *t_ptr) @@ -861,6 +869,9 @@ funcname_thread_add_timer_timeval(struct thread_master *m, assert(type == THREAD_TIMER); assert(time_relative); + frrtrace(9, frr_libfrr, schedule_timer, m, funcname, schedfrom, fromln, + t_ptr, 0, 0, arg, (long)time_relative->tv_sec); + frr_with_mutex(&m->mtx) { if (t_ptr && *t_ptr) /* thread is already scheduled; don't reschedule */ @@ -939,6 +950,9 @@ struct thread *funcname_thread_add_event(struct thread_master *m, { struct thread *thread = NULL; + frrtrace(9, frr_libfrr, schedule_event, m, funcname, schedfrom, fromln, + t_ptr, 0, val, arg, 0); + assert(m != NULL); frr_with_mutex(&m->mtx) { @@ -1163,19 +1177,30 @@ void thread_cancel_event(struct thread_master *master, void *arg) * * @param thread task to cancel */ -void thread_cancel(struct thread *thread) +void thread_cancel(struct thread **thread) { - struct thread_master *master = thread->master; + struct thread_master *master; + + if (thread == NULL || *thread == NULL) + return; + + master = (*thread)->master; + + frrtrace(9, frr_libfrr, thread_cancel, master, thread->funcname, + thread->schedfrom, thread->schedfrom_line, NULL, thread->u.fd, + thread->u.val, thread->arg, thread->u.sands.tv_sec); assert(master->owner == pthread_self()); frr_with_mutex(&master->mtx) { struct cancel_req *cr = XCALLOC(MTYPE_TMP, sizeof(struct cancel_req)); - cr->thread = thread; + cr->thread = *thread; listnode_add(master->cancel_req, cr); do_thread_cancel(master); } + + *thread = NULL; } /** @@ -1206,6 +1231,17 @@ void thread_cancel_async(struct thread_master *master, struct thread **thread, void *eventobj) { assert(!(thread && eventobj) && (thread || eventobj)); + + if (thread && *thread) + frrtrace(9, frr_libfrr, thread_cancel_async, master, + (*thread)->funcname, (*thread)->schedfrom, + (*thread)->schedfrom_line, NULL, (*thread)->u.fd, + (*thread)->u.val, (*thread)->arg, + (*thread)->u.sands.tv_sec); + else + frrtrace(9, frr_libfrr, thread_cancel_async, master, NULL, NULL, + 0, NULL, 0, 0, eventobj, 0); + assert(master->owner != pthread_self()); frr_with_mutex(&master->mtx) { @@ -1227,6 +1263,9 @@ void thread_cancel_async(struct thread_master *master, struct thread **thread, while (!master->canceled) pthread_cond_wait(&master->cancel_cond, &master->mtx); } + + if (thread) + *thread = NULL; } /* ------------------------------------------------------------------------- */ @@ -1581,6 +1620,10 @@ void thread_call(struct thread *thread) GETRUSAGE(&before); thread->real = before.real; + frrtrace(9, frr_libfrr, thread_call, thread->master, thread->funcname, + thread->schedfrom, thread->schedfrom_line, NULL, thread->u.fd, + thread->u.val, thread->arg, thread->u.sands.tv_sec); + pthread_setspecific(thread_current, thread); (*thread->func)(thread); pthread_setspecific(thread_current, NULL); diff --git a/lib/thread.h b/lib/thread.h index c22b2105cd..e2b7763c51 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -147,18 +147,15 @@ struct cpu_thread_history { #define THREAD_FD(X) ((X)->u.fd) #define THREAD_VAL(X) ((X)->u.val) -#define THREAD_OFF(thread) \ - do { \ - if (thread) { \ - thread_cancel(thread); \ - thread = NULL; \ - } \ +/* + * Please consider this macro deprecated, and do not use it in new code. + */ +#define THREAD_OFF(thread) \ + do { \ + if ((thread)) \ + thread_cancel(&(thread)); \ } while (0) -#define THREAD_READ_OFF(thread) THREAD_OFF(thread) -#define THREAD_WRITE_OFF(thread) THREAD_OFF(thread) -#define THREAD_TIMER_OFF(thread) THREAD_OFF(thread) - #define debugargdef const char *funcname, const char *schedfrom, int fromln #define thread_add_read(m,f,a,v,t) funcname_thread_add_read_write(THREAD_READ,m,f,a,v,t,#f,__FILE__,__LINE__) @@ -207,7 +204,7 @@ extern void funcname_thread_execute(struct thread_master *, debugargdef); #undef debugargdef -extern void thread_cancel(struct thread *); +extern void thread_cancel(struct thread **event); extern void thread_cancel_async(struct thread_master *, struct thread **, void *); extern void thread_cancel_event(struct thread_master *, void *); diff --git a/lib/trace.h b/lib/trace.h new file mode 100644 index 0000000000..73fc10a556 --- /dev/null +++ b/lib/trace.h @@ -0,0 +1,80 @@ +/* Tracing macros + * + * Wraps tracepoint macros for different tracing systems to allow switching + * between them at compile time. + * + * This should not be included directly by source files wishing to provide + * tracepoints. Instead, write a header that defines LTTng tracepoints and + * which includes this header, and include your new header in your source. USDT + * probes do not need tracepoint definitions, but are less capable than LTTng + * tracepoints. + * + * Copyright (C) 2020 NVIDIA Corporation + * Quentin Young + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _TRACE_H_ +#define _TRACE_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +/* + * Provided here: + * - frrtrace(n, provider, name, ...args...) + * - frrtrace_enabled(provider, name) + * - frrtracelog(level, msg, ...) + * + * Use frrtrace() to define tracepoints. n is the number of arguments; this is + * needed because USDT probe definitions use DTRACE_PROBEn macros, so the + * number of args must be passed in order to expand the correct macro. + * + * frrtrace_enabled() maps to tracepoint_enabled() under LTTng and is always + * true when using USDT. In the future it could be mapped to USDT semaphores + * but this is not implemented at present. + * + * frrtracelog() maps to tracelog() under LTTng and should only be used in zlog + * core code, to propagate zlog messages to LTTng. It expands to nothing + * otherwise. + */ + +#if defined(HAVE_LTTNG) + +#define frrtrace(nargs, provider, name, ...) \ + tracepoint(provider, name, ## __VA_ARGS__) +#define frrtrace_enabled(...) tracepoint_enabled(__VA_ARGS__) +#define frrtracelog(...) tracelog(__VA_ARGS__) + +#elif defined(HAVE_USDT) + +#include "sys/sdt.h" + +#define frrtrace(nargs, provider, name, ...) \ + DTRACE_PROBE##nargs(provider, name, ## __VA_ARGS__) +#define frrtrace_enabled(...) true +#define frrtracelog(...) + +#else + +#define frrtrace(nargs, provider, name, ...) (void)0 +#define frrtrace_enabled(...) false +#define frrtracelog(...) (void)0 + +#endif + +#endif /* _TRACE_H_ */ diff --git a/lib/workqueue.c b/lib/workqueue.c index 54090d0d0f..f8e4677220 100644 --- a/lib/workqueue.c +++ b/lib/workqueue.c @@ -104,7 +104,7 @@ void work_queue_free_and_null(struct work_queue **wqp) struct work_queue *wq = *wqp; if (wq->thread != NULL) - thread_cancel(wq->thread); + thread_cancel(&(wq->thread)); while (!work_queue_empty(wq)) { struct work_queue_item *item = work_queue_last_item(wq); @@ -215,7 +215,7 @@ void workqueue_cmd_init(void) void work_queue_plug(struct work_queue *wq) { if (wq->thread) - thread_cancel(wq->thread); + thread_cancel(&(wq->thread)); wq->thread = NULL; diff --git a/lib/yang.c b/lib/yang.c index 5bf7758e18..c59cb642f0 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -227,40 +227,22 @@ next: return ret; } -int yang_snodes_iterate_module(const struct lys_module *module, - yang_iterate_cb cb, uint16_t flags, void *arg) +int yang_snodes_iterate(const struct lys_module *module, yang_iterate_cb cb, + uint16_t flags, void *arg) { - struct lys_node *snode; - int ret = YANG_ITER_CONTINUE; - - LY_TREE_FOR (module->data, snode) { - ret = yang_snodes_iterate_subtree(snode, module, cb, flags, - arg); - if (ret == YANG_ITER_STOP) - return ret; - } - - for (uint8_t i = 0; i < module->augment_size; i++) { - ret = yang_snodes_iterate_subtree( - (const struct lys_node *)&module->augment[i], module, - cb, flags, arg); - if (ret == YANG_ITER_STOP) - return ret; - } - - return ret; -} - -int yang_snodes_iterate_all(yang_iterate_cb cb, uint16_t flags, void *arg) -{ - struct yang_module *module; + const struct lys_module *module_iter; + uint32_t idx = 0; int ret = YANG_ITER_CONTINUE; - RB_FOREACH (module, yang_modules, &yang_modules) { + idx = ly_ctx_internal_modules_count(ly_native_ctx); + while ((module_iter = ly_ctx_get_module_iter(ly_native_ctx, &idx))) { struct lys_node *snode; - LY_TREE_FOR (module->info->data, snode) { - ret = yang_snodes_iterate_subtree(snode, NULL, cb, + if (!module_iter->implemented) + continue; + + LY_TREE_FOR (module_iter->data, snode) { + ret = yang_snodes_iterate_subtree(snode, module, cb, flags, arg); if (ret == YANG_ITER_STOP) return ret; diff --git a/lib/yang.h b/lib/yang.h index 867ade9676..0cd6a4a6f2 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -186,29 +186,11 @@ extern int yang_snodes_iterate_subtree(const struct lys_node *snode, void *arg); /* - * Iterate over all libyang schema nodes from the given YANG module. + * Iterate over all libyang schema nodes from all loeaded modules of from the + * given YANG module. * * module - * YANG module to operate on. - * - * cb - * Function to call with each schema node. - * - * flags - * YANG_ITER_* flags to control how the iteration is performed. - * - * arg - * Arbitrary argument passed as the second parameter in each call to 'cb'. - * - * Returns: - * The return value of the last called callback. - */ -extern int yang_snodes_iterate_module(const struct lys_module *module, - yang_iterate_cb cb, uint16_t flags, - void *arg); - -/* - * Iterate over all libyang schema nodes from all loaded YANG modules. + * When set, iterate over all nodes of the specified module only. * * cb * Function to call with each schema node. @@ -222,8 +204,8 @@ extern int yang_snodes_iterate_module(const struct lys_module *module, * Returns: * The return value of the last called callback. */ -extern int yang_snodes_iterate_all(yang_iterate_cb cb, uint16_t flags, - void *arg); +extern int yang_snodes_iterate(const struct lys_module *module, + yang_iterate_cb cb, uint16_t flags, void *arg); /* * Build schema path or data path of the schema node. diff --git a/lib/yang_translator.c b/lib/yang_translator.c index 7dbb1f3f1a..1f64675d6a 100644 --- a/lib/yang_translator.c +++ b/lib/yang_translator.c @@ -469,12 +469,12 @@ static unsigned int yang_translator_validate(struct yang_translator *translator) args.errors = 0; for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) { - yang_snodes_iterate_module( - tmodule->module, yang_translator_validate_cb, - YANG_ITER_FILTER_NPCONTAINERS - | YANG_ITER_FILTER_LIST_KEYS - | YANG_ITER_FILTER_INPUT_OUTPUT, - &args); + yang_snodes_iterate(tmodule->module, + yang_translator_validate_cb, + YANG_ITER_FILTER_NPCONTAINERS + | YANG_ITER_FILTER_LIST_KEYS + | YANG_ITER_FILTER_INPUT_OUTPUT, + &args); } if (args.errors) @@ -500,11 +500,11 @@ static unsigned int yang_module_nodes_count(const struct lys_module *module) { unsigned int total = 0; - yang_snodes_iterate_module(module, yang_module_nodes_count_cb, - YANG_ITER_FILTER_NPCONTAINERS - | YANG_ITER_FILTER_LIST_KEYS - | YANG_ITER_FILTER_INPUT_OUTPUT, - &total); + yang_snodes_iterate(module, yang_module_nodes_count_cb, + YANG_ITER_FILTER_NPCONTAINERS + | YANG_ITER_FILTER_LIST_KEYS + | YANG_ITER_FILTER_INPUT_OUTPUT, + &total); return total; } diff --git a/lib/zassert.h b/lib/zassert.h index e50a88f407..e6b254ee8d 100644 --- a/lib/zassert.h +++ b/lib/zassert.h @@ -27,6 +27,8 @@ extern void _zlog_assert_failed(const char *assertion, const char *file, unsigned int line, const char *function) __attribute__((noreturn)); +#undef __ASSERT_FUNCTION + #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define __ASSERT_FUNCTION __func__ #elif defined(__GNUC__) diff --git a/lib/zlog.c b/lib/zlog.c index 8dfd20371b..e77feec5f2 100644 --- a/lib/zlog.c +++ b/lib/zlog.c @@ -52,6 +52,7 @@ #include "printfrr.h" #include "frrcu.h" #include "zlog.h" +#include "libfrr_trace.h" DEFINE_MTYPE_STATIC(LIB, LOG_MESSAGE, "log message") DEFINE_MTYPE_STATIC(LIB, LOG_TLSBUF, "log thread-local buffer") @@ -450,6 +451,34 @@ void vzlog(int prio, const char *fmt, va_list ap) { struct zlog_tls *zlog_tls = zlog_tls_get(); +#ifdef HAVE_LTTNG + va_list copy; + va_copy(copy, ap); + char *msg = vasprintfrr(MTYPE_LOG_MESSAGE, fmt, copy); + + switch (prio) { + case LOG_ERR: + frrtracelog(TRACE_ERR, msg); + break; + case LOG_WARNING: + frrtracelog(TRACE_WARNING, msg); + break; + case LOG_DEBUG: + frrtracelog(TRACE_DEBUG, msg); + break; + case LOG_NOTICE: + frrtracelog(TRACE_DEBUG, msg); + break; + case LOG_INFO: + default: + frrtracelog(TRACE_INFO, msg); + break; + } + + va_end(copy); + XFREE(MTYPE_LOG_MESSAGE, msg); +#endif + if (zlog_tls) vzlog_tls(zlog_tls, prio, fmt, ap); else |
