Skip to content

Commit 8ae1aff

Browse files
jasowangdavem330
authored andcommitted
tuntap: split out XDP logic
This patch split out XDP logic into a single function. This make it to be reused by XDP batching path in the following patch. Signed-off-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent ac1f1f6 commit 8ae1aff

File tree

1 file changed

+51
-37
lines changed

1 file changed

+51
-37
lines changed

drivers/net/tun.c

Lines changed: 51 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,14 +1636,14 @@ static bool tun_can_build_skb(struct tun_struct *tun, struct tun_file *tfile,
16361636
}
16371637

16381638
static struct sk_buff *__tun_build_skb(struct page_frag *alloc_frag, char *buf,
1639-
int buflen, int len, int pad, int delta)
1639+
int buflen, int len, int pad)
16401640
{
16411641
struct sk_buff *skb = build_skb(buf, buflen);
16421642

16431643
if (!skb)
16441644
return ERR_PTR(-ENOMEM);
16451645

1646-
skb_reserve(skb, pad - delta);
1646+
skb_reserve(skb, pad);
16471647
skb_put(skb, len);
16481648

16491649
get_page(alloc_frag->page);
@@ -1652,6 +1652,39 @@ static struct sk_buff *__tun_build_skb(struct page_frag *alloc_frag, char *buf,
16521652
return skb;
16531653
}
16541654

1655+
static int tun_xdp_act(struct tun_struct *tun, struct bpf_prog *xdp_prog,
1656+
struct xdp_buff *xdp, u32 act)
1657+
{
1658+
int err;
1659+
1660+
switch (act) {
1661+
case XDP_REDIRECT:
1662+
err = xdp_do_redirect(tun->dev, xdp, xdp_prog);
1663+
xdp_do_flush_map();
1664+
if (err)
1665+
return err;
1666+
break;
1667+
case XDP_TX:
1668+
err = tun_xdp_tx(tun->dev, xdp);
1669+
if (err < 0)
1670+
return err;
1671+
break;
1672+
case XDP_PASS:
1673+
break;
1674+
default:
1675+
bpf_warn_invalid_xdp_action(act);
1676+
/* fall through */
1677+
case XDP_ABORTED:
1678+
trace_xdp_exception(tun->dev, xdp_prog, act);
1679+
/* fall through */
1680+
case XDP_DROP:
1681+
this_cpu_inc(tun->pcpu_stats->rx_dropped);
1682+
break;
1683+
}
1684+
1685+
return act;
1686+
}
1687+
16551688
static struct sk_buff *tun_build_skb(struct tun_struct *tun,
16561689
struct tun_file *tfile,
16571690
struct iov_iter *from,
@@ -1661,10 +1694,10 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
16611694
struct page_frag *alloc_frag = &current->task_frag;
16621695
struct bpf_prog *xdp_prog;
16631696
int buflen = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
1664-
unsigned int delta = 0;
16651697
char *buf;
16661698
size_t copied;
1667-
int err, pad = TUN_RX_PAD;
1699+
int pad = TUN_RX_PAD;
1700+
int err = 0;
16681701

16691702
rcu_read_lock();
16701703
xdp_prog = rcu_dereference(tun->xdp_prog);
@@ -1690,67 +1723,48 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
16901723
*/
16911724
if (hdr->gso_type || !xdp_prog) {
16921725
*skb_xdp = 1;
1693-
return __tun_build_skb(alloc_frag, buf, buflen, len, pad, delta);
1726+
return __tun_build_skb(alloc_frag, buf, buflen, len, pad);
16941727
}
16951728

16961729
*skb_xdp = 0;
16971730

16981731
local_bh_disable();
16991732
rcu_read_lock();
17001733
xdp_prog = rcu_dereference(tun->xdp_prog);
1701-
if (xdp_prog && !*skb_xdp) {
1734+
if (xdp_prog) {
17021735
struct xdp_buff xdp;
1703-
void *orig_data;
17041736
u32 act;
17051737

17061738
xdp.data_hard_start = buf;
17071739
xdp.data = buf + pad;
17081740
xdp_set_data_meta_invalid(&xdp);
17091741
xdp.data_end = xdp.data + len;
17101742
xdp.rxq = &tfile->xdp_rxq;
1711-
orig_data = xdp.data;
1712-
act = bpf_prog_run_xdp(xdp_prog, &xdp);
17131743

1714-
switch (act) {
1715-
case XDP_REDIRECT:
1716-
get_page(alloc_frag->page);
1717-
alloc_frag->offset += buflen;
1718-
err = xdp_do_redirect(tun->dev, &xdp, xdp_prog);
1719-
xdp_do_flush_map();
1720-
if (err)
1721-
goto err_redirect;
1722-
goto out;
1723-
case XDP_TX:
1744+
act = bpf_prog_run_xdp(xdp_prog, &xdp);
1745+
if (act == XDP_REDIRECT || act == XDP_TX) {
17241746
get_page(alloc_frag->page);
17251747
alloc_frag->offset += buflen;
1726-
if (tun_xdp_tx(tun->dev, &xdp) < 0)
1727-
goto err_redirect;
1728-
goto out;
1729-
case XDP_PASS:
1730-
delta = orig_data - xdp.data;
1731-
len = xdp.data_end - xdp.data;
1732-
break;
1733-
default:
1734-
bpf_warn_invalid_xdp_action(act);
1735-
/* fall through */
1736-
case XDP_ABORTED:
1737-
trace_xdp_exception(tun->dev, xdp_prog, act);
1738-
/* fall through */
1739-
case XDP_DROP:
1740-
goto out;
17411748
}
1749+
err = tun_xdp_act(tun, xdp_prog, &xdp, act);
1750+
if (err < 0)
1751+
goto err_xdp;
1752+
if (err != XDP_PASS)
1753+
goto out;
1754+
1755+
pad = xdp.data - xdp.data_hard_start;
1756+
len = xdp.data_end - xdp.data;
17421757
}
17431758
rcu_read_unlock();
17441759
local_bh_enable();
17451760

1746-
return __tun_build_skb(alloc_frag, buf, buflen, len, pad, delta);
1761+
return __tun_build_skb(alloc_frag, buf, buflen, len, pad);
17471762

1748-
err_redirect:
1763+
err_xdp:
17491764
put_page(alloc_frag->page);
17501765
out:
17511766
rcu_read_unlock();
17521767
local_bh_enable();
1753-
this_cpu_inc(tun->pcpu_stats->rx_dropped);
17541768
return NULL;
17551769
}
17561770

0 commit comments

Comments
 (0)