From 420dcec358efda55dde5e78e333b61c9036f4c8a Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 27 Nov 2019 19:05:35 +0100 Subject: [PATCH 1/8] bgpd: remove redundant VNC build specs rfapi_descriptor_rfp_utils.c is already built into libbgp.a and these include paths have no effect at all. Signed-off-by: David Lamparter --- bgpd/subdir.am | 8 -------- 1 file changed, 8 deletions(-) diff --git a/bgpd/subdir.am b/bgpd/subdir.am index b338fd4f3d..203cf779b9 100644 --- a/bgpd/subdir.am +++ b/bgpd/subdir.am @@ -199,14 +199,6 @@ bgpd_bgp_btoa_SOURCES = bgpd/bgp_btoa.c bgpd_bgpd_CFLAGS = $(AM_CFLAGS) bgpd_bgp_btoa_CFLAGS = $(AM_CFLAGS) -if ENABLE_BGP_VNC -bgpd_bgpd_SOURCES += bgpd/rfapi/rfapi_descriptor_rfp_utils.c -bgpd_bgpd_CFLAGS += -Irfapi -I@top_srcdir@/$(RFPINC) - -bgpd_bgp_btoa_SOURCES += bgpd/rfapi/rfapi_descriptor_rfp_utils.c -bgpd_bgp_btoa_CFLAGS += -Irfapi -I@top_srcdir@/$(RFPINC) -endif - # RFPLDADD is set in bgpd/rfp-example/librfp/subdir.am bgpd_bgpd_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la $(LIBCAP) $(LIBM) bgpd_bgp_btoa_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la $(LIBCAP) $(LIBM) From 9fe602a17ca9de244eb4c97df613c9c7509cc3ad Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 13 Nov 2019 15:42:32 +0100 Subject: [PATCH 2/8] lib: make rcu_free() NULL-safe Signed-off-by: David Lamparter --- lib/frrcu.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/frrcu.h b/lib/frrcu.h index 8f789303cc..06d87c39f1 100644 --- a/lib/frrcu.h +++ b/lib/frrcu.h @@ -139,6 +139,8 @@ extern void rcu_enqueue(struct rcu_head *head, const struct rcu_action *action); #define rcu_free(mtype, ptr, field) \ do { \ typeof(ptr) _ptr = (ptr); \ + if (!_ptr) \ + break; \ struct rcu_head *_rcu_head = &_ptr->field; \ static const struct rcu_action _rcu_action = { \ .type = RCUA_FREE, \ From 33de8d1dd02dfb53f125c8213c896bc62f6c6d8e Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 14 Nov 2019 00:21:10 +0100 Subject: [PATCH 3/8] lib: completely get rid of the MTYPE alias hack Sometimes the easiest solution is hardest to find... the whole point of all this "static const", aliasing, & co. was to make "MTYPE_FOO" usable without adding the extra & as in "&MTYPE_FOO". Making it a size-1 array does that perfectly through the magic of ISO C array decay... Signed-off-by: David Lamparter --- lib/frrcu.c | 4 ++-- lib/memory.h | 23 ++++++++++------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/lib/frrcu.c b/lib/frrcu.c index d65a4a98bf..7e6475b648 100644 --- a/lib/frrcu.c +++ b/lib/frrcu.c @@ -206,7 +206,7 @@ void rcu_thread_unprepare(struct rcu_thread *rt) rcu_bump(); if (rt != &rcu_thread_main) /* this free() happens after seqlock_release() below */ - rcu_free_internal(&_mt_RCU_THREAD, rt, rcu_head); + rcu_free_internal(MTYPE_RCU_THREAD, rt, rcu_head); rcu_threads_del(&rcu_threads, rt); seqlock_release(&rt->rcu); @@ -269,7 +269,7 @@ static void rcu_bump(void) * "last item is being deleted - start over" case, and then we may end * up accessing old RCU queue items that are already free'd. */ - rcu_free_internal(&_mt_RCU_NEXT, rn, head_free); + rcu_free_internal(MTYPE_RCU_NEXT, rn, head_free); /* Only allow the RCU sweeper to run after these 2 items are queued. * diff --git a/lib/memory.h b/lib/memory.h index 8de5c4c2bf..44ea19b557 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -102,45 +102,42 @@ struct memgroup { } #define DECLARE_MTYPE(name) \ - extern struct memtype _mt_##name; \ - extern struct memtype *const MTYPE_##name; \ + extern struct memtype MTYPE_##name[1]; \ /* end */ #define DEFINE_MTYPE_ATTR(group, mname, attr, desc) \ - attr struct memtype _mt_##mname \ - __attribute__((section(".data.mtypes"))) = { \ + attr struct memtype MTYPE_##mname[1] \ + __attribute__((section(".data.mtypes"))) = { { \ .name = desc, \ .next = NULL, \ .n_alloc = 0, \ .size = 0, \ .ref = NULL, \ - }; \ + } }; \ static void _mtinit_##mname(void) __attribute__((_CONSTRUCTOR(1001))); \ static void _mtinit_##mname(void) \ { \ if (_mg_##group.insert == NULL) \ _mg_##group.insert = &_mg_##group.types; \ - _mt_##mname.ref = _mg_##group.insert; \ - *_mg_##group.insert = &_mt_##mname; \ - _mg_##group.insert = &_mt_##mname.next; \ + MTYPE_##mname->ref = _mg_##group.insert; \ + *_mg_##group.insert = MTYPE_##mname; \ + _mg_##group.insert = &MTYPE_##mname->next; \ } \ static void _mtfini_##mname(void) __attribute__((_DESTRUCTOR(1001))); \ static void _mtfini_##mname(void) \ { \ - if (_mt_##mname.next) \ - _mt_##mname.next->ref = _mt_##mname.ref; \ - *_mt_##mname.ref = _mt_##mname.next; \ + if (MTYPE_##mname->next) \ + MTYPE_##mname->next->ref = MTYPE_##mname->ref; \ + *MTYPE_##mname->ref = MTYPE_##mname->next; \ } \ /* end */ #define DEFINE_MTYPE(group, name, desc) \ DEFINE_MTYPE_ATTR(group, name, , desc) \ - struct memtype *const MTYPE_##name = &_mt_##name; \ /* end */ #define DEFINE_MTYPE_STATIC(group, name, desc) \ DEFINE_MTYPE_ATTR(group, name, static, desc) \ - static struct memtype *const MTYPE_##name = &_mt_##name; \ /* end */ DECLARE_MGROUP(LIB) From 1b3e9a21dd4af572deed0d40dd26c8d041e94eae Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 27 Nov 2019 21:17:57 +0100 Subject: [PATCH 4/8] lib: make some variables static Signed-off-by: David Lamparter --- lib/agg_table.c | 2 +- lib/command_lex.l | 2 +- lib/if.c | 2 +- lib/netns_linux.c | 7 ++++--- lib/netns_other.c | 2 +- lib/nexthop_group.c | 2 +- lib/ns.h | 2 -- lib/routemap.c | 6 +++--- lib/systemd.c | 4 ++-- lib/vrf.c | 4 ++-- lib/vty.c | 2 +- lib/yang.c | 2 +- lib/yang.h | 3 --- 13 files changed, 18 insertions(+), 22 deletions(-) diff --git a/lib/agg_table.c b/lib/agg_table.c index dad6a13d67..22b981e284 100644 --- a/lib/agg_table.c +++ b/lib/agg_table.c @@ -41,7 +41,7 @@ static void agg_node_destroy(route_table_delegate_t *delegate, XFREE(MTYPE_TMP, anode); } -route_table_delegate_t agg_table_delegate = { +static route_table_delegate_t agg_table_delegate = { .create_node = agg_node_create, .destroy_node = agg_node_destroy, }; diff --git a/lib/command_lex.l b/lib/command_lex.l index f361db78e9..0556605d63 100644 --- a/lib/command_lex.l +++ b/lib/command_lex.l @@ -85,7 +85,7 @@ RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\) . {return yytext[0];} %% -YY_BUFFER_STATE buffer; +static YY_BUFFER_STATE buffer; void set_lexer_string (yyscan_t *scn, const char *string) { diff --git a/lib/if.c b/lib/if.c index 31c1d9e8ba..c91407084e 100644 --- a/lib/if.c +++ b/lib/if.c @@ -58,7 +58,7 @@ DEFINE_QOBJ_TYPE(interface) DEFINE_HOOK(if_add, (struct interface * ifp), (ifp)) DEFINE_KOOH(if_del, (struct interface * ifp), (ifp)) -struct interface_master{ +static struct interface_master{ int (*create_hook)(struct interface *ifp); int (*up_hook)(struct interface *ifp); int (*down_hook)(struct interface *ifp); diff --git a/lib/netns_linux.c b/lib/netns_linux.c index 55c66fdc3d..d1a31ae35f 100644 --- a/lib/netns_linux.c +++ b/lib/netns_linux.c @@ -51,7 +51,7 @@ static struct ns *ns_lookup_name_internal(const char *name); RB_GENERATE(ns_head, ns, entry, ns_compare) -struct ns_head ns_tree = RB_INITIALIZER(&ns_tree); +static struct ns_head ns_tree = RB_INITIALIZER(&ns_tree); static struct ns *default_ns; static int ns_current_ns_fd; @@ -74,7 +74,8 @@ static inline int ns_map_compare(const struct ns_map_nsid *a, RB_HEAD(ns_map_nsid_head, ns_map_nsid); RB_PROTOTYPE(ns_map_nsid_head, ns_map_nsid, id_entry, ns_map_compare); RB_GENERATE(ns_map_nsid_head, ns_map_nsid, id_entry, ns_map_compare); -struct ns_map_nsid_head ns_map_nsid_list = RB_INITIALIZER(&ns_map_nsid_list); +static struct ns_map_nsid_head ns_map_nsid_list = + RB_INITIALIZER(&ns_map_nsid_list); static ns_id_t ns_id_external_numbering; @@ -123,7 +124,7 @@ static int have_netns(void) } /* Holding NS hooks */ -struct ns_master { +static struct ns_master { int (*ns_new_hook)(struct ns *ns); int (*ns_delete_hook)(struct ns *ns); int (*ns_enable_hook)(struct ns *ns); diff --git a/lib/netns_other.c b/lib/netns_other.c index b0aae4f8df..740d2b621e 100644 --- a/lib/netns_other.c +++ b/lib/netns_other.c @@ -34,7 +34,7 @@ static inline int ns_compare(const struct ns *ns, const struct ns *ns2); RB_GENERATE(ns_head, ns, entry, ns_compare) -struct ns_head ns_tree = RB_INITIALIZER(&ns_tree); +static struct ns_head ns_tree = RB_INITIALIZER(&ns_tree); static inline int ns_compare(const struct ns *a, const struct ns *b) { diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c index 991843a047..8d2e7bb3fc 100644 --- a/lib/nexthop_group.c +++ b/lib/nexthop_group.c @@ -752,7 +752,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd, return CMD_SUCCESS; } -struct cmd_node nexthop_group_node = { +static struct cmd_node nexthop_group_node = { NH_GROUP_NODE, "%s(config-nh-group)# ", 1 diff --git a/lib/ns.h b/lib/ns.h index 1963b8a359..20e0a38e3b 100644 --- a/lib/ns.h +++ b/lib/ns.h @@ -71,8 +71,6 @@ struct ns { RB_HEAD(ns_head, ns); RB_PROTOTYPE(ns_head, ns, entry, ns_compare) -extern struct ns_head ns_tree; - /* * API for managing NETNS. eg from zebra daemon * one want to manage the list of NETNS, etc... diff --git a/lib/routemap.c b/lib/routemap.c index c0e01488b2..14fec0283c 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -221,7 +221,7 @@ struct route_map_match_set_hooks { const char *command, const char *arg); }; -struct route_map_match_set_hooks rmap_match_set_hook; +static struct route_map_match_set_hooks rmap_match_set_hook; /* match interface */ void route_map_match_interface_hook(int (*func)( @@ -623,7 +623,7 @@ struct route_map_list { /* Master list of route map. */ static struct route_map_list route_map_master = {NULL, NULL, NULL, NULL, NULL}; -struct hash *route_map_master_hash = NULL; +static struct hash *route_map_master_hash = NULL; static unsigned int route_map_hash_key_make(const void *p) { @@ -683,7 +683,7 @@ struct route_map_dep_data { }; /* Hashes maintaining dependency between various sublists used by route maps */ -struct hash *route_map_dep_hash[ROUTE_MAP_DEP_MAX]; +static struct hash *route_map_dep_hash[ROUTE_MAP_DEP_MAX]; static unsigned int route_map_dep_hash_make_key(const void *p); static void route_map_clear_all_references(char *rmap_name); diff --git a/lib/systemd.c b/lib/systemd.c index 44db48d006..16fbbff380 100644 --- a/lib/systemd.c +++ b/lib/systemd.c @@ -93,8 +93,8 @@ void systemd_send_stopping(void) /* * How many seconds should we wait between watchdog sends */ -int wsecs = 0; -struct thread_master *systemd_master = NULL; +static int wsecs = 0; +static struct thread_master *systemd_master = NULL; static int systemd_send_watchdog(struct thread *t) { diff --git a/lib/vrf.c b/lib/vrf.c index 2411cc3111..6ca6482e08 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -67,7 +67,7 @@ static char vrf_default_name[VRF_NAMSIZ] = VRF_DEFAULT_NAME_INTERNAL; static int debug_vrf = 0; /* Holding VRF hooks */ -struct vrf_master { +static struct vrf_master { int (*vrf_new_hook)(struct vrf *); int (*vrf_delete_hook)(struct vrf *); int (*vrf_enable_hook)(struct vrf *); @@ -752,7 +752,7 @@ DEFUN (no_vrf, } -struct cmd_node vrf_node = {VRF_NODE, "%s(config-vrf)# ", 1}; +static struct cmd_node vrf_node = {VRF_NODE, "%s(config-vrf)# ", 1}; DEFUN_NOSH (vrf_netns, vrf_netns_cmd, diff --git a/lib/vty.c b/lib/vty.c index c08e5e151a..40da8abcd7 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -89,7 +89,7 @@ static char *vty_ipv6_accesslist_name = NULL; static vector Vvty_serv_thread; /* Current directory. */ -char vty_cwd[MAXPATHLEN]; +static char vty_cwd[MAXPATHLEN]; /* Login password check. */ static int no_password_check = 0; diff --git a/lib/yang.c b/lib/yang.c index d153f75530..78ea7d0dd0 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -87,7 +87,7 @@ static inline int yang_module_compare(const struct yang_module *a, } RB_GENERATE(yang_modules, yang_module, entry, yang_module_compare) -struct yang_modules yang_modules = RB_INITIALIZER(&yang_modules); +static struct yang_modules yang_modules = RB_INITIALIZER(&yang_modules); struct yang_module *yang_module_load(const char *module_name) { diff --git a/lib/yang.h b/lib/yang.h index 6892e36019..ae3e782029 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -114,9 +114,6 @@ typedef int (*yang_iterate_cb)(const struct lys_node *snode, void *arg); /* Global libyang context for native FRR models. */ extern struct ly_ctx *ly_native_ctx; -/* Tree of all loaded YANG modules. */ -extern struct yang_modules yang_modules; - /* * Create a new YANG module and load it using libyang. If the YANG module is not * found in the YANG_MODELS_PATH directory, the program will exit with an error. From 25d86233403523c3c03ecc5bc1450c6da37fc6cc Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 27 Nov 2019 21:43:27 +0100 Subject: [PATCH 5/8] lib/prefix: flip the bitrot compost Signed-off-by: David Lamparter --- lib/prefix.c | 492 ++++----------------------------------------------- lib/prefix.h | 7 - 2 files changed, 35 insertions(+), 464 deletions(-) diff --git a/lib/prefix.c b/lib/prefix.c index e2bf3b949c..219f798dcc 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -37,394 +37,6 @@ DEFINE_MTYPE_STATIC(LIB, PREFIX_FLOWSPEC, "Prefix Flowspec") static const uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; -static const struct in6_addr maskbytes6[] = { - /* /0 */ {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /1 */ - {{{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /2 */ - {{{0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /3 */ - {{{0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /4 */ - {{{0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /5 */ - {{{0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /6 */ - {{{0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /7 */ - {{{0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /8 */ - {{{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /9 */ - {{{0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /10 */ - {{{0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /11 */ - {{{0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /12 */ - {{{0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /13 */ - {{{0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /14 */ - {{{0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /15 */ - {{{0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /16 */ - {{{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /17 */ - {{{0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /18 */ - {{{0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /19 */ - {{{0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /20 */ - {{{0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /21 */ - {{{0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /22 */ - {{{0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /23 */ - {{{0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /24 */ - {{{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /25 */ - {{{0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /26 */ - {{{0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /27 */ - {{{0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /28 */ - {{{0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /29 */ - {{{0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /30 */ - {{{0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /31 */ - {{{0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /32 */ - {{{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /33 */ - {{{0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /34 */ - {{{0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /35 */ - {{{0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /36 */ - {{{0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /37 */ - {{{0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /38 */ - {{{0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /39 */ - {{{0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /40 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /41 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /42 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /43 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /44 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /45 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /46 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /47 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /48 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /49 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /50 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /51 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /52 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /53 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /54 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /55 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /56 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /57 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /58 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /59 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /60 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /61 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /62 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /63 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /64 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /65 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /66 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /67 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /68 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /69 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /70 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /71 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /72 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /73 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /74 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /75 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /76 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /77 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /78 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /79 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /80 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /81 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /82 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /83 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /84 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /85 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /86 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /87 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /88 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00}}}, - /* /89 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x00, 0x00, 0x00, 0x00}}}, - /* /90 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0x00, 0x00, 0x00, 0x00}}}, - /* /91 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xe0, 0x00, 0x00, 0x00, 0x00}}}, - /* /92 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x00, 0x00, 0x00, 0x00}}}, - /* /93 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf8, 0x00, 0x00, 0x00, 0x00}}}, - /* /94 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0x00, 0x00, 0x00, 0x00}}}, - /* /95 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0x00, 0x00, 0x00, 0x00}}}, - /* /96 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00}}}, - /* /97 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0x00, 0x00, 0x00}}}, - /* /98 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0x00, 0x00, 0x00}}}, - /* /99 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x00, 0x00, 0x00}}}, - /* /100 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x00, 0x00, 0x00}}}, - /* /101 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf8, 0x00, 0x00, 0x00}}}, - /* /102 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfc, 0x00, 0x00, 0x00}}}, - /* /103 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x00, 0x00, 0x00}}}, - /* /104 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00}}}, - /* /105 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x80, 0x00, 0x00}}}, - /* /106 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xc0, 0x00, 0x00}}}, - /* /107 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xe0, 0x00, 0x00}}}, - /* /108 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf0, 0x00, 0x00}}}, - /* /109 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf8, 0x00, 0x00}}}, - /* /110 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x00, 0x00}}}, - /* /111 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0x00, 0x00}}}, - /* /112 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x00, 0x00}}}, - /* /113 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x00}}}, - /* /114 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xc0, 0x00}}}, - /* /115 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x00}}}, - /* /116 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00}}}, - /* /117 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x00}}}, - /* /118 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x00}}}, - /* /119 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x00}}}, - /* /120 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x00}}}, - /* /121 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x80}}}, - /* /122 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xc0}}}, - /* /123 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xe0}}}, - /* /124 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf0}}}, - /* /125 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf8}}}, - /* /126 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc}}}, - /* /127 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe}}}, - /* /128 */ - {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff}}}}; - /* Number of bits in prefix type. */ #ifndef PNBBY #define PNBBY 8 @@ -432,15 +44,6 @@ static const struct in6_addr maskbytes6[] = { #define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff) -void prefix_hexdump(const struct prefix *p) -{ - char buf[PREFIX_STRLEN]; - - zlog_debug("prefix: %s", - prefix2str(p, buf, sizeof(buf))); - zlog_hexdump(p, sizeof(struct prefix)); -} - int is_zero_mac(const struct ethaddr *mac) { int i = 0; @@ -461,11 +64,6 @@ unsigned int prefix_bit(const uint8_t *prefix, const uint16_t prefixlen) return (prefix[offset] >> shift) & 1; } -unsigned int prefix6_bit(const struct in6_addr *prefix, const uint16_t prefixlen) -{ - return prefix_bit((const uint8_t *)&prefix->s6_addr, prefixlen); -} - int str2family(const char *string) { if (!strcmp("ipv4", string)) @@ -1121,31 +719,46 @@ int str2prefix_ipv6(const char *str, struct prefix_ipv6 *p) * FIXME return uint8_t as ip_maskleni() does. */ int ip6_masklen(struct in6_addr netmask) { - int len = 0; - unsigned char val; - unsigned char *pnt; - - pnt = (unsigned char *)&netmask; - - while ((*pnt == 0xff) && len < IPV6_MAX_BITLEN) { - len += 8; - pnt++; - } - - if (len < IPV6_MAX_BITLEN) { - val = *pnt; - while (val) { - len++; - val <<= 1; - } - } - return len; + if (netmask.s6_addr32[0] != 0xffffffffU) + return __builtin_clz(~ntohl(netmask.s6_addr32[0])); + if (netmask.s6_addr32[1] != 0xffffffffU) + return __builtin_clz(~ntohl(netmask.s6_addr32[1])) + 32; + if (netmask.s6_addr32[2] != 0xffffffffU) + return __builtin_clz(~ntohl(netmask.s6_addr32[2])) + 64; + if (netmask.s6_addr32[3] != 0xffffffffU) + return __builtin_clz(~ntohl(netmask.s6_addr32[3])) + 96; + /* note __builtin_clz(0) is undefined */ + return 128; } void masklen2ip6(const int masklen, struct in6_addr *netmask) { assert(masklen >= 0 && masklen <= IPV6_MAX_BITLEN); - memcpy(netmask, maskbytes6 + masklen, sizeof(struct in6_addr)); + + if (masklen == 0) { + /* note << 32 is undefined */ + memset(netmask, 0, sizeof(*netmask)); + } else if (masklen <= 32) { + netmask->s6_addr32[0] = htonl(0xffffffffU << (32 - masklen)); + netmask->s6_addr32[1] = 0; + netmask->s6_addr32[2] = 0; + netmask->s6_addr32[3] = 0; + } else if (masklen <= 64) { + netmask->s6_addr32[0] = 0xffffffffU; + netmask->s6_addr32[1] = htonl(0xffffffffU << (64 - masklen)); + netmask->s6_addr32[2] = 0; + netmask->s6_addr32[3] = 0; + } else if (masklen <= 96) { + netmask->s6_addr32[0] = 0xffffffffU; + netmask->s6_addr32[1] = 0xffffffffU; + netmask->s6_addr32[2] = htonl(0xffffffffU << (96 - masklen)); + netmask->s6_addr32[3] = 0; + } else { + netmask->s6_addr32[0] = 0xffffffffU; + netmask->s6_addr32[1] = 0xffffffffU; + netmask->s6_addr32[2] = 0xffffffffU; + netmask->s6_addr32[3] = htonl(0xffffffffU << (128 - masklen)); + } } void apply_mask_ipv6(struct prefix_ipv6 *p) @@ -1183,33 +796,6 @@ void apply_mask(struct prefix *p) return; } -/* Utility function of convert between struct prefix <=> union sockunion. - * FIXME This function isn't used anywhere. */ -struct prefix *sockunion2prefix(const union sockunion *dest, - const union sockunion *mask) -{ - if (dest->sa.sa_family == AF_INET) { - struct prefix_ipv4 *p; - - p = prefix_ipv4_new(); - p->family = AF_INET; - p->prefix = dest->sin.sin_addr; - p->prefixlen = ip_masklen(mask->sin.sin_addr); - return (struct prefix *)p; - } - if (dest->sa.sa_family == AF_INET6) { - struct prefix_ipv6 *p; - - p = prefix_ipv6_new(); - p->family = AF_INET6; - p->prefixlen = ip6_masklen(mask->sin6.sin6_addr); - memcpy(&p->prefix, &dest->sin6.sin6_addr, - sizeof(struct in6_addr)); - return (struct prefix *)p; - } - return NULL; -} - /* Utility function of convert between struct prefix <=> union sockunion. */ struct prefix *sockunion2hostprefix(const union sockunion *su, struct prefix *prefix) @@ -1521,14 +1107,6 @@ void apply_classful_mask_ipv4(struct prefix_ipv4 *p) } } -in_addr_t ipv4_network_addr(in_addr_t hostaddr, int masklen) -{ - struct in_addr mask; - - masklen2ip(masklen, &mask); - return hostaddr & mask.s_addr; -} - in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen) { struct in_addr mask; diff --git a/lib/prefix.h b/lib/prefix.h index 7a93c766a3..667627ddfe 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -392,8 +392,6 @@ extern const char *afi2str(afi_t afi); /* Check bit of the prefix. */ extern unsigned int prefix_bit(const uint8_t *prefix, const uint16_t prefixlen); -extern unsigned int prefix6_bit(const struct in6_addr *prefix, - const uint16_t prefixlen); extern struct prefix *prefix_new(void); extern void prefix_free(struct prefix **p); @@ -430,8 +428,6 @@ extern void apply_mask(struct prefix *); #define prefix_copy(a, b) ({ memset(a, 0, sizeof(*a)); prefix_copy(a, b); }) #endif -extern struct prefix *sockunion2prefix(const union sockunion *dest, - const union sockunion *mask); extern struct prefix *sockunion2hostprefix(const union sockunion *, struct prefix *p); extern void prefix2sockunion(const struct prefix *, union sockunion *); @@ -453,8 +449,6 @@ extern void apply_classful_mask_ipv4(struct prefix_ipv4 *); extern uint8_t ip_masklen(struct in_addr); extern void masklen2ip(const int, struct in_addr *); -/* returns the network portion of the host address */ -extern in_addr_t ipv4_network_addr(in_addr_t hostaddr, int masklen); /* given the address of a host on a network and the network mask length, * calculate the broadcast address for that network; * special treatment for /31: returns the address of the other host @@ -484,7 +478,6 @@ extern unsigned prefix_hash_key(const void *pp); extern int str_to_esi(const char *str, esi_t *esi); extern char *esi_to_str(const esi_t *esi, char *buf, int size); -extern void prefix_hexdump(const struct prefix *p); extern void prefix_evpn_hexdump(const struct prefix_evpn *p); static inline int ipv6_martian(struct in6_addr *addr) From eb51bb9b1fa2fbb339c583cb5b479246b0821dcc Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 27 Nov 2019 21:49:00 +0100 Subject: [PATCH 6/8] lib: random unused bits cleanup Signed-off-by: David Lamparter --- lib/buffer.c | 6 ------ lib/filter.c | 8 ++++---- lib/grammar_sandbox.c | 13 +++++++------ lib/sockopt.c | 15 --------------- lib/sockopt.h | 1 - lib/systemd.c | 2 +- lib/systemd.h | 1 - 7 files changed, 12 insertions(+), 34 deletions(-) diff --git a/lib/buffer.c b/lib/buffer.c index bb2cdb7e54..766b9791a5 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -114,12 +114,6 @@ char *buffer_getstr(struct buffer *b) return s; } -/* Return 1 if buffer is empty. */ -int buffer_empty(struct buffer *b) -{ - return (b->head == NULL); -} - /* Clear and free all allocated data. */ void buffer_reset(struct buffer *b) { diff --git a/lib/filter.c b/lib/filter.c index ed3ffe9c67..31e25d6001 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -2498,8 +2498,8 @@ DEFUN (no_ipv6_access_list_remark_comment, return no_ipv6_access_list_remark(self, vty, argc, argv); } -void config_write_access_zebra(struct vty *, struct filter *); -void config_write_access_cisco(struct vty *, struct filter *); +static void config_write_access_zebra(struct vty *, struct filter *); +static void config_write_access_cisco(struct vty *, struct filter *); /* show access-list command. */ static int filter_show(struct vty *vty, const char *name, afi_t afi) @@ -2685,7 +2685,7 @@ DEFUN (show_ipv6_access_list_name, return filter_show(vty, argv[idx_word]->arg, AFI_IP6); } -void config_write_access_cisco(struct vty *vty, struct filter *mfilter) +static void config_write_access_cisco(struct vty *vty, struct filter *mfilter) { struct filter_cisco *filter; @@ -2724,7 +2724,7 @@ void config_write_access_cisco(struct vty *vty, struct filter *mfilter) } } -void config_write_access_zebra(struct vty *vty, struct filter *mfilter) +static void config_write_access_zebra(struct vty *vty, struct filter *mfilter) { struct filter_zebra *filter; struct prefix *p; diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index a23874a517..8ccdbfcbc1 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -38,9 +38,9 @@ DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command desc") /** headers **/ void grammar_sandbox_init(void); -void pretty_print_graph(struct vty *vty, struct graph_node *, int, int, - struct graph_node **, size_t); -void init_cmdgraph(struct vty *, struct graph **); +static void pretty_print_graph(struct vty *vty, struct graph_node *, int, int, + struct graph_node **, size_t); +static void init_cmdgraph(struct vty *, struct graph **); /** shim interface commands **/ static struct graph *nodegraph = NULL, *nodegraph_free = NULL; @@ -491,8 +491,9 @@ void grammar_sandbox_init(void) * @param start the node to take as the root * @param level indent level for recursive calls, always pass 0 */ -void pretty_print_graph(struct vty *vty, struct graph_node *start, int level, - int desc, struct graph_node **stack, size_t stackpos) +static void pretty_print_graph(struct vty *vty, struct graph_node *start, + int level, int desc, struct graph_node **stack, + size_t stackpos) { // print this node char tokennum[32]; @@ -550,7 +551,7 @@ void pretty_print_graph(struct vty *vty, struct graph_node *start, int level, } /** stuff that should go in command.c + command.h */ -void init_cmdgraph(struct vty *vty, struct graph **graph) +static void init_cmdgraph(struct vty *vty, struct graph **graph) { // initialize graph, add start noe *graph = graph_new(); diff --git a/lib/sockopt.c b/lib/sockopt.c index 7726d74ff7..3b12d16cbc 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -121,21 +121,6 @@ int setsockopt_ipv6_pktinfo(int sock, int val) return ret; } -/* Set multicast hops val to the socket. */ -int setsockopt_ipv6_checksum(int sock, int val) -{ - int ret; - -#ifdef GNU_LINUX - ret = setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val)); -#else - ret = setsockopt(sock, IPPROTO_IPV6, IPV6_CHECKSUM, &val, sizeof(val)); -#endif /* GNU_LINUX */ - if (ret < 0) - flog_err(EC_LIB_SOCKET, "can't setsockopt IPV6_CHECKSUM"); - return ret; -} - /* Set multicast hops val to the socket. */ int setsockopt_ipv6_multicast_hops(int sock, int val) { diff --git a/lib/sockopt.h b/lib/sockopt.h index f6b57b8e07..59d8a65964 100644 --- a/lib/sockopt.h +++ b/lib/sockopt.h @@ -33,7 +33,6 @@ extern int getsockopt_so_sendbuf(const int sock); extern int getsockopt_so_recvbuf(const int sock); extern int setsockopt_ipv6_pktinfo(int, int); -extern int setsockopt_ipv6_checksum(int, int); extern int setsockopt_ipv6_multicast_hops(int, int); extern int setsockopt_ipv6_unicast_hops(int, int); extern int setsockopt_ipv6_hoplimit(int, int); diff --git a/lib/systemd.c b/lib/systemd.c index 16fbbff380..81b0400ab9 100644 --- a/lib/systemd.c +++ b/lib/systemd.c @@ -32,7 +32,7 @@ * Wrapper this silliness if we * don't have systemd */ -void systemd_send_information(const char *info) +static void systemd_send_information(const char *info) { #if defined HAVE_SYSTEMD sd_notify(0, info); diff --git a/lib/systemd.h b/lib/systemd.h index 1f730720ce..d9885c5d9c 100644 --- a/lib/systemd.h +++ b/lib/systemd.h @@ -32,7 +32,6 @@ extern "C" { * To turn on systemd compilation, use --enable-systemd on * configure run. */ -void systemd_send_information(const char *info); void systemd_send_stopping(void); /* From 45e69fa8f7bfdada1eb545c6ae4641c55333d144 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 27 Nov 2019 22:52:50 +0100 Subject: [PATCH 7/8] lib/linklist: flip the bitrot compost The whole lib/linklist.c code shouldn't really be used for new code (the lib/typesafe.h bits are better.) So, a new need for these unused functions shouldn't be coming up. Signed-off-by: David Lamparter --- lib/linklist.c | 23 ----------------------- lib/linklist.h | 24 ------------------------ 2 files changed, 47 deletions(-) diff --git a/lib/linklist.c b/lib/linklist.c index 0d1efdf3aa..272e153276 100644 --- a/lib/linklist.c +++ b/lib/linklist.c @@ -339,29 +339,6 @@ void list_delete_node(struct list *list, struct listnode *node) listnode_free(node); } -void list_add_list(struct list *list, struct list *add) -{ - struct listnode *n; - - for (n = listhead(add); n; n = listnextnode(n)) - listnode_add(list, n->data); -} - -struct list *list_dup(struct list *list) -{ - struct list *new = list_new(); - struct listnode *ln; - void *data; - - new->cmp = list->cmp; - new->del = list->del; - - for (ALL_LIST_ELEMENTS_RO(list, ln, data)) - listnode_add(new, data); - - return new; -} - void list_sort(struct list *list, int (*cmp)(const void **, const void **)) { struct listnode *ln, *nn; diff --git a/lib/linklist.h b/lib/linklist.h index ef914b965f..00cb9f8714 100644 --- a/lib/linklist.h +++ b/lib/linklist.h @@ -207,17 +207,6 @@ extern struct listnode *listnode_lookup(struct list *list, const void *data); */ extern void *listnode_head(struct list *list); -/* - * Duplicate a list. - * - * list - * list to duplicate - * - * Returns: - * copy of the list - */ -extern struct list *list_dup(struct list *l); - /* * Sort a list in place. * @@ -295,19 +284,6 @@ extern void list_delete_all_node(struct list *list); */ extern void list_delete_node(struct list *list, struct listnode *node); -/* - * Append a list to an existing list. - * - * Runtime is O(N) where N = listcount(add). - * - * list - * list to append to - * - * add - * list to append - */ -extern void list_add_list(struct list *list, struct list *add); - /* * Delete all nodes which satisfy a condition from a list. * Deletes the node if cond function returns true for the node. From ba7eb55ec661e18156d9d390b196b6659d0a4752 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 27 Nov 2019 23:19:10 +0100 Subject: [PATCH 8/8] tools: symalyzer Signed-off-by: David Lamparter --- .gitignore | 4 + tools/symalyzer.html | 347 +++++++++++++++++++++++++++++++++++++++ tools/symalyzer.py | 383 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 734 insertions(+) create mode 100644 tools/symalyzer.html create mode 100755 tools/symalyzer.py diff --git a/.gitignore b/.gitignore index 6cfe23e921..226dca09d0 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,10 @@ /Makefile /Makefile.in +/symalyzer_report.html +/jquery-3.4.1.min.js +/jquery-3.4.1.min.js.tmp + ### autoconf/automake subdir stuff .deps diff --git a/tools/symalyzer.html b/tools/symalyzer.html new file mode 100644 index 0000000000..eefeee3b05 --- /dev/null +++ b/tools/symalyzer.html @@ -0,0 +1,347 @@ + + + + Symalyzer report + + + + + + + + + +
+
    +
  • S means the symbol is not used outside its own file. + It could either be completely unused or used locally. It might be appropriate to make it + static.
  • +
  • Z means the symbol is not used outside its own file, + and it's not visible to the outside of the library or daemon (i.e. ELF hidden linkage.) + It could still be completely unused, or used within the library. It might be appropriate to make it + static.
  • +
  • L means the symbol is used from other files in the library, + but not from outside. It might be appropriate to make it DSO_LOCAL.
  • +
  • A means the symbol is used from some other file, most likely a + loadable module. Note this is only flagged for symbols in executable files, not libraries.
  • +
