Skip to content

Commit fca3f91

Browse files
lxindavem330
authored andcommitted
net: sched: add vxlan option support to act_tunnel_key
This patch is to allow setting vxlan options using the act_tunnel_key action. Different from geneve options, only one option can be set. And also, geneve options and vxlan options can't be set at the same time. gbp is the only param for vxlan options: # ip link add name vxlan0 type vxlan dstport 0 external # tc qdisc add dev eth0 ingress # tc filter add dev eth0 protocol ip parent ffff: \ flower indev eth0 \ ip_proto udp \ action tunnel_key \ set src_ip 10.0.99.192 \ dst_ip 10.0.99.193 \ dst_port 6081 \ id 11 \ vxlan_opts 01020304 \ action mirred egress redirect dev vxlan0 v1->v2: - add .strict_start_type for enc_opts_policy as Jakub noticed. - use Duplicate instead of Wrong in err msg for extack as Jakub suggested. Signed-off-by: Xin Long <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0617aa9 commit fca3f91

File tree

2 files changed

+97
-1
lines changed

2 files changed

+97
-1
lines changed

include/uapi/linux/tc_act/tc_tunnel_key.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ enum {
5050
* TCA_TUNNEL_KEY_ENC_OPTS_
5151
* attributes
5252
*/
53+
TCA_TUNNEL_KEY_ENC_OPTS_VXLAN, /* Nested
54+
* TCA_TUNNEL_KEY_ENC_OPTS_
55+
* attributes
56+
*/
5357
__TCA_TUNNEL_KEY_ENC_OPTS_MAX,
5458
};
5559

