MPPP: Fix M calculation
authorBenjamin Cama <benoar@dolka.fr>
Wed, 25 Jan 2012 23:19:59 +0000 (00:19 +0100)
committerBenjamin Cama <benoar@dolka.fr>
Wed, 25 Jan 2012 23:35:57 +0000 (00:35 +0100)
ppp.c

diff --git a/ppp.c b/ppp.c
index e21c103..4114bb4 100644 (file)
--- 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);