|
@@ -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;
|