summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--babeld/.gitignore1
-rw-r--r--babeld/babel_interface.c209
-rw-r--r--babeld/babeld.c38
-rw-r--r--babeld/subdir.am4
-rw-r--r--bgpd/bgp_attr.c21
-rw-r--r--bgpd/bgp_attr.h2
-rw-r--r--bgpd/bgp_damp.c3
-rw-r--r--bgpd/bgp_evpn.c7
-rw-r--r--bgpd/bgp_route.c8
-rw-r--r--bgpd/bgp_routemap.c3
-rw-r--r--bgpd/bgp_vty.c30
-rw-r--r--eigrpd/eigrp_interface.c3
-rw-r--r--isisd/isis_nb.c60
-rw-r--r--isisd/isis_nb.h30
-rw-r--r--isisd/isis_nb_state.c222
-rw-r--r--isisd/isis_spf.c6
-rw-r--r--ldpd/logmsg.c14
-rw-r--r--lib/bfd.c95
-rw-r--r--lib/bfd.h7
-rw-r--r--lib/filter_cli.c64
-rw-r--r--lib/network.c21
-rw-r--r--lib/network.h18
-rw-r--r--ospf6d/ospf6_message.c3
-rw-r--r--ospfd/ospf_interface.c3
-rw-r--r--pimd/mtracebis_netlink.c2
-rw-r--r--staticd/static_zebra.c3
-rw-r--r--vtysh/subdir.am1
-rw-r--r--yang/frr-isisd.yang73
-rw-r--r--zebra/dplane_fpm_nl.c4
-rw-r--r--zebra/kernel_netlink.c17
-rw-r--r--zebra/kernel_socket.c8
-rw-r--r--zebra/rt.h2
-rw-r--r--zebra/rt_netlink.c2
-rw-r--r--zebra/rt_netlink.h3
-rw-r--r--zebra/zebra_dplane.c229
-rw-r--r--zebra/zebra_dplane.h25
-rw-r--r--zebra/zebra_fpm_netlink.c9
-rw-r--r--zebra/zebra_netns_id.c3
-rw-r--r--zebra/zebra_rib.c10
39 files changed, 815 insertions, 448 deletions
diff --git a/babeld/.gitignore b/babeld/.gitignore
index 71ef6786c7..abb4d9321a 100644
--- a/babeld/.gitignore
+++ b/babeld/.gitignore
@@ -5,3 +5,4 @@
!Makefile
!subdir.am
!.gitignore
+*_clippy.c
diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c
index 00fb58e576..cc50898017 100644
--- a/babeld/babel_interface.c
+++ b/babeld/babel_interface.c
@@ -42,6 +42,10 @@ THE SOFTWARE.
#include "xroute.h"
#include "babel_errors.h"
+#ifndef VTYSH_EXTRACT_PL
+#include "babeld/babel_interface_clippy.c"
+#endif
+
DEFINE_MTYPE_STATIC(BABELD, BABEL_IF, "Babel Interface");
#define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0)
@@ -307,9 +311,10 @@ babel_set_wired_internal(babel_interface_nfo *babel_ifp, int wired)
}
/* [Interface Command] Tell the interface is wire. */
-DEFUN (babel_set_wired,
+DEFPY (babel_set_wired,
babel_set_wired_cmd,
- "babel wired",
+ "[no] babel wired",
+ NO_STR
"Babel interface commands\n"
"Enable wired optimizations\n")
{
@@ -319,14 +324,15 @@ DEFUN (babel_set_wired,
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_set_wired_internal(babel_ifp, 1);
+ babel_set_wired_internal(babel_ifp, no ? 0 : 1);
return CMD_SUCCESS;
}
/* [Interface Command] Tell the interface is wireless (default). */
-DEFUN (babel_set_wireless,
+DEFPY (babel_set_wireless,
babel_set_wireless_cmd,
- "babel wireless",
+ "[no] babel wireless",
+ NO_STR
"Babel interface commands\n"
"Disable wired optimizations (assume wireless)\n")
{
@@ -336,34 +342,17 @@ DEFUN (babel_set_wireless,
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_set_wired_internal(babel_ifp, 0);
+ babel_set_wired_internal(babel_ifp, no ? 1 : 0);
return CMD_SUCCESS;
}
/* [Interface Command] Enable split horizon. */
-DEFUN (babel_split_horizon,
+DEFPY (babel_split_horizon,
babel_split_horizon_cmd,
- "babel split-horizon",
- "Babel interface commands\n"
- "Enable split horizon processing\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- babel_interface_nfo *babel_ifp;
-
- babel_ifp = babel_get_if_nfo(ifp);
-
- assert (babel_ifp != NULL);
- babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON;
- return CMD_SUCCESS;
-}
-
-/* [Interface Command] Disable split horizon (default). */
-DEFUN (no_babel_split_horizon,
- no_babel_split_horizon_cmd,
- "no babel split-horizon",
+ "[no] babel split-horizon",
NO_STR
"Babel interface commands\n"
- "Disable split horizon processing\n")
+ "Enable split horizon processing\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
@@ -371,213 +360,180 @@ DEFUN (no_babel_split_horizon,
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON;
+ if (!no)
+ SET_FLAG(babel_ifp->flags, BABEL_IF_SPLIT_HORIZON);
+ else
+ UNSET_FLAG(babel_ifp->flags, BABEL_IF_SPLIT_HORIZON);
return CMD_SUCCESS;
}
/* [Interface Command]. */
-DEFUN (babel_set_hello_interval,
+DEFPY (babel_set_hello_interval,
babel_set_hello_interval_cmd,
- "babel hello-interval (20-655340)",
+ "[no] babel hello-interval (20-655340)",
+ NO_STR
"Babel interface commands\n"
"Time between scheduled hellos\n"
"Milliseconds\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
- int interval;
-
- interval = strtoul(argv[2]->arg, NULL, 10);
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_ifp->hello_interval = interval;
+ babel_ifp->hello_interval = no ?
+ BABEL_DEFAULT_HELLO_INTERVAL : hello_interval;
return CMD_SUCCESS;
}
/* [Interface Command]. */
-DEFUN (babel_set_update_interval,
+DEFPY (babel_set_update_interval,
babel_set_update_interval_cmd,
- "babel update-interval (20-655340)",
+ "[no] babel update-interval (20-655340)",
+ NO_STR
"Babel interface commands\n"
"Time between scheduled updates\n"
"Milliseconds\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
- int interval;
-
- interval = strtoul(argv[2]->arg, NULL, 10);
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_ifp->update_interval = interval;
+ babel_ifp->update_interval = no ?
+ BABEL_DEFAULT_UPDATE_INTERVAL : update_interval;
return CMD_SUCCESS;
}
-DEFUN (babel_set_rxcost,
+DEFPY (babel_set_rxcost,
babel_set_rxcost_cmd,
- "babel rxcost (1-65534)",
+ "[no] babel rxcost (1-65534)",
+ NO_STR
"Babel interface commands\n"
"Rxcost multiplier\n"
"Units\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
- int rxcost;
-
- rxcost = strtoul(argv[2]->arg, NULL, 10);
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
+ if (no)
+ rxcost = CHECK_FLAG(babel_ifp->flags, BABEL_IF_WIRED) ?
+ BABEL_DEFAULT_RXCOST_WIRED : BABEL_DEFAULT_RXCOST_WIRELESS;
+
babel_ifp->cost = rxcost;
return CMD_SUCCESS;
}
-DEFUN (babel_set_rtt_decay,
+DEFPY (babel_set_rtt_decay,
babel_set_rtt_decay_cmd,
- "babel rtt-decay (1-256)",
+ "[no] babel rtt-decay (1-256)",
+ NO_STR
"Babel interface commands\n"
"Decay factor for exponential moving average of RTT samples\n"
"Units of 1/256\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
- int decay;
-
- decay = strtoul(argv[2]->arg, NULL, 10);
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_ifp->rtt_decay = decay;
+ babel_ifp->rtt_decay = no ? BABEL_DEFAULT_RTT_DECAY : rtt_decay;
return CMD_SUCCESS;
}
-DEFUN (babel_set_rtt_min,
+DEFPY (babel_set_rtt_min,
babel_set_rtt_min_cmd,
- "babel rtt-min (1-65535)",
+ "[no] babel rtt-min (1-65535)",
+ NO_STR
"Babel interface commands\n"
"Minimum RTT starting for increasing cost\n"
"Milliseconds\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
- int rtt;
-
- rtt = strtoul(argv[2]->arg, NULL, 10);
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
/* The value is entered in milliseconds but stored as microseconds. */
- babel_ifp->rtt_min = rtt * 1000;
+ babel_ifp->rtt_min = no ? BABEL_DEFAULT_RTT_MIN : rtt_min * 1000;
return CMD_SUCCESS;
}
-DEFUN (babel_set_rtt_max,
+DEFPY (babel_set_rtt_max,
babel_set_rtt_max_cmd,
- "babel rtt-max (1-65535)",
+ "[no] babel rtt-max (1-65535)",
+ NO_STR
"Babel interface commands\n"
"Maximum RTT\n"
"Milliseconds\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
- int rtt;
-
- rtt = strtoul(argv[2]->arg, NULL, 10);
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
/* The value is entered in milliseconds but stored as microseconds. */
- babel_ifp->rtt_max = rtt * 1000;
+ babel_ifp->rtt_max = no ? BABEL_DEFAULT_RTT_MAX : rtt_max * 1000;
return CMD_SUCCESS;
}
-DEFUN (babel_set_max_rtt_penalty,
+DEFPY (babel_set_max_rtt_penalty,
babel_set_max_rtt_penalty_cmd,
- "babel max-rtt-penalty (0-65535)",
+ "[no] babel max-rtt-penalty (0-65535)",
+ NO_STR
"Babel interface commands\n"
"Maximum additional cost due to RTT\n"
"Milliseconds\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
- int penalty;
-
- penalty = strtoul(argv[2]->arg, NULL, 10);
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_ifp->max_rtt_penalty = penalty;
+ babel_ifp->max_rtt_penalty = no ?
+ BABEL_DEFAULT_MAX_RTT_PENALTY : max_rtt_penalty;
return CMD_SUCCESS;
}
-DEFUN (babel_set_enable_timestamps,
+DEFPY (babel_set_enable_timestamps,
babel_set_enable_timestamps_cmd,
- "babel enable-timestamps",
- "Babel interface commands\n"
- "Enable timestamps\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- babel_interface_nfo *babel_ifp;
-
- babel_ifp = babel_get_if_nfo(ifp);
- assert (babel_ifp != NULL);
-
- babel_ifp->flags |= BABEL_IF_TIMESTAMPS;
- return CMD_SUCCESS;
-}
-
-DEFUN (no_babel_set_enable_timestamps,
- no_babel_set_enable_timestamps_cmd,
- "no babel enable-timestamps",
+ "[no] babel enable-timestamps",
NO_STR
"Babel interface commands\n"
- "Disable timestamps\n")
+ "Enable timestamps\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
-
- babel_ifp->flags &= ~BABEL_IF_TIMESTAMPS;
+ if (!no)
+ SET_FLAG(babel_ifp->flags, BABEL_IF_TIMESTAMPS);
+ else
+ UNSET_FLAG(babel_ifp->flags, BABEL_IF_TIMESTAMPS);
return CMD_SUCCESS;
}
-DEFUN (babel_set_channel,
+DEFPY (babel_set_channel,
babel_set_channel_cmd,
- "babel channel (1-254)",
- "Babel interface commands\n"
- "Channel number for diversity routing\n"
- "Number\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- babel_interface_nfo *babel_ifp;
- int channel;
-
- channel = strtoul(argv[2]->arg, NULL, 10);
-
- babel_ifp = babel_get_if_nfo(ifp);
- assert (babel_ifp != NULL);
-
- babel_ifp->channel = channel;
- return CMD_SUCCESS;
-}
-
-DEFUN (babel_set_channel_interfering,
- babel_set_channel_interfering_cmd,
- "babel channel interfering",
+ "[no] babel channel <(1-254)$ch|interfering$interfering|"
+ "noninterfering$noninterfering>",
+ NO_STR
"Babel interface commands\n"
"Channel number for diversity routing\n"
- "Mark channel as interfering\n")
+ "Number\n"
+ "Mark channel as interfering\n"
+ "Mark channel as noninterfering\n"
+ )
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
@@ -585,24 +541,15 @@ DEFUN (babel_set_channel_interfering,
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING;
- return CMD_SUCCESS;
-}
-
-DEFUN (babel_set_channel_noninterfering,
- babel_set_channel_noninterfering_cmd,
- "babel channel noninterfering",
- "Babel interface commands\n"
- "Channel number for diversity routing\n"
- "Mark channel as noninterfering\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- babel_interface_nfo *babel_ifp;
-
- babel_ifp = babel_get_if_nfo(ifp);
- assert (babel_ifp != NULL);
+ if (no)
+ ch = CHECK_FLAG(babel_ifp->flags, BABEL_IF_WIRED) ?
+ BABEL_IF_CHANNEL_NONINTERFERING : BABEL_IF_CHANNEL_INTERFERING;
+ else if (interfering)
+ ch = BABEL_IF_CHANNEL_INTERFERING;
+ else if (noninterfering)
+ ch = BABEL_IF_CHANNEL_NONINTERFERING;
- babel_ifp->channel = BABEL_IF_CHANNEL_NONINTERFERING;
+ babel_ifp->channel = ch;
return CMD_SUCCESS;
}
@@ -1239,7 +1186,6 @@ babel_if_init(void)
install_element(BABEL_NODE, &babel_network_cmd);
install_element(BABEL_NODE, &no_babel_network_cmd);
install_element(INTERFACE_NODE, &babel_split_horizon_cmd);
- install_element(INTERFACE_NODE, &no_babel_split_horizon_cmd);
install_element(INTERFACE_NODE, &babel_set_wired_cmd);
install_element(INTERFACE_NODE, &babel_set_wireless_cmd);
install_element(INTERFACE_NODE, &babel_set_hello_interval_cmd);
@@ -1251,9 +1197,6 @@ babel_if_init(void)
install_element(INTERFACE_NODE, &babel_set_rtt_max_cmd);
install_element(INTERFACE_NODE, &babel_set_max_rtt_penalty_cmd);
install_element(INTERFACE_NODE, &babel_set_enable_timestamps_cmd);
- install_element(INTERFACE_NODE, &no_babel_set_enable_timestamps_cmd);
- install_element(INTERFACE_NODE, &babel_set_channel_interfering_cmd);
- install_element(INTERFACE_NODE, &babel_set_channel_noninterfering_cmd);
/* "show babel ..." commands */
install_element(VIEW_NODE, &show_babel_interface_cmd);
diff --git a/babeld/babeld.c b/babeld/babeld.c
index dfdc924cbd..34e1a4318b 100644
--- a/babeld/babeld.c
+++ b/babeld/babeld.c
@@ -47,6 +47,10 @@ THE SOFTWARE.
#include "babel_zebra.h"
#include "babel_errors.h"
+#ifndef VTYSH_EXTRACT_PL
+#include "babeld/babeld_clippy.c"
+#endif
+
DEFINE_MGROUP(BABELD, "babeld");
DEFINE_MTYPE_STATIC(BABELD, BABEL, "Babel Structure");
@@ -662,50 +666,42 @@ DEFUN (no_babel_diversity,
}
/* [Babel Command] */
-DEFUN (babel_diversity_factor,
+DEFPY (babel_diversity_factor,
babel_diversity_factor_cmd,
- "babel diversity-factor (1-256)",
+ "[no] babel diversity-factor (1-256)$factor",
+ NO_STR
"Babel commands\n"
"Set the diversity factor.\n"
"Factor in units of 1/256.\n")
{
- int factor;
-
- factor = strtoul(argv[2]->arg, NULL, 10);
-
- diversity_factor = factor;
+ diversity_factor = no ? BABEL_DEFAULT_DIVERSITY_FACTOR : factor;
return CMD_SUCCESS;
}
/* [Babel Command] */
-DEFUN (babel_set_resend_delay,
+DEFPY (babel_set_resend_delay,
babel_set_resend_delay_cmd,
- "babel resend-delay (20-655340)",
+ "[no] babel resend-delay (20-655340)$delay",
+ NO_STR
"Babel commands\n"
"Time before resending a message\n"
"Milliseconds\n")
{
- int interval;
-
- interval = strtoul(argv[2]->arg, NULL, 10);
-
- resend_delay = interval;
+ resend_delay = no ? BABEL_DEFAULT_RESEND_DELAY : delay;
return CMD_SUCCESS;
}
/* [Babel Command] */
-DEFUN (babel_set_smoothing_half_life,
+DEFPY (babel_set_smoothing_half_life,
babel_set_smoothing_half_life_cmd,
- "babel smoothing-half-life (0-65534)",
+ "[no] babel smoothing-half-life (0-65534)$seconds",
+ NO_STR
"Babel commands\n"
"Smoothing half-life\n"
"Seconds (0 to disable)\n")
{
- int seconds;
-
- seconds = strtoul(argv[2]->arg, NULL, 10);
-
- change_smoothing_half_life(seconds);
+ change_smoothing_half_life(no ? BABEL_DEFAULT_SMOOTHING_HALF_LIFE
+ : seconds);
return CMD_SUCCESS;
}
diff --git a/babeld/subdir.am b/babeld/subdir.am
index 4b9037283c..d2d425218b 100644
--- a/babeld/subdir.am
+++ b/babeld/subdir.am
@@ -43,4 +43,8 @@ noinst_HEADERS += \
babeld/xroute.h \
# end
+clippy_scan += \
+ babeld/babel_interface.c \
+ babeld/babeld.c
+
babeld_babeld_LDADD = lib/libfrr.la $(LIBCAP)
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index e60c1bb8dc..392b558805 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -5097,18 +5097,29 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
void bgp_path_attribute_discard_vty(struct vty *vty, struct peer *peer,
- const char *discard_attrs)
+ const char *discard_attrs, bool set)
{
int i, num_attributes;
char **attributes;
afi_t afi;
safi_t safi;
- if (discard_attrs) {
- frrstr_split(discard_attrs, " ", &attributes, &num_attributes);
+ /* If `no` command specified without arbitrary attributes,
+ * then flush all.
+ */
+ if (!discard_attrs) {
for (i = 0; i < BGP_ATTR_MAX; i++)
peer->discard_attrs[i] = false;
+ goto discard_soft_clear;
+ }
+
+ if (discard_attrs) {
+ frrstr_split(discard_attrs, " ", &attributes, &num_attributes);
+
+ if (set)
+ for (i = 0; i < BGP_ATTR_MAX; i++)
+ peer->discard_attrs[i] = false;
for (i = 0; i < num_attributes; i++) {
uint8_t attr_num = strtoul(attributes[i], NULL, 10);
@@ -5142,10 +5153,10 @@ void bgp_path_attribute_discard_vty(struct vty *vty, struct peer *peer,
continue;
}
- peer->discard_attrs[attr_num] = true;
+ peer->discard_attrs[attr_num] = set;
}
XFREE(MTYPE_TMP, attributes);
-
+ discard_soft_clear:
/* Configuring path attributes to be discarded will trigger
* an inbound Route Refresh to ensure that the routing table
* is up to date.
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index cb0bf4a43c..33283f4bf6 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -415,7 +415,7 @@ extern void attr_show_all(struct vty *vty);
extern unsigned long int attr_count(void);
extern unsigned long int attr_unknown_count(void);
extern void bgp_path_attribute_discard_vty(struct vty *vty, struct peer *peer,
- const char *discard_attrs);
+ const char *discard_attrs, bool set);
/* Cluster list prototypes. */
extern bool cluster_loop_check(struct cluster_list *cluster,
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index 664619078a..56bbaf4194 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -327,7 +327,8 @@ void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw, afi_t afi,
XFREE(MTYPE_BGP_DAMP_INFO, bdi);
}
-static void bgp_damp_parameter_set(int hlife, int reuse, int sup, int maxsup,
+static void bgp_damp_parameter_set(time_t hlife, unsigned int reuse,
+ unsigned int sup, time_t maxsup,
struct bgp_damp_config *bdc)
{
double reuse_max_ratio;
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 286f47b2bc..c9e935668e 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -2119,10 +2119,11 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
char buf3[ESI_STR_LEN];
zlog_debug(
- "VRF %s vni %u type-2 route evp %pFX RMAC %pEA nexthop %pI4 esi %s",
+ "VRF %s vni %u type-%u route evp %pFX RMAC %pEA nexthop %pI4 esi %s",
vpn->bgp_vrf ? vrf_id_to_name(vpn->bgp_vrf->vrf_id)
- : " ",
- vpn->vni, p, &attr.rmac, &attr.mp_nexthop_global_in,
+ : "None",
+ vpn->vni, p->prefix.route_type, p, &attr.rmac,
+ &attr.mp_nexthop_global_in,
esi_to_str(esi, buf3, sizeof(buf3)));
}
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 59d8544953..3f07e53bb6 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2273,8 +2273,12 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
&& peer->shared_network
&& (from == bgp->peer_self
|| peer->sort == BGP_PEER_EBGP))) {
- attr->mp_nexthop_len =
- BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
+ if (safi == SAFI_MPLS_VPN)
+ attr->mp_nexthop_len =
+ BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL;
+ else
+ attr->mp_nexthop_len =
+ BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
}
/* Clear off link-local nexthop in source, whenever it is not
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 1ce2eb4352..d00bdd2571 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -3585,7 +3585,8 @@ route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object)
path->attr->mp_nexthop_local = *address;
/* Set nexthop length. */
- if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
+ if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL &&
+ path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
SET_FLAG(path->attr->rmap_change_flags,
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 5772900ce4..5738d9ef68 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -8787,7 +8787,34 @@ DEFPY(neighbor_path_attribute_discard,
if (idx)
discard_attrs = argv_concat(argv, argc, idx);
- bgp_path_attribute_discard_vty(vty, peer, discard_attrs);
+ bgp_path_attribute_discard_vty(vty, peer, discard_attrs, true);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(no_neighbor_path_attribute_discard,
+ no_neighbor_path_attribute_discard_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor path-attribute discard [(1-255)]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Manipulate path attributes from incoming UPDATE messages\n"
+ "Drop specified attributes from incoming UPDATE messages\n"
+ "Attribute number\n")
+{
+ struct peer *peer;
+ int idx = 0;
+ const char *discard_attrs = NULL;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ argv_find(argv, argc, "(1-255)", &idx);
+ if (idx)
+ discard_attrs = argv[idx]->arg;
+
+ bgp_path_attribute_discard_vty(vty, peer, discard_attrs, false);
return CMD_SUCCESS;
}
@@ -19541,6 +19568,7 @@ void bgp_vty_init(void)
/* "neighbor path-attribute discard" commands. */
install_element(BGP_NODE, &neighbor_path_attribute_discard_cmd);
+ install_element(BGP_NODE, &no_neighbor_path_attribute_discard_cmd);
/* "neighbor passive" commands. */
install_element(BGP_NODE, &neighbor_passive_cmd);
diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c
index 28987b4af6..891d282307 100644
--- a/eigrpd/eigrp_interface.c
+++ b/eigrpd/eigrp_interface.c
@@ -37,6 +37,7 @@
#include "if.h"
#include "table.h"
#include "memory.h"
+#include "network.h"
#include "command.h"
#include "stream.h"
#include "log.h"
@@ -83,7 +84,7 @@ struct eigrp_interface *eigrp_if_new(struct eigrp *eigrp, struct interface *ifp,
/* Initialize neighbor list. */
ei->nbrs = list_new();
- ei->crypt_seqnum = time(NULL);
+ ei->crypt_seqnum = frr_sequence32_next();
/* Initialize lists */
for (i = 0; i < EIGRP_FILTER_MAX; i++) {
diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c
index 4f4e6dc730..c5653d0348 100644
--- a/isisd/isis_nb.c
+++ b/isisd/isis_nb.c
@@ -1107,6 +1107,66 @@ const struct frr_yang_module_info frr_isisd_info = {
}
},
{
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid",
+ .cbs = {
+ .get_next = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_get_next,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/af",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_af_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/value",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_value_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/weight",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_weight_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/protection-requested",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_protection_requested_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid",
+ .cbs = {
+ .get_next = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_get_next,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/af",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_af_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/value",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_value_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/weight",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_weight_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/protection-requested",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_protection_requested_get_elem,
+ }
+ },
+ {
.xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-changes",
.cbs = {
.get_elem = lib_interface_state_isis_event_counters_adjacency_changes_get_elem,
diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h
index a9f2eaea95..380ce4f251 100644
--- a/isisd/isis_nb.h
+++ b/isisd/isis_nb.h
@@ -369,6 +369,36 @@ lib_interface_state_isis_adjacencies_adjacency_neighbor_priority_get_elem(
struct nb_cb_get_elem_args *args);
struct yang_data *lib_interface_state_isis_adjacencies_adjacency_state_get_elem(
struct nb_cb_get_elem_args *args);
+const void *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_get_next(
+ struct nb_cb_get_next_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_af_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_value_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_weight_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_protection_requested_get_elem(
+ struct nb_cb_get_elem_args *args);
+const void *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_get_next(
+ struct nb_cb_get_next_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_af_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_value_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_weight_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_protection_requested_get_elem(
+ struct nb_cb_get_elem_args *args);
struct yang_data *
lib_interface_state_isis_event_counters_adjacency_changes_get_elem(
struct nb_cb_get_elem_args *args);
diff --git a/isisd/isis_nb_state.c b/isisd/isis_nb_state.c
index 4e325ed8da..5b1fc6e1d2 100644
--- a/isisd/isis_nb_state.c
+++ b/isisd/isis_nb_state.c
@@ -216,6 +216,228 @@ struct yang_data *lib_interface_state_isis_adjacencies_adjacency_state_get_elem(
/*
* XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid
+ */
+const void *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_get_next(
+ struct nb_cb_get_next_args *args)
+{
+ const struct isis_adjacency *adj = args->parent_list_entry;
+ const struct sr_adjacency *sra = args->list_entry, *sra_next = NULL;
+ struct listnode *node, *node_next;
+
+ if (args->list_entry == NULL)
+ sra_next = listnode_head(adj->adj_sids);
+ else {
+ node = listnode_lookup(adj->adj_sids, sra);
+ node_next = listnextnode(node);
+ if (node_next)
+ sra_next = listgetdata(node_next);
+ }
+
+ return sra_next;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/af
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_af_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ /* Adjacency SID is not published with circuit type Broadcast */
+ return NULL;
+ case CIRCUIT_T_P2P:
+ return yang_data_new_uint8(args->xpath, sra->u.adj_sid->family);
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/value
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_value_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ /* Adjacency SID is not published with circuit type Broadcast */
+ return NULL;
+ case CIRCUIT_T_P2P:
+ return yang_data_new_uint32(args->xpath, sra->u.adj_sid->sid);
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/weight
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_weight_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ /* Adjacency SID is not published with circuit type Broadcast */
+ return NULL;
+ case CIRCUIT_T_P2P:
+ return yang_data_new_uint8(args->xpath, sra->u.adj_sid->weight);
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/protection-requested
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_protection_requested_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ /* Adjacency SID is not published with circuit type Broadcast */
+ return NULL;
+ case CIRCUIT_T_P2P:
+ return yang_data_new_bool(args->xpath,
+ sra->u.adj_sid->flags &
+ EXT_SUBTLV_LINK_ADJ_SID_BFLG);
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid
+ */
+const void *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_get_next(
+ struct nb_cb_get_next_args *args)
+{
+ const struct isis_adjacency *adj = args->parent_list_entry;
+ const struct sr_adjacency *sra = args->list_entry, *sra_next = NULL;
+ struct listnode *node, *node_next;
+
+ if (args->list_entry == NULL)
+ sra_next = listnode_head(adj->adj_sids);
+ else {
+ node = listnode_lookup(adj->adj_sids, sra);
+ node_next = listnextnode(node);
+ if (node_next)
+ sra_next = listgetdata(node_next);
+ }
+
+ return sra_next;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/af
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_af_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ return yang_data_new_uint8(args->xpath,
+ sra->u.ladj_sid->family);
+ case CIRCUIT_T_P2P:
+ /* LAN adjacency SID is not published with circuit type P2P */
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/value
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_value_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ return yang_data_new_uint32(args->xpath, sra->u.ladj_sid->sid);
+ case CIRCUIT_T_P2P:
+ /* LAN adjacency SID is not published with circuit type P2P */
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/weight
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_weight_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ return yang_data_new_uint8(args->xpath,
+ sra->u.ladj_sid->weight);
+ case CIRCUIT_T_P2P:
+ /* LAN adjacency SID is not published with circuit type P2P */
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/protection-requested
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_protection_requested_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ return yang_data_new_bool(args->xpath,
+ sra->u.ladj_sid->flags &
+ EXT_SUBTLV_LINK_ADJ_SID_BFLG);
+ case CIRCUIT_T_P2P:
+ /* LAN adjacency SID is not published with circuit type P2P */
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
* /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-changes
*/
struct yang_data *
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 89e751b4e6..a6eef75e7e 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -2714,12 +2714,14 @@ void isis_spf_init(void)
void isis_spf_print(struct isis_spftree *spftree, struct vty *vty)
{
+ uint64_t last_run_duration = spftree->last_run_duration;
+
vty_out(vty, " last run elapsed : ");
vty_out_timestr(vty, spftree->last_run_timestamp);
vty_out(vty, "\n");
- vty_out(vty, " last run duration : %u usec\n",
- (uint32_t)spftree->last_run_duration);
+ vty_out(vty, " last run duration : %" PRIu64 " usec\n",
+ last_run_duration);
vty_out(vty, " run count : %u\n", spftree->runcount);
}
diff --git a/ldpd/logmsg.c b/ldpd/logmsg.c
index ff9294f9d2..e16006b892 100644
--- a/ldpd/logmsg.c
+++ b/ldpd/logmsg.c
@@ -137,7 +137,7 @@ log_time(time_t t)
char *buf;
static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */
static int idx = 0;
- unsigned int sec, min, hrs, day, week;
+ uint64_t sec, min, hrs, day, week;
buf = tfbuf[idx++];
if (idx == TF_BUFS)
@@ -155,11 +155,17 @@ log_time(time_t t)
week /= 7;
if (week > 0)
- snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs);
+ snprintfrr(buf, TF_LEN,
+ "%02" PRIu64 "w%01" PRIu64 "d%02" PRIu64 "h", week,
+ day, hrs);
else if (day > 0)
- snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
+ snprintfrr(buf, TF_LEN,
+ "%01" PRIu64 "d%02" PRIu64 "h%02" PRIu64 "m", day,
+ hrs, min);
else
- snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
+ snprintfrr(buf, TF_LEN,
+ "%02" PRIu64 ":%02" PRIu64 ":%02" PRIu64, hrs, min,
+ sec);
return (buf);
}
diff --git a/lib/bfd.c b/lib/bfd.c
index ae402ec5cb..9078e3559f 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -129,8 +129,6 @@ struct bfd_sessions_global {
struct thread_master *tm;
/** Pointer to zebra client data structure. */
struct zclient *zc;
- /** Zebra next hop tracking (NHT) client. */
- struct zclient *nht_zclient;
/** Debugging state. */
bool debugging;
@@ -147,31 +145,10 @@ static const struct in6_addr i6a_zero;
/*
* Prototypes
*/
-static void bfd_nht_zclient_connect(struct thread *thread);
-
-static void bfd_nht_zclient_connected(struct zclient *zclient);
-static int bfd_nht_update(ZAPI_CALLBACK_ARGS);
static void bfd_source_cache_get(struct bfd_session_params *session);
static void bfd_source_cache_put(struct bfd_session_params *session);
-static inline void
-bfd_source_cache_register(const struct bfd_source_cache *source)
-{
- zclient_send_rnh(bsglobal.nht_zclient, ZEBRA_NEXTHOP_REGISTER,
- &source->address, SAFI_UNICAST, false, false,
- source->vrf_id);
-}
-
-static inline void
-bfd_source_cache_unregister(const struct bfd_source_cache *source)
-{
- zclient_send_rnh(bsglobal.nht_zclient, ZEBRA_NEXTHOP_UNREGISTER,
- &source->address, SAFI_UNICAST, false, false,
- source->vrf_id);
-}
-
-
/*
* bfd_get_peer_info - Extract the Peer information for which the BFD session
* went down from the message sent from Zebra to clients.
@@ -1074,20 +1051,11 @@ static int bfd_protocol_integration_finish(void)
if (!SLIST_EMPTY(&bsglobal.source_list))
zlog_warn("BFD integration source cache not empty");
- zclient_stop(bsglobal.nht_zclient);
- zclient_free(bsglobal.nht_zclient);
-
return 0;
}
-static zclient_handler *const bfd_nht_handlers[] = {
- [ZEBRA_NEXTHOP_UPDATE] = bfd_nht_update,
-};
-
void bfd_protocol_integration_init(struct zclient *zc, struct thread_master *tm)
{
- struct zclient_options bfd_nht_options = zclient_options_default;
-
/* Initialize data structure. */
TAILQ_INIT(&bsglobal.bsplist);
SLIST_INIT(&bsglobal.source_list);
@@ -1102,16 +1070,6 @@ void bfd_protocol_integration_init(struct zclient *zc, struct thread_master *tm)
/* Send the client registration */
bfd_client_sendmsg(zc, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
- /* Start NHT client (for automatic source decisions). */
- bsglobal.nht_zclient =
- zclient_new(tm, &bfd_nht_options, bfd_nht_handlers,
- array_size(bfd_nht_handlers));
- bsglobal.nht_zclient->sock = -1;
- bsglobal.nht_zclient->privs = zc->privs;
- bsglobal.nht_zclient->zebra_connected = bfd_nht_zclient_connected;
- thread_add_timer(tm, bfd_nht_zclient_connect, bsglobal.nht_zclient, 1,
- &bsglobal.nht_zclient->t_connect);
-
hook_register(frr_fini, bfd_protocol_integration_finish);
}
@@ -1252,8 +1210,6 @@ static void bfd_source_cache_get(struct bfd_session_params *session)
session->source_cache = source;
source->refcount = 1;
- bfd_source_cache_register(source);
-
return;
}
@@ -1268,7 +1224,6 @@ static void bfd_source_cache_put(struct bfd_session_params *session)
return;
}
- bfd_source_cache_unregister(session->source_cache);
SLIST_REMOVE(&bsglobal.source_list, session->source_cache,
bfd_source_cache, entry);
XFREE(MTYPE_BFD_SOURCE, session->source_cache);
@@ -1378,59 +1333,19 @@ static bool bfd_source_cache_update(struct bfd_source_cache *source,
return false;
}
-static void bfd_nht_zclient_connect(struct thread *thread)
-{
- struct zclient *zclient = THREAD_ARG(thread);
-
- if (bsglobal.debugging)
- zlog_debug("BFD NHT zclient connection attempt");
-
- if (zclient_start(zclient) == -1) {
- if (bsglobal.debugging)
- zlog_debug("BFD NHT zclient connection failed");
-
- thread_add_timer(bsglobal.tm, bfd_nht_zclient_connect, zclient,
- 3, &zclient->t_connect);
- return;
- }
-
- if (bsglobal.debugging)
- zlog_debug("BFD NHT zclient connection succeeded");
-}
-
-static void bfd_nht_zclient_connected(struct zclient *zclient)
-{
- struct bfd_source_cache *source;
-
- if (bsglobal.debugging)
- zlog_debug("BFD NHT zclient connected");
-
- SLIST_FOREACH (source, &bsglobal.source_list, entry)
- bfd_source_cache_register(source);
-}
-
-static int bfd_nht_update(ZAPI_CALLBACK_ARGS)
+int bfd_nht_update(const struct prefix *match, const struct zapi_route *route)
{
struct bfd_source_cache *source;
- struct zapi_route route;
- struct prefix match;
-
- if (!zapi_nexthop_update_decode(zclient->ibuf, &match, &route)) {
- zlog_warn("BFD NHT update decode failure");
- return 0;
- }
- if (cmd != ZEBRA_NEXTHOP_UPDATE)
- return 0;
if (bsglobal.debugging)
- zlog_debug("BFD NHT update for %pFX", &route.prefix);
+ zlog_debug("BFD NHT update for %pFX", &route->prefix);
SLIST_FOREACH (source, &bsglobal.source_list, entry) {
- if (source->vrf_id != route.vrf_id)
+ if (source->vrf_id != route->vrf_id)
continue;
- if (!prefix_same(&match, &source->address))
+ if (!prefix_same(match, &source->address))
continue;
- if (bfd_source_cache_update(source, &route))
+ if (bfd_source_cache_update(source, route))
bfd_source_cache_update_sessions(source);
}
diff --git a/lib/bfd.h b/lib/bfd.h
index b7e4eea5f3..51e831785a 100644
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -473,6 +473,13 @@ extern bool bfd_protocol_integration_debug(void);
*/
extern bool bfd_protocol_integration_shutting_down(void);
+/* Update nexthop-tracking (nht) information for BFD auto source selection.
+ * The function must be called from the daemon callback function
+ * that deals with the ZEBRA_NEXTHOP_UPDATE zclient command
+ */
+extern int bfd_nht_update(const struct prefix *match,
+ const struct zapi_route *route);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/filter_cli.c b/lib/filter_cli.c
index e0f0f177e5..296c05b9f4 100644
--- a/lib/filter_cli.c
+++ b/lib/filter_cli.c
@@ -66,16 +66,21 @@ static int acl_get_seq_cb(const struct lyd_node *dnode, void *arg)
*
* \param[in] vty shell context with the candidate configuration.
* \param[in] xpath the XPath to look for the sequence leaf.
- * \returns next unused sequence number.
+ * \returns next unused sequence number, -1 if out of range when adding.
*/
-static long acl_get_seq(struct vty *vty, const char *xpath)
+static int64_t acl_get_seq(struct vty *vty, const char *xpath, bool is_remove)
{
int64_t seq = 0;
yang_dnode_iterate(acl_get_seq_cb, &seq, vty->candidate_config->dnode,
"%s/entry", xpath);
- return seq + 5;
+ seq += 5;
+ if (!is_remove && seq > UINT32_MAX) {
+ vty_out(vty, "%% Malformed sequence value\n");
+ return -1;
+ }
+ return seq;
}
static int acl_remove_if_empty(struct vty *vty, const char *iptype,
@@ -98,7 +103,7 @@ static int acl_remove_if_empty(struct vty *vty, const char *iptype,
* NOTE: if the list is empty it will return the first sequence
* number: 5.
*/
- if (acl_get_seq(vty, xpath) != 5)
+ if (acl_get_seq(vty, xpath, true) != 5)
return CMD_SUCCESS;
/* Nobody is using this list, lets remove it. */
@@ -174,16 +179,19 @@ DEFPY_YANG(
*/
snprintf(xpath, sizeof(xpath),
"/frr-filter:lib/access-list[type='ipv4'][name='%s']", name);
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
- sseq = acl_get_seq(vty, xpath);
+ sseq = acl_get_seq(vty, xpath, false);
+ if (sseq < 0)
+ return CMD_WARNING_CONFIG_FAILED;
+
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%" PRId64 "']", xpath, sseq);
} else
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%s']", xpath, seq_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action);
@@ -321,16 +329,19 @@ DEFPY_YANG(
*/
snprintf(xpath, sizeof(xpath),
"/frr-filter:lib/access-list[type='ipv4'][name='%s']", name);
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
- sseq = acl_get_seq(vty, xpath);
+ sseq = acl_get_seq(vty, xpath, false);
+ if (sseq < 0)
+ return CMD_WARNING_CONFIG_FAILED;
+
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%" PRId64 "']", xpath, sseq);
} else
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%s']", xpath, seq_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action);
@@ -483,16 +494,19 @@ DEFPY_YANG(
*/
snprintf(xpath, sizeof(xpath),
"/frr-filter:lib/access-list[type='ipv4'][name='%s']", name);
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
- sseq = acl_get_seq(vty, xpath);
+ sseq = acl_get_seq(vty, xpath, false);
+ if (sseq < 0)
+ return CMD_WARNING_CONFIG_FAILED;
+
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%" PRId64 "']", xpath, sseq);
} else
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%s']", xpath, seq_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action);
@@ -670,16 +684,19 @@ DEFPY_YANG(
*/
snprintf(xpath, sizeof(xpath),
"/frr-filter:lib/access-list[type='ipv6'][name='%s']", name);
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
- sseq = acl_get_seq(vty, xpath);
+ sseq = acl_get_seq(vty, xpath, false);
+ if (sseq < 0)
+ return CMD_WARNING_CONFIG_FAILED;
+
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%" PRId64 "']", xpath, sseq);
} else
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%s']", xpath, seq_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action);
@@ -857,16 +874,19 @@ DEFPY_YANG(
*/
snprintf(xpath, sizeof(xpath),
"/frr-filter:lib/access-list[type='mac'][name='%s']", name);
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
- sseq = acl_get_seq(vty, xpath);
+ sseq = acl_get_seq(vty, xpath, false);
+ if (sseq < 0)
+ return CMD_WARNING_CONFIG_FAILED;
+
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%" PRId64 "']", xpath, sseq);
} else
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%s']", xpath, seq_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action);
@@ -1167,7 +1187,7 @@ static int plist_remove_if_empty(struct vty *vty, const char *iptype,
* NOTE: if the list is empty it will return the first sequence
* number: 5.
*/
- if (acl_get_seq(vty, xpath) != 5)
+ if (acl_get_seq(vty, xpath, true) != 5)
return CMD_SUCCESS;
/* Nobody is using this list, lets remove it. */
@@ -1275,16 +1295,19 @@ DEFPY_YANG(
*/
snprintf(xpath, sizeof(xpath),
"/frr-filter:lib/prefix-list[type='ipv4'][name='%s']", name);
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
- sseq = acl_get_seq(vty, xpath);
+ sseq = acl_get_seq(vty, xpath, false);
+ if (sseq < 0)
+ return CMD_WARNING_CONFIG_FAILED;
+
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%" PRId64 "']", xpath, sseq);
} else
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%s']", xpath, seq_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action);
@@ -1476,16 +1499,19 @@ DEFPY_YANG(
*/
snprintf(xpath, sizeof(xpath),
"/frr-filter:lib/prefix-list[type='ipv6'][name='%s']", name);
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
- sseq = acl_get_seq(vty, xpath);
+ sseq = acl_get_seq(vty, xpath, false);
+ if (sseq < 0)
+ return CMD_WARNING_CONFIG_FAILED;
+
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%" PRId64 "']", xpath, sseq);
} else
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%s']", xpath, seq_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action);
diff --git a/lib/network.c b/lib/network.c
index b60ad9a57c..cd62b8b593 100644
--- a/lib/network.c
+++ b/lib/network.c
@@ -122,3 +122,24 @@ float ntohf(float net)
{
return htonf(net);
}
+
+uint64_t frr_sequence_next(void)
+{
+ static uint64_t last_sequence;
+ struct timespec ts;
+
+ (void)clock_gettime(CLOCK_MONOTONIC, &ts);
+ if (last_sequence == (uint64_t)ts.tv_sec) {
+ last_sequence++;
+ return last_sequence;
+ }
+
+ last_sequence = ts.tv_sec;
+ return last_sequence;
+}
+
+uint32_t frr_sequence32_next(void)
+{
+ /* coverity[Y2K38_SAFETY] */
+ return (uint32_t)frr_sequence_next();
+}
diff --git a/lib/network.h b/lib/network.h
index 10ed917572..c163eab8f7 100644
--- a/lib/network.h
+++ b/lib/network.h
@@ -82,6 +82,24 @@ extern float ntohf(float);
#endif
/**
+ * Generate a sequence number using monotonic clock with a same second call
+ * protection to help guarantee a unique incremental sequence number that never
+ * goes back (except when wrapping/overflow).
+ *
+ * **NOTE** this function is not thread safe since it uses `static` variable.
+ *
+ * This function and `frr_sequence32_next` should be used to initialize
+ * sequence numbers without directly calling other `time_t` returning
+ * functions because of `time_t` truncation warnings.
+ *
+ * \returns `uint64_t` number based on the monotonic clock.
+ */
+extern uint64_t frr_sequence_next(void);
+
+/** Same as `frr_sequence_next` but returns truncated number. */
+extern uint32_t frr_sequence32_next(void);
+
+/**
* Helper function that returns a random long value. The main purpose of
* this function is to hide a `random()` call that gets flagged by coverity
* scan and put it into one place.
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index fb54ebab15..3d29a65d1b 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -28,6 +28,7 @@
#include "linklist.h"
#include "lib_errors.h"
#include "checksum.h"
+#include "network.h"
#include "ospf6_proto.h"
#include "ospf6_lsa.h"
@@ -2300,7 +2301,7 @@ static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor *on, struct stream *s)
/* if this is initial one, initialize sequence number for DbDesc */
if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)
&& (on->dbdesc_seqnum == 0)) {
- on->dbdesc_seqnum = monotime(NULL);
+ on->dbdesc_seqnum = frr_sequence32_next();
}
/* reserved */
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index a0b14e73ee..831906b908 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -30,6 +30,7 @@
#include "command.h"
#include "stream.h"
#include "log.h"
+#include "network.h"
#include "zclient.h"
#include "bfd.h"
#include "ldp_sync.h"
@@ -274,7 +275,7 @@ struct ospf_interface *ospf_if_new(struct ospf *ospf, struct interface *ifp,
oi->t_ls_upd_event = NULL;
oi->t_ls_ack_direct = NULL;
- oi->crypt_seqnum = time(NULL);
+ oi->crypt_seqnum = frr_sequence32_next();
ospf_opaque_type9_lsa_init(oi);
diff --git a/pimd/mtracebis_netlink.c b/pimd/mtracebis_netlink.c
index 81e28f2407..9bdf949007 100644
--- a/pimd/mtracebis_netlink.c
+++ b/pimd/mtracebis_netlink.c
@@ -92,7 +92,7 @@ int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions,
rth->local.nl_family);
return -1;
}
- rth->seq = (uint32_t)time(NULL);
+ rth->seq = getpid();
return 0;
}
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index 316247adb3..85e4b1c033 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -211,6 +211,9 @@ static int static_zebra_nexthop_update(ZAPI_CALLBACK_ARGS)
return 1;
}
+ if (zclient->bfd_integration)
+ bfd_nht_update(&matched, &nhr);
+
if (matched.family == AF_INET6)
afi = AFI_IP6;
diff --git a/vtysh/subdir.am b/vtysh/subdir.am
index cc2a70ade6..72204201d9 100644
--- a/vtysh/subdir.am
+++ b/vtysh/subdir.am
@@ -37,4 +37,5 @@ $(vtysh_vtysh_OBJECTS): vtysh/vtysh_daemons.h
CLEANFILES += vtysh/vtysh_daemons.h
vtysh/vtysh_daemons.h:
+ mkdir -p vtysh
$(PERL) $(top_srcdir)/vtysh/daemons.pl $(vtysh_daemons) > vtysh/vtysh_daemons.h
diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang
index 380fce3859..5483410d04 100644
--- a/yang/frr-isisd.yang
+++ b/yang/frr-isisd.yang
@@ -881,6 +881,9 @@ module frr-isisd {
description
"This leaf describes the state of the interface.";
}
+
+ uses adjacency-sids;
+ uses lan-adjacency-sids;
}
}
}
@@ -1004,6 +1007,76 @@ module frr-isisd {
}
}
+ grouping adjacency-sids {
+ description
+ "IS-IS segment routing adjacency SID grouping.";
+ container adjacency-sids {
+ description
+ "This container lists the information of adjacency SID.";
+ list adjacency-sid {
+ leaf af {
+ type uint8;
+ description
+ "This leaf describes the protocol-family associated with the
+ adjacency SID.";
+ }
+
+ leaf value {
+ type uint32;
+ description
+ "This leaf describes the value of adjacency SID.";
+ }
+
+ leaf weight {
+ type uint8;
+ description
+ "This leaf describes the weight of the adjacency SID.";
+ }
+
+ leaf protection-requested {
+ type boolean;
+ description
+ "This leaf describes if the adjacency SID must be protected.";
+ }
+ }
+ }
+ }
+
+ grouping lan-adjacency-sids {
+ description
+ "IS-IS segment routing LAN adjacency SID grouping.";
+ container lan-adjacency-sids {
+ description
+ "This container lists the information of LAN adjacency SID.";
+ list lan-adjacency-sid {
+ leaf af {
+ type uint8;
+ description
+ "This leaf describes the protocol-family associated with the
+ LAN adjacency SID.";
+ }
+
+ leaf value {
+ type uint32;
+ description
+ "This leaf describes the value of LAN adjacency SID.";
+ }
+
+ leaf weight {
+ type uint8;
+ description
+ "This leaf describes the weight of the LAN adjacency SID.";
+ }
+
+ leaf protection-requested {
+ type boolean;
+ description
+ "This leaf describes if the LAN adjacency SID must be protected.";
+ }
+ }
+ }
+ }
+
container isis {
description
"Configuration of the IS-IS routing daemon.";
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index af75ddf742..0a9fecc9df 100644
--- a/zebra/dplane_fpm_nl.c
+++ b/zebra/dplane_fpm_nl.c
@@ -89,7 +89,7 @@ struct fpm_nl_ctx {
* When a FPM server connection becomes a bottleneck, we must keep the
* data plane contexts until we get a chance to process them.
*/
- struct dplane_ctx_q ctxqueue;
+ struct dplane_ctx_list_head ctxqueue;
pthread_mutex_t ctxqueue_mutex;
/* data plane events. */
@@ -1473,7 +1473,7 @@ static int fpm_nl_start(struct zebra_dplane_provider *prov)
fnc->socket = -1;
fnc->disabled = true;
fnc->prov = prov;
- TAILQ_INIT(&fnc->ctxqueue);
+ dplane_ctx_q_init(&fnc->ctxqueue);
pthread_mutex_init(&fnc->ctxqueue_mutex, NULL);
/* Set default values. */
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 54d9561e2b..42afe61469 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -202,13 +202,13 @@ struct nl_batch {
const struct zebra_dplane_info *zns;
- struct dplane_ctx_q ctx_list;
+ struct dplane_ctx_list_head ctx_list;
/*
* Pointer to the queue of completed contexts outbound back
* towards the dataplane module.
*/
- struct dplane_ctx_q *ctx_out_q;
+ struct dplane_ctx_list_head *ctx_out_q;
};
int netlink_config_write_helper(struct vty *vty)
@@ -1446,10 +1446,11 @@ static void nl_batch_reset(struct nl_batch *bth)
bth->msgcnt = 0;
bth->zns = NULL;
- TAILQ_INIT(&(bth->ctx_list));
+ dplane_ctx_q_init(&(bth->ctx_list));
}
-static void nl_batch_init(struct nl_batch *bth, struct dplane_ctx_q *ctx_out_q)
+static void nl_batch_init(struct nl_batch *bth,
+ struct dplane_ctx_list_head *ctx_out_q)
{
/*
* If the size of the buffer has changed, free and then allocate a new
@@ -1665,14 +1666,14 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
return FRR_NETLINK_ERROR;
}
-void kernel_update_multi(struct dplane_ctx_q *ctx_list)
+void kernel_update_multi(struct dplane_ctx_list_head *ctx_list)
{
struct nl_batch batch;
struct zebra_dplane_ctx *ctx;
- struct dplane_ctx_q handled_list;
+ struct dplane_ctx_list_head handled_list;
enum netlink_msg_status res;
- TAILQ_INIT(&handled_list);
+ dplane_ctx_q_init(&handled_list);
nl_batch_init(&batch, &handled_list);
while (true) {
@@ -1703,7 +1704,7 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list)
nl_batch_send(&batch);
- TAILQ_INIT(ctx_list);
+ dplane_ctx_q_init(ctx_list);
dplane_ctx_list_append(ctx_list, &handled_list);
}
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index f84d31cc44..684ccc3ed5 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -1516,13 +1516,13 @@ int kernel_dplane_read(struct zebra_dplane_info *info)
return 0;
}
-void kernel_update_multi(struct dplane_ctx_q *ctx_list)
+void kernel_update_multi(struct dplane_ctx_list_head *ctx_list)
{
struct zebra_dplane_ctx *ctx;
- struct dplane_ctx_q handled_list;
+ struct dplane_ctx_list_head handled_list;
enum zebra_dplane_result res = ZEBRA_DPLANE_REQUEST_SUCCESS;
- TAILQ_INIT(&handled_list);
+ dplane_ctx_q_init(&handled_list);
while (true) {
ctx = dplane_ctx_dequeue(ctx_list);
@@ -1642,7 +1642,7 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list)
dplane_ctx_enqueue_tail(&handled_list, ctx);
}
- TAILQ_INIT(ctx_list);
+ dplane_ctx_q_init(ctx_list);
dplane_ctx_list_append(ctx_list, &handled_list);
}
diff --git a/zebra/rt.h b/zebra/rt.h
index 4cf4c9d780..6f4dd48a54 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -121,7 +121,7 @@ extern int kernel_del_mac_nhg(uint32_t nhg_id);
/*
* Message batching interface.
*/
-extern void kernel_update_multi(struct dplane_ctx_q *ctx_list);
+extern void kernel_update_multi(struct dplane_ctx_list_head *ctx_list);
/*
* Called by the dplane pthread to read incoming OS messages and dispatch them.
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 1a090c78e3..79d79d74be 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -223,7 +223,7 @@ static inline bool is_selfroute(int proto)
return false;
}
-static inline int zebra2proto(int proto)
+int zebra2proto(int proto)
{
switch (proto) {
case ZEBRA_ROUTE_BABEL:
diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h
index 351f98a2ca..8506367ae4 100644
--- a/zebra/rt_netlink.h
+++ b/zebra/rt_netlink.h
@@ -150,6 +150,9 @@ const char *ifa_flags2str(uint32_t flags, char *buf, size_t buflen);
const char *nh_flags2str(uint32_t flags, char *buf, size_t buflen);
void nl_dump(void *msg, size_t msglen);
+
+extern int zebra2proto(int proto);
+
#endif /* NETLINK_DEBUG */
#ifdef __cplusplus
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 739f6adce9..7db8fba95b 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -26,7 +26,6 @@
#include "lib/frratomic.h"
#include "lib/frr_pthread.h"
#include "lib/memory.h"
-#include "lib/queue.h"
#include "lib/zebra.h"
#include "zebra/netconf_netlink.h"
#include "zebra/zebra_router.h"
@@ -103,7 +102,7 @@ struct dplane_intf_extra {
uint32_t flags;
uint32_t status;
- TAILQ_ENTRY(dplane_intf_extra) link;
+ struct dplane_intf_extra_list_item dlink;
};
/*
@@ -152,7 +151,7 @@ struct dplane_route_info {
struct nexthop_group old_backup_ng;
/* Optional list of extra interface info */
- TAILQ_HEAD(dp_intf_extra_q, dplane_intf_extra) intf_extra_q;
+ struct dplane_intf_extra_list_head intf_extra_list;
};
/*
@@ -415,7 +414,7 @@ struct zebra_dplane_ctx {
struct zebra_dplane_info zd_ns_info;
/* Embedded list linkage */
- TAILQ_ENTRY(zebra_dplane_ctx) zd_q_entries;
+ struct dplane_ctx_list_item zd_entries;
};
/* Flag that can be set by a pre-kernel provider as a signal that an update
@@ -423,6 +422,12 @@ struct zebra_dplane_ctx {
*/
#define DPLANE_CTX_FLAG_NO_KERNEL 0x01
+/* List types declared now that the structs involved are defined. */
+DECLARE_DLIST(dplane_ctx_list, struct zebra_dplane_ctx, zd_entries);
+DECLARE_DLIST(dplane_intf_extra_list, struct dplane_intf_extra, dlink);
+
+/* List for dplane plugins/providers */
+PREDECL_DLIST(dplane_prov_list);
/*
* Registration block for one dataplane provider.
@@ -461,17 +466,20 @@ struct zebra_dplane_provider {
_Atomic uint32_t dp_error_counter;
/* Queue of contexts inbound to the provider */
- struct dplane_ctx_q dp_ctx_in_q;
+ struct dplane_ctx_list_head dp_ctx_in_list;
/* Queue of completed contexts outbound from the provider back
* towards the dataplane module.
*/
- struct dplane_ctx_q dp_ctx_out_q;
+ struct dplane_ctx_list_head dp_ctx_out_list;
/* Embedded list linkage for provider objects */
- TAILQ_ENTRY(zebra_dplane_provider) dp_prov_link;
+ struct dplane_prov_list_item dp_link;
};
+/* Declare list of providers/plugins */
+DECLARE_DLIST(dplane_prov_list, struct zebra_dplane_provider, dp_link);
+
/* Declare types for list of zns info objects */
PREDECL_DLIST(zns_info_list);
@@ -496,7 +504,7 @@ static struct zebra_dplane_globals {
pthread_mutex_t dg_mutex;
/* Results callback registered by zebra 'core' */
- int (*dg_results_cb)(struct dplane_ctx_q *ctxlist);
+ int (*dg_results_cb)(struct dplane_ctx_list_head *ctxlist);
/* Sentinel for beginning of shutdown */
volatile bool dg_is_shutdown;
@@ -505,10 +513,10 @@ static struct zebra_dplane_globals {
volatile bool dg_run;
/* Update context queue inbound to the dataplane */
- TAILQ_HEAD(zdg_ctx_q, zebra_dplane_ctx) dg_update_ctx_q;
+ struct dplane_ctx_list_head dg_update_list;
/* Ordered list of providers */
- TAILQ_HEAD(zdg_prov_q, zebra_dplane_provider) dg_providers_q;
+ struct dplane_prov_list_head dg_providers;
/* List of info about each zns */
struct zns_info_list_head dg_zns_list;
@@ -668,7 +676,7 @@ void dplane_enable_sys_route_notifs(void)
*/
static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
{
- struct dplane_intf_extra *if_extra, *if_tmp;
+ struct dplane_intf_extra *if_extra;
/*
* Some internal allocations may need to be freed, depending on
@@ -713,12 +721,9 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
}
/* Optional extra interface info */
- TAILQ_FOREACH_SAFE(if_extra, &ctx->u.rinfo.intf_extra_q,
- link, if_tmp) {
- TAILQ_REMOVE(&ctx->u.rinfo.intf_extra_q, if_extra,
- link);
+ while ((if_extra = dplane_intf_extra_list_pop(
+ &ctx->u.rinfo.intf_extra_list)))
XFREE(MTYPE_DP_INTF, if_extra);
- }
break;
@@ -885,39 +890,40 @@ void dplane_ctx_fini(struct zebra_dplane_ctx **pctx)
dplane_ctx_free(pctx);
}
+/* Init a list of contexts */
+void dplane_ctx_q_init(struct dplane_ctx_list_head *q)
+{
+ dplane_ctx_list_init(q);
+}
+
/* Enqueue a context block */
-void dplane_ctx_enqueue_tail(struct dplane_ctx_q *q,
+void dplane_ctx_enqueue_tail(struct dplane_ctx_list_head *list,
const struct zebra_dplane_ctx *ctx)
{
- TAILQ_INSERT_TAIL(q, (struct zebra_dplane_ctx *)ctx, zd_q_entries);
+ dplane_ctx_list_add_tail(list, (struct zebra_dplane_ctx *)ctx);
}
/* Append a list of context blocks to another list */
-void dplane_ctx_list_append(struct dplane_ctx_q *to_list,
- struct dplane_ctx_q *from_list)
+void dplane_ctx_list_append(struct dplane_ctx_list_head *to_list,
+ struct dplane_ctx_list_head *from_list)
{
- if (TAILQ_FIRST(from_list)) {
- TAILQ_CONCAT(to_list, from_list, zd_q_entries);
+ struct zebra_dplane_ctx *ctx;
- /* And clear 'from' list */
- TAILQ_INIT(from_list);
- }
+ while ((ctx = dplane_ctx_list_pop(from_list)) != NULL)
+ dplane_ctx_list_add_tail(to_list, ctx);
}
-struct zebra_dplane_ctx *dplane_ctx_get_head(struct dplane_ctx_q *q)
+struct zebra_dplane_ctx *dplane_ctx_get_head(struct dplane_ctx_list_head *q)
{
- struct zebra_dplane_ctx *ctx = TAILQ_FIRST(q);
+ struct zebra_dplane_ctx *ctx = dplane_ctx_list_first(q);
return ctx;
}
/* Dequeue a context block from the head of a list */
-struct zebra_dplane_ctx *dplane_ctx_dequeue(struct dplane_ctx_q *q)
+struct zebra_dplane_ctx *dplane_ctx_dequeue(struct dplane_ctx_list_head *q)
{
- struct zebra_dplane_ctx *ctx = TAILQ_FIRST(q);
-
- if (ctx)
- TAILQ_REMOVE(q, ctx, zd_q_entries);
+ struct zebra_dplane_ctx *ctx = dplane_ctx_list_pop(q);
return ctx;
}
@@ -2597,14 +2603,16 @@ void dplane_ctx_rule_set_dp_flow_ptr(struct zebra_dplane_ctx *ctx,
const struct dplane_intf_extra *
dplane_ctx_get_intf_extra(const struct zebra_dplane_ctx *ctx)
{
- return TAILQ_FIRST(&ctx->u.rinfo.intf_extra_q);
+ return dplane_intf_extra_list_const_first(
+ &ctx->u.rinfo.intf_extra_list);
}
const struct dplane_intf_extra *
dplane_ctx_intf_extra_next(const struct zebra_dplane_ctx *ctx,
const struct dplane_intf_extra *ptr)
{
- return TAILQ_NEXT(ptr, link);
+ return dplane_intf_extra_list_const_next(&ctx->u.rinfo.intf_extra_list,
+ ptr);
}
vrf_id_t dplane_intf_extra_get_vrfid(const struct dplane_intf_extra *ptr)
@@ -2793,7 +2801,7 @@ int dplane_ctx_route_init_basic(struct zebra_dplane_ctx *ctx,
if (!ctx || !re)
return ret;
- TAILQ_INIT(&ctx->u.rinfo.intf_extra_q);
+ dplane_intf_extra_list_init(&ctx->u.rinfo.intf_extra_list);
ctx->zd_op = op;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
@@ -2896,8 +2904,9 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
if_extra->flags = ifp->flags;
if_extra->status = ifp->status;
- TAILQ_INSERT_TAIL(&ctx->u.rinfo.intf_extra_q,
- if_extra, link);
+ dplane_intf_extra_list_add_tail(
+ &ctx->u.rinfo.intf_extra_list,
+ if_extra);
}
}
@@ -3622,8 +3631,7 @@ static int dplane_update_enqueue(struct zebra_dplane_ctx *ctx)
/* Enqueue for processing by the dataplane pthread */
DPLANE_LOCK();
{
- TAILQ_INSERT_TAIL(&zdplane_info.dg_update_ctx_q, ctx,
- zd_q_entries);
+ dplane_ctx_list_add_tail(&zdplane_info.dg_update_list, ctx);
}
DPLANE_UNLOCK();
@@ -5520,7 +5528,7 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed)
vty_out(vty, "Zebra dataplane providers:\n");
DPLANE_LOCK();
- prov = TAILQ_FIRST(&zdplane_info.dg_providers_q);
+ prov = dplane_prov_list_first(&zdplane_info.dg_providers);
DPLANE_UNLOCK();
/* Show counters, useful info from each registered provider */
@@ -5544,7 +5552,7 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed)
out, out_q, out_max);
DPLANE_LOCK();
- prov = TAILQ_NEXT(prov, dp_prov_link);
+ prov = dplane_prov_list_next(&zdplane_info.dg_providers, prov);
DPLANE_UNLOCK();
}
@@ -5595,8 +5603,8 @@ int dplane_provider_register(const char *name,
p = XCALLOC(MTYPE_DP_PROV, sizeof(struct zebra_dplane_provider));
pthread_mutex_init(&(p->dp_mutex), NULL);
- TAILQ_INIT(&(p->dp_ctx_in_q));
- TAILQ_INIT(&(p->dp_ctx_out_q));
+ dplane_ctx_list_init(&p->dp_ctx_in_list);
+ dplane_ctx_list_init(&p->dp_ctx_out_list);
p->dp_flags = flags;
p->dp_priority = prio;
@@ -5617,16 +5625,15 @@ int dplane_provider_register(const char *name,
"provider-%u", p->dp_id);
/* Insert into list ordered by priority */
- TAILQ_FOREACH(last, &zdplane_info.dg_providers_q, dp_prov_link) {
+ frr_each (dplane_prov_list, &zdplane_info.dg_providers, last) {
if (last->dp_priority > p->dp_priority)
break;
}
if (last)
- TAILQ_INSERT_BEFORE(last, p, dp_prov_link);
+ dplane_prov_list_add_after(&zdplane_info.dg_providers, last, p);
else
- TAILQ_INSERT_TAIL(&zdplane_info.dg_providers_q, p,
- dp_prov_link);
+ dplane_prov_list_add_tail(&zdplane_info.dg_providers, p);
/* And unlock */
DPLANE_UNLOCK();
@@ -5688,10 +5695,8 @@ struct zebra_dplane_ctx *dplane_provider_dequeue_in_ctx(
dplane_provider_lock(prov);
- ctx = TAILQ_FIRST(&(prov->dp_ctx_in_q));
+ ctx = dplane_ctx_list_pop(&(prov->dp_ctx_in_list));
if (ctx) {
- TAILQ_REMOVE(&(prov->dp_ctx_in_q), ctx, zd_q_entries);
-
atomic_fetch_sub_explicit(&prov->dp_in_queued, 1,
memory_order_relaxed);
}
@@ -5705,7 +5710,7 @@ struct zebra_dplane_ctx *dplane_provider_dequeue_in_ctx(
* Dequeue work to a list, return count
*/
int dplane_provider_dequeue_in_list(struct zebra_dplane_provider *prov,
- struct dplane_ctx_q *listp)
+ struct dplane_ctx_list_head *listp)
{
int limit, ret;
struct zebra_dplane_ctx *ctx;
@@ -5715,14 +5720,11 @@ int dplane_provider_dequeue_in_list(struct zebra_dplane_provider *prov,
dplane_provider_lock(prov);
for (ret = 0; ret < limit; ret++) {
- ctx = TAILQ_FIRST(&(prov->dp_ctx_in_q));
- if (ctx) {
- TAILQ_REMOVE(&(prov->dp_ctx_in_q), ctx, zd_q_entries);
-
- TAILQ_INSERT_TAIL(listp, ctx, zd_q_entries);
- } else {
+ ctx = dplane_ctx_list_pop(&(prov->dp_ctx_in_list));
+ if (ctx)
+ dplane_ctx_list_add_tail(listp, ctx);
+ else
break;
- }
}
if (ret > 0)
@@ -5750,8 +5752,7 @@ void dplane_provider_enqueue_out_ctx(struct zebra_dplane_provider *prov,
dplane_provider_lock(prov);
- TAILQ_INSERT_TAIL(&(prov->dp_ctx_out_q), ctx,
- zd_q_entries);
+ dplane_ctx_list_add_tail(&(prov->dp_ctx_out_list), ctx);
/* Maintain out-queue counters */
atomic_fetch_add_explicit(&(prov->dp_out_queued), 1,
@@ -5921,12 +5922,12 @@ int dplane_provider_work_ready(void)
*/
void dplane_provider_enqueue_to_zebra(struct zebra_dplane_ctx *ctx)
{
- struct dplane_ctx_q temp_list;
+ struct dplane_ctx_list_head temp_list;
/* Zebra's api takes a list, so we need to use a temporary list */
- TAILQ_INIT(&temp_list);
+ dplane_ctx_list_init(&temp_list);
- TAILQ_INSERT_TAIL(&temp_list, ctx, zd_q_entries);
+ dplane_ctx_list_add_tail(&temp_list, ctx);
(zdplane_info.dg_results_cb)(&temp_list);
}
@@ -6321,11 +6322,11 @@ void dplane_rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
*/
static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
{
- struct zebra_dplane_ctx *ctx, *tctx;
- struct dplane_ctx_q work_list;
+ struct zebra_dplane_ctx *ctx;
+ struct dplane_ctx_list_head work_list;
int counter, limit;
- TAILQ_INIT(&work_list);
+ dplane_ctx_list_init(&work_list);
limit = dplane_provider_get_work_limit(prov);
@@ -6351,15 +6352,14 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
== DPLANE_OP_IPSET_ENTRY_DELETE))
kernel_dplane_process_ipset_entry(prov, ctx);
else
- TAILQ_INSERT_TAIL(&work_list, ctx, zd_q_entries);
+ dplane_ctx_list_add_tail(&work_list, ctx);
}
kernel_update_multi(&work_list);
- TAILQ_FOREACH_SAFE (ctx, &work_list, zd_q_entries, tctx) {
+ while ((ctx = dplane_ctx_list_pop(&work_list)) != NULL) {
kernel_dplane_handle_result(ctx);
- TAILQ_REMOVE(&work_list, ctx, zd_q_entries);
dplane_provider_enqueue_out_ctx(prov, ctx);
}
@@ -6486,10 +6486,10 @@ static void dplane_provider_init(void)
int dplane_clean_ctx_queue(bool (*context_cb)(struct zebra_dplane_ctx *ctx,
void *arg), void *val)
{
- struct zebra_dplane_ctx *ctx, *temp;
- struct dplane_ctx_q work_list;
+ struct zebra_dplane_ctx *ctx;
+ struct dplane_ctx_list_head work_list;
- TAILQ_INIT(&work_list);
+ dplane_ctx_list_init(&work_list);
if (context_cb == NULL)
return AOK;
@@ -6497,12 +6497,10 @@ int dplane_clean_ctx_queue(bool (*context_cb)(struct zebra_dplane_ctx *ctx,
/* Walk the pending context queue under the dplane lock. */
DPLANE_LOCK();
- TAILQ_FOREACH_SAFE(ctx, &zdplane_info.dg_update_ctx_q, zd_q_entries,
- temp) {
+ frr_each_safe (dplane_ctx_list, &zdplane_info.dg_update_list, ctx) {
if (context_cb(ctx, val)) {
- TAILQ_REMOVE(&zdplane_info.dg_update_ctx_q, ctx,
- zd_q_entries);
- TAILQ_INSERT_TAIL(&work_list, ctx, zd_q_entries);
+ dplane_ctx_list_del(&zdplane_info.dg_update_list, ctx);
+ dplane_ctx_list_add_tail(&work_list, ctx);
}
}
@@ -6511,10 +6509,8 @@ int dplane_clean_ctx_queue(bool (*context_cb)(struct zebra_dplane_ctx *ctx,
/* Now free any contexts selected by the caller, without holding
* the lock.
*/
- TAILQ_FOREACH_SAFE(ctx, &work_list, zd_q_entries, temp) {
- TAILQ_REMOVE(&work_list, ctx, zd_q_entries);
+ while ((ctx = dplane_ctx_list_pop(&work_list)) != NULL)
dplane_ctx_fini(&ctx);
- }
return AOK;
}
@@ -6552,7 +6548,7 @@ void zebra_dplane_pre_finish(void)
zdplane_info.dg_is_shutdown = true;
/* Notify provider(s) of pending shutdown. */
- TAILQ_FOREACH(prov, &zdplane_info.dg_providers_q, dp_prov_link) {
+ frr_each (dplane_prov_list, &zdplane_info.dg_providers, prov) {
if (prov->dp_fini == NULL)
continue;
@@ -6575,8 +6571,8 @@ static bool dplane_work_pending(void)
*/
DPLANE_LOCK();
{
- ctx = TAILQ_FIRST(&zdplane_info.dg_update_ctx_q);
- prov = TAILQ_FIRST(&zdplane_info.dg_providers_q);
+ ctx = dplane_ctx_list_first(&zdplane_info.dg_update_list);
+ prov = dplane_prov_list_first(&zdplane_info.dg_providers);
}
DPLANE_UNLOCK();
@@ -6587,9 +6583,9 @@ static bool dplane_work_pending(void)
dplane_provider_lock(prov);
- ctx = TAILQ_FIRST(&(prov->dp_ctx_in_q));
+ ctx = dplane_ctx_list_first(&(prov->dp_ctx_in_list));
if (ctx == NULL)
- ctx = TAILQ_FIRST(&(prov->dp_ctx_out_q));
+ ctx = dplane_ctx_list_first(&(prov->dp_ctx_out_list));
dplane_provider_unlock(prov);
@@ -6597,7 +6593,7 @@ static bool dplane_work_pending(void)
break;
DPLANE_LOCK();
- prov = TAILQ_NEXT(prov, dp_prov_link);
+ prov = dplane_prov_list_next(&zdplane_info.dg_providers, prov);
DPLANE_UNLOCK();
}
@@ -6683,10 +6679,10 @@ void zebra_dplane_finish(void)
*/
static void dplane_thread_loop(struct thread *event)
{
- struct dplane_ctx_q work_list;
- struct dplane_ctx_q error_list;
+ struct dplane_ctx_list_head work_list;
+ struct dplane_ctx_list_head error_list;
struct zebra_dplane_provider *prov;
- struct zebra_dplane_ctx *ctx, *tctx;
+ struct zebra_dplane_ctx *ctx;
int limit, counter, error_counter;
uint64_t curr, high;
bool reschedule = false;
@@ -6695,8 +6691,9 @@ static void dplane_thread_loop(struct thread *event)
limit = zdplane_info.dg_updates_per_cycle;
/* Init temporary lists used to move contexts among providers */
- TAILQ_INIT(&work_list);
- TAILQ_INIT(&error_list);
+ dplane_ctx_list_init(&work_list);
+ dplane_ctx_list_init(&error_list);
+
error_counter = 0;
/* Check for zebra shutdown */
@@ -6709,18 +6706,15 @@ static void dplane_thread_loop(struct thread *event)
DPLANE_LOCK();
/* Locate initial registered provider */
- prov = TAILQ_FIRST(&zdplane_info.dg_providers_q);
+ prov = dplane_prov_list_first(&zdplane_info.dg_providers);
/* Move new work from incoming list to temp list */
for (counter = 0; counter < limit; counter++) {
- ctx = TAILQ_FIRST(&zdplane_info.dg_update_ctx_q);
+ ctx = dplane_ctx_list_pop(&zdplane_info.dg_update_list);
if (ctx) {
- TAILQ_REMOVE(&zdplane_info.dg_update_ctx_q, ctx,
- zd_q_entries);
-
ctx->zd_provider = prov->dp_id;
- TAILQ_INSERT_TAIL(&work_list, ctx, zd_q_entries);
+ dplane_ctx_list_add_tail(&work_list, ctx);
} else {
break;
}
@@ -6750,7 +6744,7 @@ static void dplane_thread_loop(struct thread *event)
/* Capture current provider id in each context; check for
* error status.
*/
- TAILQ_FOREACH_SAFE(ctx, &work_list, zd_q_entries, tctx) {
+ frr_each_safe (dplane_ctx_list, &work_list, ctx) {
if (dplane_ctx_get_status(ctx) ==
ZEBRA_DPLANE_REQUEST_SUCCESS) {
ctx->zd_provider = prov->dp_id;
@@ -6764,9 +6758,8 @@ static void dplane_thread_loop(struct thread *event)
/* Move to error list; will be returned
* zebra main.
*/
- TAILQ_REMOVE(&work_list, ctx, zd_q_entries);
- TAILQ_INSERT_TAIL(&error_list,
- ctx, zd_q_entries);
+ dplane_ctx_list_del(&work_list, ctx);
+ dplane_ctx_list_add_tail(&error_list, ctx);
error_counter++;
}
}
@@ -6774,9 +6767,8 @@ static void dplane_thread_loop(struct thread *event)
/* Enqueue new work to the provider */
dplane_provider_lock(prov);
- if (TAILQ_FIRST(&work_list))
- TAILQ_CONCAT(&(prov->dp_ctx_in_q), &work_list,
- zd_q_entries);
+ while ((ctx = dplane_ctx_list_pop(&work_list)) != NULL)
+ dplane_ctx_list_add_tail(&(prov->dp_ctx_in_list), ctx);
atomic_fetch_add_explicit(&prov->dp_in_counter, counter,
memory_order_relaxed);
@@ -6795,7 +6787,7 @@ static void dplane_thread_loop(struct thread *event)
/* Reset the temp list (though the 'concat' may have done this
* already), and the counter
*/
- TAILQ_INIT(&work_list);
+ dplane_ctx_list_init(&work_list);
counter = 0;
/* Call into the provider code. Note that this is
@@ -6812,13 +6804,9 @@ static void dplane_thread_loop(struct thread *event)
dplane_provider_lock(prov);
while (counter < limit) {
- ctx = TAILQ_FIRST(&(prov->dp_ctx_out_q));
+ ctx = dplane_ctx_list_pop(&(prov->dp_ctx_out_list));
if (ctx) {
- TAILQ_REMOVE(&(prov->dp_ctx_out_q), ctx,
- zd_q_entries);
-
- TAILQ_INSERT_TAIL(&work_list,
- ctx, zd_q_entries);
+ dplane_ctx_list_add_tail(&work_list, ctx);
counter++;
} else
break;
@@ -6835,7 +6823,7 @@ static void dplane_thread_loop(struct thread *event)
/* Locate next provider */
DPLANE_LOCK();
- prov = TAILQ_NEXT(prov, dp_prov_link);
+ prov = dplane_prov_list_next(&zdplane_info.dg_providers, prov);
DPLANE_UNLOCK();
}
@@ -6861,12 +6849,12 @@ static void dplane_thread_loop(struct thread *event)
/* Call through to zebra main */
(zdplane_info.dg_results_cb)(&error_list);
- TAILQ_INIT(&error_list);
+ dplane_ctx_list_init(&error_list);
/* Call through to zebra main */
(zdplane_info.dg_results_cb)(&work_list);
- TAILQ_INIT(&work_list);
+ dplane_ctx_list_init(&work_list);
}
/*
@@ -6899,7 +6887,7 @@ void zebra_dplane_shutdown(void)
* Note that this call is in the main pthread, so providers must
* be prepared for that.
*/
- TAILQ_FOREACH(dp, &zdplane_info.dg_providers_q, dp_prov_link) {
+ frr_each (dplane_prov_list, &zdplane_info.dg_providers, dp) {
if (dp->dp_fini == NULL)
continue;
@@ -6920,8 +6908,9 @@ static void zebra_dplane_init_internal(void)
pthread_mutex_init(&zdplane_info.dg_mutex, NULL);
- TAILQ_INIT(&zdplane_info.dg_update_ctx_q);
- TAILQ_INIT(&zdplane_info.dg_providers_q);
+ dplane_prov_list_init(&zdplane_info.dg_providers);
+
+ dplane_ctx_list_init(&zdplane_info.dg_update_list);
zns_info_list_init(&zdplane_info.dg_zns_list);
zdplane_info.dg_updates_per_cycle = DPLANE_DEFAULT_NEW_WORK;
@@ -6970,7 +6959,7 @@ void zebra_dplane_start(void)
/* Call start callbacks for registered providers */
DPLANE_LOCK();
- prov = TAILQ_FIRST(&zdplane_info.dg_providers_q);
+ prov = dplane_prov_list_first(&zdplane_info.dg_providers);
DPLANE_UNLOCK();
while (prov) {
@@ -6980,7 +6969,7 @@ void zebra_dplane_start(void)
/* Locate next provider */
DPLANE_LOCK();
- prov = TAILQ_NEXT(prov, dp_prov_link);
+ prov = dplane_prov_list_next(&zdplane_info.dg_providers, prov);
DPLANE_UNLOCK();
}
@@ -6990,7 +6979,7 @@ void zebra_dplane_start(void)
/*
* Initialize the dataplane module at startup; called by zebra rib_init()
*/
-void zebra_dplane_init(int (*results_fp)(struct dplane_ctx_q *))
+void zebra_dplane_init(int (*results_fp)(struct dplane_ctx_list_head *))
{
zebra_dplane_init_internal();
zdplane_info.dg_results_cb = results_fp;
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 51f6f3d897..ae13243a16 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -24,7 +24,6 @@
#include "lib/prefix.h"
#include "lib/nexthop.h"
#include "lib/nexthop_group.h"
-#include "lib/queue.h"
#include "lib/vlan.h"
#include "zebra/zebra_ns.h"
#include "zebra/rib.h"
@@ -265,14 +264,15 @@ void dplane_enable_sys_route_notifs(void);
* they cannot share existing global data structures safely.
*/
-/* Define a tailq list type for context blocks. The list is exposed/public,
+/* Define a list type for context blocks. The list is exposed/public,
* but the internal linkage in the context struct is private, so there
* are accessor apis that support enqueue and dequeue.
*/
-TAILQ_HEAD(dplane_ctx_q, zebra_dplane_ctx);
+
+PREDECL_DLIST(dplane_ctx_list);
/* Declare a type for (optional) extended interface info objects. */
-TAILQ_HEAD(dplane_intf_extra_q, dplane_intf_extra);
+PREDECL_DLIST(dplane_intf_extra_list);
/* Allocate a context object */
struct zebra_dplane_ctx *dplane_ctx_alloc(void);
@@ -300,18 +300,21 @@ void dplane_ctx_fini(struct zebra_dplane_ctx **pctx);
/* Enqueue a context block to caller's tailq. This exists so that the
* context struct can remain opaque.
*/
-void dplane_ctx_enqueue_tail(struct dplane_ctx_q *q,
+void dplane_ctx_enqueue_tail(struct dplane_ctx_list_head *q,
const struct zebra_dplane_ctx *ctx);
/* Append a list of context blocks to another list - again, just keeping
* the context struct opaque.
*/
-void dplane_ctx_list_append(struct dplane_ctx_q *to_list,
- struct dplane_ctx_q *from_list);
+void dplane_ctx_list_append(struct dplane_ctx_list_head *to_list,
+ struct dplane_ctx_list_head *from_list);
/* Dequeue a context block from the head of caller's tailq */
-struct zebra_dplane_ctx *dplane_ctx_dequeue(struct dplane_ctx_q *q);
-struct zebra_dplane_ctx *dplane_ctx_get_head(struct dplane_ctx_q *q);
+struct zebra_dplane_ctx *dplane_ctx_dequeue(struct dplane_ctx_list_head *q);
+struct zebra_dplane_ctx *dplane_ctx_get_head(struct dplane_ctx_list_head *q);
+
+/* Init a list of contexts */
+void dplane_ctx_q_init(struct dplane_ctx_list_head *q);
/*
* Accessors for information from the context object
@@ -1036,7 +1039,7 @@ struct zebra_dplane_ctx *dplane_provider_dequeue_in_ctx(
/* Dequeue work to a list, maintain counter and locking, return count */
int dplane_provider_dequeue_in_list(struct zebra_dplane_provider *prov,
- struct dplane_ctx_q *listp);
+ struct dplane_ctx_list_head *listp);
/* Current completed work queue length */
uint32_t dplane_provider_out_ctx_queue_len(struct zebra_dplane_provider *prov);
@@ -1061,7 +1064,7 @@ void dplane_enable_intf_extra_info(void);
* so the expectation is that the contexts are queued for the zebra
* main pthread.
*/
-void zebra_dplane_init(int (*) (struct dplane_ctx_q *));
+void zebra_dplane_init(int (*)(struct dplane_ctx_list_head *));
/*
* Start the dataplane pthread. This step needs to be run later than the
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c
index 628d4a2a87..06c45578a6 100644
--- a/zebra/zebra_fpm_netlink.c
+++ b/zebra/zebra_fpm_netlink.c
@@ -253,14 +253,7 @@ static int netlink_route_info_add_nh(struct netlink_route_info *ri,
*/
static uint8_t netlink_proto_from_route_type(int type)
{
- switch (type) {
- case ZEBRA_ROUTE_KERNEL:
- case ZEBRA_ROUTE_CONNECT:
- return RTPROT_KERNEL;
-
- default:
- return RTPROT_ZEBRA;
- }
+ return zebra2proto(type);
}
/*
diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c
index 73d585c1a3..8905b72ec5 100644
--- a/zebra/zebra_netns_id.c
+++ b/zebra/zebra_netns_id.c
@@ -23,6 +23,7 @@
#include "vrf.h"
#include "log.h"
#include "lib_errors.h"
+#include "network.h"
#include "zebra/rib.h"
#include "zebra/zebra_dplane.h"
@@ -73,7 +74,7 @@ static struct nlmsghdr *initiate_nlh(char *buf, unsigned int *seq, int type)
nlh->nlmsg_flags = NLM_F_REQUEST;
if (type == RTM_NEWNSID)
nlh->nlmsg_flags |= NLM_F_ACK;
- nlh->nlmsg_seq = *seq = time(NULL);
+ nlh->nlmsg_seq = *seq = frr_sequence32_next();
return nlh;
}
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 81910f68b7..d5375105a9 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -72,7 +72,7 @@ DEFINE_MTYPE_STATIC(ZEBRA, WQ_WRAPPER, "WQ wrapper");
*/
static pthread_mutex_t dplane_mutex;
static struct thread *t_dplane;
-static struct dplane_ctx_q rib_dplane_q;
+static struct dplane_ctx_list_head rib_dplane_q;
DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason),
(rn, reason));
@@ -4613,13 +4613,13 @@ static void handle_pw_result(struct zebra_dplane_ctx *ctx)
static void rib_process_dplane_results(struct thread *thread)
{
struct zebra_dplane_ctx *ctx;
- struct dplane_ctx_q ctxlist;
+ struct dplane_ctx_list_head ctxlist;
bool shut_p = false;
/* Dequeue a list of completed updates with one lock/unlock cycle */
do {
- TAILQ_INIT(&ctxlist);
+ dplane_ctx_q_init(&ctxlist);
/* Take lock controlling queue of results */
frr_with_mutex (&dplane_mutex) {
@@ -4788,7 +4788,7 @@ static void rib_process_dplane_results(struct thread *thread)
* the dataplane pthread. We enqueue the results here for processing by
* the main thread later.
*/
-static int rib_dplane_results(struct dplane_ctx_q *ctxlist)
+static int rib_dplane_results(struct dplane_ctx_list_head *ctxlist)
{
/* Take lock controlling queue of results */
frr_with_mutex (&dplane_mutex) {
@@ -4833,7 +4833,7 @@ void rib_init(void)
/* Init dataplane, and register for results */
pthread_mutex_init(&dplane_mutex, NULL);
- TAILQ_INIT(&rib_dplane_q);
+ dplane_ctx_q_init(&rib_dplane_q);
zebra_dplane_init(rib_dplane_results);
}