Line data Source code
1 : /*
2 : *------------------------------------------------------------------
3 : * gtpu_api.c - gtpu api
4 : *
5 : * Copyright (c) 2017 Intel and/or its affiliates.
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at:
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : *------------------------------------------------------------------
18 : */
19 :
20 : #include <vnet/interface.h>
21 : #include <vnet/api_errno.h>
22 : #include <vnet/feature/feature.h>
23 : #include <vnet/fib/fib_table.h>
24 :
25 : #include <vppinfra/byte_order.h>
26 : #include <vlibmemory/api.h>
27 : #include <vnet/ip/ip_types_api.h>
28 : #include <gtpu/gtpu.h>
29 :
30 : #include <vnet/format_fns.h>
31 : #include <gtpu/gtpu.api_enum.h>
32 : #include <gtpu/gtpu.api_types.h>
33 :
34 : #define REPLY_MSG_ID_BASE gtm->msg_id_base
35 : #include <vlibapi/api_helper_macros.h>
36 :
37 : static void
38 0 : vl_api_gtpu_offload_rx_t_handler (vl_api_gtpu_offload_rx_t * mp)
39 : {
40 : vl_api_gtpu_offload_rx_reply_t *rmp;
41 0 : int rv = 0;
42 0 : vl_api_interface_index_t hw_if_index = ntohl (mp->hw_if_index);
43 0 : vl_api_interface_index_t sw_if_index = ntohl (mp->sw_if_index);
44 :
45 0 : if (!vnet_hw_interface_is_valid (vnet_get_main (), hw_if_index))
46 : {
47 0 : rv = VNET_API_ERROR_NO_SUCH_ENTRY;
48 0 : goto err;
49 : }
50 0 : VALIDATE_SW_IF_INDEX (mp);
51 :
52 0 : u32 t_index = vnet_gtpu_get_tunnel_index (sw_if_index);
53 0 : if (t_index == ~0)
54 : {
55 0 : rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2;
56 0 : goto err;
57 : }
58 :
59 0 : gtpu_main_t *gtm = >pu_main;
60 0 : gtpu_tunnel_t *t = pool_elt_at_index (gtm->tunnels, t_index);
61 0 : if (!ip46_address_is_ip4 (&t->dst))
62 : {
63 0 : rv = VNET_API_ERROR_INVALID_ADDRESS_FAMILY;
64 0 : goto err;
65 : }
66 :
67 0 : if ((t->decap_next_index != GTPU_INPUT_NEXT_IP4_INPUT) &&
68 0 : (t->decap_next_index != GTPU_INPUT_NEXT_IP6_INPUT))
69 : {
70 0 : rv = VNET_API_ERROR_INVALID_ADDRESS_FAMILY;
71 0 : goto err;
72 : }
73 :
74 0 : vnet_main_t *vnm = vnet_get_main ();
75 0 : vnet_hw_interface_t *hw_if = vnet_get_hw_interface (vnm, hw_if_index);
76 0 : ip4_main_t *im = &ip4_main;
77 0 : u32 rx_fib_index =
78 0 : vec_elt (im->fib_index_by_sw_if_index, hw_if->sw_if_index);
79 :
80 0 : if (t->encap_fib_index != rx_fib_index)
81 : {
82 0 : rv = VNET_API_ERROR_NO_SUCH_FIB;
83 0 : goto err;
84 : }
85 :
86 0 : if (vnet_gtpu_add_del_rx_flow (hw_if_index, t_index, mp->enable))
87 : {
88 0 : rv = VNET_API_ERROR_UNSPECIFIED;
89 0 : goto err;
90 : }
91 0 : BAD_SW_IF_INDEX_LABEL;
92 0 : err:
93 :
94 0 : REPLY_MACRO (VL_API_GTPU_OFFLOAD_RX_REPLY);
95 : }
96 :
97 : static void
98 0 : vl_api_sw_interface_set_gtpu_bypass_t_handler
99 : (vl_api_sw_interface_set_gtpu_bypass_t * mp)
100 : {
101 : vl_api_sw_interface_set_gtpu_bypass_reply_t *rmp;
102 0 : int rv = 0;
103 0 : u32 sw_if_index = ntohl (mp->sw_if_index);
104 0 : gtpu_main_t *gtm = >pu_main;
105 :
106 0 : VALIDATE_SW_IF_INDEX (mp);
107 :
108 0 : vnet_int_gtpu_bypass_mode (sw_if_index, mp->is_ipv6, mp->enable);
109 0 : BAD_SW_IF_INDEX_LABEL;
110 :
111 0 : REPLY_MACRO (VL_API_SW_INTERFACE_SET_GTPU_BYPASS_REPLY);
112 : }
113 :
114 106 : static void vl_api_gtpu_add_del_tunnel_t_handler
115 : (vl_api_gtpu_add_del_tunnel_t * mp)
116 : {
117 : vl_api_gtpu_add_del_tunnel_reply_t *rmp;
118 106 : int rv = 0;
119 106 : gtpu_main_t *gtm = >pu_main;
120 :
121 106 : vnet_gtpu_add_mod_del_tunnel_args_t a = {
122 106 : .opn = mp->is_add ? GTPU_ADD_TUNNEL : GTPU_DEL_TUNNEL,
123 106 : .mcast_sw_if_index = ntohl (mp->mcast_sw_if_index),
124 106 : .decap_next_index = ntohl (mp->decap_next_index),
125 106 : .teid = ntohl (mp->teid),
126 106 : .tteid = ntohl (mp->tteid),
127 : };
128 106 : ip_address_decode (&mp->dst_address, &a.dst);
129 106 : ip_address_decode (&mp->src_address, &a.src);
130 :
131 106 : u8 is_ipv6 = !ip46_address_is_ip4 (&a.dst);
132 106 : a.encap_fib_index = fib_table_find (fib_ip_proto (is_ipv6),
133 : ntohl (mp->encap_vrf_id));
134 106 : if (a.encap_fib_index == ~0)
135 : {
136 0 : rv = VNET_API_ERROR_NO_SUCH_FIB;
137 0 : goto out;
138 : }
139 :
140 : /* Check src & dst are different */
141 106 : if (ip46_address_cmp (&a.dst, &a.src) == 0)
142 : {
143 0 : rv = VNET_API_ERROR_SAME_SRC_DST;
144 0 : goto out;
145 : }
146 187 : if (ip46_address_is_multicast (&a.dst) &&
147 81 : !vnet_sw_if_index_is_api_valid (a.mcast_sw_if_index))
148 : {
149 0 : rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
150 0 : goto out;
151 : }
152 :
153 106 : u32 sw_if_index = ~0;
154 106 : rv = vnet_gtpu_add_mod_del_tunnel (&a, &sw_if_index);
155 :
156 106 : out:
157 : /* *INDENT-OFF* */
158 106 : REPLY_MACRO2(VL_API_GTPU_ADD_DEL_TUNNEL_REPLY,
159 : ({
160 : rmp->sw_if_index = ntohl (sw_if_index);
161 : }));
162 : /* *INDENT-ON* */
163 : }
164 :
165 0 : static void vl_api_gtpu_tunnel_update_tteid_t_handler
166 : (vl_api_gtpu_tunnel_update_tteid_t * mp)
167 : {
168 : vl_api_gtpu_tunnel_update_tteid_reply_t *rmp;
169 0 : int rv = 0;
170 0 : gtpu_main_t *gtm = >pu_main;
171 :
172 0 : vnet_gtpu_add_mod_del_tunnel_args_t a = {
173 : .opn = GTPU_UPD_TTEID,
174 0 : .teid = ntohl (mp->teid),
175 0 : .tteid = ntohl (mp->tteid),
176 : };
177 0 : ip_address_decode (&mp->dst_address, &a.dst);
178 :
179 0 : u8 is_ipv6 = !ip46_address_is_ip4 (&a.dst);
180 0 : a.encap_fib_index = fib_table_find (fib_ip_proto (is_ipv6),
181 : ntohl (mp->encap_vrf_id));
182 0 : if (a.encap_fib_index == ~0)
183 : {
184 0 : rv = VNET_API_ERROR_NO_SUCH_FIB;
185 0 : goto out;
186 : }
187 :
188 0 : rv = vnet_gtpu_add_mod_del_tunnel (&a, 0);
189 :
190 0 : out:
191 0 : REPLY_MACRO (VL_API_GTPU_TUNNEL_UPDATE_TTEID_REPLY);
192 : }
193 :
194 0 : static void send_gtpu_tunnel_details
195 : (gtpu_tunnel_t * t, vl_api_registration_t * reg, u32 context)
196 : {
197 : vl_api_gtpu_tunnel_details_t *rmp;
198 0 : gtpu_main_t *gtm = >pu_main;
199 0 : ip4_main_t *im4 = &ip4_main;
200 0 : ip6_main_t *im6 = &ip6_main;
201 0 : u8 is_ipv6 = !ip46_address_is_ip4 (&t->dst);
202 :
203 0 : rmp = vl_msg_api_alloc (sizeof (*rmp));
204 0 : clib_memset (rmp, 0, sizeof (*rmp));
205 0 : rmp->_vl_msg_id = ntohs (VL_API_GTPU_TUNNEL_DETAILS + gtm->msg_id_base);
206 :
207 0 : ip_address_encode (&t->src, is_ipv6 ? IP46_TYPE_IP6 : IP46_TYPE_IP4,
208 : &rmp->src_address);
209 0 : ip_address_encode (&t->dst, is_ipv6 ? IP46_TYPE_IP6 : IP46_TYPE_IP4,
210 : &rmp->dst_address);
211 :
212 0 : rmp->encap_vrf_id =
213 0 : is_ipv6 ? htonl (im6->fibs[t->encap_fib_index].ft_table_id) :
214 0 : htonl (im4->fibs[t->encap_fib_index].ft_table_id);
215 0 : rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
216 0 : rmp->teid = htonl (t->teid);
217 0 : rmp->tteid = htonl (t->tteid);
218 0 : rmp->decap_next_index = htonl (t->decap_next_index);
219 0 : rmp->sw_if_index = htonl (t->sw_if_index);
220 0 : rmp->context = context;
221 :
222 0 : vl_api_send_msg (reg, (u8 *) rmp);
223 0 : }
224 :
225 : static void
226 0 : vl_api_gtpu_tunnel_dump_t_handler (vl_api_gtpu_tunnel_dump_t * mp)
227 : {
228 : vl_api_registration_t *reg;
229 0 : gtpu_main_t *gtm = >pu_main;
230 : gtpu_tunnel_t *t;
231 : u32 sw_if_index;
232 :
233 0 : reg = vl_api_client_index_to_registration (mp->client_index);
234 0 : if (!reg)
235 0 : return;
236 :
237 0 : sw_if_index = ntohl (mp->sw_if_index);
238 :
239 0 : if (~0 == sw_if_index)
240 : {
241 : /* *INDENT-OFF* */
242 0 : pool_foreach (t, gtm->tunnels)
243 : {
244 0 : send_gtpu_tunnel_details(t, reg, mp->context);
245 : }
246 : /* *INDENT-ON* */
247 : }
248 : else
249 : {
250 0 : if ((sw_if_index >= vec_len (gtm->tunnel_index_by_sw_if_index)) ||
251 0 : (~0 == gtm->tunnel_index_by_sw_if_index[sw_if_index]))
252 : {
253 0 : return;
254 : }
255 0 : t = >m->tunnels[gtm->tunnel_index_by_sw_if_index[sw_if_index]];
256 0 : send_gtpu_tunnel_details (t, reg, mp->context);
257 : }
258 : }
259 :
260 : #include <gtpu/gtpu.api.c>
261 : static clib_error_t *
262 559 : gtpu_api_hookup (vlib_main_t * vm)
263 : {
264 559 : gtpu_main_t *gtm = >pu_main;
265 :
266 559 : gtm->msg_id_base = setup_message_id_table ();
267 559 : return 0;
268 : }
269 :
270 1119 : VLIB_API_INIT_FUNCTION (gtpu_api_hookup);
271 :
272 : /*
273 : * fd.io coding-style-patch-verification: ON
274 : *
275 : * Local Variables:
276 : * eval: (c-set-style "gnu")
277 : * End:
278 : */
|