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