ike-sa: Optionally try to migrate to the best path on routing priority changes
authorMartin Willi <martin@strongswan.org>
Mon, 10 Oct 2016 13:59:52 +0000 (15:59 +0200)
committerMartin Willi <martin@strongswan.org>
Fri, 17 Feb 2017 10:19:38 +0000 (11:19 +0100)
When multihomed, a setup might prefer to dynamically stay on the cheapest
available path by using MOBIKE migrations. If the cheapest path goes away and
comes back, we currently stay on the more expensive path to reduce noise and
prevent potential migration issues. This is usually just fine for links not
generating real cost.

If we have more expensive links in the setup, it can be desirable to always
migrate to the cheapest link available. By setting charon.prefer_best_path,
charon tries to migrate to the path using the highest priority link, allowing
an external application to update routes to indirectly control MOBIKE behavior.
This option has no effect if MOBIKE is unavailable.

conf/options/charon.opt
src/libcharon/sa/ike_sa.c

index 6e0b37c..7c56fc1 100644 (file)
@@ -260,6 +260,16 @@ charon.port_nat_t = 4500
        allocated.  Has to be different from **charon.port**, otherwise a random
        port will be allocated.
 
+charon.prefer_best_path = no
+       Wether to prefer updating SAs to the path with the best route.
+
+       By default, charon keeps SAs on the routing path with addresses it
+       previously used if that path is still usable. By setting this option to
+       yes, it tries more aggressively to update SAs with MOBIKE on routing
+       priority changes using the cheapest path. This adds more noise, but allows
+       to dynamically adapt SAs to routing priority changes. This option has no
+       effect if MOBIKE is not supported or disabled.
+
 charon.prefer_configured_proposals = yes
        Prefer locally configured proposals for IKE/IPsec over supplied ones as
        responder (disabling this can avoid keying retries due to INVALID_KE_PAYLOAD
index 589784c..76294ce 100644 (file)
@@ -2442,6 +2442,25 @@ static bool is_current_path_valid(private_ike_sa_t *this)
 {
        bool valid = FALSE;
        host_t *src;
+
+       if (supports_extension(this, EXT_MOBIKE) &&
+               lib->settings->get_bool(lib->settings,
+                                                               "%s.prefer_best_path", FALSE, lib->ns))
+       {
+               /* check if the current path is the best path; migrate otherwise */
+               src = charon->kernel->get_source_addr(charon->kernel, this->other_host,
+                                                                                         NULL);
+               if (src)
+               {
+                       valid = src->ip_equals(src, this->my_host);
+                       src->destroy(src);
+               }
+               if (!valid)
+               {
+                       DBG1(DBG_IKE, "old path is not preferred anymore");
+               }
+               return valid;
+       }
        src = charon->kernel->get_source_addr(charon->kernel, this->other_host,
                                                                                  this->my_host);
        if (src)
@@ -2452,6 +2471,10 @@ static bool is_current_path_valid(private_ike_sa_t *this)
                }
                src->destroy(src);
        }
+       if (!valid)
+       {
+               DBG1(DBG_IKE, "old path is not available anymore, try to find another");
+       }
        return valid;
 }
 
@@ -2478,7 +2501,6 @@ static bool is_any_path_valid(private_ike_sa_t *this)
                        break;
        }
 
-       DBG1(DBG_IKE, "old path is not available anymore, try to find another");
        enumerator = create_peer_address_enumerator(this);
        while (enumerator->enumerate(enumerator, &addr))
        {