Skip to content

Commit 2d4bc93

Browse files
jmberg-inteldavem330
authored andcommitted
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: Johannes Berg <johannes.berg@intel.com> Reviewed-by: David Ahern <dsa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent fb9eb89 commit 2d4bc93

File tree

17 files changed

+153
-34
lines changed

17 files changed

+153
-34
lines changed

crypto/crypto_user.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,8 @@ static const struct crypto_link {
483483
[CRYPTO_MSG_DELRNG - CRYPTO_MSG_BASE] = { .doit = crypto_del_rng },
484484
};
485485

486-
static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
486+
static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
487+
struct netlink_ext_ack *extack)
487488
{
488489
struct nlattr *attrs[CRYPTOCFGA_MAX+1];
489490
const struct crypto_link *link;

drivers/infiniband/core/netlink.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ int ibnl_put_attr(struct sk_buff *skb, struct nlmsghdr *nlh,
146146
}
147147
EXPORT_SYMBOL(ibnl_put_attr);
148148

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

212-
ibnl_rcv_msg(skb, nlh);
213+
ibnl_rcv_msg(skb, nlh, NULL);
213214

214215
msglen = NLMSG_ALIGN(nlh->nlmsg_len);
215216
if (msglen > skb->len)

drivers/scsi/scsi_netlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
111111

112112
next_msg:
113113
if ((err) || (nlh->nlmsg_flags & NLM_F_ACK))
114-
netlink_ack(skb, nlh, err);
114+
netlink_ack(skb, nlh, err, NULL);
115115

116116
skb_pull(skb, rlen);
117117
}

include/linux/netlink.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,35 @@ netlink_kernel_create(struct net *net, int unit, struct netlink_kernel_cfg *cfg)
6262
return __netlink_kernel_create(net, unit, THIS_MODULE, cfg);
6363
}
6464

65+
/**
66+
* struct netlink_ext_ack - netlink extended ACK report struct
67+
* @_msg: message string to report - don't access directly, use
68+
* %NL_SET_ERR_MSG
69+
* @bad_attr: attribute with error
70+
*/
71+
struct netlink_ext_ack {
72+
const char *_msg;
73+
const struct nlattr *bad_attr;
74+
};
75+
76+
/* Always use this macro, this allows later putting the
77+
* message into a separate section or such for things
78+
* like translation or listing all possible messages.
79+
* Currently string formatting is not supported (due
80+
* to the lack of an output buffer.)
81+
*/
82+
#define NL_SET_ERR_MSG(extack, msg) do { \
83+
static const char _msg[] = (msg); \
84+
\
85+
(extack)->_msg = _msg; \
86+
} while (0)
87+
6588
extern void netlink_kernel_release(struct sock *sk);
6689
extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups);
6790
extern int netlink_change_ngroups(struct sock *sk, unsigned int groups);
6891
extern void __netlink_clear_multicast_users(struct sock *sk, unsigned int group);
69-
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
92+
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
93+
const struct netlink_ext_ack *extack);
7094
extern int netlink_has_listeners(struct sock *sk, unsigned int group);
7195

7296
extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 portid, int nonblock);

include/net/netlink.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,8 @@ struct nl_info {
233233
};
234234

235235
int netlink_rcv_skb(struct sk_buff *skb,
236-
int (*cb)(struct sk_buff *, struct nlmsghdr *));
236+
int (*cb)(struct sk_buff *, struct nlmsghdr *,
237+
struct netlink_ext_ack *));
237238
int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid,
238239
unsigned int group, int report, gfp_t flags);
239240

include/uapi/linux/netlink.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ struct nlmsghdr {
6969
#define NLM_F_CREATE 0x400 /* Create, if it does not exist */
7070
#define NLM_F_APPEND 0x800 /* Add to end of list */
7171

72+
/* Flags for ACK message */
73+
#define NLM_F_CAPPED 0x100 /* request was capped */
74+
#define NLM_F_ACK_TLVS 0x200 /* extended ACK TVLs were included */
75+
7276
/*
7377
4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL
7478
4.4BSD CHANGE NLM_F_REPLACE
@@ -101,6 +105,33 @@ struct nlmsghdr {
101105
struct nlmsgerr {
102106
int error;
103107
struct nlmsghdr msg;
108+
/*
109+
* followed by the message contents unless NETLINK_CAP_ACK was set
110+
* or the ACK indicates success (error == 0)
111+
* message length is aligned with NLMSG_ALIGN()
112+
*/
113+
/*
114+
* followed by TLVs defined in enum nlmsgerr_attrs
115+
* if NETLINK_EXT_ACK was set
116+
*/
117+
};
118+
119+
/**
120+
* enum nlmsgerr_attrs - nlmsgerr attributes
121+
* @NLMSGERR_ATTR_UNUSED: unused
122+
* @NLMSGERR_ATTR_MSG: error message string (string)
123+
* @NLMSGERR_ATTR_OFFS: offset of the invalid attribute in the original
124+
* message, counting from the beginning of the header (u32)
125+
* @__NLMSGERR_ATTR_MAX: number of attributes
126+
* @NLMSGERR_ATTR_MAX: highest attribute number
127+
*/
128+
enum nlmsgerr_attrs {
129+
NLMSGERR_ATTR_UNUSED,
130+
NLMSGERR_ATTR_MSG,
131+
NLMSGERR_ATTR_OFFS,
132+
133+
__NLMSGERR_ATTR_MAX,
134+
NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1
104135
};
105136

106137
#define NETLINK_ADD_MEMBERSHIP 1
@@ -115,6 +146,7 @@ struct nlmsgerr {
115146
#define NETLINK_LISTEN_ALL_NSID 8
116147
#define NETLINK_LIST_MEMBERSHIPS 9
117148
#define NETLINK_CAP_ACK 10
149+
#define NETLINK_EXT_ACK 11
118150

119151
struct nl_pktinfo {
120152
__u32 group;

kernel/audit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1402,7 +1402,7 @@ static void audit_receive_skb(struct sk_buff *skb)
14021402
err = audit_receive_msg(skb, nlh);
14031403
/* if err or if this message says it wants a response */
14041404
if (err || (nlh->nlmsg_flags & NLM_F_ACK))
1405-
netlink_ack(skb, nlh, err);
1405+
netlink_ack(skb, nlh, err, NULL);
14061406

14071407
nlh = nlmsg_next(nlh, &len);
14081408
}

net/core/rtnetlink.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4046,7 +4046,8 @@ static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
40464046

40474047
/* Process one rtnetlink message. */
40484048

4049-
static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
4049+
static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
4050+
struct netlink_ext_ack *extack)
40504051
{
40514052
struct net *net = sock_net(skb->sk);
40524053
rtnl_doit_func doit;

net/core/sock_diag.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ static int __sock_diag_cmd(struct sk_buff *skb, struct nlmsghdr *nlh)
238238
return err;
239239
}
240240

241-
static int sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
241+
static int sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
242+
struct netlink_ext_ack *extack)
242243
{
243244
int ret;
244245

net/decnet/netfilter/dn_rtmsg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ static unsigned int dnrmg_hook(void *priv,
9696
}
9797

9898

99-
#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
99+
#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err), NULL); return; } while (0)
100100

101101
static inline void dnrmg_receive_user_skb(struct sk_buff *skb)
102102
{

0 commit comments

Comments
 (0)