merge from multibind
[l2tpns.git] / grpsess.c
index 68ec968..bfc7d8d 100644 (file)
--- a/grpsess.c
+++ b/grpsess.c
@@ -22,7 +22,7 @@ union grp_iphash {
        union grp_iphash *idx;
 } grp_ip_hash[256];                    // Mapping from IP address to group structures.
 
        union grp_iphash *idx;
 } grp_ip_hash[256];                    // Mapping from IP address to group structures.
 
-static groupidt gnextgrpid = 0;
+groupidt gnextgrpid = 0;
 
 // Find gruop by IP, < 1 for not found
 //
 
 // Find gruop by IP, < 1 for not found
 //
@@ -443,69 +443,137 @@ void grp_time_changed()
        }
 }
 
        }
 }
 
+// Uncache all IP of a session
+static void grp_uncache_ipsession(groupidt g, sessionidt s)
+{
+       int i;
+       uint8_t *a;
+       in_addr_t ip;
+       in_addr_t n_ip, j;
+       int prefixlen;
+       union iphash *h;
+
+       for (i = 0; i < grpsession[g].nbroutesgrp; i++)
+       {
+               if (grpsession[g].route[i].ip != 0)
+               {
+                       prefixlen = grpsession[g].route[i].prefixlen;
+                       ip = grpsession[g].route[i].ip & (0xffffffff << (32 - prefixlen));      // Force the ip to be the first one in the route.
+
+                       for (j = ip; j < ip+(1<<(32-prefixlen)) ; ++j)
+                       {
+                               n_ip = htonl(j); // To network order
+                               a = (uint8_t *) &n_ip;
+                               h = ip_hash;
+
+                               if (!(h = h[*a++].idx)) continue;
+                               if (!(h = h[*a++].idx)) continue;
+                               if (!(h = h[*a++].idx)) continue;
+
+                               if (s == h[*a].sess)
+                               {
+                                       h[*a].sess = 0;
+                                       //LOG(3, s, session[s].tunnel, "UnCaching ip address %s\n", fmtaddr(n_ip, 0));
+                               }
+                       }
+               }
+       }
+}
+
 // return the next session can be used on the group
 sessionidt grp_getnextsession(groupidt g, in_addr_t ip)
 {
        sessionidt s = 0, s2 = 0, s3 = 0;
        int i;
 // return the next session can be used on the group
 sessionidt grp_getnextsession(groupidt g, in_addr_t ip)
 {
        sessionidt s = 0, s2 = 0, s3 = 0;
        int i;
-       uint32_t ltime_changed = 0;
-       uint32_t mintxrate = 0xFFFFFFFF;
+       uint32_t ltime_changed = 0, mintxrate = 0xFFFFFFFF, maxtxrate = 0;
+       uint32_t txrate;
 
        if (g >= MAXGROUPE)
                return 0;
 
 
        if (g >= MAXGROUPE)
                return 0;
 
-       if ((s = sessionbyip(ip)))
+       if (grpsession[g].time_changed >= config->grp_txrate_average_time)
        {
        {
-               if ( (session[s].ppp.phase > Establish) &&
-                        (time_now - session[s].last_packet <= (config->echo_timeout + 2)) )
+               // recalculation txrate
+               ltime_changed = grpsession[g].time_changed;
+               grpsession[g].time_changed = 0;
+               for (i = 0; i < grpsession[g].nbsession; i++)
                {
                {
-                       int recaltxrate = 0;
-
-                       for (i = 0; i < grpsession[g].nbsession; i++)
+                       if ((s2 = grpsession[g].sesslist[i].sid))
                        {
                        {
-                               if (s == grpsession[g].sesslist[i].sid)
+                               grpsession[g].sesslist[i].tx_rate = session[s2].coutgrp_delta/ltime_changed;
+                               session[s2].coutgrp_delta = 0;
+
+                               txrate = grpsession[g].sesslist[i].tx_rate/grpsession[g].sesslist[i].weight;
+                               if (txrate < mintxrate)
                                {
                                {
-                                       if ((time_now - grpsession[g].sesslist[i].mark_time) > config->grp_txrate_average_time)
+                                       if ( session[s2].ppp.phase > Establish &&
+                                               (time_now - session[s2].last_packet <= (config->echo_timeout + 1)) )
                                        {
                                        {
-                                               grpsession[g].sesslist[i].mark_time = time_now;
-                                               recaltxrate = 1;
-                                               break;
+                                               grpsession[g].smin = s2;
+                                               mintxrate = txrate;
                                        }
                                }
                                        }
                                }
-                       }
 
 
-                       if (!recaltxrate)
-                               return s;
+                               if (txrate > maxtxrate)
+                               {
+                                       if ( session[s2].ppp.phase > Establish &&
+                                       (time_now - session[s2].last_packet <= (config->echo_timeout + 1)) )
+                                       {
+                                               grpsession[g].smax = s2;
+                                               maxtxrate = txrate;
+                                       }
+                               }
+                       }
                }
        }
 
                }
        }
 
-       //if (grpsession[g].time_changed > config->grp_txrate_average_time)
-       if (grpsession[g].time_changed > 1)
+       if ((s = sessionbyip(ip)))
        {
        {
-               ltime_changed = grpsession[g].time_changed;
-               grpsession[g].time_changed = 1;
+               if (s == grpsession[g].smax)
+               {
+                       s = grpsession[g].smin;
+                       grpsession[g].smax = 0;
+               }
+               else if ( (session[s].ppp.phase > Establish) &&
+                        (time_now - session[s].last_packet <= (config->echo_timeout + 1)) )
+               {
+                       return s;
+               }
+               else
+               {
+                       s = 0;
+               }
        }
 
        }
 
-       for (i = 0; i < grpsession[g].nbsession; i++)
+       if (!s)
        {
        {
-               if ((s2 = grpsession[g].sesslist[i].sid))
-               {
-                       s3 = s2;
-                       if (ltime_changed)
-                       {
-                               grpsession[g].sesslist[i].tx_rate = session[s2].coutgrp_delta/ltime_changed;
-                               session[s2].coutgrp_delta = grpsession[g].sesslist[i].tx_rate;
-                               //LOG(3, s2, session[s2].tunnel, "TX Rate: %d session weight: %d\n", grpsession[g].sesslist[i].tx_rate, grpsession[g].sesslist[i].weight);
-                       }
+               // random between 0 and nbsession-1
+               uint indexsess = (rand() % grpsession[g].nbsession);
+
+               if (indexsess >= grpsession[g].nbsession)
+                       indexsess = 0; //Sanity checks.
 
 
-                       if ( session[s2].ppp.phase > Establish &&
-                               (time_now - session[s2].last_packet <= (config->echo_timeout + 2)) )
+               s2 = grpsession[g].sesslist[indexsess].sid;
+               if (s2 &&
+                       (session[s2].ppp.phase > Establish) &&
+                       (time_now - session[s2].last_packet <= (config->echo_timeout + 1)))
+               {
+                       s = s2;
+               }
+               else
+               {
+                       for (i = 0; i < grpsession[g].nbsession; i++)
                        {
                        {
-                               uint32_t txrate = grpsession[g].sesslist[i].tx_rate/grpsession[g].sesslist[i].weight;
-                               if (txrate < mintxrate)
+                               if ((s2 = grpsession[g].sesslist[i].sid))
                                {
                                {
-                                       s = s2;
-                                       mintxrate = txrate;
+                                       s3 = s2;
+
+                                       if ( session[s2].ppp.phase > Establish &&
+                                               (time_now - session[s2].last_packet <= (config->echo_timeout + 1)) )
+                                       {
+                                               s = s2;
+                                               break;
+                                       }
                                }
                        }
                }
                                }
                        }
                }