Session group update rate calculation
authorfendo <fendo@bi12info.com>
Fri, 22 Feb 2013 17:35:46 +0000 (18:35 +0100)
committerfendo <fendo@bi12info.com>
Fri, 22 Feb 2013 17:35:46 +0000 (18:35 +0100)
grpsess.c
l2tpns.c
l2tpns.h

index 68ec968..a26c489 100644 (file)
--- a/grpsess.c
+++ b/grpsess.c
@@ -443,69 +443,143 @@ 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;
+       sessionidt s = 0, s2 = 0, s3 = 0, smax = 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 ((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)) )
+               if ((s = sessionbyip(ip)))
                {
-                       int recaltxrate = 0;
-
-                       for (i = 0; i < grpsession[g].nbsession; i++)
+                       if ( (session[s].ppp.phase > Establish) &&
+                                (time_now - session[s].last_packet <= (config->echo_timeout + 1)) )
+                       {
+                               return s;
+                       }
+                       s = 0;
+               }
+       }
+       else
+       {
+               // recalculation txrate
+               ltime_changed = grpsession[g].time_changed;
+               grpsession[g].time_changed = 0;
+               s = 0;
+               for (i = 0; i < grpsession[g].nbsession; i++)
+               {
+                       if ((s2 = grpsession[g].sesslist[i].sid))
                        {
-                               if (s == grpsession[g].sesslist[i].sid)
+                               s3 = s2;
+
+                               grpsession[g].sesslist[i].tx_rate = session[s2].coutgrp_delta/ltime_changed;
+                               session[s2].coutgrp_delta = 0;
+
+                               //LOG(3, s2, session[s2].tunnel, "TX Rate: %d session weight: %d\n",
+                               //      grpsession[g].sesslist[i].tx_rate, grpsession[g].sesslist[i].weight);
+
+                               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;
+                                               s = s2;
+                                               mintxrate = txrate;
+                                       }
+                               }
+
+                               if (txrate > maxtxrate)
+                               {
+                                       if ( session[s2].ppp.phase > Establish &&
+                                       (time_now - session[s2].last_packet <= (config->echo_timeout + 1)) )
+                                       {
+                                               smax = s2;
+                                               maxtxrate = txrate;
                                        }
                                }
                        }
+               }
 
-                       if (!recaltxrate)
-                               return s;
+               if (smax && (maxtxrate != mintxrate))
+               {
+                       grp_uncache_ipsession(g, smax);
                }
        }
 
-       //if (grpsession[g].time_changed > config->grp_txrate_average_time)
-       if (grpsession[g].time_changed > 1)
+       if (!s)
        {
-               ltime_changed = grpsession[g].time_changed;
-               grpsession[g].time_changed = 1;
-       }
+               // random between 0 and nbsession-1
+               uint indexsess = (rand() % grpsession[g].nbsession);
 
-       for (i = 0; i < grpsession[g].nbsession; i++)
-       {
-               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);
-                       }
+               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;
+                       //LOG(3, s, session[s].tunnel, "New random session\n");
+               }
+               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;
+                                       }
                                }
                        }
                }
index 52872a5..34e4a7a 100644 (file)
--- a/l2tpns.c
+++ b/l2tpns.c
@@ -98,10 +98,7 @@ uint16_t MSS = 0;            // TCP MSS
 struct cli_session_actions *cli_session_actions = NULL;        // Pending session changes requested by CLI
 struct cli_tunnel_actions *cli_tunnel_actions = NULL;  // Pending tunnel changes required by CLI
 
-union iphash {
-       sessionidt sess;
-       union iphash *idx;
-} ip_hash[256];                        // Mapping from IP address to session structures.
+union iphash ip_hash[256];     // Mapping from IP address to session structures.
 
 struct ipv6radix {
        sessionidt sess;
index 989ddd9..0283842 100644 (file)
--- a/l2tpns.h
+++ b/l2tpns.h
@@ -345,7 +345,6 @@ sessiont;
 typedef struct
 {
        uint32_t tx_rate;
-       time_t mark_time;
        sessionidt sid;
        uint8_t weight;
 }
@@ -353,9 +352,7 @@ groupsessionidt;
 
 typedef struct
 {
-       //uint16_t indexprevsessid;
        uint32_t time_changed;
-       //time_t mark_time;
        groupidt prev;
        groupsessionidt sesslist[MAXSESSINGRP];
        routet route[MAXROUTEINGRP];            // static routes
@@ -364,6 +361,12 @@ typedef struct
 }
 groupsesst;
 
+union iphash
+{
+       sessionidt sess;
+       union iphash *idx;
+};                     // Mapping from IP address to session structures.
+
 typedef struct
 {
         int state;                              // current state (bundlestate enum)
@@ -1045,6 +1048,7 @@ extern in_addr_t my_address;
 extern int clifd;
 extern int epollfd;
 extern int tunidx;             // ifr_ifindex of tun device
+extern union iphash ip_hash[256];
 
 struct event_data {
        enum {