]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/zserv.c
Merge pull request #3899 from ton31337/fix/remove_private_as_with_local_as
[mirror_frr.git] / zebra / zserv.c
index 8cc462577a2a5a317ab46b49105d0e91480d2f83..f5bb3aabb767428bccadcc61c4d33745784d2c39 100644 (file)
 #include "zebra/zapi_msg.h"       /* for zserv_handle_commands */
 #include "zebra/zebra_vrf.h"      /* for zebra_vrf_lookup_by_id, zvrf */
 #include "zebra/zserv.h"          /* for zserv */
+#include "zebra/zebra_router.h"
 #include "zebra/zebra_errors.h"   /* for error messages */
 /* clang-format on */
 
 /* privileges */
 extern struct zebra_privs_t zserv_privs;
 
+/* The listener socket for clients connecting to us */
+static int zsock;
+
 /*
  * Client thread events.
  *
@@ -312,7 +316,7 @@ static int zserv_read(struct thread *thread)
        uint32_t p2p;
        struct zmsghdr hdr;
 
-       p2p_orig = atomic_load_explicit(&zebrad.packets_to_process,
+       p2p_orig = atomic_load_explicit(&zrouter.packets_to_process,
                                        memory_order_relaxed);
        cache = stream_fifo_new();
        p2p = p2p_orig;
@@ -401,8 +405,10 @@ static int zserv_read(struct thread *thread)
                }
 
                /* Debug packet information. */
-               if (IS_ZEBRA_DEBUG_EVENT)
-                       zlog_debug("zebra message comes from socket [%d]",
+               if (IS_ZEBRA_DEBUG_PACKET)
+                       zlog_debug("zebra message[%s:%u:%u] comes from socket [%d]",
+                                  zserv_command_string(hdr.command),
+                                  hdr.vrf_id, hdr.length,
                                   sock);
 
                if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
@@ -438,7 +444,8 @@ static int zserv_read(struct thread *thread)
        }
 
        if (IS_ZEBRA_DEBUG_PACKET)
-               zlog_debug("Read %d packets", p2p_orig - p2p);
+               zlog_debug("Read %d packets from client: %s", p2p_orig - p2p,
+                          zebra_route_string(client->proto));
 
        /* Reschedule ourselves */
        zserv_client_event(client, ZSERV_CLIENT_READ);
@@ -481,9 +488,9 @@ static void zserv_client_event(struct zserv *client,
  * with the message is executed. This proceeds until there are no more messages,
  * an error occurs, or the processing limit is reached.
  *
- * The client's I/O thread can push at most zebrad.packets_to_process messages
+ * The client's I/O thread can push at most zrouter.packets_to_process messages
  * onto the input buffer before notifying us there are packets to read. As long
- * as we always process zebrad.packets_to_process messages here, then we can
+ * as we always process zrouter.packets_to_process messages here, then we can
  * rely on the read thread to handle queuing this task enough times to process
  * everything on the input queue.
  */
@@ -492,8 +499,8 @@ static int zserv_process_messages(struct thread *thread)
        struct zserv *client = THREAD_ARG(thread);
        struct stream *msg;
        struct stream_fifo *cache = stream_fifo_new();
-
-       uint32_t p2p = zebrad.packets_to_process;
+       uint32_t p2p = zrouter.packets_to_process;
+       bool need_resched = false;
 
        pthread_mutex_lock(&client->ibuf_mtx);
        {
@@ -505,6 +512,12 @@ static int zserv_process_messages(struct thread *thread)
                }
 
                msg = NULL;
+
+               /* Need to reschedule processing work if there are still
+                * packets in the fifo.
+                */
+               if (stream_fifo_head(client->ibuf_fifo))
+                       need_resched = true;
        }
        pthread_mutex_unlock(&client->ibuf_mtx);
 
@@ -516,6 +529,10 @@ static int zserv_process_messages(struct thread *thread)
 
        stream_fifo_free(cache);
 
+       /* Reschedule ourselves if necessary */
+       if (need_resched)
+               zserv_event(client, ZSERV_PROCESS_MESSAGES);
+
        return 0;
 }
 
@@ -606,12 +623,12 @@ static void zserv_client_free(struct zserv *client)
        pthread_mutex_destroy(&client->ibuf_mtx);
 
        /* Free bitmaps. */
