diff options
Diffstat (limited to 'zebra/zserv.c')
-rw-r--r-- | zebra/zserv.c | 176 |
1 files changed, 159 insertions, 17 deletions
diff --git a/zebra/zserv.c b/zebra/zserv.c index d447d065..e27db449 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -49,6 +49,8 @@ list client_list; int rtm_table_default = 0; void zebra_event (enum event event, int sock, struct zserv *client); + +extern struct thread_master *master; /* For logging of zebra meesages. */ char *zebra_command_str [] = @@ -74,6 +76,103 @@ char *zebra_command_str [] = "ZEBRA_IPV6_IMPORT_LOOKUP" }; +struct zebra_message_queue +{ + struct nsm_message_queue *next; + struct nsm_message_queue *prev; + + u_char *buf; + u_int16_t length; + u_int16_t written; +}; + +struct thread *t_write; +struct fifo message_queue; + +int +zebra_server_dequeue (struct thread *t) +{ + int sock; + int nbytes; + struct zebra_message_queue *queue; + + sock = THREAD_FD (t); + t_write = NULL; + + queue = (struct zebra_message_queue *) FIFO_HEAD (&message_queue); + if (queue) + { + nbytes = write (sock, queue->buf + queue->written, + queue->length - queue->written); + + if (nbytes <= 0) + { + if (errno != EAGAIN) + return -1; + } + else if (nbytes != (queue->length - queue->written)) + { + queue->written += nbytes; + } + else + { + FIFO_DEL (queue); + XFREE (MTYPE_TMP, queue->buf); + XFREE (MTYPE_TMP, queue); + } + } + + if (FIFO_TOP (&message_queue)) + THREAD_WRITE_ON (master, t_write, zebra_server_dequeue, NULL, sock); + + return 0; +} + +/* Enqueu message. */ +void +zebra_server_enqueue (int sock, u_char *buf, unsigned long length, + unsigned long written) +{ + struct zebra_message_queue *queue; + + queue = XCALLOC (MTYPE_TMP, sizeof (struct zebra_message_queue)); + queue->buf = XMALLOC (MTYPE_TMP, length); + memcpy (queue->buf, buf, length); + queue->length = length; + queue->written = written; + + FIFO_ADD (&message_queue, queue); + + THREAD_WRITE_ON (master, t_write, zebra_server_dequeue, NULL, sock); +} + +int +zebra_server_send_message (int sock, u_char *buf, unsigned long length) +{ + int nbytes; + + if (FIFO_TOP (&message_queue)) + { + zebra_server_enqueue (sock, buf, length, 0); + return 0; + } + + /* Send message. */ + nbytes = write (sock, buf, length); + + if (nbytes <= 0) + { + if (errno == EAGAIN) + zebra_server_enqueue (sock, buf, length, 0); + else + return -1; + } + else if (nbytes != length) + zebra_server_enqueue (sock, buf, length, nbytes); + + return 0; +} + /* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */ int zsend_interface_add (struct zserv *client, struct interface *ifp) @@ -112,7 +211,9 @@ zsend_interface_add (struct zserv *client, struct interface *ifp) /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } /* Interface deletion from zebra daemon. */ @@ -144,7 +245,9 @@ zsend_interface_delete (struct zserv *client, struct interface *ifp) /* Write packet length. */ stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } /* Interface address is added. Send ZEBRA_INTERFACE_ADDRESS_ADD to the @@ -190,7 +293,9 @@ zsend_interface_address_add (struct zserv *client, struct interface *ifp, /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } /* Interface address is deleted. Send ZEBRA_INTERFACE_ADDRESS_DELETE @@ -234,7 +339,9 @@ zsend_interface_address_delete (struct zserv *client, struct interface *ifp, /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } int @@ -267,7 +374,9 @@ zsend_interface_up (struct zserv *client, struct interface *ifp) /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } int @@ -300,7 +409,9 @@ zsend_interface_down (struct zserv *client, struct interface *ifp) /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } int @@ -357,7 +468,9 @@ zsend_ipv4_add_multipath (struct zserv *client, struct prefix *p, /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } int @@ -411,7 +524,9 @@ zsend_ipv4_delete_multipath (struct zserv *client, struct prefix *p, /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } int @@ -450,7 +565,9 @@ zsend_ipv4_add (struct zserv *client, int type, int flags, /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } int @@ -489,7 +606,9 @@ zsend_ipv4_delete (struct zserv *client, int type, int flags, /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } #ifdef HAVE_IPV6 @@ -529,7 +648,9 @@ zsend_ipv6_add (struct zserv *client, int type, int flags, /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } int @@ -585,7 +706,9 @@ zsend_ipv6_add_multipath (struct zserv *client, struct prefix *p, /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } int @@ -624,7 +747,9 @@ zsend_ipv6_delete (struct zserv *client, int type, int flags, /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } int @@ -677,7 +802,9 @@ zsend_ipv6_delete_multipath (struct zserv *client, struct prefix *p, /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } int @@ -738,7 +865,9 @@ zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr) stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } #endif /* HAVE_IPV6 */ @@ -795,7 +924,9 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr) stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } int @@ -851,7 +982,9 @@ zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p) stream_putw_at (s, 0, stream_get_endp (s)); - return writen (client->sock, s->data, stream_get_endp (s)); + zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); + + return 0; } /* Register zebra server interface information. Send current all @@ -1434,6 +1567,7 @@ zebra_write (struct thread *thread) int zebra_accept (struct thread *thread) { + int val; int accept_sock; int client_sock; struct sockaddr_in client; @@ -1450,6 +1584,11 @@ zebra_accept (struct thread *thread) return -1; } + /* Make client socket non-blocking. */ + + val = fcntl (client_sock, F_GETFL, 0); + fcntl (client_sock, F_SETFL, (val | O_NONBLOCK)); + /* Create new zebra client. */ zebra_client_create (client_sock); @@ -1807,4 +1946,7 @@ zebra_init () install_element (ENABLE_NODE, &show_ipv6_forwarding_cmd); install_element (CONFIG_NODE, &no_ipv6_forwarding_cmd); #endif /* HAVE_IPV6 */ + + FIFO_INIT(&message_queue); + t_write = NULL; } |