mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-02 22:09:48 +00:00
zebra: Synchronous client queues accumulate messages from zebra.
Zebra is currently sending messages on interface add/delete/update, VRF add/delete, and interface address change - regardless of whether its clients had requested them. This is problematic for lde and isis, which only listens to label chunk messages, and only when it is waiting for one (synchronous client). The effect is the that messages accumulate on the lde synchronous message queue. With this change: - Zebra does not send unsolicited messages to synchronous clients. - Synchronous clients send a ZEBRA_HELLO to zebra. The ZEBRA_HELLO contains a new boolean field: sychronous. - LDP and PIM have been updated to send a ZEBRA_HELLO for their synchronous clients. Signed-off-by: Karen Schoener <karen@voltanet.io>
This commit is contained in:
parent
5d2724ec25
commit
17da84a49d
11
ldpd/lde.c
11
ldpd/lde.c
@ -1631,8 +1631,11 @@ lde_address_list_free(struct lde_nbr *ln)
|
||||
|
||||
static void zclient_sync_init(unsigned short instance)
|
||||
{
|
||||
struct zclient_options options = zclient_options_default;
|
||||
options.synchronous = true;
|
||||
|
||||
/* Initialize special zclient for synchronous message exchanges. */
|
||||
zclient_sync = zclient_new(master, &zclient_options_default);
|
||||
zclient_sync = zclient_new(master, &options);
|
||||
zclient_sync->sock = -1;
|
||||
zclient_sync->redist_default = ZEBRA_ROUTE_LDP;
|
||||
zclient_sync->instance = instance;
|
||||
@ -1645,6 +1648,12 @@ static void zclient_sync_init(unsigned short instance)
|
||||
/* make socket non-blocking */
|
||||
sock_set_nonblock(zclient_sync->sock);
|
||||
|
||||
/* Send hello to notify zebra this is a synchronous client */
|
||||
while (zclient_send_hello(zclient_sync) < 0) {
|
||||
log_warnx("Error sending hello for synchronous zclient!");
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/* Connect to label manager */
|
||||
while (lm_label_manager_connect(zclient_sync, 0) != 0) {
|
||||
log_warnx("Error connecting to label manager!");
|
||||
|
@ -52,7 +52,8 @@ static void zclient_event(enum event, struct zclient *);
|
||||
static void zebra_interface_if_set_value(struct stream *s,
|
||||
struct interface *ifp);
|
||||
|
||||
struct zclient_options zclient_options_default = {.receive_notify = false};
|
||||
struct zclient_options zclient_options_default = {.receive_notify = false,
|
||||
.synchronous = false};
|
||||
|
||||
struct sockaddr_storage zclient_addr;
|
||||
socklen_t zclient_addr_len;
|
||||
@ -76,6 +77,7 @@ struct zclient *zclient_new(struct thread_master *master,
|
||||
zclient->master = master;
|
||||
|
||||
zclient->receive_notify = opt->receive_notify;
|
||||
zclient->synchronous = opt->synchronous;
|
||||
|
||||
return zclient;
|
||||
}
|
||||
@ -374,11 +376,11 @@ static int zebra_message_send(struct zclient *zclient, int command,
|
||||
return zclient_send_message(zclient);
|
||||
}
|
||||
|
||||
static int zebra_hello_send(struct zclient *zclient)
|
||||
int zclient_send_hello(struct zclient *zclient)
|
||||
{
|
||||
struct stream *s;
|
||||
|
||||
if (zclient->redist_default) {
|
||||
if (zclient->redist_default || zclient->synchronous) {
|
||||
s = zclient->obuf;
|
||||
stream_reset(s);
|
||||
|
||||
@ -390,6 +392,10 @@ static int zebra_hello_send(struct zclient *zclient)
|
||||
stream_putc(s, 1);
|
||||
else
|
||||
stream_putc(s, 0);
|
||||
if (zclient->synchronous)
|
||||
stream_putc(s, 1);
|
||||
else
|
||||
stream_putc(s, 0);
|
||||
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
return zclient_send_message(zclient);
|
||||
@ -629,7 +635,7 @@ int zclient_start(struct zclient *zclient)
|
||||
/* Create read thread. */
|
||||
zclient_event(ZCLIENT_READ, zclient);
|
||||
|
||||
zebra_hello_send(zclient);
|
||||
zclient_send_hello(zclient);
|
||||
|
||||
zebra_message_send(zclient, ZEBRA_INTERFACE_ADD, VRF_DEFAULT);
|
||||
|
||||
|
@ -255,6 +255,9 @@ struct zclient {
|
||||
/* Do we care about failure events for route install? */
|
||||
bool receive_notify;
|
||||
|
||||
/* Is this a synchronous client? */
|
||||
bool synchronous;
|
||||
|
||||
/* Socket to zebra daemon. */
|
||||
int sock;
|
||||
|
||||
@ -569,6 +572,7 @@ enum zebra_neigh_state { ZEBRA_NEIGH_INACTIVE = 0, ZEBRA_NEIGH_ACTIVE = 1 };
|
||||
|
||||
struct zclient_options {
|
||||
bool receive_notify;
|
||||
bool synchronous;
|
||||
};
|
||||
|
||||
extern struct zclient_options zclient_options_default;
|
||||
@ -796,4 +800,9 @@ extern void zclient_send_mlag_deregister(struct zclient *client);
|
||||
extern void zclient_send_mlag_data(struct zclient *client,
|
||||
struct stream *client_s);
|
||||
|
||||
/* Send the hello message.
|
||||
* Returns 0 for success or -1 on an I/O error.
|
||||
*/
|
||||
extern int zclient_send_hello(struct zclient *client);
|
||||
|
||||
#endif /* _ZEBRA_ZCLIENT_H */
|
||||
|
@ -61,6 +61,14 @@ static int zclient_lookup_connect(struct thread *t)
|
||||
zlookup->fail = 0; /* reset counter on connection */
|
||||
}
|
||||
|
||||
if (zclient_send_hello(zlookup) < 0) {
|
||||
if (close(zlookup->sock)) {
|
||||
zlog_warn("%s: closing fd=%d: errno=%d %s", __func__,
|
||||
zlookup->sock, errno, safe_strerror(errno));
|
||||
}
|
||||
zlookup->sock = -1;
|
||||
}
|
||||
|
||||
if (zlookup->sock < 0) {
|
||||
/* Since last connect failed, retry within 10 secs */
|
||||
zclient_lookup_sched(zlookup, 10);
|
||||
@ -125,7 +133,10 @@ void zclient_lookup_free(void)
|
||||
|
||||
void zclient_lookup_new(void)
|
||||
{
|
||||
zlookup = zclient_new(router->master, &zclient_options_default);
|
||||
struct zclient_options options = zclient_options_default;
|
||||
options.synchronous = true;
|
||||
|
||||
zlookup = zclient_new(router->master, &options);
|
||||
if (!zlookup) {
|
||||
flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_new() failure",
|
||||
__func__);
|
||||
@ -161,6 +172,7 @@ static int zclient_read_nexthop(struct pim_instance *pim,
|
||||
|
||||
if (PIM_DEBUG_PIM_NHT_DETAIL) {
|
||||
char addr_str[INET_ADDRSTRLEN];
|
||||
|
||||
pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
|
||||
zlog_debug("%s: addr=%s(%s)", __func__, addr_str,
|
||||
pim->vrf->name);
|
||||
|
@ -288,6 +288,10 @@ void redistribute_delete(const struct prefix *p, const struct prefix *src_p,
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
|
||||
/* Do not send unsolicited messages to synchronous clients. */
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
if (new_re) {
|
||||
/* Skip this client if it will receive an update for the
|
||||
* 'new' re
|
||||
@ -469,6 +473,12 @@ void zebra_interface_up_update(struct interface *ifp)
|
||||
if (ifp->ptm_status || !ifp->ptm_enable) {
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode,
|
||||
client)) {
|
||||
/* Do not send unsolicited messages to synchronous
|
||||
* clients.
|
||||
*/
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
zsend_interface_update(ZEBRA_INTERFACE_UP,
|
||||
client, ifp);
|
||||
zsend_interface_link_params(client, ifp);
|
||||
@ -487,6 +497,10 @@ void zebra_interface_down_update(struct interface *ifp)
|
||||
ifp->name, ifp->vrf_id);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
|
||||
/* Do not send unsolicited messages to synchronous clients. */
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp);
|
||||
}
|
||||
}
|
||||
@ -502,6 +516,10 @@ void zebra_interface_add_update(struct interface *ifp)
|
||||
ifp->vrf_id);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
|
||||
/* Do not send unsolicited messages to synchronous clients. */
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
client->ifadd_cnt++;
|
||||
zsend_interface_add(client, ifp);
|
||||
zsend_interface_link_params(client, ifp);
|
||||
@ -518,6 +536,10 @@ void zebra_interface_delete_update(struct interface *ifp)
|
||||
ifp->name, ifp->vrf_id);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
|
||||
/* Do not send unsolicited messages to synchronous clients. */
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
client->ifdel_cnt++;
|
||||
zsend_interface_delete(client, ifp);
|
||||
}
|
||||
@ -549,12 +571,17 @@ void zebra_interface_address_add_update(struct interface *ifp,
|
||||
|
||||
router_id_add_address(ifc);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client))
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
|
||||
/* Do not send unsolicited messages to synchronous clients. */
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) {
|
||||
client->connected_rt_add_cnt++;
|
||||
zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_ADD,
|
||||
client, ifp, ifc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Interface address deletion. */
|
||||
@ -578,12 +605,17 @@ void zebra_interface_address_delete_update(struct interface *ifp,
|
||||
|
||||
router_id_del_address(ifc);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client))
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
|
||||
/* Do not send unsolicited messages to synchronous clients. */
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) {
|
||||
client->connected_rt_del_cnt++;
|
||||
zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_DELETE,
|
||||
client, ifp, ifc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Interface VRF change. May need to delete from clients not interested in
|
||||
@ -600,6 +632,10 @@ void zebra_interface_vrf_update_del(struct interface *ifp, vrf_id_t new_vrf_id)
|
||||
ifp->name, ifp->vrf_id, new_vrf_id);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
|
||||
/* Do not send unsolicited messages to synchronous clients. */
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
/* Need to delete if the client is not interested in the new
|
||||
* VRF. */
|
||||
zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp);
|
||||
@ -623,6 +659,10 @@ void zebra_interface_vrf_update_add(struct interface *ifp, vrf_id_t old_vrf_id)
|
||||
ifp->name, old_vrf_id, ifp->vrf_id);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
|
||||
/* Do not send unsolicited messages to synchronous clients. */
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
/* Need to add if the client is interested in the new VRF. */
|
||||
client->ifadd_cnt++;
|
||||
zsend_interface_add(client, ifp);
|
||||
@ -910,6 +950,11 @@ void zebra_interface_parameters_update(struct interface *ifp)
|
||||
zlog_debug("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s(%u)",
|
||||
ifp->name, ifp->vrf_id);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client))
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
|
||||
/* Do not send unsolicited messages to synchronous clients. */
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
zsend_interface_link_params(client, ifp);
|
||||
}
|
||||
}
|
||||
|
@ -383,9 +383,14 @@ static void zebra_interface_nbr_address_add_update(struct interface *ifp,
|
||||
p->prefixlen, ifc->ifp->name);
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client))
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
|
||||
/* Do not send unsolicited messages to synchronous clients. */
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
|
||||
client, ifp, ifc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Interface address deletion. */
|
||||
@ -407,9 +412,14 @@ static void zebra_interface_nbr_address_delete_update(struct interface *ifp,
|
||||
p->prefixlen, ifc->ifp->name);
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client))
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
|
||||
/* Do not send unsolicited messages to synchronous clients. */
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_DELETE,
|
||||
client, ifp, ifc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send addresses on interface to client */
|
||||
@ -1744,6 +1754,10 @@ void zsend_capabilities_all_clients(void)
|
||||
|
||||
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
|
||||
/* Do not send unsolicited messages to synchronous clients. */
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
zsend_capabilities(client, zvrf);
|
||||
}
|
||||
}
|
||||
@ -1755,13 +1769,18 @@ static void zread_hello(ZAPI_HANDLER_ARGS)
|
||||
uint8_t proto;
|
||||
unsigned short instance;
|
||||
uint8_t notify;
|
||||
uint8_t synchronous;
|
||||
|
||||
STREAM_GETC(msg, proto);
|
||||
STREAM_GETW(msg, instance);
|
||||
STREAM_GETC(msg, notify);
|
||||
STREAM_GETC(msg, synchronous);
|
||||
if (notify)
|
||||
client->notify_owner = true;
|
||||
|
||||
if (synchronous)
|
||||
client->synchronous = true;
|
||||
|
||||
/* accept only dynamic routing protocols */
|
||||
if ((proto < ZEBRA_ROUTE_MAX) && (proto > ZEBRA_ROUTE_CONNECT)) {
|
||||
zlog_notice(
|
||||
@ -1778,8 +1797,10 @@ static void zread_hello(ZAPI_HANDLER_ARGS)
|
||||
zebra_gr_client_reconnect(client);
|
||||
}
|
||||
|
||||
zsend_capabilities(client, zvrf);
|
||||
zebra_vrf_update_all(client);
|
||||
if (!client->synchronous) {
|
||||
zsend_capabilities(client, zvrf);
|
||||
zebra_vrf_update_all(client);
|
||||
}
|
||||
stream_failure:
|
||||
return;
|
||||
}
|
||||
|
@ -60,8 +60,13 @@ static void zebra_vrf_add_update(struct zebra_vrf *zvrf)
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
zlog_debug("MESSAGE: ZEBRA_VRF_ADD %s", zvrf_name(zvrf));
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client))
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
|
||||
/* Do not send unsolicited messages to synchronous clients. */
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
zsend_vrf_add(client, zvrf);
|
||||
}
|
||||
}
|
||||
|
||||
static void zebra_vrf_delete_update(struct zebra_vrf *zvrf)
|
||||
@ -72,8 +77,13 @@ static void zebra_vrf_delete_update(struct zebra_vrf *zvrf)
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
zlog_debug("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf_name(zvrf));
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client))
|
||||
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
|
||||
/* Do not send unsolicited messages to synchronous clients. */
|
||||
if (client->synchronous)
|
||||
continue;
|
||||
|
||||
zsend_vrf_delete(client, zvrf);
|
||||
}
|
||||
}
|
||||
|
||||
void zebra_vrf_update_all(struct zserv *client)
|
||||
|
@ -131,6 +131,9 @@ struct zserv {
|
||||
|
||||
bool notify_owner;
|
||||
|
||||
/* Indicates if client is synchronous. */
|
||||
bool synchronous;
|
||||
|
||||
/* client's protocol */
|
||||
uint8_t proto;
|
||||
uint16_t instance;
|
||||
|
Loading…
Reference in New Issue
Block a user