blob: 10dafd2d63bb98db151f21bd19cf657cb4e9041c [file] [log] [blame]
Marco Varleseb598f1d2017-09-19 14:25:28 +02001/*
2 * Copyright (c) 2017 SUSE LLC.
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
17#include <vnet/vnet.h>
18#include <vlibmemory/api.h>
19
20#include <vnet/interface.h>
21#include <vnet/api_errno.h>
22#include <vnet/feature/feature.h>
23#include <vnet/geneve/geneve.h>
24#include <vnet/fib/fib_table.h>
Jakub Grajciar2d3282e2019-10-01 12:04:56 +020025#include <vnet/ip/ip_types_api.h>
Marco Varleseb598f1d2017-09-19 14:25:28 +020026
27#include <vnet/vnet_msg_enum.h>
28
29#define vl_typedefs /* define message structures */
30#include <vnet/vnet_all_api_h.h>
31#undef vl_typedefs
32
33#define vl_endianfun /* define message structures */
34#include <vnet/vnet_all_api_h.h>
35#undef vl_endianfun
36
37/* instantiate all the print functions we know about */
38#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
39#define vl_printfun
40#include <vnet/vnet_all_api_h.h>
41#undef vl_printfun
42
43#include <vlibapi/api_helper_macros.h>
44
45#define foreach_vpe_api_msg \
46_(SW_INTERFACE_SET_GENEVE_BYPASS, sw_interface_set_geneve_bypass) \
47_(GENEVE_ADD_DEL_TUNNEL, geneve_add_del_tunnel) \
Ole Troan7fc88cf2020-06-17 22:57:13 +020048_(GENEVE_ADD_DEL_TUNNEL2, geneve_add_del_tunnel2) \
Marco Varleseb598f1d2017-09-19 14:25:28 +020049_(GENEVE_TUNNEL_DUMP, geneve_tunnel_dump)
50
51static void
52 vl_api_sw_interface_set_geneve_bypass_t_handler
53 (vl_api_sw_interface_set_geneve_bypass_t * mp)
54{
55 vl_api_sw_interface_set_geneve_bypass_reply_t *rmp;
56 int rv = 0;
57 u32 sw_if_index = ntohl (mp->sw_if_index);
58
59 VALIDATE_SW_IF_INDEX (mp);
60
61 vnet_int_geneve_bypass_mode (sw_if_index, mp->is_ipv6, mp->enable);
62 BAD_SW_IF_INDEX_LABEL;
63
64 REPLY_MACRO (VL_API_SW_INTERFACE_SET_GENEVE_BYPASS_REPLY);
65}
66
67static void vl_api_geneve_add_del_tunnel_t_handler
68 (vl_api_geneve_add_del_tunnel_t * mp)
69{
70 vl_api_geneve_add_del_tunnel_reply_t *rmp;
71 int rv = 0;
72 ip4_main_t *im = &ip4_main;
73
74 uword *p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
75 if (!p)
76 {
77 rv = VNET_API_ERROR_NO_SUCH_FIB;
78 goto out;
79 }
80
81 vnet_geneve_add_del_tunnel_args_t a = {
82 .is_add = mp->is_add,
Jakub Grajciar2d3282e2019-10-01 12:04:56 +020083 .is_ip6 = mp->remote_address.af,
Marco Varleseb598f1d2017-09-19 14:25:28 +020084 .mcast_sw_if_index = ntohl (mp->mcast_sw_if_index),
85 .encap_fib_index = p[0],
86 .decap_next_index = ntohl (mp->decap_next_index),
87 .vni = ntohl (mp->vni),
Marco Varleseb598f1d2017-09-19 14:25:28 +020088 };
89
Jakub Grajciar2d3282e2019-10-01 12:04:56 +020090 ip_address_decode (&mp->remote_address, &a.remote);
91 ip_address_decode (&mp->local_address, &a.local);
92
Marco Varleseb598f1d2017-09-19 14:25:28 +020093 /* Check src & dst are different */
94 if (ip46_address_cmp (&a.remote, &a.local) == 0)
95 {
96 rv = VNET_API_ERROR_SAME_SRC_DST;
97 goto out;
98 }
99 if (ip46_address_is_multicast (&a.remote) &&
100 !vnet_sw_if_index_is_api_valid (a.mcast_sw_if_index))
101 {
102 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
103 goto out;
104 }
105
106 u32 sw_if_index = ~0;
107 rv = vnet_geneve_add_del_tunnel (&a, &sw_if_index);
108
109out:
110 /* *INDENT-OFF* */
111 REPLY_MACRO2(VL_API_GENEVE_ADD_DEL_TUNNEL_REPLY,
112 ({
113 rmp->sw_if_index = ntohl (sw_if_index);
114 }));
115 /* *INDENT-ON* */
116}
117
Ole Troan7fc88cf2020-06-17 22:57:13 +0200118static void vl_api_geneve_add_del_tunnel2_t_handler
119 (vl_api_geneve_add_del_tunnel2_t * mp)
120{
121 vl_api_geneve_add_del_tunnel2_reply_t *rmp;
122 int rv = 0;
123 ip4_main_t *im = &ip4_main;
124
125 uword *p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
126 if (!p)
127 {
128 rv = VNET_API_ERROR_NO_SUCH_FIB;
129 goto out;
130 }
131
132 vnet_geneve_add_del_tunnel_args_t a = {
133 .is_add = mp->is_add,
134 .is_ip6 = mp->remote_address.af,
135 .mcast_sw_if_index = ntohl (mp->mcast_sw_if_index),
136 .encap_fib_index = p[0],
137 .decap_next_index = ntohl (mp->decap_next_index),
138 .vni = ntohl (mp->vni),
139 .l3_mode = mp->l3_mode,
140 };
141
142 ip_address_decode (&mp->remote_address, &a.remote);
143 ip_address_decode (&mp->local_address, &a.local);
144
145 /* Check src & dst are different */
146 if (ip46_address_cmp (&a.remote, &a.local) == 0)
147 {
148 rv = VNET_API_ERROR_SAME_SRC_DST;
149 goto out;
150 }
151 if (ip46_address_is_multicast (&a.remote) &&
152 !vnet_sw_if_index_is_api_valid (a.mcast_sw_if_index))
153 {
154 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
155 goto out;
156 }
157
158 u32 sw_if_index = ~0;
159 rv = vnet_geneve_add_del_tunnel (&a, &sw_if_index);
160
161out:
162 /* *INDENT-OFF* */
163 REPLY_MACRO2(VL_API_GENEVE_ADD_DEL_TUNNEL2_REPLY,
164 ({
165 rmp->sw_if_index = ntohl (sw_if_index);
166 }));
167 /* *INDENT-ON* */
168}
169
Marco Varleseb598f1d2017-09-19 14:25:28 +0200170static void send_geneve_tunnel_details
Florin Coras6c4dae22018-01-09 06:39:23 -0800171 (geneve_tunnel_t * t, vl_api_registration_t * reg, u32 context)
Marco Varleseb598f1d2017-09-19 14:25:28 +0200172{
173 vl_api_geneve_tunnel_details_t *rmp;
174 ip4_main_t *im4 = &ip4_main;
175 ip6_main_t *im6 = &ip6_main;
176 u8 is_ipv6 = !ip46_address_is_ip4 (&t->remote);
177
178 rmp = vl_msg_api_alloc (sizeof (*rmp));
Dave Barachb7b92992018-10-17 10:38:51 -0400179 clib_memset (rmp, 0, sizeof (*rmp));
Marco Varleseb598f1d2017-09-19 14:25:28 +0200180 rmp->_vl_msg_id = ntohs (VL_API_GENEVE_TUNNEL_DETAILS);
Jakub Grajciar2d3282e2019-10-01 12:04:56 +0200181 ip_address_encode (&t->local, is_ipv6 ? IP46_TYPE_IP6 : IP46_TYPE_IP4,
182 &rmp->src_address);
183 ip_address_encode (&t->remote, is_ipv6 ? IP46_TYPE_IP6 : IP46_TYPE_IP4,
184 &rmp->dst_address);
185 rmp->encap_vrf_id =
186 htonl (is_ipv6 ? im6->fibs[t->encap_fib_index].
187 ft_table_id : im4->fibs[t->encap_fib_index].ft_table_id);
188
Marco Varleseb598f1d2017-09-19 14:25:28 +0200189 rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
190 rmp->vni = htonl (t->vni);
191 rmp->decap_next_index = htonl (t->decap_next_index);
192 rmp->sw_if_index = htonl (t->sw_if_index);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200193 rmp->context = context;
194
Florin Coras6c4dae22018-01-09 06:39:23 -0800195 vl_api_send_msg (reg, (u8 *) rmp);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200196}
197
198static void vl_api_geneve_tunnel_dump_t_handler
199 (vl_api_geneve_tunnel_dump_t * mp)
200{
Florin Coras6c4dae22018-01-09 06:39:23 -0800201 vl_api_registration_t *reg;
Marco Varleseb598f1d2017-09-19 14:25:28 +0200202 geneve_main_t *vxm = &geneve_main;
203 geneve_tunnel_t *t;
204 u32 sw_if_index;
205
Florin Coras6c4dae22018-01-09 06:39:23 -0800206 reg = vl_api_client_index_to_registration (mp->client_index);
207 if (!reg)
208 return;
Marco Varleseb598f1d2017-09-19 14:25:28 +0200209
210 sw_if_index = ntohl (mp->sw_if_index);
211
212 if (~0 == sw_if_index)
213 {
214 /* *INDENT-OFF* */
215 pool_foreach (t, vxm->tunnels,
216 ({
Florin Coras6c4dae22018-01-09 06:39:23 -0800217 send_geneve_tunnel_details(t, reg, mp->context);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200218 }));
219 /* *INDENT-ON* */
220 }
221 else
222 {
223 if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
224 (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
225 {
226 return;
227 }
228 t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
Florin Coras6c4dae22018-01-09 06:39:23 -0800229 send_geneve_tunnel_details (t, reg, mp->context);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200230 }
231}
232
233/*
234 * vpe_api_hookup
235 * Add vpe's API message handlers to the table.
Jim Thompsonf324dec2019-04-08 03:22:21 -0500236 * vlib has already mapped shared memory and
Marco Varleseb598f1d2017-09-19 14:25:28 +0200237 * added the client registration handlers.
238 * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
239 */
240#define vl_msg_name_crc_list
241#include <vnet/vnet_all_api_h.h>
242#undef vl_msg_name_crc_list
243
244static void
245setup_message_id_table (api_main_t * am)
246{
247#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
248 foreach_vl_msg_name_crc_geneve;
249#undef _
250}
251
252static clib_error_t *
253geneve_api_hookup (vlib_main_t * vm)
254{
Dave Barach39d69112019-11-27 11:42:13 -0500255 api_main_t *am = vlibapi_get_main ();
Marco Varleseb598f1d2017-09-19 14:25:28 +0200256
257#define _(N,n) \
258 vl_msg_api_set_handlers(VL_API_##N, #n, \
259 vl_api_##n##_t_handler, \
260 vl_noop_handler, \
261 vl_api_##n##_t_endian, \
262 vl_api_##n##_t_print, \
263 sizeof(vl_api_##n##_t), 1);
264 foreach_vpe_api_msg;
265#undef _
266
267 am->api_trace_cfg[VL_API_GENEVE_ADD_DEL_TUNNEL].size += 16 * sizeof (u32);
268
269 /*
270 * Set up the (msg_name, crc, message-id) table
271 */
272 setup_message_id_table (am);
273
274 return 0;
275}
276
277VLIB_API_INIT_FUNCTION (geneve_api_hookup);
278
279/*
280 * fd.io coding-style-patch-verification: ON
281 *
282 * Local Variables:
283 * eval: (c-set-style "gnu")
284 * End:
285 */