xref: /openbmc/linux/net/ethtool/netlink.h (revision 041b1c5d)
12b4a8990SMichal Kubecek /* SPDX-License-Identifier: GPL-2.0-only */
22b4a8990SMichal Kubecek 
32b4a8990SMichal Kubecek #ifndef _NET_ETHTOOL_NETLINK_H
42b4a8990SMichal Kubecek #define _NET_ETHTOOL_NETLINK_H
52b4a8990SMichal Kubecek 
62b4a8990SMichal Kubecek #include <linux/ethtool_netlink.h>
72b4a8990SMichal Kubecek #include <linux/netdevice.h>
82b4a8990SMichal Kubecek #include <net/genetlink.h>
9041b1c5dSMichal Kubecek #include <net/sock.h>
10041b1c5dSMichal Kubecek 
11041b1c5dSMichal Kubecek struct ethnl_req_info;
12041b1c5dSMichal Kubecek 
13041b1c5dSMichal Kubecek int ethnl_parse_header(struct ethnl_req_info *req_info,
14041b1c5dSMichal Kubecek 		       const struct nlattr *nest, struct net *net,
15041b1c5dSMichal Kubecek 		       struct netlink_ext_ack *extack, bool require_dev);
16041b1c5dSMichal Kubecek int ethnl_fill_reply_header(struct sk_buff *skb, struct net_device *dev,
17041b1c5dSMichal Kubecek 			    u16 attrtype);
18041b1c5dSMichal Kubecek struct sk_buff *ethnl_reply_init(size_t payload, struct net_device *dev, u8 cmd,
19041b1c5dSMichal Kubecek 				 u16 hdr_attrtype, struct genl_info *info,
20041b1c5dSMichal Kubecek 				 void **ehdrp);
21041b1c5dSMichal Kubecek 
22041b1c5dSMichal Kubecek /**
23041b1c5dSMichal Kubecek  * ethnl_strz_size() - calculate attribute length for fixed size string
24041b1c5dSMichal Kubecek  * @s: ETH_GSTRING_LEN sized string (may not be null terminated)
25041b1c5dSMichal Kubecek  *
26041b1c5dSMichal Kubecek  * Return: total length of an attribute with null terminated string from @s
27041b1c5dSMichal Kubecek  */
28041b1c5dSMichal Kubecek static inline int ethnl_strz_size(const char *s)
29041b1c5dSMichal Kubecek {
30041b1c5dSMichal Kubecek 	return nla_total_size(strnlen(s, ETH_GSTRING_LEN) + 1);
31041b1c5dSMichal Kubecek }
32041b1c5dSMichal Kubecek 
33041b1c5dSMichal Kubecek /**
34041b1c5dSMichal Kubecek  * ethnl_put_strz() - put string attribute with fixed size string
35041b1c5dSMichal Kubecek  * @skb:     skb with the message
36041b1c5dSMichal Kubecek  * @attrype: attribute type
37041b1c5dSMichal Kubecek  * @s:       ETH_GSTRING_LEN sized string (may not be null terminated)
38041b1c5dSMichal Kubecek  *
39041b1c5dSMichal Kubecek  * Puts an attribute with null terminated string from @s into the message.
40041b1c5dSMichal Kubecek  *
41041b1c5dSMichal Kubecek  * Return: 0 on success, negative error code on failure
42041b1c5dSMichal Kubecek  */
43041b1c5dSMichal Kubecek static inline int ethnl_put_strz(struct sk_buff *skb, u16 attrtype,
44041b1c5dSMichal Kubecek 				 const char *s)
45041b1c5dSMichal Kubecek {
46041b1c5dSMichal Kubecek 	unsigned int len = strnlen(s, ETH_GSTRING_LEN);
47041b1c5dSMichal Kubecek 	struct nlattr *attr;
48041b1c5dSMichal Kubecek 
49041b1c5dSMichal Kubecek 	attr = nla_reserve(skb, attrtype, len + 1);
50041b1c5dSMichal Kubecek 	if (!attr)
51041b1c5dSMichal Kubecek 		return -EMSGSIZE;
52041b1c5dSMichal Kubecek 
53041b1c5dSMichal Kubecek 	memcpy(nla_data(attr), s, len);
54041b1c5dSMichal Kubecek 	((char *)nla_data(attr))[len] = '\0';
55041b1c5dSMichal Kubecek 	return 0;
56041b1c5dSMichal Kubecek }
57041b1c5dSMichal Kubecek 
58041b1c5dSMichal Kubecek /**
59041b1c5dSMichal Kubecek  * ethnl_update_u32() - update u32 value from NLA_U32 attribute
60041b1c5dSMichal Kubecek  * @dst:  value to update
61041b1c5dSMichal Kubecek  * @attr: netlink attribute with new value or null
62041b1c5dSMichal Kubecek  * @mod:  pointer to bool for modification tracking
63041b1c5dSMichal Kubecek  *
64041b1c5dSMichal Kubecek  * Copy the u32 value from NLA_U32 netlink attribute @attr into variable
65041b1c5dSMichal Kubecek  * pointed to by @dst; do nothing if @attr is null. Bool pointed to by @mod
66041b1c5dSMichal Kubecek  * is set to true if this function changed the value of *dst, otherwise it
67041b1c5dSMichal Kubecek  * is left as is.
68041b1c5dSMichal Kubecek  */
69041b1c5dSMichal Kubecek static inline void ethnl_update_u32(u32 *dst, const struct nlattr *attr,
70041b1c5dSMichal Kubecek 				    bool *mod)
71041b1c5dSMichal Kubecek {
72041b1c5dSMichal Kubecek 	u32 val;
73041b1c5dSMichal Kubecek 
74041b1c5dSMichal Kubecek 	if (!attr)
75041b1c5dSMichal Kubecek 		return;
76041b1c5dSMichal Kubecek 	val = nla_get_u32(attr);
77041b1c5dSMichal Kubecek 	if (*dst == val)
78041b1c5dSMichal Kubecek 		return;
79041b1c5dSMichal Kubecek 
80041b1c5dSMichal Kubecek 	*dst = val;
81041b1c5dSMichal Kubecek 	*mod = true;
82041b1c5dSMichal Kubecek }
83041b1c5dSMichal Kubecek 
84041b1c5dSMichal Kubecek /**
85041b1c5dSMichal Kubecek  * ethnl_update_u8() - update u8 value from NLA_U8 attribute
86041b1c5dSMichal Kubecek  * @dst:  value to update
87041b1c5dSMichal Kubecek  * @attr: netlink attribute with new value or null
88041b1c5dSMichal Kubecek  * @mod:  pointer to bool for modification tracking
89041b1c5dSMichal Kubecek  *
90041b1c5dSMichal Kubecek  * Copy the u8 value from NLA_U8 netlink attribute @attr into variable
91041b1c5dSMichal Kubecek  * pointed to by @dst; do nothing if @attr is null. Bool pointed to by @mod
92041b1c5dSMichal Kubecek  * is set to true if this function changed the value of *dst, otherwise it
93041b1c5dSMichal Kubecek  * is left as is.
94041b1c5dSMichal Kubecek  */
95041b1c5dSMichal Kubecek static inline void ethnl_update_u8(u8 *dst, const struct nlattr *attr,
96041b1c5dSMichal Kubecek 				   bool *mod)
97041b1c5dSMichal Kubecek {
98041b1c5dSMichal Kubecek 	u8 val;
99041b1c5dSMichal Kubecek 
100041b1c5dSMichal Kubecek 	if (!attr)
101041b1c5dSMichal Kubecek 		return;
102041b1c5dSMichal Kubecek 	val = nla_get_u8(attr);
103041b1c5dSMichal Kubecek 	if (*dst == val)
104041b1c5dSMichal Kubecek 		return;
105041b1c5dSMichal Kubecek 
106041b1c5dSMichal Kubecek 	*dst = val;
107041b1c5dSMichal Kubecek 	*mod = true;
108041b1c5dSMichal Kubecek }
109041b1c5dSMichal Kubecek 
110041b1c5dSMichal Kubecek /**
111041b1c5dSMichal Kubecek  * ethnl_update_bool32() - update u32 used as bool from NLA_U8 attribute
112041b1c5dSMichal Kubecek  * @dst:  value to update
113041b1c5dSMichal Kubecek  * @attr: netlink attribute with new value or null
114041b1c5dSMichal Kubecek  * @mod:  pointer to bool for modification tracking
115041b1c5dSMichal Kubecek  *
116041b1c5dSMichal Kubecek  * Use the u8 value from NLA_U8 netlink attribute @attr to set u32 variable
117041b1c5dSMichal Kubecek  * pointed to by @dst to 0 (if zero) or 1 (if not); do nothing if @attr is
118041b1c5dSMichal Kubecek  * null. Bool pointed to by @mod is set to true if this function changed the
119041b1c5dSMichal Kubecek  * logical value of *dst, otherwise it is left as is.
120041b1c5dSMichal Kubecek  */
121041b1c5dSMichal Kubecek static inline void ethnl_update_bool32(u32 *dst, const struct nlattr *attr,
122041b1c5dSMichal Kubecek 				       bool *mod)
123041b1c5dSMichal Kubecek {
124041b1c5dSMichal Kubecek 	u8 val;
125041b1c5dSMichal Kubecek 
126041b1c5dSMichal Kubecek 	if (!attr)
127041b1c5dSMichal Kubecek 		return;
128041b1c5dSMichal Kubecek 	val = !!nla_get_u8(attr);
129041b1c5dSMichal Kubecek 	if (!!*dst == val)
130041b1c5dSMichal Kubecek 		return;
131041b1c5dSMichal Kubecek 
132041b1c5dSMichal Kubecek 	*dst = val;
133041b1c5dSMichal Kubecek 	*mod = true;
134041b1c5dSMichal Kubecek }
135041b1c5dSMichal Kubecek 
136041b1c5dSMichal Kubecek /**
137041b1c5dSMichal Kubecek  * ethnl_update_binary() - update binary data from NLA_BINARY atribute
138041b1c5dSMichal Kubecek  * @dst:  value to update
139041b1c5dSMichal Kubecek  * @len:  destination buffer length
140041b1c5dSMichal Kubecek  * @attr: netlink attribute with new value or null
141041b1c5dSMichal Kubecek  * @mod:  pointer to bool for modification tracking
142041b1c5dSMichal Kubecek  *
143041b1c5dSMichal Kubecek  * Use the u8 value from NLA_U8 netlink attribute @attr to rewrite data block
144041b1c5dSMichal Kubecek  * of length @len at @dst by attribute payload; do nothing if @attr is null.
145041b1c5dSMichal Kubecek  * Bool pointed to by @mod is set to true if this function changed the logical
146041b1c5dSMichal Kubecek  * value of *dst, otherwise it is left as is.
147041b1c5dSMichal Kubecek  */
148041b1c5dSMichal Kubecek static inline void ethnl_update_binary(void *dst, unsigned int len,
149041b1c5dSMichal Kubecek 				       const struct nlattr *attr, bool *mod)
150041b1c5dSMichal Kubecek {
151041b1c5dSMichal Kubecek 	if (!attr)
152041b1c5dSMichal Kubecek 		return;
153041b1c5dSMichal Kubecek 	if (nla_len(attr) < len)
154041b1c5dSMichal Kubecek 		len = nla_len(attr);
155041b1c5dSMichal Kubecek 	if (!memcmp(dst, nla_data(attr), len))
156041b1c5dSMichal Kubecek 		return;
157041b1c5dSMichal Kubecek 
158041b1c5dSMichal Kubecek 	memcpy(dst, nla_data(attr), len);
159041b1c5dSMichal Kubecek 	*mod = true;
160041b1c5dSMichal Kubecek }
161041b1c5dSMichal Kubecek 
162041b1c5dSMichal Kubecek /**
163041b1c5dSMichal Kubecek  * ethnl_update_bitfield32() - update u32 value from NLA_BITFIELD32 attribute
164041b1c5dSMichal Kubecek  * @dst:  value to update
165041b1c5dSMichal Kubecek  * @attr: netlink attribute with new value or null
166041b1c5dSMichal Kubecek  * @mod:  pointer to bool for modification tracking
167041b1c5dSMichal Kubecek  *
168041b1c5dSMichal Kubecek  * Update bits in u32 value which are set in attribute's mask to values from
169041b1c5dSMichal Kubecek  * attribute's value. Do nothing if @attr is null or the value wouldn't change;
170041b1c5dSMichal Kubecek  * otherwise, set bool pointed to by @mod to true.
171041b1c5dSMichal Kubecek  */
172041b1c5dSMichal Kubecek static inline void ethnl_update_bitfield32(u32 *dst, const struct nlattr *attr,
173041b1c5dSMichal Kubecek 					   bool *mod)
174041b1c5dSMichal Kubecek {
175041b1c5dSMichal Kubecek 	struct nla_bitfield32 change;
176041b1c5dSMichal Kubecek 	u32 newval;
177041b1c5dSMichal Kubecek 
178041b1c5dSMichal Kubecek 	if (!attr)
179041b1c5dSMichal Kubecek 		return;
180041b1c5dSMichal Kubecek 	change = nla_get_bitfield32(attr);
181041b1c5dSMichal Kubecek 	newval = (*dst & ~change.selector) | (change.value & change.selector);
182041b1c5dSMichal Kubecek 	if (*dst == newval)
183041b1c5dSMichal Kubecek 		return;
184041b1c5dSMichal Kubecek 
185041b1c5dSMichal Kubecek 	*dst = newval;
186041b1c5dSMichal Kubecek 	*mod = true;
187041b1c5dSMichal Kubecek }
188041b1c5dSMichal Kubecek 
189041b1c5dSMichal Kubecek /**
190041b1c5dSMichal Kubecek  * ethnl_reply_header_size() - total size of reply header
191041b1c5dSMichal Kubecek  *
192041b1c5dSMichal Kubecek  * This is an upper estimate so that we do not need to hold RTNL lock longer
193041b1c5dSMichal Kubecek  * than necessary (to prevent rename between size estimate and composing the
194041b1c5dSMichal Kubecek  * message). Accounts only for device ifindex and name as those are the only
195041b1c5dSMichal Kubecek  * attributes ethnl_fill_reply_header() puts into the reply header.
196041b1c5dSMichal Kubecek  */
197041b1c5dSMichal Kubecek static inline unsigned int ethnl_reply_header_size(void)
198041b1c5dSMichal Kubecek {
199041b1c5dSMichal Kubecek 	return nla_total_size(nla_total_size(sizeof(u32)) +
200041b1c5dSMichal Kubecek 			      nla_total_size(IFNAMSIZ));
201041b1c5dSMichal Kubecek }
202041b1c5dSMichal Kubecek 
203041b1c5dSMichal Kubecek /**
204041b1c5dSMichal Kubecek  * struct ethnl_req_info - base type of request information for GET requests
205041b1c5dSMichal Kubecek  * @dev:   network device the request is for (may be null)
206041b1c5dSMichal Kubecek  * @flags: request flags common for all request types
207041b1c5dSMichal Kubecek  *
208041b1c5dSMichal Kubecek  * This is a common base, additional members may follow after this structure.
209041b1c5dSMichal Kubecek  */
210041b1c5dSMichal Kubecek struct ethnl_req_info {
211041b1c5dSMichal Kubecek 	struct net_device	*dev;
212041b1c5dSMichal Kubecek 	u32			flags;
213041b1c5dSMichal Kubecek };
2142b4a8990SMichal Kubecek 
2152b4a8990SMichal Kubecek #endif /* _NET_ETHTOOL_NETLINK_H */
216