aboutsummaryrefslogtreecommitdiffstats
path: root/net/packet/af_packet.c
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2009-10-02 02:56:41 -0400
committerDavid S. Miller <davem@davemloft.net>2009-10-05 03:21:55 -0400
commit977750076d98c7ff6cbda51858bb5a5894a9d9ab (patch)
tree71b2fca8c6739e7d177996354b99504702a1b946 /net/packet/af_packet.c
parent69ef9694099802f7feeb23182dfb869e7c5f76f0 (diff)
af_packet: add interframe drop cmsg (v6)
Add Ancilliary data to better represent loss information I've had a few requests recently to provide more detail regarding frame loss during an AF_PACKET packet capture session. Specifically the requestors want to see where in a packet sequence frames were lost, i.e. they want to see that 40 frames were lost between frames 302 and 303 in a packet capture file. In order to do this we need: 1) The kernel to export this data to user space 2) The applications to make use of it This patch addresses item (1). It does this by doing the following: A) Anytime we drop a frame for which we would increment po->stats.tp_drops, we also no increment a stats called po->stats.tp_gap. B) Every time we successfully enqueue a frame to sk_receive_queue, we record the value of po->stats.tp_gap in skb->mark. skb->cb would nominally be the place to record this, but since all the space there is used up, we're overloading skb->mark. Its safe to do since any enqueued packet is guaranteed to be unshared at this point, and skb->mark isn't used for anything else in the rx path to the application. After we record tp_gap in the skb, we zero po->stats.tp_gap. This allows us to keep a counter of the number of frames lost between any two enqueued packets C) When the application goes to dequeue a frame from the packet socket, we look at skb->mark for that frame. If it is non-zero, we add a cmsg chunk to the msghdr of level SOL_PACKET and type PACKET_GAPDATA. Its a 32 bit integer that represents the number of frames lost between this packet and the last previous frame received. Note there is a chance that if there is frame loss after a receive, and then the socket is closed, some gap data might be lost. This is covered by the use of the PACKET_AUXDATA socket option, which gives total loss data. With a bit of math, the final gap can be determined that way. I've tested this patch myself, and it works well. Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> include/linux/if_packet.h | 2 ++ net/packet/af_packet.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r--net/packet/af_packet.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index d7ecca0a0c07..d398a9bf6903 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -524,6 +524,31 @@ static inline unsigned int run_filter(struct sk_buff *skb, struct sock *sk,
524} 524}
525 525
526/* 526/*
527 * If we've lost frames since the last time we queued one to the
528 * sk_receive_queue, we need to record it here.
529 * This must be called under the protection of the socket lock
530 * to prevent racing with other softirqs and user space
531 */
532static inline void record_packet_gap(struct sk_buff *skb,
533 struct packet_sock *po)
534{
535 /*
536 * We overload the mark field here, since we're about
537 * to enqueue to a receive queue and no body else will
538 * use this field at this point
539 */
540 skb->mark = po->stats.tp_gap;
541 po->stats.tp_gap = 0;
542 return;
543
544}
545
546static inline __u32 check_packet_gap(struct sk_buff *skb)
547{
548 return skb->mark;
549}
550
551/*
527 This function makes lazy skb cloning in hope that most of packets 552 This function makes lazy skb cloning in hope that most of packets
528 are discarded by BPF. 553 are discarded by BPF.
529 554
@@ -626,6 +651,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
626 651
627 spin_lock(&sk->sk_receive_queue.lock); 652 spin_lock(&sk->sk_receive_queue.lock);
628 po->stats.tp_packets++; 653 po->stats.tp_packets++;
654 record_packet_gap(skb, po);
629 __skb_queue_tail(&sk->sk_receive_queue, skb); 655 __skb_queue_tail(&sk->sk_receive_queue, skb);
630 spin_unlock(&sk->sk_receive_queue.lock); 656 spin_unlock(&sk->sk_receive_queue.lock);
631 sk->sk_data_ready(sk, skb->len); 657 sk->sk_data_ready(sk, skb->len);
@@ -634,6 +660,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
634drop_n_acct: 660drop_n_acct:
635 spin_lock(&sk->sk_receive_queue.lock); 661 spin_lock(&sk->sk_receive_queue.lock);
636 po->stats.tp_drops++; 662 po->stats.tp_drops++;
663 po->stats.tp_gap++;
637 spin_unlock(&sk->sk_receive_queue.lock); 664 spin_unlock(&sk->sk_receive_queue.lock);
638 665
639drop_n_restore: 666drop_n_restore:
@@ -811,6 +838,7 @@ drop:
811 838
812ring_is_full: 839ring_is_full:
813 po->stats.tp_drops++; 840 po->stats.tp_drops++;
841 po->stats.tp_gap++;
814 spin_unlock(&sk->sk_receive_queue.lock); 842 spin_unlock(&sk->sk_receive_queue.lock);
815 843
816 sk->sk_data_ready(sk, 0); 844 sk->sk_data_ready(sk, 0);
@@ -1418,6 +1446,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
1418 struct sk_buff *skb; 1446 struct sk_buff *skb;
1419 int copied, err; 1447 int copied, err;
1420 struct sockaddr_ll *sll; 1448 struct sockaddr_ll *sll;
1449 __u32 gap;
1421 1450
1422 err = -EINVAL; 1451 err = -EINVAL;
1423 if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT)) 1452 if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT))
@@ -1496,6 +1525,10 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
1496 put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux); 1525 put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux);
1497 } 1526 }
1498 1527
1528 gap = check_packet_gap(skb);
1529 if (gap)
1530 put_cmsg(msg, SOL_PACKET, PACKET_GAPDATA, sizeof(__u32), &gap);
1531
1499 /* 1532 /*
1500 * Free or return the buffer as appropriate. Again this 1533 * Free or return the buffer as appropriate. Again this
1501 * hides all the races and re-entrancy issues from us. 1534 * hides all the races and re-entrancy issues from us.