summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/label_manager.c127
-rw-r--r--zebra/label_manager.h2
-rw-r--r--zebra/zapi_msg.c60
3 files changed, 149 insertions, 40 deletions
diff --git a/zebra/label_manager.c b/zebra/label_manager.c
index 190ac1e57f..f3fa3ba94e 100644
--- a/zebra/label_manager.c
+++ b/zebra/label_manager.c
@@ -50,7 +50,6 @@ 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;
@@ -60,7 +59,7 @@ static void delete_label_chunk(void *val)
XFREE(MTYPE_LM_CHUNK, val);
}
-static int relay_response_back(struct zserv *zserv)
+static int relay_response_back(void)
{
int ret = 0;
struct stream *src, *dst;
@@ -69,49 +68,72 @@ static int relay_response_back(struct zserv *zserv)
uint8_t version;
vrf_id_t vrf_id;
uint16_t resp_cmd;
+ uint8_t proto;
+ const char *proto_str;
+ unsigned short instance;
+ struct zserv *zserv;
+ /* input buffer with msg from label manager */
src = zclient->ibuf;
- dst = obuf;
stream_reset(src);
+ /* parse header */
ret = zclient_read_header(src, zclient->sock, &size, &marker, &version,
&vrf_id, &resp_cmd);
if (ret < 0 && errno != EAGAIN) {
- zlog_err("%s: Error reading Label Manager response: %s",
- __func__, strerror(errno));
+ zlog_err("Error reading Label Manager response: %s",
+ strerror(errno));
return -1;
}
- zlog_debug("%s: Label Manager response received, %d bytes", __func__,
- size);
+ zlog_debug("Label Manager response received, %d bytes", size);
if (size == 0)
return -1;
- /* send response back */
+ /* Get the 'proto' field of the message */
+ proto = stream_getc(src);
+
+ /* Get the 'instance' field of the message */
+ instance = stream_getw(src);
+
+ proto_str = zebra_route_string(proto);
+
+ /* lookup the client to relay the msg to */
+ zserv = zebra_find_client(proto, instance);
+ if (!zserv) {
+ zlog_err(
+ "Error relaying LM response: can't find client %s, instance %u",
+ proto_str, instance);
+ return -1;
+ }
+ zlog_debug("Found client to relay LM response to client %s instance %u",
+ proto_str, instance);
+
+ /* copy msg into output buffer */
+ dst = obuf;
stream_copy(dst, src);
- ret = writen(zserv->sock, src->data, stream_get_endp(src));
+
+ /* send response back */
+ ret = writen(zserv->sock, dst->data, stream_get_endp(dst));
if (ret <= 0) {
- zlog_err("%s: Error sending Label Manager response back: %s",
- __func__, strerror(errno));
+ zlog_err("Error relaying LM response to %s instance %u: %s",
+ proto_str, instance, strerror(errno));
return -1;
}
- zlog_debug("%s: Label Manager response (%d bytes) sent back", __func__,
- ret);
+ zlog_debug("Relayed LM response (%d bytes) to %s instance %u", ret,
+ proto_str, instance);
return 0;
}
static int lm_zclient_read(struct thread *t)
{
- struct zserv *zserv;
int ret;
- /* Get socket to zebra. */
- zserv = THREAD_ARG(t);
zclient->t_read = NULL;
/* read response and send it back */
- ret = relay_response_back(zserv);
+ ret = relay_response_back();
return ret;
}
@@ -125,6 +147,10 @@ static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id)
zclient_create_header(s, cmd, vrf_id);
+ /* proto */
+ stream_putc(s, zserv->proto);
+ /* instance */
+ stream_putw(s, zserv->instance);
/* result */
stream_putc(s, 1);
@@ -148,38 +174,73 @@ static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id)
* @return 0 on success, -1 otherwise
*/
int zread_relay_label_manager_request(int cmd, struct zserv *zserv,
- vrf_id_t vrf_id)
+ struct stream *msg, vrf_id_t vrf_id)
{
- struct stream *src, *dst;
+ struct stream *dst;
int ret = 0;
+ uint8_t proto;
+ const char *proto_str;
+ unsigned short instance;
if (zclient->sock < 0) {
- zlog_err(
- "%s: Error relaying label chunk request: no zclient socket",
- __func__);
+ zlog_err("Unable to relay LM request: no socket");
reply_error(cmd, zserv, vrf_id);
return -1;
}
+ /* peek msg to get proto and instance id. This zebra, which acts as
+ * a proxy needs to have such values for each client in order to
+ * relay responses back to it.
+ */
+
+ /* Get the 'proto' field of incoming msg */
+ proto = stream_getc(msg);
+
+ /* Get the 'instance' field of incoming msg */
+ instance = stream_getw(msg);
+
+ /* stringify proto */
+ proto_str = zebra_route_string(proto);
+
+ /* check & set client proto if unset */
+ if (zserv->proto && zserv->proto != proto) {
+ zlog_warn("Client proto(%u) != msg proto(%u)", zserv->proto,
+ proto);
+ return -1;
+ }
+
+ /* check & set client instance if unset */
+ if (zserv->instance && zserv->instance != instance) {
+ zlog_err("Client instance(%u) != msg instance(%u)",
+ zserv->instance, instance);
+ return -1;
+ }
+
+ /* recall proto and instance */
+ zserv->instance = instance;
+ zserv->proto = proto;
+
/* in case there's any incoming message enqueued, read and forward it */
while (ret == 0)
- ret = relay_response_back(zserv);
+ ret = relay_response_back();
- /* Send request to external label manager */
- src = ibuf;
+ /* get the msg buffer used toward the 'master' Label Manager */
dst = zclient->obuf;
- stream_copy(dst, src);
+ /* copy the message */
+ stream_copy(dst, msg);
+ /* Send request to external label manager */
ret = writen(zclient->sock, dst->data, stream_get_endp(dst));
if (ret <= 0) {
- zlog_err("%s: Error relaying label chunk request: %s", __func__,
- strerror(errno));
+ zlog_err("Error relaying LM request from %s instance %u: %s",
+ proto_str, instance, strerror(errno));
reply_error(cmd, zserv, vrf_id);
return -1;
}
- zlog_debug("%s: Label chunk request relayed. %d bytes sent", __func__,
- ret);
+ zlog_debug("Relayed LM request (%d bytes) from %s instance %u", ret,
+ proto_str, instance);
+
/* Release label chunk has no response */
if (cmd == ZEBRA_RELEASE_LABEL_CHUNK)
@@ -187,7 +248,7 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv,
/* make sure we listen to the response */
if (!zclient->t_read)
- thread_add_read(zclient->master, lm_zclient_read, zserv,
+ thread_add_read(zclient->master, lm_zclient_read, NULL,
zclient->sock, &zclient->t_read);
return 0;
@@ -276,7 +337,7 @@ void label_manager_init(char *lm_zserv_path)
{
/* this is an actual label manager */
if (!lm_zserv_path) {
- zlog_debug("Initializing own label manager");
+ zlog_debug("Initializing internal label manager");
lm_is_external = false;
lbl_mgr.lc_list = list_new();
lbl_mgr.lc_list->del = delete_label_chunk;
@@ -287,7 +348,6 @@ void label_manager_init(char *lm_zserv_path)
lm_zclient_init(lm_zserv_path);
}
- ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
obuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
hook_register(zapi_client_close, release_daemon_label_chunks);
@@ -393,6 +453,5 @@ int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start,
void label_manager_close()
{
list_delete_and_null(&lbl_mgr.lc_list);
- stream_free(ibuf);
stream_free(obuf);
}
diff --git a/zebra/label_manager.h b/zebra/label_manager.h
index b998372224..3e3def5f98 100644
--- a/zebra/label_manager.h
+++ b/zebra/label_manager.h
@@ -64,7 +64,7 @@ struct label_manager {
bool lm_is_external;
int zread_relay_label_manager_request(int cmd, struct zserv *zserv,
- vrf_id_t vrf_id);
+ struct stream *msg, vrf_id_t vrf_id);
void label_manager_init(char *lm_zserv_path);
struct label_manager_chunk *assign_label_chunk(uint8_t proto,
unsigned short instance,
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 2ff660b3f9..e03caa61b7 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -887,6 +887,10 @@ static int zsend_assign_label_chunk_response(struct zserv *client,
zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id);
if (lmc) {
+ /* proto */
+ stream_putc(s, lmc->proto);
+ /* instance */
+ stream_putw(s, lmc->instance);
/* keep */
stream_putc(s, lmc->keep);
/* start and end labels */
@@ -912,6 +916,12 @@ static int zsend_label_manager_connect_response(struct zserv *client,
zclient_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id);
+ /* proto */
+ stream_putc(s, client->proto);
+
+ /* instance */
+ stream_putw(s, client->instance);
+
/* result */
stream_putc(s, result);
@@ -2398,6 +2408,26 @@ static void zread_label_manager_connect(struct zserv *client,
stream_failure:
return;
}
+static int msg_client_id_mismatch(const char *op, struct zserv *client,
+ uint8_t proto, unsigned int instance)
+{
+ if (proto != client->proto) {
+ zlog_err("%s: msg vs client proto mismatch, client=%u msg=%u",
+ op, client->proto, proto);
+ /* TODO: fail when BGP sets proto and instance */
+ /* return 1; */
+ }
+
+ if (instance != client->instance) {
+ zlog_err(
+ "%s: msg vs client instance mismatch, client=%u msg=%u",
+ op, client->instance, instance);
+ /* TODO: fail when BGP sets proto and instance */
+ /* return 1; */
+ }
+
+ return 0;
+}
static void zread_get_label_chunk(struct zserv *client, struct stream *msg,
vrf_id_t vrf_id)
@@ -2406,21 +2436,32 @@ static void zread_get_label_chunk(struct zserv *client, struct stream *msg,
uint8_t keep;
uint32_t size;
struct label_manager_chunk *lmc;
+ uint8_t proto;
+ unsigned short instance;
/* Get input stream. */
s = msg;
/* Get data. */
+ STREAM_GETC(s, proto);
+ STREAM_GETW(s, instance);
STREAM_GETC(s, keep);
STREAM_GETL(s, size);
+ /* detect client vs message (proto,instance) mismatch */
+ if (msg_client_id_mismatch("Get-label-chunk", client, proto, instance))
+ return;
+
lmc = assign_label_chunk(client->proto, client->instance, keep, size);
if (!lmc)
- zlog_err("%s: Unable to assign Label Chunk of size %u",
- __func__, size);
+ zlog_err(
+ "Unable to assign Label Chunk of size %u to %s instance %u",
+ size, zebra_route_string(client->proto),
+ client->instance);
else
- zlog_debug("Assigned Label Chunk %u - %u to %u", lmc->start,
- lmc->end, keep);
+ zlog_debug("Assigned Label Chunk %u - %u to %s instance %u",
+ lmc->start, lmc->end,
+ zebra_route_string(client->proto), client->instance);
/* send response back */
zsend_assign_label_chunk_response(client, vrf_id, lmc);
@@ -2432,14 +2473,23 @@ static void zread_release_label_chunk(struct zserv *client, struct stream *msg)
{
struct stream *s;
uint32_t start, end;
+ uint8_t proto;
+ unsigned short instance;
/* Get input stream. */
s = msg;
/* Get data. */
+ STREAM_GETC(s, proto);
+ STREAM_GETW(s, instance);
STREAM_GETL(s, start);
STREAM_GETL(s, end);
+ /* detect client vs message (proto,instance) mismatch */
+ if (msg_client_id_mismatch("Release-label-chunk", client, proto,
+ instance))
+ return;
+
release_label_chunk(client->proto, client->instance, start, end);
stream_failure:
@@ -2453,7 +2503,7 @@ static void zread_label_manager_request(ZAPI_HANDLER_ARGS)
/* external label manager */
if (lm_is_external)
- zread_relay_label_manager_request(hdr->command, client,
+ zread_relay_label_manager_request(hdr->command, client, msg,
zvrf_id(zvrf));
/* this is a label manager */
else {