diff options
author | Daniel Borkmann <dborkman@redhat.com> | 2013-04-19 02:12:29 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-04-25 01:29:43 -0400 |
commit | ee80fbf301adac644d0c9465194a7ec87bcd4a07 (patch) | |
tree | ac14fe920736575c7f8c39ed912201c6143fe501 | |
parent | 0578edc5604e3e192980f406f9e1040aa6434ca4 (diff) |
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: Daniel Borkmann <dborkman@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/packet/af_packet.c | 37 | ||||
-rw-r--r-- | net/packet/internal.h | 3 |
2 files changed, 17 insertions, 23 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index ba8309a3e01b..dd5cd49b0e09 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -528,7 +528,7 @@ static void init_prb_bdqc(struct packet_sock *po, | |||
528 | p1->hdrlen = po->tp_hdrlen; | 528 | p1->hdrlen = po->tp_hdrlen; |
529 | p1->version = po->tp_version; | 529 | p1->version = po->tp_version; |
530 | p1->last_kactive_blk_num = 0; | 530 | p1->last_kactive_blk_num = 0; |
531 | po->stats_u.stats3.tp_freeze_q_cnt = 0; | 531 | po->stats.stats3.tp_freeze_q_cnt = 0; |
532 | if (req_u->req3.tp_retire_blk_tov) | 532 | if (req_u->req3.tp_retire_blk_tov) |
533 | p1->retire_blk_tov = req_u->req3.tp_retire_blk_tov; | 533 | p1->retire_blk_tov = req_u->req3.tp_retire_blk_tov; |
534 | else | 534 | else |
@@ -696,7 +696,7 @@ static void prb_close_block(struct tpacket_kbdq_core *pkc1, | |||
696 | struct tpacket3_hdr *last_pkt; | 696 | struct tpacket3_hdr *last_pkt; |
697 | struct tpacket_hdr_v1 *h1 = &pbd1->hdr.bh1; | 697 | struct tpacket_hdr_v1 *h1 = &pbd1->hdr.bh1; |
698 | 698 | ||
699 | if (po->stats.tp_drops) | 699 | if (po->stats.stats3.tp_drops) |
700 | status |= TP_STATUS_LOSING; | 700 | status |= TP_STATUS_LOSING; |
701 | 701 | ||
702 | last_pkt = (struct tpacket3_hdr *)pkc1->prev; | 702 | last_pkt = (struct tpacket3_hdr *)pkc1->prev; |
@@ -801,7 +801,7 @@ static void prb_freeze_queue(struct tpacket_kbdq_core *pkc, | |||
801 | struct packet_sock *po) | 801 | struct packet_sock *po) |
802 | { | 802 | { |
803 | pkc->reset_pending_on_curr_blk = 1; | 803 | pkc->reset_pending_on_curr_blk = 1; |
804 | po->stats_u.stats3.tp_freeze_q_cnt++; | 804 | po->stats.stats3.tp_freeze_q_cnt++; |
805 | } | 805 | } |
806 | 806 | ||
807 | #define TOTAL_PKT_LEN_INCL_ALIGN(length) (ALIGN((length), V3_ALIGNMENT)) | 807 | #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 | nf_reset(skb); | 1687 | nf_reset(skb); |
1688 | 1688 | ||
1689 | spin_lock(&sk->sk_receive_queue.lock); | 1689 | spin_lock(&sk->sk_receive_queue.lock); |
1690 | po->stats.tp_packets++; | 1690 | po->stats.stats1.tp_packets++; |
1691 | skb->dropcount = atomic_read(&sk->sk_drops); | 1691 | skb->dropcount = atomic_read(&sk->sk_drops); |
1692 | __skb_queue_tail(&sk->sk_receive_queue, skb); | 1692 | __skb_queue_tail(&sk->sk_receive_queue, skb); |
1693 | spin_unlock(&sk->sk_receive_queue.lock); | 1693 | spin_unlock(&sk->sk_receive_queue.lock); |
@@ -1696,7 +1696,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, | |||
1696 | 1696 | ||
1697 | drop_n_acct: | 1697 | drop_n_acct: |
1698 | spin_lock(&sk->sk_receive_queue.lock); | 1698 | spin_lock(&sk->sk_receive_queue.lock); |
1699 | po->stats.tp_drops++; | 1699 | po->stats.stats1.tp_drops++; |
1700 | atomic_inc(&sk->sk_drops); | 1700 | atomic_inc(&sk->sk_drops); |
1701 | spin_unlock(&sk->sk_receive_queue.lock); | 1701 | spin_unlock(&sk->sk_receive_queue.lock); |
1702 | 1702 | ||
@@ -1796,10 +1796,10 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, | |||
1796 | * Anyways, moving it for V1/V2 only as V3 doesn't need this | 1796 | * Anyways, moving it for V1/V2 only as V3 doesn't need this |
1797 | * at packet level. | 1797 | * at packet level. |
1798 | */ | 1798 | */ |
1799 | if (po->stats.tp_drops) | 1799 | if (po->stats.stats1.tp_drops) |
1800 | status |= TP_STATUS_LOSING; | 1800 | status |= TP_STATUS_LOSING; |
1801 | } | 1801 | } |
1802 | po->stats.tp_packets++; | 1802 | po->stats.stats1.tp_packets++; |
1803 | if (copy_skb) { | 1803 | if (copy_skb) { |
1804 | status |= TP_STATUS_COPY; | 1804 | status |= TP_STATUS_COPY; |
1805 | __skb_queue_tail(&sk->sk_receive_queue, copy_skb); | 1805 | __skb_queue_tail(&sk->sk_receive_queue, copy_skb); |
@@ -1898,7 +1898,7 @@ drop: | |||
1898 | return 0; | 1898 | return 0; |
1899 | 1899 | ||
1900 | ring_is_full: | 1900 | ring_is_full: |
1901 | po->stats.tp_drops++; | 1901 | po->stats.stats1.tp_drops++; |
1902 | spin_unlock(&sk->sk_receive_queue.lock); | 1902 | spin_unlock(&sk->sk_receive_queue.lock); |
1903 | 1903 | ||
1904 | sk->sk_data_ready(sk, 0); | 1904 | sk->sk_data_ready(sk, 0); |
@@ -3247,8 +3247,7 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, | |||
3247 | struct sock *sk = sock->sk; | 3247 | struct sock *sk = sock->sk; |
3248 | struct packet_sock *po = pkt_sk(sk); | 3248 | struct packet_sock *po = pkt_sk(sk); |
3249 | void *data = &val; | 3249 | void *data = &val; |
3250 | struct tpacket_stats st; | 3250 | union tpacket_stats_u st; |
3251 | union tpacket_stats_u st_u; | ||
3252 | 3251 | ||
3253 | if (level != SOL_PACKET) | 3252 | if (level != SOL_PACKET) |
3254 | return -ENOPROTOOPT; | 3253 | return -ENOPROTOOPT; |
@@ -3262,22 +3261,18 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, | |||
3262 | switch (optname) { | 3261 | switch (optname) { |
3263 | case PACKET_STATISTICS: | 3262 | case PACKET_STATISTICS: |
3264 | spin_lock_bh(&sk->sk_receive_queue.lock); | 3263 | spin_lock_bh(&sk->sk_receive_queue.lock); |
3264 | memcpy(&st, &po->stats, sizeof(st)); | ||
3265 | memset(&po->stats, 0, sizeof(po->stats)); | ||
3266 | spin_unlock_bh(&sk->sk_receive_queue.lock); | ||
3267 | |||
3265 | if (po->tp_version == TPACKET_V3) { | 3268 | if (po->tp_version == TPACKET_V3) { |
3266 | lv = sizeof(struct tpacket_stats_v3); | 3269 | lv = sizeof(struct tpacket_stats_v3); |
3267 | memcpy(&st_u.stats3, &po->stats, | 3270 | data = &st.stats3; |
3268 | sizeof(struct tpacket_stats)); | ||
3269 | st_u.stats3.tp_freeze_q_cnt = | ||
3270 | po->stats_u.stats3.tp_freeze_q_cnt; | ||
3271 | st_u.stats3.tp_packets += po->stats.tp_drops; | ||
3272 | data = &st_u.stats3; | ||
3273 | } else { | 3271 | } else { |
3274 | lv = sizeof(struct tpacket_stats); | 3272 | lv = sizeof(struct tpacket_stats); |
3275 | st = po->stats; | 3273 | data = &st.stats1; |
3276 | st.tp_packets += st.tp_drops; | ||
3277 | data = &st; | ||
3278 | } | 3274 | } |
3279 | memset(&po->stats, 0, sizeof(st)); | 3275 | |
3280 | spin_unlock_bh(&sk->sk_receive_queue.lock); | ||
3281 | break; | 3276 | break; |
3282 | case PACKET_AUXDATA: | 3277 | case PACKET_AUXDATA: |
3283 | val = po->auxdata; | 3278 | val = po->auxdata; |
diff --git a/net/packet/internal.h b/net/packet/internal.h index 650751b9a7ee..c4e4b4561207 100644 --- a/net/packet/internal.h +++ b/net/packet/internal.h | |||
@@ -93,8 +93,7 @@ struct packet_sock { | |||
93 | /* struct sock has to be the first member of packet_sock */ | 93 | /* struct sock has to be the first member of packet_sock */ |
94 | struct sock sk; | 94 | struct sock sk; |
95 | struct packet_fanout *fanout; | 95 | struct packet_fanout *fanout; |
96 | struct tpacket_stats stats; | 96 | union tpacket_stats_u stats; |
97 | union tpacket_stats_u stats_u; | ||
98 | struct packet_ring_buffer rx_ring; | 97 | struct packet_ring_buffer rx_ring; |
99 | struct packet_ring_buffer tx_ring; | 98 | struct packet_ring_buffer tx_ring; |
100 | int copy_thresh; | 99 | int copy_thresh; |