diff options
Diffstat (limited to 'net/packet')
-rw-r--r-- | net/packet/af_packet.c | 19 | ||||
-rw-r--r-- | net/packet/internal.h | 3 |
2 files changed, 21 insertions, 1 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8f0156b10f8d..31d58565726c 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1395,7 +1395,7 @@ static unsigned int fanout_demux_rollover(struct packet_fanout *f, unsigned int num) { struct packet_sock *po, *po_next; - unsigned int i, j, room; + unsigned int i, j, room = ROOM_NONE; po = pkt_sk(f->arr[idx]); @@ -1413,6 +1413,9 @@ static unsigned int fanout_demux_rollover(struct packet_fanout *f, packet_rcv_has_room(po_next, skb) == ROOM_NORMAL) { if (i != j) po->rollover->sock = i; + atomic_long_inc(&po->rollover->num); + if (room == ROOM_LOW) + atomic_long_inc(&po->rollover->num_huge); return i; } @@ -1420,6 +1423,7 @@ static unsigned int fanout_demux_rollover(struct packet_fanout *f, i = 0; } while (i != j); + atomic_long_inc(&po->rollover->num_failed); return idx; } @@ -1554,6 +1558,9 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) po->rollover = kzalloc(sizeof(*po->rollover), GFP_KERNEL); if (!po->rollover) return -ENOMEM; + atomic_long_set(&po->rollover->num, 0); + atomic_long_set(&po->rollover->num_huge, 0); + atomic_long_set(&po->rollover->num_failed, 0); } mutex_lock(&fanout_mutex); @@ -3584,6 +3591,7 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, struct packet_sock *po = pkt_sk(sk); void *data = &val; union tpacket_stats_u st; + struct tpacket_rollover_stats rstats; if (level != SOL_PACKET) return -ENOPROTOOPT; @@ -3659,6 +3667,15 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, ((u32)po->fanout->flags << 24)) : 0); break; + case PACKET_ROLLOVER_STATS: + if (!po->rollover) + return -EINVAL; + rstats.tp_all = atomic_long_read(&po->rollover->num); + rstats.tp_huge = atomic_long_read(&po->rollover->num_huge); + rstats.tp_failed = atomic_long_read(&po->rollover->num_failed); + data = &rstats; + lv = sizeof(rstats); + break; case PACKET_TX_HAS_OFF: val = po->tp_tx_has_off; break; diff --git a/net/packet/internal.h b/net/packet/internal.h index a9d30a17c714..c035d263c1e8 100644 --- a/net/packet/internal.h +++ b/net/packet/internal.h @@ -89,6 +89,9 @@ struct packet_fanout { struct packet_rollover { int sock; + atomic_long_t num; + atomic_long_t num_huge; + atomic_long_t num_failed; #define ROLLOVER_HLEN (L1_CACHE_BYTES / sizeof(u32)) u32 history[ROLLOVER_HLEN] ____cacheline_aligned; } ____cacheline_aligned_in_smp; |