[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20251021144410.257905-7-skorodumov.dmitry@huawei.com>
Date: Tue, 21 Oct 2025 17:44:08 +0300
From: Dmitry Skorodumov <skorodumov.dmitry@...wei.com>
To: <netdev@...r.kernel.org>, <linux-kernel@...r.kernel.org>
CC: <andrey.bokhanko@...wei.com>, Dmitry Skorodumov
<skorodumov.dmitry@...wei.com>, Andrew Lunn <andrew+netdev@...n.ch>, "David
S. Miller" <davem@...emloft.net>, Eric Dumazet <edumazet@...gle.com>, Jakub
Kicinski <kuba@...nel.org>, Paolo Abeni <pabeni@...hat.com>
Subject: [PATCH net-next 6/8] ipvlan: Support GSO for port -> ipvlan
If main port interface supports GSO, we need manually segment
the skb before forwarding it to ipvlan interface.
Signed-off-by: Dmitry Skorodumov <skorodumov.dmitry@...wei.com>
---
drivers/net/ipvlan/ipvlan_main.c | 50 ++++++++++++++++++++++++--------
1 file changed, 38 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 28ce36669d39..f1b1f91f94c0 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -4,6 +4,7 @@
#include <linux/ethtool.h>
#include <net/netdev_lock.h>
+#include <net/gso.h>
#include "ipvlan.h"
@@ -76,6 +77,41 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval,
return err;
}
+static int ipvlan_receive(struct ipvl_dev *ipvlan, struct sk_buff *skb)
+{
+ struct sk_buff *segs;
+ struct sk_buff *nskb;
+ ssize_t mac_hdr_size;
+ int ret, len;
+
+ skb->pkt_type = PACKET_HOST;
+ skb->protocol = eth_type_trans(skb, skb->dev);
+ ipvlan_skb_crossing_ns(skb, ipvlan->dev);
+ ipvlan_mark_skb(skb, ipvlan->phy_dev);
+ if (skb_shinfo(skb)->gso_size == 0) {
+ len = skb->len + ETH_HLEN;
+ ret = netif_rx(skb);
+ ipvlan_count_rx(ipvlan, len, ret == NET_RX_SUCCESS, false);
+ return ret;
+ }
+
+ mac_hdr_size = skb->network_header - skb->mac_header;
+ __skb_push(skb, mac_hdr_size);
+ segs = skb_gso_segment(skb, 0);
+ dev_kfree_skb(skb);
+ if (IS_ERR(segs))
+ return 0;
+
+ skb_list_walk_safe(segs, segs, nskb) {
+ skb_mark_not_on_list(segs);
+ __skb_pull(segs, mac_hdr_size);
+ len = segs->len + ETH_HLEN;
+ ret = netif_rx(segs);
+ ipvlan_count_rx(ipvlan, len, ret == NET_RX_SUCCESS, false);
+ }
+ return ret;
+}
+
static int ipvlan_port_receive(struct sk_buff *skb, struct net_device *wdev,
struct packet_type *pt, struct net_device *orig_wdev)
{
@@ -115,18 +151,8 @@ static int ipvlan_port_receive(struct sk_buff *skb, struct net_device *wdev,
goto out;
addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
- if (addr) {
- int ret, len;
-
- ipvlan_skb_crossing_ns(skb, addr->master->dev);
- skb->protocol = eth_type_trans(skb, skb->dev);
- skb->pkt_type = PACKET_HOST;
- ipvlan_mark_skb(skb, port->dev);
- len = skb->len + ETH_HLEN;
- ret = netif_rx(skb);
- ipvlan_count_rx(ipvlan, len, ret == NET_RX_SUCCESS, false);
- return 0;
- }
+ if (addr)
+ return ipvlan_receive(addr->master, skb);
out:
dev_kfree_skb(skb);
--
2.25.1
Powered by blists - more mailing lists