summaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_gre.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-07-10 23:18:26 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-07-10 23:18:26 +0000
commitc7c4310f7fc1485925d800628bf50b3aeab535ef (patch)
treeb12aa4be0e8fb82aaaea97fb475e793e8a347c49 /net/ipv4/ip_gre.c
parent1ffd1d069ca4c5ffe16fea6175dab1b9bbb15820 (diff)
Merge with Linux 2.4.0-test3-pre8. Linus has accepted most of what
I've sent him, so we're very close to full integration of the MIPS port into his sources.
Diffstat (limited to 'net/ipv4/ip_gre.c')
-rw-r--r--net/ipv4/ip_gre.c51
1 files changed, 45 insertions, 6 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 79dc3d629..a316401b0 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -36,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>
@@ -119,11 +120,11 @@ static int ipgre_tunnel_init(struct net_device *dev);
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 */
@@ -530,6 +531,34 @@ out:
#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;
@@ -604,6 +633,7 @@ int ipgre_rcv(struct sk_buff *skb, unsigned short len)
nf_conntrack_put(skb->nfct);
skb->nfct = NULL;
#endif
+ ipgre_ecn_decapsulate(iph, skb);
netif_rx(skb);
read_unlock(&ipgre_lock);
return(0);
@@ -638,6 +668,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
int gre_hlen;
u32 dst;
int mtu;
+ int err;
if (tunnel->recursion++) {
tunnel->stat.collisions++;
@@ -789,7 +820,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
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;
@@ -834,10 +865,17 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
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++;
- NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
- do_ip_send);
tunnel->recursion--;
return 0;
@@ -846,7 +884,8 @@ tx_error_icmp:
tx_error:
stats->tx_errors++;
- dev_kfree_skb(skb);
+ if(skb)
+ dev_kfree_skb(skb);
tunnel->recursion--;
return 0;
}