diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/bfd.c | 54 | ||||
| -rw-r--r-- | lib/command.c | 3 | ||||
| -rw-r--r-- | lib/command.h | 4 | ||||
| -rw-r--r-- | lib/command_parse.y | 10 | ||||
| -rw-r--r-- | lib/ferr.c | 6 | ||||
| -rw-r--r-- | lib/lib_vty.c | 54 | ||||
| -rw-r--r-- | lib/libfrr.c | 13 | ||||
| -rw-r--r-- | lib/libfrr.h | 4 | ||||
| -rw-r--r-- | lib/log.c | 3 | ||||
| -rw-r--r-- | lib/prefix.h | 4 | ||||
| -rwxr-xr-x | lib/route_types.pl | 13 | ||||
| -rw-r--r-- | lib/route_types.txt | 64 | ||||
| -rw-r--r-- | lib/routemap.c | 29 | ||||
| -rw-r--r-- | lib/routemap.h | 13 | ||||
| -rw-r--r-- | lib/sigevent.c | 29 | ||||
| -rw-r--r-- | lib/sigevent.h | 9 | ||||
| -rw-r--r-- | lib/skiplist.c | 6 | ||||
| -rw-r--r-- | lib/subdir.am | 56 | ||||
| -rw-r--r-- | lib/thread.c | 143 | ||||
| -rw-r--r-- | lib/thread.h | 7 | ||||
| -rw-r--r-- | lib/vrf.h | 2 | ||||
| -rw-r--r-- | lib/vty.c | 7 | ||||
| -rw-r--r-- | lib/yang.c | 6 | ||||
| -rw-r--r-- | lib/yang.h | 5 | ||||
| -rw-r--r-- | lib/yang_wrappers.c | 10 | ||||
| -rw-r--r-- | lib/zclient.c | 273 | ||||
| -rw-r--r-- | lib/zclient.h | 168 | ||||
| -rw-r--r-- | lib/zebra.h | 4 |
28 files changed, 684 insertions, 315 deletions
@@ -104,7 +104,10 @@ void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx, uint32_t min_tx, if (((*bfd_info)->required_min_rx != min_rx) || ((*bfd_info)->desired_min_tx != min_tx) || ((*bfd_info)->detect_mult != detect_mult) - || (profile && strcmp((*bfd_info)->profile, profile))) + || ((*bfd_info)->profile[0] == 0 && profile) + || ((*bfd_info)->profile[0] && profile == NULL) + || (profile && (*bfd_info)->profile[0] + && strcmp((*bfd_info)->profile, profile))) *command = ZEBRA_BFD_DEST_UPDATE; } @@ -402,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) { @@ -423,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", @@ -468,6 +471,39 @@ int zclient_bfd_command(struct zclient *zc, struct bfd_session_arg *args) : sizeof(struct in6_addr); stream_put(s, &args->dst, addrlen); + /* + * For more BFD integration protocol details, see function + * `_ptm_msg_read` in `bfdd/ptm_adapter.c`. + */ +#if HAVE_BFDD > 0 + /* Session timers. */ + stream_putl(s, args->min_rx); + stream_putl(s, args->min_tx); + stream_putc(s, args->detection_multiplier); + + /* Is multi hop? */ + stream_putc(s, args->mhop != 0); + + /* Source address. */ + stream_putw(s, args->family); + stream_put(s, &args->src, addrlen); + + /* Send the expected TTL. */ + stream_putc(s, args->ttl); + + /* Send interface name if any. */ + stream_putc(s, args->ifnamelen); + if (args->ifnamelen) + stream_put(s, args->ifname, args->ifnamelen); + + /* Send the C bit indicator. */ + stream_putc(s, args->cbit); + + /* Send profile name if any. */ + stream_putc(s, args->profilelen); + if (args->profilelen) + stream_put(s, args->profile, args->profilelen); +#else /* PTM BFD */ /* Encode timers if this is a registration message. */ if (args->command != ZEBRA_BFD_DEST_DEREGISTER) { stream_putl(s, args->min_rx); @@ -500,23 +536,13 @@ int zclient_bfd_command(struct zclient *zc, struct bfd_session_arg *args) if (args->ifnamelen) stream_put(s, args->ifname, args->ifnamelen); } - - /* Send the C bit indicator. */ - stream_putc(s, args->cbit); - - /* `ptm-bfd` doesn't support profiles yet. */ -#if HAVE_BFDD > 0 - /* Send profile name if any. */ - stream_putc(s, args->profilelen); - if (args->profilelen) - stream_put(s, args->profile, args->profilelen); #endif /* HAVE_BFDD */ /* Finish the message by writing the size. */ 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/command.c b/lib/command.c index 7d335e1c36..87110157f6 100644 --- a/lib/command.c +++ b/lib/command.c @@ -154,7 +154,8 @@ static bool vty_check_node_for_xpath_decrement(enum node_type target_node, || node == BGP_IPV4M_NODE || node == BGP_IPV6M_NODE || node == BGP_VPNV4_NODE || node == BGP_VPNV6_NODE || node == BGP_EVPN_NODE || node == BGP_IPV4L_NODE - || node == BGP_IPV6L_NODE )) + || node == BGP_IPV6L_NODE || node == BGP_FLOWSPECV4_NODE + || node == BGP_FLOWSPECV6_NODE)) return false; return true; diff --git a/lib/command.h b/lib/command.h index bb007b0868..1b0504101c 100644 --- a/lib/command.h +++ b/lib/command.h @@ -530,7 +530,9 @@ extern int cmd_execute_command(vector, struct vty *, const struct cmd_element **, int); extern int cmd_execute_command_strict(vector, struct vty *, const struct cmd_element **); -extern void cmd_init(int); +extern void cmd_init(int terminal); +extern void cmd_init_config_callbacks(void (*start_config_cb)(void), + void (*end_config_cb)(void)); extern void cmd_terminate(void); extern void cmd_exit(struct vty *vty); extern int cmd_list_cmds(struct vty *vty, int do_permute); diff --git a/lib/command_parse.y b/lib/command_parse.y index 5dc19d2c9b..ba5225b702 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -492,11 +492,11 @@ terminate_graph (CMD_YYLTYPE *locp, struct parser_ctx *ctx, graph_new_node (ctx->graph, (void *)element, NULL); if (ctx->docstr && strlen (ctx->docstr) > 1) { - zlog_debug ("Excessive docstring while parsing '%s'", ctx->el->string); - zlog_debug ("----------"); + zlog_err ("Excessive docstring while parsing '%s'", ctx->el->string); + zlog_err ("----------"); while (ctx->docstr && ctx->docstr[1] != '\0') - zlog_debug ("%s", strsep(&ctx->docstr, "\n")); - zlog_debug ("----------\n"); + zlog_err ("%s", strsep(&ctx->docstr, "\n")); + zlog_err ("----------\n"); } graph_add_edge (finalnode, end_token_node); @@ -509,7 +509,7 @@ doc_next (struct parser_ctx *ctx) const char *piece = ctx->docstr ? strsep (&ctx->docstr, "\n") : ""; if (*piece == 0x03) { - zlog_debug ("Ran out of docstring while parsing '%s'", ctx->el->string); + zlog_err ("Ran out of docstring while parsing '%s'", ctx->el->string); piece = ""; } diff --git a/lib/ferr.c b/lib/ferr.c index 7b923da177..691da495cf 100644 --- a/lib/ferr.c +++ b/lib/ferr.c @@ -121,8 +121,12 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json) if (code) { ref = log_ref_get(code); - if (!ref) + if (!ref) { + if (top) + json_object_free(top); + list_delete(&errlist); return; + } listnode_add(errlist, ref); } diff --git a/lib/lib_vty.c b/lib/lib_vty.c index 9c927ca4af..0cc25f24ed 100644 --- a/lib/lib_vty.c +++ b/lib/lib_vty.c @@ -212,6 +212,57 @@ DEFUN (frr_version, return CMD_SUCCESS; } +static struct call_back { + time_t readin_time; + + void (*start_config)(void); + void (*end_config)(void); +} callback; + + +DEFUN_HIDDEN (start_config, + start_config_cmd, + "start_configuration", + "The Beginning of Configuration\n") +{ + callback.readin_time = monotime(NULL); + + if (callback.start_config) + (*callback.start_config)(); + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (end_config, + end_config_cmd, + "end_configuration", + "The End of Configuration\n") +{ + time_t readin_time; + char readin_time_str[MONOTIME_STRLEN]; + + readin_time = monotime(NULL); + readin_time -= callback.readin_time; + + frrtime_to_interval(readin_time, readin_time_str, + sizeof(readin_time_str)); + + zlog_info("Configuration Read in Took: %s", readin_time_str); + + if (callback.end_config) + (*callback.end_config)(); + + return CMD_SUCCESS; +} + +void cmd_init_config_callbacks(void (*start_config_cb)(void), + void (*end_config_cb)(void)) +{ + callback.start_config = start_config_cb; + callback.end_config = end_config_cb; +} + + static void defaults_autocomplete(vector comps, struct cmd_token *token) { const char **p; @@ -234,6 +285,9 @@ void lib_cmd_init(void) install_element(VIEW_NODE, &show_memory_cmd); install_element(VIEW_NODE, &show_modules_cmd); + + install_element(CONFIG_NODE, &start_config_cmd); + install_element(CONFIG_NODE, &end_config_cmd); } /* Stats querying from users */ diff --git a/lib/libfrr.c b/lib/libfrr.c index 800596c563..8e7777a1a9 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -99,6 +99,7 @@ static void opt_extend(const struct optspec *os) #define OPTION_TCLI 1005 #define OPTION_DB_FILE 1006 #define OPTION_LOGGING 1007 +#define OPTION_LIMIT_FDS 1008 static const struct option lo_always[] = { {"help", no_argument, NULL, 'h'}, @@ -113,6 +114,7 @@ static const struct option lo_always[] = { {"log-level", required_argument, NULL, OPTION_LOGLEVEL}, {"tcli", no_argument, NULL, OPTION_TCLI}, {"command-log-always", no_argument, NULL, OPTION_LOGGING}, + {"limit-fds", required_argument, NULL, OPTION_LIMIT_FDS}, {NULL}}; static const struct optspec os_always = { "hvdM:F:N:", @@ -126,7 +128,8 @@ static const struct optspec os_always = { " --moduledir Override modules directory\n" " --log Set Logging to stdout, syslog, or file:<name>\n" " --log-level Set Logging Level to use, debug, info, warn, etc\n" - " --tcli Use transaction-based CLI\n", + " --tcli Use transaction-based CLI\n" + " --limit-fds Limit number of fds supported\n", lo_always}; @@ -552,6 +555,9 @@ static int frr_opt(int opt) case OPTION_LOGGING: di->log_always = true; break; + case OPTION_LIMIT_FDS: + di->limit_fds = strtoul(optarg, &err, 0); + break; default: return 1; } @@ -739,6 +745,11 @@ enum frr_cli_mode frr_get_cli_mode(void) return di ? di->cli_mode : FRR_CLI_CLASSIC; } +uint32_t frr_get_fd_limit(void) +{ + return di ? di->limit_fds : 0; +} + static int rcvd_signal = 0; static void rcv_signal(int signum) diff --git a/lib/libfrr.h b/lib/libfrr.h index ab72299206..2e4dcbe093 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -102,6 +102,9 @@ struct frr_daemon_info { size_t n_yang_modules; bool log_always; + + /* Optional upper limit on the number of fds used in select/poll */ + uint32_t limit_fds; }; /* execname is the daemon's executable (and pidfile and configfile) name, @@ -134,6 +137,7 @@ extern __attribute__((__noreturn__)) void frr_help_exit(int status); extern struct thread_master *frr_init(void); extern const char *frr_get_progname(void); extern enum frr_cli_mode frr_get_cli_mode(void); +uint32_t frr_get_fd_limit(void); DECLARE_HOOK(frr_late_init, (struct thread_master * tm), (tm)) DECLARE_HOOK(frr_very_late_init, (struct thread_master * tm), (tm)) @@ -455,7 +455,8 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_NEIGH_DISCOVER), DESC_ENTRY(ZEBRA_NHG_ADD), DESC_ENTRY(ZEBRA_NHG_DEL), - DESC_ENTRY(ZEBRA_NHG_NOTIFY_OWNER)}; + DESC_ENTRY(ZEBRA_NHG_NOTIFY_OWNER), + DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_REQUEST)}; #undef DESC_ENTRY static const struct zebra_desc_table unknown = {0, "unknown", '?'}; diff --git a/lib/prefix.h b/lib/prefix.h index d2cabf3104..b7fdc26369 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -479,7 +479,7 @@ extern void apply_mask_ipv4(struct prefix_ipv4 *); #define PREFIX_COPY(DST, SRC) \ *((struct prefix *)(DST)) = *((const struct prefix *)(SRC)) #define PREFIX_COPY_IPV4(DST, SRC) \ - *((struct prefix_ipv4 *)(DST)) = *((const struct prefix_ipv4 *)(SRC)); + *((struct prefix_ipv4 *)(DST)) = *((const struct prefix_ipv4 *)(SRC)) extern int prefix_ipv4_any(const struct prefix_ipv4 *); extern void apply_classful_mask_ipv4(struct prefix_ipv4 *); @@ -499,7 +499,7 @@ extern int str2prefix_ipv6(const char *, struct prefix_ipv6 *); extern void apply_mask_ipv6(struct prefix_ipv6 *); #define PREFIX_COPY_IPV6(DST, SRC) \ - *((struct prefix_ipv6 *)(DST)) = *((const struct prefix_ipv6 *)(SRC)); + *((struct prefix_ipv6 *)(DST)) = *((const struct prefix_ipv6 *)(SRC)) extern int ip6_masklen(struct in6_addr); extern void masklen2ip6(const int, struct in6_addr *); diff --git a/lib/route_types.pl b/lib/route_types.pl index 39af8d0d56..759e9b4729 100755 --- a/lib/route_types.pl +++ b/lib/route_types.pl @@ -29,6 +29,7 @@ ## use strict; +use Getopt::Long; # input processing # @@ -37,6 +38,11 @@ my %protodetail; my %daemons; +my @enabled; + +GetOptions ("enabled=s" => \@enabled); +@enabled = split(/,/,join(',',@enabled)); + while (<STDIN>) { # skip comments and empty lines next if (/^\s*(#|$)/); @@ -56,7 +62,7 @@ while (<STDIN>) { # else: 8-field line my @f = split(/,/, $_); - unless (@f == 8 || @f == 9) { + unless (@f == 9 || @f == 10) { die "invalid input on route_types line $.\n"; } @@ -74,7 +80,8 @@ while (<STDIN>) { "ipv6" => int($f[5]), "redist" => int($f[6]), "shorthelp" => $f[7], - "restrict2" => $f[8], + "enabled" => $f[8], + "restrict2" => $f[9], }; push @protos, $proto; $daemons{$f[2]} = { @@ -109,6 +116,7 @@ sub codelist { my (@lines) = (); my $str = " \"Codes: "; for my $p (@protos) { + next unless (grep $_ eq $protodetail{$p}->{"enabled"}, @enabled); my $s = sprintf("%s - %s, ", $protodetail{$p}->{"char"}, $protodetail{$p}->{"shorthelp"}); @@ -141,6 +149,7 @@ sub collect { next if ($protodetail{$p}->{"restrict2"} ne "" && $protodetail{$p}->{"restrict2"} ne $daemon); next if ($protodetail{$p}->{"redist"} eq 0); + next unless (grep $_ eq $protodetail{$p}->{"enabled"}, @enabled); next unless (($ipv4 && $protodetail{$p}->{"ipv4"}) || ($ipv6 && $protodetail{$p}->{"ipv6"})); push @names, $protodetail{$p}->{"cname"}; diff --git a/lib/route_types.txt b/lib/route_types.txt index 37cc2fb590..c48391545d 100644 --- a/lib/route_types.txt +++ b/lib/route_types.txt @@ -45,48 +45,48 @@ # If you add a new routing protocol here, make sure you also update # meta_queue_map in zebra_rib.c # -## type cname daemon C 4 6 Redist short help Restrictions -ZEBRA_ROUTE_SYSTEM, system, NULL, 'X', 0, 0, 0, "Reserved" -ZEBRA_ROUTE_KERNEL, kernel, zebra, 'K', 1, 1, 1, "kernel route" -ZEBRA_ROUTE_CONNECT, connected, zebra, 'C', 1, 1, 1, "connected" -ZEBRA_ROUTE_STATIC, static, zebra, 'S', 1, 1, 1, "static" -ZEBRA_ROUTE_RIP, rip, ripd, 'R', 1, 0, 1, "RIP" -ZEBRA_ROUTE_RIPNG, ripng, ripngd, 'R', 0, 1, 1, "RIPng" -ZEBRA_ROUTE_OSPF, ospf, ospfd, 'O', 1, 0, 1, "OSPF" -ZEBRA_ROUTE_OSPF6, ospf6, ospf6d, 'O', 0, 1, 1, "OSPFv3" -ZEBRA_ROUTE_ISIS, isis, isisd, 'I', 1, 1, 1, "IS-IS" -ZEBRA_ROUTE_BGP, bgp, bgpd, 'B', 1, 1, 1, "BGP" -ZEBRA_ROUTE_PIM, pim, pimd, 'P', 0, 0, 0, "PIM" -ZEBRA_ROUTE_EIGRP, eigrp, eigrpd, 'E', 1, 0, 1, "EIGRP" -ZEBRA_ROUTE_NHRP, nhrp, nhrpd, 'N', 1, 1, 1, "NHRP" +## type cname daemon C 4 6 Redist short help Enabled Restrictions +ZEBRA_ROUTE_SYSTEM, system, NULL, 'X', 0, 0, 0, "Reserved", none +ZEBRA_ROUTE_KERNEL, kernel, zebra, 'K', 1, 1, 1, "kernel route", zebra +ZEBRA_ROUTE_CONNECT, connected, zebra, 'C', 1, 1, 1, "connected", zebra +ZEBRA_ROUTE_STATIC, static, zebra, 'S', 1, 1, 1, "static", zebra +ZEBRA_ROUTE_RIP, rip, ripd, 'R', 1, 0, 1, "RIP", ripd +ZEBRA_ROUTE_RIPNG, ripng, ripngd, 'R', 0, 1, 1, "RIPng", ripngd +ZEBRA_ROUTE_OSPF, ospf, ospfd, 'O', 1, 0, 1, "OSPF", ospfd +ZEBRA_ROUTE_OSPF6, ospf6, ospf6d, 'O', 0, 1, 1, "OSPFv3", ospf6d +ZEBRA_ROUTE_ISIS, isis, isisd, 'I', 1, 1, 1, "IS-IS", isisd +ZEBRA_ROUTE_BGP, bgp, bgpd, 'B', 1, 1, 1, "BGP", bgpd +ZEBRA_ROUTE_PIM, pim, pimd, 'P', 0, 0, 0, "PIM", pimd +ZEBRA_ROUTE_EIGRP, eigrp, eigrpd, 'E', 1, 0, 1, "EIGRP", eigrpd +ZEBRA_ROUTE_NHRP, nhrp, nhrpd, 'N', 1, 1, 1, "NHRP", nhrpd # HSLS and OLSR both are AFI independent (so: 1, 1), however # we want to disable for them for general Quagga distribution. # This at least makes it trivial for users of these protocols # to 'switch on' redist support (direct numeric entry remaining # possible). -ZEBRA_ROUTE_HSLS, hsls, hslsd, 'H', 0, 0, 0, "HSLS" -ZEBRA_ROUTE_OLSR, olsr, olsrd, 'o', 0, 0, 0, "OLSR" -ZEBRA_ROUTE_TABLE, table, zebra, 'T', 1, 1, 1, "Table" -ZEBRA_ROUTE_LDP, ldp, ldpd, 'L', 0, 0, 0, "LDP" +ZEBRA_ROUTE_HSLS, hsls, hslsd, 'H', 0, 0, 0, "HSLS", hslsd +ZEBRA_ROUTE_OLSR, olsr, olsrd, 'o', 0, 0, 0, "OLSR", olsrd +ZEBRA_ROUTE_TABLE, table, zebra, 'T', 1, 1, 1, "Table", zebra +ZEBRA_ROUTE_LDP, ldp, ldpd, 'L', 0, 0, 0, "LDP", ldpd #vnc when sent to zebra -ZEBRA_ROUTE_VNC, vnc, NULL, 'v', 1, 1, 1, "VNC" +ZEBRA_ROUTE_VNC, vnc, NULL, 'v', 1, 1, 1, "VNC", bgpd-vnc # vnc when sent to bgp -ZEBRA_ROUTE_VNC_DIRECT, vnc-direct,NULL, 'V', 1, 1, 1, "VNC-Direct", bgpd +ZEBRA_ROUTE_VNC_DIRECT, vnc-direct,NULL, 'V', 1, 1, 1, "VNC-Direct", bgpd-vnc, bgpd # vnc when sent to bgp (resolve NVE mode) -ZEBRA_ROUTE_VNC_DIRECT_RH, vnc-rn, NULL, 'V', 0, 0, 0, "VNC-RN" +ZEBRA_ROUTE_VNC_DIRECT_RH, vnc-rn, NULL, 'V', 0, 0, 0, "VNC-RN", bgpd-vnc # bgp unicast -> vnc -ZEBRA_ROUTE_BGP_DIRECT, bgp-direct, NULL, 'b', 0, 0, 0, "BGP-Direct" +ZEBRA_ROUTE_BGP_DIRECT, bgp-direct, NULL, 'b', 0, 0, 0, "BGP-Direct", bgpd-vnc # bgp unicast -> vnc -ZEBRA_ROUTE_BGP_DIRECT_EXT, bgp-direct-to-nve-groups, NULL, 'e', 0, 0, 0, "BGP2VNC" -ZEBRA_ROUTE_BABEL, babel, babeld, 'A', 1, 1, 1, "Babel" -ZEBRA_ROUTE_SHARP, sharp, sharpd, 'D', 1, 1, 1, "SHARP" -ZEBRA_ROUTE_PBR, pbr, pbrd, 'F', 1, 1, 0, "PBR" -ZEBRA_ROUTE_BFD, bfd, bfdd, '-', 0, 0, 0, "BFD" -ZEBRA_ROUTE_OPENFABRIC, openfabric, fabricd, 'f', 1, 1, 1, "OpenFabric" -ZEBRA_ROUTE_VRRP, vrrp, vrrpd, '-', 0, 0, 0, "VRRP" -ZEBRA_ROUTE_NHG, zebra, none, '-', 0, 0, 0, "Nexthop Group" -ZEBRA_ROUTE_SRTE, srte, none, '-', 0, 0, 0, "SR-TE" -ZEBRA_ROUTE_ALL, wildcard, none, '-', 0, 0, 0, "-" +ZEBRA_ROUTE_BGP_DIRECT_EXT, bgp-direct-to-nve-groups, NULL, 'e', 0, 0, 0, "BGP2VNC", bgpd-vnc +ZEBRA_ROUTE_BABEL, babel, babeld, 'A', 1, 1, 1, "Babel", babeld +ZEBRA_ROUTE_SHARP, sharp, sharpd, 'D', 1, 1, 1, "SHARP", sharpd +ZEBRA_ROUTE_PBR, pbr, pbrd, 'F', 1, 1, 0, "PBR", pbrd +ZEBRA_ROUTE_BFD, bfd, bfdd, '-', 0, 0, 0, "BFD", bfdd +ZEBRA_ROUTE_OPENFABRIC, openfabric, fabricd, 'f', 1, 1, 1, "OpenFabric", fabricd +ZEBRA_ROUTE_VRRP, vrrp, vrrpd, '-', 0, 0, 0, "VRRP", vrrpd +ZEBRA_ROUTE_NHG, zebra, none, '-', 0, 0, 0, "Nexthop Group", none +ZEBRA_ROUTE_SRTE, srte, none, '-', 0, 0, 0, "SR-TE", none +ZEBRA_ROUTE_ALL, wildcard, none, '-', 0, 0, 0, "-", none ## help strings diff --git a/lib/routemap.c b/lib/routemap.c index 0eb54a4794..004beb3628 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -1530,8 +1530,7 @@ enum rmap_compile_rets route_map_delete_set(struct route_map_index *index, static enum route_map_cmd_result_t route_map_apply_match(struct route_map_rule_list *match_list, - const struct prefix *prefix, route_map_object_t type, - void *object) + const struct prefix *prefix, void *object) { enum route_map_cmd_result_t ret = RMAP_NOMATCH; struct route_map_rule *match; @@ -1555,7 +1554,7 @@ route_map_apply_match(struct route_map_rule_list *match_list, * If all result in NOOP, end-result is NOOP. */ ret = (*match->cmd->func_apply)(match->value, prefix, - type, object); + object); /* * If the consolidated result of func_apply is: @@ -1647,9 +1646,10 @@ static struct list *route_map_get_index_list(struct route_node **rn, /* * This function returns the route-map index that best matches the prefix. */ -static struct route_map_index * -route_map_get_index(struct route_map *map, const struct prefix *prefix, - route_map_object_t type, void *object, uint8_t *match_ret) +static struct route_map_index *route_map_get_index(struct route_map *map, + const struct prefix *prefix, + void *object, + uint8_t *match_ret) { int ret = 0; struct list *candidate_rmap_list = NULL; @@ -1695,7 +1695,7 @@ route_map_get_index(struct route_map *map, const struct prefix *prefix, break; ret = route_map_apply_match(&index->match_list, prefix, - type, object); + object); if (ret == RMAP_MATCH) { *match_ret = ret; @@ -2369,8 +2369,7 @@ void route_map_notify_pentry_dependencies(const char *affected_name, We need to make sure our route-map processing matches the above */ route_map_result_t route_map_apply(struct route_map *map, - const struct prefix *prefix, - route_map_object_t type, void *object) + const struct prefix *prefix, void *object) { static int recursion = 0; enum route_map_cmd_result_t match_ret = RMAP_NOMATCH; @@ -2397,7 +2396,7 @@ route_map_result_t route_map_apply(struct route_map *map, if ((!map->optimization_disabled) && (map->ipv4_prefix_table || map->ipv6_prefix_table)) { - index = route_map_get_index(map, prefix, type, object, + index = route_map_get_index(map, prefix, object, (uint8_t *)&match_ret); if (index) { if (rmap_debug) @@ -2431,7 +2430,7 @@ route_map_result_t route_map_apply(struct route_map *map, index->applied++; /* Apply this index. */ match_ret = route_map_apply_match(&index->match_list, - prefix, type, object); + prefix, object); if (rmap_debug) { zlog_debug( "Route-map: %s, sequence: %d, prefix: %pFX, result: %s", @@ -2489,9 +2488,8 @@ route_map_result_t route_map_apply(struct route_map *map, * set succeeded or not. So, ignore * return code. */ - (void) (*set->cmd->func_apply)( - set->value, prefix, type, - object); + (void)(*set->cmd->func_apply)( + set->value, prefix, object); /* Call another route-map if available */ if (index->nextrm) { @@ -2504,8 +2502,7 @@ route_map_result_t route_map_apply(struct route_map *map, { recursion++; ret = route_map_apply( - nextrm, prefix, type, - object); + nextrm, prefix, object); recursion--; } diff --git a/lib/routemap.h b/lib/routemap.h index 64da4b87ef..3e208c8cb5 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -68,17 +68,6 @@ enum route_map_cmd_result_t { RMAP_ERROR }; - -typedef enum { - RMAP_RIP, - RMAP_RIPNG, - RMAP_OSPF, - RMAP_OSPF6, - RMAP_BGP, - RMAP_ZEBRA, - RMAP_ISIS, -} route_map_object_t; - typedef enum { RMAP_EXIT, RMAP_GOTO, RMAP_NEXT } route_map_end_t; typedef enum { @@ -117,7 +106,6 @@ struct route_map_rule_cmd { /* Function for value set or match. */ enum route_map_cmd_result_t (*func_apply)(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object); /* Compile argument and return result as void *. */ @@ -299,7 +287,6 @@ struct route_map *route_map_lookup_warn_noexist(struct vty *vty, const char *nam /* Apply route map to the object. */ extern route_map_result_t route_map_apply(struct route_map *map, const struct prefix *prefix, - route_map_object_t object_type, void *object); extern void route_map_add_hook(void (*func)(const char *)); diff --git a/lib/sigevent.c b/lib/sigevent.c index 04fcc814ef..8d583096f6 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -63,6 +63,33 @@ static void quagga_signal_handler(int signo) sigmaster.caught = 1; } +/* + * Check whether any signals have been received and are pending. This is done + * with the application's key signals blocked. The complete set of signals + * is returned in 'setp', so the caller can restore them when appropriate. + * If there are pending signals, returns 'true', 'false' otherwise. + */ +bool frr_sigevent_check(sigset_t *setp) +{ + sigset_t blocked; + int i; + bool ret; + + sigemptyset(setp); + sigemptyset(&blocked); + + /* Set up mask of application's signals */ + for (i = 0; i < sigmaster.sigc; i++) + sigaddset(&blocked, sigmaster.signals[i].signal); + + pthread_sigmask(SIG_BLOCK, &blocked, setp); + + /* Now that the application's signals are blocked, test. */ + ret = (sigmaster.caught != 0); + + return ret; +} + /* check if signals have been caught and run appropriate handlers */ int quagga_sigevent_process(void) { @@ -223,6 +250,8 @@ core_handler(int signo, siginfo_t *siginfo, void *context) /* dump memory stats on core */ log_memstats(stderr, "core_handler"); + + zlog_tls_buffer_fini(); abort(); } diff --git a/lib/sigevent.h b/lib/sigevent.h index a0ad88fcaa..4a39b22889 100644 --- a/lib/sigevent.h +++ b/lib/sigevent.h @@ -48,6 +48,15 @@ struct quagga_signal_t { extern void signal_init(struct thread_master *m, int sigc, struct quagga_signal_t *signals); + +/* + * Check whether any signals have been received and are pending. This is done + * with the application's key signals blocked. The complete set of signals + * is returned in 'setp', so the caller can restore them when appropriate. + * If there are pending signals, returns 'true', 'false' otherwise. + */ +bool frr_sigevent_check(sigset_t *setp); + /* check whether there are signals to handle, process any found */ extern int quagga_sigevent_process(void); diff --git a/lib/skiplist.c b/lib/skiplist.c index 2bef18f525..b79dfa6772 100644 --- a/lib/skiplist.c +++ b/lib/skiplist.c @@ -74,7 +74,6 @@ DEFINE_MTYPE_STATIC(LIB, SKIP_LIST_NODE, "Skip Node") static int randomsLeft; static int randomBits; -static struct skiplist *skiplist_last_created; /* debugging hack */ #if 1 #define CHECKLAST(sl) \ @@ -150,8 +149,6 @@ struct skiplist *skiplist_new(int flags, if (del) new->del = del; - skiplist_last_created = new; /* debug */ - return new; } @@ -586,7 +583,8 @@ void skiplist_debug(struct vty *vty, struct skiplist *l) int i; if (!l) - l = skiplist_last_created; + return; + vty_out(vty, "Skiplist %p has max level %d\n", l, l->level); for (i = l->level; i >= 0; --i) vty_out(vty, " @%d: %ld\n", i, diff --git a/lib/subdir.am b/lib/subdir.am index ed3c30799d..038282a99b 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -470,8 +470,62 @@ lib/clippy-command_parse.$(OBJEXT): lib/command_lex.h lib/lib_clippy-command_lex.$(OBJEXT): lib/command_parse.h lib/lib_clippy-command_parse.$(OBJEXT): lib/command_lex.h +rt_enabled = + +if BABELD +rt_enabled += --enabled babeld +endif +if BFDD +rt_enabled += --enabled bfdd +endif +if BGPD +rt_enabled += --enabled bgpd +if ENABLE_BGP_VNC +rt_enabled += --enabled bgpd-vnc +endif +endif +if EIGRPD +rt_enabled += --enabled eigrpd +endif +if ISISD +rt_enabled += --enabled isisd +endif +if FABRICD +rt_enabled += --enabled fabricd +endif +if LDPD +rt_enabled += --enabled ldpd +endif +if NHRPD +rt_enabled += --enabled nhrpd +endif +if OSPFD +rt_enabled += --enabled ospfd +endif +if OSPF6D +rt_enabled += --enabled ospf6d +endif +if PBRD +rt_enabled += --enabled pbrd +endif +if PIMD +rt_enabled += --enabled pimd +endif +if RIPD +rt_enabled += --enabled ripd +endif +if RIPNGD +rt_enabled += --enabled ripngd +endif +if SHARPD +rt_enabled += --enabled sharpd +endif +if ZEBRA +rt_enabled += --enabled zebra +endif + lib/route_types.h: $(top_srcdir)/lib/route_types.txt $(top_srcdir)/lib/route_types.pl - $(PERL) $(top_srcdir)/lib/route_types.pl < $(top_srcdir)/lib/route_types.txt > $@ + $(PERL) $(top_srcdir)/lib/route_types.pl $(rt_enabled) < $(top_srcdir)/lib/route_types.txt > $@ DISTCLEANFILES += lib/route_types.h if GIT_VERSION diff --git a/lib/thread.c b/lib/thread.c index 1765de9573..c886058355 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -36,6 +36,7 @@ #include "frr_pthread.h" #include "lib_errors.h" #include "libfrr_trace.h" +#include "libfrr.h" DEFINE_MTYPE_STATIC(LIB, THREAD, "Thread") DEFINE_MTYPE_STATIC(LIB, THREAD_MASTER, "Thread master") @@ -115,10 +116,9 @@ static void vty_out_cpu_thread_history(struct vty *vty, struct cpu_thread_history *a) { vty_out(vty, "%5zu %10zu.%03zu %9zu %8zu %9zu %8zu %9zu", - (size_t)a->total_active, a->cpu.total / 1000, - a->cpu.total % 1000, (size_t)a->total_calls, - (size_t)(a->cpu.total / a->total_calls), a->cpu.max, - (size_t)(a->real.total / a->total_calls), a->real.max); + a->total_active, a->cpu.total / 1000, a->cpu.total % 1000, + a->total_calls, (a->cpu.total / a->total_calls), a->cpu.max, + (a->real.total / a->total_calls), a->real.max); vty_out(vty, " %c%c%c%c%c %s\n", a->types & (1 << THREAD_READ) ? 'R' : ' ', a->types & (1 << THREAD_WRITE) ? 'W' : ' ', @@ -443,8 +443,14 @@ struct thread_master *thread_master_create(const char *name) rv->name = XSTRDUP(MTYPE_THREAD_MASTER, name); /* Initialize I/O task data structures */ - getrlimit(RLIMIT_NOFILE, &limit); - rv->fd_limit = (int)limit.rlim_cur; + + /* Use configured limit if present, ulimit otherwise. */ + rv->fd_limit = frr_get_fd_limit(); + if (rv->fd_limit == 0) { + getrlimit(RLIMIT_NOFILE, &limit); + rv->fd_limit = (int)limit.rlim_cur; + } + rv->read = XCALLOC(MTYPE_THREAD_POLL, sizeof(struct thread *) * rv->fd_limit); @@ -728,9 +734,13 @@ static void thread_free(struct thread_master *master, struct thread *thread) XFREE(MTYPE_THREAD, thread); } -static int fd_poll(struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize, - nfds_t count, const struct timeval *timer_wait) +static int fd_poll(struct thread_master *m, const struct timeval *timer_wait, + bool *eintr_p) { + sigset_t origsigs; + unsigned char trash[64]; + nfds_t count = m->handler.copycount; + /* * If timer_wait is null here, that means poll() should block * indefinitely, unless the thread_master has overridden it by setting @@ -761,15 +771,58 @@ static int fd_poll(struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize, rcu_assert_read_unlocked(); /* add poll pipe poker */ - assert(count + 1 < pfdsize); - pfds[count].fd = m->io_pipe[0]; - pfds[count].events = POLLIN; - pfds[count].revents = 0x00; + assert(count + 1 < m->handler.pfdsize); + m->handler.copy[count].fd = m->io_pipe[0]; + m->handler.copy[count].events = POLLIN; + m->handler.copy[count].revents = 0x00; + + /* We need to deal with a signal-handling race here: we + * don't want to miss a crucial signal, such as SIGTERM or SIGINT, + * that may arrive just before we enter poll(). We will block the + * key signals, then check whether any have arrived - if so, we return + * before calling poll(). If not, we'll re-enable the signals + * in the ppoll() call. + */ - num = poll(pfds, count + 1, timeout); + sigemptyset(&origsigs); + if (m->handle_signals) { + /* Main pthread that handles the app signals */ + if (frr_sigevent_check(&origsigs)) { + /* Signal to process - restore signal mask and return */ + pthread_sigmask(SIG_SETMASK, &origsigs, NULL); + num = -1; + *eintr_p = true; + goto done; + } + } else { + /* Don't make any changes for the non-main pthreads */ + pthread_sigmask(SIG_SETMASK, NULL, &origsigs); + } - unsigned char trash[64]; - if (num > 0 && pfds[count].revents != 0 && num--) +#if defined(HAVE_PPOLL) + struct timespec ts, *tsp; + + if (timeout >= 0) { + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000; + tsp = &ts; + } else + tsp = NULL; + + num = ppoll(m->handler.copy, count + 1, tsp, &origsigs); + pthread_sigmask(SIG_SETMASK, &origsigs, NULL); +#else + /* Not ideal - there is a race after we restore the signal mask */ + pthread_sigmask(SIG_SETMASK, &origsigs, NULL); + num = poll(m->handler.copy, count + 1, timeout); +#endif + +done: + + if (num < 0 && errno == EINTR) + *eintr_p = true; + + if (num > 0 && m->handler.copy[count].revents != 0 && num--) while (read(m->io_pipe[0], &trash, sizeof(trash)) > 0) ; @@ -1186,9 +1239,9 @@ void thread_cancel(struct thread **thread) master = (*thread)->master; - frrtrace(9, frr_libfrr, thread_cancel, master, thread->funcname, - thread->schedfrom, thread->schedfrom_line, NULL, thread->u.fd, - thread->u.val, thread->arg, thread->u.sands.tv_sec); + frrtrace(9, frr_libfrr, thread_cancel, master, (*thread)->funcname, + (*thread)->schedfrom, (*thread)->schedfrom_line, NULL, (*thread)->u.fd, + (*thread)->u.val, (*thread)->arg, (*thread)->u.sands.tv_sec); assert(master->owner == pthread_self()); @@ -1434,7 +1487,7 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch) struct timeval zerotime = {0, 0}; struct timeval tv; struct timeval *tw = NULL; - + bool eintr_p = false; int num = 0; do { @@ -1506,14 +1559,14 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch) pthread_mutex_unlock(&m->mtx); { - num = fd_poll(m, m->handler.copy, m->handler.pfdsize, - m->handler.copycount, tw); + eintr_p = false; + num = fd_poll(m, tw, &eintr_p); } pthread_mutex_lock(&m->mtx); /* Handle any errors received in poll() */ if (num < 0) { - if (errno == EINTR) { + if (eintr_p) { pthread_mutex_unlock(&m->mtx); /* loop around to signal handler */ continue; @@ -1703,3 +1756,49 @@ void funcname_thread_execute(struct thread_master *m, /* Give back or free thread. */ thread_add_unuse(m, thread); } + +/* Debug signal mask - if 'sigs' is NULL, use current effective mask. */ +void debug_signals(const sigset_t *sigs) +{ + int i, found; + sigset_t tmpsigs; + char buf[300]; + + /* + * We're only looking at the non-realtime signals here, so we need + * some limit value. Platform differences mean at some point we just + * need to pick a reasonable value. + */ +#if defined SIGRTMIN +# define LAST_SIGNAL SIGRTMIN +#else +# define LAST_SIGNAL 32 +#endif + + + if (sigs == NULL) { + sigemptyset(&tmpsigs); + pthread_sigmask(SIG_BLOCK, NULL, &tmpsigs); + sigs = &tmpsigs; + } + + found = 0; + buf[0] = '\0'; + + for (i = 0; i < LAST_SIGNAL; i++) { + char tmp[20]; + + if (sigismember(sigs, i) > 0) { + if (found > 0) + strlcat(buf, ",", sizeof(buf)); + snprintf(tmp, sizeof(tmp), "%d", i); + strlcat(buf, tmp, sizeof(buf)); + found++; + } + } + + if (found == 0) + snprintf(buf, sizeof(buf), "<none>"); + + zlog_debug("%s: %s", __func__, buf); +} diff --git a/lib/thread.h b/lib/thread.h index e2b7763c51..eb1b107e7b 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -115,8 +115,8 @@ struct thread { struct cpu_thread_history { int (*func)(struct thread *); - atomic_uint_fast32_t total_calls; - atomic_uint_fast32_t total_active; + atomic_size_t total_calls; + atomic_size_t total_active; struct time_stats { atomic_size_t total, max; } real; @@ -230,6 +230,9 @@ extern pthread_key_t thread_current; extern char *thread_timer_to_hhmmss(char *buf, int buf_size, struct thread *t_timer); +/* Debug signal mask */ +void debug_signals(const sigset_t *sigs); + #ifdef __cplusplus } #endif @@ -43,7 +43,7 @@ enum { IFLA_VRF_UNSPEC, IFLA_VRF_TABLE, __IFLA_VRF_MAX }; #endif #define VRF_NAMSIZ 36 -#define NS_NAMSIZ 16 +#define NS_NAMSIZ 36 /* * The command strings @@ -1810,7 +1810,12 @@ static int vty_accept(struct thread *thread) set_nonblocking(vty_sock); set_cloexec(vty_sock); - sockunion2hostprefix(&su, &p); + if (!sockunion2hostprefix(&su, &p)) { + close(vty_sock); + zlog_info("Vty unable to convert prefix from sockunion %s", + sockunion2str(&su, buf, SU_ADDRSTRLEN)); + return -1; + } /* VTY's accesslist apply. */ if (p.family == AF_INET && vty_accesslist_name) { diff --git a/lib/yang.c b/lib/yang.c index c59cb642f0..22fe938e4c 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -772,8 +772,7 @@ const struct lyd_node *yang_dnode_get_parent(const struct lyd_node *dnode, return NULL; } -/* API to check if the given node is last node in the list */ -static bool yang_is_last_list_dnode(const struct lyd_node *dnode) +bool yang_is_last_list_dnode(const struct lyd_node *dnode) { return (((dnode->next == NULL) || (dnode->next @@ -785,8 +784,7 @@ static bool yang_is_last_list_dnode(const struct lyd_node *dnode) != 0))); } -/* API to check if the given node is last node in the data tree level */ -static bool yang_is_last_level_dnode(const struct lyd_node *dnode) +bool yang_is_last_level_dnode(const struct lyd_node *dnode) { const struct lyd_node *parent; const struct lys_node_list *snode; diff --git a/lib/yang.h b/lib/yang.h index 0cd6a4a6f2..b8bf07ee7e 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -587,6 +587,11 @@ extern uint32_t yang_get_list_elements_count(const struct lyd_node *node); /* To get the immediate child of a dnode */ const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode); +/* API to check if the given node is last node in the list */ +bool yang_is_last_list_dnode(const struct lyd_node *dnode); + +/* API to check if the given node is last node in the data tree level */ +bool yang_is_last_level_dnode(const struct lyd_node *dnode); #ifdef __cplusplus } diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c index 4c658c1bfb..98f8fea0fe 100644 --- a/lib/yang_wrappers.c +++ b/lib/yang_wrappers.c @@ -1236,6 +1236,10 @@ const char *yang_afi_safi_value2identity(afi_t afi, safi_t safi) return "frr-routing:ipv4-labeled-unicast"; if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) return "frr-routing:ipv6-labeled-unicast"; + if (afi == AFI_IP && safi == SAFI_FLOWSPEC) + return "frr-routing:ipv4-flowspec"; + if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC) + return "frr-routing:ipv6-flowspec"; return NULL; } @@ -1269,6 +1273,12 @@ void yang_afi_safi_identity2value(const char *key, afi_t *afi, safi_t *safi) } else if (strmatch(key, "frr-routing:l2vpn-evpn")) { *afi = AFI_L2VPN; *safi = SAFI_EVPN; + } else if (strmatch(key, "frr-routing:ipv4-flowspec")) { + *afi = AFI_IP; + *safi = SAFI_FLOWSPEC; + } else if (strmatch(key, "frr-routing:ipv6-flowspec")) { + *afi = AFI_IP6; + *safi = SAFI_FLOWSPEC; } else { *afi = AFI_UNSPEC; *safi = SAFI_UNSPEC; diff --git a/lib/zclient.c b/lib/zclient.c index d0144279e5..053014f86d 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; @@ -1494,9 +1473,12 @@ stream_failure: bool zapi_route_notify_decode(struct stream *s, struct prefix *p, uint32_t *tableid, - enum zapi_route_notify_owner *note) + enum zapi_route_notify_owner *note, + afi_t *afi, safi_t *safi) { uint32_t t; + afi_t afi_val; + safi_t safi_val; STREAM_GET(note, s, sizeof(*note)); @@ -1504,9 +1486,16 @@ bool zapi_route_notify_decode(struct stream *s, struct prefix *p, STREAM_GETC(s, p->prefixlen); STREAM_GET(&p->u.prefix, s, prefix_blen(p)); STREAM_GETL(s, t); + STREAM_GETC(s, afi_val); + STREAM_GETC(s, safi_val); *tableid = t; + if (afi) + *afi = afi_val; + if (safi) + *safi = safi_val; + return true; stream_failure: @@ -1781,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; @@ -1799,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; @@ -1815,6 +1806,22 @@ int zebra_redistribute_default_send(int command, struct zclient *zclient, return zclient_send_message(zclient); } +/* Send route notify request to zebra */ +int zebra_route_notify_send(int command, struct zclient *zclient, bool set) +{ + struct stream *s; + + s = zclient->obuf; + stream_reset(s); + + zclient_create_header(s, command, 0); + stream_putc(s, !!set); + + stream_putw_at(s, 0, stream_get_endp(s)); + + return zclient_send_message(zclient); +} + /* Get prefix in ZServ format; family should be filled in on prefix */ static int zclient_stream_get_prefix(struct stream *s, struct prefix *p) { @@ -2575,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; @@ -2584,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); @@ -2800,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; @@ -2816,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) @@ -2941,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); } @@ -3030,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); } @@ -3195,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; @@ -3221,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 */ @@ -3290,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; @@ -3301,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; @@ -3320,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) @@ -3345,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); @@ -3372,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); @@ -3416,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); } /* @@ -3451,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; @@ -3472,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; @@ -3501,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 */ @@ -3958,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; @@ -3975,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); @@ -4047,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 80dca3fc56..ae94237b76 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 @@ -218,6 +219,7 @@ typedef enum { ZEBRA_OPAQUE_REGISTER, ZEBRA_OPAQUE_UNREGISTER, ZEBRA_NEIGH_DISCOVER, + ZEBRA_ROUTE_NOTIFY_REQUEST, } zebra_message_types_t; enum zebra_error_types { @@ -319,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); @@ -513,6 +527,13 @@ struct zapi_route { * offload situation. */ #define ZEBRA_FLAG_OFFLOADED 0x100 +/* + * This flag tells everyone that the route has + * failed offloading. + * This flag makes no sense unless you are in an asic + * offload situation. + */ +#define ZEBRA_FLAG_OFFLOAD_FAILED 0x200 /* The older XXX_MESSAGE flags live here */ uint32_t message; @@ -655,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) { @@ -752,31 +779,37 @@ 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 enum zclient_send_status +zebra_redistribute_default_send(int command, struct zclient *zclient, afi_t afi, + vrf_id_t vrf_id); -extern int 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, + bool set); /* If state has changed, update state and call zebra_redistribute_send. */ extern void zclient_redistribute(int command, struct zclient *, afi_t, int type, @@ -786,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); @@ -845,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); @@ -862,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, @@ -877,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 *); @@ -910,7 +952,8 @@ bool zapi_nhg_notify_decode(struct stream *s, uint32_t *id, enum zapi_nhg_notify_owner *note); bool zapi_route_notify_decode(struct stream *s, struct prefix *p, uint32_t *tableid, - enum zapi_route_notify_owner *note); + enum zapi_route_notify_owner *note, + afi_t *afi, safi_t *safi); bool zapi_rule_notify_decode(struct stream *s, uint32_t *seqno, uint32_t *priority, uint32_t *unique, char *ifname, enum zapi_rule_notify_owner *note); @@ -921,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 @@ -949,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, @@ -963,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 @@ -978,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 { @@ -1014,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); @@ -1041,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/lib/zebra.h b/lib/zebra.h index 14d66d6627..ded44ac636 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -359,6 +359,10 @@ typedef enum { SAFI_MAX = 8 } safi_t; +#define FOREACH_AFI_SAFI(afi, safi) \ + for (afi = AFI_IP; afi < AFI_MAX; afi++) \ + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + /* Default Administrative Distance of each protocol. */ #define ZEBRA_KERNEL_DISTANCE_DEFAULT 0 #define ZEBRA_CONNECT_DISTANCE_DEFAULT 0 |
