X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv6%2Fip6_tunnel.c;h=c75dc343bfa629742a03c89d1be451584363d907;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=0c8db0391a784b49a3cfdc265a042b76a7dbf9fc;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 0c8db0391..c75dc343b 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -48,6 +48,8 @@ #include #include #include +#include +#include MODULE_AUTHOR("Ville Nuorvala"); MODULE_DESCRIPTION("IPv6-in-IPv6 tunnel"); @@ -490,6 +492,15 @@ out: 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,9 @@ ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) skb->dev = t->dev; dst_release(skb->dst); skb->dst = NULL; + if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) + ipv6_copy_dscp(ipv6h, skb->nh.ipv6h); + ip6ip6_ecn_decapsulate(ipv6h, skb); t->stat.rx_packets++; t->stat.rx_bytes += skb->len; netif_rx(skb); @@ -621,6 +635,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 +661,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 +733,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;