[M] Change in openvpn[master]: oob: Add --server-probe-reply to advertise probe priority/weight

"stipa \(Code Review\) via Openvpn-devel" <[email protected]>
Newsgroups gmane.network.openvpn.devel
Message-ID <7698fb15275092769d7c025324c5906cb3559468-EmailReplacePatchSet-HTML@gerrit.openvpn.net>
Attention is currently required from: plaisthos.

Hello plaisthos, 

I'd like you to reexamine a change. Please visit

    http://gerrit.openvpn.net/c/openvpn/+/1752?usp=email

to look at the new patch set (#10).


Change subject: oob: Add --server-probe-reply to advertise probe priority/weight
......................................................................

oob: Add --server-probe-reply to advertise probe priority/weight

Add a server option, --server-probe-reply <priority> <weight>, that sets
the DNS-SRV-style priority and weight the server returns in its OOB
PROBE_REPLY. Both default to 0 (the previous hardcoded behaviour), and are
range-checked to 0..65535.

The values are plumbed through oob_build_probe_reply() into the probe_reply
TLV; the client already reads and ranks remotes by them.

Change-Id: Id74cfae7e9d69029d2ddbf635ee85a2a6cedc3d8
Signed-off-by: Lev Stipakov <[email protected]>
---
M Changes.rst
M doc/man-sections/server-options.rst
M src/openvpn/mudp.c
M src/openvpn/oob.c
M src/openvpn/oob.h
M src/openvpn/options.c
M src/openvpn/options.h
M tests/unit_tests/openvpn/test_oob.c
8 files changed, 91 insertions(+), 15 deletions(-)


  git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/52/1752/10

diff --git a/Changes.rst b/Changes.rst
index 1f992b2..080d928 100644
--- a/Changes.rst
+++ b/Changes.rst
@@ -1,5 +1,13 @@
 Overview of changes in 2.8
 ==========================
+New features
+------------
+Out-of-band server probing and server-controlled selection
+    With ``--server-probe``, a client probes all configured UDP remotes
+    before connecting and reorders them based on the replies: reachable
+    servers are tried first, ordered by server-advertised priority,
+    measured latency and advertised weight with DNS-SRV-like semantics.
+    Servers advertise these values with ``--server-probe-reply``.
 
 
 Overview of changes in 2.7
diff --git a/doc/man-sections/server-options.rst b/doc/man-sections/server-options.rst
index f420588..1277cf7 100644
--- a/doc/man-sections/server-options.rst
+++ b/doc/man-sections/server-options.rst
@@ -662,6 +662,31 @@
   Pushing of the ``--tun-ipv6`` directive is done for older clients which
   require an explicit ``--tun-ipv6`` in their configuration.
 
+--server-probe-reply args
+  Set the values a server advertises in its replies to out-of-band
+  probes from clients using ``--server-probe``.
+
+  Valid syntaxes::
+
+     server-probe-reply max-latency-diff
+     server-probe-reply max-latency-diff weight
+     server-probe-reply max-latency-diff weight priority
+
+  ``max-latency-diff`` is the candidate-band margin in milliseconds: a
+  probing client treats servers of the same priority whose round-trip
+  time is within this margin of the fastest one as equally good.
+  :code:`0` (the default) lets the client use its own margin.
+
+  ``weight`` (default :code:`50`) and ``priority`` (default :code:`100`)
+  have DNS SRV (RFC 2782) semantics: clients try servers with a lower
+  priority value first, and distribute load between equally-good
+  servers of the same priority proportionally to their weights.
+
+  All values are in the range :code:`0` to :code:`65535`. A UDP server
+  answers probes regardless of this option; replies are stateless,
+  replay-protected and rate-limited. The option only controls the
+  advertised values.
+
 --stale-routes-check args
   Remove routes which haven't had activity for ``n`` seconds (i.e. the ageing
   time).  This check is run every ``t`` seconds (i.e. check interval).
diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c
index 2a25053..9e33e3c 100644
--- a/src/openvpn/mudp.c
+++ b/src/openvpn/mudp.c
@@ -239,7 +239,11 @@
          * tls-auth/tls-crypt wrapping). Answer it without creating a session. */
         struct oob_probe_reply reply;
         if (!oob_build_probe_reply(&state->newbuf, (uint64_t)now, (uint64_t)handwindow,
-                                   &state->peer_session_id, &reply))
+                                   &state->peer_session_id,
+                                   (uint16_t)m->top.options.server_probe_reply_priority,
+                                   (uint16_t)m->top.options.server_probe_reply_weight,
+                                   (uint16_t)m->top.options.server_probe_reply_max_latency_diff,
+                                   &reply))
         {
             /* malformed or replayed/stale probe: silently drop */
             return false;
diff --git a/src/openvpn/oob.c b/src/openvpn/oob.c
index 3598d5b..79a2177 100644
--- a/src/openvpn/oob.c
+++ b/src/openvpn/oob.c
@@ -236,7 +236,8 @@
 
 bool
 oob_build_probe_reply(struct buffer *probe_payload, uint64_t now, uint64_t window_secs,
-                      const struct session_id *peer_sid, struct oob_probe_reply *reply)
+                      const struct session_id *peer_sid, uint16_t priority, uint16_t weight,
+                      uint16_t max_latency_diff, struct oob_probe_reply *reply)
 {
     struct oob_probe_parameter param;
     if (!oob_server_probe_read(probe_payload, &param))
@@ -252,7 +253,10 @@
 
     memset(reply, 0, sizeof(*reply));
     reply->peer_session_id = *peer_sid;
-    /* priority/weight/connect_lifetime/flags left at 0 for now */
+    reply->priority = priority;
+    reply->weight = weight;
+    reply->max_latency_diff = max_latency_diff;
+    /* connect_lifetime/flags left at 0 for now */
     return true;
 }
 
diff --git a/src/openvpn/oob.h b/src/openvpn/oob.h
index 2202b60..0f1cd08 100644
--- a/src/openvpn/oob.h
+++ b/src/openvpn/oob.h
@@ -205,8 +205,8 @@
  * answer it. Combines oob_server_probe_read() and oob_timestamp_in_window():
  * the probe is dropped (false returned) if it has no valid probe_parameter or
  * its timestamp is outside the acceptable window. On success @p reply is
- * populated with the peer's session id echoed back and the remaining fields
- * zeroed, ready to be wrapped and sent.
+ * populated with the peer's session id echoed back and the given priority and
+ * weight (other fields zeroed), ready to be wrapped and sent.
  *
  * This is the transport-agnostic decision step; the caller performs the send.
  *
@@ -214,11 +214,15 @@
  * @param now            current time (UNIX seconds)
  * @param window_secs    acceptable timestamp skew, in either direction
  * @param peer_sid       session id of the requesting peer (echoed in the reply)
+ * @param priority       priority to advertise (DNS-SRV semantics; lower preferred)
+ * @param weight         weight to advertise (DNS-SRV semantics; higher preferred)
+ * @param max_latency_diff  candidate-band margin (ms) to advertise; 0 = defer to client
  * @param reply          filled with the reply to send on success
  * @return true if a reply should be sent, false to silently drop the probe
  */
 bool oob_build_probe_reply(struct buffer *probe_payload, uint64_t now, uint64_t window_secs,
-                           const struct session_id *peer_sid, struct oob_probe_reply *reply);
+                           const struct session_id *peer_sid, uint16_t priority, uint16_t weight,
+                           uint16_t max_latency_diff, struct oob_probe_reply *reply);
 
 /* Candidate-band margin (ms) used when neither the client nor the server
  * specifies one. */
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index dc88a55..6edb78b 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -805,10 +805,14 @@
     o->ce.proto = PROTO_UDP;
     o->ce.af = AF_UNSPEC;
 
-    /* The client latency margin is -1 = "not set": the client's value is
-     * authoritative when given, otherwise each server's advertised margin (or
-     * the built-in default) applies. */
+    /* server-probe defaults. The client latency margin is -1 = "not set": the
+     * client's value is authoritative when given, otherwise each server's
+     * advertised margin (or the built-in default) applies. An (unconfigured)
+     * server advertises weight 50 / priority 100 and no margin (0). */
     o->server_probe_latency_margin = -1;
+    o->server_probe_reply_weight = 50;
+    o->server_probe_reply_priority = 100;
+    o->server_probe_reply_max_latency_diff = 0;
     o->ce.bind_ipv6_only = false;
     o->ce.connect_retry_seconds = 1;
     o->ce.connect_retry_seconds_max = 300;
@@ -6527,6 +6531,26 @@
             options->server_probe_latency_margin = margin;
         }
     }
