aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-04-19 02:12:29 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-25 01:29:43 -0400
commitee80fbf301adac644d0c9465194a7ec87bcd4a07 (patch)
treeac14fe920736575c7f8c39ed912201c6143fe501
parent0578edc5604e3e192980f406f9e1040aa6434ca4 (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.c37
-rw-r--r--net/packet/internal.h3
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
1697drop_n_acct: 1697drop_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
1900ring_is_full: 1900ring_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;