LCOV - code coverage report
Current view: top level - plugins/igmp - igmp_group.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 81 95 85.3 %
Date: 2023-07-05 22:20:52 Functions: 12 14 85.7 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * Copyright (c) 2018 Cisco and/or its affiliates.
       4             :  * Licensed under the Apache License, Version 2.0 (the "License");
       5             :  * you may not use this file except in compliance with the License.
       6             :  * You may obtain a copy of the License at:
       7             :  *
       8             :  *     http://www.apache.org/licenses/LICENSE-2.0
       9             :  *
      10             :  * Unless required by applicable law or agreed to in writing, software
      11             :  * distributed under the License is distributed on an "AS IS" BASIS,
      12             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13             :  * See the License for the specific language governing permissions and
      14             :  * limitations under the License.
      15             :  *------------------------------------------------------------------
      16             :  */
      17             : 
      18             : #include <igmp/igmp_group.h>
      19             : #include <igmp/igmp.h>
      20             : 
      21             : void
      22          29 : igmp_group_free_all_srcs (igmp_group_t * group)
      23             : {
      24             :   igmp_src_t *src;
      25             : 
      26             :   /* *INDENT-OFF* */
      27        2256 :   FOR_EACH_SRC (src, group, IGMP_FILTER_MODE_INCLUDE,
      28             :     ({
      29             :       igmp_src_free(src);
      30             :     }));
      31             :   /* *INDENT-ON* */
      32             : 
      33          29 :   hash_free (group->igmp_src_by_key[IGMP_FILTER_MODE_INCLUDE]);
      34          29 :   hash_free (group->igmp_src_by_key[IGMP_FILTER_MODE_EXCLUDE]);
      35          29 : }
      36             : 
      37             : void
      38          12 : igmp_group_src_remove (igmp_group_t * group, igmp_src_t * src)
      39             : {
      40          24 :   hash_unset_mem (group->igmp_src_by_key[IGMP_FILTER_MODE_INCLUDE], src->key);
      41          24 :   hash_unset_mem (group->igmp_src_by_key[IGMP_FILTER_MODE_EXCLUDE], src->key);
      42          12 : }
      43             : 
      44             : igmp_src_t *
      45         446 : igmp_group_src_update (igmp_group_t * group,
      46             :                        const igmp_key_t * skey, igmp_mode_t mode)
      47             : {
      48             :   igmp_src_t *src;
      49             : 
      50         446 :   src = igmp_src_lookup (group, skey);
      51             : 
      52         446 :   if (NULL == src)
      53             :     {
      54         444 :       src = igmp_src_alloc (igmp_group_index (group), skey, mode);
      55             : 
      56         888 :       hash_set_mem (group->igmp_src_by_key[IGMP_FILTER_MODE_INCLUDE],
      57             :                     src->key, igmp_src_index (src));
      58             :     }
      59             :   else
      60             :     {
      61           2 :       igmp_src_refresh (src);
      62             :     }
      63             : 
      64         446 :   return (src);
      65             : }
      66             : 
      67             : void
      68          18 : igmp_group_clear (igmp_group_t ** group)
      69             : {
      70             :   igmp_config_t *config;
      71             :   u32 ii;
      72             : 
      73          18 :   ASSERT (*group);
      74             : 
      75          18 :   config = igmp_config_get ((*group)->config);
      76             : 
      77             :   /* If interface is in ROUTER mode and IGMP proxy is enabled
      78             :    * remove mfib path.
      79             :    */
      80          18 :   if (config->mode == IGMP_MODE_ROUTER)
      81             :     {
      82           7 :       igmp_proxy_device_mfib_path_add_del (*group, /* add */ 0);
      83             :     }
      84             : 
      85          18 :   IGMP_DBG ("clear-group: %U %U",
      86             :             format_igmp_key, (*group)->key,
      87             :             format_vnet_sw_if_index_name,
      88             :             vnet_get_main (), config->sw_if_index);
      89             : 
      90          18 :   igmp_group_free_all_srcs (*group);
      91             : 
      92          90 :   for (ii = 0; ii < IGMP_GROUP_N_TIMERS; ii++)
      93             :     {
      94          72 :       igmp_timer_retire (&(*group)->timers[ii]);
      95             :     }
      96             : 
      97          36 :   hash_unset_mem (config->igmp_group_by_key, (*group)->key);
      98          18 :   clib_mem_free ((*group)->key);
      99          18 :   pool_put (igmp_main.groups, *group);
     100          18 :   *group = 0;
     101          18 : }
     102             : 
     103             : igmp_group_t *
     104          18 : igmp_group_alloc (igmp_config_t * config,
     105             :                   const igmp_key_t * gkey, igmp_filter_mode_t mode)
     106             : {
     107          18 :   igmp_main_t *im = &igmp_main;
     108             :   igmp_group_t *group;
     109             :   u32 ii;
     110             : 
     111          18 :   IGMP_DBG ("new-group: %U", format_igmp_key, gkey);
     112          18 :   pool_get (im->groups, group);
     113          18 :   clib_memset (group, 0, sizeof (igmp_group_t));
     114          18 :   group->key = clib_mem_alloc (sizeof (igmp_key_t));
     115          18 :   clib_memcpy (group->key, gkey, sizeof (igmp_key_t));
     116          18 :   group->igmp_src_by_key[IGMP_FILTER_MODE_INCLUDE] =
     117          18 :     hash_create_mem (0, sizeof (igmp_key_t), sizeof (uword));
     118          18 :   group->igmp_src_by_key[IGMP_FILTER_MODE_EXCLUDE] =
     119          18 :     hash_create_mem (0, sizeof (igmp_key_t), sizeof (uword));
     120          18 :   group->router_filter_mode = mode;
     121          18 :   group->config = igmp_config_index (config);
     122          18 :   group->n_reports_sent = 0;
     123             : 
     124          90 :   for (ii = 0; ii < IGMP_GROUP_N_TIMERS; ii++)
     125          72 :     group->timers[ii] = IGMP_TIMER_ID_INVALID;
     126             : 
     127          36 :   hash_set_mem (config->igmp_group_by_key, group->key, group - im->groups);
     128             : 
     129             :   /* If interface is in ROUTER mode and IGMP proxy is enabled
     130             :    * add mfib path.
     131             :    */
     132          18 :   if (config->mode == IGMP_MODE_ROUTER)
     133             :     {
     134           7 :       igmp_proxy_device_mfib_path_add_del (group, /* add */ 1);
     135             :     }
     136             : 
     137          18 :   return (group);
     138             : }
     139             : 
     140             : /**
     141             :  * the set of present sources minus the new set
     142             :  */
     143             : ip46_address_t *
     144          11 : igmp_group_present_minus_new (igmp_group_t * group,
     145             :                               igmp_filter_mode_t mode,
     146             :                               const ip46_address_t * saddrs)
     147             : {
     148             :   const ip46_address_t *s1;
     149             :   ip46_address_t *pmn;
     150             :   igmp_src_t *src;
     151             :   u32 found;
     152             : 
     153          11 :   pmn = NULL;
     154             : 
     155             :   /* *INDENT-OFF* */
     156          11 :   if (0 == vec_len(saddrs))
     157             :     {
     158        1642 :       FOR_EACH_SRC(src, group, mode,
     159             :         ({
     160             :           vec_add1(pmn, *src->key);
     161             :         }));
     162             :     }
     163             :   else
     164             :     {
     165         204 :       FOR_EACH_SRC(src, group, mode,
     166             :         ({
     167             :           found = 0;
     168             :           vec_foreach(s1, saddrs)
     169             :             {
     170             :               if (ip46_address_is_equal(s1, src->key))
     171             :                 {
     172             :                   found = 1;
     173             :                   break;
     174             :                 }
     175             :             }
     176             : 
     177             :           if (!found)
     178             :             vec_add1(pmn, *src->key);
     179             :         }));
     180             :     }
     181             :   /* *INDENT-ON* */
     182             : 
     183          11 :   return (pmn);
     184             : }
     185             : 
     186             : /**
     187             :  * the set of new sources minus the present set
     188             :  */
     189             : ip46_address_t *
     190          11 : igmp_group_new_minus_present (igmp_group_t * group,
     191             :                               igmp_filter_mode_t mode,
     192             :                               const ip46_address_t * saddrs)
     193             : {
     194             :   const ip46_address_t *s1;
     195             :   ip46_address_t *npm;
     196             :   igmp_src_t *src;
     197             :   u32 found;
     198             : 
     199          11 :   npm = NULL;
     200             : 
     201             :   /* *INDENT-OFF* */
     202          27 :   vec_foreach(s1, saddrs)
     203             :     {
     204          16 :       found = 0;
     205        1296 :       FOR_EACH_SRC(src, group, mode,
     206             :         ({
     207             :           if (ip46_address_is_equal(s1, src->key))
     208             :             {
     209             :               found = 1;
     210             :               break;
     211             :             }
     212             :         }));
     213             : 
     214          16 :       if (!found)
     215           2 :         vec_add1(npm, *s1);
     216             :     }
     217             :   /* *INDENT-ON* */
     218             : 
     219          11 :   return (npm);
     220             : }
     221             : 
     222             : ip46_address_t *
     223           6 : igmp_group_new_intersect_present (igmp_group_t * group,
     224             :                                   igmp_filter_mode_t mode,
     225             :                                   const ip46_address_t * saddrs)
     226             : {
     227             :   ip46_address_t *intersect;
     228             :   const ip46_address_t *s1;
     229             :   igmp_src_t *src;
     230             : 
     231           6 :   intersect = NULL;
     232             : 
     233             :   /* *INDENT-OFF* */
     234         404 :   FOR_EACH_SRC(src, group, mode,
     235             :     ({
     236             :       vec_foreach(s1, saddrs)
     237             :         {
     238             :           if (s1->ip4.as_u32 == src->key->ip4.as_u32)
     239             :             {
     240             :               vec_add1(intersect, *s1);
     241             :               break;
     242             :             }
     243             :         }
     244             :     }));
     245             :   /* *INDENT-ON* */
     246             : 
     247           6 :   return (intersect);
     248             : }
     249             : 
     250             : u32
     251          23 : igmp_group_n_srcs (const igmp_group_t * group, igmp_filter_mode_t mode)
     252             : {
     253          23 :   return (hash_elts (group->igmp_src_by_key[mode]));
     254             : }
     255             : 
     256             : 
     257             : igmp_src_t *
     258         461 : igmp_src_lookup (igmp_group_t * group, const igmp_key_t * key)
     259             : {
     260             :   uword *p;
     261         461 :   igmp_src_t *src = NULL;
     262         461 :   if (!group)
     263           0 :     return NULL;
     264             : 
     265         461 :   p = hash_get_mem (group->igmp_src_by_key[IGMP_FILTER_MODE_INCLUDE], key);
     266         461 :   if (p)
     267          14 :     src = vec_elt_at_index (igmp_main.srcs, p[0]);
     268             : 
     269         461 :   return src;
     270             : }
     271             : 
     272             : u32
     273         465 : igmp_group_index (const igmp_group_t * g)
     274             : {
     275         465 :   return (g - igmp_main.groups);
     276             : }
     277             : 
     278             : igmp_group_t *
     279          50 : igmp_group_get (u32 index)
     280             : {
     281          50 :   return (pool_elt_at_index (igmp_main.groups, index));
     282             : }
     283             : 
     284             : u8 *
     285           0 : format_igmp_group_timer_type (u8 * s, va_list * args)
     286             : {
     287           0 :   igmp_group_timer_type_t type = va_arg (*args, igmp_group_timer_type_t);
     288             : 
     289           0 :   switch (type)
     290             :     {
     291             : #define _(v,t) case IGMP_GROUP_TIMER_##v: return (format (s, "%s", t));
     292           0 :       foreach_igmp_group_timer
     293             : #undef _
     294             :     }
     295           0 :   return (s);
     296             : }
     297             : 
     298             : u8 *
     299           0 : format_igmp_group (u8 * s, va_list * args)
     300             : {
     301           0 :   igmp_group_t *group = va_arg (*args, igmp_group_t *);
     302           0 :   u32 indent = va_arg (*args, u32);
     303             :   igmp_src_t *src;
     304             :   u32 ii;
     305             : 
     306           0 :   s = format (s, "%U%U",
     307             :               format_white_space, indent, format_igmp_key, group->key);
     308             : 
     309           0 :   for (ii = 0; ii < IGMP_GROUP_N_TIMERS; ii++)
     310           0 :     s = format (s, "\n%U  %U:%U", format_white_space, indent,
     311             :                 format_igmp_group_timer_type, ii,
     312             :                 format_igmp_timer_id, group->timers[ii]);
     313             : 
     314             :   /* *INDENT-OFF* */
     315           0 :   FOR_EACH_SRC (src, group, IGMP_FILTER_MODE_INCLUDE,
     316             :   ({
     317             :     s = format (s, "\n%U", format_igmp_src, src, indent+4);
     318             :   }));
     319             :   /* *INDENT-ON* */
     320             : 
     321           0 :   return (s);
     322             : }
     323             : 
     324             : /*
     325             :  * fd.io coding-style-patch-verification: ON
     326             :  *
     327             :  * Local Variables:
     328             :  * eval: (c-set-style "gnu")
     329             :  * End:
     330             :  */

Generated by: LCOV version 1.14