mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-10 17:58:29 +00:00
zebra: Add a function handler for zserv commands
The zserv command handlers make an already long function even longer. Isolate this code so that we can rearrange the zebra_client_read function. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
parent
6680688cf2
commit
0c5e7be5b3
238
zebra/zserv.c
238
zebra/zserv.c
@ -2228,122 +2228,11 @@ static int zread_interface_set_master(struct zserv *client,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handler of zebra service request. */
|
static inline void zserv_handle_commands(struct zserv *client,
|
||||||
static int zebra_client_read(struct thread *thread)
|
uint16_t command,
|
||||||
|
uint16_t length,
|
||||||
|
struct zebra_vrf *zvrf)
|
||||||
{
|
{
|
||||||
int sock;
|
|
||||||
struct zserv *client;
|
|
||||||
size_t already;
|
|
||||||
uint16_t length, command;
|
|
||||||
uint8_t marker, version;
|
|
||||||
vrf_id_t vrf_id;
|
|
||||||
struct zebra_vrf *zvrf;
|
|
||||||
|
|
||||||
/* Get thread data. Reset reading thread because I'm running. */
|
|
||||||
sock = THREAD_FD(thread);
|
|
||||||
client = THREAD_ARG(thread);
|
|
||||||
client->t_read = NULL;
|
|
||||||
|
|
||||||
if (client->t_suicide) {
|
|
||||||
zebra_client_close(client);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read length and command (if we don't have it already). */
|
|
||||||
if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE) {
|
|
||||||
ssize_t nbyte;
|
|
||||||
if (((nbyte = stream_read_try(client->ibuf, sock,
|
|
||||||
ZEBRA_HEADER_SIZE - already))
|
|
||||||
== 0)
|
|
||||||
|| (nbyte == -1)) {
|
|
||||||
if (IS_ZEBRA_DEBUG_EVENT)
|
|
||||||
zlog_debug("connection closed socket [%d]",
|
|
||||||
sock);
|
|
||||||
zebra_client_close(client);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) {
|
|
||||||
/* Try again later. */
|
|
||||||
zebra_event(ZEBRA_READ, sock, client);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
already = ZEBRA_HEADER_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset to read from the beginning of the incoming packet. */
|
|
||||||
stream_set_getp(client->ibuf, 0);
|
|
||||||
|
|
||||||
/* Fetch header values */
|
|
||||||
length = stream_getw(client->ibuf);
|
|
||||||
marker = stream_getc(client->ibuf);
|
|
||||||
version = stream_getc(client->ibuf);
|
|
||||||
vrf_id = stream_getw(client->ibuf);
|
|
||||||
command = stream_getw(client->ibuf);
|
|
||||||
|
|
||||||
if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) {
|
|
||||||
zlog_err(
|
|
||||||
"%s: socket %d version mismatch, marker %d, version %d",
|
|
||||||
__func__, sock, marker, version);
|
|
||||||
zebra_client_close(client);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (length < ZEBRA_HEADER_SIZE) {
|
|
||||||
zlog_warn(
|
|
||||||
"%s: socket %d message length %u is less than header size %d",
|
|
||||||
__func__, sock, length, ZEBRA_HEADER_SIZE);
|
|
||||||
zebra_client_close(client);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (length > STREAM_SIZE(client->ibuf)) {
|
|
||||||
zlog_warn(
|
|
||||||
"%s: socket %d message length %u exceeds buffer size %lu",
|
|
||||||
__func__, sock, length,
|
|
||||||
(u_long)STREAM_SIZE(client->ibuf));
|
|
||||||
zebra_client_close(client);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read rest of data. */
|
|
||||||
if (already < length) {
|
|
||||||
ssize_t nbyte;
|
|
||||||
if (((nbyte = stream_read_try(client->ibuf, sock,
|
|
||||||
length - already))
|
|
||||||
== 0)
|
|
||||||
|| (nbyte == -1)) {
|
|
||||||
if (IS_ZEBRA_DEBUG_EVENT)
|
|
||||||
zlog_debug(
|
|
||||||
"connection closed [%d] when reading zebra data",
|
|
||||||
sock);
|
|
||||||
zebra_client_close(client);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (nbyte != (ssize_t)(length - already)) {
|
|
||||||
/* Try again later. */
|
|
||||||
zebra_event(ZEBRA_READ, sock, client);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
length -= ZEBRA_HEADER_SIZE;
|
|
||||||
|
|
||||||
/* Debug packet information. */
|
|
||||||
if (IS_ZEBRA_DEBUG_EVENT)
|
|
||||||
zlog_debug("zebra message comes from socket [%d]", sock);
|
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
|
|
||||||
zlog_debug("zebra message received [%s] %d in VRF %u",
|
|
||||||
zserv_command_string(command), length, vrf_id);
|
|
||||||
|
|
||||||
client->last_read_time = monotime(NULL);
|
|
||||||
client->last_read_cmd = command;
|
|
||||||
|
|
||||||
zvrf = zebra_vrf_lookup_by_id(vrf_id);
|
|
||||||
if (!zvrf) {
|
|
||||||
if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
|
|
||||||
zlog_debug("zebra received unknown VRF[%u]", vrf_id);
|
|
||||||
goto zclient_read_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case ZEBRA_ROUTER_ID_ADD:
|
case ZEBRA_ROUTER_ID_ADD:
|
||||||
zread_router_id_add(client, length, zvrf);
|
zread_router_id_add(client, length, zvrf);
|
||||||
@ -2485,6 +2374,125 @@ static int zebra_client_read(struct thread *thread)
|
|||||||
zlog_info("Zebra received unknown command %d", command);
|
zlog_info("Zebra received unknown command %d", command);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handler of zebra service request. */
|
||||||
|
static int zebra_client_read(struct thread *thread)
|
||||||
|
{
|
||||||
|
int sock;
|
||||||
|
struct zserv *client;
|
||||||
|
size_t already;
|
||||||
|
uint16_t length, command;
|
||||||
|
uint8_t marker, version;
|
||||||
|
vrf_id_t vrf_id;
|
||||||
|
struct zebra_vrf *zvrf;
|
||||||
|
|
||||||
|
/* Get thread data. Reset reading thread because I'm running. */
|
||||||
|
sock = THREAD_FD(thread);
|
||||||
|
client = THREAD_ARG(thread);
|
||||||
|
client->t_read = NULL;
|
||||||
|
|
||||||
|
if (client->t_suicide) {
|
||||||
|
zebra_client_close(client);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read length and command (if we don't have it already). */
|
||||||
|
if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE) {
|
||||||
|
ssize_t nbyte;
|
||||||
|
if (((nbyte = stream_read_try(client->ibuf, sock,
|
||||||
|
ZEBRA_HEADER_SIZE - already))
|
||||||
|
== 0)
|
||||||
|
|| (nbyte == -1)) {
|
||||||
|
if (IS_ZEBRA_DEBUG_EVENT)
|
||||||
|
zlog_debug("connection closed socket [%d]",
|
||||||
|
sock);
|
||||||
|
zebra_client_close(client);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) {
|
||||||
|
/* Try again later. */
|
||||||
|
zebra_event(ZEBRA_READ, sock, client);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
already = ZEBRA_HEADER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset to read from the beginning of the incoming packet. */
|
||||||
|
stream_set_getp(client->ibuf, 0);
|
||||||
|
|
||||||
|
/* Fetch header values */
|
||||||
|
length = stream_getw(client->ibuf);
|
||||||
|
marker = stream_getc(client->ibuf);
|
||||||
|
version = stream_getc(client->ibuf);
|
||||||
|
vrf_id = stream_getw(client->ibuf);
|
||||||
|
command = stream_getw(client->ibuf);
|
||||||
|
|
||||||
|
if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) {
|
||||||
|
zlog_err(
|
||||||
|
"%s: socket %d version mismatch, marker %d, version %d",
|
||||||
|
__func__, sock, marker, version);
|
||||||
|
zebra_client_close(client);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (length < ZEBRA_HEADER_SIZE) {
|
||||||
|
zlog_warn(
|
||||||
|
"%s: socket %d message length %u is less than header size %d",
|
||||||
|
__func__, sock, length, ZEBRA_HEADER_SIZE);
|
||||||
|
zebra_client_close(client);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (length > STREAM_SIZE(client->ibuf)) {
|
||||||
|
zlog_warn(
|
||||||
|
"%s: socket %d message length %u exceeds buffer size %lu",
|
||||||
|
__func__, sock, length,
|
||||||
|
(u_long)STREAM_SIZE(client->ibuf));
|
||||||
|
zebra_client_close(client);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read rest of data. */
|
||||||
|
if (already < length) {
|
||||||
|
ssize_t nbyte;
|
||||||
|
if (((nbyte = stream_read_try(client->ibuf, sock,
|
||||||
|
length - already))
|
||||||
|
== 0)
|
||||||
|
|| (nbyte == -1)) {
|
||||||
|
if (IS_ZEBRA_DEBUG_EVENT)
|
||||||
|
zlog_debug(
|
||||||
|
"connection closed [%d] when reading zebra data",
|
||||||
|
sock);
|
||||||
|
zebra_client_close(client);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (nbyte != (ssize_t)(length - already)) {
|
||||||
|
/* Try again later. */
|
||||||
|
zebra_event(ZEBRA_READ, sock, client);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
length -= ZEBRA_HEADER_SIZE;
|
||||||
|
|
||||||
|
/* Debug packet information. */
|
||||||
|
if (IS_ZEBRA_DEBUG_EVENT)
|
||||||
|
zlog_debug("zebra message comes from socket [%d]", sock);
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
|
||||||
|
zlog_debug("zebra message received [%s] %d in VRF %u",
|
||||||
|
zserv_command_string(command), length, vrf_id);
|
||||||
|
|
||||||
|
client->last_read_time = monotime(NULL);
|
||||||
|
client->last_read_cmd = command;
|
||||||
|
|
||||||
|
zvrf = zebra_vrf_lookup_by_id(vrf_id);
|
||||||
|
if (!zvrf) {
|
||||||
|
if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
|
||||||
|
zlog_debug("zebra received unknown VRF[%u]", vrf_id);
|
||||||
|
goto zclient_read_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
zserv_handle_commands(client, command, length, zvrf);
|
||||||
|
|
||||||
if (client->t_suicide) {
|
if (client->t_suicide) {
|
||||||
/* No need to wait for thread callback, just kill immediately.
|
/* No need to wait for thread callback, just kill immediately.
|
||||||
|
Loading…
Reference in New Issue
Block a user