summaryrefslogtreecommitdiffstats
path: root/lib/qpthreads.c
diff options
context:
space:
mode:
authorChris Hall <chris.hall@highwayman.com>2012-05-07 10:42:44 +0100
committerChris Hall <chris.hall@highwayman.com>2012-05-07 10:42:44 +0100
commit3f3eefca8629ba50b1621877f9ac56b5a77626ce (patch)
treebfa9d810c5ba9ecf5d3eb1709e9d613e6dd0cfeb /lib/qpthreads.c
parent459df04013d375de338d081149ca55a46cc42f7b (diff)
downloadquagga-ex24b.tar.bz2
quagga-ex24b.tar.xz
Fix problems with handling of oversize BGP messagesex24b
The objective is to (as gracefully as possible) deal with outgoing UPDATE messages which simply do not in the maximum size BGP message. This can happen if very large AS_PATH or Community attributes come in, and are then extended. (Sending an UPDATE to an AS2 speaking peer can create a complete second copy of the AS_PATH !) Previous versions of Quagga would crash under these circumstances. Recent version were changed to tolerate and detect oversize messages. Any oversize message is logged as an error and discarded. This version will also withdraw prefixes if the selected route simply cannot be advertised. This version also corrects the handling of messages which are limited to the maximum BGP message size -- in particular UPDATE messages which carry a large number of IPv4/Unicast prefixes. (This was broken by the earlier efforts to handle oversize messages.) Changes in this commit: * update version to 0.99.20ex24b * where a set of attributes is too big to fit into a BGP message, or so big that not even one prefix will also fit into a BGP message, the following steps are now taken: - the BGP message is discarded and an error logged (as in other recent versions -- Quagga does not crash). - any prefixes which should have been advertised with the (broken) attributes will be withdrawn, if they have been advertised earlier with valid attributes. A further error is logged, listing the affected prefixes. - prefixes which are suppressed in this way are not counted as having been sent. At present there is no "show" command which will show which prefixes have been suppress -- TBA. * for all AFI/SAFI announce as many withdrawn prefixes as will fit in a BGP message. Previously, all AFI/SAFI other than IPv4/Unicast would send one withdrawn prefix per message. (This is still the case for announcements. It seems unlikely that many IPv6 prefixes will have the same attributes... so this does not seem worth fixing immediately.) * ensure that NOTIFICATION message cannot exceed the maximum length of a BGP message, no matter how much data is sent (!). * where IPv4/Unicast prefixes share the same attributes, they are now announced in the order received. Previously, when prefixes were added to the list hung off the 'struct bgp_advertise_attr', they were in LIFO order. * add SAFI name table. * log pthread attributes when creating a pthread. * fix scheduling of withdrawn prefixes to reduce number of BGP messages generated. Bug fixes: * fix discard of invalid IPv6 link-local nexthop (recent bug). * where amount of information that is put into a BGP message is limited by the maximum message size, fix so that this works again. (This was broken recently.) * set "Bottom of Stack" bit in MPLS VPN "tag" in MP_REACH and MP_UNREACH outgoing attributes.
Diffstat (limited to 'lib/qpthreads.c')
-rw-r--r--lib/qpthreads.c81
1 files changed, 33 insertions, 48 deletions
diff --git a/lib/qpthreads.c b/lib/qpthreads.c
index ebaf6f19..4288b9ff 100644
--- a/lib/qpthreads.c
+++ b/lib/qpthreads.c
@@ -568,9 +568,8 @@ qpt_thread_create(void* (*start)(void*), void* arg, qpt_thread_attr_t* attr)
{
qstring qs ;
- qs = qpt_thread_attr_form(&thread_attr, " ") ;
-
- fputs(qs_string(qs), stderr) ;
+ qs = qpt_thread_attr_form(&thread_attr) ;
+ zlog_info("Thread created: %s", qs_string(qs)) ;
qs_free(qs) ;
}
@@ -1392,7 +1391,7 @@ qpt_data_delete(qpt_data data)
* NB: it is the caller's responsibility to dispose of the qstring
*/
extern qstring
-qpt_thread_attr_form(qpt_thread_attr_t* attr, const char *prefix)
+qpt_thread_attr_form(qpt_thread_attr_t* attr)
{
int err, i ;
qstring qs ;
@@ -1402,131 +1401,117 @@ qpt_thread_attr_form(qpt_thread_attr_t* attr, const char *prefix)
qs = qs_new(500) ;
- /* 12345678901234567890 */
- qs_printf_a(qs, "%sDetach state ", prefix) ;
err = pthread_attr_getdetachstate(attr, &i);
if (err != 0)
- qs_printf_a(qs, " *error* %s\n", errtoa(err, 0).str) ;
+ qs_printf_a(qs, "[getdetachstate *error* %s]", errtoa(err, 0).str) ;
else
{
switch(i)
{
case PTHREAD_CREATE_DETACHED:
- qs_printf_a(qs, "= %s\n", "PTHREAD_CREATE_DETACHED") ;
+ qs_printf_a(qs, "Detached") ;
break ;
case PTHREAD_CREATE_JOINABLE:
- qs_printf_a(qs, "= %s\n", "PTHREAD_CREATE_JOINABLE") ;
+ qs_printf_a(qs, "Joinable") ;
break ;
default:
- qs_printf_a(qs, "= *UNKNOWN* %d\n", i) ;
+ qs_printf_a(qs, "[getdetachstate *unknown* %d]", i) ;
break ;
} ;
} ;
- /* 12345678901234567890 */
- qs_printf_a(qs, "%sScope ", prefix) ;
- err = pthread_attr_getscope(attr, &i);
+ err = pthread_attr_getinheritsched(attr, &i);
if (err != 0)
- qs_printf_a(qs, " *error* %s\n", errtoa(err, 0).str) ;
+ qs_printf_a(qs, " [getinheritsched *error* %s]", errtoa(err, 0).str) ;
else
{
switch(i)
{
- case PTHREAD_SCOPE_SYSTEM:
- qs_printf_a(qs, "= %s\n", "PTHREAD_SCOPE_SYSTEM") ;
+ case PTHREAD_INHERIT_SCHED:
+ qs_printf_a(qs, " Inherit-Sched") ;
break ;
- case PTHREAD_SCOPE_PROCESS:
- qs_printf_a(qs, "= %s\n", "PTHREAD_SCOPE_PROCESS") ;
+ case PTHREAD_EXPLICIT_SCHED:
+ qs_printf_a(qs, " Explicit-Sched") ;
break ;
default:
- qs_printf_a(qs, "= *UNKNOWN* %d\n", i) ;
+ qs_printf_a(qs, " [getinheritsched *unknown* %d]", i) ;
break ;
} ;
} ;
- /* 12345678901234567890 */
- qs_printf_a(qs, "%sInherit scheduler ", prefix) ;
- err = pthread_attr_getinheritsched(attr, &i);
+ err = pthread_attr_getscope(attr, &i);
if (err != 0)
- qs_printf_a(qs, " *error* %s\n", errtoa(err, 0).str) ;
+ qs_printf_a(qs, " [getscope *error* %s]", errtoa(err, 0).str) ;
else
{
switch(i)
{
- case PTHREAD_INHERIT_SCHED:
- qs_printf_a(qs, "= %s\n", "PTHREAD_INHERIT_SCHED") ;
+ case PTHREAD_SCOPE_SYSTEM:
+ qs_printf_a(qs, " System-Scope") ;
break ;
- case PTHREAD_EXPLICIT_SCHED:
- qs_printf_a(qs, "= %s\n", "PTHREAD_EXPLICIT_SCHED") ;
+ case PTHREAD_SCOPE_PROCESS:
+ qs_printf_a(qs, " Process-Scope") ;
break ;
default:
- qs_printf_a(qs, "= *UNKNOWN* %d\n", i) ;
+ qs_printf_a(qs, " [getscope *unknown* %d]", i) ;
break ;
} ;
} ;
- /* 12345678901234567890 */
- qs_printf_a(qs, "%sScheduling policy ", prefix) ;
err = pthread_attr_getschedpolicy(attr, &i);
if (err != 0)
- qs_printf_a(qs, " *error* %s\n", errtoa(err, 0).str) ;
+ qs_printf_a(qs, " [getschedpolicy *error* %s]", errtoa(err, 0).str) ;
else
{
switch(i)
{
case SCHED_OTHER:
- qs_printf_a(qs, "= %s\n", "SCHED_OTHER") ;
+ qs_printf_a(qs, " SCHED_OTHER") ;
break ;
case SCHED_FIFO:
- qs_printf_a(qs, "= %s\n", "SCHED_FIFO") ;
+ qs_printf_a(qs, " SCHED_FIFO") ;
break ;
case SCHED_RR:
- qs_printf_a(qs, "= %s\n", "SCHED_RR") ;
+ qs_printf_a(qs, " SCHED_RR") ;
break ;
#ifdef SCHED_SPORADIC
case SCHED_SPORADIC:
- qs_printf_a(qs, "= %s\n", "SCHED_SPORADIC") ;
+ qs_printf_a(qs, " SCHED_SPORADIC") ;
break ;
#endif
default:
- qs_printf_a(qs, "= *UNKNOWN* %d\n", i) ;
+ qs_printf_a(qs, " SCHED_UNKNOWN=%d", i) ;
break ;
} ;
} ;
- /* 12345678901234567890 */
- qs_printf_a(qs, "%sScheduling priority ", prefix) ;
err = pthread_attr_getschedparam(attr, sp);
if (err != 0)
- qs_printf_a(qs, " *error* %s\n", errtoa(err, 0).str) ;
+ qs_printf_a(qs, " [getschedparam *error* %s]", errtoa(err, 0).str) ;
else
- qs_printf_a(qs, "= %d\n", sp->sched_priority) ;
+ qs_printf_a(qs, " Priority=%d", sp->sched_priority) ;
- /* 12345678901234567890 */
- qs_printf_a(qs, "%sGuard size ", prefix) ;
err = pthread_attr_getguardsize(attr, &v);
if (err != 0)
- qs_printf_a(qs, " *error* %s\n", errtoa(err, 0).str) ;
+ qs_printf_a(qs, " [getguardsize *error* %s]", errtoa(err, 0).str) ;
else
- qs_printf_a(qs, "= %u\n", (uint)v) ;
+ qs_printf_a(qs, " Guard-Size=%u", (uint)v) ;
- /* 12345678901234567890 */
- qs_printf_a(qs, "%sStack address/size ", prefix) ;
err = pthread_attr_getstack(attr, &stkaddr, &v) ;
if (err != 0)
- qs_printf_a(qs, " *error* %s\n", errtoa(err, 0).str) ;
+ qs_printf_a(qs, " [getstack *error* %s]", errtoa(err, 0).str) ;
else
- qs_printf_a(qs, "= %p/%u\n", stkaddr, (uint)v) ;
+ qs_printf_a(qs, " Stack=%p/%u", stkaddr, (uint)v) ;
return qs ;
} ;