diff options
-rw-r--r-- | zebra/label_manager.c | 2 | ||||
-rw-r--r-- | zebra/main.c | 5 | ||||
-rw-r--r-- | zebra/table_manager.c | 2 | ||||
-rw-r--r-- | zebra/zapi_msg.c | 44 | ||||
-rw-r--r-- | zebra/zebra_mpls.c | 4 | ||||
-rw-r--r-- | zebra/zebra_mroute.c | 2 | ||||
-rw-r--r-- | zebra/zebra_ptm.c | 2 | ||||
-rw-r--r-- | zebra/zebra_ptm_redistribute.c | 4 | ||||
-rw-r--r-- | zebra/zebra_pw.c | 2 | ||||
-rw-r--r-- | zebra/zebra_rnh.c | 4 | ||||
-rw-r--r-- | zebra/zebra_vxlan.c | 24 | ||||
-rw-r--r-- | zebra/zserv.c | 190 | ||||
-rw-r--r-- | zebra/zserv.h | 51 |
13 files changed, 223 insertions, 113 deletions
diff --git a/zebra/label_manager.c b/zebra/label_manager.c index f3fa3ba94..9bfc4001b 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -350,7 +350,7 @@ void label_manager_init(char *lm_zserv_path) obuf = stream_new(ZEBRA_MAX_PACKET_SIZ); - hook_register(zapi_client_close, release_daemon_label_chunks); + hook_register(zserv_client_close, release_daemon_label_chunks); } /** diff --git a/zebra/main.c b/zebra/main.c index 9bcbaa3c2..c5246999f 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -379,10 +379,11 @@ int main(int argc, char **argv) /* Needed for BSD routing socket. */ pid = getpid(); + /* Intialize pthread library */ frr_pthread_init(); - /* This must be done only after locking pidfile (bug #403). */ - zebra_zserv_socket_init(zserv_path); + /* Start Zebra API server */ + zserv_start(zserv_path); /* Init label manager */ label_manager_init(lblmgr_path); diff --git a/zebra/table_manager.c b/zebra/table_manager.c index cb8c38443..5bcc2c40d 100644 --- a/zebra/table_manager.c +++ b/zebra/table_manager.c @@ -78,7 +78,7 @@ void table_manager_enable(ns_id_t ns_id) return; tbl_mgr.lc_list = list_new(); tbl_mgr.lc_list->del = delete_table_chunk; - hook_register(zapi_client_close, release_daemon_table_chunks); + hook_register(zserv_client_close, release_daemon_table_chunks); } /** diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 943329b19..2c19f31c7 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -162,7 +162,7 @@ int zsend_interface_add(struct zserv *client, struct interface *ifp) zserv_encode_interface(s, ifp); client->ifadd_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* Interface deletion from zebra daemon. */ @@ -174,7 +174,7 @@ int zsend_interface_delete(struct zserv *client, struct interface *ifp) zserv_encode_interface(s, ifp); client->ifdel_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } int zsend_vrf_add(struct zserv *client, struct zebra_vrf *zvrf) @@ -185,7 +185,7 @@ int zsend_vrf_add(struct zserv *client, struct zebra_vrf *zvrf) zserv_encode_vrf(s, zvrf); client->vrfadd_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* VRF deletion from zebra daemon. */ @@ -198,7 +198,7 @@ int zsend_vrf_delete(struct zserv *client, struct zebra_vrf *zvrf) zserv_encode_vrf(s, zvrf); client->vrfdel_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } int zsend_interface_link_params(struct zserv *client, struct interface *ifp) @@ -230,7 +230,7 @@ int zsend_interface_link_params(struct zserv *client, struct interface *ifp) /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or @@ -309,7 +309,7 @@ int zsend_interface_address(int cmd, struct zserv *client, stream_putw_at(s, 0, stream_get_endp(s)); client->connected_rt_add_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } static int zsend_interface_nbr_address(int cmd, struct zserv *client, @@ -340,7 +340,7 @@ static int zsend_interface_nbr_address(int cmd, struct zserv *client, /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* Interface address addition. */ @@ -438,7 +438,7 @@ int zsend_interface_vrf_update(struct zserv *client, struct interface *ifp, stream_putw_at(s, 0, stream_get_endp(s)); client->if_vrfchg_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* Add new nbr connected IPv6 address */ @@ -511,7 +511,7 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp) else client->ifdown_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p, @@ -602,7 +602,7 @@ int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p, zebra_route_string(api.type), api.vrf_id, buf_prefix); } - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* @@ -655,7 +655,7 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client, stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } int zsend_route_notify_owner(struct route_entry *re, struct prefix *p, @@ -665,7 +665,7 @@ int zsend_route_notify_owner(struct route_entry *re, struct prefix *p, struct stream *s; uint8_t blen; - client = zebra_find_client(re->type, re->instance); + client = zserv_find_client(re->type, re->instance); if (!client || !client->notify_owner) { if (IS_ZEBRA_DEBUG_PACKET) { char buff[PREFIX_STRLEN]; @@ -703,7 +703,7 @@ int zsend_route_notify_owner(struct route_entry *re, struct prefix *p, stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } void zsend_rule_notify_owner(struct zebra_pbr_rule *rule, @@ -739,7 +739,7 @@ void zsend_rule_notify_owner(struct zebra_pbr_rule *rule, stream_putw_at(s, 0, stream_get_endp(s)); - zebra_server_send_message(client, s); + zserv_send_message(client, s); } void zsend_ipset_notify_owner(struct zebra_pbr_ipset *ipset, @@ -769,7 +769,7 @@ void zsend_ipset_notify_owner(struct zebra_pbr_ipset *ipset, stream_put(s, ipset->ipset_name, ZEBRA_IPSET_NAME_SIZE); stream_putw_at(s, 0, stream_get_endp(s)); - zebra_server_send_message(client, s); + zserv_send_message(client, s); } void zsend_ipset_entry_notify_owner(struct zebra_pbr_ipset_entry *ipset, @@ -799,7 +799,7 @@ void zsend_ipset_entry_notify_owner(struct zebra_pbr_ipset_entry *ipset, stream_put(s, ipset->backpointer->ipset_name, ZEBRA_IPSET_NAME_SIZE); stream_putw_at(s, 0, stream_get_endp(s)); - zebra_server_send_message(client, s); + zserv_send_message(client, s); } void zsend_iptable_notify_owner(struct zebra_pbr_iptable *iptable, @@ -828,7 +828,7 @@ void zsend_iptable_notify_owner(struct zebra_pbr_iptable *iptable, stream_putl(s, iptable->unique); stream_putw_at(s, 0, stream_get_endp(s)); - zebra_server_send_message(client, s); + zserv_send_message(client, s); } /* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */ @@ -855,7 +855,7 @@ int zsend_router_id_update(struct zserv *client, struct prefix *p, /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* @@ -873,7 +873,7 @@ int zsend_pw_update(struct zserv *client, struct zebra_pw *pw) /* Put length at the first point of the stream. */ stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* Send response to a get label chunk request to client */ @@ -952,7 +952,7 @@ static int zsend_assign_table_chunk_response(struct zserv *client, /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } static int zsend_table_manager_connect_response(struct zserv *client, @@ -968,7 +968,7 @@ static int zsend_table_manager_connect_response(struct zserv *client, stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* Inbound message handling ------------------------------------------------ */ @@ -2194,7 +2194,7 @@ static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf) stream_putl(s, multipath_num); stream_putw_at(s, 0, stream_get_endp(s)); - zebra_server_send_message(client, s); + zserv_send_message(client, s); } /* Tie up route-type and client->sock */ diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 3ad640653..e040808e0 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -463,7 +463,7 @@ static int fec_send(zebra_fec_t *fec, struct zserv *client) stream_put_prefix(s, &rn->p); stream_putl(s, fec->label); stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* @@ -2916,5 +2916,5 @@ void zebra_mpls_init(void) if (!mpls_processq_init(&zebrad)) mpls_enabled = 1; - hook_register(zapi_client_close, zebra_mpls_cleanup_fecs_for_client); + hook_register(zserv_client_close, zebra_mpls_cleanup_fecs_for_client); } diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c index 042bd3769..3af3cd5bb 100644 --- a/zebra/zebra_mroute.c +++ b/zebra/zebra_mroute.c @@ -67,5 +67,5 @@ stream_failure: stream_putl(s, suc); stream_putw_at(s, 0, stream_get_endp(s)); - zebra_server_send_message(client, s); + zserv_send_message(client, s); } diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index d20f93f52..8c23bf34c 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -126,7 +126,7 @@ void zebra_ptm_init(void) ptm_cb.ptm_sock = -1; - hook_register(zapi_client_close, zebra_ptm_bfd_client_deregister); + hook_register(zserv_client_close, zebra_ptm_bfd_client_deregister); } void zebra_ptm_finish(void) diff --git a/zebra/zebra_ptm_redistribute.c b/zebra/zebra_ptm_redistribute.c index 747714769..815f61d15 100644 --- a/zebra/zebra_ptm_redistribute.c +++ b/zebra/zebra_ptm_redistribute.c @@ -66,7 +66,7 @@ static int zsend_interface_bfd_update(int cmd, struct zserv *client, stream_putw_at(s, 0, stream_get_endp(s)); client->if_bfd_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } void zebra_interface_bfd_update(struct interface *ifp, struct prefix *dp, @@ -101,7 +101,7 @@ static int zsend_bfd_peer_replay(int cmd, struct zserv *client) stream_putw_at(s, 0, stream_get_endp(s)); client->bfd_peer_replay_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } void zebra_bfd_peer_replay_req(void) diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c index 28e09fe19..bf76f7e86 100644 --- a/zebra/zebra_pw.c +++ b/zebra/zebra_pw.c @@ -292,7 +292,7 @@ void zebra_pw_init(struct zebra_vrf *zvrf) RB_INIT(zebra_pw_head, &zvrf->pseudowires); RB_INIT(zebra_static_pw_head, &zvrf->static_pseudowires); - hook_register(zapi_client_close, zebra_pw_client_close); + hook_register(zserv_client_close, zebra_pw_client_close); } void zebra_pw_exit(struct zebra_vrf *zvrf) diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 90c39bcc6..d482e0ab3 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -73,7 +73,7 @@ int zebra_rnh_ipv6_default_route = 0; void zebra_rnh_init(void) { - hook_register(zapi_client_close, zebra_client_cleanup_rnh); + hook_register(zserv_client_close, zebra_client_cleanup_rnh); } static inline struct route_table *get_rnh_table(vrf_id_t vrfid, int family, @@ -1106,7 +1106,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, client->nh_last_upd_time = monotime(NULL); client->last_write_cmd = cmd; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } static void print_nh(struct nexthop *nexthop, struct vty *vty) diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 90604215e..c6adc89e5 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -1195,7 +1195,7 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, struct zserv *client = NULL; struct stream *s = NULL; - client = zebra_find_client(ZEBRA_ROUTE_BGP, 0); + client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); /* BGP may not be running. */ if (!client) return 0; @@ -1237,7 +1237,7 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, else client->macipdel_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* @@ -2779,7 +2779,7 @@ static int zvni_send_add_to_client(zebra_vni_t *zvni) struct zserv *client; struct stream *s; - client = zebra_find_client(ZEBRA_ROUTE_BGP, 0); + client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); /* BGP may not be running. */ if (!client) return 0; @@ -2801,7 +2801,7 @@ static int zvni_send_add_to_client(zebra_vni_t *zvni) zebra_route_string(client->proto)); client->vniadd_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* @@ -2812,7 +2812,7 @@ static int zvni_send_del_to_client(vni_t vni) struct zserv *client; struct stream *s; - client = zebra_find_client(ZEBRA_ROUTE_BGP, 0); + client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); /* BGP may not be running. */ if (!client) return 0; @@ -2831,7 +2831,7 @@ static int zvni_send_del_to_client(vni_t vni) zebra_route_string(client->proto)); client->vnidel_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* @@ -3745,7 +3745,7 @@ static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni) struct ethaddr rmac; char buf[ETHER_ADDR_STRLEN]; - client = zebra_find_client(ZEBRA_ROUTE_BGP, 0); + client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); /* BGP may not be running. */ if (!client) return 0; @@ -3777,7 +3777,7 @@ static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni) zebra_route_string(client->proto)); client->l3vniadd_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* @@ -3788,7 +3788,7 @@ static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni) struct stream *s = NULL; struct zserv *client = NULL; - client = zebra_find_client(ZEBRA_ROUTE_BGP, 0); + client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); /* BGP may not be running. */ if (!client) return 0; @@ -3807,7 +3807,7 @@ static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni) zebra_route_string(client->proto)); client->l3vnidel_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni) @@ -3920,7 +3920,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p, struct stream *s = NULL; char buf[PREFIX_STRLEN]; - client = zebra_find_client(ZEBRA_ROUTE_BGP, 0); + client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); /* BGP may not be running. */ if (!client) return 0; @@ -3944,7 +3944,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p, else client->prefixdel_cnt++; - return zebra_server_send_message(client, s); + return zserv_send_message(client, s); } /* re-add remote rmac if needed */ diff --git a/zebra/zserv.c b/zebra/zserv.c index f2a2bdcb8..9e2c44376 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -69,14 +69,65 @@ extern struct zebra_privs_t zserv_privs; * * These are used almost exclusively by client threads to drive their own event * loops. The only exception is in zebra_client_create(), which pushes an - * initial ZEBRA_READ event to start the API handler loop. + * initial ZSERV_CLIENT_READ event to start the API handler loop. */ -enum event { ZEBRA_READ, ZEBRA_WRITE }; +enum zserv_client_event { + /* Schedule a socket read */ + ZSERV_CLIENT_READ, + /* Schedule a buffer write */ + ZSERV_CLIENT_WRITE, + /* Schedule a buffer flush */ + ZSERV_CLIENT_FLUSH_DATA, +}; -/* Forward declarations for functions used from both threads. */ -static void zebra_event(struct zserv *client, enum event event); -static int zebra_client_handle_close(struct thread *thread); -static int zserv_process_messages(struct thread *thread); +/* + * Main thread events. + * + * These are used by client threads to notify the main thread about various + * events and to make processing requests. + */ +enum zserv_event { + /* Schedule listen job on Zebra API socket */ + ZSERV_ACCEPT, + /* The calling client has packets on its input buffer */ + ZSERV_PROCESS_MESSAGES, + /* The calling client wishes to be killed */ + ZSERV_HANDLE_CLOSE, +}; + +/* + * Zebra server event driver for all client threads. + * + * This is essentially a wrapper around thread_add_event() that centralizes + * those scheduling calls into one place. + * + * All calls to this function schedule an event on the pthread running the + * provided client. + * + * client + * the client in question, and thread target + * + * event + * the event to notify them about + */ +static void zserv_client_event(struct zserv *client, + enum zserv_client_event event); + +/* + * Zebra server event driver for the main thread. + * + * This is essentially a wrapper around thread_add_event() that centralizes + * those scheduling calls into one place. + * + * All calls to this function schedule an event on Zebra's main pthread. + * + * client + * the client in question + * + * event + * the event to notify the main thread about + */ +static void zserv_event(struct zserv *client, enum zserv_event event); /* Client thread lifecycle -------------------------------------------------- */ @@ -107,7 +158,6 @@ static void zserv_log_message(const char *errmsg, struct stream *msg, zlog_hexdump(msg->data, STREAM_READABLE(msg)); } - /* * Gracefully shut down a client connection. * @@ -116,12 +166,11 @@ static void zserv_log_message(const char *errmsg, struct stream *msg, * * Must be called from the client pthread, never the main thread. */ -static void zebra_client_close(struct zserv *client) +static void zserv_client_close(struct zserv *client) { THREAD_OFF(client->t_read); THREAD_OFF(client->t_write); - thread_add_event(zebrad.master, zebra_client_handle_close, client, 0, - NULL); + zserv_event(client, ZSERV_HANDLE_CLOSE); } static int zserv_flush_data(struct thread *thread) @@ -134,13 +183,11 @@ static int zserv_flush_data(struct thread *thread) zlog_warn( "%s: buffer_flush_available failed on zserv client fd %d, closing", __func__, client->sock); - zebra_client_close(client); + zserv_client_close(client); client = NULL; break; case BUFFER_PENDING: - client->t_write = NULL; - thread_add_write(client->pthread->master, zserv_flush_data, client, - client->sock, &client->t_write); + zserv_client_event(client, ZSERV_CLIENT_FLUSH_DATA); break; case BUFFER_EMPTY: break; @@ -188,11 +235,10 @@ static int zserv_write(struct thread *thread) client->sock); zlog_warn("%s: closing connection to %s", __func__, zebra_route_string(client->proto)); - zebra_client_close(client); + zserv_client_close(client); return -1; case BUFFER_PENDING: - thread_add_write(client->pthread->master, zserv_flush_data, - client, client->sock, &client->t_write); + zserv_client_event(client, ZSERV_CLIENT_FLUSH_DATA); break; case BUFFER_EMPTY: break; @@ -201,7 +247,7 @@ static int zserv_write(struct thread *thread) pthread_mutex_lock(&client->obuf_mtx); { if (client->obuf_fifo->count) - zebra_event(client, ZEBRA_WRITE); + zserv_client_event(client, ZSERV_CLIENT_WRITE); } pthread_mutex_unlock(&client->obuf_mtx); @@ -231,7 +277,6 @@ static void zserv_write_incoming(struct stream *orig, uint16_t command) } #endif - /* * Read and process data from a client socket. * @@ -381,36 +426,39 @@ static int zserv_read(struct thread *thread) zebrad.packets_to_process - p2p); /* Schedule job to process those packets */ - thread_add_event(zebrad.master, zserv_process_messages, client, 0, - NULL); + zserv_event(client, ZSERV_PROCESS_MESSAGES); /* Reschedule ourselves */ - zebra_event(client, ZEBRA_READ); + zserv_client_event(client, ZSERV_CLIENT_READ); return 0; zread_fail: - zebra_client_close(client); + zserv_client_close(client); return -1; } -static void zebra_event(struct zserv *client, enum event event) +static void zserv_client_event(struct zserv *client, + enum zserv_client_event event) { switch (event) { - case ZEBRA_READ: + case ZSERV_CLIENT_READ: thread_add_read(client->pthread->master, zserv_read, client, client->sock, &client->t_read); break; - case ZEBRA_WRITE: + case ZSERV_CLIENT_WRITE: thread_add_write(client->pthread->master, zserv_write, client, client->sock, &client->t_write); break; + case ZSERV_CLIENT_FLUSH_DATA: + thread_add_write(client->pthread->master, zserv_flush_data, + client, client->sock, &client->t_write); + break; } } /* Main thread lifecycle ---------------------------------------------------- */ - /* * Read and process messages from a client. * @@ -472,20 +520,19 @@ static int zserv_process_messages(struct thread *thread) pthread_mutex_lock(&client->ibuf_mtx); { if (client->ibuf_fifo->count) - thread_add_event(zebrad.master, zserv_process_messages, - client, 0, NULL); + zserv_event(client, ZSERV_PROCESS_MESSAGES); } pthread_mutex_unlock(&client->ibuf_mtx); return 0; } -int zebra_server_send_message(struct zserv *client, struct stream *msg) +int zserv_send_message(struct zserv *client, struct stream *msg) { pthread_mutex_lock(&client->obuf_mtx); { stream_fifo_push(client->obuf_fifo, msg); - zebra_event(client, ZEBRA_WRITE); + zserv_client_event(client, ZSERV_CLIENT_WRITE); } pthread_mutex_unlock(&client->obuf_mtx); return 0; @@ -493,8 +540,8 @@ int zebra_server_send_message(struct zserv *client, struct stream *msg) /* Hooks for client connect / disconnect */ -DEFINE_HOOK(zapi_client_connect, (struct zserv *client), (client)); -DEFINE_KOOH(zapi_client_close, (struct zserv *client), (client)); +DEFINE_HOOK(zserv_client_connect, (struct zserv *client), (client)); +DEFINE_KOOH(zserv_client_close, (struct zserv *client), (client)); /* * Deinitialize zebra client. @@ -508,9 +555,9 @@ DEFINE_KOOH(zapi_client_close, (struct zserv *client), (client)); * managed by the owning pthread and any tasks associated with them must have * been stopped prior to invoking this function. */ -static void zebra_client_free(struct zserv *client) +static void zserv_client_free(struct zserv *client) { - hook_call(zapi_client_close, client); + hook_call(zserv_client_close, client); /* Close file descriptor. */ if (client->sock) { @@ -562,7 +609,7 @@ static void zebra_client_free(struct zserv *client) * terminate the client thread, update relevant internal datastructures and * free any resources allocated by the main thread. */ -static int zebra_client_handle_close(struct thread *thread) +static int zserv_handle_client_close(struct thread *thread) { struct zserv *client = THREAD_ARG(thread); @@ -582,7 +629,7 @@ static int zebra_client_handle_close(struct thread *thread) client->pthread = NULL; listnode_delete(zebrad.client_list, client); - zebra_client_free(client); + zserv_client_free(client); return 0; } @@ -596,7 +643,7 @@ static int zebra_client_handle_close(struct thread *thread) * sock * client's socket file descriptor */ -static void zebra_client_create(int sock) +static void zserv_client_create(int sock) { struct zserv *client; int i; @@ -645,17 +692,19 @@ static void zebra_client_create(int sock) zebra_vrf_update_all(client); /* start read loop */ - zebra_event(client, ZEBRA_READ); + zserv_client_event(client, ZSERV_CLIENT_READ); /* call callbacks */ - hook_call(zapi_client_connect, client); + hook_call(zserv_client_connect, client); /* start pthread */ frr_pthread_run(client->pthread, NULL); } -/* Accept code of zebra server socket. */ -static int zebra_accept(struct thread *thread) +/* + * Accept socket connection. + */ +static int zserv_accept(struct thread *thread) { int accept_sock; int client_sock; @@ -665,7 +714,7 @@ static int zebra_accept(struct thread *thread) accept_sock = THREAD_FD(thread); /* Reregister myself. */ - thread_add_read(zebrad.master, zebra_accept, NULL, accept_sock, NULL); + zserv_event(NULL, ZSERV_ACCEPT); len = sizeof(struct sockaddr_in); client_sock = accept(accept_sock, (struct sockaddr *)&client, &len); @@ -680,16 +729,14 @@ static int zebra_accept(struct thread *thread) set_nonblocking(client_sock); /* Create new zebra client. */ - zebra_client_create(client_sock); + zserv_client_create(client_sock); return 0; } -/* Make zebra server socket, wiping any existing one (see bug #403). */ -void zebra_zserv_socket_init(char *path) +void zserv_start(char *path) { int ret; - int sock; mode_t old_mask; struct sockaddr_storage sa; socklen_t sa_len; @@ -702,8 +749,8 @@ void zebra_zserv_socket_init(char *path) old_mask = umask(0077); /* Make UNIX domain socket. */ - sock = socket(sa.ss_family, SOCK_STREAM, 0); - if (sock < 0) { + zebrad.sock = socket(sa.ss_family, SOCK_STREAM, 0); + if (zebrad.sock < 0) { zlog_warn("Can't create zserv socket: %s", safe_strerror(errno)); zlog_warn( @@ -712,8 +759,8 @@ void zebra_zserv_socket_init(char *path) } if (sa.ss_family != AF_UNIX) { - sockopt_reuseaddr(sock); - sockopt_reuseport(sock); + sockopt_reuseaddr(zebrad.sock); + sockopt_reuseport(zebrad.sock); } else { struct sockaddr_un *suna = (struct sockaddr_un *)&sa; if (suna->sun_path[0]) @@ -721,40 +768,60 @@ void zebra_zserv_socket_init(char *path) } zserv_privs.change(ZPRIVS_RAISE); - setsockopt_so_recvbuf(sock, 1048576); - setsockopt_so_sendbuf(sock, 1048576); + setsockopt_so_recvbuf(zebrad.sock, 1048576); + setsockopt_so_sendbuf(zebrad.sock, 1048576); zserv_privs.change(ZPRIVS_LOWER); if (sa.ss_family != AF_UNIX && zserv_privs.change(ZPRIVS_RAISE)) zlog_err("Can't raise privileges"); - ret = bind(sock, (struct sockaddr *)&sa, sa_len); + ret = bind(zebrad.sock, (struct sockaddr *)&sa, sa_len); if (ret < 0) { zlog_warn("Can't bind zserv socket on %s: %s", path, safe_strerror(errno)); zlog_warn( "zebra can't provide full functionality due to above error"); - close(sock); + close(zebrad.sock); + zebrad.sock = -1; return; } if (sa.ss_family != AF_UNIX && zserv_privs.change(ZPRIVS_LOWER)) zlog_err("Can't lower privileges"); - ret = listen(sock, 5); + ret = listen(zebrad.sock, 5); if (ret < 0) { zlog_warn("Can't listen to zserv socket %s: %s", path, safe_strerror(errno)); zlog_warn( "zebra can't provide full functionality due to above error"); - close(sock); + close(zebrad.sock); + zebrad.sock = -1; return; } umask(old_mask); - thread_add_read(zebrad.master, zebra_accept, NULL, sock, NULL); + zserv_event(NULL, ZSERV_ACCEPT); } +void zserv_event(struct zserv *client, enum zserv_event event) +{ + switch (event) { + case ZSERV_ACCEPT: + thread_add_read(zebrad.master, zserv_accept, NULL, zebrad.sock, + NULL); + break; + case ZSERV_PROCESS_MESSAGES: + thread_add_event(zebrad.master, zserv_process_messages, client, + 0, NULL); + break; + case ZSERV_HANDLE_CLOSE: + thread_add_event(zebrad.master, zserv_handle_client_close, + client, 0, NULL); + } +} + + /* General purpose ---------------------------------------------------------- */ #define ZEBRA_TIME_BUF 32 @@ -895,7 +962,7 @@ static void zebra_show_client_brief(struct vty *vty, struct zserv *client) client->v6_route_del_cnt); } -struct zserv *zebra_find_client(uint8_t proto, unsigned short instance) +struct zserv *zserv_find_client(uint8_t proto, unsigned short instance) { struct listnode *node, *nnode; struct zserv *client; @@ -973,7 +1040,10 @@ void zserv_init(void) { /* Client list init. */ zebrad.client_list = list_new(); - zebrad.client_list->del = (void (*)(void *))zebra_client_free; + zebrad.client_list->del = (void (*)(void *)) zserv_client_free; + + /* Misc init. */ + zebrad.sock = -1; install_element(ENABLE_NODE, &show_zebra_client_cmd); install_element(ENABLE_NODE, &show_zebra_client_summary_cmd); diff --git a/zebra/zserv.h b/zebra/zserv.h index 77c5d9a89..6cd8b8c29 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -160,8 +160,8 @@ struct zserv { struct zebra_vrf *zvrf /* Hooks for client connect / disconnect */ -DECLARE_HOOK(zapi_client_connect, (struct zserv *client), (client)); -DECLARE_KOOH(zapi_client_close, (struct zserv *client), (client)); +DECLARE_HOOK(zserv_client_connect, (struct zserv *client), (client)); +DECLARE_KOOH(zserv_client_close, (struct zserv *client), (client)); /* Zebra instance */ struct zebra_t { @@ -169,6 +169,9 @@ struct zebra_t { struct thread_master *master; struct list *client_list; + /* Socket */ + int sock; + /* default table */ uint32_t rtm_table_default; @@ -186,12 +189,48 @@ struct zebra_t { extern struct zebra_t zebrad; extern unsigned int multipath_num; -/* Prototypes. */ +/* + * Initialize Zebra API server. + * + * Installs CLI commands and creates the client list. + */ extern void zserv_init(void); -extern void zebra_zserv_socket_init(char *path); -extern int zebra_server_send_message(struct zserv *client, struct stream *msg); -extern struct zserv *zebra_find_client(uint8_t proto, unsigned short instance); +/* + * Start Zebra API server. + * + * Allocates resources, creates the server socket and begins listening on the + * socket. + * + * path + * where to place the Unix domain socket + */ +extern void zserv_start(char *path); + +/* + * Send a message to a connected Zebra API client. + * + * client + * the client to send to + * + * msg + * the message to send + */ +extern int zserv_send_message(struct zserv *client, struct stream *msg); + +/* + * Retrieve a client by its protocol and instance number. + * + * proto + * protocol number + * + * instance + * instance number + * + * Returns: + * The Zebra API client. + */ +extern struct zserv *zserv_find_client(uint8_t proto, unsigned short instance); #if defined(HANDLE_ZAPI_FUZZING) extern void zserv_read_file(char *input); |