aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorGauvain "GovanifY" Roussel-Tarbouriech <govanify@anarchist.pw>2018-06-06 23:38:39 +0200
committerGauvain "GovanifY" Roussel-Tarbouriech <govanify@anarchist.pw>2018-06-06 23:38:39 +0200
commitf76e672dd1e7ba62a777bfccfc9ea4d9e17c7aee (patch)
tree44407fec51d2bebbdfb5dc339d47fe779a16576a
parentqemu: retry on 404 in wget for kernel.org race (diff)
downloadwireguard-monolithic-historical-f76e672dd1e7ba62a777bfccfc9ea4d9e17c7aee.tar.xz
wireguard-monolithic-historical-f76e672dd1e7ba62a777bfccfc9ea4d9e17c7aee.zip
I have no idea what I'm doing; beginning GRO impl
-rw-r--r--src/socket.c75
1 files changed, 74 insertions, 1 deletions
diff --git a/src/socket.c b/src/socket.c
index 6c81cc6..1221ec5 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -300,6 +300,78 @@ err:
kfree_skb(skb);
return 0;
}
+static struct sk_buff **gro_receive(struct sock *sk,
+ struct sk_buff **head,
+ struct sk_buff *skb)
+{
+ struct wireguard_device *wg;
+ struct sk_buff *p, **pp = NULL;
+ struct vxlanhdr *vh, *vh2;
+ unsigned int hlen, off_vx;
+ int flush = 1;
+ struct vxlan_sock *vs = rcu_dereference_sk_user_data(sk);
+ __be32 flags;
+ struct gro_remcsum grc;
+
+
+ wg = sk->sk_user_data;
+ // TODO: Check this key?
+ //pubkey_hashtable_init(&wg->peer_hashtable);
+ skb_gro_remcsum_init(&grc);
+
+ off_vx = skb_gro_offset(skb);
+ hlen = off_vx + sizeof(*vh);
+ vh = skb_gro_header_fast(skb, off_vx);
+ if (skb_gro_header_hard(skb, hlen)) {
+ vh = skb_gro_header_slow(skb, hlen, off_vx);
+ if (unlikely(!vh))
+ goto out;
+ }
+
+ skb_gro_postpull_rcsum(skb, vh, sizeof(struct vxlanhdr));
+
+ flags = vh->vx_flags;
+
+ if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) {
+ vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr),
+ vh->vx_vni, &grc,
+ !!(vs->flags &
+ VXLAN_F_REMCSUM_NOPARTIAL));
+
+ if (!vh)
+ goto out;
+ }
+
+ skb_gro_pull(skb, sizeof(struct vxlanhdr)); /* pull vxlan header */
+
+ for (p = *head; p; p = p->next) {
+ if (!NAPI_GRO_CB(p)->same_flow)
+ continue;
+
+ vh2 = (struct vxlanhdr *)(p->data + off_vx);
+ if (vh->vx_flags != vh2->vx_flags ||
+ vh->vx_vni != vh2->vx_vni) {
+ NAPI_GRO_CB(p)->same_flow = 0;
+ continue;
+ }
+ }
+
+ pp = call_gro_receive(eth_gro_receive, head, skb);
+ flush = 0;
+
+out:
+ skb_gro_remcsum_cleanup(skb, &grc);
+ skb->remcsum_offload = 0;
+ NAPI_GRO_CB(skb)->flush |= flush;
+
+ return pp;
+}
+
+static int gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
+{
+ return eth_gro_complete(skb, nhoff + sizeof(struct vxlanhdr));
+}
+
static inline void sock_free(struct sock *sock)
{
@@ -322,7 +394,8 @@ int socket_init(struct wireguard_device *wg, u16 port)
struct udp_tunnel_sock_cfg cfg = {
.sk_user_data = wg,
.encap_type = 1,
- .encap_rcv = receive
+ .gro_receive = gro_receive,
+ .gro_complete = gro_complete
};
struct socket *new4 = NULL, *new6 = NULL;
struct udp_port_cfg port4 = {