Line data Source code
1 : /*
2 : * Copyright (c) 2015 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 : /*
16 : * ip/ip_packet.h: packet format common between ip4 & ip6
17 : *
18 : * Copyright (c) 2008 Eliot Dresselhaus
19 : *
20 : * Permission is hereby granted, free of charge, to any person obtaining
21 : * a copy of this software and associated documentation files (the
22 : * "Software"), to deal in the Software without restriction, including
23 : * without limitation the rights to use, copy, modify, merge, publish,
24 : * distribute, sublicense, and/or sell copies of the Software, and to
25 : * permit persons to whom the Software is furnished to do so, subject to
26 : * the following conditions:
27 : *
28 : * The above copyright notice and this permission notice shall be
29 : * included in all copies or substantial portions of the Software.
30 : *
31 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 : * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 : * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 : * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 : * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 : */
39 :
40 : #ifndef included_ip_packet_h
41 : #define included_ip_packet_h
42 :
43 : #include <vppinfra/byte_order.h>
44 : #include <vppinfra/error.h>
45 : #include <vppinfra/format.h>
46 :
47 : typedef enum ip_protocol
48 : {
49 : #define ip_protocol(n,s) IP_PROTOCOL_##s = n,
50 : #include "protocols.def"
51 : #undef ip_protocol
52 : } __clib_packed ip_protocol_t;
53 :
54 : /* TCP/UDP ports. */
55 : typedef enum
56 : {
57 : #define ip_port(s,n) IP_PORT_##s = n,
58 : #include "ports.def"
59 : #undef ip_port
60 : } ip_port_t;
61 :
62 : /* Classifies protocols into UDP, ICMP or other. */
63 : typedef enum
64 : {
65 : IP_BUILTIN_PROTOCOL_UDP,
66 : IP_BUILTIN_PROTOCOL_ICMP,
67 : IP_BUILTIN_PROTOCOL_UNKNOWN,
68 : } ip_builtin_protocol_t;
69 :
70 : #define foreach_ip_builtin_multicast_group \
71 : _ (1, all_hosts_on_subnet) \
72 : _ (2, all_routers_on_subnet) \
73 : _ (4, dvmrp) \
74 : _ (5, ospf_all_routers) \
75 : _ (6, ospf_designated_routers) \
76 : _ (13, pim) \
77 : _ (18, vrrp) \
78 : _ (102, hsrp) \
79 : _ (22, igmp_v3)
80 :
81 : typedef enum
82 : {
83 : #define _(n,f) IP_MULTICAST_GROUP_##f = n,
84 : foreach_ip_builtin_multicast_group
85 : #undef _
86 : } ip_multicast_group_t;
87 :
88 :
89 : /**
90 : * The set of RFC defined DSCP values.
91 : */
92 : #define foreach_ip_dscp \
93 : _(0, CS0) \
94 : _(8, CS1) \
95 : _(10, AF11) \
96 : _(12, AF12) \
97 : _(14, AF13) \
98 : _(16, CS2) \
99 : _(18, AF21) \
100 : _(20, AF22) \
101 : _(22, AF23) \
102 : _(24, CS3) \
103 : _(26, AF31) \
104 : _(28, AF32) \
105 : _(30, AF33) \
106 : _(32, CS4) \
107 : _(34, AF41) \
108 : _(36, AF42) \
109 : _(38, AF43) \
110 : _(40, CS5) \
111 : _(46, EF) \
112 : _(48, CS6) \
113 : _(50, CS7)
114 :
115 : typedef enum ip_dscp_t_
116 : {
117 : #define _(n,f) IP_DSCP_##f = n,
118 : foreach_ip_dscp
119 : #undef _
120 : } __clib_packed ip_dscp_t;
121 :
122 : extern u8 *format_ip_dscp (u8 * s, va_list * va);
123 : unformat_function_t unformat_ip_dscp;
124 :
125 : /**
126 : * IP DSCP bit shift
127 : * The ECN occupies the 2 least significant bits of the TC field
128 : */
129 : #define IP_PACKET_TC_FIELD_DSCP_BIT_SHIFT 2
130 : #define IP_PACKET_TC_FIELD_ECN_MASK 0x03
131 :
132 : /**
133 : * The set of RFC defined DSCP values.
134 : */
135 : #define foreach_ip_ecn \
136 : _(0, NON_ECN) \
137 : _(1, ECT_0) \
138 : _(2, ECT_1) \
139 : _(3, CE)
140 :
141 : typedef enum ip_ecn_t_
142 : {
143 : #define _(n,f) IP_ECN_##f = n,
144 : foreach_ip_ecn
145 : #undef _
146 : } __clib_packed ip_ecn_t;
147 :
148 : STATIC_ASSERT_SIZEOF (ip_ecn_t, 1);
149 :
150 : extern u8 *format_ip_ecn (u8 * s, va_list * va);
151 :
152 : /* Incremental checksum update. */
153 : typedef uword ip_csum_t;
154 :
155 : always_inline ip_csum_t
156 8480061730 : ip_csum_with_carry (ip_csum_t sum, ip_csum_t x)
157 : {
158 8480061730 : ip_csum_t t = sum + x;
159 8480061730 : return t + (t < x);
160 : }
161 :
162 : /* Update checksum changing field at even byte offset from x -> 0. */
163 : always_inline ip_csum_t
164 1198039 : ip_csum_add_even (ip_csum_t c, ip_csum_t x)
165 : {
166 : ip_csum_t d;
167 :
168 1198039 : d = c - x;
169 :
170 : /* Fold in carry from high bit. */
171 1198039 : d -= d > c;
172 :
173 1198039 : ip_csum_t t = ip_csum_with_carry (d, x);
174 1198040 : ASSERT ((t - c == 0) || (t - c == ~0));
175 :
176 1198040 : return d;
177 : }
178 :
179 : /* Update checksum changing field at even byte offset from 0 -> x. */
180 : always_inline ip_csum_t
181 1282082 : ip_csum_sub_even (ip_csum_t c, ip_csum_t x)
182 : {
183 1282082 : return ip_csum_with_carry (c, x);
184 : }
185 :
186 : always_inline ip_csum_t
187 1043898 : ip_csum_update_inline (ip_csum_t sum, ip_csum_t old, ip_csum_t new,
188 : u32 field_byte_offset, u32 field_n_bytes)
189 : {
190 : /* For even 1-byte fields on big-endian and odd 1-byte fields on little endian
191 : we need to shift byte into place for checksum. */
192 1043898 : if ((field_n_bytes % 2)
193 547477 : && (field_byte_offset % 2) == CLIB_ARCH_IS_LITTLE_ENDIAN)
194 : {
195 259931 : old = old << 8;
196 259931 : new = new << 8;
197 : }
198 1043898 : sum = ip_csum_sub_even (sum, old);
199 1043898 : sum = ip_csum_add_even (sum, new);
200 1043898 : return sum;
201 : }
202 :
203 : #define ip_csum_update(sum,old,new,type,field) \
204 : ip_csum_update_inline ((sum), (old), (new), \
205 : STRUCT_OFFSET_OF (type, field), \
206 : STRUCT_SIZE_OF (type, field))
207 :
208 : always_inline u16
209 26151005 : ip_csum_fold (ip_csum_t c)
210 : {
211 : /* Reduce to 16 bits. */
212 : #if defined(__x86_64__) && defined(__BMI2__)
213 : u64 tmp;
214 335262 : asm volatile(
215 : /* using ADC is much faster than mov, shift, add sequence
216 : * compiler produces */
217 : "mov %k[sum], %k[tmp] \n\t"
218 : "shr $32, %[sum] \n\t"
219 : "add %k[tmp], %k[sum] \n\t"
220 : "mov $16, %k[tmp] \n\t"
221 : "shrx %k[tmp], %k[sum], %k[tmp] \n\t"
222 : "adc %w[tmp], %w[sum] \n\t"
223 : "adc $0, %w[sum] \n\t"
224 : : [ sum ] "+&r"(c), [ tmp ] "=&r"(tmp));
225 : #else
226 : #if uword_bits == 64
227 25815743 : c = (c & (ip_csum_t) 0xffffffff) + (c >> (ip_csum_t) 32);
228 25815743 : c = (c & 0xffff) + (c >> 16);
229 : #endif
230 :
231 25815743 : c = (c & 0xffff) + (c >> 16);
232 25815743 : c = (c & 0xffff) + (c >> 16);
233 : #endif
234 26151005 : return c;
235 : }
236 :
237 : extern ip_csum_t (*vnet_incremental_checksum_fp) (ip_csum_t, void *, uword);
238 :
239 : /* Checksum routine. */
240 : always_inline ip_csum_t
241 49594135 : ip_incremental_checksum (ip_csum_t sum, void *_data, uword n_bytes)
242 : {
243 49594135 : return (*vnet_incremental_checksum_fp) (sum, _data, n_bytes);
244 : }
245 :
246 : always_inline u16
247 : ip_csum_and_memcpy_fold (ip_csum_t sum, void *dst)
248 : {
249 : return ip_csum_fold (sum);
250 : }
251 :
252 : #endif /* included_ip_packet_h */
253 :
254 : /*
255 : * fd.io coding-style-patch-verification: ON
256 : *
257 : * Local Variables:
258 : * eval: (c-set-style "gnu")
259 : * End:
260 : */
|