02ea29b64438aa090def8fd205027f0e6b7dbbc6
[vpp.git] / src / plugins / stn / stn_api.c
1 /*
2  * Copyright (c) 2017 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 #include <vlibapi/api.h>
17 #include <vlibmemory/api.h>
18
19 #include <plugins/stn/stn.h>
20 #include <vnet/ip/format.h>
21
22 #include <vppinfra/byte_order.h>
23
24 /* define message IDs */
25 #define vl_msg_id(n,h) n,
26 typedef enum
27 {
28 #include <stn/stn.api.h>
29   /* We'll want to know how many messages IDs we need... */
30   VL_MSG_FIRST_AVAILABLE,
31 } vl_msg_id_t;
32 #undef vl_msg_id
33
34 /* define message structures */
35 #define vl_typedefs
36 #include <stn/stn.api.h>
37 #undef vl_typedefs
38
39 /* define generated endian-swappers */
40 #define vl_endianfun
41 #include <stn/stn.api.h>
42 #undef vl_endianfun
43
44 /* instantiate all the print functions we know about */
45 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
46 #define vl_printfun
47 #include <stn/stn.api.h>
48 #undef vl_printfun
49
50 /* Get the API version number */
51 #define vl_api_version(n,v) static u32 api_version=(v);
52 #include <nat/nat_all_api_h.h>
53 #undef vl_api_version
54
55 #define REPLY_MSG_ID_BASE stn_main.msg_id_base
56 #include <vlibapi/api_helper_macros.h>
57
58 /* Macro to finish up custom dump fns */
59 #define FINISH                                  \
60     vec_add1 (s, 0);                            \
61     vl_print (handle, (char *)s);               \
62     vec_free (s);                               \
63     return handle;
64
65 /**
66  * @brief API message custom-dump function
67  * @param mp vl_api_stn_add_del_rule_t * mp the api message
68  * @param handle void * print function handle
69  * @returns u8 * output string
70  */
71 static void *vl_api_stn_add_del_rule_t_print
72   (vl_api_stn_add_del_rule_t * mp, void *handle)
73 {
74   u8 *s;
75
76   s = format (0, "SCRIPT: stn_add_del_rule ");
77   if (mp->is_ip4)
78     s = format (s, "address %U ", format_ip4_address, mp->ip_address);
79   else
80     s = format (s, "address %U ", format_ip6_address, mp->ip_address);
81   s = format (s, "sw_if_index %d is_add %d", mp->sw_if_index, mp->is_add);
82
83   FINISH;
84 }
85
86 static void
87 vl_api_stn_add_del_rule_t_handler (vl_api_stn_add_del_rule_t * mp)
88 {
89   stn_rule_add_del_args_t args;
90   vl_api_stn_add_del_rule_reply_t *rmp;
91   int rv = 0;
92
93   if (mp->is_ip4)
94     {
95       ip4_address_t a;
96       memcpy(&a, mp->ip_address, sizeof(a));
97       ip46_address_set_ip4(&args.address, &a);
98     }
99   else
100     memcpy(&args.address.ip6, mp->ip_address, sizeof(ip6_address_t));
101
102   args.sw_if_index = clib_net_to_host_u32(mp->sw_if_index);
103   args.del = !mp->is_add;
104
105   rv = stn_rule_add_del(&args);
106
107   REPLY_MACRO (VL_API_STN_ADD_DEL_RULE_REPLY);
108 }
109
110 static void
111 send_stn_rule (stn_rule_t *r, unix_shared_memory_queue_t *q, u32 context)
112 {
113   vl_api_stn_rule_details_t *rmp;
114
115   rmp =
116       vl_msg_api_alloc (sizeof (*rmp));
117   memset (rmp, 0, sizeof (*rmp));
118   rmp->_vl_msg_id =
119       clib_host_to_net_u32 (VL_API_STN_RULES_DUMP + stn_main.msg_id_base);
120
121   if (ip46_address_is_ip4(&r->address))
122     {
123       clib_memcpy(rmp->ip_address, &r->address.ip4, sizeof(ip4_address_t));
124       rmp->is_ip4 = 1;
125     }
126   else
127     {
128       clib_memcpy(rmp->ip_address, &r->address.ip6, sizeof(ip6_address_t));
129     }
130
131   rmp->context = context;
132   rmp->sw_if_index = clib_host_to_net_u32(r->sw_if_index);
133
134   vl_msg_api_send_shmem (q, (u8 *) & rmp);
135 }
136
137 static void
138 vl_api_stn_rules_dump_t_handler (vl_api_stn_rules_dump_t *mp)
139 {
140   unix_shared_memory_queue_t *q;
141   stn_main_t *stn = &stn_main;
142   stn_rule_t *r;
143
144   q = vl_api_client_index_to_input_queue (mp->client_index);
145   if (q == 0)
146     return;
147
148   /* *INDENT-OFF* */
149   pool_foreach (r, stn->rules,
150                 ({
151
152     send_stn_rule (r, q, mp->context);
153   }));
154   /* *INDENT-ON* */
155 }
156
157
158 /* List of message types that this plugin understands */
159 #define foreach_stn_plugin_api_msg                      \
160 _(STN_ADD_DEL_RULE, stn_add_del_rule)   \
161 _(STN_RULES_DUMP, stn_rules_dump)
162
163 /**
164  * @brief Set up the API message handling tables
165  * @param vm vlib_main_t * vlib main data structure pointer
166  * @returns 0 to indicate all is well
167  */
168 static clib_error_t *
169 stn_plugin_api_hookup (vlib_main_t * vm)
170 {
171   stn_main_t *stn = &stn_main;
172 #define _(N,n)                                                  \
173     vl_msg_api_set_handlers((VL_API_##N + stn->msg_id_base),     \
174                            #n,                                  \
175                            vl_api_##n##_t_handler,              \
176                            vl_noop_handler,                     \
177                            vl_api_##n##_t_endian,               \
178                            vl_api_##n##_t_print,                \
179                            sizeof(vl_api_##n##_t), 1);
180   foreach_stn_plugin_api_msg;
181 #undef _
182
183   return 0;
184 }
185
186 #define vl_msg_name_crc_list
187 #include <stn/stn.api.h>
188 #undef vl_msg_name_crc_list
189
190 static void
191 setup_message_id_table (stn_main_t * stn, api_main_t * am)
192 {
193 #define _(id,n,crc) \
194   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + stn->msg_id_base);
195   foreach_vl_msg_name_crc_stn;
196 #undef _
197 }
198
199 static void
200 plugin_custom_dump_configure (stn_main_t * stn)
201 {
202 #define _(n,f) api_main.msg_print_handlers \
203   [VL_API_##n + stn->msg_id_base]                \
204     = (void *) vl_api_##f##_t_print;
205   foreach_stn_plugin_api_msg;
206 #undef _
207 }
208
209 clib_error_t *
210 stn_api_init (vlib_main_t * vm, stn_main_t * sm)
211 {
212   u8 *name;
213   clib_error_t *error = 0;
214
215   name = format (0, "stn_%08x%c", api_version, 0);
216
217   /* Ask for a correctly-sized block of API message decode slots */
218   sm->msg_id_base =
219     vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
220
221   error = stn_plugin_api_hookup (vm);
222
223   /* Add our API messages to the global name_crc hash table */
224   setup_message_id_table (sm, &api_main);
225
226   plugin_custom_dump_configure (sm);
227
228   vec_free (name);
229
230   return error;
231 }