|
@@ -276,6 +276,8 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|
|
{
|
|
|
int err = 0;
|
|
|
int skb_len;
|
|
|
+ unsigned long flags;
|
|
|
+ struct sk_buff_head *list = &sk->sk_receive_queue;
|
|
|
|
|
|
/* Cast sk->rcvbuf to unsigned... It's pointless, but reduces
|
|
|
number of warnings when compiling with -W --ANK
|
|
@@ -305,7 +307,10 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|
|
*/
|
|
|
skb_len = skb->len;
|
|
|
|
|
|
- skb_queue_tail(&sk->sk_receive_queue, skb);
|
|
|
+ spin_lock_irqsave(&list->lock, flags);
|
|
|
+ skb->dropcount = atomic_read(&sk->sk_drops);
|
|
|
+ __skb_queue_tail(list, skb);
|
|
|
+ spin_unlock_irqrestore(&list->lock, flags);
|
|
|
|
|
|
if (!sock_flag(sk, SOCK_DEAD))
|
|
|
sk->sk_data_ready(sk, skb_len);
|
|
@@ -702,6 +707,12 @@ set_rcvbuf:
|
|
|
|
|
|
/* We implement the SO_SNDLOWAT etc to
|
|
|
not be settable (1003.1g 5.3) */
|
|
|
+ case SO_RXQ_OVFL:
|
|
|
+ if (valbool)
|
|
|
+ sock_set_flag(sk, SOCK_RXQ_OVFL);
|
|
|
+ else
|
|
|
+ sock_reset_flag(sk, SOCK_RXQ_OVFL);
|
|
|
+ break;
|
|
|
default:
|
|
|
ret = -ENOPROTOOPT;
|
|
|
break;
|
|
@@ -901,6 +912,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
|
|
|
v.val = sk->sk_mark;
|
|
|
break;
|
|
|
|
|
|
+ case SO_RXQ_OVFL:
|
|
|
+ v.val = !!sock_flag(sk, SOCK_RXQ_OVFL);
|
|
|
+ break;
|
|
|
+
|
|
|
default:
|
|
|
return -ENOPROTOOPT;
|
|
|
}
|