From f76e672dd1e7ba62a777bfccfc9ea4d9e17c7aee Mon Sep 17 00:00:00 2001 From: "Gauvain \"GovanifY\" Roussel-Tarbouriech" Date: Wed, 6 Jun 2018 23:38:39 +0200 Subject: I have no idea what I'm doing; beginning GRO impl --- src/socket.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) 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 = { -- cgit v1.2.3-59-g8ed1b