#include "fragmentation.h"
+/**
+ * Absolute minimum delay we impose between sending and expecting ACK to arrive.
+ */
+#define MIN_ACK_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 1)
+
+
/**
* Fragmentation context.
*/
*/
unsigned int num_rounds;
+ /**
+ * How many transmission have we completed in this round?
+ */
+ unsigned int num_transmissions;
+
/**
* GNUNET_YES if we called 'proc' and are now waiting for 'GNUNET_FRAGMENT_transmission_done'
*/
/**
* Target fragment size.
*/
- uint16_t mtu;
+ uint16_t mtu;
};
GNUNET_assert (GNUNET_NO == fc->proc_busy);
if (0 == fc->acks)
return; /* all done */
-
/* calculate delay */
wrap = 0;
while (0 == (fc->acks & (1LL << fc->next_transmission)))
{
fc->next_transmission = (fc->next_transmission + 1) % 64;
- wrap |= (fc->next_transmission == 0);
+ wrap |= (0 == fc->next_transmission);
}
bit = fc->next_transmission;
size = ntohs (fc->msg->size);
sizeof (struct FragmentHeader);
else
fsize = fc->mtu;
- if (fc->tracker != NULL)
+ if (NULL != fc->tracker)
delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker, fsize);
else
delay = GNUNET_TIME_UNIT_ZERO;
}
fc->next_transmission = (fc->next_transmission + 1) % 64;
wrap |= (fc->next_transmission == 0);
+ while (0 == (fc->acks & (1LL << fc->next_transmission)))
+ {
+ fc->next_transmission = (fc->next_transmission + 1) % 64;
+ wrap |= (fc->next_transmission == 0);
+ }
/* assemble fragmentation message */
mbuf = (const char *) &fc[1];
if (wrap)
{
/* full round transmitted wait 2x delay for ACK before going again */
+ fc->num_rounds++;
delay =
GNUNET_TIME_relative_max (GNUNET_TIME_relative_multiply (delay, 2),
- fc->delay);
+ GNUNET_TIME_relative_multiply (fc->delay,
+ fc->num_rounds));
/* never use zero, need some time for ACK always */
- delay = GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_MILLISECONDS, delay);
- fc->last_round = GNUNET_TIME_absolute_get ();
+ delay = GNUNET_TIME_relative_max (MIN_ACK_DELAY, delay);
fc->wack = GNUNET_YES;
- fc->num_rounds++;
+ fc->last_round = GNUNET_TIME_absolute_get ();
+ GNUNET_STATISTICS_update (fc->stats, _("# fragments wrap arounds"), 1,
+ GNUNET_NO);
}
fc->proc_busy = GNUNET_YES;
fc->delay_until = GNUNET_TIME_relative_to_absolute (delay);
+ fc->num_transmissions++;
fc->proc (fc->proc_cls, &fh->header);
}
struct GNUNET_FRAGMENT_Context *fc;
size_t size;
uint64_t bits;
-
+
GNUNET_STATISTICS_update (stats, _("# messages fragmented"), 1, GNUNET_NO);
GNUNET_assert (mtu >= 1024 + sizeof (struct FragmentHeader));
size = ntohs (msg->size);
return GNUNET_SYSERR; /* not our ACK */
abits = GNUNET_ntohll (fa->bits);
if ( (GNUNET_YES == fc->wack) &&
- (abits == (fc->acks & abits)) )
+ (0 != fc->num_transmissions) )
{
/* normal ACK, can update running average of delay... */
fc->wack = GNUNET_NO;
ndelay = GNUNET_TIME_absolute_get_duration (fc->last_round);
- fc->delay.rel_value = (ndelay.rel_value * fc->num_rounds + 3 * fc->delay.rel_value) / 4;
+ fc->delay.rel_value =
+ (ndelay.rel_value / fc->num_transmissions + 3 * fc->delay.rel_value) / 4;
+ fc->num_transmissions = 0;
}
GNUNET_STATISTICS_update (fc->stats,
_("# fragment acknowledgements received"), 1,