Merge pull request #5535 from opensourcerouting/santa-elf

*: cleanup elves were here
This commit is contained in:
Donald Sharp 2019-12-16 07:42:47 -05:00 committed by GitHub
commit 04dd9e420e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 813 additions and 590 deletions

4
.gitignore vendored
View File

@ -33,6 +33,10 @@
/Makefile /Makefile
/Makefile.in /Makefile.in
/symalyzer_report.html
/jquery-3.4.1.min.js
/jquery-3.4.1.min.js.tmp
### autoconf/automake subdir stuff ### autoconf/automake subdir stuff
.deps .deps

View File

@ -199,14 +199,6 @@ bgpd_bgp_btoa_SOURCES = bgpd/bgp_btoa.c
bgpd_bgpd_CFLAGS = $(AM_CFLAGS) bgpd_bgpd_CFLAGS = $(AM_CFLAGS)
bgpd_bgp_btoa_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 # RFPLDADD is set in bgpd/rfp-example/librfp/subdir.am
bgpd_bgpd_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la $(LIBCAP) $(LIBM) 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) bgpd_bgp_btoa_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la $(LIBCAP) $(LIBM)

View File

@ -41,7 +41,7 @@ static void agg_node_destroy(route_table_delegate_t *delegate,
XFREE(MTYPE_TMP, anode); XFREE(MTYPE_TMP, anode);
} }
route_table_delegate_t agg_table_delegate = { static route_table_delegate_t agg_table_delegate = {
.create_node = agg_node_create, .create_node = agg_node_create,
.destroy_node = agg_node_destroy, .destroy_node = agg_node_destroy,
}; };

View File

