diff options
-rw-r--r-- | bgpd/bgp_labelpool.c | 5 | ||||
-rw-r--r-- | bgpd/bgp_nht.c | 2 | ||||
-rw-r--r-- | bgpd/bgp_zebra.c | 15 | ||||
-rw-r--r-- | isisd/isis_zebra.c | 2 | ||||
-rw-r--r-- | ldpd/lde.c | 2 | ||||
-rw-r--r-- | ldpd/ldp_zebra.c | 33 | ||||
-rw-r--r-- | lib/bfd.c | 6 | ||||
-rw-r--r-- | lib/zclient.c | 245 | ||||
-rw-r--r-- | lib/zclient.h | 153 | ||||
-rw-r--r-- | ospf6d/ospf6_zebra.c | 2 | ||||
-rw-r--r-- | ospfd/ospf_zebra.c | 2 | ||||
-rw-r--r-- | pbrd/pbr_zebra.c | 4 | ||||
-rw-r--r-- | pimd/pim_nht.c | 2 | ||||
-rw-r--r-- | pimd/pim_zlookup.c | 2 | ||||
-rw-r--r-- | sharpd/sharp_zebra.c | 287 | ||||
-rw-r--r-- | sharpd/sharp_zebra.h | 4 | ||||
-rw-r--r-- | staticd/static_zebra.c | 3 | ||||
-rw-r--r-- | vrrpd/vrrp_zebra.c | 5 | ||||
-rw-r--r-- | vrrpd/vrrp_zebra.h | 4 | ||||
-rw-r--r-- | zebra/zapi_msg.c | 6 |
20 files changed, 460 insertions, 324 deletions
diff --git a/bgpd/bgp_labelpool.c b/bgpd/bgp_labelpool.c index feda0328b..e8d8167c3 100644 --- a/bgpd/bgp_labelpool.c +++ b/bgpd/bgp_labelpool.c @@ -392,8 +392,9 @@ void bgp_lp_get( if (lp_fifo_count(&lp->requests) > lp->pending_count) { if (!zclient || zclient->sock < 0) return; - if (!zclient_send_get_label_chunk(zclient, 0, LP_CHUNK_SIZE, - MPLS_LABEL_BASE_ANY)) + if (zclient_send_get_label_chunk(zclient, 0, LP_CHUNK_SIZE, + MPLS_LABEL_BASE_ANY) + == ZCLIENT_SEND_FAILURE) lp->pending_count += LP_CHUNK_SIZE; } } diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 5d3667af1..9635fe122 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -624,7 +624,7 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command) ret = zclient_send_rnh(zclient, command, &bnc->prefix, exact_match, bnc->bgp->vrf_id); /* TBD: handle the failure */ - if (ret < 0) + if (ret == ZCLIENT_SEND_FAILURE) flog_warn(EC_BGP_ZEBRA_SEND, "sendmsg_nexthop: zclient_send_message() failed"); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 73f03f6a9..5d43645c6 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -3051,7 +3051,8 @@ void bgp_send_pbr_rule_action(struct bgp_pbr_action *pbra, bgp_encode_pbr_rule_action(s, pbra, pbr); stream_putw_at(s, 0, stream_get_endp(s)); - if (!zclient_send_message(zclient) && install) { + if ((zclient_send_message(zclient) != ZCLIENT_SEND_FAILURE) + && install) { if (!pbr) pbra->install_in_progress = true; else @@ -3082,7 +3083,7 @@ void bgp_send_pbr_ipset_match(struct bgp_pbr_match *pbrim, bool install) bgp_encode_pbr_ipset_match(s, pbrim); stream_putw_at(s, 0, stream_get_endp(s)); - if (!zclient_send_message(zclient) && install) + if ((zclient_send_message(zclient) != ZCLIENT_SEND_FAILURE) && install) pbrim->install_in_progress = true; } @@ -3110,7 +3111,7 @@ void bgp_send_pbr_ipset_entry_match(struct bgp_pbr_match_entry *pbrime, bgp_encode_pbr_ipset_entry_match(s, pbrime); stream_putw_at(s, 0, stream_get_endp(s)); - if (!zclient_send_message(zclient) && install) + if ((zclient_send_message(zclient) != ZCLIENT_SEND_FAILURE) && install) pbrime->install_in_progress = true; } @@ -3185,7 +3186,7 @@ void bgp_send_pbr_iptable(struct bgp_pbr_action *pba, stream_putw_at(s, 0, stream_get_endp(s)); ret = zclient_send_message(zclient); if (install) { - if (ret) + if (ret != ZCLIENT_SEND_FAILURE) pba->refcnt++; else pbm->install_iptable_in_progress = true; @@ -3319,7 +3320,7 @@ int bgp_zebra_send_capabilities(struct bgp *bgp, bool disable) } if (zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient, &api) - < 0) { + == ZCLIENT_SEND_FAILURE) { zlog_err("error sending capability"); ret = BGP_GR_FAILURE; } else { @@ -3361,7 +3362,7 @@ int bgp_zebra_update(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type) api.cap = type; if (zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient, &api) - < 0) { + == ZCLIENT_SEND_FAILURE) { if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("error sending capability"); return BGP_GR_FAILURE; @@ -3393,7 +3394,7 @@ int bgp_zebra_stale_timer_update(struct bgp *bgp) api.stale_removal_time = bgp->rib_stale_time; api.vrf_id = bgp->vrf_id; if (zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient, &api) - < 0) { + == ZCLIENT_SEND_FAILURE) { if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("error sending capability"); return BGP_GR_FAILURE; diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 8bc563399..b9958a669 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -618,7 +618,7 @@ int isis_zebra_label_manager_connect(void) set_nonblocking(zclient_sync->sock); /* Send hello to notify zebra this is a synchronous client */ - if (zclient_send_hello(zclient_sync) < 0) { + if (zclient_send_hello(zclient_sync) == ZCLIENT_SEND_FAILURE) { zlog_warn("%s: failed sending hello for synchronous zclient!", __func__); close(zclient_sync->sock); diff --git a/ldpd/lde.c b/ldpd/lde.c index 67b695150..c2e11a0ae 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -2092,7 +2092,7 @@ static void zclient_sync_init(void) sock_set_nonblock(zclient_sync->sock); /* Send hello to notify zebra this is a synchronous client */ - if (zclient_send_hello(zclient_sync) < 0) { + if (zclient_send_hello(zclient_sync) == ZCLIENT_SEND_FAILURE) { log_warnx("Error sending hello for synchronous zclient!"); goto retry; } diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index 3852d8d23..df9832a28 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -127,8 +127,12 @@ ldp_zebra_opaque_unregister(void) int ldp_sync_zebra_send_state_update(struct ldp_igp_sync_if_state *state) { - return zclient_send_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE, - (const uint8_t *) state, sizeof(*state)); + if (zclient_send_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE, + (const uint8_t *)state, sizeof(*state)) + == ZCLIENT_SEND_FAILURE) + return -1; + else + return 0; } static int @@ -137,8 +141,12 @@ ldp_sync_zebra_send_announce(void) struct ldp_igp_sync_announce announce; announce.proto = ZEBRA_ROUTE_LDP; - return zclient_send_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE, - (const uint8_t *) &announce, sizeof(announce)); + if (zclient_send_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE, + (const uint8_t *)&announce, sizeof(announce)) + == ZCLIENT_SEND_FAILURE) + return -1; + else + return 0; } static int @@ -272,7 +280,10 @@ ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr) znh->label_num = 1; znh->labels[0] = kr->remote_label; - return zebra_send_mpls_labels(zclient, cmd, &zl); + if (zebra_send_mpls_labels(zclient, cmd, &zl) == ZCLIENT_SEND_FAILURE) + return -1; + + return 0; } int @@ -293,7 +304,8 @@ kmpw_add(struct zapi_pw *zpw) debug_zebra_out("pseudowire %s nexthop %s (add)", zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop)); - return (zebra_send_pw(zclient, ZEBRA_PW_ADD, zpw)); + return zebra_send_pw(zclient, ZEBRA_PW_ADD, zpw) + == ZCLIENT_SEND_FAILURE; } int @@ -302,7 +314,8 @@ kmpw_del(struct zapi_pw *zpw) debug_zebra_out("pseudowire %s nexthop %s (del)", zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop)); - return (zebra_send_pw(zclient, ZEBRA_PW_DELETE, zpw)); + return zebra_send_pw(zclient, ZEBRA_PW_DELETE, zpw) + == ZCLIENT_SEND_FAILURE; } int @@ -312,7 +325,8 @@ kmpw_set(struct zapi_pw *zpw) zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop), zpw->local_label, zpw->remote_label); - return (zebra_send_pw(zclient, ZEBRA_PW_SET, zpw)); + return zebra_send_pw(zclient, ZEBRA_PW_SET, zpw) + == ZCLIENT_SEND_FAILURE; } int @@ -321,7 +335,8 @@ kmpw_unset(struct zapi_pw *zpw) debug_zebra_out("pseudowire %s nexthop %s (unset)", zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop)); - return (zebra_send_pw(zclient, ZEBRA_PW_UNSET, zpw)); + return zebra_send_pw(zclient, ZEBRA_PW_UNSET, zpw) + == ZCLIENT_SEND_FAILURE; } void @@ -405,7 +405,7 @@ void bfd_client_sendmsg(struct zclient *zclient, int command, vrf_id_t vrf_id) { struct stream *s; - int ret; + enum zclient_send_status ret; /* Check socket. */ if (!zclient || zclient->sock < 0) { @@ -426,7 +426,7 @@ void bfd_client_sendmsg(struct zclient *zclient, int command, ret = zclient_send_message(zclient); - if (ret < 0) { + if (ret == ZCLIENT_SEND_FAILURE) { if (bfd_debug) zlog_debug( "bfd_client_sendmsg %ld: zclient_send_message() failed", @@ -542,7 +542,7 @@ int zclient_bfd_command(struct zclient *zc, struct bfd_session_arg *args) stream_putw_at(s, 0, stream_get_endp(s)); /* Send message to zebra. */ - if (zclient_send_message(zc) == -1) { + if (zclient_send_message(zc) == ZCLIENT_SEND_FAILURE) { if (bfd_debug) zlog_debug("%s: zclient_send_message failed", __func__); return -1; diff --git a/lib/zclient.c b/lib/zclient.c index bab1acf66..053014f86 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -249,12 +249,12 @@ int zclient_socket_connect(struct zclient *zclient) return sock; } -static int zclient_failed(struct zclient *zclient) +static enum zclient_send_status zclient_failed(struct zclient *zclient) { zclient->fail++; zclient_stop(zclient); zclient_event(ZCLIENT_CONNECT, zclient); - return -1; + return ZCLIENT_SEND_FAILURE; } static int zclient_flush_data(struct thread *thread) @@ -277,15 +277,23 @@ static int zclient_flush_data(struct thread *thread) zclient->sock, &zclient->t_write); break; case BUFFER_EMPTY: + if (zclient->zebra_buffer_write_ready) + (*zclient->zebra_buffer_write_ready)(); break; } return 0; } -int zclient_send_message(struct zclient *zclient) +/* + * Returns: + * ZCLIENT_SEND_FAILED - is a failure + * ZCLIENT_SEND_SUCCESS - means we sent data to zebra + * ZCLIENT_SEND_BUFFERED - means we are buffering + */ +enum zclient_send_status zclient_send_message(struct zclient *zclient) { if (zclient->sock < 0) - return -1; + return ZCLIENT_SEND_FAILURE; switch (buffer_write(zclient->wb, zclient->sock, STREAM_DATA(zclient->obuf), stream_get_endp(zclient->obuf))) { @@ -296,13 +304,15 @@ int zclient_send_message(struct zclient *zclient) return zclient_failed(zclient); case BUFFER_EMPTY: THREAD_OFF(zclient->t_write); - break; + return ZCLIENT_SEND_SUCCESS; case BUFFER_PENDING: thread_add_write(zclient->master, zclient_flush_data, zclient, zclient->sock, &zclient->t_write); - break; + return ZCLIENT_SEND_BUFFERED; } - return 0; + + /* should not get here */ + return ZCLIENT_SEND_SUCCESS; } /* @@ -362,8 +372,8 @@ stream_failure: } /* Send simple Zebra message. */ -static int zebra_message_send(struct zclient *zclient, int command, - vrf_id_t vrf_id) +static enum zclient_send_status zebra_message_send(struct zclient *zclient, + int command, vrf_id_t vrf_id) { struct stream *s; @@ -377,7 +387,7 @@ static int zebra_message_send(struct zclient *zclient, int command, return zclient_send_message(zclient); } -int zclient_send_hello(struct zclient *zclient) +enum zclient_send_status zclient_send_hello(struct zclient *zclient) { struct stream *s; @@ -403,11 +413,13 @@ int zclient_send_hello(struct zclient *zclient) return zclient_send_message(zclient); } - return 0; + return ZCLIENT_SEND_SUCCESS; } -void zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id, afi_t afi, - mpls_label_t label, enum lsp_types_t ltype) +enum zclient_send_status zclient_send_vrf_label(struct zclient *zclient, + vrf_id_t vrf_id, afi_t afi, + mpls_label_t label, + enum lsp_types_t ltype) { struct stream *s; @@ -419,7 +431,7 @@ void zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id, afi_t afi, stream_putc(s, afi); stream_putc(s, ltype); stream_putw_at(s, 0, stream_get_endp(s)); - zclient_send_message(zclient); + return zclient_send_message(zclient); } /* Send register requests to zebra daemon for the information in a VRF. */ @@ -557,9 +569,10 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id) } } -int zclient_send_router_id_update(struct zclient *zclient, - zebra_message_types_t type, afi_t afi, - vrf_id_t vrf_id) +enum zclient_send_status +zclient_send_router_id_update(struct zclient *zclient, + zebra_message_types_t type, afi_t afi, + vrf_id_t vrf_id) { struct stream *s = zclient->obuf; stream_reset(s); @@ -570,15 +583,16 @@ int zclient_send_router_id_update(struct zclient *zclient, } /* Send request to zebra daemon to start or stop RA. */ -void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id, - struct interface *ifp, int enable, - int ra_interval) +enum zclient_send_status +zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id, + struct interface *ifp, int enable, + int ra_interval) { struct stream *s; /* If not connected to the zebra yet. */ if (zclient->sock < 0) - return; + return ZCLIENT_SEND_FAILURE; /* Form and send message. */ s = zclient->obuf; @@ -594,16 +608,17 @@ void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id, stream_putw_at(s, 0, stream_get_endp(s)); - zclient_send_message(zclient); + return zclient_send_message(zclient); } -int zclient_send_interface_protodown(struct zclient *zclient, vrf_id_t vrf_id, - struct interface *ifp, bool down) +enum zclient_send_status +zclient_send_interface_protodown(struct zclient *zclient, vrf_id_t vrf_id, + struct interface *ifp, bool down) { struct stream *s; if (zclient->sock < 0) - return -1; + return ZCLIENT_SEND_FAILURE; s = zclient->obuf; stream_reset(s); @@ -611,9 +626,7 @@ int zclient_send_interface_protodown(struct zclient *zclient, vrf_id_t vrf_id, stream_putl(s, ifp->ifindex); stream_putc(s, !!down); stream_putw_at(s, 0, stream_get_endp(s)); - zclient_send_message(zclient); - - return 0; + return zclient_send_message(zclient); } /* Make connection to zebra daemon. */ @@ -712,9 +725,9 @@ static int zclient_connect(struct thread *t) return zclient_start(zclient); } -int zclient_send_rnh(struct zclient *zclient, int command, - const struct prefix *p, bool exact_match, - vrf_id_t vrf_id) +enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command, + const struct prefix *p, + bool exact_match, vrf_id_t vrf_id) { struct stream *s; @@ -750,45 +763,10 @@ int zclient_send_rnh(struct zclient *zclient, int command, * The corresponding read ("xdr_decode") function on the server * side is zapi_route_decode(). * - * 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Length (2) | Command | Route Type | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | ZEBRA Flags | Message Flags | Prefix length | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Destination IPv4 Prefix for route | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Nexthop count | - * +-+-+-+-+-+-+-+-+ - * - * - * A number of IPv4 nexthop(s) or nexthop interface index(es) are then - * described, as per the Nexthop count. Each nexthop described as: - * - * +-+-+-+-+-+-+-+-+ - * | Nexthop Type | Set to one of ZEBRA_NEXTHOP_* - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | IPv4 Nexthop address or Interface Index number | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Alternatively, if the route is a blackhole route, then Nexthop count - * is set to 1 and a nexthop of type NEXTHOP_TYPE_BLACKHOLE is the sole - * nexthop. - * - * The original struct zapi_route_*() infrastructure was built around - * the traditional (32-bit "gate OR ifindex") nexthop data unit. - * A special encoding can be used to feed onlink (64-bit "gate AND ifindex") - * nexthops into zapi_route_encode() using the same zapi_route structure. - * This is done by setting zapi_route fields as follows: - * - .message |= ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_ONLINK - * - .nexthop_num == .ifindex_num - * - .nexthop and .ifindex are filled with gate and ifindex parts of - * each compound nexthop, both in the same order - * * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1 * byte value. * - * If ZAPI_MESSAGE_METRIC is set, the metric value is written as an 8 + * If ZAPI_MESSAGE_METRIC is set, the metric value is written as a 4 * byte value. * * If ZAPI_MESSAGE_TAG is set, the tag value is written as a 4 byte value @@ -797,11 +775,11 @@ int zclient_send_rnh(struct zclient *zclient, int command, * * XXX: No attention paid to alignment. */ -int zclient_route_send(uint8_t cmd, struct zclient *zclient, - struct zapi_route *api) +enum zclient_send_status +zclient_route_send(uint8_t cmd, struct zclient *zclient, struct zapi_route *api) { if (zapi_route_encode(cmd, zclient->obuf, api) < 0) - return -1; + return ZCLIENT_SEND_FAILURE; return zclient_send_message(zclient); } @@ -1058,7 +1036,8 @@ int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg) return 0; } -int zclient_nhg_send(struct zclient *zclient, int cmd, struct zapi_nhg *api_nhg) +enum zclient_send_status zclient_nhg_send(struct zclient *zclient, int cmd, + struct zapi_nhg *api_nhg) { api_nhg->proto = zclient->redist_default; @@ -1791,8 +1770,9 @@ stream_failure: * then set/unset redist[type] in the client handle (a struct zserv) for the * sending client */ -int zebra_redistribute_send(int command, struct zclient *zclient, afi_t afi, - int type, unsigned short instance, vrf_id_t vrf_id) +enum zclient_send_status +zebra_redistribute_send(int command, struct zclient *zclient, afi_t afi, + int type, unsigned short instance, vrf_id_t vrf_id) { struct stream *s; @@ -1809,8 +1789,9 @@ int zebra_redistribute_send(int command, struct zclient *zclient, afi_t afi, return zclient_send_message(zclient); } -int zebra_redistribute_default_send(int command, struct zclient *zclient, - afi_t afi, vrf_id_t vrf_id) +enum zclient_send_status +zebra_redistribute_default_send(int command, struct zclient *zclient, afi_t afi, + vrf_id_t vrf_id) { struct stream *s; @@ -2601,8 +2582,10 @@ stream_failure: * @param base Base for the label chunk. if MPLS_LABEL_BASE_ANY we do not care * @result 0 on success, -1 otherwise */ -int zclient_send_get_label_chunk(struct zclient *zclient, uint8_t keep, - uint32_t chunk_size, uint32_t base) +enum zclient_send_status zclient_send_get_label_chunk(struct zclient *zclient, + uint8_t keep, + uint32_t chunk_size, + uint32_t base) { struct stream *s; @@ -2610,7 +2593,7 @@ int zclient_send_get_label_chunk(struct zclient *zclient, uint8_t keep, zlog_debug("Getting Label Chunk"); if (zclient->sock < 0) - return -1; + return ZCLIENT_SEND_FAILURE; s = zclient->obuf; stream_reset(s); @@ -2826,7 +2809,7 @@ int tm_table_manager_connect(struct zclient *zclient) zlog_debug("Connecting to Table Manager"); if (zclient->sock < 0) - return -1; + return ZCLIENT_SEND_FAILURE; /* send request */ s = zclient->obuf; @@ -2842,7 +2825,7 @@ int tm_table_manager_connect(struct zclient *zclient) stream_putw_at(s, 0, stream_get_endp(s)); ret = zclient_send_message(zclient); - if (ret < 0) + if (ret == ZCLIENT_SEND_FAILURE) return -1; if (zclient_debug) @@ -2967,14 +2950,17 @@ int tm_release_table_chunk(struct zclient *zclient, uint32_t start, /* Put length at the first point of the stream. */ stream_putw_at(s, 0, stream_get_endp(s)); - return zclient_send_message(zclient); + if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE) + return -1; + + return 0; } -int zebra_send_sr_policy(struct zclient *zclient, int cmd, - struct zapi_sr_policy *zp) +enum zclient_send_status zebra_send_sr_policy(struct zclient *zclient, int cmd, + struct zapi_sr_policy *zp) { if (zapi_sr_policy_encode(zclient->obuf, cmd, zp) < 0) - return -1; + return ZCLIENT_SEND_FAILURE; return zclient_send_message(zclient); } @@ -3056,11 +3042,11 @@ stream_failure: return -1; } -int zebra_send_mpls_labels(struct zclient *zclient, int cmd, - struct zapi_labels *zl) +enum zclient_send_status zebra_send_mpls_labels(struct zclient *zclient, + int cmd, struct zapi_labels *zl) { if (zapi_labels_encode(zclient->obuf, cmd, zl) < 0) - return -1; + return ZCLIENT_SEND_FAILURE; return zclient_send_message(zclient); } @@ -3221,7 +3207,8 @@ stream_failure: return -1; } -int zebra_send_pw(struct zclient *zclient, int command, struct zapi_pw *pw) +enum zclient_send_status zebra_send_pw(struct zclient *zclient, int command, + struct zapi_pw *pw) { struct stream *s; @@ -3247,7 +3234,7 @@ int zebra_send_pw(struct zclient *zclient, int command, struct zapi_pw *pw) break; default: flog_err(EC_LIB_ZAPI_ENCODE, "%s: unknown af", __func__); - return -1; + return ZCLIENT_SEND_FAILURE; } /* Put labels */ @@ -3316,7 +3303,8 @@ stream_failure: return; } -void zclient_send_mlag_register(struct zclient *client, uint32_t bit_map) +enum zclient_send_status zclient_send_mlag_register(struct zclient *client, + uint32_t bit_map) { struct stream *s; @@ -3327,15 +3315,16 @@ void zclient_send_mlag_register(struct zclient *client, uint32_t bit_map) stream_putl(s, bit_map); stream_putw_at(s, 0, stream_get_endp(s)); - zclient_send_message(client); + return zclient_send_message(client); } -void zclient_send_mlag_deregister(struct zclient *client) +enum zclient_send_status zclient_send_mlag_deregister(struct zclient *client) { - zebra_message_send(client, ZEBRA_MLAG_CLIENT_UNREGISTER, VRF_DEFAULT); + return zebra_message_send(client, ZEBRA_MLAG_CLIENT_UNREGISTER, VRF_DEFAULT); } -void zclient_send_mlag_data(struct zclient *client, struct stream *client_s) +enum zclient_send_status zclient_send_mlag_data(struct zclient *client, + struct stream *client_s) { struct stream *s; @@ -3346,7 +3335,7 @@ void zclient_send_mlag_data(struct zclient *client, struct stream *client_s) stream_put(s, client_s->data, client_s->endp); stream_putw_at(s, 0, stream_get_endp(s)); - zclient_send_message(client); + return zclient_send_message(client); } static void zclient_mlag_process_up(ZAPI_CALLBACK_ARGS) @@ -3371,17 +3360,17 @@ static void zclient_mlag_handle_msg(ZAPI_CALLBACK_ARGS) * Send an OPAQUE message, contents opaque to zebra. The message header * is a message subtype. */ -int zclient_send_opaque(struct zclient *zclient, uint32_t type, - const uint8_t *data, size_t datasize) +enum zclient_send_status zclient_send_opaque(struct zclient *zclient, + uint32_t type, const uint8_t *data, + size_t datasize) { - int ret; struct stream *s; uint16_t flags = 0; /* Check buffer size */ if (STREAM_SIZE(zclient->obuf) < (ZEBRA_HEADER_SIZE + sizeof(type) + datasize)) - return -1; + return ZCLIENT_SEND_FAILURE; s = zclient->obuf; stream_reset(s); @@ -3398,28 +3387,26 @@ int zclient_send_opaque(struct zclient *zclient, uint32_t type, /* Put length into the header at the start of the stream. */ stream_putw_at(s, 0, stream_get_endp(s)); - ret = zclient_send_message(zclient); - - return ret; + return zclient_send_message(zclient); } /* * Send an OPAQUE message to a specific zclient. The contents are opaque * to zebra. */ -int zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type, - uint8_t proto, uint16_t instance, - uint32_t session_id, const uint8_t *data, - size_t datasize) +enum zclient_send_status +zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type, + uint8_t proto, uint16_t instance, + uint32_t session_id, const uint8_t *data, + size_t datasize) { - int ret; struct stream *s; uint16_t flags = 0; /* Check buffer size */ if (STREAM_SIZE(zclient->obuf) < (ZEBRA_HEADER_SIZE + sizeof(struct zapi_opaque_msg) + datasize)) - return -1; + return ZCLIENT_SEND_FAILURE; s = zclient->obuf; stream_reset(s); @@ -3442,9 +3429,7 @@ int zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type, /* Put length into the header at the start of the stream. */ stream_putw_at(s, 0, stream_get_endp(s)); - ret = zclient_send_message(zclient); - - return ret; + return zclient_send_message(zclient); } /* @@ -3477,9 +3462,9 @@ stream_failure: /* * Send a registration request for opaque messages with a specified subtype. */ -int zclient_register_opaque(struct zclient *zclient, uint32_t type) +enum zclient_send_status zclient_register_opaque(struct zclient *zclient, + uint32_t type) { - int ret; struct stream *s; s = zclient->obuf; @@ -3498,17 +3483,15 @@ int zclient_register_opaque(struct zclient *zclient, uint32_t type) /* Put length at the first point of the stream. */ stream_putw_at(s, 0, stream_get_endp(s)); - ret = zclient_send_message(zclient); - - return ret; + return zclient_send_message(zclient); } /* * Send an un-registration request for a specified opaque subtype. */ -int zclient_unregister_opaque(struct zclient *zclient, uint32_t type) +enum zclient_send_status zclient_unregister_opaque(struct zclient *zclient, + uint32_t type) { - int ret; struct stream *s; s = zclient->obuf; @@ -3527,9 +3510,7 @@ int zclient_unregister_opaque(struct zclient *zclient, uint32_t type) /* Put length at the first point of the stream. */ stream_putw_at(s, 0, stream_get_endp(s)); - ret = zclient_send_message(zclient); - - return ret; + return zclient_send_message(zclient); } /* Utility to decode opaque registration info */ @@ -3984,9 +3965,9 @@ static void zclient_event(enum event event, struct zclient *zclient) } } -void zclient_interface_set_master(struct zclient *client, - struct interface *master, - struct interface *slave) +enum zclient_send_status zclient_interface_set_master(struct zclient *client, + struct interface *master, + struct interface *slave) { struct stream *s; @@ -4001,20 +3982,21 @@ void zclient_interface_set_master(struct zclient *client, stream_putl(s, slave->ifindex); stream_putw_at(s, 0, stream_get_endp(s)); - zclient_send_message(client); + return zclient_send_message(client); } /* * Send capabilities message to zebra */ -int32_t zclient_capabilities_send(uint32_t cmd, struct zclient *zclient, - struct zapi_cap *api) +enum zclient_send_status zclient_capabilities_send(uint32_t cmd, + struct zclient *zclient, + struct zapi_cap *api) { struct stream *s; if (zclient == NULL) - return -1; + return ZCLIENT_SEND_FAILURE; s = zclient->obuf; stream_reset(s); @@ -4073,9 +4055,10 @@ stream_failure: return 0; } -int zclient_send_neigh_discovery_req(struct zclient *zclient, - const struct interface *ifp, - const struct prefix *p) +enum zclient_send_status +zclient_send_neigh_discovery_req(struct zclient *zclient, + const struct interface *ifp, + const struct prefix *p) { struct stream *s; diff --git a/lib/zclient.h b/lib/zclient.h index 3c80ba7ef..ae94237b7 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -54,6 +54,7 @@ typedef uint16_t zebra_size_t; /* For input/output buffer to zebra. */ #define ZEBRA_MAX_PACKET_SIZ 16384U +#define ZEBRA_SMALL_PACKET_SIZE 200U /* Zebra header size. */ #define ZEBRA_HEADER_SIZE 10 @@ -320,6 +321,18 @@ struct zclient { /* Pointer to the callback functions. */ void (*zebra_connected)(struct zclient *); void (*zebra_capabilities)(struct zclient_capabilities *cap); + + /* + * When the zclient attempts to write the stream data to + * it's named pipe to/from zebra, we may have a situation + * where the other daemon has not fully drained the data + * from the socket. In this case provide a mechanism + * where we will *still* buffer the data to be sent + * and also provide a callback mechanism to the appropriate + * place where we can signal that we're ready to receive + * more data. + */ + void (*zebra_buffer_write_ready)(void); int (*router_id_update)(ZAPI_CALLBACK_ARGS); int (*interface_address_add)(ZAPI_CALLBACK_ARGS); int (*interface_address_delete)(ZAPI_CALLBACK_ARGS); @@ -663,6 +676,12 @@ enum zapi_iptable_notify_owner { ZAPI_IPTABLE_FAIL_REMOVE, }; +enum zclient_send_status { + ZCLIENT_SEND_FAILURE = -1, + ZCLIENT_SEND_SUCCESS = 0, + ZCLIENT_SEND_BUFFERED = 1 +}; + static inline const char * zapi_rule_notify_owner2str(enum zapi_rule_notify_owner note) { @@ -760,31 +779,33 @@ extern void redist_del_all_instances(struct redist_proto *red); * we have installed and play some special games * to get them both installed. */ -extern void zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id, - afi_t afi, mpls_label_t label, - enum lsp_types_t ltype); +extern enum zclient_send_status +zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id, afi_t afi, + mpls_label_t label, enum lsp_types_t ltype); extern void zclient_send_reg_requests(struct zclient *, vrf_id_t); extern void zclient_send_dereg_requests(struct zclient *, vrf_id_t); -extern int zclient_send_router_id_update(struct zclient *zclient, - zebra_message_types_t type, afi_t afi, - vrf_id_t vrf_id); - -extern void zclient_send_interface_radv_req(struct zclient *zclient, - vrf_id_t vrf_id, - struct interface *ifp, int enable, - int ra_interval); -extern int zclient_send_interface_protodown(struct zclient *zclient, - vrf_id_t vrf_id, - struct interface *ifp, bool down); +extern enum zclient_send_status +zclient_send_router_id_update(struct zclient *zclient, + zebra_message_types_t type, afi_t afi, + vrf_id_t vrf_id); + +extern enum zclient_send_status +zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id, + struct interface *ifp, int enable, + int ra_interval); +extern enum zclient_send_status +zclient_send_interface_protodown(struct zclient *zclient, vrf_id_t vrf_id, + struct interface *ifp, bool down); /* Send redistribute command to zebra daemon. Do not update zclient state. */ -extern int zebra_redistribute_send(int command, struct zclient *, afi_t, - int type, unsigned short instance, - vrf_id_t vrf_id); +extern enum zclient_send_status +zebra_redistribute_send(int command, struct zclient *, afi_t, int type, + unsigned short instance, vrf_id_t vrf_id); -extern int zebra_redistribute_default_send(int command, struct zclient *zclient, - afi_t afi, vrf_id_t vrf_id); +extern enum zclient_send_status +zebra_redistribute_default_send(int command, struct zclient *zclient, afi_t afi, + vrf_id_t vrf_id); /* Send route notify request to zebra */ extern int zebra_route_notify_send(int command, struct zclient *zclient, @@ -798,9 +819,14 @@ extern void zclient_redistribute(int command, struct zclient *, afi_t, int type, extern void zclient_redistribute_default(int command, struct zclient *, afi_t, vrf_id_t vrf_id); -/* Send the message in zclient->obuf to the zebra daemon (or enqueue it). - Returns 0 for success or -1 on an I/O error. */ -extern int zclient_send_message(struct zclient *); +/* + * Send the message in zclient->obuf to the zebra daemon (or enqueue it). + * Returns: + * -1 on a I/O error + * 0 data was successfully sent + * 1 data was buffered for future usage + */ +extern enum zclient_send_status 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); @@ -857,9 +883,9 @@ extern int zclient_read_header(struct stream *s, int sock, uint16_t *size, */ extern bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr); -extern void zclient_interface_set_master(struct zclient *client, - struct interface *master, - struct interface *slave); +extern enum zclient_send_status +zclient_interface_set_master(struct zclient *client, struct interface *master, + struct interface *slave); extern struct interface *zebra_interface_state_read(struct stream *s, vrf_id_t); extern struct connected *zebra_interface_address_read(int, struct stream *, vrf_id_t); @@ -874,8 +900,9 @@ extern struct interface *zebra_interface_link_params_read(struct stream *s, vrf_id_t vrf_id); extern size_t zebra_interface_link_params_write(struct stream *, struct interface *); -extern int zclient_send_get_label_chunk(struct zclient *zclient, uint8_t keep, - uint32_t chunk_size, uint32_t base); +extern enum zclient_send_status +zclient_send_get_label_chunk(struct zclient *zclient, uint8_t keep, + uint32_t chunk_size, uint32_t base); extern int lm_label_manager_connect(struct zclient *zclient, int async); extern int lm_get_label_chunk(struct zclient *zclient, uint8_t keep, @@ -889,29 +916,32 @@ extern int tm_get_table_chunk(struct zclient *zclient, uint32_t chunk_size, extern int tm_release_table_chunk(struct zclient *zclient, uint32_t start, uint32_t end); -extern int zebra_send_sr_policy(struct zclient *zclient, int cmd, - struct zapi_sr_policy *zp); +extern enum zclient_send_status zebra_send_sr_policy(struct zclient *zclient, + int cmd, + struct zapi_sr_policy *zp); extern int zapi_sr_policy_encode(struct stream *s, int cmd, struct zapi_sr_policy *zp); extern int zapi_sr_policy_decode(struct stream *s, struct zapi_sr_policy *zp); extern int zapi_sr_policy_notify_status_decode(struct stream *s, struct zapi_sr_policy *zp); -extern int zebra_send_mpls_labels(struct zclient *zclient, int cmd, - struct zapi_labels *zl); +extern enum zclient_send_status zebra_send_mpls_labels(struct zclient *zclient, + int cmd, + struct zapi_labels *zl); extern int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl); extern int zapi_labels_decode(struct stream *s, struct zapi_labels *zl); -extern int zebra_send_pw(struct zclient *zclient, int command, - struct zapi_pw *pw); +extern enum zclient_send_status zebra_send_pw(struct zclient *zclient, + int command, struct zapi_pw *pw); extern int zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS, struct zapi_pw_status *pw); -extern int zclient_route_send(uint8_t, struct zclient *, struct zapi_route *); -extern int zclient_send_rnh(struct zclient *zclient, int command, - const struct prefix *p, bool exact_match, - vrf_id_t vrf_id); +extern enum zclient_send_status zclient_route_send(uint8_t, struct zclient *, + struct zapi_route *); +extern enum zclient_send_status +zclient_send_rnh(struct zclient *zclient, int command, const struct prefix *p, + bool exact_match, vrf_id_t vrf_id); int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh, uint32_t api_flags, uint32_t api_message); extern int zapi_route_encode(uint8_t, struct stream *, struct zapi_route *); @@ -934,8 +964,8 @@ bool zapi_ipset_notify_decode(struct stream *s, extern int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg); extern int zapi_nhg_decode(struct stream *s, int cmd, struct zapi_nhg *api_nhg); -extern int zclient_nhg_send(struct zclient *zclient, int cmd, - struct zapi_nhg *api_nhg); +extern enum zclient_send_status +zclient_nhg_send(struct zclient *zclient, int cmd, struct zapi_nhg *api_nhg); #define ZEBRA_IPSET_NAME_SIZE 32 @@ -962,8 +992,9 @@ const char *zapi_nexthop2str(const struct zapi_nexthop *znh, char *buf, extern bool zapi_error_decode(struct stream *s, enum zebra_error_types *error); /* Encode and decode restart capabilities */ -extern int32_t zclient_capabilities_send(uint32_t cmd, struct zclient *zclient, - struct zapi_cap *api); +extern enum zclient_send_status +zclient_capabilities_send(uint32_t cmd, struct zclient *zclient, + struct zapi_cap *api); extern int32_t zapi_capabilities_decode(struct stream *s, struct zapi_cap *api); static inline void zapi_route_set_blackhole(struct zapi_route *api, @@ -976,12 +1007,13 @@ static inline void zapi_route_set_blackhole(struct zapi_route *api, SET_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP); }; -extern void zclient_send_mlag_register(struct zclient *client, - uint32_t bit_map); -extern void zclient_send_mlag_deregister(struct zclient *client); +extern enum zclient_send_status +zclient_send_mlag_register(struct zclient *client, uint32_t bit_map); +extern enum zclient_send_status +zclient_send_mlag_deregister(struct zclient *client); -extern void zclient_send_mlag_data(struct zclient *client, - struct stream *client_s); +extern enum zclient_send_status zclient_send_mlag_data(struct zclient *client, + struct stream *client_s); /* * Send an OPAQUE message, contents opaque to zebra - but note that @@ -991,13 +1023,15 @@ extern void zclient_send_mlag_data(struct zclient *client, * below to avoid sub-type collisions. Clients use the registration * apis to manage the specific opaque subtypes they want to receive. */ -int zclient_send_opaque(struct zclient *zclient, uint32_t type, - const uint8_t *data, size_t datasize); +enum zclient_send_status zclient_send_opaque(struct zclient *zclient, + uint32_t type, const uint8_t *data, + size_t datasize); -int zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type, - uint8_t proto, uint16_t instance, - uint32_t session_id, const uint8_t *data, - size_t datasize); +enum zclient_send_status +zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type, + uint8_t proto, uint16_t instance, + uint32_t session_id, const uint8_t *data, + size_t datasize); /* Struct representing the decoded opaque header info */ struct zapi_opaque_msg { @@ -1027,8 +1061,10 @@ struct zapi_opaque_reg_info { /* Decode incoming opaque */ int zclient_opaque_decode(struct stream *msg, struct zapi_opaque_msg *info); -int zclient_register_opaque(struct zclient *zclient, uint32_t type); -int zclient_unregister_opaque(struct zclient *zclient, uint32_t type); +enum zclient_send_status zclient_register_opaque(struct zclient *zclient, + uint32_t type); +enum zclient_send_status zclient_unregister_opaque(struct zclient *zclient, + uint32_t type); int zapi_opaque_reg_decode(struct stream *msg, struct zapi_opaque_reg_info *info); @@ -1054,11 +1090,12 @@ enum zapi_opaque_registry { /* Send the hello message. * Returns 0 for success or -1 on an I/O error. */ -extern int zclient_send_hello(struct zclient *client); +extern enum zclient_send_status zclient_send_hello(struct zclient *client); -extern int zclient_send_neigh_discovery_req(struct zclient *zclient, - const struct interface *ifp, - const struct prefix *p); +extern enum zclient_send_status +zclient_send_neigh_discovery_req(struct zclient *zclient, + const struct interface *ifp, + const struct prefix *p); #ifdef __cplusplus } diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 8d3ee1ad0..f21e940a7 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -362,7 +362,7 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request, else ret = zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); - if (ret < 0) + if (ret == ZCLIENT_SEND_FAILURE) flog_err(EC_LIB_ZAPI_SOCKET, "zclient_route_send() %s failed: %s", (type == REM ? "delete" : "add"), diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index d449f9d2f..e7dbdbd9a 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -1915,7 +1915,7 @@ int ospf_zebra_label_manager_connect(void) set_nonblocking(zclient_sync->sock); /* Send hello to notify zebra this is a synchronous client */ - if (zclient_send_hello(zclient_sync) < 0) { + if (zclient_send_hello(zclient_sync) == ZCLIENT_SEND_FAILURE) { zlog_warn("%s: failed sending hello for synchronous zclient!", __func__); close(zclient_sync->sock); diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index 82a2d2feb..222a10e75 100644 --- a/pbrd/pbr_zebra.c +++ b/pbrd/pbr_zebra.c @@ -476,8 +476,8 @@ void pbr_send_rnh(struct nexthop *nhop, bool reg) break; } - if (zclient_send_rnh(zclient, command, &p, - false, nhop->vrf_id) < 0) { + if (zclient_send_rnh(zclient, command, &p, false, nhop->vrf_id) + == ZCLIENT_SEND_FAILURE) { zlog_warn("%s: Failure to send nexthop to zebra", __func__); } } diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index f691e8b75..68e0a4569 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -55,7 +55,7 @@ void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient, p = &(pnc->rpf.rpf_addr); ret = zclient_send_rnh(zclient, command, p, false, pim->vrf_id); - if (ret < 0) + if (ret == ZCLIENT_SEND_FAILURE) zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); if (PIM_DEBUG_PIM_NHT) diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index dc4c621e9..05c9af873 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -61,7 +61,7 @@ static int zclient_lookup_connect(struct thread *t) zlookup->fail = 0; /* reset counter on connection */ } - if (zclient_send_hello(zlookup) < 0) { + if (zclient_send_hello(zlookup) == ZCLIENT_SEND_FAILURE) { if (close(zlookup->sock)) { zlog_warn("%s: closing fd=%d: errno=%d %s", __func__, zlookup->sock, errno, safe_strerror(errno)); diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 7a335fca3..627caea37 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -211,66 +211,217 @@ int sharp_install_lsps_helper(bool install_p, bool update_p, cmd = ZEBRA_MPLS_LABELS_DELETE; } - ret = zebra_send_mpls_labels(zclient, cmd, &zl); + if (zebra_send_mpls_labels(zclient, cmd, &zl) == ZCLIENT_SEND_FAILURE) + return -1; - return ret; + return 0; } -void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id, - uint8_t instance, uint32_t nhgid, - const struct nexthop_group *nhg, - const struct nexthop_group *backup_nhg, - uint32_t routes) +enum where_to_restart { + SHARP_INSTALL_ROUTES_RESTART, + SHARP_DELETE_ROUTES_RESTART, +}; + +struct buffer_delay { + struct prefix p; + uint32_t count; + uint32_t routes; + vrf_id_t vrf_id; + uint8_t instance; + uint32_t nhgid; + const struct nexthop_group *nhg; + const struct nexthop_group *backup_nhg; + enum where_to_restart restart; +} wb; + +/* + * route_add - Encodes a route to zebra + * + * This function returns true when the route was buffered + * by the underlying stream system + */ +static bool route_add(const struct prefix *p, vrf_id_t vrf_id, uint8_t instance, + uint32_t nhgid, const struct nexthop_group *nhg, + const struct nexthop_group *backup_nhg) +{ + struct zapi_route api; + struct zapi_nexthop *api_nh; + struct nexthop *nh; + int i = 0; + + memset(&api, 0, sizeof(api)); + api.vrf_id = vrf_id; + api.type = ZEBRA_ROUTE_SHARP; + api.instance = instance; + api.safi = SAFI_UNICAST; + memcpy(&api.prefix, p, sizeof(*p)); + + SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + + /* Only send via ID if nhgroup has been successfully installed */ + if (nhgid && sharp_nhgroup_id_is_installed(nhgid)) { + SET_FLAG(api.message, ZAPI_MESSAGE_NHG); + api.nhgid = nhgid; + } else { + for (ALL_NEXTHOPS_PTR(nhg, nh)) { + api_nh = &api.nexthops[i]; + + zapi_nexthop_from_nexthop(api_nh, nh); + + i++; + } + api.nexthop_num = i; + } + + /* Include backup nexthops, if present */ + if (backup_nhg && backup_nhg->nexthop) { + SET_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS); + + i = 0; + for (ALL_NEXTHOPS_PTR(backup_nhg, nh)) { + api_nh = &api.backup_nexthops[i]; + + zapi_backup_nexthop_from_nexthop(api_nh, nh); + + i++; + } + + api.backup_nexthop_num = i; + } + + if (zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api) + == ZCLIENT_SEND_BUFFERED) + return true; + else + return false; +} + +/* + * route_delete - Encodes a route for deletion to zebra + * + * This function returns true when the route sent was + * buffered by the underlying stream system. + */ +static bool route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance) +{ + struct zapi_route api; + + memset(&api, 0, sizeof(api)); + api.vrf_id = vrf_id; + api.type = ZEBRA_ROUTE_SHARP; + api.safi = SAFI_UNICAST; + api.instance = instance; + memcpy(&api.prefix, p, sizeof(*p)); + + if (zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api) + == ZCLIENT_SEND_BUFFERED) + return true; + else + return false; +} + +static void sharp_install_routes_restart(struct prefix *p, uint32_t count, + vrf_id_t vrf_id, uint8_t instance, + uint32_t nhgid, + const struct nexthop_group *nhg, + const struct nexthop_group *backup_nhg, + uint32_t routes) { uint32_t temp, i; bool v4 = false; - zlog_debug("Inserting %u routes", routes); - if (p->family == AF_INET) { v4 = true; temp = ntohl(p->u.prefix4.s_addr); } else temp = ntohl(p->u.val32[3]); - /* Only use backup route/nexthops if present */ - if (backup_nhg && (backup_nhg->nexthop == NULL)) - backup_nhg = NULL; - - monotime(&sg.r.t_start); - for (i = 0; i < routes; i++) { - route_add(p, vrf_id, (uint8_t)instance, nhgid, nhg, backup_nhg); + for (i = count; i < routes; i++) { + bool buffered = route_add(p, vrf_id, (uint8_t)instance, nhgid, + nhg, backup_nhg); if (v4) p->u.prefix4.s_addr = htonl(++temp); else p->u.val32[3] = htonl(++temp); + + if (buffered) { + wb.p = *p; + wb.count = i+1; + wb.routes = routes; + wb.vrf_id = vrf_id; + wb.instance = instance; + wb.nhgid = nhgid; + wb.nhg = nhg; + wb.backup_nhg = backup_nhg; + wb.restart = SHARP_INSTALL_ROUTES_RESTART; + + return; + } } } -void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id, - uint8_t instance, uint32_t routes) +void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id, + uint8_t instance, uint32_t nhgid, + const struct nexthop_group *nhg, + const struct nexthop_group *backup_nhg, + uint32_t routes) +{ + zlog_debug("Inserting %u routes", routes); + + /* Only use backup route/nexthops if present */ + if (backup_nhg && (backup_nhg->nexthop == NULL)) + backup_nhg = NULL; + + monotime(&sg.r.t_start); + sharp_install_routes_restart(p, 0, vrf_id, instance, nhgid, nhg, + backup_nhg, routes); +} + +static void sharp_remove_routes_restart(struct prefix *p, uint32_t count, + vrf_id_t vrf_id, uint8_t instance, + uint32_t routes) { uint32_t temp, i; bool v4 = false; - zlog_debug("Removing %u routes", routes); - if (p->family == AF_INET) { v4 = true; temp = ntohl(p->u.prefix4.s_addr); } else temp = ntohl(p->u.val32[3]); - monotime(&sg.r.t_start); - for (i = 0; i < routes; i++) { - route_delete(p, vrf_id, (uint8_t)instance); + for (i = count; i < routes; i++) { + bool buffered = route_delete(p, vrf_id, (uint8_t)instance); + if (v4) p->u.prefix4.s_addr = htonl(++temp); else p->u.val32[3] = htonl(++temp); + + if (buffered) { + wb.p = *p; + wb.count = i + 1; + wb.vrf_id = vrf_id; + wb.instance = instance; + wb.routes = routes; + wb.restart = SHARP_DELETE_ROUTES_RESTART; + + return; + } } } +void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id, + uint8_t instance, uint32_t routes) +{ + zlog_debug("Removing %u routes", routes); + + monotime(&sg.r.t_start); + + sharp_remove_routes_restart(p, 0, vrf_id, instance, routes); +} + static void handle_repeated(bool installed) { struct prefix p = sg.r.orig_prefix; @@ -294,6 +445,21 @@ static void handle_repeated(bool installed) } } +static void sharp_zclient_buffer_ready(void) +{ + switch (wb.restart) { + case SHARP_INSTALL_ROUTES_RESTART: + sharp_install_routes_restart(&wb.p, wb.count, wb.vrf_id, + wb.instance, wb.nhgid, wb.nhg, + wb.backup_nhg, wb.routes); + return; + case SHARP_DELETE_ROUTES_RESTART: + sharp_remove_routes_restart(&wb.p, wb.count, wb.vrf_id, + wb.instance, wb.routes); + return; + } +} + static int route_notify_owner(ZAPI_CALLBACK_ARGS) { struct timeval r; @@ -408,74 +574,6 @@ void nhg_del(uint32_t id) zclient_nhg_send(zclient, ZEBRA_NHG_DEL, &api_nhg); } -void route_add(const struct prefix *p, vrf_id_t vrf_id, uint8_t instance, - uint32_t nhgid, const struct nexthop_group *nhg, - const struct nexthop_group *backup_nhg) -{ - struct zapi_route api; - struct zapi_nexthop *api_nh; - struct nexthop *nh; - int i = 0; - - memset(&api, 0, sizeof(api)); - api.vrf_id = vrf_id; - api.type = ZEBRA_ROUTE_SHARP; - api.instance = instance; - api.safi = SAFI_UNICAST; - memcpy(&api.prefix, p, sizeof(*p)); - - SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - - /* Only send via ID if nhgroup has been successfully installed */ - if (nhgid && sharp_nhgroup_id_is_installed(nhgid)) { - SET_FLAG(api.message, ZAPI_MESSAGE_NHG); - api.nhgid = nhgid; - } else { - for (ALL_NEXTHOPS_PTR(nhg, nh)) { - api_nh = &api.nexthops[i]; - - zapi_nexthop_from_nexthop(api_nh, nh); - - i++; - } - api.nexthop_num = i; - } - - /* Include backup nexthops, if present */ - if (backup_nhg && backup_nhg->nexthop) { - SET_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS); - - i = 0; - for (ALL_NEXTHOPS_PTR(backup_nhg, nh)) { - api_nh = &api.backup_nexthops[i]; - - zapi_backup_nexthop_from_nexthop(api_nh, nh); - - i++; - } - - api.backup_nexthop_num = i; - } - - zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); -} - -void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance) -{ - struct zapi_route api; - - memset(&api, 0, sizeof(api)); - api.vrf_id = vrf_id; - api.type = ZEBRA_ROUTE_SHARP; - api.safi = SAFI_UNICAST; - api.instance = instance; - memcpy(&api.prefix, p, sizeof(*p)); - zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); - - return; -} - void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import, bool watch, bool connected) { @@ -493,7 +591,8 @@ void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import, command = ZEBRA_IMPORT_ROUTE_UNREGISTER; } - if (zclient_send_rnh(zclient, command, p, connected, vrf_id) < 0) + if (zclient_send_rnh(zclient, command, p, connected, vrf_id) + == ZCLIENT_SEND_FAILURE) zlog_warn("%s: Failure to send nexthop to zebra", __func__); } @@ -679,7 +778,7 @@ void sharp_opaque_send(uint32_t type, uint32_t proto, uint32_t instance, ret = zclient_send_opaque_unicast(zclient, type, proto, instance, session_id, buf, sizeof(buf)); - if (ret < 0) { + if (ret == ZCLIENT_SEND_FAILURE) { zlog_debug("%s: send_opaque() failed => %d", __func__, ret); break; @@ -768,7 +867,7 @@ void sharp_zebra_init(void) zclient->nexthop_update = sharp_nexthop_update; zclient->import_check_update = sharp_nexthop_update; zclient->nhg_notify_owner = nhg_notify_owner; - + zclient->zebra_buffer_write_ready = sharp_zclient_buffer_ready; zclient->redistribute_route_add = sharp_redistribute_route; zclient->redistribute_route_del = sharp_redistribute_route; zclient->opaque_msg_handler = sharp_opaque_handler; diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h index 4a767abab..8c5fa5e15 100644 --- a/sharpd/sharp_zebra.h +++ b/sharpd/sharp_zebra.h @@ -32,10 +32,6 @@ extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label); extern void nhg_add(uint32_t id, const struct nexthop_group *nhg, const struct nexthop_group *backup_nhg); extern void nhg_del(uint32_t id); -extern void route_add(const struct prefix *p, vrf_id_t, uint8_t instance, - uint32_t nhgid, const struct nexthop_group *nhg, - const struct nexthop_group *backup_nhg); -extern void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance); extern void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import, bool watch, bool connected); diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 0bccbfbea..19c578c60 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -331,7 +331,8 @@ void static_zebra_nht_register(struct route_node *rn, struct static_nexthop *nh, static_nht_hash_free(nhtd); } - if (zclient_send_rnh(zclient, cmd, &p, false, nh->nh_vrf_id) < 0) + if (zclient_send_rnh(zclient, cmd, &p, false, nh->nh_vrf_id) + == ZCLIENT_SEND_FAILURE) zlog_warn("%s: Failure to send nexthop to zebra", __func__); } /* diff --git a/vrrpd/vrrp_zebra.c b/vrrpd/vrrp_zebra.c index 37a1e4a62..385d44357 100644 --- a/vrrpd/vrrp_zebra.c +++ b/vrrpd/vrrp_zebra.c @@ -179,14 +179,13 @@ void vrrp_zebra_radv_set(struct vrrp_router *r, bool enable) enable, VRRP_RADV_INT); } -int vrrp_zclient_send_interface_protodown(struct interface *ifp, bool down) +void vrrp_zclient_send_interface_protodown(struct interface *ifp, bool down) { DEBUGD(&vrrp_dbg_zebra, VRRP_LOGPFX "Requesting Zebra to set %s protodown %s", ifp->name, down ? "on" : "off"); - return zclient_send_interface_protodown(zclient, ifp->vrf_id, ifp, - down); + zclient_send_interface_protodown(zclient, ifp->vrf_id, ifp, down); } void vrrp_zebra_init(void) diff --git a/vrrpd/vrrp_zebra.h b/vrrpd/vrrp_zebra.h index 02d7055b8..c09943dce 100644 --- a/vrrpd/vrrp_zebra.h +++ b/vrrpd/vrrp_zebra.h @@ -26,8 +26,8 @@ extern void vrrp_zebra_init(void); extern void vrrp_zebra_radv_set(struct vrrp_router *r, bool enable); -extern int vrrp_zclient_send_interface_protodown(struct interface *ifp, - bool down); +extern void vrrp_zclient_send_interface_protodown(struct interface *ifp, + bool down); extern int vrrp_ifp_create(struct interface *ifp); extern int vrrp_ifp_up(struct interface *ifp); diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 1d6801990..f7c123231 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -764,7 +764,11 @@ static int route_notify_internal(const struct prefix *p, int type, "Notifying Owner: %s about prefix %pFX(%u) %d vrf: %u", zebra_route_string(type), p, table_id, note, vrf_id); - s = stream_new(ZEBRA_MAX_PACKET_SIZ); + /* We're just allocating a small-ish buffer here, since we only + * encode a small amount of data. + */ + s = stream_new(ZEBRA_SMALL_PACKET_SIZE); + stream_reset(s); zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, vrf_id); |