Skip to content

Commit

Permalink
Merge pull request #5560 from sworleys/Pim-Vrf-Hang-3
Browse files Browse the repository at this point in the history
lib,zebra: add zapi msg top level error handling
  • Loading branch information
Mark Stapp committed Jan 8, 2020
2 parents f20b318 + b83e35c commit 94d7dc5
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 10 deletions.
1 change: 1 addition & 0 deletions lib/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,7 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_VXLAN_SG_ADD),
DESC_ENTRY(ZEBRA_VXLAN_SG_DEL),
DESC_ENTRY(ZEBRA_VXLAN_SG_REPLAY),
DESC_ENTRY(ZEBRA_ERROR),
};
#undef DESC_ENTRY

Expand Down
28 changes: 28 additions & 0 deletions lib/zclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,21 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr)
return false;
}

bool zapi_error_decode(struct stream *s, enum zebra_error_types *error)
{
memset(error, 0, sizeof(*error));

STREAM_GET(error, s, sizeof(*error));

if (zclient_debug)
zlog_debug("%s: type: %s", __func__,
zebra_error_type2str(*error));

return true;
stream_failure:
return false;
}

/*
* send a ZEBRA_REDISTRIBUTE_ADD or ZEBRA_REDISTRIBUTE_DELETE
* for the route type (ZEBRA_ROUTE_KERNEL etc.). The zebra server will
Expand Down Expand Up @@ -1706,6 +1721,17 @@ static void zclient_interface_down(struct zclient *zclient, vrf_id_t vrf_id)
if_down_via_zapi(ifp);
}

static void zclient_handle_error(ZAPI_CALLBACK_ARGS)
{
enum zebra_error_types error;
struct stream *s = zclient->ibuf;

zapi_error_decode(s, &error);

if (zclient->handle_error)
(*zclient->handle_error)(error);
}

static void link_params_set_value(struct stream *s, struct if_link_params *iflp)
{

Expand Down Expand Up @@ -3153,6 +3179,8 @@ static int zclient_read(struct thread *thread)
case ZEBRA_MLAG_FORWARD_MSG:
zclient_mlag_handle_msg(command, zclient, length, vrf_id);
break;
case ZEBRA_ERROR:
zclient_handle_error(command, zclient, length, vrf_id);
default:
break;
}
Expand Down
30 changes: 30 additions & 0 deletions lib/zclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,34 @@ typedef enum {
ZEBRA_MLAG_CLIENT_REGISTER,
ZEBRA_MLAG_CLIENT_UNREGISTER,
ZEBRA_MLAG_FORWARD_MSG,
ZEBRA_ERROR,
} zebra_message_types_t;

enum zebra_error_types {
ZEBRA_UNKNOWN_ERROR, /* Error of unknown type */
ZEBRA_NO_VRF, /* Vrf in header was not found */
ZEBRA_INVALID_MSG_TYPE, /* No handler found for msg type */
};

static inline const char *zebra_error_type2str(enum zebra_error_types type)
{
const char *ret = "UNKNOWN";

switch (type) {
case ZEBRA_UNKNOWN_ERROR:
ret = "ZEBRA_UNKNOWN_ERROR";
break;
case ZEBRA_NO_VRF:
ret = "ZEBRA_NO_VRF";
break;
case ZEBRA_INVALID_MSG_TYPE:
ret = "ZEBRA_INVALID_MSG_TYPE";
break;
}

return ret;
}

