summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/log.c1
-rw-r--r--lib/zclient.c28
-rw-r--r--lib/zclient.h30
-rw-r--r--pimd/pim_zlookup.c11
-rw-r--r--zebra/zapi_msg.c63
-rw-r--r--zebra/zserv.h1
6 files changed, 124 insertions, 10 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/pimd/pim_zlookup.c b/pimd/pim_zlookup.c
index 77526281d1..0454c0d69e 100644
--- a/pimd/pim_zlookup.c
+++ b/pimd/pim_zlookup.c
@@ -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);
@@ -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));
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;