vxlan-gpe: add udp-port configuration support
[vpp.git] / src / plugins / ioam / lib-vxlan-gpe / vxlan_gpe_api.c
1 /*
2  * Copyright (c) 2016 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  *------------------------------------------------------------------
17  * vxlan_gpe_api.c - iOAM VxLAN-GPE related APIs to create
18  *               and maintain profiles
19  *------------------------------------------------------------------
20  */
21
22 #include <vnet/vnet.h>
23 #include <vnet/plugin/plugin.h>
24 #include <ioam/lib-vxlan-gpe/vxlan_gpe_ioam.h>
25 #include <vlibapi/api_helper_macros.h>
26 #include <vlibapi/api.h>
27 #include <vlibmemory/api.h>
28 #include <vnet/format_fns.h>
29 #include <vnet/ip/ip_types_api.h>
30 #include <vnet/udp/udp_local.h>
31
32 /* define message IDs */
33 #include <ioam/lib-vxlan-gpe/ioam_vxlan_gpe.api_enum.h>
34 #include <ioam/lib-vxlan-gpe/ioam_vxlan_gpe.api_types.h>
35
36 static void vl_api_vxlan_gpe_ioam_enable_t_handler
37   (vl_api_vxlan_gpe_ioam_enable_t * mp)
38 {
39   int rv = 0;
40   vl_api_vxlan_gpe_ioam_enable_reply_t *rmp;
41   clib_error_t *error;
42
43   /* Ignoring the profile id as currently a single profile
44    * is supported */
45   error =
46     vxlan_gpe_ioam_enable (mp->trace_enable, mp->pow_enable, mp->trace_ppc);
47   if (error)
48     {
49       clib_error_report (error);
50       rv = clib_error_get_code (error);
51     }
52
53   REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_ENABLE_REPLY);
54 }
55
56 static void vl_api_vxlan_gpe_ioam_disable_t_handler
57   (vl_api_vxlan_gpe_ioam_disable_t * mp)
58 {
59   int rv = 0;
60   vl_api_vxlan_gpe_ioam_disable_reply_t *rmp;
61   clib_error_t *error;
62
63   /* Ignoring the profile id as currently a single profile
64    * is supported */
65   error = vxlan_gpe_ioam_disable (0, 0, 0);
66   if (error)
67     {
68       clib_error_report (error);
69       rv = clib_error_get_code (error);
70     }
71
72   REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_DISABLE_REPLY);
73 }
74
75 static void vl_api_vxlan_gpe_ioam_vni_enable_t_handler
76   (vl_api_vxlan_gpe_ioam_vni_enable_t * mp)
77 {
78   int rv = 0;
79   vl_api_vxlan_gpe_ioam_vni_enable_reply_t *rmp;
80   clib_error_t *error;
81   vxlan4_gpe_tunnel_key_t key4;
82   uword *p = NULL;
83   vxlan_gpe_main_t *gm = &vxlan_gpe_main;
84   vxlan_gpe_tunnel_t *t = 0;
85   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
86   u32 vni;
87
88
89   if (clib_net_to_host_u32 (mp->local.af) == ADDRESS_IP4 &&
90       clib_net_to_host_u32 (mp->remote.af) == ADDRESS_IP4)
91     {
92       clib_memcpy (&key4.local, &mp->local.un.ip4, sizeof (key4.local));
93       clib_memcpy (&key4.remote, &mp->remote.un.ip4, sizeof (key4.remote));
94       vni = clib_net_to_host_u32 (mp->vni);
95       key4.vni = clib_host_to_net_u32 (vni << 8);
96       key4.port = clib_host_to_net_u16 (UDP_DST_PORT_VXLAN_GPE);
97
98       p = hash_get_mem (gm->vxlan4_gpe_tunnel_by_key, &key4);
99     }
100   else
101     {
102       return;
103     }
104
105   if (!p)
106     return;
107
108   t = pool_elt_at_index (gm->tunnels, p[0]);
109
110   error = vxlan_gpe_ioam_set (t, hm->has_trace_option,
111                               hm->has_pot_option,
112                               hm->has_ppc_option, 0 /* is_ipv6 */ );
113
114
115   if (error)
116     {
117       clib_error_report (error);
118       rv = clib_error_get_code (error);
119     }
120
121   REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_VNI_ENABLE_REPLY);
122 }
123
124
125 static void vl_api_vxlan_gpe_ioam_vni_disable_t_handler
126   (vl_api_vxlan_gpe_ioam_vni_disable_t * mp)
127 {
128   int rv = 0;
129   vl_api_vxlan_gpe_ioam_vni_enable_reply_t *rmp;
130   clib_error_t *error;
131   vxlan4_gpe_tunnel_key_t key4;
132   uword *p = NULL;
133   vxlan_gpe_main_t *gm = &vxlan_gpe_main;
134   vxlan_gpe_tunnel_t *t = 0;
135   u32 vni;
136
137
138   if (clib_net_to_host_u32 (mp->local.af) == ADDRESS_IP4 &&
139       clib_net_to_host_u32 (mp->remote.af) == ADDRESS_IP4)
140     {
141       clib_memcpy (&key4.local, &mp->local, sizeof (key4.local));
142       clib_memcpy (&key4.remote, &mp->remote, sizeof (key4.remote));
143       vni = clib_net_to_host_u32 (mp->vni);
144       key4.vni = clib_host_to_net_u32 (vni << 8);
145       key4.port = clib_host_to_net_u16 (UDP_DST_PORT_VXLAN_GPE);
146
147       p = hash_get_mem (gm->vxlan4_gpe_tunnel_by_key, &key4);
148     }
149   else
150     {
151       return;
152     }
153
154   if (!p)
155     return;
156
157   t = pool_elt_at_index (gm->tunnels, p[0]);
158
159   error = vxlan_gpe_ioam_clear (t, 0, 0, 0, 0);
160
161
162   if (error)
163     {
164       clib_error_report (error);
165       rv = clib_error_get_code (error);
166     }
167
168
169   REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_VNI_DISABLE_REPLY);
170 }
171
172 static void vl_api_vxlan_gpe_ioam_transit_enable_t_handler
173   (vl_api_vxlan_gpe_ioam_transit_enable_t * mp)
174 {
175   int rv = 0;
176   vl_api_vxlan_gpe_ioam_transit_enable_reply_t *rmp;
177   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
178   ip46_address_t dst_addr;
179
180   ip_address_decode (&mp->dst_addr, &dst_addr);
181   bool is_ip6 = clib_net_to_host_u32 (mp->dst_addr.af) == ADDRESS_IP6;
182   rv = vxlan_gpe_enable_disable_ioam_for_dest (sm->vlib_main,
183                                                dst_addr,
184                                                ntohl (mp->outer_fib_index),
185                                                is_ip6, 1 /* is_add */ );
186
187   REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_TRANSIT_ENABLE_REPLY);
188 }
189
190 static void vl_api_vxlan_gpe_ioam_transit_disable_t_handler
191   (vl_api_vxlan_gpe_ioam_transit_disable_t * mp)
192 {
193   int rv = 0;
194   vl_api_vxlan_gpe_ioam_transit_disable_reply_t *rmp;
195   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
196   ip46_address_t dst_addr;
197
198   ip_address_decode (&mp->dst_addr, &dst_addr);
199   bool is_ip6 = clib_net_to_host_u32 (mp->dst_addr.af) == ADDRESS_IP6;
200   rv = vxlan_gpe_ioam_disable_for_dest (sm->vlib_main,
201                                         dst_addr,
202                                         ntohl (mp->outer_fib_index), is_ip6);
203   REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_TRANSIT_DISABLE_REPLY);
204 }
205
206 #include <ioam/lib-vxlan-gpe/ioam_vxlan_gpe.api.c>
207 static clib_error_t *
208 ioam_vxlan_gpe_init (vlib_main_t * vm)
209 {
210   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
211   u32 encap_node_index = vxlan_gpe_encap_ioam_v4_node.index;
212   u32 decap_node_index = vxlan_gpe_decap_ioam_v4_node.index;
213   vlib_node_t *vxlan_gpe_encap_node = NULL;
214   vlib_node_t *vxlan_gpe_decap_node = NULL;
215   uword next_node = 0;
216
217   sm->vlib_main = vm;
218   sm->vnet_main = vnet_get_main ();
219   sm->unix_time_0 = (u32) time (0);     /* Store starting time */
220   sm->vlib_time_0 = vlib_time_now (vm);
221
222   /* Ask for a correctly-sized block of API message decode slots */
223   sm->msg_id_base = setup_message_id_table ();
224
225   /* Hook the ioam-encap node to vxlan-gpe-encap */
226   vxlan_gpe_encap_node = vlib_get_node_by_name (vm, (u8 *) "vxlan-gpe-encap");
227   sm->encap_v4_next_node =
228     vlib_node_add_next (vm, vxlan_gpe_encap_node->index, encap_node_index);
229
230   vxlan_gpe_decap_node =
231     vlib_get_node_by_name (vm, (u8 *) "vxlan4-gpe-input");
232   next_node =
233     vlib_node_add_next (vm, vxlan_gpe_decap_node->index, decap_node_index);
234   vxlan_gpe_register_decap_protocol (VXLAN_GPE_PROTOCOL_IOAM, next_node);
235
236   vec_new (vxlan_gpe_ioam_sw_interface_t, pool_elts (sm->sw_interfaces));
237   sm->dst_by_ip4 = hash_create_mem (0, sizeof (fib_prefix_t), sizeof (uword));
238
239   sm->dst_by_ip6 = hash_create_mem (0, sizeof (fib_prefix_t), sizeof (uword));
240
241   vxlan_gpe_ioam_interface_init ();
242
243   return 0;
244 }
245
246 VLIB_INIT_FUNCTION (ioam_vxlan_gpe_init);
247
248 /*
249  * fd.io coding-style-patch-verification: ON
250  *
251  * Local Variables:
252  * eval: (c-set-style "gnu")
253  * End:
254  */