]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd, lib: Indicate when we are buffering instead of immediately sending down ZAPI
authorDonald Sharp <sharpd@nvidia.com>
Mon, 12 Oct 2020 13:51:09 +0000 (09:51 -0400)
committerDonald Sharp <sharpd@nvidia.com>
Sun, 15 Nov 2020 19:50:17 +0000 (14:50 -0500)
When FRR sends data over the ZAPI protocol from the upper levels to zebra, indicate
to the calling functions that we have started buffering data to be sent if the
socket is full underneath it.

Also add a call back function `zebra_buffer_write_ready` that we can call
when an upper level protocol's socket buffer has been drained.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
bgpd/bgp_zebra.c
lib/zclient.c
lib/zclient.h

index 17bb41cb9f9b773ff0b5e4344bfe9a944dff74d3..b2fec55eae5f031846c1a332903f7a4ddbafd34e 100644 (file)
@@ -3050,7 +3050,7 @@ void bgp_send_pbr_rule_action(struct bgp_pbr_action *pbra,
        bgp_encode_pbr_rule_action(s, pbra, pbr);
 
        stream_putw_at(s, 0, stream_get_endp(s));
-       if (!zclient_send_message(zclient) && install) {
+       if ((zclient_send_message(zclient) != -1) && install) {
                if (!pbr)
                        pbra->install_in_progress = true;
                else
@@ -3081,7 +3081,7 @@ void bgp_send_pbr_ipset_match(struct bgp_pbr_match *pbrim, bool install)
        bgp_encode_pbr_ipset_match(s, pbrim);
 
        stream_putw_at(s, 0, stream_get_endp(s));
-       if (!zclient_send_message(zclient) && install)
+       if ((zclient_send_message(zclient) != -1) && install)
                pbrim->install_in_progress = true;
 }
 
@@ -3109,7 +3109,7 @@ void bgp_send_pbr_ipset_entry_match(struct bgp_pbr_match_entry *pbrime,
        bgp_encode_pbr_ipset_entry_match(s, pbrime);
 
        stream_putw_at(s, 0, stream_get_endp(s));
-       if (!zclient_send_message(zclient) && install)
+       if ((zclient_send_message(zclient) != -1) && install)
                pbrime->install_in_progress = true;
 }
 
@@ -3184,7 +3184,7 @@ void bgp_send_pbr_iptable(struct bgp_pbr_action *pba,
        stream_putw_at(s, 0, stream_get_endp(s));
        ret = zclient_send_message(zclient);
        if (install) {
-               if (ret)
+               if (ret != -1)
                        pba->refcnt++;
                else
                        pbm->install_iptable_in_progress = true;
index b27e2cef7301acc88ad6bbacedb601db8bbe0d98..980ecc5ed8d4e818e5563f164f68d256736c5ec5 100644 (file)
@@ -277,11 +277,18 @@ static int zclient_flush_data(struct thread *thread)
                                 zclient->sock, &zclient->t_write);
                break;
        case BUFFER_EMPTY:
+               if (zclient->zebra_buffer_write_ready)
+                       (*zclient->zebra_buffer_write_ready)();
                break;
        }
        return 0;
 }
 
+/*
+ * -1 is a failure
+ *  0 means we sent
+ *  1 means we are buffering
+ */
 int zclient_send_message(struct zclient *zclient)
 {
        if (zclient->sock < 0)
@@ -296,12 +303,16 @@ int zclient_send_message(struct zclient *zclient)
                return zclient_failed(zclient);
        case BUFFER_EMPTY:
                THREAD_OFF(zclient->t_write);
+               return 0;
                break;
        case BUFFER_PENDING:
                thread_add_write(zclient->master, zclient_flush_data, zclient,
                                 zclient->sock, &zclient->t_write);
+               return 1;
                break;
        }
+
+       /* should not get here */
        return 0;
 }
 
@@ -406,8 +417,8 @@ int zclient_send_hello(struct zclient *zclient)
        return 0;
 }
 
-void zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id, afi_t afi,
-                           mpls_label_t label, enum lsp_types_t ltype)
+int zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id, afi_t afi,
+                          mpls_label_t label, enum lsp_types_t ltype)
 {
        struct stream *s;
 
@@ -419,7 +430,7 @@ void zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id, afi_t afi,
        stream_putc(s, afi);
        stream_putc(s, ltype);
        stream_putw_at(s, 0, stream_get_endp(s));
-       zclient_send_message(zclient);
+       return zclient_send_message(zclient);
 }
 
 /* Send register requests to zebra daemon for the information in a VRF. */
@@ -570,15 +581,15 @@ int zclient_send_router_id_update(struct zclient *zclient,
 }
 
 /* Send request to zebra daemon to start or stop RA. */
