summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Worley <sworley@cumulusnetworks.com>2019-12-17 17:00:52 -0500
committerStephen Worley <sworley@cumulusnetworks.com>2020-01-08 12:22:29 -0500
commit9ab0b2a37afc6b098e9ae444459dbb783ad0a5ff (patch)
tree3b8a18344f931ad514ee2123f99e653576e04bf7
parentf84f7121f6e142be732a25b4e7cd1105f7593495 (diff)
lib,zebra: add zapi msg top level error handling
Add error handling for top level failures (not able to execute command, unable to find vrf for command, etc.) With this error handling we add a new zapi message type of ZEBRA_ERROR used when we are unable to properly handle a zapi command and pass it down into the lower level code. In the event of this, we reply with a message of type enum zebra_error_types containing the error type. The sent packet will look like so: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length | Marker | Version | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | VRF ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Command | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ERROR TYPE | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Also add appropriate hooks for clients to subscribe to for handling these types of errors. Signed-off-by: Stephen Worley <sworley@cumulusnetworks.com>
-rw-r--r--lib/log.c1
-rw-r--r--lib/zclient.c28
-rw-r--r--lib/zclient.h30
-rw-r--r--zebra/zapi_msg.c63
-rw-r--r--zebra/zserv.h1
5 files changed, 114 insertions, 9 deletions
diff --git a/lib/log.c b/lib/log.c
index c777868736..798b776d00 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -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
diff --git a/lib/zclient.c b/lib/zclient.c
index fd1b181e58..093af44389 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -1467,6 +1467,21 @@ stream_failure:
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
@@ -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)
{
@@ -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;
}
diff --git a/lib/zclient.h b/lib/zclient.h
index 70304127a2..38b6030fa3 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -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;
@@ -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. */
@@ -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)
{
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 5a63c1e4f6..651babdeba 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -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. */
@@ -2518,6 +2537,36 @@ stream_failure:
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,
@@ -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);
}
diff --git a/zebra/zserv.h b/zebra/zserv.h
index ccc8d92aa2..d8d82a52ec 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -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;