mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									0578edc560
								
							
						
					
					
						commit
						ee80fbf301
					
				
					 2 changed files with 17 additions and 23 deletions
				
			
		| 
						 | 
					@ -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,
 | 
				
			||||||
	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,
 | 
				
			||||||
				  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,
 | 
				
			||||||
	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,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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,
 | 
				
			||||||
	 * 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,
 | 
				
			||||||
	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,
 | 
				
			||||||
	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,
 | 
				
			||||||
	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 {
 | 
				
			||||||
	/* 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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue