diff options
Diffstat (limited to 'sys/altq/altq_red.c')
-rw-r--r-- | sys/altq/altq_red.c | 85 |
1 files changed, 39 insertions, 46 deletions
diff --git a/sys/altq/altq_red.c b/sys/altq/altq_red.c index 70d7ec18097..b2d91f3ac7f 100644 --- a/sys/altq/altq_red.c +++ b/sys/altq/altq_red.c @@ -1,8 +1,8 @@ -/* $OpenBSD: altq_red.c,v 1.3 2002/03/14 01:26:26 millert Exp $ */ -/* $KAME: altq_red.c,v 1.8 2000/12/14 08:12:46 thorpej Exp $ */ +/* $OpenBSD: altq_red.c,v 1.4 2002/05/17 07:16:26 kjc Exp $ */ +/* $KAME: altq_red.c,v 1.10 2002/04/03 05:38:51 kjc Exp $ */ /* - * Copyright (C) 1997-2000 + * Copyright (C) 1997-2002 * Sony Computer Science Laboratories Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -837,46 +837,33 @@ mark_ecn(m, pktattr, flags) case AF_INET: if (flags & REDF_ECN4) { struct ip *ip = (struct ip *)pktattr->pattr_hdr; + u_int8_t otos; + int sum; if (ip->ip_v != 4) return (0); /* version mismatch! */ - if (ip->ip_tos & IPTOS_ECT) { - /* ECN-capable, mark ECN bit. */ - if ((ip->ip_tos & IPTOS_CE) == 0) { -#if (IPTOS_CE == 0x01) - u_short sum; - - ip->ip_tos |= IPTOS_CE; - /* - * optimized version when IPTOS_CE - * is 0x01. - * HC' = HC -1 when HC > 0 - * = 0xfffe when HC = 0 - */ - sum = ntohs(ip->ip_sum); - if (sum == 0) - sum = 0xfffe; - else - sum -= 1; - ip->ip_sum = htons(sum); -#else /* IPTOS_CE != 0x01 */ - long sum; - - ip->ip_tos |= IPTOS_CE; - /* - * update checksum (from RFC1624) - * HC' = ~(~HC + ~m + m') - */ - sum = ~ntohs(ip->ip_sum) & 0xffff; - sum += 0xffff + IPTOS_CE; - sum = (sum >> 16) + (sum & 0xffff); - sum += (sum >> 16); /* add carry */ - - ip->ip_sum = htons(~sum & 0xffff); -#endif /* IPTOS_CE != 0x01 */ - } - return (1); - } + + if ((ip->ip_tos & IPTOS_ECN_MASK) == IPTOS_ECN_NOTECT) + return (0); /* not-ECT */ + if ((ip->ip_tos & IPTOS_ECN_MASK) == IPTOS_ECN_CE) + return (1); /* already marked */ + + /* + * ecn-capable but not marked, + * mark CE and update checksum + */ + otos = ip->ip_tos; + ip->ip_tos |= IPTOS_ECN_CE; + /* + * update checksum (from RFC1624) + * HC' = ~(~HC + ~m + m') + */ + sum = ~ntohs(ip->ip_sum) & 0xffff; + sum += (~otos & 0xffff) + ip->ip_tos; + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); /* add carry */ + ip->ip_sum = htons(~sum & 0xffff); + return (1); } break; #ifdef INET6 @@ -888,12 +875,18 @@ mark_ecn(m, pktattr, flags) flowlabel = ntohl(ip6->ip6_flow); if ((flowlabel >> 28) != 6) return (0); /* version mismatch! */ - if (flowlabel & (IPTOS_ECT << 20)) { - /* ECN-capable, mark ECN bit. */ - flowlabel |= (IPTOS_CE << 20); - ip6->ip6_flow = htonl(flowlabel); - return (1); - } + if ((flowlabel & (IPTOS_ECN_MASK << 20)) == + (IPTOS_ECN_NOTECT << 20)) + return (0); /* not-ECT */ + if ((flowlabel & (IPTOS_ECN_MASK << 20)) == + (IPTOS_ECN_CE << 20)) + return (1); /* already marked */ + /* + * ecn-capable but not marked, mark CE + */ + flowlabel |= (IPTOS_ECN_CE << 20); + ip6->ip6_flow = htonl(flowlabel); + return (1); } break; #endif /* INET6 */ |