--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_LINUX_NETCONF_H_
+#define _UAPI_LINUX_NETCONF_H_
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+
+struct netconfmsg {
+ __u8 ncm_family;
+};
+
+enum {
+ NETCONFA_UNSPEC,
+ NETCONFA_IFINDEX,
+ NETCONFA_FORWARDING,
+ NETCONFA_RP_FILTER,
+ NETCONFA_MC_FORWARDING,
+ NETCONFA_PROXY_NEIGH,
+ NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
+ NETCONFA_INPUT,
+ NETCONFA_BC_FORWARDING,
+ __NETCONFA_MAX
+};
+#define NETCONFA_MAX (__NETCONFA_MAX - 1)
+#define NETCONFA_ALL -1
+
+#define NETCONFA_IFINDEX_ALL -1
+#define NETCONFA_IFINDEX_DEFAULT -2
+
+#endif /* _UAPI_LINUX_NETCONF_H_ */
include/linux/lwtunnel.h \
include/linux/mpls_iptunnel.h \
include/linux/neighbour.h \
+ include/linux/netconf.h \
include/linux/netlink.h \
include/linux/nexthop.h \
include/linux/rtnetlink.h \
#include "zebra/zebra_vxlan.h"
#include "zebra/zebra_evpn_mh.h"
#include "zebra/zebra_l2.h"
+#include "zebra/netconf_netlink.h"
extern struct zebra_privs_t zserv_privs;
/* Hardware type and address. */
ifp->ll_type = netlink_to_zebra_link_type(ifi->ifi_type);
+
netlink_interface_update_hw_addr(tb, ifp);
if_add_update(ifp);
netlink_nexthop_read(zns);
interface_addr_lookup_netlink(zns);
+
+ /* Read some other properties via the 'netconf' apis */
+ netconf_lookup_netlink(zns);
+
}
#endif /* GNU_LINUX */
#include "zebra/rt_netlink.h"
#include "zebra/if_netlink.h"
#include "zebra/rule_netlink.h"
+#include "zebra/netconf_netlink.h"
#include "zebra/zebra_errors.h"
#ifndef SO_RCVBUFFORCE
{RTM_NEWNEXTHOP, "RTM_NEWNEXTHOP"},
{RTM_DELNEXTHOP, "RTM_DELNEXTHOP"},
{RTM_GETNEXTHOP, "RTM_GETNEXTHOP"},
+ {RTM_NEWNETCONF, "RTM_NEWNETCONF"},
+ {RTM_DELNETCONF, "RTM_DELNETCONF"},
{0}};
static const struct message rtproto_str[] = {
case RTM_DELNEXTHOP:
return netlink_nexthop_change(h, ns_id, startup);
+ case RTM_NEWNETCONF:
+ case RTM_DELNETCONF:
+ return netlink_netconf_change(h, ns_id, startup);
+
/* Messages handled in the dplane thread */
case RTM_NEWADDR:
case RTM_DELADDR:
RTMGRP_NEIGH |
((uint32_t) 1 << (RTNLGRP_IPV4_RULE - 1)) |
((uint32_t) 1 << (RTNLGRP_IPV6_RULE - 1)) |
- ((uint32_t) 1 << (RTNLGRP_NEXTHOP - 1));
+ ((uint32_t) 1 << (RTNLGRP_NEXTHOP - 1)) |
+ ((uint32_t) 1 << (RTNLGRP_IPV4_NETCONF - 1)) |
+ ((uint32_t) 1 << (RTNLGRP_MPLS_NETCONF - 1));
dplane_groups = (RTMGRP_LINK |
RTMGRP_IPV4_IFADDR |
--- /dev/null
+/*
+ * netconf_netlink.c - netconf interaction with the kernel using
+ * netlink
+ * Copyright (C) 2021 Nvidia, Inc.
+ * Donald Sharp
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FRR; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <zebra.h>
+
+#ifdef HAVE_NETLINK /* Netlink OSes only */
+
+#include <ns.h>
+
+#include "linux/netconf.h"
+
+#include "zebra/zebra_ns.h"
+#include "zebra/zebra_dplane.h"
+#include "zebra/kernel_netlink.h"
+#include "zebra/netconf_netlink.h"
+#include "zebra/debug.h"
+
+static struct rtattr *netconf_rta(struct netconfmsg *ncm)
+{
+ return (struct rtattr *)((char *)ncm
+ + NLMSG_ALIGN(sizeof(struct netconfmsg)));
+}
+
+int netlink_netconf_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
+{
+ struct netconfmsg *ncm;
+ struct rtattr *tb[NETCONFA_MAX + 1] = {};
+ int len;
+ ifindex_t ifindex;
+ bool mpls_on = false;
+ bool mc_on = false;
+
+ if (h->nlmsg_type != RTM_NEWNETCONF && h->nlmsg_type != RTM_DELNETCONF)
+ return 0;
+
+ len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct netconfmsg));
+ if (len < 0) {
+ zlog_err("%s: Message received from netlink is of a broken size: %d %zu",
+ __func__, h->nlmsg_len,
+ (size_t)NLMSG_LENGTH(sizeof(struct netconfmsg)));
+ return -1;
+ }
+
+ ncm = NLMSG_DATA(h);
+
+ netlink_parse_rtattr(tb, NETCONFA_MAX, netconf_rta(ncm), len);
+
+ if (!tb[NETCONFA_IFINDEX]) {
+ zlog_err("%s: Message received from netlink that we expected to receive an interface on",
+ __func__);
+ return 0;
+ }
+
+ ifindex = *(ifindex_t *)RTA_DATA(tb[NETCONFA_IFINDEX]);
+
+ switch (ifindex) {
+ case NETCONFA_IFINDEX_ALL:
+ case NETCONFA_IFINDEX_DEFAULT:
+ /*
+ * We need the ability to handle netlink messages intended
+ * for all and default interfaces. I am not 100% sure
+ * what that is yet, or where we would store it.
+ */
+ return 0;
+ default:
+ break;
+ }
+ if (tb[NETCONFA_INPUT]) {
+ mpls_on = *(bool *)RTA_DATA(tb[NETCONFA_INPUT]);
+ /* Create a context and pass it up for processing */
+ }
+
+ if (tb[NETCONFA_MC_FORWARDING]) {
+ mc_on = *(bool *)RTA_DATA(tb[NETCONFA_MC_FORWARDING]);
+ /* Create a context and pass it up for processing */
+ }
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("Interface %u is mpls on: %d multicast on: %d",
+ ifindex, mpls_on, mc_on);
+
+ return 0;
+}
+
+static int netlink_request_netconf(struct nlsock *netlink_cmd)
+{
+ struct {
+ struct nlmsghdr n;
+ struct netconfmsg ncm;
+ char buf[1024];
+ } req;
+
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct netconfmsg));
+ req.n.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
+ req.n.nlmsg_type = RTM_GETNETCONF;
+ req.ncm.ncm_family = AF_UNSPEC;
+
+ return netlink_request(netlink_cmd, &req);
+}
+
+int netconf_lookup_netlink(struct zebra_ns *zns)
+{
+ int ret;
+ struct zebra_dplane_info dp_info;
+ struct nlsock *netlink_cmd = &zns->netlink_cmd;
+
+ zebra_dplane_info_from_zns(&dp_info, zns, true);
+
+ ret = netlink_request_netconf(netlink_cmd);
+ if (ret < 0)
+ return ret;
+
+ ret = netlink_parse_info(netlink_netconf_change, netlink_cmd, &dp_info,
+ 0, 1);
+ return ret;
+}
+
+#endif /* HAVE_NETLINK */
--- /dev/null
+/*
+ * netconf_netlink.h - netconf interaction with the kernel using
+ * netlink
+ * Copyright (C) 2021 Nvidia, Inc.
+ * Donald Sharp
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FRR; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#ifndef __NETCONF_NETLINK_H__
+#define __NETCONF_NETLINK_H__
+
+#ifdef HAVE_NETLINK /* Netlink-only module */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int netlink_netconf_change(struct nlmsghdr *h, ns_id_t ns_id,
+ int startup);
+
+extern int netconf_lookup_netlink(struct zebra_ns *zns);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAVE_NETLINK */
+
+#endif /* NETCONF_NETLINK_H */
zebra/kernel_socket.c \
zebra/label_manager.c \
zebra/main.c \
+ zebra/netconf_netlink.c \
zebra/redistribute.c \
zebra/router-id.c \
zebra/rt_netlink.c \
zebra/kernel_netlink.h \
zebra/kernel_socket.h \
zebra/label_manager.h \
+ zebra/netconf_netlink.h \
zebra/redistribute.h \
zebra/rib.h \
zebra/router-id.h \