aboutsummaryrefslogtreecommitdiff
path: root/src/fragmentation
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-07-09 16:21:14 +0000
committerChristian Grothoff <christian@grothoff.org>2011-07-09 16:21:14 +0000
commit54a83ae9ffdf895596369a78929a8213fb8d900c (patch)
tree46b208fb2e7ee25a18b27a4eb4ab08fcbb0e2fc4 /src/fragmentation
parent3883c9b973ddcbdc88d9807dbe4252a56ece5f92 (diff)
downloadgnunet-54a83ae9ffdf895596369a78929a8213fb8d900c.tar.gz
gnunet-54a83ae9ffdf895596369a78929a8213fb8d900c.zip
fragging
Diffstat (limited to 'src/fragmentation')
-rw-r--r--src/fragmentation/fragmentation.h7
-rw-r--r--src/fragmentation/fragmentation_new.c143
2 files changed, 146 insertions, 4 deletions
diff --git a/src/fragmentation/fragmentation.h b/src/fragmentation/fragmentation.h
index e9b3faba5..9473fa31a 100644
--- a/src/fragmentation/fragmentation.h
+++ b/src/fragmentation/fragmentation.h
@@ -46,6 +46,13 @@ struct FragmentAcknowledgement
46 46
47 struct GNUNET_MessageHeader header; 47 struct GNUNET_MessageHeader header;
48 48
49 /**
50 * Bits that are being acknowledged, in big-endian.
51 * (bits that are set correspond to fragments that
52 * have not yet been received).
53 */
54 uint64_t bits;
55
49}; 56};
50 57
51 58
diff --git a/src/fragmentation/fragmentation_new.c b/src/fragmentation/fragmentation_new.c
index a95afc4a4..66633e4c1 100644
--- a/src/fragmentation/fragmentation_new.c
+++ b/src/fragmentation/fragmentation_new.c
@@ -48,6 +48,11 @@ struct GNUNET_FRAGMENT_Context
48 struct GNUNET_TIME_Relative delay; 48 struct GNUNET_TIME_Relative delay;
49 49
50 /** 50 /**
51 * Time we transmitted the last message of the last round.
52 */
53 struct GNUNET_TIME_Absolute last_round;
54
55 /**
51 * Message to fragment (allocated at the end of this struct). 56 * Message to fragment (allocated at the end of this struct).
52 */ 57 */
53 const struct GNUNET_MessageHeader *msg; 58 const struct GNUNET_MessageHeader *msg;
@@ -73,6 +78,16 @@ struct GNUNET_FRAGMENT_Context
73 GNUNET_SCHEDULER_TaskIdentifier task; 78 GNUNET_SCHEDULER_TaskIdentifier task;
74 79
75 /** 80 /**
81 * Round-robin selector for the next transmission.
82 */
83 unsigned int next_transmission;
84
85 /**
86 * GNUNET_YES if we are waiting for an ACK.
87 */
88 int wack;
89
90 /**
76 * Target fragment size. 91 * Target fragment size.
77 */ 92 */
78 uint16_t mtu; 93 uint16_t mtu;
@@ -91,8 +106,85 @@ transmit_next (void *cls,
91 const struct GNUNET_SCHEDULER_TaskContext *tc) 106 const struct GNUNET_SCHEDULER_TaskContext *tc)
92{ 107{
93 struct GNUNET_FRAGMENT_Context *fc = cls; 108 struct GNUNET_FRAGMENT_Context *fc = cls;
109 char msg[fc->mtu];
110 const char *mbuf;
111 struct FragmentHeader *fh;
112 struct GNUNET_TIME_Relative delay;
113 unsigned int bit;
114 size_t size;
115 size_t fsize;
116 int wrap;
94 117
95 fc->task = GNUNET_SCHEDULER_NO_TASK; 118 fc->task = GNUNET_SCHEDULER_NO_TASK;
119 if (0 == fc->acks)
120 return; /* all done */
121
122 /* calculate delay */
123 wrap = 0;
124 while (0 == (fc->acks & (1 << fc->next_transmission)))
125 {
126 fc->next_transmission = (fc->next_transmission + 1) % 64;
127 wrap |= (fc->next_transmission == 0);
128 }
129 bit = fc->next_transmission;
130 size = ntohs (fc->msg->size);
131 if (bit == size / (fc->mtu - sizeof (struct FragmentHeader)))
132 fsize = size % (fc->mtu - sizeof (struct FragmentHeader)) + sizeof (struct FragmentHeader);
133 else
134 fsize = fc->mtu;
135 delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker,
136 fsize);
137 if (delay.rel_value > 0)
138 {
139 fc->task = GNUNET_SCHEDULER_add_delayed (GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker,
140 fc->mtu),
141 &transmit_next,
142 fc);
143 return;
144 }
145 fc->next_transmission = (fc->next_transmission + 1) % 64;
146 wrap |= (fc->next_transmission == 0);
147
148 /* assemble fragmentation message */
149 mbuf = (const char*) &fc[1];
150 fh = (struct FragmentHeader*) msg;
151 fh->header.size = htons (fsize);
152 fh->header.type = htons (GNUNET_MESSAGE_TYPE_FRAGMENT);
153 /* FIXME: add specific ID info... */
154 memcpy (&fc[1],
155 &mbuf[bit * (fc->mtu - sizeof (struct FragmentHeader))],
156 fsize - sizeof (struct FragmentHeader));
157 fc->proc (fc->proc_cls, &fh->header);
158 GNUNET_BANDWIDTH_tracker_consume (fc->tracker, fsize);
159 GNUNET_STATISTICS_update (fc->stats,
160 _("Fragments transmitted"),
161 1, GNUNET_NO);
162 if (0 != fc->last_round.abs_value)
163 GNUNET_STATISTICS_update (fc->stats,
164 _("Fragments retransmitted"),
165 1, GNUNET_NO);
166
167 /* select next message to calculate delay */
168 bit = fc->next_transmission;
169 size = ntohs (fc->msg->size);
170 if (bit == size / (fc->mtu - sizeof (struct FragmentHeader)))
171 fsize = size % (fc->mtu - sizeof (struct FragmentHeader));
172 else
173 fsize = fc->mtu;
174 delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker,
175 fsize);
176 if (wrap)
177 {
178 /* full round transmitted wait 2x delay for ACK before going again */
179 delay = GNUNET_TIME_relative_max (GNUNET_TIME_relative_multiply (delay, 2),
180 fc->delay);
181 fc->last_round = GNUNET_TIME_absolute_get ();
182 fc->wack = GNUNET_YES;
183 }
184 fc->task = GNUNET_SCHEDULER_add_delayed (GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker,
185 fc->mtu),
186 &transmit_next,
187 fc);
96} 188}
97 189
98 190
@@ -127,8 +219,14 @@ GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats,
127 size_t size; 219 size_t size;
128 uint64_t bits; 220 uint64_t bits;
129 221
222 GNUNET_STATISTICS_update (stats,
223 _("Messages fragmented"),
224 1, GNUNET_NO);
130 GNUNET_assert (mtu >= 1024 + sizeof (struct FragmentHeader)); 225 GNUNET_assert (mtu >= 1024 + sizeof (struct FragmentHeader));
131 size = ntohs (msg->size); 226 size = ntohs (msg->size);
227 GNUNET_STATISTICS_update (stats,
228 _("Total size of fragmented messages"),
229 size, GNUNET_NO);
132 GNUNET_assert (size > mtu); 230 GNUNET_assert (size > mtu);
133 fc = GNUNET_malloc (sizeof (struct GNUNET_FRAGMENT_Context) + size); 231 fc = GNUNET_malloc (sizeof (struct GNUNET_FRAGMENT_Context) + size);
134 fc->stats = stats; 232 fc->stats = stats;
@@ -145,9 +243,8 @@ GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats,
145 fc->acks = UINT64_MAX; /* set all 64 bit */ 243 fc->acks = UINT64_MAX; /* set all 64 bit */
146 else 244 else
147 fc->acks = (1 << bits) - 1; /* set lowest 'bits' bit */ 245 fc->acks = (1 << bits) - 1; /* set lowest 'bits' bit */
148 fc->task = GNUNET_SCHEDULER_add_delayed (GNUNET_BANDWIDTH_tracker_get_delay (tracker, mtu), 246 fc->task = GNUNET_SCHEDULER_add_now (&transmit_next,
149 &transmit_next, 247 fc);
150 fc);
151 return fc; 248 return fc;
152} 249}
153 250
@@ -167,7 +264,45 @@ int
167GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc, 264GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc,
168 const struct GNUNET_MessageHeader *msg) 265 const struct GNUNET_MessageHeader *msg)
169{ 266{
170 return GNUNET_SYSERR; 267 const struct FragmentAcknowledgement *fa;
268 uint64_t abits;
269 struct GNUNET_TIME_Relative ndelay;
270
271 if (sizeof (struct FragmentAcknowledgement) !=
272 ntohs (msg->size))
273 {
274 GNUNET_break_op (0);
275 return GNUNET_SYSERR;
276 }
277 fa = (const struct FragmentAcknowledgement *) msg;
278 abits = GNUNET_ntohll (fa->bits);
279 /* FIXME: match FA to us... */
280
281 if (GNUNET_YES == fc->wack)
282 {
283 /* normal ACK, can update running average of delay... */
284 fc->wack = GNUNET_NO;
285 ndelay = GNUNET_TIME_absolute_get_duration (fc->last_round);
286 fc->delay.rel_value = (ndelay.rel_value + 3 * fc->delay.rel_value) / 4;
287 }
288
289 fc->acks &= abits;
290 if (0 != fc->acks)
291 {
292 /* more to transmit, do so right now (if tracker permits...) */
293 GNUNET_SCHEDULER_cancel (fc->task);
294 fc->task = GNUNET_SCHEDULER_add_now (&transmit_next,
295 fc);
296 return GNUNET_NO;
297 }
298
299 /* all done */
300 if (fc->task != GNUNET_SCHEDULER_NO_TASK)
301 {
302 GNUNET_SCHEDULER_cancel (fc->task);
303 fc->task = GNUNET_SCHEDULER_NO_TASK;
304 }
305 return GNUNET_OK;
171} 306}
172 307
173 308