Skip to content

Commit d1ba24f

Browse files
committed
Merge branch 'act_tunnel_key'
Hadar Hen Zion says: ==================== net/sched: ip tunnel metadata set/release/classify by using TC This patchset introduces ip tunnel manipulation support using the TC subsystem. In the decap flow, it enables the user to redirect packets from a shared tunnel device and classify by outer and inner headers. The outer headers are extracted from the metadata and used by the flower filter. A new action act_tunnel_key, releases the metadata. In the encap flow, act_tunnel_key creates a metadata object to be used by the shared tunnel device. The actual redirection to the tunnel device is done using act_mirred. For example: $ tc qdisc add dev vnet0 ingress $ tc filter add dev vnet0 protocol ip parent ffff: \ flower \ ip_proto 1 \ action tunnel_key set \ src_ip 11.11.0.1 \ dst_ip 11.11.0.2 \ id 11 \ action mirred egress redirect dev vxlan0 $ tc qdisc add dev vxlan0 ingress $ 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 \ action tunnel_key release \ action mirred egress redirect dev vnet0 Amir & Hadar Changes from V6: - Add kfree_rcu to tunnel_key_release function - Use reverse Christmas tree order in tunnel_key_init function Changes from V5: - Add __rcu notation to struct tcf_tunnel_key_params in struct tcf_tunnel_key - Fix indentation in include/net/dst_metadata.h - Fix syntx error in commit message Changes from V4: - Fix tunnel_key_init function error flow. - Add 'action' variable to struct tcf_tunnel_key_params and use it instead of tcf_action variable which is not protected by rcu lock. Changes from V3: - Use percpu stats - No spinlock on datapatch - protecting parameters with rcu - Fix buggy handling of set/release dst - Use nla_get_in_addr and nla_put_in_addr - Fix change logs - Pass in6_addr by pointer - Rename utility functions to start with double underscore Changes from V2: - Use union in struct fl_flow_key for enc_ipv6 and enc_ipv4. - Rename functions _ip_tun_rx_dst and _ipv6_tun_rx_dst to _ip_tun_set_dst and _ipv6_tun_set_dst accordingly. - Remove local parameter 'encapdecap' from tunnel_key_init function. - Don't copy in6_addr values in tunnel_key_dump_addresses function, use pointers. Changes from V1: - More cleanups to key32_to_tunnel_id() and tunnel_id_to_key32() - IPv6 Support added - Set TUNNEL_KEY flag to make GRE work - Handle zero tunnel id properly in act_tunnel_key - Don't leave junk in decap action - Fix bug in act_tunnel_key initialization where (exists & ocr) is true - Remove BUG() from code - Rename action to tunnel_key - Improve grep-ability of code - Reuse code from ip_tun_rx_dst() and ipv6_tun_rx_dst() Changes from RFC: - Add a new action instead of making mirred too complex - No need to specify UDP port in action - it is already in the tunnel device configuration - Added a decap operation to drop tunnel metadata ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents e808bb6 + d0f6dd8 commit d1ba24f

File tree

12 files changed

+606
-55
lines changed

12 files changed

+606
-55
lines changed

drivers/net/vxlan.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,7 +1291,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
12911291
struct metadata_dst *tun_dst;
12921292

12931293
tun_dst = udp_tun_rx_dst(skb, vxlan_get_sk_family(vs), TUNNEL_KEY,
1294-
vxlan_vni_to_tun_id(vni), sizeof(*md));
1294+
key32_to_tunnel_id(vni), sizeof(*md));
12951295

12961296
if (!tun_dst)
12971297
goto drop;
@@ -1945,7 +1945,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
19451945
goto drop;
19461946
}
19471947
dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port;
1948-
vni = vxlan_tun_id_to_vni(info->key.tun_id);
1948+
vni = tunnel_id_to_key32(info->key.tun_id);
19491949
remote_ip.sa.sa_family = ip_tunnel_info_af(info);
19501950
if (remote_ip.sa.sa_family == AF_INET) {
19511951
remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst;

include/net/dst_metadata.h

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -112,30 +112,44 @@ static inline struct ip_tunnel_info *skb_tunnel_info_unclone(struct sk_buff *skb
112112
return &dst->u.tun_info;
113113
}
114114

115-
static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb,
116-
__be16 flags,
117-
__be64 tunnel_id,
118-
int md_size)
115+
static inline struct metadata_dst *__ip_tun_set_dst(__be32 saddr,
116+
__be32 daddr,
117+
__u8 tos, __u8 ttl,
118+
__be16 flags,
119+
__be64 tunnel_id,
120+
int md_size)
119121
{
120-
const struct iphdr *iph = ip_hdr(skb);
121122
struct metadata_dst *tun_dst;
122123

123124
tun_dst = tun_rx_dst(md_size);
124125
if (!tun_dst)
125126
return NULL;
126127

127128
ip_tunnel_key_init(&tun_dst->u.tun_info.key,
128-
iph->saddr, iph->daddr, iph->tos, iph->ttl,
129+
saddr, daddr, tos, ttl,
129130
0, 0, 0, tunnel_id, flags);
130131
return tun_dst;
131132
}
132133

133-
static inline struct metadata_dst *ipv6_tun_rx_dst(struct sk_buff *skb,
134+
static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb,
134135
__be16 flags,
135136
__be64 tunnel_id,
136137
int md_size)
137138
{
138-
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
139+
const struct iphdr *iph = ip_hdr(skb);
140+
141+
return __ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl,
142+
flags, tunnel_id, md_size);
143+
}
144+
145+
static inline struct metadata_dst *__ipv6_tun_set_dst(const struct in6_addr *saddr,
146+
const struct in6_addr *daddr,
147+
__u8 tos, __u8 ttl,
148+
__be32 label,
149+
__be16 flags,
150+
__be64 tunnel_id,
151+
int md_size)
152+
{
139153
struct metadata_dst *tun_dst;
140154
struct ip_tunnel_info *info;
141155

@@ -150,14 +164,26 @@ static inline struct metadata_dst *ipv6_tun_rx_dst(struct sk_buff *skb,
150164
info->key.tp_src = 0;
151165
info->key.tp_dst = 0;
152166

153-
info->key.u.ipv6.src = ip6h->saddr;
154-
info->key.u.ipv6.dst = ip6h->daddr;
167+
info->key.u.ipv6.src = *saddr;
168+
info->key.u.ipv6.dst = *daddr;
155169

156-
info->key.tos = ipv6_get_dsfield(ip6h);
157-
info->key.ttl = ip6h->hop_limit;
158-
info->key.label = ip6_flowlabel(ip6h);
170+
info->key.tos = tos;
171+
info->key.ttl = ttl;
172+
info->key.label = label;
159173

160174
return tun_dst;
161175
}
162176

177+
static inline struct metadata_dst *ipv6_tun_rx_dst(struct sk_buff *skb,
178+
__be16 flags,
179+
__be64 tunnel_id,
180+
int md_size)
181+
{
182+
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
183+
184+
return __ipv6_tun_set_dst(&ip6h->saddr, &ip6h->daddr,
185+
ipv6_get_dsfield(ip6h), ip6h->hop_limit,
186+
ip6_flowlabel(ip6h), flags, tunnel_id,
187+
md_size);
188+
}
163189
#endif /* __NET_DST_METADATA_H */

include/net/ip_tunnels.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,25 @@ static inline unsigned short ip_tunnel_info_af(const struct ip_tunnel_info
222222
return tun_info->mode & IP_TUNNEL_INFO_IPV6 ? AF_INET6 : AF_INET;
223223
}
224224

225+
static inline __be64 key32_to_tunnel_id(__be32 key)
226+
{
227+
#ifdef __BIG_ENDIAN
228+
return (__force __be64)key;
229+
#else
230+
return (__force __be64)((__force u64)key << 32);
231+
#endif
232+
}
233+
234+
/* Returns the least-significant 32 bits of a __be64. */
235+
static inline __be32 tunnel_id_to_key32(__be64 tun_id)
236+
{
237+
#ifdef __BIG_ENDIAN
238+
return (__force __be32)tun_id;
239+
#else
240+
return (__force __be32)((__force u64)tun_id >> 32);
241+
#endif
242+
}
243+
225244
#ifdef CONFIG_INET
226245

227246
int ip_tunnel_init(struct net_device *dev);

include/net/tc_act/tc_tunnel_key.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (c) 2016, Amir Vadai <[email protected]>
3+
* 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+
*/
10+
11+
#ifndef __NET_TC_TUNNEL_KEY_H
12+
#define __NET_TC_TUNNEL_KEY_H
13+
14+
#include <net/act_api.h>
15+
16+
struct tcf_tunnel_key_params {
17+
struct rcu_head rcu;
18+
int tcft_action;
19+
int action;
20+
struct metadata_dst *tcft_enc_metadata;
21+
};
22+
23+
struct tcf_tunnel_key {
24+
struct tc_action common;
25+
struct tcf_tunnel_key_params __rcu *params;
26+
};
27+
28+
#define to_tunnel_key(a) ((struct tcf_tunnel_key *)a)
29+
30+
#endif /* __NET_TC_TUNNEL_KEY_H */

include/net/vxlan.h

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -350,24 +350,6 @@ static inline __be32 vxlan_vni_field(__be32 vni)
350350
#endif
351351
}
352352

