Merge from master
authorfendo <fendo@bi12info.com>
Tue, 12 Nov 2013 21:38:40 +0000 (22:38 +0100)
committerfendo <fendo@bi12info.com>
Tue, 12 Nov 2013 21:38:40 +0000 (22:38 +0100)
1  2 
l2tpns.c
l2tpns.h
ppp.c

diff --combined l2tpns.c
+++ b/l2tpns.c
@@@ -75,7 -75,7 +75,7 @@@ int cluster_sockfd = -1;      // Intra-clust
  int epollfd = -1;             // event polling
  time_t basetime = 0;          // base clock
  char hostname[MAXHOSTNAME] = "";      // us.
 -static int tunidx;            // ifr_ifindex of tun device
 +int tunidx;                           // ifr_ifindex of tun device
  int nlseqnum = 0;             // netlink sequence number
  int min_initok_nlseqnum = 0;  // minimun seq number for messages after init is ok
  static int syslog_log = 0;    // are we logging to syslog
@@@ -92,7 -92,10 +92,7 @@@ uint16_t MSS = 0;            // TCP MS
  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;
@@@ -183,9 -186,9 +183,10 @@@ config_descriptt config_values[] = 
        CONFIG("disable_sending_hello", disable_sending_hello, BOOL),
        CONFIG("disable_no_spoof", disable_no_spoof, BOOL),
        CONFIG("bind_multi_address", bind_multi_address, STRING),
 +      CONFIG("grp_txrate_average_time", grp_txrate_average_time, INT),
        CONFIG("pppoe_only_equal_svc_name", pppoe_only_equal_svc_name, BOOL),
        CONFIG("multi_hostname", multi_hostname, STRING),
+       CONFIG("no_throttle_local_IP", no_throttle_local_IP, BOOL),
        { NULL, 0, 0, 0 }
  };
  
@@@ -214,7 -217,6 +215,7 @@@ tunnelt *tunnel = NULL;                    // Array of t
  bundlet *bundle = NULL;                       // Array of bundle structures.
  fragmentationt *frag = NULL;          // Array of fragmentation structures.
  sessiont *session = NULL;             // Array of session structures.
 +groupsesst *grpsession = NULL;                // Array of groupsesst structures.
  sessionlocalt *sess_local = NULL;     // Array of local per-session counters.
  radiust *radius = NULL;                       // Array of radius structures.
  ippoolt *ip_address_pool = NULL;      // Array of dynamic IP addresses.
@@@ -225,6 -227,9 +226,6 @@@ struct Tstats *_statistics = NULL
  struct Tringbuffer *ringbuffer = NULL;
  #endif
  
 -static ssize_t netlink_send(struct nlmsghdr *nh);
 -static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen);
 -static void cache_ipmap(in_addr_t ip, sessionidt s);
  static void uncache_ipmap(in_addr_t ip);
  static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s);
  static void free_ip_address(sessionidt s);
@@@ -253,9 -258,8 +254,9 @@@ static clockt now(double *f
        if (f) *f = t.tv_sec + t.tv_usec / 1000000.0;
        if (t.tv_sec != time_now)
        {
 -          time_now = t.tv_sec;
 -          time_changed++;
 +              time_now = t.tv_sec;
 +              time_changed++;
 +              grp_time_changed();
        }
  
        // Time in milliseconds
@@@ -614,7 -618,7 +615,7 @@@ static void initnetlink(void
        }
  }
  
 -static ssize_t netlink_send(struct nlmsghdr *nh)
 +ssize_t netlink_send(struct nlmsghdr *nh)
  {
        struct sockaddr_nl nladdr;
        struct iovec iov;
@@@ -650,7 -654,7 +651,7 @@@ static ssize_t netlink_recv(void *buf, 
  }
  
  /* adapted from iproute2 */
 -static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen)
 +void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen)
  {
        int len = RTA_LENGTH(alen);
        struct rtattr *rta;
@@@ -1030,7 -1034,7 +1031,7 @@@ sessionidt sessionbyipv6(struct in6_add
  //
  // (It's actually cached in network order)
  //
 -static void cache_ipmap(in_addr_t ip, sessionidt s)
 +void cache_ipmap(in_addr_t ip, sessionidt s)
  {
        in_addr_t nip = htonl(ip);      // MUST be in network order. I.e. MSB must in be ((char *) (&ip))[0]
        uint8_t *a = (uint8_t *) &nip;
@@@ -1412,7 -1416,6 +1413,7 @@@ static void update_session_out_stat(ses
  void processipout(uint8_t *buf, int len)
  {
        sessionidt s;
 +      groupidt g;
        sessiont *sp;
        tunnelidt t;
        in_addr_t ip, ip_src;
  
        ip_src = *(uint32_t *)(buf + 12);
        ip = *(uint32_t *)(buf + 16);
 -      if (!(s = sessionbyip(ip)))
 +      if ((g = grp_groupbyip(ip)))
 +      {
 +              s = grp_getnextsession(g, ip, ip_src);
 +              if (!s)
 +              {
 +                      // Is this a packet for a session that doesn't exist?
 +                      static int rate = 0;    // Number of ICMP packets we've sent this second.
 +                      static int last = 0;    // Last time we reset the ICMP packet counter 'rate'.
 +
 +                      if (last != time_now)
 +                      {
 +                              last = time_now;
 +                              rate = 0;
 +                      }
 +
 +                      if (rate++ < config->icmp_rate) // Only send a max of icmp_rate per second.
 +                      {
 +                              LOG(4, 0, 0, "IP: Sending ICMP host unreachable to %s\n", fmtaddr(*(in_addr_t *)(buf + 12), 0));
 +                              host_unreachable(*(in_addr_t *)(buf + 12), *(uint16_t *)(buf + 4),
 +                                      config->bind_address ? config->bind_address : my_address, buf, len);
 +                      }
 +                      return;
 +              }
 +      }
 +      else if (!(s = sessionbyip(ip)))
        {
                // Is this a packet for a session that doesn't exist?
                static int rate = 0;    // Number of ICMP packets we've sent this second.
  
        if (sp->tbf_out)
        {
-               // Are we throttling this session?
-               if (config->cluster_iam_master)
-                       tbf_queue_packet(sp->tbf_out, data, size);
-               else
-                       master_throttle_packet(sp->tbf_out, data, size);
-               return;
+               if (!config->no_throttle_local_IP || !sessionbyip(ip_src))
+               {
+                       // Are we throttling this session?
+                       if (config->cluster_iam_master)
+                               tbf_queue_packet(sp->tbf_out, data, size);
+                       else
+                               master_throttle_packet(sp->tbf_out, data, size);
+                       return;
+               }
        }
  
        if (sp->walled_garden && !config->cluster_iam_master)
@@@ -2116,7 -2098,7 +2120,7 @@@ void sessionshutdown(sessionidt s, cha
                session[s].die = TIME + 150; // Clean up in 15 seconds
  
        if (session[s].ip)
 -      {                          // IP allocated, clear and unroute
 +      {       // IP allocated, clear and unroute
                int r;
                int routed = 0;
                for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++)
@@@ -2316,8 -2298,6 +2320,8 @@@ static void sessionclear(sessionidt s
  // kill a session now
  void sessionkill(sessionidt s, char *reason)
  {
 +      groupidt g;
 +
        CSTAT(sessionkill);
  
        if (!session[s].opened) // not alive
        }
  
        LOG(2, s, session[s].tunnel, "Kill session %d (%s): %s\n", s, session[s].user, reason);
 +
 +      if ((g = grp_groupbysession(s)))
 +      {
 +              grp_removesession(g, s);
 +      }
 +
        sessionclear(s);
        cluster_send_session(s);
  }
@@@ -3749,7 -3723,7 +3753,7 @@@ static void regular_cleanups(double per
  
                // No data in ECHO_TIMEOUT seconds, send LCP ECHO
                if (session[s].ppp.phase >= Establish && (time_now - session[s].last_packet >= config->echo_timeout) &&
 -                      (time_now - sess_local[s].last_echo >= ECHO_TIMEOUT))
 +                      (time_now - sess_local[s].last_echo >= config->echo_timeout))
                {
                        uint8_t b[MAXETHER];
  
@@@ -4686,8 -4660,6 +4690,8 @@@ static void initdata(int optdebug, cha
  #endif /* BGP */
  
        lac_initremotelnsdata();
 +
 +      grp_initdata();
  }
  
  static int assign_ip_address(sessionidt s)
@@@ -5228,9 -5200,6 +5232,9 @@@ int main(int argc, char *argv[]
                        LOG(0, 0, 0, "Can't lock pages: %s\n", strerror(errno));
        }
  
 +      //LOG(3, 0, 0, "Debug sizeof struct: sessiont %lu, tunnelt %lu, bundlet %lu, groupsesst %lu\n",
 +      //      sizeof(sessiont), sizeof(tunnelt), sizeof(bundlet), sizeof(groupsesst));
 +
        mainloop();
  
        /* remove plugins (so cleanup code gets run) */
@@@ -5742,7 -5711,6 +5746,7 @@@ int sessionsetup(sessionidt s, tunnelid
        if (!session[s].bundle || (bundle[session[s].bundle].num_of_links == 1))
        {
                int routed = 0;
 +              groupidt g;
  
                // Add the route for this session.
                for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++)
                }
                else
                        cache_ipmap(session[s].ip, s);
 +
 +              if ((g = grp_groupbysession(s)))
 +              {
 +                      grp_setgrouproute(g, 1);
 +                      cluster_send_groupe(g);
 +              }
        }
  
        sess_local[s].lcp_authtype = 0; // RADIUS authentication complete
diff --combined l2tpns.h
+++ b/l2tpns.h
@@@ -24,9 -24,6 +24,9 @@@
  #define MAXADDRESS    20              // Maximum length for the Endpoint Discrminiator address
  #define MAXSESSION    60000           // could be up to 65535
  #define MAXTBFS               6000            // Maximum token bucket filters. Might need up to 2 * session.
 +#define MAXSESSINGRP  12              // Maximum number of member links in grouped session
 +#define MAXGROUPE             300     // could be up to 65535, Maximum number of grouped session
 +#define MAXROUTEINGRP 15              // max static routes per group
  
  // Tunnel Id reserved for pppoe
  #define TUNNEL_ID_PPPOE       1
@@@ -219,7 -216,6 +219,7 @@@ enum 
  typedef uint16_t sessionidt;
  typedef uint16_t bundleidt;
  typedef uint16_t tunnelidt;
 +typedef uint16_t groupidt;
  typedef uint32_t clockt;
  typedef uint8_t hasht[16];
  
@@@ -337,39 -333,10 +337,39 @@@ typedef struc
        struct in6_addr ipv6route;      // Static IPv6 route
        sessionidt forwardtosession;    // LNS id_session to forward
        uint8_t src_hwaddr[ETH_ALEN];   // MAC addr source (for pppoe sessions 6 bytes)
 -      char reserved[4];               // Space to expand structure without changing HB_VERSION
 +      char reserved[4];                               // Space to expand structure without changing HB_VERSION
  }
  sessiont;
  
 +typedef struct
 +{
 +      uint32_t tx_rate;
 +      uint32_t prev_coutgrp;
 +      sessionidt sid;
 +      uint8_t weight;
 +}
 +groupsesslistt;
 +
 +typedef struct
 +{
 +      int state;                              // current state (groupestate enum)
 +      uint32_t time_changed;
 +      groupidt prev;
 +      sessionidt smax;
 +      sessionidt smin;
 +      groupsesslistt sesslist[MAXSESSINGRP];
 +      routet route[MAXROUTEINGRP];            // static routes
 +      uint8_t nbroutesgrp;
 +      uint8_t nbsession;
 +}
 +groupsesst;
 +
 +union iphash
 +{
 +      sessionidt sess;
 +      union iphash *idx;
 +};                    // Mapping from IP address to session structures.
 +
  typedef struct
  {
          int state;                              // current state (bundlestate enum)
@@@ -552,13 -519,6 +552,13 @@@ enu
        BUNDLEUNDEF,            // Undefined
  };
  
 +enum
 +{
 +      GROUPEFREE,             // Not in use
 +      GROUPEOPEN,             // Active bundle
 +      GROUPEUNDEF             // Undefined
 +};
 +
  enum
  {
        NULLCLASS = 0,          //End Point Discriminator classes
@@@ -767,10 -727,8 +767,10 @@@ typedef struc
        int             cluster_undefined_sessions;     // How many sessions we're yet to receive from the master.
        int             cluster_undefined_bundles;      // How many bundles we're yet to receive from the master.
        int             cluster_undefined_tunnels;      // How many tunnels we're yet to receive from the master.
 +      int             cluster_undefined_groupes;      // How many groupes we're yet to receive from the master.
        int             cluster_highest_sessionid;
        int             cluster_highest_bundleid;
 +      int             cluster_highest_groupeid;
        int             cluster_highest_tunnelid;
        clockt          cluster_last_hb;                // Last time we saw a heartbeat from the master.
        int             cluster_last_hb_ver;            // Heartbeat version last seen from master
        int nbmultiaddress; // number multi address to bind
        int indexlacudpfd;      // Index UDP LAC file handle (in udpfd[])
        int nbmultihostname;    // number hostname, normally the same number as the nbudpfd
 +      int grp_txrate_average_time; // caculation txrate average time (default 10s)
+       int no_throttle_local_IP;       // no throttle traffic from session to session
        in_addr_t bind_n_address[MAX_BINDADDR];
        in_addr_t iftun_n_address[MAX_BINDADDR];
        char bind_multi_address[256];
@@@ -994,26 -952,12 +995,26 @@@ int ip_filter(uint8_t *buf, int len, ui
  int cmd_show_ipcache(struct cli_def *cli, const char *command, char **argv, int argc);
  int cmd_show_hist_idle(struct cli_def *cli, const char *command, char **argv, int argc);
  int cmd_show_hist_open(struct cli_def *cli, const char *command, char **argv, int argc);
 +void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen);
 +ssize_t netlink_send(struct nlmsghdr *nh);
 +void cache_ipmap(in_addr_t ip, sessionidt s);
  tunnelidt lac_new_tunnel();
  void lac_tunnelclear(tunnelidt t);
  void lac_send_SCCRQ(tunnelidt t, uint8_t * auth, unsigned int auth_len);
  void lac_send_ICRQ(tunnelidt t, sessionidt s);
  void lac_tunnelshutdown(tunnelidt t, char *reason, int result, int error, char *msg);
  
 +// grpsess.c
 +sessionidt grp_getnextsession(groupidt g, in_addr_t ip, in_addr_t ip_src);
 +void grp_initdata(void);
 +void grp_processvendorspecific(sessionidt s, uint8_t *pvs);
 +groupidt grp_groupbysession(sessionidt s);
 +groupidt grp_groupbyip(in_addr_t ip);
 +void grp_setgrouproute(groupidt g, int add);
 +void grp_time_changed(void);
 +void grp_removesession(groupidt g, sessionidt s);
 +int grp_cluster_load_groupe(groupidt g, groupsesst *new);
 +
  #undef LOG
  #undef LOG_HEX
  #define LOG(D, s, t, f, ...)  ({ if (D <= config->debug) _log(D, s, t, f, ## __VA_ARGS__); })
@@@ -1048,8 -992,6 +1049,8 @@@ extern bundlet *bundle
  extern sessiont *session;
  extern sessionlocalt *sess_local;
  extern ippoolt *ip_address_pool;
 +extern groupsesst *grpsession;
 +extern groupidt gnextgrpid;
  #define sessionfree (session[0].next)
  
  
@@@ -1062,8 -1004,6 +1063,8 @@@ extern struct Tstats *_statistics
  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 {
diff --combined ppp.c
--- 1/ppp.c
--- 2/ppp.c
+++ b/ppp.c
@@@ -5,9 -5,6 +5,9 @@@
  #include <unistd.h>
  #include <errno.h>
  #include <stdlib.h>
 +#include <sys/socket.h>
 +#include <linux/rtnetlink.h>
 +
  #include "l2tpns.h"
  #include "constants.h"
  #include "plugin.h"
@@@ -1738,7 -1735,7 +1738,7 @@@ static void update_sessions_in_stat(ses
  // (i.e. this routine writes to p[-4]).
  void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
  {
-       in_addr_t ip;
+       in_addr_t ip, ip_dst;
  
        CSTAT(processipin);
  
        }
  
        ip = ntohl(*(uint32_t *)(p + 12));
+       ip_dst = *(uint32_t *)(p + 16);
  
        if (l > MAXETHER)
        {
  
        if (session[s].tbf_in)
        {
-               // Are we throttling this session?
-               if (config->cluster_iam_master)
-                       tbf_queue_packet(session[s].tbf_in, p, l);
-               else
-                       master_throttle_packet(session[s].tbf_in, p, l);
-               return;
+               if (!config->no_throttle_local_IP || !sessionbyip(ip_dst))
+               {
+                       // Are we throttling this session?
+                       if (config->cluster_iam_master)
+                               tbf_queue_packet(session[s].tbf_in, p, l);
+                       else
+                               master_throttle_packet(session[s].tbf_in, p, l);
+                       return;
+               }
        }
  
        // send to ethernet