.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2016, Amir Vadai <amir@vadai.me> |
---|
3 | 4 | * Copyright (c) 2016, Mellanox Technologies. All rights reserved. |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify |
---|
6 | | - * it under the terms of the GNU General Public License as published by |
---|
7 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
8 | | - * (at your option) any later version. |
---|
9 | 5 | */ |
---|
10 | 6 | |
---|
11 | 7 | #include <linux/module.h> |
---|
.. | .. |
---|
14 | 10 | #include <linux/skbuff.h> |
---|
15 | 11 | #include <linux/rtnetlink.h> |
---|
16 | 12 | #include <net/geneve.h> |
---|
| 13 | +#include <net/vxlan.h> |
---|
| 14 | +#include <net/erspan.h> |
---|
17 | 15 | #include <net/netlink.h> |
---|
18 | 16 | #include <net/pkt_sched.h> |
---|
19 | 17 | #include <net/dst.h> |
---|
| 18 | +#include <net/pkt_cls.h> |
---|
20 | 19 | |
---|
21 | 20 | #include <linux/tc_act/tc_tunnel_key.h> |
---|
22 | 21 | #include <net/tc_act/tc_tunnel_key.h> |
---|
.. | .. |
---|
34 | 33 | params = rcu_dereference_bh(t->params); |
---|
35 | 34 | |
---|
36 | 35 | tcf_lastuse_update(&t->tcf_tm); |
---|
37 | | - bstats_cpu_update(this_cpu_ptr(t->common.cpu_bstats), skb); |
---|
| 36 | + tcf_action_update_bstats(&t->common, skb); |
---|
38 | 37 | action = READ_ONCE(t->tcf_action); |
---|
39 | 38 | |
---|
40 | 39 | switch (params->tcft_action) { |
---|
.. | .. |
---|
56 | 55 | |
---|
57 | 56 | static const struct nla_policy |
---|
58 | 57 | enc_opts_policy[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1] = { |
---|
| 58 | + [TCA_TUNNEL_KEY_ENC_OPTS_UNSPEC] = { |
---|
| 59 | + .strict_start_type = TCA_TUNNEL_KEY_ENC_OPTS_VXLAN }, |
---|
59 | 60 | [TCA_TUNNEL_KEY_ENC_OPTS_GENEVE] = { .type = NLA_NESTED }, |
---|
| 61 | + [TCA_TUNNEL_KEY_ENC_OPTS_VXLAN] = { .type = NLA_NESTED }, |
---|
| 62 | + [TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN] = { .type = NLA_NESTED }, |
---|
60 | 63 | }; |
---|
61 | 64 | |
---|
62 | 65 | static const struct nla_policy |
---|
.. | .. |
---|
67 | 70 | .len = 128 }, |
---|
68 | 71 | }; |
---|
69 | 72 | |
---|
| 73 | +static const struct nla_policy |
---|
| 74 | +vxlan_opt_policy[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX + 1] = { |
---|
| 75 | + [TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP] = { .type = NLA_U32 }, |
---|
| 76 | +}; |
---|
| 77 | + |
---|
| 78 | +static const struct nla_policy |
---|
| 79 | +erspan_opt_policy[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX + 1] = { |
---|
| 80 | + [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER] = { .type = NLA_U8 }, |
---|
| 81 | + [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX] = { .type = NLA_U32 }, |
---|
| 82 | + [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR] = { .type = NLA_U8 }, |
---|
| 83 | + [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID] = { .type = NLA_U8 }, |
---|
| 84 | +}; |
---|
| 85 | + |
---|
70 | 86 | static int |
---|
71 | 87 | tunnel_key_copy_geneve_opt(const struct nlattr *nla, void *dst, int dst_len, |
---|
72 | 88 | struct netlink_ext_ack *extack) |
---|
.. | .. |
---|
75 | 91 | int err, data_len, opt_len; |
---|
76 | 92 | u8 *data; |
---|
77 | 93 | |
---|
78 | | - err = nla_parse_nested(tb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX, |
---|
79 | | - nla, geneve_opt_policy, extack); |
---|
| 94 | + err = nla_parse_nested_deprecated(tb, |
---|
| 95 | + TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX, |
---|
| 96 | + nla, geneve_opt_policy, extack); |
---|
80 | 97 | if (err < 0) |
---|
81 | 98 | return err; |
---|
82 | 99 | |
---|
.. | .. |
---|
118 | 135 | return opt_len; |
---|
119 | 136 | } |
---|
120 | 137 | |
---|
| 138 | +static int |
---|
| 139 | +tunnel_key_copy_vxlan_opt(const struct nlattr *nla, void *dst, int dst_len, |
---|
| 140 | + struct netlink_ext_ack *extack) |
---|
| 141 | +{ |
---|
| 142 | + struct nlattr *tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX + 1]; |
---|
| 143 | + int err; |
---|
| 144 | + |
---|
| 145 | + err = nla_parse_nested(tb, TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX, nla, |
---|
| 146 | + vxlan_opt_policy, extack); |
---|
| 147 | + if (err < 0) |
---|
| 148 | + return err; |
---|
| 149 | + |
---|
| 150 | + if (!tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP]) { |
---|
| 151 | + NL_SET_ERR_MSG(extack, "Missing tunnel key vxlan option gbp"); |
---|
| 152 | + return -EINVAL; |
---|
| 153 | + } |
---|
| 154 | + |
---|
| 155 | + if (dst) { |
---|
| 156 | + struct vxlan_metadata *md = dst; |
---|
| 157 | + |
---|
| 158 | + md->gbp = nla_get_u32(tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP]); |
---|
| 159 | + md->gbp &= VXLAN_GBP_MASK; |
---|
| 160 | + } |
---|
| 161 | + |
---|
| 162 | + return sizeof(struct vxlan_metadata); |
---|
| 163 | +} |
---|
| 164 | + |
---|
| 165 | +static int |
---|
| 166 | +tunnel_key_copy_erspan_opt(const struct nlattr *nla, void *dst, int dst_len, |
---|
| 167 | + struct netlink_ext_ack *extack) |
---|
| 168 | +{ |
---|
| 169 | + struct nlattr *tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX + 1]; |
---|
| 170 | + int err; |
---|
| 171 | + u8 ver; |
---|
| 172 | + |
---|
| 173 | + err = nla_parse_nested(tb, TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX, nla, |
---|
| 174 | + erspan_opt_policy, extack); |
---|
| 175 | + if (err < 0) |
---|
| 176 | + return err; |
---|
| 177 | + |
---|
| 178 | + if (!tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER]) { |
---|
| 179 | + NL_SET_ERR_MSG(extack, "Missing tunnel key erspan option ver"); |
---|
| 180 | + return -EINVAL; |
---|
| 181 | + } |
---|
| 182 | + |
---|
| 183 | + ver = nla_get_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER]); |
---|
| 184 | + if (ver == 1) { |
---|
| 185 | + if (!tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX]) { |
---|
| 186 | + NL_SET_ERR_MSG(extack, "Missing tunnel key erspan option index"); |
---|
| 187 | + return -EINVAL; |
---|
| 188 | + } |
---|
| 189 | + } else if (ver == 2) { |
---|
| 190 | + if (!tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR] || |
---|
| 191 | + !tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID]) { |
---|
| 192 | + NL_SET_ERR_MSG(extack, "Missing tunnel key erspan option dir or hwid"); |
---|
| 193 | + return -EINVAL; |
---|
| 194 | + } |
---|
| 195 | + } else { |
---|
| 196 | + NL_SET_ERR_MSG(extack, "Tunnel key erspan option ver is incorrect"); |
---|
| 197 | + return -EINVAL; |
---|
| 198 | + } |
---|
| 199 | + |
---|
| 200 | + if (dst) { |
---|
| 201 | + struct erspan_metadata *md = dst; |
---|
| 202 | + |
---|
| 203 | + md->version = ver; |
---|
| 204 | + if (ver == 1) { |
---|
| 205 | + nla = tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX]; |
---|
| 206 | + md->u.index = nla_get_be32(nla); |
---|
| 207 | + } else { |
---|
| 208 | + nla = tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR]; |
---|
| 209 | + md->u.md2.dir = nla_get_u8(nla); |
---|
| 210 | + nla = tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID]; |
---|
| 211 | + set_hwid(&md->u.md2, nla_get_u8(nla)); |
---|
| 212 | + } |
---|
| 213 | + } |
---|
| 214 | + |
---|
| 215 | + return sizeof(struct erspan_metadata); |
---|
| 216 | +} |
---|
| 217 | + |
---|
121 | 218 | static int tunnel_key_copy_opts(const struct nlattr *nla, u8 *dst, |
---|
122 | 219 | int dst_len, struct netlink_ext_ack *extack) |
---|
123 | 220 | { |
---|
124 | | - int err, rem, opt_len, len = nla_len(nla), opts_len = 0; |
---|
| 221 | + int err, rem, opt_len, len = nla_len(nla), opts_len = 0, type = 0; |
---|
125 | 222 | const struct nlattr *attr, *head = nla_data(nla); |
---|
126 | 223 | |
---|
127 | | - err = nla_validate(head, len, TCA_TUNNEL_KEY_ENC_OPTS_MAX, |
---|
128 | | - enc_opts_policy, extack); |
---|
| 224 | + err = nla_validate_deprecated(head, len, TCA_TUNNEL_KEY_ENC_OPTS_MAX, |
---|
| 225 | + enc_opts_policy, extack); |
---|
129 | 226 | if (err) |
---|
130 | 227 | return err; |
---|
131 | 228 | |
---|
132 | 229 | nla_for_each_attr(attr, head, len, rem) { |
---|
133 | 230 | switch (nla_type(attr)) { |
---|
134 | 231 | case TCA_TUNNEL_KEY_ENC_OPTS_GENEVE: |
---|
| 232 | + if (type && type != TUNNEL_GENEVE_OPT) { |
---|
| 233 | + NL_SET_ERR_MSG(extack, "Duplicate type for geneve options"); |
---|
| 234 | + return -EINVAL; |
---|
| 235 | + } |
---|
135 | 236 | opt_len = tunnel_key_copy_geneve_opt(attr, dst, |
---|
136 | 237 | dst_len, extack); |
---|
137 | 238 | if (opt_len < 0) |
---|
.. | .. |
---|
145 | 246 | dst_len -= opt_len; |
---|
146 | 247 | dst += opt_len; |
---|
147 | 248 | } |
---|
| 249 | + type = TUNNEL_GENEVE_OPT; |
---|
| 250 | + break; |
---|
| 251 | + case TCA_TUNNEL_KEY_ENC_OPTS_VXLAN: |
---|
| 252 | + if (type) { |
---|
| 253 | + NL_SET_ERR_MSG(extack, "Duplicate type for vxlan options"); |
---|
| 254 | + return -EINVAL; |
---|
| 255 | + } |
---|
| 256 | + opt_len = tunnel_key_copy_vxlan_opt(attr, dst, |
---|
| 257 | + dst_len, extack); |
---|
| 258 | + if (opt_len < 0) |
---|
| 259 | + return opt_len; |
---|
| 260 | + opts_len += opt_len; |
---|
| 261 | + type = TUNNEL_VXLAN_OPT; |
---|
| 262 | + break; |
---|
| 263 | + case TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN: |
---|
| 264 | + if (type) { |
---|
| 265 | + NL_SET_ERR_MSG(extack, "Duplicate type for erspan options"); |
---|
| 266 | + return -EINVAL; |
---|
| 267 | + } |
---|
| 268 | + opt_len = tunnel_key_copy_erspan_opt(attr, dst, |
---|
| 269 | + dst_len, extack); |
---|
| 270 | + if (opt_len < 0) |
---|
| 271 | + return opt_len; |
---|
| 272 | + opts_len += opt_len; |
---|
| 273 | + type = TUNNEL_ERSPAN_OPT; |
---|
148 | 274 | break; |
---|
149 | 275 | } |
---|
150 | 276 | } |
---|
.. | .. |
---|
181 | 307 | #else |
---|
182 | 308 | return -EAFNOSUPPORT; |
---|
183 | 309 | #endif |
---|
| 310 | + case TCA_TUNNEL_KEY_ENC_OPTS_VXLAN: |
---|
| 311 | +#if IS_ENABLED(CONFIG_INET) |
---|
| 312 | + info->key.tun_flags |= TUNNEL_VXLAN_OPT; |
---|
| 313 | + return tunnel_key_copy_opts(nla, ip_tunnel_info_opts(info), |
---|
| 314 | + opts_len, extack); |
---|
| 315 | +#else |
---|
| 316 | + return -EAFNOSUPPORT; |
---|
| 317 | +#endif |
---|
| 318 | + case TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN: |
---|
| 319 | +#if IS_ENABLED(CONFIG_INET) |
---|
| 320 | + info->key.tun_flags |= TUNNEL_ERSPAN_OPT; |
---|
| 321 | + return tunnel_key_copy_opts(nla, ip_tunnel_info_opts(info), |
---|
| 322 | + opts_len, extack); |
---|
| 323 | +#else |
---|
| 324 | + return -EAFNOSUPPORT; |
---|
| 325 | +#endif |
---|
184 | 326 | default: |
---|
185 | 327 | NL_SET_ERR_MSG(extack, "Cannot set tunnel options for unknown tunnel type"); |
---|
186 | 328 | return -EINVAL; |
---|
.. | .. |
---|
207 | 349 | return; |
---|
208 | 350 | if (p->tcft_action == TCA_TUNNEL_KEY_ACT_SET) |
---|
209 | 351 | dst_release(&p->tcft_enc_metadata->dst); |
---|
| 352 | + |
---|
210 | 353 | kfree_rcu(p, rcu); |
---|
211 | 354 | } |
---|
212 | 355 | |
---|
213 | 356 | static int tunnel_key_init(struct net *net, struct nlattr *nla, |
---|
214 | 357 | struct nlattr *est, struct tc_action **a, |
---|
215 | 358 | int ovr, int bind, bool rtnl_held, |
---|
| 359 | + struct tcf_proto *tp, u32 act_flags, |
---|
216 | 360 | struct netlink_ext_ack *extack) |
---|
217 | 361 | { |
---|
218 | 362 | struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); |
---|
219 | 363 | struct nlattr *tb[TCA_TUNNEL_KEY_MAX + 1]; |
---|
220 | 364 | struct tcf_tunnel_key_params *params_new; |
---|
221 | 365 | struct metadata_dst *metadata = NULL; |
---|
| 366 | + struct tcf_chain *goto_ch = NULL; |
---|
222 | 367 | struct tc_tunnel_key *parm; |
---|
223 | 368 | struct tcf_tunnel_key *t; |
---|
224 | 369 | bool exists = false; |
---|
225 | 370 | __be16 dst_port = 0; |
---|
| 371 | + __be64 key_id = 0; |
---|
226 | 372 | int opts_len = 0; |
---|
227 | | - __be64 key_id; |
---|
228 | | - __be16 flags; |
---|
| 373 | + __be16 flags = 0; |
---|
229 | 374 | u8 tos, ttl; |
---|
230 | 375 | int ret = 0; |
---|
231 | 376 | u32 index; |
---|
.. | .. |
---|
236 | 381 | return -EINVAL; |
---|
237 | 382 | } |
---|
238 | 383 | |
---|
239 | | - err = nla_parse_nested(tb, TCA_TUNNEL_KEY_MAX, nla, tunnel_key_policy, |
---|
240 | | - extack); |
---|
| 384 | + err = nla_parse_nested_deprecated(tb, TCA_TUNNEL_KEY_MAX, nla, |
---|
| 385 | + tunnel_key_policy, extack); |
---|
241 | 386 | if (err < 0) { |
---|
242 | 387 | NL_SET_ERR_MSG(extack, "Failed to parse nested tunnel key attributes"); |
---|
243 | 388 | return err; |
---|
.. | .. |
---|
261 | 406 | case TCA_TUNNEL_KEY_ACT_RELEASE: |
---|
262 | 407 | break; |
---|
263 | 408 | case TCA_TUNNEL_KEY_ACT_SET: |
---|
264 | | - if (!tb[TCA_TUNNEL_KEY_ENC_KEY_ID]) { |
---|
265 | | - NL_SET_ERR_MSG(extack, "Missing tunnel key id"); |
---|
266 | | - ret = -EINVAL; |
---|
267 | | - goto err_out; |
---|
| 409 | + if (tb[TCA_TUNNEL_KEY_ENC_KEY_ID]) { |
---|
| 410 | + __be32 key32; |
---|
| 411 | + |
---|
| 412 | + key32 = nla_get_be32(tb[TCA_TUNNEL_KEY_ENC_KEY_ID]); |
---|
| 413 | + key_id = key32_to_tunnel_id(key32); |
---|
| 414 | + flags = TUNNEL_KEY; |
---|
268 | 415 | } |
---|
269 | 416 | |
---|
270 | | - key_id = key32_to_tunnel_id(nla_get_be32(tb[TCA_TUNNEL_KEY_ENC_KEY_ID])); |
---|
271 | | - |
---|
272 | | - flags = TUNNEL_KEY | TUNNEL_CSUM; |
---|
| 417 | + flags |= TUNNEL_CSUM; |
---|
273 | 418 | if (tb[TCA_TUNNEL_KEY_NO_CSUM] && |
---|
274 | 419 | nla_get_u8(tb[TCA_TUNNEL_KEY_NO_CSUM])) |
---|
275 | 420 | flags &= ~TUNNEL_CSUM; |
---|
.. | .. |
---|
327 | 472 | goto err_out; |
---|
328 | 473 | } |
---|
329 | 474 | |
---|
| 475 | +#ifdef CONFIG_DST_CACHE |
---|
| 476 | + ret = dst_cache_init(&metadata->u.tun_info.dst_cache, GFP_KERNEL); |
---|
| 477 | + if (ret) |
---|
| 478 | + goto release_tun_meta; |
---|
| 479 | +#endif |
---|
| 480 | + |
---|
330 | 481 | if (opts_len) { |
---|
331 | 482 | ret = tunnel_key_opts_set(tb[TCA_TUNNEL_KEY_ENC_OPTS], |
---|
332 | 483 | &metadata->u.tun_info, |
---|
.. | .. |
---|
344 | 495 | } |
---|
345 | 496 | |
---|
346 | 497 | if (!exists) { |
---|
347 | | - ret = tcf_idr_create(tn, index, est, a, |
---|
348 | | - &act_tunnel_key_ops, bind, true); |
---|
| 498 | + ret = tcf_idr_create_from_flags(tn, index, est, a, |
---|
| 499 | + &act_tunnel_key_ops, bind, |
---|
| 500 | + act_flags); |
---|
349 | 501 | if (ret) { |
---|
350 | 502 | NL_SET_ERR_MSG(extack, "Cannot create TC IDR"); |
---|
351 | 503 | goto release_tun_meta; |
---|
.. | .. |
---|
358 | 510 | goto release_tun_meta; |
---|
359 | 511 | } |
---|
360 | 512 | |
---|
| 513 | + err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); |
---|
| 514 | + if (err < 0) { |
---|
| 515 | + ret = err; |
---|
| 516 | + exists = true; |
---|
| 517 | + goto release_tun_meta; |
---|
| 518 | + } |
---|
361 | 519 | t = to_tunnel_key(*a); |
---|
362 | 520 | |
---|
363 | 521 | params_new = kzalloc(sizeof(*params_new), GFP_KERNEL); |
---|
.. | .. |
---|
365 | 523 | NL_SET_ERR_MSG(extack, "Cannot allocate tunnel key parameters"); |
---|
366 | 524 | ret = -ENOMEM; |
---|
367 | 525 | exists = true; |
---|
368 | | - goto release_tun_meta; |
---|
| 526 | + goto put_chain; |
---|
369 | 527 | } |
---|
370 | 528 | params_new->tcft_action = parm->t_action; |
---|
371 | 529 | params_new->tcft_enc_metadata = metadata; |
---|
372 | 530 | |
---|
373 | 531 | spin_lock_bh(&t->tcf_lock); |
---|
374 | | - t->tcf_action = parm->action; |
---|
375 | | - rcu_swap_protected(t->params, params_new, |
---|
376 | | - lockdep_is_held(&t->tcf_lock)); |
---|
| 532 | + goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
---|
| 533 | + params_new = rcu_replace_pointer(t->params, params_new, |
---|
| 534 | + lockdep_is_held(&t->tcf_lock)); |
---|
377 | 535 | spin_unlock_bh(&t->tcf_lock); |
---|
378 | 536 | tunnel_key_release_params(params_new); |
---|
379 | | - |
---|
380 | | - if (ret == ACT_P_CREATED) |
---|
381 | | - tcf_idr_insert(tn, *a); |
---|
| 537 | + if (goto_ch) |
---|
| 538 | + tcf_chain_put_by_act(goto_ch); |
---|
382 | 539 | |
---|
383 | 540 | return ret; |
---|
| 541 | + |
---|
| 542 | +put_chain: |
---|
| 543 | + if (goto_ch) |
---|
| 544 | + tcf_chain_put_by_act(goto_ch); |
---|
384 | 545 | |
---|
385 | 546 | release_tun_meta: |
---|
386 | 547 | if (metadata) |
---|
.. | .. |
---|
410 | 571 | u8 *src = (u8 *)(info + 1); |
---|
411 | 572 | struct nlattr *start; |
---|
412 | 573 | |
---|
413 | | - start = nla_nest_start(skb, TCA_TUNNEL_KEY_ENC_OPTS_GENEVE); |
---|
| 574 | + start = nla_nest_start_noflag(skb, TCA_TUNNEL_KEY_ENC_OPTS_GENEVE); |
---|
414 | 575 | if (!start) |
---|
415 | 576 | return -EMSGSIZE; |
---|
416 | 577 | |
---|
.. | .. |
---|
435 | 596 | return 0; |
---|
436 | 597 | } |
---|
437 | 598 | |
---|
| 599 | +static int tunnel_key_vxlan_opts_dump(struct sk_buff *skb, |
---|
| 600 | + const struct ip_tunnel_info *info) |
---|
| 601 | +{ |
---|
| 602 | + struct vxlan_metadata *md = (struct vxlan_metadata *)(info + 1); |
---|
| 603 | + struct nlattr *start; |
---|
| 604 | + |
---|
| 605 | + start = nla_nest_start_noflag(skb, TCA_TUNNEL_KEY_ENC_OPTS_VXLAN); |
---|
| 606 | + if (!start) |
---|
| 607 | + return -EMSGSIZE; |
---|
| 608 | + |
---|
| 609 | + if (nla_put_u32(skb, TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP, md->gbp)) { |
---|
| 610 | + nla_nest_cancel(skb, start); |
---|
| 611 | + return -EMSGSIZE; |
---|
| 612 | + } |
---|
| 613 | + |
---|
| 614 | + nla_nest_end(skb, start); |
---|
| 615 | + return 0; |
---|
| 616 | +} |
---|
| 617 | + |
---|
| 618 | +static int tunnel_key_erspan_opts_dump(struct sk_buff *skb, |
---|
| 619 | + const struct ip_tunnel_info *info) |
---|
| 620 | +{ |
---|
| 621 | + struct erspan_metadata *md = (struct erspan_metadata *)(info + 1); |
---|
| 622 | + struct nlattr *start; |
---|
| 623 | + |
---|
| 624 | + start = nla_nest_start_noflag(skb, TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN); |
---|
| 625 | + if (!start) |
---|
| 626 | + return -EMSGSIZE; |
---|
| 627 | + |
---|
| 628 | + if (nla_put_u8(skb, TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER, md->version)) |
---|
| 629 | + goto err; |
---|
| 630 | + |
---|
| 631 | + if (md->version == 1 && |
---|
| 632 | + nla_put_be32(skb, TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX, md->u.index)) |
---|
| 633 | + goto err; |
---|
| 634 | + |
---|
| 635 | + if (md->version == 2 && |
---|
| 636 | + (nla_put_u8(skb, TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR, |
---|
| 637 | + md->u.md2.dir) || |
---|
| 638 | + nla_put_u8(skb, TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID, |
---|
| 639 | + get_hwid(&md->u.md2)))) |
---|
| 640 | + goto err; |
---|
| 641 | + |
---|
| 642 | + nla_nest_end(skb, start); |
---|
| 643 | + return 0; |
---|
| 644 | +err: |
---|
| 645 | + nla_nest_cancel(skb, start); |
---|
| 646 | + return -EMSGSIZE; |
---|
| 647 | +} |
---|
| 648 | + |
---|
438 | 649 | static int tunnel_key_opts_dump(struct sk_buff *skb, |
---|
439 | 650 | const struct ip_tunnel_info *info) |
---|
440 | 651 | { |
---|
.. | .. |
---|
444 | 655 | if (!info->options_len) |
---|
445 | 656 | return 0; |
---|
446 | 657 | |
---|
447 | | - start = nla_nest_start(skb, TCA_TUNNEL_KEY_ENC_OPTS); |
---|
| 658 | + start = nla_nest_start_noflag(skb, TCA_TUNNEL_KEY_ENC_OPTS); |
---|
448 | 659 | if (!start) |
---|
449 | 660 | return -EMSGSIZE; |
---|
450 | 661 | |
---|
451 | 662 | if (info->key.tun_flags & TUNNEL_GENEVE_OPT) { |
---|
452 | 663 | err = tunnel_key_geneve_opts_dump(skb, info); |
---|
| 664 | + if (err) |
---|
| 665 | + goto err_out; |
---|
| 666 | + } else if (info->key.tun_flags & TUNNEL_VXLAN_OPT) { |
---|
| 667 | + err = tunnel_key_vxlan_opts_dump(skb, info); |
---|
| 668 | + if (err) |
---|
| 669 | + goto err_out; |
---|
| 670 | + } else if (info->key.tun_flags & TUNNEL_ERSPAN_OPT) { |
---|
| 671 | + err = tunnel_key_erspan_opts_dump(skb, info); |
---|
453 | 672 | if (err) |
---|
454 | 673 | goto err_out; |
---|
455 | 674 | } else { |
---|
.. | .. |
---|
518 | 737 | struct ip_tunnel_key *key = &info->key; |
---|
519 | 738 | __be32 key_id = tunnel_id_to_key32(key->tun_id); |
---|
520 | 739 | |
---|
521 | | - if (nla_put_be32(skb, TCA_TUNNEL_KEY_ENC_KEY_ID, key_id) || |
---|
| 740 | + if (((key->tun_flags & TUNNEL_KEY) && |
---|
| 741 | + nla_put_be32(skb, TCA_TUNNEL_KEY_ENC_KEY_ID, key_id)) || |
---|
522 | 742 | tunnel_key_dump_addresses(skb, |
---|
523 | 743 | ¶ms->tcft_enc_metadata->u.tun_info) || |
---|
524 | | - nla_put_be16(skb, TCA_TUNNEL_KEY_ENC_DST_PORT, key->tp_dst) || |
---|
| 744 | + (key->tp_dst && |
---|
| 745 | + nla_put_be16(skb, TCA_TUNNEL_KEY_ENC_DST_PORT, |
---|
| 746 | + key->tp_dst)) || |
---|
525 | 747 | nla_put_u8(skb, TCA_TUNNEL_KEY_NO_CSUM, |
---|
526 | 748 | !(key->tun_flags & TUNNEL_CSUM)) || |
---|
527 | 749 | tunnel_key_opts_dump(skb, info)) |
---|
.. | .. |
---|
558 | 780 | return tcf_generic_walker(tn, skb, cb, type, ops, extack); |
---|
559 | 781 | } |
---|
560 | 782 | |
---|
561 | | -static int tunnel_key_search(struct net *net, struct tc_action **a, u32 index, |
---|
562 | | - struct netlink_ext_ack *extack) |
---|
| 783 | +static int tunnel_key_search(struct net *net, struct tc_action **a, u32 index) |
---|
563 | 784 | { |
---|
564 | 785 | struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); |
---|
565 | 786 | |
---|
.. | .. |
---|
568 | 789 | |
---|
569 | 790 | static struct tc_action_ops act_tunnel_key_ops = { |
---|
570 | 791 | .kind = "tunnel_key", |
---|
571 | | - .type = TCA_ACT_TUNNEL_KEY, |
---|
| 792 | + .id = TCA_ID_TUNNEL_KEY, |
---|
572 | 793 | .owner = THIS_MODULE, |
---|
573 | 794 | .act = tunnel_key_act, |
---|
574 | 795 | .dump = tunnel_key_dump, |
---|