Commit 746f0d39 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

[IPV6]: Handle ECN correctly in ip6ip6 tunnels.

This patch adds ECN encapsulation/decapsulation to ip6_tunnel.c.
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a0e2318c
......@@ -48,6 +48,8 @@
#include <net/addrconf.h>
#include <net/ip6_tunnel.h>
#include <net/xfrm.h>
#include <net/dsfield.h>
#include <net/inet_ecn.h>
MODULE_AUTHOR("Ville Nuorvala");
MODULE_DESCRIPTION("IPv6-in-IPv6 tunnel");
......@@ -490,6 +492,15 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
read_unlock(&ip6ip6_lock);
}
static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
struct sk_buff *skb)
{
struct ipv6hdr *inner_iph = skb->nh.ipv6h;
if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
IP6_ECN_set_ce(inner_iph);
}
/**
* ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally
* @skb: received socket buffer
......@@ -531,6 +542,7 @@ ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
skb->dev = t->dev;
dst_release(skb->dst);
skb->dst = NULL;
ip6ip6_ecn_decapsulate(ipv6h, skb);
t->stat.rx_packets++;
t->stat.rx_bytes += skb->len;
netif_rx(skb);
......@@ -621,6 +633,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
u8 proto;
int err;
int pkt_len;
int dsfield;
if (t->recursion++) {
stats->collisions++;
......@@ -646,6 +659,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
memcpy(&fl, &t->fl, sizeof (fl));
proto = fl.proto;
dsfield = ipv6_get_dsfield(ipv6h);
if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS))
fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_TCLASS_MASK);
if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL))
......@@ -717,6 +731,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
skb->nh.raw = skb_push(skb, sizeof(struct ipv6hdr));
ipv6h = skb->nh.ipv6h;
*(u32*)ipv6h = fl.fl6_flowlabel | htonl(0x60000000);
dsfield = INET_ECN_encapsulate(0, dsfield);
ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield);
ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
ipv6h->hop_limit = t->parms.hop_limit;
ipv6h->nexthdr = proto;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment