Index: ip_ecn.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_ecn.c,v retrieving revision 1.9 diff -u -p -r1.9 ip_ecn.c --- ip_ecn.c 14 Nov 2018 23:55:04 -0000 1.9 +++ ip_ecn.c 29 Nov 2018 01:26:32 -0000 @@ -49,34 +49,7 @@ #include /* - * ECN and TOS (or TCLASS) processing rules at tunnel encapsulation and - * decapsulation from RFC3168: - * - * Outer Hdr at Inner Hdr at - * Encapsulator Decapsulator - * Header fields: -------------------- ------------ - * DS Field copied from inner hdr no change - * ECN Field constructed by (I) constructed by (E) - * - * ECN_ALLOWED (full functionality): - * (I) if the ECN field in the inner header is set to CE, then set the - * ECN field in the outer header to ECT(0). - * otherwise, copy the ECN field to the outer header. - * - * (E) if the ECN field in the outer header is set to CE and the ECN - * field of the inner header is not-ECT, drop the packet. - * if the ECN field in the inner header is set to ECT(0) or ECT(1) - * and the ECN field in the outer header is set to CE, then copy CE to - * the inner header. otherwise, make no change to the inner header. - * - * ECN_FORBIDDEN (limited functionality): - * (I) set the ECN field to not-ECT in the outer header. - * - * (E) if the ECN field in the outer header is set to CE, drop the packet. - * otherwise, make no change to the ECN field in the inner header. - * - * the drop rule is for backward compatibility and protection against - * erasure of CE. + * ECN processing rules at tunnel ingress and egress are from RFC6040. */ /* @@ -94,15 +67,12 @@ ip_ecn_ingress(int mode, u_int8_t *outer case ECN_ALLOWED: /* ECN allowed */ case ECN_ALLOWED_IPSEC: /* - * full-functionality: if the inner is CE, set ECT(0) - * to the outer. otherwise, copy the ECN field. + * Normal Mode: ECN field is already copied to outer header */ - if ((*inner & IPTOS_ECN_MASK) == IPTOS_ECN_CE) - *outer &= ~IPTOS_ECN_ECT1; break; case ECN_FORBIDDEN: /* ECN forbidden */ /* - * limited-functionality: set not-ECT to the outer + * Compatability Mode: set not-ECT to the outer */ *outer &= ~IPTOS_ECN_MASK; break; @@ -119,39 +89,58 @@ ip_ecn_ingress(int mode, u_int8_t *outer int ip_ecn_egress(int mode, u_int8_t *outer, u_int8_t *inner) { + uint8_t oecn, iecn; + if (!outer || !inner) panic("NULL pointer passed to ip_ecn_egress"); - switch (mode) { - case ECN_ALLOWED: - case ECN_ALLOWED_IPSEC: - /* - * full-functionality: if the outer is CE and the inner is - * not-ECT, should drop it. otherwise, copy CE. - * However, according to RFC4301, we should just leave the - * inner as non-ECT for IPsec. - */ - if ((*outer & IPTOS_ECN_MASK) == IPTOS_ECN_CE) { - if ((*inner & IPTOS_ECN_MASK) == IPTOS_ECN_NOTECT) { - if (mode == ECN_ALLOWED_IPSEC) - return (1); - else - return (0); - } - *inner |= IPTOS_ECN_CE; + oecn = *outer & IPTOS_ECN_MASK; + iecn = *inner & IPTOS_ECN_MASK; + + switch (oecn) { + case IPTOS_ECN_NOTECT: + /* inner is unchanged */ + break; + case IPTOS_ECN_ECT0: + switch (iecn) { + case IPTOS_ECN_NOTECT: + /* (!!!) */ + break; + case IPTOS_ECN_ECT1: + /* (!) */ + break; + default: + break; } break; - case ECN_FORBIDDEN: /* ECN forbidden */ - /* - * limited-functionality: if the outer is CE, should drop it. - * otherwise, leave the inner. - */ - if ((*outer & IPTOS_ECN_MASK) == IPTOS_ECN_CE) - return (0); + case IPTOS_ECN_ECT1: + switch (iecn) { + case IPTOS_ECN_NOTECT: + /* (!!!) */ + break; + case IPTOS_ECN_ECT0: + CLR(*inner, IPTOS_ECN_MASK); + SET(*inner, IPTOS_ECN_ECT1); + break; + case IPTOS_ECN_CE: + /* (!!!) */ + break; + default: + break; + } break; - case ECN_NOCARE: /* no consideration to ECN */ + case IPTOS_ECN_CE: + switch (iecn) { + case IPTOS_ECN_NOTECT: + /* (!!!) */ + return (0); + default: + SET(*inner, IPTOS_ECN_CE); + break; + } break; } + return (1); }