gateway: add SmartGatewayEgressInterfaces configuration parameter
authorFerry Huberts <ferry.huberts@pelagic.nl>
Tue, 4 Dec 2012 11:41:17 +0000 (12:41 +0100)
committerFerry Huberts <ferry.huberts@pelagic.nl>
Thu, 13 Dec 2012 12:23:22 +0000 (13:23 +0100)
Signed-off-by: Ferry Huberts <ferry.huberts@pelagic.nl>
Reviewed-by: Henning Rogge <hrogge@googlemail.com>
README-Olsr-Extensions
files/olsrd.conf.default.full
files/olsrd.conf.default.lq
files/olsrd.conf.default.lq-fisheye
lib/jsoninfo/src/olsrd_jsoninfo.c
src/cfgparser/cfgfile_gen.c
src/cfgparser/olsrd_conf.c
src/cfgparser/oparse.y
src/cfgparser/oscan.lex
src/olsr_cfg.h

index c7663fe..50b5b28 100644 (file)
@@ -256,20 +256,25 @@ All other parameters will be ignored if SmartGateway is set to "no"
    breaking connections (due to the selection of a new gateway) on a dynamic
    network.
    The default setting is 1.
-2- SmartGatewayAllowNAT controls whether you want to allow the selection
+2- SmartGatewayEgressInterfaces determines the egress interfaces that are part
+   of the multi-gateway setup and therefore only relevant when
+   SmartGatewayUseCount is larger than 1 (in which case it must be explicitly
+   set).
+   The default setting is 'not set'.
+3- SmartGatewayAllowNAT controls whether you want to allow the selection
    of an outgoing ipv4 gateway with NAT (Network Address Translation).
    The default setting is "yes".
-3- SmartGatewayPeriod determines the period (in milliseconds) on which
+4- SmartGatewayPeriod determines the period (in milliseconds) on which
    a new smart gateway selection is performed.
    The default setting is 10000 milliseconds.
-4- SmartGatewayStableCount determines the number of times the link state
+5- SmartGatewayStableCount determines the number of times the link state
    database must be stable before a new smart gateway is selected.
    The default setting is 6.
-5- SmartGatewayThreshold controls whether you want to allow re-selection
+6- SmartGatewayThreshold controls whether you want to allow re-selection
    of a new outgoing gateway if its routing cost is lower or equal to the
    configured percentage of the routing cost of the current gateway.
    The default setting is 0, which disables it.
-6- SmartGatewayWeightExitLinkUp, SmartGatewayWeightExitLinkDown,
+7- SmartGatewayWeightExitLinkUp, SmartGatewayWeightExitLinkDown,
    SmartGatewayWeightEtx and SmartGatewayDividerEtx control the weighing
    of gateway bandwidth and ETX costs.
 
index 72de099..549b562 100644 (file)
 
 # SmartGatewayUseCount 1
 
+# Determines the egress interfaces that are part of the multi-gateway setup and
+# therefore only relevant when SmartGatewayUseCount is larger than 1 (in which
+# case it must be explicitly set).
+# (default is not set)
+
+# SmartGatewayEgressInterfaces ""
+
 # Allows the selection of a smartgateway with NAT (only for IPv4)
 # (default is "yes")
 
index b3c2976..2946d96 100644 (file)
 
 # SmartGatewayUseCount 1
 
+# Determines the egress interfaces that are part of the multi-gateway setup and
+# therefore only relevant when SmartGatewayUseCount is larger than 1 (in which
+# case it must be explicitly set).
+# (default is not set)
+
+# SmartGatewayEgressInterfaces ""
+
 # Allows the selection of a smartgateway with NAT (only for IPv4)
 # (default is "yes")
 
index 878505f..10a0dae 100644 (file)
 
 # SmartGatewayUseCount 1
 
+# Determines the egress interfaces that are part of the multi-gateway setup and
+# therefore only relevant when SmartGatewayUseCount is larger than 1 (in which
+# case it must be explicitly set).
+# (default is not set)
+
+# SmartGatewayEgressInterfaces ""
+
 # Allows the selection of a smartgateway with NAT (only for IPv4)
 # (default is "yes")
 
