summaryrefslogtreecommitdiffstats
path: root/3rdparty/openpgm-svn-r1135/pgm/include/impl/txw.h
blob: 650cd6a68bd03fcb82891f3447fc360419ec8fbf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/* vim:ts=8:sts=4:sw=4:noai:noexpandtab
 * 
 * basic transmit window.
 *
 * Copyright (c) 2006 Miru Limited.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __PGM_IMPL_TXW_H__
#define __PGM_IMPL_TXW_H__

typedef struct pgm_txw_state_t pgm_txw_state_t;
typedef struct pgm_txw_t pgm_txw_t;

#include <impl/framework.h>

PGM_BEGIN_DECLS

/* must be smaller than PGM skbuff control buffer */
struct pgm_txw_state_t {
	uint32_t	unfolded_checksum;	/* first 32-bit word must be checksum */

	unsigned	waiting_retransmit:1;	/* in retransmit queue */
	unsigned	retransmit_count:15;
	unsigned	nak_elimination_count:16;

	uint8_t		pkt_cnt_requested;	/* # parity packets to send */
	uint8_t		pkt_cnt_sent;		/* # parity packets already sent */
};

struct pgm_txw_t {
	const pgm_tsi_t* restrict	tsi;

/* option: lockless atomics */
        volatile uint32_t		lead;
        volatile uint32_t		trail;

        pgm_queue_t			retransmit_queue;

	pgm_rs_t			rs;
	uint8_t				tg_sqn_shift;
	struct pgm_sk_buff_t* restrict	parity_buffer;

/* Advance with data */
	pgm_time_t			adv_ivl_expiry;	
	unsigned			increment_window_naks;
	unsigned			adv_secs;		/* TXW_ADV_SECS */
	unsigned			adv_sqns;		/* TXW_ADV_SECS in sequences */

	unsigned			is_fec_enabled:1;
	unsigned			adv_mode:1;		/* 0 = advance by time, 1 = advance by data */

	size_t				size;			/* window content size in bytes */
	unsigned			alloc;			/* length of pdata[] */
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
/* C99 flexible array, sizeof() invalid */
	struct pgm_sk_buff_t*		pdata[];
#elif !defined(__STDC_VERSION__) || defined(__cplusplus)
/* C90 and older */
	struct pgm_sk_buff_t*		pdata[1];
#else
/* GNU C variable-length object */
	struct pgm_sk_buff_t*   	pdata[0];
#endif
};

PGM_GNUC_INTERNAL pgm_txw_t* pgm_txw_create (const pgm_tsi_t*const, const uint16_t, const uint32_t, const unsigned, const ssize_t, const bool, const uint8_t, const uint8_t) PGM_GNUC_WARN_UNUSED_RESULT;
PGM_GNUC_INTERNAL void pgm_txw_shutdown (pgm_txw_t*const);
PGM_GNUC_INTERNAL void pgm_txw_add (pgm_txw_t*const restrict, struct pgm_sk_buff_t*const restrict);
PGM_GNUC_INTERNAL struct pgm_sk_buff_t* pgm_txw_peek (const pgm_txw_t*const, const uint32_t) PGM_GNUC_WARN_UNUSED_RESULT;
PGM_GNUC_INTERNAL bool pgm_txw_retransmit_push (pgm_txw_t*const, const uint32_t, const bool, const uint8_t) PGM_GNUC_WARN_UNUSED_RESULT;
PGM_GNUC_INTERNAL struct pgm_sk_buff_t* pgm_txw_retransmit_try_peek (pgm_txw_t*const) PGM_GNUC_WARN_UNUSED_RESULT;
PGM_GNUC_INTERNAL void pgm_txw_retransmit_remove_head (pgm_txw_t*const);
PGM_GNUC_INTERNAL uint32_t pgm_txw_get_unfolded_checksum (const struct pgm_sk_buff_t*const) PGM_GNUC_PURE;
PGM_GNUC_INTERNAL void pgm_txw_set_unfolded_checksum (struct pgm_sk_buff_t*const, const uint32_t);
PGM_GNUC_INTERNAL void pgm_txw_inc_retransmit_count (struct pgm_sk_buff_t*const);
PGM_GNUC_INTERNAL bool pgm_txw_retransmit_is_empty (const pgm_txw_t*const) PGM_GNUC_WARN_UNUSED_RESULT;

/* declare for GCC attributes */
static inline size_t pgm_txw_max_length (const pgm_txw_t*const) PGM_GNUC_WARN_UNUSED_RESULT;
static inline uint32_t pgm_txw_length (const pgm_txw_t*const) PGM_GNUC_WARN_UNUSED_RESULT;
static inline size_t pgm_txw_size (const pgm_txw_t*const) PGM_GNUC_WARN_UNUSED_RESULT;
static inline bool pgm_txw_is_empty (const pgm_txw_t* const) PGM_GNUC_WARN_UNUSED_RESULT;
static inline bool pgm_txw_is_full (const pgm_txw_t* const) PGM_GNUC_WARN_UNUSED_RESULT;
static inline uint32_t pgm_txw_lead (const pgm_txw_t* const) PGM_GNUC_WARN_UNUSED_RESULT;
static inline uint32_t pgm_txw_lead_atomic (const pgm_txw_t* const) PGM_GNUC_WARN_UNUSED_RESULT;
static inline uint32_t pgm_txw_next_lead (const pgm_txw_t* const) PGM_GNUC_WARN_UNUSED_RESULT;
static inline uint32_t pgm_txw_trail (const pgm_txw_t* const) PGM_GNUC_WARN_UNUSED_RESULT;
static inline uint32_t pgm_txw_trail_atomic (const pgm_txw_t* const) PGM_GNUC_WARN_UNUSED_RESULT;

static inline
size_t
pgm_txw_max_length (
	const pgm_txw_t*const window
	)
{
	pgm_assert (NULL != window);
	return window->alloc;
}

static inline
uint32_t
pgm_txw_length (
	const pgm_txw_t*const window
	)
{
	pgm_assert (NULL != window);
	return ( 1 + window->lead ) - window->trail;
}

static inline
size_t
pgm_txw_size (
	const pgm_txw_t*const window
	)
{
	pgm_assert (NULL != window);
	return window->size;
}

static inline
bool
pgm_txw_is_empty (
	const pgm_txw_t*const window
	)
{
	pgm_assert (NULL != window);
	return (0 == pgm_txw_length (window));
}

static inline
bool
pgm_txw_is_full (
	const pgm_txw_t*const window
	)
{
	pgm_assert (NULL != window);
	return (pgm_txw_length (window) == pgm_txw_max_length (window));
}

static inline
uint32_t
pgm_txw_lead (
	const pgm_txw_t*const window
	)
{
	pgm_assert (NULL != window);
	return window->lead;
}

/* atomics may rely on global variables and so cannot be defined __pure__ */
static inline
uint32_t
pgm_txw_lead_atomic (
	const pgm_txw_t*const window
	)
{
	pgm_assert (NULL != window);
	return pgm_atomic_read32 (&window->lead);
}

static inline
uint32_t
pgm_txw_next_lead (
	const pgm_txw_t*const window
	)
{
	pgm_assert (NULL != window);
	return (uint32_t)(pgm_txw_lead (window) + 1);
}

static inline
uint32_t
pgm_txw_trail (
	const pgm_txw_t*const window
	)
{
	pgm_assert (NULL != window);
	return window->trail;
}

static inline
uint32_t
pgm_txw_trail_atomic (
	const pgm_txw_t*const window
	)
{
	pgm_assert (NULL != window);
	return pgm_atomic_read32 (&window->trail);
}

PGM_END_DECLS

#endif /* __PGM_IMPL_TXW_H__ */