Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1ba24fe authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
parents e808bb6e d0f6dd8a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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;
+39 −13
Original line number Diff line number Diff line
@@ -112,12 +112,13 @@ 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,
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);
@@ -125,17 +126,30 @@ static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb,
		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 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)
{
	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
	struct metadata_dst *tun_dst;
	struct ip_tunnel_info *info;

@@ -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 −0
Original line number Diff line number Diff line
@@ -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);
+30 −0
Original line number Diff line number Diff line
/*
 * 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 */
+0 −18
Original line number Diff line number Diff line
@@ -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;
Loading