176404edcSAsim Jamshed #include <string.h>
276404edcSAsim Jamshed
376404edcSAsim Jamshed #include "memory_mgt.h"
476404edcSAsim Jamshed #include "debug.h"
576404edcSAsim Jamshed #include "tcp_send_buffer.h"
676404edcSAsim Jamshed #include "tcp_sb_queue.h"
776404edcSAsim Jamshed
876404edcSAsim Jamshed #define MAX(a, b) ((a)>(b)?(a):(b))
976404edcSAsim Jamshed #define MIN(a, b) ((a)<(b)?(a):(b))
1076404edcSAsim Jamshed
1176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
1276404edcSAsim Jamshed struct sb_manager
1376404edcSAsim Jamshed {
1476404edcSAsim Jamshed size_t chunk_size;
1576404edcSAsim Jamshed uint32_t cur_num;
1676404edcSAsim Jamshed uint32_t cnum;
1776404edcSAsim Jamshed mem_pool_t mp;
1876404edcSAsim Jamshed sb_queue_t freeq;
1976404edcSAsim Jamshed
2076404edcSAsim Jamshed } sb_manager;
2176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
2276404edcSAsim Jamshed uint32_t
SBGetCurnum(sb_manager_t sbm)2376404edcSAsim Jamshed SBGetCurnum(sb_manager_t sbm)
2476404edcSAsim Jamshed {
2576404edcSAsim Jamshed return sbm->cur_num;
2676404edcSAsim Jamshed }
2776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
2876404edcSAsim Jamshed sb_manager_t
SBManagerCreate(size_t chunk_size,uint8_t disable_rings,uint32_t concurrency)2976404edcSAsim Jamshed SBManagerCreate(size_t chunk_size, uint8_t disable_rings, uint32_t concurrency)
3076404edcSAsim Jamshed {
3176404edcSAsim Jamshed sb_manager_t sbm = (sb_manager_t)calloc(1, sizeof(sb_manager));
3276404edcSAsim Jamshed if (!sbm) {
3376404edcSAsim Jamshed TRACE_ERROR("SBManagerCreate() failed. %s\n", strerror(errno));
3476404edcSAsim Jamshed return NULL;
3576404edcSAsim Jamshed }
3676404edcSAsim Jamshed
3776404edcSAsim Jamshed sbm->chunk_size = chunk_size;
3876404edcSAsim Jamshed sbm->cnum = concurrency;
3976404edcSAsim Jamshed sbm->mp = (mem_pool_t)MPCreate(chunk_size,
4076404edcSAsim Jamshed (uint64_t)chunk_size * (!disable_rings * concurrency),
4176404edcSAsim Jamshed 0);
4276404edcSAsim Jamshed if (!sbm->mp) {
4376404edcSAsim Jamshed TRACE_ERROR("Failed to create mem pool for sb.\n");
4476404edcSAsim Jamshed free(sbm);
4576404edcSAsim Jamshed return NULL;
4676404edcSAsim Jamshed }
4776404edcSAsim Jamshed
4876404edcSAsim Jamshed sbm->freeq = CreateSBQueue(concurrency);
4976404edcSAsim Jamshed if (!sbm->freeq) {
5076404edcSAsim Jamshed TRACE_ERROR("Failed to create free buffer queue.\n");
51*8a941c7eSAsim Jamshed MPDestroy(sbm->mp);
52*8a941c7eSAsim Jamshed free(sbm);
5376404edcSAsim Jamshed return NULL;
5476404edcSAsim Jamshed }
5576404edcSAsim Jamshed
5676404edcSAsim Jamshed return sbm;
5776404edcSAsim Jamshed }
5876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
5976404edcSAsim Jamshed struct tcp_send_buffer *
SBInit(sb_manager_t sbm,uint32_t init_seq)6076404edcSAsim Jamshed SBInit(sb_manager_t sbm, uint32_t init_seq)
6176404edcSAsim Jamshed {
6276404edcSAsim Jamshed struct tcp_send_buffer *buf;
6376404edcSAsim Jamshed
6476404edcSAsim Jamshed /* first try dequeue from free buffer queue */
6576404edcSAsim Jamshed buf = SBDequeue(sbm->freeq);
6676404edcSAsim Jamshed if (!buf) {
6776404edcSAsim Jamshed buf = (struct tcp_send_buffer *)malloc(sizeof(struct tcp_send_buffer));
6876404edcSAsim Jamshed if (!buf) {
6976404edcSAsim Jamshed perror("calloc() for buf");
7076404edcSAsim Jamshed return NULL;
7176404edcSAsim Jamshed }
7276404edcSAsim Jamshed buf->data = MPAllocateChunk(sbm->mp);
7376404edcSAsim Jamshed if (!buf->data) {
7476404edcSAsim Jamshed TRACE_ERROR("Failed to fetch memory chunk for data.\n");
75*8a941c7eSAsim Jamshed free(buf);
7676404edcSAsim Jamshed return NULL;
7776404edcSAsim Jamshed }
7876404edcSAsim Jamshed sbm->cur_num++;
7976404edcSAsim Jamshed }
8076404edcSAsim Jamshed
8176404edcSAsim Jamshed buf->head = buf->data;
8276404edcSAsim Jamshed
8376404edcSAsim Jamshed buf->head_off = buf->tail_off = 0;
8476404edcSAsim Jamshed buf->len = buf->cum_len = 0;
8576404edcSAsim Jamshed buf->size = sbm->chunk_size;
8676404edcSAsim Jamshed
8776404edcSAsim Jamshed buf->init_seq = buf->head_seq = init_seq;
8876404edcSAsim Jamshed
8976404edcSAsim Jamshed return buf;
9076404edcSAsim Jamshed }
9176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
9276404edcSAsim Jamshed void
SBFree(sb_manager_t sbm,struct tcp_send_buffer * buf)9376404edcSAsim Jamshed SBFree(sb_manager_t sbm, struct tcp_send_buffer *buf)
9476404edcSAsim Jamshed {
9576404edcSAsim Jamshed if (!buf)
9676404edcSAsim Jamshed return;
9776404edcSAsim Jamshed
9876404edcSAsim Jamshed SBEnqueue(sbm->freeq, buf);
9976404edcSAsim Jamshed }
10076404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
10176404edcSAsim Jamshed size_t
SBPut(sb_manager_t sbm,struct tcp_send_buffer * buf,const void * data,size_t len)102a5e1a556SAsim Jamshed SBPut(sb_manager_t sbm, struct tcp_send_buffer *buf, const void *data, size_t len)
10376404edcSAsim Jamshed {
10476404edcSAsim Jamshed size_t to_put;
10576404edcSAsim Jamshed
10676404edcSAsim Jamshed if (len <= 0)
10776404edcSAsim Jamshed return 0;
10876404edcSAsim Jamshed
10976404edcSAsim Jamshed /* if no space, return -2 */
11076404edcSAsim Jamshed to_put = MIN(len, buf->size - buf->len);
11176404edcSAsim Jamshed if (to_put <= 0) {
11276404edcSAsim Jamshed return -2;
11376404edcSAsim Jamshed }
11476404edcSAsim Jamshed
11576404edcSAsim Jamshed if (buf->tail_off + to_put < buf->size) {
11676404edcSAsim Jamshed /* if the data fit into the buffer, copy it */
11776404edcSAsim Jamshed memcpy(buf->data + buf->tail_off, data, to_put);
11876404edcSAsim Jamshed buf->tail_off += to_put;
11976404edcSAsim Jamshed } else {
12076404edcSAsim Jamshed /* if buffer overflows, move the existing payload and merge */
12176404edcSAsim Jamshed memmove(buf->data, buf->head, buf->len);
12276404edcSAsim Jamshed buf->head = buf->data;
12376404edcSAsim Jamshed buf->head_off = 0;
12476404edcSAsim Jamshed memcpy(buf->head + buf->len, data, to_put);
12576404edcSAsim Jamshed buf->tail_off = buf->len + to_put;
12676404edcSAsim Jamshed }
12776404edcSAsim Jamshed buf->len += to_put;
12876404edcSAsim Jamshed buf->cum_len += to_put;
12976404edcSAsim Jamshed
13076404edcSAsim Jamshed return to_put;
13176404edcSAsim Jamshed }
13276404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
13376404edcSAsim Jamshed size_t
SBRemove(sb_manager_t sbm,struct tcp_send_buffer * buf,size_t len)13476404edcSAsim Jamshed SBRemove(sb_manager_t sbm, struct tcp_send_buffer *buf, size_t len)
13576404edcSAsim Jamshed {
13676404edcSAsim Jamshed size_t to_remove;
13776404edcSAsim Jamshed
13876404edcSAsim Jamshed if (len <= 0)
13976404edcSAsim Jamshed return 0;
14076404edcSAsim Jamshed
14176404edcSAsim Jamshed to_remove = MIN(len, buf->len);
14276404edcSAsim Jamshed if (to_remove <= 0) {
14376404edcSAsim Jamshed return -2;
14476404edcSAsim Jamshed }
14576404edcSAsim Jamshed
14676404edcSAsim Jamshed buf->head_off += to_remove;
14776404edcSAsim Jamshed buf->head = buf->data + buf->head_off;
14876404edcSAsim Jamshed buf->head_seq += to_remove;
14976404edcSAsim Jamshed buf->len -= to_remove;
15076404edcSAsim Jamshed
15176404edcSAsim Jamshed /* if buffer is empty, move the head to 0 */
15276404edcSAsim Jamshed if (buf->len == 0 && buf->head_off > 0) {
15376404edcSAsim Jamshed buf->head = buf->data;
15476404edcSAsim Jamshed buf->head_off = buf->tail_off = 0;
15576404edcSAsim Jamshed }
15676404edcSAsim Jamshed
15776404edcSAsim Jamshed return to_remove;
15876404edcSAsim Jamshed }
15976404edcSAsim Jamshed /*---------------------------------------------------------------------------*/
160