Vlan patch for large UDP packets
| Newsgroups | gmane.linux.network.bridge.ebtables.devel |
|---|---|
| Message-ID | <081620051253.29796.4301E1E1000B1E200000746422070215530E03070A0406@comcast.net> |
If you send a large UDP packet through a bridge that is running over a VLAN, the kernel will panic. The attached patch will fix the problem. This fix was back ported from a working 2.6 kernel. Basically the fragments that are created in ip_fragment() need to leave room in the refragmented packets for the VLAN data. This patch applies to the 2.4.31 kernel. - Joy Leima -
vlan.patch
(application/octet-stream, 2.1 KB)
--- /usr/src/not_correct/linux-2.4.31/include/linux/netfilter_bridge.h 2005-08-16 09:10:04.000000000 +0200
+++ /usr/src/linux-2.4.31/include/linux/netfilter_bridge.h 2005-08-01 09:40:01.000000000 +0200
@@ -91,6 +91,19 @@
__u32 ipv4;
} daddr;
};
+
+
+/* This is called by the IP fragmenting code and it ensures there is
+ * enough room for the encapsulating header (if there is one). */
+static inline
+int nf_bridge_pad(struct sk_buff *skb)
+{
+ if (skb->nf_bridge) {
+ if (skb->protocol == __constant_htons(ETH_P_8021Q))
+ return 4;
+ }
+ return 0;
+}
#endif /* CONFIG_NETFILTER */
#endif /* __KERNEL__ */
--- /usr/src/not_correct/linux-2.4.31/net/ipv4/ip_output.c 2005-08-16 09:10:04.000000000 +0200
+++ /usr/src/linux-2.4.31/net/ipv4/ip_output.c 2005-08-01 09:43:32.000000000 +0200
@@ -77,6 +77,7 @@
#include <linux/netfilter_ipv4.h>
#include <linux/mroute.h>
#include <linux/netlink.h>
+#include <linux/netfilter_bridge.h>
/*
* Shall we try to damage output packets if routing dev changes?
@@ -769,7 +770,8 @@
int not_last_frag;
struct rtable *rt = (struct rtable*)skb->dst;
int err = 0;
-
+ unsigned int ll_rs = 0;
+
dev = rt->u.dst.dev;
/*
@@ -785,6 +787,10 @@
hlen = iph->ihl * 4;
left = skb->len - hlen; /* Space per frame */
mtu = rt->u.dst.pmtu - hlen; /* Size of data space */
+#ifdef CONFIG_NETFILTER
+ ll_rs = nf_bridge_pad(skb);
+ mtu -= ll_rs;
+#endif
ptr = raw + hlen; /* Where to start from */
/*
@@ -812,7 +818,7 @@
* Allocate buffer.
*/
- if ((skb2 = alloc_skb(len+hlen+dev->hard_header_len+15,GFP_ATOMIC)) == NULL) {
+ if ((skb2 = alloc_skb(len+hlen+dev->hard_header_len+15+ll_rs,GFP_ATOMIC)) == NULL) {
NETDEBUG(printk(KERN_INFO "IP: frag: no memory for new fragment!\n"));
err = -ENOMEM;
goto fail;
@@ -824,7 +830,7 @@
skb2->pkt_type = skb->pkt_type;
skb2->priority = skb->priority;
- skb_reserve(skb2, (dev->hard_header_len+15)&~15);
+ skb_reserve(skb2, (dev->hard_header_len+15+ll_rs)&~15);
skb_put(skb2, len + hlen);
skb2->nh.raw = skb2->data;
skb2->h.raw = skb2->data + hlen;