From 2d362d1099f346202cb628665ff4ae563b2594f5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 21 Dec 2009 12:54:58 +0300 Subject: lib: make some structures constant * isisd/isis_pdu.c * maskbit: this pre-initialized array is not modified * lib/prefix.c * maskbit: idem * lib/command.c * facility_map: idem * itoa64: idem * default_motd: make local var static * facility_name(): update local var accordingly * facility_match(): idem --- lib/command.c | 10 +++++----- lib/prefix.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/command.c b/lib/command.c index 31c067a3..478125f2 100644 --- a/lib/command.c +++ b/lib/command.c @@ -82,14 +82,14 @@ static struct cmd_node config_node = }; /* Default motd string. */ -const char *default_motd = +static const char *default_motd = "\r\n\ Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\ " QUAGGA_COPYRIGHT "\r\n\ \r\n"; -static struct facility_map { +static const struct facility_map { int facility; const char *name; size_t match; @@ -122,7 +122,7 @@ static struct facility_map { static const char * facility_name(int facility) { - struct facility_map *fm; + const struct facility_map *fm; for (fm = syslog_facilities; fm->name; fm++) if (fm->facility == facility) @@ -133,7 +133,7 @@ facility_name(int facility) static int facility_match(const char *str) { - struct facility_map *fm; + const struct facility_map *fm; for (fm = syslog_facilities; fm->name; fm++) if (!strncmp(str,fm->name,fm->match)) @@ -506,7 +506,7 @@ install_element (enum node_type ntype, struct cmd_element *cmd) cmd->cmdsize = cmd_cmdsize (cmd->strvec); } -static unsigned char itoa64[] = +static const unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; static void diff --git a/lib/prefix.c b/lib/prefix.c index 2afaa09c..c85e6594 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -29,7 +29,7 @@ #include "log.h" /* Maskbit. */ -static u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, +static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; /* Number of bits in prefix type. */ -- cgit v1.2.3 From 0917f7e7c5920b70295c44bd8aad537bc3ee8581 Mon Sep 17 00:00:00 2001 From: David Ward Date: Wed, 13 Jan 2010 20:10:56 +0300 Subject: lib: fix memory logging * lib/memory.h * mtype_zcalloc(): correct function prototype * XFREE(): make both definitions consistent in setting the pointer to NULL after freeing the memory These changes will only have an effect if MEMORY_LOG is defined (it is not by default). --- lib/memory.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/memory.h b/lib/memory.h index 42eb5cae..a7eddce4 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -46,7 +46,10 @@ extern struct mlist mlists[]; #define XREALLOC(mtype, ptr, size) \ mtype_zrealloc (__FILE__, __LINE__, (mtype), (ptr), (size)) #define XFREE(mtype, ptr) \ - mtype_zfree (__FILE__, __LINE__, (mtype), (ptr)) + do { \ + mtype_zfree (__FILE__, __LINE__, (mtype), (ptr)); \ + ptr = NULL; } \ + while (0) #define XSTRDUP(mtype, str) \ mtype_zstrdup (__FILE__, __LINE__, (mtype), (str)) #else @@ -69,8 +72,7 @@ extern char *zstrdup (int type, const char *str); extern void *mtype_zmalloc (const char *file, int line, int type, size_t size); -extern void *mtype_zcalloc (const char *file, int line, int type, - size_t num, size_t size); +extern void *mtype_zcalloc (const char *file, int line, int type, size_t size); extern void *mtype_zrealloc (const char *file, int line, int type, void *ptr, size_t size); -- cgit v1.2.3 From 3f3dc2bd5f8cbde24cb581ed0aed0e372bfd556c Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 20 Jan 2010 17:39:13 +0300 Subject: lib: fix PIE build flags Because the final executables are built as position independent executables (PIE) -- when configure has detected compiler supported for PIE -- the objects in the library archive must be built in that way, too. Otherwise the runtime linker has to do unneccesary relocation for each start of the program. Even worse, the programs won't even be able to start on a (hardened) kernel that doesn't allow those relocations to happen by preventing making the .text segment writable (PaX's MPROTECT feature comes to mind). The attached patch fixes this issue by adding the appropriate flags to the Makefile.am. --- lib/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/Makefile.am b/lib/Makefile.am index 315e919b..6264878e 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -14,6 +14,9 @@ libzebra_la_SOURCES = \ zclient.c sockopt.c smux.c md5.c if_rmap.c keychain.c privs.c \ sigevent.c pqueue.c jhash.c memtypes.c workqueue.c +AM_CFLAGS = $(PICFLAGS) +AM_LDFLAGS = $(PILDFLAGS) + BUILT_SOURCES = memtypes.h route_types.h libzebra_la_DEPENDENCIES = @LIB_REGEX@ -- cgit v1.2.3 From dca6c883ea6219460efbe3dadde4b8b9cb12c845 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 27 Jan 2010 12:38:16 +0300 Subject: lib: undo the last PIE commit Stephen: A recent change breaks build Quagga on Debian Lenny with amd64 (but not i386). Not sure whether this is cause by ld, gcc, or libtool; but whatever it just won't work for a large number of users. Mathias: I would guess it's a problem of libtool because it adds "-fPIC -DPIC" to the compiler flags but doesn't remove -fPIE. That wouldn't be a problem if the compiler would ignore the -fPIE in favor to the latter -fPIC, but obviously it does not. [...] Those objects were actually compiled with -fPIC but also -fPIE which seems to confuse gcc. --- lib/Makefile.am | 3 --- 1 file changed, 3 deletions(-) (limited to 'lib') diff --git a/lib/Makefile.am b/lib/Makefile.am index 6264878e..315e919b 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -14,9 +14,6 @@ libzebra_la_SOURCES = \ zclient.c sockopt.c smux.c md5.c if_rmap.c keychain.c privs.c \ sigevent.c pqueue.c jhash.c memtypes.c workqueue.c -AM_CFLAGS = $(PICFLAGS) -AM_LDFLAGS = $(PILDFLAGS) - BUILT_SOURCES = memtypes.h route_types.h libzebra_la_DEPENDENCIES = @LIB_REGEX@ -- cgit v1.2.3 From b16793870794919ecc34138bdc51703cc3f409ca Mon Sep 17 00:00:00 2001 From: Greg Troxel Date: Fri, 17 Sep 2010 12:19:13 -0400 Subject: Document rules for zalloc and friends. lib/memory.c:z{a,c,re}alloc, zfree, zdup: add requires/effects comments. --- lib/memory.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/memory.c b/lib/memory.c index dc09d8a6..4bac31db 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -58,7 +58,11 @@ zerror (const char *fname, int type, size_t size) abort(); } -/* Memory allocation. */ +/* + * Allocate memory of a given size, to be tracked by a given type. + * Effects: Returns a pointer to usable memory. If memory cannot + * be allocated, aborts execution. + */ void * zmalloc (int type, size_t size) { @@ -74,7 +78,9 @@ zmalloc (int type, size_t size) return memory; } -/* Memory allocation with num * size with cleared. */ +/* + * Allocate memory as in zmalloc, and also clear the memory. + */ void * zcalloc (int type, size_t size) { @@ -90,7 +96,13 @@ zcalloc (int type, size_t size) return memory; } -/* Memory reallocation. */ +/* + * Given a pointer returned by zmalloc or zcalloc, free it and + * return a pointer to a new size, basically acting like realloc(). + * Requires: ptr was returned by zmalloc, zcalloc, or zrealloc with the + * same type. + * Effects: Returns a pointer to the new memory, or aborts. + */ void * zrealloc (int type, void *ptr, size_t size) { @@ -102,7 +114,12 @@ zrealloc (int type, void *ptr, size_t size) return memory; } -/* Memory free. */ +/* + * Free memory allocated by z*alloc or zstrdup. + * Requires: ptr was returned by zmalloc, zcalloc, or zrealloc with the + * same type. + * Effects: The memory is freed and may no longer be referenced. + */ void zfree (int type, void *ptr) { @@ -110,7 +127,12 @@ zfree (int type, void *ptr) free (ptr); } -/* String duplication. */ +/* + * Duplicate a string, counting memory usage by type. + * Effects: The string is duplicated, and the return value must + * eventually be passed to zfree with the same type. The function will + * succeed or abort. + */ char * zstrdup (int type, const char *str) { -- cgit v1.2.3 From b830c89a4532819a78c251c559566767b89ee5ac Mon Sep 17 00:00:00 2001 From: Nico Golde Date: Sun, 1 Aug 2010 15:24:35 +0200 Subject: lib/vty.c: add missing format string when printing out motd message Signed-off-by: G.Balaji --- lib/vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/vty.c b/lib/vty.c index e4818eb6..bd1dbac0 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -250,7 +250,7 @@ vty_hello (struct vty *vty) vty_out (vty, "MOTD file not found%s", VTY_NEWLINE); } else if (host.motd) - vty_out (vty, host.motd); + vty_out (vty, "%s", host.motd); } /* Put out prompt and wait input from user. */ -- cgit v1.2.3 From 4c9641ba4df276080c670e03f65b1d442660a50f Mon Sep 17 00:00:00 2001 From: Michael Lambert Date: Thu, 22 Jul 2010 13:20:55 -0400 Subject: bgpd, lib: adopt afi_t and safi_t in several places * bgpd/bgp_attr.c, bgpd/bgp_open.h, bgpd/bgp_route.c, lib/prefix.c, lib/prefix.h: Various integer types were being used where, if we had strict type checking, afi_t and safi_t would be required. Signed-off-by: G.Balaji (cherry picked from commit c8af35ffa2dc79ff7d7ff00b1b61f1f50a100ab6) --- lib/prefix.c | 4 ++-- lib/prefix.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/prefix.c b/lib/prefix.c index c85e6594..7dc866d1 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -41,7 +41,7 @@ static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, /* Address Famiy Identifier to Address Family converter. */ int -afi2family (int afi) +afi2family (afi_t afi) { if (afi == AFI_IP) return AF_INET; @@ -52,7 +52,7 @@ afi2family (int afi) return 0; } -int +afi_t family2afi (int family) { if (family == AF_INET) diff --git a/lib/prefix.h b/lib/prefix.h index a7598b7e..5f1ff05c 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -144,8 +144,8 @@ prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen) } /* Prototypes. */ -extern int afi2family (int); -extern int family2afi (int); +extern int afi2family (afi_t); +extern afi_t family2afi (int); extern struct prefix *prefix_new (void); extern void prefix_free (struct prefix *); -- cgit v1.2.3 From 08a7a91646a1ee317c402b421e3a7036a640bcf4 Mon Sep 17 00:00:00 2001 From: Dmitry Tejblum Date: Mon, 18 Oct 2010 19:05:39 +0400 Subject: zclient: fix router-id calculation for IPv6 (#595) If router-id is not specified in ospf6d.conf, ospf6d will get it from the zebra daemon. But ospf6d originates Link LSAs before the router-id is returned by zebra, thus this router's Link LSAs will be flooded with AdvRouter set to 0. * zclient.c: zclient_start(): send ZEBRA_INTERFACE_ADD message after ZEBRA_ROUTER_ID_ADD, not before --- lib/zclient.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/zclient.c b/lib/zclient.c index d3d53227..52a3627d 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -339,12 +339,12 @@ zclient_start (struct zclient *zclient) /* Create read thread. */ zclient_event (ZCLIENT_READ, zclient); - /* We need interface information. */ - zebra_message_send (zclient, ZEBRA_INTERFACE_ADD); - /* We need router-id information. */ zebra_message_send (zclient, ZEBRA_ROUTER_ID_ADD); + /* We need interface information. */ + zebra_message_send (zclient, ZEBRA_INTERFACE_ADD); + /* Flush all redistribute request. */ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) if (i != zclient->redist_default && zclient->redist[i]) -- cgit v1.2.3 From 8526100eebf9c56ff6fac2b80938b232bb687946 Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Mon, 11 Jan 2010 16:30:45 +0000 Subject: lib: thread history funcname shouldn't be constant, it's freed * thread.h: (struct cpu_thread_history.funcname) malloc gets called on this so it should not be const * thread.c: (cpu_record_print) cast the (const char *) to (char *), this function knows what it's doing (free wont be called on it). --- lib/thread.c | 2 +- lib/thread.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/thread.c b/lib/thread.c index e89af541..af52b057 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -303,7 +303,7 @@ cpu_record_print(struct vty *vty, thread_type filter) void *args[3] = {&tmp, vty, &filter}; memset(&tmp, 0, sizeof tmp); - tmp.funcname = "TOTAL"; + tmp.funcname = (char *)"TOTAL"; tmp.types = filter; #ifdef HAVE_RUSAGE diff --git a/lib/thread.h b/lib/thread.h index b52bc541..937bedbb 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -82,7 +82,7 @@ struct thread struct cpu_thread_history { int (*func)(struct thread *); - const char *funcname; + char *funcname; unsigned int total_calls; struct time_stats { -- cgit v1.2.3 From 2613abe64fe48761d798942af8dc0ec90c804b22 Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Mon, 11 Jan 2010 16:33:07 +0000 Subject: lib: Thread scheduler should be fair and not let events starve I/O and timers * thread.c: (thread_fetch) the current scheduler will service events indefinitely, ignoring I/O and timers, so long as there are events. In other words, events can crowd out I/O and timers. In theory this shouldn't be a huge problem as events are generated only by timers and I/O, however in practice it means normal-load behaviour is not as useful a predictor of high-load behaviour as it should be. Fix this by considering all the kinds of threads, in every run of the scheduler. For any given run, we prioritise events, however across runs the scheduler should be fair. This has been observed to give more stable inter-packet times in testing of ospfd (i.e. lower std-dev). (thread_process) new heler to queue all the given threads onto the ready list --- lib/thread.c | 57 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/thread.c b/lib/thread.c index af52b057..fb6fe375 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -903,6 +903,24 @@ thread_timer_process (struct thread_list *list, struct timeval *timenow) return ready; } +/* process a list en masse, e.g. for event thread lists */ +static unsigned int +thread_process (struct thread_list *list) +{ + struct thread *thread; + unsigned int ready = 0; + + for (thread = list->head; thread; thread = thread->next) + { + thread_list_delete (list, thread); + thread->type = THREAD_READY; + thread_list_add (&thread->master->ready, thread); + ready++; + } + return ready; +} + + /* Fetch next ready thread. */ struct thread * thread_fetch (struct thread_master *m, struct thread *fetch) @@ -911,41 +929,48 @@ thread_fetch (struct thread_master *m, struct thread *fetch) fd_set readfd; fd_set writefd; fd_set exceptfd; - struct timeval timer_val; + struct timeval timer_val = { .tv_sec = 0, .tv_usec = 0 }; struct timeval timer_val_bg; - struct timeval *timer_wait; + struct timeval *timer_wait = &timer_val; struct timeval *timer_wait_bg; while (1) { int num = 0; - /* Signals are highest priority */ + /* Signals pre-empt everything */ quagga_sigevent_process (); - /* Normal event are the next highest priority. */ - if ((thread = thread_trim_head (&m->event)) != NULL) - return thread_run (m, thread, fetch); - - /* If there are any ready threads from previous scheduler runs, - * process top of them. + /* Drain the ready queue of already scheduled jobs, before scheduling + * more. */ if ((thread = thread_trim_head (&m->ready)) != NULL) return thread_run (m, thread, fetch); + /* To be fair to all kinds of threads, and avoid starvation, we + * need to be careful to consider all thread types for scheduling + * in each quanta. I.e. we should not return early from here on. + */ + + /* Normal event are the next highest priority. */ + thread_process (&m->event); + /* Structure copy. */ readfd = m->readfd; writefd = m->writefd; exceptfd = m->exceptfd; /* Calculate select wait timer if nothing else to do */ - quagga_get_relative (NULL); - timer_wait = thread_timer_wait (&m->timer, &timer_val); - timer_wait_bg = thread_timer_wait (&m->background, &timer_val_bg); - - if (timer_wait_bg && - (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0))) - timer_wait = timer_wait_bg; + if (m->ready.count == 0) + { + quagga_get_relative (NULL); + timer_wait = thread_timer_wait (&m->timer, &timer_val); + timer_wait_bg = thread_timer_wait (&m->background, &timer_val_bg); + + if (timer_wait_bg && + (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0))) + timer_wait = timer_wait_bg; + } num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait); -- cgit v1.2.3 From e276eb82820eb92d221f183496e28da4ffe0fe68 Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Sat, 9 Jan 2010 16:15:00 +0000 Subject: lib: Add a command to clear the thread CPU history data * (general) this can be useful when investigating thread latency problems, when you don't want to have to restart a daemon between tests. * thread.c: (cpu_record_(hash_)clear) wipe the stored thread cpu history data, according to the filter, similar to the vty print code. (clear_thread_cpu_cmd) new command to clear data. * thread.h: export new command * command.c: install it --- lib/command.c | 2 ++ lib/thread.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/thread.h | 1 + 3 files changed, 86 insertions(+) (limited to 'lib') diff --git a/lib/command.c b/lib/command.c index 478125f2..5a13f39c 100644 --- a/lib/command.c +++ b/lib/command.c @@ -3650,6 +3650,8 @@ cmd_init (int terminal) install_element (VIEW_NODE, &show_thread_cpu_cmd); install_element (ENABLE_NODE, &show_thread_cpu_cmd); install_element (RESTRICTED_NODE, &show_thread_cpu_cmd); + + install_element (ENABLE_NODE, &clear_thread_cpu_cmd); install_element (VIEW_NODE, &show_work_queues_cmd); install_element (ENABLE_NODE, &show_work_queues_cmd); } diff --git a/lib/thread.c b/lib/thread.c index fb6fe375..fd841c21 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -382,6 +382,89 @@ DEFUN(show_thread_cpu, cpu_record_print(vty, filter); return CMD_SUCCESS; } + +static void +cpu_record_hash_clear (struct hash_backet *bucket, + void *args) +{ + thread_type *filter = args; + struct cpu_thread_history *a = bucket->data; + + a = bucket->data; + if ( !(a->types & *filter) ) + return; + + hash_release (cpu_record, bucket->data); +} + +static void +cpu_record_clear (thread_type filter) +{ + thread_type *tmp = &filter; + hash_iterate (cpu_record, + (void (*) (struct hash_backet*,void*)) cpu_record_hash_clear, + tmp); +} + +DEFUN(clear_thread_cpu, + clear_thread_cpu_cmd, + "clear thread cpu [FILTER]", + "Clear stored data\n" + "Thread information\n" + "Thread CPU usage\n" + "Display filter (rwtexb)\n") +{ + int i = 0; + thread_type filter = (thread_type) -1U; + + if (argc > 0) + { + filter = 0; + while (argv[0][i] != '\0') + { + switch ( argv[0][i] ) + { + case 'r': + case 'R': + filter |= (1 << THREAD_READ); + break; + case 'w': + case 'W': + filter |= (1 << THREAD_WRITE); + break; + case 't': + case 'T': + filter |= (1 << THREAD_TIMER); + break; + case 'e': + case 'E': + filter |= (1 << THREAD_EVENT); + break; + case 'x': + case 'X': + filter |= (1 << THREAD_EXECUTE); + break; + case 'b': + case 'B': + filter |= (1 << THREAD_BACKGROUND); + break; + default: + break; + } + ++i; + } + if (filter == 0) + { + vty_out(vty, "Invalid filter \"%s\" specified," + " must contain at least one of 'RWTEXB'%s", + argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + } + + cpu_record_clear (filter); + return CMD_SUCCESS; +} /* List allocation and head/tail print out. */ static void diff --git a/lib/thread.h b/lib/thread.h index 937bedbb..978aa6b0 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -197,6 +197,7 @@ extern int thread_should_yield (struct thread *); /* Internal libzebra exports */ extern void thread_getrusage (RUSAGE_T *); extern struct cmd_element show_thread_cpu_cmd; +extern struct cmd_element clear_thread_cpu_cmd; /* replacements for the system gettimeofday(), clock_gettime() and * time() functions, providing support for non-decrementing clock on -- cgit v1.2.3 From 3322055b392f20f4b97122a8034e479719e4b86d Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Mon, 11 Jan 2010 13:55:01 +0000 Subject: lib: Make workqueue more conservative about ramping up * workqueue.c: (work_queue_run) Err more on the side of keeping granularity down, by being more conservative about increasing it. Also, fix mispelling. --- lib/workqueue.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/workqueue.c b/lib/workqueue.c index 7c811edd..52b5f41c 100644 --- a/lib/workqueue.c +++ b/lib/workqueue.c @@ -341,7 +341,7 @@ work_queue_run (struct thread *thread) stats: -#define WQ_HYSTERIS_FACTOR 2 +#define WQ_HYSTERESIS_FACTOR 4 /* we yielded, check whether granularity should be reduced */ if (yielded && (cycles < wq->cycles.granularity)) @@ -349,17 +349,18 @@ stats: wq->cycles.granularity = ((cycles > 0) ? cycles : WORK_QUEUE_MIN_GRANULARITY); } - - if (cycles >= (wq->cycles.granularity)) + /* otherwise, should granularity increase? */ + else if (cycles >= (wq->cycles.granularity)) { if (cycles > wq->cycles.best) wq->cycles.best = cycles; - /* along with yielded check, provides hysteris for granularity */ - if (cycles > (wq->cycles.granularity * WQ_HYSTERIS_FACTOR * 2)) - wq->cycles.granularity *= WQ_HYSTERIS_FACTOR; /* quick ramp-up */ - else if (cycles > (wq->cycles.granularity * WQ_HYSTERIS_FACTOR)) - wq->cycles.granularity += WQ_HYSTERIS_FACTOR; + /* along with yielded check, provides hysteresis for granularity */ + if (cycles > (wq->cycles.granularity * WQ_HYSTERESIS_FACTOR + * WQ_HYSTERESIS_FACTOR)) + wq->cycles.granularity *= WQ_HYSTERESIS_FACTOR; /* quick ramp-up */ + else if (cycles > (wq->cycles.granularity * WQ_HYSTERESIS_FACTOR)) + wq->cycles.granularity += WQ_HYSTERESIS_FACTOR; } #undef WQ_HYSTERIS_FACTOR -- cgit v1.2.3 From d358344759d85a965bbd767f4a994695f99b842e Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Sun, 24 Jan 2010 21:41:02 +0000 Subject: lib: prefix.c nano-optimisation * lib/prefix.c: (prefix_match) nano-optimisation, let it return early without copying pointers. --- lib/prefix.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/prefix.c b/lib/prefix.c index 7dc866d1..61a278ca 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -70,15 +70,16 @@ prefix_match (const struct prefix *n, const struct prefix *p) { int offset; int shift; - - /* Set both prefix's head pointer. */ - const u_char *np = (const u_char *)&n->u.prefix; - const u_char *pp = (const u_char *)&p->u.prefix; + const u_char *np, *pp; /* If n's prefix is longer than p's one return 0. */ if (n->prefixlen > p->prefixlen) return 0; + /* Set both prefix's head pointer. */ + np = (const u_char *)&n->u.prefix; + pp = (const u_char *)&p->u.prefix; + offset = n->prefixlen / PNBBY; shift = n->prefixlen % PNBBY; -- cgit v1.2.3 From f8416810aad4cba6f622c6b3f9352abdd54cd01e Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Tue, 13 Apr 2010 22:42:33 +0100 Subject: lib: Fix bug in prefix trie lookup * lib/table.c: (route_node_match) fix overshoot that was causing this function to go 1 bit too far and thus reading past end of prefix. (route_node_lookup) be defensive - don't assume others will clean up leaves when removing info. --- lib/table.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/table.c b/lib/table.c index 04df3af5..e40e6707 100644 --- a/lib/table.c +++ b/lib/table.c @@ -209,6 +209,10 @@ route_node_match (const struct route_table *table, const struct prefix *p) { if (node->info) matched = node; + + if (node->p.prefixlen == p->prefixlen) + break; + node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)]; } @@ -260,8 +264,8 @@ route_node_lookup (struct route_table *table, struct prefix *p) while (node && node->p.prefixlen <= p->prefixlen && prefix_match (&node->p, p)) { - if (node->p.prefixlen == p->prefixlen && node->info) - return route_lock_node (node); + if (node->p.prefixlen == p->prefixlen) + return node->info ? route_lock_node (node) : NULL; node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)]; } @@ -283,10 +287,8 @@ route_node_get (struct route_table *table, struct prefix *p) prefix_match (&node->p, p)) { if (node->p.prefixlen == p->prefixlen) - { - route_lock_node (node); - return node; - } + return route_lock_node (node); + match = node; node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)]; } -- cgit v1.2.3 From cca85d27a59c31e1b20e4c4adc7d9bb57606e584 Mon Sep 17 00:00:00 2001 From: Chris Hall Date: Fri, 23 Jul 2010 11:27:11 -0700 Subject: lib: Fix accounting of memory * lib/memory.c: (zrealloc) If is called with NULL pointer then it should increment allocations because it behaves the same as zmalloc. (zfree) is called with NULL pointer, it does nothing therefore allocation count should not change. --- lib/memory.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/memory.c b/lib/memory.c index 4bac31db..4090fd90 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -111,6 +111,9 @@ zrealloc (int type, void *ptr, size_t size) memory = realloc (ptr, size); if (memory == NULL) zerror ("realloc", type, size); + if (ptr == NULL) + alloc_inc (type); + return memory; } @@ -123,8 +126,11 @@ zrealloc (int type, void *ptr, size_t size) void zfree (int type, void *ptr) { - alloc_dec (type); - free (ptr); + if (ptr != NULL) + { + alloc_dec (type); + free (ptr); + } } /* -- cgit v1.2.3 From 6c88b44dcb26b60bb1f93e5c387aa102019ed849 Mon Sep 17 00:00:00 2001 From: Chris Caputo Date: Tue, 27 Jul 2010 16:28:55 +0000 Subject: bgpd: fix bgp_node locking issues * bgpd: Connected table locks were being locked but not unlocked, such that eventually a lock would exceed 2^31 and become negative, thus triggering an assert later on. * bgp_main.c: (bgp_exit) delete connected elements along with ifp's. * bgp_nexthop.c: (bgp_nexthop_lookup{,_ipv6}) add missing unlocks (bgp_multiaccess_check_v4) ditto (bgp_connected_{add,delete}) Use a distinct memtype for bgp_connected_ref. (bgp_scan_finish) reset the nexthop cache to clean it up when bgpd exits * bgp_route.c: fix missing bgp_node unlocks * lib/memtype.c: (memory_list_bgp) add MTYPE_BGP_CONN * testing: has been tested for almost 2 months now. --- lib/memtypes.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/memtypes.c b/lib/memtypes.c index 05d93225..59020671 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -108,6 +108,7 @@ struct memory_list memory_list_bgp[] = { MTYPE_BGP_NODE, "BGP node" }, { MTYPE_BGP_ROUTE, "BGP route" }, { MTYPE_BGP_ROUTE_EXTRA, "BGP ancillary route info" }, + { MTYPE_BGP_CONN, "BGP connected" }, { MTYPE_BGP_STATIC, "BGP static" }, { MTYPE_BGP_ADVERTISE_ATTR, "BGP adv attr" }, { MTYPE_BGP_ADVERTISE, "BGP adv" }, -- cgit v1.2.3 From 6392aa83c4f895ebbd23817c68d9b0da0de2e0f8 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 27 Aug 2010 14:11:14 -0700 Subject: lib: Better hashing of string values using Bernstein hash * hash.{h,c}: (string_hash_make) Hash optimised for strings, current implementation using Bernstein hash, which offers a good compromise between distribution and performance. * distribute.c: (distribute_hash_make) use previous instead of additive string hash. * if_rmap.c: (if_rmap_hash_make) ditto --- lib/distribute.c | 13 ++++--------- lib/hash.c | 11 +++++++++++ lib/hash.h | 2 ++ lib/if_rmap.c | 9 ++------- 4 files changed, 19 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/distribute.c b/lib/distribute.c index 242a225c..420849da 100644 --- a/lib/distribute.c +++ b/lib/distribute.c @@ -114,16 +114,11 @@ distribute_get (const char *ifname) } static unsigned int -distribute_hash_make (struct distribute *dist) +distribute_hash_make (void *arg) { - unsigned int i, key; + const struct distribute *dist = arg; - key = 0; - if (dist->ifname) - for (i = 0; i < strlen (dist->ifname); i++) - key += dist->ifname[i]; - - return key; + return dist->ifname ? string_hash_make (dist->ifname) : 0; } /* If two distribute-list have same value then return 1 else return @@ -763,7 +758,7 @@ distribute_list_reset () void distribute_list_init (int node) { - disthash = hash_create ((unsigned int (*) (void *)) distribute_hash_make, + disthash = hash_create (distribute_hash_make, (int (*) (const void *, const void *)) distribute_cmp); if(node==RIP_NODE) { diff --git a/lib/hash.c b/lib/hash.c index 672327ec..6db79ea7 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -101,6 +101,17 @@ hash_lookup (struct hash *hash, void *data) return hash_get (hash, data, NULL); } +/* Simple Bernstein hash which is simple and fast for common case */ +unsigned int string_hash_make (const char *str) +{ + unsigned int hash = 0; + + while (*str) + hash = (hash * 33) ^ (unsigned int) *str++; + + return hash; +} + /* This function release registered value from specified hash. When release is successfully finished, return the data pointer in the hash backet. */ diff --git a/lib/hash.h b/lib/hash.h index f4b1c23e..4cb772e5 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -70,4 +70,6 @@ extern void hash_iterate (struct hash *, extern void hash_clean (struct hash *, void (*) (void *)); extern void hash_free (struct hash *); +extern unsigned int string_hash_make (const char *); + #endif /* _ZEBRA_HASH_H */ diff --git a/lib/if_rmap.c b/lib/if_rmap.c index ddc62fd5..9774be4b 100644 --- a/lib/if_rmap.c +++ b/lib/if_rmap.c @@ -109,14 +109,9 @@ if_rmap_get (const char *ifname) static unsigned int if_rmap_hash_make (void *data) { - struct if_rmap *if_rmap = data; - unsigned int i, key; + const struct if_rmap *if_rmap = data; - key = 0; - for (i = 0; i < strlen (if_rmap->ifname); i++) - key += if_rmap->ifname[i]; - - return key; + return string_hash_make (if_rmap->ifname); } static int -- cgit v1.2.3 From 4bd045d5dd28653af899c01d6f0c413d74677114 Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Wed, 10 Nov 2010 13:00:54 -0800 Subject: lib: Add a function to delete all interfaces if.c: (if_terminate) This adds a cleanup function that can be called when a daemon exits, similar to vty_terminate(). --- lib/if.c | 18 ++++++++++++++++++ lib/if.h | 1 + 2 files changed, 19 insertions(+) (limited to 'lib') diff --git a/lib/if.c b/lib/if.c index e3107116..b61bdbff 100644 --- a/lib/if.c +++ b/lib/if.c @@ -878,3 +878,21 @@ if_init (void) memset (&if_master, 0, sizeof if_master); } + +void +if_terminate (void) +{ + for (;;) + { + struct interface *ifp; + + ifp = listnode_head (iflist); + if (ifp == NULL) + break; + + if_delete (ifp); + } + + list_delete (iflist); + iflist = NULL; +} diff --git a/lib/if.h b/lib/if.h index c99ab81b..841ce51e 100644 --- a/lib/if.h +++ b/lib/if.h @@ -266,6 +266,7 @@ extern int if_is_pointopoint (struct interface *); extern int if_is_multicast (struct interface *); extern void if_add_hook (int, int (*)(struct interface *)); extern void if_init (void); +extern void if_terminate (void); extern void if_dump_all (void); extern const char *if_flag_dump(unsigned long); -- cgit v1.2.3 From 7e69d993673597334b1e1b3d1072a4c064f293d5 Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Wed, 10 Nov 2010 13:01:17 -0800 Subject: lib: zlog should clean up its memory * log.c: (closezlog) Also free the dynamically allocated filename when a log is closed. --- lib/log.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/log.c b/lib/log.c index 0c2f655b..df6e13db 100644 --- a/lib/log.c +++ b/lib/log.c @@ -653,6 +653,9 @@ closezlog (struct zlog *zl) if (zl->fp != NULL) fclose (zl->fp); + if (zl->filename != NULL) + free (zl->filename); + XFREE (MTYPE_ZLOG, zl); } -- cgit v1.2.3 From 58192df7746231fbc82e248b5ddfc7cab95ab1e7 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 5 Aug 2010 10:26:24 -0700 Subject: lib: add TCP_CORK wrapper * sockunion.{c,h}: (sockopt_cork) wrapper for TCP_CORK socket option for those platforms that provide it. For other platforms, it is just a nop. --- lib/sockunion.c | 10 ++++++++++ lib/sockunion.h | 1 + 2 files changed, 11 insertions(+) (limited to 'lib') diff --git a/lib/sockunion.c b/lib/sockunion.c index 6a40f332..f6c060f5 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -527,6 +527,16 @@ sockopt_ttl (int family, int sock, int ttl) return 0; } +int +sockopt_cork (int sock, int onoff) +{ +#ifdef TCP_CORK + return setsockopt (sock, IPPROTO_TCP, TCP_CORK, &onoff, sizeof(onoff)); +#else + return 0; +#endif +} + /* If same family and same prefix return 1. */ int sockunion_same (union sockunion *su1, union sockunion *su2) diff --git a/lib/sockunion.h b/lib/sockunion.h index 96b9a0d4..91bfbc7f 100644 --- a/lib/sockunion.h +++ b/lib/sockunion.h @@ -102,6 +102,7 @@ extern int sockopt_reuseport (int); extern int sockunion_bind (int sock, union sockunion *, unsigned short, union sockunion *); extern int sockopt_ttl (int family, int sock, int ttl); +extern int sockopt_cork (int sock, int onoff); extern int sockunion_socket (union sockunion *su); extern const char *inet_sutop (union sockunion *su, char *str); extern enum connect_result sockunion_connect (int fd, union sockunion *su, -- cgit v1.2.3 From fc95186c30884c96543aecfc56cfe5b08774525b Mon Sep 17 00:00:00 2001 From: Christian Hammers Date: Wed, 23 Mar 2011 13:07:55 +0300 Subject: lib: fix more format warnings (#637) The following patch was also neccessary to compile. * command.c: (config_logmsg_cmd) use "%s" format spec * if.c: (connected_log) ditto --- lib/command.c | 2 +- lib/if.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/command.c b/lib/command.c index 5a13f39c..264e0f7b 100644 --- a/lib/command.c +++ b/lib/command.c @@ -3056,7 +3056,7 @@ DEFUN (config_logmsg, if ((level = level_match(argv[0])) == ZLOG_DISABLED) return CMD_ERR_NO_MATCH; - zlog(NULL, level, ((message = argv_concat(argv, argc, 1)) ? message : "")); + zlog(NULL, level, "%s", ((message = argv_concat(argv, argc, 1)) ? message : "")); if (message) XFREE(MTYPE_TMP, message); return CMD_SUCCESS; diff --git a/lib/if.c b/lib/if.c index b61bdbff..86f754b6 100644 --- a/lib/if.c +++ b/lib/if.c @@ -664,7 +664,7 @@ connected_log (struct connected *connected, char *str) strncat (logbuf, inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), BUFSIZ - strlen(logbuf)); } - zlog (NULL, LOG_INFO, logbuf); + zlog (NULL, LOG_INFO, "%s", logbuf); } /* If two connected address has same prefix return 1. */ -- cgit v1.2.3 From fa411a212b55bba650d68fd0456686f3e47b7395 Mon Sep 17 00:00:00 2001 From: Nick Hilliard Date: Wed, 23 Mar 2011 15:33:17 +0000 Subject: bgpd: RFC 5082 Generalized TTL Security Mechanism support * bgpd: Add support for RFC 5082 GTSM, which allows the TTL field to be used to verify that incoming packets have been sent from neighbours no more than X IP hops away. In other words, this allows packets that were sent from further away (i.e. not by the neighbour with known distance, and so possibly a miscreant) to be filtered out. * lib/sockunion.{c,h}: (sockopt_minttl) new function, to set a minimum TTL using the IP_MINTTL socket opt. * bgpd.h: (BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK) define for command error for minttl. (struct peer) add a config variable, to store the configured minttl. (peer_ttl_security_hops_{set,unset}) configuration handlers * bgpd.c: (peer_group_get) init gtsm_hops (peer_ebgp_multihop_{un,}set) check for conflicts with GTSM. Multihop and GTSM can't both be active for a peer at the same time. (peer_ttl_security_hops_set) set minttl, taking care to avoid conflicts with ebgp_multihop. (bgp_config_write_peer) write out minttl as "neighbor .. ttl-security hops X". * bgp_vty.c: (bgp_vty_return) message for BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK (peer_ebgp_multihop_{un,}set_vty) * bgp_network.c: (bgp_accept) set minttl on accepted sockets if appropriate. (bgp_connect) ditto for outbound. --- lib/sockunion.c | 22 ++++++++++++++++++++++ lib/sockunion.h | 1 + 2 files changed, 23 insertions(+) (limited to 'lib') diff --git a/lib/sockunion.c b/lib/sockunion.c index f6c060f5..a32809c1 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -537,6 +537,28 @@ sockopt_cork (int sock, int onoff) #endif } +int +sockopt_minttl (int family, int sock, int minttl) +{ + int ret; + + zlog_debug ("sockopt_minttl: set minttl to %d", minttl); + +#ifdef IP_MINTTL + ret = setsockopt (sock, IPPROTO_IP, IP_MINTTL, &minttl, sizeof(minttl)); +#else + ret = -1; + errno = EOPNOTSUPP; +#endif /* IP_MINTTL */ + if (ret < 0) + { + zlog (NULL, LOG_WARNING, "can't set sockopt IP_MINTTL to %d on socket %d: %s", minttl, sock, safe_strerror (errno)); + return -1; + } + + return 0; +} + /* If same family and same prefix return 1. */ int sockunion_same (union sockunion *su1, union sockunion *su2) diff --git a/lib/sockunion.h b/lib/sockunion.h index 91bfbc7f..0ee2d63b 100644 --- a/lib/sockunion.h +++ b/lib/sockunion.h @@ -102,6 +102,7 @@ extern int sockopt_reuseport (int); extern int sockunion_bind (int sock, union sockunion *, unsigned short, union sockunion *); extern int sockopt_ttl (int family, int sock, int ttl); +extern int sockopt_minttl (int family, int sock, int minttl); extern int sockopt_cork (int sock, int onoff); extern int sockunion_socket (union sockunion *su); extern const char *inet_sutop (union sockunion *su, char *str); -- cgit v1.2.3 From 89b6d1f8e2759cc38bc768067abe3a296d93f454 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 24 Mar 2011 10:51:59 +0000 Subject: bgpd: Cleanups & fixes for minttl / GTSM * bgp_vty.c: (peer_ebgp_multihop_{un,}set_vty) tail-call cleanup. ({no_,}neighbor_ttl_security) ditto. * bgpd.c: (peer_ttl_security_hops_set) Peer group checks and TTL set only need to be done on transition. * sockunion.c: (sockopt_minttl) remove always-on debug and improve readability. --- lib/sockunion.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/sockunion.c b/lib/sockunion.c index a32809c1..df05acb3 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -540,23 +540,23 @@ sockopt_cork (int sock, int onoff) int sockopt_minttl (int family, int sock, int minttl) { +#ifdef IP_MINTTL int ret; - zlog_debug ("sockopt_minttl: set minttl to %d", minttl); - -#ifdef IP_MINTTL ret = setsockopt (sock, IPPROTO_IP, IP_MINTTL, &minttl, sizeof(minttl)); -#else - ret = -1; - errno = EOPNOTSUPP; -#endif /* IP_MINTTL */ if (ret < 0) { - zlog (NULL, LOG_WARNING, "can't set sockopt IP_MINTTL to %d on socket %d: %s", minttl, sock, safe_strerror (errno)); + zlog (NULL, LOG_WARNING, + "can't set sockopt IP_MINTTL to %d on socket %d: %s", + minttl, sock, safe_strerror (errno)); return -1; } return 0; +#else + errno = EOPNOTSUPP; + return -1; +#endif /* IP_MINTTL */ } /* If same family and same prefix return 1. */ -- cgit v1.2.3 From d876bdf4a84f40ac3f9bec8d5040858b3725db3e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 5 Aug 2010 10:26:27 -0700 Subject: lib: Add support for IPv6 ttl security * sockunion.c: (sockopt_minttl) Add IPv6 support for min hop count. The kernel support is Linux kernel 2.6.35 or later. --- lib/sockunion.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/sockunion.c b/lib/sockunion.c index df05acb3..a5382a72 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -541,22 +541,30 @@ int sockopt_minttl (int family, int sock, int minttl) { #ifdef IP_MINTTL - int ret; - - ret = setsockopt (sock, IPPROTO_IP, IP_MINTTL, &minttl, sizeof(minttl)); - if (ret < 0) + if (family == AF_INET) { - zlog (NULL, LOG_WARNING, - "can't set sockopt IP_MINTTL to %d on socket %d: %s", - minttl, sock, safe_strerror (errno)); - return -1; + int ret = setsockopt (sock, IPPROTO_IP, IP_MINTTL, &minttl, sizeof(minttl)); + if (ret < 0) + zlog (NULL, LOG_WARNING, + "can't set sockopt IP_MINTTL to %d on socket %d: %s", + minttl, sock, safe_strerror (errno)); + return ret; } +#endif /* IP_MINTTL */ +#ifdef IPV6_MINHOPCNT + if (family == AF_INET6) + { + int ret = setsockopt (sock, IPPROTO_IPV6, IPV6_MINHOPCNT, &minttl, sizeof(minttl)); + if (ret < 0) + zlog (NULL, LOG_WARNING, + "can't set sockopt IPV6_MINHOPCNT to %d on socket %d: %s", + minttl, sock, safe_strerror (errno)); + return ret; + } +#endif - return 0; -#else errno = EOPNOTSUPP; return -1; -#endif /* IP_MINTTL */ } /* If same family and same prefix return 1. */ -- cgit v1.2.3 From 6bd3ef2441f6b45d96c69ee8183d2bec8173ddb5 Mon Sep 17 00:00:00 2001 From: Chris Hall Date: Tue, 2 Aug 2011 15:57:48 +0100 Subject: Fix SEGV when closing legacy threaded VTY Fix of simple typo. --- lib/vty_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/vty_io.c b/lib/vty_io.c index 2eadc2d1..b0915559 100644 --- a/lib/vty_io.c +++ b/lib/vty_io.c @@ -1195,7 +1195,7 @@ uty_sock_close(vio_sock sock) sock->fd = -1 ; if (sock->t_read != NULL) - thread_cancel(sock->t_write) ; + thread_cancel(sock->t_read) ; if (sock->t_write != NULL) thread_cancel(sock->t_write) ; -- cgit v1.2.3