summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/bfd.c54
-rw-r--r--lib/command.c3
-rw-r--r--lib/command.h4
-rw-r--r--lib/command_parse.y10
-rw-r--r--lib/ferr.c6
-rw-r--r--lib/lib_vty.c54
-rw-r--r--lib/libfrr.c13
-rw-r--r--lib/libfrr.h4
-rw-r--r--lib/log.c3
-rw-r--r--lib/prefix.h4
-rwxr-xr-xlib/route_types.pl13
-rw-r--r--lib/route_types.txt64
-rw-r--r--lib/routemap.c29
-rw-r--r--lib/routemap.h13
-rw-r--r--lib/sigevent.c29
-rw-r--r--lib/sigevent.h9
-rw-r--r--lib/skiplist.c6
-rw-r--r--lib/subdir.am56
-rw-r--r--lib/thread.c143
-rw-r--r--lib/thread.h7
-rw-r--r--lib/vrf.h2
-rw-r--r--lib/vty.c7
-rw-r--r--lib/yang.c6
-rw-r--r--lib/yang.h5
-rw-r--r--lib/yang_wrappers.c10
-rw-r--r--lib/zclient.c273
-rw-r--r--lib/zclient.h168
-rw-r--r--lib/zebra.h4
28 files changed, 684 insertions, 315 deletions
diff --git a/lib/bfd.c b/lib/bfd.c
index d1a0ec671e..cdf7008601 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -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))
diff --git a/lib/log.c b/lib/log.c
index b629658f75..7b37ba7f27 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -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
diff --git a/lib/vrf.h b/lib/vrf.h
index 2d2fbe4fef..c636b9ea7e 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -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
diff --git a/lib/vty.c b/lib/vty.c
index fea4c49032..21b3d47b09 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -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