blob: 11dc97d89b753e605a576d1e6a304715b36af860 [file] [log] [blame]
Dave Barach68b0fb02017-02-28 15:15:56 -05001/*
Florin Coras288eaab2019-02-03 15:26:14 -08002 * Copyright (c) 2016-2019 Cisco and/or its affiliates.
Dave Barach68b0fb02017-02-28 15:15:56 -05003 * 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#include <vnet/session/application_interface.h>
Dave Barach68b0fb02017-02-28 15:15:56 -050016#include <vnet/session/session.h>
17#include <vlibmemory/api.h>
18#include <vnet/dpo/load_balance.h>
Dave Barach68b0fb02017-02-28 15:15:56 -050019
20/** @file
21 VPP's application/session API bind/unbind/connect/disconnect calls
22*/
23
Florin Coras371ca502018-02-21 12:07:41 -080024/*
25 * TLS server cert and keys to be used for testing only
26 */
27const char test_srv_crt_rsa[] =
28 "-----BEGIN CERTIFICATE-----\r\n"
Florin Coras8f89dd02018-03-05 16:53:07 -080029 "MIID5zCCAs+gAwIBAgIJALeMYCEHrTtJMA0GCSqGSIb3DQEBCwUAMIGJMQswCQYD\r\n"
30 "VQQGEwJVUzELMAkGA1UECAwCQ0ExETAPBgNVBAcMCFNhbiBKb3NlMQ4wDAYDVQQK\r\n"
31 "DAVDaXNjbzEOMAwGA1UECwwFZmQuaW8xFjAUBgNVBAMMDXRlc3R0bHMuZmQuaW8x\r\n"
32 "IjAgBgkqhkiG9w0BCQEWE3ZwcC1kZXZAbGlzdHMuZmQuaW8wHhcNMTgwMzA1MjEx\r\n"
33 "NTEyWhcNMjgwMzAyMjExNTEyWjCBiTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNB\r\n"
34 "MREwDwYDVQQHDAhTYW4gSm9zZTEOMAwGA1UECgwFQ2lzY28xDjAMBgNVBAsMBWZk\r\n"
35 "LmlvMRYwFAYDVQQDDA10ZXN0dGxzLmZkLmlvMSIwIAYJKoZIhvcNAQkBFhN2cHAt\r\n"
36 "ZGV2QGxpc3RzLmZkLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\r\n"
37 "4C1k8a1DuStgggqT4o09fP9sJ2dC54bxhS/Xk2VEfaIZ222WSo4X/syRVfVy9Yah\r\n"
38 "cpI1zJ/RDxaZSFhgA+nPZBrFMsrULkrdAOpOVj8eDEp9JuWdO2ODSoFnCvLxcYWB\r\n"
39 "Yc5kHryJpEaGJl1sFQSesnzMFty/59ta0stk0Fp8r5NhIjWvSovGzPo6Bhz+VS2c\r\n"
40 "ebIZh4x1t2hHaFcgm0qJoJ6DceReWCW8w+yOVovTolGGq+bpb2Hn7MnRSZ2K2NdL\r\n"
41 "+aLXpkZbS/AODP1FF2vTO1mYL290LO7/51vJmPXNKSDYMy5EvILr5/VqtjsFCwRL\r\n"
42 "Q4jcM/+GeHSAFWx4qIv0BwIDAQABo1AwTjAdBgNVHQ4EFgQUWa1SOB37xmT53tZQ\r\n"
43 "aXuLLhRI7U8wHwYDVR0jBBgwFoAUWa1SOB37xmT53tZQaXuLLhRI7U8wDAYDVR0T\r\n"
44 "BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAoUht13W4ya27NVzQuCMvqPWL3VM4\r\n"
45 "3xbPFk02FaGz/WupPu276zGlzJAZrbuDcQowwwU1Ni1Yygxl96s1c2M5rHDTrOKG\r\n"
46 "rK0hbkSFBo+i6I8u4HiiQ4rYmG0Hv6+sXn3of0HsbtDPGgWZoipPWDljPYEURu3e\r\n"
47 "3HRe/Dtsj9CakBoSDzs8ndWaBR+f4sM9Tk1cjD46Gq2T/qpSPXqKxEUXlzhdCAn4\r\n"
48 "twub17Bq2kykHpppCwPg5M+v30tHG/R2Go15MeFWbEJthFk3TZMjKL7UFs7fH+x2\r\n"
49 "wSonXb++jY+KmCb93C+soABBizE57g/KmiR2IxQ/LMjDik01RSUIaM0lLA==\r\n"
50 "-----END CERTIFICATE-----\r\n";
Florin Coras371ca502018-02-21 12:07:41 -080051const u32 test_srv_crt_rsa_len = sizeof (test_srv_crt_rsa);
52
53const char test_srv_key_rsa[] =
Florin Coras8f89dd02018-03-05 16:53:07 -080054 "-----BEGIN PRIVATE KEY-----\r\n"
55 "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDgLWTxrUO5K2CC\r\n"
56 "CpPijT18/2wnZ0LnhvGFL9eTZUR9ohnbbZZKjhf+zJFV9XL1hqFykjXMn9EPFplI\r\n"
57 "WGAD6c9kGsUyytQuSt0A6k5WPx4MSn0m5Z07Y4NKgWcK8vFxhYFhzmQevImkRoYm\r\n"
58 "XWwVBJ6yfMwW3L/n21rSy2TQWnyvk2EiNa9Ki8bM+joGHP5VLZx5shmHjHW3aEdo\r\n"
59 "VyCbSomgnoNx5F5YJbzD7I5Wi9OiUYar5ulvYefsydFJnYrY10v5otemRltL8A4M\r\n"
60 "/UUXa9M7WZgvb3Qs7v/nW8mY9c0pINgzLkS8guvn9Wq2OwULBEtDiNwz/4Z4dIAV\r\n"
61 "bHioi/QHAgMBAAECggEBAMzGipP8+oT166U+NlJXRFifFVN1DvdhG9PWnOxGL+c3\r\n"
62 "ILmBBC08WQzmHshPemBvR6DZkA1H23cV5JTiLWrFtC00CvhXsLRMrE5+uWotI6yE\r\n"
63 "iofybMroHvD6/X5R510UX9hQ6MHu5ShLR5VZ9zXHz5MpTmB/60jG5dLx+jgcwBK8\r\n"
64 "LuGv2YB/WCUwT9QJ3YU2eaingnXtz/MrFbkbltrqlnBdlD+kTtw6Yac9y1XuuQXc\r\n"
65 "BPeulLNDuPolJVWbUvDBZrpt2dXTgz8ws1sv+wCNE0xwQJsqW4Nx3QkpibUL9RUr\r\n"
66 "CVbKlNfa9lopT6nGKlgX69R/uH35yh9AOsfasro6w0ECgYEA82UJ8u/+ORah+0sF\r\n"
67 "Q0FfW5MTdi7OAUHOz16pUsGlaEv0ERrjZxmAkHA/VRwpvDBpx4alCv0Hc39PFLIk\r\n"
68 "nhSsM2BEuBkTAs6/GaoNAiBtQVE/hN7awNRWVmlieS0go3Y3dzaE9IUMyj8sPOFT\r\n"
69 "5JdJ6BM69PHKCkY3dKdnnfpFEuECgYEA68mRpteunF1mdZgXs+WrN+uLlRrQR20F\r\n"
70 "ZyMYiUCH2Dtn26EzA2moy7FipIIrQcX/j+KhYNGM3e7MU4LymIO29E18mn8JODnH\r\n"
71 "sQOXzBTsf8A4yIVMkcuQD3bfb0JiUGYUPOidTp2N7IJA7+6Yc3vQOyb74lnKnJoO\r\n"
72 "gougPT2wS+cCgYAn7muzb6xFsXDhyW0Tm6YJYBfRS9yAWEuVufINobeBZPSl2cN1\r\n"
73 "Jrnw+HlrfTNbrJWuJmjtZJXUXQ6cVp2rUbjutNyRV4vG6iRwEXYQ40EJdkr1gZpi\r\n"
74 "CHQhuShuuPih2MNAy7EEbM+sXrDjTBR3bFqzuHPzu7dp+BshCFX3lRfAAQKBgGQt\r\n"
75 "K5i7IhCFDjb/+3IPLgOAK7mZvsvZ4eXD33TQ2eZgtut1PXtBtNl17/b85uv293Fm\r\n"
76 "VDISVcsk3eLNS8zIiT6afUoWlxAwXEs0v5WRfjl4radkGvgGiJpJYvyeM67877RB\r\n"
77 "EDSKc/X8ESLfOB44iGvZUEMG6zJFscx9DgN25iQZAoGAbyd+JEWwdVH9/K3IH1t2\r\n"
78 "PBkZX17kNWv+iVM1WyFjbe++vfKZCrOJiyiqhDeEqgrP3AuNMlaaduC3VRC3G5oV\r\n"
79 "Mj1tlhDWQ/qhvKdCKNdIVQYDE75nw+FRWV8yYkHAnXYW3tNoweDIwixE0hkPR1bc\r\n"
80 "oEjPLVNtx8SOj/M4rhaPT3I=\r\n" "-----END PRIVATE KEY-----\r\n";
Florin Coras371ca502018-02-21 12:07:41 -080081const u32 test_srv_key_rsa_len = sizeof (test_srv_key_rsa);
82
Florin Coras4829bab2018-09-14 13:17:41 -070083#define app_interface_check_thread_and_barrier(_fn, _arg) \
Florin Coras568ebc72018-09-18 16:12:50 -070084 if (PREDICT_FALSE (!vlib_thread_is_main_w_barrier ())) \
Florin Coras4829bab2018-09-14 13:17:41 -070085 { \
86 vlib_rpc_call_main_thread (_fn, (u8 *) _arg, sizeof(*_arg)); \
87 return 0; \
88 }
89
Florin Corascea194d2017-10-02 00:18:51 -070090u8
91session_endpoint_in_ns (session_endpoint_t * sep)
92{
Florin Corase1b819e2018-03-15 07:45:27 -070093 u8 is_lep = session_endpoint_is_local (sep);
94 if (!is_lep && sep->sw_if_index != ENDPOINT_INVALID_INDEX
Florin Corascea194d2017-10-02 00:18:51 -070095 && !ip_interface_has_address (sep->sw_if_index, &sep->ip, sep->is_ip4))
Dave Barach68b0fb02017-02-28 15:15:56 -050096 {
Florin Corascea194d2017-10-02 00:18:51 -070097 clib_warning ("sw_if_index %u not configured with ip %U",
98 sep->sw_if_index, format_ip46_address, &sep->ip,
99 sep->is_ip4);
100 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500101 }
Florin Corase1b819e2018-03-15 07:45:27 -0700102 return (is_lep || ip_is_local (sep->fib_index, &sep->ip, sep->is_ip4));
Dave Barach68b0fb02017-02-28 15:15:56 -0500103}
104
105int
106api_parse_session_handle (u64 handle, u32 * session_index, u32 * thread_index)
107{
108 session_manager_main_t *smm = vnet_get_session_manager_main ();
Florin Coras288eaab2019-02-03 15:26:14 -0800109 session_t *pool;
Dave Barach68b0fb02017-02-28 15:15:56 -0500110
111 *thread_index = handle & 0xFFFFFFFF;
112 *session_index = handle >> 32;
113
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700114 if (*thread_index >= vec_len (smm->wrk))
Dave Barach68b0fb02017-02-28 15:15:56 -0500115 return VNET_API_ERROR_INVALID_VALUE;
116
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700117 pool = smm->wrk[*thread_index].sessions;
Dave Barach68b0fb02017-02-28 15:15:56 -0500118
119 if (pool_is_free_index (pool, *session_index))
120 return VNET_API_ERROR_INVALID_VALUE_2;
121
122 return 0;
123}
124
Florin Corascea194d2017-10-02 00:18:51 -0700125static void
Florin Coras5665ced2018-10-25 18:03:45 -0700126session_endpoint_update_for_app (session_endpoint_cfg_t * sep,
127 application_t * app, u8 is_connect)
Florin Corascea194d2017-10-02 00:18:51 -0700128{
129 app_namespace_t *app_ns;
Florin Coras5665ced2018-10-25 18:03:45 -0700130 u32 ns_index, fib_index;
Florin Corasda3eec12018-09-07 13:29:17 -0700131
132 ns_index = app->ns_index;
133
134 /* App is a transport proto, so fetch the calling app's ns */
135 if (app->flags & APP_OPTIONS_FLAGS_IS_TRANSPORT_APP)
136 {
137 app_worker_t *owner_wrk;
138 application_t *owner_app;
139
140 owner_wrk = app_worker_get (sep->app_wrk_index);
141 owner_app = application_get (owner_wrk->app_index);
142 ns_index = owner_app->ns_index;
143 }
144 app_ns = app_namespace_get (ns_index);
Florin Coras5665ced2018-10-25 18:03:45 -0700145 if (!app_ns)
146 return;
147
148 /* Ask transport and network to bind to/connect using local interface
149 * that "supports" app's namespace. This will fix our local connection
150 * endpoint.
151 */
John Lo4744ddb2018-11-26 22:13:57 -0500152
153 /* If in default namespace and user requested a fib index use it */
154 if (ns_index == 0 && sep->fib_index != ENDPOINT_INVALID_INDEX)
155 fib_index = sep->fib_index;
156 else
157 fib_index = sep->is_ip4 ? app_ns->ip4_fib_index : app_ns->ip6_fib_index;
Florin Coras5665ced2018-10-25 18:03:45 -0700158 sep->peer.fib_index = fib_index;
159 sep->fib_index = fib_index;
160
161 if (!is_connect)
Florin Corascea194d2017-10-02 00:18:51 -0700162 {
Florin Corascea194d2017-10-02 00:18:51 -0700163 sep->sw_if_index = app_ns->sw_if_index;
Florin Coras5665ced2018-10-25 18:03:45 -0700164 }
165 else
166 {
167 if (app_ns->sw_if_index != APP_NAMESPACE_INVALID_INDEX
168 && sep->peer.sw_if_index != ENDPOINT_INVALID_INDEX
169 && sep->peer.sw_if_index != app_ns->sw_if_index)
170 clib_warning ("Local sw_if_index different from app ns sw_if_index");
171
172 sep->peer.sw_if_index = app_ns->sw_if_index;
Florin Corascea194d2017-10-02 00:18:51 -0700173 }
174}
175
Florin Corasab2f6db2018-08-31 14:31:41 -0700176static inline int
Florin Corasc9940fc2019-02-05 20:55:11 -0800177vnet_listen_inline (vnet_listen_args_t * a)
Dave Barach68b0fb02017-02-28 15:15:56 -0500178{
Florin Corasc9940fc2019-02-05 20:55:11 -0800179 app_listener_t *app_listener;
Florin Coras15531972018-08-12 23:50:53 -0700180 app_worker_t *app_wrk;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700181 application_t *app;
Florin Coras5fda7a32018-02-14 08:04:31 -0800182 int rv;
Dave Barach68b0fb02017-02-28 15:15:56 -0500183
Florin Coras15531972018-08-12 23:50:53 -0700184 app = application_get_if_valid (a->app_index);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700185 if (!app)
Florin Corasc9940fc2019-02-05 20:55:11 -0800186 return VNET_API_ERROR_APPLICATION_NOT_ATTACHED;
187
Florin Coras15531972018-08-12 23:50:53 -0700188 app_wrk = application_get_worker (app, a->wrk_map_index);
Florin Corasc9940fc2019-02-05 20:55:11 -0800189 if (!app_wrk)
190 return VNET_API_ERROR_INVALID_VALUE;
191
Florin Corasab2f6db2018-08-31 14:31:41 -0700192 a->sep_ext.app_wrk_index = app_wrk->wrk_index;
Dave Barach68b0fb02017-02-28 15:15:56 -0500193
Florin Coras5665ced2018-10-25 18:03:45 -0700194 session_endpoint_update_for_app (&a->sep_ext, app, 0 /* is_connect */ );
Florin Coras15531972018-08-12 23:50:53 -0700195 if (!session_endpoint_in_ns (&a->sep))
Dave Barach68b0fb02017-02-28 15:15:56 -0500196 return VNET_API_ERROR_INVALID_VALUE_2;
197
Florin Corascea194d2017-10-02 00:18:51 -0700198 /*
Florin Corasc9940fc2019-02-05 20:55:11 -0800199 * Check if we already have an app listener
Florin Corascea194d2017-10-02 00:18:51 -0700200 */
Florin Corasc9940fc2019-02-05 20:55:11 -0800201 app_listener = app_listener_lookup (app, &a->sep_ext);
202 if (app_listener)
Florin Corascea194d2017-10-02 00:18:51 -0700203 {
Florin Corasc9940fc2019-02-05 20:55:11 -0800204 if (app_listener->app_index != app->app_index)
205 return VNET_API_ERROR_ADDRESS_IN_USE;
206 if (app_worker_start_listen (app_wrk, app_listener))
207 return -1;
208 a->handle = app_listener_handle (app_listener);
209 return 0;
Florin Corascea194d2017-10-02 00:18:51 -0700210 }
211
Florin Corascea194d2017-10-02 00:18:51 -0700212 /*
Florin Corasc9940fc2019-02-05 20:55:11 -0800213 * Create new app listener
Florin Corascea194d2017-10-02 00:18:51 -0700214 */
Florin Corasc9940fc2019-02-05 20:55:11 -0800215 if ((rv = app_listener_alloc_and_init (app, &a->sep_ext, &app_listener)))
216 return rv;
Florin Corascea194d2017-10-02 00:18:51 -0700217
Florin Corasc9940fc2019-02-05 20:55:11 -0800218 if ((rv = app_worker_start_listen (app_wrk, app_listener)))
Florin Corasab2f6db2018-08-31 14:31:41 -0700219 {
Florin Corasc9940fc2019-02-05 20:55:11 -0800220 app_listener_cleanup (app_listener);
Florin Corasab2f6db2018-08-31 14:31:41 -0700221 return rv;
222 }
Florin Coras5fda7a32018-02-14 08:04:31 -0800223
Florin Corasc9940fc2019-02-05 20:55:11 -0800224 a->handle = app_listener_handle (app_listener);
225 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500226}
227
Florin Corasab2f6db2018-08-31 14:31:41 -0700228static inline int
Florin Corasc9940fc2019-02-05 20:55:11 -0800229vnet_unlisten_inline (vnet_unbind_args_t * a)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700230{
Florin Corasc9940fc2019-02-05 20:55:11 -0800231 app_worker_t *app_wrk;
232 app_listener_t *al;
Florin Corasf8f516a2018-02-08 15:10:09 -0800233 application_t *app;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700234
Florin Corasab2f6db2018-08-31 14:31:41 -0700235 if (!(app = application_get_if_valid (a->app_index)))
Florin Corasc9940fc2019-02-05 20:55:11 -0800236 return VNET_API_ERROR_APPLICATION_NOT_ATTACHED;
237
238 al = app_listener_get_w_handle (a->handle);
239 if (al->app_index != app->app_index)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700240 {
Florin Corasc9940fc2019-02-05 20:55:11 -0800241 clib_warning ("app doesn't own handle %llu!", a->handle);
242 return -1;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700243 }
244
Florin Corasc9940fc2019-02-05 20:55:11 -0800245 app_wrk = application_get_worker (app, a->wrk_map_index);
246 if (!app_wrk)
Florin Corascea194d2017-10-02 00:18:51 -0700247 {
Florin Corasc9940fc2019-02-05 20:55:11 -0800248 clib_warning ("no app %u worker %u", app->app_index, a->wrk_map_index);
249 return -1;
Florin Corascea194d2017-10-02 00:18:51 -0700250 }
251
Florin Corasc9940fc2019-02-05 20:55:11 -0800252 return app_worker_stop_listen (app_wrk, al);
Florin Corascea194d2017-10-02 00:18:51 -0700253}
254
Florin Coras15531972018-08-12 23:50:53 -0700255static int
256application_connect (vnet_connect_args_t * a)
Dave Barach68b0fb02017-02-28 15:15:56 -0500257{
Florin Coras15531972018-08-12 23:50:53 -0700258 app_worker_t *server_wrk, *client_wrk;
Florin Corasc9940fc2019-02-05 20:55:11 -0800259 application_t *client;
Florin Corasf8f516a2018-02-08 15:10:09 -0800260 local_session_t *ll;
Florin Corasc9940fc2019-02-05 20:55:11 -0800261 app_listener_t *al;
262 u32 table_index;
263 session_t *ls;
Florin Coras15531972018-08-12 23:50:53 -0700264 u8 fib_proto;
Florin Corasf8f516a2018-02-08 15:10:09 -0800265 u64 lh;
Florin Corascea194d2017-10-02 00:18:51 -0700266
Florin Coras15531972018-08-12 23:50:53 -0700267 if (session_endpoint_is_zero (&a->sep))
Florin Corascea194d2017-10-02 00:18:51 -0700268 return VNET_API_ERROR_INVALID_VALUE;
269
Florin Coras15531972018-08-12 23:50:53 -0700270 client = application_get (a->app_index);
Florin Coras5665ced2018-10-25 18:03:45 -0700271 session_endpoint_update_for_app (&a->sep_ext, client, 1 /* is_connect */ );
Florin Coras15531972018-08-12 23:50:53 -0700272 client_wrk = application_get_worker (client, a->wrk_map_index);
Dave Barach68b0fb02017-02-28 15:15:56 -0500273
274 /*
Florin Corasf8f516a2018-02-08 15:10:09 -0800275 * First check the local scope for locally attached destinations.
Florin Corascea194d2017-10-02 00:18:51 -0700276 * If we have local scope, we pass *all* connects through it since we may
277 * have special policy rules even for non-local destinations, think proxy.
Dave Barach68b0fb02017-02-28 15:15:56 -0500278 */
Florin Corasf8f516a2018-02-08 15:10:09 -0800279 if (application_has_local_scope (client))
Dave Barach68b0fb02017-02-28 15:15:56 -0500280 {
Florin Corasf8f516a2018-02-08 15:10:09 -0800281 table_index = application_local_session_table (client);
Florin Coras15531972018-08-12 23:50:53 -0700282 lh = session_lookup_local_endpoint (table_index, &a->sep);
Florin Corasf8f516a2018-02-08 15:10:09 -0800283 if (lh == SESSION_DROP_HANDLE)
Florin Corasa2ff7b82017-11-08 17:55:03 -0800284 return VNET_API_ERROR_APP_CONNECT_FILTERED;
Florin Coras7999e832017-10-31 01:51:04 -0700285
Florin Coras5fda7a32018-02-14 08:04:31 -0800286 if (lh == SESSION_INVALID_HANDLE)
287 goto global_scope;
288
Florin Corasc9940fc2019-02-05 20:55:11 -0800289 ll = application_get_local_listener_w_handle (lh);
290 al = app_listener_get_w_session ((session_t *) ll);
Florin Corasf8f516a2018-02-08 15:10:09 -0800291
Dave Barach68b0fb02017-02-28 15:15:56 -0500292 /*
Florin Coras7999e832017-10-31 01:51:04 -0700293 * Break loop if rule in local table points to connecting app. This
294 * can happen if client is a generic proxy. Route connect through
295 * global table instead.
Dave Barach68b0fb02017-02-28 15:15:56 -0500296 */
Florin Corasc9940fc2019-02-05 20:55:11 -0800297 if (al->app_index == a->app_index)
298 goto global_scope;
299
300 server_wrk = app_listener_select_worker (al);
301 return app_worker_local_session_connect (client_wrk, server_wrk, ll,
302 a->api_context);
Dave Barach68b0fb02017-02-28 15:15:56 -0500303 }
304
Dave Barach68b0fb02017-02-28 15:15:56 -0500305 /*
Florin Corascea194d2017-10-02 00:18:51 -0700306 * If nothing found, check the global scope for locally attached
307 * destinations. Make sure first that we're allowed to.
Dave Barach68b0fb02017-02-28 15:15:56 -0500308 */
Florin Coras5fda7a32018-02-14 08:04:31 -0800309
310global_scope:
Florin Coras15531972018-08-12 23:50:53 -0700311 if (session_endpoint_is_local (&a->sep))
Florin Corascea194d2017-10-02 00:18:51 -0700312 return VNET_API_ERROR_SESSION_CONNECT;
313
Florin Corasf8f516a2018-02-08 15:10:09 -0800314 if (!application_has_global_scope (client))
Florin Corascea194d2017-10-02 00:18:51 -0700315 return VNET_API_ERROR_APP_CONNECT_SCOPE;
316
Florin Coras15531972018-08-12 23:50:53 -0700317 fib_proto = session_endpoint_fib_proto (&a->sep);
318 table_index = application_session_table (client, fib_proto);
Florin Corasc9940fc2019-02-05 20:55:11 -0800319 ls = session_lookup_listener (table_index, &a->sep);
320 if (ls)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700321 {
Florin Corasc9940fc2019-02-05 20:55:11 -0800322 al = app_listener_get_w_session (ls);
323 server_wrk = app_listener_select_worker (al);
324 ll = (local_session_t *) ls;
Florin Coras623eb562019-02-03 19:28:34 -0800325 return app_worker_local_session_connect (client_wrk, server_wrk, ll,
326 a->api_context);
Florin Coras3cbc04b2017-10-02 00:18:51 -0700327 }
Florin Corascea194d2017-10-02 00:18:51 -0700328
329 /*
330 * Not connecting to a local server, propagate to transport
331 */
Florin Corasc9940fc2019-02-05 20:55:11 -0800332 if (app_worker_connect_session (client_wrk, &a->sep, a->api_context))
Florin Corascea194d2017-10-02 00:18:51 -0700333 return VNET_API_ERROR_SESSION_CONNECT;
334 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500335}
336
337/**
338 * unformat a vnet URI
339 *
Florin Coras8f89dd02018-03-05 16:53:07 -0800340 * transport-proto://[hostname]ip46-addr:port
341 * eg. tcp://ip46-addr:port
342 * tls://[testtsl.fd.io]ip46-addr:port
Dave Barach68b0fb02017-02-28 15:15:56 -0500343 *
344 * u8 ip46_address[16];
345 * u16 port_in_host_byte_order;
346 * stream_session_type_t sst;
347 * u8 *fifo_name;
348 *
349 * if (unformat (input, "%U", unformat_vnet_uri, &ip46_address,
350 * &sst, &port, &fifo_name))
351 * etc...
352 *
353 */
354uword
355unformat_vnet_uri (unformat_input_t * input, va_list * args)
356{
Florin Coras5665ced2018-10-25 18:03:45 -0700357 session_endpoint_cfg_t *sep = va_arg (*args, session_endpoint_cfg_t *);
Florin Coras371ca502018-02-21 12:07:41 -0800358 u32 transport_proto = 0, port;
359
Florin Coras8f89dd02018-03-05 16:53:07 -0800360 if (unformat (input, "%U://%U/%d", unformat_transport_proto,
361 &transport_proto, unformat_ip4_address, &sep->ip.ip4, &port))
362 {
363 sep->transport_proto = transport_proto;
364 sep->port = clib_host_to_net_u16 (port);
365 sep->is_ip4 = 1;
366 return 1;
367 }
368 else if (unformat (input, "%U://[%s]%U/%d", unformat_transport_proto,
369 &transport_proto, &sep->hostname, unformat_ip4_address,
370 &sep->ip.ip4, &port))
Dave Barach68b0fb02017-02-28 15:15:56 -0500371 {
Florin Coras4399c2e2018-01-25 06:34:42 -0800372 sep->transport_proto = transport_proto;
Florin Coras371ca502018-02-21 12:07:41 -0800373 sep->port = clib_host_to_net_u16 (port);
Florin Corascea194d2017-10-02 00:18:51 -0700374 sep->is_ip4 = 1;
Dave Barach68b0fb02017-02-28 15:15:56 -0500375 return 1;
376 }
Florin Coras371ca502018-02-21 12:07:41 -0800377 else if (unformat (input, "%U://%U/%d", unformat_transport_proto,
378 &transport_proto, unformat_ip6_address, &sep->ip.ip6,
379 &port))
Dave Barach68b0fb02017-02-28 15:15:56 -0500380 {
Florin Coras4399c2e2018-01-25 06:34:42 -0800381 sep->transport_proto = transport_proto;
Florin Coras371ca502018-02-21 12:07:41 -0800382 sep->port = clib_host_to_net_u16 (port);
Marco Varlese191a5942017-10-30 18:17:21 +0100383 sep->is_ip4 = 0;
384 return 1;
385 }
Florin Coras8f89dd02018-03-05 16:53:07 -0800386 else if (unformat (input, "%U://[%s]%U/%d", unformat_transport_proto,
387 &transport_proto, &sep->hostname, unformat_ip6_address,
388 &sep->ip.ip6, &port))
389 {
390 sep->transport_proto = transport_proto;
391 sep->port = clib_host_to_net_u16 (port);
392 sep->is_ip4 = 0;
393 return 1;
394 }
Dave Barach68b0fb02017-02-28 15:15:56 -0500395 return 0;
396}
397
Dave Barachb7f1faa2017-08-29 11:43:37 -0400398static u8 *cache_uri;
Florin Coras5665ced2018-10-25 18:03:45 -0700399static session_endpoint_cfg_t *cache_sep;
Dave Barachb7f1faa2017-08-29 11:43:37 -0400400
Dave Barach68b0fb02017-02-28 15:15:56 -0500401int
Florin Coras5665ced2018-10-25 18:03:45 -0700402parse_uri (char *uri, session_endpoint_cfg_t * sep)
Dave Barach68b0fb02017-02-28 15:15:56 -0500403{
404 unformat_input_t _input, *input = &_input;
405
Dave Barachb7f1faa2017-08-29 11:43:37 -0400406 if (cache_uri && !strncmp (uri, (char *) cache_uri, vec_len (cache_uri)))
407 {
Florin Corascea194d2017-10-02 00:18:51 -0700408 *sep = *cache_sep;
Dave Barachb7f1faa2017-08-29 11:43:37 -0400409 return 0;
410 }
411
Dave Barach68b0fb02017-02-28 15:15:56 -0500412 /* Make sure */
413 uri = (char *) format (0, "%s%c", uri, 0);
414
415 /* Parse uri */
416 unformat_init_string (input, uri, strlen (uri));
Florin Corascea194d2017-10-02 00:18:51 -0700417 if (!unformat (input, "%U", unformat_vnet_uri, sep))
Dave Barach68b0fb02017-02-28 15:15:56 -0500418 {
419 unformat_free (input);
420 return VNET_API_ERROR_INVALID_VALUE;
421 }
422 unformat_free (input);
423
Dave Barachb7f1faa2017-08-29 11:43:37 -0400424 vec_free (cache_uri);
425 cache_uri = (u8 *) uri;
Florin Corascea194d2017-10-02 00:18:51 -0700426 if (cache_sep)
427 clib_mem_free (cache_sep);
428 cache_sep = clib_mem_alloc (sizeof (*sep));
429 *cache_sep = *sep;
Dave Barachb7f1faa2017-08-29 11:43:37 -0400430
Dave Barach68b0fb02017-02-28 15:15:56 -0500431 return 0;
432}
433
Florin Corascea194d2017-10-02 00:18:51 -0700434static int
Florin Coras15531972018-08-12 23:50:53 -0700435app_validate_namespace (u8 * namespace_id, u64 secret, u32 * app_ns_index)
Florin Corascea194d2017-10-02 00:18:51 -0700436{
437 app_namespace_t *app_ns;
438 if (vec_len (namespace_id) == 0)
439 {
440 /* Use default namespace */
441 *app_ns_index = 0;
442 return 0;
443 }
444
445 *app_ns_index = app_namespace_index_from_id (namespace_id);
446 if (*app_ns_index == APP_NAMESPACE_INVALID_INDEX)
447 return VNET_API_ERROR_APP_INVALID_NS;
448 app_ns = app_namespace_get (*app_ns_index);
449 if (!app_ns)
450 return VNET_API_ERROR_APP_INVALID_NS;
451 if (app_ns->ns_secret != secret)
452 return VNET_API_ERROR_APP_WRONG_NS_SECRET;
453 return 0;
454}
455
Florin Coras3b4c64e2018-11-21 08:53:17 -0800456static u8 *
457app_name_from_api_index (u32 api_client_index)
458{
459 vl_api_registration_t *regp;
460 regp = vl_api_client_index_to_registration (api_client_index);
461 if (regp)
462 return format (0, "%s%c", regp->name, 0);
463
464 clib_warning ("api client index %u does not have an api registration!",
465 api_client_index);
466 return format (0, "unknown%c", 0);
467}
468
Florin Coras6cf30ad2017-04-04 23:08:23 -0700469/**
Florin Corascea194d2017-10-02 00:18:51 -0700470 * Attach application to vpp
Florin Coras6cf30ad2017-04-04 23:08:23 -0700471 *
472 * Allocates a vpp app, i.e., a structure that keeps back pointers
473 * to external app and a segment manager for shared memory fifo based
474 * communication with the external app.
475 */
Florin Corascea194d2017-10-02 00:18:51 -0700476clib_error_t *
Florin Coras6cf30ad2017-04-04 23:08:23 -0700477vnet_application_attach (vnet_app_attach_args_t * a)
Dave Barach68b0fb02017-02-28 15:15:56 -0500478{
Florin Corasb384b542018-01-15 01:08:33 -0800479 svm_fifo_segment_private_t *fs;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700480 application_t *app = 0;
Florin Coras15531972018-08-12 23:50:53 -0700481 app_worker_t *app_wrk;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700482 segment_manager_t *sm;
Florin Corascea194d2017-10-02 00:18:51 -0700483 u32 app_ns_index = 0;
Florin Corasc1f5a432018-11-20 11:31:26 -0800484 u8 *app_name = 0;
Florin Corasb384b542018-01-15 01:08:33 -0800485 u64 secret;
Dave Barach68b0fb02017-02-28 15:15:56 -0500486 int rv;
487
Florin Coras0bee9ce2018-03-22 21:24:31 -0700488 if (a->api_client_index != APP_INVALID_INDEX)
Florin Coras3b4c64e2018-11-21 08:53:17 -0800489 app = application_lookup (a->api_client_index);
Florin Coras0bee9ce2018-03-22 21:24:31 -0700490 else if (a->name)
491 app = application_lookup_name (a->name);
492 else
493 return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
494 "api index or name must be provided");
495
Florin Corascea194d2017-10-02 00:18:51 -0700496 if (app)
Florin Coras0bee9ce2018-03-22 21:24:31 -0700497 return clib_error_return_code (0, VNET_API_ERROR_APP_ALREADY_ATTACHED, 0,
498 "app already attached");
Florin Corascea194d2017-10-02 00:18:51 -0700499
Florin Coras3b4c64e2018-11-21 08:53:17 -0800500 if (a->api_client_index != APP_INVALID_INDEX)
501 {
502 app_name = app_name_from_api_index (a->api_client_index);
503 a->name = app_name;
504 }
505
Florin Corascea194d2017-10-02 00:18:51 -0700506 secret = a->options[APP_OPTIONS_NAMESPACE_SECRET];
Florin Coras15531972018-08-12 23:50:53 -0700507 if ((rv = app_validate_namespace (a->namespace_id, secret, &app_ns_index)))
Florin Corascea194d2017-10-02 00:18:51 -0700508 return clib_error_return_code (0, rv, 0, "namespace validation: %d", rv);
509 a->options[APP_OPTIONS_NAMESPACE] = app_ns_index;
Florin Coras15531972018-08-12 23:50:53 -0700510
511 if ((rv = application_alloc_and_init ((app_init_args_t *) a)))
Florin Corascea194d2017-10-02 00:18:51 -0700512 return clib_error_return_code (0, rv, 0, "app init: %d", rv);
Dave Barach68b0fb02017-02-28 15:15:56 -0500513
Florin Coras15531972018-08-12 23:50:53 -0700514 app = application_get (a->app_index);
Florin Coras623eb562019-02-03 19:28:34 -0800515 if ((rv = application_alloc_worker_and_init (app, &app_wrk)))
Florin Coras15531972018-08-12 23:50:53 -0700516 return clib_error_return_code (0, rv, 0, "app default wrk init: %d", rv);
517
518 a->app_evt_q = app_wrk->event_queue;
Florin Corasc1f5a432018-11-20 11:31:26 -0800519 app_wrk->api_client_index = a->api_client_index;
Florin Coras15531972018-08-12 23:50:53 -0700520 sm = segment_manager_get (app_wrk->first_segment_manager);
Florin Corasa332c462018-01-31 06:52:17 -0800521 fs = segment_manager_get_segment_w_lock (sm, 0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500522
Florin Coras7999e832017-10-31 01:51:04 -0700523 if (application_is_proxy (app))
524 application_setup_proxy (app);
525
Florin Corasb384b542018-01-15 01:08:33 -0800526 ASSERT (vec_len (fs->ssvm.name) <= 128);
527 a->segment = &fs->ssvm;
Florin Corasd85de682018-11-29 17:02:29 -0800528 a->segment_handle = segment_manager_segment_handle (sm, fs);
Florin Corasb384b542018-01-15 01:08:33 -0800529
Florin Corasa332c462018-01-31 06:52:17 -0800530 segment_manager_segment_reader_unlock (sm);
Florin Corasc1f5a432018-11-20 11:31:26 -0800531 vec_free (app_name);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700532 return 0;
533}
534
Florin Corascea194d2017-10-02 00:18:51 -0700535/**
536 * Detach application from vpp
537 */
Florin Coras6cf30ad2017-04-04 23:08:23 -0700538int
539vnet_application_detach (vnet_app_detach_args_t * a)
540{
541 application_t *app;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700542
Florin Coras4829bab2018-09-14 13:17:41 -0700543 app = application_get_if_valid (a->app_index);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700544 if (!app)
545 {
546 clib_warning ("app not attached");
547 return VNET_API_ERROR_APPLICATION_NOT_ATTACHED;
548 }
549
Florin Coras4829bab2018-09-14 13:17:41 -0700550 app_interface_check_thread_and_barrier (vnet_application_detach, a);
Florin Coras053a0e42018-11-13 15:52:38 -0800551 application_detach_process (app, a->api_client_index);
Dave Barach68b0fb02017-02-28 15:15:56 -0500552 return 0;
553}
554
Dave Barach68b0fb02017-02-28 15:15:56 -0500555int
Florin Corasc9940fc2019-02-05 20:55:11 -0800556vnet_bind_uri (vnet_listen_args_t * a)
Dave Barach68b0fb02017-02-28 15:15:56 -0500557{
Florin Coras5665ced2018-10-25 18:03:45 -0700558 session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
Dave Barach68b0fb02017-02-28 15:15:56 -0500559 int rv;
560
Florin Corascea194d2017-10-02 00:18:51 -0700561 rv = parse_uri (a->uri, &sep);
Dave Barach68b0fb02017-02-28 15:15:56 -0500562 if (rv)
563 return rv;
Florin Coras41c9e042018-09-11 00:10:41 -0700564 sep.app_wrk_index = 0;
Florin Corasc3638fe2018-08-24 13:58:49 -0700565 clib_memcpy (&a->sep_ext, &sep, sizeof (sep));
Florin Corasc9940fc2019-02-05 20:55:11 -0800566 return vnet_listen_inline (a);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700567}
568
569int
570vnet_unbind_uri (vnet_unbind_args_t * a)
571{
Florin Coras5665ced2018-10-25 18:03:45 -0700572 session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
Florin Coras288eaab2019-02-03 15:26:14 -0800573 session_t *listener;
Florin Coras36ec1f52018-05-29 21:15:38 -0700574 u32 table_index;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700575 int rv;
576
Florin Corascea194d2017-10-02 00:18:51 -0700577 rv = parse_uri (a->uri, &sep);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700578 if (rv)
579 return rv;
580
Florin Coras36ec1f52018-05-29 21:15:38 -0700581 /* NOTE: only default fib tables supported for uri apis */
582 table_index = session_lookup_get_index_for_fib (fib_ip_proto (!sep.is_ip4),
583 0);
584 listener = session_lookup_listener (table_index,
585 (session_endpoint_t *) & sep);
Dave Barach68b0fb02017-02-28 15:15:56 -0500586 if (!listener)
587 return VNET_API_ERROR_ADDRESS_NOT_IN_USE;
Florin Corasab2f6db2018-08-31 14:31:41 -0700588 a->handle = listen_session_get_handle (listener);
Florin Corasc9940fc2019-02-05 20:55:11 -0800589 return vnet_unlisten_inline (a);
Dave Barach68b0fb02017-02-28 15:15:56 -0500590}
591
Florin Corascea194d2017-10-02 00:18:51 -0700592clib_error_t *
Dave Barach68b0fb02017-02-28 15:15:56 -0500593vnet_connect_uri (vnet_connect_args_t * a)
594{
Florin Coras5665ced2018-10-25 18:03:45 -0700595 session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
Dave Barach68b0fb02017-02-28 15:15:56 -0500596 int rv;
597
Dave Barach68b0fb02017-02-28 15:15:56 -0500598 /* Parse uri */
Florin Coras371ca502018-02-21 12:07:41 -0800599 rv = parse_uri (a->uri, &sep);
Dave Barach68b0fb02017-02-28 15:15:56 -0500600 if (rv)
Florin Corascea194d2017-10-02 00:18:51 -0700601 return clib_error_return_code (0, rv, 0, "app init: %d", rv);
Florin Coras371ca502018-02-21 12:07:41 -0800602
Florin Corasc3638fe2018-08-24 13:58:49 -0700603 clib_memcpy (&a->sep_ext, &sep, sizeof (sep));
Florin Coras15531972018-08-12 23:50:53 -0700604 if ((rv = application_connect (a)))
Florin Corascea194d2017-10-02 00:18:51 -0700605 return clib_error_return_code (0, rv, 0, "connect failed");
606 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500607}
608
609int
Florin Coras6cf30ad2017-04-04 23:08:23 -0700610vnet_disconnect_session (vnet_disconnect_args_t * a)
Dave Barach68b0fb02017-02-28 15:15:56 -0500611{
Florin Corasf8f516a2018-02-08 15:10:09 -0800612 if (session_handle_is_local (a->handle))
613 {
614 local_session_t *ls;
Florin Coras99368312018-08-02 10:45:44 -0700615
616 /* Disconnect reply came to worker 1 not main thread */
Florin Coras4829bab2018-09-14 13:17:41 -0700617 app_interface_check_thread_and_barrier (vnet_disconnect_session, a);
Florin Coras99368312018-08-02 10:45:44 -0700618
Florin Coras623eb562019-02-03 19:28:34 -0800619 if (!(ls = app_worker_get_local_session_from_handle (a->handle)))
Florin Coras99368312018-08-02 10:45:44 -0700620 return 0;
621
Florin Coras623eb562019-02-03 19:28:34 -0800622 return app_worker_local_session_disconnect (a->app_index, ls);
Florin Corasf8f516a2018-02-08 15:10:09 -0800623 }
624 else
625 {
Florin Coras21795132018-09-09 09:40:51 -0700626 app_worker_t *app_wrk;
Florin Coras288eaab2019-02-03 15:26:14 -0800627 session_t *s;
Florin Coras21795132018-09-09 09:40:51 -0700628
Florin Corasf8f516a2018-02-08 15:10:09 -0800629 s = session_get_from_handle_if_valid (a->handle);
Florin Coras21795132018-09-09 09:40:51 -0700630 if (!s)
631 return VNET_API_ERROR_INVALID_VALUE;
632 app_wrk = app_worker_get (s->app_wrk_index);
633 if (app_wrk->app_index != a->app_index)
Florin Corasf8f516a2018-02-08 15:10:09 -0800634 return VNET_API_ERROR_INVALID_VALUE;
Dave Barach68b0fb02017-02-28 15:15:56 -0500635
Florin Corasf8f516a2018-02-08 15:10:09 -0800636 /* We're peeking into another's thread pool. Make sure */
637 ASSERT (s->session_index == session_index_from_handle (a->handle));
Dave Barach68b0fb02017-02-28 15:15:56 -0500638
Florin Coras5a2ec8f2018-12-27 11:53:11 -0800639 session_close (s);
Florin Corasf8f516a2018-02-08 15:10:09 -0800640 }
Dave Barach68b0fb02017-02-28 15:15:56 -0500641 return 0;
642}
643
Florin Corascea194d2017-10-02 00:18:51 -0700644clib_error_t *
Florin Corasc9940fc2019-02-05 20:55:11 -0800645vnet_listen (vnet_listen_args_t * a)
Dave Barach68b0fb02017-02-28 15:15:56 -0500646{
Dave Barach68b0fb02017-02-28 15:15:56 -0500647 int rv;
Florin Corasc9940fc2019-02-05 20:55:11 -0800648 if ((rv = vnet_listen_inline (a)))
Florin Coras54693d22018-07-17 10:46:29 -0700649 return clib_error_return_code (0, rv, 0, "bind failed: %d", rv);
Dave Barach68b0fb02017-02-28 15:15:56 -0500650 return 0;
651}
652
Florin Corascea194d2017-10-02 00:18:51 -0700653clib_error_t *
Florin Corasc9940fc2019-02-05 20:55:11 -0800654vnet_unlisten (vnet_unbind_args_t * a)
Dave Barach68b0fb02017-02-28 15:15:56 -0500655{
Florin Corascea194d2017-10-02 00:18:51 -0700656 int rv;
Florin Corasc9940fc2019-02-05 20:55:11 -0800657 if ((rv = vnet_unlisten_inline (a)))
Florin Coras54693d22018-07-17 10:46:29 -0700658 return clib_error_return_code (0, rv, 0, "unbind failed: %d", rv);
Florin Corascea194d2017-10-02 00:18:51 -0700659 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500660}
661
Florin Corascea194d2017-10-02 00:18:51 -0700662clib_error_t *
Dave Barach68b0fb02017-02-28 15:15:56 -0500663vnet_connect (vnet_connect_args_t * a)
664{
Florin Corascea194d2017-10-02 00:18:51 -0700665 int rv;
Florin Coras371ca502018-02-21 12:07:41 -0800666
Florin Coras15531972018-08-12 23:50:53 -0700667 if ((rv = application_connect (a)))
Florin Coras54693d22018-07-17 10:46:29 -0700668 return clib_error_return_code (0, rv, 0, "connect failed: %d", rv);
Florin Corascea194d2017-10-02 00:18:51 -0700669 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500670}
671
Dave Barach68b0fb02017-02-28 15:15:56 -0500672/*
673 * fd.io coding-style-patch-verification: ON
674 *
675 * Local Variables:
676 * eval: (c-set-style "gnu")
677 * End:
678 */