index 142d0d8..4636365 100644 (file)
@@ -987,6 +987,21 @@ ipc_print_config(struct autobuf *abuf)
   abuf_json_boolean(abuf, "smartGateway", olsr_cnf->smart_gw_active);
   if (olsr_cnf->smart_gw_active) {
     abuf_json_int(abuf, "smartGatewayUseCount", olsr_cnf->smart_gw_use_count);
+    {
+      struct autobuf egressbuf;
+      struct sgw_egress_if * egressif = olsr_cnf->smart_gw_egress_interfaces;
+
+      abuf_init(&egressbuf, (olsr_cnf->smart_gw_egress_interfaces_count * IFNAMSIZ) /* interface names */
+          + (olsr_cnf->smart_gw_egress_interfaces_count - 1) /* commas */);
+      while (egressif) {
+        if (egressbuf.len) {
+          abuf_puts(&egressbuf, ",");
+        }
+        abuf_appendf(&egressbuf, "%s", egressif->name);
+      }
+      abuf_json_string(abuf, "smartGatewayEgressInterfaces", egressbuf.buf);
+      abuf_free(&egressbuf);
+    }
     abuf_json_boolean(abuf, "smartGatewayAllowNat", olsr_cnf->smart_gw_allow_nat);
     abuf_json_boolean(abuf, "smartGatewayUplinkNat", olsr_cnf->smart_gw_uplink_nat);
     abuf_json_int(abuf, "smartGatewayPeriod", olsr_cnf->smart_gw_period);
index 629fa9c..6fb7761 100644 (file)
@@ -448,6 +448,23 @@ void olsrd_write_cnf_autobuf(struct autobuf *out, struct olsrd_config *cnf) {
       cnf->smart_gw_use_count);
   abuf_puts(out,
     "\n"
+    "# Determines the egress interfaces that are part of the multi-gateway setup and\n"
+    "# therefore only relevant when SmartGatewayUseCount is larger than 1 (in which\n"
+    "# case it must be explicitly set).\n"
+    "# (default is not set)\n"
+    "\n");
+  abuf_appendf(out, "%sSmartGatewayEgressInterfaces",
+      !cnf->smart_gw_egress_interfaces ? "# " : "");
+  {
+    struct sgw_egress_if * sgwegressif = olsr_cnf->smart_gw_egress_interfaces;
+    while (sgwegressif) {
+      abuf_appendf(out, " \"%s\"", sgwegressif->name);
+      sgwegressif = sgwegressif->next;
+    }
+    abuf_puts(out, "\n");
+  }
+  abuf_puts(out,
+    "\n"
     "# Allows the selection of a smartgateway with NAT (only for IPv4)\n"
     "# (default is \"yes\")\n"
     "\n");
index c747655..ebcef3d 100644 (file)
@@ -559,6 +559,37 @@ olsrd_sanity_check_cnf(struct olsrd_config *cnf)
         cnf->smart_gw_use_count, MIN_SMARTGW_USE_COUNT_MIN, MAX_SMARTGW_USE_COUNT_MAX);
     return -1;
   }
+
+  if (cnf->smart_gw_use_count > 1) {
+    struct sgw_egress_if * sgwegressif = cnf->smart_gw_egress_interfaces;
+
+    /* egress interface(s) must be set */
+    if (!sgwegressif) {
+      fprintf(stderr, "Error, no egress interfaces configured in multi-gateway mode\n");
+      return -1;
+    }
+
+    /* an egress interface must not be an OLSR interface */
+    while (sgwegressif) {
+      struct olsr_if * olsrif = cnf->interfaces;
+      while (olsrif) {
+        if (!strcmp(olsrif->name, sgwegressif->name)) {
+          fprintf(stderr, "Error, egress interface %s already is an OLSR interface\n", sgwegressif->name);
+          return -1;
+        }
+        olsrif = olsrif->next;
+      }
+      cnf->smart_gw_egress_interfaces_count++;
+      sgwegressif = sgwegressif->next;
+    }
+
+    if (cnf->smart_gw_egress_interfaces_count > MAX_SMARTGW_EGRESS_INTERFACE_COUNT_MAX) {
+      fprintf(stderr, "Error, egress interface count %u not in range [1, %u]\n",
+          cnf->smart_gw_egress_interfaces_count, MAX_SMARTGW_EGRESS_INTERFACE_COUNT_MAX);
+      return -1;
+    }
+  }
+
   if (cnf->smart_gw_period < MIN_SMARTGW_PERIOD || cnf->smart_gw_period > MAX_SMARTGW_PERIOD) {
     fprintf(stderr, "Error, bad gateway period: %d msec (should be %d-%d)\n",
         cnf->smart_gw_period, MIN_SMARTGW_PERIOD, MAX_SMARTGW_PERIOD);
@@ -793,6 +824,8 @@ set_default_cnf(struct olsrd_config *cnf)
 
   cnf->smart_gw_active = DEF_SMART_GW;
   cnf->smart_gw_use_count = DEF_GW_USE_COUNT;
+  cnf->smart_gw_egress_interfaces = NULL;
+  cnf->smart_gw_egress_interfaces_count = 0;
   cnf->smart_gw_allow_nat = DEF_GW_ALLOW_NAT;
   cnf->smart_gw_period = DEF_GW_PERIOD;
   cnf->smart_gw_stablecount = DEF_GW_STABLE_COUNT;
@@ -923,6 +956,16 @@ olsrd_print_cnf(struct olsrd_config *cnf)
 
   printf("SmGw. Use Count  : %u\n", cnf->smart_gw_use_count);
 
+  printf("SmGw. Egress I/Fs:");
+  {
+    struct sgw_egress_if * sgwegressif = cnf->smart_gw_egress_interfaces;
+    while (sgwegressif) {
+      printf(" %s", sgwegressif->name);
+      sgwegressif = sgwegressif->next;
+    }
+  }
+  printf("\n");
+
   printf("SmGw. Allow NAT  : %s\n", cnf->smart_gw_allow_nat ? "yes" : "no");
 
   printf("SmGw. period     : %d\n", cnf->smart_gw_period);
index 9c253ac..4cb8e1d 100644 (file)
@@ -56,6 +56,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <string.h>
+#include <ctype.h>
 
 #define PARSER_DEBUG 1
 
@@ -216,6 +217,7 @@ static int add_ipv6_addr(YYSTYPE ipaddr_arg, YYSTYPE prefixlen_arg)
 %token TOK_USE_NIIT
 %token TOK_SMART_GW
 %token TOK_SMART_GW_USE_COUNT
+%token TOK_SMART_GW_EGRESS_IFS
 %token TOK_SMART_GW_ALLOW_NAT
 %token TOK_SMART_GW_PERIOD
 %token TOK_SMART_GW_STABLECOUNT
@@ -319,6 +321,7 @@ stmt:       idebug
           | bsrc_ip_routes
           | amain_ip
           | bset_ipforward
+          | ssgw_egress_ifs
 ;
 
 block:      TOK_HNA4 hna4body
@@ -1314,6 +1317,75 @@ ismart_gw_use_count: TOK_SMART_GW_USE_COUNT TOK_INTEGER
 }
 ;
 
