From eecccf0b30d5ec19960633d1b62cf5f9936d1f16 Mon Sep 17 00:00:00 2001 From: fendo Date: Fri, 22 Feb 2013 18:35:46 +0100 Subject: [PATCH 1/1] Session group update rate calculation --- grpsess.c | 150 ++++++++++++++++++++++++++++++++++++++++-------------- l2tpns.c | 5 +- l2tpns.h | 10 ++-- 3 files changed, 120 insertions(+), 45 deletions(-) diff --git a/grpsess.c b/grpsess.c index 68ec968..a26c489 100644 --- 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; + } } } } diff --git a/l2tpns.c b/l2tpns.c index 52872a5..34e4a7a 100644 --- 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; diff --git a/l2tpns.h b/l2tpns.h index 989ddd9..0283842 100644 --- 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 { -- 2.20.1