|
@@ -181,6 +181,7 @@ struct tun_file {
|
|
};
|
|
};
|
|
struct napi_struct napi;
|
|
struct napi_struct napi;
|
|
bool napi_enabled;
|
|
bool napi_enabled;
|
|
|
|
+ bool napi_frags_enabled;
|
|
struct mutex napi_mutex; /* Protects access to the above napi */
|
|
struct mutex napi_mutex; /* Protects access to the above napi */
|
|
struct list_head next;
|
|
struct list_head next;
|
|
struct tun_struct *detached;
|
|
struct tun_struct *detached;
|
|
@@ -313,9 +314,10 @@ static int tun_napi_poll(struct napi_struct *napi, int budget)
|
|
}
|
|
}
|
|
|
|
|
|
static void tun_napi_init(struct tun_struct *tun, struct tun_file *tfile,
|
|
static void tun_napi_init(struct tun_struct *tun, struct tun_file *tfile,
|
|
- bool napi_en)
|
|
|
|
|
|
+ bool napi_en, bool napi_frags)
|
|
{
|
|
{
|
|
tfile->napi_enabled = napi_en;
|
|
tfile->napi_enabled = napi_en;
|
|
|
|
+ tfile->napi_frags_enabled = napi_en && napi_frags;
|
|
if (napi_en) {
|
|
if (napi_en) {
|
|
netif_napi_add(tun->dev, &tfile->napi, tun_napi_poll,
|
|
netif_napi_add(tun->dev, &tfile->napi, tun_napi_poll,
|
|
NAPI_POLL_WEIGHT);
|
|
NAPI_POLL_WEIGHT);
|
|
@@ -335,9 +337,9 @@ static void tun_napi_del(struct tun_file *tfile)
|
|
netif_napi_del(&tfile->napi);
|
|
netif_napi_del(&tfile->napi);
|
|
}
|
|
}
|
|
|
|
|
|
-static bool tun_napi_frags_enabled(const struct tun_struct *tun)
|
|
|
|
|
|
+static bool tun_napi_frags_enabled(const struct tun_file *tfile)
|
|
{
|
|
{
|
|
- return READ_ONCE(tun->flags) & IFF_NAPI_FRAGS;
|
|
|
|
|
|
+ return tfile->napi_frags_enabled;
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_TUN_VNET_CROSS_LE
|
|
#ifdef CONFIG_TUN_VNET_CROSS_LE
|
|
@@ -792,7 +794,7 @@ static void tun_detach_all(struct net_device *dev)
|
|
}
|
|
}
|
|
|
|
|
|
static int tun_attach(struct tun_struct *tun, struct file *file,
|
|
static int tun_attach(struct tun_struct *tun, struct file *file,
|
|
- bool skip_filter, bool napi)
|
|
|
|
|
|
+ bool skip_filter, bool napi, bool napi_frags)
|
|
{
|
|
{
|
|
struct tun_file *tfile = file->private_data;
|
|
struct tun_file *tfile = file->private_data;
|
|
struct net_device *dev = tun->dev;
|
|
struct net_device *dev = tun->dev;
|
|
@@ -865,7 +867,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
|
|
tun_enable_queue(tfile);
|
|
tun_enable_queue(tfile);
|
|
} else {
|
|
} else {
|
|
sock_hold(&tfile->sk);
|
|
sock_hold(&tfile->sk);
|
|
- tun_napi_init(tun, tfile, napi);
|
|
|
|
|
|
+ tun_napi_init(tun, tfile, napi, napi_frags);
|
|
}
|
|
}
|
|
|
|
|
|
tun_set_real_num_queues(tun);
|
|
tun_set_real_num_queues(tun);
|
|
@@ -1708,7 +1710,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
|
|
int err;
|
|
int err;
|
|
u32 rxhash = 0;
|
|
u32 rxhash = 0;
|
|
int skb_xdp = 1;
|
|
int skb_xdp = 1;
|
|
- bool frags = tun_napi_frags_enabled(tun);
|
|
|
|
|
|
+ bool frags = tun_napi_frags_enabled(tfile);
|
|
|
|
|
|
if (!(tun->dev->flags & IFF_UP))
|
|
if (!(tun->dev->flags & IFF_UP))
|
|
return -EIO;
|
|
return -EIO;
|
|
@@ -2533,7 +2535,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
|
|
return err;
|
|
return err;
|
|
|
|
|
|
err = tun_attach(tun, file, ifr->ifr_flags & IFF_NOFILTER,
|
|
err = tun_attach(tun, file, ifr->ifr_flags & IFF_NOFILTER,
|
|
- ifr->ifr_flags & IFF_NAPI);
|
|
|
|
|
|
+ ifr->ifr_flags & IFF_NAPI,
|
|
|
|
+ ifr->ifr_flags & IFF_NAPI_FRAGS);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
|
|
|
|
@@ -2631,7 +2634,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
|
|
(ifr->ifr_flags & TUN_FEATURES);
|
|
(ifr->ifr_flags & TUN_FEATURES);
|
|
|
|
|
|
INIT_LIST_HEAD(&tun->disabled);
|
|
INIT_LIST_HEAD(&tun->disabled);
|
|
- err = tun_attach(tun, file, false, ifr->ifr_flags & IFF_NAPI);
|
|
|
|
|
|
+ err = tun_attach(tun, file, false, ifr->ifr_flags & IFF_NAPI,
|
|
|
|
+ ifr->ifr_flags & IFF_NAPI_FRAGS);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto err_free_flow;
|
|
goto err_free_flow;
|
|
|
|
|
|
@@ -2780,7 +2784,8 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
|
|
ret = security_tun_dev_attach_queue(tun->security);
|
|
ret = security_tun_dev_attach_queue(tun->security);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto unlock;
|
|
goto unlock;
|
|
- ret = tun_attach(tun, file, false, tun->flags & IFF_NAPI);
|
|
|
|
|
|
+ ret = tun_attach(tun, file, false, tun->flags & IFF_NAPI,
|
|
|
|
+ tun->flags & IFF_NAPI_FRAGS);
|
|
} else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {
|
|
} else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {
|
|
tun = rtnl_dereference(tfile->tun);
|
|
tun = rtnl_dereference(tfile->tun);
|
|
if (!tun || !(tun->flags & IFF_MULTI_QUEUE) || tfile->detached)
|
|
if (!tun || !(tun->flags & IFF_MULTI_QUEUE) || tfile->detached)
|