Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netlink: allow sending extended ACK with cookie on success

Now that we have extended error reporting and a new message format for
netlink ACK messages, also extend this to be able to return arbitrary
cookie data on success.

This will allow, for example, nl80211 to not send an extra message for
cookies identifying newly created objects, but return those directly
in the ACK message.

The cookie data size is currently limited to 20 bytes (since Jamal
talked about using SHA1 for identifiers.)

Thanks to Jamal Hadi Salim for bringing up this idea during the
discussions.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Johannes Berg and committed by
David S. Miller
ba0dc5f6 7ab606d1

+33 -11
+7
include/linux/netlink.h
··· 62 62 return __netlink_kernel_create(net, unit, THIS_MODULE, cfg); 63 63 } 64 64 65 + /* this can be increased when necessary - don't expose to userland */ 66 + #define NETLINK_MAX_COOKIE_LEN 20 67 + 65 68 /** 66 69 * struct netlink_ext_ack - netlink extended ACK report struct 67 70 * @_msg: message string to report - don't access directly, use 68 71 * %NL_SET_ERR_MSG 69 72 * @bad_attr: attribute with error 73 + * @cookie: cookie data to return to userspace (for success) 74 + * @cookie_len: actual cookie data length 70 75 */ 71 76 struct netlink_ext_ack { 72 77 const char *_msg; 73 78 const struct nlattr *bad_attr; 79 + u8 cookie[NETLINK_MAX_COOKIE_LEN]; 80 + u8 cookie_len; 74 81 }; 75 82 76 83 /* Always use this macro, this allows later putting the
+4
include/uapi/linux/netlink.h
··· 122 122 * @NLMSGERR_ATTR_MSG: error message string (string) 123 123 * @NLMSGERR_ATTR_OFFS: offset of the invalid attribute in the original 124 124 * message, counting from the beginning of the header (u32) 125 + * @NLMSGERR_ATTR_COOKIE: arbitrary subsystem specific cookie to 126 + * be used - in the success case - to identify a created 127 + * object or operation or similar (binary) 125 128 * @__NLMSGERR_ATTR_MAX: number of attributes 126 129 * @NLMSGERR_ATTR_MAX: highest attribute number 127 130 */ ··· 132 129 NLMSGERR_ATTR_UNUSED, 133 130 NLMSGERR_ATTR_MSG, 134 131 NLMSGERR_ATTR_OFFS, 132 + NLMSGERR_ATTR_COOKIE, 135 133 136 134 __NLMSGERR_ATTR_MAX, 137 135 NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1
+22 -11
net/netlink/af_netlink.c
··· 2311 2311 } 2312 2312 } else { 2313 2313 flags |= NLM_F_CAPPED; 2314 + 2315 + if (nlk->flags & NETLINK_F_EXT_ACK && 2316 + extack && extack->cookie_len) 2317 + tlvlen += nla_total_size(extack->cookie_len); 2314 2318 } 2315 2319 2316 2320 if (tlvlen) ··· 2341 2337 errmsg->error = err; 2342 2338 memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh)); 2343 2339 2344 - if (err && nlk->flags & NETLINK_F_EXT_ACK && extack) { 2345 - if (extack->_msg) 2346 - WARN_ON(nla_put_string(skb, NLMSGERR_ATTR_MSG, 2347 - extack->_msg)); 2348 - if (extack->bad_attr && 2349 - !WARN_ON((u8 *)extack->bad_attr < in_skb->data || 2350 - (u8 *)extack->bad_attr >= in_skb->data + 2351 - in_skb->len)) 2352 - WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_OFFS, 2353 - (u8 *)extack->bad_attr - 2354 - in_skb->data)); 2340 + if (nlk->flags & NETLINK_F_EXT_ACK && extack) { 2341 + if (err) { 2342 + if (extack->_msg) 2343 + WARN_ON(nla_put_string(skb, NLMSGERR_ATTR_MSG, 2344 + extack->_msg)); 2345 + if (extack->bad_attr && 2346 + !WARN_ON((u8 *)extack->bad_attr < in_skb->data || 2347 + (u8 *)extack->bad_attr >= in_skb->data + 2348 + in_skb->len)) 2349 + WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_OFFS, 2350 + (u8 *)extack->bad_attr - 2351 + in_skb->data)); 2352 + } else { 2353 + if (extack->cookie_len) 2354 + WARN_ON(nla_put(skb, NLMSGERR_ATTR_COOKIE, 2355 + extack->cookie_len, 2356 + extack->cookie)); 2357 + } 2355 2358 } 2356 2359 2357 2360 nlmsg_end(skb, rep);