aboutsummaryrefslogtreecommitdiff
path: root/pkgs/patches-linux-5.15/721-net-add-packet-mangeling.patch
blob: 206e16cb1743ec6899a6db20d00da146bf1efce8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
From ffe387740bbe88dd88bbe04d6375902708003d6e Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 7 Jul 2017 17:25:00 +0200
Subject: net: add packet mangeling

ar8216 switches have a hardware bug, which renders normal 802.1q support
unusable. Packet mangling is required to fix up the vlan for incoming
packets.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 include/linux/netdevice.h | 11 +++++++++++
 include/linux/skbuff.h    | 14 ++++----------
 net/Kconfig               |  6 ++++++
 net/core/dev.c            | 20 +++++++++++++++-----
 net/core/skbuff.c         | 17 +++++++++++++++++
 net/ethernet/eth.c        |  6 ++++++
 6 files changed, 59 insertions(+), 15 deletions(-)

--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1669,6 +1669,10 @@ enum netdev_priv_flags {
 	IFF_TX_SKB_NO_LINEAR		= BIT_ULL(31),
 };
 
+enum netdev_extra_priv_flags {
+	IFF_NO_IP_ALIGN			= 1<<0,
+};
+
 #define IFF_802_1Q_VLAN			IFF_802_1Q_VLAN
 #define IFF_EBRIDGE			IFF_EBRIDGE
 #define IFF_BONDING			IFF_BONDING
@@ -1701,6 +1705,7 @@ enum netdev_priv_flags {
 #define IFF_L3MDEV_RX_HANDLER		IFF_L3MDEV_RX_HANDLER
 #define IFF_LIVE_RENAME_OK		IFF_LIVE_RENAME_OK
 #define IFF_TX_SKB_NO_LINEAR		IFF_TX_SKB_NO_LINEAR
+#define IFF_NO_IP_ALIGN			IFF_NO_IP_ALIGN
 
 /* Specifies the type of the struct net_device::ml_priv pointer */
 enum netdev_ml_priv_type {
@@ -2002,6 +2007,7 @@ struct net_device {
 	/* Read-mostly cache-line for fast-path access */
 	unsigned int		flags;
 	unsigned int		priv_flags;
+	unsigned int		extra_priv_flags;
 	const struct net_device_ops *netdev_ops;
 	int			ifindex;
 	unsigned short		gflags;
@@ -2062,6 +2068,11 @@ struct net_device {
 	const struct tlsdev_ops *tlsdev_ops;
 #endif
 
+#ifdef CONFIG_ETHERNET_PACKET_MANGLE
+	void (*eth_mangle_rx)(struct net_device *dev, struct sk_buff *skb);
+	struct sk_buff *(*eth_mangle_tx)(struct net_device *dev, struct sk_buff *skb);
+#endif
+
 	const struct header_ops *header_ops;
 
 	unsigned char		operstate;
@@ -2136,6 +2147,10 @@ struct net_device {
 	struct mctp_dev __rcu	*mctp_ptr;
 #endif
 
+#ifdef CONFIG_ETHERNET_PACKET_MANGLE
+	void			*phy_ptr; /* PHY device specific data */
+#endif
+
 /*
  * Cache lines mostly used on receive path (including eth_type_trans())
  */
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2852,6 +2852,10 @@ static inline int pskb_trim(struct sk_bu
 	return (len < skb->len) ? __pskb_trim(skb, len) : 0;
 }
 
+extern struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev,
+		unsigned int length, gfp_t gfp);
+
+
 /**
  *	pskb_trim_unique - remove end from a paged unique (not cloned) buffer
  *	@skb: buffer to alter
@@ -3002,16 +3006,6 @@ static inline struct sk_buff *dev_alloc_
 }
 
 
-static inline struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev,
-		unsigned int length, gfp_t gfp)
-{
-	struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp);
-
-	if (NET_IP_ALIGN && skb)
-		skb_reserve(skb, NET_IP_ALIGN);
-	return skb;
-}
-
 static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev,
 		unsigned int length)
 {
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -26,6 +26,12 @@ menuconfig NET
 
 if NET
 
+config ETHERNET_PACKET_MANGLE
+	bool
+	help
+	  This option can be selected by phy drivers that need to mangle
+	  packets going in or out of an ethernet device.
+
 config WANT_COMPAT_NETLINK_MESSAGES
 	bool
 	help
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3588,6 +3588,11 @@ static int xmit_one(struct sk_buff *skb,
 	if (dev_nit_active(dev))
 		dev_queue_xmit_nit(skb, dev);
 
+#ifdef CONFIG_ETHERNET_PACKET_MANGLE
+	if (dev->eth_mangle_tx && !(skb = dev->eth_mangle_tx(dev, skb)))
+		return NETDEV_TX_OK;
+#endif
+
 	len = skb->len;
 	PRANDOM_ADD_NOISE(skb, dev, txq, len + jiffies);
 	trace_net_dev_start_xmit(skb, dev);
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -61,6 +61,7 @@
 #include <linux/if_vlan.h>
 #include <linux/mpls.h>
 #include <linux/kcov.h>
+#include <linux/if.h>
 
 #include <net/protocol.h>
 #include <net/dst.h>
@@ -602,6 +603,22 @@ skb_fail:
 }
 EXPORT_SYMBOL(__napi_alloc_skb);
 
+struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev,
+		unsigned int length, gfp_t gfp)
+{
+	struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp);
+
+#ifdef CONFIG_ETHERNET_PACKET_MANGLE
+	if (dev && (dev->extra_priv_flags & IFF_NO_IP_ALIGN))
+		return skb;
+#endif
+
+	if (NET_IP_ALIGN && skb)
+		skb_reserve(skb, NET_IP_ALIGN);
+	return skb;
+}
+EXPORT_SYMBOL(__netdev_alloc_skb_ip_align);
+
 void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off,
 		     int size, unsigned int truesize)
 {
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -170,6 +170,12 @@ __be16 eth_type_trans(struct sk_buff *sk
 	const struct ethhdr *eth;
 
 	skb->dev = dev;
+
+#ifdef CONFIG_ETHERNET_PACKET_MANGLE
+	if (dev->eth_mangle_rx)
+		dev->eth_mangle_rx(dev, skb);
+#endif
+
 	skb_reset_mac_header(skb);
 
 	eth = (struct ethhdr *)skb->data;