summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@nvidia.com>2022-06-30 13:50:04 +0200
committerDonald Sharp <sharpd@nvidia.com>2022-06-30 13:57:55 +0200
commitfe953d7cded8c59859a766e7bcc62a9cee8a04a3 (patch)
treecf31e5a0f722e5894e5436b7f85ba1c82ed95922 /zebra
parentMerge pull request #11493 from patrasar/pim_reg_stop_fix (diff)
downloadfrr-fe953d7cded8c59859a766e7bcc62a9cee8a04a3.tar.xz
frr-fe953d7cded8c59859a766e7bcc62a9cee8a04a3.zip
zebra: Correct implication of SOL_NETLINK NETLINK_ADD_MEMBERSHIP usage
The usage of SOL_NETLINK for adding memberships of interest is 1 group per call. The netink_socket function implied that the call could be a bitfield of values. This is not correct at all. This will trip someone else up in the future when a new value is needed. Let's get it right `now` before it becomes a problem. Let's also add a bit of extra code to give operator a better understanding of what went wrong when a kernel does not support the option. Finally as a point of future reference should FRR just switch over to a loop to add the required loops instead of having this bastardized approach of some going in one way and some going in another way? Signed-off-by: Donald Sharp <sharpd@nvidia.com>
Diffstat (limited to 'zebra')
-rw-r--r--zebra/kernel_netlink.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 4bd0ac27f..e372eaf6a 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -290,9 +290,20 @@ static int netlink_recvbuf(struct nlsock *nl, uint32_t newsize)
return 0;
}
+static const char *group2str(uint32_t group)
+{
+ switch (group) {
+ case RTNLGRP_TUNNEL:
+ return "RTNLGRP_TUNNEL";
+ default:
+ return "UNKNOWN";
+ }
+}
+
/* Make socket for Linux netlink interface. */
static int netlink_socket(struct nlsock *nl, unsigned long groups,
- unsigned long ext_groups, ns_id_t ns_id)
+ uint32_t ext_groups[], uint8_t ext_group_size,
+ ns_id_t ns_id)
{
int ret;
struct sockaddr_nl snl;
@@ -312,14 +323,21 @@ static int netlink_socket(struct nlsock *nl, unsigned long groups,
snl.nl_groups = groups;
#if defined SOL_NETLINK
- if (ext_groups) {
- ret = setsockopt(sock, SOL_NETLINK,
- NETLINK_ADD_MEMBERSHIP, &ext_groups,
- sizeof(ext_groups));
- if (ret < 0) {
- zlog_notice(
- "can't setsockopt NETLINK_ADD_MEMBERSHIP: %s(%d)",
- safe_strerror(errno), errno);
+ if (ext_group_size) {
+ uint8_t i;
+
+ for (i = 0; i < ext_group_size; i++) {
+ ret = setsockopt(sock, SOL_NETLINK,
+ NETLINK_ADD_MEMBERSHIP,
+ &ext_groups[i],
+ sizeof(ext_groups[i]));
+ if (ret < 0) {
+ zlog_notice(
+ "can't setsockopt NETLINK_ADD_MEMBERSHIP for group %s(%u), this linux kernel does not support it: %s(%d)",
+ group2str(ext_groups[i]),
+ ext_groups[i],
+ safe_strerror(errno), errno);
+ }
}
}
#endif
@@ -1734,7 +1752,8 @@ void kernel_init(struct zebra_ns *zns)
snprintf(zns->netlink.name, sizeof(zns->netlink.name),
"netlink-listen (NS %u)", zns->ns_id);
zns->netlink.sock = -1;
- if (netlink_socket(&zns->netlink, groups, ext_groups, zns->ns_id) < 0) {
+ if (netlink_socket(&zns->netlink, groups, &ext_groups, 1, zns->ns_id) <
+ 0) {
zlog_err("Failure to create %s socket",
zns->netlink.name);
exit(-1);
@@ -1745,7 +1764,7 @@ void kernel_init(struct zebra_ns *zns)
snprintf(zns->netlink_cmd.name, sizeof(zns->netlink_cmd.name),
"netlink-cmd (NS %u)", zns->ns_id);
zns->netlink_cmd.sock = -1;
- if (netlink_socket(&zns->netlink_cmd, 0, 0, zns->ns_id) < 0) {
+ if (netlink_socket(&zns->netlink_cmd, 0, 0, 0, zns->ns_id) < 0) {
zlog_err("Failure to create %s socket",
zns->netlink_cmd.name);
exit(-1);
@@ -1758,7 +1777,7 @@ void kernel_init(struct zebra_ns *zns)
sizeof(zns->netlink_dplane_out.name), "netlink-dp (NS %u)",
zns->ns_id);
zns->netlink_dplane_out.sock = -1;
- if (netlink_socket(&zns->netlink_dplane_out, 0, 0, zns->ns_id) < 0) {
+ if (netlink_socket(&zns->netlink_dplane_out, 0, 0, 0, zns->ns_id) < 0) {
zlog_err("Failure to create %s socket",
zns->netlink_dplane_out.name);
exit(-1);
@@ -1771,7 +1790,7 @@ void kernel_init(struct zebra_ns *zns)
sizeof(zns->netlink_dplane_in.name), "netlink-dp-in (NS %u)",
zns->ns_id);
zns->netlink_dplane_in.sock = -1;
- if (netlink_socket(&zns->netlink_dplane_in, dplane_groups, 0,
+ if (netlink_socket(&zns->netlink_dplane_in, dplane_groups, 0, 0,
zns->ns_id) < 0) {
zlog_err("Failure to create %s socket",
zns->netlink_dplane_in.name);