diff options
author | paulo <paul@bayleaf.org.uk> | 2010-01-28 17:41:28 +0000 |
---|---|---|
committer | paulo <paul@bayleaf.org.uk> | 2010-01-28 17:41:28 +0000 |
commit | 4daba96cdd1dd33b21d8b7cc96b5a5b3c6230e41 (patch) | |
tree | a16d0b34403b3ec97c7ac315038d52e480aa6b5a | |
parent | 63fdb51ba64992b4e26f248f80079a84b96f6270 (diff) | |
download | quagga-4daba96cdd1dd33b21d8b7cc96b5a5b3c6230e41.tar.bz2 quagga-4daba96cdd1dd33b21d8b7cc96b5a5b3c6230e41.tar.xz |
Changed zclient to use qfiles etc when we have a nexus. For BGP client
it runs in the routing_nexus. Makefile tidied. Fixed a few warnings.
Re-enabled zclient, horrors of horrors bpg_nexthop thought it OK to
poke arround with zclients threads directly. Now fixed, all private to
zclient.
-rw-r--r-- | bgpd/Makefile.am | 35 | ||||
-rw-r--r-- | bgpd/bgp_main.c | 24 | ||||
-rw-r--r-- | bgpd/bgp_nexthop.c | 33 | ||||
-rw-r--r-- | bgpd/bgp_peer.c | 3 | ||||
-rw-r--r-- | bgpd/bgp_zebra.c | 4 | ||||
-rw-r--r-- | lib/if.c | 2 | ||||
-rw-r--r-- | lib/zclient.c | 264 | ||||
-rw-r--r-- | lib/zclient.h | 7 | ||||
-rw-r--r-- | tests/test-stream.c | 10 |
9 files changed, 288 insertions, 94 deletions
diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 55aad179..ef5e735d 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -11,24 +11,27 @@ noinst_LIBRARIES = libbgp.a sbin_PROGRAMS = bgpd libbgp_a_SOURCES = \ - bgpd.c bgp_fsm.c bgp_aspath.c bgp_community.c bgp_attr.c \ - bgp_debug.c bgp_route.c bgp_zebra.c bgp_open.c bgp_routemap.c \ - bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \ - bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_mplsvpn.c bgp_nexthop.c \ - bgp_peer.c bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c \ - bgp_engine.c bgp_session.c bgp_connection.c \ - bgp_common.c bgp_notification.c bgp_peer_index.c bgp_msg_write.c \ - bgp_route_refresh.c bgp_msg_read.c bgp_open_state.c + bgp_advertise.c bgp_aspath.c bgp_attr.c \ + bgp_clist.c bgp_common.c bgp_community.c bgp_connection.c \ + bgp_damp.c bgpd.c bgp_debug.c bgp_dump.c \ + bgp_ecommunity.c bgp_engine.c bgp_filter.c bgp_fsm.c \ + bgp_main.c bgp_mplsvpn.c bgp_msg_read.c bgp_msg_write.c \ + bgp_network.c bgp_nexthop.c bgp_notification.c bgp_open.c \ + bgp_open_state.c bgp_packet.c bgp_peer.c bgp_peer_index.c \ + bgp_regex.c bgp_route.c bgp_routemap.c bgp_route_refresh.c \ + bgp_session.c bgp_snmp.c bgp_table.c bgp_vty.c \ + bgp_zebra.c noinst_HEADERS = \ - bgp_aspath.h bgp_attr.h bgp_community.h bgp_debug.h bgp_fsm.h \ - bgp_network.h bgp_open.h bgp_packet.h bgp_regex.h bgp_route.h \ - bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \ - bgp_ecommunity.h bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \ - bgp_peer.h bgp_advertise.h bgp_snmp.h bgp_vty.h \ - bgp_engine.h bgp_session.h bgp_connection.h \ - bgp_common.h bgp_notification.h bgp_peer_index.h bgp_msg_write.h \ - bgp_route_refresh.h bgp.h bgp_msg_read.h bgp_open_state.h + bgp_advertise.h bgp_aspath.h bgp_attr.h bgp_clist.h \ + bgp_common.h bgp_community.h bgp_connection.h bgp_damp.h \ + bgp_debug.h bgpd.h bgp_dump.h bgp_ecommunity.h \ + bgp_engine.h bgp_filter.h bgp_fsm.h bgp.h \ + bgp_mplsvpn.h bgp_msg_read.h bgp_msg_write.h bgp_network.h \ + bgp_nexthop.h bgp_notification.h bgp_open.h bgp_open_state.h \ + bgp_packet.h bgp_peer.h bgp_peer_index.h bgp_regex.h \ + bgp_route.h bgp_route_refresh.h bgp_session.h bgp_snmp.h \ + bgp_table.h bgp_vty.h bgp_zebra.h bgpd_SOURCES = bgp_main.c bgpd_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@ diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index e98d841e..6f04d63f 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -51,6 +51,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_filter.h" #include "bgpd/bgp_network.h" #include "bgpd/bgp_engine.h" +#include "bgpd/bgp_zebra.h" /* bgpd options, we use GNU getopt library. */ static const struct option longopts[] = @@ -401,10 +402,18 @@ init_second_stage(int pthreads) bgp_nexus->event_hook[1] = bgp_event_hook; confirm(NUM_EVENT_HOOK >= 2); - /* vty can use either nexus or threads. For bgp client we always - * want nexus, regardless of pthreads. + /* vty and zclient can use either nexus or threads. + * For bgp client we always want nexus, regardless of pthreads. */ vty_init_r(cli_nexus, routing_nexus); + zclient_init_r(routing_nexus); + + /* Now we have our nexus we can init BGP. */ + /* BGP related initialization. */ + bgp_init (); + + /* Sort CLI commands. */ + sort_node (); } /* Main routine of bgpd. Treatment of argument and start bgp finite @@ -418,6 +427,7 @@ main (int argc, char **argv) int dryrun = 0; char *progname; int tmp_port; + int threaded = 0; /* Set umask before anything for security */ umask (0027); @@ -506,8 +516,7 @@ main (int argc, char **argv) usage (progname, 0); break; case 't': - if (!qpthreads_enabled) - init_second_stage(1); + threaded = 1; break; default: usage (progname, 1); @@ -527,11 +536,8 @@ main (int argc, char **argv) vty_init (master); memory_init (); - /* BGP related initialization. */ - bgp_init (); - - /* Sort CLI commands. */ - sort_node (); + if (threaded) + init_second_stage(1); /* Parse config file. */ vty_read_config_first_cmd_special (config_file, config_default, after_first_cmd); diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 7a096faa..32dae086 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -1082,29 +1082,6 @@ bgp_import (struct thread *t) return 0; } -/* Connect to zebra for nexthop lookup. */ -static int -zlookup_connect (struct thread *t) -{ - struct zclient *zlookup; - - zlookup = THREAD_ARG (t); - zlookup->t_connect = NULL; - - if (zlookup->sock != -1) - return 0; - -#ifdef HAVE_TCP_ZEBRA - zlookup->sock = zclient_socket (); -#else - zlookup->sock = zclient_socket_un (ZEBRA_SERV_PATH); -#endif /* HAVE_TCP_ZEBRA */ - if (zlookup->sock < 0) - return -1; - - return 0; -} - /* Check specified multiaccess next-hop. */ int bgp_multiaccess_check_v4 (struct in_addr nexthop, char *peer) @@ -1282,13 +1259,9 @@ bgp_scan_init (void) zlookup = zclient_new (); zlookup->sock = -1; - /* TODO: reinstate zebra interface when ready */ - if (0) - { - zlookup->enable = 1 ; - zlookup->t_connect = thread_add_event (master, zlookup_connect, - zlookup, 0); - } ; + /* enable zebra client and schedule connection */ + zlookup->enable = 1 ; + zlookup_schedule(zlookup); bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT; bgp_import_interval = BGP_IMPORT_INTERVAL_DEFAULT; diff --git a/bgpd/bgp_peer.c b/bgpd/bgp_peer.c index dca9054d..f314e17b 100644 --- a/bgpd/bgp_peer.c +++ b/bgpd/bgp_peer.c @@ -51,7 +51,7 @@ #include "plist.h" #include "mqueue.h" #include "workqueue.h" -#include "if.c" +#include "if.h" #ifdef HAVE_SNMP #include "bgpd/bgp_snmp.h" @@ -129,7 +129,6 @@ bgp_session_do_event(mqueue_block mqb, mqb_flag_t flag) default: /* If now Stopped, then for some reason the BGP Engine has either */ /* stopped trying to connect, or the session has been stopped. */ - /* TODO: stop from BGP Engine requires a Disable to be sent... */ if (args->stopped) bgp_session_has_stopped(peer); break ; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index a9f13da2..19fefb9b 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1042,11 +1042,9 @@ bgp_zebra_init (void) zclient->ipv6_route_delete = zebra_read_ipv6; #endif /* HAVE_IPV6 */ - /* TODO: restore zebra when have threaded it !! */ -#if 1 + /* disable zebra client */ zclient->enable = 0 ; /* disable it */ zclient_stop(zclient) ; /* and make sure all threads stopped */ -#endif /* Interface related init. */ if_init (); @@ -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. */ diff --git a/lib/zclient.c b/lib/zclient.c index d3d53227..8cfa5d52 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -32,18 +32,25 @@ #include "zclient.h" #include "memory.h" #include "table.h" - -/* Zebra client events. */ -enum event {ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT}; -/* Prototype for event manager. */ -static void zclient_event (enum event, struct zclient *); +/* Zebra client events. */ +enum event {ZLOOKUP_SCHEDULE, ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT}; extern struct thread_master *master; /* This file local debug flag. */ int zclient_debug = 0; - + +/* Nexus to use, if any */ +static qpn_nexus zclient_nexus = NULL; + +/* prototypes */ +static int zclient_read (struct zclient *zclient); +static void zclient_event (enum event, struct zclient *); +static void zclient_event_r (enum event event, struct zclient *zclient); +static void zclient_event_t (enum event event, struct zclient *zclient); +static void zclient_connect_r (qtimer qtr, void* timer_info, qtime_t when); + /* Allocate zclient structure. */ struct zclient * zclient_new () @@ -55,6 +62,13 @@ zclient_new () zclient->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ); zclient->wb = buffer_new(0); + if (zclient_nexus) + { + zclient->qf = qps_file_init_new(zclient->qf, NULL); + zclient->qtr = qtimer_init_new(zclient->qtr, zclient_nexus->pile, + zclient_connect_r, zclient); + } + return zclient; } @@ -73,9 +87,29 @@ zclient_free (struct zclient *zclient) if (zclient->wb) buffer_free(zclient->wb); + /* qfile and qtimer */ + if (zclient->qf) + { + qps_remove_file(zclient->qf); + qps_file_free(zclient->qf); + zclient->qf = NULL; + } + if (zclient->qtr) + { + qtimer_free(zclient->qtr); + zclient->qtr = NULL; + } + XFREE (MTYPE_ZCLIENT, zclient); } +/* Initialize to use a nexus (qpselect etc). */ +void +zclient_init_r (qpn_nexus n) +{ + zclient_nexus = n; +} + /* Initialize zebra client. Argument redist_default is unwanted redistribute route type. */ void @@ -108,6 +142,13 @@ zclient_init (struct zclient *zclient, int redist_default) zclient_event (ZCLIENT_SCHEDULE, zclient); } +/* Schedule lookup connection */ +void +zlookup_schedule(struct zclient *zclient) +{ + zclient_event (ZLOOKUP_SCHEDULE, zclient); +} + /* Stop zebra client services. */ void zclient_stop (struct zclient *zclient) @@ -120,6 +161,12 @@ zclient_stop (struct zclient *zclient) THREAD_OFF(zclient->t_connect); THREAD_OFF(zclient->t_write); + if (zclient->qf) + qps_remove_file(zclient->qf); + + if (zclient->qtr) + qtimer_unset(zclient->qtr); + /* Reset streams. */ stream_reset(zclient->ibuf); stream_reset(zclient->obuf); @@ -217,8 +264,37 @@ zclient_failed(struct zclient *zclient) return -1; } +/* Write as much data as possible. + * nexus version */ +static void +zclient_flush_data_r(qps_file qf, void* file_info) +{ + struct zclient *zclient = file_info; + + qps_disable_modes(qf, qps_write_mbit); + + if (zclient->sock < 0) + return; + + switch (buffer_flush_available(zclient->wb, zclient->sock)) + { + case BUFFER_ERROR: + zlog_warn("%s: buffer_flush_available failed on zclient fd %d, closing", + __func__, zclient->sock); + zclient_failed(zclient); + break; + case BUFFER_PENDING: + qps_enable_mode(qf, qps_write_mnum, zclient_flush_data_r) ; + break; + case BUFFER_EMPTY: + break; + } +} + +/* Write as much data as possible. + * thread version */ static int -zclient_flush_data(struct thread *thread) +zclient_flush_data_t(struct thread *thread) { struct zclient *zclient = THREAD_ARG(thread); @@ -233,7 +309,7 @@ zclient_flush_data(struct thread *thread) return zclient_failed(zclient); break; case BUFFER_PENDING: - zclient->t_write = thread_add_write(master, zclient_flush_data, + zclient->t_write = thread_add_write(master, zclient_flush_data_t, zclient, zclient->sock); break; case BUFFER_EMPTY: @@ -256,11 +332,17 @@ zclient_send_message(struct zclient *zclient) return zclient_failed(zclient); break; case BUFFER_EMPTY: - THREAD_OFF(zclient->t_write); + if (zclient_nexus) + qps_disable_modes(zclient->qf, qps_write_mbit); + else + THREAD_OFF(zclient->t_write); break; case BUFFER_PENDING: - THREAD_WRITE_ON(master, zclient->t_write, - zclient_flush_data, zclient, zclient->sock); + if (zclient_nexus) + qps_enable_mode(zclient->qf, qps_write_mnum, zclient_flush_data_r) ; + else + THREAD_WRITE_ON(master, zclient->t_write, + zclient_flush_data_t, zclient, zclient->sock); break; } return 0; @@ -313,6 +395,10 @@ zclient_start (struct zclient *zclient) if (zclient->t_connect) return 0; + /* Check timer */ + if (zclient->qtr && qtr_is_active(zclient->qtr)) + return 0; + /* Make socket. */ #ifdef HAVE_TCP_ZEBRA zclient->sock = zclient_socket (); @@ -336,6 +422,9 @@ zclient_start (struct zclient *zclient) if (zclient_debug) zlog_debug ("zclient connect success with socket [%d]", zclient->sock); + if (zclient_nexus) + qps_add_file(zclient_nexus->selection, zclient->qf, zclient->sock, zclient); + /* Create read thread. */ zclient_event (ZCLIENT_READ, zclient); @@ -358,9 +447,24 @@ zclient_start (struct zclient *zclient) } /* This function is a wrapper function for calling zclient_start from + qtimer. */ +static void +zclient_connect_r (qtimer qtr, void* timer_info, qtime_t when) +{ + struct zclient *zclient = timer_info; + + qtimer_unset(qtr); + + if (zclient_debug) + zlog_debug ("zclient_connect is called"); + + zclient_start (zclient); +} + +/* This function is a wrapper function for calling zclient_start from timer or event thread. */ static int -zclient_connect (struct thread *t) +zclient_connect_t (struct thread *t) { struct zclient *zclient; @@ -372,7 +476,51 @@ zclient_connect (struct thread *t) return zclient_start (zclient); } - + +/* Connect to zebra for nexthop lookup. + * thread version */ +static int +zlookup_connect_t (struct thread *t) +{ + struct zclient *zlookup; + + zlookup = THREAD_ARG (t); + zlookup->t_connect = NULL; + + if (zlookup->sock != -1) + return 0; + +#ifdef HAVE_TCP_ZEBRA + zlookup->sock = zclient_socket (); +#else + zlookup->sock = zclient_socket_un (ZEBRA_SERV_PATH); +#endif /* HAVE_TCP_ZEBRA */ + if (zlookup->sock < 0) + return -1; + + return 0; +} + +/* Connect to zebra for nexthop lookup. + * nexus version */ +static void +zlookup_connect_r (qtimer qtr, void* timer_info, qtime_t when) +{ + struct zclient *zlookup = timer_info; + + qtimer_unset(qtr); + + if (zlookup->sock != -1) + return; + +#ifdef HAVE_TCP_ZEBRA + zlookup->sock = zclient_socket (); +#else + zlookup->sock = zclient_socket_un (ZEBRA_SERV_PATH); +#endif /* HAVE_TCP_ZEBRA */ +} + + /* * "xdr_encode"-like interface that allows daemon (client) to send * a message to zebra server for a route that needs to be @@ -791,20 +939,32 @@ zebra_interface_address_read (int type, struct stream *s) return ifc; } - +/* nexus: Zebra client message read function. */ +static void +zclient_read_r (qps_file qf, void* file_info) +{ + struct zclient *zclient = file_info; + qps_disable_modes(qf, qps_read_mbit); + zclient_read(zclient); +} + +/* thread: Zebra client message read function. */ +static int +zclient_read_t (struct thread *thread) +{ + struct zclient *zclient = THREAD_ARG (thread); + zclient->t_read = NULL; + return zclient_read(zclient); +} + /* Zebra client message read function. */ static int -zclient_read (struct thread *thread) +zclient_read (struct zclient *zclient) { int ret; size_t already; uint16_t length, command; uint8_t marker, version; - struct zclient *zclient; - - /* Get socket to zebra. */ - zclient = THREAD_ARG (thread); - zclient->t_read = NULL; /* Read zebra header (if we don't have it already). */ if ((already = stream_get_endp(zclient->ibuf)) < ZEBRA_HEADER_SIZE) @@ -991,15 +1151,30 @@ zclient_redistribute_default (int command, struct zclient *zclient) zebra_message_send (zclient, command); } +/* Arm event. */ static void zclient_event (enum event event, struct zclient *zclient) { + if (zclient_nexus) + zclient_event_r(event, zclient); + else + zclient_event_t(event, zclient); +} + +/* Arm event. + * nexus version */ +static void +zclient_event_r (enum event event, struct zclient *zclient) +{ switch (event) { + case ZLOOKUP_SCHEDULE: + if (!qtr_is_active(zclient->qtr)) + qtimer_set(zclient->qtr, qt_get_monotonic(), zlookup_connect_r) ; + break; case ZCLIENT_SCHEDULE: - if (! zclient->t_connect) - zclient->t_connect = - thread_add_event (master, zclient_connect, zclient, 0); + if (!qtr_is_active(zclient->qtr)) + qtimer_set(zclient->qtr, qt_get_monotonic(), zclient_connect_r) ; break; case ZCLIENT_CONNECT: if (zclient->fail >= 10) @@ -1007,14 +1182,47 @@ zclient_event (enum event event, struct zclient *zclient) if (zclient_debug) zlog_debug ("zclient connect schedule interval is %d", zclient->fail < 3 ? 10 : 60); + if (!qtr_is_active(zclient->qtr)) + qtimer_set(zclient->qtr, + qt_add_monotonic(QTIME(zclient->fail < 3 ? 10 : 60)), zclient_connect_r) ; + break; + case ZCLIENT_READ: + qps_enable_mode(zclient->qf, qps_read_mnum, zclient_read_r) ; + break; + } +} + +/* Arm event. + * thread version */ +static void +zclient_event_t (enum event event, struct zclient *zclient) +{ + switch (event) + { + case ZLOOKUP_SCHEDULE: + if (! zclient->t_connect) + zclient->t_connect = + thread_add_event (master, zlookup_connect_t, zclient, 0); + break; + case ZCLIENT_SCHEDULE: + if (! zclient->t_connect) + zclient->t_connect = + thread_add_event (master, zclient_connect_t, zclient, 0); + break; + case ZCLIENT_CONNECT: + if (zclient->fail >= 10) + return; + if (zclient_debug) + zlog_debug ("zclient connect schedule interval is %d", + zclient->fail < 3 ? 10 : 60); if (! zclient->t_connect) - zclient->t_connect = - thread_add_timer (master, zclient_connect, zclient, - zclient->fail < 3 ? 10 : 60); + zclient->t_connect = + thread_add_timer (master, zclient_connect_t, zclient, + zclient->fail < 3 ? 10 : 60); break; case ZCLIENT_READ: - zclient->t_read = - thread_add_read (master, zclient_read, zclient, zclient->sock); + zclient->t_read = + thread_add_read (master, zclient_read_t, zclient, zclient->sock); break; } } diff --git a/lib/zclient.h b/lib/zclient.h index 21786ab8..394407eb 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -24,6 +24,7 @@ /* For struct interface and struct connected. */ #include "if.h" +#include "qpnexus.h" /* For input/output buffer to zebra. */ #define ZEBRA_MAX_PACKET_SIZ 4096 @@ -60,6 +61,10 @@ struct zclient /* Thread to write buffered data to zebra. */ struct thread *t_write; + /* If using nexus, qfile and qtimer */ + qps_file qf; + qtimer qtr; + /* Redistribute information. */ u_char redist_default; u_char redist[ZEBRA_ROUTE_MAX]; @@ -121,11 +126,13 @@ struct zapi_ipv4 /* Prototypes of zebra client service functions. */ extern struct zclient *zclient_new (void); +extern void zclient_init_r (qpn_nexus); extern void zclient_init (struct zclient *, int); extern int zclient_start (struct zclient *); extern void zclient_stop (struct zclient *); extern void zclient_reset (struct zclient *); extern void zclient_free (struct zclient *); +extern void zlookup_schedule(struct zclient *); /* Get TCP socket connection to zebra daemon at loopback address. */ extern int zclient_socket (void); diff --git a/tests/test-stream.c b/tests/test-stream.c index 785ce588..e145436f 100644 --- a/tests/test-stream.c +++ b/tests/test-stream.c @@ -2,7 +2,7 @@ #include <stream.h> #include <thread.h> -static long int ham = 0xdeadbeefdeadbeef; +static int64_t ham = 0xdeadbeefdeadbeef; struct thread_master *master; static void @@ -11,9 +11,9 @@ print_stream (struct stream *s) size_t getp = stream_get_getp (s); printf ("endp: %ld, readable: %ld, writeable: %ld\n", - stream_get_endp (s), - STREAM_READABLE (s), - STREAM_WRITEABLE (s)); + (long int)stream_get_endp (s), + (long int)STREAM_READABLE (s), + (long int)STREAM_WRITEABLE (s)); while (STREAM_READABLE (s)) { @@ -48,7 +48,7 @@ main (void) printf ("c: 0x%hhx\n", stream_getc (s)); printf ("w: 0x%hx\n", stream_getw (s)); printf ("l: 0x%x\n", stream_getl (s)); - printf ("q: 0x%lx\n", stream_getq (s)); + printf ("q: 0x%llx\n", (long long unsigned)stream_getq (s)); return 0; } |