[Intel-wired-lan] [net-next PATCH v4 1/2] ixgbe: add XDP support for pass and drop actions

William Tu u9012063 at gmail.com
Sat Mar 11 20:05:02 UTC 2017


On Sat, Mar 11, 2017 at 8:48 AM, John Fastabend
<john.fastabend at gmail.com> wrote:
> On 17-03-11 07:49 AM, William Tu wrote:
>> On Fri, Mar 10, 2017 at 11:11 AM, John Fastabend
>> <john.fastabend at gmail.com> wrote:
>>> Basic XDP drop support for ixgbe. Uses READ_ONCE/xchg semantics on XDP
>>> programs instead of rcu primitives as suggested by Daniel Borkmann and
>>> Alex Duyck.
>>>
>>> Signed-off-by: John Fastabend <john.r.fastabend at intel.com>
>>> ---
>
> [...]
>
>>>  /**
>>>   * ixgbe_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf
>>>   * @q_vector: structure containing interrupt and ring information
>>> @@ -2184,6 +2230,7 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
>>>                 union ixgbe_adv_rx_desc *rx_desc;
>>>                 struct ixgbe_rx_buffer *rx_buffer;
>>>                 struct sk_buff *skb;
>>> +               struct xdp_buff xdp;
>>>                 unsigned int size;
>>>
>>>                 /* return some buffers to hardware, one at a time is too slow */
>>> @@ -2205,15 +2252,29 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
>>>
>>>                 rx_buffer = ixgbe_get_rx_buffer(rx_ring, rx_desc, &skb, size);
>>>
>>> -               /* retrieve a buffer from the ring */
>>> -               if (skb)
>>> +               if (!skb) {
>>> +                       xdp.data = page_address(rx_buffer->page) +
>>> +                                               rx_buffer->page_offset;
>>> +                       xdp.data_hard_start = xdp.data -
>>> +                                               ixgbe_rx_offset(rx_ring);
>
> We have ixgbe_rx_offset(rx_ring) headroom to support adding headers.
>
>>> +                       xdp.data_end = xdp.data + size;
>>> +
>>> +                       skb = ixgbe_run_xdp(rx_ring, &xdp);
>>> +               }
>>> +
>>> +               if (IS_ERR(skb)) {
>>> +                       total_rx_packets++;
>>> +                       total_rx_bytes += size;
>>> +                       rx_buffer->pagecnt_bias++;
>>> +               } else if (skb) {
>>>                         ixgbe_add_rx_frag(rx_ring, rx_buffer, skb, size);
>>> -               else if (ring_uses_build_skb(rx_ring))
>>> +               } else if (ring_uses_build_skb(rx_ring)) {
>>>                         skb = ixgbe_build_skb(rx_ring, rx_buffer,
>>> -                                             rx_desc, size);
>>> -               else
>>> +                                             &xdp, rx_desc);
>>> +               } else {
>>>                         skb = ixgbe_construct_skb(rx_ring, rx_buffer,
>>> -                                                 rx_desc, size);
>>> +                                                 &xdp, rx_desc);
>>> +               }
>>>
>>>                 /* exit if we failed to retrieve a buffer */
>>>                 if (!skb) {
>
> [...]
>
>>> +static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
>>> +{
>>> +       int i, frame_size = dev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
>>> +       struct ixgbe_adapter *adapter = netdev_priv(dev);
>>> +       struct bpf_prog *old_prog;
>>> +
>>> +       if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
>>> +               return -EINVAL;
>>> +
>>> +       if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
>>> +               return -EINVAL;
>>> +
>>> +       /* verify ixgbe ring attributes are sufficient for XDP */
>>> +       for (i = 0; i < adapter->num_rx_queues; i++) {
>>> +               struct ixgbe_ring *ring = adapter->rx_ring[i];
>>> +
>>> +               if (ring_is_rsc_enabled(ring))
>>> +                       return -EINVAL;
>>> +
>>> +               if (frame_size > ixgbe_rx_bufsz(ring))
>>> +                       return -EINVAL;
>>> +       }
>>> +
>>> +       old_prog = xchg(&adapter->xdp_prog, prog);
>>> +       for (i = 0; i < adapter->num_rx_queues; i++)
>>> +               xchg(&adapter->rx_ring[i]->xdp_prog, adapter->xdp_prog);
>>> +
>>> +       if (old_prog)
>>> +               bpf_prog_put(old_prog);
>>> +
>>> +       return 0;
>>> +}
>>
>> Since the patch does not support xdp_adjust_head() yet, should we
>> detect and return -EOPNOTSUPP?
>>
>
> It actually should support xdp_adjust_head() :)
>
> At least I tested the xdp tunnel program in ./bpf/samples/ and it worked.
> Also I do a standard test where I push the packet up the stack after adding
> headers and that appears to work although I wonder a bit about some of the
> skb metadata. By working in this case I just use tshark and verify the pkt
> is received with the new header by the stack.
>
>> --William
>
Oh, you're right, that's my mistake. It has adjust head support. thanks!
--William


More information about the Intel-wired-lan mailing list