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