Skip to content

Commit 79b1011

Browse files
lxindavem330
authored andcommitted
net: sched: allow flower to match erspan options
This patch is to allow matching options in erspan. The options can be described in the form: VER:INDEX:DIR:HWID/VER:INDEX_MASK:DIR_MASK:HWID_MASK. When ver is set to 1, index will be applied while dir and hwid will be ignored, and when ver is set to 2, dir and hwid will be used while index will be ignored. Different from geneve, only one option can be set. And also, geneve options, vxlan options or erspan options can't be set at the same time. # ip link add name erspan1 type erspan external # tc qdisc add dev erspan1 ingress # tc filter add dev erspan1 protocol ip parent ffff: \ flower \ enc_src_ip 10.0.99.192 \ enc_dst_ip 10.0.99.193 \ enc_key_id 11 \ erspan_opts 1:12:0:0/1:ffff:0:0 \ ip_proto udp \ action mirred egress redirect dev eth0 v1->v2: - improve some err msgs of extack. Signed-off-by: Xin Long <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d8f9dfa commit 79b1011

File tree

2 files changed

+161
-0
lines changed

2 files changed

+161
-0
lines changed

include/uapi/linux/pkt_cls.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,10 @@ enum {
575575
* TCA_FLOWER_KEY_ENC_OPT_VXLAN_
576576
* attributes
577577
*/
578+
TCA_FLOWER_KEY_ENC_OPTS_ERSPAN, /* Nested
579+
* TCA_FLOWER_KEY_ENC_OPT_ERSPAN_
580+
* attributes
581+
*/
578582
__TCA_FLOWER_KEY_ENC_OPTS_MAX,
579583
};
580584

@@ -601,6 +605,18 @@ enum {
601605
#define TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX \
602606
(__TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX - 1)
603607

608+
enum {
609+
TCA_FLOWER_KEY_ENC_OPT_ERSPAN_UNSPEC,
610+
TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER, /* u8 */
611+
TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX, /* be32 */
612+
TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR, /* u8 */
613+
TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID, /* u8 */
614+
__TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX,
615+
};
616+
617+
#define TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX \
618+
(__TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX - 1)
619+
604620
enum {
605621
TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
606622
TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),

net/sched/cls_flower.c

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <net/flow_dissector.h>
2424
#include <net/geneve.h>
2525
#include <net/vxlan.h>
26+
#include <net/erspan.h>
2627

2728
#include <net/dst.h>
2829
#include <net/dst_metadata.h>
@@ -693,6 +694,7 @@ enc_opts_policy[TCA_FLOWER_KEY_ENC_OPTS_MAX + 1] = {
693694
.strict_start_type = TCA_FLOWER_KEY_ENC_OPTS_VXLAN },
694695
[TCA_FLOWER_KEY_ENC_OPTS_GENEVE] = { .type = NLA_NESTED },
695696
[TCA_FLOWER_KEY_ENC_OPTS_VXLAN] = { .type = NLA_NESTED },
697+
[TCA_FLOWER_KEY_ENC_OPTS_ERSPAN] = { .type = NLA_NESTED },
696698
};
697699

698700
static const struct nla_policy
@@ -708,6 +710,14 @@ vxlan_opt_policy[TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX + 1] = {
708710
[TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP] = { .type = NLA_U32 },
709711
};
710712

713+
static const struct nla_policy
714+
erspan_opt_policy[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX + 1] = {
715+
[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER] = { .type = NLA_U8 },
716+
[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX] = { .type = NLA_U32 },
717+
[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR] = { .type = NLA_U8 },
718+
[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID] = { .type = NLA_U8 },
719+
};
720+
711721
static void fl_set_key_val(struct nlattr **tb,
712722
void *val, int val_type,
713723
void *mask, int mask_type, int len)
@@ -972,6 +982,70 @@ static int fl_set_vxlan_opt(const struct nlattr *nla, struct fl_flow_key *key,
972982
return sizeof(*md);
973983
}
974984