@ -114,12 +114,6 @@ char *buffer_getstr(struct buffer *b)
return s; return s;
} }
/* Return 1 if buffer is empty. */
int buffer_empty(struct buffer *b)
{
return (b->head == NULL);
}
/* Clear and free all allocated data. */ /* Clear and free all allocated data. */
void buffer_reset(struct buffer *b) void buffer_reset(struct buffer *b)
{ {

View File

@ -85,7 +85,7 @@ RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\)
. {return yytext[0];} . {return yytext[0];}
%% %%
YY_BUFFER_STATE buffer; static YY_BUFFER_STATE buffer;
void set_lexer_string (yyscan_t *scn, const char *string) void set_lexer_string (yyscan_t *scn, const char *string)
{ {

View File

@ -2498,8 +2498,8 @@ DEFUN (no_ipv6_access_list_remark_comment,
return no_ipv6_access_list_remark(self, vty, argc, argv); return no_ipv6_access_list_remark(self, vty, argc, argv);
} }
void config_write_access_zebra(struct vty *, struct filter *); static void config_write_access_zebra(struct vty *, struct filter *);
void config_write_access_cisco(struct vty *, struct filter *); static void config_write_access_cisco(struct vty *, struct filter *);
/* show access-list command. */ /* show access-list command. */
static int filter_show(struct vty *vty, const char *name, afi_t afi) 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); 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; 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 filter_zebra *filter;
struct prefix *p; struct prefix *p;

View File

@ -206,7 +206,7 @@ void rcu_thread_unprepare(struct rcu_thread *rt)
rcu_bump(); rcu_bump();
if (rt != &rcu_thread_main) if (rt != &rcu_thread_main)
/* this free() happens after seqlock_release() below */ /* 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); rcu_threads_del(&rcu_threads, rt);
seqlock_release(&rt->rcu); 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 * "last item is being deleted - start over" case, and then we may end
* up accessing old RCU queue items that are already free'd. * 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. /* Only allow the RCU sweeper to run after these 2 items are queued.
* *

View File

@ -139,6 +139,8 @@ extern void rcu_enqueue(struct rcu_head *head, const struct rcu_action *action);
#define rcu_free(mtype, ptr, field) \ #define rcu_free(mtype, ptr, field) \
do { \ do { \
typeof(ptr) _ptr = (ptr); \ typeof(ptr) _ptr = (ptr); \
if (!_ptr) \
break; \
struct rcu_head *_rcu_head = &_ptr->field; \ struct rcu_head *_rcu_head = &_ptr->field; \
static const struct rcu_action _rcu_action = { \ static const struct rcu_action _rcu_action = { \
.type = RCUA_FREE, \ .type = RCUA_FREE, \

View File

@ -38,9 +38,9 @@ DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command desc")
/** headers **/ /** headers **/
void grammar_sandbox_init(void); void grammar_sandbox_init(void);
void pretty_print_graph(struct vty *vty, struct graph_node *, int, int, static void pretty_print_graph(struct vty *vty, struct graph_node *, int, int,
struct graph_node **, size_t); struct graph_node **, size_t);
void init_cmdgraph(struct vty *, struct graph **); static void init_cmdgraph(struct vty *, struct graph **);
/** shim interface commands **/ /** shim interface commands **/
static struct graph *nodegraph = NULL, *nodegraph_free = NULL; 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 start the node to take as the root
* @param level indent level for recursive calls, always pass 0 * @param level indent level for recursive calls, always pass 0
*/ */
void pretty_print_graph(struct vty *vty, struct graph_node *start, int level, static void pretty_print_graph(struct vty *vty, struct graph_node *start,
int desc, struct graph_node **stack, size_t stackpos) int level, int desc, struct graph_node **stack,
size_t stackpos)
{ {
// print this node // print this node
char tokennum[32]; 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 */ /** 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 // initialize graph, add start noe
*graph = graph_new(); *graph = graph_new();

View File

@ -58,7 +58,7 @@ DEFINE_QOBJ_TYPE(interface)
DEFINE_HOOK(if_add, (struct interface * ifp), (ifp)) DEFINE_HOOK(if_add, (struct interface * ifp), (ifp))
DEFINE_KOOH(if_del, (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 (*create_hook)(struct interface *ifp);
int (*up_hook)(struct interface *ifp); int (*up_hook)(struct interface *ifp);
int (*down_hook)(struct interface *ifp); int (*down_hook)(struct interface *ifp);

View File

@ -339,29 +339,6 @@ void list_delete_node(struct list *list, struct listnode *node)
listnode_free(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 **)) void list_sort(struct list *list, int (*cmp)(const void **, const void **))
{ {
struct listnode *ln, *nn; struct listnode *ln, *nn;

View File

@ -207,17 +207,6 @@ extern struct listnode *listnode_lookup(struct list *list, const void *data);
*/ */
extern void *listnode_head(struct list *list); 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. * 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); 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. * Delete all nodes which satisfy a condition from a list.
* Deletes the node if cond function returns true for the node. * Deletes the node if cond function returns true for the node.

View File

@ -102,45 +102,42 @@ struct memgroup {
} }
#define DECLARE_MTYPE(name) \ #define DECLARE_MTYPE(name) \
extern struct memtype _mt_##name; \ extern struct memtype MTYPE_##name[1]; \
extern struct memtype *const MTYPE_##name; \
/* end */ /* end */
#define DEFINE_MTYPE_ATTR(group, mname, attr, desc) \ #define DEFINE_MTYPE_ATTR(group, mname, attr, desc) \
attr struct memtype _mt_##mname \ attr struct memtype MTYPE_##mname[1] \
__attribute__((section(".data.mtypes"))) = { \ __attribute__((section(".data.mtypes"))) = { { \
.name = desc, \ .name = desc, \
.next = NULL, \ .next = NULL, \
.n_alloc = 0, \ .n_alloc = 0, \
.size = 0, \ .size = 0, \
.ref = NULL, \ .ref = NULL, \
}; \ } }; \
static void _mtinit_##mname(void) __attribute__((_CONSTRUCTOR(1001))); \ static void _mtinit_##mname(void) __attribute__((_CONSTRUCTOR(1001))); \
static void _mtinit_##mname(void) \ static void _mtinit_##mname(void) \
{ \ { \
if (_mg_##group.insert == NULL) \ if (_mg_##group.insert == NULL) \
_mg_##group.insert = &_mg_##group.types; \ _mg_##group.insert = &_mg_##group.types; \
_mt_##mname.ref = _mg_##group.insert; \ MTYPE_##mname->ref = _mg_##group.insert; \
*_mg_##group.insert = &_mt_##mname; \ *_mg_##group.insert = MTYPE_##mname; \
_mg_##group.insert = &_mt_##mname.next; \ _mg_##group.insert = &MTYPE_##mname->next; \
} \ } \
static void _mtfini_##mname(void) __attribute__((_DESTRUCTOR(1001))); \ static void _mtfini_##mname(void) __attribute__((_DESTRUCTOR(1001))); \
static void _mtfini_##mname(void) \ static void _mtfini_##mname(void) \
{ \ { \
if (_mt_##mname.next) \ if (MTYPE_##mname->next) \
_mt_##mname.next->ref = _mt_##mname.ref; \ MTYPE_##mname->next->ref = MTYPE_##mname->ref; \
*_mt_##mname.ref = _mt_##mname.next; \ *MTYPE_##mname->ref = MTYPE_##mname->next; \
} \ } \
/* end */ /* end */
#define DEFINE_MTYPE(group, name, desc) \ #define DEFINE_MTYPE(group, name, desc) \
DEFINE_MTYPE_ATTR(group, name, , desc) \ DEFINE_MTYPE_ATTR(group, name, , desc) \
struct memtype *const MTYPE_##name = &_mt_##name; \
/* end */ /* end */
#define DEFINE_MTYPE_STATIC(group, name, desc) \ #define DEFINE_MTYPE_STATIC(group, name, desc) \
DEFINE_MTYPE_ATTR(group, name, static, desc) \ DEFINE_MTYPE_ATTR(group, name, static, desc) \
static struct memtype *const MTYPE_##name = &_mt_##name; \
/* end */ /* end */
DECLARE_MGROUP(LIB) DECLARE_MGROUP(LIB)

View File

@ -51,7 +51,7 @@ static struct ns *ns_lookup_name_internal(const char *name);
RB_GENERATE(ns_head, ns, entry, ns_compare) 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 struct ns *default_ns;
static int ns_current_ns_fd; 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_HEAD(ns_map_nsid_head, ns_map_nsid);
RB_PROTOTYPE(ns_map_nsid_head, ns_map_nsid, id_entry, ns_map_compare); 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); 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; static ns_id_t ns_id_external_numbering;
@ -123,7 +124,7 @@ static int have_netns(void)
} }
/* Holding NS hooks */ /* Holding NS hooks */
struct ns_master { static struct ns_master {
int (*ns_new_hook)(struct ns *ns); int (*ns_new_hook)(struct ns *ns);
int (*ns_delete_hook)(struct ns *ns); int (*ns_delete_hook)(struct ns *ns);
int (*ns_enable_hook)(struct ns *ns); int (*ns_enable_hook)(struct ns *ns);

View File

@ -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) 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) static inline int ns_compare(const struct ns *a, const struct ns *b)
{ {

View File

@ -797,7 +797,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
struct cmd_node nexthop_group_node = { static struct cmd_node nexthop_group_node = {
NH_GROUP_NODE, NH_GROUP_NODE,
"%s(config-nh-group)# ", "%s(config-nh-group)# ",
1 1

View File

@ -71,8 +71,6 @@ struct ns {
RB_HEAD(ns_head, ns); RB_HEAD(ns_head, ns);
RB_PROTOTYPE(ns_head, ns, entry, ns_compare) RB_PROTOTYPE(ns_head, ns, entry, ns_compare)
extern struct ns_head ns_tree;
/* /*
* API for managing NETNS. eg from zebra daemon * API for managing NETNS. eg from zebra daemon
* one want to manage the list of NETNS, etc... * one want to manage the list of NETNS, etc...

View File

@ -37,394 +37,6 @@ DEFINE_MTYPE_STATIC(LIB, PREFIX_FLOWSPEC, "Prefix Flowspec")
static const uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, static const uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
0xf8, 0xfc, 0xfe, 0xff}; 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. */ /* Number of bits in prefix type. */
#ifndef PNBBY #ifndef PNBBY
#define PNBBY 8 #define PNBBY 8
@ -432,15 +44,6 @@ static const struct in6_addr maskbytes6[] = {
#define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff) #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 is_zero_mac(const struct ethaddr *mac)
{ {
int i = 0; int i = 0;
@ -461,11 +64,6 @@ unsigned int prefix_bit(const uint8_t *prefix, const uint16_t prefixlen)
return (prefix[offset] >> shift) & 1; 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) int str2family(const char *string)
{ {
if (!strcmp("ipv4", 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. */ * FIXME return uint8_t as ip_maskleni() does. */
int ip6_masklen(struct in6_addr netmask) int ip6_masklen(struct in6_addr netmask)
{ {
int len = 0; if (netmask.s6_addr32[0] != 0xffffffffU)
unsigned char val; return __builtin_clz(~ntohl(netmask.s6_addr32[0]));
unsigned char *pnt; if (netmask.s6_addr32[1] != 0xffffffffU)
return __builtin_clz(~ntohl(netmask.s6_addr32[1])) + 32;
pnt = (unsigned char *)&netmask; if (netmask.s6_addr32[2] != 0xffffffffU)
return __builtin_clz(~ntohl(netmask.s6_addr32[2])) + 64;
while ((*pnt == 0xff) && len < IPV6_MAX_BITLEN) { if (netmask.s6_addr32[3] != 0xffffffffU)
len += 8; return __builtin_clz(~ntohl(netmask.s6_addr32[3])) + 96;
pnt++; /* note __builtin_clz(0) is undefined */
} return 128;
if (len < IPV6_MAX_BITLEN) {
val = *pnt;
while (val) {
len++;
val <<= 1;
}
}
return len;
} }
void masklen2ip6(const int masklen, struct in6_addr *netmask) void masklen2ip6(const int masklen, struct in6_addr *netmask)
{ {
assert(masklen >= 0 && masklen <= IPV6_MAX_BITLEN); 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) void apply_mask_ipv6(struct prefix_ipv6 *p)
@ -1183,33 +796,6 @@ void apply_mask(struct prefix *p)
return; 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. */ /* Utility function of convert between struct prefix <=> union sockunion. */
struct prefix *sockunion2hostprefix(const union sockunion *su, struct prefix *sockunion2hostprefix(const union sockunion *su,
struct prefix *prefix) 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) in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen)
{ {
struct in_addr mask; struct in_addr mask;

View File

@ -392,8 +392,6 @@ extern const char *afi2str(afi_t afi);
/* Check bit of the prefix. */ /* Check bit of the prefix. */
extern unsigned int prefix_bit(const uint8_t *prefix, const uint16_t prefixlen); 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 struct prefix *prefix_new(void);
extern void prefix_free(struct prefix **p); 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); }) #define prefix_copy(a, b) ({ memset(a, 0, sizeof(*a)); prefix_copy(a, b); })
#endif #endif
extern struct prefix *sockunion2prefix(const union sockunion *dest,
const union sockunion *mask);
extern struct prefix *sockunion2hostprefix(const union sockunion *, extern struct prefix *sockunion2hostprefix(const union sockunion *,
struct prefix *p); struct prefix *p);
extern void prefix2sockunion(const struct prefix *, union sockunion *); 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 uint8_t ip_masklen(struct in_addr);
extern void masklen2ip(const int, 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, /* given the address of a host on a network and the network mask length,
* calculate the broadcast address for that network; * calculate the broadcast address for that network;
* special treatment for /31: returns the address of the other host * 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 int str_to_esi(const char *str, esi_t *esi);
extern char *esi_to_str(const esi_t *esi, char *buf, int size); 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); extern void prefix_evpn_hexdump(const struct prefix_evpn *p);
static inline int ipv6_martian(struct in6_addr *addr) static inline int ipv6_martian(struct in6_addr *addr)

View File

@ -221,7 +221,7 @@ struct route_map_match_set_hooks {
const char *command, const char *arg); 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 */ /* match interface */
void route_map_match_interface_hook(int (*func)( void route_map_match_interface_hook(int (*func)(
@ -623,7 +623,7 @@ struct route_map_list {
/* Master list of route map. */ /* Master list of route map. */
static struct route_map_list route_map_master = {NULL, NULL, NULL, NULL, NULL}; 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) 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 */ /* 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 unsigned int route_map_dep_hash_make_key(const void *p);
static void route_map_clear_all_references(char *rmap_name); static void route_map_clear_all_references(char *rmap_name);

View File

@ -121,21 +121,6 @@ int setsockopt_ipv6_pktinfo(int sock, int val)
return ret; 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. */ /* Set multicast hops val to the socket. */
int setsockopt_ipv6_multicast_hops(int sock, int val) int setsockopt_ipv6_multicast_hops(int sock, int val)
{ {

View File

@ -33,7 +33,6 @@ extern int getsockopt_so_sendbuf(const int sock);
extern int getsockopt_so_recvbuf(const int sock); extern int getsockopt_so_recvbuf(const int sock);
extern int setsockopt_ipv6_pktinfo(int, int); 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_multicast_hops(int, int);
extern int setsockopt_ipv6_unicast_hops(int, int); extern int setsockopt_ipv6_unicast_hops(int, int);
extern int setsockopt_ipv6_hoplimit(int, int); extern int setsockopt_ipv6_hoplimit(int, int);

View File

@ -32,7 +32,7 @@
* Wrapper this silliness if we * Wrapper this silliness if we
* don't have systemd * don't have systemd
*/ */
void systemd_send_information(const char *info) static void systemd_send_information(const char *info)
{ {
#if defined HAVE_SYSTEMD #if defined HAVE_SYSTEMD
sd_notify(0, info); sd_notify(0, info);
@ -93,8 +93,8 @@ void systemd_send_stopping(void)
/* /*
* How many seconds should we wait between watchdog sends * How many seconds should we wait between watchdog sends
*/ */
int wsecs = 0; static int wsecs = 0;
struct thread_master *systemd_master = NULL; static struct thread_master *systemd_master = NULL;
static int systemd_send_watchdog(struct thread *t) static int systemd_send_watchdog(struct thread *t)
{ {

View File

@ -32,7 +32,6 @@ extern "C" {
* To turn on systemd compilation, use --enable-systemd on * To turn on systemd compilation, use --enable-systemd on
* configure run. * configure run.
*/ */
void systemd_send_information(const char *info);
void systemd_send_stopping(void); void systemd_send_stopping(void);
/* /*

View File

@ -67,7 +67,7 @@ static char vrf_default_name[VRF_NAMSIZ] = VRF_DEFAULT_NAME_INTERNAL;
static int debug_vrf = 0; static int debug_vrf = 0;
/* Holding VRF hooks */ /* Holding VRF hooks */
struct vrf_master { static struct vrf_master {
int (*vrf_new_hook)(struct vrf *); int (*vrf_new_hook)(struct vrf *);
int (*vrf_delete_hook)(struct vrf *); int (*vrf_delete_hook)(struct vrf *);
int (*vrf_enable_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, DEFUN_NOSH (vrf_netns,
vrf_netns_cmd, vrf_netns_cmd,

View File

@ -89,7 +89,7 @@ static char *vty_ipv6_accesslist_name = NULL;
static vector Vvty_serv_thread; static vector Vvty_serv_thread;
/* Current directory. */ /* Current directory. */
char vty_cwd[MAXPATHLEN]; static char vty_cwd[MAXPATHLEN];
/* Login password check. */ /* Login password check. */
static int no_password_check = 0; static int no_password_check = 0;

View File

@ -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) 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) struct yang_module *yang_module_load(const char *module_name)
{ {

View File

@ -114,9 +114,6 @@ typedef int (*yang_iterate_cb)(const struct lys_node *snode, void *arg);
/* Global libyang context for native FRR models. */ /* Global libyang context for native FRR models. */
extern struct ly_ctx *ly_native_ctx; 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 * 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. * found in the YANG_MODELS_PATH directory, the program will exit with an error.

347
tools/symalyzer.html Normal file
View File

@ -0,0 +1,347 @@
<html>
<!--
- 2019 by David Lamparter, placed in public domain
-->
<head>
<title>Symalyzer report</title>
<style type="text/css">
html {
margin:auto;
max-width:70em;
font-family:Fira Sans, sans-serif;
}
dl {
display:grid;
grid-template-columns: 1.4em 1.4em 1fr 1fr;
grid-auto-rows: auto;
}
dt.dir {
background-color:#ff8;
color:#000;
border:1px solid #000;
border-bottom:2px solid #000;
font-size:14pt;
padding:2pt 15pt;
margin:0pt;
margin-top:10pt;
grid-column:1 / -1;
}
dt.file {
background-color:#ffa;
color:#000;
border-bottom:1px solid #000;
font-size:12pt;
padding:2pt 15pt;
margin:5pt 0pt;
grid-column:1 / -1;
}
dt.file.filehidden {
background-color:#ffc;
font-size:10pt;
padding:0.5pt 15pt;
margin-bottom:-5pt;
}
dd {
display:inline-block;
vertical-align:middle;
margin:0;
}
dd.symtype {
grid-column:1;
border:1px solid #666;
text-align:center;
}
dd.symklass {
grid-column:2;
border:1px solid #666;
text-align:center;
}
dd.symname {
grid-column:3;
font-family:monospace;
padding:0 0.5em;
padding-top:2px;
border-bottom:1px dashed #ccc;
}
dd.symloc {
grid-column:4;
padding:0 0.5em;
border-bottom:1px dashed #ccc;
}
.symloc-unknown {
font-style:italic;
color:#aaa;
}
.symtype.sym-static {
background-color:#cf4;
color:#000;
}
.symtype.sym-extrastatic {
background-color:#fe8;
color:#000;
}
.symtype.sym-liblocal {
background-color:#fc6;
color:#000;
}
.symklass.symk-T {
background-color:#ddd;
color:#000;
}
.symklass.symk-B,
.symklass.symk-C,
.symklass.symk-D {
background-color:#faa;
color:#000;
}
.symklass.symk-R {
background-color:#fd8;
color:#000;
}
.symtype.sym-api {
background-color:#d9f;
color:#000;
}
.symname.sym-api,
.symloc.sym-api {
background-color:#f8e8ff;
}
dt.file.dirhidden,
dd.dirhidden {
display:none;
}
dd.filehidden {
display:none;
}
dd.symhidden {
display:none;
}
ul {
font-size:10pt;
}
li {
margin-bottom:6pt;
text-indent:-2.5em;
margin-left:2.5em;
}
code {
background-color:#eee;
color:#060;
text-decoration:underline;
}
b.symtype,
b.symklass {
display:inline-block;
text-align:center;
border:1px solid #666;
width:1.4em;
text-indent:0;
}
</style>
<script src="jquery-3.4.1.min.js"></script>
<script>
function dirtoggle(elem, visible) {
if (visible) {
elem.removeClass("dirhidden");
} else {
elem.addClass("dirhidden");
}
var next = elem.next();
while (next.is("dd") || next.is("dt.file")) {
if (visible) {
next.removeClass("dirhidden");
} else {
next.addClass("dirhidden");
}
next = next.next();
}
}
function filetoggle(elem, visible) {
if (visible) {
elem.removeClass("filehidden");
} else {
elem.addClass("filehidden");
}
var next = elem.next();
while (next.is("dd")) {
if (visible) {
next.removeClass("filehidden");
} else {
next.addClass("filehidden");
}
next = next.next();
}
}
function symtoggle(elem, visible) {
if (visible) {
elem.removeClass("symhidden");
} else {
elem.addClass("symhidden");
}
var next = elem.next();
while (next.is(".symklass") || next.is(".symname") || next.is(".symloc")) {
if (visible) {
next.removeClass("symhidden");
} else {
next.addClass("symhidden");
}
next = next.next();
}
}
$(document).ready(function(){
$("dt.dir").each(function(){
var elem = $(this);
elem.click(function(){
dirtoggle(elem, elem.is(".dirhidden"));
});
dirtoggle(elem, false);
});
$("dt.file").each(function(){
var elem = $(this);
elem.click(function(){
filetoggle(elem, elem.is(".filehidden"));
});
/* filetoggle(elem, false); */
});
$("#f_hide_all").click(function(){
$("dt.file").each(function(){
filetoggle($(this), false);
});
});
$("#f_show_all").click(function(){
$("dt.file").each(function(){
filetoggle($(this), true);
});
});
$("#s_show_all").click(function(){
$("dd.symtype").each(function(){
symtoggle($(this), true);
});
});
$("#s_hide_all").click(function(){
$("dd.symtype").each(function(){
symtoggle($(this), false);
});
});
$("#s_show_vars").click(function(){
$("dd.symtype").each(function(){
var elem_type = $(this);
if (elem_type.text() === "A") {
return;
}
var elem_klass = elem_type.next();
if ("BbCDdGgnRrSs".indexOf(elem_klass.text()) >= 0) {
symtoggle(elem_type, true);
}
});
});
$("#s_show_funcs").click(function(){
$("dd.symtype").each(function(){
var elem_type = $(this);
if (elem_type.text() === "A") {
return;
}
var elem_klass = elem_type.next();
if ("Tt".indexOf(elem_klass.text()) >= 0) {
symtoggle(elem_type, true);
}
});
});
$("#s_show_api").click(function(){
$("dd.sym-api").each(function(){
symtoggle($(this), true);
});
});
$("#jsbuttons").show();
});
</script>
</head>
<body>
<table style="display:none" id="jsbuttons">
<tr><td>Files</td><td>
<button type="button" id="f_hide_all">Hide all</button>
<button type="button" id="f_show_all">Show all</button>
</td></tr>
<tr><td>Symbols</td><td>
<button type="button" id="s_hide_all">Hide all</button>
<button type="button" id="s_show_all">Show all</button><br>
<button type="button" id="s_show_vars">Show variables</button>
<button type="button" id="s_show_funcs">Show functions</button>
<button type="button" id="s_show_api">Show module/API usage</button>
</td></tr>
</table>
<div style="display:grid;grid-template-columns:1fr 1fr;">
<ul>
<li><b class="symtype sym-static">S</b> 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
<code>static</code>.</li>
<li><b class="symtype sym-extrastatic">Z</b> 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
<code>static</code>.</li>
<li><b class="symtype sym-liblocal">L</b> means the symbol is used from other files in the library,
but not from outside. It might be appropriate to make it <code>DSO_LOCAL</code>.</li>
<li><b class="symtype sym-api">A</b> 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.</li>
</ul>
<ul>
<li><b class="symklass symk-T">T</b> are normal functions ("program <u>T</u>ext")</li>
<li style="text-indent:0;margin-left:0">
<b class="symklass symk-B">B</b> (<u>B</u>SS),<br>
<b class="symklass symk-C">C</b> (<u>C</u>ommon),<br>
<b class="symklass symk-D">D</b> (<u>D</u>ata)<br>
are various types of writable global variables</li>
<li><b class="symklass symk-R">R</b> are read-only global variables ("<u>R</u>odata")</li>
</ul>
</div>
<dl>
{%- for subdir, subreport in dirgroups.items()|sort %}
<dt class="dir">{{ subdir }}</dt>
{%- for obj, reports in subreport.items()|sort %}
<dt class="file">{{ obj }}</dt>
{%- for report in reports|sort %}
{#- <dd class="{{ report.idlong }}"> #}
<dd class="sym-{{ report.idlong }} symtype" title="{{ report.title }}">{{ report.idshort }}</dd>
<dd class="sym-{{ report.idlong }} symk-{{ report.sym.klass }} symklass" title="{{ klasses.get(report.sym.klass, '???') }}">{{ report.sym.klass }}</dd>
<dd class="sym-{{ report.idlong }} symname">{{ report.sym.name }}</dd>
{% if report.sym.loc %}
<dd class="sym-{{ report.idlong }} symloc">{{ report.sym.loc }}</dd>
{% else %}
<dd class="sym-{{ report.idlong }} symloc symloc-unknown">unknown</dd>
{% endif %}
{#- </dd> #}
{%- endfor %}
{%- endfor %}
{%- endfor %}
</dl>
</body>
</html>

383
tools/symalyzer.py Executable file
View File

@ -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)