> > When enabled with DPDK OvS relies on mbufs allocated by mempools to > receive and output data on DPDK ports. Until now, each OvS dp_packet has > only one mbuf associated, which is allocated with the maximum possible > size, taking the MTU into account. This approach, however, doesn't allow > us to increase the allocated size in an mbuf, if needed, since an mbuf > is allocated and initialised upon mempool creation. Thus, in the current > implementatin this is dealt with by calling OVS_NOTEACHED() and > terminating OvS. > > To avoid this, and allow the allocated size to be increased, multiple > mbufs can be linked together, in the multi-segment mbufs approach. Thus, > dp_packet_resize__() has been modified to handle the DPBUF_DPDK case > and > allocate and link new mbufs together as needed. > > Signed-off-by: Tiago Lam <tiago....@intel.com> > --- > lib/dp-packet.c | 84 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 82 insertions(+), 2 deletions(-) > > diff --git a/lib/dp-packet.c b/lib/dp-packet.c > index 7b603c7..6a57c3c 100644 > --- a/lib/dp-packet.c > +++ b/lib/dp-packet.c > @@ -238,8 +238,86 @@ dp_packet_resize__(struct dp_packet *b, size_t > new_headroom, size_t new_tailroom > > switch (b->source) { > case DPBUF_DPDK: > - OVS_NOT_REACHED(); > + { > +#ifdef DPDK_NETDEV
Is it possible for the b->source == DPBUF_DPDK and DPDK_NETDEV to not be defined? If not, the #ifdef can be removed. > + uint16_t max_data_len, nb_segs; > + size_t miss_len; > + size_t head_diff = 0; > + struct rte_mbuf *mbuf, *fmbuf; > + struct rte_mempool *mp; > + > + if (!netdev_dpdk_is_multi_segment_mbufs_enabled()) { > + /* XXX: Handle single mbufs case better */ > + return; > + } > + > + /* Calculate missing length in need of allocation */ > + if (new_headroom != dp_packet_headroom(b)) { > + /* This is a headroom adjustment. Find out how much, if anything > */ > + head_diff = new_headroom - dp_packet_headroom(b); > + > + if (head_diff <= new_tailroom) { > + miss_len = 0; > + } else { > + miss_len = head_diff - new_tailroom; > + } > + } else { > + /* Otherwise this is a tailroom adjustment */ > + miss_len = new_tailroom - dp_packet_tailroom(b); > + } > + > + mbuf = CONST_CAST(struct rte_mbuf *, &b->mbuf); > + /* All new allocated mbuf's max data len is the same */ > + max_data_len = mbuf->buf_len - mbuf->data_off; > + /* Calculate # of needed mbufs to accomodate 'miss_len' */ > + nb_segs = miss_len / max_data_len; > + if (miss_len % max_data_len) { > + nb_segs += 1; > + } > + > + /* Proceed with the allocation of new mbufs */ > + mp = mbuf->pool; > + fmbuf = mbuf; > + mbuf = rte_pktmbuf_lastseg(mbuf); > + > + for (int i = 0; i < nb_segs; i++) { > + /* This takes care of initialising buf_len, data_len and other > + * fields properly */ > + struct dp_packet *pkt = dpdk_buf_alloc(mp); > + mbuf->next = CONST_CAST(struct rte_mbuf *, &pkt->mbuf); > + if (!mbuf->next) { > + /* XXX: Flag a WARN and return an error as this will likely > + * result in undefined behaviour */ > + free_dpdk_buf((struct dp_packet *) fmbuf); > + fmbuf = NULL; > + break; > + } > > + fmbuf->nb_segs += 1; > + > + mbuf = mbuf->next; > + } > + > + /* Deal with headroom. If 'head_diff' calculated above is different > + * than zero (thus, positive) the 'new_headroom' requested is bigger > + * than the currently available headroom and thus, now that the > needed > + * space and mbufs have been allocated, the data needs to be shift > + * right. > + * XXX: Doesn't verify or take into account that new_headroom may > fall > + * outside of an mbuf limits */ > + if (head_diff > 0) { > + new_headroom = dp_packet_headroom(b) + head_diff; > + > + dp_packet_shift(b, head_diff); > + } > + > + new_base = dp_packet_base(b); > + > + break; > +#else > + OVS_NOT_REACHED(); > +#endif > + } > case DPBUF_MALLOC: > if (new_headroom == dp_packet_headroom(b)) { > new_base = xrealloc(dp_packet_base(b), new_allocated); > @@ -263,7 +341,9 @@ dp_packet_resize__(struct dp_packet *b, size_t > new_headroom, size_t new_tailroom > OVS_NOT_REACHED(); > } > > - dp_packet_set_allocated(b, new_allocated); > + if (b->source != DPBUF_DPDK) { > + dp_packet_set_allocated(b, new_allocated); > + } > dp_packet_set_base(b, new_base); > > new_data = (char *) new_base + new_headroom; > -- > 2.7.4 > > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev