Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 Dec 2022 05:49:45 GMT
From:      Kristof Provost <kp@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 92f0cf77db18 - main - if_ovpn: allow peer lookup by vpn4/vpn6 address
Message-ID:  <202212140549.2BE5njUg034660@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=92f0cf77db18502cac9a731cd2f6e8f3cc8a9369

commit 92f0cf77db18502cac9a731cd2f6e8f3cc8a9369
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2022-11-29 11:06:32 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2022-12-14 05:48:59 +0000

    if_ovpn: allow peer lookup by vpn4/vpn6 address
    
    Introduce two more RB_TREEs so that we can look up peers by their peer
    id (already present) or vpn4 or vpn6 address.
    This removes the last linear scan of the peer list.
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D37605
---
 sys/net/if_ovpn.c | 81 ++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 63 insertions(+), 18 deletions(-)

diff --git a/sys/net/if_ovpn.c b/sys/net/if_ovpn.c
index 2cfe55568348..cf5f2cc6fcf6 100644
--- a/sys/net/if_ovpn.c
+++ b/sys/net/if_ovpn.c
@@ -174,6 +174,8 @@ struct ovpn_counters {
 #define OVPN_COUNTER_SIZE (sizeof(struct ovpn_counters)/sizeof(uint64_t))
 
 RB_HEAD(ovpn_kpeers, ovpn_kpeer);
+RB_HEAD(ovpn_kpeers_by_ip, ovpn_kpeer);
+RB_HEAD(ovpn_kpeers_by_ip6, ovpn_kpeer);
 
 struct ovpn_softc {
 	int			 refcount;
@@ -182,6 +184,8 @@ struct ovpn_softc {
 	struct socket		*so;
 	int			 peercount;
 	struct ovpn_kpeers	 peers;
+	struct ovpn_kpeers_by_ip	peers_by_ip;
+	struct ovpn_kpeers_by_ip6	peers_by_ip6;
 
 	/* Pending notification */
 	struct buf_ring		*notifring;
@@ -192,6 +196,10 @@ struct ovpn_softc {
 };
 
 static struct ovpn_kpeer *ovpn_find_peer(struct ovpn_softc *, uint32_t);
+static struct ovpn_kpeer *ovpn_find_peer_by_ip(struct ovpn_softc *,
+    const struct in_addr);
+static struct ovpn_kpeer *ovpn_find_peer_by_ip6(struct ovpn_softc *,
+    const struct in6_addr *);
 static bool ovpn_udp_input(struct mbuf *, int, struct inpcb *,
     const struct sockaddr *, void *);
 static int ovpn_transmit_to_peer(struct ifnet *, struct mbuf *,
@@ -200,10 +208,23 @@ static int ovpn_encap(struct ovpn_softc *, uint32_t, struct mbuf *);
 static int ovpn_get_af(struct mbuf *);
 static void ovpn_free_kkey_dir(struct ovpn_kkey_dir *);
 static bool ovpn_check_replay(struct ovpn_kkey_dir *, uint32_t);
-static int ovpn_peer_compare(struct ovpn_kpeer *, struct ovpn_kpeer *);
+static int ovpn_peer_compare(const struct ovpn_kpeer *,
+    const struct ovpn_kpeer *);
+static int ovpn_peer_compare_by_ip(const struct ovpn_kpeer *,
+    const struct ovpn_kpeer *);
+static int ovpn_peer_compare_by_ip6(const struct ovpn_kpeer *,
+    const struct ovpn_kpeer *);
 
 static RB_PROTOTYPE(ovpn_kpeers, ovpn_kpeer, tree, ovpn_peer_compare);
 static RB_GENERATE(ovpn_kpeers, ovpn_kpeer, tree, ovpn_peer_compare);
+static RB_PROTOTYPE(ovpn_kpeers_by_ip, ovpn_kpeer, tree,
+    ovpn_peer_compare_by_ip);
+static RB_GENERATE(ovpn_kpeers_by_ip, ovpn_kpeer, tree,
+    ovpn_peer_compare_by_ip);
+static RB_PROTOTYPE(ovpn_kpeers_by_ip6, ovpn_kpeer, tree,
+    ovpn_peer_compare_by_ip6);
+static RB_GENERATE(ovpn_kpeers_by_ip6, ovpn_kpeer, tree,
+    ovpn_peer_compare_by_ip6);
 
 #define OVPN_MTU_MIN		576
 #define OVPN_MTU_MAX		(IP_MAXPACKET - sizeof(struct ip) - \
@@ -267,11 +288,24 @@ SYSCTL_INT(_net_link_openvpn, OID_AUTO, netisr_queue,
 	"Use netisr_queue() rather than netisr_dispatch().");
 
 static int
-ovpn_peer_compare(struct ovpn_kpeer *a, struct ovpn_kpeer *b)
+ovpn_peer_compare(const struct ovpn_kpeer *a, const struct ovpn_kpeer *b)
 {
 	return (a->peerid - b->peerid);
 }
 
+static int
+ovpn_peer_compare_by_ip(const struct ovpn_kpeer *a, const struct ovpn_kpeer *b)
+{
+	return (memcmp(&a->vpn4, &b->vpn4, sizeof(a->vpn4)));
+}
+
+static int
+ovpn_peer_compare_by_ip6(const struct ovpn_kpeer *a,
+    const struct ovpn_kpeer *b)
+{
+	return (memcmp(&a->vpn6, &b->vpn6, sizeof(a->vpn6)));
+}
+
 static struct ovpn_kpeer *
 ovpn_find_peer(struct ovpn_softc *sc, uint32_t peerid)
 {
@@ -596,8 +630,14 @@ ovpn_new_peer(struct ifnet *ifp, const nvlist_t *nvl)
 	if (sc->so == NULL)
 		sc->so = so;
 
-	/* Insert the peer into the list. */
+	/* Insert the peer into the lists. */
 	RB_INSERT(ovpn_kpeers, &sc->peers, peer);
+	if (nvlist_exists_binary(nvl, "vpn_ipv4")) {
+		RB_INSERT(ovpn_kpeers_by_ip, &sc->peers_by_ip, peer);
+	}
+	if (nvlist_exists_binary(nvl, "vpn_ipv6")) {
+		RB_INSERT(ovpn_kpeers_by_ip6, &sc->peers_by_ip6, peer);
+	}
 	sc->peercount++;
 	soref(sc->so);
 
@@ -608,6 +648,12 @@ ovpn_new_peer(struct ifnet *ifp, const nvlist_t *nvl)
 	}
 	if (ret != 0) {
 		RB_REMOVE(ovpn_kpeers, &sc->peers, peer);
+		if (nvlist_exists_binary(nvl, "vpn_ipv4")) {
+			RB_REMOVE(ovpn_kpeers_by_ip, &sc->peers_by_ip, peer);
+		}
+		if (nvlist_exists_binary(nvl, "vpn_ipv6")) {
+			RB_REMOVE(ovpn_kpeers_by_ip6, &sc->peers_by_ip6, peer);
+		}
 		sc->peercount--;
 		goto error_locked;
 	}
@@ -633,7 +679,7 @@ done:
 static int
 _ovpn_del_peer(struct ovpn_softc *sc, struct ovpn_kpeer *peer)
 {
-	struct ovpn_kpeer *tmp __diagused;
+	struct ovpn_kpeer *tmp;
 
 	OVPN_WASSERT(sc);
 	CURVNET_ASSERT_SET();
@@ -643,6 +689,13 @@ _ovpn_del_peer(struct ovpn_softc *sc, struct ovpn_kpeer *peer)
 	tmp = RB_REMOVE(ovpn_kpeers, &sc->peers, peer);
 	MPASS(tmp != NULL);
 
+	tmp = ovpn_find_peer_by_ip(sc, peer->vpn4);
+	if (tmp)
+		RB_REMOVE(ovpn_kpeers_by_ip, &sc->peers_by_ip, tmp);
+	tmp = ovpn_find_peer_by_ip6(sc, &peer->vpn6);
+	if (tmp)
+		RB_REMOVE(ovpn_kpeers_by_ip6, &sc->peers_by_ip6, tmp);
+
 	sc->peercount--;
 
 	ovpn_peer_release_ref(peer, true);
@@ -1628,17 +1681,13 @@ ovpn_get_af(struct mbuf *m)
 static struct ovpn_kpeer *
 ovpn_find_peer_by_ip(struct ovpn_softc *sc, const struct in_addr addr)
 {
-	struct ovpn_kpeer *peer = NULL;
+	struct ovpn_kpeer peer;
 
 	OVPN_ASSERT(sc);
 
-	/* TODO: Add a second RB so we can look up by IP. */
-	RB_FOREACH(peer, ovpn_kpeers, &sc->peers) {
-		if (addr.s_addr == peer->vpn4.s_addr)
-			return (peer);
-	}
+	peer.vpn4 = addr;
 
-	return (peer);
+	return (RB_FIND(ovpn_kpeers_by_ip, &sc->peers_by_ip, &peer));
 }
 #endif
 
@@ -1646,17 +1695,13 @@ ovpn_find_peer_by_ip(struct ovpn_softc *sc, const struct in_addr addr)
 static struct ovpn_kpeer *
 ovpn_find_peer_by_ip6(struct ovpn_softc *sc, const struct in6_addr *addr)
 {
-	struct ovpn_kpeer *peer = NULL;
+	struct ovpn_kpeer peer;
 
 	OVPN_ASSERT(sc);
 
-	/* TODO: Add a third RB so we can look up by IPv6 address. */
-	RB_FOREACH(peer, ovpn_kpeers, &sc->peers) {
-		if (memcmp(addr, &peer->vpn6, sizeof(*addr)) == 0)
-			return (peer);
-	}
+	peer.vpn6 = *addr;
 
-	return (peer);
+	return (RB_FIND(ovpn_kpeers_by_ip6, &sc->peers_by_ip6, &peer));
 }
 #endif
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202212140549.2BE5njUg034660>