LCOV - code coverage report
Current view: top level - plugins/dhcp - dhcp_proxy.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 102 148 68.9 %
Date: 2023-10-26 01:39:38 Functions: 9 13 69.2 %

          Line data    Source code
       1             : /*
       2             :  * proxy_node.c: common dhcp v4 and v6 proxy node processing
       3             :  *
       4             :  * Copyright (c) 2013 Cisco and/or its affiliates.
       5             :  * Licensed under the Apache License, Version 2.0 (the "License");
       6             :  * you may not use this file except in compliance with the License.
       7             :  * You may obtain a copy of the License at:
       8             :  *
       9             :  *     http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             :  */
      17             : 
      18             : #include <dhcp/dhcp_proxy.h>
      19             : #include <vnet/fib/fib_table.h>
      20             : #include <vnet/mfib/mfib_table.h>
      21             : 
      22             : /**
      23             :  * @brief Shard 4/6 instance of DHCP main
      24             :  */
      25             : dhcp_proxy_main_t dhcp_proxy_main;
      26             : 
      27             : static void
      28           4 : dhcp_proxy_rx_table_lock (fib_protocol_t proto, u32 fib_index)
      29             : {
      30           4 :   if (FIB_PROTOCOL_IP4 == proto)
      31           2 :     fib_table_lock (fib_index, proto, FIB_SOURCE_DHCP);
      32             :   else
      33           2 :     mfib_table_lock (fib_index, proto, MFIB_SOURCE_DHCP);
      34           4 : }
      35             : 
      36             : static void
      37          10 : dhcp_proxy_rx_table_unlock (fib_protocol_t proto, u32 fib_index)
      38             : {
      39          10 :   if (FIB_PROTOCOL_IP4 == proto)
      40           6 :     fib_table_unlock (fib_index, proto, FIB_SOURCE_DHCP);
      41             :   else
      42           4 :     mfib_table_unlock (fib_index, proto, MFIB_SOURCE_DHCP);
      43          10 : }
      44             : 
      45             : u32
      46           0 : dhcp_proxy_rx_table_get_table_id (fib_protocol_t proto, u32 fib_index)
      47             : {
      48           0 :   if (FIB_PROTOCOL_IP4 == proto)
      49             :     {
      50             :       fib_table_t *fib;
      51             : 
      52           0 :       fib = fib_table_get (fib_index, proto);
      53             : 
      54           0 :       return (fib->ft_table_id);
      55             :     }
      56             :   else
      57             :     {
      58             :       mfib_table_t *mfib;
      59             : 
      60           0 :       mfib = mfib_table_get (fib_index, proto);
      61             : 
      62           0 :       return (mfib->mft_table_id);
      63             :     }
      64             : }
      65             : 
      66             : void
      67           6 : dhcp_proxy_walk (fib_protocol_t proto, dhcp_proxy_walk_fn_t fn, void *ctx)
      68             : {
      69           6 :   dhcp_proxy_main_t *dpm = &dhcp_proxy_main;
      70             :   dhcp_proxy_t *server;
      71             :   u32 server_index, i;
      72             : 
      73          15 :   vec_foreach_index (i, dpm->dhcp_server_index_by_rx_fib_index[proto])
      74             :   {
      75           9 :     server_index = dpm->dhcp_server_index_by_rx_fib_index[proto][i];
      76           9 :     if (~0 == server_index)
      77           9 :       continue;
      78             : 
      79           0 :     server = pool_elt_at_index (dpm->dhcp_servers[proto], server_index);
      80             : 
      81           0 :     if (!fn (server, ctx))
      82           0 :       break;
      83             :   }
      84           6 : }
      85             : 
      86             : void
      87           0 : dhcp_vss_walk (fib_protocol_t proto, dhcp_vss_walk_fn_t fn, void *ctx)
      88             : {
      89           0 :   dhcp_proxy_main_t *dpm = &dhcp_proxy_main;
      90             :   mfib_table_t *mfib;
      91             :   dhcp_vss_t *vss;
      92             :   u32 vss_index, i;
      93             :   fib_table_t *fib;
      94             : 
      95           0 :   vec_foreach_index (i, dpm->vss_index_by_rx_fib_index[proto])
      96             :   {
      97           0 :     vss_index = dpm->vss_index_by_rx_fib_index[proto][i];
      98           0 :     if (~0 == vss_index)
      99           0 :       continue;
     100             : 
     101           0 :     vss = pool_elt_at_index (dpm->vss[proto], vss_index);
     102             : 
     103           0 :     if (FIB_PROTOCOL_IP4 == proto)
     104             :       {
     105           0 :         fib = fib_table_get (i, proto);
     106             : 
     107           0 :         if (!fn (vss, fib->ft_table_id, ctx))
     108           0 :           break;
     109             :       }
     110             :     else
     111             :       {
     112           0 :         mfib = mfib_table_get (i, proto);
     113             : 
     114           0 :         if (!fn (vss, mfib->mft_table_id, ctx))
     115           0 :           break;
     116             :       }
     117             :   }
     118           0 : }
     119             : 
     120             : static u32
     121          10 : dhcp_proxy_server_find (dhcp_proxy_t * proxy,
     122             :                         fib_protocol_t proto,
     123             :                         ip46_address_t * addr, u32 server_table_id)
     124             : {
     125             :   dhcp_server_t *server;
     126             :   u32 ii, fib_index;
     127             : 
     128          14 :   vec_foreach_index (ii, proxy->dhcp_servers)
     129             :   {
     130          12 :     server = &proxy->dhcp_servers[ii];
     131          12 :     fib_index = fib_table_find (proto, server_table_id);
     132             : 
     133          12 :     if (ip46_address_is_equal (&server->dhcp_server,
     134           8 :                                addr) &&
     135           8 :         (server->server_fib_index == fib_index))
     136             :       {
     137           8 :         return (ii);
     138             :       }
     139             :   }
     140           2 :   return (~0);
     141             : }
     142             : 
     143             : int
     144           8 : dhcp_proxy_server_del (fib_protocol_t proto,
     145             :                        u32 rx_fib_index,
     146             :                        ip46_address_t * addr, u32 server_table_id)
     147             : {
     148           8 :   dhcp_proxy_main_t *dpm = &dhcp_proxy_main;
     149           8 :   dhcp_proxy_t *proxy = 0;
     150             : 
     151           8 :   proxy = dhcp_get_proxy (dpm, rx_fib_index, proto);
     152             : 
     153           8 :   if (NULL != proxy)
     154             :     {
     155             :       dhcp_server_t *server;
     156             :       u32 index;
     157             : 
     158           8 :       index = dhcp_proxy_server_find (proxy, proto, addr, server_table_id);
     159             : 
     160           8 :       if (~0 != index)
     161             :         {
     162           8 :           server = &proxy->dhcp_servers[index];
     163           8 :           fib_table_unlock (server->server_fib_index, proto, FIB_SOURCE_DHCP);
     164             : 
     165           8 :           vec_del1 (proxy->dhcp_servers, index);
     166             : 
     167           8 :           if (0 == vec_len (proxy->dhcp_servers))
     168             :             {
     169             :               /* no servers left, delete the proxy config */
     170           6 :               dpm->dhcp_server_index_by_rx_fib_index[proto][rx_fib_index] =
     171             :                 ~0;
     172           6 :               vec_free (proxy->dhcp_servers);
     173           6 :               pool_put (dpm->dhcp_servers[proto], proxy);
     174           6 :               return (1);
     175             :             }
     176             :         }
     177             :     }
     178             : 
     179             :   /* the proxy still exists */
     180           2 :   return (0);
     181             : }
     182             : 
     183             : int
     184           8 : dhcp_proxy_server_add (fib_protocol_t proto,
     185             :                        ip46_address_t * addr,
     186             :                        ip46_address_t * src_address,
     187             :                        u32 rx_fib_index, u32 server_table_id)
     188             : {
     189           8 :   dhcp_proxy_main_t *dpm = &dhcp_proxy_main;
     190           8 :   dhcp_proxy_t *proxy = 0;
     191           8 :   int new = 0;
     192             : 
     193           8 :   proxy = dhcp_get_proxy (dpm, rx_fib_index, proto);
     194             : 
     195           8 :   if (NULL == proxy)
     196             :     {
     197          12 :       vec_validate_init_empty (dpm->dhcp_server_index_by_rx_fib_index[proto],
     198             :                                rx_fib_index, ~0);
     199             : 
     200           6 :       pool_get (dpm->dhcp_servers[proto], proxy);
     201           6 :       clib_memset (proxy, 0, sizeof (*proxy));
     202           6 :       new = 1;
     203             : 
     204           6 :       dpm->dhcp_server_index_by_rx_fib_index[proto][rx_fib_index] =
     205           6 :         proxy - dpm->dhcp_servers[proto];
     206             : 
     207           6 :       proxy->dhcp_src_address = *src_address;
     208           6 :       proxy->rx_fib_index = rx_fib_index;
     209             :     }
     210             :   else
     211             :     {
     212           2 :       if (~0 != dhcp_proxy_server_find (proxy, proto, addr, server_table_id))
     213             :         {
     214           0 :           return (new);
     215             :         }
     216             :     }
     217             : 
     218          16 :   dhcp_server_t server = {
     219             :     .dhcp_server = *addr,
     220           8 :     .server_fib_index = fib_table_find_or_create_and_lock (proto,
     221             :                                                            server_table_id,
     222             :                                                            FIB_SOURCE_DHCP),
     223             :   };
     224             : 
     225           8 :   vec_add1 (proxy->dhcp_servers, server);
     226             : 
     227           8 :   return (new);
     228             : }
     229             : 
     230             : typedef struct dhcp4_proxy_dump_walk_ctx_t_
     231             : {
     232             :   fib_protocol_t proto;
     233             :   void *opaque;
     234             :   u32 context;
     235             : } dhcp_proxy_dump_walk_cxt_t;
     236             : 
     237             : static int
     238           0 : dhcp_proxy_dump_walk (dhcp_proxy_t * proxy, void *arg)
     239             : {
     240           0 :   dhcp_proxy_dump_walk_cxt_t *ctx = arg;
     241             : 
     242           0 :   dhcp_send_details (ctx->proto, ctx->opaque, ctx->context, proxy);
     243             : 
     244           0 :   return (1);
     245             : }
     246             : 
     247             : void
     248           6 : dhcp_proxy_dump (fib_protocol_t proto, void *opaque, u32 context)
     249             : {
     250           6 :   dhcp_proxy_dump_walk_cxt_t ctx = {
     251             :     .proto = proto,
     252             :     .opaque = opaque,
     253             :     .context = context,
     254             :   };
     255           6 :   dhcp_proxy_walk (proto, dhcp_proxy_dump_walk, &ctx);
     256           6 : }
     257             : 
     258             : int
     259           0 : dhcp_vss_show_walk (dhcp_vss_t * vss, u32 rx_table_id, void *ctx)
     260             : {
     261           0 :   vlib_main_t *vm = ctx;
     262             : 
     263           0 :   if (vss->vss_type == VSS_TYPE_VPN_ID)
     264             :     {
     265           0 :       u32 oui = ((u32) vss->vpn_id[0] << 16) + ((u32) vss->vpn_id[1] << 8)
     266           0 :         + ((u32) vss->vpn_id[2]);
     267           0 :       u32 fib_id = ((u32) vss->vpn_id[3] << 24) + ((u32) vss->vpn_id[4] << 16)
     268           0 :         + ((u32) vss->vpn_id[5] << 8) + ((u32) vss->vpn_id[6]);
     269           0 :       vlib_cli_output (vm, " fib_table: %d  oui: %d vpn_index: %d",
     270             :                        rx_table_id, oui, fib_id);
     271             :     }
     272           0 :   else if (vss->vss_type == VSS_TYPE_ASCII)
     273           0 :     vlib_cli_output (vm, " fib_table: %d  vpn_id: %s",
     274             :                      rx_table_id, vss->vpn_ascii_id);
     275             :   else
     276           0 :     vlib_cli_output (vm, " fib_table: %d  default global vpn", rx_table_id);
     277             : 
     278           0 :   return (1);
     279             : }
     280             : 
     281             : void
     282           4 : update_vss (dhcp_vss_t * v,
     283             :             u8 vss_type, u8 * vpn_ascii_id, u32 oui, u32 vpn_index)
     284             : {
     285           4 :   v->vss_type = vss_type;
     286           4 :   if (v->vpn_ascii_id)
     287             :     {
     288           0 :       if (v->vpn_ascii_id == (u8 *) ~ 0)
     289           0 :         v->vpn_ascii_id = 0;
     290             :       else
     291           0 :         vec_free (v->vpn_ascii_id);
     292             :     }
     293             : 
     294           4 :   if (vss_type == VSS_TYPE_ASCII)
     295           2 :     v->vpn_ascii_id = vpn_ascii_id;
     296           2 :   else if (vss_type == VSS_TYPE_VPN_ID)
     297             :     {
     298           2 :       v->vpn_id[0] = (oui >> 16) & 0xff;
     299           2 :       v->vpn_id[1] = (oui >> 8) & 0xff;
     300           2 :       v->vpn_id[2] = (oui >> 0) & 0xff;
     301           2 :       v->vpn_id[3] = (vpn_index >> 24) & 0xff;
     302           2 :       v->vpn_id[4] = (vpn_index >> 16) & 0xff;
     303           2 :       v->vpn_id[5] = (vpn_index >> 8) & 0xff;
     304           2 :       v->vpn_id[6] = (vpn_index >> 0) & 0xff;
     305             :     }
     306           4 : }
     307             : 
     308             : int
     309           7 : dhcp_proxy_set_vss (fib_protocol_t proto,
     310             :                     u32 tbl_id,
     311             :                     u8 vss_type,
     312             :                     u8 * vpn_ascii_id, u32 oui, u32 vpn_index, u8 is_del)
     313             : {
     314           7 :   dhcp_proxy_main_t *dm = &dhcp_proxy_main;
     315           7 :   dhcp_vss_t *v = NULL;
     316             :   u32 rx_fib_index;
     317           7 :   int rc = 0;
     318             : 
     319           7 :   if (proto == FIB_PROTOCOL_IP4)
     320           4 :     rx_fib_index = fib_table_find_or_create_and_lock (proto, tbl_id,
     321             :                                                       FIB_SOURCE_DHCP);
     322             :   else
     323           3 :     rx_fib_index = mfib_table_find_or_create_and_lock (proto, tbl_id,
     324             :                                                        MFIB_SOURCE_DHCP);
     325           7 :   v = dhcp_get_vss_info (dm, rx_fib_index, proto);
     326             : 
     327           7 :   if (NULL != v)
     328             :     {
     329           3 :       if (is_del)
     330             :         {
     331             :           /* release the lock held on the table when the VSS
     332             :            * info was created */
     333           3 :           dhcp_proxy_rx_table_unlock (proto, rx_fib_index);
     334             : 
     335           3 :           vec_free (v->vpn_ascii_id);
     336           3 :           pool_put (dm->vss[proto], v);
     337           3 :           dm->vss_index_by_rx_fib_index[proto][rx_fib_index] = ~0;
     338             :         }
     339             :       else
     340             :         {
     341           0 :           update_vss (v, vss_type, vpn_ascii_id, oui, vpn_index);
     342             :         }
     343             :     }
     344             :   else
     345             :     {
     346           4 :       if (is_del)
     347           0 :         rc = VNET_API_ERROR_NO_SUCH_ENTRY;
     348             :       else
     349             :         {
     350             :           /* create a new entry */
     351          10 :           vec_validate_init_empty (dm->vss_index_by_rx_fib_index[proto],
     352             :                                    rx_fib_index, ~0);
     353             : 
     354             :           /* hold a lock on the table whilst the VSS info exist */
     355           4 :           pool_get (dm->vss[proto], v);
     356           4 :           update_vss (v, vss_type, vpn_ascii_id, oui, vpn_index);
     357           4 :           dm->vss_index_by_rx_fib_index[proto][rx_fib_index] =
     358           4 :             v - dm->vss[proto];
     359           4 :           dhcp_proxy_rx_table_lock (proto, rx_fib_index);
     360             :         }
     361             :     }
     362             : 
     363             :   /* Release the lock taken during the create_or_lock at the start */
     364           7 :   dhcp_proxy_rx_table_unlock (proto, rx_fib_index);
     365             : 
     366           7 :   return (rc);
     367             : }
     368             : 
     369             : /*
     370             :  * fd.io coding-style-patch-verification: ON
     371             :  *
     372             :  * Local Variables:
     373             :  * eval: (c-set-style "gnu")
     374             :  * End:
     375             :  */

Generated by: LCOV version 1.14