diff options
| -rw-r--r-- | lib/log.c | 1 | ||||
| -rw-r--r-- | lib/zclient.c | 28 | ||||
| -rw-r--r-- | lib/zclient.h | 30 | ||||
| -rw-r--r-- | pimd/pim_zlookup.c | 11 | ||||
| -rw-r--r-- | zebra/zapi_msg.c | 63 | ||||
| -rw-r--r-- | zebra/zserv.h | 1 |
6 files changed, 124 insertions, 10 deletions
@@ -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; |