-       for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++)
+       for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) {
                for (int i = 0; i < ZEBRA_ROUTE_MAX; i++)
                        vrf_bitmap_free(client->redist[afi][i]);
 
-       vrf_bitmap_free(client->redist_default);
-       vrf_bitmap_free(client->ifinfo);
+               vrf_bitmap_free(client->redist_default[afi]);
+       }
        vrf_bitmap_free(client->ridinfo);
 
        XFREE(MTYPE_TMP, client);
@@ -626,15 +643,16 @@ void zserv_close_client(struct zserv *client)
                zlog_debug("Closing client '%s'",
                           zebra_route_string(client->proto));
 
-       thread_cancel_event(zebrad.master, client);
+       thread_cancel_event(zrouter.master, client);
        THREAD_OFF(client->t_cleanup);
+       THREAD_OFF(client->t_process);
 
        /* destroy pthread */
        frr_pthread_destroy(client->pthread);
        client->pthread = NULL;
 
        /* remove from client list */
-       listnode_delete(zebrad.client_list, client);
+       listnode_delete(zrouter.client_list, client);
 
        /* delete client */
        zserv_client_free(client);
@@ -683,24 +701,24 @@ static struct zserv *zserv_client_create(int sock)
        client->wb = buffer_new(0);
 
        /* Set table number. */
-       client->rtm_table = zebrad.rtm_table_default;
+       client->rtm_table = zrouter.rtm_table_default;
 
        atomic_store_explicit(&client->connect_time, (uint32_t) monotime(NULL),
                              memory_order_relaxed);
 
        /* Initialize flags */
-       for (afi = AFI_IP; afi < AFI_MAX; afi++)
+       for (afi = AFI_IP; afi < AFI_MAX; afi++) {
                for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
                        client->redist[afi][i] = vrf_bitmap_init();
-       client->redist_default = vrf_bitmap_init();
-       client->ifinfo = vrf_bitmap_init();
+               client->redist_default[afi] = vrf_bitmap_init();
+       }
        client->ridinfo = vrf_bitmap_init();
 
        /* by default, it's not a synchronous client */
        client->is_synchronous = 0;
 
        /* Add this client to linked list. */
-       listnode_add(zebrad.client_list, client);
+       listnode_add(zrouter.client_list, client);
 
        struct frr_pthread_attr zclient_pthr_attrs = {
                .start = frr_pthread_attr_default.start,
@@ -710,8 +728,6 @@ static struct zserv *zserv_client_create(int sock)
                frr_pthread_new(&zclient_pthr_attrs, "Zebra API client thread",
                                "zebra_apic");
 
-       zebra_vrf_update_all(client);
-
        /* start read loop */
        zserv_client_event(client, ZSERV_CLIENT_READ);
 
@@ -757,6 +773,18 @@ static int zserv_accept(struct thread *thread)
        return 0;
 }
 
