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)
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;
}
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;
}
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);
}
*(u32*)iph &= ~htonl(INET_ECN_MASK << 20);
}
-#define ip6_get_dsfield(iph) ((ntohs(*(u16*)(iph)) >> 4) & 0xFF)
-
#endif
/* 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);
}
}
{
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);
}
}
}
{
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);
}
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);
}
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);
}
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);
}
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;