diff options
Diffstat (limited to 'net/packet/af_packet.c')
| -rw-r--r-- | net/packet/af_packet.c | 83 | 
1 files changed, 19 insertions, 64 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index acb7b86574cd..9b27d0cd766d 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -209,7 +209,7 @@ static void prb_clear_rxhash(struct tpacket_kbdq_core *,  static void prb_fill_vlan_info(struct tpacket_kbdq_core *,  		struct tpacket3_hdr *);  static void packet_flush_mclist(struct sock *sk); -static void packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb); +static u16 packet_pick_tx_queue(struct sk_buff *skb);  struct packet_skb_cb {  	union { @@ -243,40 +243,7 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po);  static int packet_direct_xmit(struct sk_buff *skb)  { -	struct net_device *dev = skb->dev; -	struct sk_buff *orig_skb = skb; -	struct netdev_queue *txq; -	int ret = NETDEV_TX_BUSY; -	bool again = false; - -	if (unlikely(!netif_running(dev) || -		     !netif_carrier_ok(dev))) -		goto drop; - -	skb = validate_xmit_skb_list(skb, dev, &again); -	if (skb != orig_skb) -		goto drop; - -	packet_pick_tx_queue(dev, skb); -	txq = skb_get_tx_queue(dev, skb); - -	local_bh_disable(); - -	HARD_TX_LOCK(dev, txq, smp_processor_id()); -	if (!netif_xmit_frozen_or_drv_stopped(txq)) -		ret = netdev_start_xmit(skb, dev, txq, false); -	HARD_TX_UNLOCK(dev, txq); - -	local_bh_enable(); - -	if (!dev_xmit_complete(ret)) -		kfree_skb(skb); - -	return ret; -drop: -	atomic_long_inc(&dev->tx_dropped); -	kfree_skb_list(skb); -	return NET_XMIT_DROP; +	return dev_direct_xmit(skb, packet_pick_tx_queue(skb));  }  static struct net_device *packet_cached_dev_get(struct packet_sock *po) @@ -313,8 +280,9 @@ static u16 __packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb)  	return (u16) raw_smp_processor_id() % dev->real_num_tx_queues;  } -static void packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb) +static u16 packet_pick_tx_queue(struct sk_buff *skb)  { +	struct net_device *dev = skb->dev;  	const struct net_device_ops *ops = dev->netdev_ops;  	u16 queue_index; @@ -326,7 +294,7 @@ static void packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb)  		queue_index = __packet_pick_tx_queue(dev, skb);  	} -	skb_set_queue_mapping(skb, queue_index); +	return queue_index;  }  /* __register_prot_hook must be invoked through register_prot_hook @@ -2037,7 +2005,7 @@ static int packet_rcv_vnet(struct msghdr *msg, const struct sk_buff *skb,  		return -EINVAL;  	*len -= sizeof(vnet_hdr); -	if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le(), true)) +	if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le(), true, 0))  		return -EINVAL;  	return memcpy_to_msg(msg, (void *)&vnet_hdr, sizeof(vnet_hdr)); @@ -2294,6 +2262,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,  		if (po->stats.stats1.tp_drops)  			status |= TP_STATUS_LOSING;  	} + +	if (do_vnet && +	    virtio_net_hdr_from_skb(skb, h.raw + macoff - +				    sizeof(struct virtio_net_hdr), +				    vio_le(), true, 0)) +		goto drop_n_account; +  	po->stats.stats1.tp_packets++;  	if (copy_skb) {  		status |= TP_STATUS_COPY; @@ -2301,15 +2276,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,  	}  	spin_unlock(&sk->sk_receive_queue.lock); -	if (do_vnet) { -		if (virtio_net_hdr_from_skb(skb, h.raw + macoff - -					    sizeof(struct virtio_net_hdr), -					    vio_le(), true)) { -			spin_lock(&sk->sk_receive_queue.lock); -			goto drop_n_account; -		} -	} -  	skb_copy_bits(skb, 0, h.raw + macoff, snaplen);  	if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp))) @@ -2912,6 +2878,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)  			goto out_free;  	} else if (reserve) {  		skb_reserve(skb, -reserve); +		if (len < reserve) +			skb_reset_network_header(skb);  	}  	/* Returns -EFAULT on error */ @@ -4194,7 +4162,7 @@ static char *alloc_one_pg_vec_page(unsigned long order)  		return buffer;  	/* __get_free_pages failed, fall back to vmalloc */ -	buffer = vzalloc((1 << order) * PAGE_SIZE); +	buffer = vzalloc(array_size((1 << order), PAGE_SIZE));  	if (buffer)  		return buffer; @@ -4282,7 +4250,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,  			goto out;  		if (po->tp_version >= TPACKET_V3 &&  		    req->tp_block_size <= -			  BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv)) +		    BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv) + sizeof(struct tpacket3_hdr))  			goto out;  		if (unlikely(req->tp_frame_size < po->tp_hdrlen +  					po->tp_reserve)) @@ -4556,20 +4524,6 @@ static const struct seq_operations packet_seq_ops = {  	.stop	= packet_seq_stop,  	.show	= packet_seq_show,  }; - -static int packet_seq_open(struct inode *inode, struct file *file) -{ -	return seq_open_net(inode, file, &packet_seq_ops, -			    sizeof(struct seq_net_private)); -} - -static const struct file_operations packet_seq_fops = { -	.open		= packet_seq_open, -	.read		= seq_read, -	.llseek		= seq_lseek, -	.release	= seq_release_net, -}; -  #endif  static int __net_init packet_net_init(struct net *net) @@ -4577,7 +4531,8 @@ static int __net_init packet_net_init(struct net *net)  	mutex_init(&net->packet.sklist_lock);  	INIT_HLIST_HEAD(&net->packet.sklist); -	if (!proc_create("packet", 0, net->proc_net, &packet_seq_fops)) +	if (!proc_create_net("packet", 0, net->proc_net, &packet_seq_ops, +			sizeof(struct seq_net_private)))  		return -ENOMEM;  	return 0;  |