Attention is currently required from: plaisthos.
Hello plaisthos,
I'd like you to do a code review.
Please visit
http://gerrit.openvpn.net/c/openvpn/+/1434?usp=email
to review the following change.
Change subject: dco_linux: parse stats in PEER_DEL notification if available
......................................................................
dco_linux: parse stats in PEER_DEL notification if available
Upon receiving a PEER_DEL notification, update the peer's statistics
counters if such information is present in the message. This allows
openvpn to avoid issuing a PEER_GET request-reply, eliminating issues
caused by overlapping traffic on the netlink socket when multiple
PEER_DEL notifications are received simultaneously.
Since we cannot assume the kernel module will always send a PEER_DEL
with statistics, introduce a boolean flag to track whether the counters
were already updated or if a PEER_GET request is still required.
Change-Id: I7f3b95cacdf359536e827f176f2b81da4b00f22f
Signed-off-by: Ralf Lici <[email protected]>
---
M src/openvpn/dco.c
M src/openvpn/dco.h
M src/openvpn/dco_freebsd.c
M src/openvpn/dco_freebsd.h
M src/openvpn/dco_linux.c
M src/openvpn/dco_linux.h
M src/openvpn/dco_win.c
M src/openvpn/dco_win.h
M src/openvpn/multi.c
9 files changed, 82 insertions(+), 45 deletions(-)
git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/34/1434/1
diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c
index 7abdad3..3329ff9 100644
--- a/src/openvpn/dco.c
+++ b/src/openvpn/dco.c
@@ -778,4 +778,10 @@
#endif /* if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) ||
defined(_WIN32) */
}
+bool
+dco_del_peer_stats_updated(dco_context_t *dco)
+{
+ return dco->dco_del_peer_stats_updated;
+}
+
#endif /* defined(ENABLE_DCO) */
diff --git a/src/openvpn/dco.h b/src/openvpn/dco.h
index cd6e32a..a81a968 100644
--- a/src/openvpn/dco.h
+++ b/src/openvpn/dco.h
@@ -242,6 +242,16 @@
int dco_get_peer_stats(struct context *c, const bool raise_sigusr1_on_err);
/**
+ * Check if the peer stats were already updated while parsing a PEER_DEL
+ * notification. This is simply a getter for the internal
+ * dco->dco_del_peer_stats_updated field.
+ *
+ * @param dco DCO device context
+ * @return value of dco->dco_del_peer_stats_updated
+ */
+bool dco_del_peer_stats_updated(dco_context_t *dco);
+
+/**
* Retrieve the list of ciphers supported by the current platform
*
* @return list of colon-separated ciphers
@@ -377,6 +387,12 @@
return 0;
}
+static inline bool
+dco_del_peer_stats_updated(dco_context_t *dco)
+{
+ return false;
+}
+
static inline const char *
dco_get_supported_ciphers(void)
{
diff --git a/src/openvpn/dco_freebsd.c b/src/openvpn/dco_freebsd.c
index d1ad092..e47ddd2 100644
--- a/src/openvpn/dco_freebsd.c
+++ b/src/openvpn/dco_freebsd.c
@@ -559,13 +559,13 @@
return ret;
}
-static void
+static bool
dco_update_peer_stat(struct multi_context *m, uint32_t peerid, const nvlist_t
*nvl)
{
if (peerid >= m->max_clients || !m->instances[peerid])
{
msg(M_WARN, "dco_update_peer_stat: invalid peer ID %u returned by
kernel", peerid);
- return;
+ return false;
}
struct multi_instance *mi = m->instances[peerid];
@@ -575,6 +575,7 @@
msg(D_DCO_DEBUG, "%s: peer-id %u, dco_read_bytes: " counter_format "
dco_write_bytes: " counter_format,
__func__, peerid, mi->context.c2.dco_read_bytes,
mi->context.c2.dco_write_bytes);
+ return true;
}
int
@@ -620,6 +621,7 @@
{
case OVPN_NOTIF_DEL_PEER:
dco->dco_del_peer_reason = OVPN_DEL_PEER_REASON_EXPIRED;
+ dco->dco_del_peer_stats_updated = false;
if (nvlist_exists_number(nvl, "del_reason"))
{
@@ -642,12 +644,13 @@
if (dco->c->mode == CM_TOP)
{
- dco_update_peer_stat(dco->c->multi,
dco->dco_message_peer_id, bytes);
+ dco->dco_del_peer_stats_updated =
dco_update_peer_stat(dco->c->multi, dco->dco_message_peer_id, bytes);
}
else
{
dco->c->c2.dco_read_bytes = nvlist_get_number(bytes, "in");
dco->c->c2.dco_write_bytes = nvlist_get_number(bytes,
"out");
+ dco->dco_del_peer_stats_updated = true;
}
}
diff --git a/src/openvpn/dco_freebsd.h b/src/openvpn/dco_freebsd.h
index 5e2a552..72056b0 100644
--- a/src/openvpn/dco_freebsd.h
+++ b/src/openvpn/dco_freebsd.h
@@ -60,6 +60,7 @@
int dco_message_type;
int dco_message_peer_id;
int dco_del_peer_reason;
+ bool dco_del_peer_stats_updated;
struct sockaddr_storage dco_float_peer_ss;
struct context *c;
diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c
index 2664029..743eb5c 100644
--- a/src/openvpn/dco_linux.c
+++ b/src/openvpn/dco_linux.c
@@ -49,10 +49,10 @@
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
-/* When parsing multiple DEL_PEER notifications, openvpn tries to request stats
- * for each DEL_PEER message (see setenv_stats). This triggers a GET_PEER
- * request-reply while we are still parsing the rest of the initial
- * notifications, which can lead to NLE_BUSY or even NLE_NOMEM.
+/* When parsing multiple DEL_PEER notifications that do not include stats,
+ * openvpn tries to request them for each DEL_PEER message (see setenv_stats).
+ * This triggers a GET_PEER request-reply while we are still parsing the rest
+ * of the initial notifications, which can lead to NLE_BUSY or even NLE_NOMEM.
*
* This basic lock ensures we don't bite our own tail by issuing a dco_get_peer
* while still busy receiving and parsing other messages.
@@ -814,9 +814,38 @@
}
}
-static void
-dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id)
+static bool
+dco_update_peer_stat(dco_context_t *dco, struct nlattr *tb[], uint32_t id)
{
+ struct context_2 *c2;
+
+ if (dco->ifmode == OVPN_MODE_P2P)
+ {
+ c2 = &dco->c->c2;
+ if (c2->tls_multi->dco_peer_id != id)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (id >= dco->c->multi->max_clients)
+ {
+ msg(M_WARN, "%s: received out of bound id %u (max=%u)", __func__,
id,
+ dco->c->multi->max_clients);
+ return false;
+ }
+
+ struct multi_instance *mi = dco->c->multi->instances[id];
+ if (!mi)
+ {
+ msg(M_WARN | M_NOIPREFIX, "%s: received data for a non-existing
peer %u", __func__, id);
+ return false;
+ }
+
+ c2 = &mi->context.c2;
+ }
+
if (tb[OVPN_A_PEER_LINK_RX_BYTES])
{
c2->dco_read_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_LINK_RX_BYTES]);
@@ -824,7 +853,8 @@
}
else
{
- msg(M_WARN, "%s: no link RX bytes provided in reply for peer %u",
__func__, id);
+ msg(M_WARN, "%s: no link RX bytes provided for peer %u", __func__, id);
+ return false;
}
if (tb[OVPN_A_PEER_LINK_TX_BYTES])
@@ -834,7 +864,8 @@
}
else
{
- msg(M_WARN, "%s: no link TX bytes provided in reply for peer %u",
__func__, id);
+ msg(M_WARN, "%s: no link TX bytes provided for peer %u", __func__, id);
+ return false;
}
if (tb[OVPN_A_PEER_VPN_RX_BYTES])
@@ -844,7 +875,8 @@
}
else
{
- msg(M_WARN, "%s: no VPN RX bytes provided in reply for peer %u",
__func__, id);
+ msg(M_WARN, "%s: no VPN RX bytes provided for peer %u", __func__, id);
+ return false;
}
if (tb[OVPN_A_PEER_VPN_TX_BYTES])
@@ -854,8 +886,11 @@
}
else
{
- msg(M_WARN, "%s: no VPN TX bytes provided in reply for peer %u",
__func__, id);
+ msg(M_WARN, "%s: no VPN TX bytes provided for peer %u", __func__, id);
+ return false;
}
+
+ return true;
}
static int
@@ -877,40 +912,10 @@
}
uint32_t peer_id = nla_get_u32(tb_peer[OVPN_A_PEER_ID]);
- struct context_2 *c2;
msg(D_DCO_DEBUG | M_NOIPREFIX, "%s: parsing message for peer %u...",
__func__, peer_id);
- if (dco->ifmode == OVPN_MODE_P2P)
- {
- c2 = &dco->c->c2;
- if (c2->tls_multi->dco_peer_id != peer_id)
- {
- return NL_SKIP;
- }
- }
- else
- {
- if (peer_id >= dco->c->multi->max_clients)
- {
- msg(M_WARN, "%s: received out of bound peer_id %u (max=%u)",
__func__, peer_id,
- dco->c->multi->max_clients);
- return NL_SKIP;
- }
-
- struct multi_instance *mi = dco->c->multi->instances[peer_id];
- if (!mi)
- {
- msg(M_WARN | M_NOIPREFIX, "%s: received data for a non-existing
peer %u", __func__, peer_id);
- return NL_SKIP;
- }
-
- c2 = &mi->context.c2;
- }
-
- dco_update_peer_stat(c2, tb_peer, peer_id);
-
- return NL_OK;
+ return dco_update_peer_stat(dco, tb_peer, peer_id) ? NL_OK : NL_SKIP;
}
static bool
@@ -976,6 +981,9 @@
dco->dco_del_peer_reason = reason;
dco->dco_message_type = OVPN_CMD_PEER_DEL_NTF;
+ /* parse stats if available */
+ dco->dco_del_peer_stats_updated = dco_update_peer_stat(dco, dp_attrs,
peerid);
+
return NL_OK;
}
diff --git a/src/openvpn/dco_linux.h b/src/openvpn/dco_linux.h
index efd5b27..e275061 100644
--- a/src/openvpn/dco_linux.h
+++ b/src/openvpn/dco_linux.h
@@ -80,6 +80,7 @@
int dco_message_peer_id;
int dco_message_key_id;
int dco_del_peer_reason;
+ bool dco_del_peer_stats_updated;
struct sockaddr_storage dco_float_peer_ss;
} dco_context_t;
diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c
index 94f043f..030d353 100644
--- a/src/openvpn/dco_win.c
+++ b/src/openvpn/dco_win.c
@@ -681,6 +681,7 @@
dco->dco_message_peer_id = dco->notif_buf.PeerId;
dco->dco_message_type = dco->notif_buf.Cmd;
dco->dco_del_peer_reason = dco->notif_buf.DelPeerReason;
+ dco->dco_del_peer_stats_updated = false;
dco->dco_float_peer_ss = dco->notif_buf.FloatAddress;
}
else
diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h
index 02b8389..599f41d 100644
--- a/src/openvpn/dco_win.h
+++ b/src/openvpn/dco_win.h
@@ -53,6 +53,7 @@
int dco_message_peer_id;
int dco_message_type;
int dco_del_peer_reason;
+ bool dco_del_peer_stats_updated;
struct sockaddr_storage dco_float_peer_ss;
struct context *c;
diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c
index 153695c..4c7d3e2 100644
--- a/src/openvpn/multi.c
+++ b/src/openvpn/multi.c
@@ -510,7 +510,7 @@
static void
setenv_stats(struct multi_context *m, struct context *c)
{
- if (dco_enabled(&m->top.options))
+ if (dco_enabled(&m->top.options) &&
!dco_del_peer_stats_updated(&m->top.c1.tuntap->dco))
{
if (dco_get_peer_stats_multi(&m->top.c1.tuntap->dco, false) < 0)
{
--
To view, visit http://gerrit.openvpn.net/c/openvpn/+/1434?usp=email
To unsubscribe, or for help writing mail filters, visit
http://gerrit.openvpn.net/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: I7f3b95cacdf359536e827f176f2b81da4b00f22f
Gerrit-Change-Number: 1434
Gerrit-PatchSet: 1
Gerrit-Owner: ralf_lici <[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