@@ -67,4 +71,13 @@ enum {
6771
#define TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX \
6872
(__TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX - 1)
6973

74+
enum {
75+
TCA_TUNNEL_KEY_ENC_OPT_VXLAN_UNSPEC,
76+
TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP, /* u32 */
77+
__TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX,
78+
};
79+
80+
#define TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX \
81+
(__TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX - 1)
82+
7083
#endif

net/sched/act_tunnel_key.c

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/skbuff.h>
1111
#include <linux/rtnetlink.h>
1212
#include <net/geneve.h>
13+
#include <net/vxlan.h>
1314
#include <net/netlink.h>
1415
#include <net/pkt_sched.h>
1516
#include <net/dst.h>
@@ -53,7 +54,10 @@ static int tunnel_key_act(struct sk_buff *skb, const struct tc_action *a,
5354

5455
static const struct nla_policy
5556
enc_opts_policy[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1] = {
57+
[TCA_TUNNEL_KEY_ENC_OPTS_UNSPEC] = {
58+
.strict_start_type = TCA_TUNNEL_KEY_ENC_OPTS_VXLAN },
5659
[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE] = { .type = NLA_NESTED },
60+
[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN] = { .type = NLA_NESTED },
5761
};
5862

5963
static const struct nla_policy
@@ -64,6 +68,11 @@ geneve_opt_policy[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX + 1] = {
6468
.len = 128 },
6569
};
6670

71+
static const struct nla_policy
72+
vxlan_opt_policy[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX + 1] = {
73+
[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP] = { .type = NLA_U32 },
74+
};
75+
6776
static int
6877
tunnel_key_copy_geneve_opt(const struct nlattr *nla, void *dst, int dst_len,
6978
struct netlink_ext_ack *extack)
@@ -116,10 +125,36 @@ tunnel_key_copy_geneve_opt(const struct nlattr *nla, void *dst, int dst_len,
116125
return opt_len;
117126
}
118127

128+
static int
129+
tunnel_key_copy_vxlan_opt(const struct nlattr *nla, void *dst, int dst_len,
130+
struct netlink_ext_ack *extack)
131+
{
132+
struct nlattr *tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX + 1];
133+
int err;
134+
135+
err = nla_parse_nested(tb, TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX, nla,
136+
vxlan_opt_policy, extack);
137+
if (err < 0)
138+
return err;
139+
140+
if (!tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP]) {
141+
NL_SET_ERR_MSG(extack, "Missing tunnel key vxlan option gbp");
142+
return -EINVAL;
143+
}
144+
145+
if (dst) {
146+
struct vxlan_metadata *md = dst;
147+
148+
md->gbp = nla_get_u32(tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP]);
149+
}
150+
151+
return sizeof(struct vxlan_metadata);
152+
}
153+
119154
static int tunnel_key_copy_opts(const struct nlattr *nla, u8 *dst,
120155
int dst_len, struct netlink_ext_ack *extack)
121156
{
122-
int err, rem, opt_len, len = nla_len(nla), opts_len = 0;
157+
int err, rem, opt_len, len = nla_len(nla), opts_len = 0, type = 0;
123158
const struct nlattr *attr, *head = nla_data(nla);
124159

125160
err = nla_validate_deprecated(head, len, TCA_TUNNEL_KEY_ENC_OPTS_MAX,
@@ -130,6 +165,10 @@ static int tunnel_key_copy_opts(const struct nlattr *nla, u8 *dst,
130165
nla_for_each_attr(attr, head, len, rem) {
131166
switch (nla_type(attr)) {
132167
case TCA_TUNNEL_KEY_ENC_OPTS_GENEVE:
168+
if (type && type != TUNNEL_GENEVE_OPT) {
169+
NL_SET_ERR_MSG(extack, "Duplicate type for geneve options");
170+
return -EINVAL;
171+
}
133172
opt_len = tunnel_key_copy_geneve_opt(attr, dst,
134173
dst_len, extack);
135174
if (opt_len < 0)
@@ -139,6 +178,19 @@ static int tunnel_key_copy_opts(const struct nlattr *nla, u8 *dst,
139178
dst_len -= opt_len;
140179
dst += opt_len;
141180
}
181+
type = TUNNEL_GENEVE_OPT;
182+
break;
183+
case TCA_TUNNEL_KEY_ENC_OPTS_VXLAN:
184+
if (type) {
185+
NL_SET_ERR_MSG(extack, "Duplicate type for vxlan options");
186+
return -EINVAL;
187+
}
188+
opt_len = tunnel_key_copy_vxlan_opt(attr, dst,
189+
dst_len, extack);
190+
if (opt_len < 0)
191+
return opt_len;
192+
opts_len += opt_len;
193+
type = TUNNEL_VXLAN_OPT;
142194
break;
143195
}
144196
}
@@ -174,6 +226,14 @@ static int tunnel_key_opts_set(struct nlattr *nla, struct ip_tunnel_info *info,
174226
opts_len, extack);
175227
#else
176228
return -EAFNOSUPPORT;
229+
#endif
230+
case TCA_TUNNEL_KEY_ENC_OPTS_VXLAN:
231+
#if IS_ENABLED(CONFIG_INET)
232+
info->key.tun_flags |= TUNNEL_VXLAN_OPT;
233+
return tunnel_key_copy_opts(nla, ip_tunnel_info_opts(info),
234+
opts_len, extack);
235+
#else
236+
return -EAFNOSUPPORT;
177237
#endif
178238
default:
179239
NL_SET_ERR_MSG(extack, "Cannot set tunnel options for unknown tunnel type");
@@ -451,6 +511,25 @@ static int tunnel_key_geneve_opts_dump(struct sk_buff *skb,
451511
return 0;
452512
}
453513

514+
static int tunnel_key_vxlan_opts_dump(struct sk_buff *skb,
515+
const struct ip_tunnel_info *info)
516+
{
517+
struct vxlan_metadata *md = (struct vxlan_metadata *)(info + 1);
518+
struct nlattr *start;
519+
520+
start = nla_nest_start_noflag(skb, TCA_TUNNEL_KEY_ENC_OPTS_VXLAN);
521+
if (!start)
522+
return -EMSGSIZE;
523+
524+
if (nla_put_u32(skb, TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP, md->gbp)) {
525+
nla_nest_cancel(skb, start);
526+
return -EMSGSIZE;
527+
}
528+
529+
nla_nest_end(skb, start);
530+
return 0;
531+
}
532+
454533
static int tunnel_key_opts_dump(struct sk_buff *skb,
455534
const struct ip_tunnel_info *info)
456535
{
@@ -468,6 +547,10 @@ static int tunnel_key_opts_dump(struct sk_buff *skb,
468547
err = tunnel_key_geneve_opts_dump(skb, info);
469548
if (err)
470549
goto err_out;
550+
} else if (info->key.tun_flags & TUNNEL_VXLAN_OPT) {
551+
err = tunnel_key_vxlan_opts_dump(skb, info);
552+
if (err)
553+
goto err_out;
471554
} else {
472555
err_out:
473556
nla_nest_cancel(skb, start);

0 commit comments

Comments
 (0)