diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | lib/memtypes.c | 1 | ||||
-rw-r--r-- | lib/vty.c | 416 | ||||
-rw-r--r-- | lib/vty.h | 15 |
4 files changed, 351 insertions, 85 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 4ac42d37..3184a9b6 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -13,7 +13,7 @@ libzebra_la_SOURCES = \ filter.c routemap.c distribute.c stream.c str.c log.c plist.c \ 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 symtab.c heap.c \ - qtime.c qpthreads.c mqueue.c qpselect.c qtimers.c + qtime.c qpthreads.c mqueue.c qpselect.c qtimers.c qpnexus.c BUILT_SOURCES = memtypes.h route_types.h @@ -29,7 +29,7 @@ pkginclude_HEADERS = \ plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \ privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \ workqueue.h route_types.h symtab.h heap.h \ - qtime.h qpthreads.h mqueue.h qpselect.h qtimers.h + qtime.h qpthreads.h mqueue.h qpselect.h qtimers.h qpnexus.h EXTRA_DIST = regex.c regex-gnu.h memtypes.awk route_types.awk route_types.txt diff --git a/lib/memtypes.c b/lib/memtypes.c index 18d42a9e..8146f21f 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -39,6 +39,7 @@ struct memory_list memory_list_lib[] = { MTYPE_QPS_FILE, "qpselect file" }, { MTYPE_QTIMER_PILE, "qtimer pile structure" }, { MTYPE_QTIMER, "qtimer timer" }, + { MTYPE_QPN_NEXUS, "qtn nexus" }, { MTYPE_VTY, "VTY" }, { MTYPE_VTY_OUT_BUF, "VTY output buffer" }, { MTYPE_VTY_HIST, "VTY history" }, @@ -39,6 +39,7 @@ #include <arpa/telnet.h> #include "qpthreads.h" +#include "qpnexus.h" /* Needs to be qpthread safe */ qpt_mutex_t* vty_mutex = NULL; @@ -88,6 +89,13 @@ static void uty_hello (struct vty *vty); static void uty_close (struct vty *vty); static int uty_config_unlock (struct vty *vty); static int uty_shell (struct vty *vty); +static int uty_read (struct vty *vty, int vty_sock); +static int uty_flush (struct vty *vty, int vty_sock); +static void vty_event_t (enum event event, int sock, struct vty *vty); +static void vty_event_r (enum event event, int sock, struct vty *vty); +static int uty_accept (int accept_sock); +static int uty_timeout (struct vty *vty); +static void vty_timeout_r (qtimer qtr, void* timer_info, qtime_t when); /* Extern host structure from command.c */ extern struct host host; @@ -105,10 +113,10 @@ static char *vty_accesslist_name = NULL; static char *vty_ipv6_accesslist_name = NULL; /* VTY server thread. */ -vector Vvty_serv_thread; +static vector Vvty_serv_thread; /* Current directory. */ -char *vty_cwd = NULL; +static char *vty_cwd = NULL; /* Configure lock. */ static int vty_config; @@ -123,6 +131,10 @@ static u_char restricted_mode = 0; /* Integrated configuration file path */ char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG; +/* Master of the threads. */ +static struct thread_master *master = NULL; +static qpn_nexus master_nexus = NULL; + /* VTY standard output function. vty == NULL or VTY_SHELL => stdout */ int vty_out (struct vty *vty, const char *format, ...) @@ -1487,20 +1499,45 @@ vty_buffer_reset (struct vty *vty) vty_redraw_line (vty); } -/* Callback: Read data via vty socket. */ +/* Callback: qpthreads., Read data via vty socket. */ +static void +vty_read_r (qps_file qf, void* file_info) +{ + int vty_sock = qf->fd; + struct vty *vty = (struct vty *)file_info; + + LOCK + + /* is this necessary? */ + qps_disable_modes(qf, qps_read_mbit); + uty_read(vty, vty_sock); + + UNLOCK +} + +/* Callback: threads. Read data via vty socket. */ static int vty_read (struct thread *thread) { - int i; - int nbytes; - unsigned char buf[VTY_READ_BUFSIZ]; - int vty_sock = THREAD_FD (thread); struct vty *vty = THREAD_ARG (thread); + int result ; LOCK vty->t_read = NULL; + result = uty_read(vty, vty_sock); + + UNLOCK + return result; +} + +static int +uty_read (struct vty *vty, int vty_sock) +{ + int i; + int nbytes; + unsigned char buf[VTY_READ_BUFSIZ]; /* Read raw data from socket */ if ((nbytes = read (vty->fd, buf, VTY_READ_BUFSIZ)) <= 0) @@ -1510,7 +1547,6 @@ vty_read (struct thread *thread) if (ERRNO_IO_RETRY(errno)) { vty_event (VTY_READ, vty_sock, vty); - UNLOCK return 0; } vty->monitor = 0; /* disable monitoring to avoid infinite recursion */ @@ -1699,22 +1735,40 @@ vty_read (struct thread *thread) vty_event (VTY_READ, vty_sock, vty); } - UNLOCK - return 0; } -/* Callback: Flush buffer to the vty. */ +/* Callback: qpthreads. Flush buffer to the vty. */ +static void +vty_flush_r (qps_file qf, void* file_info) +{ + int vty_sock = qf->fd; + struct vty *vty = (struct vty *)file_info; + + LOCK + + qps_disable_modes(qf, qps_write_mbit); + + /* Temporary disable read thread. */ + if ((vty->lines == 0)) + { + qps_disable_modes(qf, qps_read_mbit); + } + + uty_flush(vty, vty_sock); + + UNLOCK +} + +/* Callback: threads. Flush buffer to the vty. */ static int vty_flush (struct thread *thread) { - int erase; - buffer_status_t flushrc; int vty_sock = THREAD_FD (thread); struct vty *vty = THREAD_ARG (thread); + int result; LOCK - vty->t_write = NULL; /* Temporary disable read thread. */ @@ -1723,6 +1777,17 @@ vty_flush (struct thread *thread) thread_cancel (vty->t_read); vty->t_read = NULL; } + result = uty_flush(vty, vty_sock); + + UNLOCK + return result; +} + +static int +uty_flush (struct vty *vty, int vty_sock) +{ + int erase; + buffer_status_t flushrc; /* Function execution continue. */ erase = ((vty->status == VTY_MORE || vty->status == VTY_MORELINE)); @@ -1765,8 +1830,6 @@ vty_flush (struct thread *thread) break; } - UNLOCK - return 0; } @@ -1839,6 +1902,15 @@ vty_create (int vty_sock, union sockunion *su) vty_prompt (vty); + if (master_nexus) + { + vty->qf = qps_file_init_new(vty->qf, NULL); + qps_add_file(master_nexus->selection, vty->qf, vty_sock, vty); + qps_set_action(vty->qf, qps_read_mbit, vty_read_r); + qps_set_action(vty->qf, qps_write_mbit, vty_flush_r); + vty->qtr = qtimer_init_new(vty->qtr, master_nexus->pile, vty_timeout_r, vty); + } + /* Add read/write thread. */ vty_event (VTY_WRITE, vty_sock, vty); vty_event (VTY_READ, vty_sock, vty); @@ -1846,23 +1918,44 @@ vty_create (int vty_sock, union sockunion *su) return vty; } -/* Callback: Accept connection from the network. */ +/* Callback: qpthreads. Accept connection from the network. */ +static void +vty_accept_r (qps_file qf, void* file_info) +{ + LOCK + + int accept_sock = qf->fd; + uty_accept(accept_sock); + + UNLOCK +} + +/* Callback: threads. Accept connection from the network. */ static int vty_accept (struct thread *thread) { + int result; + + LOCK + + int accept_sock = THREAD_FD (thread); + result = uty_accept(accept_sock); + + UNLOCK + return result; +} + +static int +uty_accept (int accept_sock) +{ int vty_sock; struct vty *vty; union sockunion su; int ret; unsigned int on; - int accept_sock; struct prefix *p = NULL; struct access_list *acl = NULL; - LOCK - - accept_sock = THREAD_FD (thread); - /* We continue hearing vty socket. */ vty_event (VTY_SERV, accept_sock, NULL); @@ -1873,7 +1966,6 @@ vty_accept (struct thread *thread) if (vty_sock < 0) { uzlog (NULL, LOG_WARNING, "can't accept vty socket : %s", safe_strerror (errno)); - UNLOCK return -1; } set_nonblocking(vty_sock); @@ -1896,8 +1988,6 @@ vty_accept (struct thread *thread) vty_event (VTY_SERV, accept_sock, NULL); prefix_free (p); - - UNLOCK return 0; } } @@ -1919,8 +2009,6 @@ vty_accept (struct thread *thread) vty_event (VTY_SERV, accept_sock, NULL); prefix_free (p); - - UNLOCK return 0; } } @@ -1937,7 +2025,6 @@ vty_accept (struct thread *thread) vty = vty_create (vty_sock, &su); - UNLOCK return 0; } @@ -2153,18 +2240,36 @@ vty_serv_un (const char *path) /* #define VTYSH_DEBUG 1 */ +/* Callback: qpthreads. Accept connection */ +void int +vtysh_accept_r (qps_file qf, void* file_info) +{ + LOCK + int accept_sock = qf->fd; + utysh_accept (accept_sock); + UNLOCK +} + +/* Callback: threads. Accept connection */ static int vtysh_accept (struct thread *thread) { - int accept_sock; + LOCK + int accept_sock = THREAD_FD (thread); + result = utysh_accept (accept_sock); + UNLOCK + return result; +} + +static int +utysh_accept (int accept_sock) +{ int sock; int client_len; struct sockaddr_un client; struct vty *vty; - LOCK - - accept_sock = THREAD_FD (thread); + assert(vty_lock_count); vty_event (VTYSH_SERV, accept_sock, NULL); @@ -2177,7 +2282,6 @@ vtysh_accept (struct thread *thread) if (sock < 0) { uzlog (NULL, LOG_WARNING, "can't accept vty socket : %s", safe_strerror (errno)); - UNLOCK return -1; } @@ -2186,7 +2290,6 @@ vtysh_accept (struct thread *thread) uzlog (NULL, LOG_WARNING, "vtysh_accept: could not set vty socket %d to non-blocking," " %s, closing", sock, safe_strerror (errno)); close (sock); - UNLOCK return -1; } @@ -2201,7 +2304,6 @@ vtysh_accept (struct thread *thread) vty_event (VTYSH_READ, sock, vty); - UNLOCK return 0; } @@ -2228,23 +2330,48 @@ vtysh_flush(struct vty *vty) return 0; } +/* Callback: qpthreads., Read data via vty socket. */ +static void +vtysh_read_r (qps_file qf, void* file_info) +{ + int vty_sock = qf->fd; + struct vty *vty = (struct vty *)file_info; + + LOCK + + /* is this necessary? */ + qps_disable_modes(qf, qps_read_mbit); + utysh_read(vty, vty_soc); + + UNLOCK +} + +/* Callback: threads. Read data via vty socket. */ static int vtysh_read (struct thread *thread) { + int vty_sock = THREAD_FD (thread); + struct vty *vty = THREAD_ARG (thread); + int result; + + LOCK + + vty->t_read = NULL; + result = uty_read(vty, vty_soc); + + UNLOCK + return result; +} + +static int +utysh_read (struct vty *vty, int sock) +{ int ret; - int sock; int nbytes; - struct vty *vty; unsigned char buf[VTY_READ_BUFSIZ]; unsigned char *p; u_char header[4] = {0, 0, 0, 0}; - LOCK - - sock = THREAD_FD (thread); - vty = THREAD_ARG (thread); - vty->t_read = NULL; - if ((nbytes = read (sock, buf, VTY_READ_BUFSIZ)) <= 0) { if (nbytes < 0) @@ -2252,7 +2379,6 @@ vtysh_read (struct thread *thread) if (ERRNO_IO_RETRY(errno)) { vty_event (VTYSH_READ, sock, vty); - UNLOCK return 0; } vty->monitor = 0; /* disable monitoring to avoid infinite recursion */ @@ -2264,7 +2390,6 @@ vtysh_read (struct thread *thread) #ifdef VTYSH_DEBUG printf ("close vtysh\n"); #endif /* VTYSH_DEBUG */ - UNLOCK return 0; } @@ -2294,18 +2419,30 @@ vtysh_read (struct thread *thread) if (!vty->t_write && (vtysh_flush(vty) < 0)) /* Try to flush results; exit if a write error occurs. */ - UNLOCK return 0; } } vty_event (VTYSH_READ, sock, vty); - UNLOCK return 0; } -/* Callback */ +/* Callback: qpthraeds. Write */ +static void +vtysh_write_r (qps_file qf, void* file_info) +{ + struct vty *vty = (struct vty *)file_info; + + LOCK + + qps_disable_modes(qf, qps_write_mbit); + vtysh_flush(vty); + + UNLOCK +} + +//* Callback: thraeds. Write */ static int vtysh_write (struct thread *thread) { @@ -2377,6 +2514,17 @@ uty_close (struct vty *vty) thread_cancel (vty->t_write); if (vty->t_timeout) thread_cancel (vty->t_timeout); + if (vty->qf) + { + qps_remove_file(vty->qf); + qps_file_free(vty->qf); + vty->qf = NULL; + } + if (vty->qtr) + { + qtimer_free(vty->qtr); + vty->qtr = NULL; + } /* Flush buffer. */ buffer_flush_all (vty->obuf, vty->fd); @@ -2408,16 +2556,33 @@ uty_close (struct vty *vty) XFREE (MTYPE_VTY, vty); } -/* Callback: When time out occur output message then close connection. */ +/* Callback: qpthreads. When time out occur output message then close connection. */ +static void +vty_timeout_r (qtimer qtr, void* timer_info, qtime_t when) +{ + struct vty *vty = (struct vty *)timer_info; + LOCK + qtimer_unset(qtr); + uty_timeout(vty); + UNLOCK +} + +/* Callback: threads. When time out occur output message then close connection. */ static int vty_timeout (struct thread *thread) { - struct vty *vty; - - LOCK; - - vty = THREAD_ARG (thread); + int result; + struct vty *vty = THREAD_ARG (thread); + LOCK vty->t_timeout = NULL; + result = uty_timeout(vty); + UNLOCK + return result; +} + +static int +uty_timeout (struct vty *vty) +{ vty->v_timeout = 0; /* Clear buffer*/ @@ -2428,7 +2593,6 @@ vty_timeout (struct thread *thread) vty->status = VTY_CLOSE; uty_close (vty); - UNLOCK return 0; } @@ -2723,12 +2887,19 @@ uty_config_unlock (struct vty *vty) return vty->config; } -/* Master of the threads. */ -static struct thread_master *master; - static void vty_event (enum event event, int sock, struct vty *vty) { + if (master_nexus) + vty_event_r(event, sock, vty); + else + vty_event_t(event, sock, vty); +} + +/* thread event setter */ +static void +vty_event_t (enum event event, int sock, struct vty *vty) + { struct thread *vty_serv_thread; assert(vty_lock_count); @@ -2765,7 +2936,7 @@ vty_event (enum event event, int sock, struct vty *vty) case VTY_WRITE: if (! vty->t_write) vty->t_write = thread_add_write (master, vty_flush, vty, sock); - break; + break; case VTY_TIMEOUT_RESET: if (vty->t_timeout) { @@ -2781,6 +2952,72 @@ vty_event (enum event event, int sock, struct vty *vty) } } +/* qpthreads event setter */ +static void +vty_event_r (enum event event, int sock, struct vty *vty) + { + + qps_file accept_file = NULL; + + assert(vty_lock_count); + + switch (event) + { + case VTY_SERV: + accept_file = vector_get_item(Vvty_serv_thread, sock); + if (accept_file == NULL) + { + accept_file = qps_file_init_new(accept_file, NULL); + qps_add_file(master_nexus->selection, accept_file, sock, NULL); + qps_set_action(accept_file, qps_read_mbit, vty_accept_r); + vector_set_index(Vvty_serv_thread, sock, accept_file); + } + qps_enable_mode(accept_file, qps_read_mbit, NULL) ; + break; +#ifdef VTYSH + case VTYSH_SERV: + accept_file = vector_get_item(Vvty_serv_thread, sock); + if (accept_file == NULL) + { + accept_file = qps_file_init_new(accept_file, NULL); + qps_add_file(master, accept_file, sock, NULL); + qps_set_action(accept_file, qps_read_mbit, vtysh_accept_r); + vector_set_index(Vvty_serv_thread, sock, accept_file); + } + qps_enable_mode(accept_file, qps_read_mbit, NULL) ; + break; + case VTYSH_READ: + qps_enable_mode(vty->file, qps_read_mbit, NULL) ; + break; + case VTYSH_WRITE: + qps_enable_mode(vty->file, qps_write_mbit, NULL) ; + break; +#endif /* VTYSH */ + case VTY_READ: + qps_enable_mode(vty->qf, qps_read_mbit, NULL) ; + + /* Time out treatment. */ + if (vty->v_timeout) + { + qtimer_set(vty->qtr, qtimer_time_future(QTIME(vty->v_timeout)), NULL) ; + } + break; + case VTY_WRITE: + qps_enable_mode(vty->qf, qps_write_mbit, NULL) ; + break; + case VTY_TIMEOUT_RESET: + if (vty->v_timeout) + { + qtimer_set(vty->qtr, qtimer_time_future(QTIME(vty->v_timeout)), NULL) ; + } + else + { + qtimer_unset(vty->qtr); + } + break; + } +} + DEFUN (config_who, config_who_cmd, "who", @@ -3106,6 +3343,7 @@ vty_reset () unsigned int i; struct vty *vty; struct thread *vty_serv_thread; + qps_file qf; LOCK @@ -3117,13 +3355,28 @@ vty_reset () uty_close (vty); } - for (i = 0; i < vector_active (Vvty_serv_thread); i++) - if ((vty_serv_thread = vector_slot (Vvty_serv_thread, i)) != NULL) - { - thread_cancel (vty_serv_thread); - vector_slot (Vvty_serv_thread, i) = NULL; - close (i); - } + if (master_nexus) + { + for (i = 0; i < vector_active (Vvty_serv_thread); i++) + if ((qf = vector_slot (Vvty_serv_thread, i)) != NULL) + { + qps_remove_file(qf); + qps_file_free(qf); + vector_slot (Vvty_serv_thread, i) = NULL; + close (i); + } + } + else + { + assert(master); + for (i = 0; i < vector_active (Vvty_serv_thread); i++) + if ((vty_serv_thread = vector_slot (Vvty_serv_thread, i)) != NULL) + { + thread_cancel (vty_serv_thread); + vector_slot (Vvty_serv_thread, i) = NULL; + close (i); + } + } vty_timeout_val = VTY_TIMEOUT_DEFAULT; @@ -3199,15 +3452,24 @@ vty_init_vtysh () UNLOCK } -/* Install vty's own commands like `who' command. */ +/* qpthreads: Install vty's own commands like `who' command. */ void -vty_init_r (struct thread_master *master_thread) +vty_init_r (void) { + master_nexus = qpn_init_new(master_nexus); vty_mutex = qpt_mutex_init(vty_mutex, qpt_mutex_quagga); - vty_init(master_thread); + vty_init(NULL); +} + +/* create and execute our thread */ +void +vty_exec_r(void) +{ + if (master_nexus) + qpn_exec(master_nexus); } -/* Install vty's own commands like `who' command. */ +/* threads: Install vty's own commands like `who' command. */ void vty_init (struct thread_master *master_thread) { @@ -3259,16 +3521,13 @@ vty_init (struct thread_master *master_thread) } void -vty_terminate_r (void) -{ - vty_terminate(); - vty_mutex = qpt_mutex_destroy(vty_mutex, 1); -} - -void vty_terminate (void) { LOCK + + if (master_nexus) + master_nexus->terminate = 1; + if (vty_cwd) XFREE (MTYPE_TMP, vty_cwd); @@ -3279,6 +3538,9 @@ vty_terminate (void) vector_free (Vvty_serv_thread); } UNLOCK + + if (vty_mutex) + vty_mutex = qpt_mutex_destroy(vty_mutex, 1); } #undef LOCK @@ -24,6 +24,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "thread.h" #include "log.h" #include "qpthreads.h" +#include "qpselect.h" +#include "qtimers.h" #define VTY_BUFSIZ 512 #define VTY_MAXHIST 20 @@ -31,7 +33,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA /* VTY struct. */ struct vty { - /* File descripter of this vty. */ + /* File descriptor of this vty. */ int fd; /* Is this vty connect to file or not */ @@ -40,7 +42,7 @@ struct vty /* Node status of this vty */ int node; - /* What address is this vty comming from. */ + /* What address is this vty coming from. */ char *address; /* Failure count */ @@ -113,11 +115,14 @@ struct vty int config; /* Read and write thread. */ + + qps_file qf; struct thread *t_read; struct thread *t_write; /* Timeout seconds and thread. */ unsigned long v_timeout; + qtimer qtr; struct thread *t_timeout; }; @@ -212,12 +217,10 @@ extern int vty_lock_count; #endif /* Prototypes. */ -extern void vty_init_r (struct thread_master *); -extern void vty_terminate_r (void); - +extern void vty_init_r (void); +extern void vty_exec_r(void); extern void vty_init (struct thread_master *); extern void vty_init_vtysh (void); -extern void vty_terminate_r (void); extern void vty_terminate (void); extern void vty_reset (void); extern struct vty *vty_new (void); |