route: Extend flow representation with tunnel key

Add a new flowi_tunnel structure which is a subset of ip_tunnel_key to
allow routes to match on tunnel metadata. For now, the tunnel id is
added to flowi_tunnel which allows for routes to be bound to specific
virtual tunnels.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Thomas Graf 2015-07-21 10:43:59 +02:00 committed by David S. Miller
parent ee122c79d4
commit 1b7179d3ad
3 changed files with 18 additions and 0 deletions

View File

@ -19,6 +19,10 @@
#define LOOPBACK_IFINDEX 1 #define LOOPBACK_IFINDEX 1
struct flowi_tunnel {
__be64 tun_id;
};
struct flowi_common { struct flowi_common {
int flowic_oif; int flowic_oif;
int flowic_iif; int flowic_iif;
@ -30,6 +34,7 @@ struct flowi_common {
#define FLOWI_FLAG_ANYSRC 0x01 #define FLOWI_FLAG_ANYSRC 0x01
#define FLOWI_FLAG_KNOWN_NH 0x02 #define FLOWI_FLAG_KNOWN_NH 0x02
__u32 flowic_secid; __u32 flowic_secid;
struct flowi_tunnel flowic_tun_key;
}; };
union flowi_uli { union flowi_uli {
@ -66,6 +71,7 @@ struct flowi4 {
#define flowi4_proto __fl_common.flowic_proto #define flowi4_proto __fl_common.flowic_proto
#define flowi4_flags __fl_common.flowic_flags #define flowi4_flags __fl_common.flowic_flags
#define flowi4_secid __fl_common.flowic_secid #define flowi4_secid __fl_common.flowic_secid
#define flowi4_tun_key __fl_common.flowic_tun_key
/* (saddr,daddr) must be grouped, same order as in IP header */ /* (saddr,daddr) must be grouped, same order as in IP header */
__be32 saddr; __be32 saddr;
@ -95,6 +101,7 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
fl4->flowi4_proto = proto; fl4->flowi4_proto = proto;
fl4->flowi4_flags = flags; fl4->flowi4_flags = flags;
fl4->flowi4_secid = 0; fl4->flowi4_secid = 0;
fl4->flowi4_tun_key.tun_id = 0;
fl4->daddr = daddr; fl4->daddr = daddr;
fl4->saddr = saddr; fl4->saddr = saddr;
fl4->fl4_dport = dport; fl4->fl4_dport = dport;
@ -165,6 +172,7 @@ struct flowi {
#define flowi_proto u.__fl_common.flowic_proto #define flowi_proto u.__fl_common.flowic_proto
#define flowi_flags u.__fl_common.flowic_flags #define flowi_flags u.__fl_common.flowic_flags
#define flowi_secid u.__fl_common.flowic_secid #define flowi_secid u.__fl_common.flowic_secid
#define flowi_tun_key u.__fl_common.flowic_tun_key
} __attribute__((__aligned__(BITS_PER_LONG/8))); } __attribute__((__aligned__(BITS_PER_LONG/8)));
static inline struct flowi *flowi4_to_flowi(struct flowi4 *fl4) static inline struct flowi *flowi4_to_flowi(struct flowi4 *fl4)

View File

@ -280,6 +280,7 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb)
fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
fl4.flowi4_scope = scope; fl4.flowi4_scope = scope;
fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0; fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0;
fl4.flowi4_tun_key.tun_id = 0;
if (!fib_lookup(net, &fl4, &res, 0)) if (!fib_lookup(net, &fl4, &res, 0))
return FIB_RES_PREFSRC(net, res); return FIB_RES_PREFSRC(net, res);
} else { } else {
@ -313,6 +314,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
fl4.saddr = dst; fl4.saddr = dst;
fl4.flowi4_tos = tos; fl4.flowi4_tos = tos;
fl4.flowi4_scope = RT_SCOPE_UNIVERSE; fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
fl4.flowi4_tun_key.tun_id = 0;
no_addr = idev->ifa_list == NULL; no_addr = idev->ifa_list == NULL;

View File

@ -91,6 +91,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/jhash.h> #include <linux/jhash.h>
#include <net/dst.h> #include <net/dst.h>
#include <net/dst_metadata.h>
#include <net/net_namespace.h> #include <net/net_namespace.h>
#include <net/protocol.h> #include <net/protocol.h>
#include <net/ip.h> #include <net/ip.h>
@ -110,6 +111,7 @@
#include <linux/kmemleak.h> #include <linux/kmemleak.h>
#endif #endif
#include <net/secure_seq.h> #include <net/secure_seq.h>
#include <net/ip_tunnels.h>
#define RT_FL_TOS(oldflp4) \ #define RT_FL_TOS(oldflp4) \
((oldflp4)->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK)) ((oldflp4)->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))
@ -1673,6 +1675,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
{ {
struct fib_result res; struct fib_result res;
struct in_device *in_dev = __in_dev_get_rcu(dev); struct in_device *in_dev = __in_dev_get_rcu(dev);
struct ip_tunnel_info *tun_info;
struct flowi4 fl4; struct flowi4 fl4;
unsigned int flags = 0; unsigned int flags = 0;
u32 itag = 0; u32 itag = 0;
@ -1690,6 +1693,11 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
by fib_lookup. by fib_lookup.
*/ */
tun_info = skb_tunnel_info(skb);
if (tun_info && tun_info->mode == IP_TUNNEL_INFO_RX)
fl4.flowi4_tun_key.tun_id = tun_info->key.tun_id;
else
fl4.flowi4_tun_key.tun_id = 0;
skb_dst_drop(skb); skb_dst_drop(skb);
if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr)) if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr))