Skip to content

Commit

Permalink
packet: rollover statistics
Browse files Browse the repository at this point in the history
Rollover indicates exceptional conditions. Export a counter to inform
socket owners of this state.

If no socket with sufficient room is found, rollover fails. Also count
these events.

Finally, also count when flows are rolled over early thanks to huge
flow detection, to validate its correctness.

Tested:
  Read counters in bench_rollover on all other tests in the patchset

Signed-off-by: Willem de Bruijn <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
wdebruij authored and davem330 committed May 13, 2015
1 parent 3b3a5b0 commit a9b6391
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 1 deletion.
7 changes: 7 additions & 0 deletions include/uapi/linux/if_packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ struct sockaddr_ll {
#define PACKET_FANOUT 18
#define PACKET_TX_HAS_OFF 19
#define PACKET_QDISC_BYPASS 20
#define PACKET_ROLLOVER_STATS 21

#define PACKET_FANOUT_HASH 0
#define PACKET_FANOUT_LB 1
Expand All @@ -75,6 +76,12 @@ struct tpacket_stats_v3 {
unsigned int tp_freeze_q_cnt;
};

struct tpacket_rollover_stats {
__aligned_u64 tp_all;
__aligned_u64 tp_huge;
__aligned_u64 tp_failed;
};

union tpacket_stats_u {
struct tpacket_stats stats1;
struct tpacket_stats_v3 stats3;
Expand Down
19 changes: 18 additions & 1 deletion net/packet/af_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]);

Expand All @@ -1413,13 +1413,17 @@ 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;
}

if (++i == num)
i = 0;
} while (i != j);

atomic_long_inc(&po->rollover->num_failed);
return idx;
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions net/packet/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit a9b6391

Please sign in to comment.