176404edcSAsim Jamshed #include <stdio.h>
276404edcSAsim Jamshed #include <stdlib.h>
376404edcSAsim Jamshed #include <stdint.h>
476404edcSAsim Jamshed #include <stdbool.h>
576404edcSAsim Jamshed #include <string.h>
676404edcSAsim Jamshed #include <assert.h>
776404edcSAsim Jamshed #include <errno.h>
876404edcSAsim Jamshed #include <unistd.h>
976404edcSAsim Jamshed #include <sys/uio.h>
1076404edcSAsim Jamshed #include <ctype.h>
1176404edcSAsim Jamshed #include "debug.h"
1276404edcSAsim Jamshed #include "tcp_rb.h"
1376404edcSAsim Jamshed
1476404edcSAsim Jamshed #define FREE(x) do { free(x); x = NULL; } while (0)
1576404edcSAsim Jamshed #ifndef MIN
1676404edcSAsim Jamshed #define MIN(a, b) ((a) < (b) ? (a) : (b))
1776404edcSAsim Jamshed #endif
1876404edcSAsim Jamshed #ifndef MAX
1976404edcSAsim Jamshed #define MAX(a, b) ((a) < (b) ? (b) : (a))
2076404edcSAsim Jamshed #endif
2176404edcSAsim Jamshed
2276404edcSAsim Jamshed #define PRINTF(f, args...) printf("%s:%d: " f, __FILE__, __LINE__, ##args)
2376404edcSAsim Jamshed
2476404edcSAsim Jamshed /* -------------------------------------------------------------------------- */
2576404edcSAsim Jamshed /* Private */
2676404edcSAsim Jamshed /* -------------------------------------------------------------------------- */
2776404edcSAsim Jamshed
2876404edcSAsim Jamshed static inline boff_t
loff2boff(tcprb_t * rb,loff_t loff)2976404edcSAsim Jamshed loff2boff(tcprb_t *rb, loff_t loff)
3076404edcSAsim Jamshed {
3176404edcSAsim Jamshed int woff = loff - rb->head; /* window offset */
3276404edcSAsim Jamshed if (woff < 0 || woff > rb->len)
3376404edcSAsim Jamshed return -1;
3476404edcSAsim Jamshed
3576404edcSAsim Jamshed return (boff_t)((loff + rb->corr) % rb->len);
3676404edcSAsim Jamshed }
3776404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
3876404edcSAsim Jamshed static inline tcpfrag_t *
frags_new(void)3976404edcSAsim Jamshed frags_new(void)
4076404edcSAsim Jamshed {
4176404edcSAsim Jamshed return (tcpfrag_t *)calloc(sizeof(tcpfrag_t), 1);
4276404edcSAsim Jamshed }
4376404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
4476404edcSAsim Jamshed static inline void
frags_del(tcpfrag_t * f)4576404edcSAsim Jamshed frags_del(tcpfrag_t *f)
4676404edcSAsim Jamshed {
4776404edcSAsim Jamshed free(f);
4876404edcSAsim Jamshed }
4976404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
5076404edcSAsim Jamshed static inline void
frags_insert(tcprb_t * rb,tcpfrag_t * f)5176404edcSAsim Jamshed frags_insert(tcprb_t *rb, tcpfrag_t *f)
5276404edcSAsim Jamshed {
5376404edcSAsim Jamshed struct _tcpfrag_t *walk;
5476404edcSAsim Jamshed
5576404edcSAsim Jamshed TAILQ_FOREACH(walk, &rb->frags, link)
5676404edcSAsim Jamshed if (walk->head > f->head) {
5776404edcSAsim Jamshed TAILQ_INSERT_BEFORE(walk, f, link);
5876404edcSAsim Jamshed break;
5976404edcSAsim Jamshed }
6076404edcSAsim Jamshed
6176404edcSAsim Jamshed if (!walk)
6276404edcSAsim Jamshed TAILQ_INSERT_TAIL(&rb->frags, f, link);
6376404edcSAsim Jamshed }
6476404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
6576404edcSAsim Jamshed static inline tcpbufseg_t *
bufseg_new(mem_pool_t mp)6676404edcSAsim Jamshed bufseg_new(mem_pool_t mp)
6776404edcSAsim Jamshed {
6876404edcSAsim Jamshed //return (tcpbufseg_t *)malloc(sizeof(tcpbufseg_t));
6976404edcSAsim Jamshed return (tcpbufseg_t *)MPAllocateChunk(mp);
7076404edcSAsim Jamshed }
7176404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
7276404edcSAsim Jamshed static inline void
bufseg_del(mem_pool_t mp,tcpbufseg_t * b)7376404edcSAsim Jamshed bufseg_del(mem_pool_t mp, tcpbufseg_t *b)
7476404edcSAsim Jamshed {
7576404edcSAsim Jamshed //free(b);
7676404edcSAsim Jamshed MPFreeChunk(mp, b);
7776404edcSAsim Jamshed }
7876404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
7976404edcSAsim Jamshed /* For on-demand buffser segment allocation, the buffer segment queue must
8076404edcSAsim Jamshed * be always traversed in directin of from head to tail */
8176404edcSAsim Jamshed static inline tcpbufseg_t *
buf_first(tcprb_t * rb)8276404edcSAsim Jamshed buf_first(tcprb_t *rb)
8376404edcSAsim Jamshed {
8476404edcSAsim Jamshed tcpbufseg_t *tmp;
8576404edcSAsim Jamshed
8676404edcSAsim Jamshed if ((tmp = TAILQ_FIRST(&rb->bufsegs)))
8776404edcSAsim Jamshed return tmp;
8876404edcSAsim Jamshed
8976404edcSAsim Jamshed if ((rb->lbufsegs == 0) || ((tmp = bufseg_new(rb->mp)) == NULL))
9076404edcSAsim Jamshed return NULL;
9176404edcSAsim Jamshed
9276404edcSAsim Jamshed tmp->id = 0;
9376404edcSAsim Jamshed TAILQ_INSERT_TAIL(&rb->bufsegs, tmp, link);
9476404edcSAsim Jamshed
9576404edcSAsim Jamshed return tmp;
9676404edcSAsim Jamshed }
9776404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
9876404edcSAsim Jamshed static inline tcpbufseg_t *
buf_next(tcprb_t * rb,tcpbufseg_t * buf)9976404edcSAsim Jamshed buf_next(tcprb_t *rb, tcpbufseg_t *buf)
10076404edcSAsim Jamshed {
10176404edcSAsim Jamshed tcpbufseg_t *tmp;
10276404edcSAsim Jamshed
10376404edcSAsim Jamshed if ((tmp = TAILQ_NEXT(buf, link)))
10476404edcSAsim Jamshed return tmp;
10576404edcSAsim Jamshed
10676404edcSAsim Jamshed if ((rb->lbufsegs <= buf->id + 1) || ((tmp = bufseg_new(rb->mp)) == NULL))
10776404edcSAsim Jamshed return NULL;
10876404edcSAsim Jamshed
10976404edcSAsim Jamshed tmp->id = buf->id + 1;
11076404edcSAsim Jamshed TAILQ_INSERT_TAIL(&rb->bufsegs, tmp, link);
11176404edcSAsim Jamshed
11276404edcSAsim Jamshed return tmp;
11376404edcSAsim Jamshed }
11476404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
11576404edcSAsim Jamshed static inline tcpbufseg_t *
buf_getbuf(tcprb_t * rb,boff_t off)11676404edcSAsim Jamshed buf_getbuf(tcprb_t *rb, boff_t off)
11776404edcSAsim Jamshed {
11876404edcSAsim Jamshed tcpbufseg_t *buf;
11976404edcSAsim Jamshed int id = off / UNITBUFSIZE;
12076404edcSAsim Jamshed assert(id >= 0);
12176404edcSAsim Jamshed
12276404edcSAsim Jamshed #if 0
12376404edcSAsim Jamshed int max = rb->len / UNITBUFSIZE;
12476404edcSAsim Jamshed
12576404edcSAsim Jamshed if (max / 2 > id) {
12676404edcSAsim Jamshed buf = TAILQ_FIRST(&rb->bufsegs);
12776404edcSAsim Jamshed while (id--)
12876404edcSAsim Jamshed buf = TAILQ_NEXT(buf, link);
12976404edcSAsim Jamshed } else {
13076404edcSAsim Jamshed buf = TAILQ_LAST(&rb->bufsegs, blist);
13176404edcSAsim Jamshed while (max - ++id)
13276404edcSAsim Jamshed buf = TAILQ_PREV(buf, blist, link);
13376404edcSAsim Jamshed }
13476404edcSAsim Jamshed #else
13576404edcSAsim Jamshed buf = buf_first(rb);
13676404edcSAsim Jamshed while (id--)
13776404edcSAsim Jamshed buf = buf_next(rb, buf);
13876404edcSAsim Jamshed #endif
13976404edcSAsim Jamshed
14076404edcSAsim Jamshed assert(buf);
14176404edcSAsim Jamshed
14276404edcSAsim Jamshed return buf;
14376404edcSAsim Jamshed }
14476404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
14576404edcSAsim Jamshed #define TAILQ_LOOP_NEXT(head, headname, elm, field) \
14676404edcSAsim Jamshed ((*(((struct headname *)((head)->tqh_last))->tqh_last)) == (elm) ? \
14776404edcSAsim Jamshed ((head)->tqh_first) : ((elm)->field.tqe_next))
14876404edcSAsim Jamshed
14976404edcSAsim Jamshed static inline int
buf_try_resize(tcprb_t * rb,int len,loff_t data,int datalen)15076404edcSAsim Jamshed buf_try_resize(tcprb_t *rb, int len, loff_t data, int datalen)
15176404edcSAsim Jamshed {
15276404edcSAsim Jamshed /* FIXME: resizing is temporally disabled because of on-demand buffer
15376404edcSAsim Jamshed * allocation patch */
15476404edcSAsim Jamshed //return 0;
15576404edcSAsim Jamshed
15676404edcSAsim Jamshed assert(rb);
15776404edcSAsim Jamshed assert(rb->len);
15876404edcSAsim Jamshed assert(len % UNITBUFSIZE == 0 || len < 2);
15976404edcSAsim Jamshed
16076404edcSAsim Jamshed int segdiff = (len - rb->len) / UNITBUFSIZE;
16176404edcSAsim Jamshed if (segdiff == 0)
16276404edcSAsim Jamshed return 0;
16376404edcSAsim Jamshed
16476404edcSAsim Jamshed boff_t head = loff2boff(rb, data);
16576404edcSAsim Jamshed boff_t tail = (data + datalen - 1) % rb->len;
16676404edcSAsim Jamshed
16776404edcSAsim Jamshed tcpbufseg_t *headseg = buf_getbuf(rb, head);
16876404edcSAsim Jamshed tcpbufseg_t *tailseg = buf_getbuf(rb, tail);
16976404edcSAsim Jamshed
17076404edcSAsim Jamshed if (segdiff > 0) {
17176404edcSAsim Jamshed /* Expand the buffer */
17276404edcSAsim Jamshed rb->len = len;
17376404edcSAsim Jamshed boff_t new_head = loff2boff(rb, data);
17476404edcSAsim Jamshed rb->corr = (rb->corr + (segdiff * UNITBUFSIZE) - (new_head - head))
17576404edcSAsim Jamshed % rb->len;
17676404edcSAsim Jamshed if (rb->corr < 0)
17776404edcSAsim Jamshed rb->corr += rb->len;
17876404edcSAsim Jamshed
17976404edcSAsim Jamshed if (head > tail && headseg == tailseg) {
18076404edcSAsim Jamshed tcpbufseg_t *seg = bufseg_new(rb->mp);
18176404edcSAsim Jamshed assert(seg);
18276404edcSAsim Jamshed memcpy(&seg->buf[head % UNITBUFSIZE],
18376404edcSAsim Jamshed &headseg->buf[head % UNITBUFSIZE],
18476404edcSAsim Jamshed UNITBUFSIZE - (head % UNITBUFSIZE));
18576404edcSAsim Jamshed TAILQ_INSERT_AFTER(&rb->bufsegs, tailseg, seg, link);
18676404edcSAsim Jamshed headseg = seg;
18776404edcSAsim Jamshed segdiff--;
18876404edcSAsim Jamshed }
18976404edcSAsim Jamshed while (segdiff--) {
19076404edcSAsim Jamshed tcpbufseg_t *seg = bufseg_new(rb->mp);
19176404edcSAsim Jamshed assert(seg);
19276404edcSAsim Jamshed TAILQ_INSERT_AFTER(&rb->bufsegs, tailseg, seg, link);
19376404edcSAsim Jamshed }
19476404edcSAsim Jamshed } else /* if (segdiff < 0) */ {
19576404edcSAsim Jamshed /* Shrink the buffer */
19676404edcSAsim Jamshed tcpbufseg_t *seg;
19776404edcSAsim Jamshed
19876404edcSAsim Jamshed segdiff *= -1;
19976404edcSAsim Jamshed int shrinkable = (rb->len - datalen) / UNITBUFSIZE;
20076404edcSAsim Jamshed int tobeshrank = segdiff;
20176404edcSAsim Jamshed
20276404edcSAsim Jamshed rb->len -= (tobeshrank * UNITBUFSIZE);
20376404edcSAsim Jamshed if (rb->len) {
20476404edcSAsim Jamshed boff_t new_head = loff2boff(rb, data);
20576404edcSAsim Jamshed rb->corr = (rb->corr - (tobeshrank * UNITBUFSIZE) -
20676404edcSAsim Jamshed (new_head - head)) % rb->len;
20776404edcSAsim Jamshed if (rb->corr < 0)
20876404edcSAsim Jamshed rb->corr += rb->len;
20976404edcSAsim Jamshed }
21076404edcSAsim Jamshed
21176404edcSAsim Jamshed if (shrinkable < segdiff) {
21276404edcSAsim Jamshed /* Mark some fragments as empty */
21376404edcSAsim Jamshed loff_t eh = data + rb->len +
21476404edcSAsim Jamshed (UNITBUFSIZE - (loff2boff(rb, data) % UNITBUFSIZE));
21576404edcSAsim Jamshed //loff_t et = eh + (segdiff - shrinkable) * UNITBUFSIZE;
21676404edcSAsim Jamshed loff_t et = data + datalen;
21776404edcSAsim Jamshed
21876404edcSAsim Jamshed struct _tcpfrag_t *f = TAILQ_FIRST(&rb->frags), *new;
21976404edcSAsim Jamshed
22076404edcSAsim Jamshed TAILQ_FOREACH(f, &rb->frags, link) {
22176404edcSAsim Jamshed if (f->tail <= eh)
22276404edcSAsim Jamshed continue;
22376404edcSAsim Jamshed
22476404edcSAsim Jamshed if (f->tail > et) {
22576404edcSAsim Jamshed new = frags_new();
22676404edcSAsim Jamshed new->head = et;
22776404edcSAsim Jamshed new->tail = f->tail;
22876404edcSAsim Jamshed TAILQ_INSERT_AFTER(&rb->frags, f, new, link);
22976404edcSAsim Jamshed
23076404edcSAsim Jamshed f->tail = et;
23176404edcSAsim Jamshed }
23276404edcSAsim Jamshed
23376404edcSAsim Jamshed if (f->head >= eh && f->tail <= et) {
23476404edcSAsim Jamshed f->empty = true;
23576404edcSAsim Jamshed continue;
23676404edcSAsim Jamshed }
23776404edcSAsim Jamshed
23876404edcSAsim Jamshed if (f->head < eh) {
23976404edcSAsim Jamshed new = frags_new();
24076404edcSAsim Jamshed new->head = eh;
24176404edcSAsim Jamshed new->tail = f->tail;
24276404edcSAsim Jamshed TAILQ_INSERT_AFTER(&rb->frags, f, new, link);
24376404edcSAsim Jamshed
24476404edcSAsim Jamshed f->tail = eh;
24576404edcSAsim Jamshed continue;
24676404edcSAsim Jamshed }
24776404edcSAsim Jamshed }
24876404edcSAsim Jamshed
24976404edcSAsim Jamshed /* shrink the buffer */
25076404edcSAsim Jamshed int skip = rb->len / UNITBUFSIZE;
25176404edcSAsim Jamshed for (seg = headseg; seg; ) {
25276404edcSAsim Jamshed if (skip-- <= 0) {
25376404edcSAsim Jamshed TAILQ_REMOVE(&rb->bufsegs, seg, link);
25476404edcSAsim Jamshed bufseg_del(rb->mp, seg);
25576404edcSAsim Jamshed }
25676404edcSAsim Jamshed seg = TAILQ_LOOP_NEXT(&rb->bufsegs, blist, tailseg, link);
25776404edcSAsim Jamshed if (seg == headseg)
25876404edcSAsim Jamshed break;
25976404edcSAsim Jamshed }
26076404edcSAsim Jamshed } else {
26176404edcSAsim Jamshed while (tobeshrank &&
26276404edcSAsim Jamshed (seg = TAILQ_LOOP_NEXT(&rb->bufsegs, blist, tailseg, link))
26376404edcSAsim Jamshed != headseg) {
26476404edcSAsim Jamshed TAILQ_REMOVE(&rb->bufsegs, seg, link);
26576404edcSAsim Jamshed bufseg_del(rb->mp, seg);
26676404edcSAsim Jamshed tobeshrank--;
26776404edcSAsim Jamshed }
26876404edcSAsim Jamshed if (tobeshrank) {
26976404edcSAsim Jamshed assert(tobeshrank == 1);
27076404edcSAsim Jamshed assert((tail % UNITBUFSIZE) < (head % UNITBUFSIZE));
27176404edcSAsim Jamshed memcpy(&tailseg->buf[head % UNITBUFSIZE],
27276404edcSAsim Jamshed &headseg->buf[head % UNITBUFSIZE],
27376404edcSAsim Jamshed UNITBUFSIZE - (head % UNITBUFSIZE));
27476404edcSAsim Jamshed TAILQ_REMOVE(&rb->bufsegs, headseg, link);
27576404edcSAsim Jamshed bufseg_del(rb->mp, headseg);
27676404edcSAsim Jamshed headseg = tailseg;
27776404edcSAsim Jamshed tobeshrank = 0;
27876404edcSAsim Jamshed }
27976404edcSAsim Jamshed }
28076404edcSAsim Jamshed }
28176404edcSAsim Jamshed
28276404edcSAsim Jamshed return 0;
28376404edcSAsim Jamshed }
28476404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
28576404edcSAsim Jamshed /* buf_read() and buf_write() are highly symmetic, so use macro for function
28676404edcSAsim Jamshed * definition to ease code maintenance. */
28776404edcSAsim Jamshed
28876404edcSAsim Jamshed /* TODO: We do not have tailing anymore. simplify these functions */
28976404edcSAsim Jamshed
29076404edcSAsim Jamshed #define MEMCPY_FOR_read(a, b, len) memcpy(a, b, len)
29176404edcSAsim Jamshed #define MEMCPY_FOR_write(a, b, len) memcpy(b, a, len)
29276404edcSAsim Jamshed
29376404edcSAsim Jamshed #define FUNCDEF_BUF_RW(rw) \
29476404edcSAsim Jamshed static inline void \
29576404edcSAsim Jamshed buf_##rw(tcprb_t *rb, uint8_t *buf, int len, loff_t off) \
29676404edcSAsim Jamshed { \
29776404edcSAsim Jamshed tcpbufseg_t *bufseg = NULL; \
29876404edcSAsim Jamshed \
29976404edcSAsim Jamshed assert(rb); \
30076404edcSAsim Jamshed \
30176404edcSAsim Jamshed boff_t from = loff2boff(rb, off); \
30276404edcSAsim Jamshed boff_t to = loff2boff(rb, off + len); \
30376404edcSAsim Jamshed tcpbufseg_t *bufseg_from = buf_getbuf(rb, from); \
30476404edcSAsim Jamshed tcpbufseg_t *bufseg_to = buf_getbuf(rb, to); \
30576404edcSAsim Jamshed \
30676404edcSAsim Jamshed if (from > to) { \
30776404edcSAsim Jamshed off = UNITBUFSIZE - (from % UNITBUFSIZE); \
30876404edcSAsim Jamshed MEMCPY_FOR_##rw(&buf[0], &bufseg_from->buf[from % UNITBUFSIZE], off); \
30976404edcSAsim Jamshed for (bufseg = buf_next(rb, bufseg_from); \
31076404edcSAsim Jamshed bufseg && (bufseg != bufseg_to); \
31176404edcSAsim Jamshed bufseg = buf_next(rb, bufseg)) { \
31276404edcSAsim Jamshed MEMCPY_FOR_##rw(&buf[off], &bufseg->buf[0], UNITBUFSIZE); \
31376404edcSAsim Jamshed off += UNITBUFSIZE; \
31476404edcSAsim Jamshed } \
31576404edcSAsim Jamshed for (bufseg = buf_first(rb); \
31676404edcSAsim Jamshed bufseg && (bufseg != bufseg_to); \
31776404edcSAsim Jamshed bufseg = buf_next(rb, bufseg)) { \
31876404edcSAsim Jamshed MEMCPY_FOR_##rw(&buf[off], &bufseg->buf[0], UNITBUFSIZE); \
31976404edcSAsim Jamshed off += UNITBUFSIZE; \
32076404edcSAsim Jamshed } \
32176404edcSAsim Jamshed MEMCPY_FOR_##rw(&buf[off], &bufseg_to->buf[0], to % UNITBUFSIZE); \
32276404edcSAsim Jamshed } else if (bufseg_from == bufseg_to) { \
32376404edcSAsim Jamshed MEMCPY_FOR_##rw(&buf[0], &bufseg_from->buf[from % UNITBUFSIZE], len); \
32476404edcSAsim Jamshed } else { \
32576404edcSAsim Jamshed off = UNITBUFSIZE - (from % UNITBUFSIZE); \
32676404edcSAsim Jamshed MEMCPY_FOR_##rw(&buf[0], &bufseg_from->buf[from % UNITBUFSIZE], off); \
32776404edcSAsim Jamshed for (bufseg = buf_next(rb, bufseg_from); \
32876404edcSAsim Jamshed bufseg && (bufseg != bufseg_to); \
32976404edcSAsim Jamshed bufseg = buf_next(rb, bufseg)) { \
33076404edcSAsim Jamshed MEMCPY_FOR_##rw(&buf[off], &bufseg->buf[0], UNITBUFSIZE); \
33176404edcSAsim Jamshed off += UNITBUFSIZE; \
33276404edcSAsim Jamshed } \
33376404edcSAsim Jamshed MEMCPY_FOR_##rw(&buf[off], &bufseg_to->buf[0], to % UNITBUFSIZE); \
33476404edcSAsim Jamshed } \
33576404edcSAsim Jamshed }
33676404edcSAsim Jamshed
33776404edcSAsim Jamshed FUNCDEF_BUF_RW(read)
FUNCDEF_BUF_RW(write)33876404edcSAsim Jamshed FUNCDEF_BUF_RW(write)
33976404edcSAsim Jamshed /* -------------------------------------------------------------------------- */
34076404edcSAsim Jamshed /* Public */
34176404edcSAsim Jamshed /* -------------------------------------------------------------------------- */
34276404edcSAsim Jamshed
34376404edcSAsim Jamshed inline loff_t
34476404edcSAsim Jamshed seq2loff(tcprb_t *rb, uint32_t seq, uint32_t isn)
34576404edcSAsim Jamshed {
34676404edcSAsim Jamshed loff_t off = seq - isn;
34776404edcSAsim Jamshed
34876404edcSAsim Jamshed while (off < rb->head)
34976404edcSAsim Jamshed off += 0x100000000;
35076404edcSAsim Jamshed
35176404edcSAsim Jamshed return off;
35276404edcSAsim Jamshed }
35376404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
35476404edcSAsim Jamshed inline tcprb_t *
tcprb_new(mem_pool_t mp,int len,unsigned buf_mgmt)35576404edcSAsim Jamshed tcprb_new(mem_pool_t mp, int len, unsigned buf_mgmt)
35676404edcSAsim Jamshed {
35776404edcSAsim Jamshed tcprb_t *rb;
35876404edcSAsim Jamshed
35976404edcSAsim Jamshed if (len % UNITBUFSIZE || len < 2)
36076404edcSAsim Jamshed return NULL;
36176404edcSAsim Jamshed
36276404edcSAsim Jamshed if (!(rb = calloc(sizeof(tcprb_t), 1)))
36376404edcSAsim Jamshed return NULL;
36476404edcSAsim Jamshed
36576404edcSAsim Jamshed TAILQ_INIT(&rb->bufsegs);
36676404edcSAsim Jamshed rb->lbufsegs = ((len - 1) / UNITBUFSIZE) + 1;
36776404edcSAsim Jamshed
36876404edcSAsim Jamshed #if 0
36976404edcSAsim Jamshed int i;
37076404edcSAsim Jamshed for (i = 0; i < rb->lbufsegs; i++) {
37176404edcSAsim Jamshed tcpbufseg_t *bufseg = bufseg_new(mp);
37276404edcSAsim Jamshed if (!bufseg) {
37376404edcSAsim Jamshed TAILQ_FOREACH(bufseg, &rb->bufsegs, link)
37476404edcSAsim Jamshed bufseg_del(mp, bufseg);
37576404edcSAsim Jamshed FREE(rb);
37676404edcSAsim Jamshed return NULL;
37776404edcSAsim Jamshed }
37876404edcSAsim Jamshed TAILQ_INSERT_TAIL(&rb->bufsegs, bufseg, link);
37976404edcSAsim Jamshed }
38076404edcSAsim Jamshed #endif
38176404edcSAsim Jamshed
38276404edcSAsim Jamshed rb->buf_mgmt = buf_mgmt;
38376404edcSAsim Jamshed rb->mp = mp;
38476404edcSAsim Jamshed rb->len = rb->metalen = len;
38576404edcSAsim Jamshed TAILQ_INIT(&rb->frags);
38676404edcSAsim Jamshed
38776404edcSAsim Jamshed return rb;
38876404edcSAsim Jamshed }
38976404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
39076404edcSAsim Jamshed inline int
tcprb_del(tcprb_t * rb)39176404edcSAsim Jamshed tcprb_del(tcprb_t *rb)
39276404edcSAsim Jamshed {
39376404edcSAsim Jamshed struct _tcpbufseg_t *bwalk, *bnext;
39476404edcSAsim Jamshed struct _tcpfrag_t *fwalk, *fnext;
39576404edcSAsim Jamshed
39676404edcSAsim Jamshed for (bwalk = TAILQ_FIRST(&rb->bufsegs); bwalk; bwalk = bnext) {
39776404edcSAsim Jamshed bnext = TAILQ_NEXT(bwalk, link);
39876404edcSAsim Jamshed bufseg_del(rb->mp, bwalk);
39976404edcSAsim Jamshed }
40076404edcSAsim Jamshed
40176404edcSAsim Jamshed for (fwalk = TAILQ_FIRST(&rb->frags); fwalk; fwalk = fnext) {
40276404edcSAsim Jamshed fnext = TAILQ_NEXT(fwalk, link);
40376404edcSAsim Jamshed frags_del(fwalk);
40476404edcSAsim Jamshed }
40576404edcSAsim Jamshed
40676404edcSAsim Jamshed FREE(rb);
40776404edcSAsim Jamshed
40876404edcSAsim Jamshed return 0;
40976404edcSAsim Jamshed }
41076404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
41176404edcSAsim Jamshed inline int
tcprb_setpile(tcprb_t * rb,loff_t new)41276404edcSAsim Jamshed tcprb_setpile(tcprb_t *rb, loff_t new)
41376404edcSAsim Jamshed {
41476404edcSAsim Jamshed if (!rb || new > (rb->head + rb->len) || new < rb->head)
41576404edcSAsim Jamshed return -1;
41676404edcSAsim Jamshed
41776404edcSAsim Jamshed tcpfrag_t *cf = TAILQ_FIRST(&rb->frags); /* contiguous buffer seg. */
41876404edcSAsim Jamshed
41976404edcSAsim Jamshed if (!cf || (cf->head != rb->head)) {
42076404edcSAsim Jamshed /* No contiguous buffer seg. */
42176404edcSAsim Jamshed assert(rb->pile == rb->head);
42276404edcSAsim Jamshed return -1;
42376404edcSAsim Jamshed }
42476404edcSAsim Jamshed
42576404edcSAsim Jamshed if (new > cf->tail)
42676404edcSAsim Jamshed return -1;
42776404edcSAsim Jamshed
42876404edcSAsim Jamshed rb->pile = new;
42976404edcSAsim Jamshed
43076404edcSAsim Jamshed return 0;
43176404edcSAsim Jamshed }
43276404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
43376404edcSAsim Jamshed inline int
tcprb_cflen(tcprb_t * rb)43476404edcSAsim Jamshed tcprb_cflen(tcprb_t *rb)
43576404edcSAsim Jamshed {
43676404edcSAsim Jamshed tcpfrag_t *cf = TAILQ_FIRST(&rb->frags); /* contiguous buffer seg. */
43776404edcSAsim Jamshed
43876404edcSAsim Jamshed if (!cf || (cf->head != rb->head))
43976404edcSAsim Jamshed /* No contiguous buffer seg. to taverse */
44076404edcSAsim Jamshed return 0;
44176404edcSAsim Jamshed
44276404edcSAsim Jamshed int cflen = cf->tail - rb->pile; /* length of cf */
44376404edcSAsim Jamshed
44476404edcSAsim Jamshed assert(cflen >= 0);
44576404edcSAsim Jamshed
44676404edcSAsim Jamshed return cflen;
44776404edcSAsim Jamshed }
44876404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
44976404edcSAsim Jamshed inline int
tcprb_ffhead(tcprb_t * rb,int len)45076404edcSAsim Jamshed tcprb_ffhead(tcprb_t *rb, int len)
45176404edcSAsim Jamshed {
45276404edcSAsim Jamshed if (!rb || len < 0)
45376404edcSAsim Jamshed return 0;
45476404edcSAsim Jamshed else if (len == 0)
45576404edcSAsim Jamshed return 0;
45676404edcSAsim Jamshed
45776404edcSAsim Jamshed tcpfrag_t *cf = TAILQ_FIRST(&rb->frags); /* contiguous buffer seg. */
45876404edcSAsim Jamshed
45976404edcSAsim Jamshed if (!cf || (cf->head != rb->head))
46076404edcSAsim Jamshed /* No contiguous buffer seg. to taverse */
46176404edcSAsim Jamshed return 0;
46276404edcSAsim Jamshed
46376404edcSAsim Jamshed int cflen = cf->tail - cf->head; /* length of cf */
46476404edcSAsim Jamshed assert(cflen > 0);
46576404edcSAsim Jamshed
46676404edcSAsim Jamshed int ff = MIN(len, cflen);
46776404edcSAsim Jamshed ff = MIN(ff, rb->pile - rb->head); /* head cannot go further than pile */
46876404edcSAsim Jamshed
46976404edcSAsim Jamshed if (cflen == ff) {
47076404edcSAsim Jamshed /* Fast forward entire contiguous segment */
47176404edcSAsim Jamshed TAILQ_REMOVE(&rb->frags, cf, link);
47276404edcSAsim Jamshed frags_del(cf);
47376404edcSAsim Jamshed } else {
47476404edcSAsim Jamshed cf->head += ff;
47576404edcSAsim Jamshed }
47676404edcSAsim Jamshed
47776404edcSAsim Jamshed rb->head += ff;
47876404edcSAsim Jamshed
47976404edcSAsim Jamshed return ff;
48076404edcSAsim Jamshed }
48176404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
482*05e3289cSYoungGyoun /* return the number of bytes that would be fast forwarded */
483*05e3289cSYoungGyoun inline int
tcprb_fflen(tcprb_t * rb,uint8_t * buf,int len,loff_t off)484*05e3289cSYoungGyoun tcprb_fflen(tcprb_t *rb, uint8_t *buf, int len, loff_t off)
485*05e3289cSYoungGyoun {
486*05e3289cSYoungGyoun if (!rb || !buf || len < 0 ||
487*05e3289cSYoungGyoun off < rb->head || off >= rb->pile + rb->metalen)
488*05e3289cSYoungGyoun return -1;
489*05e3289cSYoungGyoun /* nothing to write or already written */
490*05e3289cSYoungGyoun else if (len == 0 || off + len < rb->pile)
491*05e3289cSYoungGyoun return 0;
492*05e3289cSYoungGyoun
493*05e3289cSYoungGyoun int ff = (off + len) - (rb->head + MIN(rb->len, rb->metalen));
494*05e3289cSYoungGyoun if (ff <= 0)
495*05e3289cSYoungGyoun return 0;
496*05e3289cSYoungGyoun
497*05e3289cSYoungGyoun tcpfrag_t *cf = TAILQ_FIRST(&rb->frags); /* contiguous buffer seg. */
498*05e3289cSYoungGyoun
499*05e3289cSYoungGyoun if (!cf || (cf->head != rb->head))
500*05e3289cSYoungGyoun /* No contiguous buffer seg. to traverse */
501*05e3289cSYoungGyoun return 0;
502*05e3289cSYoungGyoun
503*05e3289cSYoungGyoun int cflen = cf->tail - cf->head; /* length of cf */
504*05e3289cSYoungGyoun assert(cflen > 0);
505*05e3289cSYoungGyoun
506*05e3289cSYoungGyoun int fflen = MIN(len, cflen);
507*05e3289cSYoungGyoun fflen = MIN(ff, rb->pile - rb->head); /* head cannot go further than pile */
508*05e3289cSYoungGyoun
509*05e3289cSYoungGyoun return fflen;
510*05e3289cSYoungGyoun }
511*05e3289cSYoungGyoun /*--------------------------------------------------------------------------*/
51276404edcSAsim Jamshed static inline int
tcprb_get_datalen(tcprb_t * rb)51376404edcSAsim Jamshed tcprb_get_datalen(tcprb_t *rb)
51476404edcSAsim Jamshed {
51576404edcSAsim Jamshed tcpfrag_t *lastfrag = TAILQ_LAST(&rb->frags, flist);
51676404edcSAsim Jamshed return lastfrag ? (int)(lastfrag->tail - rb->head) : 0;
51776404edcSAsim Jamshed }
51876404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
51976404edcSAsim Jamshed inline int
tcprb_resize_meta(tcprb_t * rb,int len)52076404edcSAsim Jamshed tcprb_resize_meta(tcprb_t *rb, int len)
52176404edcSAsim Jamshed {
52276404edcSAsim Jamshed #ifdef DISABLE_DYN_RESIZE
52376404edcSAsim Jamshed assert(len == 0);
52476404edcSAsim Jamshed
52576404edcSAsim Jamshed struct _tcpfrag_t *fwalk, *fnext;
52676404edcSAsim Jamshed
52776404edcSAsim Jamshed rb->metalen = 0;
52876404edcSAsim Jamshed
52976404edcSAsim Jamshed for (fwalk = TAILQ_FIRST(&rb->frags); fwalk; fwalk = fnext) {
53076404edcSAsim Jamshed fnext = TAILQ_NEXT(fwalk, link);
53176404edcSAsim Jamshed TAILQ_REMOVE(&rb->frags, fwalk, link);
53276404edcSAsim Jamshed frags_del(fwalk);
53376404edcSAsim Jamshed }
53476404edcSAsim Jamshed
53576404edcSAsim Jamshed return 0;
53676404edcSAsim Jamshed #else
53776404edcSAsim Jamshed int diff, ff, datalen;
53876404edcSAsim Jamshed
53976404edcSAsim Jamshed if ((diff = len - rb->metalen) > 0) {
54076404edcSAsim Jamshed rb->metalen = len;
54176404edcSAsim Jamshed } else if (diff < 0) {
54276404edcSAsim Jamshed ff = diff - (rb->len - tcprb_get_datalen(rb));
54376404edcSAsim Jamshed tcprb_ffhead(rb, ff);
54476404edcSAsim Jamshed datalen = tcprb_get_datalen(rb);
54576404edcSAsim Jamshed rb->metalen = MAX(datalen, len);
54676404edcSAsim Jamshed }
54776404edcSAsim Jamshed
54876404edcSAsim Jamshed return rb->metalen;
54976404edcSAsim Jamshed #endif
55076404edcSAsim Jamshed }
55176404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
55276404edcSAsim Jamshed inline int
tcprb_setpolicy(tcprb_t * rb,uint8_t policy)553a834ea89SAsim Jamshed tcprb_setpolicy(tcprb_t *rb, uint8_t policy)
554a834ea89SAsim Jamshed {
555a834ea89SAsim Jamshed if (policy >= MOS_OVERLAP_CNT)
556a834ea89SAsim Jamshed return -1;
557a834ea89SAsim Jamshed
558a834ea89SAsim Jamshed rb->overlap = policy;
559a834ea89SAsim Jamshed return 0;
560a834ea89SAsim Jamshed }
561a834ea89SAsim Jamshed /*--------------------------------------------------------------------------*/
562a834ea89SAsim Jamshed inline int
tcprb_resize(tcprb_t * rb,int len)56376404edcSAsim Jamshed tcprb_resize(tcprb_t *rb, int len)
56476404edcSAsim Jamshed {
56576404edcSAsim Jamshed #ifdef DISABLE_DYN_RESIZE
56676404edcSAsim Jamshed assert(len == 0);
56776404edcSAsim Jamshed
56876404edcSAsim Jamshed struct _tcpbufseg_t *bwalk, *bnext;
56976404edcSAsim Jamshed struct _tcpfrag_t *fwalk, *fnext;
57076404edcSAsim Jamshed
57176404edcSAsim Jamshed rb->metalen = 0;
57276404edcSAsim Jamshed rb->len = 0;
57376404edcSAsim Jamshed
57476404edcSAsim Jamshed for (bwalk = TAILQ_FIRST(&rb->bufsegs); bwalk; bwalk = bnext) {
57576404edcSAsim Jamshed bnext = TAILQ_NEXT(bwalk, link);
57676404edcSAsim Jamshed TAILQ_REMOVE(&rb->bufsegs, bwalk, link);
57776404edcSAsim Jamshed bufseg_del(rb->mp, bwalk);
57876404edcSAsim Jamshed }
57976404edcSAsim Jamshed
58076404edcSAsim Jamshed for (fwalk = TAILQ_FIRST(&rb->frags); fwalk; fwalk = fnext) {
58176404edcSAsim Jamshed fnext = TAILQ_NEXT(fwalk, link);
58276404edcSAsim Jamshed TAILQ_REMOVE(&rb->frags, fwalk, link);
58376404edcSAsim Jamshed frags_del(fwalk);
58476404edcSAsim Jamshed }
58576404edcSAsim Jamshed
58676404edcSAsim Jamshed return 0;
58776404edcSAsim Jamshed #else
58876404edcSAsim Jamshed int diff, ff;
58976404edcSAsim Jamshed
59076404edcSAsim Jamshed if (len % UNITBUFSIZE)
59176404edcSAsim Jamshed return -1;
59276404edcSAsim Jamshed else if (len == rb->len)
59376404edcSAsim Jamshed return 0;
59476404edcSAsim Jamshed
59576404edcSAsim Jamshed if ((diff = rb->len - len) > 0 && /* shrinking */
59676404edcSAsim Jamshed (ff = diff - (rb->len - tcprb_get_datalen(rb))))
59776404edcSAsim Jamshed tcprb_ffhead(rb, ff);
59876404edcSAsim Jamshed
59976404edcSAsim Jamshed return buf_try_resize(rb, len, rb->head,
60076404edcSAsim Jamshed tcprb_get_datalen(rb));
60176404edcSAsim Jamshed #endif
60276404edcSAsim Jamshed }
60376404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
60476404edcSAsim Jamshed inline int
tcprb_ppeek(tcprb_t * rb,uint8_t * buf,int len,loff_t off)60576404edcSAsim Jamshed tcprb_ppeek(tcprb_t *rb, uint8_t *buf, int len, loff_t off)
60676404edcSAsim Jamshed {
60776404edcSAsim Jamshed struct _tcpfrag_t *f;
60876404edcSAsim Jamshed
60976404edcSAsim Jamshed if (!rb || rb->buf_mgmt != BUFMGMT_FULL || !buf || len < 0)
61076404edcSAsim Jamshed return -1;
61176404edcSAsim Jamshed else if (len == 0)
61276404edcSAsim Jamshed return 0;
61376404edcSAsim Jamshed
61476404edcSAsim Jamshed TAILQ_FOREACH(f, &rb->frags, link)
61576404edcSAsim Jamshed if (off >= f->head && off < f->tail) {
61676404edcSAsim Jamshed if (f->empty)
61776404edcSAsim Jamshed f = NULL;
61876404edcSAsim Jamshed break;
61976404edcSAsim Jamshed }
62076404edcSAsim Jamshed
62176404edcSAsim Jamshed if (!f) /* No proper fragment found */
62276404edcSAsim Jamshed return -1;
62376404edcSAsim Jamshed
62476404edcSAsim Jamshed int plen = MIN(len, f->tail - off);
62576404edcSAsim Jamshed
62676404edcSAsim Jamshed buf_read(rb, buf, plen, off);
62776404edcSAsim Jamshed
62876404edcSAsim Jamshed return plen;
62976404edcSAsim Jamshed }
63076404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
63176404edcSAsim Jamshed inline int
tcprb_pwrite(tcprb_t * rb,uint8_t * buf,int len,loff_t off)63276404edcSAsim Jamshed tcprb_pwrite(tcprb_t *rb, uint8_t *buf, int len, loff_t off)
63376404edcSAsim Jamshed {
63476404edcSAsim Jamshed int ff, olen;
63576404edcSAsim Jamshed loff_t efhead = -1; /* head of empty fragment */
63676404edcSAsim Jamshed int eflen = 0; /* length of empty fragment */
63776404edcSAsim Jamshed
638*05e3289cSYoungGyoun /*
639*05e3289cSYoungGyoun * we don't raise MOS_ON_ERROR anymore here,
640*05e3289cSYoungGyoun * (out of receive buffer case is handled at ProcessTCPPayload())
641*05e3289cSYoungGyoun */
64276404edcSAsim Jamshed if (!rb || !buf || len < 0 ||
64376404edcSAsim Jamshed off < rb->head || off >= rb->pile + rb->metalen)
64476404edcSAsim Jamshed return -1;
64576404edcSAsim Jamshed else if (len == 0)
64676404edcSAsim Jamshed return 0;
64776404edcSAsim Jamshed else if (off + len < rb->pile) /* already written */
64876404edcSAsim Jamshed return len;
64976404edcSAsim Jamshed
650*05e3289cSYoungGyoun /* check whether we should move its head offset (fast forward) */
65176404edcSAsim Jamshed olen = len;
65276404edcSAsim Jamshed if ((ff = (off + len) - (rb->head + MIN(rb->len, rb->metalen))) > 0)
65376404edcSAsim Jamshed len -= ff - tcprb_ffhead(rb, ff);
65476404edcSAsim Jamshed if (rb->metalen > rb->len)
65576404edcSAsim Jamshed eflen = MIN(olen - len, rb->metalen - rb->len);
65676404edcSAsim Jamshed if (eflen)
65776404edcSAsim Jamshed efhead = off + len;
65876404edcSAsim Jamshed
65976404edcSAsim Jamshed /* write data */
66076404edcSAsim Jamshed struct _tcpfrag_t *f = TAILQ_FIRST(&rb->frags), *fnext;
66176404edcSAsim Jamshed int uoff = 0; /* offset of `buf` */
66276404edcSAsim Jamshed
66376404edcSAsim Jamshed /* head: position of first byte of the fragment
66476404edcSAsim Jamshed * tail: head + length of the fragment */
66576404edcSAsim Jamshed while (uoff < len) {
66676404edcSAsim Jamshed bool skip = false;
66776404edcSAsim Jamshed int wrlen = 0; /* length to be written */
66876404edcSAsim Jamshed
66976404edcSAsim Jamshed while (f) {
67076404edcSAsim Jamshed struct _tcpfrag_t *ef, *nef;
67176404edcSAsim Jamshed fnext = TAILQ_NEXT(f, link);
67276404edcSAsim Jamshed
67376404edcSAsim Jamshed if (f->empty) {
67476404edcSAsim Jamshed /* skip empty fragment */
67576404edcSAsim Jamshed f = fnext;
67676404edcSAsim Jamshed continue;
67776404edcSAsim Jamshed }
67876404edcSAsim Jamshed
67976404edcSAsim Jamshed if (f->head <= off + uoff) {
68076404edcSAsim Jamshed if (f->tail > off + uoff) {
68176404edcSAsim Jamshed skip = true;
68276404edcSAsim Jamshed wrlen = f->tail - (off + uoff);
68376404edcSAsim Jamshed break;
68476404edcSAsim Jamshed } else if (f->tail == off + uoff) {
68576404edcSAsim Jamshed skip = false;
68676404edcSAsim Jamshed
68776404edcSAsim Jamshed /* shrink empty fragment */
68876404edcSAsim Jamshed for (ef = fnext;
68976404edcSAsim Jamshed ef && ef->empty && ef->head < f->tail + len - uoff;
69076404edcSAsim Jamshed ef = nef) {
69176404edcSAsim Jamshed nef = TAILQ_NEXT(ef, link);
69276404edcSAsim Jamshed
69376404edcSAsim Jamshed if (ef->tail <= f->tail + len - uoff) {
69476404edcSAsim Jamshed TAILQ_REMOVE(&rb->frags, ef, link);
69576404edcSAsim Jamshed } else {
69676404edcSAsim Jamshed ef->head = f->tail + len - uoff;
69776404edcSAsim Jamshed /* break is not necessary, but for early escape */
69876404edcSAsim Jamshed break;
69976404edcSAsim Jamshed }
70076404edcSAsim Jamshed }
70176404edcSAsim Jamshed fnext = TAILQ_NEXT(f, link);
70276404edcSAsim Jamshed
70376404edcSAsim Jamshed wrlen = fnext ? MIN(fnext->head - (off + uoff), len - uoff)
70476404edcSAsim Jamshed : len - uoff;
70576404edcSAsim Jamshed f->tail += wrlen;
70676404edcSAsim Jamshed if (fnext && (f->tail == fnext->head)) {
70776404edcSAsim Jamshed /* merge 'f' and 'fnext' */
70876404edcSAsim Jamshed f->tail = fnext->tail;
70976404edcSAsim Jamshed TAILQ_REMOVE(&rb->frags, fnext, link);
71076404edcSAsim Jamshed frags_del(fnext);
71176404edcSAsim Jamshed }
71276404edcSAsim Jamshed break;
71376404edcSAsim Jamshed }
71476404edcSAsim Jamshed } else if (f->head <= off + len) {
71576404edcSAsim Jamshed skip = false;
71676404edcSAsim Jamshed wrlen = MIN(f->head - (off + uoff), len - uoff);
71776404edcSAsim Jamshed f->head -= wrlen;
71876404edcSAsim Jamshed
71976404edcSAsim Jamshed /* shrink empty fragment */
72076404edcSAsim Jamshed for (ef = TAILQ_PREV(f, flist, link);
72176404edcSAsim Jamshed ef && ef->empty && ef->tail < f->head;
72276404edcSAsim Jamshed ef = nef) {
72376404edcSAsim Jamshed nef = TAILQ_PREV(ef, flist, link);
72476404edcSAsim Jamshed
72576404edcSAsim Jamshed if (ef->head <= f->head) {
72676404edcSAsim Jamshed TAILQ_REMOVE(&rb->frags, ef, link);
72776404edcSAsim Jamshed } else {
72876404edcSAsim Jamshed ef->tail = f->head;
72976404edcSAsim Jamshed /* break is not necessary, but for early escape */
73076404edcSAsim Jamshed break;
73176404edcSAsim Jamshed }
73276404edcSAsim Jamshed }
73376404edcSAsim Jamshed
73476404edcSAsim Jamshed break;
73576404edcSAsim Jamshed } else /* if (f->head > off + len) */ {
73676404edcSAsim Jamshed /* early escape */
73776404edcSAsim Jamshed f = NULL;
73876404edcSAsim Jamshed break;
73976404edcSAsim Jamshed }
74076404edcSAsim Jamshed
74176404edcSAsim Jamshed f = fnext;
74276404edcSAsim Jamshed }
74376404edcSAsim Jamshed
74476404edcSAsim Jamshed if (!f) {
74576404edcSAsim Jamshed struct _tcpfrag_t *new;
74676404edcSAsim Jamshed
74776404edcSAsim Jamshed /* create new fragment and insert it into the list */
74876404edcSAsim Jamshed new = frags_new();
74976404edcSAsim Jamshed
75076404edcSAsim Jamshed new->head = off;
75176404edcSAsim Jamshed new->tail = off + len;
75276404edcSAsim Jamshed wrlen = len;
75376404edcSAsim Jamshed
75476404edcSAsim Jamshed frags_insert(rb, new);
75576404edcSAsim Jamshed }
75676404edcSAsim Jamshed
75776404edcSAsim Jamshed /* copy data */
758a834ea89SAsim Jamshed if ((rb->overlap == MOS_OVERLAP_POLICY_LAST || !skip)
759a834ea89SAsim Jamshed && rb->buf_mgmt)
76076404edcSAsim Jamshed buf_write(rb, &buf[uoff], wrlen, off + uoff);
76176404edcSAsim Jamshed uoff += wrlen;
76276404edcSAsim Jamshed }
76376404edcSAsim Jamshed
76476404edcSAsim Jamshed /* Insert empty fragment if necessary */
76576404edcSAsim Jamshed if (eflen) {
76676404edcSAsim Jamshed assert(rb->metalen > rb->len);
76776404edcSAsim Jamshed
76876404edcSAsim Jamshed struct _tcpfrag_t *new;
76976404edcSAsim Jamshed
77076404edcSAsim Jamshed /* create new fragment and insert it into the list */
77176404edcSAsim Jamshed new = frags_new();
77276404edcSAsim Jamshed
77376404edcSAsim Jamshed new->empty = true;
77476404edcSAsim Jamshed new->head = efhead;
77576404edcSAsim Jamshed new->tail = efhead + eflen;
77676404edcSAsim Jamshed
77776404edcSAsim Jamshed frags_insert(rb, new);
77876404edcSAsim Jamshed }
77976404edcSAsim Jamshed
78076404edcSAsim Jamshed return len;
78176404edcSAsim Jamshed }
78276404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
78376404edcSAsim Jamshed #define PRT_CL_RST "\x1b[0m"
78476404edcSAsim Jamshed #define PRT_FG_BLK "\x1b[30m"
78576404edcSAsim Jamshed #define PRT_FG_RED "\x1b[31m"
78676404edcSAsim Jamshed #define PRT_FG_GRN "\x1b[32m"
78776404edcSAsim Jamshed #define PRT_FG_YEL "\x1b[33m"
78876404edcSAsim Jamshed #define PRT_FG_BLU "\x1b[34m"
78976404edcSAsim Jamshed #define PRT_FG_PUR "\x1b[35m"
79076404edcSAsim Jamshed #define PRT_FG_CYN "\x1b[36m"
79176404edcSAsim Jamshed #define PRT_FG_GRY "\x1b[37m"
79276404edcSAsim Jamshed #define PRT_BG_BLK "\x1b[40m"
79376404edcSAsim Jamshed #define PRT_BG_RED "\x1b[41m"
79476404edcSAsim Jamshed #define PRT_BG_GRN "\x1b[42m"
79576404edcSAsim Jamshed #define PRT_BG_YEL "\x1b[43m"
79676404edcSAsim Jamshed #define PRT_BG_BLU "\x1b[44m"
79776404edcSAsim Jamshed #define PRT_BG_PUR "\x1b[45m"
79876404edcSAsim Jamshed #define PRT_BG_CYN "\x1b[46m"
79976404edcSAsim Jamshed #define PRT_BG_GRY "\x1b[47m"
80076404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
80176404edcSAsim Jamshed inline void
tcprb_printfrags(struct _tcprb_t * rb)80276404edcSAsim Jamshed tcprb_printfrags(struct _tcprb_t *rb)
80376404edcSAsim Jamshed {
80476404edcSAsim Jamshed struct _tcpfrag_t *walk;
80576404edcSAsim Jamshed
80676404edcSAsim Jamshed printf("frags: ");
80776404edcSAsim Jamshed TAILQ_FOREACH(walk, &rb->frags, link) {
80876404edcSAsim Jamshed printf("[%lu - %lu]:'", walk->head, walk->tail - 1);
80976404edcSAsim Jamshed #if 1
81076404edcSAsim Jamshed if (walk->empty)
81176404edcSAsim Jamshed printf("EMPTY");
81276404edcSAsim Jamshed else {
81376404edcSAsim Jamshed loff_t i;
81476404edcSAsim Jamshed for (i = walk->head; i < walk->tail; i++) {
81576404edcSAsim Jamshed tcpbufseg_t *bufseg;
81676404edcSAsim Jamshed boff_t j = loff2boff(rb, i);
81776404edcSAsim Jamshed bufseg = buf_getbuf(rb, j);
81876404edcSAsim Jamshed char c = bufseg->buf[j % UNITBUFSIZE];
81976404edcSAsim Jamshed if (isgraph(c))
82076404edcSAsim Jamshed printf("%c", c);
82176404edcSAsim Jamshed else {
82276404edcSAsim Jamshed printf(PRT_FG_BLU);
82376404edcSAsim Jamshed if (c == ' ')
82476404edcSAsim Jamshed printf(" ");
82576404edcSAsim Jamshed else if (c == '\0')
82676404edcSAsim Jamshed printf("0");
82776404edcSAsim Jamshed else if (c == '\r')
82876404edcSAsim Jamshed printf("R");
82976404edcSAsim Jamshed else if (c == '\n')
83076404edcSAsim Jamshed printf("N");
83176404edcSAsim Jamshed else if (c == '\t')
83276404edcSAsim Jamshed printf("T");
83376404edcSAsim Jamshed else
83476404edcSAsim Jamshed printf("?");
83576404edcSAsim Jamshed printf(PRT_CL_RST);
83676404edcSAsim Jamshed }
83776404edcSAsim Jamshed }
83876404edcSAsim Jamshed }
83976404edcSAsim Jamshed #endif
84076404edcSAsim Jamshed printf("' ");
84176404edcSAsim Jamshed }
84276404edcSAsim Jamshed printf("\n");
84376404edcSAsim Jamshed }
84476404edcSAsim Jamshed inline void
tcprb_printbufsegs(tcprb_t * rb)84576404edcSAsim Jamshed tcprb_printbufsegs(tcprb_t *rb)
84676404edcSAsim Jamshed {
84776404edcSAsim Jamshed struct _tcpbufseg_t *walk;
84876404edcSAsim Jamshed
84976404edcSAsim Jamshed printf("bufsegs: ");
85076404edcSAsim Jamshed TAILQ_FOREACH(walk, &rb->bufsegs, link) {
85176404edcSAsim Jamshed printf("[%d]:'", walk->id);
85276404edcSAsim Jamshed #if 1
85376404edcSAsim Jamshed int j;
85476404edcSAsim Jamshed for (j = 0; j < UNITBUFSIZE; j++) {
85576404edcSAsim Jamshed char c = walk->buf[j];
85676404edcSAsim Jamshed if (isgraph(c))
85776404edcSAsim Jamshed printf("%c", c);
85876404edcSAsim Jamshed else {
85976404edcSAsim Jamshed printf(PRT_FG_BLU);
86076404edcSAsim Jamshed if (c == ' ')
86176404edcSAsim Jamshed printf(" ");
86276404edcSAsim Jamshed else if (c == '\0')
86376404edcSAsim Jamshed printf("0");
86476404edcSAsim Jamshed else if (c == '\r')
86576404edcSAsim Jamshed printf("R");
86676404edcSAsim Jamshed else if (c == '\n')
86776404edcSAsim Jamshed printf("N");
86876404edcSAsim Jamshed else if (c == '\t')
86976404edcSAsim Jamshed printf("T");
87076404edcSAsim Jamshed else
87176404edcSAsim Jamshed printf("?");
87276404edcSAsim Jamshed printf(PRT_CL_RST);
87376404edcSAsim Jamshed }
87476404edcSAsim Jamshed }
87576404edcSAsim Jamshed #endif
87676404edcSAsim Jamshed printf("' ");
87776404edcSAsim Jamshed }
87876404edcSAsim Jamshed printf("\n");
87976404edcSAsim Jamshed }
88076404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
88176404edcSAsim Jamshed inline void
tcprb_printrb(struct _tcprb_t * rb)88276404edcSAsim Jamshed tcprb_printrb(struct _tcprb_t *rb)
88376404edcSAsim Jamshed {
88476404edcSAsim Jamshed printf(" rb: len: %d, meta: %d, "
88576404edcSAsim Jamshed "(head: %ld <= pile: %ld <= tail: %ld)\n ",
88676404edcSAsim Jamshed rb->len, rb->metalen, rb->head, rb->pile, rb->head + rb->metalen);
88776404edcSAsim Jamshed tcprb_printfrags(rb);
88876404edcSAsim Jamshed tcprb_printbufsegs(rb);
88976404edcSAsim Jamshed printf("-------------------------------------------------\n");
89076404edcSAsim Jamshed }
89176404edcSAsim Jamshed /*--------------------------------------------------------------------------*/
892a834ea89SAsim Jamshed inline void
tcp_rb_overlapchk(mtcp_manager_t mtcp,struct pkt_ctx * pctx,struct tcp_stream * recvside_stream)893a834ea89SAsim Jamshed tcp_rb_overlapchk(mtcp_manager_t mtcp, struct pkt_ctx *pctx,
894a834ea89SAsim Jamshed struct tcp_stream *recvside_stream)
895a834ea89SAsim Jamshed {
896a834ea89SAsim Jamshed #define DOESOVERLAP(a1, a2, b1, b2) \
897a834ea89SAsim Jamshed ((a1 != b2) && (a2 != b1) && ((a1 > b2) != (a2 > b1)))
898a834ea89SAsim Jamshed
899a834ea89SAsim Jamshed /* Check whether this packet is retransmitted or not. */
900a834ea89SAsim Jamshed tcprb_t *rb;
901a834ea89SAsim Jamshed struct socket_map *walk;
902a834ea89SAsim Jamshed if (pctx->p.payloadlen > 0 && recvside_stream->rcvvar != NULL
903a834ea89SAsim Jamshed && (rb = recvside_stream->rcvvar->rcvbuf) != NULL) {
904a834ea89SAsim Jamshed struct _tcpfrag_t *f;
905a834ea89SAsim Jamshed loff_t off = seq2loff(rb, pctx->p.seq, recvside_stream->rcvvar->irs + 1);
906a834ea89SAsim Jamshed TAILQ_FOREACH(f, &rb->frags, link)
907a834ea89SAsim Jamshed if (DOESOVERLAP(f->head, f->tail, off, off + pctx->p.payloadlen)) {
908a834ea89SAsim Jamshed /*
909a834ea89SAsim Jamshed * call it immediately (before pkt payload is attached
910a834ea89SAsim Jamshed * to the tcp ring buffer)
911a834ea89SAsim Jamshed */
912*05e3289cSYoungGyoun if (recvside_stream->side == MOS_SIDE_CLI) {
913*05e3289cSYoungGyoun SOCKQ_FOREACH_REVERSE(walk, &recvside_stream->msocks) {
914*05e3289cSYoungGyoun HandleCallback(mtcp, MOS_HK_RCV, walk,
915*05e3289cSYoungGyoun recvside_stream->side,
916*05e3289cSYoungGyoun pctx, MOS_ON_REXMIT);
917*05e3289cSYoungGyoun } SOCKQ_FOREACH_END;
918*05e3289cSYoungGyoun } else { /* recvside_stream->side == MOS_SIDE_SVR */
919a834ea89SAsim Jamshed SOCKQ_FOREACH_START(walk, &recvside_stream->msocks) {
920a834ea89SAsim Jamshed HandleCallback(mtcp, MOS_HK_RCV, walk,
921a834ea89SAsim Jamshed recvside_stream->side,
922a834ea89SAsim Jamshed pctx, MOS_ON_REXMIT);
923a834ea89SAsim Jamshed } SOCKQ_FOREACH_END;
924*05e3289cSYoungGyoun }
925a834ea89SAsim Jamshed /* recvside_stream->cb_events |= MOS_ON_REXMIT; */
926a834ea89SAsim Jamshed TRACE_DBG("RETX!\n");
927a834ea89SAsim Jamshed break;
928a834ea89SAsim Jamshed }
929a834ea89SAsim Jamshed }
930a834ea89SAsim Jamshed }
931a834ea89SAsim Jamshed /*--------------------------------------------------------------------------*/
932