diff --git a/include/linux/netconf.h b/include/linux/netconf.h new file mode 100644 index 0000000000..fac4edd553 --- /dev/null +++ b/include/linux/netconf.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_LINUX_NETCONF_H_ +#define _UAPI_LINUX_NETCONF_H_ + +#include +#include + +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_ */ diff --git a/include/subdir.am b/include/subdir.am index 86129c4d68..a06a8e5649 100644 --- a/include/subdir.am +++ b/include/subdir.am @@ -5,6 +5,7 @@ noinst_HEADERS += \ 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 \ diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 141e4074d5..b915d4720a 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -74,6 +74,7 @@ #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; @@ -1001,6 +1002,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) /* 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); @@ -2078,6 +2080,10 @@ void interface_list(struct zebra_ns *zns) netlink_nexthop_read(zns); interface_addr_lookup_netlink(zns); + + /* Read some other properties via the 'netconf' apis */ + netconf_lookup_netlink(zns); + } #endif /* GNU_LINUX */ diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 23e7098d04..0cd69e6c2c 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -48,6 +48,7 @@ #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 @@ -108,6 +109,8 @@ static const struct message nlmsg_str[] = {{RTM_NEWROUTE, "RTM_NEWROUTE"}, {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[] = { @@ -370,6 +373,10 @@ static int netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id, 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: @@ -1593,7 +1600,9 @@ void kernel_init(struct zebra_ns *zns) 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 | diff --git a/zebra/netconf_netlink.c b/zebra/netconf_netlink.c new file mode 100644 index 0000000000..e43685b794 --- /dev/null +++ b/zebra/netconf_netlink.c @@ -0,0 +1,139 @@ +/* + * 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 + +#ifdef HAVE_NETLINK /* Netlink OSes only */ + +#include + +#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 */ diff --git a/zebra/netconf_netlink.h b/zebra/netconf_netlink.h new file mode 100644 index 0000000000..0eae2119dd --- /dev/null +++ b/zebra/netconf_netlink.h @@ -0,0 +1,45 @@ +/* + * 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 */ diff --git a/zebra/subdir.am b/zebra/subdir.am index f0cc6ce71b..77e0898d81 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -69,6 +69,7 @@ zebra_zebra_SOURCES = \ 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 \ @@ -148,6 +149,7 @@ noinst_HEADERS += \ 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 \