-void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,
-                                    struct interface *ifp, int enable,
-                                    int ra_interval)
+int zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,
+                                   struct interface *ifp, int enable,
+                                   int ra_interval)
 {
        struct stream *s;
 
        /* If not connected to the zebra yet. */
        if (zclient->sock < 0)
-               return;
+               return -1;
 
        /* Form and send message. */
        s = zclient->obuf;
@@ -594,7 +605,7 @@ void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,
 
        stream_putw_at(s, 0, stream_get_endp(s));
 
-       zclient_send_message(zclient);
+       return zclient_send_message(zclient);
 }
 
 int zclient_send_interface_protodown(struct zclient *zclient, vrf_id_t vrf_id,
@@ -611,9 +622,7 @@ int zclient_send_interface_protodown(struct zclient *zclient, vrf_id_t vrf_id,
        stream_putl(s, ifp->ifindex);
        stream_putc(s, !!down);
        stream_putw_at(s, 0, stream_get_endp(s));
-       zclient_send_message(zclient);
-
-       return 0;
+       return zclient_send_message(zclient);
 }
 
 /* Make connection to zebra daemon. */
@@ -3281,7 +3290,7 @@ stream_failure:
        return;
 }
 
-void zclient_send_mlag_register(struct zclient *client, uint32_t bit_map)
+int zclient_send_mlag_register(struct zclient *client, uint32_t bit_map)
 {
        struct stream *s;
 
@@ -3292,15 +3301,15 @@ void zclient_send_mlag_register(struct zclient *client, uint32_t bit_map)
        stream_putl(s, bit_map);
 
        stream_putw_at(s, 0, stream_get_endp(s));
-       zclient_send_message(client);
+       return zclient_send_message(client);
 }
 
-void zclient_send_mlag_deregister(struct zclient *client)
+int zclient_send_mlag_deregister(struct zclient *client)
 {
-       zebra_message_send(client, ZEBRA_MLAG_CLIENT_UNREGISTER, VRF_DEFAULT);
+       return zebra_message_send(client, ZEBRA_MLAG_CLIENT_UNREGISTER, VRF_DEFAULT);
 }
 
-void zclient_send_mlag_data(struct zclient *client, struct stream *client_s)
+int zclient_send_mlag_data(struct zclient *client, struct stream *client_s)
 {
        struct stream *s;
 
@@ -3311,7 +3320,7 @@ void zclient_send_mlag_data(struct zclient *client, struct stream *client_s)
        stream_put(s, client_s->data, client_s->endp);
 
        stream_putw_at(s, 0, stream_get_endp(s));
-       zclient_send_message(client);
+       return zclient_send_message(client);
 }
 
 static void zclient_mlag_process_up(ZAPI_CALLBACK_ARGS)
@@ -3339,7 +3348,6 @@ static void zclient_mlag_handle_msg(ZAPI_CALLBACK_ARGS)
 int zclient_send_opaque(struct zclient *zclient, uint32_t type,
                        const uint8_t *data, size_t datasize)
 {
-       int ret;
        struct stream *s;
        uint16_t flags = 0;
 
@@ -3363,9 +3371,7 @@ int zclient_send_opaque(struct zclient *zclient, uint32_t type,
        /* Put length into the header at the start of the stream. */
        stream_putw_at(s, 0, stream_get_endp(s));
 
-       ret = zclient_send_message(zclient);
-
-       return ret;
+       return zclient_send_message(zclient);
 }
 
 /*
@@ -3377,7 +3383,6 @@ int zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type,
                                uint32_t session_id, const uint8_t *data,
                                size_t datasize)
 {
-       int ret;
        struct stream *s;
        uint16_t flags = 0;
 
@@ -3407,9 +3412,7 @@ int zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type,
        /* Put length into the header at the start of the stream. */
        stream_putw_at(s, 0, stream_get_endp(s));
 
-       ret = zclient_send_message(zclient);
-
-       return ret;
+       return zclient_send_message(zclient);
 }
 
 /*
@@ -3444,7 +3447,6 @@ stream_failure:
  */
 int zclient_register_opaque(struct zclient *zclient, uint32_t type)
 {
-       int ret;
        struct stream *s;
 
        s = zclient->obuf;
@@ -3463,9 +3465,7 @@ int zclient_register_opaque(struct zclient *zclient, uint32_t type)
        /* Put length at the first point of the stream. */
        stream_putw_at(s, 0, stream_get_endp(s));
 
-       ret = zclient_send_message(zclient);
-
-       return ret;
+       return zclient_send_message(zclient);
 }
 
 /*
@@ -3473,7 +3473,6 @@ int zclient_register_opaque(struct zclient *zclient, uint32_t type)
  */
 int zclient_unregister_opaque(struct zclient *zclient, uint32_t type)
 {
-       int ret;
        struct stream *s;
 
        s = zclient->obuf;
@@ -3492,9 +3491,7 @@ int zclient_unregister_opaque(struct zclient *zclient, uint32_t type)
        /* Put length at the first point of the stream. */
        stream_putw_at(s, 0, stream_get_endp(s));
 
-       ret = zclient_send_message(zclient);
-
-       return ret;
+       return zclient_send_message(zclient);
 }
 
 /* Utility to decode opaque registration info */
@@ -3949,9 +3946,9 @@ static void zclient_event(enum event event, struct zclient *zclient)
        }
 }
 
