This patch allows a host to be configured to respond to any address in a specified range as if it were local, without actually needing to configure the address on an interface. This is done through routing table configuration. For instance, to configure a host to respond to any address in 10.1/16 received on eth0 as a local address we can do: ip rule add from all iif eth0 lookup 200 ip route add local 10.1/16 dev lo proto kernel scope host src 127.0.0.1 table 200 This host is now reachable by any 10.1/16 address (route lookup on input for packets received on eth0 can find the route). On output, the rule will not be matched so that this host can still send packets to 10.1/16 (not sent on loopback). Presumably, external routing can be configured to make sense out of this. To make this work, we needed to modify the logic in finding the interface which is assigned a given source address for output (dev_ip_find). We perform a normal fib_lookup instead of just a lookup on the local table, and in the lookup we ignore the input interface for matching. This patch is useful to implement IP-anycast for subnets of virtual addresses. Signed-off-by: Tom Herbert <therbert@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
		
			
				
	
	
		
			119 lines
		
	
	
	
		
			2.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			119 lines
		
	
	
	
		
			2.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 *
 | 
						|
 *	Generic internet FLOW.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef _NET_FLOW_H
 | 
						|
#define _NET_FLOW_H
 | 
						|
 | 
						|
#include <linux/in6.h>
 | 
						|
#include <asm/atomic.h>
 | 
						|
 | 
						|
struct flowi {
 | 
						|
	int	oif;
 | 
						|
	int	iif;
 | 
						|
	__u32	mark;
 | 
						|
 | 
						|
	union {
 | 
						|
		struct {
 | 
						|
			__be32			daddr;
 | 
						|
			__be32			saddr;
 | 
						|
			__u8			tos;
 | 
						|
			__u8			scope;
 | 
						|
		} ip4_u;
 | 
						|
		
 | 
						|
		struct {
 | 
						|
			struct in6_addr		daddr;
 | 
						|
			struct in6_addr		saddr;
 | 
						|
			__be32			flowlabel;
 | 
						|
		} ip6_u;
 | 
						|
 | 
						|
		struct {
 | 
						|
			__le16			daddr;
 | 
						|
			__le16			saddr;
 | 
						|
			__u8			scope;
 | 
						|
		} dn_u;
 | 
						|
	} nl_u;
 | 
						|
#define fld_dst		nl_u.dn_u.daddr
 | 
						|
#define fld_src		nl_u.dn_u.saddr
 | 
						|
#define fld_scope	nl_u.dn_u.scope
 | 
						|
#define fl6_dst		nl_u.ip6_u.daddr
 | 
						|
#define fl6_src		nl_u.ip6_u.saddr
 | 
						|
#define fl6_flowlabel	nl_u.ip6_u.flowlabel
 | 
						|
#define fl4_dst		nl_u.ip4_u.daddr
 | 
						|
#define fl4_src		nl_u.ip4_u.saddr
 | 
						|
#define fl4_tos		nl_u.ip4_u.tos
 | 
						|
#define fl4_scope	nl_u.ip4_u.scope
 | 
						|
 | 
						|
	__u8	proto;
 | 
						|
	__u8	flags;
 | 
						|
#define FLOWI_FLAG_ANYSRC 0x01
 | 
						|
#define FLOWI_FLAG_MATCH_ANY_IIF 0x02
 | 
						|
	union {
 | 
						|
		struct {
 | 
						|
			__be16	sport;
 | 
						|
			__be16	dport;
 | 
						|
		} ports;
 | 
						|
 | 
						|
		struct {
 | 
						|
			__u8	type;
 | 
						|
			__u8	code;
 | 
						|
		} icmpt;
 | 
						|
 | 
						|
		struct {
 | 
						|
			__le16	sport;
 | 
						|
			__le16	dport;
 | 
						|
		} dnports;
 | 
						|
 | 
						|
		__be32		spi;
 | 
						|
 | 
						|
		struct {
 | 
						|
			__u8	type;
 | 
						|
		} mht;
 | 
						|
	} uli_u;
 | 
						|
#define fl_ip_sport	uli_u.ports.sport
 | 
						|
#define fl_ip_dport	uli_u.ports.dport
 | 
						|
#define fl_icmp_type	uli_u.icmpt.type
 | 
						|
#define fl_icmp_code	uli_u.icmpt.code
 | 
						|
#define fl_ipsec_spi	uli_u.spi
 | 
						|
#define fl_mh_type	uli_u.mht.type
 | 
						|
	__u32           secid;	/* used by xfrm; see secid.txt */
 | 
						|
} __attribute__((__aligned__(BITS_PER_LONG/8)));
 | 
						|
 | 
						|
#define FLOW_DIR_IN	0
 | 
						|
#define FLOW_DIR_OUT	1
 | 
						|
#define FLOW_DIR_FWD	2
 | 
						|
 | 
						|
struct net;
 | 
						|
struct sock;
 | 
						|
struct flow_cache_ops;
 | 
						|
 | 
						|
struct flow_cache_object {
 | 
						|
	const struct flow_cache_ops *ops;
 | 
						|
};
 | 
						|
 | 
						|
struct flow_cache_ops {
 | 
						|
	struct flow_cache_object *(*get)(struct flow_cache_object *);
 | 
						|
	int (*check)(struct flow_cache_object *);
 | 
						|
	void (*delete)(struct flow_cache_object *);
 | 
						|
};
 | 
						|
 | 
						|
typedef struct flow_cache_object *(*flow_resolve_t)(
 | 
						|
		struct net *net, struct flowi *key, u16 family,
 | 
						|
		u8 dir, struct flow_cache_object *oldobj, void *ctx);
 | 
						|
 | 
						|
extern struct flow_cache_object *flow_cache_lookup(
 | 
						|
		struct net *net, struct flowi *key, u16 family,
 | 
						|
		u8 dir, flow_resolve_t resolver, void *ctx);
 | 
						|
 | 
						|
extern void flow_cache_flush(void);
 | 
						|
extern atomic_t flow_cache_genid;
 | 
						|
 | 
						|
static inline int flow_cache_uli_match(struct flowi *fl1, struct flowi *fl2)
 | 
						|
{
 | 
						|
	return (fl1->proto == fl2->proto &&
 | 
						|
		!memcmp(&fl1->uli_u, &fl2->uli_u, sizeof(fl1->uli_u)));
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |