IPv6 load-balancing
[l2tpns.git] / l2tpns.c
index 5c887ec..5445013 100644 (file)
--- a/l2tpns.c
+++ b/l2tpns.c
@@ -94,7 +94,11 @@ 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 ip_hash[256];     // Mapping from IP address to session structures.
+union iphash
+{
+       sessionidt sess;
+       union iphash *idx;
+}ip_hash[256]; // Mapping from IP address to session structures.
 
 struct ipv6radix {
        sessionidt sess;
@@ -979,7 +983,6 @@ static sessionidt lookup_ipv6map(struct in6_addr ip)
        int s;
        char ipv6addr[INET6_ADDRSTRLEN];
 
-       curnode = &ipv6_hash[ip.s6_addr[0]];
        curnode = &ipv6_hash[((ip.s6_addr[0]) & 0xF0)>>4];
        i = 1;
        s = curnode->sess;
@@ -1076,7 +1079,6 @@ void cache_ipmap(in_addr_t ip, sessionidt s)
 
        if (s > 0)
                LOG(4, s, session[s].tunnel, "Caching ip address %s\n", fmtaddr(nip, 0));
-
        else if (s == 0)
                LOG(4, 0, 0, "Un-caching ip address %s\n", fmtaddr(nip, 0));
        // else a map to an ip pool index.
@@ -1484,7 +1486,7 @@ void processipout(uint8_t *buf, int len)
        ip = *(uint32_t *)(buf + 16);
        if ((g = grp_groupbyip(ip)))
        {
-               s = grp_getnextsession(g, ip, ip_src);
+               s = grp_getnextsession(g, &ip, &ip_src, 0);
                if (!s)
                {
                        // Is this a packet for a session that doesn't exist?
@@ -1735,9 +1737,11 @@ void processipout(uint8_t *buf, int len)
 static void processipv6out(uint8_t * buf, int len)
 {
        sessionidt s;
+       groupidt g;
        sessiont *sp;
        tunnelidt t;
-       struct in6_addr ip6;
+       struct in6_addr *p_ip6;
+       struct in6_addr *p_ip6_src;
 
        uint8_t *data = buf;    // Keep a copy of the originals.
        int size = len;
@@ -1770,12 +1774,16 @@ static void processipv6out(uint8_t * buf, int len)
                return;
        }
 
-       ip6 = *(struct in6_addr *)(buf+24);
-       s = sessionbyipv6(ip6);
+       p_ip6_src = (struct in6_addr *)(buf+8);
+       p_ip6 = (struct in6_addr *)(buf+24);
 
-       if (s == 0)
+       if ((g = grp_groupbyipv6(*p_ip6)))
        {
-               s = sessionbyipv6new(ip6);
+               s = grp_getnextsession(g, p_ip6, p_ip6_src, 1);
+       }
+       else if (!(s = sessionbyipv6(*p_ip6)))
+       {
+               s = sessionbyipv6new(*p_ip6);
        }
 
        if (s == 0)
@@ -5958,9 +5966,12 @@ int load_session(sessionidt s, sessiont *new)
        }
 
        // check v6 routing
-       for (i = 0; i < MAXROUTE6 && new->route6[i].ipv6prefixlen; i++)
+       if (new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened)
        {
-               route6set(s, new->route6[i].ipv6route, new->route6[i].ipv6prefixlen, 1);
+               for (i = 0; i < MAXROUTE6 && new->route6[i].ipv6prefixlen; i++)
+               {
+                       route6set(s, new->route6[i].ipv6route, new->route6[i].ipv6prefixlen, 1);
+               }
        }
 
        if (new->ipv6address.s6_addr[0] && new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened)