Skip to content

Commit

Permalink
Merge branch 'act_tunnel_key'
Browse files Browse the repository at this point in the history
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 <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Sep 11, 2016
2 parents e808bb6 + d0f6dd8 commit d1ba24f
Show file tree
Hide file tree
Showing 12 changed files with 606 additions and 55 deletions.
4 changes: 2 additions & 2 deletions drivers/net/vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1291,7 +1291,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
struct metadata_dst *tun_dst;

tun_dst = udp_tun_rx_dst(skb, vxlan_get_sk_family(vs), TUNNEL_KEY,
vxlan_vni_to_tun_id(vni), sizeof(*md));
key32_to_tunnel_id(vni), sizeof(*md));

if (!tun_dst)
goto drop;
Expand Down Expand Up @@ -1945,7 +1945,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
goto drop;
}
dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port;
vni = vxlan_tun_id_to_vni(info->key.tun_id);
vni = tunnel_id_to_key32(info->key.tun_id);
remote_ip.sa.sa_family = ip_tunnel_info_af(info);
if (remote_ip.sa.sa_family == AF_INET) {
remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst;
Expand Down
52 changes: 39 additions & 13 deletions include/net/dst_metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,30 +112,44 @@ static inline struct ip_tunnel_info *skb_tunnel_info_unclone(struct sk_buff *skb
return &dst->u.tun_info;
}

static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb,
__be16 flags,
__be64 tunnel_id,
int md_size)
static inline struct metadata_dst *__ip_tun_set_dst(__be32 saddr,
__be32 daddr,
__u8 tos, __u8 ttl,
__be16 flags,
__be64 tunnel_id,
int md_size)
{
const struct iphdr *iph = ip_hdr(skb);
struct metadata_dst *tun_dst;

tun_dst = tun_rx_dst(md_size);
if (!tun_dst)
return NULL;

ip_tunnel_key_init(&tun_dst->u.tun_info.key,
iph->saddr, iph->daddr, iph->tos, iph->ttl,
saddr, daddr, tos, ttl,
0, 0, 0, tunnel_id, flags);
return tun_dst;
}

static inline struct metadata_dst *ipv6_tun_rx_dst(struct sk_buff *skb,
static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb,
__be16 flags,
__be64 tunnel_id,
int md_size)
{
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
const struct iphdr *iph = ip_hdr(skb);

return __ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl,
flags, tunnel_id, md_size);
}

static inline struct metadata_dst *__ipv6_tun_set_dst(const struct in6_addr *saddr,
const struct in6_addr *daddr,
__u8 tos, __u8 ttl,
__be32 label,
__be16 flags,
__be64 tunnel_id,
int md_size)
{
struct metadata_dst *tun_dst;
struct ip_tunnel_info *info;

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

info->key.u.ipv6.src = ip6h->saddr;
info->key.u.ipv6.dst = ip6h->daddr;
info->key.u.ipv6.src = *saddr;
info->key.u.ipv6.dst = *daddr;

info->key.tos = ipv6_get_dsfield(ip6h);
info->key.ttl = ip6h->hop_limit;
info->key.label = ip6_flowlabel(ip6h);
info->key.tos = tos;
info->key.ttl = ttl;
info->key.label = label;

return tun_dst;
}

static inline struct metadata_dst *ipv6_tun_rx_dst(struct sk_buff *skb,
__be16 flags,
__be64 tunnel_id,
int md_size)
{
const struct ipv6hdr *ip6h = ipv6_hdr(skb);

return __ipv6_tun_set_dst(&ip6h->saddr, &ip6h->daddr,
ipv6_get_dsfield(ip6h), ip6h->hop_limit,
ip6_flowlabel(ip6h), flags, tunnel_id,
md_size);
}
#endif /* __NET_DST_METADATA_H */
19 changes: 19 additions & 0 deletions include/net/ip_tunnels.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,25 @@ static inline unsigned short ip_tunnel_info_af(const struct ip_tunnel_info
return tun_info->mode & IP_TUNNEL_INFO_IPV6 ? AF_INET6 : AF_INET;
}

static inline __be64 key32_to_tunnel_id(__be32 key)
{
#ifdef __BIG_ENDIAN
return (__force __be64)key;
#else
return (__force __be64)((__force u64)key << 32);
#endif
}

/* Returns the least-significant 32 bits of a __be64. */
static inline __be32 tunnel_id_to_key32(__be64 tun_id)
{
#ifdef __BIG_ENDIAN
return (__force __be32)tun_id;
#else
return (__force __be32)((__force u64)tun_id >> 32);
#endif
}

#ifdef CONFIG_INET

int ip_tunnel_init(struct net_device *dev);
Expand Down
30 changes: 30 additions & 0 deletions include/net/tc_act/tc_tunnel_key.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2016, Amir Vadai <amir@vadai.me>
* Copyright (c) 2016, Mellanox Technologies. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/

#ifndef __NET_TC_TUNNEL_KEY_H
#define __NET_TC_TUNNEL_KEY_H

#include <net/act_api.h>

struct tcf_tunnel_key_params {
struct rcu_head rcu;
int tcft_action;
int action;
struct metadata_dst *tcft_enc_metadata;
};

struct tcf_tunnel_key {
struct tc_action common;
struct tcf_tunnel_key_params __rcu *params;
};

#define to_tunnel_key(a) ((struct tcf_tunnel_key *)a)

#endif /* __NET_TC_TUNNEL_KEY_H */
18 changes: 0 additions & 18 deletions include/net/vxlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,24 +350,6 @@ static inline __be32 vxlan_vni_field(__be32 vni)
#endif
}

