FD.io VPP  v17.07.01-10-g3be13f0
Vector Packet Processing
udp.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 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 #ifndef __included_udp_h__
16 #define __included_udp_h__
17 
18 #include <vnet/vnet.h>
19 #include <vnet/udp/udp_packet.h>
20 #include <vnet/ip/ip.h>
21 #include <vnet/ip/ip4.h>
22 #include <vnet/ip/ip4_packet.h>
23 #include <vnet/pg/pg.h>
24 #include <vnet/ip/format.h>
25 
26 #include <vnet/ip/ip.h>
27 #include <vnet/session/transport.h>
28 
29 typedef struct
30 {
31  transport_connection_t connection; /** must be first */
32 
33  /** ersatz MTU to limit fifo pushes to test data size */
36 
37 typedef struct _udp_uri_main
38 {
39  /* Per-worker thread udp connection pools */
40  udp_connection_t **udp_sessions;
41  udp_connection_t *udp_listeners;
42 
43  /* convenience */
49 
52 
55 {
56  return &udp_uri_main;
57 }
58 
60 udp_connection_get (u32 conn_index, u32 thread_index)
61 {
62  return pool_elt_at_index (udp_uri_main.udp_sessions[thread_index],
63  conn_index);
64 }
65 
67 udp_listener_get (u32 conn_index)
68 {
69  return pool_elt_at_index (udp_uri_main.udp_listeners, conn_index);
70 }
71 
72 typedef enum
73 {
74 #define udp_error(n,s) UDP_ERROR_##n,
75 #include <vnet/udp/udp_error.def>
76 #undef udp_error
78 } udp_error_t;
79 
80 #define foreach_udp4_dst_port \
81 _ (67, dhcp_to_server) \
82 _ (68, dhcp_to_client) \
83 _ (500, ikev2) \
84 _ (2152, GTPU) \
85 _ (3784, bfd4) \
86 _ (3785, bfd_echo4) \
87 _ (4341, lisp_gpe) \
88 _ (4342, lisp_cp) \
89 _ (4739, ipfix) \
90 _ (4789, vxlan) \
91 _ (4789, vxlan6) \
92 _ (4790, VXLAN_GPE) \
93 _ (6633, vpath_3)
94 
95 
96 #define foreach_udp6_dst_port \
97 _ (547, dhcpv6_to_server) \
98 _ (546, dhcpv6_to_client) \
99 _ (2152, GTPU6) \
100 _ (3784, bfd6) \
101 _ (3785, bfd_echo6) \
102 _ (4341, lisp_gpe6) \
103 _ (4342, lisp_cp6) \
104 _ (4790, VXLAN6_GPE) \
105 _ (6633, vpath6_3)
106 
107 typedef enum
108 {
109 #define _(n,f) UDP_DST_PORT_##f = n,
111 #undef _
113 
114 typedef enum
115 {
116 #define _(n,f) UDP6_DST_PORT_##f = n,
118 #undef _
120 
121 typedef struct
122 {
123  /* Name (a c string). */
124  char *name;
125 
126  /* GRE protocol type in host byte order. */
128 
129  /* Node which handles this type. */
131 
132  /* Next index for this type. */
135 
136 typedef enum
137 {
138  UDP_IP6 = 0,
139  UDP_IP4, /* the code is full of is_ip4... */
141 } udp_af_t;
142 
143 typedef struct
144 {
145  udp_dst_port_info_t *dst_port_infos[N_UDP_AF];
146 
147  /* Hash tables mapping name/protocol to protocol info index. */
148  uword *dst_port_info_by_name[N_UDP_AF];
149  uword *dst_port_info_by_dst_port[N_UDP_AF];
150 
151  /* Sparse vector mapping udp dst_port in network byte order
152  to next index. */
157 
158  /* convenience */
160 } udp_main_t;
161 
164 {
165  uword *p = hash_get (um->dst_port_info_by_dst_port[is_ip4], dst_port);
166  return p ? vec_elt_at_index (um->dst_port_infos[is_ip4], p[0]) : 0;
167 }
168 
171 
173 
175  udp_dst_port_t dst_port,
176  u32 node_index, u8 is_ip4);
177 
178 void
180  udp_dst_port_t dst_port, u8 is_ip4);
181 
182 void udp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add);
183 
184 always_inline void
186 {
187  u16 new_l0;
188  udp_header_t *udp0;
189 
190  if (is_ip4)
191  {
192  ip4_header_t *ip0;
193  ip_csum_t sum0;
194  u16 old_l0 = 0;
195 
196  ip0 = vlib_buffer_get_current (b0);
197 
198  /* fix the <bleep>ing outer-IP checksum */
199  sum0 = ip0->checksum;
200  /* old_l0 always 0, see the rewrite setup */
201  new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
202 
203  sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
204  length /* changed member */ );
205  ip0->checksum = ip_csum_fold (sum0);
206  ip0->length = new_l0;
207 
208  /* Fix UDP length */
209  udp0 = (udp_header_t *) (ip0 + 1);
210  new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
211  - sizeof (*ip0));
212  udp0->length = new_l0;
213  }
214  else
215  {
216  ip6_header_t *ip0;
217  int bogus0;
218 
219  ip0 = vlib_buffer_get_current (b0);
220 
221  new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
222  - sizeof (*ip0));
223  ip0->payload_length = new_l0;
224 
225  /* Fix UDP length */
226  udp0 = (udp_header_t *) (ip0 + 1);
227  udp0->length = new_l0;
228 
229  udp0->checksum =
230  ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0, &bogus0);
231  ASSERT (bogus0 == 0);
232 
233  if (udp0->checksum == 0)
234  udp0->checksum = 0xffff;
235  }
236 }
237 
238 always_inline void
239 ip_udp_encap_one (vlib_main_t * vm, vlib_buffer_t * b0, u8 * ec0, word ec_len,
240  u8 is_ip4)
241 {
242  vlib_buffer_advance (b0, -ec_len);
243 
244  if (is_ip4)
245  {
246  ip4_header_t *ip0;
247 
248  ip0 = vlib_buffer_get_current (b0);
249 
250  /* Apply the encap string. */
251  clib_memcpy (ip0, ec0, ec_len);
252  ip_udp_fixup_one (vm, b0, 1);
253  }
254  else
255  {
256  ip6_header_t *ip0;
257 
258  ip0 = vlib_buffer_get_current (b0);
259 
260  /* Apply the encap string. */
261  clib_memcpy (ip0, ec0, ec_len);
262  ip_udp_fixup_one (vm, b0, 0);
263  }
264 }
265 
266 always_inline void
268  u8 * ec0, u8 * ec1, word ec_len, u8 is_v4)
269 {
270  u16 new_l0, new_l1;
271  udp_header_t *udp0, *udp1;
272 
273  ASSERT (_vec_len (ec0) == _vec_len (ec1));
274 
275  vlib_buffer_advance (b0, -ec_len);
276  vlib_buffer_advance (b1, -ec_len);
277 
278  if (is_v4)
279  {
280  ip4_header_t *ip0, *ip1;
281  ip_csum_t sum0, sum1;
282  u16 old_l0 = 0, old_l1 = 0;
283 
284  ip0 = vlib_buffer_get_current (b0);
285  ip1 = vlib_buffer_get_current (b1);
286 
287  /* Apply the encap string */
288  clib_memcpy (ip0, ec0, ec_len);
289  clib_memcpy (ip1, ec1, ec_len);
290 
291  /* fix the <bleep>ing outer-IP checksum */
292  sum0 = ip0->checksum;
293  sum1 = ip1->checksum;
294 
295  /* old_l0 always 0, see the rewrite setup */
296  new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
297  new_l1 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1));
298 
299  sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
300  length /* changed member */ );
301  sum1 = ip_csum_update (sum1, old_l1, new_l1, ip4_header_t,
302  length /* changed member */ );
303 
304  ip0->checksum = ip_csum_fold (sum0);
305  ip1->checksum = ip_csum_fold (sum1);
306 
307  ip0->length = new_l0;
308  ip1->length = new_l1;
309 
310  /* Fix UDP length */
311  udp0 = (udp_header_t *) (ip0 + 1);
312  udp1 = (udp_header_t *) (ip1 + 1);
313 
314  new_l0 =
315  clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) -
316  sizeof (*ip0));
317  new_l1 =
318  clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1) -
319  sizeof (*ip1));
320  udp0->length = new_l0;
321  udp1->length = new_l1;
322  }
323  else
324  {
325  ip6_header_t *ip0, *ip1;
326  int bogus0, bogus1;
327 
328  ip0 = vlib_buffer_get_current (b0);
329  ip1 = vlib_buffer_get_current (b1);
330 
331  /* Apply the encap string. */
332  clib_memcpy (ip0, ec0, ec_len);
333  clib_memcpy (ip1, ec1, ec_len);
334 
335  new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
336  - sizeof (*ip0));
337  new_l1 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1)
338  - sizeof (*ip1));
339  ip0->payload_length = new_l0;
340  ip1->payload_length = new_l1;
341 
342  /* Fix UDP length */
343  udp0 = (udp_header_t *) (ip0 + 1);
344  udp1 = (udp_header_t *) (ip1 + 1);
345 
346  udp0->length = new_l0;
347  udp1->length = new_l1;
348 
349  udp0->checksum =
350  ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0, &bogus0);
351  udp1->checksum =
352  ip6_tcp_udp_icmp_compute_checksum (vm, b1, ip1, &bogus1);
353  ASSERT (bogus0 == 0);
354  ASSERT (bogus1 == 0);
355 
356  if (udp0->checksum == 0)
357  udp0->checksum = 0xffff;
358  if (udp1->checksum == 0)
359  udp1->checksum = 0xffff;
360  }
361 }
362 
363 /*
364  * fd.io coding-style-patch-verification: ON
365  *
366  * Local Variables:
367  * eval: (c-set-style "gnu")
368  * End:
369  */
370 
371 #endif /* __included_udp_h__ */
uword( unformat_function_t)(unformat_input_t *input, va_list *args)
Definition: format.h:231
static udp_connection_t * udp_listener_get(u32 conn_index)
Definition: udp.h:67
u16 * next_by_dst_port6
Definition: udp.h:154
unformat_function_t unformat_udp_header
Definition: udp.h:172
struct _transport_connection transport_connection_t
uword * dst_port_info_by_dst_port[N_UDP_AF]
Definition: udp.h:149
struct _vlib_node_registration vlib_node_registration_t
static udp_dst_port_info_t * udp_get_dst_port_info(udp_main_t *um, udp_dst_port_t dst_port, u8 is_ip4)
Definition: udp.h:163
uword ip_csum_t
Definition: ip_packet.h:90
u8 *( format_function_t)(u8 *s, va_list *args)
Definition: format.h:48
u8 punt_unknown6
Definition: udp.h:156
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:100
#define always_inline
Definition: clib.h:84
u8 punt_unknown4
Definition: udp.h:155
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define foreach_udp6_dst_port
Definition: udp.h:96
udp_uri_main_t udp_uri_main
Definition: udp.c:25
struct _udp_uri_main udp_uri_main_t
#define hash_get(h, key)
Definition: hash.h:248
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:397
u16 * next_by_dst_port4
Definition: udp.h:153
udp_dst_port_info_t * dst_port_infos[N_UDP_AF]
Definition: udp.h:145
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:188
vnet_main_t vnet_main
Definition: misc.c:43
static void ip_udp_encap_one(vlib_main_t *vm, vlib_buffer_t *b0, u8 *ec0, word ec_len, u8 is_ip4)
Definition: udp.h:239
Definition: udp.h:138
void udp_punt_unknown(vlib_main_t *vm, u8 is_ip4, u8 is_add)
Definition: udp_local.c:549
static void ip_udp_fixup_one(vlib_main_t *vm, vlib_buffer_t *b0, u8 is_ip4)
Definition: udp.h:185
format_function_t format_udp_rx_trace
Definition: udp.h:170
static void ip_udp_encap_two(vlib_main_t *vm, vlib_buffer_t *b0, vlib_buffer_t *b1, u8 *ec0, u8 *ec1, word ec_len, u8 is_v4)
Definition: udp.h:267
void udp_unregister_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u8 is_ip4)
Definition: udp_local.c:526
#define clib_memcpy(a, b, c)
Definition: string.h:69
static udp_connection_t * udp_connection_get(u32 conn_index, u32 thread_index)
Definition: udp.h:60
udp_error_t
Definition: udp.h:72
udp_dst_port_t
Definition: udp.h:107
u16 ip6_tcp_udp_icmp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip6_header_t *ip0, int *bogus_lengthp)
Definition: ip6_forward.c:1195
int vlib_main(vlib_main_t *volatile vm, unformat_input_t *input)
Definition: main.c:1692
#define foreach_udp4_dst_port
Definition: udp.h:80
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
udp_af_t
Definition: udp.h:136
ip6_main_t ip6_main
Definition: ip6_forward.c:2926
udp_dst_port_t dst_port
Definition: udp.h:127
char * name
Definition: udp.h:124
IPv4 main type.
Definition: ip4.h:83
vlib_node_registration_t udp4_uri_input_node
(constructor) VLIB_REGISTER_NODE (udp4_uri_input_node)
Definition: udp_input.c:303
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:201
u64 uword
Definition: types.h:112
unsigned short u16
Definition: types.h:57
u16 payload_length
Definition: ip6_packet.h:332
i64 word
Definition: types.h:111
transport_connection_t connection
Definition: udp.h:31
unsigned char u8
Definition: types.h:56
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:139
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1168
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
Definition: udp_local.c:488
u32 mtu
must be first
Definition: udp.h:34
static udp_uri_main_t * vnet_get_udp_main()
Definition: udp.h:54
vlib_main_t * vlib_main
Definition: udp.h:159
udp6_dst_port_t
Definition: udp.h:114
Definition: udp.h:139
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:145
Definition: udp.h:140
format_function_t format_udp_header
Definition: udp.h:169