1*76404edcSAsim Jamshed /*
2*76404edcSAsim Jamshed * TCP free fragment queue for ring buffer - tcp_rb_frag_queue.c/h
3*76404edcSAsim Jamshed *
4*76404edcSAsim Jamshed * EunYoung Jeong
5*76404edcSAsim Jamshed *
6*76404edcSAsim Jamshed * Part of this code borrows Click's simple queue implementation
7*76404edcSAsim Jamshed *
8*76404edcSAsim Jamshed * ============================== Click License =============================
9*76404edcSAsim Jamshed *
10*76404edcSAsim Jamshed * Copyright (c) 1999-2000 Massachusetts Institute of Technology
11*76404edcSAsim Jamshed *
12*76404edcSAsim Jamshed * Permission is hereby granted, free of charge, to any person obtaining a
13*76404edcSAsim Jamshed * copy of this software and associated documentation files (the "Software"),
14*76404edcSAsim Jamshed * to deal in the Software without restriction, subject to the conditions
15*76404edcSAsim Jamshed * listed in the Click LICENSE file. These conditions include: you must
16*76404edcSAsim Jamshed * preserve this copyright notice, and you cannot mention the copyright
17*76404edcSAsim Jamshed * holders in advertising related to the Software without their permission.
18*76404edcSAsim Jamshed * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
19*76404edcSAsim Jamshed * notice is a summary of the Click LICENSE file; the license in that file is
20*76404edcSAsim Jamshed * legally binding.
21*76404edcSAsim Jamshed */
22*76404edcSAsim Jamshed
23*76404edcSAsim Jamshed #include "tcp_rb_frag_queue.h"
24*76404edcSAsim Jamshed #include "debug.h"
25*76404edcSAsim Jamshed
26*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
27*76404edcSAsim Jamshed #ifndef _INDEX_TYPE_
28*76404edcSAsim Jamshed #define _INDEX_TYPE_
29*76404edcSAsim Jamshed typedef uint32_t index_type;
30*76404edcSAsim Jamshed typedef int32_t signed_index_type;
31*76404edcSAsim Jamshed #endif
32*76404edcSAsim Jamshed /*---------------------------------------------------------------------------*/
33*76404edcSAsim Jamshed struct rb_frag_queue
34*76404edcSAsim Jamshed {
35*76404edcSAsim Jamshed index_type _capacity;
36*76404edcSAsim Jamshed volatile index_type _head;
37*76404edcSAsim Jamshed volatile index_type _tail;
38*76404edcSAsim Jamshed
39*76404edcSAsim Jamshed struct fragment_ctx * volatile * _q;
40*76404edcSAsim Jamshed };
41*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
42*76404edcSAsim Jamshed static inline index_type
NextIndex(rb_frag_queue_t rb_fragq,index_type i)43*76404edcSAsim Jamshed NextIndex(rb_frag_queue_t rb_fragq, index_type i)
44*76404edcSAsim Jamshed {
45*76404edcSAsim Jamshed return (i != rb_fragq->_capacity ? i + 1: 0);
46*76404edcSAsim Jamshed }
47*76404edcSAsim Jamshed /*---------------------------------------------------------------------------*/
48*76404edcSAsim Jamshed static inline index_type
PrevIndex(rb_frag_queue_t rb_fragq,index_type i)49*76404edcSAsim Jamshed PrevIndex(rb_frag_queue_t rb_fragq, index_type i)
50*76404edcSAsim Jamshed {
51*76404edcSAsim Jamshed return (i != 0 ? i - 1: rb_fragq->_capacity);
52*76404edcSAsim Jamshed }
53*76404edcSAsim Jamshed /*---------------------------------------------------------------------------*/
54*76404edcSAsim Jamshed static inline void
RBFragMemoryBarrier(struct fragment_ctx * volatile frag,volatile index_type index)55*76404edcSAsim Jamshed RBFragMemoryBarrier(struct fragment_ctx * volatile frag, volatile index_type index)
56*76404edcSAsim Jamshed {
57*76404edcSAsim Jamshed __asm__ volatile("" : : "m" (frag), "m" (index));
58*76404edcSAsim Jamshed }
59*76404edcSAsim Jamshed /*---------------------------------------------------------------------------*/
60*76404edcSAsim Jamshed rb_frag_queue_t
CreateRBFragQueue(int capacity)61*76404edcSAsim Jamshed CreateRBFragQueue(int capacity)
62*76404edcSAsim Jamshed {
63*76404edcSAsim Jamshed rb_frag_queue_t rb_fragq;
64*76404edcSAsim Jamshed
65*76404edcSAsim Jamshed rb_fragq = (rb_frag_queue_t)calloc(1, sizeof(struct rb_frag_queue));
66*76404edcSAsim Jamshed if (!rb_fragq)
67*76404edcSAsim Jamshed return NULL;
68*76404edcSAsim Jamshed
69*76404edcSAsim Jamshed rb_fragq->_q = (struct fragment_ctx **)
70*76404edcSAsim Jamshed calloc(capacity + 1, sizeof(struct fragment_ctx *));
71*76404edcSAsim Jamshed if (!rb_fragq->_q) {
72*76404edcSAsim Jamshed free(rb_fragq);
73*76404edcSAsim Jamshed return NULL;
74*76404edcSAsim Jamshed }
75*76404edcSAsim Jamshed
76*76404edcSAsim Jamshed rb_fragq->_capacity = capacity;
77*76404edcSAsim Jamshed rb_fragq->_head = rb_fragq->_tail = 0;
78*76404edcSAsim Jamshed
79*76404edcSAsim Jamshed return rb_fragq;
80*76404edcSAsim Jamshed }
81*76404edcSAsim Jamshed /*---------------------------------------------------------------------------*/
82*76404edcSAsim Jamshed void
DestroyRBFragQueue(rb_frag_queue_t rb_fragq)83*76404edcSAsim Jamshed DestroyRBFragQueue(rb_frag_queue_t rb_fragq)
84*76404edcSAsim Jamshed {
85*76404edcSAsim Jamshed if (!rb_fragq)
86*76404edcSAsim Jamshed return;
87*76404edcSAsim Jamshed
88*76404edcSAsim Jamshed if (rb_fragq->_q) {
89*76404edcSAsim Jamshed free((void *)rb_fragq->_q);
90*76404edcSAsim Jamshed rb_fragq->_q = NULL;
91*76404edcSAsim Jamshed }
92*76404edcSAsim Jamshed
93*76404edcSAsim Jamshed free(rb_fragq);
94*76404edcSAsim Jamshed }
95*76404edcSAsim Jamshed /*---------------------------------------------------------------------------*/
96*76404edcSAsim Jamshed int
RBFragEnqueue(rb_frag_queue_t rb_fragq,struct fragment_ctx * frag)97*76404edcSAsim Jamshed RBFragEnqueue(rb_frag_queue_t rb_fragq, struct fragment_ctx *frag)
98*76404edcSAsim Jamshed {
99*76404edcSAsim Jamshed index_type h = rb_fragq->_head;
100*76404edcSAsim Jamshed index_type t = rb_fragq->_tail;
101*76404edcSAsim Jamshed index_type nt = NextIndex(rb_fragq, t);
102*76404edcSAsim Jamshed
103*76404edcSAsim Jamshed if (nt != h) {
104*76404edcSAsim Jamshed rb_fragq->_q[t] = frag;
105*76404edcSAsim Jamshed RBFragMemoryBarrier(rb_fragq->_q[t], rb_fragq->_tail);
106*76404edcSAsim Jamshed rb_fragq->_tail = nt;
107*76404edcSAsim Jamshed return 0;
108*76404edcSAsim Jamshed }
109*76404edcSAsim Jamshed
110*76404edcSAsim Jamshed TRACE_ERROR("Exceed capacity of frag queue!\n");
111*76404edcSAsim Jamshed return -1;
112*76404edcSAsim Jamshed }
113*76404edcSAsim Jamshed /*---------------------------------------------------------------------------*/
114*76404edcSAsim Jamshed struct fragment_ctx *
RBFragDequeue(rb_frag_queue_t rb_fragq)115*76404edcSAsim Jamshed RBFragDequeue(rb_frag_queue_t rb_fragq)
116*76404edcSAsim Jamshed {
117*76404edcSAsim Jamshed index_type h = rb_fragq->_head;
118*76404edcSAsim Jamshed index_type t = rb_fragq->_tail;
119*76404edcSAsim Jamshed
120*76404edcSAsim Jamshed if (h != t) {
121*76404edcSAsim Jamshed struct fragment_ctx *frag = rb_fragq->_q[h];
122*76404edcSAsim Jamshed RBFragMemoryBarrier(rb_fragq->_q[h], rb_fragq->_head);
123*76404edcSAsim Jamshed rb_fragq->_head = NextIndex(rb_fragq, h);
124*76404edcSAsim Jamshed assert(frag);
125*76404edcSAsim Jamshed
126*76404edcSAsim Jamshed return frag;
127*76404edcSAsim Jamshed }
128*76404edcSAsim Jamshed
129*76404edcSAsim Jamshed return NULL;
130*76404edcSAsim Jamshed }
131*76404edcSAsim Jamshed /*---------------------------------------------------------------------------*/
132