From d3ef8f699343db2578996a3f45625cc2daf603fa Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 28 Feb 2024 14:34:38 -0500 Subject: [PATCH] LU-9680 lnet: add NLM_F_DUMP_FILTERED support In addition to different API levels for the netlink packets we can also filter the data sent back when user land sends the NLM_F_DUMP_FILTERED. Support this across the various netlink dumpit functions. This work is needed for the proper support for lnetctl export command. Update the export to work with the Netlink API. This results in proper IPv6 support for the export command. Test-Parameters: trivial testlist=sanity-lnet Change-Id: I0e8993b1f9a08199f282965601781aa6fd0e4844 Signed-off-by: James Simmons Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/53004 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Frank Sehr Reviewed-by: Chris Horn Reviewed-by: Oleg Drokin --- libcfs/include/libcfs/linux/linux-net.h | 4 ++ lnet/lnet/api-ni.c | 76 +++++++++++++++++++++++++-------- lnet/utils/lnetctl.c | 42 ++++++++++++++++-- lustre/tests/sanity-lnet.sh | 4 +- 4 files changed, 103 insertions(+), 23 deletions(-) diff --git a/libcfs/include/libcfs/linux/linux-net.h b/libcfs/include/libcfs/linux/linux-net.h index b13a1e6..a2ce21c 100644 --- a/libcfs/include/libcfs/linux/linux-net.h +++ b/libcfs/include/libcfs/linux/linux-net.h @@ -38,6 +38,10 @@ } while (0) #endif +#ifndef NLM_F_DUMP_FILTERED +#define NLM_F_DUMP_FILTERED 0x20 /* Dump was filtered as requested */ +#endif + #ifndef HAVE_NLA_STRDUP char *nla_strdup(const struct nlattr *nla, gfp_t flags); #endif /* !HAVE_NLA_STRDUP */ diff --git a/lnet/lnet/api-ni.c b/lnet/lnet/api-ni.c index de2c556..b8c2edc 100644 --- a/lnet/lnet/api-ni.c +++ b/lnet/lnet/api-ni.c @@ -5437,6 +5437,26 @@ report_err: return rc; } +static const struct ln_key_list net_update_props_list = { + .lkl_maxattr = LNET_NET_ATTR_MAX, + .lkl_list = { + [LNET_NET_ATTR_HDR] = { + .lkp_value = "", + .lkp_key_format = LNKF_SEQUENCE | LNKF_MAPPING, + .lkp_data_type = NLA_NUL_STRING, + }, + [LNET_NET_ATTR_TYPE] = { + .lkp_value = "net type", + .lkp_data_type = NLA_STRING + }, + [LNET_NET_ATTR_LOCAL] = { + .lkp_value = "local NI(s)", + .lkp_key_format = LNKF_SEQUENCE | LNKF_MAPPING, + .lkp_data_type = NLA_NESTED + }, + }, +}; + static int lnet_net_show_dump(struct sk_buff *msg, struct netlink_callback *cb) { @@ -5446,7 +5466,7 @@ static int lnet_net_show_dump(struct sk_buff *msg, #endif struct genlmsghdr *gnlh = nlmsg_data(cb->nlh); int portid = NETLINK_CB(cb->skb).portid; - bool found = false, started = true; + bool found = false, started = false; const struct lnet_lnd *lnd = NULL; int idx = nlist->lngl_idx, rc = 0; int seq = cb->nlh->nlmsg_seq; @@ -5467,6 +5487,10 @@ static int lnet_net_show_dump(struct sk_buff *msg, nlist->lngl_net_id != net->net_id) continue; + if (cb->nlh->nlmsg_flags & NLM_F_DUMP_FILTERED && + LNET_NETTYP(net->net_id) == LOLND) + continue; + if (gnlh->version && LNET_NETTYP(net->net_id) != LOLND) { if (!net->net_lnd) { NL_SET_ERR_MSG(extack, @@ -5502,9 +5526,10 @@ static int lnet_net_show_dump(struct sk_buff *msg, if (lnd) { all[ARRAY_SIZE(all) - 2] = lnd->lnd_keys; - if (idx) + if (idx) { + all[0] = &net_update_props_list; flags |= NLM_F_REPLACE; - started = true; + } } rc = lnet_genl_send_scalar_list(msg, portid, seq, @@ -5514,6 +5539,7 @@ static int lnet_net_show_dump(struct sk_buff *msg, NL_SET_ERR_MSG(extack, "failed to send key table"); GOTO(net_unlock, rc); } + started = true; } hdr = genlmsg_put(msg, portid, seq, &lnet_family, @@ -5541,13 +5567,15 @@ static int lnet_net_show_dump(struct sk_buff *msg, ni_attr = nla_nest_start(msg, dev++); found = true; lnet_ni_lock(ni); - nla_put_string(msg, LNET_NET_LOCAL_NI_ATTR_NID, - libcfs_nidstr(&ni->ni_nid)); - if (!nid_is_lo0(&ni->ni_nid) && - lnet_ni_get_status_locked(ni) != LNET_NI_STATUS_UP) - status = "down"; - nla_put_string(msg, LNET_NET_LOCAL_NI_ATTR_STATUS, - status); + if (!(cb->nlh->nlmsg_flags & NLM_F_DUMP_FILTERED)) { + nla_put_string(msg, LNET_NET_LOCAL_NI_ATTR_NID, + libcfs_nidstr(&ni->ni_nid)); + if (!nid_is_lo0(&ni->ni_nid) && + lnet_ni_get_status_locked(ni) != LNET_NI_STATUS_UP) + status = "down"; + nla_put_string(msg, LNET_NET_LOCAL_NI_ATTR_STATUS, + status); + } if (!nid_is_lo0(&ni->ni_nid) && ni->ni_interface) { struct nlattr *intf_nest, *intf_attr; @@ -5575,6 +5603,11 @@ static int lnet_net_show_dump(struct sk_buff *msg, struct nlattr *tun_attr, *ni_tun; int j; + if (cb->nlh->nlmsg_flags & NLM_F_DUMP_FILTERED) { + lnet_ni_unlock(ni); + goto skip_msg_stats; + } + stats.iel_send_count = lnet_sum_stats(&ni->ni_stats, LNET_STATS_TYPE_SEND); stats.iel_recv_count = lnet_sum_stats(&ni->ni_stats, @@ -5727,7 +5760,9 @@ skip_msg_stats: nla_nest_end(msg, lnd_tun_attr); } - nla_put_s32(msg, LNET_NET_LOCAL_NI_DEV_CPT, ni->ni_dev_cpt); + if (!(cb->nlh->nlmsg_flags & NLM_F_DUMP_FILTERED)) + nla_put_s32(msg, LNET_NET_LOCAL_NI_DEV_CPT, + ni->ni_dev_cpt); /* Report cpts. We could send this as a nested list * of integers but older versions of the tools @@ -6959,12 +6994,14 @@ static int lnet_route_show_dump(struct sk_buff *msg, nla_put_u32(msg, LNET_ROUTE_ATTR_HEALTH_SENSITIVITY, prop->lrp_sensitivity); - nla_put_string(msg, LNET_ROUTE_ATTR_STATE, - prop->lrp_flags & LNET_RT_ALIVE ? - "up" : "down"); - nla_put_string(msg, LNET_ROUTE_ATTR_TYPE, - prop->lrp_flags & LNET_RT_MULTI_HOP ? - "multi-hop" : "single-hop"); + if (!(cb->nlh->nlmsg_flags & NLM_F_DUMP_FILTERED)) { + nla_put_string(msg, LNET_ROUTE_ATTR_STATE, + prop->lrp_flags & LNET_RT_ALIVE ? + "up" : "down"); + nla_put_string(msg, LNET_ROUTE_ATTR_TYPE, + prop->lrp_flags & LNET_RT_MULTI_HOP ? + "multi-hop" : "single-hop"); + } } genlmsg_end(msg, hdr); } @@ -7419,6 +7456,9 @@ static int lnet_peer_ni_show_dump(struct sk_buff *msg, } } + if (cb->nlh->nlmsg_flags & NLM_F_DUMP_FILTERED) + goto skip_state; + if (lnet_isrouter(lpni) || lnet_peer_aliveness_enabled(lpni)) { nla_put_string(msg, LNET_PEER_NI_LIST_ATTR_STATE, @@ -7428,7 +7468,7 @@ static int lnet_peer_ni_show_dump(struct sk_buff *msg, nla_put_string(msg, LNET_PEER_NI_LIST_ATTR_STATE, "NA"); } - +skip_state: if (gnlh->version) { struct lnet_ioctl_element_msg_stats lpni_msg_stats; struct nlattr *send_stats_list, *send_stats; diff --git a/lnet/utils/lnetctl.c b/lnet/utils/lnetctl.c index 47143d0..8851c1c 100644 --- a/lnet/utils/lnetctl.c +++ b/lnet/utils/lnetctl.c @@ -24,6 +24,10 @@ #define LNET_CONFIGURE true #define LNET_UNCONFIGURE false +#ifndef NLM_F_DUMP_FILTERED +#define NLM_F_DUMP_FILTERED 0x20 +#endif + static int jt_config_lnet(int argc, char **argv); static int jt_unconfig_lnet(int argc, char **argv); static int jt_add_route(int argc, char **argv); @@ -3909,22 +3913,24 @@ static int jt_export(int argc, char **argv) { struct cYAML *show_rc = NULL; struct cYAML *err_rc = NULL; + int flags = NLM_F_DUMP; int rc; FILE *f = NULL; int opt; bool backup = false; char *file = NULL; - const char *const short_options = "bh"; static const struct option long_options[] = { { .name = "backup", .has_arg = no_argument, .val = 'b' }, { .name = "help", .has_arg = no_argument, .val = 'h' }, - { .name = NULL } }; + { .name = NULL } + }; while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { switch (opt) { case 'b': + flags |= NLM_F_DUMP_FILTERED; backup = true; break; case 'h': @@ -3949,6 +3955,36 @@ static int jt_export(int argc, char **argv) return -1; } + rc = yaml_lnet_config_ni(NULL, NULL, NULL, NULL, -1, NULL, + flags & NLM_F_DUMP_FILTERED ? 1 : 2, + flags); + if (rc < 0) { + if (rc == -EOPNOTSUPP) + goto old_api; + } + + rc = yaml_lnet_route(NULL, NULL, -1, -1, -1, LNET_GENL_VERSION, flags); + if (rc < 0) { + if (rc == -EOPNOTSUPP) + goto old_api; + } + + rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, backup); + if (rc != LUSTRE_CFG_RC_NO_ERR) { + cYAML_print_tree2file(stderr, err_rc); + cYAML_free_tree(err_rc); + err_rc = NULL; + } + + rc = yaml_lnet_peer(NULL, NULL, false, -1, false, false, + flags & NLM_F_DUMP_FILTERED ? 0 : 3, flags); + if (rc < 0) { + if (rc == -EOPNOTSUPP) + goto old_api; + } + goto show_others; + +old_api: rc = lustre_lnet_show_net(NULL, 2, -1, &show_rc, &err_rc, backup); if (rc != LUSTRE_CFG_RC_NO_ERR) { cYAML_print_tree2file(stderr, err_rc); @@ -3977,7 +4013,7 @@ static int jt_export(int argc, char **argv) cYAML_free_tree(err_rc); err_rc = NULL; } - +show_others: rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc); if (rc != LUSTRE_CFG_RC_NO_ERR) { cYAML_print_tree2file(stderr, err_rc); diff --git a/lustre/tests/sanity-lnet.sh b/lustre/tests/sanity-lnet.sh index 9c2c14a..78cc861 100755 --- a/lustre/tests/sanity-lnet.sh +++ b/lustre/tests/sanity-lnet.sh @@ -192,8 +192,8 @@ validate_peer_nids() { # The primary nid also shows up in the list of secondary nids local expect_s="$(($num_peers + $(($nids_per_peer*$num_peers))))" - local actual_p=$(grep -c -- '- primary nid:' $TMP/sanity-lnet-$testnum-actual.yaml) - local actual_s=$(grep -c -- '- nid:' $TMP/sanity-lnet-$testnum-actual.yaml) + local actual_p=$(awk '/-\s+primary nid:/{print $NF}' $TMP/sanity-lnet-$testnum-actual.yaml | wc -l) + local actual_s=$(awk '/-\s+nid:/{print $NF}' $TMP/sanity-lnet-$testnum-actual.yaml | wc -l) if [[ $expect_p -ne $actual_p ]]; then compare_yaml_files error "Expected $expect_p but found $actual_p primary nids" -- 1.8.3.1