985+
static int fl_set_erspan_opt(const struct nlattr *nla, struct fl_flow_key *key,
986+
int depth, int option_len,
987+
struct netlink_ext_ack *extack)
988+
{
989+
struct nlattr *tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX + 1];
990+
struct erspan_metadata *md;
991+
int err;
992+
993+
md = (struct erspan_metadata *)&key->enc_opts.data[key->enc_opts.len];
994+
memset(md, 0xff, sizeof(*md));
995+
md->version = 1;
996+
997+
if (!depth)
998+
return sizeof(*md);
999+
1000+
if (nla_type(nla) != TCA_FLOWER_KEY_ENC_OPTS_ERSPAN) {
1001+
NL_SET_ERR_MSG(extack, "Non-erspan option type for mask");
1002+
return -EINVAL;
1003+
}
1004+
1005+
err = nla_parse_nested(tb, TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX, nla,
1006+
erspan_opt_policy, extack);
1007+
if (err < 0)
1008+
return err;
1009+
1010+
if (!option_len && !tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER]) {
1011+
NL_SET_ERR_MSG(extack, "Missing tunnel key erspan option ver");
1012+
return -EINVAL;
1013+
}
1014+
1015+
if (tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER])
1016+
md->version = nla_get_u8(tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER]);
1017+
1018+
if (md->version == 1) {
1019+
if (!option_len && !tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX]) {
1020+
NL_SET_ERR_MSG(extack, "Missing tunnel key erspan option index");
1021+
return -EINVAL;
1022+
}
1023+
if (tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX]) {
1024+
nla = tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX];
1025+
md->u.index = nla_get_be32(nla);
1026+
}
1027+
} else if (md->version == 2) {
1028+
if (!option_len && (!tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR] ||
1029+
!tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID])) {
1030+
NL_SET_ERR_MSG(extack, "Missing tunnel key erspan option dir or hwid");
1031+
return -EINVAL;
1032+
}
1033+
if (tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR]) {
1034+
nla = tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR];
1035+
md->u.md2.dir = nla_get_u8(nla);
1036+
}
1037+
if (tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID]) {
1038+
nla = tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID];
1039+
set_hwid(&md->u.md2, nla_get_u8(nla));
1040+
}
1041+
} else {
1042+
NL_SET_ERR_MSG(extack, "Tunnel key erspan option ver is incorrect");
1043+
return -EINVAL;
1044+
}
1045+
1046+
return sizeof(*md);
1047+
}
1048+
9751049
static int fl_set_enc_opt(struct nlattr **tb, struct fl_flow_key *key,
9761050
struct fl_flow_key *mask,
9771051
struct netlink_ext_ack *extack)
@@ -1065,6 +1139,39 @@ static int fl_set_enc_opt(struct nlattr **tb, struct fl_flow_key *key,
10651139
return -EINVAL;
10661140
}
10671141

1142+
if (msk_depth)
1143+
nla_opt_msk = nla_next(nla_opt_msk, &msk_depth);
1144+
break;
1145+
case TCA_FLOWER_KEY_ENC_OPTS_ERSPAN:
1146+
if (key->enc_opts.dst_opt_type) {
1147+
NL_SET_ERR_MSG(extack, "Duplicate type for erspan options");
1148+
return -EINVAL;
1149+
}
1150+
option_len = 0;
1151+
key->enc_opts.dst_opt_type = TUNNEL_ERSPAN_OPT;
1152+
option_len = fl_set_erspan_opt(nla_opt_key, key,
1153+
key_depth, option_len,
1154+
extack);
1155+
if (option_len < 0)
1156+
return option_len;
1157+
1158+
key->enc_opts.len += option_len;
1159+
/* At the same time we need to parse through the mask
1160+
* in order to verify exact and mask attribute lengths.
1161+
*/
1162+
mask->enc_opts.dst_opt_type = TUNNEL_ERSPAN_OPT;
1163+
option_len = fl_set_erspan_opt(nla_opt_msk, mask,
1164+
msk_depth, option_len,
1165+
extack);
1166+
if (option_len < 0)
1167+
return option_len;
1168+
1169+
mask->enc_opts.len += option_len;
1170+
if (key->enc_opts.len != mask->enc_opts.len) {
1171+
NL_SET_ERR_MSG(extack, "Key and mask miss aligned");
1172+
return -EINVAL;
1173+
}
1174+
10681175
if (msk_depth)
10691176
nla_opt_msk = nla_next(nla_opt_msk, &msk_depth);
10701177
break;
@@ -2239,6 +2346,39 @@ static int fl_dump_key_vxlan_opt(struct sk_buff *skb,
22392346
return -EMSGSIZE;
22402347
}
22412348

2349+
static int fl_dump_key_erspan_opt(struct sk_buff *skb,
2350+
struct flow_dissector_key_enc_opts *enc_opts)
2351+
{
2352+
struct erspan_metadata *md;
2353+
struct nlattr *nest;
2354+
2355+
nest = nla_nest_start_noflag(skb, TCA_FLOWER_KEY_ENC_OPTS_ERSPAN);
2356+
if (!nest)
2357+
goto nla_put_failure;
2358+
2359+
md = (struct erspan_metadata *)&enc_opts->data[0];
2360+
if (nla_put_u8(skb, TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER, md->version))
2361+
goto nla_put_failure;
2362+
2363+
if (md->version == 1 &&
2364+
nla_put_be32(skb, TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX, md->u.index))
2365+
goto nla_put_failure;
2366+
2367+
if (md->version == 2 &&
2368+
(nla_put_u8(skb, TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR,
2369+
md->u.md2.dir) ||
2370+
nla_put_u8(skb, TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID,
2371+
get_hwid(&md->u.md2))))
2372+
goto nla_put_failure;
2373+
2374+
nla_nest_end(skb, nest);
2375+
return 0;
2376+
2377+
nla_put_failure:
2378+
nla_nest_cancel(skb, nest);
2379+
return -EMSGSIZE;
2380+
}
2381+
22422382
static int fl_dump_key_ct(struct sk_buff *skb,
22432383
struct flow_dissector_key_ct *key,
22442384
struct flow_dissector_key_ct *mask)
@@ -2297,6 +2437,11 @@ static int fl_dump_key_options(struct sk_buff *skb, int enc_opt_type,
22972437
if (err)
22982438
goto nla_put_failure;
22992439
break;
2440+
case TUNNEL_ERSPAN_OPT:
2441+
err = fl_dump_key_erspan_opt(skb, enc_opts);
2442+
if (err)
2443+
goto nla_put_failure;
2444+
break;
23002445
default:
23012446
goto nla_put_failure;
23022447
}

0 commit comments

Comments
 (0)