Re: [net-next, PATCH 2/2, v1] net: socionext: add AF_XDP support

2018-09-10 Thread Toshiaki Makita
On 2018/09/11 1:21, Ilias Apalodimas wrote:
>>> @@ -707,6 +731,26 @@ static int netsec_process_rx(struct netsec_priv *priv, 
>>> int budget)
>>> if (unlikely(!buf_addr))
>>> break;
>>>  
>>> +   if (xdp_prog) {
>>> +   xdp_result = netsec_run_xdp(desc, priv, xdp_prog,
>>> +   pkt_len);
>>> +   if (xdp_result != NETSEC_XDP_PASS) {
>>> +   xdp_flush |= xdp_result & NETSEC_XDP_REDIR;
>>> +
>>> +   dma_unmap_single_attrs(priv->dev,
>>> +  desc->dma_addr,
>>> +  desc->len, DMA_TO_DEVICE,
>>> +  DMA_ATTR_SKIP_CPU_SYNC);
>>> +
>>> +   desc->len = desc_len;
>>> +   desc->dma_addr = dma_handle;
>>> +   desc->addr = buf_addr;
>>> +   netsec_rx_fill(priv, idx, 1);
>>> +   nsetsec_adv_desc(&dring->tail);
>>> +   }
>>> +   continue;
>>
>> Continue even on XDP_PASS? Is this really correct?
>>
>> Also seems there is no handling of adjust_head/tail for XDP_PASS case.
>>
> A question on this. Should XDP related frames be allocated using 1 page
> per packet?

AFAIK there is no such constraint, e.g. i40e allocates 1 page per 2 packets.

-- 
Toshiaki Makita



Re: [net-next, PATCH 2/2, v1] net: socionext: add AF_XDP support

2018-09-10 Thread Ilias Apalodimas
> > @@ -707,6 +731,26 @@ static int netsec_process_rx(struct netsec_priv *priv, 
> > int budget)
> > if (unlikely(!buf_addr))
> > break;
> >  
> > +   if (xdp_prog) {
> > +   xdp_result = netsec_run_xdp(desc, priv, xdp_prog,
> > +   pkt_len);
> > +   if (xdp_result != NETSEC_XDP_PASS) {
> > +   xdp_flush |= xdp_result & NETSEC_XDP_REDIR;
> > +
> > +   dma_unmap_single_attrs(priv->dev,
> > +  desc->dma_addr,
> > +  desc->len, DMA_TO_DEVICE,
> > +  DMA_ATTR_SKIP_CPU_SYNC);
> > +
> > +   desc->len = desc_len;
> > +   desc->dma_addr = dma_handle;
> > +   desc->addr = buf_addr;
> > +   netsec_rx_fill(priv, idx, 1);
> > +   nsetsec_adv_desc(&dring->tail);
> > +   }
> > +   continue;
> 
> Continue even on XDP_PASS? Is this really correct?
> 
> Also seems there is no handling of adjust_head/tail for XDP_PASS case.
> 
A question on this. Should XDP related frames be allocated using 1 page
per packet?

Thanks

Ilias


Re: [net-next, PATCH 2/2, v1] net: socionext: add AF_XDP support

2018-09-10 Thread Ilias Apalodimas
On Mon, Sep 10, 2018 at 07:56:49PM +0900, Toshiaki Makita wrote:
> On 2018/09/10 17:24, Ilias Apalodimas wrote:
> > Add basic AF_XDP support without zero-copy
> > 
> > Signed-off-by: Ilias Apalodimas 
> > ---
> ...
> > @@ -707,6 +731,26 @@ static int netsec_process_rx(struct netsec_priv *priv, 
> > int budget)
> > if (unlikely(!buf_addr))
> > break;
> >  
> > +   if (xdp_prog) {
> > +   xdp_result = netsec_run_xdp(desc, priv, xdp_prog,
> > +   pkt_len);
> > +   if (xdp_result != NETSEC_XDP_PASS) {
> > +   xdp_flush |= xdp_result & NETSEC_XDP_REDIR;
> > +
> > +   dma_unmap_single_attrs(priv->dev,
> > +  desc->dma_addr,
> > +  desc->len, DMA_TO_DEVICE,
> > +  DMA_ATTR_SKIP_CPU_SYNC);
> > +
> > +   desc->len = desc_len;
> > +   desc->dma_addr = dma_handle;
> > +   desc->addr = buf_addr;
> > +   netsec_rx_fill(priv, idx, 1);
> > +   nsetsec_adv_desc(&dring->tail);
> > +   }
> > +   continue;
> 
> Continue even on XDP_PASS? Is this really correct?
> 
> Also seems there is no handling of adjust_head/tail for XDP_PASS case.
No continue is wrong there, thanks for the catch. This should return the packet
to the network stack. I'll fix it on v2.

> 
> > +   }
> > +
> > skb = build_skb(desc->addr, desc->len);
> > if (unlikely(!skb)) {
> > dma_unmap_single(priv->dev, dma_handle, desc_len,
> > @@ -740,6 +784,9 @@ static int netsec_process_rx(struct netsec_priv *priv, 
> > int budget)
> > nsetsec_adv_desc(&dring->tail);
> > }
> >  
> > +   if (xdp_flush & NETSEC_XDP_REDIR)
> > +   xdp_do_flush_map();
> > +
> > return done;
> >  }
> ...
> > +static u32 netsec_run_xdp(struct netsec_desc *desc, struct netsec_priv 
> > *priv,
> > + struct bpf_prog *prog, u16 len)
> > +
> > +{
> > +   struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_RX];
> > +   struct xdp_buff xdp;
> > +   u32 ret = NETSEC_XDP_PASS;
> > +   int err;
> > +   u32 act;
> > +
> > +   xdp.data_hard_start = desc->addr;
> > +   xdp.data = desc->addr;
> 
> There is no headroom. REDIRECT using devmap/cpumap will fail due to
> this. Generally we need XDP_PACKET_HEADROOM.
> 
Ok, i'll modify the patch to include XDP_PACKET_HEADROOM
> > +   xdp_set_data_meta_invalid(&xdp);
> > +   xdp.data_end = xdp.data + len;
> > +   xdp.rxq = &dring->xdp_rxq;
> > +
> > +   rcu_read_lock();
> > +   act = bpf_prog_run_xdp(prog, &xdp);
> > +
> > +   switch (act) {
> > +   case XDP_PASS:
> > +   ret = NETSEC_XDP_PASS;
> > +   break;
> > +   case XDP_TX:
> > +   ret = netsec_xmit_xdp(priv, &xdp, desc);
> > +   break;
> > +   case XDP_REDIRECT:
> > +   err = xdp_do_redirect(priv->ndev, &xdp, prog);
> > +   if (!err) {
> > +   ret = NETSEC_XDP_REDIR;
> > +   } else {
> > +   ret = NETSEC_XDP_CONSUMED;
> > +   xdp_return_buff(&xdp);
> > +   }
> > +   break;
> > +   default:
> > +   bpf_warn_invalid_xdp_action(act);
> > +   /* fall through */
> > +   case XDP_ABORTED:
> > +   trace_xdp_exception(priv->ndev, prog, act);
> > +   /* fall through -- handle aborts by dropping packet */
> > +   case XDP_DROP:
> > +   ret = NETSEC_XDP_CONSUMED;
> > +   break;
> > +   }
> > +
> > +   rcu_read_unlock();
> > +
> > +   return ret;
> > +}
> > +
> > +static int netsec_xdp_setup(struct netsec_priv *priv, struct bpf_prog 
> > *prog)
> > +{
> > +   struct net_device *dev = priv->ndev;
> > +   struct bpf_prog *old_prog;
> > +
> > +   /* For now just support only the usual MTU sized frames */
> > +   if (prog && dev->mtu > 1500) {
> > +   netdev_warn(dev, "Jumbo frames not yet supported with XDP\n");
> 
> Why not using extack?
> 
Wasn't aware that this should use the extack for errors. I just saw the same
check on an existing driver and thought that was the way to go
> > +   return -EOPNOTSUPP;
> > +   }
> > +

Thanks for having a look!

/Ilias


Re: [net-next, PATCH 2/2, v1] net: socionext: add AF_XDP support

2018-09-10 Thread Toshiaki Makita
On 2018/09/10 17:24, Ilias Apalodimas wrote:
> Add basic AF_XDP support without zero-copy
> 
> Signed-off-by: Ilias Apalodimas 
> ---
...
> @@ -707,6 +731,26 @@ static int netsec_process_rx(struct netsec_priv *priv, 
> int budget)
>   if (unlikely(!buf_addr))
>   break;
>  
> + if (xdp_prog) {
> + xdp_result = netsec_run_xdp(desc, priv, xdp_prog,
> + pkt_len);
> + if (xdp_result != NETSEC_XDP_PASS) {
> + xdp_flush |= xdp_result & NETSEC_XDP_REDIR;
> +
> + dma_unmap_single_attrs(priv->dev,
> +desc->dma_addr,
> +desc->len, DMA_TO_DEVICE,
> +DMA_ATTR_SKIP_CPU_SYNC);
> +
> + desc->len = desc_len;
> + desc->dma_addr = dma_handle;
> + desc->addr = buf_addr;
> + netsec_rx_fill(priv, idx, 1);
> + nsetsec_adv_desc(&dring->tail);
> + }
> + continue;

Continue even on XDP_PASS? Is this really correct?

Also seems there is no handling of adjust_head/tail for XDP_PASS case.

> + }
> +
>   skb = build_skb(desc->addr, desc->len);
>   if (unlikely(!skb)) {
>   dma_unmap_single(priv->dev, dma_handle, desc_len,
> @@ -740,6 +784,9 @@ static int netsec_process_rx(struct netsec_priv *priv, 
> int budget)
>   nsetsec_adv_desc(&dring->tail);
>   }
>  
> + if (xdp_flush & NETSEC_XDP_REDIR)
> + xdp_do_flush_map();
> +
>   return done;
>  }
...
> +static u32 netsec_run_xdp(struct netsec_desc *desc, struct netsec_priv *priv,
> +   struct bpf_prog *prog, u16 len)
> +
> +{
> + struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_RX];
> + struct xdp_buff xdp;
> + u32 ret = NETSEC_XDP_PASS;
> + int err;
> + u32 act;
> +
> + xdp.data_hard_start = desc->addr;
> + xdp.data = desc->addr;

There is no headroom. REDIRECT using devmap/cpumap will fail due to
this. Generally we need XDP_PACKET_HEADROOM.

> + xdp_set_data_meta_invalid(&xdp);
> + xdp.data_end = xdp.data + len;
> + xdp.rxq = &dring->xdp_rxq;
> +
> + rcu_read_lock();
> + act = bpf_prog_run_xdp(prog, &xdp);
> +
> + switch (act) {
> + case XDP_PASS:
> + ret = NETSEC_XDP_PASS;
> + break;
> + case XDP_TX:
> + ret = netsec_xmit_xdp(priv, &xdp, desc);
> + break;
> + case XDP_REDIRECT:
> + err = xdp_do_redirect(priv->ndev, &xdp, prog);
> + if (!err) {
> + ret = NETSEC_XDP_REDIR;
> + } else {
> + ret = NETSEC_XDP_CONSUMED;
> + xdp_return_buff(&xdp);
> + }
> + break;
> + default:
> + bpf_warn_invalid_xdp_action(act);
> + /* fall through */
> + case XDP_ABORTED:
> + trace_xdp_exception(priv->ndev, prog, act);
> + /* fall through -- handle aborts by dropping packet */
> + case XDP_DROP:
> + ret = NETSEC_XDP_CONSUMED;
> + break;
> + }
> +
> + rcu_read_unlock();
> +
> + return ret;
> +}
> +
> +static int netsec_xdp_setup(struct netsec_priv *priv, struct bpf_prog *prog)
> +{
> + struct net_device *dev = priv->ndev;
> + struct bpf_prog *old_prog;
> +
> + /* For now just support only the usual MTU sized frames */
> + if (prog && dev->mtu > 1500) {
> + netdev_warn(dev, "Jumbo frames not yet supported with XDP\n");

Why not using extack?

> + return -EOPNOTSUPP;
> + }
> +

-- 
Toshiaki Makita



[net-next, PATCH 2/2, v1] net: socionext: add AF_XDP support

2018-09-10 Thread Ilias Apalodimas
Add basic AF_XDP support without zero-copy

Signed-off-by: Ilias Apalodimas 
---
 drivers/net/ethernet/socionext/netsec.c | 211 ++--
 1 file changed, 202 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/socionext/netsec.c 
b/drivers/net/ethernet/socionext/netsec.c
index 666fee2..7464ca6 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -9,6 +9,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include 
 #include 
@@ -238,6 +240,11 @@
 
 #define NETSEC_F_NETSEC_VER_MAJOR_NUM(x)   ((x) & 0x)
 
+#define NETSEC_XDP_PASS  0
+#define NETSEC_XDP_CONSUMED  BIT(0)
+#define NETSEC_XDP_TXBIT(1)
+#define NETSEC_XDP_REDIR BIT(2)
+
 enum ring_id {
NETSEC_RING_TX = 0,
NETSEC_RING_RX
@@ -256,11 +263,13 @@ struct netsec_desc_ring {
void *vaddr;
u16 pkt_cnt;
u16 head, tail;
+   struct xdp_rxq_info xdp_rxq;
 };
 
 struct netsec_priv {
struct netsec_desc_ring desc_ring[NETSEC_RING_MAX];
struct ethtool_coalesce et_coalesce;
+   struct bpf_prog *xdp_prog;
spinlock_t reglock; /* protect reg access */
struct napi_struct napi;
phy_interface_t phy_interface;
@@ -297,6 +306,8 @@ struct netsec_rx_pkt_info {
 };
 
 static void netsec_rx_fill(struct netsec_priv *priv, u16 from, u16 num);
+static u32 netsec_run_xdp(struct netsec_desc *desc, struct netsec_priv *priv,
+ struct bpf_prog *prog, u16 len);
 
 static void *netsec_alloc_rx_data(struct netsec_priv *priv,
  dma_addr_t *dma_addr, u16 *len);
@@ -613,13 +624,23 @@ static int netsec_clean_tx_dring(struct netsec_priv 
*priv, int budget)
 
eop = (entry->attr >> NETSEC_TX_LAST) & 1;
 
-   dma_unmap_single(priv->dev, desc->dma_addr, desc->len,
-DMA_TO_DEVICE);
-   if (eop) {
-   pkts++;
+   if (desc->skb) {
+   dma_unmap_single(priv->dev, desc->dma_addr, desc->len,
+DMA_TO_DEVICE);
+   }
+
+   if (!eop) {
+   *desc = (struct netsec_desc){};
+   continue;
+   }
+
+   if (!desc->skb) {
+   skb_free_frag(desc->addr);
+   } else {
bytes += desc->skb->len;
dev_kfree_skb(desc->skb);
}
+   pkts++;
*desc = (struct netsec_desc){};
}
dring->pkt_cnt -= budget;
@@ -659,8 +680,11 @@ static void nsetsec_adv_desc(u16 *idx)
 static int netsec_process_rx(struct netsec_priv *priv, int budget)
 {
struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_RX];
+   struct bpf_prog *xdp_prog = READ_ONCE(priv->xdp_prog);
struct net_device *ndev = priv->ndev;
-   struct sk_buff *skb;
+   struct sk_buff *skb = NULL;
+   u32 xdp_flush = 0;
+   u32 xdp_result;
int done = 0;
 
while (done < budget) {
@@ -707,6 +731,26 @@ static int netsec_process_rx(struct netsec_priv *priv, int 
budget)
if (unlikely(!buf_addr))
break;
 
+   if (xdp_prog) {
+   xdp_result = netsec_run_xdp(desc, priv, xdp_prog,
+   pkt_len);
+   if (xdp_result != NETSEC_XDP_PASS) {
+   xdp_flush |= xdp_result & NETSEC_XDP_REDIR;
+
+   dma_unmap_single_attrs(priv->dev,
+  desc->dma_addr,
+  desc->len, DMA_TO_DEVICE,
+  DMA_ATTR_SKIP_CPU_SYNC);
+
+   desc->len = desc_len;
+   desc->dma_addr = dma_handle;
+   desc->addr = buf_addr;
+   netsec_rx_fill(priv, idx, 1);
+   nsetsec_adv_desc(&dring->tail);
+   }
+   continue;
+   }
+
skb = build_skb(desc->addr, desc->len);
if (unlikely(!skb)) {
dma_unmap_single(priv->dev, dma_handle, desc_len,
@@ -740,6 +784,9 @@ static int netsec_process_rx(struct netsec_priv *priv, int 
budget)
nsetsec_adv_desc(&dring->tail);
}
 
+   if (xdp_flush & NETSEC_XDP_REDIR)
+   xdp_do_flush_map();
+
return done;
 }
 
@@ -892,6 +939,9 @@ static void netsec_uninit_pkt_dring(struct netsec_priv 
*priv, int id)
if (!dring->vaddr || !dring->desc)
return;
 
+   if (xdp_rxq_info_is_reg(&dring->xdp_rxq))
+   xdp_rxq_info_unreg(&dring-