]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib,zebra: add zapi msg top level error handling
authorStephen Worley <sworley@cumulusnetworks.com>
Tue, 17 Dec 2019 22:00:52 +0000 (17:00 -0500)
committerStephen Worley <sworley@cumulusnetworks.com>
Wed, 8 Jan 2020 17:22:29 +0000 (12:22 -0500)
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>
lib/log.c
lib/zclient.c
lib/zclient.h
zebra/zapi_msg.c
zebra/zserv.h

index c77786873601024fec83ed7165a1c057aaae0e99..798b776d0074f479dda58a1f2a4263d403ea21af 100644 (file)
--- 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
 
index fd1b181e58b235ff29cdd04ab76504d7b1997467..093af443893083d29342070f15abf5720271c3bc 100644 (file)
@@ -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;
        }
index 70304127a26b9f75f68bd5ab855d808ca0834b1e..38b6030fa32e5ec191a952ab4062e30f44a419a8 100644 (file)
@@ -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)
 {
index 5a63c1e4f669a89de37c40695e1829be94aec069..651babdebac59b82483c5aa67a959d9c330f447c 100644 (file)
@@ -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);
 }
index ccc8d92aa2d6f5d311e2dcbdb0ec86d3d1fec119..d8d82a52ec47bab8765843ba94351734211fed23 100644 (file)
@@ -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;