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