4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the GNU Lesser General Public License
8 * LGPL version 2.1 or (at your discretion) any later version.
9 * LGPL version 2.1 accompanies this distribution, and is available at
10 * http://www.gnu.org/licenses/lgpl-2.1.html
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
22 * Copyright (c) 2021 UT-Battelle, LLC
24 * Author: James Simmons <jsimmons@infradead.org>
32 #include <linux/lnet/lnet-nl.h>
33 #include "liblnetconfig.h"
36 #define fallthrough do {} while (0) /* fallthrough */
39 #ifndef SOL_NETLINK /* for glibc < 2.24 */
40 # define SOL_NETLINK 270
43 #ifndef NETLINK_EXT_ACK
44 #define NETLINK_EXT_ACK 11
47 #ifndef NLM_F_ACK_TLVS
48 #define NLM_F_ACK_TLVS 0x200 /* extended ACK TVLs were included */
59 #ifndef HAVE_NLA_GET_S32
64 * Return payload of 32 bit signed integer attribute.
66 * @arg nla 32 bit integer attribute.
68 * @return Payload as 32 bit integer.
70 int32_t nla_get_s32(const struct nlattr *nla)
72 return *(const int32_t *) nla_data(nla);
74 #endif /* ! HAVE_NLA_GET_S32 */
76 #ifndef HAVE_NLA_GET_S64
81 * Return payload of s64 attribute
83 * @arg nla s64 netlink attribute
85 * @return Payload as 64 bit integer.
87 int64_t nla_get_s64(const struct nlattr *nla)
91 if (nla && nla_len(nla) >= sizeof(tmp))
92 memcpy(&tmp, nla_data(nla), sizeof(tmp));
97 #define NLA_PUT_S64(msg, attrtype, value) \
98 NLA_PUT_TYPE(msg, int64_t, attrtype, value)
100 #ifndef NLA_NUL_STRING
101 #define NLA_NUL_STRING 10
105 LNET_NLA_UNSPEC = NLA_UNSPEC,
106 LNET_NLA_U8 = NLA_U8,
107 LNET_NLA_U16 = NLA_U16,
108 LNET_NLA_U32 = NLA_U32,
109 LNET_NLA_U64 = NLA_U64,
110 LNET_NLA_STRING = NLA_STRING,
111 LNET_NLA_FLAG = NLA_FLAG,
112 LNET_NLA_MSECS = NLA_MSECS,
113 LNET_NLA_NESTED = NLA_NESTED,
114 LNET_NLA_NESTED_COMPAT = NLA_NESTED + 1,
115 LNET_NLA_NUL_STRING = NLA_NUL_STRING,
116 LNET_NLA_BINARY = NLA_NUL_STRING + 1,
117 LNET_NLA_S8 = NLA_S8,
118 LNET_NLA_S16 = NLA_S16,
119 LNET_NLA_S32 = NLA_S32,
120 LNET_NLA_S64 = NLA_S64,
124 #define LNET_NLA_TYPE_MAX (__LNET_NLA_TYPE_MAX - 1)
126 static uint16_t nla_attr_minlen[LNET_NLA_TYPE_MAX+1] = {
127 [NLA_U8] = sizeof(uint8_t),
128 [NLA_U16] = sizeof(uint16_t),
129 [NLA_U32] = sizeof(uint32_t),
130 [NLA_U64] = sizeof(uint64_t),
135 static int lnet_validate_nla(const struct nlattr *nla, int maxtype,
136 const struct nla_policy *policy)
138 const struct nla_policy *pt;
139 unsigned int minlen = 0;
140 int type = nla_type(nla);
142 if (type < 0 || type > maxtype)
147 if (pt->type > NLA_TYPE_MAX)
152 else if (pt->type != NLA_UNSPEC)
153 minlen = nla_attr_minlen[pt->type];
155 if (nla_len(nla) < minlen)
158 if (pt->maxlen && nla_len(nla) > pt->maxlen)
161 if (pt->type == NLA_STRING) {
162 const char *data = nla_data(nla);
164 if (data[nla_len(nla) - 1] != '\0')
171 int lnet_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head,
172 int len, const struct nla_policy *policy)
177 memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
179 nla_for_each_attr(nla, head, len, rem) {
180 int type = nla_type(nla);
186 err = lnet_validate_nla(nla, maxtype, policy);
197 int lnet_genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
198 int maxtype, const struct nla_policy *policy)
200 struct genlmsghdr *ghdr;
202 if (!genlmsg_valid_hdr(nlh, hdrlen))
203 return -NLE_MSG_TOOSHORT;
205 ghdr = nlmsg_data(nlh);
206 return lnet_nla_parse(tb, maxtype, genlmsg_attrdata(ghdr, hdrlen),
207 genlmsg_attrlen(ghdr, hdrlen), policy);
210 #else /* !HAVE_NLA_GET_S64 */
212 #define lnet_genlmsg_parse genlmsg_parse
214 #endif /* HAVE_NLA_GET_S64 */
217 * Set NETLINK_BROADCAST_ERROR flags on socket to report ENOBUFS errors.
219 * @sk Socket to change the flags.
221 * Return 0 on success or a Netlink error code.
223 static int nl_socket_enable_broadcast_error(struct nl_sock *sk)
225 const int state = 1; /* enable errors */
228 if (nl_socket_get_fd(sk) < 0)
229 return -NLE_BAD_SOCK;
231 err = setsockopt(nl_socket_get_fd(sk), SOL_NETLINK,
232 NETLINK_BROADCAST_ERROR, &state, sizeof(state));
234 return -nl_syserr2nlerr(errno);
240 * Enable/disable extending ACK for netlink socket. Used for
241 * sending extra debugging information.
243 * @arg sk Netlink socket.
244 * @arg state New state (0 - disabled, 1 - enabled)
246 * @return 0 on success or a negative error code
248 static int nl_socket_set_ext_ack(struct nl_sock *sk, int state)
252 if (nl_socket_get_fd(sk) < 0)
253 return -NLE_BAD_SOCK;
255 err = setsockopt(nl_socket_get_fd(sk), SOL_NETLINK,
256 NETLINK_EXT_ACK, &state, sizeof(state));
257 if (err < 0 && errno != ENOPROTOOPT)
258 return -nl_syserr2nlerr(errno);
264 * Create a Netlink socket
266 * @sk The nl_sock which we used to handle the Netlink
268 * @async_events tell the Netlink socket this will receive asynchronous
271 * Return 0 on success or a negative error code.
273 static int lustre_netlink_register(struct nl_sock *sk, bool async_events)
277 rc = genl_connect(sk);
281 rc = nl_socket_enable_broadcast_error(sk);
285 rc = nl_socket_set_ext_ack(sk, true);
290 /* Required to receive async netlink event notifications */
291 nl_socket_disable_seq_check(sk);
292 /* Don't need ACK for events generated by kernel */
293 nl_socket_disable_auto_ack(sk);
300 * Filter Netlink socket by groups
303 * @family The family name of the Netlink socket.
304 * @group Netlink messages will only been sent if they belong to this
307 * Return 0 on success or a negative error code.
309 static int lustre_netlink_add_group(struct nl_sock *nl, const char *family,
315 group_id = genl_ctrl_resolve_grp(nl, family, group);
319 /* subscribe to generic netlink multicast group */
320 return nl_socket_add_membership(nl, group_id);
323 /* A YAML file is used to describe data. In a YAML document the content is
324 * all about a collection of scalars used to create new data types such as
325 * key-value pairs. This allows complex documents to represent anything from
326 * a string to a tree.
330 * YAML scalars are a simple value which can be a string, number or Boolean.
331 * They are the simplest data types. They can exist in a YAML document but
332 * are typically used to build more complex data formats.
336 * In YAML collections are scalar elements presented in the form of
337 * an array, called a sequence, or mappings (hashes) that are scalar
338 * key value pairs. All elements belonging to the same collection are
339 * the lines that begin at the same indentation level
341 * Sequences use a dash followed by a space.
342 * Mappings use a colon followed by a space (: ) to mark each key/value pair:
344 * Collections can be represented in two forms, flow and block.
345 * Note they are equivalent. Example of block sequence is;
351 * and a block mapping example is:
357 * YAML flow styles for collections uses explicit indicators rather than
358 * indentation to denote scope.
360 * A sequence can be written as a comma separated list within
361 * square brackets ([]):
363 * [ PHP, Perl, Python ]
365 * A mapping can be written as a comma separated list of key/values within
368 * { PHP: 5.2, MySQL: 5.1, Apache: 2.2.20 }
370 * NOTE!! flow and block are equivalent.
374 * A list is a defined array of data which can be either an flow or block
375 * sequence. Lists can be nested. Example
377 * numbers: [ 1, 2, 3, 4 ]
387 * Are comprised of a key: value format with contents indented. This is
388 * built on top of the flow or block mapping. Like lists they can be nested.
396 /* In YAML you have the concept of parsers and emitters. Parser
397 * consume YAML input from a file, character buffer, or in our
398 * case Netlink and emitters take data from some source and
399 * present it in a YAML format.
401 * In this section of the code we are handling the parsing of the
402 * Netlink packets coming in and using them to piece together a
403 * YAML document. We could in theory just dump a YAML document
404 * one line at a time over Netlink but the amount of data could
405 * become very large and impact performance. Additionally, having
406 * pseudo-YAML code in the kernel would be frowned on. We can
407 * optimize the network traffic by taking advantage of the fact
408 * that for key/value pairs the keys rarely change. We can
409 * break up the data into keys and the values. The first Netlink
410 * data packets received will be a nested keys table which we
411 * can cache locally. As we receive the value pairs we can then
412 * reconstruct the key : value pair by looking up the the key
413 * in the stored table. In effect we end up with a one key to
414 * many values stream of data.
416 * The data structures below are used to create a tree data
417 * structure which is the natural flow of both YAML and
420 struct yaml_nl_node {
421 struct nl_list_head list;
422 struct nl_list_head children;
423 struct ln_key_list keys;
426 struct yaml_netlink_input {
427 yaml_parser_t *parser;
435 unsigned int version;
436 struct yaml_nl_node *cur;
437 struct yaml_nl_node *root;
440 /* Sadly this is not exported out of libyaml. We want to
441 * give descent error message to help people track down
442 * issues. This is internal only to this code. The end
443 * user will never need to use this.
446 yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem,
447 size_t offset, int value)
449 parser->error = YAML_READER_ERROR;
450 parser->problem = problem;
451 parser->problem_offset = offset;
452 parser->problem_value = value;
457 /* This is used to handle all the Netlink packets containing the keys
458 * for the key/value pairs. Instead of creating unique code to handle
459 * every type of Netlink attributes possible we create a generic
460 * abstract so the same code be used with everything. To make this
461 * work the key table trasmitted must report the tree structure and
462 * state of the keys. We use nested attributes as a way to notify libyaml
463 * we have a new collection. This is used to create the tree structure
464 * of the YAML document. Each collection of attributes define the following:
466 * LN_SCALAR_ATTR_INDEX:
467 * enum XXX_ATTR that defines which value we are dealing with. This
468 * varies greatly depending on the subsystem we have developed for.
470 * LN_SCALAR_ATTR_NLA_TYPE:
471 * The Netlink attribute type (NLA_STRING, NLA_U32, etc..) the coming
474 * LN_SCALAR_ATTR_VALUE:
475 * The string represnting key's actually scalar value.
477 * LN_SCALAR_ATTR_INT_VALUE:
478 * For this case the key is an integer value. This shouldn't be
479 * sent for the receive case since we are going to just turn it
480 * into a string for YAML. Sending packets will make use of this.
482 * LN_SCALAR_ATTR_KEY_TYPE:
483 * What YAML format is it? block or flow. Only useful for
484 * LN_SCALAR_ATTR_NLA_TYPE of type NLA_NESTED or NLA_NUL_STRING
486 * LN_SCALAR_ATTR_LIST + LN_SCALAR_LIST_SIZE:
487 * Defined the next collection which is a collection of nested
488 * attributes of the above.
490 static struct nla_policy scalar_attr_policy[LN_SCALAR_MAX + 1] = {
491 [LN_SCALAR_ATTR_LIST] = { .type = NLA_NESTED },
492 [LN_SCALAR_ATTR_LIST_SIZE] = { .type = NLA_U16 },
493 [LN_SCALAR_ATTR_INDEX] = { .type = NLA_U16 },
494 [LN_SCALAR_ATTR_NLA_TYPE] = { .type = NLA_U16 },
495 [LN_SCALAR_ATTR_VALUE] = { .type = NLA_STRING },
496 [LN_SCALAR_ATTR_INT_VALUE] = { .type = NLA_S64 },
497 [LN_SCALAR_ATTR_KEY_FORMAT] = { .type = NLA_U16 },
500 static int yaml_parse_key_list(struct yaml_netlink_input *data,
501 struct yaml_nl_node *parent,
504 struct nlattr *tbl_info[LN_SCALAR_MAX + 1];
505 struct yaml_nl_node *node = NULL;
509 nla_for_each_nested(attr, list, rem) {
512 if (nla_parse_nested(tbl_info, LN_SCALAR_MAX, attr,
516 if (tbl_info[LN_SCALAR_ATTR_LIST_SIZE]) {
519 cnt = nla_get_u16(tbl_info[LN_SCALAR_ATTR_LIST_SIZE]) + 1;
521 size_t len = sizeof(struct nl_list_head) * 2;
523 len += sizeof(struct ln_key_props) * cnt;
524 node = calloc(1, len);
528 node->keys.lkl_maxattr = cnt;
529 NL_INIT_LIST_HEAD(&node->children);
530 nl_init_list_head(&node->list);
537 nl_list_add_tail(&node->list,
542 if (tbl_info[LN_SCALAR_ATTR_INDEX])
543 index = nla_get_u16(tbl_info[LN_SCALAR_ATTR_INDEX]);
545 if (!node || index == 0)
548 if (tbl_info[LN_SCALAR_ATTR_KEY_FORMAT]) {
551 format = nla_get_u16(tbl_info[LN_SCALAR_ATTR_KEY_FORMAT]);
552 node->keys.lkl_list[index].lkp_key_format = format;
555 if (tbl_info[LN_SCALAR_ATTR_NLA_TYPE]) {
558 type = nla_get_u16(tbl_info[LN_SCALAR_ATTR_NLA_TYPE]);
559 node->keys.lkl_list[index].lkp_data_type = type;
562 if (tbl_info[LN_SCALAR_ATTR_VALUE]) {
565 name = nla_strdup(tbl_info[LN_SCALAR_ATTR_VALUE]);
568 node->keys.lkl_list[index].lkp_value = name;
571 if (tbl_info[LN_SCALAR_ATTR_LIST]) {
572 int rc = yaml_parse_key_list(data, node,
573 tbl_info[LN_SCALAR_ATTR_LIST]);
581 static struct yaml_nl_node *get_next_child(struct yaml_nl_node *node,
584 struct yaml_nl_node *child;
587 nl_list_for_each_entry(child, &node->children, list)
595 * In the YAML C implementation the scanner transforms the input stream
596 * (Netlink in this case) into a sequence of keys. First we need to
597 * examine the potential keys involved to see the mapping to Netlink.
598 * We have chosen to examine the YAML stack with keys since they are
599 * more detailed when compared to yaml_document_t / yaml_nodes and
602 * STREAM-START(encoding) # The stream start.
603 * STREAM-END # The stream end.
604 * VERSION-DIRECTIVE(major,minor) # The '%YAML' directive.
605 * TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive.
606 * DOCUMENT-START # '---'
607 * DOCUMENT-END # '...'
608 * BLOCK-SEQUENCE-START # Indentation increase denoting a block
609 * BLOCK-MAPPING-START # sequence or a block mapping.
610 * BLOCK-END # Indentation decrease.
611 * FLOW-SEQUENCE-START # '['
612 * FLOW-SEQUENCE-END # ']'
613 * FLOW-MAPPING-START # '{'
614 * FLOW-MAPPING-END # '}'
617 * KEY # '?' or nothing (simple keys).
619 * ALIAS(anchor) # '*anchor'
620 * ANCHOR(anchor) # '&anchor'
621 * TAG(handle,suffix) # '!handle!suffix'
622 * SCALAR(value,style) # A scalar.
624 * For our read_handler / write_handler STREAM-START / STREAM-END,
625 * VERSION-DIRECTIVE, and TAG-DIRECTIVE are hanndler by the libyaml
626 * internal scanner so we don't need to deal with it. Normally for
627 * LNet / Lustre DOCUMENT-START / DOCUMENT-END are not needed but it
628 * could be easily handled. In the case of multiplex streams we could
629 * see these used to differentiate data coming in.
631 * It is here we handle any simple scalars or values of the key /value
632 * pair. How the YAML document is formated is dependent on the key
635 static void yaml_parse_value_list(struct yaml_netlink_input *data, int *size,
636 struct nlattr *attr_array[],
637 struct ln_key_props *parent)
639 struct yaml_nl_node *node = data->cur;
640 struct ln_key_props *keys = node->keys.lkl_list;
641 int mapping = parent->lkp_key_format;
642 int child_idx = 0, len = 0, i;
644 for (i = 1; i < node->keys.lkl_maxattr; i++) {
647 attr = attr_array[i];
648 if (!attr && !keys[i].lkp_value)
651 if (keys[i].lkp_data_type != NLA_NUL_STRING &&
652 keys[i].lkp_data_type != NLA_NESTED) {
653 if (!attr && keys[i].lkp_data_type != NLA_FLAG)
656 if (!(mapping & LNKF_FLOW)) {
657 unsigned int indent = data->indent ?
660 memset(data->buffer, ' ', indent);
661 if (mapping & LNKF_SEQUENCE) {
662 ((char *)data->buffer)[indent - 2] = '-';
663 if (mapping & LNKF_MAPPING)
664 mapping &= ~LNKF_SEQUENCE;
666 data->buffer += indent;
670 if (mapping & LNKF_MAPPING) {
671 len = snprintf(data->buffer, *size, "%s: ",
680 switch (keys[i].lkp_data_type) {
682 struct yaml_nl_node *next = get_next_child(node,
684 int num = next ? next->keys.lkl_maxattr : 0;
685 struct nla_policy nest_policy[num];
686 struct yaml_nl_node *old;
687 struct nlattr *cnt_attr;
694 memset(nest_policy, 0, sizeof(struct nla_policy) * num);
695 for (j = 1; j < num; j++)
696 nest_policy[j].type = next->keys.lkl_list[j].lkp_data_type;
698 if (keys[i].lkp_key_format & LNKF_FLOW) {
701 if (keys[i].lkp_key_format &
704 len = snprintf(data->buffer, *size,
710 if (keys[i].lkp_key_format &
713 if (keys[i].lkp_key_format &
717 if (keys[i].lkp_value) {
718 len = snprintf(data->buffer,
735 nla_for_each_nested(cnt_attr, attr, rem) {
736 struct nlattr *nest_info[num];
738 if (nla_parse_nested(nest_info, num, cnt_attr,
742 data->indent += indent;
743 yaml_parse_value_list(data, size, nest_info,
745 data->indent -= indent;
748 if (keys[i].lkp_key_format & LNKF_FLOW) {
749 char *tmp = (char *)data->buffer - 2;
750 char *brace = " }\n";
752 if (keys[i].lkp_key_format &
756 memcpy(tmp, brace, strlen(brace));
766 if (data->cur != data->root)
769 /* The top level is special so only print
772 if (strlen(keys[i].lkp_value)) {
773 len = snprintf(data->buffer,
783 if (!(mapping & LNKF_FLOW)) {
784 if (mapping & LNKF_SEQUENCE)
786 else if (mapping & LNKF_MAPPING)
790 if (attr && parent->lkp_value) {
791 free(parent->lkp_value);
792 parent->lkp_value = nla_strdup(attr);
798 len = snprintf(data->buffer, *size, "%s",
799 nla_get_string(attr));
803 len = snprintf(data->buffer, *size, "%s",
804 attr ? "true" : "false");
808 len = snprintf(data->buffer, *size, "%hu",
813 len = snprintf(data->buffer, *size, "%u",
818 len = snprintf(data->buffer, *size, "%ju",
823 len = snprintf(data->buffer, *size, "%hd",
828 len = snprintf(data->buffer, *size, "%d",
833 len = snprintf(data->buffer, *size, "%jd",
841 if (mapping & LNKF_FLOW) {
842 strcat((char *)data->buffer, ", ");
845 if ((mapping == LNKF_SEQUENCE) &&
847 ((char *)data->buffer)[len++] = ':';
849 ((char *)data->buffer)[len++] = '\n';
853 } else if (len < 0) {
855 data->buffer -= data->indent + 2;
856 *size -= data->indent + 2;
861 static bool cleanup_children(struct yaml_nl_node *parent)
863 struct yaml_nl_node *child;
865 if (nl_list_empty(&parent->children)) {
866 struct ln_key_props *keys = parent->keys.lkl_list;
869 for (i = 1; i < parent->keys.lkl_maxattr; i++)
870 if (keys[i].lkp_value)
871 free(keys[i].lkp_value);
872 nl_list_del(&parent->list);
876 while ((child = get_next_child(parent, 0)) != NULL) {
877 if (cleanup_children(child))
884 /* This is the CB_VALID callback for the Netlink library that we
885 * have hooked into. Any successful Netlink message is passed to
886 * this function which handles both the incoming key tables and
887 * the values of the key/value pairs being received. We use
888 * the NLM_F_CREATE flag to determine if the incoming Netlink
889 * message is a key table or a packet containing value pairs.
891 static int yaml_netlink_msg_parse(struct nl_msg *msg, void *arg)
893 struct yaml_netlink_input *data = arg;
894 struct nlmsghdr *nlh = nlmsg_hdr(msg);
896 if (nlh->nlmsg_flags & NLM_F_CREATE) {
897 struct genlmsghdr *ghdr = genlmsg_hdr(nlh);
898 struct nlattr *attrs[LN_SCALAR_MAX + 1];
900 if (lnet_genlmsg_parse(nlh, 0, attrs, LN_SCALAR_MAX,
904 /* If root already exists this means we are updating the
905 * key table. Free old key table.
907 if (data->root && (nlh->nlmsg_flags & NLM_F_REPLACE)) {
908 cleanup_children(data->root);
913 if (attrs[LN_SCALAR_ATTR_LIST]) {
914 int rc = yaml_parse_key_list(data, NULL,
915 attrs[LN_SCALAR_ATTR_LIST]);
919 /* reset to root node */
920 data->cur = data->root;
923 /* For streaming insert '---' to define start of
924 * YAML document. This allows use to extract
925 * documents out of a multiplexed stream.
928 char *start_doc = "---\n";
929 size_t len = strlen(start_doc) + 1;
931 strncpy(data->buffer, start_doc, len);
932 data->buffer += len - 1;
934 data->version = ghdr->version;
936 uint16_t maxtype = data->cur->keys.lkl_maxattr;
937 struct nla_policy policy[maxtype];
938 struct nlattr *attrs[maxtype];
941 memset(policy, 0, sizeof(struct nla_policy) * maxtype);
942 for (i = 1; i < maxtype; i++)
943 policy[i].type = data->cur->keys.lkl_list[i].lkp_data_type;
945 if (lnet_genlmsg_parse(nlh, 0, attrs, maxtype, policy))
948 size = data->parser->raw_buffer.end -
949 (unsigned char *)data->buffer;
950 yaml_parse_value_list(data, &size, attrs,
951 &data->cur->keys.lkl_list[1]);
954 /* Let yaml_netlink_msg_complete end collecting data */
958 /* This is the libnl callback for when an error has happened
959 * kernel side. An error message is sent back to the user.
961 static int yaml_netlink_msg_error(struct sockaddr_nl *who,
962 struct nlmsgerr *errmsg, void *arg)
964 struct nlmsghdr *nlh = (void *)errmsg - NLMSG_HDRLEN;
965 struct yaml_netlink_input *data = arg;
967 if ((nlh->nlmsg_type == NLMSG_ERROR ||
968 nlh->nlmsg_flags & NLM_F_ACK_TLVS) && errmsg->error) {
969 /* libyaml stomps on the reader error so we need to
970 * cache the source of the error.
972 const char *errstr = nl_geterror(nl_syserr2nlerr(errmsg->error));
974 #ifdef HAVE_USRSPC_NLMSGERR
975 /* Newer kernels support NLM_F_ACK_TLVS in nlmsg_flags
976 * which gives greater detail why we failed.
978 if ((nlh->nlmsg_flags & NLM_F_ACK_TLVS) &&
979 !(nlh->nlmsg_flags & NLM_F_CAPPED)) {
980 struct nlattr *head = ((void *)&errmsg->msg);
981 struct nlattr *tb[NLMSGERR_ATTR_MAX];
983 if (nla_parse(tb, NLMSGERR_ATTR_MAX, head,
984 nlmsg_attrlen(nlh, 0), NULL) == 0) {
985 if (tb[NLMSGERR_ATTR_MSG])
986 errstr = nla_strdup(tb[NLMSGERR_ATTR_MSG]);
989 #endif /* HAVE_USRSPC_NLMSGERR */
990 data->errmsg = errstr;
991 data->error = errmsg->error;
992 data->parser->error = YAML_READER_ERROR;
993 data->complete = true;
998 /* This is the libnl callback for when the last Netlink packet
999 * is finished being parsed or its called right away in case
1000 * the Linux kernel reports back an error from the Netlink layer.
1002 static int yaml_netlink_msg_complete(struct nl_msg *msg, void *arg)
1004 struct yaml_netlink_input *data = arg;
1005 struct nlmsghdr *nlh = nlmsg_hdr(msg);
1007 /* For the case of NLM_F_DUMP the kernel will send error msgs
1008 * yet not be labled NLMSG_ERROR which results in this code
1009 * path being executed.
1011 yaml_netlink_msg_error(NULL, nlmsg_data(nlh), arg);
1012 if (data->parser->error == YAML_READER_ERROR)
1015 /* Free internal data. */
1017 cleanup_children(data->root);
1022 /* For streaming insert '...' to define end of
1026 char *end_doc = "...\n";
1027 size_t len = strlen(end_doc) + 1;
1029 strncpy(data->buffer, end_doc, len);
1030 data->buffer += len - 1;
1032 data->complete = true;
1035 return data->async ? NL_OK : NL_STOP;
1039 * In order for yaml_parser_set_input_netlink() to work we have to
1040 * register a yaml_read_handler_t callback. This is that call back
1041 * which listens for Netlink packets. Internally nl_recvmsg_report()
1042 * calls the various callbacks discussed above.
1044 static int yaml_netlink_read_handler(void *arg, unsigned char *buffer,
1045 size_t size, size_t *size_read)
1047 struct yaml_netlink_input *data = arg;
1048 struct nl_sock *nl = data->nl;
1052 if (data->complete) {
1057 data->buffer = buffer;
1059 cb = nl_socket_get_cb(nl);
1060 rc = nl_recvmsgs_report(nl, cb);
1061 if (rc == -NLE_INTR) {
1064 } else if (!data->errmsg && rc < 0) {
1065 data->errmsg = nl_geterror(rc);
1067 } else if (data->parser->error) {
1068 /* data->errmsg is set in NL_CB_FINISH */
1072 rc = (unsigned char *)data->buffer - buffer;
1080 /* libyaml by default just reports "input error" for parser read_handler_t
1081 * issues which is not useful. This provides away to get better debugging
1084 YAML_DECLARE(const char *)
1085 yaml_parser_get_reader_error(yaml_parser_t *parser)
1087 struct yaml_netlink_input *buf = parser->read_handler_data;
1097 yaml_parser_get_reader_proto_version(yaml_parser_t *parser)
1099 struct yaml_netlink_input *buf = parser->read_handler_data;
1104 return buf->version;
1107 /* yaml_parser_set_input_netlink() mirrors the libyaml function
1108 * yaml_parser_set_input_file(). Internally it does setup of the
1109 * libnl socket callbacks to parse the Netlink messages received
1110 * as well as register the special yaml_read_handler_t for libyaml.
1111 * This is exposed for public use.
1114 yaml_parser_set_input_netlink(yaml_parser_t *reply, struct nl_sock *nl,
1117 struct yaml_netlink_input *buf;
1120 buf = calloc(1, sizeof(*buf));
1122 reply->error = YAML_MEMORY_ERROR;
1126 rc = lustre_netlink_register(nl, stream);
1128 yaml_parser_set_reader_error(reply,
1129 "netlink setup failed", 0,
1135 buf->async = stream;
1136 buf->parser = reply;
1137 yaml_parser_set_input(buf->parser, yaml_netlink_read_handler, buf);
1139 rc = nl_socket_modify_cb(buf->nl, NL_CB_VALID, NL_CB_CUSTOM,
1140 yaml_netlink_msg_parse, buf);
1142 yaml_parser_set_reader_error(reply,
1143 "netlink msg recv setup failed",
1148 rc = nl_socket_modify_cb(buf->nl, NL_CB_FINISH, NL_CB_CUSTOM,
1149 yaml_netlink_msg_complete, buf);
1151 yaml_parser_set_reader_error(reply,
1152 "netlink msg cleanup setup failed",
1157 rc = nl_socket_modify_err_cb(nl, NL_CB_CUSTOM, yaml_netlink_msg_error,
1160 yaml_parser_set_reader_error(reply,
1161 "failed to register error handling",
1167 return rc < 0 ? false : true;
1170 /* The role of the YAML emitter for us is to take a YAML document and
1171 * change into a Netlink stream to send to the kernel to be processed.
1172 * This provides the infrastructure to do this.
1174 struct yaml_netlink_output {
1175 yaml_emitter_t *emitter;
1185 /* Internal use for this file only. We fill in details of why creating
1186 * a Netlink packet to send failed. The end user will be able to debug
1190 yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem)
1192 emitter->error = YAML_WRITER_ERROR;
1193 emitter->problem = problem;
1198 static unsigned int indent_level(const char *str)
1200 char *tmp = (char *)str;
1202 while (isspace(*tmp))
1207 #define LNKF_BLOCK 8
1209 static enum lnet_nl_key_format yaml_format_type(yaml_emitter_t *emitter,
1211 unsigned int *offset)
1213 unsigned int indent = *offset, new_indent = 0;
1214 enum lnet_nl_key_format fmt = 0;
1217 new_indent = indent_level(line);
1218 if (new_indent < indent) {
1219 *offset = indent - emitter->best_indent;
1223 if (strncmp(line + new_indent, "- ", 2) == 0) {
1224 memset(line + new_indent, ' ', 2);
1226 fmt |= LNKF_SEQUENCE;
1229 /* hdr: [ a : 1, b : 2, c : 3 ] */
1230 tmp = strstr(line + new_indent, ": ");
1232 tmp = line + new_indent;
1234 fmt |= LNKF_MAPPING;
1236 flow = strchr(line + new_indent, '{');
1238 flow = strchr(line + new_indent, '[');
1241 fmt &= ~LNKF_MAPPING;
1243 } else if (strchr(tmp, '}') || strchr(tmp, ']')) {
1244 if (strchr(tmp, ']'))
1245 fmt &= ~LNKF_MAPPING;
1249 if (indent != new_indent) {
1250 *offset = new_indent;
1257 static int yaml_fill_scalar_data(struct nl_msg *msg,
1258 enum lnet_nl_key_format fmt,
1261 char *sep = strstr(line, ": "); /* handle mappings */
1266 char *tmp = strchr(line, ':');
1268 if (tmp && strlen(tmp) == 1) /* handle simple scalar */
1274 if (strspn(line, "-0123456789") == strlen(line)) {
1275 num = strtoll(line, NULL, 0);
1277 NLA_PUT_S64(msg, LN_SCALAR_ATTR_INT_VALUE, num);
1279 NLA_PUT_STRING(msg, LN_SCALAR_ATTR_VALUE, line);
1282 if (fmt & LNKF_FLOW) {
1283 memset(line, ' ', strlen(line) + 1);
1284 goto nla_put_failure;
1287 if (fmt & LNKF_MAPPING && sep) {
1288 while (isspace(*sep))
1292 goto nla_put_failure;
1294 if (strspn(sep, "-0123456789") == strlen(sep)) {
1295 num = strtoll(sep, NULL, 0);
1296 NLA_PUT_S64(msg, LN_SCALAR_ATTR_INT_VALUE, num);
1298 NLA_PUT_STRING(msg, LN_SCALAR_ATTR_VALUE, sep);
1305 static int yaml_create_nested_list(struct yaml_netlink_output *out,
1306 struct nl_msg *msg, char **hdr,
1307 char **entry, unsigned int *indent,
1308 enum lnet_nl_key_format fmt)
1310 struct nlattr *mapping = NULL, *seq = NULL;
1314 /* Not needed for FLOW only case */
1315 if (fmt & LNKF_SEQUENCE) {
1316 seq = nla_nest_start(msg, LN_SCALAR_ATTR_LIST);
1318 yaml_emitter_set_writer_error(out->emitter,
1319 "Emmitter netlink list creation failed");
1321 goto nla_put_failure;
1325 if (fmt & LNKF_FLOW) {
1326 struct nlattr *list = NULL;
1327 bool format = false;
1330 if (fmt != LNKF_FLOW) {
1331 rc = yaml_fill_scalar_data(msg, fmt, *hdr + *indent);
1333 goto nla_put_failure;
1336 tmp = strchr(*hdr, '{');
1338 tmp = strchr(*hdr, '[');
1340 yaml_emitter_set_writer_error(out->emitter,
1341 "Emmitter flow format invalid");
1343 goto nla_put_failure;
1345 fmt |= LNKF_SEQUENCE;
1347 fmt |= LNKF_MAPPING;
1350 list = nla_nest_start(msg, LN_SCALAR_ATTR_LIST);
1352 yaml_emitter_set_writer_error(out->emitter,
1353 "Emmitter netlink list creation failed");
1355 goto nla_put_failure;
1359 while ((line = strsep(hdr, ",")) != NULL) {
1360 while (!isalnum(line[0]))
1363 /* Flow can be splt across lines by libyaml library. */
1364 if (strchr(line, ',')) {
1370 tmp = strchr(line, '}');
1372 tmp = strchr(line, ']');
1378 rc = yaml_fill_scalar_data(msg, fmt, line);
1380 goto nla_put_failure;
1382 /* Move to next YAML line */
1393 yaml_emitter_set_writer_error(out->emitter,
1394 "Emmitter flow format invalid");
1396 goto nla_put_failure;
1399 if (line && line[0] == '-')
1402 nla_nest_end(msg, list);
1405 if (fmt & LNKF_BLOCK && strchr(*hdr, ':')) {
1406 mapping = nla_nest_start(msg, LN_SCALAR_ATTR_LIST);
1408 yaml_emitter_set_writer_error(out->emitter,
1409 "Emmitter netlink list creation failed");
1411 goto nla_put_failure;
1415 rc = yaml_fill_scalar_data(msg, fmt, *hdr + *indent);
1417 goto nla_put_failure;
1420 line = strsep(entry, "\n");
1422 if (!line || !strlen(line) || strcmp(line, "...") == 0)
1425 fmt = yaml_format_type(out->emitter, line, indent);
1426 if (fmt == LNKF_BLOCK)
1429 /* sequences of simple scalars, general mappings, and
1430 * plain scalars are not nested structures in a
1433 if (fmt == LNKF_SEQUENCE || fmt == LNKF_MAPPING || fmt == 0) {
1434 rc = yaml_fill_scalar_data(msg, fmt,
1437 goto nla_put_failure;
1439 rc = yaml_create_nested_list(out, msg, &line,
1443 goto nla_put_failure;
1445 /* if the original line that called
1446 * yaml_create_nested_list above was an
1447 * sequence and the next line is also
1448 * then break to treat it as a mapping / scalar
1449 * instead to avoid over nesting.
1452 fmt = yaml_format_type(out->emitter, line, indent);
1453 if ((fmt & LNKF_SEQUENCE) || (fmt & LNKF_BLOCK))
1458 goto have_next_line;
1460 } while (strcmp(*entry, ""));
1463 nla_nest_end(msg, mapping);
1468 /* test if next line is sequence at the same level. */
1469 if (line && (line[0] != '\0') && (fmt & LNKF_BLOCK)) {
1470 int old_indent = indent_level(*hdr);
1472 fmt = yaml_format_type(out->emitter, line, indent);
1473 if (fmt != LNKF_BLOCK && old_indent == *indent) {
1474 /* If we have a normal mapping set then treate
1475 * it as a collection of scalars i.e don't create
1476 * another nested level. For scalar:\n and plain
1477 * scalar case we send it to next_mapping to
1478 * create another nested level.
1480 tmp = strchr(line, ':');
1483 if (strstr(line, ": "))
1484 fmt |= LNKF_MAPPING;
1485 if (strstr(line, "- "))
1486 fmt |= LNKF_SEQUENCE;
1491 goto have_next_line;
1498 nla_nest_end(msg, seq);
1500 if (*entry && !strlen(*entry) && fmt != LNKF_BLOCK)
1504 /* strsep in the above loop moves entry to a value pass the end of the
1505 * nested list. So to avoid losing this value we replace hdr with line.
1512 /* YAML allows ' and " in its documents but those characters really
1513 * confuse libc string handling. The workaround is to replace
1514 * ' and " with another reserved character for YAML '%' which is
1515 * for tags which shouldn't matter if we send in a Netlink packet.
1516 * The kernel side will need to handle % in a special way.
1518 static void yaml_quotation_handling(char *buf)
1520 char *tmp = buf, *line;
1522 line = strstr(tmp, "! \'");
1526 while ((line = strchr(tmp, '\"')) != NULL) {
1528 tmp = strchr(line, '\"');
1532 while ((line = strchr(tmp, '\'')) != NULL) {
1534 tmp = strchr(line, '\'');
1539 /* libyaml takes the YAML documents and places the data into an
1540 * internal buffer to the library. We take each line and turn it
1541 * into a Netlink message using the same format as the key table.
1542 * The reason for this approach is that we can do filters at the
1543 * key level or the key + value level.
1545 static int yaml_netlink_write_handler(void *data, unsigned char *buffer,
1548 struct yaml_netlink_output *out = data;
1549 char *buf = strndup((char *)buffer, size);
1550 char *entry = buf, *tmp = buf, *line;
1551 enum lnet_nl_key_format fmt = 0;
1552 struct nl_msg *msg = NULL;
1553 unsigned int indent = 0;
1554 bool nogroups = true;
1557 yaml_quotation_handling(entry);
1559 while (entry && strcmp(line = strsep(&entry, "\n"), "")) {
1561 if (strcmp(line, "---") == 0 || strcmp(line, "...") == 0)
1564 /* In theory we could have a sequence of groups but a bug in
1565 * libyaml prevents this from happing
1567 if (line[0] != ' ' && line[0] != '-') {
1570 if (strchr(line, '{') || strchr(line, '['))
1573 tmp = strchr(line, ':');
1578 rc = lustre_netlink_add_group(out->nl, out->family,
1581 yaml_emitter_set_writer_error(out->emitter,
1582 "Netlink group does not exist");
1583 goto nla_put_failure;
1586 /* Handle case first line contains more than a
1592 goto already_have_line;
1598 msg = nlmsg_alloc();
1600 out->emitter->error = YAML_MEMORY_ERROR;
1601 goto nla_put_failure;
1604 usr_hdr = genlmsg_put(msg, out->pid,
1607 out->flags, out->cmd,
1610 out->emitter->error = YAML_MEMORY_ERROR;
1612 goto nla_put_failure;
1619 fmt = yaml_format_type(out->emitter, line, &indent);
1621 rc = yaml_create_nested_list(out, msg, &line,
1625 yaml_emitter_set_writer_error(out->emitter,
1628 goto nla_put_failure;
1630 /* yaml_create_nested_list set line to the next
1631 * entry. We can just add it to the msg directly.
1634 goto already_have_line;
1636 rc = yaml_fill_scalar_data(msg, fmt,
1639 yaml_emitter_set_writer_error(out->emitter,
1642 goto nla_put_failure;
1648 /* Don't success if no valid groups found */
1650 yaml_emitter_set_writer_error(out->emitter,
1651 "Emitter contains no valid Netlink groups");
1652 goto nla_put_failure;
1656 rc = nl_send_auto(out->nl, msg);
1659 rc = genl_send_simple(out->nl, out->family_id, out->cmd,
1660 out->version, out->flags);
1663 yaml_emitter_set_writer_error(out->emitter,
1667 return out->emitter->error == YAML_NO_ERROR ? 1 : 0;
1670 /* This function is used by external utilities to use Netlink with
1671 * libyaml so we can turn YAML documentations into Netlink message
1672 * to send. This behavior mirrors yaml_emitter_set_output_file()
1673 * which is used to write out a YAML document to a file.
1676 yaml_emitter_set_output_netlink(yaml_emitter_t *sender, struct nl_sock *nl,
1677 char *family, int version, int cmd, int flags)
1679 struct yaml_netlink_output *out;
1681 out = calloc(1, sizeof(*out));
1683 sender->error = YAML_MEMORY_ERROR;
1688 out->family_id = genl_ctrl_resolve(nl, family);
1689 if (out->family_id < 0) {
1690 yaml_emitter_set_writer_error(sender,
1691 "failed to resolve Netlink family id");
1696 out->emitter = sender;
1698 out->family = family;
1699 out->version = version;
1702 out->pid = nl_socket_get_local_port(nl);
1703 yaml_emitter_set_output(sender, yaml_netlink_write_handler, out);
1707 /* Error handling helpers */
1708 void yaml_emitter_log_error(yaml_emitter_t *emitter, FILE *log)
1710 /* YAML_WRITER_ERROR means no Netlink support so use old API */
1711 switch (emitter->error) {
1712 case YAML_MEMORY_ERROR:
1713 fprintf(log, "Memory error: Not enough memory for emitting\n");
1715 case YAML_WRITER_ERROR:
1716 fprintf(log, "Writer error: %s\n", emitter->problem);
1718 case YAML_EMITTER_ERROR:
1719 fprintf(log, "Emitter error: %s\n", emitter->problem);
1725 void yaml_parser_log_error(yaml_parser_t *parser, FILE *log, const char *errmsg)
1729 switch (parser->error) {
1730 case YAML_MEMORY_ERROR:
1731 fprintf(log, "Memory error: Not enough memory for parser\n");
1734 case YAML_SCANNER_ERROR:
1735 case YAML_PARSER_ERROR:
1736 if (parser->context) {
1738 "%s error: %s at line %d, column %d\n%s at line %d, column %d\n",
1739 parser->error == YAML_SCANNER_ERROR ? "Scanner" : "Parser",
1741 (int)parser->context_mark.line + 1,
1742 (int)parser->context_mark.column + 1,
1744 (int)parser->problem_mark.line + 1,
1745 (int)parser->problem_mark.column + 1);
1747 fprintf(log, "%s error: %s at line %d, column %d\n",
1748 parser->error == YAML_SCANNER_ERROR ? "Scanner" : "Parser",
1750 (int)parser->problem_mark.line + 1,
1751 (int)parser->problem_mark.column + 1);
1755 case YAML_READER_ERROR:
1756 extra = yaml_parser_get_reader_error(parser);
1758 extra = parser->problem;
1760 if (parser->problem_value != -1) {
1761 fprintf(log, "Reader error: '%s':#%X at %ld'\n",
1762 extra, parser->problem_value,
1763 (long)parser->problem_offset);
1765 fprintf(log, "Reader error: '%s' at %ld\n",
1766 extra, (long)parser->problem_offset);