+
    +
  • T are normal functions ("program Text")
  • +
  • + B (BSS),
    + C (Common),
    + D (Data)
    + are various types of writable global variables
  • +
  • R are read-only global variables ("Rodata")
  • +
+
+
+ {%- for subdir, subreport in dirgroups.items()|sort %} +
{{ subdir }}
+ {%- for obj, reports in subreport.items()|sort %} +
{{ obj }}
+ {%- for report in reports|sort %} + {#-
#} +
{{ report.idshort }}
+
{{ report.sym.klass }}
+
{{ report.sym.name }}
+ {% if report.sym.loc %} +
{{ report.sym.loc }}
+ {% else %} +
unknown
+ {% endif %} + {#- #} + {%- endfor %} + {%- endfor %} + {%- endfor %} +
+ + diff --git a/tools/symalyzer.py b/tools/symalyzer.py new file mode 100755 index 0000000000..b3b5c4e567 --- /dev/null +++ b/tools/symalyzer.py @@ -0,0 +1,383 @@ +#!/usr/bin/python3 +# +# 2019 by David Lamparter, placed in public domain +# +# This tool generates a report of possibly unused symbols in the build. It's +# particularly useful for libfrr to find bitrotting functions that aren't even +# used anywhere anymore. +# +# Note that the tool can't distinguish between "a symbol is completely unused" +# and "a symbol is used only in its file" since file-internal references are +# invisible in nm output. However, the compiler will warn you if a static +# symbol is unused. +# +# This tool is only tested on Linux, it probably needs `nm` from GNU binutils +# (as opposed to BSD `nm`). Could use pyelftools instead but that's a lot of +# extra work. +# +# This is a developer tool, please don't put it in any packages :) + +import sys, os, subprocess +import re +from collections import namedtuple + +class MakeVars(object): + ''' + makevars['FOO_CFLAGS'] gets you "FOO_CFLAGS" from Makefile + ''' + def __init__(self): + self._data = dict() + + def getvars(self, varlist): + ''' + get a batch list of variables from make. faster than individual calls. + ''' + rdfd, wrfd = os.pipe() + + shvars = ['shvar-%s' % s for s in varlist] + make = subprocess.Popen(['make', '-s', 'VARFD=%d' % wrfd] + shvars, pass_fds = [wrfd]) + os.close(wrfd) + data = b'' + + rdf = os.fdopen(rdfd, 'rb') + while True: + rdata = rdf.read() + if len(rdata) == 0: + break + data += rdata + + del rdf + make.wait() + + data = data.decode('US-ASCII').strip().split('\n') + for row in data: + k, v = row.split('=', 1) + v = v[1:-1] + self._data[k] = v + + def __getitem__(self, k): + if k not in self._data: + self.getvars([k]) + return self._data[k] + + def get(self, k, defval = None): + if k not in self._data: + self.getvars([k]) + return self._data[k] or defval + +SymRowBase = namedtuple('SymRow', ['target', 'object', 'name', 'address', 'klass', 'typ', 'size', 'line', 'section', 'loc']) +class SymRow(SymRowBase): + ''' + wrapper around a line of `nm` output + ''' + lib_re = re.compile(r'/lib[^/]+\.(so|la)$') + def is_global(self): + return self.klass.isupper() or self.klass in 'uvw' + def scope(self): + if self.lib_re.search(self.target) is None: + return self.target + # "global" + return None + + def is_export(self): + ''' + FRR-specific list of symbols which are considered "externally used" + + e.g. hooks are by design APIs for external use, same for qobj_t_* + frr_inet_ntop is here because it's used through an ELF alias to + "inet_ntop()" + ''' + if self.name in ['main', 'frr_inet_ntop', '_libfrr_version']: + return True + if self.name.startswith('_hook_'): + return True + if self.name.startswith('qobj_t_'): + return True + return False + +class Symbols(dict): + ''' + dict of all symbols in all libs & executables + ''' + + from_re = re.compile(r'^Symbols from (.*?):$') + lt_re = re.compile(r'^(.*/)([^/]+)\.l[oa]$') + + def __init__(self): + super().__init__() + + class ReportSym(object): + def __init__(self, sym): + self.sym = sym + def __repr__(self): + return '<%-25s %-40s [%s]>' % (self.__class__.__name__ + ':', self.sym.name, self.sym.loc) + def __lt__(self, other): + return self.sym.name.__lt__(other.sym.name) + + class ReportSymCouldBeStaticAlreadyLocal(ReportSym): + idshort = 'Z' + idlong = 'extrastatic' + title = "symbol is local to library, but only used in its source file (make static?)" + class ReportSymCouldBeStatic(ReportSym): + idshort = 'S' + idlong = 'static' + title = "symbol is only used in its source file (make static?)" + class ReportSymCouldBeLibLocal(ReportSym): + idshort = 'L' + idlong = 'liblocal' + title = "symbol is only used inside of library" + class ReportSymModuleAPI(ReportSym): + idshort = 'A' + idlong = 'api' + title = "symbol (in executable) is referenced externally from a module" + + class Symbol(object): + def __init__(self, name): + super().__init__() + self.name = name + self.defs = {} + self.refs = [] + + def process(self, row): + scope = row.scope() + if row.section == '*UND*': + self.refs.append(row) + else: + self.defs.setdefault(scope, []).append(row) + + def evaluate(self, out): + ''' + generate output report + + invoked after all object files have been read in, so it can look + at inter-object-file relationships + ''' + if len(self.defs) == 0: + out.extsyms.add(self.name) + return + + for scopename, symdefs in self.defs.items(): + common_defs = [symdef for symdef in symdefs if symdef.section == '*COM*'] + proper_defs = [symdef for symdef in symdefs if symdef.section != '*COM*'] + + if len(proper_defs) > 1: + print(self.name, ' DUPLICATE') + print('\tD: %s %s' % (scopename, '\n\t\t'.join([repr(s) for s in symdefs]))) + for syms in self.refs: + print('\tR: %s' % (syms, )) + return + + if len(proper_defs): + primary_def = proper_defs[0] + elif len(common_defs): + # "common" = global variables without initializer; + # they can occur in multiple .o files and the linker will + # merge them into one variable/storage location. + primary_def = common_defs[0] + else: + # undefined symbol, e.g. libc + continue + + if scopename is not None and len(self.refs) > 0: + for ref in self.refs: + if ref.target != primary_def.target and ref.target.endswith('.la'): + outobj = out.report.setdefault(primary_def.object, []) + outobj.append(out.ReportSymModuleAPI(primary_def)) + break + + if len(self.refs) == 0: + if primary_def.is_export(): + continue + outobj = out.report.setdefault(primary_def.object, []) + if primary_def.visible: + outobj.append(out.ReportSymCouldBeStatic(primary_def)) + else: + outobj.append(out.ReportSymCouldBeStaticAlreadyLocal(primary_def)) + continue + + if scopename is None and primary_def.visible: + # lib symbol + for ref in self.refs: + if ref.target != primary_def.target: + break + else: + outobj = out.report.setdefault(primary_def.object, []) + outobj.append(out.ReportSymCouldBeLibLocal(primary_def)) + + + def evaluate(self): + self.extsyms = set() + self.report = {} + + for sym in self.values(): + sym.evaluate(self) + + def load(self, target, files): + def libtoolmustdie(fn): + m = self.lt_re.match(fn) + if m is None: + return fn + return m.group(1) + '.libs/' + m.group(2) + '.o' + + def libtooltargetmustdie(fn): + m = self.lt_re.match(fn) + if m is None: + a, b = fn.rsplit('/', 1) + return '%s/.libs/%s' % (a, b) + return m.group(1) + '.libs/' + m.group(2) + '.so' + + files = list(set([libtoolmustdie(fn) for fn in files])) + + def parse_nm_output(text): + filename = None + path_rel_to = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + for line in text.split('\n'): + if line.strip() == '': + continue + m = self.from_re.match(line) + if m is not None: + filename = m.group(1) + continue + if line.startswith('Name'): + continue + + items = [i.strip() for i in line.split('|')] + loc = None + if '\t' in items[-1]: + items[-1], loc = items[-1].split('\t', 1) + fn, lno = loc.rsplit(':', 1) + fn = os.path.relpath(fn, path_rel_to) + loc = '%s:%s' % (fn, lno) + + items[1] = int(items[1] if items[1] != '' else '0', 16) + items[4] = int(items[4] if items[4] != '' else '0', 16) + items.append(loc) + row = SymRow(target, filename, *items) + + if row.section == '.group' or row.name == '_GLOBAL_OFFSET_TABLE_': + continue + if not row.is_global(): + continue + + yield row + + visible_syms = set() + + # the actual symbol report uses output from the individual object files + # (e.g. lib/.libs/foo.o), but we also read the linked binary (e.g. + # lib/.libs/libfrr.so) to determine which symbols are actually visible + # in the linked result (this covers ELF "hidden"/"internal" linkage) + + libfile = libtooltargetmustdie(target) + nmlib = subprocess.Popen(['nm', '-l', '-g', '--defined-only', '-f', 'sysv', libfile], stdout = subprocess.PIPE) + out = nmlib.communicate()[0].decode('US-ASCII') + + for row in parse_nm_output(out): + visible_syms.add(row.name) + + nm = subprocess.Popen(['nm', '-l', '-f', 'sysv'] + files, stdout = subprocess.PIPE) + out = nm.communicate()[0].decode('US-ASCII') + + for row in parse_nm_output(out): + row.visible = row.name in visible_syms + sym = self.setdefault(row.name, self.Symbol(row.name)) + sym.process(row) + + +def write_html_report(syms): + try: + import jinja2 + except ImportError: + sys.stderr.write('jinja2 could not be imported, not writing HTML report!\n') + return + + self_path = os.path.dirname(os.path.abspath(__file__)) + jenv = jinja2.Environment(loader=jinja2.FileSystemLoader(self_path)) + template = jenv.get_template('symalyzer.html') + + dirgroups = {} + for fn, reports in syms.report.items(): + dirname, filename = fn.replace('.libs/', '').rsplit('/', 1) + dirgroups.setdefault(dirname, {})[fn] = reports + + klasses = { + 'T': 'code / plain old regular function (Text)', + 'D': 'global variable, read-write, with nonzero initializer (Data)', + 'B': 'global variable, read-write, with zero initializer (BSS)', + 'C': 'global variable, read-write, with zero initializer (Common)', + 'R': 'global variable, read-only (Rodata)', + } + + with open('symalyzer_report.html.tmp', 'w') as fd: + fd.write(template.render(dirgroups = dirgroups, klasses = klasses)) + os.rename('symalyzer_report.html.tmp', 'symalyzer_report.html') + + if not os.path.exists('jquery-3.4.1.min.js'): + url = 'https://code.jquery.com/jquery-3.4.1.min.js' + sys.stderr.write( + 'trying to grab a copy of jquery from %s\nif this fails, please get it manually (the HTML output is done.)\n' % (url)) + import requests + r = requests.get('https://code.jquery.com/jquery-3.4.1.min.js') + if r.status_code != 200: + sys.stderr.write('failed -- please download jquery-3.4.1.min.js and put it next to the HTML report\n') + else: + with open('jquery-3.4.1.min.js.tmp', 'w') as fd: + fd.write(r.text) + os.rename('jquery-3.4.1.min.js.tmp', 'jquery-3.4.1.min.js.tmp') + sys.stderr.write('done.\n') + +def automake_escape(s): + return s.replace('.', '_').replace('/', '_') + +if __name__ == '__main__': + mv = MakeVars() + + if not (os.path.exists('config.version') and os.path.exists('lib/.libs/libfrr.so')): + sys.stderr.write('please execute this script in the root directory of an FRR build tree\n') + sys.stderr.write('./configure && make need to have completed successfully\n') + sys.exit(1) + + amtargets = ['bin_PROGRAMS', 'sbin_PROGRAMS', 'lib_LTLIBRARIES', 'module_LTLIBRARIES'] + targets = [] + + mv.getvars(amtargets) + for amtarget in amtargets: + targets.extend([item for item in mv[amtarget].strip().split() if item != 'tools/ssd']) + + mv.getvars(['%s_LDADD' % automake_escape(t) for t in targets]) + ldobjs = targets[:] + for t in targets: + ldadd = mv['%s_LDADD' % automake_escape(t)].strip().split() + for item in ldadd: + if item.startswith('-'): + continue + if item.endswith('.a'): + ldobjs.append(item) + + mv.getvars(['%s_OBJECTS' % automake_escape(o) for o in ldobjs]) + + syms = Symbols() + + for t in targets: + objs = mv['%s_OBJECTS' % automake_escape(t)].strip().split() + ldadd = mv['%s_LDADD' % automake_escape(t)].strip().split() + for item in ldadd: + if item.startswith('-'): + continue + if item.endswith('.a'): + objs.extend(mv['%s_OBJECTS' % automake_escape(item)].strip().split()) + + sys.stderr.write('processing %s...\n' % t) + sys.stderr.flush() + #print(t, '\n\t', objs) + syms.load(t, objs) + + syms.evaluate() + + for obj, reports in sorted(syms.report.items()): + print('%s:' % obj) + for report in reports: + print('\t%r' % report) + + write_html_report(syms)