summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/zclient.c12
-rw-r--r--lib/zclient.h65
-rw-r--r--zebra/label_manager.c22
-rw-r--r--zebra/redistribute.c24
-rw-r--r--zebra/redistribute.h15
-rw-r--r--zebra/rtadv.c14
-rw-r--r--zebra/rtadv.h5
-rw-r--r--zebra/zebra_mpls.c5
-rw-r--r--zebra/zebra_mroute.c14
-rw-r--r--zebra/zebra_mroute.h5
-rw-r--r--zebra/zebra_ptm.c38
-rw-r--r--zebra/zebra_ptm.h12
-rw-r--r--zebra/zebra_ptm_redistribute.c10
-rw-r--r--zebra/zebra_rnh.c5
-rw-r--r--zebra/zebra_vxlan.c132
-rw-r--r--zebra/zebra_vxlan.h24
-rw-r--r--zebra/zserv.c1812
-rw-r--r--zebra/zserv.h14
18 files changed, 1127 insertions, 1101 deletions
diff --git a/lib/zclient.c b/lib/zclient.c
index fa3a5f6691..c720e2519b 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -322,6 +322,18 @@ stream_failure:
return 0;
}
+bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr)
+{
+ STREAM_GETW(zmsg, hdr->length);
+ STREAM_GETC(zmsg, hdr->marker);
+ STREAM_GETC(zmsg, hdr->version);
+ STREAM_GETL(zmsg, hdr->vrf_id);
+ STREAM_GETW(zmsg, hdr->command);
+ return true;
+stream_failure:
+ return false;
+}
+
/* Send simple Zebra message. */
static int zebra_message_send(struct zclient *zclient, int command,
vrf_id_t vrf_id)
diff --git a/lib/zclient.h b/lib/zclient.h
index 1aa94b641c..8033488444 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -237,14 +237,13 @@ struct zclient {
*/
#define ZAPI_MESSAGE_TABLEID 0x80
+#define ZSERV_VERSION 5
/* Zserv protocol message header */
-struct zserv_header {
+struct zmsghdr {
uint16_t length;
- uint8_t marker; /* corresponds to command field in old zserv
- * always set to 255 in new zserv.
- */
+ /* Always set to 255 in new zserv */
+ uint8_t marker;
uint8_t version;
-#define ZSERV_VERSION 5
vrf_id_t vrf_id;
uint16_t command;
};
@@ -380,9 +379,11 @@ struct zclient_options {
/* Prototypes of zebra client service functions. */
extern struct zclient *zclient_new(struct thread_master *);
+/* clang-format off */
#if CONFDATE > 20181101
CPP_NOTICE("zclient_new_notify can take over or zclient_new now");
#endif
+/* clang-format on */
extern struct zclient_options zclient_options_default;
@@ -449,9 +450,58 @@ extern int zclient_send_message(struct zclient *);
/* create header for command, length to be filled in by user later */
extern void zclient_create_header(struct stream *, uint16_t, vrf_id_t);
+/*
+ * Read sizeof(struct zmsghdr) bytes from the provided socket and parse the
+ * received data into the specified fields. If this is successful, read the
+ * rest of the packet into the provided stream.
+ *
+ * s
+ * The stream to read into
+ *
+ * sock
+ * The socket to read from
+ *
+ * size
+ * Parsed message size will be placed in the pointed-at integer
+ *
+ * marker
+ * Parsed marker will be placed in the pointed-at byte
+ *
+ * version
+ * Parsed version will be placed in the pointed-at byte
+ *
+ * vrf_id
+ * Parsed VRF ID will be placed in the pointed-at vrf_id_t
+ *
+ * cmd
+ * Parsed command number will be placed in the pointed-at integer
+ *
+ * Returns:
+ * -1 if:
+ * - insufficient data for header was read
+ * - a version mismatch was detected
+ * - a marker mismatch was detected
+ * - header size field specified more data than could be read
+ */
extern int zclient_read_header(struct stream *s, int sock, u_int16_t *size,
u_char *marker, u_char *version,
vrf_id_t *vrf_id, u_int16_t *cmd);
+/*
+ * Parse header from ZAPI message stream into struct zmsghdr.
+ * This function assumes the stream getp points at the first byte of the header.
+ * If the function is successful then the stream getp will point to the byte
+ * immediately after the last byte of the header.
+ *
+ * zmsg
+ * The stream containing the header
+ *
+ * hdr
+ * The header struct to parse into.
+ *
+ * Returns:
+ * true if parsing succeeded, false otherwise
+ */
+extern bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr);
extern void zclient_interface_set_master(struct zclient *client,
struct interface *master,
@@ -468,10 +518,11 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s,
extern void zebra_interface_if_set_value(struct stream *, struct interface *);
extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid);
+/* clang-format off */
#if CONFDATE > 20180823
-CPP_NOTICE(
- "zapi_ipv4_route, zapi_ipv6_route, zapi_ipv4_route_ipv6_nexthop as well as the zapi_ipv4 and zapi_ipv6 data structures should be removed now");
+CPP_NOTICE("zapi_ipv4_route, zapi_ipv6_route, zapi_ipv4_route_ipv6_nexthop as well as the zapi_ipv4 and zapi_ipv6 data structures should be removed now");
#endif
+/* clang-format on */
extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *,
struct zapi_ipv4 *) __attribute__((deprecated));
diff --git a/zebra/label_manager.c b/zebra/label_manager.c
index 5bf0fce094..b58f0c9ff8 100644
--- a/zebra/label_manager.c
+++ b/zebra/label_manager.c
@@ -50,6 +50,8 @@ DEFINE_MTYPE_STATIC(LBL_MGR, LM_CHUNK, "Label Manager Chunk");
* it will be a proxy to relay messages to external label manager
* This zclient thus is to connect to it
*/
+static struct stream *ibuf;
+static struct stream *obuf;
static struct zclient *zclient;
bool lm_is_external;
@@ -69,7 +71,7 @@ static int relay_response_back(struct zserv *zserv)
u_int16_t resp_cmd;
src = zclient->ibuf;
- dst = zserv->obuf;
+ dst = obuf;
stream_reset(src);
@@ -87,7 +89,7 @@ static int relay_response_back(struct zserv *zserv)
/* send response back */
stream_copy(dst, src);
- ret = writen(zserv->sock, dst->data, stream_get_endp(dst));
+ ret = writen(zserv->sock, src->data, stream_get_endp(src));
if (ret <= 0) {
zlog_err("%s: Error sending Label Manager response back: %s",
__func__, strerror(errno));
@@ -116,10 +118,10 @@ static int lm_zclient_read(struct thread *t)
static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id)
{
+ int ret;
struct stream *s;
- s = zserv->obuf;
- stream_reset(s);
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, cmd, vrf_id);
@@ -129,7 +131,10 @@ static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id)
/* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
- return writen(zserv->sock, s->data, stream_get_endp(s));
+ ret = writen(zserv->sock, s->data, stream_get_endp(s));
+
+ stream_free(s);
+ return ret;
}
/**
* Receive a request to get or release a label chunk and forward it to external
@@ -161,7 +166,7 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv,
ret = relay_response_back(zserv);
/* Send request to external label manager */
- src = zserv->ibuf;
+ src = ibuf;
dst = zclient->obuf;
stream_copy(dst, src);
@@ -247,6 +252,9 @@ void label_manager_init(char *lm_zserv_path)
lm_is_external = true;
lm_zclient_init(lm_zserv_path);
}
+
+ ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ obuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
}
/**
@@ -379,4 +387,6 @@ int release_daemon_chunks(u_char proto, u_short instance)
void label_manager_close()
{
list_delete_and_null(&lbl_mgr.lc_list);
+ stream_free(ibuf);
+ stream_free(obuf);
}
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index a7b2361ac6..5a239306fb 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -243,16 +243,15 @@ void redistribute_delete(struct prefix *p, struct prefix *src_p,
}
}
-void zebra_redistribute_add(int command, struct zserv *client, int length,
- struct zebra_vrf *zvrf)
+void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
{
afi_t afi = 0;
int type = 0;
u_short instance;
- STREAM_GETC(client->ibuf, afi);
- STREAM_GETC(client->ibuf, type);
- STREAM_GETW(client->ibuf, instance);
+ STREAM_GETC(msg, afi);
+ STREAM_GETC(msg, type);
+ STREAM_GETW(msg, instance);
if (afi == 0 || afi > AFI_MAX) {
zlog_warn("%s: Specified afi %d does not exist",
@@ -287,16 +286,15 @@ stream_failure:
return;
}
-void zebra_redistribute_delete(int command, struct zserv *client, int length,
- struct zebra_vrf *zvrf)
+void zebra_redistribute_delete(ZAPI_HANDLER_ARGS)
{
afi_t afi = 0;
int type = 0;
u_short instance;
- STREAM_GETC(client->ibuf, afi);
- STREAM_GETC(client->ibuf, type);
- STREAM_GETW(client->ibuf, instance);
+ STREAM_GETC(msg, afi);
+ STREAM_GETC(msg, type);
+ STREAM_GETW(msg, instance);
if (afi == 0 || afi > AFI_MAX) {
zlog_warn("%s: Specified afi %d does not exist",
@@ -325,15 +323,13 @@ stream_failure:
return;
}
-void zebra_redistribute_default_add(int command, struct zserv *client,
- int length, struct zebra_vrf *zvrf)
+void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS)
{
vrf_bitmap_set(client->redist_default, zvrf_id(zvrf));
zebra_redistribute_default(client, zvrf_id(zvrf));
}
-void zebra_redistribute_default_delete(int command, struct zserv *client,
- int length, struct zebra_vrf *zvrf)
+void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS)
{
vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf));
}
diff --git a/zebra/redistribute.h b/zebra/redistribute.h
index 5edb06c3da..e551f820cc 100644
--- a/zebra/redistribute.h
+++ b/zebra/redistribute.h
@@ -27,15 +27,12 @@
#include "vty.h"
#include "vrf.h"
-extern void zebra_redistribute_add(int, struct zserv *, int,
- struct zebra_vrf *zvrf);
-extern void zebra_redistribute_delete(int, struct zserv *, int,
- struct zebra_vrf *zvrf);
-
-extern void zebra_redistribute_default_add(int, struct zserv *, int,
- struct zebra_vrf *zvrf);
-extern void zebra_redistribute_default_delete(int, struct zserv *, int,
- struct zebra_vrf *zvrf);
+/* ZAPI command handlers */
+extern void zebra_redistribute_add(ZAPI_HANDLER_ARGS);
+extern void zebra_redistribute_delete(ZAPI_HANDLER_ARGS);
+extern void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS);
+extern void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS);
+/* ----------------- */
extern void redistribute_update(struct prefix *, struct prefix *,
struct route_entry *, struct route_entry *);
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index 5eebca163b..d0b821bfd2 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -801,8 +801,7 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
* if the operator has explicitly enabled RA. The enable request can also
* specify a RA interval (in seconds).
*/
-void zebra_interface_radv_set(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf, int enable)
+static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
{
struct stream *s;
ifindex_t ifindex;
@@ -810,7 +809,7 @@ void zebra_interface_radv_set(struct zserv *client, u_short length,
struct zebra_if *zif;
int ra_interval;
- s = client->ibuf;
+ s = msg;
/* Get interface index and RA interval. */
STREAM_GETL(s, ifindex);
@@ -859,6 +858,15 @@ stream_failure:
return;
}
+void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)
+{
+ zebra_interface_radv_set(client, hdr, msg, zvrf, 0);
+}
+void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
+{
+ zebra_interface_radv_set(client, hdr, msg, zvrf, 1);
+}
+
DEFUN (ipv6_nd_suppress_ra,
ipv6_nd_suppress_ra_cmd,
"ipv6 nd suppress-ra",
diff --git a/zebra/rtadv.h b/zebra/rtadv.h
index 2cae6d06f9..8fd67c8a63 100644
--- a/zebra/rtadv.h
+++ b/zebra/rtadv.h
@@ -103,7 +103,8 @@ typedef enum {
extern void rtadv_init(struct zebra_ns *);
extern void rtadv_terminate(struct zebra_ns *);
extern void rtadv_cmd_init(void);
-extern void zebra_interface_radv_set(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf, int enable);
+extern void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS);
+extern void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS);
+
#endif /* _ZEBRA_RTADV_H */
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 0af06806d3..1868b4676d 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -455,8 +455,7 @@ static int fec_send(zebra_fec_t *fec, struct zserv *client)
rn = fec->rn;
/* Get output stream. */
- s = client->obuf;
- stream_reset(s);
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_FEC_UPDATE, VRF_DEFAULT);
@@ -464,7 +463,7 @@ static int fec_send(zebra_fec_t *fec, struct zserv *client)
stream_put_prefix(s, &rn->p);
stream_putl(s, fec->label);
stream_putw_at(s, 0, stream_get_endp(s));
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
/*
diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c
index e9cd19ebe0..042bd3769e 100644
--- a/zebra/zebra_mroute.c
+++ b/zebra/zebra_mroute.c
@@ -32,17 +32,16 @@
#include "zebra/rt.h"
#include "zebra/debug.h"
-int zebra_ipmr_route_stats(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS)
{
struct mcast_route_data mroute;
struct stream *s;
int suc = -1;
memset(&mroute, 0, sizeof(mroute));
- STREAM_GET(&mroute.sg.src, client->ibuf, 4);
- STREAM_GET(&mroute.sg.grp, client->ibuf, 4);
- STREAM_GETL(client->ibuf, mroute.ifindex);
+ STREAM_GET(&mroute.sg.src, msg, 4);
+ STREAM_GET(&mroute.sg.grp, msg, 4);
+ STREAM_GETL(msg, mroute.ifindex);
if (IS_ZEBRA_DEBUG_KERNEL) {
char sbuf[40];
@@ -57,7 +56,7 @@ int zebra_ipmr_route_stats(struct zserv *client, u_short length,
suc = kernel_get_ipmr_sg_stats(zvrf, &mroute);
stream_failure:
- s = client->obuf;
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
@@ -68,6 +67,5 @@ stream_failure:
stream_putl(s, suc);
stream_putw_at(s, 0, stream_get_endp(s));
- zebra_server_send_message(client);
- return 0;
+ zebra_server_send_message(client, s);
}
diff --git a/zebra/zebra_mroute.h b/zebra/zebra_mroute.h
index 616c3a83ab..3385153600 100644
--- a/zebra/zebra_mroute.h
+++ b/zebra/zebra_mroute.h
@@ -22,13 +22,14 @@
#ifndef __ZEBRA_MROUTE_H__
#define __ZEBRA_MROUTE_H__
+#include "zebra/zserv.h"
+
struct mcast_route_data {
struct prefix_sg sg;
unsigned int ifindex;
unsigned long long lastused;
};
-int zebra_ipmr_route_stats(struct zserv *client, u_short length,
- struct zebra_vrf *zvf);
+void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS);
#endif
diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c
index f6775fa0b1..67c7220b6f 100644
--- a/zebra/zebra_ptm.c
+++ b/zebra/zebra_ptm.c
@@ -661,8 +661,7 @@ int zebra_ptm_sock_read(struct thread *thread)
}
/* BFD peer/dst register/update */
-int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length,
- int command, struct zebra_vrf *zvrf)
+void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS)
{
struct stream *s;
struct prefix src_p;
@@ -680,20 +679,20 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length,
int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
unsigned int pid;
- if (command == ZEBRA_BFD_DEST_UPDATE)
+ if (hdr->command == ZEBRA_BFD_DEST_UPDATE)
client->bfd_peer_upd8_cnt++;
else
client->bfd_peer_add_cnt++;
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("bfd_dst_register msg from client %s: length=%d",
- zebra_route_string(client->proto), length);
+ zebra_route_string(client->proto), hdr->length);
if (ptm_cb.ptm_sock == -1) {
ptm_cb.t_timer = NULL;
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
ptm_cb.reconnect_time, &ptm_cb.t_timer);
- return -1;
+ return;
}
ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
@@ -703,7 +702,7 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length,
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
tmp_buf);
- s = client->ibuf;
+ s = msg;
STREAM_GETL(s, pid);
sprintf(tmp_buf, "%d", pid);
@@ -816,16 +815,14 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length,
ptm_cb.out_data);
zebra_ptm_send_message(ptm_cb.out_data, data_len);
- return 0;
+ return;
stream_failure:
ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
- return 0;
}
/* BFD peer/dst deregister */
-int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS)
{
struct stream *s;
struct prefix src_p;
@@ -843,13 +840,13 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length,
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("bfd_dst_deregister msg from client %s: length=%d",
- zebra_route_string(client->proto), length);
+ zebra_route_string(client->proto), hdr->length);
if (ptm_cb.ptm_sock == -1) {
ptm_cb.t_timer = NULL;
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
ptm_cb.reconnect_time, &ptm_cb.t_timer);
- return -1;
+ return;
}
ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
@@ -861,7 +858,7 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length,
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
tmp_buf);
- s = client->ibuf;
+ s = msg;
STREAM_GETL(s, pid);
sprintf(tmp_buf, "%d", pid);
@@ -948,15 +945,14 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length,
zebra_ptm_send_message(ptm_cb.out_data, data_len);
- return 0;
+ return;
stream_failure:
ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
- return 0;
}
/* BFD client register */
-int zebra_ptm_bfd_client_register(struct zserv *client, u_short length)
+void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS)
{
struct stream *s;
unsigned int pid;
@@ -968,16 +964,16 @@ int zebra_ptm_bfd_client_register(struct zserv *client, u_short length)
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("bfd_client_register msg from client %s: length=%d",
- zebra_route_string(client->proto), length);
+ zebra_route_string(client->proto), hdr->length);
- s = client->ibuf;
+ s = msg;
STREAM_GETL(s, pid);
if (ptm_cb.ptm_sock == -1) {
ptm_cb.t_timer = NULL;
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
ptm_cb.reconnect_time, &ptm_cb.t_timer);
- return -1;
+ return;
}
ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
@@ -1003,7 +999,7 @@ int zebra_ptm_bfd_client_register(struct zserv *client, u_short length)
SET_FLAG(ptm_cb.client_flags[client->proto],
ZEBRA_PTM_BFD_CLIENT_FLAG_REG);
- return 0;
+ return;
stream_failure:
/*
@@ -1013,7 +1009,7 @@ stream_failure:
* if (out_ctxt)
* ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
*/
- return 0;
+ return;
}
/* BFD client deregister */
diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h
index 392853b599..0b41410bec 100644
--- a/zebra/zebra_ptm.h
+++ b/zebra/zebra_ptm.h
@@ -28,6 +28,8 @@ extern const char ZEBRA_PTM_SOCK_NAME[];
#define ZEBRA_PTM_BFD_CLIENT_FLAG_REG (1 << 1) /* client registered with BFD */
+#include "zebra/zserv.h"
+
/* Zebra ptm context block */
struct zebra_ptm_cb {
int ptm_sock; /* ptm file descriptor. */
@@ -62,12 +64,12 @@ int zebra_ptm_connect(struct thread *t);
void zebra_ptm_write(struct vty *vty);
int zebra_ptm_get_enable_state(void);
-int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length,
- int command, struct zebra_vrf *zvrf);
-int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf);
+/* ZAPI message handlers */
+void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS);
+void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS);
+void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS);
+
void zebra_ptm_show_status(struct vty *vty, struct interface *ifp);
-int zebra_ptm_bfd_client_register(struct zserv *client, u_short length);
void zebra_ptm_if_init(struct zebra_if *zebra_ifp);
void zebra_ptm_if_set_ptm_state(struct interface *ifp,
struct zebra_if *zebra_ifp);
diff --git a/zebra/zebra_ptm_redistribute.c b/zebra/zebra_ptm_redistribute.c
index 8fddd400cc..fe788ac4d7 100644
--- a/zebra/zebra_ptm_redistribute.c
+++ b/zebra/zebra_ptm_redistribute.c
@@ -38,8 +38,7 @@ static int zsend_interface_bfd_update(int cmd, struct zserv *client,
if (!client->ifinfo)
return 0;
- s = client->obuf;
- stream_reset(s);
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, cmd, vrf_id);
if (ifp)
@@ -66,7 +65,7 @@ static int zsend_interface_bfd_update(int cmd, struct zserv *client,
stream_putw_at(s, 0, stream_get_endp(s));
client->if_bfd_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
void zebra_interface_bfd_update(struct interface *ifp, struct prefix *dp,
@@ -93,8 +92,7 @@ static int zsend_bfd_peer_replay(int cmd, struct zserv *client)
{
struct stream *s;
- s = client->obuf;
- stream_reset(s);
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, cmd, VRF_DEFAULT);
@@ -102,7 +100,7 @@ static int zsend_bfd_peer_replay(int cmd, struct zserv *client)
stream_putw_at(s, 0, stream_get_endp(s));
client->bfd_peer_replay_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
void zebra_bfd_peer_replay_req(void)
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index dd3fe17702..c9fb782ba6 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -995,8 +995,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
re = rnh->state;
/* Get output stream. */
- s = client->obuf;
- stream_reset(s);
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, cmd, vrf_id);
@@ -1063,7 +1062,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
client->nh_last_upd_time = monotime(NULL);
client->last_write_cmd = cmd;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
static void print_nh(struct nexthop *nexthop, struct vty *vty)
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index d3ede66fb0..256fa9e4b7 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -1157,8 +1157,7 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
if (!client)
return 0;
- s = client->obuf;
- stream_reset(s);
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, cmd, VRF_DEFAULT);
stream_putl(s, vni);
@@ -1195,7 +1194,7 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
else
client->macipdel_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
/*
@@ -2565,8 +2564,7 @@ static int zvni_send_add_to_client(zebra_vni_t *zvni)
if (!client)
return 0;
- s = client->obuf;
- stream_reset(s);
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT);
stream_putl(s, zvni->vni);
@@ -2583,7 +2581,7 @@ static int zvni_send_add_to_client(zebra_vni_t *zvni)
zebra_route_string(client->proto));
client->vniadd_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
/*
@@ -2599,7 +2597,7 @@ static int zvni_send_del_to_client(vni_t vni)
if (!client)
return 0;
- s = client->obuf;
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
zclient_create_header(s, ZEBRA_VNI_DEL, VRF_DEFAULT);
@@ -2613,7 +2611,7 @@ static int zvni_send_del_to_client(vni_t vni)
zebra_route_string(client->proto));
client->vnidel_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
/*
@@ -3550,8 +3548,7 @@ static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni)
memset(&rmac, 0, sizeof(struct ethaddr));
zl3vni_get_rmac(zl3vni, &rmac);
- s = client->obuf;
- stream_reset(s);
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni));
stream_putl(s, zl3vni->vni);
@@ -3574,7 +3571,7 @@ static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni)
zebra_route_string(client->proto));
client->l3vniadd_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
/*
@@ -3590,8 +3587,7 @@ static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni)
if (!client)
return 0;
- s = client->obuf;
- stream_reset(s);
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_L3VNI_DEL, zl3vni_vrf_id(zl3vni));
stream_putl(s, zl3vni->vni);
@@ -3605,7 +3601,7 @@ static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni)
zebra_route_string(client->proto));
client->l3vnidel_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni)
@@ -3723,8 +3719,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
if (!client)
return 0;
- s = client->obuf;
- stream_reset(s);
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, cmd, vrf_id);
stream_put(s, p, sizeof(struct prefix));
@@ -3743,7 +3738,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
else
client->prefixdel_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
/* re-add remote rmac if needed */
@@ -4863,8 +4858,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
/*
* Handle message from client to delete a remote MACIP for a VNI.
*/
-int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS)
{
struct stream *s;
vni_t vni;
@@ -4884,9 +4878,9 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length,
memset(&ip, 0, sizeof(struct ipaddr));
memset(&vtep_ip, 0, sizeof(struct in_addr));
- s = client->ibuf;
+ s = msg;
- while (l < length) {
+ while (l < hdr->length) {
/* Obtain each remote MACIP and process. */
/* Message contains VNI, followed by MAC followed by IP (if any)
* followed by remote VTEP IP.
@@ -5008,7 +5002,7 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length,
}
stream_failure:
- return 0;
+ return;
}
/*
@@ -5016,8 +5010,7 @@ stream_failure:
* could be just the add of a MAC address or the add of a neighbor
* (IP+MAC).
*/
-int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
{
struct stream *s;
vni_t vni;
@@ -5045,12 +5038,12 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
zlog_warn(
"%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
__PRETTY_FUNCTION__);
- return -1;
+ return;
}
- s = client->ibuf;
+ s = msg;
- while (l < length) {
+ while (l < hdr->length) {
/* Obtain each remote MACIP and process. */
/* Message contains VNI, followed by MAC followed by IP (if any)
* followed by remote VTEP IP.
@@ -5159,7 +5152,7 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
prefix_mac2str(&macaddr, buf,
sizeof(buf)),
vni, inet_ntoa(vtep_ip));
- return -1;
+ return;
}
/* Is this MAC created for a MACIP? */
@@ -5212,7 +5205,7 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
prefix_mac2str(&macaddr, buf,
sizeof(buf)),
vni, inet_ntoa(vtep_ip));
- return -1;
+ return;
}
} else if (memcmp(&n->emac, &macaddr, sizeof(macaddr))
@@ -5240,7 +5233,7 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
}
stream_failure:
- return 0;
+ return;
}
/*
@@ -5543,8 +5536,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
/*
* Handle message from client to delete a remote VTEP for a VNI.
*/
-int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS)
{
struct stream *s;
u_short l = 0;
@@ -5559,18 +5551,18 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length,
zlog_warn(
"%s: EVPN is not enabled yet we have received a vtep del command",
__PRETTY_FUNCTION__);
- return -1;
+ return;
}
if (zvrf_id(zvrf) != VRF_DEFAULT) {
zlog_err("Recv MACIP DEL for non-default VRF %u",
zvrf_id(zvrf));
- return -1;
+ return;
}
- s = client->ibuf;
+ s = msg;
- while (l < length) {
+ while (l < hdr->length) {
/* Obtain each remote VTEP and process. */
STREAM_GETL(s, vni);
l += 4;
@@ -5623,14 +5615,13 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length,
}
stream_failure:
- return 0;
+ return;
}
/*
* Handle message from client to add a remote VTEP for a VNI.
*/
-int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)
{
struct stream *s;
u_short l = 0;
@@ -5644,18 +5635,18 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length,
zlog_warn(
"%s: EVPN not enabled yet we received a vtep_add zapi call",
__PRETTY_FUNCTION__);
- return -1;
+ return;
}
if (zvrf_id(zvrf) != VRF_DEFAULT) {
zlog_err("Recv MACIP ADD for non-default VRF %u",
zvrf_id(zvrf));
- return -1;
+ return;
}
- s = client->ibuf;
+ s = msg;
- while (l < length) {
+ while (l < hdr->length) {
/* Obtain each remote VTEP and process. */
STREAM_GETL(s, vni);
l += 4;
@@ -5705,7 +5696,7 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length,
}
stream_failure:
- return 0;
+ return;
}
/*
@@ -6512,8 +6503,7 @@ int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
* Handle message from client to enable/disable advertisement of g/w macip
* routes
*/
-int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)
{
struct stream *s;
int advertise;
@@ -6527,19 +6517,19 @@ int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length,
if (zvrf_id(zvrf) != VRF_DEFAULT) {
zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
zvrf_id(zvrf));
- return -1;
+ return;
}
- s = client->ibuf;
+ s = msg;
advertise = stream_getc(s);
vni = stream_get3(s);
zvni = zvni_lookup(vni);
if (!zvni)
- return 0;
+ return;
if (zvni->advertise_subnet == advertise)
- return 0;
+ return;
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
@@ -6551,35 +6541,32 @@ int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length,
ifp = zvni->vxlan_if;
if (!ifp)
- return 0;
+ return;
zif = ifp->info;
/* If down or not mapped to a bridge, we're done. */
if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
- return 0;
+ return;
zl2_info = zif->l2info.vxl;
vlan_if =
zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
if (!vlan_if)
- return 0;
+ return;
if (zvni->advertise_subnet)
zvni_advertise_subnet(zvni, vlan_if, 1);
else
zvni_advertise_subnet(zvni, vlan_if, 0);
-
- return 0;
}
/*
* Handle message from client to enable/disable advertisement of g/w macip
* routes
*/
-int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)
{
struct stream *s;
int advertise;
@@ -6590,10 +6577,10 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
if (zvrf_id(zvrf) != VRF_DEFAULT) {
zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
zvrf_id(zvrf));
- return -1;
+ return;
}
- s = client->ibuf;
+ s = msg;
STREAM_GETC(s, advertise);
STREAM_GET(&vni, s, 3);
@@ -6606,7 +6593,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
: "disabled");
if (zvrf->advertise_gw_macip == advertise)
- return 0;
+ return;
zvrf->advertise_gw_macip = advertise;
@@ -6625,7 +6612,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
zvni = zvni_lookup(vni);
if (!zvni)
- return 0;
+ return;
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
@@ -6635,26 +6622,26 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
: "disabled");
if (zvni->advertise_gw_macip == advertise)
- return 0;
+ return;
zvni->advertise_gw_macip = advertise;
ifp = zvni->vxlan_if;
if (!ifp)
- return 0;
+ return;
zif = ifp->info;
/* If down or not mapped to a bridge, we're done. */
if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
- return 0;
+ return;
zl2_info = zif->l2info.vxl;
vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
zif->brslave_info.br_if);
if (!vlan_if)
- return 0;
+ return;
if (advertise_gw_macip_enabled(zvni)) {
/* Add primary SVI MAC-IP */
@@ -6676,7 +6663,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
}
stream_failure:
- return 0;
+ return;
}
@@ -6686,8 +6673,7 @@ stream_failure:
* when disabled, the entries should be deleted and remote VTEPs and MACs
* uninstalled from the kernel.
*/
-int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
{
struct stream *s = NULL;
int advertise = 0;
@@ -6695,10 +6681,10 @@ int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length,
if (zvrf_id(zvrf) != VRF_DEFAULT) {
zlog_err("EVPN VNI Adv for non-default VRF %u", zvrf_id(zvrf));
- return -1;
+ return;
}
- s = client->ibuf;
+ s = msg;
STREAM_GETC(s, advertise);
if (IS_ZEBRA_DEBUG_VXLAN)
@@ -6707,7 +6693,7 @@ int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length,
is_evpn_enabled() ? "enabled" : "disabled");
if (zvrf->advertise_all_vni == advertise)
- return 0;
+ return;
zvrf->advertise_all_vni = advertise;
if (is_evpn_enabled()) {
@@ -6732,13 +6718,13 @@ int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length,
/* cleanup all l3vnis */
zns = zebra_ns_lookup(NS_DEFAULT);
if (!zns)
- return -1;
+ return;
hash_iterate(zns->l3vni_table, zl3vni_cleanup_all, NULL);
}
stream_failure:
- return 0;
+ return;
}
/*
diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h
index 7abf0050fc..6f25ad1e24 100644
--- a/zebra/zebra_vxlan.h
+++ b/zebra/zebra_vxlan.h
@@ -33,6 +33,7 @@
#include "lib/json.h"
#include "zebra/zebra_vrf.h"
+#include "zebra/zserv.h"
/* Is EVPN enabled? */
#define EVPN_ENABLED(zvrf) (zvrf)->advertise_all_vni
@@ -51,6 +52,15 @@ static inline int is_evpn_enabled()
#define VNI_STR_LEN 32
+/* ZAPI message handlers */
+extern void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS);
+extern void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS);
+extern void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS);
+extern void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS);
+extern void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS);
+extern void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS);
+extern void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS);
+
extern int is_l3vni_for_prefix_routes_only(vni_t vni);
extern ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id);
extern int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf);
@@ -117,10 +127,6 @@ extern int zebra_vxlan_local_neigh_add_update(
extern int zebra_vxlan_local_neigh_del(struct interface *ifp,
struct interface *link_if,
struct ipaddr *ip);
-extern int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf);
-extern int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf);
extern int zebra_vxlan_local_mac_add_update(struct interface *ifp,
struct interface *br_if,
struct ethaddr *mac, vlanid_t vid,
@@ -140,16 +146,6 @@ extern int zebra_vxlan_if_down(struct interface *ifp);
extern int zebra_vxlan_if_add(struct interface *ifp);
extern int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags);
extern int zebra_vxlan_if_del(struct interface *ifp);
-extern int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf);
-extern int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf);
-extern int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf);
-extern int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf);
-extern int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf);
extern int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
char *err, int err_str_sz,
int filter, int add);
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 1a2ad7f8b4..f53baf65d0 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -63,94 +63,23 @@
#include "zebra/zebra_pbr.h"
/* Event list of zebra. */
-enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE };
-
-static void zebra_event(enum event event, int sock, struct zserv *client);
-
+enum event { ZEBRA_READ, ZEBRA_WRITE };
+/* privileges */
extern struct zebra_privs_t zserv_privs;
+/* post event into client */
+static void zebra_event(struct zserv *client, enum event event);
-static void zebra_client_close(struct zserv *client);
-static int zserv_delayed_close(struct thread *thread)
-{
- struct zserv *client = THREAD_ARG(thread);
+/* Public interface ======================================================== */
- client->t_suicide = NULL;
- zebra_client_close(client);
- return 0;
-}
-
-static int zserv_flush_data(struct thread *thread)
+int zebra_server_send_message(struct zserv *client, struct stream *msg)
{
- struct zserv *client = THREAD_ARG(thread);
-
- client->t_write = NULL;
- if (client->t_suicide) {
- zebra_client_close(client);
- return -1;
- }
- switch (buffer_flush_available(client->wb, client->sock)) {
- case BUFFER_ERROR:
- zlog_warn(
- "%s: buffer_flush_available failed on zserv client fd %d, "
- "closing",
- __func__, client->sock);
- zebra_client_close(client);
- client = NULL;
- break;
- case BUFFER_PENDING:
- client->t_write = NULL;
- thread_add_write(zebrad.master, zserv_flush_data, client,
- client->sock, &client->t_write);
- break;
- case BUFFER_EMPTY:
- break;
- }
-
- if (client)
- client->last_write_time = monotime(NULL);
+ stream_fifo_push(client->obuf_fifo, msg);
+ zebra_event(client, ZEBRA_WRITE);
return 0;
}
-int zebra_server_send_message(struct zserv *client)
-{
- if (client->t_suicide)
- return -1;
-
- if (client->is_synchronous)
- return 0;
-
- stream_set_getp(client->obuf, 0);
- client->last_write_cmd = stream_getw_from(client->obuf, 6);
- switch (buffer_write(client->wb, client->sock,
- STREAM_DATA(client->obuf),
- stream_get_endp(client->obuf))) {
- case BUFFER_ERROR:
- zlog_warn(
- "%s: buffer_write failed to zserv client fd %d, closing",
- __func__, client->sock);
- /* Schedule a delayed close since many of the functions that
- call this
- one do not check the return code. They do not allow for the
- possibility that an I/O error may have caused the client to
- be
- deleted. */
- client->t_suicide = NULL;
- thread_add_event(zebrad.master, zserv_delayed_close, client, 0,
- &client->t_suicide);
- return -1;
- case BUFFER_EMPTY:
- THREAD_OFF(client->t_write);
- break;
- case BUFFER_PENDING:
- thread_add_write(zebrad.master, zserv_flush_data, client,
- client->sock, &client->t_write);
- break;
- }
-
- client->last_write_time = monotime(NULL);
- return 0;
-}
+/* Encoding helpers -------------------------------------------------------- */
static void zserv_encode_interface(struct stream *s, struct interface *ifp)
{
@@ -202,6 +131,34 @@ static void zserv_encode_vrf(struct stream *s, struct zebra_vrf *zvrf)
stream_putw_at(s, 0, stream_get_endp(s));
}
+static int zserv_encode_nexthop(struct stream *s, struct nexthop *nexthop)
+{
+ stream_putc(s, nexthop->type);
+ switch (nexthop->type) {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ stream_put_in_addr(s, &nexthop->gate.ipv4);
+ stream_putl(s, nexthop->ifindex);
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ stream_put(s, &nexthop->gate.ipv6, 16);
+ break;
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ stream_put(s, &nexthop->gate.ipv6, 16);
+ stream_putl(s, nexthop->ifindex);
+ break;
+ case NEXTHOP_TYPE_IFINDEX:
+ stream_putl(s, nexthop->ifindex);
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ return 1;
+}
+
+/* Send handlers ----------------------------------------------------------- */
+
/* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
/*
* This function is called in the following situations:
@@ -215,65 +172,54 @@ static void zserv_encode_vrf(struct stream *s, struct zebra_vrf *zvrf)
*/
int zsend_interface_add(struct zserv *client, struct interface *ifp)
{
- struct stream *s;
-
- s = client->obuf;
- stream_reset(s);
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_INTERFACE_ADD, ifp->vrf_id);
zserv_encode_interface(s, ifp);
client->ifadd_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
/* Interface deletion from zebra daemon. */
int zsend_interface_delete(struct zserv *client, struct interface *ifp)
{
- struct stream *s;
-
- s = client->obuf;
- stream_reset(s);
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id);
zserv_encode_interface(s, ifp);
client->ifdel_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
int zsend_vrf_add(struct zserv *client, struct zebra_vrf *zvrf)
{
- struct stream *s;
-
- s = client->obuf;
- stream_reset(s);
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_VRF_ADD, zvrf_id(zvrf));
zserv_encode_vrf(s, zvrf);
client->vrfadd_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
/* VRF deletion from zebra daemon. */
int zsend_vrf_delete(struct zserv *client, struct zebra_vrf *zvrf)
-{
- struct stream *s;
- s = client->obuf;
- stream_reset(s);
+{
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_VRF_DELETE, zvrf_id(zvrf));
zserv_encode_vrf(s, zvrf);
client->vrfdel_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
int zsend_interface_link_params(struct zserv *client, struct interface *ifp)
{
- struct stream *s;
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
/* Check this client need interface information. */
if (!client->ifinfo)
@@ -281,8 +227,6 @@ int zsend_interface_link_params(struct zserv *client, struct interface *ifp)
if (!ifp->link_params)
return 0;
- s = client->obuf;
- stream_reset(s);
zclient_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id);
@@ -296,7 +240,7 @@ int zsend_interface_link_params(struct zserv *client, struct interface *ifp)
/* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
/* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or
@@ -341,11 +285,8 @@ int zsend_interface_address(int cmd, struct zserv *client,
struct interface *ifp, struct connected *ifc)
{
int blen;
- struct stream *s;
struct prefix *p;
-
- s = client->obuf;
- stream_reset(s);
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, cmd, ifp->vrf_id);
stream_putl(s, ifp->ifindex);
@@ -378,7 +319,7 @@ int zsend_interface_address(int cmd, struct zserv *client,
stream_putw_at(s, 0, stream_get_endp(s));
client->connected_rt_add_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
static int zsend_interface_nbr_address(int cmd, struct zserv *client,
@@ -386,12 +327,9 @@ static int zsend_interface_nbr_address(int cmd, struct zserv *client,
struct nbr_connected *ifc)
{
int blen;
- struct stream *s;
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
struct prefix *p;
- s = client->obuf;
- stream_reset(s);
-
zclient_create_header(s, cmd, ifp->vrf_id);
stream_putl(s, ifp->ifindex);
@@ -412,7 +350,7 @@ static int zsend_interface_nbr_address(int cmd, struct zserv *client,
/* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
/* Interface address addition. */
@@ -498,10 +436,7 @@ int zsend_interface_addresses(struct zserv *client, struct interface *ifp)
int zsend_interface_vrf_update(struct zserv *client, struct interface *ifp,
vrf_id_t vrf_id)
{
- struct stream *s;
-
- s = client->obuf;
- stream_reset(s);
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id);
@@ -513,7 +448,7 @@ int zsend_interface_vrf_update(struct zserv *client, struct interface *ifp,
stream_putw_at(s, 0, stream_get_endp(s));
client->if_vrfchg_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
/* Add new nbr connected IPv6 address */
@@ -575,10 +510,7 @@ void nbr_connected_delete_ipv6(struct interface *ifp, struct in6_addr *address)
*/
int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)
{
- struct stream *s;
-
- s = client->obuf;
- stream_reset(s);
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, cmd, ifp->vrf_id);
zserv_encode_interface(s, ifp);
@@ -588,7 +520,7 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)
else
client->ifdown_cnt++;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
@@ -660,59 +592,272 @@ int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
api.mtu = re->mtu;
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+
/* Encode route and send. */
- if (zapi_route_encode(cmd, client->obuf, &api) < 0)
+ if (zapi_route_encode(cmd, s, &api) < 0)
return -1;
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
-static int zsend_write_nexthop(struct stream *s, struct nexthop *nexthop)
+/*
+ * Modified version of zsend_ipv4_nexthop_lookup(): Query unicast rib if
+ * nexthop is not found on mrib. Returns both route metric and protocol
+ * distance.
+ */
+static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client,
+ struct in_addr addr,
+ struct route_entry *re,
+ struct zebra_vrf *zvrf)
{
- stream_putc(s, nexthop->type);
- switch (nexthop->type) {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- stream_put_in_addr(s, &nexthop->gate.ipv4);
- stream_putl(s, nexthop->ifindex);
- break;
- case NEXTHOP_TYPE_IPV6:
- stream_put(s, &nexthop->gate.ipv6, 16);
- break;
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- stream_put(s, &nexthop->gate.ipv6, 16);
- stream_putl(s, nexthop->ifindex);
- break;
- case NEXTHOP_TYPE_IFINDEX:
- stream_putl(s, nexthop->ifindex);
- break;
- default:
- /* do nothing */
- break;
+ struct stream *s;
+ unsigned long nump;
+ u_char num;
+ struct nexthop *nexthop;
+
+ /* Get output stream. */
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ stream_reset(s);
+
+ /* Fill in result. */
+ zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id(zvrf));
+ stream_put_in_addr(s, &addr);
+
+ if (re) {
+ stream_putc(s, re->distance);
+ stream_putl(s, re->metric);
+ num = 0;
+ nump = stream_get_endp(
+ s); /* remember position for nexthop_num */
+ stream_putc(s, 0); /* reserve room for nexthop_num */
+ /* Only non-recursive routes are elegible to resolve the nexthop
+ * we
+ * are looking up. Therefore, we will just iterate over the top
+ * chain of nexthops. */
+ for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next)
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ num += zserv_encode_nexthop(s, nexthop);
+
+ stream_putc_at(s, nump, num); /* store nexthop_num */
+ } else {
+ stream_putc(s, 0); /* distance */
+ stream_putl(s, 0); /* metric */
+ stream_putc(s, 0); /* nexthop_num */
}
- return 1;
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zebra_server_send_message(client, s);
+}
+
+int zsend_route_notify_owner(struct route_entry *re, struct prefix *p,
+ enum zapi_route_notify_owner note)
+{
+ struct zserv *client;
+ struct stream *s;
+ uint8_t blen;
+
+ client = zebra_find_client(re->type, re->instance);
+ if (!client || !client->notify_owner) {
+ if (IS_ZEBRA_DEBUG_PACKET) {
+ char buff[PREFIX_STRLEN];
+
+ zlog_debug(
+ "Not Notifying Owner: %u about prefix %s(%u) %d",
+ re->type, prefix2str(p, buff, sizeof(buff)),
+ re->table, note);
+ }
+ return 0;
+ }
+
+ if (IS_ZEBRA_DEBUG_PACKET) {
+ char buff[PREFIX_STRLEN];
+
+ zlog_debug("Notifying Owner: %u about prefix %s(%u) %d",
+ re->type, prefix2str(p, buff, sizeof(buff)),
+ re->table, note);
+ }
+
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ stream_reset(s);
+
+ zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, re->vrf_id);
+
+ stream_put(s, &note, sizeof(note));
+
+ stream_putc(s, p->family);
+
+ blen = prefix_blen(p);
+ stream_putc(s, p->prefixlen);
+ stream_put(s, &p->u.prefix, blen);
+
+ stream_putl(s, re->table);
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zebra_server_send_message(client, s);
+}
+
+void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
+ enum zapi_rule_notify_owner note)
+{
+ struct listnode *node;
+ struct zserv *client;
+ struct stream *s;
+
+ if (IS_ZEBRA_DEBUG_PACKET) {
+ zlog_debug("%s: Notifying %u", __PRETTY_FUNCTION__,
+ rule->unique);
+ }
+
+ for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) {
+ if (rule->sock == client->sock)
+ break;
+ }
+
+ if (!client)
+ return;
+
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ stream_reset(s);
+
+ zclient_create_header(s, ZEBRA_RULE_NOTIFY_OWNER, VRF_DEFAULT);
+ stream_put(s, &note, sizeof(note));
+ stream_putl(s, rule->seq);
+ stream_putl(s, rule->priority);
+ stream_putl(s, rule->unique);
+ if (rule->ifp)
+ stream_putl(s, rule->ifp->ifindex);
+ else
+ stream_putl(s, 0);
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ zebra_server_send_message(client, s);
+}
+
+/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
+int zsend_router_id_update(struct zserv *client, struct prefix *p,
+ vrf_id_t vrf_id)
+{
+ int blen;
+
+ /* Check this client need interface information. */
+ if (!vrf_bitmap_check(client->ridinfo, vrf_id))
+ return 0;
+
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+
+ /* Message type. */
+ zclient_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id);
+
+ /* Prefix information. */
+ stream_putc(s, p->family);
+ blen = prefix_blen(p);
+ stream_put(s, &p->u.prefix, blen);
+ stream_putc(s, p->prefixlen);
+
+ /* Write packet size. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zebra_server_send_message(client, s);
+}
+
+/*
+ * Function used by Zebra to send a PW status update to LDP daemon
+ */
+int zsend_pw_update(struct zserv *client, struct zebra_pw *pw)
+{
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+
+ zclient_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id);
+ stream_write(s, pw->ifname, IF_NAMESIZE);
+ stream_putl(s, pw->ifindex);
+ stream_putl(s, pw->status);
+
+ /* Put length at the first point of the stream. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zebra_server_send_message(client, s);
}
+/* Send response to a get label chunk request to client */
+static int zsend_assign_label_chunk_response(struct zserv *client,
+ vrf_id_t vrf_id,
+ struct label_manager_chunk *lmc)
+{
+ int ret;
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+
+ zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id);
+
+ if (lmc) {
+ /* keep */
+ stream_putc(s, lmc->keep);
+ /* start and end labels */
+ stream_putl(s, lmc->start);
+ stream_putl(s, lmc->end);
+ }
+
+ /* Write packet size. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ ret = writen(client->sock, s->data, stream_get_endp(s));
+ stream_free(s);
+ return ret;
+}
+
+/* Send response to a label manager connect request to client */
+static int zsend_label_manager_connect_response(struct zserv *client,
+ vrf_id_t vrf_id, u_short result)
+{
+ int ret;
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+
+ zclient_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id);
+
+ /* result */
+ stream_putc(s, result);
+
+ /* Write packet size. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ ret = writen(client->sock, s->data, stream_get_endp(s));
+ stream_free(s);
+
+ return ret;
+}
+
+/* Inbound message handling ------------------------------------------------ */
+
+int cmd2type[] = {
+ [ZEBRA_NEXTHOP_REGISTER] = RNH_NEXTHOP_TYPE,
+ [ZEBRA_NEXTHOP_UNREGISTER] = RNH_NEXTHOP_TYPE,
+ [ZEBRA_IMPORT_ROUTE_REGISTER] = RNH_IMPORT_CHECK_TYPE,
+ [ZEBRA_IMPORT_ROUTE_UNREGISTER] = RNH_IMPORT_CHECK_TYPE,
+};
+
/* Nexthop register */
-static int zserv_rnh_register(struct zserv *client, u_short length,
- rnh_type_t type, struct zebra_vrf *zvrf)
+static void zread_rnh_register(ZAPI_HANDLER_ARGS)
{
struct rnh *rnh;
struct stream *s;
struct prefix p;
u_short l = 0;
u_char flags = 0;
+ uint16_t type = cmd2type[hdr->command];
if (IS_ZEBRA_DEBUG_NHT)
zlog_debug(
- "rnh_register msg from client %s: length=%d, type=%s\n",
- zebra_route_string(client->proto), length,
+ "rnh_register msg from client %s: hdr->length=%d, type=%s\n",
+ zebra_route_string(client->proto), hdr->length,
(type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route");
- s = client->ibuf;
+ s = msg;
client->nh_reg_time = monotime(NULL);
- while (l < length) {
+ while (l < hdr->length) {
STREAM_GETC(s, flags);
STREAM_GETW(s, p.family);
STREAM_GETC(s, p.prefixlen);
@@ -720,18 +865,18 @@ static int zserv_rnh_register(struct zserv *client, u_short length,
if (p.family == AF_INET) {
if (p.prefixlen > IPV4_MAX_BITLEN) {
zlog_warn(
- "%s: Specified prefix length %d is too large for a v4 address",
+ "%s: Specified prefix hdr->length %d is too large for a v4 address",
__PRETTY_FUNCTION__, p.prefixlen);
- return -1;
+ return;
}
STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
l += IPV4_MAX_BYTELEN;
} else if (p.family == AF_INET6) {
if (p.prefixlen > IPV6_MAX_BITLEN) {
zlog_warn(
- "%s: Specified prefix length %d is to large for a v6 address",
+ "%s: Specified prefix hdr->length %d is to large for a v6 address",
__PRETTY_FUNCTION__, p.prefixlen);
- return -1;
+ return;
}
STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN);
l += IPV6_MAX_BYTELEN;
@@ -739,7 +884,7 @@ static int zserv_rnh_register(struct zserv *client, u_short length,
zlog_err(
"rnh_register: Received unknown family type %d\n",
p.family);
- return -1;
+ return;
}
rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type);
if (type == RNH_NEXTHOP_TYPE) {
@@ -753,8 +898,9 @@ static int zserv_rnh_register(struct zserv *client, u_short length,
if (flags
&& !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH))
SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
- else if (!flags && CHECK_FLAG(rnh->flags,
- ZEBRA_NHT_EXACT_MATCH))
+ else if (!flags
+ && CHECK_FLAG(rnh->flags,
+ ZEBRA_NHT_EXACT_MATCH))
UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
}
@@ -764,25 +910,26 @@ static int zserv_rnh_register(struct zserv *client, u_short length,
}
stream_failure:
- return 0;
+ return;
}
/* Nexthop register */
-static int zserv_rnh_unregister(struct zserv *client, u_short length,
- rnh_type_t type, struct zebra_vrf *zvrf)
+static void zread_rnh_unregister(ZAPI_HANDLER_ARGS)
{
struct rnh *rnh;
struct stream *s;
struct prefix p;
u_short l = 0;
+ uint16_t type = cmd2type[hdr->command];
if (IS_ZEBRA_DEBUG_NHT)
- zlog_debug("rnh_unregister msg from client %s: length=%d\n",
- zebra_route_string(client->proto), length);
+ zlog_debug(
+ "rnh_unregister msg from client %s: hdr->length=%d\n",
+ zebra_route_string(client->proto), hdr->length);
- s = client->ibuf;
+ s = msg;
- while (l < length) {
+ while (l < hdr->length) {
uint8_t flags;
STREAM_GETC(s, flags);
@@ -795,18 +942,18 @@ static int zserv_rnh_unregister(struct zserv *client, u_short length,
if (p.family == AF_INET) {
if (p.prefixlen > IPV4_MAX_BITLEN) {
zlog_warn(
- "%s: Specified prefix length %d is to large for a v4 address",
+ "%s: Specified prefix hdr->length %d is to large for a v4 address",
__PRETTY_FUNCTION__, p.prefixlen);
- return -1;
+ return;
}
STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
l += IPV4_MAX_BYTELEN;
} else if (p.family == AF_INET6) {
if (p.prefixlen > IPV6_MAX_BITLEN) {
zlog_warn(
- "%s: Specified prefix length %d is to large for a v6 address",
+ "%s: Specified prefix hdr->length %d is to large for a v6 address",
__PRETTY_FUNCTION__, p.prefixlen);
- return -1;
+ return;
}
STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN);
l += IPV6_MAX_BYTELEN;
@@ -814,7 +961,7 @@ static int zserv_rnh_unregister(struct zserv *client, u_short length,
zlog_err(
"rnh_register: Received unknown family type %d\n",
p.family);
- return -1;
+ return;
}
rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type);
if (rnh) {
@@ -823,38 +970,37 @@ static int zserv_rnh_unregister(struct zserv *client, u_short length,
}
}
stream_failure:
- return 0;
+ return;
}
#define ZEBRA_MIN_FEC_LENGTH 5
/* FEC register */
-static int zserv_fec_register(struct zserv *client, u_short length)
+static void zread_fec_register(ZAPI_HANDLER_ARGS)
{
struct stream *s;
- struct zebra_vrf *zvrf;
u_short l = 0;
struct prefix p;
- u_int16_t flags;
- u_int32_t label_index = MPLS_INVALID_LABEL_INDEX;
+ uint16_t flags;
+ uint32_t label_index = MPLS_INVALID_LABEL_INDEX;
- s = client->ibuf;
+ s = msg;
zvrf = vrf_info_lookup(VRF_DEFAULT);
if (!zvrf)
- return 0; // unexpected
+ return; // unexpected
/*
* The minimum amount of data that can be sent for one fec
* registration
*/
- if (length < ZEBRA_MIN_FEC_LENGTH) {
+ if (hdr->length < ZEBRA_MIN_FEC_LENGTH) {
zlog_err(
- "fec_register: Received a fec register of length %d, it is of insufficient size to properly decode",
- length);
- return -1;
+ "fec_register: Received a fec register of hdr->length %d, it is of insufficient size to properly decode",
+ hdr->length);
+ return;
}
- while (l < length) {
+ while (l < hdr->length) {
STREAM_GETW(s, flags);
memset(&p, 0, sizeof(p));
STREAM_GETW(s, p.family);
@@ -862,16 +1008,16 @@ static int zserv_fec_register(struct zserv *client, u_short length)
zlog_err(
"fec_register: Received unknown family type %d\n",
p.family);
- return -1;
+ return;
}
STREAM_GETC(s, p.prefixlen);
if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN)
|| (p.family == AF_INET6
&& p.prefixlen > IPV6_MAX_BITLEN)) {
zlog_warn(
- "%s: Specified prefix length: %d is to long for %d",
+ "%s: Specified prefix hdr->length: %d is to long for %d",
__PRETTY_FUNCTION__, p.prefixlen, p.family);
- return -1;
+ return;
}
l += 5;
STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen));
@@ -885,35 +1031,34 @@ static int zserv_fec_register(struct zserv *client, u_short length)
}
stream_failure:
- return 0;
+ return;
}
/* FEC unregister */
-static int zserv_fec_unregister(struct zserv *client, u_short length)
+static void zread_fec_unregister(ZAPI_HANDLER_ARGS)
{
struct stream *s;
- struct zebra_vrf *zvrf;
u_short l = 0;
struct prefix p;
uint16_t flags;
- s = client->ibuf;
+ s = msg;
zvrf = vrf_info_lookup(VRF_DEFAULT);
if (!zvrf)
- return 0; // unexpected
+ return; // unexpected
/*
* The minimum amount of data that can be sent for one
* fec unregistration
*/
- if (length < ZEBRA_MIN_FEC_LENGTH) {
+ if (hdr->length < ZEBRA_MIN_FEC_LENGTH) {
zlog_err(
- "fec_unregister: Received a fec unregister of length %d, it is of insufficient size to properly decode",
- length);
- return -1;
+ "fec_unregister: Received a fec unregister of hdr->length %d, it is of insufficient size to properly decode",
+ hdr->length);
+ return;
}
- while (l < length) {
+ while (l < hdr->length) {
STREAM_GETW(s, flags);
if (flags != 0)
goto stream_failure;
@@ -924,16 +1069,16 @@ static int zserv_fec_unregister(struct zserv *client, u_short length)
zlog_err(
"fec_unregister: Received unknown family type %d\n",
p.family);
- return -1;
+ return;
}
STREAM_GETC(s, p.prefixlen);
if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN)
|| (p.family == AF_INET6
&& p.prefixlen > IPV6_MAX_BITLEN)) {
zlog_warn(
- "%s: Received prefix length %d which is greater than %d can support",
+ "%s: Received prefix hdr->length %d which is greater than %d can support",
__PRETTY_FUNCTION__, p.prefixlen, p.family);
- return -1;
+ return;
}
l += 5;
STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen));
@@ -942,199 +1087,15 @@ static int zserv_fec_unregister(struct zserv *client, u_short length)
}
stream_failure:
- return 0;
-}
-
-/*
- Modified version of zsend_ipv4_nexthop_lookup():
- Query unicast rib if nexthop is not found on mrib.
- Returns both route metric and protocol distance.
-*/
-static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client,
- struct in_addr addr,
- struct route_entry *re,
- struct zebra_vrf *zvrf)
-{
- struct stream *s;
- unsigned long nump;
- u_char num;
- struct nexthop *nexthop;
-
- /* Get output stream. */
- s = client->obuf;
- stream_reset(s);
-
- /* Fill in result. */
- zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id(zvrf));
- stream_put_in_addr(s, &addr);
-
- if (re) {
- stream_putc(s, re->distance);
- stream_putl(s, re->metric);
- num = 0;
- nump = stream_get_endp(
- s); /* remember position for nexthop_num */
- stream_putc(s, 0); /* reserve room for nexthop_num */
- /* Only non-recursive routes are elegible to resolve the nexthop
- * we
- * are looking up. Therefore, we will just iterate over the top
- * chain of nexthops. */
- for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next)
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- num += zsend_write_nexthop(s, nexthop);
-
- stream_putc_at(s, nump, num); /* store nexthop_num */
- } else {
- stream_putc(s, 0); /* distance */
- stream_putl(s, 0); /* metric */
- stream_putc(s, 0); /* nexthop_num */
- }
-
- stream_putw_at(s, 0, stream_get_endp(s));
-
- return zebra_server_send_message(client);
-}
-
-int zsend_route_notify_owner(struct route_entry *re, struct prefix *p,
- enum zapi_route_notify_owner note)
-{
- struct zserv *client;
- struct stream *s;
- uint8_t blen;
-
- client = zebra_find_client(re->type, re->instance);
- if (!client || !client->notify_owner) {
- if (IS_ZEBRA_DEBUG_PACKET) {
- char buff[PREFIX_STRLEN];
-
- zlog_debug(
- "Not Notifying Owner: %u about prefix %s(%u) %d",
- re->type, prefix2str(p, buff, sizeof(buff)),
- re->table, note);
- }
- return 0;
- }
-
- if (IS_ZEBRA_DEBUG_PACKET) {
- char buff[PREFIX_STRLEN];
-
- zlog_debug("Notifying Owner: %u about prefix %s(%u) %d",
- re->type, prefix2str(p, buff, sizeof(buff)),
- re->table, note);
- }
-
- s = client->obuf;
- stream_reset(s);
-
- zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, re->vrf_id);
-
- stream_put(s, &note, sizeof(note));
-
- stream_putc(s, p->family);
-
- blen = prefix_blen(p);
- stream_putc(s, p->prefixlen);
- stream_put(s, &p->u.prefix, blen);
-
- stream_putl(s, re->table);
-
- stream_putw_at(s, 0, stream_get_endp(s));
-
- return zebra_server_send_message(client);
-}
-
-void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
- enum zapi_rule_notify_owner note)
-{
- struct listnode *node;
- struct zserv *client;
- struct stream *s;
-
- if (IS_ZEBRA_DEBUG_PACKET) {
- zlog_debug("%s: Notifying %u",
- __PRETTY_FUNCTION__, rule->unique);
- }
-
- for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) {
- if (rule->sock == client->sock)
- break;
- }
-
- if (!client)
- return;
-
- s = client->obuf;
- stream_reset(s);
-
- zclient_create_header(s, ZEBRA_RULE_NOTIFY_OWNER, VRF_DEFAULT);
- stream_put(s, &note, sizeof(note));
- stream_putl(s, rule->seq);
- stream_putl(s, rule->priority);
- stream_putl(s, rule->unique);
- if (rule->ifp)
- stream_putl(s, rule->ifp->ifindex);
- else
- stream_putl(s, 0);
-
- stream_putw_at(s, 0, stream_get_endp(s));
-
- zebra_server_send_message(client);
+ return;
}
-/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
-int zsend_router_id_update(struct zserv *client, struct prefix *p,
- vrf_id_t vrf_id)
-{
- struct stream *s;
- int blen;
-
- /* Check this client need interface information. */
- if (!vrf_bitmap_check(client->ridinfo, vrf_id))
- return 0;
-
- s = client->obuf;
- stream_reset(s);
-
- /* Message type. */
- zclient_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id);
-
- /* Prefix information. */
- stream_putc(s, p->family);
- blen = prefix_blen(p);
- stream_put(s, &p->u.prefix, blen);
- stream_putc(s, p->prefixlen);
-
- /* Write packet size. */
- stream_putw_at(s, 0, stream_get_endp(s));
-
- return zebra_server_send_message(client);
-}
/*
- * Function used by Zebra to send a PW status update to LDP daemon
+ * Register zebra server interface information.
+ * Send current all interface and address information.
*/
-int zsend_pw_update(struct zserv *client, struct zebra_pw *pw)
-{
- struct stream *s;
-
- s = client->obuf;
- stream_reset(s);
-
- zclient_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id);
- stream_write(s, pw->ifname, IF_NAMESIZE);
- stream_putl(s, pw->ifindex);
- stream_putl(s, pw->status);
-
- /* Put length at the first point of the stream. */
- stream_putw_at(s, 0, stream_get_endp(s));
-
- return zebra_server_send_message(client);
-}
-
-/* Register zebra server interface information. Send current all
- interface and address information. */
-static int zread_interface_add(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+static void zread_interface_add(ZAPI_HANDLER_ARGS)
{
struct vrf *vrf;
struct interface *ifp;
@@ -1148,22 +1109,16 @@ static int zread_interface_add(struct zserv *client, u_short length,
if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE))
continue;
- if (zsend_interface_add(client, ifp) < 0)
- return -1;
-
- if (zsend_interface_addresses(client, ifp) < 0)
- return -1;
+ zsend_interface_add(client, ifp);
+ zsend_interface_addresses(client, ifp);
}
}
- return 0;
}
/* Unregister zebra server interface information. */
-static int zread_interface_delete(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+static void zread_interface_delete(ZAPI_HANDLER_ARGS)
{
vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf));
- return 0;
}
void zserv_nexthop_num_warn(const char *caller, const struct prefix *p,
@@ -1178,8 +1133,7 @@ void zserv_nexthop_num_warn(const char *caller, const struct prefix *p,
}
}
-static int zread_route_add(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+static void zread_route_add(ZAPI_HANDLER_ARGS)
{
struct stream *s;
struct zapi_route api;
@@ -1191,9 +1145,8 @@ static int zread_route_add(struct zserv *client, u_short length,
int i, ret;
vrf_id_t vrf_id = 0;
- s = client->ibuf;
- if (zapi_route_decode(s, &api) < 0)
- return -1;
+ s = msg;
+ zapi_route_decode(s, &api);
/* Allocate new route. */
vrf_id = zvrf_id(zvrf);
@@ -1277,7 +1230,7 @@ static int zread_route_add(struct zserv *client, u_short length,
__PRETTY_FUNCTION__, api.nexthop_num);
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
- return -1;
+ return;
}
/* MPLS labels for BGP-LU or Segment Routing */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL)
@@ -1309,7 +1262,7 @@ static int zread_route_add(struct zserv *client, u_short length,
__PRETTY_FUNCTION__);
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
- return -1;
+ return;
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
src_p = &api.src_prefix;
@@ -1331,27 +1284,24 @@ static int zread_route_add(struct zserv *client, u_short length,
client->v6_route_upd8_cnt++;
break;
}
-
- return 0;
}
-static int zread_route_del(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+static void zread_route_del(ZAPI_HANDLER_ARGS)
{
struct stream *s;
struct zapi_route api;
afi_t afi;
struct prefix_ipv6 *src_p = NULL;
- s = client->ibuf;
+ s = msg;
if (zapi_route_decode(s, &api) < 0)
- return -1;
+ return;
afi = family2afi(api.prefix.family);
if (afi != AFI_IP6 && CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
zlog_warn("%s: Received a src prefix while afi is not v6",
__PRETTY_FUNCTION__);
- return -1;
+ return;
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
src_p = &api.src_prefix;
@@ -1369,8 +1319,6 @@ static int zread_route_del(struct zserv *client, u_short length,
client->v6_route_del_cnt++;
break;
}
-
- return 0;
}
/* This function support multiple nexthop. */
@@ -1378,8 +1326,7 @@ static int zread_route_del(struct zserv *client, u_short length,
* Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and
* add kernel route.
*/
-static int zread_ipv4_add(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+static void zread_ipv4_add(ZAPI_HANDLER_ARGS)
{
int i;
struct route_entry *re;
@@ -1398,7 +1345,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
enum blackhole_type bh_type = BLACKHOLE_NULL;
/* Get input stream. */
- s = client->ibuf;
+ s = msg;
/* Allocate new re. */
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
@@ -1409,7 +1356,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
zlog_warn("%s: Specified route type %d is not a legal value\n",
__PRETTY_FUNCTION__, re->type);
XFREE(MTYPE_RE, re);
- return -1;
+ return;
}
STREAM_GETW(s, re->instance);
STREAM_GETL(s, re->flags);
@@ -1426,7 +1373,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
"%s: Specified prefix length %d is greater than what v4 can be",
__PRETTY_FUNCTION__, p.prefixlen);
XFREE(MTYPE_RE, re);
- return -1;
+ return;
}
STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen));
@@ -1478,7 +1425,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
__PRETTY_FUNCTION__);
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
- return -1;
+ return;
break;
case NEXTHOP_TYPE_BLACKHOLE:
route_entry_nexthop_blackhole_add(re, bh_type);
@@ -1489,7 +1436,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
__PRETTY_FUNCTION__, nexthop_type);
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
- return -1;
+ return;
}
}
}
@@ -1524,24 +1471,22 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
else if (ret < 0)
client->v4_route_upd8_cnt++;
- return 0;
+ return;
stream_failure:
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
- return -1;
}
/* Zebra server IPv4 prefix delete function. */
-static int zread_ipv4_delete(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+static void zread_ipv4_delete(ZAPI_HANDLER_ARGS)
{
struct stream *s;
struct zapi_ipv4 api;
struct prefix p;
u_int32_t table_id;
- s = client->ibuf;
+ s = msg;
/* Type, flags, message. */
STREAM_GETC(s, api.type);
@@ -1557,7 +1502,7 @@ static int zread_ipv4_delete(struct zserv *client, u_short length,
if (p.prefixlen > IPV4_MAX_BITLEN) {
zlog_warn("%s: Passed in prefixlen %d is impossible",
__PRETTY_FUNCTION__, p.prefixlen);
- return -1;
+ return;
}
STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen));
@@ -1568,28 +1513,25 @@ static int zread_ipv4_delete(struct zserv *client, u_short length,
client->v4_route_del_cnt++;
stream_failure:
- return 0;
+ return;
}
/* MRIB Nexthop lookup for IPv4. */
-static int zread_ipv4_nexthop_lookup_mrib(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+static void zread_ipv4_nexthop_lookup_mrib(ZAPI_HANDLER_ARGS)
{
struct in_addr addr;
struct route_entry *re;
- STREAM_GET(&addr.s_addr, client->ibuf, IPV4_MAX_BYTELEN);
+ STREAM_GET(&addr.s_addr, msg, IPV4_MAX_BYTELEN);
re = rib_match_ipv4_multicast(zvrf_id(zvrf), addr, NULL);
- return zsend_ipv4_nexthop_lookup_mrib(client, addr, re, zvrf);
+ zsend_ipv4_nexthop_lookup_mrib(client, addr, re, zvrf);
stream_failure:
- return -1;
+ return;
}
/* Zebra server IPv6 prefix add function. */
-static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
- u_short length,
- struct zebra_vrf *zvrf)
+static void zread_ipv4_route_ipv6_nexthop_add(ZAPI_HANDLER_ARGS)
{
unsigned int i;
struct stream *s;
@@ -1610,7 +1552,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
enum blackhole_type bh_type = BLACKHOLE_NULL;
/* Get input stream. */
- s = client->ibuf;
+ s = msg;
memset(&nhop_addr, 0, sizeof(struct in6_addr));
@@ -1623,7 +1565,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
zlog_warn("%s: Specified route type: %d is not a legal value\n",
__PRETTY_FUNCTION__, re->type);
XFREE(MTYPE_RE, re);
- return -1;
+ return;
}
STREAM_GETW(s, re->instance);
STREAM_GETL(s, re->flags);
@@ -1640,7 +1582,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
"%s: Prefix Length %d is greater than what a v4 address can use",
__PRETTY_FUNCTION__, p.prefixlen);
XFREE(MTYPE_RE, re);
- return -1;
+ return;
}
STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen));
@@ -1695,7 +1637,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
__PRETTY_FUNCTION__);
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
- return -1;
+ return;
}
}
@@ -1753,16 +1695,14 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
else if (ret < 0)
client->v4_route_upd8_cnt++;
- return 0;
+ return;
stream_failure:
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
- return -1;
}
-static int zread_ipv6_add(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+static void zread_ipv6_add(ZAPI_HANDLER_ARGS)
{
unsigned int i;
struct stream *s;
@@ -1785,7 +1725,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
enum blackhole_type bh_type = BLACKHOLE_NULL;
/* Get input stream. */
- s = client->ibuf;
+ s = msg;
memset(&nhop_addr, 0, sizeof(struct in6_addr));
@@ -1798,7 +1738,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
zlog_warn("%s: Specified route type: %d is not a legal value\n",
__PRETTY_FUNCTION__, re->type);
XFREE(MTYPE_RE, re);
- return -1;
+ return;
}
STREAM_GETW(s, re->instance);
STREAM_GETL(s, re->flags);
@@ -1815,7 +1755,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
"%s: Specified prefix length %d is to large for v6 prefix",
__PRETTY_FUNCTION__, p.prefixlen);
XFREE(MTYPE_RE, re);
- return -1;
+ return;
}
STREAM_GET(&p.u.prefix6, s, PSIZE(p.prefixlen));
@@ -1828,7 +1768,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
"%s: Specified src prefix length %d is to large for v6 prefix",
__PRETTY_FUNCTION__, src_p.prefixlen);
XFREE(MTYPE_RE, re);
- return -1;
+ return;
}
STREAM_GET(&src_p.prefix, s, PSIZE(src_p.prefixlen));
src_pp = &src_p;
@@ -1891,7 +1831,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
__PRETTY_FUNCTION__);
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
- return -1;
+ return;
}
}
@@ -1947,25 +1887,22 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
else if (ret < 0)
client->v6_route_upd8_cnt++;
- return 0;
+ return;
stream_failure:
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
-
- return -1;
}
/* Zebra server IPv6 prefix delete function. */
-static int zread_ipv6_delete(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+static void zread_ipv6_delete(ZAPI_HANDLER_ARGS)
{
struct stream *s;
struct zapi_ipv6 api;
struct prefix p;
struct prefix_ipv6 src_p, *src_pp;
- s = client->ibuf;
+ s = msg;
/* Type, flags, message. */
STREAM_GETC(s, api.type);
@@ -1996,12 +1933,11 @@ static int zread_ipv6_delete(struct zserv *client, u_short length,
client->v6_route_del_cnt++;
stream_failure:
- return 0;
+ return;
}
/* Register zebra server router-id information. Send current router-id */
-static int zread_router_id_add(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+static void zread_router_id_add(ZAPI_HANDLER_ARGS)
{
struct prefix p;
@@ -2010,28 +1946,26 @@ static int zread_router_id_add(struct zserv *client, u_short length,
router_id_get(&p, zvrf_id(zvrf));
- return zsend_router_id_update(client, &p, zvrf_id(zvrf));
+ zsend_router_id_update(client, &p, zvrf_id(zvrf));
}
/* Unregister zebra server router-id information. */
-static int zread_router_id_delete(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+static void zread_router_id_delete(ZAPI_HANDLER_ARGS)
{
vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf));
- return 0;
}
/* Tie up route-type and client->sock */
-static void zread_hello(struct zserv *client)
+static void zread_hello(ZAPI_HANDLER_ARGS)
{
/* type of protocol (lib/zebra.h) */
u_char proto;
u_short instance;
u_char notify;
- STREAM_GETC(client->ibuf, proto);
- STREAM_GETW(client->ibuf, instance);
- STREAM_GETC(client->ibuf, notify);
+ STREAM_GETC(msg, proto);
+ STREAM_GETW(msg, instance);
+ STREAM_GETC(msg, notify);
if (notify)
client->notify_owner = true;
@@ -2052,8 +1986,7 @@ stream_failure:
}
/* Unregister all information in a VRF. */
-static int zread_vrf_unregister(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+static void zread_vrf_unregister(ZAPI_HANDLER_ARGS)
{
int i;
afi_t afi;
@@ -2064,12 +1997,9 @@ static int zread_vrf_unregister(struct zserv *client, u_short length,
vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf));
vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf));
vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf));
-
- return 0;
}
-static void zread_mpls_labels(int command, struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+static void zread_mpls_labels(ZAPI_HANDLER_ARGS)
{
struct stream *s;
enum lsp_types_t type;
@@ -2081,7 +2011,7 @@ static void zread_mpls_labels(int command, struct zserv *client, u_short length,
u_int8_t distance;
/* Get input stream. */
- s = client->ibuf;
+ s = msg;
/* Get data. */
STREAM_GETC(s, type);
@@ -2139,12 +2069,12 @@ static void zread_mpls_labels(int command, struct zserv *client, u_short length,
if (!mpls_enabled)
return;
- if (command == ZEBRA_MPLS_LABELS_ADD) {
+ if (hdr->command == ZEBRA_MPLS_LABELS_ADD) {
mpls_lsp_install(zvrf, type, in_label, out_label, gtype, &gate,
ifindex);
mpls_ftn_update(1, zvrf, type, &prefix, gtype, &gate, ifindex,
distance, out_label);
- } else if (command == ZEBRA_MPLS_LABELS_DELETE) {
+ } else if (hdr->command == ZEBRA_MPLS_LABELS_DELETE) {
mpls_lsp_uninstall(zvrf, type, in_label, gtype, &gate, ifindex);
mpls_ftn_update(0, zvrf, type, &prefix, gtype, &gate, ifindex,
distance, out_label);
@@ -2152,27 +2082,9 @@ static void zread_mpls_labels(int command, struct zserv *client, u_short length,
stream_failure:
return;
}
-/* Send response to a label manager connect request to client */
-static int zsend_label_manager_connect_response(struct zserv *client,
- vrf_id_t vrf_id, u_short result)
-{
- struct stream *s;
-
- s = client->obuf;
- stream_reset(s);
-
- zclient_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id);
-
- /* result */
- stream_putc(s, result);
- /* Write packet size. */
- stream_putw_at(s, 0, stream_get_endp(s));
-
- return writen(client->sock, s->data, stream_get_endp(s));
-}
-
-static void zread_label_manager_connect(struct zserv *client, vrf_id_t vrf_id)
+static void zread_label_manager_connect(struct zserv *client,
+ struct stream *msg, vrf_id_t vrf_id)
{
struct stream *s;
/* type of protocol (lib/zebra.h) */
@@ -2180,7 +2092,7 @@ static void zread_label_manager_connect(struct zserv *client, vrf_id_t vrf_id)
u_short instance;
/* Get input stream. */
- s = client->ibuf;
+ s = msg;
/* Get data. */
STREAM_GETC(s, proto);
@@ -2213,33 +2125,9 @@ static void zread_label_manager_connect(struct zserv *client, vrf_id_t vrf_id)
stream_failure:
return;
}
-/* Send response to a get label chunk request to client */
-static int zsend_assign_label_chunk_response(struct zserv *client,
- vrf_id_t vrf_id,
- struct label_manager_chunk *lmc)
-{
- struct stream *s;
-
- s = client->obuf;
- stream_reset(s);
-
- zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id);
- if (lmc) {
- /* keep */
- stream_putc(s, lmc->keep);
- /* start and end labels */
- stream_putl(s, lmc->start);
- stream_putl(s, lmc->end);
- }
-
- /* Write packet size. */
- stream_putw_at(s, 0, stream_get_endp(s));
-
- return writen(client->sock, s->data, stream_get_endp(s));
-}
-
-static void zread_get_label_chunk(struct zserv *client, vrf_id_t vrf_id)
+static void zread_get_label_chunk(struct zserv *client, struct stream *msg,
+ vrf_id_t vrf_id)
{
struct stream *s;
u_char keep;
@@ -2247,7 +2135,7 @@ static void zread_get_label_chunk(struct zserv *client, vrf_id_t vrf_id)
struct label_manager_chunk *lmc;
/* Get input stream. */
- s = client->ibuf;
+ s = msg;
/* Get data. */
STREAM_GETC(s, keep);
@@ -2267,13 +2155,13 @@ stream_failure:
return;
}
-static void zread_release_label_chunk(struct zserv *client)
+static void zread_release_label_chunk(struct zserv *client, struct stream *msg)
{
struct stream *s;
uint32_t start, end;
/* Get input stream. */
- s = client->ibuf;
+ s = msg;
/* Get data. */
STREAM_GETL(s, start);
@@ -2284,20 +2172,20 @@ static void zread_release_label_chunk(struct zserv *client)
stream_failure:
return;
}
-static void zread_label_manager_request(int cmd, struct zserv *client,
- struct zebra_vrf *zvrf)
+static void zread_label_manager_request(ZAPI_HANDLER_ARGS)
{
/* to avoid sending other messages like ZERBA_INTERFACE_UP */
- if (cmd == ZEBRA_LABEL_MANAGER_CONNECT)
+ if (hdr->command == ZEBRA_LABEL_MANAGER_CONNECT)
client->is_synchronous = 1;
/* external label manager */
if (lm_is_external)
- zread_relay_label_manager_request(cmd, client, zvrf_id(zvrf));
+ zread_relay_label_manager_request(hdr->command, client,
+ zvrf_id(zvrf));
/* this is a label manager */
else {
- if (cmd == ZEBRA_LABEL_MANAGER_CONNECT)
- zread_label_manager_connect(client, zvrf_id(zvrf));
+ if (hdr->command == ZEBRA_LABEL_MANAGER_CONNECT)
+ zread_label_manager_connect(client, msg, zvrf_id(zvrf));
else {
/* Sanity: don't allow 'unidentified' requests */
if (!client->proto) {
@@ -2305,16 +2193,16 @@ static void zread_label_manager_request(int cmd, struct zserv *client,
"Got label request from an unidentified client");
return;
}
- if (cmd == ZEBRA_GET_LABEL_CHUNK)
- zread_get_label_chunk(client, zvrf_id(zvrf));
- else if (cmd == ZEBRA_RELEASE_LABEL_CHUNK)
- zread_release_label_chunk(client);
+ if (hdr->command == ZEBRA_GET_LABEL_CHUNK)
+ zread_get_label_chunk(client, msg,
+ zvrf_id(zvrf));
+ else if (hdr->command == ZEBRA_RELEASE_LABEL_CHUNK)
+ zread_release_label_chunk(client, msg);
}
}
}
-static int zread_pseudowire(int command, struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+static void zread_pseudowire(ZAPI_HANDLER_ARGS)
{
struct stream *s;
char ifname[IF_NAMESIZE];
@@ -2330,7 +2218,7 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length,
struct zebra_pw *pw;
/* Get input stream. */
- s = client->ibuf;
+ s = msg;
/* Get data. */
STREAM_GET(ifname, s, IF_NAMESIZE);
@@ -2345,7 +2233,7 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length,
STREAM_GET(&nexthop.ipv6, s, 16);
break;
default:
- return -1;
+ return;
}
STREAM_GETL(s, local_label);
STREAM_GETL(s, remote_label);
@@ -2354,13 +2242,13 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length,
protocol = client->proto;
pw = zebra_pw_find(zvrf, ifname);
- switch (command) {
+ switch (hdr->command) {
case ZEBRA_PW_ADD:
if (pw) {
zlog_warn("%s: pseudowire %s already exists [%s]",
__func__, ifname,
- zserv_command_string(command));
- return -1;
+ zserv_command_string(hdr->command));
+ return;
}
zebra_pw_add(zvrf, ifname, protocol, client);
@@ -2368,8 +2256,8 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length,
case ZEBRA_PW_DELETE:
if (!pw) {
zlog_warn("%s: pseudowire %s not found [%s]", __func__,
- ifname, zserv_command_string(command));
- return -1;
+ ifname, zserv_command_string(hdr->command));
+ return;
}
zebra_pw_del(zvrf, pw);
@@ -2378,11 +2266,11 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length,
case ZEBRA_PW_UNSET:
if (!pw) {
zlog_warn("%s: pseudowire %s not found [%s]", __func__,
- ifname, zserv_command_string(command));
- return -1;
+ ifname, zserv_command_string(hdr->command));
+ return;
}
- switch (command) {
+ switch (hdr->command) {
case ZEBRA_PW_SET:
pw->enabled = 1;
break;
@@ -2397,7 +2285,7 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length,
}
stream_failure:
- return 0;
+ return;
}
/* Cleanup registered nexthops (across VRFs) upon client disconnect. */
@@ -2427,116 +2315,11 @@ static void zebra_client_close_cleanup_rnh(struct zserv *client)
}
}
-/* free zebra client information. */
-static void zebra_client_free(struct zserv *client)
-{
- /* Send client de-registration to BFD */
- zebra_ptm_bfd_client_deregister(client->proto);
-
- /* Cleanup any registered nexthops - across all VRFs. */
- zebra_client_close_cleanup_rnh(client);
-
- /* Release Label Manager chunks */
- release_daemon_chunks(client->proto, client->instance);
-
- /* Cleanup any FECs registered by this client. */
- zebra_mpls_cleanup_fecs_for_client(vrf_info_lookup(VRF_DEFAULT),
- client);
-
- /* Remove pseudowires associated with this client */
- zebra_pw_client_close(client);
-
- /* Close file descriptor. */
- if (client->sock) {
- unsigned long nroutes;
-
- close(client->sock);
- nroutes = rib_score_proto(client->proto, client->instance);
- zlog_notice(
- "client %d disconnected. %lu %s routes removed from the rib",
- client->sock, nroutes,
- zebra_route_string(client->proto));
- client->sock = -1;
- }
-
- /* Free stream buffers. */
- if (client->ibuf)
- stream_free(client->ibuf);
- if (client->obuf)
- stream_free(client->obuf);
- if (client->wb)
- buffer_free(client->wb);
-
- /* Release threads. */
- if (client->t_read)
- thread_cancel(client->t_read);
- if (client->t_write)
- thread_cancel(client->t_write);
- if (client->t_suicide)
- thread_cancel(client->t_suicide);
-
- /* Free bitmaps. */
- for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++)
- for (int i = 0; i < ZEBRA_ROUTE_MAX; i++)
- vrf_bitmap_free(client->redist[afi][i]);
-
- vrf_bitmap_free(client->redist_default);
- vrf_bitmap_free(client->ifinfo);
- vrf_bitmap_free(client->ridinfo);
-
- XFREE(MTYPE_TMP, client);
-}
-
-static void zebra_client_close(struct zserv *client)
-{
- listnode_delete(zebrad.client_list, client);
- zebra_client_free(client);
-}
-
-/* Make new client. */
-static void zebra_client_create(int sock)
-{
- struct zserv *client;
- int i;
- afi_t afi;
-
- client = XCALLOC(MTYPE_TMP, sizeof(struct zserv));
-
- /* Make client input/output buffer. */
- client->sock = sock;
- client->ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
- client->obuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
- client->wb = buffer_new(0);
-
- /* Set table number. */
- client->rtm_table = zebrad.rtm_table_default;
-
- client->connect_time = monotime(NULL);
- /* Initialize flags */
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- client->redist[afi][i] = vrf_bitmap_init();
- client->redist_default = vrf_bitmap_init();
- client->ifinfo = vrf_bitmap_init();
- client->ridinfo = vrf_bitmap_init();
-
- /* by default, it's not a synchronous client */
- client->is_synchronous = 0;
-
- /* Add this client to linked list. */
- listnode_add(zebrad.client_list, client);
-
- /* Make new read thread. */
- zebra_event(ZEBRA_READ, sock, client);
-
- zebra_vrf_update_all(client);
-}
-
-static int zread_interface_set_master(struct zserv *client, u_short length)
+static void zread_interface_set_master(ZAPI_HANDLER_ARGS)
{
struct interface *master;
struct interface *slave;
- struct stream *s = client->ibuf;
+ struct stream *s = msg;
int ifindex;
vrf_id_t vrf_id;
@@ -2549,16 +2332,16 @@ static int zread_interface_set_master(struct zserv *client, u_short length)
slave = if_lookup_by_index(ifindex, vrf_id);
if (!master || !slave)
- return 0;
+ return;
kernel_interface_set_master(master, slave);
stream_failure:
- return 1;
+ return;
}
-static void zread_vrf_label(struct zserv *client, struct zebra_vrf *zvrf)
+static void zread_vrf_label(ZAPI_HANDLER_ARGS)
{
struct interface *ifp;
mpls_label_t nlabel;
@@ -2567,7 +2350,7 @@ static void zread_vrf_label(struct zserv *client, struct zebra_vrf *zvrf)
struct zebra_vrf *def_zvrf;
enum lsp_types_t ltype;
- s = client->ibuf;
+ s = msg;
STREAM_GETL(s, nlabel);
STREAM_GETC(s, afi);
if (nlabel == zvrf->label[afi]) {
@@ -2626,15 +2409,14 @@ stream_failure:
return;
}
-static inline void zread_rule(uint16_t command, struct zserv *client,
- uint16_t length, struct zebra_vrf *zvrf)
+static inline void zread_rule(ZAPI_HANDLER_ARGS)
{
struct zebra_pbr_rule zpr;
struct stream *s;
uint32_t total, i;
ifindex_t ifindex;
- s = client->ibuf;
+ s = msg;
STREAM_GETL(s, total);
for (i = 0; i < total; i++) {
@@ -2675,7 +2457,7 @@ static inline void zread_rule(uint16_t command, struct zserv *client,
if (zpr.filter.dst_port)
zpr.filter.filter_bm |= PBR_FILTER_DST_PORT;
- if (command == ZEBRA_RULE_ADD)
+ if (hdr->command == ZEBRA_RULE_ADD)
zebra_pbr_add_rule(zvrf->zns, &zpr);
else
zebra_pbr_del_rule(zvrf->zns, &zpr);
@@ -2685,158 +2467,314 @@ stream_failure:
return;
}
-static inline void zserv_handle_commands(struct zserv *client, uint16_t command,
- uint16_t length,
- struct zebra_vrf *zvrf)
-{
- switch (command) {
- case ZEBRA_ROUTER_ID_ADD:
- zread_router_id_add(client, length, zvrf);
- break;
- case ZEBRA_ROUTER_ID_DELETE:
- zread_router_id_delete(client, length, zvrf);
- break;
- case ZEBRA_INTERFACE_ADD:
- zread_interface_add(client, length, zvrf);
- break;
- case ZEBRA_INTERFACE_DELETE:
- zread_interface_delete(client, length, zvrf);
- break;
- case ZEBRA_ROUTE_ADD:
- zread_route_add(client, length, zvrf);
- break;
- case ZEBRA_ROUTE_DELETE:
- zread_route_del(client, length, zvrf);
- break;
- case ZEBRA_IPV4_ROUTE_ADD:
- zread_ipv4_add(client, length, zvrf);
- break;
- case ZEBRA_IPV4_ROUTE_DELETE:
- zread_ipv4_delete(client, length, zvrf);
- break;
- case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD:
- zread_ipv4_route_ipv6_nexthop_add(client, length, zvrf);
- break;
- case ZEBRA_IPV6_ROUTE_ADD:
- zread_ipv6_add(client, length, zvrf);
- break;
- case ZEBRA_IPV6_ROUTE_DELETE:
- zread_ipv6_delete(client, length, zvrf);
- break;
- case ZEBRA_REDISTRIBUTE_ADD:
- zebra_redistribute_add(command, client, length, zvrf);
- break;
- case ZEBRA_REDISTRIBUTE_DELETE:
- zebra_redistribute_delete(command, client, length, zvrf);
- break;
- case ZEBRA_REDISTRIBUTE_DEFAULT_ADD:
- zebra_redistribute_default_add(command, client, length, zvrf);
- break;
- case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE:
- zebra_redistribute_default_delete(command, client, length,
- zvrf);
- break;
- case ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB:
- zread_ipv4_nexthop_lookup_mrib(client, length, zvrf);
- break;
- case ZEBRA_HELLO:
- zread_hello(client);
- break;
- case ZEBRA_NEXTHOP_REGISTER:
- zserv_rnh_register(client, length, RNH_NEXTHOP_TYPE, zvrf);
- break;
- case ZEBRA_NEXTHOP_UNREGISTER:
- zserv_rnh_unregister(client, length, RNH_NEXTHOP_TYPE, zvrf);
- break;
- case ZEBRA_IMPORT_ROUTE_REGISTER:
- zserv_rnh_register(client, length, RNH_IMPORT_CHECK_TYPE, zvrf);
- break;
- case ZEBRA_IMPORT_ROUTE_UNREGISTER:
- zserv_rnh_unregister(client, length, RNH_IMPORT_CHECK_TYPE,
- zvrf);
- break;
- case ZEBRA_BFD_DEST_UPDATE:
- case ZEBRA_BFD_DEST_REGISTER:
- zebra_ptm_bfd_dst_register(client, length, command, zvrf);
- break;
- case ZEBRA_BFD_DEST_DEREGISTER:
- zebra_ptm_bfd_dst_deregister(client, length, zvrf);
- break;
- case ZEBRA_VRF_UNREGISTER:
- zread_vrf_unregister(client, length, zvrf);
- break;
- case ZEBRA_VRF_LABEL:
- zread_vrf_label(client, zvrf);
- break;
- case ZEBRA_BFD_CLIENT_REGISTER:
- zebra_ptm_bfd_client_register(client, length);
- break;
- case ZEBRA_INTERFACE_ENABLE_RADV:
+void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
+ [ZEBRA_ROUTER_ID_ADD] = zread_router_id_add,
+ [ZEBRA_ROUTER_ID_DELETE] = zread_router_id_delete,
+ [ZEBRA_INTERFACE_ADD] = zread_interface_add,
+ [ZEBRA_INTERFACE_DELETE] = zread_interface_delete,
+ [ZEBRA_ROUTE_ADD] = zread_route_add,
+ [ZEBRA_ROUTE_DELETE] = zread_route_del,
+ [ZEBRA_IPV4_ROUTE_ADD] = zread_ipv4_add,
+ [ZEBRA_IPV4_ROUTE_DELETE] = zread_ipv4_delete,
+ [ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD] = zread_ipv4_route_ipv6_nexthop_add,
+ [ZEBRA_IPV6_ROUTE_ADD] = zread_ipv6_add,
+ [ZEBRA_IPV6_ROUTE_DELETE] = zread_ipv6_delete,
+ [ZEBRA_REDISTRIBUTE_ADD] = zebra_redistribute_add,
+ [ZEBRA_REDISTRIBUTE_DELETE] = zebra_redistribute_delete,
+ [ZEBRA_REDISTRIBUTE_DEFAULT_ADD] = zebra_redistribute_default_add,
+ [ZEBRA_REDISTRIBUTE_DEFAULT_DELETE] = zebra_redistribute_default_delete,
+ [ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB] = zread_ipv4_nexthop_lookup_mrib,
+ [ZEBRA_HELLO] = zread_hello,
+ [ZEBRA_NEXTHOP_REGISTER] = zread_rnh_register,
+ [ZEBRA_NEXTHOP_UNREGISTER] = zread_rnh_unregister,
+ [ZEBRA_IMPORT_ROUTE_REGISTER] = zread_rnh_register,
+ [ZEBRA_IMPORT_ROUTE_UNREGISTER] = zread_rnh_unregister,
+ [ZEBRA_BFD_DEST_UPDATE] = zebra_ptm_bfd_dst_register,
+ [ZEBRA_BFD_DEST_REGISTER] = zebra_ptm_bfd_dst_register,
+ [ZEBRA_BFD_DEST_DEREGISTER] = zebra_ptm_bfd_dst_deregister,
+ [ZEBRA_VRF_UNREGISTER] = zread_vrf_unregister,
+ [ZEBRA_VRF_LABEL] = zread_vrf_label,
+ [ZEBRA_BFD_CLIENT_REGISTER] = zebra_ptm_bfd_client_register,
#if defined(HAVE_RTADV)
- zebra_interface_radv_set(client, length, zvrf, 1);
-#endif
- break;
- case ZEBRA_INTERFACE_DISABLE_RADV:
-#if defined(HAVE_RTADV)
- zebra_interface_radv_set(client, length, zvrf, 0);
+ [ZEBRA_INTERFACE_ENABLE_RADV] = zebra_interface_radv_enable,
+ [ZEBRA_INTERFACE_DISABLE_RADV] = zebra_interface_radv_disable,
+#else
+ [ZEBRA_INTERFACE_ENABLE_RADV] = NULL,
+ [ZEBRA_INTERFACE_DISABLE_RADV] = NULL,
#endif
+ [ZEBRA_MPLS_LABELS_ADD] = zread_mpls_labels,
+ [ZEBRA_MPLS_LABELS_DELETE] = zread_mpls_labels,
+ [ZEBRA_IPMR_ROUTE_STATS] = zebra_ipmr_route_stats,
+ [ZEBRA_LABEL_MANAGER_CONNECT] = zread_label_manager_request,
+ [ZEBRA_GET_LABEL_CHUNK] = zread_label_manager_request,
+ [ZEBRA_RELEASE_LABEL_CHUNK] = zread_label_manager_request,
+ [ZEBRA_FEC_REGISTER] = zread_fec_register,
+ [ZEBRA_FEC_UNREGISTER] = zread_fec_unregister,
+ [ZEBRA_ADVERTISE_DEFAULT_GW] = zebra_vxlan_advertise_gw_macip,
+ [ZEBRA_ADVERTISE_SUBNET] = zebra_vxlan_advertise_subnet,
+ [ZEBRA_ADVERTISE_ALL_VNI] = zebra_vxlan_advertise_all_vni,
+ [ZEBRA_REMOTE_VTEP_ADD] = zebra_vxlan_remote_vtep_add,
+ [ZEBRA_REMOTE_VTEP_DEL] = zebra_vxlan_remote_vtep_del,
+ [ZEBRA_REMOTE_MACIP_ADD] = zebra_vxlan_remote_macip_add,
+ [ZEBRA_REMOTE_MACIP_DEL] = zebra_vxlan_remote_macip_del,
+ [ZEBRA_INTERFACE_SET_MASTER] = zread_interface_set_master,
+ [ZEBRA_PW_ADD] = zread_pseudowire,
+ [ZEBRA_PW_DELETE] = zread_pseudowire,
+ [ZEBRA_PW_SET] = zread_pseudowire,
+ [ZEBRA_PW_UNSET] = zread_pseudowire,
+ [ZEBRA_RULE_ADD] = zread_rule,
+ [ZEBRA_RULE_DELETE] = zread_rule,
+};
+
+static inline void zserv_handle_commands(struct zserv *client,
+ struct zmsghdr *hdr,
+ struct stream *msg,
+ struct zebra_vrf *zvrf)
+{
+ if (hdr->command > sizeof(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);
+
+ stream_free(msg);
+}
+
+/* Lifecycle ---------------------------------------------------------------- */
+
+/* free zebra client information. */
+static void zebra_client_free(struct zserv *client)
+{
+ /* Send client de-registration to BFD */
+ zebra_ptm_bfd_client_deregister(client->proto);
+
+ /* Cleanup any registered nexthops - across all VRFs. */
+ zebra_client_close_cleanup_rnh(client);
+
+ /* Release Label Manager chunks */
+ release_daemon_chunks(client->proto, client->instance);
+
+ /* Cleanup any FECs registered by this client. */
+ zebra_mpls_cleanup_fecs_for_client(vrf_info_lookup(VRF_DEFAULT),
+ client);
+
+ /* Remove pseudowires associated with this client */
+ zebra_pw_client_close(client);
+
+ /* Close file descriptor. */
+ if (client->sock) {
+ unsigned long nroutes;
+
+ close(client->sock);
+ nroutes = rib_score_proto(client->proto, client->instance);
+ zlog_notice(
+ "client %d disconnected. %lu %s routes removed from the rib",
+ client->sock, nroutes,
+ zebra_route_string(client->proto));
+ client->sock = -1;
+ }
+
+ /* Free stream buffers. */
+ if (client->ibuf_work)
+ stream_free(client->ibuf_work);
+ if (client->obuf_work)
+ stream_free(client->obuf_work);
+ if (client->ibuf_fifo)
+ stream_fifo_free(client->ibuf_fifo);
+ if (client->obuf_fifo)
+ stream_fifo_free(client->obuf_fifo);
+ if (client->wb)
+ buffer_free(client->wb);
+
+ /* Release threads. */
+ if (client->t_read)
+ thread_cancel(client->t_read);
+ if (client->t_write)
+ thread_cancel(client->t_write);
+ if (client->t_suicide)
+ thread_cancel(client->t_suicide);
+
+ /* Free bitmaps. */
+ for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (int i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ vrf_bitmap_free(client->redist[afi][i]);
+
+ vrf_bitmap_free(client->redist_default);
+ vrf_bitmap_free(client->ifinfo);
+ vrf_bitmap_free(client->ridinfo);
+
+ XFREE(MTYPE_TMP, client);
+}
+
+/*
+ * Called from client thread to terminate itself.
+ */
+static void zebra_client_close(struct zserv *client)
+{
+ listnode_delete(zebrad.client_list, client);
+ zebra_client_free(client);
+}
+
+/* Make new client. */
+static void zebra_client_create(int sock)
+{
+ struct zserv *client;
+ int i;
+ afi_t afi;
+
+ client = XCALLOC(MTYPE_TMP, sizeof(struct zserv));
+
+ /* Make client input/output buffer. */
+ client->sock = sock;
+ client->ibuf_fifo = stream_fifo_new();
+ client->obuf_fifo = stream_fifo_new();
+ client->ibuf_work = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ client->obuf_work = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ client->wb = buffer_new(0);
+
+ /* Set table number. */
+ client->rtm_table = zebrad.rtm_table_default;
+
+ client->connect_time = monotime(NULL);
+ /* Initialize flags */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ client->redist[afi][i] = vrf_bitmap_init();
+ client->redist_default = vrf_bitmap_init();
+ client->ifinfo = vrf_bitmap_init();
+ client->ridinfo = vrf_bitmap_init();
+
+ /* by default, it's not a synchronous client */
+ client->is_synchronous = 0;
+
+ /* Add this client to linked list. */
+ listnode_add(zebrad.client_list, client);
+
+ zebra_vrf_update_all(client);
+
+ /* start read loop */
+ zebra_event(client, ZEBRA_READ);
+}
+
+static int zserv_delayed_close(struct thread *thread)
+{
+ struct zserv *client = THREAD_ARG(thread);
+
+ client->t_suicide = NULL;
+ zebra_client_close(client);
+ return 0;
+}
+
+/*
+ * Log zapi message to zlog.
+ *
+ * errmsg (optional)
+ * Debugging message
+ *
+ * msg
+ * The message
+ *
+ * hdr (optional)
+ * The message header
+ */
+static void zserv_log_message(const char *errmsg, struct stream *msg,
+ struct zmsghdr *hdr)
+{
+ zlog_debug("Rx'd ZAPI message");
+ if (errmsg)
+ zlog_debug("%s", errmsg);
+ if (hdr) {
+ zlog_debug(" Length: %d", hdr->length);
+ zlog_debug("Command: %s", zserv_command_string(hdr->command));
+ zlog_debug(" VRF: %u", hdr->vrf_id);
+ }
+ zlog_hexdump(msg->data, STREAM_READABLE(msg));
+}
+
+static int zserv_flush_data(struct thread *thread)
+{
+ struct zserv *client = THREAD_ARG(thread);
+
+ client->t_write = NULL;
+ if (client->t_suicide) {
+ zebra_client_close(client);
+ return -1;
+ }
+ switch (buffer_flush_available(client->wb, client->sock)) {
+ case BUFFER_ERROR:
+ zlog_warn(
+ "%s: buffer_flush_available failed on zserv client fd %d, closing",
+ __func__, client->sock);
+ zebra_client_close(client);
+ client = NULL;
break;
- case ZEBRA_MPLS_LABELS_ADD:
- case ZEBRA_MPLS_LABELS_DELETE:
- zread_mpls_labels(command, client, length, zvrf);
- break;
- case ZEBRA_IPMR_ROUTE_STATS:
- zebra_ipmr_route_stats(client, length, zvrf);
- break;
- case ZEBRA_LABEL_MANAGER_CONNECT:
- case ZEBRA_GET_LABEL_CHUNK:
- case ZEBRA_RELEASE_LABEL_CHUNK:
- zread_label_manager_request(command, client, zvrf);
- break;
- case ZEBRA_FEC_REGISTER:
- zserv_fec_register(client, length);
- break;
- case ZEBRA_FEC_UNREGISTER:
- zserv_fec_unregister(client, length);
- break;
- case ZEBRA_ADVERTISE_DEFAULT_GW:
- zebra_vxlan_advertise_gw_macip(client, length, zvrf);
- break;
- case ZEBRA_ADVERTISE_SUBNET:
- zebra_vxlan_advertise_subnet(client, length, zvrf);
- break;
- case ZEBRA_ADVERTISE_ALL_VNI:
- zebra_vxlan_advertise_all_vni(client, length, zvrf);
- break;
- case ZEBRA_REMOTE_VTEP_ADD:
- zebra_vxlan_remote_vtep_add(client, length, zvrf);
- break;
- case ZEBRA_REMOTE_VTEP_DEL:
- zebra_vxlan_remote_vtep_del(client, length, zvrf);
- break;
- case ZEBRA_REMOTE_MACIP_ADD:
- zebra_vxlan_remote_macip_add(client, length, zvrf);
- break;
- case ZEBRA_REMOTE_MACIP_DEL:
- zebra_vxlan_remote_macip_del(client, length, zvrf);
- break;
- case ZEBRA_INTERFACE_SET_MASTER:
- zread_interface_set_master(client, length);
+ case BUFFER_PENDING:
+ client->t_write = NULL;
+ thread_add_write(zebrad.master, zserv_flush_data, client,
+ client->sock, &client->t_write);
break;
- case ZEBRA_PW_ADD:
- case ZEBRA_PW_DELETE:
- case ZEBRA_PW_SET:
- case ZEBRA_PW_UNSET:
- zread_pseudowire(command, client, length, zvrf);
+ case BUFFER_EMPTY:
break;
- case ZEBRA_RULE_ADD:
- case ZEBRA_RULE_DELETE:
- zread_rule(command, client, length, zvrf);
+ }
+
+ if (client)
+ client->last_write_time = monotime(NULL);
+ return 0;
+}
+
+/*
+ * Write a single packet.
+ */
+static int zserv_write(struct thread *thread)
+{
+ struct zserv *client = THREAD_ARG(thread);
+ struct stream *msg;
+ int writerv;
+
+ if (client->t_suicide)
+ return -1;
+
+ if (client->is_synchronous)
+ return 0;
+
+ msg = stream_fifo_pop(client->obuf_fifo);
+ stream_set_getp(msg, 0);
+ client->last_write_cmd = stream_getw_from(msg, 6);
+
+ writerv = buffer_write(client->wb, client->sock, STREAM_DATA(msg),
+ stream_get_endp(msg));
+
+ stream_free(msg);
+
+ switch (writerv) {
+ case BUFFER_ERROR:
+ zlog_warn(
+ "%s: buffer_write failed to zserv client fd %d, closing",
+ __func__, client->sock);
+ /*
+ * Schedule a delayed close since many of the functions that
+ * call this one do not check the return code. They do not
+ * allow for the possibility that an I/O error may have caused
+ * the client to be deleted.
+ */
+ client->t_suicide = NULL;
+ thread_add_event(zebrad.master, zserv_delayed_close, client, 0,
+ &client->t_suicide);
+ return -1;
+ case BUFFER_EMPTY:
+ THREAD_OFF(client->t_write);
break;
- default:
- zlog_info("Zebra received unknown command %d", command);
+ case BUFFER_PENDING:
+ thread_add_write(zebrad.master, zserv_flush_data, client,
+ client->sock, &client->t_write);
break;
}
+
+ if (client->obuf_fifo->count)
+ zebra_event(client, ZEBRA_WRITE);
+
+ client->last_write_time = monotime(NULL);
+ return 0;
}
#if defined(HANDLE_ZAPI_FUZZING)
@@ -2859,26 +2797,61 @@ static void zserv_write_incoming(struct stream *orig, uint16_t command)
}
#endif
+static int zserv_process_messages(struct thread *thread)
+{
+ struct zserv *client = THREAD_ARG(thread);
+ struct zebra_vrf *zvrf;
+ struct zmsghdr hdr;
+ struct stream *msg;
+ bool hdrvalid;
+
+ do {
+ msg = stream_fifo_pop(client->ibuf_fifo);
+
+ /* break if out of messages */
+ if (!msg)
+ continue;
+
+ /* read & check header */
+ hdrvalid = zapi_parse_header(msg, &hdr);
+ if (!hdrvalid && IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) {
+ const char *emsg = "Message has corrupt header";
+ zserv_log_message(emsg, msg, NULL);
+ }
+ if (!hdrvalid)
+ continue;
+
+ /* lookup vrf */
+ zvrf = zebra_vrf_lookup_by_id(hdr.vrf_id);
+ if (!zvrf && IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) {
+ const char *emsg = "Message specifies unknown VRF";
+ zserv_log_message(emsg, msg, &hdr);
+ }
+ if (!zvrf)
+ continue;
+
+ /* process commands */
+ zserv_handle_commands(client, &hdr, msg, zvrf);
+
+ } while (msg);
+
+ return 0;
+}
+
/* Handler of zebra service request. */
-static int zebra_client_read(struct thread *thread)
+static int zserv_read(struct thread *thread)
{
int sock;
struct zserv *client;
size_t already;
- uint16_t length, command;
- uint8_t marker, version;
- vrf_id_t vrf_id;
- struct zebra_vrf *zvrf;
#if defined(HANDLE_ZAPI_FUZZING)
int packets = 1;
#else
int packets = zebrad.packets_to_process;
#endif
-
/* Get thread data. Reset reading thread because I'm running. */
sock = THREAD_FD(thread);
client = THREAD_ARG(thread);
- client->t_read = NULL;
if (client->t_suicide) {
zebra_client_close(client);
@@ -2886,88 +2859,89 @@ static int zebra_client_read(struct thread *thread)
}
while (packets) {
+ struct zmsghdr hdr;
+ ssize_t nb;
+ bool hdrvalid;
+ char errmsg[256];
+
+ already = stream_get_endp(client->ibuf_work);
+
/* Read length and command (if we don't have it already). */
- if ((already = stream_get_endp(client->ibuf))
- < ZEBRA_HEADER_SIZE) {
- ssize_t nbyte;
- if (((nbyte = stream_read_try(client->ibuf, sock,
- ZEBRA_HEADER_SIZE
- - already))
- == 0)
- || (nbyte == -1)) {
- if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug(
- "connection closed socket [%d]",
- sock);
- zebra_client_close(client);
- return -1;
- }
- if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) {
+ if (already < ZEBRA_HEADER_SIZE) {
+ nb = stream_read_try(client->ibuf_work, sock,
+ ZEBRA_HEADER_SIZE - already);
+ if ((nb == 0 || nb == -1) && IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("connection closed socket [%d]",
+ sock);
+ if ((nb == 0 || nb == -1))
+ goto zread_fail;
+ if (nb != (ssize_t)(ZEBRA_HEADER_SIZE - already)) {
/* Try again later. */
- zebra_event(ZEBRA_READ, sock, client);
- return 0;
+ break;
}
already = ZEBRA_HEADER_SIZE;
}
/* Reset to read from the beginning of the incoming packet. */
- stream_set_getp(client->ibuf, 0);
+ stream_set_getp(client->ibuf_work, 0);
/* Fetch header values */
- STREAM_GETW(client->ibuf, length);
- STREAM_GETC(client->ibuf, marker);
- STREAM_GETC(client->ibuf, version);
- STREAM_GETL(client->ibuf, vrf_id);
- STREAM_GETW(client->ibuf, command);
+ hdrvalid = zapi_parse_header(client->ibuf_work, &hdr);
- if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) {
- zlog_err(
- "%s: socket %d version mismatch, marker %d, version %d",
- __func__, sock, marker, version);
- zebra_client_close(client);
- return -1;
+ if (!hdrvalid) {
+ snprintf(errmsg, sizeof(errmsg),
+ "%s: Message has corrupt header", __func__);
+ zserv_log_message(errmsg, client->ibuf_work, NULL);
+ goto zread_fail;
}
- if (length < ZEBRA_HEADER_SIZE) {
- zlog_warn(
- "%s: socket %d message length %u is less than header size %d",
- __func__, sock, length, ZEBRA_HEADER_SIZE);
- zebra_client_close(client);
- return -1;
+
+ /* Validate header */
+ if (hdr.marker != ZEBRA_HEADER_MARKER
+ || hdr.version != ZSERV_VERSION) {
+ snprintf(
+ errmsg, sizeof(errmsg),
+ "Message has corrupt header\n%s: socket %d version mismatch, marker %d, version %d",
+ __func__, sock, hdr.marker, hdr.version);
+ zserv_log_message(errmsg, client->ibuf_work, &hdr);
+ goto zread_fail;
}
- if (length > STREAM_SIZE(client->ibuf)) {
- zlog_warn(
- "%s: socket %d message length %u exceeds buffer size %lu",
- __func__, sock, length,
- (u_long)STREAM_SIZE(client->ibuf));
- zebra_client_close(client);
- return -1;
+ if (hdr.length < ZEBRA_HEADER_SIZE) {
+ snprintf(
+ errmsg, sizeof(errmsg),
+ "Message has corrupt header\n%s: socket %d message length %u is less than header size %d",
+ __func__, sock, hdr.length, ZEBRA_HEADER_SIZE);
+ zserv_log_message(errmsg, client->ibuf_work, &hdr);
+ goto zread_fail;
+ }
+ if (hdr.length > STREAM_SIZE(client->ibuf_work)) {
+ snprintf(
+ errmsg, sizeof(errmsg),
+ "Message has corrupt header\n%s: socket %d message length %u exceeds buffer size %lu",
+ __func__, sock, hdr.length,
+ (unsigned long)STREAM_SIZE(client->ibuf_work));
+ goto zread_fail;
}
/* Read rest of data. */
- if (already < length) {
- ssize_t nbyte;
- if (((nbyte = stream_read_try(client->ibuf, sock,
- length - already))
- == 0)
- || (nbyte == -1)) {
- if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug(
- "connection closed [%d] when reading zebra data",
- sock);
- zebra_client_close(client);
- return -1;
- }
- if (nbyte != (ssize_t)(length - already)) {
+ if (already < hdr.length) {
+ nb = stream_read_try(client->ibuf_work, sock,
+ hdr.length - already);
+ if ((nb == 0 || nb == -1) && IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug(
+ "connection closed [%d] when reading zebra data",
+ sock);
+ if ((nb == 0 || nb == -1))
+ goto zread_fail;
+ if (nb != (ssize_t)(hdr.length - already)) {
/* Try again later. */
- zebra_event(ZEBRA_READ, sock, client);
- return 0;
+ break;
}
}
#if defined(HANDLE_ZAPI_FUZZING)
- zserv_write_incoming(client->ibuf, command);
+ zserv_write_incoming(client->ibuf_work, command);
#endif
- length -= ZEBRA_HEADER_SIZE;
+ hdr.length -= ZEBRA_HEADER_SIZE;
/* Debug packet information. */
if (IS_ZEBRA_DEBUG_EVENT)
@@ -2975,41 +2949,54 @@ static int zebra_client_read(struct thread *thread)
sock);
if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
- zlog_debug("zebra message received [%s] %d in VRF %u",
- zserv_command_string(command), length,
- vrf_id);
+ zserv_log_message(NULL, client->ibuf_work, &hdr);
client->last_read_time = monotime(NULL);
- client->last_read_cmd = command;
-
- zvrf = zebra_vrf_lookup_by_id(vrf_id);
- if (!zvrf) {
- if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
- zlog_debug("zebra received unknown VRF[%u]",
- vrf_id);
- goto zclient_read_out;
- }
+ client->last_read_cmd = hdr.command;
- zserv_handle_commands(client, command, length, zvrf);
+ stream_set_getp(client->ibuf_work, 0);
+ struct stream *msg = stream_dup(client->ibuf_work);
- if (client->t_suicide) {
- /* No need to wait for thread callback, just kill
- * immediately.
- */
- zebra_client_close(client);
- return -1;
- }
- packets -= 1;
- stream_reset(client->ibuf);
+ stream_fifo_push(client->ibuf_fifo, msg);
+
+ if (client->t_suicide)
+ goto zread_fail;
+
+ --packets;
+ stream_reset(client->ibuf_work);
}
-stream_failure:
-zclient_read_out:
- stream_reset(client->ibuf);
- zebra_event(ZEBRA_READ, sock, client);
+ if (IS_ZEBRA_DEBUG_PACKET)
+ zlog_debug("Read %d packets",
+ zebrad.packets_to_process - packets);
+
+ /* Schedule job to process those packets */
+ thread_add_event(zebrad.master, &zserv_process_messages, client, 0,
+ NULL);
+
+ /* Reschedule ourselves */
+ zebra_event(client, ZEBRA_READ);
+
return 0;
+
+zread_fail:
+ zebra_client_close(client);
+ return -1;
}
+static void zebra_event(struct zserv *client, enum event event)
+{
+ switch (event) {
+ case ZEBRA_READ:
+ thread_add_read(zebrad.master, zserv_read, client, client->sock,
+ &client->t_read);
+ break;
+ case ZEBRA_WRITE:
+ thread_add_write(zebrad.master, zserv_write, client,
+ client->sock, &client->t_write);
+ break;
+ }
+}
/* Accept code of zebra server socket. */
static int zebra_accept(struct thread *thread)
@@ -3022,7 +3009,7 @@ static int zebra_accept(struct thread *thread)
accept_sock = THREAD_FD(thread);
/* Reregister myself. */
- zebra_event(ZEBRA_SERV, accept_sock, NULL);
+ thread_add_read(zebrad.master, zebra_accept, NULL, accept_sock, NULL);
len = sizeof(struct sockaddr_in);
client_sock = accept(accept_sock, (struct sockaddr *)&client, &len);
@@ -3109,26 +3096,7 @@ void zebra_zserv_socket_init(char *path)
umask(old_mask);
- zebra_event(ZEBRA_SERV, sock, NULL);
-}
-
-
-static void zebra_event(enum event event, int sock, struct zserv *client)
-{
- switch (event) {
- case ZEBRA_SERV:
- thread_add_read(zebrad.master, zebra_accept, client, sock,
- NULL);
- break;
- case ZEBRA_READ:
- client->t_read = NULL;
- thread_add_read(zebrad.master, zebra_client_read, client, sock,
- &client->t_read);
- break;
- case ZEBRA_WRITE:
- /**/
- break;
- }
+ thread_add_read(zebrad.master, zebra_accept, NULL, sock, NULL);
}
#define ZEBRA_TIME_BUF 32
diff --git a/zebra/zserv.h b/zebra/zserv.h
index 8519693726..62707510c2 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -47,8 +47,12 @@ struct zserv {
int sock;
/* Input/output buffer to the client. */
- struct stream *ibuf;
- struct stream *obuf;
+ struct stream_fifo *ibuf_fifo;
+ struct stream_fifo *obuf_fifo;
+
+ /* Private I/O buffers */
+ struct stream *ibuf_work;
+ struct stream *obuf_work;
/* Buffer of data waiting to be written to client. */
struct buffer *wb;
@@ -129,6 +133,10 @@ struct zserv {
int last_write_cmd;
};
+#define ZAPI_HANDLER_ARGS \
+ struct zserv *client, struct zmsghdr *hdr, struct stream *msg, \
+ struct zebra_vrf *zvrf
+
/* Zebra instance */
struct zebra_t {
/* Thread master */
@@ -185,7 +193,7 @@ extern void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
extern void zserv_nexthop_num_warn(const char *, const struct prefix *,
const unsigned int);
-extern int zebra_server_send_message(struct zserv *client);
+extern int zebra_server_send_message(struct zserv *client, struct stream *msg);
extern struct zserv *zebra_find_client(u_char proto, u_short instance);