Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d4bc933 authored by Johannes Berg's avatar Johannes Berg Committed by David S. Miller
Browse files

netlink: extended ACK reporting



Add the base infrastructure and UAPI for netlink extended ACK
reporting. All "manual" calls to netlink_ack() pass NULL for now and
thus don't get extended ACK reporting.

Big thanks goes to Pablo Neira Ayuso for not only bringing up the
whole topic at netconf (again) but also coming up with the nlattr
passing trick and various other ideas.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Reviewed-by: default avatarDavid Ahern <dsa@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fb9eb899
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -483,7 +483,8 @@ static const struct crypto_link {
	[CRYPTO_MSG_DELRNG	- CRYPTO_MSG_BASE] = { .doit = crypto_del_rng },
	[CRYPTO_MSG_DELRNG	- CRYPTO_MSG_BASE] = { .doit = crypto_del_rng },
};
};


static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
			       struct netlink_ext_ack *extack)
{
{
	struct nlattr *attrs[CRYPTOCFGA_MAX+1];
	struct nlattr *attrs[CRYPTOCFGA_MAX+1];
	const struct crypto_link *link;
	const struct crypto_link *link;
+3 −2
Original line number Original line Diff line number Diff line
@@ -146,7 +146,8 @@ int ibnl_put_attr(struct sk_buff *skb, struct nlmsghdr *nlh,
}
}
EXPORT_SYMBOL(ibnl_put_attr);
EXPORT_SYMBOL(ibnl_put_attr);


static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
			struct netlink_ext_ack *extack)
{
{
	struct ibnl_client *client;
	struct ibnl_client *client;
	int type = nlh->nlmsg_type;
	int type = nlh->nlmsg_type;
@@ -209,7 +210,7 @@ static void ibnl_rcv_reply_skb(struct sk_buff *skb)
		if (nlh->nlmsg_flags & NLM_F_REQUEST)
		if (nlh->nlmsg_flags & NLM_F_REQUEST)
			return;
			return;


		ibnl_rcv_msg(skb, nlh);
		ibnl_rcv_msg(skb, nlh, NULL);


		msglen = NLMSG_ALIGN(nlh->nlmsg_len);
		msglen = NLMSG_ALIGN(nlh->nlmsg_len);
		if (msglen > skb->len)
		if (msglen > skb->len)
+1 −1
Original line number Original line Diff line number Diff line
@@ -111,7 +111,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)


next_msg:
next_msg:
		if ((err) || (nlh->nlmsg_flags & NLM_F_ACK))
		if ((err) || (nlh->nlmsg_flags & NLM_F_ACK))
			netlink_ack(skb, nlh, err);
			netlink_ack(skb, nlh, err, NULL);


		skb_pull(skb, rlen);
		skb_pull(skb, rlen);
	}
	}
+25 −1
Original line number Original line Diff line number Diff line
@@ -62,11 +62,35 @@ netlink_kernel_create(struct net *net, int unit, struct netlink_kernel_cfg *cfg)
	return __netlink_kernel_create(net, unit, THIS_MODULE, cfg);
	return __netlink_kernel_create(net, unit, THIS_MODULE, cfg);
}
}


/**
 * struct netlink_ext_ack - netlink extended ACK report struct
 * @_msg: message string to report - don't access directly, use
 *	%NL_SET_ERR_MSG
 * @bad_attr: attribute with error
 */
struct netlink_ext_ack {
	const char *_msg;
	const struct nlattr *bad_attr;
};

/* Always use this macro, this allows later putting the
 * message into a separate section or such for things
 * like translation or listing all possible messages.
 * Currently string formatting is not supported (due
 * to the lack of an output buffer.)
 */
#define NL_SET_ERR_MSG(extack, msg) do {	\
	static const char _msg[] = (msg);	\
						\
	(extack)->_msg = _msg;			\
} while (0)

extern void netlink_kernel_release(struct sock *sk);
extern void netlink_kernel_release(struct sock *sk);
extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups);
extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups);
extern int netlink_change_ngroups(struct sock *sk, unsigned int groups);
extern int netlink_change_ngroups(struct sock *sk, unsigned int groups);
extern void __netlink_clear_multicast_users(struct sock *sk, unsigned int group);
extern void __netlink_clear_multicast_users(struct sock *sk, unsigned int group);
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
			const struct netlink_ext_ack *extack);
extern int netlink_has_listeners(struct sock *sk, unsigned int group);
extern int netlink_has_listeners(struct sock *sk, unsigned int group);


extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 portid, int nonblock);
extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 portid, int nonblock);
+2 −1
Original line number Original line Diff line number Diff line
@@ -233,7 +233,8 @@ struct nl_info {
};
};


int netlink_rcv_skb(struct sk_buff *skb,
int netlink_rcv_skb(struct sk_buff *skb,
		    int (*cb)(struct sk_buff *, struct nlmsghdr *));
		    int (*cb)(struct sk_buff *, struct nlmsghdr *,
			      struct netlink_ext_ack *));
int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid,
int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid,
		 unsigned int group, int report, gfp_t flags);
		 unsigned int group, int report, gfp_t flags);


Loading