lqnatthresh: maintain an advantage for the current (NAT) inet gw
[olsrd.git] / src / routing_table.c
index f9db44a..242a9bb 100644 (file)
 
 #include <assert.h>
 
+/*
+ * Sven-Ola: if the current internet gateway is switched, the
+ * NAT connection info is lost for any active TCP/UDP session.
+ * For this reason, we do not want to switch if the advantage
+ * is only minimal (cost of loosing all NATs is too high).
+ * The following rt_path keeps track of the current inet gw.
+ */
+static struct rt_path *current_inetgw = NULL;
+
 /* Root of our RIB */
 struct avl_tree routingtree;
 
@@ -343,6 +352,11 @@ olsr_free_rt_path(struct rt_path *rtp)
     rtp->rtp_tc = NULL;
   }
 
+  /* no current inet gw if the rt_path is removed */
+  if (current_inetgw == rtp) {
+    current_inetgw = NULL;
+  }
+
   free(rtp);
 }
 
@@ -410,15 +424,20 @@ olsr_get_nh(const struct rt_entry *rt)
  * than the second one, FALSE otherwise.
  */
 static olsr_bool
-olsr_cmp_rtp(const struct rt_path *rtp1, const struct rt_path *rtp2)
+olsr_cmp_rtp(const struct rt_path *rtp1, const struct rt_path *rtp2, const struct rt_path *inetgw)
 {
-   /* etx comes first */
-    if (rtp1->rtp_metric.etx < rtp2->rtp_metric.etx) {
+    float etx1 = rtp1->rtp_metric.etx;
+    float etx2 = rtp2->rtp_metric.etx;
+    if (inetgw == rtp1) etx1 *= olsr_cnf->lq_nat_thresh;
+    if (inetgw == rtp2) etx2 *= olsr_cnf->lq_nat_thresh;
+
+    /* etx comes first */
+    if (etx1 < etx2) {
       return OLSR_TRUE;
     }
 
     /* hopcount is next tie breaker */
-    if ((rtp1->rtp_metric.etx == rtp2->rtp_metric.etx) &&
+    if ((etx1 == etx2) &&
         (rtp1->rtp_metric.hops < rtp2->rtp_metric.hops)) {
       return OLSR_TRUE;
     }
@@ -442,7 +461,7 @@ olsr_cmp_rtp(const struct rt_path *rtp1, const struct rt_path *rtp2)
 olsr_bool
 olsr_cmp_rt(const struct rt_entry *rt1, const struct rt_entry *rt2)
 {
-  return olsr_cmp_rtp(rt1->rt_best, rt2->rt_best);
+  return olsr_cmp_rtp(rt1->rt_best, rt2->rt_best, NULL);
 }
 
 /**
@@ -463,10 +482,14 @@ olsr_rt_best(struct rt_entry *rt)
   while ((node = avl_walk_next(node))) {
     struct rt_path *rtp = node->data;
 
-    if (olsr_cmp_rtp(rtp, rt->rt_best)) {
+    if (olsr_cmp_rtp(rtp, rt->rt_best, current_inetgw)) {
       rt->rt_best = rtp;
     }
   }
+
+  if (0 == rt->rt_dst.prefix_len) {
+    current_inetgw = rt->rt_best;
+  }
 }
 
 /**