X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/e57abd6b9e216dee2a29897ba64d7fb24f5c6ecd..d674ec8153ca664525d38bab8c761cc34ecd79bd:/ppp.c diff --git a/ppp.c b/ppp.c index e21c103..3f5a9a5 100644 --- a/ppp.c +++ b/ppp.c @@ -1866,18 +1866,36 @@ void processmpin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) // 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); @@ -1981,16 +1999,55 @@ void processmpin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) 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; + uint8_t end_found = 0; + // look for end of previous frame + // start at M-1, going backward + for (end_index = (M_index + (MAXFRAGNUM-1)) & MAXFRAGNUM_MASK; + end_index != this_fragmentation->start_index; + end_index = (end_index + (MAXFRAGNUM-1)) & MAXFRAGNUM_MASK) + { + fragmentt *this_frag = &this_fragmentation->frag[end_index]; + fragmentt *front_frag = &this_fragmentation->frag[(end_index+1)&MAXFRAGNUM_MASK]; + // before a MP_BEGIN, we must be a MP_END + if (front_frag->length && (front_frag->flags & MP_BEGIN)) + { + end_found = 1; + break; + } + // we are a MP_END + if (this_frag->length && (this_frag->flags & MP_END)) + { + end_found = 1; + break; + } + } + // ok, we may not count it for found if end_index == this_fragmentation->start_index + // but it complicates things too much and it will be discarded on next round anyway + + //clear length and flags of the discarded fragments + if (end_found) + { + begin_index = this_fragmentation->start_index; + while (begin_index != end_index) + { + this_fragmentation->fragment[begin_index].flags = 0; + this_fragmentation->fragment[begin_index].length = 0; + begin_index = (begin_index + 1) & MAXFRAGNUM_MASK; + } + this_fragmentation->fragment[begin_index].flags = 0; + this_fragmentation->fragment[begin_index].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);