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

Archive Download this file



interactive