Root/target/linux/lantiq/patches/0022-MIPS-lantiq-adds-udp-in-kernel-redirect.patch

1From 14ff975c660696fa636e8d6b58d0abed0ddc72ce Mon Sep 17 00:00:00 2001
2From: John Crispin <blogic@openwrt.org>
3Date: Thu, 29 Sep 2011 20:29:54 +0200
4Subject: [PATCH 22/24] MIPS: lantiq: adds udp in-kernel redirect
5
6---
7 include/linux/udp_redirect.h | 57 +++++++++++++
8 net/Kconfig | 6 ++
9 net/ipv4/Makefile | 3 +
10 net/ipv4/udp.c | 28 ++++++-
11 net/ipv4/udp_redirect_symb.c | 186 ++++++++++++++++++++++++++++++++++++++++++
12 5 files changed, 276 insertions(+), 4 deletions(-)
13 create mode 100644 include/linux/udp_redirect.h
14 create mode 100644 net/ipv4/udp_redirect_symb.c
15
16--- /dev/null
17+++ b/include/linux/udp_redirect.h
18@@ -0,0 +1,57 @@
19+#ifndef _UDP_REDIRECT_H
20+#define _UDP_REDIRECT_H
21+
22+/******************************************************************************
23+
24+ Copyright (c) 2006
25+ Infineon Technologies AG
26+ Am Campeon 1-12; 81726 Munich, Germany
27+
28+ THE DELIVERY OF THIS SOFTWARE AS WELL AS THE HEREBY GRANTED NON-EXCLUSIVE,
29+ WORLDWIDE LICENSE TO USE, COPY, MODIFY, DISTRIBUTE AND SUBLICENSE THIS
30+ SOFTWARE IS FREE OF CHARGE.
31+
32+ THE LICENSED SOFTWARE IS PROVIDED "AS IS" AND INFINEON EXPRESSLY DISCLAIMS
33+ ALL REPRESENTATIONS AND WARRANTIES, WHETHER EXPRESS OR IMPLIED, INCLUDING
34+ WITHOUT LIMITATION, WARRANTIES OR REPRESENTATIONS OF WORKMANSHIP,
35+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, THAT THE
36+ OPERATING OF THE LICENSED SOFTWARE WILL BE ERROR FREE OR FREE OF ANY THIRD
37+ PARTY CLAIMS, INCLUDING WITHOUT LIMITATION CLAIMS OF THIRD PARTY INTELLECTUAL
38+ PROPERTY INFRINGEMENT.
39+
40+ EXCEPT FOR ANY LIABILITY DUE TO WILFUL ACTS OR GROSS NEGLIGENCE AND EXCEPT
41+ FOR ANY PERSONAL INJURY INFINEON SHALL IN NO EVENT BE LIABLE FOR ANY CLAIM
42+ OR DAMAGES OF ANY KIND, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
43+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
44+ DEALINGS IN THE SOFTWARE.
45+
46+******************************************************************************/
47+
48+/* ============================= */
49+/* Includes */
50+/* ============================= */
51+#ifndef _LINUX_TYPES_H
52+#include <linux/types.h>
53+#endif
54+
55+
56+/* ============================= */
57+/* Definitions */
58+/* ============================= */
59+#define UDP_REDIRECT_MAGIC (void*)0x55445052L
60+
61+
62+/* ============================= */
63+/* Global variable declaration */
64+/* ============================= */
65+extern int (*udp_do_redirect_fn)(struct sock *sk, struct sk_buff *skb);
66+extern int (*udpredirect_getfrag_fn)(void *p, char * to,
67+ int offset, int fraglen, int odd,
68+ struct sk_buff *skb);
69+/* ============================= */
70+/* Global function declaration */
71+/* ============================= */
72+
73+extern int udpredirect_getfrag(void *p, char * to, int offset,
74+ int fraglen, int odd, struct sk_buff *skb);
75+#endif
76--- a/net/Kconfig
77+++ b/net/Kconfig
78@@ -72,6 +72,12 @@ config INET
79 
80       Short answer: say Y.
81 
82+config IFX_UDP_REDIRECT
83+ bool "IFX Kernel Packet Interface for UDP redirection"
84+ help
85+ You can say Y here if you want to use hooks from kernel for
86+ UDP redirection.
87+
88 if INET
89 source "net/ipv4/Kconfig"
90 source "net/ipv6/Kconfig"
91--- a/net/ipv4/Makefile
92+++ b/net/ipv4/Makefile
93@@ -14,6 +14,9 @@ obj-y := route.o inetpeer.o protocol
94          inet_fragment.o ping.o
95 
96 obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o
97+ifneq ($(CONFIG_IFX_UDP_REDIRECT),)
98+obj-$(CONFIG_IFX_UDP_REDIRECT) += udp_redirect_symb.o
99+endif
100 obj-$(CONFIG_PROC_FS) += proc.o
101 obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
102 obj-$(CONFIG_IP_MROUTE) += ipmr.o
103--- a/net/ipv4/udp.c
104+++ b/net/ipv4/udp.c
105@@ -108,6 +108,10 @@
106 #include <trace/events/udp.h>
107 #include "udp_impl.h"
108 
109+#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
110+#include <linux/udp_redirect.h>
111+#endif
112+
113 struct udp_table udp_table __read_mostly;
114 EXPORT_SYMBOL(udp_table);
115 
116@@ -803,7 +807,7 @@ int udp_sendmsg(struct kiocb *iocb, stru
117     u8 tos;
118     int err, is_udplite = IS_UDPLITE(sk);
119     int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
120- int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
121+ int (*getfrag)(void *, char *, int, int, int, struct sk_buff *) = NULL;
122     struct sk_buff *skb;
123     struct ip_options_data opt_copy;
124 
125@@ -820,7 +824,13 @@ int udp_sendmsg(struct kiocb *iocb, stru
126     ipc.opt = NULL;
127     ipc.tx_flags = 0;
128 
129- getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
130+/* UDPREDIRECT */
131+#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
132+ if(udpredirect_getfrag_fn && sk->sk_user_data == UDP_REDIRECT_MAGIC)
133+ getfrag = udpredirect_getfrag_fn;
134+ else
135+#endif /* IFX_UDP_REDIRECT */
136+ getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
137 
138     fl4 = &inet->cork.fl.u.ip4;
139     if (up->pending) {
140@@ -1621,6 +1631,7 @@ int __udp4_lib_rcv(struct sk_buff *skb,
141     struct rtable *rt = skb_rtable(skb);
142     __be32 saddr, daddr;
143     struct net *net = dev_net(skb->dev);
144+ int ret = 0;
145 
146     /*
147      * Validate the packet.
148@@ -1653,7 +1664,16 @@ int __udp4_lib_rcv(struct sk_buff *skb,
149     sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
150 
151     if (sk != NULL) {
152- int ret = udp_queue_rcv_skb(sk, skb);
153+ /* UDPREDIRECT */
154+#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
155+ if(udp_do_redirect_fn && sk->sk_user_data == UDP_REDIRECT_MAGIC)
156+ {
157+ udp_do_redirect_fn(sk,skb);
158+ kfree_skb(skb);
159+ return(0);
160+ }
161+#endif
162+ ret = udp_queue_rcv_skb(sk, skb);
163         sock_put(sk);
164 
165         /* a return value > 0 means to resubmit the input, but
166@@ -1950,7 +1970,7 @@ struct proto udp_prot = {
167     .clear_sk = sk_prot_clear_portaddr_nulls,
168 };
169 EXPORT_SYMBOL(udp_prot);
170-
171+EXPORT_SYMBOL(udp_rcv);
172 /* ------------------------------------------------------------------------ */
173 #ifdef CONFIG_PROC_FS
174 
175--- /dev/null
176+++ b/net/ipv4/udp_redirect_symb.c
177@@ -0,0 +1,186 @@
178+/******************************************************************************
179+
180+ Copyright (c) 2006
181+ Infineon Technologies AG
182+ Am Campeon 1-12; 81726 Munich, Germany
183+
184+ THE DELIVERY OF THIS SOFTWARE AS WELL AS THE HEREBY GRANTED NON-EXCLUSIVE,
185+ WORLDWIDE LICENSE TO USE, COPY, MODIFY, DISTRIBUTE AND SUBLICENSE THIS
186+ SOFTWARE IS FREE OF CHARGE.
187+
188+ THE LICENSED SOFTWARE IS PROVIDED "AS IS" AND INFINEON EXPRESSLY DISCLAIMS
189+ ALL REPRESENTATIONS AND WARRANTIES, WHETHER EXPRESS OR IMPLIED, INCLUDING
190+ WITHOUT LIMITATION, WARRANTIES OR REPRESENTATIONS OF WORKMANSHIP,
191+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, THAT THE
192+ OPERATING OF THE LICENSED SOFTWARE WILL BE ERROR FREE OR FREE OF ANY THIRD
193+ PARTY CLAIMS, INCLUDING WITHOUT LIMITATION CLAIMS OF THIRD PARTY INTELLECTUAL
194+ PROPERTY INFRINGEMENT.
195+
196+ EXCEPT FOR ANY LIABILITY DUE TO WILFUL ACTS OR GROSS NEGLIGENCE AND EXCEPT
197+ FOR ANY PERSONAL INJURY INFINEON SHALL IN NO EVENT BE LIABLE FOR ANY CLAIM
198+ OR DAMAGES OF ANY KIND, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
199+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
200+ DEALINGS IN THE SOFTWARE.
201+
202+******************************************************************************/
203+#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
204+/* ============================= */
205+/* Includes */
206+/* ============================= */
207+#include <net/checksum.h>
208+#include <net/udp.h>
209+#include <linux/module.h>
210+#include <linux/skbuff.h>
211+#include <linux/udp_redirect.h>
212+
213+/* ============================= */
214+/* Global variable definition */
215+/* ============================= */
216+int (*udpredirect_getfrag_fn) (void *p, char * to, int offset,
217+ int fraglen, int odd, struct sk_buff *skb) = NULL;
218+int (*udp_do_redirect_fn)(struct sock *sk, struct sk_buff *skb) = NULL;
219+
220+/* ============================= */
221+/* Local type definitions */
222+/* ============================= */
223+struct udpfakehdr
224+{
225+ struct udphdr uh;
226+ u32 saddr;
227+ u32 daddr;
228+ struct iovec *iov;
229+ u32 wcheck;
230+};
231+
232+/* ============================= */
233+/* Local function declaration */
234+/* ============================= */
235+static int udpredirect_csum_partial_copy_fromiovecend(unsigned char *kdata,
236+ struct iovec *iov, int offset, unsigned int len, __wsum *csump);
237+
238+static int udpredirect_memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
239+ int len);
240+
241+/* ============================= */
242+/* Global function definition */
243+/* ============================= */
244+
245+/*
246+ Copy of udp_getfrag() from udp.c
247+ This function exists because no copy_from_user() is needed for udpredirect.
248+*/
249+
250+int
251+udpredirect_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
252+{
253+ struct iovec *iov = from;
254+
255+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
256+ if (udpredirect_memcpy_fromiovecend(to, iov, offset, len) < 0)
257+ return -EFAULT;
258+ } else {
259+ __wsum csum = 0;
260+ if (udpredirect_csum_partial_copy_fromiovecend(to, iov, offset, len, &csum) < 0)
261+ return -EFAULT;
262+ skb->csum = csum_block_add(skb->csum, csum, odd);
263+ }
264+ return 0;
265+}
266+
267+static int udpredirect_memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
268+ int len)
269+{
270+ /* Skip over the finished iovecs */
271+ while (offset >= iov->iov_len) {
272+ offset -= iov->iov_len;
273+ iov++;
274+ }
275+
276+ while (len > 0) {
277+ u8 __user *base = iov->iov_base + offset;
278+ int copy = min_t(unsigned int, len, iov->iov_len - offset);
279+
280+ offset = 0;
281+ memcpy(kdata, base, copy);
282+ len -= copy;
283+ kdata += copy;
284+ iov++;
285+ }
286+
287+ return 0;
288+}
289+
290+/*
291+ Copy of csum_partial_copy_fromiovecend() from iovec.c
292+ This function exists because no copy_from_user() is needed for udpredirect.
293+*/
294+
295+int udpredirect_csum_partial_copy_fromiovecend(unsigned char *kdata, struct iovec *iov,
296+ int offset, unsigned int len, __wsum *csump)
297+{
298+ __wsum csum = *csump;
299+ int partial_cnt = 0, err = 0;
300+
301+ /* Skip over the finished iovecs */
302+ while (offset >= iov->iov_len) {
303+ offset -= iov->iov_len;
304+ iov++;
305+ }
306+
307+ while (len > 0) {
308+ u8 __user *base = iov->iov_base + offset;
309+ int copy = min_t(unsigned int, len, iov->iov_len - offset);
310+
311+ offset = 0;
312+
313+ /* There is a remnant from previous iov. */
314+ if (partial_cnt) {
315+ int par_len = 4 - partial_cnt;
316+
317+ /* iov component is too short ... */
318+ if (par_len > copy) {
319+ memcpy(kdata, base, copy);
320+ kdata += copy;
321+ base += copy;
322+ partial_cnt += copy;
323+ len -= copy;
324+ iov++;
325+ if (len)
326+ continue;
327+ *csump = csum_partial(kdata - partial_cnt,
328+ partial_cnt, csum);
329+ goto out;
330+ }
331+ memcpy(kdata, base, par_len);
332+ csum = csum_partial(kdata - partial_cnt, 4, csum);
333+ kdata += par_len;
334+ base += par_len;
335+ copy -= par_len;
336+ len -= par_len;
337+ partial_cnt = 0;
338+ }
339+
340+ if (len > copy) {
341+ partial_cnt = copy % 4;
342+ if (partial_cnt) {
343+ copy -= partial_cnt;
344+ memcpy(kdata + copy, base + copy, partial_cnt);
345+ }
346+ }
347+
348+ if (copy) {
349+ csum = csum_partial_copy_nocheck(base, kdata, copy, csum);
350+ }
351+ len -= copy + partial_cnt;
352+ kdata += copy + partial_cnt;
353+ iov++;
354+ }
355+ *csump = csum;
356+out:
357+ return err;
358+}
359+
360+EXPORT_SYMBOL(udpredirect_getfrag);
361+EXPORT_SYMBOL(udp_do_redirect_fn);
362+EXPORT_SYMBOL(udpredirect_getfrag_fn);
363+#endif /* CONFIG_IFX_UDP_REDIRECT* */
364

Archive Download this file



interactive