MPPP: Fix discarding frames (a bit complicated)
authorBenjamin Cama <benoar@dolka.fr>
Thu, 26 Jan 2012 01:38:49 +0000 (02:38 +0100)
committerBenjamin Cama <benoar@dolka.fr>
Thu, 26 Jan 2012 01:38:49 +0000 (02:38 +0100)
ppp.c

diff --git a/ppp.c b/ppp.c
index 4114bb4..3f5a9a5 100644 (file)
--- a/ppp.c
+++ b/ppp.c
@@ -1999,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)
-       {
-               this_fragmentation->fragment[begin_index].flags = 0;
-               this_fragmentation->fragment[begin_index].length = 0;
-               begin_index = (begin_index + 1) & MAXFRAGNUM_MASK;
+
+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)
+       {
+               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);