Skip to content

Commit 80747ca

Browse files
ordexPaolo Abeni
authored andcommitted
ovpn: introduce the ovpn_peer object
An ovpn_peer object holds the whole status of a remote peer (regardless whether it is a server or a client). This includes status for crypto, tx/rx buffers, napi, etc. Only support for one peer is introduced (P2P mode). Multi peer support is introduced with a later patch. Along with the ovpn_peer, also the ovpn_bind object is introcued as the two are strictly related. An ovpn_bind object wraps a sockaddr representing the local coordinates being used to talk to a specific peer. Signed-off-by: Antonio Quartulli <[email protected]> Link: https://patch.msgid.link/[email protected] Reviewed-by: Sabrina Dubroca <[email protected]> Tested-by: Oleksandr Natalenko <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent 8327a3b commit 80747ca

File tree

8 files changed

+670
-1
lines changed

8 files changed

+670
-1
lines changed

drivers/net/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ config OVPN
119119
tristate "OpenVPN data channel offload"
120120
depends on NET && INET
121121
depends on IPV6 || !IPV6
122+
select DST_CACHE
122123
help
123124
This module enhances the performance of the OpenVPN userspace software
124125
by offloading the data channel processing to kernelspace.

drivers/net/ovpn/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
# Author: Antonio Quartulli <[email protected]>
88

99
obj-$(CONFIG_OVPN) := ovpn.o
10+
ovpn-y += bind.o
1011
ovpn-y += main.o
1112
ovpn-y += io.o
1213
ovpn-y += netlink.o
1314
ovpn-y += netlink-gen.o
15+
ovpn-y += peer.o

drivers/net/ovpn/bind.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* OpenVPN data channel offload
3+
*
4+
* Copyright (C) 2012-2025 OpenVPN, Inc.
5+
*
6+
* Author: James Yonan <[email protected]>
7+
* Antonio Quartulli <[email protected]>
8+
*/
9+
10+
#include <linux/netdevice.h>
11+
#include <linux/socket.h>
12+
13+
#include "ovpnpriv.h"
14+
#include "bind.h"
15+
#include "peer.h"
16+
17+
/**
18+
* ovpn_bind_from_sockaddr - retrieve binding matching sockaddr
19+
* @ss: the sockaddr to match
20+
*
21+
* Return: the bind matching the passed sockaddr if found, NULL otherwise
22+
*/
23+
struct ovpn_bind *ovpn_bind_from_sockaddr(const struct sockaddr_storage *ss)
24+
{
25+
struct ovpn_bind *bind;
26+
size_t sa_len;
27+
28+
if (ss->ss_family == AF_INET)
29+
sa_len = sizeof(struct sockaddr_in);
30+
else if (ss->ss_family == AF_INET6)
31+
sa_len = sizeof(struct sockaddr_in6);
32+
else
33+
return ERR_PTR(-EAFNOSUPPORT);
34+
35+
bind = kzalloc(sizeof(*bind), GFP_ATOMIC);
36+
if (unlikely(!bind))
37+
return ERR_PTR(-ENOMEM);
38+
39+
memcpy(&bind->remote, ss, sa_len);
40+
41+
return bind;
42+
}
43+
44+
/**
45+
* ovpn_bind_reset - assign new binding to peer
46+
* @peer: the peer whose binding has to be replaced
47+
* @new: the new bind to assign
48+
*/
49+
void ovpn_bind_reset(struct ovpn_peer *peer, struct ovpn_bind *new)
50+
{
51+
struct ovpn_bind *old;
52+
53+
spin_lock_bh(&peer->lock);
54+
old = rcu_replace_pointer(peer->bind, new, true);
55+
spin_unlock_bh(&peer->lock);
56+
57+
kfree_rcu(old, rcu);
58+
}