+void zserv_close(void)
+{
+       /*
+        * On shutdown, let's close the socket down
+        * so that long running processes of killing the
+        * routing table doesn't leave us in a bad
+        * state where a client tries to reconnect
+        */
+       close(zsock);
+       zsock = -1;
+}
+
 void zserv_start(char *path)
 {
        int ret;
@@ -772,16 +800,16 @@ void zserv_start(char *path)
        old_mask = umask(0077);
 
        /* Make UNIX domain socket. */
-       zebrad.sock = socket(sa.ss_family, SOCK_STREAM, 0);
-       if (zebrad.sock < 0) {
+       zsock = socket(sa.ss_family, SOCK_STREAM, 0);
+       if (zsock < 0) {
                flog_err_sys(EC_LIB_SOCKET, "Can't create zserv socket: %s",
                             safe_strerror(errno));
                return;
        }
 
        if (sa.ss_family != AF_UNIX) {
-               sockopt_reuseaddr(zebrad.sock);
-               sockopt_reuseport(zebrad.sock);
+               sockopt_reuseaddr(zsock);
+               sockopt_reuseport(zsock);
        } else {
                struct sockaddr_un *suna = (struct sockaddr_un *)&sa;
                if (suna->sun_path[0])
@@ -789,28 +817,28 @@ void zserv_start(char *path)
        }
 
        frr_elevate_privs(&zserv_privs) {
-               setsockopt_so_recvbuf(zebrad.sock, 1048576);
-               setsockopt_so_sendbuf(zebrad.sock, 1048576);
+               setsockopt_so_recvbuf(zsock, 1048576);
+               setsockopt_so_sendbuf(zsock, 1048576);
        }
 
        frr_elevate_privs((sa.ss_family != AF_UNIX) ? &zserv_privs : NULL) {
-               ret = bind(zebrad.sock, (struct sockaddr *)&sa, sa_len);
+               ret = bind(zsock, (struct sockaddr *)&sa, sa_len);
        }
        if (ret < 0) {
                flog_err_sys(EC_LIB_SOCKET, "Can't bind zserv socket on %s: %s",
                             path, safe_strerror(errno));
-               close(zebrad.sock);
-               zebrad.sock = -1;
+               close(zsock);
+               zsock = -1;
                return;
        }
 
-       ret = listen(zebrad.sock, 5);
+       ret = listen(zsock, 5);
        if (ret < 0) {
                flog_err_sys(EC_LIB_SOCKET,
                             "Can't listen to zserv socket %s: %s", path,
                             safe_strerror(errno));
-               close(zebrad.sock);
-               zebrad.sock = -1;
+               close(zsock);
+               zsock = -1;
                return;
        }
 
@@ -823,15 +851,15 @@ 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,
+               thread_add_read(zrouter.master, zserv_accept, NULL, zsock,
                                NULL);
                break;
        case ZSERV_PROCESS_MESSAGES:
-               thread_add_event(zebrad.master, zserv_process_messages, client,
-                                0, NULL);
+               thread_add_event(zrouter.master, zserv_process_messages, client,
+                                0, &client->t_process);
                break;
        case ZSERV_HANDLE_CLIENT_FAIL:
-               thread_add_event(zebrad.master, zserv_handle_client_fail,
+               thread_add_event(zrouter.master, zserv_handle_client_fail,
                                 client, 0, &client->t_cleanup);
        }
 }
@@ -875,7 +903,7 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
        char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF];
        char wbuf[ZEBRA_TIME_BUF], nhbuf[ZEBRA_TIME_BUF], mbuf[ZEBRA_TIME_BUF];
        time_t connect_time, last_read_time, last_write_time;
-       uint16_t last_read_cmd, last_write_cmd;
+       uint32_t last_read_cmd, last_write_cmd;
 
        vty_out(vty, "Client: %s", zebra_route_string(client->proto));
        if (client->instance)
@@ -940,6 +968,10 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
                client->ifdel_cnt);
        vty_out(vty, "BFD peer    %-12d%-12d%-12d\n", client->bfd_peer_add_cnt,
                client->bfd_peer_upd8_cnt, client->bfd_peer_del_cnt);
+       vty_out(vty, "NHT v4      %-12d%-12d%-12d\n",
+               client->v4_nh_watch_add_cnt, 0, client->v4_nh_watch_rem_cnt);
+       vty_out(vty, "NHT v6      %-12d%-12d%-12d\n",
+               client->v6_nh_watch_add_cnt, 0, client->v6_nh_watch_rem_cnt);
        vty_out(vty, "Interface Up Notifications: %d\n", client->ifup_cnt);
        vty_out(vty, "Interface Down Notifications: %d\n", client->ifdown_cnt);
        vty_out(vty, "VNI add notifications: %d\n", client->vniadd_cnt);
@@ -987,7 +1019,7 @@ struct zserv *zserv_find_client(uint8_t proto, unsigned short instance)
        struct listnode *node, *nnode;
        struct zserv *client;
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
                if (client->proto == proto && client->instance == instance)
                        return client;
        }
@@ -1006,7 +1038,7 @@ DEFUN (show_zebra_client,
        struct listnode *node;
        struct zserv *client;
 
-       for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client))
+       for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client))
                zebra_show_client_detail(vty, client);
 
        return CMD_SUCCESS;
@@ -1029,7 +1061,7 @@ DEFUN (show_zebra_client_summary,
        vty_out(vty,
                "--------------------------------------------------------------------------------\n");
 
-       for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client))
+       for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client))
                zebra_show_client_brief(vty, client);
 
        vty_out(vty, "Routes column shows (added+updated)/deleted\n");
@@ -1052,10 +1084,10 @@ void zserv_read_file(char *input)
 void zserv_init(void)
 {
        /* Client list init. */
-       zebrad.client_list = list_new();
+       zrouter.client_list = list_new();
 
        /* Misc init. */
-       zebrad.sock = -1;
+       zsock = -1;
 
        install_element(ENABLE_NODE, &show_zebra_client_cmd);
        install_element(ENABLE_NODE, &show_zebra_client_summary_cmd);