Skip to content

Commit bc3103f

Browse files
amirvdavem330
authored andcommitted
net/sched: cls_flower: Classify packet in ip tunnels
Introduce classifying by metadata extracted by the tunnel device. Outer header fields - source/dest ip and tunnel id, are extracted from the metadata when classifying. For example, the following will add a filter on the ingress Qdisc of shared vxlan device named 'vxlan0'. To forward packets with outer src ip 11.11.0.2, dst ip 11.11.0.1 and tunnel id 11. The packets will be forwarded to tap device 'vnet0' (after metadata is released): $ tc filter add dev vxlan0 protocol ip parent ffff: \ flower \ enc_src_ip 11.11.0.2 \ enc_dst_ip 11.11.0.1 \ enc_key_id 11 \ dst_ip 11.11.11.1 \ action tunnel_key release \ action mirred egress redirect dev vnet0 The action tunnel_key, will be introduced in the next patch in this series. Signed-off-by: Amir Vadai <amir@vadai.me> Signed-off-by: Hadar Hen Zion <hadarh@mellanox.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 2ff378b commit bc3103f

File tree

2 files changed

+110
-1
lines changed

2 files changed

+110
-1
lines changed

include/uapi/linux/pkt_cls.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,17 @@ enum {
431431
TCA_FLOWER_KEY_VLAN_ID,
432432
TCA_FLOWER_KEY_VLAN_PRIO,
433433
TCA_FLOWER_KEY_VLAN_ETH_TYPE,
434+
435+
TCA_FLOWER_KEY_ENC_KEY_ID, /* be32 */
436+
TCA_FLOWER_KEY_ENC_IPV4_SRC, /* be32 */
437+
TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,/* be32 */
438+
TCA_FLOWER_KEY_ENC_IPV4_DST, /* be32 */
439+
TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,/* be32 */
440+
TCA_FLOWER_KEY_ENC_IPV6_SRC, /* struct in6_addr */
441+
TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,/* struct in6_addr */
442+
TCA_FLOWER_KEY_ENC_IPV6_DST, /* struct in6_addr */
443+
TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,/* struct in6_addr */
444+
434445
__TCA_FLOWER_MAX,
435446
};
436447

net/sched/cls_flower.c

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@
2323
#include <net/ip.h>
2424
#include <net/flow_dissector.h>
2525

26+
#include <net/dst.h>
27+
#include <net/dst_metadata.h>
28+
2629
struct fl_flow_key {
2730
int indev_ifindex;
2831
struct flow_dissector_key_control control;
32+
struct flow_dissector_key_control enc_control;
2933
struct flow_dissector_key_basic basic;
3034
struct flow_dissector_key_eth_addrs eth;
3135
struct flow_dissector_key_vlan vlan;
@@ -35,6 +39,11 @@ struct fl_flow_key {
3539
struct flow_dissector_key_ipv6_addrs ipv6;
3640
};
3741
struct flow_dissector_key_ports tp;
42+
struct flow_dissector_key_keyid enc_key_id;
43+
union {
44+
struct flow_dissector_key_ipv4_addrs enc_ipv4;
45+
struct flow_dissector_key_ipv6_addrs enc_ipv6;
46+
};
3847
} __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
3948

