diff options
Diffstat (limited to 'net/ipv6/udp.c')
| -rw-r--r-- | net/ipv6/udp.c | 53 | 
1 files changed, 30 insertions, 23 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index dd309626ae9..d1477b350f7 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -7,8 +7,6 @@   *   *	Based on linux/ipv4/udp.c   * - *	$Id: udp.c,v 1.65 2002/02/01 22:01:04 davem Exp $ - *   *	Fixes:   *	Hideaki YOSHIFUJI	:	sin6_scope_id support   *	YOSHIFUJI Hideaki @USAGI and:	Support IPV6_V6ONLY socket option, which @@ -67,7 +65,7 @@ static struct sock *__udp6_lib_lookup(struct net *net,  	int badness = -1;  	read_lock(&udp_hash_lock); -	sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { +	sk_for_each(sk, node, &udptable[udp_hashfn(net, hnum)]) {  		struct inet_sock *inet = inet_sk(sk);  		if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum && @@ -168,7 +166,8 @@ try_again:  		goto out_free;  	if (!peeked) -		UDP6_INC_STATS_USER(UDP_MIB_INDATAGRAMS, is_udplite); +		UDP6_INC_STATS_USER(sock_net(sk), +				UDP_MIB_INDATAGRAMS, is_udplite);  	sock_recv_timestamp(msg, sk, skb); @@ -215,7 +214,7 @@ out:  csum_copy_err:  	lock_sock(sk);  	if (!skb_kill_datagram(sk, skb, flags)) -		UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite); +		UDP6_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite);  	release_sock(sk);  	if (flags & MSG_DONTWAIT) @@ -299,14 +298,17 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)  	if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) {  		/* Note that an ENOMEM error is charged twice */ -		if (rc == -ENOMEM) -			UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, is_udplite); +		if (rc == -ENOMEM) { +			UDP6_INC_STATS_BH(sock_net(sk), +					UDP_MIB_RCVBUFERRORS, is_udplite); +			atomic_inc(&sk->sk_drops); +		}  		goto drop;  	}  	return 0;  drop: -	UDP6_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite); +	UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite);  	kfree_skb(skb);  	return -1;  } @@ -355,15 +357,16 @@ static struct sock *udp_v6_mcast_next(struct sock *sk,   * Note: called only from the BH handler context,   * so we don't need to lock the hashes.   */ -static int __udp6_lib_mcast_deliver(struct sk_buff *skb, struct in6_addr *saddr, -			   struct in6_addr *daddr, struct hlist_head udptable[]) +static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, +		struct in6_addr *saddr, struct in6_addr *daddr, +		struct hlist_head udptable[])  {  	struct sock *sk, *sk2;  	const struct udphdr *uh = udp_hdr(skb);  	int dif;  	read_lock(&udp_hash_lock); -	sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]); +	sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]);  	dif = inet6_iif(skb);  	sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);  	if (!sk) { @@ -437,6 +440,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],  	struct net_device *dev = skb->dev;  	struct in6_addr *saddr, *daddr;  	u32 ulen = 0; +	struct net *net = dev_net(skb->dev);  	if (!pskb_may_pull(skb, sizeof(struct udphdr)))  		goto short_packet; @@ -475,7 +479,8 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],  	 *	Multicast receive code  	 */  	if (ipv6_addr_is_multicast(daddr)) -		return __udp6_lib_mcast_deliver(skb, saddr, daddr, udptable); +		return __udp6_lib_mcast_deliver(net, skb, +				saddr, daddr, udptable);  	/* Unicast */ @@ -483,7 +488,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],  	 * check socket cache ... must talk to Alan about his plans  	 * for sock caches... i'll skip this for now.  	 */ -	sk = __udp6_lib_lookup(dev_net(skb->dev), saddr, uh->source, +	sk = __udp6_lib_lookup(net, saddr, uh->source,  			       daddr, uh->dest, inet6_iif(skb), udptable);  	if (sk == NULL) { @@ -492,7 +497,8 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],  		if (udp_lib_checksum_complete(skb))  			goto discard; -		UDP6_INC_STATS_BH(UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); +		UDP6_INC_STATS_BH(net, UDP_MIB_NOPORTS, +				proto == IPPROTO_UDPLITE);  		icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, dev); @@ -517,7 +523,7 @@ short_packet:  		       ulen, skb->len);  discard: -	UDP6_INC_STATS_BH(UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); +	UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE);  	kfree_skb(skb);  	return 0;  } @@ -587,7 +593,8 @@ out:  	up->len = 0;  	up->pending = 0;  	if (!err) -		UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS, is_udplite); +		UDP6_INC_STATS_USER(sock_net(sk), +				UDP_MIB_OUTDATAGRAMS, is_udplite);  	return err;  } @@ -869,7 +876,8 @@ out:  	 * seems like overkill.  	 */  	if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { -		UDP6_INC_STATS_USER(UDP_MIB_SNDBUFERRORS, is_udplite); +		UDP6_INC_STATS_USER(sock_net(sk), +				UDP_MIB_SNDBUFERRORS, is_udplite);  	}  	return err; @@ -881,15 +889,13 @@ do_confirm:  	goto out;  } -int udpv6_destroy_sock(struct sock *sk) +void udpv6_destroy_sock(struct sock *sk)  {  	lock_sock(sk);  	udp_v6_flush_pending_frames(sk);  	release_sock(sk);  	inet6_destroy_sock(sk); - -	return 0;  }  /* @@ -955,7 +961,7 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket  	srcp  = ntohs(inet->sport);  	seq_printf(seq,  		   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " -		   "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p\n", +		   "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n",  		   bucket,  		   src->s6_addr32[0], src->s6_addr32[1],  		   src->s6_addr32[2], src->s6_addr32[3], srcp, @@ -967,7 +973,8 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket  		   0, 0L, 0,  		   sock_i_uid(sp), 0,  		   sock_i_ino(sp), -		   atomic_read(&sp->sk_refcnt), sp); +		   atomic_read(&sp->sk_refcnt), sp, +		   atomic_read(&sp->sk_drops));  }  int udp6_seq_show(struct seq_file *seq, void *v) @@ -978,7 +985,7 @@ int udp6_seq_show(struct seq_file *seq, void *v)  			   "local_address                         "  			   "remote_address                        "  			   "st tx_queue rx_queue tr tm->when retrnsmt" -			   "   uid  timeout inode\n"); +			   "   uid  timeout inode ref pointer drops\n");  	else  		udp6_sock_seq_show(seq, v, ((struct udp_iter_state *)seq->private)->bucket);  	return 0;  |