+ssgw_egress_ifs:   TOK_SMART_GW_EGRESS_IFS sgw_egress_ifs
+;
+
+sgw_egress_ifs:   | sgw_egress_ifs sgw_egress_if
+;
+
+sgw_egress_if: TOK_STRING
+{
+  struct sgw_egress_if *in, *last;
+  char * str = $1->string;
+  char *end;
+
+  /* Trim leading space */
+  while(isspace(*str)) {
+    str++;
+  }
+
+  /* Trim trailing space */
+  end = str + strlen(str) - 1;
+  while((end > str) && isspace(*end)) {
+    end--;
+  }
+
+  /* Write new null terminator */
+  *(end + 1) = '\0';
+
+  if(*str == 0) {
+    PARSER_DEBUG_PRINTF("Smart gateway egress interface: <empty> (skipped)\n");
+  } else {
+    PARSER_DEBUG_PRINTF("Smart gateway egress interface: %s\n", str);
+
+    in = olsr_cnf->smart_gw_egress_interfaces;
+    last = NULL;
+    while (in != NULL) {
+      if (strcmp(in->name, str) == 0) {
+        free ($1->string);
+        break;
+      }
+      last = in;
+      in = in->next;
+    }
+
+    if (in != NULL) {
+      /* remove old interface from list to add it later at the beginning */
+      if (last) {
+        last->next = in->next;
+      }
+      else {
+        olsr_cnf->smart_gw_egress_interfaces = in->next;
+      }
+    }
+    else {
+      in = malloc(sizeof(*in));
+      if (in == NULL) {
+        fprintf(stderr, "Out of memory(ADD IF)\n");
+        YYABORT;
+      }
+      memset(in, 0, sizeof(*in));
+
+      in->name = str;
+    }
+    /* Queue */
+    in->next = olsr_cnf->smart_gw_egress_interfaces;
+    olsr_cnf->smart_gw_egress_interfaces = in;
+    free($1);
+  }
+}
+;
+
 bsmart_gw_allow_nat: TOK_SMART_GW_ALLOW_NAT TOK_BOOLEAN
 {
        PARSER_DEBUG_PRINTF("Smart gateway allow client nat: %s\n", $2->boolean ? "yes" : "no");
index 25e109f..c40fa3a 100644 (file)
@@ -471,6 +471,11 @@ IPV6ADDR {IPV6PAT1}|{IPV6PAT2}|{IPV6PAT3}|{IPV6PAT4}|{IPV6PAT5}|{IPV6PAT6}|{IPV6
     return TOK_SMART_GW_USE_COUNT;
 }
 
+"SmartGatewayEgressInterfaces" {
+    yylval = NULL;
+    return TOK_SMART_GW_EGRESS_IFS;
+}
+
 "SmartGatewayAllowNAT" {
     yylval = NULL;
     return TOK_SMART_GW_ALLOW_NAT;
index 6bccbb2..3686497 100644 (file)
 #define MIN_SMARTGW_USE_COUNT_MIN  1
 #define MAX_SMARTGW_USE_COUNT_MAX  1
 
+#define MAX_SMARTGW_EGRESS_INTERFACE_COUNT_MAX 32
+
 #define MIN_SMARTGW_PERIOD   1*1000
 #define MAX_SMARTGW_PERIOD   320000*1000
 
@@ -235,6 +237,12 @@ struct plugin_entry {
   struct plugin_entry *next;
 };
 
+struct sgw_egress_if {
+  char *name;
+  uint8_t mark;
+  struct sgw_egress_if *next;
+};
+
 /*
  * The config struct
  */
@@ -281,6 +289,8 @@ struct olsrd_config {
 
   bool smart_gw_active, smart_gw_allow_nat, smart_gw_uplink_nat;
   uint8_t smart_gw_use_count;
+  struct sgw_egress_if * smart_gw_egress_interfaces;
+  uint8_t smart_gw_egress_interfaces_count;
   uint32_t smart_gw_period;
   uint8_t smart_gw_stablecount;
   uint8_t smart_gw_thresh;