Annotation of sys/netinet/ip_ecn.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ip_ecn.c,v 1.4 2002/05/16 14:10:51 kjc Exp $ */
2: /* $KAME: ip_ecn.c,v 1.9 2000/10/01 12:44:48 itojun Exp $ */
3:
4: /*
5: * Copyright (C) 1999 WIDE Project.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the project nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: *
32: */
33: /*
34: * ECN consideration on tunnel ingress/egress operation.
35: * http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt
36: */
37:
38: #include <sys/param.h>
39: #include <sys/systm.h>
40: #include <sys/mbuf.h>
41:
42: #ifdef INET
43: #include <netinet/in.h>
44: #include <netinet/in_systm.h>
45: #include <netinet/ip.h>
46: #endif
47:
48: #ifdef INET6
49: #ifndef INET
50: #include <netinet/in.h>
51: #endif
52: #include <netinet/ip6.h>
53: #endif
54:
55: #include <netinet/ip_ecn.h>
56:
57: /*
58: * ECN and TOS (or TCLASS) processing rules at tunnel encapsulation and
59: * decapsulation from RFC3168:
60: *
61: * Outer Hdr at Inner Hdr at
62: * Encapsulator Decapsulator
63: * Header fields: -------------------- ------------
64: * DS Field copied from inner hdr no change
65: * ECN Field constructed by (I) constructed by (E)
66: *
67: * ECN_ALLOWED (full functionality):
68: * (I) if the ECN field in the inner header is set to CE, then set the
69: * ECN field in the outer header to ECT(0).
70: * otherwise, copy the ECN field to the outer header.
71: *
72: * (E) if the ECN field in the outer header is set to CE and the ECN
73: * field of the inner header is not-ECT, drop the packet.
74: * if the ECN field in the inner header is set to ECT(0) or ECT(1)
75: * and the ECN field in the outer header is set to CE, then copy CE to
76: * the inner header. otherwise, make no change to the inner header.
77: *
78: * ECN_FORBIDDEN (limited functionality):
79: * (I) set the ECN field to not-ECT in the outer header.
80: *
81: * (E) if the ECN field in the outer header is set to CE, drop the packet.
82: * otherwise, make no change to the ECN field in the inner header.
83: *
84: * the drop rule is for backward compatibility and protection against
85: * erasure of CE.
86: */
87:
88: /*
89: * modify outer ECN (TOS) field on ingress operation (tunnel encapsulation).
90: * call it after you've done the default initialization/copy for the outer.
91: */
92: void
93: ip_ecn_ingress(mode, outer, inner)
94: int mode;
95: u_int8_t *outer;
96: u_int8_t *inner;
97: {
98: if (!outer || !inner)
99: panic("NULL pointer passed to ip_ecn_ingress");
100:
101: *outer = *inner;
102: switch (mode) {
103: case ECN_ALLOWED: /* ECN allowed */
104: /*
105: * full-functionality: if the inner is CE, set ECT(0)
106: * to the outer. otherwise, copy the ECN field.
107: */
108: if ((*inner & IPTOS_ECN_MASK) == IPTOS_ECN_CE)
109: *outer &= ~IPTOS_ECN_ECT1;
110: break;
111: case ECN_FORBIDDEN: /* ECN forbidden */
112: /*
113: * limited-functionality: set not-ECT to the outer
114: */
115: *outer &= ~IPTOS_ECN_MASK;
116: break;
117: case ECN_NOCARE: /* no consideration to ECN */
118: break;
119: }
120: }
121:
122: /*
123: * modify inner ECN (TOS) field on egress operation (tunnel decapsulation).
124: * call it after you've done the default initialization/copy for the inner.
125: * the caller should drop the packet if the return value is 0.
126: */
127: int
128: ip_ecn_egress(mode, outer, inner)
129: int mode;
130: u_int8_t *outer;
131: u_int8_t *inner;
132: {
133: if (!outer || !inner)
134: panic("NULL pointer passed to ip_ecn_egress");
135:
136: switch (mode) {
137: case ECN_ALLOWED:
138: /*
139: * full-functionality: if the outer is CE and the inner is
140: * not-ECT, should drop it. otherwise, copy CE.
141: */
142: if ((*outer & IPTOS_ECN_MASK) == IPTOS_ECN_CE) {
143: if ((*inner & IPTOS_ECN_MASK) == IPTOS_ECN_NOTECT)
144: return (0);
145: *inner |= IPTOS_ECN_CE;
146: }
147: break;
148: case ECN_FORBIDDEN: /* ECN forbidden */
149: /*
150: * limited-functionality: if the outer is CE, should drop it.
151: * otherwise, leave the inner.
152: */
153: if ((*outer & IPTOS_ECN_MASK) == IPTOS_ECN_CE)
154: return (0);
155: break;
156: case ECN_NOCARE: /* no consideration to ECN */
157: break;
158: }
159: return (1);
160: }
161:
162: #ifdef INET6
163: void
164: ip6_ecn_ingress(mode, outer, inner)
165: int mode;
166: u_int32_t *outer;
167: u_int32_t *inner;
168: {
169: u_int8_t outer8, inner8;
170:
171: if (!outer || !inner)
172: panic("NULL pointer passed to ip6_ecn_ingress");
173:
174: inner8 = (ntohl(*inner) >> 20) & 0xff;
175: ip_ecn_ingress(mode, &outer8, &inner8);
176: *outer &= ~htonl(0xff << 20);
177: *outer |= htonl((u_int32_t)outer8 << 20);
178: }
179:
180: int
181: ip6_ecn_egress(mode, outer, inner)
182: int mode;
183: u_int32_t *outer;
184: u_int32_t *inner;
185: {
186: u_int8_t outer8, inner8, oinner8;
187:
188: if (!outer || !inner)
189: panic("NULL pointer passed to ip6_ecn_egress");
190:
191: outer8 = (ntohl(*outer) >> 20) & 0xff;
192: inner8 = oinner8 = (ntohl(*inner) >> 20) & 0xff;
193: if (ip_ecn_egress(mode, &outer8, &inner8) == 0)
194: return (0);
195: if (inner8 != oinner8) {
196: *inner &= ~htonl(0xff << 20);
197: *inner |= htonl((u_int32_t)inner8 << 20);
198: }
199: return (1);
200: }
201: #endif
CVSweb