static inline __be32 vxlan_tun_id_to_vni(__be64 tun_id)
{
#if defined(__BIG_ENDIAN)
return (__force __be32)tun_id;
#else
return (__force __be32)((__force u64)tun_id >> 32);
#endif
}

static inline __be64 vxlan_vni_to_tun_id(__be32 vni)
{
#if defined(__BIG_ENDIAN)
return (__force __be64)vni;
#else
return (__force __be64)((u64)(__force u32)vni << 32);
#endif
}

static inline size_t vxlan_rco_start(__be32 vni_field)
{
return be32_to_cpu(vni_field & VXLAN_RCO_MASK) << VXLAN_RCO_SHIFT;
Expand Down
11 changes: 11 additions & 0 deletions include/uapi/linux/pkt_cls.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,17 @@ enum {
TCA_FLOWER_KEY_VLAN_ID,
TCA_FLOWER_KEY_VLAN_PRIO,
TCA_FLOWER_KEY_VLAN_ETH_TYPE,

TCA_FLOWER_KEY_ENC_KEY_ID, /* be32 */
TCA_FLOWER_KEY_ENC_IPV4_SRC, /* be32 */
TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,/* be32 */
TCA_FLOWER_KEY_ENC_IPV4_DST, /* be32 */
TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,/* be32 */
TCA_FLOWER_KEY_ENC_IPV6_SRC, /* struct in6_addr */
TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,/* struct in6_addr */
TCA_FLOWER_KEY_ENC_IPV6_DST, /* struct in6_addr */
TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,/* struct in6_addr */

__TCA_FLOWER_MAX,
};

Expand Down
41 changes: 41 additions & 0 deletions include/uapi/linux/tc_act/tc_tunnel_key.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2016, Amir Vadai <amir@vadai.me>
* Copyright (c) 2016, Mellanox Technologies. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/

#ifndef __LINUX_TC_TUNNEL_KEY_H
#define __LINUX_TC_TUNNEL_KEY_H

#include <linux/pkt_cls.h>

#define TCA_ACT_TUNNEL_KEY 17

#define TCA_TUNNEL_KEY_ACT_SET 1
#define TCA_TUNNEL_KEY_ACT_RELEASE 2

struct tc_tunnel_key {
tc_gen;
int t_action;
};

enum {
TCA_TUNNEL_KEY_UNSPEC,
TCA_TUNNEL_KEY_TM,
TCA_TUNNEL_KEY_PARMS,
TCA_TUNNEL_KEY_ENC_IPV4_SRC, /* be32 */
TCA_TUNNEL_KEY_ENC_IPV4_DST, /* be32 */
TCA_TUNNEL_KEY_ENC_IPV6_SRC, /* struct in6_addr */
TCA_TUNNEL_KEY_ENC_IPV6_DST, /* struct in6_addr */
TCA_TUNNEL_KEY_ENC_KEY_ID, /* be64 */
TCA_TUNNEL_KEY_PAD,
__TCA_TUNNEL_KEY_MAX,
};

#define TCA_TUNNEL_KEY_MAX (__TCA_TUNNEL_KEY_MAX - 1)

#endif
23 changes: 2 additions & 21 deletions net/ipv4/ip_gre.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,25 +246,6 @@ static void gre_err(struct sk_buff *skb, u32 info)
ipgre_err(skb, info, &tpi);
}

static __be64 key_to_tunnel_id(__be32 key)
{
#ifdef __BIG_ENDIAN
return (__force __be64)((__force u32)key);
#else
return (__force __be64)((__force u64)key << 32);
#endif
}

/* Returns the least-significant 32 bits of a __be64. */
static __be32 tunnel_id_to_key(__be64 x)
{
#ifdef __BIG_ENDIAN
return (__force __be32)x;
#else
return (__force __be32)((__force u64)x >> 32);
#endif
}

static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
{
Expand All @@ -290,7 +271,7 @@ static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
__be64 tun_id;

flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
tun_id = key_to_tunnel_id(tpi->key);
tun_id = key32_to_tunnel_id(tpi->key);
tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
if (!tun_dst)
return PACKET_REJECT;
Expand Down Expand Up @@ -446,7 +427,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,

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

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

Expand Down
11 changes: 11 additions & 0 deletions net/sched/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,17 @@ config NET_ACT_IFE
To compile this code as a module, choose M here: the
module will be called act_ife.

config NET_ACT_TUNNEL_KEY
tristate "IP tunnel metadata manipulation"
depends on NET_CLS_ACT
---help---
Say Y here to set/release ip tunnel metadata.

If unsure, say N.

To compile this code as a module, choose M here: the
module will be called act_tunnel_key.

config NET_IFE_SKBMARK
tristate "Support to encoding decoding skb mark on IFE action"
depends on NET_ACT_IFE
Expand Down
1 change: 1 addition & 0 deletions net/sched/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ obj-$(CONFIG_NET_ACT_CONNMARK) += act_connmark.o
obj-$(CONFIG_NET_ACT_IFE) += act_ife.o
obj-$(CONFIG_NET_IFE_SKBMARK) += act_meta_mark.o
obj-$(CONFIG_NET_IFE_SKBPRIO) += act_meta_skbprio.o
obj-$(CONFIG_NET_ACT_TUNNEL_KEY)+= act_tunnel_key.o
obj-$(CONFIG_NET_SCH_FIFO) += sch_fifo.o
obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o
obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o
Expand Down
Loading

0 comments on commit d1ba24f

Please sign in to comment.