-void zclient_interface_set_master(struct zclient *client,
-                                 struct interface *master,
-                                 struct interface *slave)
+int zclient_interface_set_master(struct zclient *client,
+                                struct interface *master,
+                                struct interface *slave)
 {
        struct stream *s;
 
@@ -3966,7 +3963,7 @@ void zclient_interface_set_master(struct zclient *client,
        stream_putl(s, slave->ifindex);
 
        stream_putw_at(s, 0, stream_get_endp(s));
-       zclient_send_message(client);
+       return zclient_send_message(client);
 }
 
 /*
index d9237048bdb0e9c61ba7c9b2dbf9617c8959fe4a..e8629acbee2434ee64179fad229f49904a6d6d85 100644 (file)
@@ -321,6 +321,18 @@ struct zclient {
        /* Pointer to the callback functions. */
        void (*zebra_connected)(struct zclient *);
        void (*zebra_capabilities)(struct zclient_capabilities *cap);
+
+       /*
+        * When the zclient attempts to write the stream data to
+        * it's named pipe to/from zebra, we may have a situation
+        * where the other daemon has not fully drained the data
+        * from the socket.  In this case provide a mechanism
+        * where we will *still* buffer the data to be sent
+        * and also provide a callback mechanism to the appropriate
+        * place where we can signal that we're ready to receive
+        * more data.
+        */
+       void (*zebra_buffer_write_ready)(void);
        int (*router_id_update)(ZAPI_CALLBACK_ARGS);
        int (*interface_address_add)(ZAPI_CALLBACK_ARGS);
        int (*interface_address_delete)(ZAPI_CALLBACK_ARGS);
@@ -754,9 +766,9 @@ extern void redist_del_all_instances(struct redist_proto *red);
  * we have installed and play some special games
  * to get them both installed.
  */
-extern void zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id,
-                                  afi_t afi, mpls_label_t label,
-                                  enum lsp_types_t ltype);
+extern int zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id,
+                                 afi_t afi, mpls_label_t label,
+                                 enum lsp_types_t ltype);
 
 extern void zclient_send_reg_requests(struct zclient *, vrf_id_t);
 extern void zclient_send_dereg_requests(struct zclient *, vrf_id_t);
@@ -764,10 +776,10 @@ extern int zclient_send_router_id_update(struct zclient *zclient,
                                         zebra_message_types_t type, afi_t afi,
                                         vrf_id_t vrf_id);
 
-extern void zclient_send_interface_radv_req(struct zclient *zclient,
-                                           vrf_id_t vrf_id,
-                                           struct interface *ifp, int enable,
-                                           int ra_interval);
+extern int zclient_send_interface_radv_req(struct zclient *zclient,
+                                          vrf_id_t vrf_id,
+                                          struct interface *ifp, int enable,
+                                          int ra_interval);
 extern int zclient_send_interface_protodown(struct zclient *zclient,
                                            vrf_id_t vrf_id,
                                            struct interface *ifp, bool down);
@@ -792,8 +804,13 @@ extern void zclient_redistribute(int command, struct zclient *, afi_t, int type,
 extern void zclient_redistribute_default(int command, struct zclient *,
                                         afi_t, vrf_id_t vrf_id);
 
-/* Send the message in zclient->obuf to the zebra daemon (or enqueue it).
-   Returns 0 for success or -1 on an I/O error. */
+/*
+ * Send the message in zclient->obuf to the zebra daemon (or enqueue it).
+ * Returns:
+ * -1 on a I/O error
+ *  0 data was successfully sent
+ *  1 data was buffered for future usage
+ */
 extern int zclient_send_message(struct zclient *);
 
 /* create header for command, length to be filled in by user later */
@@ -851,9 +868,9 @@ extern int zclient_read_header(struct stream *s, int sock, uint16_t *size,
  */
 extern bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr);
 
-extern void zclient_interface_set_master(struct zclient *client,
-                                        struct interface *master,
-                                        struct interface *slave);
+extern int zclient_interface_set_master(struct zclient *client,
+                                       struct interface *master,
+                                       struct interface *slave);
 extern struct interface *zebra_interface_state_read(struct stream *s, vrf_id_t);
 extern struct connected *zebra_interface_address_read(int, struct stream *,
                                                      vrf_id_t);
@@ -970,12 +987,12 @@ static inline void zapi_route_set_blackhole(struct zapi_route *api,
        SET_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP);
 };
 
-extern void zclient_send_mlag_register(struct zclient *client,
-                                      uint32_t bit_map);
-extern void zclient_send_mlag_deregister(struct zclient *client);
+extern int zclient_send_mlag_register(struct zclient *client,
+                                     uint32_t bit_map);
+extern int zclient_send_mlag_deregister(struct zclient *client);
 
-extern void zclient_send_mlag_data(struct zclient *client,
-                                  struct stream *client_s);
+extern int zclient_send_mlag_data(struct zclient *client,
+                                 struct stream *client_s);
 
 /*
  * Send an OPAQUE message, contents opaque to zebra - but note that