[ovs-dev] [PATCH v8 08/13] dp-packet: Handle multi-seg mubfs in shift() func.
Eelco Chaudron
echaudro at redhat.com
Mon Jun 18 11:55:33 UTC 2018
On 11 Jun 2018, at 18:21, Tiago Lam wrote:
> In its current implementation dp_packet_shift() is also unaware of
> multi-seg mbufs (that holds data in memory non-contiguously) and
> assumes
> that data exists contiguously in memory, memmove'ing data to perform
> the
> shift.
>
> To add support for multi-seg mbuds a new set of functions was
> introduced, dp_packet_mbuf_shift() and dp_packet_mbuf_write(). These
> functions are used by dp_packet_shift(), when handling multi-seg
> mbufs,
> to shift and write data within a chain of mbufs.
>
> Signed-off-by: Tiago Lam <tiago.lam at intel.com>
> ---
> lib/dp-packet.c | 102
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> lib/dp-packet.h | 8 +++++
> 2 files changed, 110 insertions(+)
>
> diff --git a/lib/dp-packet.c b/lib/dp-packet.c
> index 9f8503e..399fadb 100644
> --- a/lib/dp-packet.c
> +++ b/lib/dp-packet.c
> @@ -294,6 +294,102 @@ dp_packet_prealloc_headroom(struct dp_packet *b,
> size_t size)
> }
> }
>
> +#ifdef DPDK_NETDEV
> +/* Write len data bytes in a mbuf at specified offset.
> + *
> + * 'mbuf', pointer to the destination mbuf where 'ofs' is, and the
> mbuf where
> + * the data will first be written.
> + * 'ofs', the offset within the provided 'mbuf' where 'data' is to be
> written.
> + * 'len', the size of the to be written 'data'.
> + * 'data', pointer to the to be written bytes.
> + *
> + * XXX: This function is the counterpart of the `rte_pktmbuf_read()`
> function
> + * available with DPDK, in the rte_mbuf.h */
> +void
> +dp_packet_mbuf_write(struct rte_mbuf *mbuf, int16_t ofs, uint32_t
> len,
> + const void *data)
> +{
> + char *dst_addr;
> + uint16_t data_len;
> + int len_copy;
> + while (mbuf) {
> + if (len == 0) {
> + break;
> + }
> +
> + dst_addr = rte_pktmbuf_mtod_offset(mbuf, char *, ofs);
> + data_len = MBUF_BUF_END(mbuf->buf_addr, mbuf->buf_len) -
> dst_addr;
> +
> + len_copy = MIN(len, data_len);
> + /* We don't know if 'data' is the result of a
> rte_pktmbuf_read() call,
> + * in which case we may end up writing to the same region of
> memory we
> + * are reading from and overlapping. Hence the use of
> memmove() here */
> + memmove(dst_addr, data, len_copy);
> +
> + data = ((char *) data) + len_copy;
> + len -= len_copy;
> + ofs = 0;
> +
> + mbuf = mbuf->next;
> + }
> +}
> +
> +static void
> +dp_packet_mbuf_shift_(struct rte_mbuf *dbuf, int16_t dst_ofs,
> + const struct rte_mbuf *sbuf, uint16_t src_ofs,
> int len)
> +{
> + char rd[len];
> + const char *wd = rte_pktmbuf_read(sbuf, src_ofs, len, rd);
> +
> + ovs_assert(wd);
> +
This implementation copies the entire packet to a temp buffer and then
copies it back. Would it be "faster" to do a direct memmove, starting
with the last/first segment depending on the direction?
> + dp_packet_mbuf_write(dbuf, dst_ofs, len, wd);
> +}
> +
> +/* Similarly to dp_packet_shift(), shifts the data within the mbufs
> of a
> + * dp_packet of DPBUF_DPDK source by 'delta' bytes.
> + * Caller must make sure of the following conditions:
> + * - When shifting left, delta can't be bigger than the data_len
> available in
> + * the last mbuf;
> + * - When shifting right, delta can't be bigger than the space
> available in the
> + * first mbuf (buf_len - data_off).
> + * Both these conditions guarantee that a shift operation doesn't
> fall outside
> + * the bounds of the existing mbufs, so that the first and last mbufs
> (when
> + * using multi-segment mbufs), remain the same. */
> +static void
> +dp_packet_mbuf_shift(struct dp_packet *b, int delta)
> +{
> + uint16_t src_ofs;
> + int16_t dst_ofs;
> +
> + struct rte_mbuf *mbuf = CONST_CAST(struct rte_mbuf *, &b->mbuf);
> + struct rte_mbuf *tmbuf = rte_pktmbuf_lastseg(mbuf);
> +
> + if (delta < 0) {
> + ovs_assert(-delta <= tmbuf->data_len);
> + } else {
> + ovs_assert(delta < (mbuf->buf_len - mbuf->data_off));
> + }
> +
> + /* Set the destination and source offsets to copy to */
> + dst_ofs = delta;
> + src_ofs = 0;
> +
> + /* Shift data from src mbuf and offset to dst mbuf and offset */
> + dp_packet_mbuf_shift_(mbuf, dst_ofs, mbuf, src_ofs,
> + rte_pktmbuf_pkt_len(mbuf));
> +
> + /* Update mbufs' properties, and if using multi-segment mbufs,
> first and
> + * last mbuf's data_len also needs to be adjusted */
> + mbuf->data_off = mbuf->data_off + dst_ofs;
> +
> + if (mbuf != tmbuf) {
> + tmbuf->data_len += delta;
> + mbuf->data_len -= delta;
> + }
> +}
> +#endif
> +
> /* Shifts all of the data within the allocated space in 'b' by
> 'delta' bytes.
> * For example, a 'delta' of 1 would cause each byte of data to move
> one byte
> * forward (from address 'p' to 'p+1'), and a 'delta' of -1 would
> cause each
> @@ -306,6 +402,12 @@ dp_packet_shift(struct dp_packet *b, int delta)
> : true);
>
> if (delta != 0) {
> +#ifdef DPDK_NETDEV
> + if (b->source == DPBUF_DPDK) {
> + dp_packet_mbuf_shift(b, delta);
> + return;
> + }
> +#endif
> char *dst = (char *) dp_packet_data(b) + delta;
> memmove(dst, dp_packet_data(b), dp_packet_size(b));
> dp_packet_set_data(b, dst);
> diff --git a/lib/dp-packet.h b/lib/dp-packet.h
> index 272597f..4946fa3 100644
> --- a/lib/dp-packet.h
> +++ b/lib/dp-packet.h
> @@ -80,6 +80,11 @@ struct dp_packet {
> };
> };
>
> +#ifdef DPDK_NETDEV
> +#define MBUF_BUF_END(BUF_ADDR, BUF_LEN) \
> + (char *) (((char *) BUF_ADDR) + BUF_LEN)
> +#endif
> +
> static inline void *dp_packet_data(const struct dp_packet *);
> static inline void dp_packet_set_data(struct dp_packet *, void *);
> static inline void *dp_packet_base(const struct dp_packet *);
> @@ -136,6 +141,9 @@ static inline void *dp_packet_at_assert(const
> struct dp_packet *,
> #ifdef DPDK_NETDEV
> static inline void * dp_packet_at_offset(const struct dp_packet *b,
> size_t offset);
> +void
> +dp_packet_mbuf_write(struct rte_mbuf *mbuf, int16_t ofs, uint32_t
> len,
> + const void *data);
> #endif
> static inline void *dp_packet_tail(const struct dp_packet *);
> static inline void *dp_packet_end(const struct dp_packet *);
> --
> 2.7.4
More information about the dev
mailing list