diff options
Diffstat (limited to 'drivers/net/tun.c')
| -rw-r--r-- | drivers/net/tun.c | 44 | 
1 files changed, 30 insertions, 14 deletions
| diff --git a/drivers/net/tun.c b/drivers/net/tun.c index bbd707b9ef7a..3d4c24572ecd 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -465,7 +465,7 @@ static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,  	rcu_read_lock();  	numqueues = ACCESS_ONCE(tun->numqueues); -	txq = skb_get_hash(skb); +	txq = __skb_get_hash_symmetric(skb);  	if (txq) {  		e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq);  		if (e) { @@ -867,7 +867,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)  		 */  		__u32 rxhash; -		rxhash = skb_get_hash(skb); +		rxhash = __skb_get_hash_symmetric(skb);  		if (rxhash) {  			struct tun_flow_entry *e;  			e = tun_flow_find(&tun->flows[tun_hashfn(rxhash)], @@ -1334,7 +1334,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,  	skb_reset_network_header(skb);  	skb_probe_transport_header(skb, 0); -	rxhash = skb_get_hash(skb); +	rxhash = __skb_get_hash_symmetric(skb);  #ifndef CONFIG_4KSTACKS  	tun_rx_batched(tun, tfile, skb, more);  #else @@ -1510,9 +1510,8 @@ out:  static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,  			   struct iov_iter *to, -			   int noblock) +			   int noblock, struct sk_buff *skb)  { -	struct sk_buff *skb;  	ssize_t ret;  	int err; @@ -1521,10 +1520,12 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,  	if (!iov_iter_count(to))  		return 0; -	/* Read frames from ring */ -	skb = tun_ring_recv(tfile, noblock, &err); -	if (!skb) -		return err; +	if (!skb) { +		/* Read frames from ring */ +		skb = tun_ring_recv(tfile, noblock, &err); +		if (!skb) +			return err; +	}  	ret = tun_put_user(tun, tfile, skb, to);  	if (unlikely(ret < 0)) @@ -1544,7 +1545,7 @@ static ssize_t tun_chr_read_iter(struct kiocb *iocb, struct iov_iter *to)  	if (!tun)  		return -EBADFD; -	ret = tun_do_read(tun, tfile, to, file->f_flags & O_NONBLOCK); +	ret = tun_do_read(tun, tfile, to, file->f_flags & O_NONBLOCK, NULL);  	ret = min_t(ssize_t, ret, len);  	if (ret > 0)  		iocb->ki_pos = ret; @@ -1560,7 +1561,6 @@ static void tun_free_netdev(struct net_device *dev)  	free_percpu(tun->pcpu_stats);  	tun_flow_uninit(tun);  	security_tun_dev_free_security(tun->security); -	free_netdev(dev);  }  static void tun_setup(struct net_device *dev) @@ -1571,7 +1571,8 @@ static void tun_setup(struct net_device *dev)  	tun->group = INVALID_GID;  	dev->ethtool_ops = &tun_ethtool_ops; -	dev->destructor = tun_free_netdev; +	dev->needs_free_netdev = true; +	dev->priv_destructor = tun_free_netdev;  	/* We prefer our own queue length */  	dev->tx_queue_len = TUN_READQ_SIZE;  } @@ -1579,7 +1580,8 @@ static void tun_setup(struct net_device *dev)  /* Trivial set of netlink ops to allow deleting tun or tap   * device with netlink.   */ -static int tun_validate(struct nlattr *tb[], struct nlattr *data[]) +static int tun_validate(struct nlattr *tb[], struct nlattr *data[], +			struct netlink_ext_ack *extack)  {  	return -EINVAL;  } @@ -1646,7 +1648,8 @@ static int tun_recvmsg(struct socket *sock, struct msghdr *m, size_t total_len,  					 SOL_PACKET, TUN_TX_TIMESTAMP);  		goto out;  	} -	ret = tun_do_read(tun, tfile, &m->msg_iter, flags & MSG_DONTWAIT); +	ret = tun_do_read(tun, tfile, &m->msg_iter, flags & MSG_DONTWAIT, +			  m->msg_control);  	if (ret > (ssize_t)total_len) {  		m->msg_flags |= MSG_TRUNC;  		ret = flags & MSG_TRUNC ? ret : total_len; @@ -2626,6 +2629,19 @@ struct socket *tun_get_socket(struct file *file)  }  EXPORT_SYMBOL_GPL(tun_get_socket); +struct skb_array *tun_get_skb_array(struct file *file) +{ +	struct tun_file *tfile; + +	if (file->f_op != &tun_fops) +		return ERR_PTR(-EINVAL); +	tfile = file->private_data; +	if (!tfile) +		return ERR_PTR(-EBADFD); +	return &tfile->tx_array; +} +EXPORT_SYMBOL_GPL(tun_get_skb_array); +  module_init(tun_init);  module_exit(tun_cleanup);  MODULE_DESCRIPTION(DRV_DESCRIPTION); | 
