// update M
sess_local[s].last_seq = seq_num;
- if (seq_num < this_fragmentation->M)
- this_fragmentation->M = seq_num;
- else
{
- uint32_t i, min = sess_local[(this_bundle->members[0])].last_seq;;
- for (i = 1; i < this_bundle->num_of_links; i++)
+ /* seq # can be spread over the wrapping limit, and we must
+ choose the "lowest" one, taking into account the wrapping:
+
+ |-#-##--#----------------------M--###-#|
+
+ but we must also care when the last highest seq # wraps,
+ so we keep two minimums: one for the higher limit, and
+ one for the lower one.
+
+ In the nominal case, low_min = high_min.
+ */
+ uint32_t i, low_min, high_min;
+ low_min = sess_local[(this_bundle->members[0])].last_seq;;
+ high_min = this_bundle->max_seq; // max_seq is impossible to reach
+
+ for (i = 0; i < this_bundle->num_of_links; i++)
{
uint32_t s_seq = sess_local[(this_bundle->members[i])].last_seq;
- if (s_seq < min)
- min = s_seq;
+ if (s_seq < low_min)
+ low_min = s_seq;
+ if (s_seq >= this_fragmentation->M && s_seq < high_min)
+ high_min = s_seq;
}
- this_fragmentation->M = min;
+
+ // if high_min was found, it's the "lowest" one
+ if (high_min < this_bundle->max_seq)
+ this_fragmentation->M = high_min;
+ else
+ this_fragmentation->M = low_min;
}
LOG(4, s, t, "MPPP: Setting M to %d\n", this_fragmentation->M);
// return if a lost fragment is found
if (!(this_fragmentation->fragment[begin_index].length))
- return; // assembling frame failed
+ goto discard_lost_frames; // assembling frame failed
// get the end of his frame
while (this_fragmentation->fragment[end_index].length)
{
// return if a lost fragment is found
if (!(this_fragmentation->fragment[end_index].length))
- return; // assembling frame failed
+ goto discard_lost_frames; // assembling frame failed
// assemble the packet
//assemble frame, process it, reset fragmentation
break;
}
}
- //discard fragments received before the recently assembled frame
- begin_index = this_fragmentation->start_index;
- this_fragmentation->start_index = (end_index + 1) & MAXFRAGNUM_MASK;
- this_fragmentation->start_seq = (this_fragmentation->fragment[end_index].seq + 1) & (this_bundle->max_seq-1);
- //clear length and flags of the discarded fragments
- while (begin_index != this_fragmentation->start_index)
+
+discard_lost_frames:
+ //discard fragments numbererd below M and part of an unassembled frame,
+ //but not the one from the frame beginning just before M
+
+ // if we have something to discard
+ if (M_index != this_fragmentation->start_index)
{
- this_fragmentation->fragment[begin_index].flags = 0;
- this_fragmentation->fragment[begin_index].length = 0;
- begin_index = (begin_index + 1) & MAXFRAGNUM_MASK;
+ // look for end of previous frame
+ // start at M-1, going backward
+ uint16_t index = M_index;
+ uint8_t end_or_hole_found = 0;
+
+ while (index != this_fragmentation->start_index)
+ {
+ fragmentt *this_frag;
+
+ if (!end_or_hole_found)
+ {
+ fragmentt *front_frag = &this_fragmentation->frag[index];
+
+ // before a MP_BEGIN, there must be a MP_END
+ if (front_frag->length && (front_frag->flags & MP_BEGIN))
+ {
+ end_or_hole_found = 1;
+ end_index = index;
+ }
+ }
+
+ index = (index + (MAXFRAGNUM-1)) & MAXFRAGNUM_MASK;
+ this_frag = &this_fragmentation->frag[index];
+
+ if (!end_or_hole_found)
+ {
+ // we are a hole or a MP_END
+ if (!this_frag->length || (this_frag->flags & MP_END))
+ {
+ end_or_hole_found = 1;
+ end_index = index;
+ }
+ }
+
+ if (end_or_hole_found)
+ {
+ this_frag->flags = 0;
+ this_frag->length = 0;
+ }
+ }
+
+ this_fragmentation->start_index = (end_index + 1) & MAXFRAGNUM_MASK;
+ this_fragmentation->start_seq = (this_fragmentation->fragment[end_index].seq + 1) & (this_bundle->max_seq-1);
}
LOG(4, s, t, "MPPP after assembling: M index is =%d, start index is = %d, start seq=%d\n",M_index, this_fragmentation->start_index, this_fragmentation->start_seq);