05a47031dc22d5457b0cec97e3ce109a9c0bcdee
[vpp.git] / src / vnet / udp / builtin_server.c
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 builtin server
18 */
19
20 #include <vnet/udp/udp.h>
21 #include <vnet/session/session.h>
22 #include <vnet/session/application_interface.h>
23
24 /** per-worker built-in server copy buffers */
25 u8 **copy_buffers;
26 static int app_index = ~0;
27
28 static int
29 builtin_session_create_callback (stream_session_t * s)
30 {
31   /* Simple version: declare session ready-to-go... */
32   s->session_state = SESSION_STATE_READY;
33   return 0;
34 }
35
36 static void
37 builtin_session_disconnect_callback (stream_session_t * s)
38 {
39   stream_session_disconnect (s);
40 }
41
42 static void
43 builtin_session_reset_callback (stream_session_t * s)
44 {
45   clib_warning ("Reset session %U", format_stream_session, s, 2);
46   stream_session_cleanup (s);
47 }
48
49 static int
50 builtin_session_connected_callback (u32 app_index, u32 api_context,
51                                     stream_session_t * s, u8 is_fail)
52 {
53   clib_warning ("called...");
54   return -1;
55 }
56
57 static int
58 builtin_server_rx_callback (stream_session_t * s)
59 {
60   svm_fifo_t *rx_fifo, *tx_fifo;
61   u32 this_transfer, max_deq, max_enq;
62   int actual_transfer;
63   u8 *my_copy_buffer;
64   session_fifo_event_t evt;
65   unix_shared_memory_queue_t *q;
66
67   my_copy_buffer = copy_buffers[s->thread_index];
68   rx_fifo = s->server_rx_fifo;
69   tx_fifo = s->server_tx_fifo;
70
71   max_deq = svm_fifo_max_dequeue (rx_fifo);
72   max_enq = svm_fifo_max_enqueue (tx_fifo);
73   this_transfer = max_enq < max_deq ? max_enq : max_deq;
74
75   vec_validate (my_copy_buffer, this_transfer - 1);
76   _vec_len (my_copy_buffer) = this_transfer;
77
78   actual_transfer = svm_fifo_dequeue_nowait (rx_fifo, this_transfer,
79                                              my_copy_buffer);
80   ASSERT (actual_transfer == this_transfer);
81   actual_transfer = svm_fifo_enqueue_nowait (tx_fifo, this_transfer,
82                                              my_copy_buffer);
83   ASSERT (actual_transfer == this_transfer);
84
85   copy_buffers[s->thread_index] = my_copy_buffer;
86
87   if (svm_fifo_set_event (tx_fifo))
88     {
89       /* Fabricate TX event, send to ourselves */
90       evt.fifo = tx_fifo;
91       evt.event_type = FIFO_EVENT_APP_TX;
92       q = session_manager_get_vpp_event_queue (s->thread_index);
93       unix_shared_memory_queue_add (q, (u8 *) & evt,
94                                     0 /* do wait for mutex */ );
95     }
96
97   return 0;
98 }
99
100 /* *INDENT-OFF* */
101 static session_cb_vft_t builtin_server = {
102     .session_accept_callback = builtin_session_create_callback,
103     .session_connected_callback = builtin_session_connected_callback,
104     .session_disconnect_callback = builtin_session_disconnect_callback,
105     .builtin_server_rx_callback = builtin_server_rx_callback,
106     .session_reset_callback = builtin_session_reset_callback
107 };
108 /* *INDENT-ON* */
109
110 static int
111 attach_builtin_uri_server ()
112 {
113   vnet_app_attach_args_t _a, *a = &_a;
114   u8 segment_name[128];
115   u32 segment_name_length;
116   u64 options[16];
117
118   segment_name_length = ARRAY_LEN (segment_name);
119
120   memset (a, 0, sizeof (*a));
121   memset (options, 0, sizeof (options));
122
123   a->api_client_index = ~0;
124   a->segment_name = segment_name;
125   a->segment_name_length = segment_name_length;
126   a->session_cb_vft = &builtin_server;
127
128   options[APP_OPTIONS_ACCEPT_COOKIE] = 0x12345678;
129   options[APP_OPTIONS_SEGMENT_SIZE] = (2 << 30);        /*$$$$ config / arg */
130   options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
131   options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = 1024;
132
133   a->options = options;
134
135   if (vnet_application_attach (a))
136     return -1;
137
138   app_index = a->app_index;
139   return 0;
140 }
141
142 static int
143 bind_builtin_uri_server (u8 * uri)
144 {
145   vnet_bind_args_t _a, *a = &_a;
146   int rv;
147
148   rv = attach_builtin_uri_server ();
149   if (rv)
150     return rv;
151
152   memset (a, 0, sizeof (*a));
153   a->uri = (char *) uri;
154   a->app_index = app_index;
155
156   rv = vnet_bind_uri (a);
157
158   return rv;
159 }
160
161 static int
162 unbind_builtin_uri_server (u8 * uri)
163 {
164   vnet_unbind_args_t _a, *a = &_a;
165
166   a->app_index = app_index;
167   a->uri = (char *) uri;
168
169   return vnet_unbind_uri (a);
170 }
171
172 static clib_error_t *
173 builtin_server_init (vlib_main_t * vm)
174 {
175   vlib_thread_main_t *vtm = vlib_get_thread_main ();
176   u32 num_threads;
177
178   num_threads = 1 /* main thread */  + vtm->n_threads;
179
180   vec_validate (copy_buffers, num_threads - 1);
181   return 0;
182 }
183
184 VLIB_INIT_FUNCTION (builtin_server_init);
185
186 static clib_error_t *
187 builtin_uri_bind_command_fn (vlib_main_t * vm,
188                              unformat_input_t * input,
189                              vlib_cli_command_t * cmd)
190 {
191   u8 *uri = 0;
192   int rv;
193
194   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
195     {
196       if (unformat (input, "uri %s", &uri))
197         ;
198       else
199         break;
200     }
201
202   if (uri == 0)
203     return clib_error_return (0, "uri to bind not specified...");
204
205   vnet_session_enable_disable (vm, 1 /* turn on UDP, etc. */ );
206
207   rv = bind_builtin_uri_server (uri);
208
209   vec_free (uri);
210
211   switch (rv)
212     {
213     case 0:
214       break;
215
216     default:
217       return clib_error_return (0, "bind_uri_server returned %d", rv);
218       break;
219     }
220
221   return 0;
222 }
223
224 /* *INDENT-OFF* */
225 VLIB_CLI_COMMAND (builtin_uri_bind_command, static) =
226 {
227   .path = "builtin uri bind",
228   .short_help = "builtin uri bind",
229   .function = builtin_uri_bind_command_fn,
230 };
231 /* *INDENT-ON* */
232
233 static clib_error_t *
234 builtin_uri_unbind_command_fn (vlib_main_t * vm,
235                                unformat_input_t * input,
236                                vlib_cli_command_t * cmd)
237 {
238   u8 *uri = 0;
239   int rv;
240
241   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
242     {
243       if (unformat (input, "uri %s", &uri))
244         ;
245       else
246         break;
247     }
248
249   if (uri == 0)
250     return clib_error_return (0, "uri to unbind not specified...");
251
252   rv = unbind_builtin_uri_server (uri);
253
254   vec_free (uri);
255
256   switch (rv)
257     {
258     case 0:
259       break;
260
261     default:
262       return clib_error_return (0, "unbind_uri_server returned %d", rv);
263       break;
264     }
265
266   return 0;
267 }
268
269 /* *INDENT-OFF* */
270 VLIB_CLI_COMMAND (builtin_uri_unbind_command, static) =
271 {
272   .path = "builtin uri unbind",
273   .short_help = "builtin uri unbind",
274   .function = builtin_uri_unbind_command_fn,
275 };
276 /* *INDENT-ON* */
277
278 /*
279  * fd.io coding-style-patch-verification: ON
280  *
281  * Local Variables:
282  * eval: (c-set-style "gnu")
283  * End:
284  */