struct redist_proto {
uint8_t enabled;
struct list *instances;
Expand Down Expand Up @@ -280,6 +306,7 @@ struct zclient {
int (*mlag_process_up)(void);
int (*mlag_process_down)(void);
int (*mlag_handle_msg)(struct stream *msg, int len);
int (*handle_error)(enum zebra_error_types error);
};

/* Zebra API message flag. */
Expand Down Expand Up @@ -728,6 +755,9 @@ int zapi_nexthop_from_nexthop(struct zapi_nexthop *znh,
extern bool zapi_nexthop_update_decode(struct stream *s,
struct zapi_route *nhr);

/* Decode the zebra error message */
extern bool zapi_error_decode(struct stream *s, enum zebra_error_types *error);

static inline void zapi_route_set_blackhole(struct zapi_route *api,
enum blackhole_type bh_type)
{
Expand Down
11 changes: 10 additions & 1 deletion pimd/pim_zlookup.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,14 @@ static int zclient_read_nexthop(struct pim_instance *pim,
zclient_lookup_failed(zlookup);
return -1;
}

if (command == ZEBRA_ERROR) {
enum zebra_error_types error;

zapi_error_decode(s, &error);
/* Do nothing with it for now */
return -1;
}
}

raddr.s_addr = stream_get_ipv4(s);
Expand Down Expand Up @@ -338,7 +346,8 @@ static int zclient_lookup_nexthop_once(struct pim_instance *pim,

s = zlookup->obuf;
stream_reset(s);
zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, pim->vrf_id);
zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB,
pim->vrf->vrf_id);
stream_put_in_addr(s, &addr);
stream_putw_at(s, 0, stream_get_endp(s));

Expand Down
63 changes: 54 additions & 9 deletions zebra/zapi_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,25 @@ static int zserv_encode_nexthop(struct stream *s, struct nexthop *nexthop)
return 1;
}

/*
* Zebra error addition adds error type.
*
*
* 0 1
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | enum zebra_error_types |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
static void zserv_encode_error(struct stream *s, enum zebra_error_types error)
{
stream_put(s, &error, sizeof(error));

/* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
}

/* Send handlers ----------------------------------------------------------- */

/* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
Expand Down Expand Up @@ -2518,6 +2537,36 @@ static inline void zread_iptable(ZAPI_HANDLER_ARGS)
return;
}

static void zsend_error_msg(struct zserv *client, enum zebra_error_types error,
struct zmsghdr *bad_hdr)
{

struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);

zclient_create_header(s, ZEBRA_ERROR, bad_hdr->vrf_id);

zserv_encode_error(s, error);

client->error_cnt++;
zserv_send_message(client, s);
}

static void zserv_error_no_vrf(ZAPI_HANDLER_ARGS)
{
if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
zlog_debug("ZAPI message specifies unknown VRF: %d",
hdr->vrf_id);

return zsend_error_msg(client, ZEBRA_NO_VRF, hdr);
}

static void zserv_error_invalid_msg_type(ZAPI_HANDLER_ARGS)
{
zlog_info("Zebra received unknown command %d", hdr->command);

return zsend_error_msg(client, ZEBRA_INVALID_MSG_TYPE, hdr);
}

void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_ROUTER_ID_ADD] = zread_router_id_add,
[ZEBRA_ROUTER_ID_DELETE] = zread_router_id_delete,
Expand Down Expand Up @@ -2643,16 +2692,12 @@ void zserv_handle_commands(struct zserv *client, struct stream *msg)

/* lookup vrf */
zvrf = zebra_vrf_lookup_by_id(hdr.vrf_id);
if (!zvrf) {
if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
zlog_debug("ZAPI message specifies unknown VRF: %d",
hdr.vrf_id);
return;
}
if (!zvrf)
return zserv_error_no_vrf(client, &hdr, msg, zvrf);

if (hdr.command >= array_size(zserv_handlers)
|| zserv_handlers[hdr.command] == NULL)
zlog_info("Zebra received unknown command %d", hdr.command);
else
zserv_handlers[hdr.command](client, &hdr, msg, zvrf);
return zserv_error_invalid_msg_type(client, &hdr, msg, zvrf);

zserv_handlers[hdr.command](client, &hdr, msg, zvrf);
}
1 change: 1 addition & 0 deletions zebra/zserv.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ struct zserv {
uint32_t v6_nh_watch_rem_cnt;
uint32_t vxlan_sg_add_cnt;
uint32_t vxlan_sg_del_cnt;
uint32_t error_cnt;

time_t nh_reg_time;
time_t nh_dereg_time;
Expand Down

0 comments on commit 94d7dc5

Please sign in to comment.