patch-2.4.0-test3 linux/net/ipv4/ipip.c

Next file: linux/net/ipv4/netfilter/ip_conntrack_core.c
Previous file: linux/net/ipv4/ip_sockglue.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test2/linux/net/ipv4/ipip.c linux/net/ipv4/ipip.c
@@ -1,7 +1,7 @@
 /*
  *	Linux NET3:	IP/IP protocol decoder. 
  *
- *	Version: $Id: ipip.c,v 1.34 2000/05/22 08:12:19 davem Exp $
+ *	Version: $Id: ipip.c,v 1.37 2000/07/07 23:47:45 davem Exp $
  *
  *	Authors:
  *		Sam Lantinga (slouken@cs.ucdavis.edu)  02/01/95
@@ -107,12 +107,14 @@
 #include <linux/if_arp.h>
 #include <linux/mroute.h>
 #include <linux/init.h>
+#include <linux/netfilter_ipv4.h>
 
 #include <net/sock.h>
 #include <net/ip.h>
 #include <net/icmp.h>
 #include <net/protocol.h>
 #include <net/ipip.h>
+#include <net/inet_ecn.h>
 
 #define HASH_SIZE  16
 #define HASH(addr) ((addr^(addr>>4))&0xF)
@@ -121,11 +123,11 @@
 static int ipip_tunnel_init(struct net_device *dev);
 
 static struct net_device ipip_fb_tunnel_dev = {
-	"tunl%d", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipip_fb_tunnel_init,
+	"tunl0", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipip_fb_tunnel_init,
 };
 
 static struct ip_tunnel ipip_fb_tunnel = {
-	NULL, &ipip_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"tunl%d", }
+	NULL, &ipip_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"tunl0", }
 };
 
 static struct ip_tunnel *tunnels_r_l[HASH_SIZE];
@@ -464,6 +466,13 @@
 #endif
 }
 
+static inline void ipip_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
+{
+	if (INET_ECN_is_ce(iph->tos) &&
+	    INET_ECN_is_not_ce(skb->nh.iph->tos))
+		IP_ECN_set_ce(iph);
+}
+
 int ipip_rcv(struct sk_buff *skb, unsigned short len)
 {
 	struct iphdr *iph;
@@ -488,6 +497,7 @@
 		nf_conntrack_put(skb->nfct);
 		skb->nfct = NULL;
 #endif
+		ipip_ecn_decapsulate(iph, skb);
 		netif_rx(skb);
 		read_unlock(&ipip_lock);
 		return 0;
@@ -499,6 +509,12 @@
 	return 0;
 }
 
+/* Need this wrapper because NF_HOOK takes the function address */
+static inline int do_ip_send(struct sk_buff *skb)
+{
+	return ip_send(skb);
+}
+
 /*
  *	This function assumes it is being called from dev_queue_xmit()
  *	and that skb is filled properly by that function.
@@ -518,6 +534,7 @@
 	int    max_headroom;			/* The extra header space needed */
 	u32    dst = tiph->daddr;
 	int    mtu;
+	int    err;
 
 	if (tunnel->recursion++) {
 		tunnel->stat.collisions++;
@@ -613,7 +630,7 @@
 	iph->ihl		=	sizeof(struct iphdr)>>2;
 	iph->frag_off		=	df;
 	iph->protocol		=	IPPROTO_IPIP;
-	iph->tos		=	tos;
+	iph->tos		=	INET_ECN_encapsulate(tos, old_iph->tos);
 	iph->daddr		=	rt->rt_dst;
 	iph->saddr		=	rt->rt_src;
 
@@ -629,9 +646,17 @@
 	skb->nfct = NULL;
 #endif
 
+	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+		do_ip_send);
+	if(err < 0) {
+		if(net_ratelimit())
+			printk(KERN_ERR "ipip_tunnel_xmit: ip_send() failed, err=%d\n", -err);
+		skb = NULL;
+		goto tx_error;
+	}
+
 	stats->tx_bytes += skb->len;
 	stats->tx_packets++;
-	ip_send(skb);
 	tunnel->recursion--;
 	return 0;
 
@@ -639,7 +664,8 @@
 	dst_link_failure(skb);
 tx_error:
 	stats->tx_errors++;
-	dev_kfree_skb(skb);
+	if(skb)
+		dev_kfree_skb(skb);
 	tunnel->recursion--;
 	return 0;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)