All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Wang, Xiao W" <xiao.w.wang@intel.com>
To: David Marchand <david.marchand@redhat.com>
Cc: Maxime Coquelin <maxime.coquelin@redhat.com>,
	"Xia, Chenbo" <chenbo.xia@intel.com>,
	"Jiang, Cheng1" <cheng1.jiang@intel.com>, dev <dev@dpdk.org>,
	dpdk stable <stable@dpdk.org>
Subject: Re: [dpdk-dev] [PATCH v4] vhost: check header for legacy dequeue offload
Date: Wed, 16 Jun 2021 14:33:34 +0000	[thread overview]
Message-ID: <BN8PR11MB3795E1C00F81051BFC9421B0B80F9@BN8PR11MB3795.namprd11.prod.outlook.com> (raw)
In-Reply-To: <CAJFAV8wNG3O6OPu93cz+pyum74Ns-eh0mfkydos6-w=oyZvk0w@mail.gmail.com>

Hi David,

Thanks for your comments.
I agree with your suggestions. BTW, I notice some other invalid corner cases which need rolling back mbuf->l2_len, l3_len and ol_flag.
E.g. the default case in the "switch {}" context is not valid.
BTW, l4_proto variable is better to be a uint8_t, rather than uint16_t.

I will prepare a new version.

BRs,
Xiao

