Commit ee80fbf3 authored by Daniel Borkmann's avatar Daniel Borkmann Committed by David S. Miller

packet: account statistics only in tpacket_stats_u

Currently, packet_sock has a struct tpacket_stats stats member for
TPACKET_V1 and TPACKET_V2 statistic accounting, and with TPACKET_V3
``union tpacket_stats_u stats_u'' was introduced, where however only
statistics for TPACKET_V3 are held, and when copied to user space,
TPACKET_V3 does some hackery and access also tpacket_stats' stats,
although everything could have been done within the union itself.

Unify accounting within the tpacket_stats_u union so that we can
remove 8 bytes from packet_sock that are there unnecessary. Note that
even if we switch to TPACKET_V3 and would use non mmap(2)ed option,
this still works due to the union with same types + offsets, that are
exposed to the user space.
Signed-off-by: default avatarDaniel Borkmann <dborkman@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0578edc5
...@@ -528,7 +528,7 @@ static void init_prb_bdqc(struct packet_sock *po, ...@@ -528,7 +528,7 @@ static void init_prb_bdqc(struct packet_sock *po,
p1->hdrlen = po->tp_hdrlen; p1->hdrlen = po->tp_hdrlen;
p1->version = po->tp_version; p1->version = po->tp_version;
p1->last_kactive_blk_num = 0; p1->last_kactive_blk_num = 0;
po->stats_u.stats3.tp_freeze_q_cnt = 0; po->stats.stats3.tp_freeze_q_cnt = 0;
if (req_u->req3.tp_retire_blk_tov) if (req_u->req3.tp_retire_blk_tov)
p1->retire_blk_tov = req_u->req3.tp_retire_blk_tov; p1->retire_blk_tov = req_u->req3.tp_retire_blk_tov;
else else
...@@ -696,7 +696,7 @@ static void prb_close_block(struct tpacket_kbdq_core *pkc1, ...@@ -696,7 +696,7 @@ static void prb_close_block(struct tpacket_kbdq_core *pkc1,
struct tpacket3_hdr *last_pkt; struct tpacket3_hdr *last_pkt;
struct tpacket_hdr_v1 *h1 = &pbd1->hdr.bh1; struct tpacket_hdr_v1 *h1 = &pbd1->hdr.bh1;
if (po->stats.tp_drops) if (po->stats.stats3.tp_drops)
status |= TP_STATUS_LOSING; status |= TP_STATUS_LOSING;
last_pkt = (struct tpacket3_hdr *)pkc1->prev; last_pkt = (struct tpacket3_hdr *)pkc1->prev;
...@@ -801,7 +801,7 @@ static void prb_freeze_queue(struct tpacket_kbdq_core *pkc, ...@@ -801,7 +801,7 @@ static void prb_freeze_queue(struct tpacket_kbdq_core *pkc,
struct packet_sock *po) struct packet_sock *po)
{ {
pkc->reset_pending_on_curr_blk = 1; pkc->reset_pending_on_curr_blk = 1;
po->stats_u.stats3.tp_freeze_q_cnt++; po->stats.stats3.tp_freeze_q_cnt++;
} }
#define TOTAL_PKT_LEN_INCL_ALIGN(length) (ALIGN((length), V3_ALIGNMENT)) #define TOTAL_PKT_LEN_INCL_ALIGN(length) (ALIGN((length), V3_ALIGNMENT))
...@@ -1687,7 +1687,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -1687,7 +1687,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
nf_reset(skb); nf_reset(skb);
spin_lock(&sk->sk_receive_queue.lock); spin_lock(&sk->sk_receive_queue.lock);
po->stats.tp_packets++; po->stats.stats1.tp_packets++;
skb->dropcount = atomic_read(&sk->sk_drops); skb->dropcount = atomic_read(&sk->sk_drops);
__skb_queue_tail(&sk->sk_receive_queue, skb); __skb_queue_tail(&sk->sk_receive_queue, skb);
spin_unlock(&sk->sk_receive_queue.lock); spin_unlock(&sk->sk_receive_queue.lock);
...@@ -1696,7 +1696,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -1696,7 +1696,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
drop_n_acct: drop_n_acct:
spin_lock(&sk->sk_receive_queue.lock); spin_lock(&sk->sk_receive_queue.lock);
po->stats.tp_drops++; po->stats.stats1.tp_drops++;
atomic_inc(&sk->sk_drops); atomic_inc(&sk->sk_drops);
spin_unlock(&sk->sk_receive_queue.lock); spin_unlock(&sk->sk_receive_queue.lock);
...@@ -1796,10 +1796,10 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -1796,10 +1796,10 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
* Anyways, moving it for V1/V2 only as V3 doesn't need this * Anyways, moving it for V1/V2 only as V3 doesn't need this
* at packet level. * at packet level.
*/ */
if (po->stats.tp_drops) if (po->stats.stats1.tp_drops)
status |= TP_STATUS_LOSING; status |= TP_STATUS_LOSING;
} }
po->stats.tp_packets++; po->stats.stats1.tp_packets++;
if (copy_skb) { if (copy_skb) {
status |= TP_STATUS_COPY; status |= TP_STATUS_COPY;
__skb_queue_tail(&sk->sk_receive_queue, copy_skb); __skb_queue_tail(&sk->sk_receive_queue, copy_skb);
...@@ -1898,7 +1898,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -1898,7 +1898,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
return 0; return 0;
ring_is_full: ring_is_full:
po->stats.tp_drops++; po->stats.stats1.tp_drops++;
spin_unlock(&sk->sk_receive_queue.lock); spin_unlock(&sk->sk_receive_queue.lock);
sk->sk_data_ready(sk, 0); sk->sk_data_ready(sk, 0);
...@@ -3247,8 +3247,7 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, ...@@ -3247,8 +3247,7 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct packet_sock *po = pkt_sk(sk); struct packet_sock *po = pkt_sk(sk);
void *data = &val; void *data = &val;
struct tpacket_stats st; union tpacket_stats_u st;
union tpacket_stats_u st_u;
if (level != SOL_PACKET) if (level != SOL_PACKET)
return -ENOPROTOOPT; return -ENOPROTOOPT;
...@@ -3262,22 +3261,18 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, ...@@ -3262,22 +3261,18 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
switch (optname) { switch (optname) {
case PACKET_STATISTICS: case PACKET_STATISTICS:
spin_lock_bh(&sk->sk_receive_queue.lock); spin_lock_bh(&sk->sk_receive_queue.lock);
memcpy(&st, &po->stats, sizeof(st));
memset(&po->stats, 0, sizeof(po->stats));
spin_unlock_bh(&sk->sk_receive_queue.lock);
if (po->tp_version == TPACKET_V3) { if (po->tp_version == TPACKET_V3) {
lv = sizeof(struct tpacket_stats_v3); lv = sizeof(struct tpacket_stats_v3);
memcpy(&st_u.stats3, &po->stats, data = &st.stats3;
sizeof(struct tpacket_stats));
st_u.stats3.tp_freeze_q_cnt =
po->stats_u.stats3.tp_freeze_q_cnt;
st_u.stats3.tp_packets += po->stats.tp_drops;
data = &st_u.stats3;
} else { } else {
lv = sizeof(struct tpacket_stats); lv = sizeof(struct tpacket_stats);
st = po->stats; data = &st.stats1;
st.tp_packets += st.tp_drops;
data = &st;
} }
memset(&po->stats, 0, sizeof(st));
spin_unlock_bh(&sk->sk_receive_queue.lock);
break; break;
case PACKET_AUXDATA: case PACKET_AUXDATA:
val = po->auxdata; val = po->auxdata;
......
...@@ -93,8 +93,7 @@ struct packet_sock { ...@@ -93,8 +93,7 @@ struct packet_sock {
/* struct sock has to be the first member of packet_sock */ /* struct sock has to be the first member of packet_sock */
struct sock sk; struct sock sk;
struct packet_fanout *fanout; struct packet_fanout *fanout;
struct tpacket_stats stats; union tpacket_stats_u stats;
union tpacket_stats_u stats_u;
struct packet_ring_buffer rx_ring; struct packet_ring_buffer rx_ring;
struct packet_ring_buffer tx_ring; struct packet_ring_buffer tx_ring;
int copy_thresh; int copy_thresh;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment