summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/interface.c4
-rw-r--r--zebra/label_manager.c133
-rw-r--r--zebra/label_manager.h2
-rw-r--r--zebra/redistribute.c66
-rw-r--r--zebra/zebra_rnh.c2
-rw-r--r--zebra/zserv.c5
6 files changed, 133 insertions, 79 deletions
diff --git a/zebra/interface.c b/zebra/interface.c
index 7ff782f7cc..7b0d31338d 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -709,6 +709,10 @@ if_delete_update (struct interface *ifp)
interface deletion message. */
ifp->ifindex = IFINDEX_INTERNAL;
ifp->node = NULL;
+
+ /* if the ifp is in a vrf, move it to default so vrf can be deleted if desired */
+ if (ifp->vrf_id)
+ if_handle_vrf_change (ifp, VRF_DEFAULT);
}
/* VRF change for an interface */
diff --git a/zebra/label_manager.c b/zebra/label_manager.c
index cbb35631ac..fbe4cea467 100644
--- a/zebra/label_manager.c
+++ b/zebra/label_manager.c
@@ -55,6 +55,80 @@ static void delete_label_chunk(void *val)
XFREE(MTYPE_LM_CHUNK, val);
}
+static int relay_response_back(struct zserv *zserv)
+{
+ int ret = 0;
+ struct stream *src, *dst;
+ u_int16_t size = 0;
+ u_char marker;
+ u_char version;
+ vrf_id_t vrf_id;
+ u_int16_t resp_cmd;
+
+ src = zclient->ibuf;
+ dst = zserv->obuf;
+
+ stream_reset(src);
+
+ 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));
+ return -1;
+ }
+ zlog_debug("%s: Label Manager response received, %d bytes", __func__,
+ size);
+ if (size == 0)
+ return -1;
+
+ /* send response back */
+ stream_copy(dst, src);
+ 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));
+ return -1;
+ }
+ zlog_debug("%s: Label Manager response (%d bytes) sent back", __func__,
+ ret);
+
+ 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);
+
+ return ret;
+}
+
+static int reply_error (int cmd, struct zserv *zserv, vrf_id_t vrf_id)
+{
+ struct stream *s;
+
+ s = zserv->obuf;
+ stream_reset (s);
+
+ zserv_create_header (s, cmd, vrf_id);
+
+ /* result */
+ stream_putc (s, 1);
+
+ /* Write packet size. */
+ stream_putw_at (s, 0, stream_get_endp (s));
+
+ return writen (zserv->sock, s->data, stream_get_endp (s));
+
+}
/**
* Receive a request to get or release a label chunk and forward it to external
* label manager.
@@ -63,19 +137,25 @@ static void delete_label_chunk(void *val)
* proxy.
*
* @param cmd Type of request (connect, get or release)
- * @param src Input buffer from zserv
+ * @param zserv
* @return 0 on success, -1 otherwise
*/
-int zread_relay_label_manager_request(int cmd, struct zserv *zserv)
+int zread_relay_label_manager_request(int cmd, struct zserv *zserv, vrf_id_t vrf_id)
{
struct stream *src, *dst;
- int ret;
+ int ret = 0;
if (zclient->sock < 0) {
zlog_err("%s: Error relaying label chunk request: no zclient socket",
__func__);
+ reply_error (cmd, zserv, vrf_id);
return -1;
}
+
+ /* in case there's any incoming message enqueued, read and forward it */
+ while (ret == 0)
+ ret = relay_response_back(zserv);
+
/* Send request to external label manager */
src = zserv->ibuf;
dst = zclient->obuf;
@@ -86,6 +166,7 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv)
if (ret <= 0) {
zlog_err("%s: Error relaying label chunk request: %s", __func__,
strerror(errno));
+ reply_error (cmd, zserv, vrf_id);
return -1;
}
zlog_debug("%s: Label chunk request relayed. %d bytes sent", __func__,
@@ -95,43 +176,15 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv)
if (cmd == ZEBRA_RELEASE_LABEL_CHUNK)
return 0;
- /* read response */
- src = zclient->ibuf;
- dst = zserv->obuf;
-
- stream_reset(src);
-
- u_int16_t size;
- u_char marker;
- u_char version;
- vrf_id_t vrf_id;
- u_int16_t resp_cmd;
- ret = zclient_read_header(src, zclient->sock, &size, &marker, &version,
- &vrf_id, &resp_cmd);
- if (ret < 0) {
- zlog_err("%s: Error reading label chunk response: %s", __func__,
- strerror(errno));
- return -1;
- }
- zlog_debug("%s: Label chunk response received, %d bytes", __func__,
- size);
-
- /* send response back */
- stream_copy(dst, src);
- stream_copy(zserv->obuf, zclient->ibuf);
- ret = writen(zserv->sock, dst->data, stream_get_endp(dst));
- if (ret <= 0) {
- zlog_err("%s: Error sending label chunk response back: %s",
- __func__, strerror(errno));
- return -1;
- }
- zlog_debug("%s: Label chunk response (%d bytes) sent back", __func__,
- ret);
+ /* make sure we listen to the response */
+ if (!zclient->t_read)
+ thread_add_read(zclient->master, lm_zclient_read, zserv,
+ zclient->sock, &zclient->t_read);
return 0;
}
-static int zclient_connect(struct thread *t)
+static int lm_zclient_connect(struct thread *t)
{
zclient->t_connect = NULL;
@@ -140,11 +193,15 @@ static int zclient_connect(struct thread *t)
if (zclient_socket_connect(zclient) < 0) {
zlog_err("Error connecting synchronous zclient!");
- thread_add_timer(zebrad.master, zclient_connect, zclient,
+ thread_add_timer(zebrad.master, lm_zclient_connect, zclient,
CONNECTION_DELAY, &zclient->t_connect);
return -1;
}
+ /* make socket non-blocking */
+ if (set_nonblocking(zclient->sock) < 0)
+ zlog_warn("%s: set_nonblocking(%d) failed", __func__, zclient->sock);
+
return 0;
}
@@ -163,7 +220,7 @@ static void lm_zclient_init(char *lm_zserv_path)
zclient = zclient_new(zebrad.master);
zclient->sock = -1;
zclient->t_connect = NULL;
- zclient_connect (NULL);
+ lm_zclient_connect(NULL);
}
/**
diff --git a/zebra/label_manager.h b/zebra/label_manager.h
index a68c301f16..b7d6118a0e 100644
--- a/zebra/label_manager.h
+++ b/zebra/label_manager.h
@@ -61,7 +61,7 @@ struct label_manager {
bool lm_is_external;
-int zread_relay_label_manager_request(int cmd, struct zserv *zserv);
+int zread_relay_label_manager_request(int cmd, struct zserv *zserv, vrf_id_t vrf_id);
void label_manager_init(char *lm_zserv_path);
struct label_manager_chunk *assign_label_chunk(u_char proto, u_short instance,
u_char keep, uint32_t size);
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 95e84ffc3c..1493bd9cb6 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -106,45 +106,41 @@ zebra_redistribute_default (struct zserv *client, vrf_id_t vrf_id)
/* Redistribute routes. */
static void
-zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t vrf_id)
+zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t vrf_id, int afi)
{
struct rib *newrib;
struct route_table *table;
struct route_node *rn;
- int afi;
- for (afi = AFI_IP; afi <= AFI_IP6; afi++)
- {
- table = zebra_vrf_table (afi, SAFI_UNICAST, vrf_id);
- if (! table)
- continue;
+ table = zebra_vrf_table (afi, SAFI_UNICAST, vrf_id);
+ if (! table)
+ return;
- for (rn = route_top (table); rn; rn = route_next (rn))
- RNODE_FOREACH_RIB (rn, newrib)
- {
- struct prefix *dst_p, *src_p;
- srcdest_rnode_prefixes(rn, &dst_p, &src_p);
-
- if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("%s: checking: selected=%d, type=%d, distance=%d, "
- "zebra_check_addr=%d", __func__,
- CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED),
- newrib->type, newrib->distance,
- zebra_check_addr (dst_p));
-
- if (! CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED))
- continue;
- if ((type != ZEBRA_ROUTE_ALL &&
- (newrib->type != type || newrib->instance != instance)))
- continue;
- if (newrib->distance == DISTANCE_INFINITY)
- continue;
- if (! zebra_check_addr (dst_p))
- continue;
-
- zsend_redistribute_route (1, client, dst_p, src_p, newrib);
- }
- }
+ for (rn = route_top (table); rn; rn = route_next (rn))
+ RNODE_FOREACH_RIB (rn, newrib)
+ {
+ struct prefix *dst_p, *src_p;
+ srcdest_rnode_prefixes(rn, &dst_p, &src_p);
+
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("%s: checking: selected=%d, type=%d, distance=%d, "
+ "zebra_check_addr=%d", __func__,
+ CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED),
+ newrib->type, newrib->distance,
+ zebra_check_addr (dst_p));
+
+ if (! CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED))
+ continue;
+ if ((type != ZEBRA_ROUTE_ALL &&
+ (newrib->type != type || newrib->instance != instance)))
+ continue;
+ if (newrib->distance == DISTANCE_INFINITY)
+ continue;
+ if (! zebra_check_addr (dst_p))
+ continue;
+
+ zsend_redistribute_route (1, client, dst_p, src_p, newrib);
+ }
}
/* Either advertise a route for redistribution to registered clients or */
@@ -264,13 +260,13 @@ zebra_redistribute_add (int command, struct zserv *client, int length,
if (! redist_check_instance (&client->mi_redist[afi][type], instance))
{
redist_add_instance (&client->mi_redist[afi][type], instance);
- zebra_redistribute (client, type, instance, zvrf_id (zvrf));
+ zebra_redistribute (client, type, instance, zvrf_id (zvrf), afi);
}
} else {
if (! vrf_bitmap_check (client->redist[afi][type], zvrf_id (zvrf)))
{
vrf_bitmap_set (client->redist[afi][type], zvrf_id (zvrf));
- zebra_redistribute (client, type, 0, zvrf_id (zvrf));
+ zebra_redistribute (client, type, 0, zvrf_id (zvrf), afi);
}
}
}
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 20b0c13a40..16c157e307 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -554,7 +554,7 @@ zebra_rnh_process_static_routes (vrf_id_t vrfid, int family,
{
RNODE_FOREACH_RIB(static_rn, srib)
{
- if (srib->type == ZEBRA_ROUTE_STATIC)
+ if (srib->type != ZEBRA_ROUTE_STATIC)
continue;
/* Set the filter flag for the correct nexthop - static route may
diff --git a/zebra/zserv.c b/zebra/zserv.c
index a59ef3031d..76c0756ada 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -2045,10 +2045,7 @@ zread_label_manager_request (int cmd, struct zserv *client, vrf_id_t vrf_id)
/* external label manager */
if (lm_is_external)
- {
- if (zread_relay_label_manager_request (cmd, client) != 0)
- zsend_label_manager_connect_response (client, vrf_id, 1);
- }
+ zread_relay_label_manager_request (cmd, client, vrf_id);
/* this is a label manager */
else
{