353-
static inline __be32 vxlan_tun_id_to_vni(__be64 tun_id)
354-
{
355-
#if defined(__BIG_ENDIAN)
356-
return (__force __be32)tun_id;
357-
#else
358-
return (__force __be32)((__force u64)tun_id >> 32);
359-
#endif
360-
}
361-
362-
static inline __be64 vxlan_vni_to_tun_id(__be32 vni)
363-
{
364-
#if defined(__BIG_ENDIAN)
365-
return (__force __be64)vni;
366-
#else
367-
return (__force __be64)((u64)(__force u32)vni << 32);
368-
#endif
369-
}
370-
371353
static inline size_t vxlan_rco_start(__be32 vni_field)
372354
{
373355
return be32_to_cpu(vni_field & VXLAN_RCO_MASK) << VXLAN_RCO_SHIFT;

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2016, Amir Vadai <[email protected]>
3+
* 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+
*/
10+
11+
#ifndef __LINUX_TC_TUNNEL_KEY_H
12+
#define __LINUX_TC_TUNNEL_KEY_H
13+
14+
#include <linux/pkt_cls.h>
15+
16+
#define TCA_ACT_TUNNEL_KEY 17
17+
18+
#define TCA_TUNNEL_KEY_ACT_SET 1
19+
#define TCA_TUNNEL_KEY_ACT_RELEASE 2
20+
21+
struct tc_tunnel_key {
22+
tc_gen;
23+
int t_action;
24+
};
25+
26+
enum {
27+
TCA_TUNNEL_KEY_UNSPEC,
28+
TCA_TUNNEL_KEY_TM,
29+
TCA_TUNNEL_KEY_PARMS,
30+
TCA_TUNNEL_KEY_ENC_IPV4_SRC, /* be32 */
31+
TCA_TUNNEL_KEY_ENC_IPV4_DST, /* be32 */
32+
TCA_TUNNEL_KEY_ENC_IPV6_SRC, /* struct in6_addr */
33+
TCA_TUNNEL_KEY_ENC_IPV6_DST, /* struct in6_addr */
34+
TCA_TUNNEL_KEY_ENC_KEY_ID, /* be64 */
35+
TCA_TUNNEL_KEY_PAD,
36+
__TCA_TUNNEL_KEY_MAX,
37+
};
38+
39+
#define TCA_TUNNEL_KEY_MAX (__TCA_TUNNEL_KEY_MAX - 1)
40+
41+
#endif

net/ipv4/ip_gre.c

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -246,25 +246,6 @@ static void gre_err(struct sk_buff *skb, u32 info)
246246
ipgre_err(skb, info, &tpi);
247247
}
248248

249-
static __be64 key_to_tunnel_id(__be32 key)
250-
{
251-
#ifdef __BIG_ENDIAN
252-
return (__force __be64)((__force u32)key);
253-
#else
254-
return (__force __be64)((__force u64)key << 32);
255-
#endif
256-
}
257-
258-
/* Returns the least-significant 32 bits of a __be64. */
259-
static __be32 tunnel_id_to_key(__be64 x)
260-
{
261-
#ifdef __BIG_ENDIAN
262-
return (__force __be32)x;
263-
#else
264-
return (__force __be32)((__force u64)x >> 32);
265-
#endif
266-
}
267-
268249
static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
269250
struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
270251
{
@@ -290,7 +271,7 @@ static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
290271
__be64 tun_id;
291272

292273
flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
293-
tun_id = key_to_tunnel_id(tpi->key);
274+
tun_id = key32_to_tunnel_id(tpi->key);
294275
tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
295276
if (!tun_dst)
296277
return PACKET_REJECT;
@@ -446,7 +427,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
446427

447428
flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY);
448429
gre_build_header(skb, tunnel_hlen, flags, proto,
449-
tunnel_id_to_key(tun_info->key.tun_id), 0);
430+
tunnel_id_to_key32(tun_info->key.tun_id), 0);
450431

451432
df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
452433

net/sched/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,17 @@ config NET_ACT_IFE
761761
To compile this code as a module, choose M here: the
762762
module will be called act_ife.
763763

764+
config NET_ACT_TUNNEL_KEY
765+
tristate "IP tunnel metadata manipulation"
766+
depends on NET_CLS_ACT
767+
---help---
768+
Say Y here to set/release ip tunnel metadata.
769+
770+
If unsure, say N.
771+
772+
To compile this code as a module, choose M here: the
773+
module will be called act_tunnel_key.
774+
764775
config NET_IFE_SKBMARK
765776
tristate "Support to encoding decoding skb mark on IFE action"
766777
depends on NET_ACT_IFE

net/sched/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ obj-$(CONFIG_NET_ACT_CONNMARK) += act_connmark.o
2222
obj-$(CONFIG_NET_ACT_IFE) += act_ife.o
2323
obj-$(CONFIG_NET_IFE_SKBMARK) += act_meta_mark.o
2424
obj-$(CONFIG_NET_IFE_SKBPRIO) += act_meta_skbprio.o
25+
obj-$(CONFIG_NET_ACT_TUNNEL_KEY)+= act_tunnel_key.o
2526
obj-$(CONFIG_NET_SCH_FIFO) += sch_fifo.o
2627
obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o
2728
obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o

0 commit comments

Comments
 (0)