bgpd, lib: Indicate when we are buffering instead of immediately sending down ZAPI

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>
This commit is contained in:
Donald Sharp 2020-10-12 09:51:09 -04:00
parent 32f7e999f2
commit db71415b41
3 changed files with 72 additions and 58 deletions

View 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;

View 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,7 +417,7 @@ 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,
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,7 +581,7 @@ 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,
int zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,
struct interface *ifp, int enable,
int ra_interval)
{
@ -578,7 +589,7 @@ void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,
/* 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,7 +3946,7 @@ static void zclient_event(enum event event, struct zclient *zclient)
}
}
void zclient_interface_set_master(struct zclient *client,
int zclient_interface_set_master(struct zclient *client,
struct interface *master,
struct interface *slave)
{
@ -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);
}
/*

View 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,7 +766,7 @@ 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,
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);
@ -764,7 +776,7 @@ 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,
extern int zclient_send_interface_radv_req(struct zclient *zclient,
vrf_id_t vrf_id,
struct interface *ifp, int enable,
int ra_interval);
@ -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,7 +868,7 @@ 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,
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);
@ -970,11 +987,11 @@ 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,
extern int 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_deregister(struct zclient *client);
extern void zclient_send_mlag_data(struct zclient *client,
extern int zclient_send_mlag_data(struct zclient *client,
struct stream *client_s);
/*