tunnels.c (0ea460474d70d809eac0640c1cf408ec54e23966) | tunnels.c (966e50597666d530b69de2abb9c83ff0a9bd3ee6) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2 3#include <linux/ethtool_netlink.h> 4#include <net/udp_tunnel.h> | 1// SPDX-License-Identifier: GPL-2.0-only 2 3#include <linux/ethtool_netlink.h> 4#include <net/udp_tunnel.h> |
5#include <net/vxlan.h> |
|
5 6#include "bitset.h" 7#include "common.h" 8#include "netlink.h" 9 10static const struct nla_policy 11ethtool_tunnel_info_policy[ETHTOOL_A_TUNNEL_INFO_MAX + 1] = { 12 [ETHTOOL_A_TUNNEL_INFO_UNSPEC] = { .type = NLA_REJECT }, 13 [ETHTOOL_A_TUNNEL_INFO_HEADER] = { .type = NLA_NESTED }, 14}; 15 16static_assert(ETHTOOL_UDP_TUNNEL_TYPE_VXLAN == ilog2(UDP_TUNNEL_TYPE_VXLAN)); 17static_assert(ETHTOOL_UDP_TUNNEL_TYPE_GENEVE == ilog2(UDP_TUNNEL_TYPE_GENEVE)); 18static_assert(ETHTOOL_UDP_TUNNEL_TYPE_VXLAN_GPE == 19 ilog2(UDP_TUNNEL_TYPE_VXLAN_GPE)); 20 | 6 7#include "bitset.h" 8#include "common.h" 9#include "netlink.h" 10 11static const struct nla_policy 12ethtool_tunnel_info_policy[ETHTOOL_A_TUNNEL_INFO_MAX + 1] = { 13 [ETHTOOL_A_TUNNEL_INFO_UNSPEC] = { .type = NLA_REJECT }, 14 [ETHTOOL_A_TUNNEL_INFO_HEADER] = { .type = NLA_NESTED }, 15}; 16 17static_assert(ETHTOOL_UDP_TUNNEL_TYPE_VXLAN == ilog2(UDP_TUNNEL_TYPE_VXLAN)); 18static_assert(ETHTOOL_UDP_TUNNEL_TYPE_GENEVE == ilog2(UDP_TUNNEL_TYPE_GENEVE)); 19static_assert(ETHTOOL_UDP_TUNNEL_TYPE_VXLAN_GPE == 20 ilog2(UDP_TUNNEL_TYPE_VXLAN_GPE)); 21 |
22static ssize_t ethnl_udp_table_reply_size(unsigned int types, bool compact) 23{ 24 ssize_t size; 25 26 size = ethnl_bitset32_size(&types, NULL, __ETHTOOL_UDP_TUNNEL_TYPE_CNT, 27 udp_tunnel_type_names, compact); 28 if (size < 0) 29 return size; 30 31 return size + 32 nla_total_size(0) + /* _UDP_TABLE */ 33 nla_total_size(sizeof(u32)); /* _UDP_TABLE_SIZE */ 34} 35 |
|
21static ssize_t 22ethnl_tunnel_info_reply_size(const struct ethnl_req_info *req_base, 23 struct netlink_ext_ack *extack) 24{ 25 bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS; 26 const struct udp_tunnel_nic_info *info; 27 unsigned int i; | 36static ssize_t 37ethnl_tunnel_info_reply_size(const struct ethnl_req_info *req_base, 38 struct netlink_ext_ack *extack) 39{ 40 bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS; 41 const struct udp_tunnel_nic_info *info; 42 unsigned int i; |
43 ssize_t ret; |
|
28 size_t size; | 44 size_t size; |
29 int ret; | |
30 31 info = req_base->dev->udp_tunnel_nic_info; 32 if (!info) { 33 NL_SET_ERR_MSG(extack, 34 "device does not report tunnel offload info"); 35 return -EOPNOTSUPP; 36 } 37 38 size = nla_total_size(0); /* _INFO_UDP_PORTS */ 39 40 for (i = 0; i < UDP_TUNNEL_NIC_MAX_TABLES; i++) { 41 if (!info->tables[i].n_entries) | 45 46 info = req_base->dev->udp_tunnel_nic_info; 47 if (!info) { 48 NL_SET_ERR_MSG(extack, 49 "device does not report tunnel offload info"); 50 return -EOPNOTSUPP; 51 } 52 53 size = nla_total_size(0); /* _INFO_UDP_PORTS */ 54 55 for (i = 0; i < UDP_TUNNEL_NIC_MAX_TABLES; i++) { 56 if (!info->tables[i].n_entries) |
42 return size; | 57 break; |
43 | 58 |
44 size += nla_total_size(0); /* _UDP_TABLE */ 45 size += nla_total_size(sizeof(u32)); /* _UDP_TABLE_SIZE */ 46 ret = ethnl_bitset32_size(&info->tables[i].tunnel_types, NULL, 47 __ETHTOOL_UDP_TUNNEL_TYPE_CNT, 48 udp_tunnel_type_names, compact); | 59 ret = ethnl_udp_table_reply_size(info->tables[i].tunnel_types, 60 compact); |
49 if (ret < 0) 50 return ret; 51 size += ret; 52 53 size += udp_tunnel_nic_dump_size(req_base->dev, i); 54 } 55 | 61 if (ret < 0) 62 return ret; 63 size += ret; 64 65 size += udp_tunnel_nic_dump_size(req_base->dev, i); 66 } 67 |
68 if (info->flags & UDP_TUNNEL_NIC_INFO_STATIC_IANA_VXLAN) { 69 ret = ethnl_udp_table_reply_size(0, compact); 70 if (ret < 0) 71 return ret; 72 size += ret; 73 74 size += nla_total_size(0) + /* _TABLE_ENTRY */ 75 nla_total_size(sizeof(__be16)) + /* _ENTRY_PORT */ 76 nla_total_size(sizeof(u32)); /* _ENTRY_TYPE */ 77 } 78 |
|
56 return size; 57} 58 59static int 60ethnl_tunnel_info_fill_reply(const struct ethnl_req_info *req_base, 61 struct sk_buff *skb) 62{ 63 bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS; 64 const struct udp_tunnel_nic_info *info; | 79 return size; 80} 81 82static int 83ethnl_tunnel_info_fill_reply(const struct ethnl_req_info *req_base, 84 struct sk_buff *skb) 85{ 86 bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS; 87 const struct udp_tunnel_nic_info *info; |
65 struct nlattr *ports, *table; | 88 struct nlattr *ports, *table, *entry; |
66 unsigned int i; 67 68 info = req_base->dev->udp_tunnel_nic_info; 69 if (!info) 70 return -EOPNOTSUPP; 71 72 ports = nla_nest_start(skb, ETHTOOL_A_TUNNEL_INFO_UDP_PORTS); 73 if (!ports) --- 18 unchanged lines hidden (view full) --- 92 goto err_cancel_table; 93 94 if (udp_tunnel_nic_dump_write(req_base->dev, i, skb)) 95 goto err_cancel_table; 96 97 nla_nest_end(skb, table); 98 } 99 | 89 unsigned int i; 90 91 info = req_base->dev->udp_tunnel_nic_info; 92 if (!info) 93 return -EOPNOTSUPP; 94 95 ports = nla_nest_start(skb, ETHTOOL_A_TUNNEL_INFO_UDP_PORTS); 96 if (!ports) --- 18 unchanged lines hidden (view full) --- 115 goto err_cancel_table; 116 117 if (udp_tunnel_nic_dump_write(req_base->dev, i, skb)) 118 goto err_cancel_table; 119 120 nla_nest_end(skb, table); 121 } 122 |
123 if (info->flags & UDP_TUNNEL_NIC_INFO_STATIC_IANA_VXLAN) { 124 u32 zero = 0; 125 126 table = nla_nest_start(skb, ETHTOOL_A_TUNNEL_UDP_TABLE); 127 if (!table) 128 goto err_cancel_ports; 129 130 if (nla_put_u32(skb, ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE, 1)) 131 goto err_cancel_table; 132 133 if (ethnl_put_bitset32(skb, ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES, 134 &zero, NULL, 135 __ETHTOOL_UDP_TUNNEL_TYPE_CNT, 136 udp_tunnel_type_names, compact)) 137 goto err_cancel_table; 138 139 entry = nla_nest_start(skb, ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY); 140 141 if (nla_put_be16(skb, ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT, 142 htons(IANA_VXLAN_UDP_PORT)) || 143 nla_put_u32(skb, ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE, 144 ilog2(UDP_TUNNEL_TYPE_VXLAN))) 145 goto err_cancel_entry; 146 147 nla_nest_end(skb, entry); 148 nla_nest_end(skb, table); 149 } 150 |
|
100 nla_nest_end(skb, ports); 101 102 return 0; 103 | 151 nla_nest_end(skb, ports); 152 153 return 0; 154 |
155err_cancel_entry: 156 nla_nest_cancel(skb, entry); |
|
104err_cancel_table: 105 nla_nest_cancel(skb, table); 106err_cancel_ports: 107 nla_nest_cancel(skb, ports); 108 return -EMSGSIZE; 109} 110 111static int --- 148 unchanged lines hidden --- | 157err_cancel_table: 158 nla_nest_cancel(skb, table); 159err_cancel_ports: 160 nla_nest_cancel(skb, ports); 161 return -EMSGSIZE; 162} 163 164static int --- 148 unchanged lines hidden --- |