summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_bfd.c6
-rw-r--r--bgpd/bgp_bmp.c4
-rw-r--r--bgpd/bgp_route.c18
-rw-r--r--bgpd/bgp_rpki.c40
-rw-r--r--bgpd/bgp_table.c88
-rw-r--r--bgpd/bgp_table.h12
-rwxr-xr-xconfigure.ac7
-rw-r--r--doc/user/installation.rst12
-rw-r--r--doc/user/sharp.rst12
-rw-r--r--isisd/isis_route.c4
-rw-r--r--isisd/isis_zebra.c12
-rw-r--r--isisd/isis_zebra.h8
-rw-r--r--ldpd/lde.c2
-rw-r--r--ldpd/ldpd.c3
-rw-r--r--ldpd/ldpe.c3
-rw-r--r--lib/command.c5
-rw-r--r--lib/filter_cli.c85
-rw-r--r--lib/prefix.c6
-rw-r--r--lib/prefix.h12
-rw-r--r--lib/stream.h2
-rw-r--r--lib/zclient.c2
-rw-r--r--pimd/pim_mlag.c62
-rw-r--r--sharpd/sharp_vty.c30
-rw-r--r--sharpd/sharp_zebra.c101
-rw-r--r--sharpd/sharp_zebra.h4
-rw-r--r--tests/bgpd/test_bgp_table.c97
-rw-r--r--tests/bgpd/test_bgp_table.py2
-rwxr-xr-xtests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py16
-rwxr-xr-xtools/frr-reload.py6
-rw-r--r--zebra/dplane_fpm_nl.c32
-rw-r--r--zebra/if_netlink.c24
-rw-r--r--zebra/kernel_netlink.c72
-rw-r--r--zebra/kernel_netlink.h59
-rw-r--r--zebra/rt_netlink.c887
-rw-r--r--zebra/rt_netlink.h17
-rw-r--r--zebra/rule_netlink.c32
-rw-r--r--zebra/subdir.am3
-rw-r--r--zebra/zebra_fpm_netlink.c87
-rw-r--r--zebra/zebra_mlag.c4
-rw-r--r--zebra/zebra_mlag.h4
-rw-r--r--zebra/zebra_mpls_netlink.c13
-rw-r--r--zebra/zebra_netns_id.c9
42 files changed, 1089 insertions, 815 deletions
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index a200589bd3..1be7eff560 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -207,15 +207,9 @@ static void bgp_bfd_update_peer(struct peer *peer)
*/
void bgp_bfd_reset_peer(struct peer *peer)
{
- struct bfd_info *bfd_info;
-
if (!peer->bfd_info)
return;
- bfd_info = (struct bfd_info *)peer->bfd_info;
- /* if status is not down, reset bfd */
- if (bfd_info->status != BFD_STATUS_DOWN)
- bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER);
bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER);
}
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index 8902a8789a..fb4c50e3ef 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -859,7 +859,9 @@ static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
{
struct stream *hdr, *msg;
struct timeval tv = { .tv_sec = uptime, .tv_usec = 0 };
+ struct timeval uptime_real;
+ monotime_to_realtime(&tv, &uptime_real);
if (attr)
msg = bmp_update(p, peer, attr, afi, safi);
else
@@ -867,7 +869,7 @@ static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
hdr = stream_new(BGP_MAX_PACKET_SIZE);
bmp_common_hdr(hdr, BMP_VERSION_3, BMP_TYPE_ROUTE_MONITORING);
- bmp_per_peer_hdr(hdr, peer, flags, &tv);
+ bmp_per_peer_hdr(hdr, peer, flags, &uptime_real);
stream_putl_at(hdr, BMP_LENGTH_POS,
stream_get_endp(hdr) + stream_get_endp(msg));
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index b0fbdbcf01..94a305760a 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -3239,6 +3239,9 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
struct bgp_node *rn)
{
bool ret = false;
+ bool is_bgp_static_route =
+ (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
+ : false;
/* Only validated for unicast and multicast currently. */
/* Also valid for EVPN where the nexthop is an IP address. */
@@ -3247,7 +3250,7 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
/* If NEXT_HOP is present, validate it. */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
- if (attr->nexthop.s_addr == INADDR_ANY
+ if ((attr->nexthop.s_addr == INADDR_ANY && !is_bgp_static_route)
|| IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
|| bgp_nexthop_self(bgp, afi, type, stype, attr, rn))
return true;
@@ -3266,7 +3269,8 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
switch (attr->mp_nexthop_len) {
case BGP_ATTR_NHLEN_IPV4:
case BGP_ATTR_NHLEN_VPNV4:
- ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
+ ret = ((attr->mp_nexthop_global_in.s_addr == INADDR_ANY
+ && !is_bgp_static_route)
|| IPV4_CLASS_DE(
ntohl(attr->mp_nexthop_global_in.s_addr))
|| bgp_nexthop_self(bgp, afi, type, stype, attr,
@@ -3275,12 +3279,14 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
case BGP_ATTR_NHLEN_IPV6_GLOBAL:
case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
- ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
+ ret = ((IN6_IS_ADDR_UNSPECIFIED(
+ &attr->mp_nexthop_global)
+ && !is_bgp_static_route)
|| IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
|| IN6_IS_ADDR_MULTICAST(
- &attr->mp_nexthop_global)
- || bgp_nexthop_self(bgp, afi, type, stype,
- attr, rn));
+ &attr->mp_nexthop_global)
+ || bgp_nexthop_self(bgp, afi, type, stype, attr,
+ rn));
break;
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 1ba07e95e6..3228b38990 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -402,25 +402,23 @@ static int bgpd_sync_callback(struct thread *thread)
if (!peer->bgp->rib[afi][safi])
continue;
- struct list *matches = list_new();
-
- matches->del =
- (void (*)(void *))bgp_unlock_node;
-
- bgp_table_range_lookup(
- peer->bgp->rib[afi][safi], prefix,
- rec.max_len, matches);
-
-
- struct bgp_node *bgp_node;
- struct listnode *bgp_listnode;
-
- for (ALL_LIST_ELEMENTS_RO(matches, bgp_listnode,
- bgp_node))
- revalidate_bgp_node(bgp_node, afi,
- safi);
-
- list_delete(&matches);
+ struct bgp_node *match;
+ struct bgp_node *node;
+
+ match = bgp_table_subtree_lookup(
+ peer->bgp->rib[afi][safi], prefix);
+ node = match;
+
+ while (node) {
+ if (bgp_node_has_bgp_path_info_data(
+ node)) {
+ revalidate_bgp_node(node, afi,
+ safi);
+ }
+
+ node = bgp_route_next_until(node,
+ match);
+ }
}
}
}
@@ -811,7 +809,7 @@ static int add_tcp_cache(const char *host, const char *port,
{
struct rtr_socket *rtr_socket;
struct tr_tcp_config *tcp_config =
- XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_tcp_config));
+ XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_tcp_config));
struct tr_socket *tr_socket =
XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
struct cache *cache =
@@ -845,7 +843,7 @@ static int add_ssh_cache(const char *host, const unsigned int port,
const uint8_t preference)
{
struct tr_ssh_config *ssh_config =
- XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_ssh_config));
+ XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_ssh_config));
struct cache *cache =
XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
struct tr_socket *tr_socket =
diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c
index dcf9852a67..8acd42ffc0 100644
--- a/bgpd/bgp_table.c
+++ b/bgpd/bgp_table.c
@@ -164,90 +164,42 @@ void bgp_delete_listnode(struct bgp_node *node)
}
}
-static struct bgp_node *
-bgp_route_next_until_maxlen(struct bgp_node *node, const struct bgp_node *limit,
- const uint8_t maxlen)
+struct bgp_node *bgp_table_subtree_lookup(const struct bgp_table *table,
+ const struct prefix *p)
{
- const struct prefix *p = bgp_node_get_prefix(node);
+ struct bgp_node *node = bgp_node_from_rnode(table->route_table->top);
+ struct bgp_node *matched = NULL;
- if (node->l_left) {
- const struct prefix *left_p =
- bgp_node_get_prefix(bgp_node_from_rnode(node->l_left));
+ if (node == NULL)
+ return NULL;
- if (p->prefixlen < maxlen && left_p->prefixlen <= maxlen)
- return bgp_node_from_rnode(node->l_left);
- }
- if (node->l_right) {
- const struct prefix *right_p =
- bgp_node_get_prefix(bgp_node_from_rnode(node->l_right));
+ while (node) {
+ const struct prefix *node_p = bgp_node_get_prefix(node);
- if (p->prefixlen < maxlen && right_p->prefixlen <= maxlen)
- return bgp_node_from_rnode(node->l_right);
- }
+ if (node_p->prefixlen >= p->prefixlen) {
+ if (!prefix_match(p, node_p))
+ return NULL;
- while (node->parent && node != limit) {
- if (bgp_node_from_rnode(node->parent->l_left) == node
- && node->parent->l_right) {
- return bgp_node_from_rnode(node->parent->l_right);
+ matched = node;
+ break;
}
- node = bgp_node_from_rnode(node->parent);
- }
- return NULL;
-}
-void bgp_table_range_lookup(const struct bgp_table *table,
- const struct prefix *p,
- uint8_t maxlen, struct list *matches)
-{
- struct bgp_node *node = bgp_node_from_rnode(table->route_table->top);
- struct bgp_node *matched = NULL;
+ if (!prefix_match(node_p, p))
+ return NULL;
- if (node == NULL)
- return;
-
- const struct prefix *node_p = bgp_node_get_prefix(node);
-
- while (node && node_p->prefixlen <= p->prefixlen
- && prefix_match(node_p, p)) {
- if (bgp_node_has_bgp_path_info_data(node)
- && node_p->prefixlen == p->prefixlen) {
+ if (node_p->prefixlen == p->prefixlen) {
matched = node;
break;
}
+
node = bgp_node_from_rnode(node->link[prefix_bit(
&p->u.prefix, node_p->prefixlen)]);
- node_p = bgp_node_get_prefix(node);
}
- if (!node)
- return;
-
- node_p = bgp_node_get_prefix(node);
- if (matched == NULL && node_p->prefixlen <= maxlen
- && prefix_match(p, node_p) && node->parent == NULL)
- matched = node;
- else if ((matched == NULL && node_p->prefixlen > maxlen)
- || !node->parent)
- return;
- else if (matched == NULL && node->parent)
- matched = node = bgp_node_from_rnode(node->parent);
-
if (!matched)
- return;
-
- if (bgp_node_has_bgp_path_info_data(matched)) {
- bgp_lock_node(matched);
- listnode_add(matches, matched);
- }
+ return NULL;
- while ((node = bgp_route_next_until_maxlen(node, matched, maxlen))) {
- node_p = bgp_node_get_prefix(node);
- if (prefix_match(p, node_p)) {
- if (bgp_node_has_bgp_path_info_data(node)) {
- bgp_lock_node(node);
- listnode_add(matches, node);
- }
- }
- }
+ bgp_lock_node(matched);
+ return matched;
}
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index da2ca3181a..c35833e66b 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -347,9 +347,15 @@ static inline uint64_t bgp_table_version(struct bgp_table *table)
return table->version;
}
-void bgp_table_range_lookup(const struct bgp_table *table,
- const struct prefix *p,
- uint8_t maxlen, struct list *matches);
+/* Find the subtree of the prefix p
+ *
+ * This will return the first node that belongs the the subtree of p. Including
+ * p itself, if it is in the tree.
+ *
+ * If the subtree is not present in the table, NULL is returned.
+ */
+struct bgp_node *bgp_table_subtree_lookup(const struct bgp_table *table,
+ const struct prefix *p);
static inline struct bgp_aggregate *
diff --git a/configure.ac b/configure.ac
index d4c652c6e5..3c65bc91a0 100755
--- a/configure.ac
+++ b/configure.ac
@@ -645,6 +645,9 @@ AC_ARG_WITH([crypto],
AC_ARG_WITH([frr-format],
AS_HELP_STRING([--with-frr-format[=<.../frr-format.so>]], [use frr-format GCC plugin]))
+AC_ARG_ENABLE([version-build-config],
+ AS_HELP_STRING([--disable-version-build-config], [do not include build configs in show version command]))
+
#if openssl, else use the internal
AS_IF([test "$with_crypto" = "openssl"], [
AC_CHECK_LIB([crypto], [EVP_DigestInit], [LIBS="$LIBS -lcrypto"], [], [])
@@ -1682,6 +1685,10 @@ case "${enable_bmp}" in
;;
esac
+if test "$enable_version_build_config" != "no";then
+ AC_DEFINE([ENABLE_VERSION_BUILD_CONFIG], [1], [Report build configs in show version])
+fi
+
dnl ##########################################################################
dnl LARGE if block
if test "$enable_clippy_only" != "yes"; then
diff --git a/doc/user/installation.rst b/doc/user/installation.rst
index 9cd1210529..622af67b0f 100644
--- a/doc/user/installation.rst
+++ b/doc/user/installation.rst
@@ -279,6 +279,18 @@ options from the list below.
With this option, we provide a way to strip out these characters for APK dev
package builds.
+..option:: --disable-version-build-config
+
+ Remove the "configuerd with" field that has all of the build configuration
+ arguments when reporting the version string in `show version` command.
+
+..option:: --with-pkg-extra-version=VER
+ Add extra version field, for packagers/distributions
+
+..option:: --with-pkg-git-version
+
+ Add git information to MOTD and build version string
+
.. option:: --enable-multipath=X
Compile FRR with up to X way ECMP supported. This number can be from 0-999.
diff --git a/doc/user/sharp.rst b/doc/user/sharp.rst
index dd0e67d4b7..1c474193f2 100644
--- a/doc/user/sharp.rst
+++ b/doc/user/sharp.rst
@@ -125,3 +125,15 @@ keyword. At present, no sharp commands will be preserved in the config.
single subtype. The messages must specify a protocol daemon by
name, and can include optional zapi ``instance`` and ``session``
values.
+
+.. index:: sharp create session
+.. clicmd:: sharp create session (1-1024)
+
+ Create an additional zapi client session for testing, using the
+ specified session id.
+
+.. index:: sharp remove session
+.. clicmd:: sharp remove session (1-1024)
+
+ Remove a test zapi client session that was created with the
+ specified session id.
diff --git a/isisd/isis_route.c b/isisd/isis_route.c
index fa6af6c216..ffb5bdb357 100644
--- a/isisd/isis_route.c
+++ b/isisd/isis_route.c
@@ -355,7 +355,7 @@ static void isis_route_update(struct isis_area *area, struct prefix *prefix,
if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return;
- isis_zebra_route_add_route(prefix, src_p, route_info);
+ isis_zebra_route_add_route(area->isis, prefix, src_p, route_info);
hook_call(isis_route_update_hook, area, prefix, route_info);
SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
@@ -364,7 +364,7 @@ static void isis_route_update(struct isis_area *area, struct prefix *prefix,
if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return;
- isis_zebra_route_del_route(prefix, src_p, route_info);
+ isis_zebra_route_del_route(area->isis, prefix, src_p, route_info);
hook_call(isis_route_update_hook, area, prefix, route_info);
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index db0efcaf5a..a80a18d887 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -151,7 +151,8 @@ static int isis_zebra_link_params(ZAPI_CALLBACK_ARGS)
return 0;
}
-void isis_zebra_route_add_route(struct prefix *prefix,
+void isis_zebra_route_add_route(struct isis *isis,
+ struct prefix *prefix,
struct prefix_ipv6 *src_p,
struct isis_route_info *route_info)
{
@@ -165,7 +166,7 @@ void isis_zebra_route_add_route(struct prefix *prefix,
return;
memset(&api, 0, sizeof(api));
- api.vrf_id = VRF_DEFAULT;
+ api.vrf_id = isis->vrf_id;
api.type = PROTO_TYPE;
api.safi = SAFI_UNICAST;
api.prefix = *prefix;
@@ -188,7 +189,7 @@ void isis_zebra_route_add_route(struct prefix *prefix,
api_nh = &api.nexthops[count];
if (fabricd)
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
- api_nh->vrf_id = VRF_DEFAULT;
+ api_nh->vrf_id = isis->vrf_id;
switch (nexthop->family) {
case AF_INET:
@@ -226,7 +227,8 @@ void isis_zebra_route_add_route(struct prefix *prefix,
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
}
-void isis_zebra_route_del_route(struct prefix *prefix,
+void isis_zebra_route_del_route(struct isis *isis,
+ struct prefix *prefix,
struct prefix_ipv6 *src_p,
struct isis_route_info *route_info)
{
@@ -236,7 +238,7 @@ void isis_zebra_route_del_route(struct prefix *prefix,
return;
memset(&api, 0, sizeof(api));
- api.vrf_id = VRF_DEFAULT;
+ api.vrf_id = isis->vrf_id;
api.type = PROTO_TYPE;
api.safi = SAFI_UNICAST;
api.prefix = *prefix;
diff --git a/isisd/isis_zebra.h b/isisd/isis_zebra.h
index fd1c1df610..4449b63c2e 100644
--- a/isisd/isis_zebra.h
+++ b/isisd/isis_zebra.h
@@ -22,6 +22,8 @@
#ifndef _ZEBRA_ISIS_ZEBRA_H
#define _ZEBRA_ISIS_ZEBRA_H
+#include "isisd.h"
+
extern struct zclient *zclient;
struct label_chunk {
@@ -38,10 +40,12 @@ struct isis_route_info;
struct sr_prefix;
struct sr_adjacency;
-void isis_zebra_route_add_route(struct prefix *prefix,
+void isis_zebra_route_add_route(struct isis *isis,
+ struct prefix *prefix,
struct prefix_ipv6 *src_p,
struct isis_route_info *route_info);
-void isis_zebra_route_del_route(struct prefix *prefix,
+void isis_zebra_route_del_route(struct isis *isis,
+ struct prefix *prefix,
struct prefix_ipv6 *src_p,
struct isis_route_info *route_info);
void isis_zebra_send_prefix_sid(int cmd, const struct sr_prefix *srp);
diff --git a/ldpd/lde.c b/ldpd/lde.c
index 3220278960..afcbe6cd44 100644
--- a/ldpd/lde.c
+++ b/ldpd/lde.c
@@ -206,6 +206,8 @@ lde_shutdown(void)
free(iev_main_sync);
log_info("label decision engine exiting");
+
+ zlog_fini();
exit(0);
}
diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c
index 56734a4f76..e3b6f4dfcc 100644
--- a/ldpd/ldpd.c
+++ b/ldpd/ldpd.c
@@ -495,7 +495,8 @@ start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync)
int argc = 0, nullfd;
pid_t pid;
- switch (pid = fork()) {
+ pid = fork();
+ switch (pid) {
case -1:
fatal("cannot fork");
case 0:
diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c
index bae8a6e5c3..3f0a4fd33e 100644
--- a/ldpd/ldpe.c
+++ b/ldpd/ldpe.c
@@ -235,6 +235,9 @@ ldpe_shutdown(void)
free(pkt_ptr);
log_info("ldp engine exiting");
+
+ zlog_fini();
+
exit(0);
}
diff --git a/lib/command.c b/lib/command.c
index c9715965aa..80b75d9b23 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -144,7 +144,9 @@ void print_version(const char *progname)
{
printf("%s version %s\n", progname, FRR_VERSION);
printf("%s\n", FRR_COPYRIGHT);
+#ifdef ENABLE_VERSION_BUILD_CONFIG
printf("configured with:\n\t%s\n", FRR_CONFIG_ARGS);
+#endif
}
char *argv_concat(struct cmd_token **argv, int argc, int shift)
@@ -1334,8 +1336,9 @@ DEFUN (show_version,
vty_out(vty, "%s %s (%s).\n", FRR_FULL_NAME, FRR_VERSION,
cmd_hostname_get() ? cmd_hostname_get() : "");
vty_out(vty, "%s%s\n", FRR_COPYRIGHT, GIT_INFO);
+#ifdef ENABLE_VERSION_BUILD_CONFIG
vty_out(vty, "configured with:\n %s\n", FRR_CONFIG_ARGS);
-
+#endif
return CMD_SUCCESS;
}
diff --git a/lib/filter_cli.c b/lib/filter_cli.c
index 0091d8b03f..fe8190d098 100644
--- a/lib/filter_cli.c
+++ b/lib/filter_cli.c
@@ -20,15 +20,16 @@
* 02110-1301 USA.
*/
+#include "zebra.h"
#include "northbound.h"
#include "prefix.h"
-#include "zebra.h"
#include "lib/command.h"
#include "lib/filter.h"
#include "lib/northbound_cli.h"
#include "lib/plist.h"
#include "lib/plist_int.h"
+#include "lib/printfrr.h"
#ifndef VTYSH_EXTRACT_PL
#include "lib/filter_cli_clippy.c"
@@ -197,11 +198,11 @@ DEFPY(
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
sseq = acl_get_seq(vty, xpath);
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
} else
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%s']", xpath, seq_str);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%s']", xpath, seq_str);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL);
@@ -270,8 +271,8 @@ DEFPY(
if (sseq == -1)
return CMD_WARNING;
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
@@ -312,11 +313,11 @@ DEFPY(
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
sseq = acl_get_seq(vty, xpath);
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
} else
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%s']", xpath, seq_str);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%s']", xpath, seq_str);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL);
@@ -376,7 +377,7 @@ DEFPY(
/* If the user provided sequence number, then just go for it. */
if (seq_str != NULL) {
- snprintf(
+ snprintfrr(
xpath, sizeof(xpath),
"/frr-filter:lib/access-list-legacy[number='%s']/entry[sequence='%s']",
number_str, seq_str);
@@ -421,8 +422,8 @@ DEFPY(
if (sseq == -1)
return CMD_WARNING;
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
@@ -577,11 +578,11 @@ DEFPY(
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
sseq = acl_get_seq(vty, xpath);
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
} else
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%s']", xpath, seq_str);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%s']", xpath, seq_str);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL);
@@ -648,8 +649,8 @@ DEFPY(
if (sseq == -1)
return CMD_WARNING;
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
@@ -748,11 +749,11 @@ DEFPY(
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
sseq = acl_get_seq(vty, xpath);
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
} else
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%s']", xpath, seq_str);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%s']", xpath, seq_str);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL);
@@ -820,8 +821,8 @@ DEFPY(
if (sseq == -1)
return CMD_WARNING;
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
@@ -923,11 +924,11 @@ DEFPY(
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
sseq = acl_get_seq(vty, xpath);
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
} else
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%s']", xpath, seq_str);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%s']", xpath, seq_str);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL);
@@ -991,8 +992,8 @@ DEFPY(
if (sseq == -1)
return CMD_WARNING;
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
@@ -1231,8 +1232,8 @@ static int plist_remove(struct vty *vty, const char *iptype, const char *name,
if (pentry == NULL)
return CMD_WARNING;
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%" PRId64 "']", xpath, pentry->seq);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%" PRId64 "']", xpath, pentry->seq);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
rv = nb_cli_apply_changes(vty, NULL);
@@ -1271,11 +1272,11 @@ DEFPY(
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
sseq = acl_get_seq(vty, xpath);
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
} else
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%s']", xpath, seq_str);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%s']", xpath, seq_str);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL);
@@ -1431,11 +1432,11 @@ DEFPY(
if (seq_str == NULL) {
/* Use XPath to find the next sequence number. */
sseq = acl_get_seq(vty, xpath);
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
} else
- snprintf(xpath_entry, sizeof(xpath_entry),
- "%s/entry[sequence='%s']", xpath, seq_str);
+ snprintfrr(xpath_entry, sizeof(xpath_entry),
+ "%s/entry[sequence='%s']", xpath, seq_str);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL);
diff --git a/lib/prefix.c b/lib/prefix.c
index 112630e9c8..0900100be3 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -75,10 +75,10 @@ bool is_mcast_mac(const struct ethaddr *mac)
return false;
}
-unsigned int prefix_bit(const uint8_t *prefix, const uint16_t prefixlen)
+unsigned int prefix_bit(const uint8_t *prefix, const uint16_t bit_index)
{
- unsigned int offset = prefixlen / 8;
- unsigned int shift = 7 - (prefixlen % 8);
+ unsigned int offset = bit_index / 8;
+ unsigned int shift = 7 - (bit_index % 8);
return (prefix[offset] >> shift) & 1;
}
diff --git a/lib/prefix.h b/lib/prefix.h
index 506efffb94..0bd457cc23 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -392,8 +392,16 @@ extern const char *family2str(int family);
extern const char *safi2str(safi_t safi);
extern const char *afi2str(afi_t afi);
-/* Check bit of the prefix. */
-extern unsigned int prefix_bit(const uint8_t *prefix, const uint16_t prefixlen);
+/*
+ * Check bit of the prefix.
+ *
+ * prefix
+ * byte buffer
+ *
+ * bit_index
+ * which bit to fetch from byte buffer, 0 indexed.
+ */
+extern unsigned int prefix_bit(const uint8_t *prefix, const uint16_t bit_index);
extern struct prefix *prefix_new(void);
extern void prefix_free(struct prefix **p);
diff --git a/lib/stream.h b/lib/stream.h
index 7cacf57d27..245f35db51 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -426,7 +426,7 @@ static inline const uint8_t *ptr_get_be32(const uint8_t *ptr, uint32_t *out)
float r; \
uint32_t d; \
} _pval; \
- if (stream_getl2((S), &_pval.d)) \
+ if (!stream_getl2((S), &_pval.d)) \
goto stream_failure; \
(P) = _pval.r; \
} while (0)
diff --git a/lib/zclient.c b/lib/zclient.c
index aa5fa082a1..793864243c 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -164,7 +164,7 @@ void zclient_stop(struct zclient *zclient)
int i;
if (zclient_debug)
- zlog_debug("zclient stopped");
+ zlog_debug("zclient %p stopped", zclient);
/* Stop threads. */
THREAD_OFF(zclient->t_read);
diff --git a/pimd/pim_mlag.c b/pimd/pim_mlag.c
index 02f206144f..305dd5cf2c 100644
--- a/pimd/pim_mlag.c
+++ b/pimd/pim_mlag.c
@@ -41,8 +41,7 @@ extern struct zclient *zclient;
"%s: add Dual-active Interface to %s " \
"to oil:%s", \
__func__, ch->interface->name, ch->sg_str); \
- pim_channel_add_oif(ch_oil, ch->interface, \
- PIM_OIF_FLAG_PROTO_IGMP, __func__); \
+ pim_channel_update_oif_mute(ch_oil, ch->interface->info); \
} while (0)
#define PIM_MLAG_DEL_OIF_TO_OIL(ch, ch_oil) \
@@ -52,8 +51,7 @@ extern struct zclient *zclient;
"%s: del Dual-active Interface to %s " \
"to oil:%s", \
__func__, ch->interface->name, ch->sg_str); \
- pim_channel_del_oif(ch_oil, ch->interface, \
- PIM_OIF_FLAG_PROTO_IGMP, __func__); \
+ pim_channel_update_oif_mute(ch_oil, ch->interface->info); \
} while (0)
@@ -91,14 +89,36 @@ static void pim_mlag_inherit_mlag_flags(struct pim_upstream *up, bool is_df)
{
struct listnode *listnode;
struct pim_upstream *child;
+ struct listnode *chnode;
+ struct listnode *chnextnode;
+ struct pim_ifchannel *ch;
+ struct pim_interface *pim_ifp = NULL;
+ struct channel_oil *ch_oil = NULL;
- for (ALL_LIST_ELEMENTS_RO(up->sources, listnode, child)) {
- PIM_UPSTREAM_FLAG_SET_MLAG_PEER(child->flags);
- if (is_df)
- PIM_UPSTREAM_FLAG_UNSET_MLAG_NON_DF(child->flags);
- else
- PIM_UPSTREAM_FLAG_SET_MLAG_NON_DF(child->flags);
- pim_mlag_calculate_df_for_ifchannels(child, is_df);
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("%s: Updating DF for uptream:%s childs", __func__,
+ up->sg_str);
+
+
+ for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
+ pim_ifp = (ch->interface) ? ch->interface->info : NULL;
+ if (!pim_ifp || !PIM_I_am_DualActive(pim_ifp))
+ continue;
+
+ for (ALL_LIST_ELEMENTS_RO(up->sources, listnode, child)) {
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("%s: Updating DF for child:%s",
+ __func__, child->sg_str);
+ ch_oil = (child) ? child->channel_oil : NULL;
+
+ if (!ch_oil)
+ continue;
+
+ if (is_df)
+ PIM_MLAG_ADD_OIF_TO_OIL(ch, ch_oil);
+ else
+ PIM_MLAG_DEL_OIF_TO_OIL(ch, ch_oil);
+ }
}
}
@@ -134,8 +154,8 @@ bool pim_mlag_up_df_role_update(struct pim_instance *pim,
* Interface configuration
*/
if (PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags)) {
- pim_mlag_calculate_df_for_ifchannels(up, is_df);
pim_mlag_inherit_mlag_flags(up, is_df);
+ pim_mlag_calculate_df_for_ifchannels(up, is_df);
}
/* If the DF role has changed check if ipmr-lo needs to be
@@ -170,8 +190,7 @@ static bool pim_mlag_up_df_role_elect(struct pim_instance *pim,
uint32_t local_cost;
bool rv;
- if (!pim_up_mlag_is_local(up)
- && !PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags))
+ if (!pim_up_mlag_is_local(up))
return false;
/* We are yet to rx a status update from the local MLAG daemon so
@@ -501,8 +520,7 @@ static void pim_mlag_up_local_replay(void)
RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
pim = vrf->info;
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
- if (pim_up_mlag_is_local(up)
- || PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags))
+ if (pim_up_mlag_is_local(up))
pim_mlag_up_local_add_send(pim, up);
}
}
@@ -523,9 +541,7 @@ static void pim_mlag_up_local_reeval(bool mlagd_send, const char *reason_code)
RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
pim = vrf->info;
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
- if (!pim_up_mlag_is_local(up)
- && !PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(
- up->flags))
+ if (!pim_up_mlag_is_local(up))
continue;
/* if role changes re-send to peer */
if (pim_mlag_up_df_role_elect(pim, up) &&
@@ -985,6 +1001,10 @@ void pim_if_configure_mlag_dualactive(struct pim_interface *pim_ifp)
if (!pim_ifp || !pim_ifp->pim || pim_ifp->activeactive == true)
return;
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("%s: Configuring active-active on Interface: %s",
+ __func__, "NULL");
+
pim_ifp->activeactive = true;
if (pim_ifp->pim)
pim_ifp->pim->inst_mlag_intf_cnt++;
@@ -1010,6 +1030,10 @@ void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp)
if (!pim_ifp || !pim_ifp->pim || pim_ifp->activeactive == false)
return;
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("%s: UnConfiguring active-active on Interface: %s",
+ __func__, "NULL");
+
pim_ifp->activeactive = false;
pim_ifp->pim->inst_mlag_intf_cnt--;
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index 72e9c22f17..48220d1c9b 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -547,6 +547,34 @@ DEFPY (logpump,
return CMD_SUCCESS;
}
+DEFPY (create_session,
+ create_session_cmd,
+ "sharp create session (1-1024)",
+ "Sharp Routing Protocol\n"
+ "Create data\n"
+ "Create a test session\n"
+ "Session ID\n")
+{
+ if (sharp_zclient_create(session) != 0) {
+ vty_out(vty, "%% Client session error\n");
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (remove_session,
+ remove_session_cmd,
+ "sharp remove session (1-1024)",
+ "Sharp Routing Protocol\n"
+ "Remove data\n"
+ "Remove a test session\n"
+ "Session ID\n")
+{
+ sharp_zclient_delete(session);
+ return CMD_SUCCESS;
+}
+
DEFPY (send_opaque,
send_opaque_cmd,
"sharp send opaque type (1-255) (1-1000)$count",
@@ -626,6 +654,8 @@ void sharp_vty_init(void)
install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd);
install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd);
install_element(ENABLE_NODE, &logpump_cmd);
+ install_element(ENABLE_NODE, &create_session_cmd);
+ install_element(ENABLE_NODE, &remove_session_cmd);
install_element(ENABLE_NODE, &send_opaque_cmd);
install_element(ENABLE_NODE, &send_opaque_unicast_cmd);
install_element(ENABLE_NODE, &send_opaque_reg_cmd);
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index 6ebc04b9eb..baa4e2ad5b 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -25,14 +25,9 @@
#include "command.h"
#include "network.h"
#include "prefix.h"
-#include "routemap.h"
-#include "table.h"
#include "stream.h"
#include "memory.h"
#include "zclient.h"
-#include "filter.h"
-#include "plist.h"
-#include "log.h"
#include "nexthop.h"
#include "nexthop_group.h"
@@ -44,9 +39,41 @@
struct zclient *zclient = NULL;
/* For registering threads. */
-extern struct thread_master *master;
+struct thread_master *master;
-/* Inteface addition message from zebra. */
+/* Privs info */
+struct zebra_privs_t sharp_privs;
+
+DEFINE_MTYPE_STATIC(SHARPD, ZC, "Test zclients");
+
+/* Struct to hold list of test zclients */
+struct sharp_zclient {
+ struct sharp_zclient *prev;
+ struct sharp_zclient *next;
+ struct zclient *client;
+};
+
+/* Head of test zclient list */
+static struct sharp_zclient *sharp_clients_head;
+
+static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS);
+
+/* Utility to add a test zclient struct to the list */
+static void add_zclient(struct zclient *client)
+{
+ struct sharp_zclient *node;
+
+ node = XCALLOC(MTYPE_ZC, sizeof(struct sharp_zclient));
+
+ node->client = client;
+
+ node->next = sharp_clients_head;
+ if (sharp_clients_head)
+ sharp_clients_head->prev = node;
+ sharp_clients_head = node;
+}
+
+/* Interface addition message from zebra. */
static int sharp_ifp_create(struct interface *ifp)
{
return 0;
@@ -480,6 +507,62 @@ static int sharp_redistribute_route(ZAPI_CALLBACK_ARGS)
return 0;
}
+/* Add a zclient with a specified session id, for testing. */
+int sharp_zclient_create(uint32_t session_id)
+{
+ struct zclient *client;
+ struct sharp_zclient *node;
+
+ /* Check for duplicates */
+ for (node = sharp_clients_head; node != NULL; node = node->next) {
+ if (node->client->session_id == session_id)
+ return -1;
+ }
+
+ client = zclient_new(master, &zclient_options_default);
+ client->sock = -1;
+ client->session_id = session_id;
+
+ zclient_init(client, ZEBRA_ROUTE_SHARP, 0, &sharp_privs);
+
+ /* Register handlers for messages we expect this session to see */
+ client->opaque_msg_handler = sharp_opaque_handler;
+
+ /* Enqueue on the list of test clients */
+ add_zclient(client);
+
+ return 0;
+}
+
+/* Delete one of the extra test zclients */
+int sharp_zclient_delete(uint32_t session_id)
+{
+ struct sharp_zclient *node;
+
+ /* Search for session */
+ for (node = sharp_clients_head; node != NULL; node = node->next) {
+ if (node->client->session_id == session_id) {
+ /* Dequeue from list */
+ if (node->next)
+ node->next->prev = node->prev;
+ if (node->prev)
+ node->prev->next = node->next;
+ if (node == sharp_clients_head)
+ sharp_clients_head = node->next;
+
+ /* Clean up zclient */
+ zclient_stop(node->client);
+ zclient_free(node->client);
+
+ /* Free memory */
+ XFREE(MTYPE_ZC, node);
+ break;
+ }
+ }
+
+ return 0;
+}
+
/* Handler for opaque messages */
static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS)
{
@@ -491,7 +574,7 @@ static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS)
if (zclient_opaque_decode(s, &info) != 0)
return -1;
- zlog_debug("%s: [%d] received opaque type %u", __func__,
+ zlog_debug("%s: [%u] received opaque type %u", __func__,
zclient->session_id, info.type);
return 0;
@@ -564,8 +647,6 @@ void sharp_opaque_reg_send(bool is_reg, uint32_t proto, uint32_t instance,
}
-extern struct zebra_privs_t sharp_privs;
-
void sharp_zebra_init(void)
{
struct zclient_options opt = {.receive_notify = true};
diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h
index 7604f4b0a4..cb2f38a6ab 100644
--- a/sharpd/sharp_zebra.h
+++ b/sharpd/sharp_zebra.h
@@ -24,6 +24,10 @@
extern void sharp_zebra_init(void);
+/* Add and delete extra zapi client sessions, for testing */
+int sharp_zclient_create(uint32_t session_id);
+int sharp_zclient_delete(uint32_t session_id);
+
extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label);
extern void route_add(const struct prefix *p, vrf_id_t, uint8_t instance,
const struct nexthop_group *nhg,
diff --git a/tests/bgpd/test_bgp_table.c b/tests/bgpd/test_bgp_table.c
index 79a8bb4408..7d81d42afb 100644
--- a/tests/bgpd/test_bgp_table.c
+++ b/tests/bgpd/test_bgp_table.c
@@ -73,70 +73,64 @@ static void add_node(struct bgp_table *table, const char *prefix_str)
rn->info = node;
}
-static void print_range_result(struct list *list)
+static bool prefix_in_array(const struct prefix *p, struct prefix *prefix_array,
+ size_t prefix_array_size)
{
-
- struct listnode *listnode;
- struct bgp_node *bnode;
-
- for (ALL_LIST_ELEMENTS_RO(list, listnode, bnode)) {
- char buf[PREFIX2STR_BUFFER];
-
- prefix2str(bgp_node_get_prefix(bnode), buf, PREFIX2STR_BUFFER);
- printf("%s\n", buf);
+ for (size_t i = 0; i < prefix_array_size; ++i) {
+ if (prefix_same(p, &prefix_array[i]))
+ return true;
}
+ return false;
}
-static void check_lookup_result(struct list *list, va_list arglist)
+static void check_lookup_result(struct bgp_node *match, va_list arglist)
{
char *prefix_str;
- unsigned int prefix_count = 0;
+ struct prefix *prefixes = NULL;
+ size_t prefix_count = 0;
- printf("Searching results\n");
while ((prefix_str = va_arg(arglist, char *))) {
- struct listnode *listnode;
- struct bgp_node *bnode;
- struct prefix p;
- bool found = false;
+ ++prefix_count;
+ prefixes = realloc(prefixes, sizeof(*prefixes) * prefix_count);
- prefix_count++;
- printf("Searching for %s\n", prefix_str);
-
- if (str2prefix(prefix_str, &p) <= 0)
+ if (str2prefix(prefix_str, &prefixes[prefix_count - 1]) <= 0)
assert(0);
+ }
- for (ALL_LIST_ELEMENTS_RO(list, listnode, bnode)) {
- if (prefix_same(bgp_node_get_prefix(bnode), &p))
- found = true;
- }
+ /* check if the result is empty and if it is allowd to be empty */
+ assert((prefix_count == 0 && !match) || prefix_count > 0);
+ if (!match)
+ return;
- assert(found);
- }
+ struct bgp_node *node = match;
+
+ while ((node = bgp_route_next_until(node, match))) {
+ const struct prefix *node_p = bgp_node_get_prefix(node);
- printf("Checking for unexpected result items\n");
- printf("Expecting %d found %d\n", prefix_count, listcount(list));
- assert(prefix_count == listcount(list));
+ if (bgp_node_has_bgp_path_info_data(node)
+ && !prefix_in_array(node_p, prefixes, prefix_count)) {
+ char buf[PREFIX2STR_BUFFER];
+
+ prefix2str(node_p, buf, PREFIX2STR_BUFFER);
+ printf("prefix %s was not expected!\n", buf);
+ assert(0);
+ }
+ }
}
-static void do_test(struct bgp_table *table, const char *prefix,
- uint32_t maxlen, ...)
+static void do_test(struct bgp_table *table, const char *prefix, ...)
{
va_list arglist;
- struct list *list = list_new();
struct prefix p;
- list->del = (void (*)(void *))bgp_unlock_node;
- va_start(arglist, maxlen);
- printf("\nDoing lookup for %s-%d\n", prefix, maxlen);
+ va_start(arglist, prefix);
+ printf("\nDoing lookup for %s\n", prefix);
if (str2prefix(prefix, &p) <= 0)
assert(0);
- bgp_table_range_lookup(table, &p, maxlen, list);
- print_range_result(list);
-
- check_lookup_result(list, arglist);
+ struct bgp_node *node = bgp_table_subtree_lookup(table, &p);
- list_delete(&list);
+ check_lookup_result(node, arglist);
va_end(arglist);
@@ -163,27 +157,22 @@ static void test_range_lookup(void)
for (int i = 0; i < num_prefixes; i++)
add_node(table, prefixes[i]);
- do_test(table, "1.16.0.0/17", 20, "1.16.64.0/19", "1.16.32.0/20", NULL);
- do_test(table, "1.16.128.0/17", 20, "1.16.128.0/18", "1.16.192.0/18",
- "1.16.160.0/19", NULL);
-
- do_test(table, "1.16.128.0/17", 20, "1.16.128.0/18", "1.16.192.0/18",
+ do_test(table, "1.16.0.0/17", "1.16.64.0/19", "1.16.32.0/20",
+ "1.16.32.0/20", "1.16.32.0/21", NULL);
+ do_test(table, "1.16.128.0/17", "1.16.128.0/18", "1.16.192.0/18",
"1.16.160.0/19", NULL);
- do_test(table, "1.16.0.0/16", 18, "1.16.0.0/16", "1.16.128.0/18",
- "1.16.192.0/18", NULL);
-
- do_test(table, "1.16.0.0/16", 21, "1.16.0.0/16", "1.16.128.0/18",
+ do_test(table, "1.16.0.0/16", "1.16.0.0/16", "1.16.128.0/18",
"1.16.192.0/18", "1.16.64.0/19", "1.16.160.0/19",
"1.16.32.0/20", "1.16.32.0/21", NULL);
- do_test(table, "1.17.0.0/16", 20, NULL);
+ do_test(table, "1.17.0.0/16", NULL);
- do_test(table, "128.0.0.0/8", 16, NULL);
+ do_test(table, "128.0.0.0/8", NULL);
- do_test(table, "16.0.0.0/8", 16, "16.0.0.0/16", NULL);
+ do_test(table, "16.0.0.0/8", "16.0.0.0/16", NULL);
- do_test(table, "0.0.0.0/2", 21, "1.16.0.0/16", "1.16.128.0/18",
+ do_test(table, "0.0.0.0/2", "1.16.0.0/16", "1.16.128.0/18",
"1.16.192.0/18", "1.16.64.0/19", "1.16.160.0/19",
"1.16.32.0/20", "1.16.32.0/21", "16.0.0.0/16", NULL);
}
diff --git a/tests/bgpd/test_bgp_table.py b/tests/bgpd/test_bgp_table.py
index 4deaf08c22..53bd37233a 100644
--- a/tests/bgpd/test_bgp_table.py
+++ b/tests/bgpd/test_bgp_table.py
@@ -3,5 +3,5 @@ import frrtest
class TestTable(frrtest.TestMultiOut):
program = './test_bgp_table'
-for i in range(9):
+for i in range(7):
TestTable.onesimple('Checks successfull')
diff --git a/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py b/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py
index eb4f0d4a83..b1f755ad06 100755
--- a/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py
+++ b/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py
@@ -129,14 +129,6 @@ def setup_module(mod):
# Initialize all routers.
tgen.start_router()
- # Verify that we are using the proper version and that the BFD
- # daemon exists.
- for router in router_list.values():
- # Check for Version
- if router.has_version("<", "5.1"):
- tgen.set_error("Unsupported FRR version")
- break
-
def teardown_module(_mod):
"Teardown the pytest environment"
@@ -176,7 +168,7 @@ def test_bfd_connection():
test_func = partial(
topotest.router_json_cmp, router, "show bfd peers json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=16, wait=1)
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
@@ -220,7 +212,7 @@ def test_bgp_fast_convergence():
"show ip bgp vrf {}-cust1 json".format(router.name),
expected,
)
- _, res = topotest.run_and_expect(test_func, None, count=40, wait=0.5)
+ _, res = topotest.run_and_expect(test_func, None, count=40, wait=1)
assertmsg = "{}: bgp did not converge".format(router.name)
assert res is None, assertmsg
@@ -262,7 +254,7 @@ def test_bfd_fast_convergence():
test_func = partial(
topotest.router_json_cmp, router, "show bfd peers json", expected
)
- _, res = topotest.run_and_expect(test_func, None, count=20, wait=0.5)
+ _, res = topotest.run_and_expect(test_func, None, count=40, wait=1)
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert res is None, assertmsg
@@ -295,7 +287,7 @@ def test_bgp_fast_reconvergence():
"show ip bgp vrf {}-cust1 json".format(router.name),
expected,
)
- _, res = topotest.run_and_expect(test_func, None, count=3, wait=1)
+ _, res = topotest.run_and_expect(test_func, None, count=16, wait=1)
assertmsg = "{}: bgp did not converge".format(router.name)
assert res is None, assertmsg
diff --git a/tools/frr-reload.py b/tools/frr-reload.py
index bdba65ee2f..bf39dcc03f 100755
--- a/tools/frr-reload.py
+++ b/tools/frr-reload.py
@@ -146,9 +146,10 @@ class Vtysh(object):
return stdout.decode('UTF-8')
def mark_show_run(self, daemon = None):
- cmd = 'show running-config no-header'
+ cmd = 'show running-config'
if daemon:
cmd += ' %s' % daemon
+ cmd += ' no-header'
show_run = self._call_cmd(cmd, stdout=subprocess.PIPE)
mark = self._call(['-m', '-f', '-'], stdin=show_run.stdout, stdout=subprocess.PIPE)
@@ -504,7 +505,8 @@ end
"table ",
"username ",
"zebra ",
- "vrrp autoconfigure")
+ "vrrp autoconfigure",
+ "evpn mh")
for line in self.lines:
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index 88d5ab5cec..ef208bdc83 100644
--- a/zebra/dplane_fpm_nl.c
+++ b/zebra/dplane_fpm_nl.c
@@ -709,12 +709,13 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
switch (op) {
case DPLANE_OP_ROUTE_UPDATE:
case DPLANE_OP_ROUTE_DELETE:
- rv = netlink_route_multipath(RTM_DELROUTE, ctx, nl_buf,
- sizeof(nl_buf), true,
- fnc->use_nhg);
+ rv = netlink_route_multipath_msg_encode(RTM_DELROUTE, ctx,
+ nl_buf, sizeof(nl_buf),
+ true, fnc->use_nhg);
if (rv <= 0) {
- zlog_err("%s: netlink_route_multipath failed",
- __func__);
+ zlog_err(
+ "%s: netlink_route_multipath_msg_encode failed",
+ __func__);
return 0;
}
@@ -726,12 +727,13 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
/* FALL THROUGH */
case DPLANE_OP_ROUTE_INSTALL:
- rv = netlink_route_multipath(
+ rv = netlink_route_multipath_msg_encode(
RTM_NEWROUTE, ctx, &nl_buf[nl_buf_len],
sizeof(nl_buf) - nl_buf_len, true, fnc->use_nhg);
if (rv <= 0) {
- zlog_err("%s: netlink_route_multipath failed",
- __func__);
+ zlog_err(
+ "%s: netlink_route_multipath_msg_encode failed",
+ __func__);
return 0;
}
@@ -751,10 +753,11 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
break;
case DPLANE_OP_NH_DELETE:
- rv = netlink_nexthop_encode(RTM_DELNEXTHOP, ctx, nl_buf,
- sizeof(nl_buf));
+ rv = netlink_nexthop_msg_encode(RTM_DELNEXTHOP, ctx, nl_buf,
+ sizeof(nl_buf));
if (rv <= 0) {
- zlog_err("%s: netlink_nexthop_encode failed", __func__);
+ zlog_err("%s: netlink_nexthop_msg_encode failed",
+ __func__);
return 0;
}
@@ -762,10 +765,11 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
break;
case DPLANE_OP_NH_INSTALL:
case DPLANE_OP_NH_UPDATE:
- rv = netlink_nexthop_encode(RTM_NEWNEXTHOP, ctx, nl_buf,
- sizeof(nl_buf));
+ rv = netlink_nexthop_msg_encode(RTM_NEWNEXTHOP, ctx, nl_buf,
+ sizeof(nl_buf));
if (rv <= 0) {
- zlog_err("%s: netlink_nexthop_encode failed", __func__);
+ zlog_err("%s: netlink_nexthop_msg_encode failed",
+ __func__);
return 0;
}
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 7677db7efd..a29a810902 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -798,7 +798,7 @@ static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family,
/* Include filter, if specified. */
if (filter_mask)
- addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filter_mask);
+ nl_attr_put32(&req.n, sizeof(req), IFLA_EXT_MASK, filter_mask);
return netlink_request(netlink_cmd, &req);
}
@@ -903,8 +903,8 @@ int kernel_interface_set_master(struct interface *master,
req.ifa.ifi_index = slave->ifindex;
- addattr_l(&req.n, sizeof(req), IFLA_MASTER, &master->ifindex, 4);
- addattr_l(&req.n, sizeof(req), IFLA_LINK, &slave->ifindex, 4);
+ nl_attr_put32(&req.n, sizeof(req), IFLA_MASTER, master->ifindex);
+ nl_attr_put32(&req.n, sizeof(req), IFLA_LINK, slave->ifindex);
return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
0);
@@ -942,20 +942,20 @@ static int netlink_address_ctx(const struct zebra_dplane_ctx *ctx)
req.ifa.ifa_index = dplane_ctx_get_ifindex(ctx);
- addattr_l(&req.n, sizeof(req), IFA_LOCAL, &p->u.prefix, bytelen);
+ nl_attr_put(&req.n, sizeof(req), IFA_LOCAL, &p->u.prefix, bytelen);
if (p->family == AF_INET) {
if (dplane_ctx_intf_is_connected(ctx)) {
p = dplane_ctx_get_intf_dest(ctx);
- addattr_l(&req.n, sizeof(req), IFA_ADDRESS,
- &p->u.prefix, bytelen);
+ nl_attr_put(&req.n, sizeof(req), IFA_ADDRESS,
+ &p->u.prefix, bytelen);
} else if (cmd == RTM_NEWADDR) {
struct in_addr broad = {
.s_addr = ipv4_broadcast_addr(p->u.prefix4.s_addr,
p->prefixlen)
};
- addattr_l(&req.n, sizeof(req), IFA_BROADCAST,
- &broad, bytelen);
+ nl_attr_put(&req.n, sizeof(req), IFA_BROADCAST, &broad,
+ bytelen);
}
}
@@ -967,8 +967,8 @@ static int netlink_address_ctx(const struct zebra_dplane_ctx *ctx)
if (dplane_ctx_intf_has_label(ctx)) {
label = dplane_ctx_get_intf_label(ctx);
- addattr_l(&req.n, sizeof(req), IFA_LABEL, label,
- strlen(label) + 1);
+ nl_attr_put(&req.n, sizeof(req), IFA_LABEL, label,
+ strlen(label) + 1);
}
return netlink_talk_info(netlink_talk_filter, &req.n,
@@ -1520,8 +1520,8 @@ int netlink_protodown(struct interface *ifp, bool down)
req.ifa.ifi_index = ifp->ifindex;
- addattr_l(&req.n, sizeof(req), IFLA_PROTO_DOWN, &down, sizeof(down));
- addattr_l(&req.n, sizeof(req), IFLA_LINK, &ifp->ifindex, 4);
+ nl_attr_put(&req.n, sizeof(req), IFLA_PROTO_DOWN, &down, sizeof(down));
+ nl_attr_put32(&req.n, sizeof(req), IFLA_LINK, ifp->ifindex);
return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
0);
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index a1f7014ce9..75a8e9f17d 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -527,8 +527,8 @@ void netlink_parse_rtattr_nested(struct rtattr **tb, int max,
netlink_parse_rtattr(tb, max, RTA_DATA(rta), RTA_PAYLOAD(rta));
}
-int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
- const void *data, unsigned int alen)
+bool nl_attr_put(struct nlmsghdr *n, unsigned int maxlen, int type,
+ const void *data, unsigned int alen)
{
int len;
struct rtattr *rta;
@@ -536,7 +536,7 @@ int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
len = RTA_LENGTH(alen);
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen)
- return -1;
+ return false;
rta = (struct rtattr *)(((char *)n) + NLMSG_ALIGN(n->nlmsg_len));
rta->rta_type = type;
@@ -549,72 +549,56 @@ int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
- return 0;
-}
-
-int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type,
- const void *data, unsigned int alen)
-{
- unsigned int len;
- struct rtattr *subrta;
-
- len = RTA_LENGTH(alen);
-
- if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen)
- return -1;
-
- subrta = (struct rtattr *)(((char *)rta) + RTA_ALIGN(rta->rta_len));
- subrta->rta_type = type;
- subrta->rta_len = len;
-
- if (data)
- memcpy(RTA_DATA(subrta), data, alen);
- else
- assert(alen == 0);
-
- rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len);
-
- return 0;
+ return true;
}
-int addattr16(struct nlmsghdr *n, unsigned int maxlen, int type, uint16_t data)
+bool nl_attr_put16(struct nlmsghdr *n, unsigned int maxlen, int type,
+ uint16_t data)
{
- return addattr_l(n, maxlen, type, &data, sizeof(uint16_t));
+ return nl_attr_put(n, maxlen, type, &data, sizeof(uint16_t));
}
-int addattr32(struct nlmsghdr *n, unsigned int maxlen, int type, int data)
+bool nl_attr_put32(struct nlmsghdr *n, unsigned int maxlen, int type,
+ uint32_t data)
{
- return addattr_l(n, maxlen, type, &data, sizeof(uint32_t));
+ return nl_attr_put(n, maxlen, type, &data, sizeof(uint32_t));
}
-struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type)
+struct rtattr *nl_attr_nest(struct nlmsghdr *n, unsigned int maxlen, int type)
{
struct rtattr *nest = NLMSG_TAIL(n);
- addattr_l(n, maxlen, type, NULL, 0);
+ if (!nl_attr_put(n, maxlen, type, NULL, 0))
+ return NULL;
+
nest->rta_type |= NLA_F_NESTED;
return nest;
}
-int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest)
+int nl_attr_nest_end(struct nlmsghdr *n, struct rtattr *nest)
{
nest->rta_len = (uint8_t *)NLMSG_TAIL(n) - (uint8_t *)nest;
return n->nlmsg_len;
}
-struct rtattr *rta_nest(struct rtattr *rta, int maxlen, int type)
+struct rtnexthop *nl_attr_rtnh(struct nlmsghdr *n, unsigned int maxlen)
{
- struct rtattr *nest = RTA_TAIL(rta);
+ struct rtnexthop *rtnh = (struct rtnexthop *)NLMSG_TAIL(n);
- rta_addattr_l(rta, maxlen, type, NULL, 0);
- nest->rta_type |= NLA_F_NESTED;
- return nest;
+ if (NLMSG_ALIGN(n->nlmsg_len) + RTNH_ALIGN(sizeof(struct rtnexthop))
+ > maxlen)
+ return NULL;
+
+ memset(rtnh, 0, sizeof(struct rtnexthop));
+ n->nlmsg_len =
+ NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(sizeof(struct rtnexthop));
+
+ return rtnh;
}
-int rta_nest_end(struct rtattr *rta, struct rtattr *nest)
+void nl_attr_rtnh_end(struct nlmsghdr *n, struct rtnexthop *rtnh)
{
- nest->rta_len = (uint8_t *)RTA_TAIL(rta) - (uint8_t *)nest;
- return rta->rta_len;
+ rtnh->rtnh_len = (uint8_t *)NLMSG_TAIL(n) - (uint8_t *)rtnh;
}
const char *nl_msg_type_to_str(uint16_t msg_type)
diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h
index 6a4077abf6..bd8159faf3 100644
--- a/zebra/kernel_netlink.h
+++ b/zebra/kernel_netlink.h
@@ -30,22 +30,57 @@ extern "C" {
#define NL_RCV_PKT_BUF_SIZE 32768
#define NL_PKT_BUF_SIZE 8192
+/*
+ * nl_attr_put - add an attribute to the Netlink message.
+ *
+ * Returns true if the attribute could be added to the message (fits into the
+ * buffer), otherwise false is returned.
+ */
+extern bool nl_attr_put(struct nlmsghdr *n, unsigned int maxlen, int type,
+ const void *data, unsigned int alen);
+extern bool nl_attr_put16(struct nlmsghdr *n, unsigned int maxlen, int type,
+ uint16_t data);
+extern bool nl_attr_put32(struct nlmsghdr *n, unsigned int maxlen, int type,
+ uint32_t data);
+
+/*
+ * nl_attr_nest - start an attribute nest.
+ *
+ * Returns a valid pointer to the beginning of the nest if the attribute
+ * describing the nest could be added to the message (fits into the buffer),
+ * otherwise NULL is returned.
+ */
+extern struct rtattr *nl_attr_nest(struct nlmsghdr *n, unsigned int maxlen,
+ int type);
+
+/*
+ * nl_attr_nest_end - finalize nesting of attributes.
+ *
+ * Updates the length field of the attribute header to include the appeneded
+ * attributes. Returns a total length of the Netlink message.
+ */
+extern int nl_attr_nest_end(struct nlmsghdr *n, struct rtattr *nest);
+
+/*
+ * nl_attr_rtnh - append a rtnexthop record to the Netlink message.
+ *
+ * Returns a valid pointer to the rtnexthop struct if it could be added to
+ * the message (fits into the buffer), otherwise NULL is returned.
+ */
+extern struct rtnexthop *nl_attr_rtnh(struct nlmsghdr *n, unsigned int maxlen);
+
+/*
+ * nl_attr_rtnh_end - finalize adding a rtnexthop record.
+ *
+ * Updates the length field of the rtnexthop to include the appeneded
+ * attributes.
+ */
+extern void nl_attr_rtnh_end(struct nlmsghdr *n, struct rtnexthop *rtnh);
+
extern void netlink_parse_rtattr(struct rtattr **tb, int max,
struct rtattr *rta, int len);
extern void netlink_parse_rtattr_nested(struct rtattr **tb, int max,
struct rtattr *rta);
-extern int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
- const void *data, unsigned int alen);
-extern int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type,
- const void *data, unsigned int alen);
-extern int addattr16(struct nlmsghdr *n, unsigned int maxlen, int type,
- uint16_t data);
-extern int addattr32(struct nlmsghdr *n, unsigned int maxlen, int type,
- int data);
-extern struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type);
-extern int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest);
-extern struct rtattr *rta_nest(struct rtattr *rta, int maxlen, int type);
-extern int rta_nest_end(struct rtattr *rta, struct rtattr *nest);
extern const char *nl_msg_type_to_str(uint16_t msg_type);
extern const char *nl_rtproto_to_str(uint8_t rtproto);
extern const char *nl_family_to_str(uint8_t family);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 095c5570a2..9883e73876 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1029,11 +1029,15 @@ int netlink_route_read(struct zebra_ns *zns)
return 0;
}
-static void _netlink_route_nl_add_gateway_info(uint8_t route_family,
- uint8_t gw_family,
- struct nlmsghdr *nlmsg,
- size_t req_size, int bytelen,
- const struct nexthop *nexthop)
+/*
+ * The function returns true if the gateway info could be added
+ * to the message, otherwise false is returned.
+ */
+static bool _netlink_route_add_gateway_info(uint8_t route_family,
+ uint8_t gw_family,
+ struct nlmsghdr *nlmsg,
+ size_t req_size, int bytelen,
+ const struct nexthop *nexthop)
{
if (route_family == AF_MPLS) {
struct gw_family_t gw_fam;
@@ -1043,45 +1047,22 @@ static void _netlink_route_nl_add_gateway_info(uint8_t route_family,
memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
else
memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
- addattr_l(nlmsg, req_size, RTA_VIA, &gw_fam.family,
- bytelen + 2);
+ if (!nl_attr_put(nlmsg, req_size, RTA_VIA, &gw_fam.family,
+ bytelen + 2))
+ return false;
} else {
- if (gw_family == AF_INET)
- addattr_l(nlmsg, req_size, RTA_GATEWAY,
- &nexthop->gate.ipv4, bytelen);
- else
- addattr_l(nlmsg, req_size, RTA_GATEWAY,
- &nexthop->gate.ipv6, bytelen);
+ if (gw_family == AF_INET) {
+ if (!nl_attr_put(nlmsg, req_size, RTA_GATEWAY,
+ &nexthop->gate.ipv4, bytelen))
+ return false;
+ } else {
+ if (!nl_attr_put(nlmsg, req_size, RTA_GATEWAY,
+ &nexthop->gate.ipv6, bytelen))
+ return false;
+ }
}
-}
-
-static void _netlink_route_rta_add_gateway_info(uint8_t route_family,
- uint8_t gw_family,
- struct rtattr *rta,
- struct rtnexthop *rtnh,
- size_t req_size, int bytelen,
- const struct nexthop *nexthop)
-{
- if (route_family == AF_MPLS) {
- struct gw_family_t gw_fam;
- gw_fam.family = gw_family;
- if (gw_family == AF_INET)
- memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
- else
- memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
- rta_addattr_l(rta, req_size, RTA_VIA, &gw_fam.family,
- bytelen + 2);
- rtnh->rtnh_len += RTA_LENGTH(bytelen + 2);
- } else {
- if (gw_family == AF_INET)
- rta_addattr_l(rta, req_size, RTA_GATEWAY,
- &nexthop->gate.ipv4, bytelen);
- else
- rta_addattr_l(rta, req_size, RTA_GATEWAY,
- &nexthop->gate.ipv6, bytelen);
- rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
- }
+ return true;
}
static int build_label_stack(struct mpls_label_stack *nh_label,
@@ -1114,6 +1095,86 @@ static int build_label_stack(struct mpls_label_stack *nh_label,
return num_labels;
}
+static bool _netlink_route_encode_label_info(struct mpls_label_stack *nh_label,
+ struct nlmsghdr *nlmsg,
+ size_t buflen, struct rtmsg *rtmsg,
+ char *label_buf,
+ size_t label_buf_size)
+{
+ mpls_lse_t out_lse[MPLS_MAX_LABELS];
+ int num_labels;
+
+ /*
+ * label_buf is *only* currently used within debugging.
+ * As such when we assign it we are guarding it inside
+ * a debug test. If you want to change this make sure
+ * you fix this assumption
+ */
+ label_buf[0] = '\0';
+
+ num_labels =
+ build_label_stack(nh_label, out_lse, label_buf, label_buf_size);
+
+ if (num_labels) {
+ /* Set the BoS bit */
+ out_lse[num_labels - 1] |= htonl(1 << MPLS_LS_S_SHIFT);
+
+ if (rtmsg->rtm_family == AF_MPLS) {
+ if (!nl_attr_put(nlmsg, buflen, RTA_NEWDST, &out_lse,
+ num_labels * sizeof(mpls_lse_t)))
+ return false;
+ } else {
+ struct rtattr *nest;
+
+ if (!nl_attr_put16(nlmsg, buflen, RTA_ENCAP_TYPE,
+ LWTUNNEL_ENCAP_MPLS))
+ return false;
+
+ nest = nl_attr_nest(nlmsg, buflen, RTA_ENCAP);
+ if (!nest)
+ return false;
+
+ if (!nl_attr_put(nlmsg, buflen, MPLS_IPTUNNEL_DST,
+ &out_lse,
+ num_labels * sizeof(mpls_lse_t)))
+ return false;
+ nl_attr_nest_end(nlmsg, nest);
+ }
+ }
+
+ return true;
+}
+
+static bool _netlink_route_encode_nexthop_src(const struct nexthop *nexthop,
+ int family,
+ struct nlmsghdr *nlmsg,
+ size_t buflen, int bytelen)
+{
+ if (family == AF_INET) {
+ if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY) {
+ if (!nl_attr_put(nlmsg, buflen, RTA_PREFSRC,
+ &nexthop->rmap_src.ipv4, bytelen))
+ return false;
+ } else if (nexthop->src.ipv4.s_addr != INADDR_ANY) {
+ if (!nl_attr_put(nlmsg, buflen, RTA_PREFSRC,
+ &nexthop->src.ipv4, bytelen))
+ return false;
+ }
+ } else if (family == AF_INET6) {
+ if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) {
+ if (!nl_attr_put(nlmsg, buflen, RTA_PREFSRC,
+ &nexthop->rmap_src.ipv6, bytelen))
+ return false;
+ } else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) {
+ if (!nl_attr_put(nlmsg, buflen, RTA_PREFSRC,
+ &nexthop->src.ipv6, bytelen))
+ return false;
+ }
+ }
+
+ return true;
+}
+
/* This function takes a nexthop as argument and adds
* the appropriate netlink attributes to an existing
* netlink message.
@@ -1124,8 +1185,11 @@ static int build_label_stack(struct mpls_label_stack *nh_label,
* @param nexthop: Nexthop information
* @param nlmsg: nlmsghdr structure to fill in.
* @param req_size: The size allocated for the message.
+ *
+ * The function returns true if the nexthop could be added
+ * to the message, otherwise false is returned.
*/
-static void _netlink_route_build_singlepath(const struct prefix *p,
+static bool _netlink_route_build_singlepath(const struct prefix *p,
const char *routedesc, int bytelen,
const struct nexthop *nexthop,
struct nlmsghdr *nlmsg,
@@ -1133,9 +1197,7 @@ static void _netlink_route_build_singlepath(const struct prefix *p,
size_t req_size, int cmd)
{
- mpls_lse_t out_lse[MPLS_MAX_LABELS];
char label_buf[256];
- int num_labels = 0;
struct vrf *vrf;
char addrstr[INET6_ADDRSTRLEN];
@@ -1143,77 +1205,49 @@ static void _netlink_route_build_singlepath(const struct prefix *p,
vrf = vrf_lookup_by_id(nexthop->vrf_id);
- /*
- * label_buf is *only* currently used within debugging.
- * As such when we assign it we are guarding it inside
- * a debug test. If you want to change this make sure
- * you fix this assumption
- */
- label_buf[0] = '\0';
-
- num_labels = build_label_stack(nexthop->nh_label, out_lse, label_buf,
- sizeof(label_buf));
-
- if (num_labels) {
- /* Set the BoS bit */
- out_lse[num_labels - 1] |= htonl(1 << MPLS_LS_S_SHIFT);
-
- if (rtmsg->rtm_family == AF_MPLS)
- addattr_l(nlmsg, req_size, RTA_NEWDST, &out_lse,
- num_labels * sizeof(mpls_lse_t));
- else {
- struct rtattr *nest;
- uint16_t encap = LWTUNNEL_ENCAP_MPLS;
-
- addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE, &encap,
- sizeof(uint16_t));
- nest = addattr_nest(nlmsg, req_size, RTA_ENCAP);
- addattr_l(nlmsg, req_size, MPLS_IPTUNNEL_DST, &out_lse,
- num_labels * sizeof(mpls_lse_t));
- addattr_nest_end(nlmsg, nest);
- }
- }
+ if (!_netlink_route_encode_label_info(nexthop->nh_label, nlmsg,
+ req_size, rtmsg, label_buf,
+ sizeof(label_buf)))
+ return false;
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
rtmsg->rtm_flags |= RTNH_F_ONLINK;
if (is_route_v4_over_v6(rtmsg->rtm_family, nexthop->type)) {
rtmsg->rtm_flags |= RTNH_F_ONLINK;
- addattr_l(nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4);
- addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
-
- if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY
- && (cmd == RTM_NEWROUTE))
- addattr_l(nlmsg, req_size, RTA_PREFSRC,
- &nexthop->rmap_src.ipv4, bytelen);
- else if (nexthop->src.ipv4.s_addr != INADDR_ANY
- && (cmd == RTM_NEWROUTE))
- addattr_l(nlmsg, req_size, RTA_PREFSRC,
- &nexthop->src.ipv4, bytelen);
+ if (!nl_attr_put(nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4))
+ return false;
+ if (!nl_attr_put32(nlmsg, req_size, RTA_OIF, nexthop->ifindex))
+ return false;
+
+ if (cmd == RTM_NEWROUTE) {
+ if (!_netlink_route_encode_nexthop_src(
+ nexthop, AF_INET, nlmsg, req_size, bytelen))
+ return false;
+ }
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("%s: 5549 (%s): %pFX nexthop via %s %s if %u vrf %s(%u)",
__func__, routedesc, p, ipv4_ll_buf,
label_buf, nexthop->ifindex,
VRF_LOGNAME(vrf), nexthop->vrf_id);
- return;
+ return true;
}
if (nexthop->type == NEXTHOP_TYPE_IPV4
|| nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
/* Send deletes to the kernel without specifying the next-hop */
- if (cmd != RTM_DELROUTE)
- _netlink_route_nl_add_gateway_info(
- rtmsg->rtm_family, AF_INET, nlmsg, req_size,
- bytelen, nexthop);
+ if (cmd != RTM_DELROUTE) {
+ if (!_netlink_route_add_gateway_info(
+ rtmsg->rtm_family, AF_INET, nlmsg, req_size,
+ bytelen, nexthop))
+ return false;
+ }
if (cmd == RTM_NEWROUTE) {
- if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY)
- addattr_l(nlmsg, req_size, RTA_PREFSRC,
- &nexthop->rmap_src.ipv4, bytelen);
- else if (nexthop->src.ipv4.s_addr != INADDR_ANY)
- addattr_l(nlmsg, req_size, RTA_PREFSRC,
- &nexthop->src.ipv4, bytelen);
+ if (!_netlink_route_encode_nexthop_src(
+ nexthop, AF_INET, nlmsg, req_size, bytelen))
+ return false;
}
if (IS_ZEBRA_DEBUG_KERNEL) {
@@ -1228,17 +1262,16 @@ static void _netlink_route_build_singlepath(const struct prefix *p,
if (nexthop->type == NEXTHOP_TYPE_IPV6
|| nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
- _netlink_route_nl_add_gateway_info(rtmsg->rtm_family, AF_INET6,
- nlmsg, req_size, bytelen,
- nexthop);
+ if (!_netlink_route_add_gateway_info(rtmsg->rtm_family,
+ AF_INET6, nlmsg, req_size,
+ bytelen, nexthop))
+ return false;
if (cmd == RTM_NEWROUTE) {
- if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
- addattr_l(nlmsg, req_size, RTA_PREFSRC,
- &nexthop->rmap_src.ipv6, bytelen);
- else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
- addattr_l(nlmsg, req_size, RTA_PREFSRC,
- &nexthop->src.ipv6, bytelen);
+ if (!_netlink_route_encode_nexthop_src(
+ nexthop, AF_INET6, nlmsg, req_size,
+ bytelen))
+ return false;
}
if (IS_ZEBRA_DEBUG_KERNEL) {
@@ -1256,17 +1289,16 @@ static void _netlink_route_build_singlepath(const struct prefix *p,
* This is especially useful if we are doing route
* leaking.
*/
- if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
- addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
+ if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE) {
+ if (!nl_attr_put32(nlmsg, req_size, RTA_OIF, nexthop->ifindex))
+ return false;
+ }
if (nexthop->type == NEXTHOP_TYPE_IFINDEX) {
if (cmd == RTM_NEWROUTE) {
- if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY)
- addattr_l(nlmsg, req_size, RTA_PREFSRC,
- &nexthop->rmap_src.ipv4, bytelen);
- else if (nexthop->src.ipv4.s_addr != INADDR_ANY)
- addattr_l(nlmsg, req_size, RTA_PREFSRC,
- &nexthop->src.ipv4, bytelen);
+ if (!_netlink_route_encode_nexthop_src(
+ nexthop, AF_INET, nlmsg, req_size, bytelen))
+ return false;
}
if (IS_ZEBRA_DEBUG_KERNEL)
@@ -1274,11 +1306,12 @@ static void _netlink_route_build_singlepath(const struct prefix *p,
__func__, routedesc, p, nexthop->ifindex,
VRF_LOGNAME(vrf), nexthop->vrf_id);
}
+
+ return true;
}
/* This function takes a nexthop as argument and
- * appends to the given rtattr/rtnexthop pair the
- * representation of the nexthop. If the nexthop
+ * appends to the given netlink msg. If the nexthop
* defines a preferred source, the src parameter
* will be modified to point to that src, otherwise
* it will be kept unmodified.
@@ -1287,77 +1320,45 @@ static void _netlink_route_build_singlepath(const struct prefix *p,
* (direct/recursive, single-/multipath)
* @param bytelen: Length of addresses in bytes.
* @param nexthop: Nexthop information
- * @param rta: rtnetlink attribute structure
- * @param rtnh: pointer to an rtnetlink nexthop structure
+ * @param nlmsg: nlmsghdr structure to fill in.
+ * @param req_size: The size allocated for the message.
* @param src: pointer pointing to a location where
* the prefsrc should be stored.
+ *
+ * The function returns true if the nexthop could be added
+ * to the message, otherwise false is returned.
*/
-static void
-_netlink_route_build_multipath(const struct prefix *p, const char *routedesc,
- int bytelen, const struct nexthop *nexthop,
- struct rtattr *rta, struct rtnexthop *rtnh,
- struct rtmsg *rtmsg, const union g_addr **src)
+static bool _netlink_route_build_multipath(const struct prefix *p,
+ const char *routedesc, int bytelen,
+ const struct nexthop *nexthop,
+ struct nlmsghdr *nlmsg,
+ size_t req_size, struct rtmsg *rtmsg,
+ const union g_addr **src)
{
- mpls_lse_t out_lse[MPLS_MAX_LABELS];
char label_buf[256];
- int num_labels = 0;
struct vrf *vrf;
+ struct rtnexthop *rtnh;
- rtnh->rtnh_len = sizeof(*rtnh);
- rtnh->rtnh_flags = 0;
- rtnh->rtnh_hops = 0;
- rta->rta_len += rtnh->rtnh_len;
+ rtnh = nl_attr_rtnh(nlmsg, req_size);
+ if (rtnh == NULL)
+ return false;
assert(nexthop);
vrf = vrf_lookup_by_id(nexthop->vrf_id);
- /*
- * label_buf is *only* currently used within debugging.
- * As such when we assign it we are guarding it inside
- * a debug test. If you want to change this make sure
- * you fix this assumption
- */
- label_buf[0] = '\0';
-
- num_labels = build_label_stack(nexthop->nh_label, out_lse, label_buf,
- sizeof(label_buf));
-
- if (num_labels) {
- /* Set the BoS bit */
- out_lse[num_labels - 1] |= htonl(1 << MPLS_LS_S_SHIFT);
-
- if (rtmsg->rtm_family == AF_MPLS) {
- rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_NEWDST,
- &out_lse,
- num_labels * sizeof(mpls_lse_t));
- rtnh->rtnh_len +=
- RTA_LENGTH(num_labels * sizeof(mpls_lse_t));
- } else {
- struct rtattr *nest;
- uint16_t encap = LWTUNNEL_ENCAP_MPLS;
- int len = rta->rta_len;
-
- rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_ENCAP_TYPE,
- &encap, sizeof(uint16_t));
- nest = rta_nest(rta, NL_PKT_BUF_SIZE, RTA_ENCAP);
- rta_addattr_l(rta, NL_PKT_BUF_SIZE, MPLS_IPTUNNEL_DST,
- &out_lse,
- num_labels * sizeof(mpls_lse_t));
- rta_nest_end(rta, nest);
- rtnh->rtnh_len += rta->rta_len - len;
- }
- }
+ if (!_netlink_route_encode_label_info(nexthop->nh_label, nlmsg,
+ req_size, rtmsg, label_buf,
+ sizeof(label_buf)))
+ return false;
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
rtnh->rtnh_flags |= RTNH_F_ONLINK;
if (is_route_v4_over_v6(rtmsg->rtm_family, nexthop->type)) {
- bytelen = 4;
rtnh->rtnh_flags |= RTNH_F_ONLINK;
- rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_GATEWAY, &ipv4_ll,
- bytelen);
- rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
+ if (!nl_attr_put(nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4))
+ return false;
rtnh->rtnh_ifindex = nexthop->ifindex;
if (nexthop->weight)
rtnh->rtnh_hops = nexthop->weight - 1;
@@ -1373,14 +1374,17 @@ _netlink_route_build_multipath(const struct prefix *p, const char *routedesc,
__func__, routedesc, p, ipv4_ll_buf, label_buf,
nexthop->ifindex, VRF_LOGNAME(vrf),
nexthop->vrf_id);
- return;
+ nl_attr_rtnh_end(nlmsg, rtnh);
+ return true;
}
if (nexthop->type == NEXTHOP_TYPE_IPV4
|| nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
- _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET,
- rta, rtnh, NL_PKT_BUF_SIZE,
- bytelen, nexthop);
+ if (!_netlink_route_add_gateway_info(rtmsg->rtm_family, AF_INET,
+ nlmsg, req_size, bytelen,
+ nexthop))
+ return false;
+
if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY)
*src = &nexthop->rmap_src;
else if (nexthop->src.ipv4.s_addr != INADDR_ANY)
@@ -1394,9 +1398,10 @@ _netlink_route_build_multipath(const struct prefix *p, const char *routedesc,
}
if (nexthop->type == NEXTHOP_TYPE_IPV6
|| nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
- _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET6,
- rta, rtnh, NL_PKT_BUF_SIZE,
- bytelen, nexthop);
+ if (!_netlink_route_add_gateway_info(rtmsg->rtm_family,
+ AF_INET6, nlmsg, req_size,
+ bytelen, nexthop))
+ return false;
if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
*src = &nexthop->rmap_src;
@@ -1433,9 +1438,12 @@ _netlink_route_build_multipath(const struct prefix *p, const char *routedesc,
if (nexthop->weight)
rtnh->rtnh_hops = nexthop->weight - 1;
+
+ nl_attr_rtnh_end(nlmsg, rtnh);
+ return true;
}
-static inline void _netlink_mpls_build_singlepath(const struct prefix *p,
+static inline bool _netlink_mpls_build_singlepath(const struct prefix *p,
const char *routedesc,
const zebra_nhlfe_t *nhlfe,
struct nlmsghdr *nlmsg,
@@ -1447,31 +1455,33 @@ static inline void _netlink_mpls_build_singlepath(const struct prefix *p,
family = NHLFE_FAMILY(nhlfe);
bytelen = (family == AF_INET ? 4 : 16);
- _netlink_route_build_singlepath(p, routedesc, bytelen, nhlfe->nexthop,
- nlmsg, rtmsg, req_size, cmd);
+ return _netlink_route_build_singlepath(p, routedesc, bytelen,
+ nhlfe->nexthop, nlmsg, rtmsg,
+ req_size, cmd);
}
-static inline void
+static inline bool
_netlink_mpls_build_multipath(const struct prefix *p, const char *routedesc,
- const zebra_nhlfe_t *nhlfe, struct rtattr *rta,
- struct rtnexthop *rtnh, struct rtmsg *rtmsg,
- const union g_addr **src)
+ const zebra_nhlfe_t *nhlfe,
+ struct nlmsghdr *nlmsg, size_t req_size,
+ struct rtmsg *rtmsg, const union g_addr **src)
{
int bytelen;
uint8_t family;
family = NHLFE_FAMILY(nhlfe);
bytelen = (family == AF_INET ? 4 : 16);
- _netlink_route_build_multipath(p, routedesc, bytelen, nhlfe->nexthop,
- rta, rtnh, rtmsg, src);
+ return _netlink_route_build_multipath(p, routedesc, bytelen,
+ nhlfe->nexthop, nlmsg, req_size,
+ rtmsg, src);
}
static void _netlink_mpls_debug(int cmd, uint32_t label, const char *routedesc)
{
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("netlink_mpls_multipath() (%s): %s %u/20", routedesc,
- nl_msg_type_to_str(cmd), label);
+ zlog_debug("netlink_mpls_multipath_msg_encode() (%s): %s %u/20",
+ routedesc, nl_msg_type_to_str(cmd), label);
}
static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
@@ -1498,10 +1508,10 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
req.ndm.ndm_ifindex = ifindex;
req.ndm.ndm_type = RTN_UNICAST;
- addattr_l(&req.n, sizeof(req),
- NDA_PROTOCOL, &protocol, sizeof(protocol));
- addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
- addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
+ nl_attr_put(&req.n, sizeof(req), NDA_PROTOCOL, &protocol,
+ sizeof(protocol));
+ nl_attr_put32(&req.n, sizeof(req), NDA_DST, addr);
+ nl_attr_put(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
0);
@@ -1531,29 +1541,44 @@ static bool nexthop_set_src(const struct nexthop *nexthop, int family,
return false;
}
-static void netlink_route_nexthop_encap(struct nlmsghdr *n, size_t nlen,
- struct nexthop *nh)
+/*
+ * The function returns true if the attribute could be added
+ * to the message, otherwise false is returned.
+ */
+static int netlink_route_nexthop_encap(struct nlmsghdr *n, size_t nlen,
+ struct nexthop *nh)
{
struct rtattr *nest;
switch (nh->nh_encap_type) {
case NET_VXLAN:
- addattr_l(n, nlen, RTA_ENCAP_TYPE, &nh->nh_encap_type,
- sizeof(uint16_t));
+ if (!nl_attr_put16(n, nlen, RTA_ENCAP_TYPE, nh->nh_encap_type))
+ return false;
+
+ nest = nl_attr_nest(n, nlen, RTA_ENCAP);
+ if (!nest)
+ return false;
- nest = addattr_nest(n, nlen, RTA_ENCAP);
- addattr32(n, nlen, 0 /* VXLAN_VNI */, nh->nh_encap.vni);
- addattr_nest_end(n, nest);
+ if (!nl_attr_put32(n, nlen, 0 /* VXLAN_VNI */,
+ nh->nh_encap.vni))
+ return false;
+ nl_attr_nest_end(n, nest);
break;
}
+
+ return true;
}
/*
* Routing table change via netlink interface, using a dataplane context object
+ *
+ * Returns -1 on failure, 0 when the msg doesn't fit entirely in the buffer
+ * otherwise the number of bytes written to buf.
*/
-ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
- uint8_t *data, size_t datalen, bool fpm,
- bool force_nhg)
+ssize_t netlink_route_multipath_msg_encode(int cmd,
+ struct zebra_dplane_ctx *ctx,
+ uint8_t *data, size_t datalen,
+ bool fpm, bool force_nhg)
{
int bytelen;
struct nexthop *nexthop = NULL;
@@ -1573,6 +1598,9 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
p = dplane_ctx_get_dest(ctx);
src_p = dplane_ctx_get_src(ctx);
+ if (datalen < sizeof(*req))
+ return 0;
+
memset(req, 0, sizeof(*req));
bytelen = (p->family == AF_INET ? 4 : 16);
@@ -1609,9 +1637,13 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
if (cmd != RTM_DELROUTE)
req->r.rtm_type = RTN_UNICAST;
- addattr_l(&req->n, datalen, RTA_DST, &p->u.prefix, bytelen);
- if (src_p)
- addattr_l(&req->n, datalen, RTA_SRC, &src_p->u.prefix, bytelen);
+ if (!nl_attr_put(&req->n, datalen, RTA_DST, &p->u.prefix, bytelen))
+ return 0;
+ if (src_p) {
+ if (!nl_attr_put(&req->n, datalen, RTA_SRC, &src_p->u.prefix,
+ bytelen))
+ return 0;
+ }
/* Metric. */
/* Hardcode the metric for all routes coming from zebra. Metric isn't
@@ -1620,7 +1652,9 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
* path(s)
* by the routing protocol and for communicating with protocol peers.
*/
- addattr32(&req->n, datalen, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
+ if (!nl_attr_put32(&req->n, datalen, RTA_PRIORITY,
+ NL_DEFAULT_ROUTE_METRIC))
+ return 0;
#if defined(SUPPORT_REALMS)
{
@@ -1631,8 +1665,10 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
else
tag = dplane_ctx_get_tag(ctx);
- if (tag > 0 && tag <= 255)
- addattr32(&req->n, datalen, RTA_FLOW, tag);
+ if (tag > 0 && tag <= 255) {
+ if (!nl_attr_put32(&req->n, datalen, RTA_FLOW, tag))
+ return 0;
+ }
}
#endif
/* Table corresponding to this route. */
@@ -1641,7 +1677,8 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
req->r.rtm_table = table_id;
else {
req->r.rtm_table = RT_TABLE_UNSPEC;
- addattr32(&req->n, datalen, RTA_TABLE, table_id);
+ if (!nl_attr_put32(&req->n, datalen, RTA_TABLE, table_id))
+ return 0;
}
if (IS_ZEBRA_DEBUG_KERNEL)
@@ -1657,33 +1694,34 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
* it.
*/
if (cmd == RTM_DELROUTE)
- return req->n.nlmsg_len;
+ return NLMSG_ALIGN(req->n.nlmsg_len);
if (dplane_ctx_get_mtu(ctx) || dplane_ctx_get_nh_mtu(ctx)) {
- char buf[NL_PKT_BUF_SIZE];
- struct rtattr *rta = (void *)buf;
+ struct rtattr *nest;
uint32_t mtu = dplane_ctx_get_mtu(ctx);
uint32_t nexthop_mtu = dplane_ctx_get_nh_mtu(ctx);
if (!mtu || (nexthop_mtu && nexthop_mtu < mtu))
mtu = nexthop_mtu;
- rta->rta_type = RTA_METRICS;
- rta->rta_len = RTA_LENGTH(0);
- rta_addattr_l(rta, NL_PKT_BUF_SIZE,
- RTAX_MTU, &mtu, sizeof(mtu));
- addattr_l(&req->n, datalen, RTA_METRICS, RTA_DATA(rta),
- RTA_PAYLOAD(rta));
+
+ nest = nl_attr_nest(&req->n, datalen, RTA_METRICS);
+ if (nest == NULL)
+ return 0;
+
+ if (!nl_attr_put(&req->n, datalen, RTAX_MTU, &mtu, sizeof(mtu)))
+ return 0;
+ nl_attr_nest_end(&req->n, nest);
}
if (kernel_nexthops_supported() || force_nhg) {
/* Kernel supports nexthop objects */
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "netlink_route_multipath(): %pFX nhg_id is %u",
- p, dplane_ctx_get_nhe_id(ctx));
+ zlog_debug("%s: %pFX nhg_id is %u", __func__, p,
+ dplane_ctx_get_nhe_id(ctx));
- addattr32(&req->n, datalen, RTA_NH_ID,
- dplane_ctx_get_nhe_id(ctx));
+ if (!nl_attr_put32(&req->n, datalen, RTA_NH_ID,
+ dplane_ctx_get_nhe_id(ctx)))
+ return 0;
/* Have to determine src still */
for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
@@ -1694,15 +1732,18 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
}
if (setsrc) {
- if (p->family == AF_INET)
- addattr_l(&req->n, datalen, RTA_PREFSRC,
- &src.ipv4, bytelen);
- else if (p->family == AF_INET6)
- addattr_l(&req->n, datalen, RTA_PREFSRC,
- &src.ipv6, bytelen);
+ if (p->family == AF_INET) {
+ if (!nl_attr_put(&req->n, datalen, RTA_PREFSRC,
+ &src.ipv4, bytelen))
+ return 0;
+ } else if (p->family == AF_INET6) {
+ if (!nl_attr_put(&req->n, datalen, RTA_PREFSRC,
+ &src.ipv6, bytelen))
+ return 0;
+ }
}
- return req->n.nlmsg_len;
+ return NLMSG_ALIGN(req->n.nlmsg_len);
}
/* Count overall nexthops so we can decide whether to use singlepath
@@ -1741,7 +1782,7 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
req->r.rtm_type = RTN_BLACKHOLE;
break;
}
- return req->n.nlmsg_len;
+ return NLMSG_ALIGN(req->n.nlmsg_len);
}
if (CHECK_FLAG(nexthop->flags,
NEXTHOP_FLAG_RECURSIVE)) {
@@ -1759,9 +1800,10 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
? "recursive, single-path"
: "single-path";
- _netlink_route_build_singlepath(
- p, routedesc, bytelen, nexthop, &req->n,
- &req->r, datalen, cmd);
+ if (!_netlink_route_build_singlepath(
+ p, routedesc, bytelen, nexthop,
+ &req->n, &req->r, datalen, cmd))
+ return 0;
nexthop_num++;
break;
}
@@ -1770,28 +1812,31 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
* Add encapsulation information when installing via
* FPM.
*/
- if (fpm)
- netlink_route_nexthop_encap(&req->n, datalen,
- nexthop);
+ if (fpm) {
+ if (!netlink_route_nexthop_encap(
+ &req->n, datalen, nexthop))
+ return 0;
+ }
}
if (setsrc) {
- if (p->family == AF_INET)
- addattr_l(&req->n, datalen, RTA_PREFSRC,
- &src.ipv4, bytelen);
- else if (p->family == AF_INET6)
- addattr_l(&req->n, datalen, RTA_PREFSRC,
- &src.ipv6, bytelen);
+ if (p->family == AF_INET) {
+ if (!nl_attr_put(&req->n, datalen, RTA_PREFSRC,
+ &src.ipv4, bytelen))
+ return 0;
+ } else if (p->family == AF_INET6) {
+ if (!nl_attr_put(&req->n, datalen, RTA_PREFSRC,
+ &src.ipv6, bytelen))
+ return 0;
+ }
}
} else { /* Multipath case */
- char buf[NL_PKT_BUF_SIZE];
- struct rtattr *rta = (void *)buf;
- struct rtnexthop *rtnh;
+ struct rtattr *nest;
const union g_addr *src1 = NULL;
- rta->rta_type = RTA_MULTIPATH;
- rta->rta_len = RTA_LENGTH(0);
- rtnh = RTA_DATA(rta);
+ nest = nl_attr_nest(&req->n, datalen, RTA_MULTIPATH);
+ if (nest == NULL)
+ return 0;
nexthop_num = 0;
for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
@@ -1812,10 +1857,10 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
: "multipath";
nexthop_num++;
- _netlink_route_build_multipath(
- p, routedesc, bytelen, nexthop, rta,
- rtnh, &req->r, &src1);
- rtnh = RTNH_NEXT(rtnh);
+ if (!_netlink_route_build_multipath(
+ p, routedesc, bytelen, nexthop,
+ &req->n, datalen, &req->r, &src1))
+ return 0;
if (!setsrc && src1) {
if (p->family == AF_INET)
@@ -1826,30 +1871,40 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
setsrc = 1;
}
}
+ }
- /*
- * Add encapsulation information when installing via
- * FPM.
- */
- if (fpm)
- netlink_route_nexthop_encap(&req->n, datalen,
- nexthop);
+ nl_attr_nest_end(&req->n, nest);
+
+ /*
+ * Add encapsulation information when installing via
+ * FPM.
+ */
+ if (fpm) {
+ for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx),
+ nexthop)) {
+ if (CHECK_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_RECURSIVE))
+ continue;
+ if (!netlink_route_nexthop_encap(
+ &req->n, datalen, nexthop))
+ return 0;
+ }
}
+
if (setsrc) {
- if (p->family == AF_INET)
- addattr_l(&req->n, datalen, RTA_PREFSRC,
- &src.ipv4, bytelen);
- else if (p->family == AF_INET6)
- addattr_l(&req->n, datalen, RTA_PREFSRC,
- &src.ipv6, bytelen);
+ if (p->family == AF_INET) {
+ if (!nl_attr_put(&req->n, datalen, RTA_PREFSRC,
+ &src.ipv4, bytelen))
+ return 0;
+ } else if (p->family == AF_INET6) {
+ if (!nl_attr_put(&req->n, datalen, RTA_PREFSRC,
+ &src.ipv6, bytelen))
+ return 0;
+ }
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("Setting source");
}
-
- if (rta->rta_len > RTA_LENGTH(0))
- addattr_l(&req->n, datalen, RTA_MULTIPATH,
- RTA_DATA(rta), RTA_PAYLOAD(rta));
}
/* If there is no useful nexthop then return. */
@@ -1858,7 +1913,7 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
zlog_debug("%s: No useful nexthop.", __func__);
}
- return req->n.nlmsg_len;
+ return NLMSG_ALIGN(req->n.nlmsg_len);
}
int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
@@ -1885,10 +1940,10 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
req.ndm.ndm_family = RTNL_FAMILY_IPMR;
req.n.nlmsg_type = RTM_GETROUTE;
- addattr_l(&req.n, sizeof(req), RTA_IIF, &mroute->ifindex, 4);
- addattr_l(&req.n, sizeof(req), RTA_OIF, &mroute->ifindex, 4);
- addattr_l(&req.n, sizeof(req), RTA_SRC, &mroute->sg.src.s_addr, 4);
- addattr_l(&req.n, sizeof(req), RTA_DST, &mroute->sg.grp.s_addr, 4);
+ nl_attr_put32(&req.n, sizeof(req), RTA_IIF, mroute->ifindex);
+ nl_attr_put32(&req.n, sizeof(req), RTA_OIF, mroute->ifindex);
+ nl_attr_put32(&req.n, sizeof(req), RTA_SRC, mroute->sg.src.s_addr);
+ nl_attr_put32(&req.n, sizeof(req), RTA_DST, mroute->sg.grp.s_addr);
/*
* What?
*
@@ -1905,7 +1960,7 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
*/
actual_table = (zvrf->table_id == RT_TABLE_MAIN) ? RT_TABLE_DEFAULT :
zvrf->table_id;
- addattr_l(&req.n, sizeof(req), RTA_TABLE, &actual_table, 4);
+ nl_attr_put32(&req.n, sizeof(req), RTA_TABLE, actual_table);
suc = netlink_talk(netlink_route_change_read_multicast, &req.n,
&zns->netlink_cmd, zns, 0);
@@ -1917,7 +1972,7 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
/* Char length to debug ID with */
#define ID_LENGTH 10
-static void _netlink_nexthop_build_group(struct nlmsghdr *n, size_t req_size,
+static bool _netlink_nexthop_build_group(struct nlmsghdr *n, size_t req_size,
uint32_t id,
const struct nh_grp *z_grp,
const uint8_t count)
@@ -1947,11 +2002,15 @@ static void _netlink_nexthop_build_group(struct nlmsghdr *n, size_t req_size,
}
}
}
- addattr_l(n, req_size, NHA_GROUP, grp, count * sizeof(*grp));
+ if (!nl_attr_put(n, req_size, NHA_GROUP, grp,
+ count * sizeof(*grp)))
+ return false;
}
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("%s: ID (%u): %s", __func__, id, buf);
+
+ return true;
}
/**
@@ -1962,10 +2021,12 @@ static void _netlink_nexthop_build_group(struct nlmsghdr *n, size_t req_size,
* \param[out] buf buffer to hold the packet.
* \param[in] buflen amount of buffer bytes.
*
- * \returns -1 on failure or the number of bytes written to buf.
+ * \returns -1 on failure, 0 when the msg doesn't fit entirely in the buffer
+ * otherwise the number of bytes written to buf.
*/
-ssize_t netlink_nexthop_encode(uint16_t cmd, const struct zebra_dplane_ctx *ctx,
- void *buf, size_t buflen)
+ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
+ const struct zebra_dplane_ctx *ctx,
+ void *buf, size_t buflen)
{
struct {
struct nlmsghdr n;
@@ -1979,7 +2040,10 @@ ssize_t netlink_nexthop_encode(uint16_t cmd, const struct zebra_dplane_ctx *ctx,
label_buf[0] = '\0';
- memset(req, 0, buflen);
+ if (buflen < sizeof(*req))
+ return 0;
+
+ memset(req, 0, sizeof(*req));
req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg));
req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
@@ -2002,7 +2066,8 @@ ssize_t netlink_nexthop_encode(uint16_t cmd, const struct zebra_dplane_ctx *ctx,
return -1;
}
- addattr32(&req->n, buflen, NHA_ID, id);
+ if (!nl_attr_put32(&req->n, buflen, NHA_ID, id))
+ return 0;
if (cmd == RTM_NEWNEXTHOP) {
/*
@@ -2011,12 +2076,13 @@ ssize_t netlink_nexthop_encode(uint16_t cmd, const struct zebra_dplane_ctx *ctx,
* group is installed as an id that just refers to a list of
* other ids.
*/
- if (dplane_ctx_get_nhe_nh_grp_count(ctx))
- _netlink_nexthop_build_group(
- &req->n, buflen, id,
- dplane_ctx_get_nhe_nh_grp(ctx),
- dplane_ctx_get_nhe_nh_grp_count(ctx));
- else {
+ if (dplane_ctx_get_nhe_nh_grp_count(ctx)) {
+ if (!_netlink_nexthop_build_group(
+ &req->n, buflen, id,
+ dplane_ctx_get_nhe_nh_grp(ctx),
+ dplane_ctx_get_nhe_nh_grp_count(ctx)))
+ return 0;
+ } else {
const struct nexthop *nh =
dplane_ctx_get_nhe_ng(ctx)->nexthop;
afi_t afi = dplane_ctx_get_nhe_afi(ctx);
@@ -2029,17 +2095,22 @@ ssize_t netlink_nexthop_encode(uint16_t cmd, const struct zebra_dplane_ctx *ctx,
switch (nh->type) {
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
- addattr_l(&req->n, buflen, NHA_GATEWAY,
- &nh->gate.ipv4, IPV4_MAX_BYTELEN);
+ if (!nl_attr_put(&req->n, buflen, NHA_GATEWAY,
+ &nh->gate.ipv4,
+ IPV4_MAX_BYTELEN))
+ return 0;
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
- addattr_l(&req->n, buflen, NHA_GATEWAY,
- &nh->gate.ipv6, IPV6_MAX_BYTELEN);
+ if (!nl_attr_put(&req->n, buflen, NHA_GATEWAY,
+ &nh->gate.ipv6,
+ IPV6_MAX_BYTELEN))
+ return 0;
break;
case NEXTHOP_TYPE_BLACKHOLE:
- addattr_l(&req->n, buflen, NHA_BLACKHOLE, NULL,
- 0);
+ if (!nl_attr_put(&req->n, buflen, NHA_BLACKHOLE,
+ NULL, 0))
+ return 0;
/* Blackhole shouldn't have anymore attributes
*/
goto nexthop_done;
@@ -2055,7 +2126,9 @@ ssize_t netlink_nexthop_encode(uint16_t cmd, const struct zebra_dplane_ctx *ctx,
return -1;
}
- addattr32(&req->n, buflen, NHA_OIF, nh->ifindex);
+ if (!nl_attr_put32(&req->n, buflen, NHA_OIF,
+ nh->ifindex))
+ return 0;
if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK))
req->nhm.nh_flags |= RTNH_F_ONLINK;
@@ -2075,25 +2148,32 @@ ssize_t netlink_nexthop_encode(uint16_t cmd, const struct zebra_dplane_ctx *ctx,
if (req->nhm.nh_family == AF_MPLS)
goto nexthop_done;
#if 0
- addattr_l(&req->n, buflen, NHA_NEWDST,
+ if (!nl_attr_put(&req->n, buflen, NHA_NEWDST,
&out_lse,
num_labels
- * sizeof(mpls_lse_t));
+ * sizeof(mpls_lse_t)))
+ return 0;
#endif
else {
struct rtattr *nest;
uint16_t encap = LWTUNNEL_ENCAP_MPLS;
- addattr_l(&req->n, buflen,
- NHA_ENCAP_TYPE, &encap,
- sizeof(uint16_t));
- nest = addattr_nest(&req->n, buflen,
+ if (!nl_attr_put16(&req->n, buflen,
+ NHA_ENCAP_TYPE,
+ encap))
+ return 0;
+ nest = nl_attr_nest(&req->n, buflen,
NHA_ENCAP);
- addattr_l(&req->n, buflen,
- MPLS_IPTUNNEL_DST, &out_lse,
- num_labels
- * sizeof(mpls_lse_t));
- addattr_nest_end(&req->n, nest);
+ if (!nest)
+ return 0;
+ if (!nl_attr_put(
+ &req->n, buflen,
+ MPLS_IPTUNNEL_DST, &out_lse,
+ num_labels
+ * sizeof(
+ mpls_lse_t)))
+ return 0;
+ nl_attr_nest_end(&req->n, nest);
}
}
@@ -2104,7 +2184,7 @@ nexthop_done:
__func__, id, nh, nh->ifindex,
vrf_id_to_name(nh->vrf_id),
nh->vrf_id, label_buf);
- }
+}
req->nhm.nh_protocol =
zebra2proto(dplane_ctx_get_nhe_type(ctx));
@@ -2154,7 +2234,7 @@ enum zebra_dplane_result kernel_nexthop_update(struct zebra_dplane_ctx *ctx)
if (!kernel_nexthops_supported())
return ZEBRA_DPLANE_REQUEST_SUCCESS;
- if (netlink_nexthop_encode(cmd, ctx, buf, sizeof(buf)) > 0)
+ if (netlink_nexthop_msg_encode(cmd, ctx, buf, sizeof(buf)) > 0)
ret = netlink_talk_info(netlink_talk_filter, (void *)&buf,
dplane_ctx_get_ns(ctx), 0);
else
@@ -2195,12 +2275,14 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
*/
if (RSYSTEM_ROUTE(dplane_ctx_get_type(ctx)) &&
!RSYSTEM_ROUTE(dplane_ctx_get_old_type(ctx))) {
- netlink_route_multipath(RTM_DELROUTE, ctx,
- nl_pkt, sizeof(nl_pkt),
- false, false);
- netlink_talk_info(netlink_talk_filter,
- (struct nlmsghdr *)nl_pkt,
- dplane_ctx_get_ns(ctx), 0);
+ if (netlink_route_multipath_msg_encode(
+ RTM_DELROUTE, ctx, nl_pkt,
+ sizeof(nl_pkt), false, false)
+ > 0)
+ netlink_talk_info(
+ netlink_talk_filter,
+ (struct nlmsghdr *)nl_pkt,
+ dplane_ctx_get_ns(ctx), 0);
}
} else {
/*
@@ -2216,12 +2298,14 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
* screwed.
*/
if (!RSYSTEM_ROUTE(dplane_ctx_get_old_type(ctx))) {
- netlink_route_multipath(RTM_DELROUTE, ctx,
- nl_pkt, sizeof(nl_pkt),
- false, false);
- netlink_talk_info(netlink_talk_filter,
- (struct nlmsghdr *)nl_pkt,
- dplane_ctx_get_ns(ctx), 0);
+ if (netlink_route_multipath_msg_encode(
+ RTM_DELROUTE, ctx, nl_pkt,
+ sizeof(nl_pkt), false, false)
+ > 0)
+ netlink_talk_info(
+ netlink_talk_filter,
+ (struct nlmsghdr *)nl_pkt,
+ dplane_ctx_get_ns(ctx), 0);
}
cmd = RTM_NEWROUTE;
}
@@ -2231,11 +2315,15 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
}
if (!RSYSTEM_ROUTE(dplane_ctx_get_type(ctx))) {
- netlink_route_multipath(cmd, ctx, nl_pkt, sizeof(nl_pkt), false,
- false);
- ret = netlink_talk_info(netlink_talk_filter,
- (struct nlmsghdr *)nl_pkt,
- dplane_ctx_get_ns(ctx), 0);
+ if (netlink_route_multipath_msg_encode(
+ cmd, ctx, nl_pkt, sizeof(nl_pkt), false, false)
+ > 0)
+ ret = netlink_talk_info(netlink_talk_filter,
+ (struct nlmsghdr *)nl_pkt,
+ dplane_ctx_get_ns(ctx), 0);
+ else
+ ret = -1;
+
} else
ret = 0;
if ((cmd == RTM_NEWROUTE) && (ret == 0)) {
@@ -2559,8 +2647,8 @@ int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
}
/**
- * netlink_update_neigh_ctx_internal() - Common helper api for evpn
- * neighbor updates using dataplane context object.
+ * netlink_neigh_update_msg_encode() - Common helper api for encoding
+ * evpn neighbor update as netlink messages using dataplane context object.
* Here, a neighbor refers to a bridge forwarding database entry for
* either unicast forwarding or head-end replication or an IP neighbor
* entry.
@@ -2579,14 +2667,13 @@ int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
* @data: data buffer pointer
* @datalen: total amount of data buffer space
*
- * Return: Result status
+ * Return: 0 when the msg doesn't fit entirely in the buffer
+ * otherwise the number of bytes written to buf.
*/
-static ssize_t
-netlink_update_neigh_ctx_internal(const struct zebra_dplane_ctx *ctx,
- int cmd, const struct ethaddr *mac,
- const struct ipaddr *ip, bool replace_obj,
- uint8_t family, uint8_t type, uint8_t flags,
- uint16_t state, void *data, size_t datalen)
+static ssize_t netlink_neigh_update_msg_encode(
+ const struct zebra_dplane_ctx *ctx, int cmd, const struct ethaddr *mac,
+ const struct ipaddr *ip, bool replace_obj, uint8_t family, uint8_t type,
+ uint8_t flags, uint16_t state, void *data, size_t datalen)
{
uint8_t protocol = RTPROT_ZEBRA;
struct {
@@ -2597,6 +2684,8 @@ netlink_update_neigh_ctx_internal(const struct zebra_dplane_ctx *ctx,
int ipa_len;
enum dplane_op_e op;
+ if (datalen < sizeof(*req))
+ return 0;
memset(req, 0, datalen);
op = dplane_ctx_get_op(ctx);
@@ -2614,22 +2703,30 @@ netlink_update_neigh_ctx_internal(const struct zebra_dplane_ctx *ctx,
req->ndm.ndm_flags = flags;
req->ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx);
- addattr_l(&req->n, sizeof(req),
- NDA_PROTOCOL, &protocol, sizeof(protocol));
- if (mac)
- addattr_l(&req->n, datalen, NDA_LLADDR, mac, 6);
+ if (!nl_attr_put(&req->n, sizeof(req), NDA_PROTOCOL, &protocol,
+ sizeof(protocol)))
+ return 0;
+
+ if (mac) {
+ if (!nl_attr_put(&req->n, datalen, NDA_LLADDR, mac, 6))
+ return 0;
+ }
ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
- addattr_l(&req->n, datalen, NDA_DST, &ip->ip.addr, ipa_len);
+ if (!nl_attr_put(&req->n, datalen, NDA_DST, &ip->ip.addr, ipa_len))
+ return 0;
if (op == DPLANE_OP_MAC_INSTALL || op == DPLANE_OP_MAC_DELETE) {
vlanid_t vid = dplane_ctx_mac_get_vlan(ctx);
- if (vid > 0)
- addattr16(&req->n, datalen, NDA_VLAN, vid);
+ if (vid > 0) {
+ if (!nl_attr_put16(&req->n, datalen, NDA_VLAN, vid))
+ return 0;
+ }
- addattr32(&req->n, datalen, NDA_MASTER,
- dplane_ctx_mac_get_br_ifindex(ctx));
+ if (!nl_attr_put32(&req->n, datalen, NDA_MASTER,
+ dplane_ctx_mac_get_br_ifindex(ctx)))
+ return 0;
}
return NLMSG_ALIGN(req->n.nlmsg_len);
@@ -2645,10 +2742,12 @@ static int netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx,
struct ethaddr dst_mac = {.octet = {0}};
uint8_t nl_pkt[NL_PKT_BUF_SIZE];
- netlink_update_neigh_ctx_internal(
- ctx, cmd, &dst_mac, dplane_ctx_neigh_get_ipaddr(ctx), false,
- PF_BRIDGE, 0, NTF_SELF, (NUD_NOARP | NUD_PERMANENT), nl_pkt,
- sizeof(nl_pkt));
+ if (netlink_neigh_update_msg_encode(
+ ctx, cmd, &dst_mac, dplane_ctx_neigh_get_ipaddr(ctx), false,
+ PF_BRIDGE, 0, NTF_SELF, (NUD_NOARP | NUD_PERMANENT), nl_pkt,
+ sizeof(nl_pkt))
+ <= 0)
+ return -1;
return netlink_talk_info(netlink_talk_filter,
(struct nlmsghdr *)nl_pkt,
@@ -2845,7 +2944,7 @@ static int netlink_request_macs(struct nlsock *netlink_cmd, int family,
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
req.ifm.ifi_family = family;
if (master_ifindex)
- addattr32(&req.n, sizeof(req), IFLA_MASTER, master_ifindex);
+ nl_attr_put32(&req.n, sizeof(req), IFLA_MASTER, master_ifindex);
return netlink_request(netlink_cmd, &req);
}
@@ -2934,13 +3033,13 @@ static int netlink_request_specific_mac_in_bridge(struct zebra_ns *zns,
req.ndm.ndm_family = family; /* AF_BRIDGE */
/* req.ndm.ndm_state = NUD_REACHABLE; */
- addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
+ nl_attr_put(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
br_zif = (struct zebra_if *)br_if->info;
if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0)
- addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
+ nl_attr_put16(&req.n, sizeof(req), NDA_VLAN, vid);
- addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
+ nl_attr_put32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
@@ -3026,9 +3125,9 @@ netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, uint8_t *data,
ipaddr2str(&vtep_ip, ipbuf, sizeof(ipbuf)));
}
- total = netlink_update_neigh_ctx_internal(
- ctx, cmd, dplane_ctx_mac_get_addr(ctx), &vtep_ip,
- true, AF_BRIDGE, 0, flags, state, data, datalen);
+ total = netlink_neigh_update_msg_encode(
+ ctx, cmd, dplane_ctx_mac_get_addr(ctx), &vtep_ip, true,
+ AF_BRIDGE, 0, flags, state, data, datalen);
return total;
}
@@ -3246,7 +3345,7 @@ static int netlink_request_neigh(struct nlsock *netlink_cmd, int family,
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
req.ndm.ndm_family = family;
if (ifindex)
- addattr32(&req.n, sizeof(req), NDA_IFINDEX, ifindex);
+ nl_attr_put32(&req.n, sizeof(req), NDA_IFINDEX, ifindex);
return netlink_request(netlink_cmd, &req);
}
@@ -3325,7 +3424,7 @@ static int netlink_request_specific_neigh_in_vlan(struct zebra_ns *zns,
req.ndm.ndm_family = AF_INET6;
}
- addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
+ nl_attr_put(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
if (IS_ZEBRA_DEBUG_KERNEL) {
char buf[INET6_ADDRSTRLEN];
@@ -3444,9 +3543,11 @@ static int netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
flags, state);
}
- netlink_update_neigh_ctx_internal(
- ctx, cmd, mac, ip, true, family, RTN_UNICAST, flags,
- state, nl_pkt, sizeof(nl_pkt));
+ if (netlink_neigh_update_msg_encode(ctx, cmd, mac, ip, true, family,
+ RTN_UNICAST, flags, state, nl_pkt,
+ sizeof(nl_pkt))
+ <= 0)
+ return -1;
return netlink_talk_info(netlink_talk_filter, (struct nlmsghdr *)nl_pkt,
dplane_ctx_get_ns(ctx), 0);
@@ -3501,7 +3602,8 @@ enum zebra_dplane_result kernel_neigh_update_ctx(struct zebra_dplane_ctx *ctx)
* MPLS label forwarding table change via netlink interface, using dataplane
* context information.
*/
-int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
+ssize_t netlink_mpls_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx,
+ void *buf, size_t buflen)
{
mpls_lse_t lse;
const struct nhlfe_list_head *head;
@@ -3515,10 +3617,13 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
struct {
struct nlmsghdr n;
struct rtmsg r;
- char buf[NL_PKT_BUF_SIZE];
- } req;
+ char buf[0];
+ } *req = buf;
- memset(&req, 0, sizeof(req) - NL_PKT_BUF_SIZE);
+ if (buflen < sizeof(*req))
+ return 0;
+
+ memset(req, 0, sizeof(*req));
/*
* Count # nexthops so we can decide whether to use singlepath
@@ -3547,30 +3652,31 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
(!dplane_ctx_get_best_nhlfe(ctx) && (cmd != RTM_DELROUTE)))
return 0;
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
- req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
- req.n.nlmsg_type = cmd;
- req.n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid;
+ req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+ req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
+ req->n.nlmsg_type = cmd;
+ req->n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid;
- req.r.rtm_family = AF_MPLS;
- req.r.rtm_table = RT_TABLE_MAIN;
- req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
- req.r.rtm_scope = RT_SCOPE_UNIVERSE;
- req.r.rtm_type = RTN_UNICAST;
+ req->r.rtm_family = AF_MPLS;
+ req->r.rtm_table = RT_TABLE_MAIN;
+ req->r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
+ req->r.rtm_scope = RT_SCOPE_UNIVERSE;
+ req->r.rtm_type = RTN_UNICAST;
if (cmd == RTM_NEWROUTE) {
/* We do a replace to handle update. */
- req.n.nlmsg_flags |= NLM_F_REPLACE;
+ req->n.nlmsg_flags |= NLM_F_REPLACE;
/* set the protocol value if installing */
route_type = re_type_from_lsp_type(
dplane_ctx_get_best_nhlfe(ctx)->type);
- req.r.rtm_protocol = zebra2proto(route_type);
+ req->r.rtm_protocol = zebra2proto(route_type);
}
/* Fill destination */
lse = mpls_lse_encode(dplane_ctx_get_in_label(ctx), 0, 0, 1);
- addattr_l(&req.n, sizeof(req), RTA_DST, &lse, sizeof(mpls_lse_t));
+ if (!nl_attr_put(&req->n, buflen, RTA_DST, &lse, sizeof(mpls_lse_t)))
+ return 0;
/* Fill nexthops (paths) based on single-path or multipath. The paths
* chosen depend on the operation.
@@ -3596,23 +3702,22 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
&& CHECK_FLAG(nexthop->flags,
NEXTHOP_FLAG_FIB)))) {
/* Add the gateway */
- _netlink_mpls_build_singlepath(
- &p, routedesc, nhlfe, &req.n, &req.r,
- sizeof(req), cmd);
+ if (!_netlink_mpls_build_singlepath(
+ &p, routedesc, nhlfe, &req->n,
+ &req->r, buflen, cmd))
+ return false;
nexthop_num++;
break;
}
}
} else { /* Multipath case */
- char buf[NL_PKT_BUF_SIZE];
- struct rtattr *rta = (void *)buf;
- struct rtnexthop *rtnh;
+ struct rtattr *nest;
const union g_addr *src1 = NULL;
- rta->rta_type = RTA_MULTIPATH;
- rta->rta_len = RTA_LENGTH(0);
- rtnh = RTA_DATA(rta);
+ nest = nl_attr_nest(&req->n, buflen, RTA_MULTIPATH);
+ if (!nest)
+ return 0;
routedesc = "multipath";
_netlink_mpls_debug(cmd, dplane_ctx_get_in_label(ctx),
@@ -3636,21 +3741,17 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
nexthop_num++;
/* Build the multipath */
- _netlink_mpls_build_multipath(&p, routedesc,
- nhlfe, rta, rtnh,
- &req.r, &src1);
- rtnh = RTNH_NEXT(rtnh);
+ if (!_netlink_mpls_build_multipath(
+ &p, routedesc, nhlfe, &req->n,
+ buflen, &req->r, &src1))
+ return 0;
}
}
/* Add the multipath */
- if (rta->rta_len > RTA_LENGTH(0))
- addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH,
- RTA_DATA(rta), RTA_PAYLOAD(rta));
+ nl_attr_nest_end(&req->n, nest);
}
- /* Talk to netlink socket. */
- return netlink_talk_info(netlink_talk_filter, &req.n,
- dplane_ctx_get_ns(ctx), 0);
+ return NLMSG_ALIGN(req->n.nlmsg_len);
}
#endif /* HAVE_NETLINK */
diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h
index c09609f47c..429ff0bf85 100644
--- a/zebra/rt_netlink.h
+++ b/zebra/rt_netlink.h
@@ -64,11 +64,14 @@ extern "C" {
void rt_netlink_init(void);
/* MPLS label forwarding table change, using dataplane context information. */
-extern int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx);
+extern ssize_t netlink_mpls_multipath_msg_encode(int cmd,
+ struct zebra_dplane_ctx *ctx,
+ void *buf, size_t buflen);
-extern ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
- uint8_t *data, size_t datalen, bool fpm,
- bool force_nhg);
+extern ssize_t netlink_route_multipath_msg_encode(int cmd,
+ struct zebra_dplane_ctx *ctx,
+ uint8_t *data, size_t datalen,
+ bool fpm, bool force_nhg);
extern ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx,
uint8_t *data, size_t datalen);
@@ -78,9 +81,9 @@ extern int netlink_route_read(struct zebra_ns *zns);
extern int netlink_nexthop_change(struct nlmsghdr *h, ns_id_t ns_id,
int startup);
extern int netlink_nexthop_read(struct zebra_ns *zns);
-extern ssize_t netlink_nexthop_encode(uint16_t cmd,
- const struct zebra_dplane_ctx *ctx,
- void *buf, size_t buflen);
+extern ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
+ const struct zebra_dplane_ctx *ctx,
+ void *buf, size_t buflen);
extern int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id);
extern int netlink_macfdb_read(struct zebra_ns *zns);
diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c
index 9da008bb61..b7be398506 100644
--- a/zebra/rule_netlink.c
+++ b/zebra/rule_netlink.c
@@ -55,8 +55,8 @@
*
* Encodes netlink RTM_ADDRULE/RTM_DELRULE message to buffer buf of size buflen.
*
- * Returns -1 on failure or the number of bytes
- * written to buf.
+ * Returns -1 on failure, 0 when the msg doesn't fit entirely in the buffer
+ * or the number of bytes written to buf.
*/
static ssize_t netlink_rule_msg_encode(
int cmd, const struct zebra_dplane_ctx *ctx, uint32_t filter_bm,
@@ -87,36 +87,48 @@ static ssize_t netlink_rule_msg_encode(
req->frh.family = family;
req->frh.action = FR_ACT_TO_TBL;
- addattr_l(&req->n, buflen, FRA_PROTOCOL, &protocol, sizeof(protocol));
+ if (!nl_attr_put(&req->n, buflen, FRA_PROTOCOL, &protocol,
+ sizeof(protocol)))
+ return 0;
/* rule's pref # */
- addattr32(&req->n, buflen, FRA_PRIORITY, priority);
+ if (!nl_attr_put32(&req->n, buflen, FRA_PRIORITY, priority))
+ return 0;
/* interface on which applied */
- addattr_l(&req->n, buflen, FRA_IFNAME, ifname, strlen(ifname) + 1);
+ if (!nl_attr_put(&req->n, buflen, FRA_IFNAME, ifname,
+ strlen(ifname) + 1))
+ return 0;
/* source IP, if specified */
if (filter_bm & PBR_FILTER_SRC_IP) {
req->frh.src_len = src_ip->prefixlen;
- addattr_l(&req->n, buflen, FRA_SRC, &src_ip->u.prefix, bytelen);
+ if (!nl_attr_put(&req->n, buflen, FRA_SRC, &src_ip->u.prefix,
+ bytelen))
+ return 0;
}
/* destination IP, if specified */
if (filter_bm & PBR_FILTER_DST_IP) {
req->frh.dst_len = dst_ip->prefixlen;
- addattr_l(&req->n, buflen, FRA_DST, &dst_ip->u.prefix, bytelen);
+ if (!nl_attr_put(&req->n, buflen, FRA_DST, &dst_ip->u.prefix,
+ bytelen))
+ return 0;
}
/* fwmark, if specified */
- if (filter_bm & PBR_FILTER_FWMARK)
- addattr32(&req->n, buflen, FRA_FWMARK, fwmark);
+ if (filter_bm & PBR_FILTER_FWMARK) {
+ if (!nl_attr_put32(&req->n, buflen, FRA_FWMARK, fwmark))
+ return 0;
+ }
/* Route table to use to forward, if filter criteria matches. */
if (table < 256)
req->frh.table = table;
else {
req->frh.table = RT_TABLE_UNSPEC;
- addattr32(&req->n, buflen, FRA_TABLE, table);
+ if (!nl_attr_put32(&req->n, buflen, FRA_TABLE, table))
+ return 0;
}
if (IS_ZEBRA_DEBUG_KERNEL)
diff --git a/zebra/subdir.am b/zebra/subdir.am
index d98ef52571..49e60820bc 100644
--- a/zebra/subdir.am
+++ b/zebra/subdir.am
@@ -44,6 +44,7 @@ endif
zebra_zebra_LDADD = lib/libfrr.la $(LIBCAP)
if HAVE_PROTOBUF3
zebra_zebra_LDADD += mlag/libmlag_pb.la $(PROTOBUF_C_LIBS)
+zebra/zebra_mlag.$(OBJEXT): mlag/mlag.pb-c.h
endif
zebra_zebra_SOURCES = \
zebra/connected.c \
@@ -188,8 +189,10 @@ zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_netlink.c
if HAVE_PROTOBUF
zebra_zebra_fpm_la_LIBADD += fpm/libfrrfpm_pb.la qpb/libfrr_pb.la $(PROTOBUF_C_LIBS)
zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_protobuf.c
+zebra/zebra_fpm_protobuf.lo: fpm/fpm.pb-c.h qpb/qpb.pb-c.h
if DEV_BUILD
zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_dt.c
+zebra/zebra_fpm_dt.lo: fpm/fpm.pb-c.h qpb/qpb.pb-c.h
endif
endif
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c
index b194f80fc7..a18885ddb7 100644
--- a/zebra/zebra_fpm_netlink.c
+++ b/zebra/zebra_fpm_netlink.c
@@ -361,9 +361,9 @@ static int netlink_route_info_encode(struct netlink_route_info *ri,
size_t buf_offset;
struct netlink_nh_info *nhi;
enum fpm_nh_encap_type_t encap;
- struct rtattr *nest;
+ struct rtattr *nest, *inner_nest;
+ struct rtnexthop *rtnh;
struct vxlan_encap_info_t *vxlan;
- int nest_len;
struct {
struct nlmsghdr n;
@@ -400,20 +400,21 @@ static int netlink_route_info_encode(struct netlink_route_info *ri,
req->r.rtm_table = ri->rtm_table;
else {
req->r.rtm_table = RT_TABLE_UNSPEC;
- addattr32(&req->n, in_buf_len, RTA_TABLE, ri->rtm_table);
+ nl_attr_put32(&req->n, in_buf_len, RTA_TABLE, ri->rtm_table);
}
req->r.rtm_dst_len = ri->prefix->prefixlen;
req->r.rtm_protocol = ri->rtm_protocol;
req->r.rtm_scope = RT_SCOPE_UNIVERSE;
- addattr_l(&req->n, in_buf_len, RTA_DST, &ri->prefix->u.prefix, bytelen);
+ nl_attr_put(&req->n, in_buf_len, RTA_DST, &ri->prefix->u.prefix,
+ bytelen);
req->r.rtm_type = ri->rtm_type;
/* Metric. */
if (ri->metric)
- addattr32(&req->n, in_buf_len, RTA_PRIORITY, *ri->metric);
+ nl_attr_put32(&req->n, in_buf_len, RTA_PRIORITY, *ri->metric);
if (ri->num_nhs == 0)
goto done;
@@ -422,12 +423,13 @@ static int netlink_route_info_encode(struct netlink_route_info *ri,
nhi = &ri->nhs[0];
if (nhi->gateway) {
- addattr_l(&req->n, in_buf_len, RTA_GATEWAY,
- nhi->gateway, bytelen);
+ nl_attr_put(&req->n, in_buf_len, RTA_GATEWAY,
+ nhi->gateway, bytelen);
}
if (nhi->if_index) {
- addattr32(&req->n, in_buf_len, RTA_OIF, nhi->if_index);
+ nl_attr_put32(&req->n, in_buf_len, RTA_OIF,
+ nhi->if_index);
}
encap = nhi->encap_info.encap_type;
@@ -436,12 +438,13 @@ static int netlink_route_info_encode(struct netlink_route_info *ri,
case FPM_NH_ENCAP_MAX:
break;
case FPM_NH_ENCAP_VXLAN:
- addattr_l(&req->n, in_buf_len, RTA_ENCAP_TYPE, &encap,
- sizeof(uint16_t));
+ nl_attr_put16(&req->n, in_buf_len, RTA_ENCAP_TYPE,
+ encap);
vxlan = &nhi->encap_info.vxlan_encap;
- nest = addattr_nest(&req->n, in_buf_len, RTA_ENCAP);
- addattr32(&req->n, in_buf_len, VXLAN_VNI, vxlan->vni);
- addattr_nest_end(&req->n, nest);
+ nest = nl_attr_nest(&req->n, in_buf_len, RTA_ENCAP);
+ nl_attr_put32(&req->n, in_buf_len, VXLAN_VNI,
+ vxlan->vni);
+ nl_attr_nest_end(&req->n, nest);
break;
}
@@ -451,28 +454,15 @@ static int netlink_route_info_encode(struct netlink_route_info *ri,
/*
* Multipath case.
*/
- char buf[NL_PKT_BUF_SIZE];
- struct rtattr *rta = (void *)buf;
- struct rtnexthop *rtnh;
-
- rta->rta_type = RTA_MULTIPATH;
- rta->rta_len = RTA_LENGTH(0);
- rtnh = RTA_DATA(rta);
+ nest = nl_attr_nest(&req->n, in_buf_len, RTA_MULTIPATH);
for (nexthop_num = 0; nexthop_num < ri->num_nhs; nexthop_num++) {
+ rtnh = nl_attr_rtnh(&req->n, in_buf_len);
nhi = &ri->nhs[nexthop_num];
- rtnh->rtnh_len = sizeof(*rtnh);
- rtnh->rtnh_flags = 0;
- rtnh->rtnh_hops = 0;
- rtnh->rtnh_ifindex = 0;
- rta->rta_len += rtnh->rtnh_len;
-
- if (nhi->gateway) {
- rta_addattr_l(rta, sizeof(buf), RTA_GATEWAY,
- nhi->gateway, bytelen);
- rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
- }
+ if (nhi->gateway)
+ nl_attr_put(&req->n, in_buf_len, RTA_GATEWAY,
+ nhi->gateway, bytelen);
if (nhi->if_index) {
rtnh->rtnh_ifindex = nhi->if_index;
@@ -484,31 +474,28 @@ static int netlink_route_info_encode(struct netlink_route_info *ri,
case FPM_NH_ENCAP_MAX:
break;
case FPM_NH_ENCAP_VXLAN:
- rta_addattr_l(rta, sizeof(buf), RTA_ENCAP_TYPE,
- &encap, sizeof(uint16_t));
- rtnh->rtnh_len += sizeof(struct rtattr) +
- sizeof(uint16_t);
+ nl_attr_put16(&req->n, in_buf_len, RTA_ENCAP_TYPE,
+ encap);
vxlan = &nhi->encap_info.vxlan_encap;
- nest = rta_nest(rta, sizeof(buf), RTA_ENCAP);
- rta_addattr_l(rta, sizeof(buf), VXLAN_VNI, &vxlan->vni,
- sizeof(uint32_t));
- nest_len = rta_nest_end(rta, nest);
- rtnh->rtnh_len += nest_len;
+ inner_nest =
+ nl_attr_nest(&req->n, in_buf_len, RTA_ENCAP);
+ nl_attr_put32(&req->n, in_buf_len, VXLAN_VNI,
+ vxlan->vni);
+ nl_attr_nest_end(&req->n, inner_nest);
break;
}
- rtnh = RTNH_NEXT(rtnh);
+ nl_attr_rtnh_end(&req->n, rtnh);
}
- assert(rta->rta_len > RTA_LENGTH(0));
- addattr_l(&req->n, in_buf_len, RTA_MULTIPATH, RTA_DATA(rta),
- RTA_PAYLOAD(rta));
+ nl_attr_nest_end(&req->n, nest);
+ assert(nest->rta_len > RTA_LENGTH(0));
done:
if (ri->pref_src) {
- addattr_l(&req->n, in_buf_len, RTA_PREFSRC, &ri->pref_src,
- bytelen);
+ nl_attr_put(&req->n, in_buf_len, RTA_PREFSRC, &ri->pref_src,
+ bytelen);
}
assert(req->n.nlmsg_len < in_buf_len);
@@ -614,10 +601,10 @@ int zfpm_netlink_encode_mac(struct fpm_mac_info_t *mac, char *in_buf,
req->ndm.ndm_flags |= NTF_EXT_LEARNED;
/* Add attributes */
- addattr_l(&req->hdr, in_buf_len, NDA_LLADDR, &mac->macaddr, 6);
- addattr_l(&req->hdr, in_buf_len, NDA_DST, &mac->r_vtep_ip, 4);
- addattr32(&req->hdr, in_buf_len, NDA_MASTER, mac->svi_if);
- addattr32(&req->hdr, in_buf_len, NDA_VNI, mac->vni);
+ nl_attr_put(&req->hdr, in_buf_len, NDA_LLADDR, &mac->macaddr, 6);
+ nl_attr_put(&req->hdr, in_buf_len, NDA_DST, &mac->r_vtep_ip, 4);
+ nl_attr_put32(&req->hdr, in_buf_len, NDA_MASTER, mac->svi_if);
+ nl_attr_put32(&req->hdr, in_buf_len, NDA_VNI, mac->vni);
assert(req->hdr.nlmsg_len < in_buf_len);
diff --git a/zebra/zebra_mlag.c b/zebra/zebra_mlag.c
index 8ba7998f50..3cf4ba8d39 100644
--- a/zebra/zebra_mlag.c
+++ b/zebra/zebra_mlag.c
@@ -33,6 +33,10 @@
#include "zebra/zapi_msg.h"
#include "zebra/debug.h"
+#ifdef HAVE_PROTOBUF_VERSION_3
+#include "mlag/mlag.pb-c.h"
+#endif
+
DEFINE_HOOK(zebra_mlag_private_write_data,
(uint8_t *data, uint32_t len), (data, len))
DEFINE_HOOK(zebra_mlag_private_monitor_state, (), ())
diff --git a/zebra/zebra_mlag.h b/zebra/zebra_mlag.h
index 66f5c4c67e..d10a1f9157 100644
--- a/zebra/zebra_mlag.h
+++ b/zebra/zebra_mlag.h
@@ -26,10 +26,6 @@
#include "zclient.h"
#include "zebra/zserv.h"
-#ifdef HAVE_PROTOBUF_VERSION_3
-#include "mlag/mlag.pb-c.h"
-#endif
-
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/zebra/zebra_mpls_netlink.c b/zebra/zebra_mpls_netlink.c
index a9233530dc..c95a021639 100644
--- a/zebra/zebra_mpls_netlink.c
+++ b/zebra/zebra_mpls_netlink.c
@@ -26,13 +26,16 @@
#include "zebra/rt.h"
#include "zebra/rt_netlink.h"
#include "zebra/zebra_mpls.h"
+#include "zebra/kernel_netlink.h"
/*
* LSP forwarding update using dataplane context information.
*/
enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx)
{
- int cmd, ret = -1;
+ uint8_t nl_pkt[NL_PKT_BUF_SIZE];
+ ssize_t ret = -1;
+ int cmd;
/* Call to netlink layer based on type of update */
if (dplane_ctx_get_op(ctx) == DPLANE_OP_LSP_DELETE) {
@@ -53,7 +56,13 @@ enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx)
/* Invalid op? */
goto done;
- ret = netlink_mpls_multipath(cmd, ctx);
+ ret = netlink_mpls_multipath_msg_encode(cmd, ctx, nl_pkt,
+ sizeof(nl_pkt));
+ if (ret <= 0)
+ return ZEBRA_DPLANE_REQUEST_FAILURE;
+
+ ret = netlink_talk_info(netlink_talk_filter, (struct nlmsghdr *)nl_pkt,
+ dplane_ctx_get_ns(ctx), 0);
done:
diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c
index 0d86421b9e..79121bb086 100644
--- a/zebra/zebra_netns_id.c
+++ b/zebra/zebra_netns_id.c
@@ -216,8 +216,8 @@ ns_id_t zebra_ns_id_get(const char *netnspath, int fd_param)
nlh->nlmsg_len += NETLINK_ALIGN(sizeof(struct rtgenmsg));
rt->rtgen_family = AF_UNSPEC;
- addattr32(nlh, NETLINK_SOCKET_BUFFER_SIZE, NETNSA_FD, fd);
- addattr32(nlh, NETLINK_SOCKET_BUFFER_SIZE, NETNSA_NSID, ns_id);
+ nl_attr_put32(nlh, NETLINK_SOCKET_BUFFER_SIZE, NETNSA_FD, fd);
+ nl_attr_put32(nlh, NETLINK_SOCKET_BUFFER_SIZE, NETNSA_NSID, ns_id);
ret = send_receive(sock, nlh, seq, buf);
if (ret < 0) {
@@ -282,8 +282,9 @@ ns_id_t zebra_ns_id_get(const char *netnspath, int fd_param)
nlh->nlmsg_len += NETLINK_ALIGN(sizeof(struct rtgenmsg));
rt->rtgen_family = AF_UNSPEC;
- addattr32(nlh, NETLINK_SOCKET_BUFFER_SIZE, NETNSA_FD, fd);
- addattr32(nlh, NETLINK_SOCKET_BUFFER_SIZE, NETNSA_NSID, ns_id);
+ nl_attr_put32(nlh, NETLINK_SOCKET_BUFFER_SIZE, NETNSA_FD, fd);
+ nl_attr_put32(nlh, NETLINK_SOCKET_BUFFER_SIZE, NETNSA_NSID,
+ ns_id);
ret = send_receive(sock, nlh, seq, buf);
if (ret < 0) {