patch-2.4.0-test3 linux/net/ipv4/ip_gre.c
Next file: linux/net/ipv4/ip_sockglue.c
Previous file: linux/net/ipv4/ip_fragment.c
Back to the patch index
Back to the overall index
- Lines: 132
- Date:
Sun Jul 9 22:30:41 2000
- Orig file:
v2.4.0-test2/linux/net/ipv4/ip_gre.c
- Orig date:
Tue May 23 15:31:37 2000
diff -u --recursive --new-file v2.4.0-test2/linux/net/ipv4/ip_gre.c linux/net/ipv4/ip_gre.c
@@ -27,6 +27,7 @@
#include <linux/in6.h>
#include <linux/inetdevice.h>
#include <linux/igmp.h>
+#include <linux/netfilter_ipv4.h>
#include <net/sock.h>
#include <net/ip.h>
@@ -35,6 +36,7 @@
#include <net/ipip.h>
#include <net/arp.h>
#include <net/checksum.h>
+#include <net/inet_ecn.h>
#ifdef CONFIG_IPV6
#include <net/ipv6.h>
@@ -118,11 +120,11 @@
static int ipgre_fb_tunnel_init(struct net_device *dev);
static struct net_device ipgre_fb_tunnel_dev = {
- "gre%d", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipgre_fb_tunnel_init,
+ "gre0", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipgre_fb_tunnel_init,
};
static struct ip_tunnel ipgre_fb_tunnel = {
- NULL, &ipgre_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"gre%d", }
+ NULL, &ipgre_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"gre0", }
};
/* Tunnel hash table */
@@ -529,6 +531,34 @@
#endif
}
+static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
+{
+ if (INET_ECN_is_ce(iph->tos)) {
+ if (skb->protocol == __constant_htons(ETH_P_IP)) {
+ if (INET_ECN_is_not_ce(skb->nh.iph->tos))
+ IP_ECN_set_ce(skb->nh.iph);
+ } else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
+ if (INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
+ IP6_ECN_set_ce(skb->nh.ipv6h);
+ }
+ }
+}
+
+static inline u8
+ipgre_ecn_encapsulate(u8 tos, struct iphdr *old_iph, struct sk_buff *skb)
+{
+#ifdef CONFIG_INET_ECN
+ u8 inner = 0;
+ if (skb->protocol == __constant_htons(ETH_P_IP))
+ inner = old_iph->tos;
+ else if (skb->protocol == __constant_htons(ETH_P_IPV6))
+ inner = ip6_get_dsfield((struct ipv6hdr*)old_iph);
+ return INET_ECN_encapsulate(tos, inner);
+#else
+ return tos;
+#endif
+}
+
int ipgre_rcv(struct sk_buff *skb, unsigned short len)
{
struct iphdr *iph = skb->nh.iph;
@@ -603,6 +633,7 @@
nf_conntrack_put(skb->nfct);
skb->nfct = NULL;
#endif
+ ipgre_ecn_decapsulate(iph, skb);
netif_rx(skb);
read_unlock(&ipgre_lock);
return(0);
@@ -616,6 +647,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);
+}
+
static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
@@ -631,6 +668,7 @@
int gre_hlen;
u32 dst;
int mtu;
+ int err;
if (tunnel->recursion++) {
tunnel->stat.collisions++;
@@ -782,7 +820,7 @@
iph->ihl = sizeof(struct iphdr) >> 2;
iph->frag_off = df;
iph->protocol = IPPROTO_GRE;
- iph->tos = tos;
+ iph->tos = ipgre_ecn_encapsulate(tos, old_iph, skb);
iph->daddr = rt->rt_dst;
iph->saddr = rt->rt_src;
@@ -827,9 +865,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 "ipgre_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;
@@ -838,7 +884,8 @@
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)