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

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

Merge branch 'redirect_via_sock'



As described in my patch series from the other day, we need to
rearrange redirect handling so that the local initiators of packets
(sockets, tunnels, xfrms, etc.) that implement the protocols compute
the route and pass this down into the ipv4/ipv6 routing code.

These changes here do so by implementing a new dst_ops->redirect
method.

No more do we have this funny code that tries several different sets
of routing keys to try and figure out which route the redirect should
actually be applied to.

No more do we have the problem wherein TOS rewriting causes problems
for us.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 46d3ceab 1ed5c48f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ struct dst_ops {
	struct dst_entry *	(*negative_advice)(struct dst_entry *);
	void			(*link_failure)(struct sk_buff *);
	void			(*update_pmtu)(struct dst_entry *dst, u32 mtu);
	void			(*redirect)(struct dst_entry *dst, struct sk_buff *skb);
	int			(*local_out)(struct sk_buff *skb);
	struct neighbour *	(*neigh_lookup)(const struct dst_entry *dst,
						struct sk_buff *skb,
+2 −7
Original line number Diff line number Diff line
@@ -133,17 +133,12 @@ extern int rt6_route_rcv(struct net_device *dev,
					      u8 *opt, int len,
					      const struct in6_addr *gwaddr);

extern void			rt6_redirect(const struct in6_addr *dest,
					     const struct in6_addr *src,
					     const struct in6_addr *saddr,
					     struct neighbour *neigh,
					     u8 *lladdr,
					     int on_link);

extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
			    int oif, u32 mark);
extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk,
			       __be32 mtu);
extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);

struct netlink_callback;

+2 −0
Original line number Diff line number Diff line
@@ -251,6 +251,8 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl)
		atomic_dec(&fl->users);
}

extern void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info);

extern int 			ip6_ra_control(struct sock *sk, int sel);

extern int			ipv6_parse_hopopts(struct sk_buff *skb);
+50 −0
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ enum {
#include <linux/icmpv6.h>
#include <linux/in6.h>
#include <linux/types.h>
#include <linux/if_arp.h>
#include <linux/netdevice.h>

#include <net/neighbour.h>

@@ -80,6 +82,54 @@ struct nd_opt_hdr {
	__u8		nd_opt_len;
} __packed;

/* ND options */
struct ndisc_options {
	struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX];
#ifdef CONFIG_IPV6_ROUTE_INFO
	struct nd_opt_hdr *nd_opts_ri;
	struct nd_opt_hdr *nd_opts_ri_end;
#endif
	struct nd_opt_hdr *nd_useropts;
	struct nd_opt_hdr *nd_useropts_end;
};

#define nd_opts_src_lladdr	nd_opt_array[ND_OPT_SOURCE_LL_ADDR]
#define nd_opts_tgt_lladdr	nd_opt_array[ND_OPT_TARGET_LL_ADDR]
#define nd_opts_pi		nd_opt_array[ND_OPT_PREFIX_INFO]
#define nd_opts_pi_end		nd_opt_array[__ND_OPT_PREFIX_INFO_END]
#define nd_opts_rh		nd_opt_array[ND_OPT_REDIRECT_HDR]
#define nd_opts_mtu		nd_opt_array[ND_OPT_MTU]

#define NDISC_OPT_SPACE(len) (((len)+2+7)&~7)

extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
						 struct ndisc_options *ndopts);

/*
 * Return the padding between the option length and the start of the
 * link addr.  Currently only IP-over-InfiniBand needs this, although
 * if RFC 3831 IPv6-over-Fibre Channel is ever implemented it may
 * also need a pad of 2.
 */
static int ndisc_addr_option_pad(unsigned short type)
{
	switch (type) {
	case ARPHRD_INFINIBAND: return 2;
	default:                return 0;
	}
}

static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p,
				      struct net_device *dev)
{
	u8 *lladdr = (u8 *)(p + 1);
	int lladdrlen = p->nd_opt_len << 3;
	int prepad = ndisc_addr_option_pad(dev->type);
	if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad))
		return NULL;
	return lladdr + prepad;
}

static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, __u32 *hash_rnd)
{
	const u32 *p32 = pkey;
+3 −2
Original line number Diff line number Diff line
@@ -108,8 +108,6 @@ extern struct ip_rt_acct __percpu *ip_rt_acct;

struct in_device;
extern int		ip_rt_init(void);
extern void		ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw,
				       __be32 src, struct net_device *dev);
extern void		rt_cache_flush(struct net *net, int how);
extern void		rt_cache_flush_batch(struct net *net);
extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp);
@@ -181,6 +179,9 @@ static inline int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 s
extern void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
			     int oif, u32 mark, u8 protocol, int flow_flags);
extern void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu);
extern void ipv4_redirect(struct sk_buff *skb, struct net *net,
			  int oif, u32 mark, u8 protocol, int flow_flags);
extern void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk);
extern void ip_rt_send_redirect(struct sk_buff *skb);

extern unsigned int		inet_addr_type(struct net *net, __be32 addr);
Loading