diff options
-rw-r--r-- | bgpd/bgp_connection.c | 6 | ||||
-rw-r--r-- | bgpd/bgp_engine.c | 55 | ||||
-rw-r--r-- | bgpd/bgp_engine.h | 20 | ||||
-rw-r--r-- | bgpd/bgp_main.c | 76 | ||||
-rw-r--r-- | bgpd/bgp_msg_read.c | 1 | ||||
-rw-r--r-- | bgpd/bgp_network.c | 2 | ||||
-rw-r--r-- | bgpd/bgp_packet.c | 2 | ||||
-rw-r--r-- | bgpd/bgp_peer.c | 29 | ||||
-rw-r--r-- | bgpd/bgp_peer.h | 3 | ||||
-rw-r--r-- | bgpd/bgp_session.c | 2 | ||||
-rw-r--r-- | bgpd/bgpd.c | 30 | ||||
-rw-r--r-- | lib/command.c | 12 | ||||
-rw-r--r-- | lib/qpnexus.c | 133 | ||||
-rw-r--r-- | lib/qpnexus.h | 19 | ||||
-rw-r--r-- | lib/vty.c | 8 |
15 files changed, 173 insertions, 225 deletions
diff --git a/bgpd/bgp_connection.c b/bgpd/bgp_connection.c index ba13c33a..9d937033 100644 --- a/bgpd/bgp_connection.c +++ b/bgpd/bgp_connection.c @@ -149,9 +149,9 @@ bgp_connection_init_new(bgp_connection connection, bgp_session session, qps_file_init_new(&connection->qf, NULL) ; /* Initialise all the timers */ - qtimer_init_new(&connection->hold_timer, p_bgp_engine->pile, + qtimer_init_new(&connection->hold_timer, bgp_nexus->pile, NULL, connection) ; - qtimer_init_new(&connection->keepalive_timer, p_bgp_engine->pile, + qtimer_init_new(&connection->keepalive_timer, bgp_nexus->pile, NULL, connection) ; /* Copy log destination and make host name + (primary)/(secondary) */ @@ -483,7 +483,7 @@ bgp_connection_open(bgp_connection connection, int fd) bgp_connection_disable_accept(connection) ; /* Set the file going */ - qps_add_file(p_bgp_engine->selection, &connection->qf, fd, connection) ; + qps_add_file(bgp_nexus->selection, &connection->qf, fd, connection) ; /* Clear sundry state is clear */ connection->post = bgp_fsm_null_event ; /* no post event event */ diff --git a/bgpd/bgp_engine.c b/bgpd/bgp_engine.c index c47094f6..f963d0d9 100644 --- a/bgpd/bgp_engine.c +++ b/bgpd/bgp_engine.c @@ -62,10 +62,7 @@ * */ -qpn_nexus p_bgp_engine ; - -static struct qpn_nexus bgp_engine ; - +extern qpn_nexus bgp_nexus ; /*============================================================================== * Start the BGP Engine Thread. @@ -74,43 +71,22 @@ static struct qpn_nexus bgp_engine ; * */ -static void* bgp_engine_loop(void* arg) ; - -/* TODO: BGP Engine side of bgp_engine_start() must call bgp_open_listeners() - * for which it needs the port and address from command line. +/* BGP Engine side of bgp_engine_start() must call bgp_open_listeners() + * for which it needs the port and address from command line. + * + * Implemented in bgp_main.c */ -extern void -bgp_engine_start(void) -{ - p_bgp_engine = qpn_init_new(&bgp_engine) ; - - p_bgp_engine->start = bgp_engine_loop ; - - p_bgp_engine->thread_id = qpt_thread_self() ; - - p_bgp_engine->selection = qps_selection_init_new(NULL) ; - p_bgp_engine->pile = qtimer_pile_init_new(NULL) ; - p_bgp_engine->queue = mqueue_init_new(NULL, mqt_signal_broadcast) ; - p_bgp_engine->mts = mqueue_thread_signal_init(NULL, - p_bgp_engine->thread_id, SIGMQUEUE) ; - - qpn_exec(p_bgp_engine) ; -} ; - /*============================================================================== * Stop the BGP Engine Thread. * */ -/* TODO: BGP Engine side of bgp_engine_stop() must call bgp_close_listeners() +/* BGP Engine side of bgp_engine_stop() must call bgp_close_listeners() + * + * Implemented in bgp_main.c */ -extern void -bgp_engine_stop(void) -{ -} ; - /*============================================================================== * The BGP Engine Thread main loop * @@ -154,24 +130,11 @@ bgp_engine_stop(void) * * Which generate FSM events. * + * Implemented in qpnexus.c * */ - - - - - - -/*============================================================================== - * The qpnexus for the BGP Engine. - * - * - */ - - - /*============================================================================== * The write queue for the BGP Engine * diff --git a/bgpd/bgp_engine.h b/bgpd/bgp_engine.h index 2ffba5d0..46a82093 100644 --- a/bgpd/bgp_engine.h +++ b/bgpd/bgp_engine.h @@ -37,15 +37,9 @@ #endif - - -extern qpn_nexus p_bgp_engine ; -extern qpn_nexus p_peering_engine ; - -extern void -bgp_engine_start(void) ; - - +extern qpn_nexus cli_nexus; +extern qpn_nexus bgp_nexus; +extern qpn_nexus routing_nexus; /*============================================================================== * @@ -56,7 +50,7 @@ bgp_engine_start(void) ; Inline void bgp_to_bgp_engine(mqueue_block mqb) { - mqueue_enqueue(p_bgp_engine->queue, mqb, 0) ; + mqueue_enqueue(bgp_nexus->queue, mqb, 0) ; } ; /* Send given message to the BGP Engine -- priority @@ -64,7 +58,7 @@ bgp_to_bgp_engine(mqueue_block mqb) Inline void bgp_to_bgp_engine_priority(mqueue_block mqb) { - mqueue_enqueue(p_bgp_engine->queue, mqb, 1) ; + mqueue_enqueue(bgp_nexus->queue, mqb, 1) ; } ; /*============================================================================== @@ -76,7 +70,7 @@ bgp_to_bgp_engine_priority(mqueue_block mqb) Inline void bgp_to_peering_engine(mqueue_block mqb) { - mqueue_enqueue(p_peering_engine->queue, mqb, 0) ; + mqueue_enqueue(routing_nexus->queue, mqb, 0) ; } ; /* Send given message to the Peering Engine -- priority @@ -84,7 +78,7 @@ bgp_to_peering_engine(mqueue_block mqb) Inline void bgp_to_peering_engine_priority(mqueue_block mqb) { - mqueue_enqueue(p_peering_engine->queue, mqb, 1) ; + mqueue_enqueue(routing_nexus->queue, mqb, 1) ; } ; #endif /* QUAGGA_BGP_ENGINE_H */ diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index c7eca751..e6afe1ec 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -49,6 +49,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_clist.h" #include "bgpd/bgp_debug.h" #include "bgpd/bgp_filter.h" +#include "bgpd/bgp_network.h" /* bgpd options, we use GNU getopt library. */ static const struct option longopts[] = @@ -80,6 +81,7 @@ void sigusr2 (void); /* prototypes */ static void bgp_exit (int); static void init_second_stage(int pthreads); +static void bgp_in_thread_init(void); static struct quagga_signal_t bgp_signals[] = { @@ -221,14 +223,10 @@ sigint (void) if (bgp_nexus != NULL) qpn_terminate(bgp_nexus); - - if (cli_nexus != NULL) - qpn_terminate(cli_nexus); - } - else - { - bgp_exit (0); } + + if (cli_nexus != NULL) + qpn_terminate(cli_nexus); } /* SIGUSR1 handler. */ @@ -340,8 +338,11 @@ bgp_exit (int status) if (CONF_BGP_DEBUG (normal, NORMAL)) log_memstats_stderr ("bgpd"); - routing_nexus = qpn_free(routing_nexus); - bgp_nexus = qpn_free(bgp_nexus); + if (qpthreads_enabled) + { + routing_nexus = qpn_free(routing_nexus); + bgp_nexus = qpn_free(bgp_nexus); + } cli_nexus = qpn_free(cli_nexus); qexit (status); @@ -364,6 +365,17 @@ init_second_stage(int pthreads) { qlib_init_second_stage(pthreads); bgp_peer_index_mutex_init(NULL); + + /* if using pthreads create additional mutexes */ + if (pthreads) + { + bgp_nexus = qpn_init_new(cli_nexus, 0); + routing_nexus = qpn_init_new(cli_nexus, 0); + } + + /* legacy threads are executed in routing_nexus */ + routing_nexus->master = master; + vty_init_r(cli_nexus, routing_nexus); } /* Main routine of bgpd. Treatment of argument and start bgp finite state machine is handled at here. */ @@ -375,7 +387,6 @@ main (int argc, char **argv) int daemon_mode = 0; int dryrun = 0; char *progname; - struct thread thread; int tmp_port; /* Set umask before anything for security */ @@ -393,6 +404,11 @@ main (int argc, char **argv) zlog_default = openzlog (progname, ZLOG_BGP, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); + /* Make nexus for main thread, always needed */ + cli_nexus = qpn_init_new(cli_nexus, 1); /* main thread */ + bgp_nexus = cli_nexus; /* use main thread for now */ + routing_nexus = cli_nexus; /* use main thread for now */ + /* BGP master init. */ bgp_master_init (); @@ -518,15 +534,6 @@ main (int argc, char **argv) if (!qpthreads_enabled) init_second_stage(0); - if (qpthreads_enabled) - { - cli_nexus = qpn_init_main(cli_nexus); /* main thread */ - bgp_nexus = qpn_init_bgp(bgp_nexus); - routing_nexus = qpn_init_bgp(routing_nexus); - - vty_init_r(cli_nexus, bgp_nexus); - } - /* Make bgp vty socket. */ vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH); @@ -539,32 +546,39 @@ main (int argc, char **argv) (bm->address ? bm->address : "<all>"), (int)bm->port); + /* in-thread initialization and finalization. + * NB if !qpthreads_enabled then there is only 1 nexus object + * with all nexus pointers being alises for it. So if different + * logical nexus need their own init or final then will need a single + * init or final routine. + */ + bgp_nexus->in_thread_init = bgp_in_thread_init; + bgp_nexus->in_thread_final = bgp_close_listeners; - /* Launch finite state machines */ + /* Launch finite state machine(s) */ if (qpthreads_enabled) { void * thread_result = NULL; - /* TODO: exec routing_nexus */ - /* qpn_exec(routing_nexus); */ + qpn_exec(routing_nexus); qpn_exec(bgp_nexus); qpn_exec(cli_nexus); /* must be last to start - on main thread */ /* terminating, wait for all threads to finish */ - /* TODO: join with routing_nexus */ - /* thread_result = qpt_thread_join(routing_nexus->thread_id); */ + thread_result = qpt_thread_join(routing_nexus->thread_id); thread_result = qpt_thread_join(bgp_nexus->thread_id); - bgp_exit(0); } else { - /* Start finite state machine, here we go! */ - while (thread_fetch (master, &thread)) - thread_call (&thread); + qpn_exec(cli_nexus); /* only nexus - on main thread */ } - /* Not reached. */ - return (0); + bgp_exit(0); } - +/* bgp_nexus in-thread initialization */ +static void +bgp_in_thread_init(void) +{ + bgp_open_listeners(bm->port, bm->address); +} diff --git a/bgpd/bgp_msg_read.c b/bgpd/bgp_msg_read.c index 4e581f4f..bbe8796d 100644 --- a/bgpd/bgp_msg_read.c +++ b/bgpd/bgp_msg_read.c @@ -30,6 +30,7 @@ #include "bgpd/bgp_session.h" #include "bgpd/bgp_open_state.h" #include "bgpd/bgp_fsm.h" +#include "bgpd/bgp_vty.h" diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 0f02ae38..10b3eba8 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -323,7 +323,7 @@ bgp_init_listener(int sock, struct sockaddr *sa, socklen_t salen) listener = XCALLOC(MTYPE_BGP_LISTENER, sizeof(struct bgp_listener)) ; qps_file_init_new(&listener->qf, NULL) ; - qps_add_file(p_bgp_engine->selection, &listener->qf, sock, listener) ; + qps_add_file(bgp_nexus->selection, &listener->qf, sock, listener) ; qps_enable_mode(&listener->qf, qps_read_mnum, bgp_accept_action) ; memcpy(&listener->su, sa, salen) ; diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index f432f7a7..7814e111 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -613,7 +613,7 @@ bgp_write_proceed (struct peer *peer) #endif /*------------------------------------------------------------------------------ -/* Write packets to the peer -- subject to the XON flow control. + * Write packets to the peer -- subject to the XON flow control. * * Empties the obuf queue first. * diff --git a/bgpd/bgp_peer.c b/bgpd/bgp_peer.c index fa5a0d1c..8f84a0ef 100644 --- a/bgpd/bgp_peer.c +++ b/bgpd/bgp_peer.c @@ -897,6 +897,35 @@ peer_free (struct peer *peer) XFREE (MTYPE_BGP_PEER, peer); } +void +peer_nsf_stop (struct peer *peer) +{ + afi_t afi; + safi_t safi; + + UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT); + UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE); + + for (afi = AFI_IP ; afi < AFI_MAX ; afi++) + for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++) + peer->nsf[afi][safi] = 0; + + if (peer->t_gr_restart) + { + BGP_TIMER_OFF (peer->t_gr_restart); + if (BGP_DEBUG (events, EVENTS)) + zlog_debug ("%s graceful restart timer stopped", peer->host); + } + if (peer->t_gr_stale) + { + BGP_TIMER_OFF (peer->t_gr_stale); + if (BGP_DEBUG (events, EVENTS)) + zlog_debug ("%s graceful restart stalepath timer stopped", peer->host); + } + bgp_clear_route_all (peer); +} + + /* Disable then enable the peer. Sends notification. */ void bgp_peer_reenable(bgp_peer peer, bgp_notify notification) diff --git a/bgpd/bgp_peer.h b/bgpd/bgp_peer.h index c3c8b88d..2a8eb78a 100644 --- a/bgpd/bgp_peer.h +++ b/bgpd/bgp_peer.h @@ -493,5 +493,8 @@ peer_delete (struct peer *peer); extern void peer_free (struct peer *peer); +extern void +peer_nsf_stop (struct peer *peer); + #endif /* _QUAGGA_BGP_PEER_H */ diff --git a/bgpd/bgp_session.c b/bgpd/bgp_session.c index 0aae7168..5ab0f3b8 100644 --- a/bgpd/bgp_session.c +++ b/bgpd/bgp_session.c @@ -371,7 +371,7 @@ bgp_session_do_disable(mqueue_block mqb, mqb_flag_t flag) struct bgp_session_disable_args* args = mqb_get_args(mqb) ; /* Immediately discard any other messages for this session. */ - mqueue_revoke(p_bgp_engine->queue, session) ; + mqueue_revoke(bgp_nexus->queue, session) ; /* Get the FSM to send any notification and close connections */ bgp_fsm_disable_session(session, args->notification) ; diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 442ef607..d7baa608 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -959,36 +959,6 @@ peer_deactivate (struct peer *peer, afi_t afi, safi_t safi) return 0; } -static void -peer_nsf_stop (struct peer *peer) -{ - afi_t afi; - safi_t safi; - - UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT); - UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE); - - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++) - peer->nsf[afi][safi] = 0; - - if (peer->t_gr_restart) - { - BGP_TIMER_OFF (peer->t_gr_restart); - if (BGP_DEBUG (events, EVENTS)) - zlog_debug ("%s graceful restart timer stopped", peer->host); - } - if (peer->t_gr_stale) - { - BGP_TIMER_OFF (peer->t_gr_stale); - if (BGP_DEBUG (events, EVENTS)) - zlog_debug ("%s graceful restart stalepath timer stopped", peer->host); - } - bgp_clear_route_all (peer); -} - - - static int peer_group_cmp (struct peer_group *g1, struct peer_group *g2) { diff --git a/lib/command.c b/lib/command.c index c3c9145d..574e45bf 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1992,7 +1992,7 @@ node_parent ( enum node_type node ) /* Execute command by argument vline vector. */ static int cmd_execute_command_real (vector vline, struct vty *vty, - struct cmd_element **cmd, qpn_nexus bgp_nexus) + struct cmd_element **cmd, qpn_nexus dest_nexus) { unsigned int i; unsigned int index; @@ -2111,7 +2111,7 @@ cmd_execute_command_real (vector vline, struct vty *vty, if (qpthreads_enabled && !(matched_element->attr & CMD_ATTR_CALL)) { /* Don't do it now, but send to bgp qpthread */ - cq_enqueue(matched_element, vty, argc, argv, bgp_nexus); + cq_enqueue(matched_element, vty, argc, argv, dest_nexus); return CMD_QUEUED; } else @@ -2122,7 +2122,7 @@ cmd_execute_command_real (vector vline, struct vty *vty, int cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd, - qpn_nexus bgp_nexus, int vtysh) { + qpn_nexus dest_nexus, int vtysh) { int ret, saved_ret, tried = 0; enum node_type onode, try_node; @@ -2143,7 +2143,7 @@ cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd, vector_set_index (shifted_vline, index-1, vector_lookup(vline, index)); } - ret = cmd_execute_command_real (shifted_vline, vty, cmd, bgp_nexus); + ret = cmd_execute_command_real (shifted_vline, vty, cmd, dest_nexus); vector_free(shifted_vline); vty_set_node(vty, onode); @@ -2151,7 +2151,7 @@ cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd, } - saved_ret = ret = cmd_execute_command_real (vline, vty, cmd, bgp_nexus); + saved_ret = ret = cmd_execute_command_real (vline, vty, cmd, dest_nexus); if (vtysh) return saved_ret; @@ -2162,7 +2162,7 @@ cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd, { try_node = node_parent(try_node); vty_set_node(vty, try_node); - ret = cmd_execute_command_real (vline, vty, cmd, bgp_nexus); + ret = cmd_execute_command_real (vline, vty, cmd, dest_nexus); tried = 1; if (ret == CMD_SUCCESS || ret == CMD_WARNING) { diff --git a/lib/qpnexus.c b/lib/qpnexus.c index 5ecb97cf..98bd767c 100644 --- a/lib/qpnexus.c +++ b/lib/qpnexus.c @@ -28,12 +28,8 @@ /* prototypes */ static void* qpn_start(void* arg); -static void* qpn_start_bgp(void* arg); static void qpn_in_thread_init(qpn_nexus qpn); -/* Master of the threads. */ -extern struct thread_master *master; - /*============================================================================== * Quagga Nexus Interface -- qpn_xxxx * @@ -50,54 +46,17 @@ extern struct thread_master *master; * Returns the qpn_nexus. */ qpn_nexus -qpn_init_new(qpn_nexus qpn) +qpn_init_new(qpn_nexus qpn, int main_thread) { if (qpn == NULL) qpn = XCALLOC(MTYPE_QPN_NEXUS, sizeof(struct qpn_nexus)) ; else memset(qpn, 0, sizeof(struct qpn_nexus)) ; - return qpn; -} - -/* Initialize main qpthread */ -qpn_nexus -qpn_init_main(qpn_nexus qpn) -{ - qpn = qpn_init_new(qpn); - qpn->selection = qps_selection_init_new(qpn->selection); - qpn->pile = qtimer_pile_init_new(qpn->pile); - qpn->queue = mqueue_init_new(qpn->queue, mqt_signal_unicast); - qpn->main_thread = 1; - qpn->start = qpn_start; - - return qpn; -} - -/* Initialize bgp engine's qpthread */ -qpn_nexus -qpn_init_bgp(qpn_nexus qpn) -{ - qpn = qpn_init_new(qpn); - qpn->queue = mqueue_init_new(qpn->queue, mqt_signal_unicast); - qpn->start = qpn_start_bgp; - - return qpn; -} - -/* Initialize Routing engine's qpthread - * - * Although not expected to do I/O we still use qps_selection (pselect) as - * the mechanism to wait for either a timeout or a signal from the message - * queue. -*/ -qpn_nexus -qpn_init_routing(qpn_nexus qpn) -{ - qpn = qpn_init_new(qpn); qpn->selection = qps_selection_init_new(qpn->selection); qpn->pile = qtimer_pile_init_new(qpn->pile); qpn->queue = mqueue_init_new(qpn->queue, mqt_signal_unicast); + qpn->main_thread = main_thread; qpn->start = qpn_start; return qpn; @@ -155,9 +114,30 @@ qpn_exec(qpn_nexus qpn) } } -/* Thread routine, complete init, then run finite state machine - * using mqueue, qps_selection and qtimer -*/ +/*============================================================================== + * Pthread routine + * + * Processes: + * + * 1) Main thread only -- signals. + * + * 2) Pending work -- local queue. + * + * 3) messages coming from other pthreads -- mqueue_queue. + * + * 4) I/O -- qpselect + * + * This deals with all active sockets for read/write/connect/accept. + * + * Each time a socket is readable, one message is read and dispatched. + * The pselect timeout is set to be when the next timer is due. + * + * 5) Timers -- qtimers + * + * 6) Legacy threads. To deal with legacy timer mechanism. + * + * + */ static void* qpn_start(void* arg) { @@ -165,6 +145,7 @@ qpn_start(void* arg) mqueue_block mqb; int actions; qtime_mono_t now; + struct thread thread; /* now in our thread, complete initialisation */ qpn_in_thread_init(qpn); @@ -176,13 +157,8 @@ qpn_start(void* arg) if (qpn->main_thread) quagga_sigevent_process (); - /* process timers */ - now = qt_get_monotonic(); - while (qtimer_pile_dispatch_next(qpn->pile, now)) - { - } - - /* drain the message queue, will be waiting when it's empty */ + /* drain the message queue, will be in waiting for signal state + * when it's empty */ for (;;) { mqb = mqueue_dequeue(qpn->queue, 1, qpn->mts) ; @@ -193,6 +169,7 @@ qpn_start(void* arg) } /* block for some input, output, signal or timeout */ + now = qt_get_monotonic(); actions = qps_pselect(qpn->selection, qtimer_pile_top_time(qpn->pile, now + QTIME(MAX_PSELECT_TIMOUT)) ); @@ -201,43 +178,27 @@ qpn_start(void* arg) actions = qps_dispatch_next(qpn->selection) ; mqueue_done_waiting(qpn->queue, qpn->mts); - } - return NULL; -} - -/* Bgp engine's qpthread, complete init, then run finite state machine - * using legacy threads -*/ -static void* -qpn_start_bgp(void* arg) -{ - qpn_nexus qpn = arg; - struct thread thread; - mqueue_block mqb; - - /* now in our thread, complete initialisation */ - qpn_in_thread_init(qpn); - - while (!qpn->terminate) - { - /* drain the message queue, will be waiting when it's empty */ - for (;;) + /* process timers */ + now = qt_get_monotonic(); + while (qtimer_pile_dispatch_next(qpn->pile, now)) { - mqb = mqueue_dequeue(qpn->queue, 1, qpn->mts) ; - if (mqb == NULL) - break; - - mqb_dispatch(mqb, mqb_action); } - /* TODO: use qpselect stuff */ - if (thread_fetch (master, &thread)) - thread_call (&thread); - - mqueue_done_waiting(qpn->queue, qpn->mts); + /* legacy threads */ + /* TODO: legacy threads must not pselect. How is the pselect above + * to know when to timeout for legacy timers? */ + if (qpn->master != NULL) + { + if (thread_fetch (qpn->master, &thread)) + thread_call (&thread); + } } + /* last bit of code to run in this thread */ + if (qpn->in_thread_final) + qpn->in_thread_final(); + return NULL; } @@ -281,6 +242,10 @@ qpn_in_thread_init(qpn_nexus qpn) qpn->mts = mqueue_thread_signal_init(qpn->mts, qpn->thread_id, SIGMQUEUE); if (qpn->selection != NULL) qps_set_signal(qpn->selection, SIGMQUEUE, newmask); + + /* custom in-thread initialization */ + if (qpn->in_thread_init != NULL) + qpn->in_thread_init(); } /* Ask the thread to terminate itself quickly and cleanly */ diff --git a/lib/qpnexus.h b/lib/qpnexus.h index 69fe8044..c717ed23 100644 --- a/lib/qpnexus.h +++ b/lib/qpnexus.h @@ -80,19 +80,28 @@ struct qpn_nexus mqueue_queue queue; mqueue_thread_signal mts; - /* qpthread routine */ + /* legacy threads */ + struct thread_master *master; + + /* qpthread routine, can override */ void* (*start)(void*); + /* in-thread initialize, can override. Called within the thread + * after all other initializion just before thread loop */ + void (*in_thread_init)(void); + + /* in-thread finalize, can override. Called within thread + * just before thread dies. Nexus components all exist but + * thread loop is no longer executed */ + void (*in_thread_final)(void); + }; /*============================================================================== * Functions */ -extern qpn_nexus qpn_init_new(qpn_nexus qtn); -extern qpn_nexus qpn_init_main(qpn_nexus qtn); -extern qpn_nexus qpn_init_bgp(qpn_nexus qtn); -extern qpn_nexus qpn_init_routing(qpn_nexus qtn); +extern qpn_nexus qpn_init_new(qpn_nexus qtn, int main_thread); extern void qpn_exec(qpn_nexus qtn); extern void qpn_terminate(qpn_nexus qpn); extern qpn_nexus qpn_free(qpn_nexus qpn); @@ -141,7 +141,7 @@ char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG; /* Master of the threads. */ static struct thread_master *master = NULL; static qpn_nexus cli_nexus = NULL; -static qpn_nexus bgp_nexus = NULL; +static qpn_nexus routing_nexus = NULL; /* VTY standard output function. vty == NULL or VTY_SHELL => stdout */ int @@ -553,7 +553,7 @@ vty_command (struct vty *vty, char *buf) #endif /* CONSUMED_TIME_CHECK */ UNLOCK - ret = cmd_execute_command (vline, vty, NULL, bgp_nexus, 0); + ret = cmd_execute_command (vline, vty, NULL, routing_nexus, 0); LOCK /* Get the name of the protocol if any */ @@ -3644,10 +3644,10 @@ vty_set_lines(struct vty *vty, int lines) /* qpthreads: Install vty's own commands like `who' command. */ void -vty_init_r (qpn_nexus cli_n, qpn_nexus bgp_n) +vty_init_r (qpn_nexus cli_n, qpn_nexus routing_n) { cli_nexus = cli_n; - bgp_nexus = bgp_n; + routing_nexus = routing_n; qpt_mutex_init(&vty_mutex, qpt_mutex_recursive); } |