l4p/tcp: fix removing overlapped data 58/20458/5
authorJielong Zhou <jielong.zjl@antfin.com>
Tue, 2 Jul 2019 12:53:44 +0000 (20:53 +0800)
committerKonstantin Ananyev <konstantin.ananyev@intel.com>
Tue, 13 Aug 2019 12:27:56 +0000 (13:27 +0100)
rte_pktmbuf_adj and rte_pktmbuf_trim don't support removing data more than
one segment. We reimplemented these funtions to support removing multiple
segments.

Change-Id: I3e2d48310595ecae0acef0674ea2c78fa1068c5b
Signed-off-by: Jielong Zhou <jielong.zjl@antfin.com>
Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
lib/libtle_l4p/misc.h
lib/libtle_l4p/tcp_ofo.h
lib/libtle_l4p/tcp_rxtx.c

index 8be5dfe..327296f 100644 (file)
@@ -510,6 +510,106 @@ _iovec_to_mbsegs(struct iovec *iv, uint32_t seglen, struct rte_mbuf *mb[],
        return i;
 }
 
+/**
+ * Remove len bytes at the beginning of an mbuf.
+ *
+ * It's an enhancement version of rte_pktmbuf_abj which not support
+ * adjusting length greater than the length of the first segment.
+ *
+ * Returns a pointer to the new mbuf. If the
+ * length is greater than the total length of the mbuf, then the
+ * function will fail and return NULL, without modifying the mbuf.
+ *
+ * @param m
+ *   The packet mbuf.
+ * @param len
+ *   The amount of data to remove (in bytes).
+ * @return
+ *   A pointer to the new start of the data.
+ */
+static inline struct rte_mbuf *
+_rte_pktmbuf_adj(struct rte_mbuf *m, uint32_t len)
+{
+       struct rte_mbuf *next;
+       uint32_t remain, plen;
+       uint16_t segs;
+
+       if (unlikely(len > m->pkt_len))
+               return NULL;
+
+       plen = m->pkt_len;
+       remain = len;
+       segs = m->nb_segs;
+       /* don't free last segment */
+       while (remain >= m->data_len && m->next) {
+               next = m->next;
+               remain -= m->data_len;
+               segs--;
+               rte_pktmbuf_free_seg(m);
+               m = next;
+       }
+
+       if (remain) {
+               m->data_len = (uint16_t)(m->data_len - remain);
+               m->data_off = (uint16_t)(m->data_off + remain);
+       }
+
+       m->pkt_len = plen - len;
+       m->nb_segs = segs;
+       return m;
+}
+
+/**
+ * Remove len bytes of data at the end of the mbuf.
+ *
+ * It's an enhancement version of rte_pktmbuf_trim, which not support
+ * removing length greater than the length of the last segment.
+ *
+ * @param m
+ *   The packet mbuf.
+ * @param len
+ *   The amount of data to remove (in bytes).
+ * @return
+ *   - 0: On success.
+ *   - -1: On error.
+ */
+static inline int
+_rte_pktmbuf_trim(struct rte_mbuf *m, uint32_t len)
+{
+       struct rte_mbuf *last, *next, *tmp;
+       uint32_t remain;
+       uint16_t segs;
+
+       if (unlikely(len > m->pkt_len))
+               return -1;
+
+       tmp = m;
+       /* find the last segment will remain after trim */
+       remain = m->pkt_len - len;
+       while (remain > tmp->data_len) {
+               remain -= tmp->data_len;
+               tmp = tmp->next;
+       }
+
+       /* trim the remained last segment */
+       tmp->data_len = remain;
+
+       /* remove trimmed segments */
+       segs = m->nb_segs;
+       last = tmp;
+       for (tmp = tmp->next; tmp != NULL; tmp = next) {
+               next = tmp->next;
+               rte_pktmbuf_free_seg(tmp);
+               segs--;
+       }
+
+       last->next = NULL;
+       m->pkt_len -= len;
+       m->nb_segs = segs;
+
+       return 0;
+}
+
 #ifdef __cplusplus
 }
 #endif
index 3da388e..9d88266 100644 (file)
@@ -276,7 +276,7 @@ _ofodb_enqueue(struct rte_ring *r, const struct ofodb *db, uint32_t *seq)
                        pkt = db->obj[++i];
                } else {
                        /* pkt is partly overlapped */
-                       rte_pktmbuf_adj(pkt, *seq - begin);
+                       db->obj[i] = _rte_pktmbuf_adj(pkt, *seq - begin);
                        break;
                }
        }
index d1d2a16..a519645 100644 (file)
@@ -973,7 +973,7 @@ rx_ack_listen(struct tle_tcp_stream *s, struct stbl *st,
 }
 
 static inline int
-data_pkt_adjust(const struct tcb *tcb, struct rte_mbuf *mb, uint32_t hlen,
+data_pkt_adjust(const struct tcb *tcb, struct rte_mbuf **mb, uint32_t hlen,
        uint32_t *seqn, uint32_t *plen)
 {
        uint32_t len, n, seq;
@@ -981,7 +981,7 @@ data_pkt_adjust(const struct tcb *tcb, struct rte_mbuf *mb, uint32_t hlen,
        seq = *seqn;
        len = *plen;
 
-       rte_pktmbuf_adj(mb, hlen);
+       rte_pktmbuf_adj(*mb, hlen);
        if (len == 0)
                return -ENODATA;
        /* cut off the start of the packet */
@@ -990,7 +990,7 @@ data_pkt_adjust(const struct tcb *tcb, struct rte_mbuf *mb, uint32_t hlen,
                if (n >= len)
                        return -ENODATA;
 
-               rte_pktmbuf_adj(mb, n);
+               *mb = _rte_pktmbuf_adj(*mb, n);
                *seqn = seq + n;
                *plen = len - n;
        }
@@ -1097,7 +1097,7 @@ rx_fin(struct tle_tcp_stream *s, uint32_t state,
 
        if (plen != 0) {
 
-               ret = data_pkt_adjust(&s->tcb, mb, hlen, &seq, &plen);
+               ret = data_pkt_adjust(&s->tcb, &mb, hlen, &seq, &plen);
                if (ret != 0)
                        return ret;
                if (rx_data_enqueue(s, seq, plen, &mb, 1) != 1)
@@ -1303,7 +1303,7 @@ rx_data_ack(struct tle_tcp_stream *s, struct dack_info *tack,
 
                if (ret == 0) {
                        /* skip duplicate data, if any */
-                       ret = data_pkt_adjust(&s->tcb, mb[i], hlen,
+                       ret = data_pkt_adjust(&s->tcb, &mb[i], hlen,
                                &seq, &plen);
                }