diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 14:43:13 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 14:43:13 -0700 | 
| commit | 951cc93a7493a81a47e20231441bc6cf17c98a37 (patch) | |
| tree | f53934f0f225e0215a85c8c59af4c6513e89e3f1 /net/ipv4/route.c | |
| parent | a7e1aabb28e8154ce987b622fd78d80a1ca39361 (diff) | |
| parent | 415b3334a21aa67806c52d1acf4e72e14f7f402f (diff) | |
| download | olio-linux-3.10-951cc93a7493a81a47e20231441bc6cf17c98a37.tar.xz olio-linux-3.10-951cc93a7493a81a47e20231441bc6cf17c98a37.zip  | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1287 commits)
  icmp: Fix regression in nexthop resolution during replies.
  net: Fix ppc64 BPF JIT dependencies.
  acenic: include NET_SKB_PAD headroom to incoming skbs
  ixgbe: convert to ndo_fix_features
  ixgbe: only enable WoL for magic packet by default
  ixgbe: remove ifdef check for non-existent define
  ixgbe: Pass staterr instead of re-reading status and error bits from descriptor
  ixgbe: Move interrupt related values out of ring and into q_vector
  ixgbe: add structure for containing RX/TX rings to q_vector
  ixgbe: inline the ixgbe_maybe_stop_tx function
  ixgbe: Update ATR to use recorded TX queues instead of CPU for routing
  igb: Fix for DH89xxCC near end loopback test
  e1000: always call e1000_check_for_link() on e1000_ce4100 MACs.
  netxen: add fw version compatibility check
  be2net: request native mode each time the card is reset
  ipv4: Constrain UFO fragment sizes to multiples of 8 bytes
  virtio_net: Fix panic in virtnet_remove
  ipv6: make fragment identifications less predictable
  ipv6: unshare inetpeers
  can: make function can_get_bittiming static
  ...
Diffstat (limited to 'net/ipv4/route.c')
| -rw-r--r-- | net/ipv4/route.c | 94 | 
1 files changed, 66 insertions, 28 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index aa13ef10511..33137307d52 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -108,6 +108,7 @@  #ifdef CONFIG_SYSCTL  #include <linux/sysctl.h>  #endif +#include <net/atmclip.h>  #define RT_FL_TOS(oldflp4) \      ((u32)(oldflp4->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))) @@ -184,6 +185,8 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old)  	return p;  } +static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr); +  static struct dst_ops ipv4_dst_ops = {  	.family =		AF_INET,  	.protocol =		cpu_to_be16(ETH_P_IP), @@ -198,6 +201,7 @@ static struct dst_ops ipv4_dst_ops = {  	.link_failure =		ipv4_link_failure,  	.update_pmtu =		ip_rt_update_pmtu,  	.local_out =		__ip_local_out, +	.neigh_lookup =		ipv4_neigh_lookup,  };  #define ECN_OR_COST(class)	TC_PRIO_##class @@ -411,8 +415,10 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)  			   "HHUptod\tSpecDst");  	else {  		struct rtable *r = v; +		struct neighbour *n;  		int len; +		n = dst_get_neighbour(&r->dst);  		seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t"  			      "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n",  			r->dst.dev ? r->dst.dev->name : "*", @@ -425,9 +431,8 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)  			(int)((dst_metric(&r->dst, RTAX_RTT) >> 3) +  			      dst_metric(&r->dst, RTAX_RTTVAR)),  			r->rt_key_tos, -			r->dst.hh ? atomic_read(&r->dst.hh->hh_refcnt) : -1, -			r->dst.hh ? (r->dst.hh->hh_output == -				       dev_queue_xmit) : 0, +			-1, +			(n && (n->nud_state & NUD_CONNECTED)) ? 1 : 0,  			r->rt_spec_dst, &len);  		seq_printf(seq, "%*s\n", 127 - len, ""); @@ -1006,6 +1011,37 @@ static int slow_chain_length(const struct rtable *head)  	return length >> FRACT_BITS;  } +static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr) +{ +	struct neigh_table *tbl = &arp_tbl; +	static const __be32 inaddr_any = 0; +	struct net_device *dev = dst->dev; +	const __be32 *pkey = daddr; +	struct neighbour *n; + +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) +	if (dev->type == ARPHRD_ATM) +		tbl = clip_tbl_hook; +#endif +	if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) +		pkey = &inaddr_any; + +	n = __ipv4_neigh_lookup(tbl, dev, *(__force u32 *)pkey); +	if (n) +		return n; +	return neigh_create(tbl, pkey, dev); +} + +static int rt_bind_neighbour(struct rtable *rt) +{ +	struct neighbour *n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); +	if (IS_ERR(n)) +		return PTR_ERR(n); +	dst_set_neighbour(&rt->dst, n); + +	return 0; +} +  static struct rtable *rt_intern_hash(unsigned hash, struct rtable *rt,  				     struct sk_buff *skb, int ifindex)  { @@ -1042,7 +1078,7 @@ restart:  		rt->dst.flags |= DST_NOCACHE;  		if (rt->rt_type == RTN_UNICAST || rt_is_output_route(rt)) { -			int err = arp_bind_neighbour(&rt->dst); +			int err = rt_bind_neighbour(rt);  			if (err) {  				if (net_ratelimit())  					printk(KERN_WARNING @@ -1138,7 +1174,7 @@ restart:  	   route or unicast forwarding path.  	 */  	if (rt->rt_type == RTN_UNICAST || rt_is_output_route(rt)) { -		int err = arp_bind_neighbour(&rt->dst); +		int err = rt_bind_neighbour(rt);  		if (err) {  			spin_unlock_bh(rt_hash_lock_addr(hash)); @@ -1439,20 +1475,20 @@ static int ip_error(struct sk_buff *skb)  	int code;  	switch (rt->dst.error) { -		case EINVAL: -		default: -			goto out; -		case EHOSTUNREACH: -			code = ICMP_HOST_UNREACH; -			break; -		case ENETUNREACH: -			code = ICMP_NET_UNREACH; -			IP_INC_STATS_BH(dev_net(rt->dst.dev), -					IPSTATS_MIB_INNOROUTES); -			break; -		case EACCES: -			code = ICMP_PKT_FILTERED; -			break; +	case EINVAL: +	default: +		goto out; +	case EHOSTUNREACH: +		code = ICMP_HOST_UNREACH; +		break; +	case ENETUNREACH: +		code = ICMP_NET_UNREACH; +		IP_INC_STATS_BH(dev_net(rt->dst.dev), +				IPSTATS_MIB_INNOROUTES); +		break; +	case EACCES: +		code = ICMP_PKT_FILTERED; +		break;  	}  	if (!rt->peer) @@ -1592,23 +1628,24 @@ static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)  {  	struct rtable *rt = (struct rtable *) dst;  	__be32 orig_gw = rt->rt_gateway; +	struct neighbour *n;  	dst_confirm(&rt->dst); -	neigh_release(rt->dst.neighbour); -	rt->dst.neighbour = NULL; +	neigh_release(dst_get_neighbour(&rt->dst)); +	dst_set_neighbour(&rt->dst, NULL);  	rt->rt_gateway = peer->redirect_learned.a4; -	if (arp_bind_neighbour(&rt->dst) || -	    !(rt->dst.neighbour->nud_state & NUD_VALID)) { -		if (rt->dst.neighbour) -			neigh_event_send(rt->dst.neighbour, NULL); +	rt_bind_neighbour(rt); +	n = dst_get_neighbour(&rt->dst); +	if (!n || !(n->nud_state & NUD_VALID)) { +		if (n) +			neigh_event_send(n, NULL);  		rt->rt_gateway = orig_gw;  		return -EAGAIN;  	} else {  		rt->rt_flags |= RTCF_REDIRECTED; -		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, -					rt->dst.neighbour); +		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);  	}  	return 0;  } @@ -2708,6 +2745,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {  	.default_advmss		=	ipv4_default_advmss,  	.update_pmtu		=	ipv4_rt_blackhole_update_pmtu,  	.cow_metrics		=	ipv4_rt_blackhole_cow_metrics, +	.neigh_lookup		=	ipv4_neigh_lookup,  };  struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig) @@ -3303,7 +3341,7 @@ int __init ip_rt_init(void)  	xfrm_init();  	xfrm4_init(ip_rt_max_size);  #endif -	rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL); +	rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL, NULL);  #ifdef CONFIG_SYSCTL  	register_pernet_subsys(&sysctl_route_ops);  |