summaryrefslogtreecommitdiff
path: root/zebra/netconf_netlink.c
diff options
context:
space:
mode:
authorMark Stapp <mstapp@nvidia.com>2021-10-28 11:23:31 -0400
committerMark Stapp <mstapp@nvidia.com>2022-02-25 10:18:32 -0500
commitcd787a8a45ea3c94a689d5ff01ddf62467373550 (patch)
tree6d33a836729d423443dd004ca2eda91933c44ea6 /zebra/netconf_netlink.c
parent728f2017ae285aea6f7e8bda369eaae7a3083899 (diff)
zebra: use dataplane to read interface NETCONF info
Use the dataplane to query and read interface NETCONF data; add netconf-oriented data to the dplane context object, and add accessors for it. Add handler for incoming update processing. Signed-off-by: Mark Stapp <mstapp@nvidia.com>
Diffstat (limited to 'zebra/netconf_netlink.c')
-rw-r--r--zebra/netconf_netlink.c104
1 files changed, 70 insertions, 34 deletions
diff --git a/zebra/netconf_netlink.c b/zebra/netconf_netlink.c
index e43685b794..587f6c749e 100644
--- a/zebra/netconf_netlink.c
+++ b/zebra/netconf_netlink.c
@@ -37,25 +37,53 @@
static struct rtattr *netconf_rta(struct netconfmsg *ncm)
{
- return (struct rtattr *)((char *)ncm
- + NLMSG_ALIGN(sizeof(struct netconfmsg)));
+ return (struct rtattr *)((char *)ncm +
+ NLMSG_ALIGN(sizeof(struct netconfmsg)));
}
+/*
+ * Handle netconf update about a single interface: create dplane
+ * context, and enqueue for processing in the main zebra pthread.
+ */
+static int netlink_netconf_dplane_update(ns_id_t ns_id, ifindex_t ifindex,
+ enum dplane_netconf_status_e mpls_on,
+ enum dplane_netconf_status_e mcast_on)
+{
+ struct zebra_dplane_ctx *ctx;
+
+ ctx = dplane_ctx_alloc();
+ dplane_ctx_set_op(ctx, DPLANE_OP_INTF_NETCONFIG);
+ dplane_ctx_set_netconf_ns_id(ctx, ns_id);
+ dplane_ctx_set_netconf_ifindex(ctx, ifindex);
+
+ dplane_ctx_set_netconf_mpls(ctx, mpls_on);
+ dplane_ctx_set_netconf_mcast(ctx, mcast_on);
+
+ /* Enqueue ctx for main pthread to process */
+ dplane_provider_enqueue_to_zebra(ctx);
+
+ return 0;
+}
+
+/*
+ * Parse and process an incoming netlink netconf update.
+ */
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;
+ uint32_t ival;
+ enum dplane_netconf_status_e mpls_on = DPLANE_NETCONF_STATUS_UNKNOWN;
+ enum dplane_netconf_status_e mcast_on = DPLANE_NETCONF_STATUS_UNKNOWN;
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",
+ zlog_err("%s: Message received from netlink is of a broken size: %d, min %zu",
__func__, h->nlmsg_len,
(size_t)NLMSG_LENGTH(sizeof(struct netconfmsg)));
return -1;
@@ -66,8 +94,7 @@ int netlink_netconf_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
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__);
+ zlog_err("NETCONF message received from netlink without an ifindex");
return 0;
}
@@ -81,59 +108,68 @@ int netlink_netconf_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
* for all and default interfaces. I am not 100% sure
* what that is yet, or where we would store it.
*/
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: Ignoring global ifindex %d",
+ __func__, ifindex);
+
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 */
+ ival = *(uint32_t *)RTA_DATA(tb[NETCONFA_INPUT]);
+ if (ival != 0)
+ mpls_on = DPLANE_NETCONF_STATUS_ENABLED;
+ else
+ mpls_on = DPLANE_NETCONF_STATUS_DISABLED;
}
if (tb[NETCONFA_MC_FORWARDING]) {
- mc_on = *(bool *)RTA_DATA(tb[NETCONFA_MC_FORWARDING]);
- /* Create a context and pass it up for processing */
+ ival = *(uint32_t *)RTA_DATA(tb[NETCONFA_MC_FORWARDING]);
+ if (ival != 0)
+ mcast_on = DPLANE_NETCONF_STATUS_ENABLED;
+ else
+ mcast_on = DPLANE_NETCONF_STATUS_DISABLED;
}
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Interface %u is mpls on: %d multicast on: %d",
- ifindex, mpls_on, mc_on);
+ zlog_debug("%s: interface %u is mpls on: %d multicast on: %d",
+ __func__, ifindex, mpls_on, mcast_on);
+
+ /* Create a dplane context and pass it along for processing */
+ netlink_netconf_dplane_update(ns_id, ifindex, mpls_on, mcast_on);
return 0;
}
-static int netlink_request_netconf(struct nlsock *netlink_cmd)
+/*
+ * Request info from the host OS. This only sends the request; any replies
+ * are processed asynchronously.
+ */
+int netlink_request_netconf(int sockfd)
{
+ struct nlsock *nls;
struct {
struct nlmsghdr n;
struct netconfmsg ncm;
char buf[1024];
- } req;
+ } req = {};
+
+ nls = kernel_netlink_nlsock_lookup(sockfd);
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: nlsock %s", __func__, nls ? nls->name : "NULL");
+
+ if (nls == NULL)
+ return -1;
- 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;
+ return netlink_request(nls, &req);
}
#endif /* HAVE_NETLINK */