> -----Original Message-----
> From: David Marchand <david.marchand@redhat.com>
> Sent: Tuesday, June 15, 2021 3:57 PM
> To: Wang, Xiao W <xiao.w.wang@intel.com>
> Cc: Maxime Coquelin <maxime.coquelin@redhat.com>; Xia, Chenbo
> <chenbo.xia@intel.com>; Jiang, Cheng1 <cheng1.jiang@intel.com>; dev
> <dev@dpdk.org>; dpdk stable <stable@dpdk.org>
> Subject: Re: [dpdk-dev] [PATCH v4] vhost: check header for legacy dequeue
> offload
> 
> On Tue, Jun 15, 2021 at 9:06 AM Xiao Wang <xiao.w.wang@intel.com>
> wrote:
> > diff --git a/lib/vhost/virtio_net.c b/lib/vhost/virtio_net.c
> > index 8da8a86a10..351ff0a841 100644
> > --- a/lib/vhost/virtio_net.c
> > +++ b/lib/vhost/virtio_net.c
> > @@ -2259,44 +2259,64 @@ virtio_net_with_host_offload(struct
> virtio_net *dev)
> >         return false;
> >  }
> >
> > -static void
> > -parse_ethernet(struct rte_mbuf *m, uint16_t *l4_proto, void **l4_hdr)
> > +static int
> > +parse_ethernet(struct rte_mbuf *m, uint16_t *l4_proto, void **l4_hdr,
> > +               uint16_t *len)
> >  {
> 
> 
> This function name is misleading, name could be parse_headers().
> Its semantic gets more and more confusing with those l4_hdr and len
> pointers.
> 
> This function fills ->lX_len in the mbuf, everything is available for caller.
> 
> Caller can check that rte_pktmbuf_data_len() is >= m->l2_len +
> m->l3_len + somesize.
> => no need for len.
> 
> l4_hdr can simply be deduced with rte_pktmbuf_mtod_offset(m, struct
> somestruct *, m->l2_len + m->l3_len).
> => no need for l4_hdr.
> 
> 
> >         struct rte_ipv4_hdr *ipv4_hdr;
> >         struct rte_ipv6_hdr *ipv6_hdr;
> >         void *l3_hdr = NULL;
> 
> No need for l3_hdr.
> 
> 
> >         struct rte_ether_hdr *eth_hdr;
> >         uint16_t ethertype;
> > +       uint16_t data_len = m->data_len;
> 
> Avoid direct access to mbuf internals, we have inline helpers:
> rte_pktmbuf_data_len(m).
> 
> 
> > +
> > +       if (data_len <= sizeof(struct rte_ether_hdr))
> 
> Strictly speaking, < is enough.
> 
> 
> > +               return -EINVAL;
> >
> >         eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
> >
> >         m->l2_len = sizeof(struct rte_ether_hdr);
> >         ethertype = rte_be_to_cpu_16(eth_hdr->ether_type);
> > +       data_len -= sizeof(struct rte_ether_hdr);
> 
> No need to decrement data_len if checks below are all done for absolute
> value.
> See suggestions below.
> 
> 
> >
> >         if (ethertype == RTE_ETHER_TYPE_VLAN) {
> > +               if (data_len <= sizeof(struct rte_vlan_hdr))
> > +                       return -EINVAL;
> 
> if (data_len < sizeof(rte_ether_hdr) + sizeof(struct rte_vlan_hdr))
> 
> 
> > +
> >                 struct rte_vlan_hdr *vlan_hdr =
> >                         (struct rte_vlan_hdr *)(eth_hdr + 1);
> >
> >                 m->l2_len += sizeof(struct rte_vlan_hdr);
> >                 ethertype = rte_be_to_cpu_16(vlan_hdr->eth_proto);
> > +               data_len -= sizeof(struct rte_vlan_hdr);
> 
> Idem.
> 
> 
> >         }
> >
> >         l3_hdr = (char *)eth_hdr + m->l2_len;
> >
> >         switch (ethertype) {
> >         case RTE_ETHER_TYPE_IPV4:
> > +               if (data_len <= sizeof(struct rte_ipv4_hdr))
> > +                       return -EINVAL;
> 
> if (data_len < m->l2_len + sizeof(struct rte_ipv4_hdr))
> 
> 
> >                 ipv4_hdr = l3_hdr;
> 
> ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, m->l2_len);
> 
> 
> >                 *l4_proto = ipv4_hdr->next_proto_id;
> >                 m->l3_len = rte_ipv4_hdr_len(ipv4_hdr);
> > +               if (data_len <= m->l3_len) {
> 
> if (data_len < m->l2_len + m->l3_len)
> 
> 
> > +                       m->l3_len = 0;
> > +                       return -EINVAL;
> 
> Returning here leaves m->l2_len set.
> 
> 
> > +               }
> >                 *l4_hdr = (char *)l3_hdr + m->l3_len;
> >                 m->ol_flags |= PKT_TX_IPV4;
> > +               data_len -= m->l3_len;
> >                 break;
> >         case RTE_ETHER_TYPE_IPV6:
> > +               if (data_len <= sizeof(struct rte_ipv6_hdr))
> > +                       return -EINVAL;
> 
> if (data_len < m->l2_len + sizeof(struct rte_ipv6_hdr))
> Returning here leaves m->l2_len set.
> 
> 
> >                 ipv6_hdr = l3_hdr;
> 
> ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *, m->l2_len);
> 
> 
> >                 *l4_proto = ipv6_hdr->proto;
> >                 m->l3_len = sizeof(struct rte_ipv6_hdr);
> >                 *l4_hdr = (char *)l3_hdr + m->l3_len;
> >                 m->ol_flags |= PKT_TX_IPV6;
> > +               data_len -= m->l3_len;
> >                 break;
> >         default:
> >                 m->l3_len = 0;
> > @@ -2304,6 +2324,9 @@ parse_ethernet(struct rte_mbuf *m, uint16_t
> *l4_proto, void **l4_hdr)
> >                 *l4_hdr = NULL;
> >                 break;
> >         }
> > +
> > +       *len = data_len;
> > +       return 0;
> >  }
> >
> >  static __rte_always_inline void
> > @@ -2312,21 +2335,27 @@ vhost_dequeue_offload_legacy(struct
> virtio_net_hdr *hdr, struct rte_mbuf *m)
> >         uint16_t l4_proto = 0;
> >         void *l4_hdr = NULL;
> >         struct rte_tcp_hdr *tcp_hdr = NULL;
> > +       uint16_t len = 0, tcp_len;
> > +
> > +       if (parse_ethernet(m, &l4_proto, &l4_hdr, &len) < 0)
> > +               return;
> >
> > -       parse_ethernet(m, &l4_proto, &l4_hdr);
> >         if (hdr->flags == VIRTIO_NET_HDR_F_NEEDS_CSUM) {
> >                 if (hdr->csum_start == (m->l2_len + m->l3_len)) {
> >                         switch (hdr->csum_offset) {
> >                         case (offsetof(struct rte_tcp_hdr, cksum)):
> > -                               if (l4_proto == IPPROTO_TCP)
> > +                               if (l4_proto == IPPROTO_TCP &&
> > +                                       len >= sizeof(struct rte_tcp_hdr))
> 
> if (rte_pktmbuf_data_len(m) >= m->l2_len + m->l3_len + sizeof(struct
> rte_tcp_hdr))
> Then, if this check is wrong, we leave l2_len, l3_len + PKT_TX_IPVx
> flag set in mbuf.
> 
> These two comments apply to other updates below.
> 
> >                                         m->ol_flags |= PKT_TX_TCP_CKSUM;
> >                                 break;
> >                         case (offsetof(struct rte_udp_hdr, dgram_cksum)):
> > -                               if (l4_proto == IPPROTO_UDP)
> > +                               if (l4_proto == IPPROTO_UDP &&
> > +                                       len >= sizeof(struct rte_udp_hdr))
> >                                         m->ol_flags |= PKT_TX_UDP_CKSUM;
> >                                 break;
> >                         case (offsetof(struct rte_sctp_hdr, cksum)):
> > -                               if (l4_proto == IPPROTO_SCTP)
> > +                               if (l4_proto == IPPROTO_SCTP &&
> > +                                       len >= sizeof(struct rte_sctp_hdr))
> >                                         m->ol_flags |= PKT_TX_SCTP_CKSUM;
> >                                 break;
> >                         default:
> > @@ -2339,12 +2368,21 @@ vhost_dequeue_offload_legacy(struct
> virtio_net_hdr *hdr, struct rte_mbuf *m)
> >                 switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
> >                 case VIRTIO_NET_HDR_GSO_TCPV4:
> >                 case VIRTIO_NET_HDR_GSO_TCPV6:
> > +                       if (l4_proto != IPPROTO_TCP ||
> > +                               len < sizeof(struct rte_tcp_hdr))
> > +                               break;
> >                         tcp_hdr = l4_hdr;
> 
> tcp_hdr = rte_pktmbuf_mtod_offset(m, struct rte_tcp_hdr *, m->l2_len +
> m->l3_len);
> 
> 
> 
> > +                       tcp_len = (tcp_hdr->data_off & 0xf0) >> 2;
> > +                       if (len < tcp_len)
> > +                               break;
> >                         m->ol_flags |= PKT_TX_TCP_SEG;
> >                         m->tso_segsz = hdr->gso_size;
> > -                       m->l4_len = (tcp_hdr->data_off & 0xf0) >> 2;
> > +                       m->l4_len = tcp_len;
> >                         break;
> >                 case VIRTIO_NET_HDR_GSO_UDP:
> > +                       if (l4_proto != IPPROTO_UDP ||
> > +                               len < sizeof(struct rte_udp_hdr))
> > +                               break;
> >                         m->ol_flags |= PKT_TX_UDP_SEG;
> >                         m->tso_segsz = hdr->gso_size;
> >                         m->l4_len = sizeof(struct rte_udp_hdr);
> > --
> > 2.15.1
> >
> 
> 
> --
> David Marchand


  reply	other threads:[~2021-06-16 14:33 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-11  6:38 [dpdk-dev] [PATCH] vhost: add header check in dequeue offload Xiao Wang
2021-03-11 10:38 ` Ananyev, Konstantin
2021-03-12 15:19   ` Wang, Xiao W
2021-03-15 15:32 ` [dpdk-dev] [PATCH v2] " Xiao Wang
2021-03-15 16:17   ` [dpdk-dev] [dpdk-stable] " David Marchand
2021-03-15 18:53     ` Ananyev, Konstantin
2021-03-16  9:13       ` Wang, Xiao W
2021-03-17  6:31 ` [dpdk-dev] [PATCH v3] " Xiao Wang
2021-04-01 12:04   ` David Marchand
2021-04-02  8:38     ` Wang, Xiao W
2021-04-12  9:08       ` Wang, Xiao W
2021-04-12  9:33         ` David Marchand
2021-04-13 14:30           ` Maxime Coquelin
2021-05-08  5:54             ` Wang, Xiao W
2021-06-15  6:35   ` [dpdk-dev] [PATCH v4] vhost: check header for legacy " Xiao Wang
2021-06-15  7:57     ` David Marchand
2021-06-16 14:33       ` Wang, Xiao W [this message]
2021-06-21  8:21   ` [dpdk-dev] [PATCH v5] " Xiao Wang
2021-07-13  9:34     ` Maxime Coquelin
2021-07-20  2:43     ` Xia, Chenbo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=BN8PR11MB3795E1C00F81051BFC9421B0B80F9@BN8PR11MB3795.namprd11.prod.outlook.com \
    --to=xiao.w.wang@intel.com \
    --cc=chenbo.xia@intel.com \
    --cc=cheng1.jiang@intel.com \
    --cc=david.marchand@redhat.com \
    --cc=dev@dpdk.org \
    --cc=maxime.coquelin@redhat.com \
    --cc=stable@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.