+    else if (streq(p[0], "server-probe-reply") && !p[4])
+    {
+        VERIFY_PERMISSION(OPT_P_GENERAL);
+        /* --server-probe-reply [max-latency-diff] [weight] [prio]; each optional */
+        int vals[3] = { options->server_probe_reply_max_latency_diff,
+                        options->server_probe_reply_weight,
+                        options->server_probe_reply_priority };
+        for (int i = 0; i < 3 && p[i + 1]; i++)
+        {
+            vals[i] = positive_atoi(p[i + 1], msglevel);
+            if (vals[i] > 0xffff)
+            {
+                msg(msglevel, "--server-probe-reply: values must be 0 to 65535");
+                goto err;
+            }
+        }
+        options->server_probe_reply_max_latency_diff = vals[0];
+        options->server_probe_reply_weight = vals[1];
+        options->server_probe_reply_priority = vals[2];
+    }
     else if (streq(p[0], "nice") && p[1] && !p[2])
     {
         VERIFY_PERMISSION(OPT_P_NICE);
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index 6b1120a..6e4829d 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -339,6 +339,12 @@
     /* client: default candidate-band margin in ms (--server-probe [max-latency-diff]):
      * servers within this RTT of the fastest are treated as equally fast */
     int server_probe_latency_margin;
+    /* server: values advertised in the OOB PROBE_REPLY (--server-probe-reply).
+     * priority/weight follow DNS-SRV semantics; max_latency_diff overrides the
+     * client's margin for this server (0 = defer to the client). */
+    int server_probe_reply_priority;
+    int server_probe_reply_weight;
+    int server_probe_reply_max_latency_diff;
 
     bool mlock;
 
diff --git a/tests/unit_tests/openvpn/test_oob.c b/tests/unit_tests/openvpn/test_oob.c
index 3657291..8861d68 100644
--- a/tests/unit_tests/openvpn/test_oob.c
+++ b/tests/unit_tests/openvpn/test_oob.c
@@ -305,7 +305,7 @@
 }
 
 /* A valid, in-window SERVER_PROBE yields a reply that echoes the peer's
- * session id and zeroes the remaining fields. */
+ * session id and carries the configured priority and weight. */
 static void
 test_build_probe_reply_valid(void **state)
 {
@@ -320,12 +320,13 @@
     memcpy(peer.id, "PEER1234", SID_SIZE);
 
     struct oob_probe_reply reply;
-    assert_true(oob_build_probe_reply(&buf, now, 30, &peer, &reply));
+    assert_true(oob_build_probe_reply(&buf, now, 30, &peer, 5, 50, 25, &reply));
     assert_memory_equal(reply.peer_session_id.id, peer.id, SID_SIZE);
-    assert_int_equal(reply.priority, 0);
-    assert_int_equal(reply.weight, 0);
+    assert_int_equal(reply.priority, 5);
+    assert_int_equal(reply.weight, 50);
     assert_int_equal(reply.connect_lifetime, 0);
     assert_int_equal(reply.flags, 0);
+    assert_int_equal(reply.max_latency_diff, 25);
 
     gc_free(&gc);
 }
@@ -343,7 +344,7 @@
 
     struct session_id peer = { 0 };
     struct oob_probe_reply reply;
-    assert_false(oob_build_probe_reply(&buf, now, 30, &peer, &reply));
+    assert_false(oob_build_probe_reply(&buf, now, 30, &peer, 0, 0, 0, &reply));
 
     gc_free(&gc);
 }
@@ -361,7 +362,7 @@
 
     struct session_id peer = { 0 };
     struct oob_probe_reply reply;
-    assert_false(oob_build_probe_reply(&buf, 1000000, 30, &peer, &reply));
+    assert_false(oob_build_probe_reply(&buf, 1000000, 30, &peer, 0, 0, 0, &reply));
 
     gc_free(&gc);
 }

-- 
To view, visit http://gerrit.openvpn.net/c/openvpn/+/1752?usp=email
To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings?usp=email

Gerrit-MessageType: newpatchset
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: Id74cfae7e9d69029d2ddbf635ee85a2a6cedc3d8
Gerrit-Change-Number: 1752
Gerrit-PatchSet: 10
Gerrit-Owner: stipa <[email protected]>
Gerrit-Reviewer: plaisthos <[email protected]>
Gerrit-CC: openvpn-devel <[email protected]>
Gerrit-Attention: plaisthos <[email protected]>

_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.