Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) #include <linux/ethtool_netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #include <net/udp_tunnel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <net/vxlan.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include "bitset.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include "netlink.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) const struct nla_policy ethnl_tunnel_info_get_policy[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 	[ETHTOOL_A_TUNNEL_INFO_HEADER]		=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 		NLA_POLICY_NESTED(ethnl_header_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) static_assert(ETHTOOL_UDP_TUNNEL_TYPE_VXLAN == ilog2(UDP_TUNNEL_TYPE_VXLAN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) static_assert(ETHTOOL_UDP_TUNNEL_TYPE_GENEVE == ilog2(UDP_TUNNEL_TYPE_GENEVE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) static_assert(ETHTOOL_UDP_TUNNEL_TYPE_VXLAN_GPE ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	      ilog2(UDP_TUNNEL_TYPE_VXLAN_GPE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) static ssize_t ethnl_udp_table_reply_size(unsigned int types, bool compact)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	ssize_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	size = ethnl_bitset32_size(&types, NULL, __ETHTOOL_UDP_TUNNEL_TYPE_CNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 				   udp_tunnel_type_names, compact);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	if (size < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 		return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	return size +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 		nla_total_size(0) + /* _UDP_TABLE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 		nla_total_size(sizeof(u32)); /* _UDP_TABLE_SIZE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) ethnl_tunnel_info_reply_size(const struct ethnl_req_info *req_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 			     struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	const struct udp_tunnel_nic_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	info = req_base->dev->udp_tunnel_nic_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	if (!info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		NL_SET_ERR_MSG(extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 			       "device does not report tunnel offload info");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	size =	nla_total_size(0); /* _INFO_UDP_PORTS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	for (i = 0; i < UDP_TUNNEL_NIC_MAX_TABLES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		if (!info->tables[i].n_entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		ret = ethnl_udp_table_reply_size(info->tables[i].tunnel_types,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 						 compact);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		size += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		size += udp_tunnel_nic_dump_size(req_base->dev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	if (info->flags & UDP_TUNNEL_NIC_INFO_STATIC_IANA_VXLAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		ret = ethnl_udp_table_reply_size(0, compact);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		size += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		size += nla_total_size(0) +		 /* _TABLE_ENTRY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 			nla_total_size(sizeof(__be16)) + /* _ENTRY_PORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 			nla_total_size(sizeof(u32));	 /* _ENTRY_TYPE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) ethnl_tunnel_info_fill_reply(const struct ethnl_req_info *req_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 			     struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	const struct udp_tunnel_nic_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	struct nlattr *ports, *table, *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	info = req_base->dev->udp_tunnel_nic_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	ports = nla_nest_start(skb, ETHTOOL_A_TUNNEL_INFO_UDP_PORTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	if (!ports)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	for (i = 0; i < UDP_TUNNEL_NIC_MAX_TABLES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		if (!info->tables[i].n_entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		table = nla_nest_start(skb, ETHTOOL_A_TUNNEL_UDP_TABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		if (!table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 			goto err_cancel_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		if (nla_put_u32(skb, ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 				info->tables[i].n_entries))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			goto err_cancel_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		if (ethnl_put_bitset32(skb, ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 				       &info->tables[i].tunnel_types, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 				       __ETHTOOL_UDP_TUNNEL_TYPE_CNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 				       udp_tunnel_type_names, compact))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 			goto err_cancel_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		if (udp_tunnel_nic_dump_write(req_base->dev, i, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			goto err_cancel_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		nla_nest_end(skb, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	if (info->flags & UDP_TUNNEL_NIC_INFO_STATIC_IANA_VXLAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		u32 zero = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		table = nla_nest_start(skb, ETHTOOL_A_TUNNEL_UDP_TABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		if (!table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 			goto err_cancel_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		if (nla_put_u32(skb, ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 			goto err_cancel_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		if (ethnl_put_bitset32(skb, ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 				       &zero, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 				       __ETHTOOL_UDP_TUNNEL_TYPE_CNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 				       udp_tunnel_type_names, compact))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 			goto err_cancel_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		entry = nla_nest_start(skb, ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		if (nla_put_be16(skb, ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 				 htons(IANA_VXLAN_UDP_PORT)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		    nla_put_u32(skb, ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 				ilog2(UDP_TUNNEL_TYPE_VXLAN)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			goto err_cancel_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		nla_nest_end(skb, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		nla_nest_end(skb, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	nla_nest_end(skb, ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) err_cancel_entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	nla_nest_cancel(skb, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) err_cancel_table:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	nla_nest_cancel(skb, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) err_cancel_ports:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	nla_nest_cancel(skb, ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) int ethnl_tunnel_info_doit(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	struct ethnl_req_info req_info = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	struct nlattr **tb = info->attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	struct sk_buff *rskb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	void *reply_payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	int reply_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	ret = ethnl_parse_header_dev_get(&req_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 					 tb[ETHTOOL_A_TUNNEL_INFO_HEADER],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 					 genl_info_net(info), info->extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 					 true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	ret = ethnl_tunnel_info_reply_size(&req_info, info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		goto err_unlock_rtnl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	reply_len = ret + ethnl_reply_header_size();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	rskb = ethnl_reply_init(reply_len, req_info.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 				ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 				ETHTOOL_A_TUNNEL_INFO_HEADER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 				info, &reply_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	if (!rskb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		goto err_unlock_rtnl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	ret = ethnl_tunnel_info_fill_reply(&req_info, rskb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		goto err_free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	dev_put(req_info.dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	genlmsg_end(rskb, reply_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	return genlmsg_reply(rskb, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) err_free_msg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	nlmsg_free(rskb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) err_unlock_rtnl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	dev_put(req_info.dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct ethnl_tunnel_info_dump_ctx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	struct ethnl_req_info	req_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	int			pos_hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	int			pos_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int ethnl_tunnel_info_start(struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	struct ethnl_tunnel_info_dump_ctx *ctx = (void *)cb->ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	struct nlattr **tb = info->attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	memset(ctx, 0, sizeof(*ctx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	ret = ethnl_parse_header_dev_get(&ctx->req_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 					 tb[ETHTOOL_A_TUNNEL_INFO_HEADER],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 					 sock_net(cb->skb->sk), cb->extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 					 false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	if (ctx->req_info.dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		dev_put(ctx->req_info.dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		ctx->req_info.dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	struct ethnl_tunnel_info_dump_ctx *ctx = (void *)cb->ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	struct net *net = sock_net(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	int s_idx = ctx->pos_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	int h, idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	void *ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	cb->seq = net->dev_base_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	for (h = ctx->pos_hash; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		struct hlist_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		head = &net->dev_index_head[h];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		hlist_for_each_entry(dev, head, index_hlist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 			if (idx < s_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 				goto cont;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			ehdr = ethnl_dump_put(skb, cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 					      ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 			if (!ehdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 				ret = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 			ret = ethnl_fill_reply_header(skb, dev, ETHTOOL_A_TUNNEL_INFO_HEADER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 			if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 				genlmsg_cancel(skb, ehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 			ctx->req_info.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 			ret = ethnl_tunnel_info_fill_reply(&ctx->req_info, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 			ctx->req_info.dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 			if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 				genlmsg_cancel(skb, ehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 				if (ret == -EOPNOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 					goto cont;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 			genlmsg_end(skb, ehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 			idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	ctx->pos_hash = h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	ctx->pos_idx = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	nl_dump_check_consistent(cb, nlmsg_hdr(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	if (ret == -EMSGSIZE && skb->len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }