Skip to content

Commit

Permalink
l4p/tcp: fix removing overlapped data
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
dillanzhou authored and kananyev committed Aug 13, 2019
1 parent 17f6b7a commit e4380f4
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 6 deletions.
100 changes: 100 additions & 0 deletions lib/libtle_l4p/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/libtle_l4p/tcp_ofo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
10 changes: 5 additions & 5 deletions lib/libtle_l4p/tcp_rxtx.c
Original file line number Diff line number Diff line change
Expand Up @@ -973,15 +973,15 @@ 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;

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 */
Expand All @@ -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;
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}

Expand Down

0 comments on commit e4380f4

Please sign in to comment.