[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20201211122612.869225-10-jonas@norrbonn.se>
Date: Fri, 11 Dec 2020 13:26:09 +0100
From: Jonas Bonn <jonas@...rbonn.se>
To: netdev@...r.kernel.org
Cc: pablo@...filter.org, laforge@...monks.org,
Jonas Bonn <jonas@...rbonn.se>
Subject: [PATCH net-next v2 09/12] gtp: support GRO
This patch implements GRO callbacks for UDP-tunneled GTP traffic.
iperf3 numbers
Without GRO for GTP tunnels:
Accepted connection from 172.99.2.1, port 48783
[ 5] local 172.99.0.1 port 5201 connected to 172.99.2.1 port 46095
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.00 sec 563 MBytes 576306 KBytes/sec
[ 5] 1.00-2.00 sec 681 MBytes 697814 KBytes/sec
[ 5] 2.00-3.00 sec 677 MBytes 693612 KBytes/sec
[ 5] 3.00-4.00 sec 679 MBytes 695690 KBytes/sec
[ 5] 4.00-5.00 sec 683 MBytes 699521 KBytes/sec
[ 5] 5.00-6.00 sec 682 MBytes 698922 KBytes/sec
[ 5] 6.00-7.00 sec 683 MBytes 699820 KBytes/sec
[ 5] 7.00-8.00 sec 682 MBytes 698052 KBytes/sec
[ 5] 8.00-9.00 sec 683 MBytes 699245 KBytes/sec
[ 5] 9.00-10.00 sec 683 MBytes 699554 KBytes/sec
[ 5] 10.00-10.00 sec 616 KBytes 687914 KBytes/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.00 sec 6.54 GBytes 685853 KBytes/sec receiver
With GRO for GTP tunnels:
Accepted connection from 172.99.2.1, port 40847
[ 5] local 172.99.0.1 port 5201 connected to 172.99.2.1 port 55053
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.00 sec 989 MBytes 1012640 KBytes/sec
[ 5] 1.00-2.00 sec 1.23 GBytes 1291408 KBytes/sec
[ 5] 2.00-3.00 sec 1.26 GBytes 1320197 KBytes/sec
[ 5] 3.00-4.00 sec 1.29 GBytes 1350097 KBytes/sec
[ 5] 4.00-5.00 sec 1.23 GBytes 1284512 KBytes/sec
[ 5] 5.00-6.00 sec 1.26 GBytes 1326329 KBytes/sec
[ 5] 6.00-7.00 sec 1.28 GBytes 1338620 KBytes/sec
[ 5] 7.00-8.00 sec 1.28 GBytes 1346391 KBytes/sec
[ 5] 8.00-9.00 sec 1.30 GBytes 1366394 KBytes/sec
[ 5] 9.00-10.00 sec 1.26 GBytes 1323848 KBytes/sec
[ 5] 10.00-10.00 sec 384 KBytes 1113043 KBytes/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.00 sec 12.4 GBytes 1296036 KBytes/sec receiver
Signed-off-by: Jonas Bonn <jonas@...rbonn.se>
---
drivers/net/gtp.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 126 insertions(+)
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 7bbeec173113..86639fae8d45 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -361,6 +361,128 @@ static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
return ret;
}
+static int gtp_gro_complete(struct sock *sk, struct sk_buff * skb, int nhoff)
+{
+ size_t hdrlen;
+ char* gtphdr = skb->data + nhoff;
+ u8 version;
+ __be16 type;
+ struct packet_offload *ptype;
+ uint8_t ipver;
+ int err;
+
+ version = *gtphdr >> 5;
+ switch (version) {
+ case GTP_V0:
+ hdrlen = sizeof(struct gtp0_header);
+ break;
+ case GTP_V1:
+ hdrlen = sizeof(struct gtp1_header);
+ if (*gtphdr & GTP1_F_MASK)
+ hdrlen += 4;
+ break;
+ }
+
+ skb_set_inner_network_header(skb, nhoff + hdrlen);
+
+ ipver = inner_ip_hdr(skb)->version;
+ switch (ipver) {
+ case 4:
+ type = cpu_to_be16(ETH_P_IP);
+ break;
+ case 6:
+ type = cpu_to_be16(ETH_P_IPV6);
+ break;
+ default:
+ goto out;
+ }
+
+ rcu_read_lock();
+ ptype = gro_find_complete_by_type(type);
+ if (!ptype)
+ goto out_unlock;
+
+ err = ptype->callbacks.gro_complete(skb, nhoff + hdrlen);
+
+ skb_set_inner_mac_header(skb, nhoff + hdrlen);
+
+out_unlock:
+ rcu_read_unlock();
+out:
+
+ return err;
+
+}
+
+static struct sk_buff *gtp_gro_receive(struct sock *sk,
+ struct list_head *head,
+ struct sk_buff *skb)
+{
+ size_t off, hdrlen;
+ char* gtphdr;
+ u8 version;
+ struct sk_buff *pp = NULL;
+ __be16 type;
+ struct packet_offload *ptype;
+
+ off = skb_gro_offset(skb);
+
+ gtphdr = skb_gro_header_fast(skb, off);
+ if (skb_gro_header_hard(skb, off+1)) {
+ gtphdr = skb_gro_header_slow(skb, off+1, off);
+ if (unlikely(!gtphdr))
+ goto out;
+ }
+
+ version = *gtphdr >> 5;
+ switch (version) {
+ case GTP_V0:
+ hdrlen = sizeof(struct gtp0_header);
+ break;
+ case GTP_V1:
+ hdrlen = sizeof(struct gtp1_header);
+ if (*gtphdr & GTP1_F_MASK)
+ hdrlen += 4;
+ break;
+ }
+
+ gtphdr = skb_gro_header_fast(skb, off);
+ if (skb_gro_header_hard(skb, off+hdrlen)) {
+ gtphdr = skb_gro_header_slow(skb, off+hdrlen, off);
+ if (unlikely(!gtphdr))
+ goto out;
+ }
+
+ skb_set_inner_network_header(skb, off + hdrlen);
+
+ switch(inner_ip_hdr(skb)->version) {
+ case 4:
+ type = cpu_to_be16(ETH_P_IP);
+ break;
+ case 6:
+ type = cpu_to_be16(ETH_P_IPV6);
+ break;
+ default:
+ goto out;
+ }
+
+ rcu_read_lock();
+ ptype = gro_find_receive_by_type(type);
+ if (!ptype)
+ goto out_unlock;
+
+ skb_gro_pull(skb, hdrlen);
+ skb_gro_postpull_rcsum(skb, gtphdr, hdrlen);
+
+ pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
+
+out_unlock:
+ rcu_read_unlock();
+out:
+
+ return pp;
+}
+
static int gtp_dev_init(struct net_device *dev)
{
struct gtp_dev *gtp = netdev_priv(dev);
@@ -622,7 +744,9 @@ static void gtp_link_setup(struct net_device *dev)
dev->priv_flags |= IFF_NO_QUEUE;
dev->features |= NETIF_F_LLTX;
+ dev->hw_features |= NETIF_F_RXCSUM;
dev->hw_features |= NETIF_F_SG | NETIF_F_GSO_SOFTWARE | NETIF_F_HW_CSUM;
+ dev->features |= NETIF_F_RXCSUM;
dev->features |= NETIF_F_SG | NETIF_F_GSO_SOFTWARE | NETIF_F_HW_CSUM;
netif_keep_dst(dev);
@@ -818,6 +942,8 @@ static struct sock *gtp_encap_enable_socket(int fd, int type,
tuncfg.encap_type = type;
tuncfg.encap_rcv = gtp_encap_recv;
tuncfg.encap_destroy = gtp_encap_destroy;
+ tuncfg.gro_receive = gtp_gro_receive;
+ tuncfg.gro_complete = gtp_gro_complete;
setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg);
--
2.27.0
Powered by blists - more mailing lists