diff options
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/interface.c | 4 | ||||
| -rw-r--r-- | zebra/label_manager.c | 133 | ||||
| -rw-r--r-- | zebra/label_manager.h | 2 | ||||
| -rw-r--r-- | zebra/redistribute.c | 66 | ||||
| -rw-r--r-- | zebra/zebra_rnh.c | 2 | ||||
| -rw-r--r-- | zebra/zserv.c | 5 |
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 { |