drivers/net/ovpn/bind.h

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/* OpenVPN data channel offload
3+
*
4+
* Copyright (C) 2012-2025 OpenVPN, Inc.
5+
*
6+
* Author: James Yonan <[email protected]>
7+
* Antonio Quartulli <[email protected]>
8+
*/
9+
10+
#ifndef _NET_OVPN_OVPNBIND_H_
11+
#define _NET_OVPN_OVPNBIND_H_
12+
13+
#include <net/ip.h>
14+
#include <linux/in.h>
15+
#include <linux/in6.h>
16+
#include <linux/rcupdate.h>
17+
#include <linux/skbuff.h>
18+
#include <linux/spinlock.h>
19+
20+
struct ovpn_peer;
21+
22+
/**
23+
* union ovpn_sockaddr - basic transport layer address
24+
* @in4: IPv4 address
25+
* @in6: IPv6 address
26+
*/
27+
union ovpn_sockaddr {
28+
struct sockaddr_in in4;
29+
struct sockaddr_in6 in6;
30+
};
31+
32+
/**
33+
* struct ovpn_bind - remote peer binding
34+
* @remote: the remote peer sockaddress
35+
* @local: local endpoint used to talk to the peer
36+
* @local.ipv4: local IPv4 used to talk to the peer
37+
* @local.ipv6: local IPv6 used to talk to the peer
38+
* @rcu: used to schedule RCU cleanup job
39+
*/
40+
struct ovpn_bind {
41+
union ovpn_sockaddr remote; /* remote sockaddr */
42+
43+
union {
44+
struct in_addr ipv4;
45+
struct in6_addr ipv6;
46+
} local;
47+
48+
struct rcu_head rcu;
49+
};
50+
51+
/**
52+
* ovpn_bind_skb_src_match - match packet source with binding
53+
* @bind: the binding to match
54+
* @skb: the packet to match
55+
*
56+
* Return: true if the packet source matches the remote peer sockaddr
57+
* in the binding
58+
*/
59+
static inline bool ovpn_bind_skb_src_match(const struct ovpn_bind *bind,
60+
const struct sk_buff *skb)
61+
{
62+
const union ovpn_sockaddr *remote;
63+
64+
if (unlikely(!bind))
65+
return false;
66+
67+
remote = &bind->remote;
68+
69+
switch (skb->protocol) {
70+
case htons(ETH_P_IP):
71+
if (unlikely(remote->in4.sin_family != AF_INET))
72+
return false;
73+
74+
if (unlikely(remote->in4.sin_addr.s_addr != ip_hdr(skb)->saddr))
75+
return false;
76+
77+
if (unlikely(remote->in4.sin_port != udp_hdr(skb)->source))
78+
return false;
79+
break;
80+
case htons(ETH_P_IPV6):
81+
if (unlikely(remote->in6.sin6_family != AF_INET6))
82+
return false;
83+
84+
if (unlikely(!ipv6_addr_equal(&remote->in6.sin6_addr,
85+
&ipv6_hdr(skb)->saddr)))
86+
return false;
87+
88+
if (unlikely(remote->in6.sin6_port != udp_hdr(skb)->source))
89+
return false;
90+
break;
91+
default:
92+
return false;
93+
}
94+
95+
return true;
96+
}
97+
98+
struct ovpn_bind *ovpn_bind_from_sockaddr(const struct sockaddr_storage *sa);
99+
void ovpn_bind_reset(struct ovpn_peer *peer, struct ovpn_bind *bind);
100+
101+
#endif /* _NET_OVPN_OVPNBIND_H_ */

drivers/net/ovpn/main.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "main.h"
2020
#include "netlink.h"
2121
#include "io.h"
22+
#include "peer.h"
2223
#include "proto.h"
2324

2425
static const struct net_device_ops ovpn_netdev_ops = {
@@ -92,6 +93,7 @@ static int ovpn_newlink(struct net_device *dev,
9293

9394
ovpn->dev = dev;
9495
ovpn->mode = mode;
96+
spin_lock_init(&ovpn->lock);
9597

9698
/* Set carrier explicitly after registration, this way state is
9799
* clearly defined.
@@ -109,6 +111,16 @@ static int ovpn_newlink(struct net_device *dev,
109111
return register_netdevice(dev);
110112
}
111113

114+
static void ovpn_dellink(struct net_device *dev, struct list_head *head)
115+
{
116+
struct ovpn_priv *ovpn = netdev_priv(dev);
117+
118+
if (ovpn->mode == OVPN_MODE_P2P)
119+
ovpn_peer_release_p2p(ovpn, OVPN_DEL_PEER_REASON_TEARDOWN);
120+
121+
unregister_netdevice_queue(dev, head);
122+
}
123+
112124
static int ovpn_fill_info(struct sk_buff *skb, const struct net_device *dev)
113125
{
114126
struct ovpn_priv *ovpn = netdev_priv(dev);
@@ -127,7 +139,7 @@ static struct rtnl_link_ops ovpn_link_ops = {
127139
.policy = ovpn_policy,
128140
.maxtype = IFLA_OVPN_MAX,
129141
.newlink = ovpn_newlink,
130-
.dellink = unregister_netdevice_queue,
142+
.dellink = ovpn_dellink,
131143
.fill_info = ovpn_fill_info,
132144
};
133145

drivers/net/ovpn/ovpnpriv.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@
1717
* struct ovpn_priv - per ovpn interface state
1818
* @dev: the actual netdev representing the tunnel
1919
* @mode: device operation mode (i.e. p2p, mp, ..)
20+
* @lock: protect this object
21+
* @peer: in P2P mode, this is the only remote peer
2022
*/
2123
struct ovpn_priv {
2224
struct net_device *dev;
2325
enum ovpn_mode mode;
26+
spinlock_t lock; /* protect writing to the ovpn_priv object */
27+
struct ovpn_peer __rcu *peer;
2428
};
2529

2630
#endif /* _NET_OVPN_OVPNSTRUCT_H_ */

0 commit comments

Comments
 (0)