LCOV - code coverage report
Current view: top level - plugins/vxlan - vxlan_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 81 183 44.3 %
Date: 2023-07-05 22:20:52 Functions: 8 13 61.5 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * vxlan_api.c - vxlan api
       4             :  *
       5             :  * Copyright (c) 2016 Cisco 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/vnet.h>
      21             : #include <vlibmemory/api.h>
      22             : 
      23             : #include <vnet/interface.h>
      24             : #include <vnet/api_errno.h>
      25             : #include <vnet/feature/feature.h>
      26             : #include <vxlan/vxlan.h>
      27             : #include <vnet/fib/fib_table.h>
      28             : #include <vnet/ip/ip_types_api.h>
      29             : #include <vnet/udp/udp_local.h>
      30             : #include <vnet/format_fns.h>
      31             : #include <vxlan/vxlan.api_enum.h>
      32             : #include <vxlan/vxlan.api_types.h>
      33             : 
      34             : static u16 msg_id_base;
      35             : 
      36             : #define REPLY_MSG_ID_BASE msg_id_base
      37             : #include <vlibapi/api_helper_macros.h>
      38             : 
      39             : static void
      40           0 : vl_api_vxlan_offload_rx_t_handler (vl_api_vxlan_offload_rx_t * mp)
      41             : {
      42             :   vl_api_vxlan_offload_rx_reply_t *rmp;
      43           0 :   int rv = 0;
      44           0 :   u32 hw_if_index = ntohl (mp->hw_if_index);
      45           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
      46             : 
      47           0 :   if (!vnet_hw_interface_is_valid (vnet_get_main (), hw_if_index))
      48             :     {
      49           0 :       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
      50           0 :       goto err;
      51             :     }
      52           0 :   VALIDATE_SW_IF_INDEX (mp);
      53             : 
      54           0 :   u32 t_index = vnet_vxlan_get_tunnel_index (sw_if_index);
      55           0 :   if (t_index == ~0)
      56             :     {
      57           0 :       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2;
      58           0 :       goto err;
      59             :     }
      60             : 
      61           0 :   vxlan_main_t *vxm = &vxlan_main;
      62           0 :   vxlan_tunnel_t *t = pool_elt_at_index (vxm->tunnels, t_index);
      63           0 :   if (!ip46_address_is_ip4 (&t->dst))
      64             :     {
      65           0 :       rv = VNET_API_ERROR_INVALID_ADDRESS_FAMILY;
      66           0 :       goto err;
      67             :     }
      68             : 
      69           0 :   vnet_main_t *vnm = vnet_get_main ();
      70           0 :   vnet_hw_interface_t *hw_if = vnet_get_hw_interface (vnm, hw_if_index);
      71           0 :   ip4_main_t *im = &ip4_main;
      72           0 :   u32 rx_fib_index =
      73           0 :     vec_elt (im->fib_index_by_sw_if_index, hw_if->sw_if_index);
      74             : 
      75           0 :   if (t->encap_fib_index != rx_fib_index)
      76             :     {
      77           0 :       rv = VNET_API_ERROR_NO_SUCH_FIB;
      78           0 :       goto err;
      79             :     }
      80             : 
      81           0 :   if (vnet_vxlan_add_del_rx_flow (hw_if_index, t_index, mp->enable))
      82             :     {
      83           0 :       rv = VNET_API_ERROR_UNSPECIFIED;
      84           0 :       goto err;
      85             :     }
      86           0 :   BAD_SW_IF_INDEX_LABEL;
      87           0 : err:
      88             : 
      89           0 :   REPLY_MACRO (VL_API_VXLAN_OFFLOAD_RX_REPLY);
      90             : }
      91             : 
      92             : static void
      93           0 :   vl_api_sw_interface_set_vxlan_bypass_t_handler
      94             :   (vl_api_sw_interface_set_vxlan_bypass_t * mp)
      95             : {
      96             :   vl_api_sw_interface_set_vxlan_bypass_reply_t *rmp;
      97           0 :   int rv = 0;
      98           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
      99             : 
     100           0 :   VALIDATE_SW_IF_INDEX (mp);
     101             : 
     102           0 :   vnet_int_vxlan_bypass_mode (sw_if_index, mp->is_ipv6, mp->enable);
     103           0 :   BAD_SW_IF_INDEX_LABEL;
     104             : 
     105           0 :   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VXLAN_BYPASS_REPLY);
     106             : }
     107             : 
     108             : static int
     109        5840 : vxlan_add_del_tunnel_clean_input (vnet_vxlan_add_del_tunnel_args_t *a,
     110             :                                   u32 encap_vrf_id)
     111             : {
     112        5840 :   a->is_ip6 = !ip46_address_is_ip4 (&a->src);
     113             : 
     114        5840 :   a->encap_fib_index = fib_table_find (fib_ip_proto (a->is_ip6), encap_vrf_id);
     115        5840 :   if (a->encap_fib_index == ~0)
     116             :     {
     117           0 :       return VNET_API_ERROR_NO_SUCH_FIB;
     118             :     }
     119             : 
     120        5840 :   if (ip46_address_is_ip4 (&a->src) != ip46_address_is_ip4 (&a->dst))
     121             :     {
     122           0 :       return VNET_API_ERROR_INVALID_VALUE;
     123             :     }
     124             : 
     125             :   /* Check src & dst are different */
     126        5840 :   if (ip46_address_cmp (&a->dst, &a->src) == 0)
     127             :     {
     128           0 :       return VNET_API_ERROR_SAME_SRC_DST;
     129             :     }
     130       10724 :   if (ip46_address_is_multicast (&a->dst) &&
     131        4884 :       !vnet_sw_if_index_is_api_valid (a->mcast_sw_if_index))
     132             :     {
     133           0 :       return VNET_API_ERROR_INVALID_SW_IF_INDEX;
     134             :     }
     135        5840 :   return 0;
     136             : }
     137             : 
     138             : static void
     139           0 : vl_api_vxlan_add_del_tunnel_t_handler (vl_api_vxlan_add_del_tunnel_t *mp)
     140             : {
     141             :   vl_api_vxlan_add_del_tunnel_reply_t *rmp;
     142           0 :   u32 sw_if_index = ~0;
     143           0 :   int rv = 0;
     144             : 
     145           0 :   vnet_vxlan_add_del_tunnel_args_t a = {
     146           0 :     .is_add = mp->is_add,
     147           0 :     .instance = ntohl (mp->instance),
     148           0 :     .mcast_sw_if_index = ntohl (mp->mcast_sw_if_index),
     149           0 :     .decap_next_index = ntohl (mp->decap_next_index),
     150           0 :     .vni = ntohl (mp->vni),
     151             :   };
     152           0 :   ip_address_decode (&mp->src_address, &a.src);
     153           0 :   ip_address_decode (&mp->dst_address, &a.dst);
     154             : 
     155           0 :   rv = vxlan_add_del_tunnel_clean_input (&a, ntohl (mp->encap_vrf_id));
     156           0 :   if (rv)
     157           0 :     goto out;
     158           0 :   a.dst_port = a.is_ip6 ? UDP_DST_PORT_vxlan6 : UDP_DST_PORT_vxlan,
     159           0 :   a.src_port = a.is_ip6 ? UDP_DST_PORT_vxlan6 : UDP_DST_PORT_vxlan,
     160           0 :   rv = vnet_vxlan_add_del_tunnel (&a, &sw_if_index);
     161             : 
     162           0 : out:
     163           0 :   REPLY_MACRO2(VL_API_VXLAN_ADD_DEL_TUNNEL_REPLY,
     164             :   ({
     165             :     rmp->sw_if_index = ntohl (sw_if_index);
     166             :   }));
     167             : }
     168             : 
     169             : static void
     170        2920 : vl_api_vxlan_add_del_tunnel_v2_t_handler (vl_api_vxlan_add_del_tunnel_v2_t *mp)
     171             : {
     172             :   vl_api_vxlan_add_del_tunnel_v2_reply_t *rmp;
     173        2920 :   u32 sw_if_index = ~0;
     174        2920 :   int rv = 0;
     175             : 
     176        2920 :   vnet_vxlan_add_del_tunnel_args_t a = {
     177        2920 :     .is_add = mp->is_add,
     178        2920 :     .instance = ntohl (mp->instance),
     179        2920 :     .mcast_sw_if_index = ntohl (mp->mcast_sw_if_index),
     180        2920 :     .decap_next_index = ntohl (mp->decap_next_index),
     181        2920 :     .vni = ntohl (mp->vni),
     182        2920 :     .dst_port = ntohs (mp->dst_port),
     183        2920 :     .src_port = ntohs (mp->src_port),
     184             :   };
     185             : 
     186        2920 :   ip_address_decode (&mp->src_address, &a.src);
     187        2920 :   ip_address_decode (&mp->dst_address, &a.dst);
     188             : 
     189        2920 :   rv = vxlan_add_del_tunnel_clean_input (&a, ntohl (mp->encap_vrf_id));
     190        2920 :   if (rv)
     191           0 :     goto out;
     192        2920 :   rv = vnet_vxlan_add_del_tunnel (&a, &sw_if_index);
     193        2920 : out:
     194        2920 :   REPLY_MACRO2 (VL_API_VXLAN_ADD_DEL_TUNNEL_V2_REPLY,
     195             :                 ({ rmp->sw_if_index = ntohl (sw_if_index); }));
     196             : }
     197             : 
     198             : static void
     199        2920 : vl_api_vxlan_add_del_tunnel_v3_t_handler (vl_api_vxlan_add_del_tunnel_v3_t *mp)
     200             : {
     201             :   vl_api_vxlan_add_del_tunnel_v3_reply_t *rmp;
     202        2920 :   u32 sw_if_index = ~0;
     203        2920 :   int rv = 0;
     204             : 
     205        2920 :   vnet_vxlan_add_del_tunnel_args_t a = {
     206        2920 :     .is_add = mp->is_add,
     207        2920 :     .instance = ntohl (mp->instance),
     208        2920 :     .mcast_sw_if_index = ntohl (mp->mcast_sw_if_index),
     209        2920 :     .decap_next_index = ntohl (mp->decap_next_index),
     210        2920 :     .vni = ntohl (mp->vni),
     211        2920 :     .dst_port = ntohs (mp->dst_port),
     212        2920 :     .src_port = ntohs (mp->src_port),
     213        2920 :     .is_l3 = mp->is_l3,
     214             :   };
     215             : 
     216        2920 :   ip_address_decode (&mp->src_address, &a.src);
     217        2920 :   ip_address_decode (&mp->dst_address, &a.dst);
     218             : 
     219        2920 :   rv = vxlan_add_del_tunnel_clean_input (&a, ntohl (mp->encap_vrf_id));
     220        2920 :   if (rv)
     221           0 :     goto out;
     222        2920 :   rv = vnet_vxlan_add_del_tunnel (&a, &sw_if_index);
     223        2920 : out:
     224        2920 :   REPLY_MACRO2 (VL_API_VXLAN_ADD_DEL_TUNNEL_V3_REPLY,
     225             :                 ({ rmp->sw_if_index = ntohl (sw_if_index); }));
     226             : }
     227             : 
     228           0 : static void send_vxlan_tunnel_details
     229             :   (vxlan_tunnel_t * t, vl_api_registration_t * reg, u32 context)
     230             : {
     231             :   vl_api_vxlan_tunnel_details_t *rmp;
     232           0 :   ip4_main_t *im4 = &ip4_main;
     233           0 :   ip6_main_t *im6 = &ip6_main;
     234             : 
     235           0 :   rmp = vl_msg_api_alloc (sizeof (*rmp));
     236           0 :   clib_memset (rmp, 0, sizeof (*rmp));
     237           0 :   rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_VXLAN_TUNNEL_DETAILS);
     238             : 
     239           0 :   ip_address_encode (&t->src, IP46_TYPE_ANY, &rmp->src_address);
     240           0 :   ip_address_encode (&t->dst, IP46_TYPE_ANY, &rmp->dst_address);
     241             : 
     242           0 :   if (ip46_address_is_ip4 (&t->dst))
     243           0 :     rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
     244             :   else
     245           0 :     rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
     246             : 
     247           0 :   rmp->instance = htonl (t->user_instance);
     248           0 :   rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
     249           0 :   rmp->vni = htonl (t->vni);
     250           0 :   rmp->decap_next_index = htonl (t->decap_next_index);
     251           0 :   rmp->sw_if_index = htonl (t->sw_if_index);
     252           0 :   rmp->context = context;
     253             : 
     254           0 :   vl_api_send_msg (reg, (u8 *) rmp);
     255           0 : }
     256             : 
     257           0 : static void vl_api_vxlan_tunnel_dump_t_handler
     258             :   (vl_api_vxlan_tunnel_dump_t * mp)
     259             : {
     260             :   vl_api_registration_t *reg;
     261           0 :   vxlan_main_t *vxm = &vxlan_main;
     262             :   vxlan_tunnel_t *t;
     263             :   u32 sw_if_index;
     264             : 
     265           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
     266           0 :   if (!reg)
     267           0 :     return;
     268             : 
     269           0 :   sw_if_index = ntohl (mp->sw_if_index);
     270             : 
     271           0 :   if (~0 == sw_if_index)
     272             :     {
     273           0 :       pool_foreach (t, vxm->tunnels)
     274           0 :         send_vxlan_tunnel_details(t, reg, mp->context);
     275             :     }
     276             :   else
     277             :     {
     278           0 :       if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
     279           0 :           (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
     280             :         {
     281           0 :           return;
     282             :         }
     283           0 :       t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
     284           0 :       send_vxlan_tunnel_details (t, reg, mp->context);
     285             :     }
     286             : }
     287             : 
     288             : static void
     289       39700 : send_vxlan_tunnel_v2_details (vxlan_tunnel_t *t, vl_api_registration_t *reg,
     290             :                               u32 context)
     291             : {
     292             :   vl_api_vxlan_tunnel_v2_details_t *rmp;
     293       39700 :   ip4_main_t *im4 = &ip4_main;
     294       39700 :   ip6_main_t *im6 = &ip6_main;
     295             : 
     296       39700 :   rmp = vl_msg_api_alloc (sizeof (*rmp));
     297       39700 :   clib_memset (rmp, 0, sizeof (*rmp));
     298       39700 :   rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_VXLAN_TUNNEL_V2_DETAILS);
     299             : 
     300       39700 :   ip_address_encode (&t->src, IP46_TYPE_ANY, &rmp->src_address);
     301       39700 :   ip_address_encode (&t->dst, IP46_TYPE_ANY, &rmp->dst_address);
     302       39700 :   rmp->src_port = htons (t->src_port);
     303       39700 :   rmp->dst_port = htons (t->dst_port);
     304             : 
     305       39700 :   if (ip46_address_is_ip4 (&t->dst))
     306       34376 :     rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
     307             :   else
     308        5324 :     rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
     309             : 
     310       39700 :   rmp->instance = htonl (t->user_instance);
     311       39700 :   rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
     312       39700 :   rmp->vni = htonl (t->vni);
     313       39700 :   rmp->decap_next_index = htonl (t->decap_next_index);
     314       39700 :   rmp->sw_if_index = htonl (t->sw_if_index);
     315       39700 :   rmp->context = context;
     316             : 
     317       39700 :   vl_api_send_msg (reg, (u8 *) rmp);
     318       39700 : }
     319             : 
     320             : static void
     321        3416 : vl_api_vxlan_tunnel_v2_dump_t_handler (vl_api_vxlan_tunnel_v2_dump_t *mp)
     322             : {
     323             :   vl_api_registration_t *reg;
     324        3416 :   vxlan_main_t *vxm = &vxlan_main;
     325             :   vxlan_tunnel_t *t;
     326             :   u32 sw_if_index;
     327             : 
     328        3416 :   reg = vl_api_client_index_to_registration (mp->client_index);
     329        3416 :   if (!reg)
     330           0 :     return;
     331             : 
     332        3416 :   sw_if_index = ntohl (mp->sw_if_index);
     333             : 
     334        3416 :   if (~0 == sw_if_index)
     335             :     {
     336       43116 :       pool_foreach (t, vxm->tunnels)
     337       39700 :         send_vxlan_tunnel_v2_details (t, reg, mp->context);
     338             :     }
     339             :   else
     340             :     {
     341           0 :       if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
     342           0 :           (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
     343             :         {
     344           0 :           return;
     345             :         }
     346           0 :       t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
     347           0 :       send_vxlan_tunnel_v2_details (t, reg, mp->context);
     348             :     }
     349             : }
     350             : 
     351             : #include <vxlan/vxlan.api.c>
     352             : static clib_error_t *
     353         559 : vxlan_api_hookup (vlib_main_t * vm)
     354             : {
     355         559 :   api_main_t *am = vlibapi_get_main ();
     356             : 
     357         559 :   vl_api_increase_msg_trace_size (am, VL_API_VXLAN_ADD_DEL_TUNNEL,
     358             :                                   16 * sizeof (u32));
     359             : 
     360             :   /*
     361             :    * Set up the (msg_name, crc, message-id) table
     362             :    */
     363         559 :   msg_id_base = setup_message_id_table ();
     364             : 
     365         559 :   return 0;
     366             : }
     367             : 
     368        1119 : VLIB_API_INIT_FUNCTION (vxlan_api_hookup);
     369             : 
     370             : /*
     371             :  * fd.io coding-style-patch-verification: ON
     372             :  *
     373             :  * Local Variables:
     374             :  * eval: (c-set-style "gnu")
     375             :  * End:
     376             :  */

Generated by: LCOV version 1.14