]> git.hungrycats.org Git - linux/commitdiff
[IPV4/IPV6]: Update ECN handling.
authorHerbert Xu <herbert@gondor.apana.org.au>
Wed, 8 Sep 2004 06:38:11 +0000 (23:38 -0700)
committerDavid S. Miller <davem@nuts.davemloft.net>
Wed, 8 Sep 2004 06:38:11 +0000 (23:38 -0700)
This patch brings the IP ECN handling up-to-date with repsect to
RFC 3168.  Mostly this means treating ECT(1) in the same way as
ECT(0).

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/inet_ecn.h
include/net/tcp_ecn.h
net/ipv4/ip_gre.c
net/ipv4/ipip.c
net/ipv4/xfrm4_input.c
net/ipv6/sit.c
net/ipv6/xfrm6_input.c
net/sched/sch_red.c

index 4b9c7556273ae877578b6821c0e2868667a167f5..8d0df10e4549b5d2c0a6efdd5ad50b02e8c10997 100644 (file)
@@ -16,9 +16,9 @@ static inline int INET_ECN_is_ce(__u8 dsfield)
        return (dsfield & INET_ECN_MASK) == INET_ECN_CE;
 }
 
-static inline int INET_ECN_is_not_ce(__u8 dsfield)
+static inline int INET_ECN_is_not_ect(__u8 dsfield)
 {
-       return (dsfield & INET_ECN_MASK) == INET_ECN_ECT_0;
+       return (dsfield & INET_ECN_MASK) == INET_ECN_NOT_ECT;
 }
 
 static inline int INET_ECN_is_capable(__u8 dsfield)
@@ -29,8 +29,7 @@ static inline int INET_ECN_is_capable(__u8 dsfield)
 static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
 {
        outer &= ~INET_ECN_MASK;
-       if (INET_ECN_is_capable(inner))
-               outer |= (inner & INET_ECN_MASK);
+       outer |= (inner & INET_ECN_MASK) ?: INET_ECN_ECT_0;
        return outer;
 }
 
@@ -50,7 +49,19 @@ static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
 static inline void IP_ECN_set_ce(struct iphdr *iph)
 {
        u32 check = iph->check;
-       check += __constant_htons(0xFFFE);
+
+       switch (iph->tos & INET_ECN_MASK) {
+       default:
+       case INET_ECN_NOT_ECT:
+       case INET_ECN_CE:
+               return;
+       case INET_ECN_ECT_1:
+               check += __constant_htons(0xFFFD);
+               break;
+       case INET_ECN_ECT_0:
+               check += __constant_htons(0xFFFE);
+               break;
+       }
        iph->check = check + (check>=0xFFFF);
        iph->tos |= INET_ECN_CE;
 }
@@ -60,10 +71,14 @@ static inline void IP_ECN_clear(struct iphdr *iph)
        iph->tos &= ~INET_ECN_MASK;
 }
 
+#define ip6_get_dsfield(iph) ((ntohs(*(u16*)(iph)) >> 4) & 0xFF)
+
 struct ipv6hdr;
 
 static inline void IP6_ECN_set_ce(struct ipv6hdr *iph)
 {
+       if (INET_ECN_is_not_ect(ip6_get_dsfield(iph)))
+               return;
        *(u32*)iph |= htonl(INET_ECN_CE << 20);
 }
 
@@ -72,6 +87,4 @@ static inline void IP6_ECN_clear(struct ipv6hdr *iph)
        *(u32*)iph &= ~htonl(INET_ECN_MASK << 20);
 }
 
-#define ip6_get_dsfield(iph) ((ntohs(*(u16*)(iph)) >> 4) & 0xFF)
-
 #endif
index 06105757262dbbbb9dea5aa715587b87b422aa9b..38e0feddc148fa9dd043649137f11aaaf17035f8 100644 (file)
@@ -90,7 +90,7 @@ TCP_ECN_check_ce(struct tcp_opt *tp, struct sk_buff *skb)
                /* Funny extension: if ECT is not set on a segment,
                 * it is surely retransmit. It is not in ECN RFC,
                 * but Linux follows this rule. */
-               else if (!INET_ECN_is_capable((TCP_SKB_CB(skb)->flags)))
+               else if (INET_ECN_is_not_ect((TCP_SKB_CB(skb)->flags)))
                        tcp_enter_quickack_mode(tp);
        }
 }
index 2a3a8fb7e6a1f0cfde1ad7efe0b10f5a1246925f..ed106d11aba178f6cf66123a103aefe5d9a580ce 100644 (file)
@@ -533,11 +533,9 @@ static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
 {
        if (INET_ECN_is_ce(iph->tos)) {
                if (skb->protocol == htons(ETH_P_IP)) {
-                       if (INET_ECN_is_not_ce(skb->nh.iph->tos))
-                               IP_ECN_set_ce(skb->nh.iph);
+                       IP_ECN_set_ce(skb->nh.iph);
                } else if (skb->protocol == htons(ETH_P_IPV6)) {
-                       if (INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
-                               IP6_ECN_set_ce(skb->nh.ipv6h);
+                       IP6_ECN_set_ce(skb->nh.ipv6h);
                }
        }
 }
index 98ba22404ac37144be32a675304f05be4f65afda..5c480d407dd88087d8d73197d3ca3b71825314df 100644 (file)
@@ -461,8 +461,7 @@ static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff
 {
        struct iphdr *inner_iph = skb->nh.iph;
 
-       if (INET_ECN_is_ce(outer_iph->tos) &&
-           INET_ECN_is_not_ce(inner_iph->tos))
+       if (INET_ECN_is_ce(outer_iph->tos))
                IP_ECN_set_ce(inner_iph);
 }
 
index b045c87197f13c73def04b50457b84435db08374..f074d49306368f526e4475bb6d2109d826595872 100644 (file)
@@ -24,8 +24,7 @@ static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
        struct iphdr *outer_iph = skb->nh.iph;
        struct iphdr *inner_iph = skb->h.ipiph;
 
-       if (INET_ECN_is_ce(outer_iph->tos) &&
-           INET_ECN_is_not_ce(inner_iph->tos))
+       if (INET_ECN_is_ce(outer_iph->tos))
                IP_ECN_set_ce(inner_iph);
 }
 
index 23482d1bdcf098f156231d8f85333b05e7815aa2..6ce7719d43a9c9969990b136fef89c0a2c62201c 100644 (file)
@@ -360,8 +360,7 @@ out:
 
 static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
 {
-       if (INET_ECN_is_ce(iph->tos) &&
-           INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
+       if (INET_ECN_is_ce(iph->tos))
                IP6_ECN_set_ce(skb->nh.ipv6h);
 }
 
index 92e74233fcdbcc401149ae4b2c6c70a5e2bc17c0..89000c7889f80f4c0d4892fcc051fa69d97faecb 100644 (file)
@@ -21,8 +21,7 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
        struct ipv6hdr *outer_iph = skb->nh.ipv6h;
        struct ipv6hdr *inner_iph = skb->h.ipv6h;
 
-       if (INET_ECN_is_ce(ip6_get_dsfield(outer_iph)) &&
-           INET_ECN_is_not_ce(ip6_get_dsfield(inner_iph)))
+       if (INET_ECN_is_ce(ip6_get_dsfield(outer_iph)))
                IP6_ECN_set_ce(inner_iph);
 }
 
index 5630abb209adb1ac1f3f88856ee434e34e8c4dbe..e5899f67ed64046cc4eb0138ff68ca83de3947cb 100644 (file)
@@ -162,13 +162,12 @@ static int red_ecn_mark(struct sk_buff *skb)
 
        switch (skb->protocol) {
        case __constant_htons(ETH_P_IP):
-               if (!INET_ECN_is_capable(skb->nh.iph->tos))
+               if (INET_ECN_is_not_ect(skb->nh.iph->tos))
                        return 0;
-               if (INET_ECN_is_not_ce(skb->nh.iph->tos))
-                       IP_ECN_set_ce(skb->nh.iph);
+               IP_ECN_set_ce(skb->nh.iph);
                return 1;
        case __constant_htons(ETH_P_IPV6):
-               if (!INET_ECN_is_capable(ip6_get_dsfield(skb->nh.ipv6h)))
+               if (INET_ECN_is_not_ect(ip6_get_dsfield(skb->nh.ipv6h)))
                        return 0;
                IP6_ECN_set_ce(skb->nh.ipv6h);
                return 1;