api: add helper macros for native endian
[vpp.git] / src / plugins / nat / pnat / pnat_api.c
1 /*
2  * Copyright (c) 2021 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 #include "pnat.h"
16 #include <pnat/pnat.api_enum.h>
17 #include <pnat/pnat.api_types.h>
18 #include <vlibmemory/api.h>
19 #include <vnet/fib/fib_table.h>
20 #include <vnet/ip/ip.h>
21 #include <vnet/ip/ip_types_api.h>
22 #include <vnet/ip/reass/ip4_sv_reass.h>
23 #include <vnet/ip/reass/ip6_full_reass.h>
24 #include <vnet/ip/reass/ip6_sv_reass.h>
25 #include <vpp/app/version.h>
26
27 /*
28  * This file contains the API handlers for the pnat.api
29  */
30
31 #define REPLY_MSG_ID_BASE pm->msg_id_base
32 #include <vlibapi/api_helper_macros.h>
33
34 static void vl_api_pnat_binding_add_t_handler(vl_api_pnat_binding_add_t *mp) {
35     pnat_main_t *pm = &pnat_main;
36     vl_api_pnat_binding_add_reply_t *rmp;
37     u32 binding_index;
38     int rv = pnat_binding_add(&mp->match, &mp->rewrite, &binding_index);
39     REPLY_MACRO2_END(VL_API_PNAT_BINDING_ADD_REPLY,
40                      ({ rmp->binding_index = binding_index; }));
41 }
42
43 static void
44 vl_api_pnat_binding_attach_t_handler(vl_api_pnat_binding_attach_t *mp) {
45     pnat_main_t *pm = &pnat_main;
46     vl_api_pnat_binding_attach_reply_t *rmp;
47     int rv;
48
49     VALIDATE_SW_IF_INDEX_END(mp);
50
51     rv =
52         pnat_binding_attach(mp->sw_if_index, mp->attachment, mp->binding_index);
53
54 bad_sw_if_index:
55     REPLY_MACRO_END(VL_API_PNAT_BINDING_ATTACH_REPLY);
56 }
57
58 static void
59 vl_api_pnat_binding_detach_t_handler(vl_api_pnat_binding_detach_t *mp) {
60     pnat_main_t *pm = &pnat_main;
61     vl_api_pnat_binding_detach_reply_t *rmp;
62     int rv;
63
64     VALIDATE_SW_IF_INDEX_END(mp);
65
66     rv =
67         pnat_binding_detach(mp->sw_if_index, mp->attachment, mp->binding_index);
68
69 bad_sw_if_index:
70     REPLY_MACRO_END(VL_API_PNAT_BINDING_DETACH_REPLY);
71 }
72
73 static void vl_api_pnat_binding_del_t_handler(vl_api_pnat_binding_del_t *mp) {
74     pnat_main_t *pm = &pnat_main;
75     vl_api_pnat_binding_del_reply_t *rmp;
76     int rv = pnat_binding_del(mp->binding_index);
77     REPLY_MACRO_END(VL_API_PNAT_BINDING_DEL_REPLY);
78 }
79
80 /*
81  * Workaround for a bug in vppapigen that doesn't register the endian handler
82  * for _details messages. When that's fixed it should be possible to use
83  * REPLY_MACRO_DETAILS4_END and not have to care about endian-ness in the
84  * handler itself.
85  */
86 #define vl_endianfun
87 #include <pnat/pnat.api.h>
88 #undef vl_endianfun
89 static void send_bindings_details(u32 index, vl_api_registration_t *rp,
90                                   u32 context) {
91     pnat_main_t *pm = &pnat_main;
92     vl_api_pnat_bindings_details_t *rmp;
93     pnat_translation_t *t = pool_elt_at_index(pm->translations, index);
94
95     /* Make sure every field is initiated (or don't skip the clib_memset()) */
96
97     REPLY_MACRO_DETAILS4(VL_API_PNAT_BINDINGS_DETAILS, rp, context, ({
98                              rmp->match = t->match;
99                              rmp->rewrite = t->rewrite;
100
101                              /* Endian hack until apigen registers _details
102                               * endian functions */
103                              vl_api_pnat_bindings_details_t_endian(rmp);
104                              rmp->_vl_msg_id = htons(rmp->_vl_msg_id);
105                              rmp->context = htonl(rmp->context);
106                          }));
107 }
108
109 static void vl_api_pnat_bindings_get_t_handler(vl_api_pnat_bindings_get_t *mp) {
110     pnat_main_t *pm = &pnat_main;
111     vl_api_pnat_bindings_get_reply_t *rmp;
112
113     i32 rv = 0;
114
115     if (pool_elts(pm->translations) == 0) {
116         REPLY_MACRO(VL_API_PNAT_BINDINGS_GET_REPLY);
117         return;
118     }
119
120     /*
121      * "cursor" comes from the get call, and allows client to continue a dump
122      */
123     REPLY_AND_DETAILS_MACRO(VL_API_PNAT_BINDINGS_GET_REPLY, pm->translations, ({
124                                 send_bindings_details(cursor, rp, mp->context);
125                             }));
126 }
127
128 static void send_interfaces_details(u32 index, vl_api_registration_t *rp,
129                                     u32 context) {
130     pnat_main_t *pm = &pnat_main;
131     vl_api_pnat_interfaces_details_t *rmp;
132     pnat_interface_t *i = pool_elt_at_index(pm->interfaces, index);
133
134     /* Make sure every field is initiated (or don't skip the clib_memset()) */
135
136     REPLY_MACRO_DETAILS4(
137         VL_API_PNAT_INTERFACES_DETAILS, rp, context, ({
138             rmp->sw_if_index = i->sw_if_index;
139             clib_memcpy(rmp->enabled, i->enabled, sizeof(rmp->enabled));
140             clib_memcpy(rmp->lookup_mask, i->lookup_mask,
141                         sizeof(rmp->lookup_mask));
142
143             /* Endian hack until apigen registers _details
144              * endian functions */
145             vl_api_pnat_interfaces_details_t_endian(rmp);
146             rmp->_vl_msg_id = htons(rmp->_vl_msg_id);
147             rmp->context = htonl(rmp->context);
148         }));
149 }
150
151 static void
152 vl_api_pnat_interfaces_get_t_handler(vl_api_pnat_interfaces_get_t *mp) {
153     pnat_main_t *pm = &pnat_main;
154     vl_api_pnat_interfaces_get_reply_t *rmp;
155
156     i32 rv = 0;
157
158     if (pool_elts(pm->interfaces) == 0) {
159         REPLY_MACRO(VL_API_PNAT_INTERFACES_GET_REPLY);
160         return;
161     }
162
163     /*
164      * "cursor" comes from the get call, and allows client to continue a dump
165      */
166     REPLY_AND_DETAILS_MACRO(
167         VL_API_PNAT_INTERFACES_GET_REPLY, pm->interfaces,
168         ({ send_interfaces_details(cursor, rp, mp->context); }));
169 }
170
171 /* API definitions */
172 #include <vnet/format_fns.h>
173 #include <pnat/pnat.api.c>
174
175 /* Set up the API message handling tables */
176 clib_error_t *pnat_plugin_api_hookup(vlib_main_t *vm) {
177     pnat_main_t *pm = &pnat_main;
178
179     pm->msg_id_base = setup_message_id_table();
180
181     return 0;
182 }
183
184 /*
185  * Register the plugin and hook up the API
186  */
187 #include <vnet/plugin/plugin.h>
188 VLIB_PLUGIN_REGISTER() = {
189     .version = VPP_BUILD_VER,
190     .description = "Policy 1:1 NAT",
191 };
192
193 clib_error_t *pnat_init(vlib_main_t *vm) {
194     pnat_main_t *pm = &pnat_main;
195     memset(pm, 0, sizeof(*pm));
196
197     return pnat_plugin_api_hookup(vm);
198 }
199
200 VLIB_INIT_FUNCTION(pnat_init);