4049
struct fl_flow_mask_range {
@@ -124,11 +133,31 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp,
124133
struct cls_fl_filter *f;
125134
struct fl_flow_key skb_key;
126135
struct fl_flow_key skb_mkey;
136+
struct ip_tunnel_info *info;
127137

128138
if (!atomic_read(&head->ht.nelems))
129139
return -1;
130140

131141
fl_clear_masked_range(&skb_key, &head->mask);
142+
143+
info = skb_tunnel_info(skb);
144+
if (info) {
145+
struct ip_tunnel_key *key = &info->key;
146+
147+
switch (ip_tunnel_info_af(info)) {
148+
case AF_INET:
149+
skb_key.enc_ipv4.src = key->u.ipv4.src;
150+
skb_key.enc_ipv4.dst = key->u.ipv4.dst;
151+
break;
152+
case AF_INET6:
153+
skb_key.enc_ipv6.src = key->u.ipv6.src;
154+
skb_key.enc_ipv6.dst = key->u.ipv6.dst;
155+
break;
156+
}
157+
158+
skb_key.enc_key_id.keyid = tunnel_id_to_key32(key->tun_id);
159+
}
160+
132161
skb_key.indev_ifindex = skb->skb_iif;
133162
/* skb_flow_dissect() does not set n_proto in case an unknown protocol,
134163
* so do it rather here.
@@ -297,7 +326,15 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = {
297326
[TCA_FLOWER_KEY_VLAN_ID] = { .type = NLA_U16 },
298327
[TCA_FLOWER_KEY_VLAN_PRIO] = { .type = NLA_U8 },
299328
[TCA_FLOWER_KEY_VLAN_ETH_TYPE] = { .type = NLA_U16 },
300-
329+
[TCA_FLOWER_KEY_ENC_KEY_ID] = { .type = NLA_U32 },
330+
[TCA_FLOWER_KEY_ENC_IPV4_SRC] = { .type = NLA_U32 },
331+
[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK] = { .type = NLA_U32 },
332+
[TCA_FLOWER_KEY_ENC_IPV4_DST] = { .type = NLA_U32 },
333+
[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK] = { .type = NLA_U32 },
334+
[TCA_FLOWER_KEY_ENC_IPV6_SRC] = { .len = sizeof(struct in6_addr) },
335+
[TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK] = { .len = sizeof(struct in6_addr) },
336+
[TCA_FLOWER_KEY_ENC_IPV6_DST] = { .len = sizeof(struct in6_addr) },
337+
[TCA_FLOWER_KEY_ENC_IPV6_DST_MASK] = { .len = sizeof(struct in6_addr) },
301338
};
302339

303340
static void fl_set_key_val(struct nlattr **tb,
@@ -409,6 +446,40 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
409446
sizeof(key->tp.dst));
410447
}
411448

449+
if (tb[TCA_FLOWER_KEY_ENC_IPV4_SRC] ||
450+
tb[TCA_FLOWER_KEY_ENC_IPV4_DST]) {
451+
key->enc_control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
452+
fl_set_key_val(tb, &key->enc_ipv4.src,
453+
TCA_FLOWER_KEY_ENC_IPV4_SRC,
454+
&mask->enc_ipv4.src,
455+
TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,
456+
sizeof(key->enc_ipv4.src));
457+
fl_set_key_val(tb, &key->enc_ipv4.dst,
458+
TCA_FLOWER_KEY_ENC_IPV4_DST,
459+
&mask->enc_ipv4.dst,
460+
TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,
461+
sizeof(key->enc_ipv4.dst));
462+
}
463+
464+
if (tb[TCA_FLOWER_KEY_ENC_IPV6_SRC] ||
465+
tb[TCA_FLOWER_KEY_ENC_IPV6_DST]) {
466+
key->enc_control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
467+
fl_set_key_val(tb, &key->enc_ipv6.src,
468+
TCA_FLOWER_KEY_ENC_IPV6_SRC,
469+
&mask->enc_ipv6.src,
470+
TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,
471+
sizeof(key->enc_ipv6.src));
472+
fl_set_key_val(tb, &key->enc_ipv6.dst,
473+
TCA_FLOWER_KEY_ENC_IPV6_DST,
474+
&mask->enc_ipv6.dst,
475+
TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,
476+
sizeof(key->enc_ipv6.dst));
477+
}
478+
479+
fl_set_key_val(tb, &key->enc_key_id.keyid, TCA_FLOWER_KEY_ENC_KEY_ID,
480+
&mask->enc_key_id.keyid, TCA_FLOWER_KEY_ENC_KEY_ID,
481+
sizeof(key->enc_key_id.keyid));
482+
412483
return 0;
413484
}
414485

@@ -821,6 +892,33 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
821892
sizeof(key->tp.dst))))
822893
goto nla_put_failure;
823894

895+
if (key->enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS &&
896+
(fl_dump_key_val(skb, &key->enc_ipv4.src,
897+
TCA_FLOWER_KEY_ENC_IPV4_SRC, &mask->enc_ipv4.src,
898+
TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,
899+
sizeof(key->enc_ipv4.src)) ||
900+
fl_dump_key_val(skb, &key->enc_ipv4.dst,
901+
TCA_FLOWER_KEY_ENC_IPV4_DST, &mask->enc_ipv4.dst,
902+
TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,
903+
sizeof(key->enc_ipv4.dst))))
904+
goto nla_put_failure;
905+
else if (key->enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS &&
906+
(fl_dump_key_val(skb, &key->enc_ipv6.src,
907+
TCA_FLOWER_KEY_ENC_IPV6_SRC, &mask->enc_ipv6.src,
908+
TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,
909+
sizeof(key->enc_ipv6.src)) ||
910+
fl_dump_key_val(skb, &key->enc_ipv6.dst,
911+
TCA_FLOWER_KEY_ENC_IPV6_DST,
912+
&mask->enc_ipv6.dst,
913+
TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,
914+
sizeof(key->enc_ipv6.dst))))
915+
goto nla_put_failure;
916+
917+
if (fl_dump_key_val(skb, &key->enc_key_id, TCA_FLOWER_KEY_ENC_KEY_ID,
918+
&mask->enc_key_id, TCA_FLOWER_KEY_ENC_KEY_ID,
919+
sizeof(key->enc_key_id)))
920+
goto nla_put_failure;
921+
824922
nla_put_u32(skb, TCA_FLOWER_FLAGS, f->flags);
825923

826924
if (tcf_exts_dump(skb, &f->exts))

0 commit comments

Comments
 (0)