FD.io VPP  v17.07.01-10-g3be13f0
Vector Packet Processing
udp.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 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 /** @file
17  udp state machine, etc.
18 */
19 
20 #include <vnet/udp/udp.h>
21 #include <vnet/session/session.h>
22 #include <vnet/dpo/load_balance.h>
23 #include <vnet/fib/ip4_fib.h>
24 
26 
27 u32
28 udp_session_bind_ip4 (u32 session_index,
29  ip46_address_t * ip, u16 port_number_host_byte_order)
30 {
32  udp_connection_t *listener;
33 
34  pool_get (um->udp_listeners, listener);
35  memset (listener, 0, sizeof (udp_connection_t));
36  listener->c_lcl_port = clib_host_to_net_u16 (port_number_host_byte_order);
37  listener->c_lcl_ip4.as_u32 = ip->ip4.as_u32;
38  listener->c_proto = SESSION_TYPE_IP4_UDP;
39  udp_register_dst_port (um->vlib_main, port_number_host_byte_order,
40  udp4_uri_input_node.index, 1 /* is_ipv4 */ );
41  return 0;
42 }
43 
44 u32
45 udp_session_bind_ip6 (u32 session_index,
46  ip46_address_t * ip, u16 port_number_host_byte_order)
47 {
49  udp_connection_t *listener;
50 
51  pool_get (um->udp_listeners, listener);
52  listener->c_lcl_port = clib_host_to_net_u16 (port_number_host_byte_order);
53  clib_memcpy (&listener->c_lcl_ip6, &ip->ip6, sizeof (ip6_address_t));
54  listener->c_proto = SESSION_TYPE_IP6_UDP;
55  udp_register_dst_port (um->vlib_main, port_number_host_byte_order,
56  udp4_uri_input_node.index, 0 /* is_ipv4 */ );
57  return 0;
58 }
59 
60 u32
61 udp_session_unbind_ip4 (u32 listener_index)
62 {
63  vlib_main_t *vm = vlib_get_main ();
64  udp_connection_t *listener;
65  listener = udp_listener_get (listener_index);
66 
67  /* deregister the udp_local mapping */
68  udp_unregister_dst_port (vm, listener->c_lcl_port, 1 /* is_ipv4 */ );
69  return 0;
70 }
71 
72 u32
73 udp_session_unbind_ip6 (u32 listener_index)
74 {
75  vlib_main_t *vm = vlib_get_main ();
76  udp_connection_t *listener;
77 
78  listener = udp_listener_get (listener_index);
79 
80  /* deregister the udp_local mapping */
81  udp_unregister_dst_port (vm, listener->c_lcl_port, 0 /* is_ipv4 */ );
82  return 0;
83 }
84 
86 udp_session_get_listener (u32 listener_index)
87 {
88  udp_connection_t *us;
89 
90  us = udp_listener_get (listener_index);
91  return &us->connection;
92 }
93 
94 u32
96 {
97  udp_connection_t *us;
98  u8 *data;
99  udp_header_t *udp;
100 
101  us = (udp_connection_t *) tconn;
102 
103  if (tconn->is_ip4)
104  {
105  ip4_header_t *ip;
106 
107  data = vlib_buffer_get_current (b);
108  udp = (udp_header_t *) (data - sizeof (udp_header_t));
109  ip = (ip4_header_t *) ((u8 *) udp - sizeof (ip4_header_t));
110 
111  /* Build packet header, swap rx key src + dst fields */
112  ip->src_address.as_u32 = us->c_lcl_ip4.as_u32;
113  ip->dst_address.as_u32 = us->c_rmt_ip4.as_u32;
114  ip->ip_version_and_header_length = 0x45;
115  ip->ttl = 254;
116  ip->protocol = IP_PROTOCOL_UDP;
117  ip->length = clib_host_to_net_u16 (b->current_length + sizeof (*udp));
118  ip->checksum = ip4_header_checksum (ip);
119 
120  udp->src_port = us->c_lcl_port;
121  udp->dst_port = us->c_rmt_port;
122  udp->length = clib_host_to_net_u16 (b->current_length);
123  udp->checksum = 0;
124 
125  b->current_length = sizeof (*ip) + sizeof (*udp);
127  }
128  else
129  {
130  vlib_main_t *vm = vlib_get_main ();
131  ip6_header_t *ip;
132  u16 payload_length;
133  int bogus = ~0;
134 
135  data = vlib_buffer_get_current (b);
136  udp = (udp_header_t *) (data - sizeof (udp_header_t));
137  ip = (ip6_header_t *) ((u8 *) udp - sizeof (ip6_header_t));
138 
139  /* Build packet header, swap rx key src + dst fields */
140  clib_memcpy (&ip->src_address, &us->c_lcl_ip6, sizeof (ip6_address_t));
141  clib_memcpy (&ip->dst_address, &us->c_rmt_ip6, sizeof (ip6_address_t));
142 
144  clib_host_to_net_u32 (0x6 << 28);
145 
146  ip->hop_limit = 0xff;
147  ip->protocol = IP_PROTOCOL_UDP;
148 
149  payload_length = vlib_buffer_length_in_chain (vm, b);
150  payload_length -= sizeof (*ip);
151 
152  ip->payload_length = clib_host_to_net_u16 (payload_length);
153 
154  udp->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b, ip, &bogus);
155  ASSERT (!bogus);
156 
157  udp->src_port = us->c_lcl_port;
158  udp->dst_port = us->c_rmt_port;
159  udp->length = clib_host_to_net_u16 (b->current_length);
160  udp->checksum = 0;
161 
162  b->current_length = sizeof (*ip) + sizeof (*udp);
163 
165  }
166 }
167 
169 udp_session_get (u32 connection_index, u32 my_thread_index)
170 {
172 
173  udp_connection_t *us;
174  us =
175  pool_elt_at_index (um->udp_sessions[my_thread_index], connection_index);
176  return &us->connection;
177 }
178 
179 void
180 udp_session_close (u32 connection_index, u32 my_thread_index)
181 {
183  pool_put_index (um->udp_sessions[my_thread_index], connection_index);
184 }
185 
186 u8 *
187 format_udp_session_ip4 (u8 * s, va_list * args)
188 {
189  u32 uci = va_arg (*args, u32);
190  u32 thread_index = va_arg (*args, u32);
191  udp_connection_t *u4;
192 
193  u4 = udp_connection_get (uci, thread_index);
194 
195  s = format (s, "[%s] %U:%d->%U:%d", "udp", format_ip4_address,
196  &u4->c_lcl_ip4, clib_net_to_host_u16 (u4->c_lcl_port),
197  format_ip4_address, &u4->c_rmt_ip4,
198  clib_net_to_host_u16 (u4->c_rmt_port));
199  return s;
200 }
201 
202 u8 *
203 format_udp_session_ip6 (u8 * s, va_list * args)
204 {
205  u32 uci = va_arg (*args, u32);
206  u32 thread_index = va_arg (*args, u32);
207  udp_connection_t *tc = udp_connection_get (uci, thread_index);
208  s = format (s, "[%s] %U:%d->%U:%d", "udp", format_ip6_address,
209  &tc->c_lcl_ip6, clib_net_to_host_u16 (tc->c_lcl_port),
210  format_ip6_address, &tc->c_rmt_ip6,
211  clib_net_to_host_u16 (tc->c_rmt_port));
212  return s;
213 }
214 
215 u8 *
216 format_udp_listener_session_ip4 (u8 * s, va_list * args)
217 {
218  u32 tci = va_arg (*args, u32);
220  s = format (s, "[%s] %U:%d->%U:%d", "udp", format_ip4_address,
221  &tc->c_lcl_ip4, clib_net_to_host_u16 (tc->c_lcl_port),
222  format_ip4_address, &tc->c_rmt_ip4,
223  clib_net_to_host_u16 (tc->c_rmt_port));
224  return s;
225 }
226 
227 u8 *
228 format_udp_listener_session_ip6 (u8 * s, va_list * args)
229 {
230  u32 tci = va_arg (*args, u32);
232  s = format (s, "[%s] %U:%d->%U:%d", "udp", format_ip6_address,
233  &tc->c_lcl_ip6, clib_net_to_host_u16 (tc->c_lcl_port),
234  format_ip6_address, &tc->c_rmt_ip6,
235  clib_net_to_host_u16 (tc->c_rmt_port));
236  return s;
237 }
238 
239 u16
241 {
242  /* TODO figure out MTU of output interface */
243  return 400;
244 }
245 
246 u32
248 {
249  /* No constraint on TX window */
250  return ~0;
251 }
252 
253 int
254 udp_open_connection (ip46_address_t * addr, u16 port)
255 {
256  clib_warning ("Not implemented");
257  return 0;
258 }
259 
260 /* *INDENT-OFF* */
262  .bind = udp_session_bind_ip4,
263  .open = udp_open_connection,
264  .unbind = udp_session_unbind_ip4,
265  .push_header = udp_push_header,
266  .get_connection = udp_session_get,
267  .get_listener = udp_session_get_listener,
268  .close = udp_session_close,
269  .send_mss = udp_send_mss_uri,
270  .send_space = udp_send_space_uri,
271  .format_connection = format_udp_session_ip4,
272  .format_listener = format_udp_listener_session_ip4
273 };
274 
276  .bind = udp_session_bind_ip6,
277  .open = udp_open_connection,
278  .unbind = udp_session_unbind_ip6,
279  .push_header = udp_push_header,
280  .get_connection = udp_session_get,
281  .get_listener = udp_session_get_listener,
282  .close = udp_session_close,
283  .send_mss = udp_send_mss_uri,
284  .send_space = udp_send_space_uri,
285  .format_connection = format_udp_session_ip6,
286  .format_listener = format_udp_listener_session_ip6
287 };
288 /* *INDENT-ON* */
289 
290 static clib_error_t *
292 {
294  ip_main_t *im = &ip_main;
296  u32 num_threads;
297  clib_error_t *error = 0;
298  ip_protocol_info_t *pi;
299 
300  um->vlib_main = vm;
301  um->vnet_main = vnet_get_main ();
302 
303  if ((error = vlib_call_init_function (vm, ip_main_init)))
304  return error;
305  if ((error = vlib_call_init_function (vm, ip4_lookup_init)))
306  return error;
307  if ((error = vlib_call_init_function (vm, ip6_lookup_init)))
308  return error;
309 
310  /*
311  * Registrations
312  */
313 
314  /* IP registration */
315  pi = ip_get_protocol_info (im, IP_PROTOCOL_UDP);
316  if (pi == 0)
317  return clib_error_return (0, "UDP protocol info AWOL");
320 
321 
322  /* Register as transport with URI */
323  session_register_transport (SESSION_TYPE_IP4_UDP, &udp4_proto);
324  session_register_transport (SESSION_TYPE_IP6_UDP, &udp6_proto);
325 
326  /*
327  * Initialize data structures
328  */
329 
330  num_threads = 1 /* main thread */ + tm->n_threads;
331  vec_validate (um->udp_sessions, num_threads - 1);
332 
333  return error;
334 }
335 
337 
338 /*
339  * fd.io coding-style-patch-verification: ON
340  *
341  * Local Variables:
342  * eval: (c-set-style "gnu")
343  * End:
344  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:436
static udp_connection_t * udp_listener_get(u32 conn_index)
Definition: udp.h:67
format_function_t format_udp_header
Definition: format.h:102
ip4_address_t src_address
Definition: ip4_packet.h:164
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
struct _transport_connection transport_connection_t
static clib_error_t * udp_init(vlib_main_t *vm)
Definition: udp.c:291
static const transport_proto_vft_t udp6_proto
Definition: udp.c:275
transport_connection_t * udp_session_get_listener(u32 listener_index)
Definition: udp.c:86
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
Definition: ip.h:106
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 pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
ip6_address_t src_address
Definition: ip6_packet.h:341
u32 udp_send_space_uri(transport_connection_t *t)
Definition: udp.c:247
u32 udp_session_bind_ip4(u32 session_index, ip46_address_t *ip, u16 port_number_host_byte_order)
Definition: udp.c:28
format_function_t format_ip4_address
Definition: format.h:79
unformat_function_t * unformat_pg_edit
Definition: ip.h:87
u8 * format_udp_listener_session_ip4(u8 *s, va_list *args)
Definition: udp.c:216
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
u16 udp_send_mss_uri(transport_connection_t *t)
Definition: udp.c:240
ip4_address_t dst_address
Definition: ip4_packet.h:164
#define clib_error_return(e, args...)
Definition: error.h:99
void udp_session_close(u32 connection_index, u32 my_thread_index)
Definition: udp.c:180
#define vlib_call_init_function(vm, x)
Definition: init.h:162
struct _transport_proto_vft transport_proto_vft_t
struct _udp_uri_main udp_uri_main_t
u8 * format_udp_session_ip6(u8 *s, va_list *args)
Definition: udp.c:203
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:397
static ip_protocol_info_t * ip_get_protocol_info(ip_main_t *im, u32 protocol)
Definition: ip.h:133
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:71
format_function_t * format_header
Definition: ip.h:78
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:188
clib_error_t * ip_main_init(vlib_main_t *vm)
Definition: ip_init.c:45
format_function_t format_ip6_address
Definition: format.h:95
ip_main_t ip_main
Definition: ip_init.c:42
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_warning(format, args...)
Definition: error.h:59
unformat_function_t unformat_pg_udp_header
Definition: format.h:104
#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
u32 udp_push_header(transport_connection_t *tconn, vlib_buffer_t *b)
Definition: udp.c:95
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
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:255
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format_udp_listener_session_ip6(u8 *s, va_list *args)
Definition: udp.c:228
vlib_node_registration_t udp4_uri_input_node
(constructor) VLIB_REGISTER_NODE (udp4_uri_input_node)
Definition: udp_input.c:303
u8 * format_udp_session_ip4(u8 *s, va_list *args)
Definition: udp.c:187
clib_error_t * ip4_lookup_init(vlib_main_t *vm)
Definition: ip4_forward.c:1171
void session_register_transport(u8 type, const transport_proto_vft_t *vft)
Definition: session.c:1041
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:328
udp_uri_main_t udp_uri_main
Definition: udp.c:25
unsigned short u16
Definition: types.h:57
static const transport_proto_vft_t udp4_proto
Definition: udp.c:261
u16 payload_length
Definition: ip6_packet.h:332
transport_connection_t connection
Definition: udp.h:31
unsigned char u8
Definition: types.h:56
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
int udp_open_connection(ip46_address_t *addr, u16 port)
Definition: udp.c:254
vhost_vring_addr_t addr
Definition: vhost-user.h:82
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
u8 ip_version_and_header_length
Definition: ip4_packet.h:132
static clib_error_t * ip6_lookup_init(vlib_main_t *vm)
Definition: ip6_forward.c:2929
static udp_uri_main_t * vnet_get_udp_main()
Definition: udp.h:54
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:239
u32 udp_session_bind_ip6(u32 session_index, ip46_address_t *ip, u16 port_number_host_byte_order)
Definition: udp.c:45
transport_connection_t * udp_session_get(u32 connection_index, u32 my_thread_index)
Definition: udp.c:169
ip6_address_t dst_address
Definition: ip6_packet.h:341
u32 udp_session_unbind_ip6(u32 listener_index)
Definition: udp.c:73
u32 udp_session_unbind_ip4(u32 listener_index)
Definition: udp.c:61