LCOV - code coverage report
Current view: top level - vnsw/agent/services/multicast/grpmgmt - gmpr_instance.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 59 82 72.0 %
Date: 2026-08-03 02:19:58 Functions: 4 5 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* $Id: gmpr_instance.c 346474 2009-11-14 10:18:58Z ssiano $
       2             :  *
       3             :  * gmpr_instance.c - GMP Router-side instance support
       4             :  *
       5             :  * Dave Katz, March 2008
       6             :  *
       7             :  * Copyright (c) 2008, Juniper Networks, Inc.
       8             :  * All rights reserved.
       9             :  */
      10             : #include "gmpx_basic_types.h"
      11             : #include "gmp.h"
      12             : #include "gmpx_environment.h"
      13             : #include "gmp_private.h"
      14             : #include "gmp_router.h"
      15             : #include "gmpr_private.h"
      16             : #include "igmp_protocol.h"
      17             : #include "mld_proto.h"
      18             : 
      19             : task_thread gmpr_global_instance_thread;        /* Thread of instances */
      20             : 
      21             : 
      22             : /*
      23             :  * gmpr_query_smear_expiry
      24             :  * 
      25             :  * The query timer smear timer has expired.  Smear the query timers and
      26             :  * restart the smear timer.
      27             :  */
      28             : static void
      29           0 : gmpr_query_smear_expiry (gmpx_timer *timer, void *context)
      30             : {
      31             :     gmpr_instance *instance;
      32             : 
      33           0 :     instance = context;
      34             : 
      35             :     /* Smear the timers. */
      36             : 
      37           0 :     gmpx_smear_timer_group(instance->rinst_proto, GMP_TIMER_GROUP_GEN_QUERY);
      38             : 
      39             :     /* Restart the timer. */
      40             : 
      41           0 :     gmpx_start_timer(timer, GMP_QUERY_SMEAR_IVL, 0);
      42             : 
      43             :     /* We're no longer accelerated. */
      44             : 
      45           0 :     instance->rinst_smear_timer_accelerated = FALSE;
      46           0 : }
      47             : 
      48             : 
      49             : /*
      50             :  * gmpr_accelerate_query_smear
      51             :  *
      52             :  * Schedule a smearing of general query timers soon, if this has not already
      53             :  * been done recently.
      54             :  */
      55             : void
      56        1833 : gmpr_accelerate_query_smear (gmpr_instance *instance)
      57             : {
      58             : #if 0
      59             :     /* Do it if it's not already scheduled. */
      60             : 
      61             :     if (!instance->rinst_smear_timer_accelerated) {
      62             :         gmpx_start_timer(instance->rinst_smear_timer,
      63             :                          GMP_QUERY_QUICK_SMEAR_IVL, 0);
      64             :         instance->rinst_smear_timer_accelerated = TRUE;
      65             :     }
      66             : #endif
      67        1833 : }
      68             : 
      69             : 
      70             : /*
      71             :  * gmpr_instance_create
      72             :  *
      73             :  * Create a router-side GMP instance.
      74             :  *
      75             :  * Returns a pointer to the instance, or NULL if we're out of memory.
      76             :  */
      77             : gmpr_instance *
      78         125 : gmpr_instance_create (gmp_proto proto, void *inst_context)
      79             : {
      80             :     gmpr_instance *instance;
      81             :     boolean first_instance;
      82             : 
      83             :     /* Note if this is the first instance. */
      84             : 
      85             :     first_instance =
      86         125 :         thread_circular_thread_empty(&gmpr_global_instance_thread);
      87             : 
      88             :     /* Allocate the block. */
      89             : 
      90         125 :     instance = gmpx_malloc_block(gmpr_instance_tag);
      91             : 
      92         125 :     if (instance) {                     /* Got one */
      93             : 
      94             :         /* Save the context. */
      95             : 
      96         125 :         instance->rinst_context = inst_context;
      97             : 
      98             :         /* Set the protocol type. */
      99             : 
     100         125 :         instance->rinst_proto = proto;
     101             : 
     102             :         /* Set the address length and minimum max resp field value. */
     103             : 
     104         125 :         switch (proto) {
     105         125 :           case GMP_PROTO_IGMP:
     106         125 :             instance->rinst_addrlen = IPV4_ADDR_LEN;
     107         125 :             instance->rinst_min_max_resp = IGMP_MAX_RESP_MSEC;
     108         125 :             break;
     109             : 
     110           0 :           case GMP_PROTO_MLD:
     111           0 :             instance->rinst_addrlen = IPV6_ADDR_LEN;
     112           0 :             instance->rinst_min_max_resp = MLD_MAX_RESP_MSEC;
     113           0 :             break;
     114             : 
     115           0 :           default:
     116           0 :             gmpx_assert(FALSE);         /* Invalid protocol type! */
     117             :         }
     118             : 
     119             :         /* Initialize the patricia trees. */
     120             : 
     121         125 :         instance->rinst_intfs = 
     122         125 :             gmpx_patroot_init(sizeof(gmpx_intf_id),
     123             :                               GMPX_PATRICIA_OFFSET(gmpr_intf,
     124             :                                                    rintf_inst_patnode,
     125             :                                                    rintf_id));
     126         125 :         if (!instance->rinst_intfs) { /* No memory */
     127           0 :             gmpx_free_block(gmpr_instance_tag, instance);
     128           0 :             return NULL;
     129             :         }
     130         125 :         instance->rinst_global_state_root =
     131         125 :             gmpx_patroot_init(instance->rinst_addrlen,
     132             :                               GMPX_PATRICIA_OFFSET(gmpr_global_group,
     133             :                                                    global_group_node,
     134             :                                                    global_group_addr));
     135         125 :         if (!instance->rinst_global_state_root) { /* No memory */
     136           0 :             gmpx_patroot_destroy(instance->rinst_intfs);
     137           0 :             gmpx_free_block(gmpr_instance_tag, instance);
     138           0 :             return NULL;
     139             :         }
     140             : 
     141             :         /* Set the magic number and link it into the list. */
     142             : 
     143         125 :         instance->rinst_magic = GMPR_INSTANCE_MAGIC;
     144         125 :         thread_circular_add_top(&gmpr_global_instance_thread,
     145             :                                 &instance->rinst_thread);
     146             : 
     147             :         /* Initialize thread heads. */
     148             : 
     149         125 :         thread_new_circular_thread(&instance->rinst_client_thread);
     150         125 :         thread_new_circular_thread(&instance->rinst_startup_intf_thread);
     151             : 
     152             :         /* Create the client ordinal context. */
     153             : 
     154         125 :         instance->rinst_ord_handle = ord_create_context(ORD_COMPACT);
     155         125 :         if (!instance->rinst_ord_handle)
     156           0 :             return NULL;                /* Out of memory */
     157             : 
     158             :         /* Initialize the address catalog. */
     159             : 
     160         125 :         if (gmp_init_addr_catalog(&instance->rinst_addr_cat,
     161             :                                   instance->rinst_addrlen) < 0) {
     162           0 :             return NULL;                /* Out of memory */
     163             :         }
     164             : 
     165             :         /* Create and start the smear timer. */
     166             : 
     167         125 :         instance->rinst_smear_timer =
     168         125 :             gmpx_create_timer(instance->rinst_context, "GMP query smear timer",
     169             :                               gmpr_query_smear_expiry, instance);
     170         125 :         gmpr_accelerate_query_smear(instance);
     171             : 
     172             :         /* If this is the first instance, register with the packet handler. */
     173             : 
     174         125 :         if (first_instance)
     175         125 :             gmpr_register_packet_handler();
     176             : 
     177             :         /* Register the protocol. */
     178             : 
     179         125 :         gmpp_enab_disab_proto(GMP_ROLE_ROUTER, proto, TRUE);
     180             :     }
     181             : 
     182         125 :     return instance;
     183             : }
     184             : 
     185             : 
     186             : /*
     187             :  * gmpr_get_instance
     188             :  * 
     189             :  * Return an instance pointer, given an instance ID.
     190             :  *
     191             :  * Verifies that the instance ID is valid.
     192             :  */
     193             : gmpr_instance *
     194        8915 : gmpr_get_instance (gmp_instance_id instance_id)
     195             : {
     196             :     gmpr_instance *instance;
     197             : 
     198             :     /* Do the (trivial) conversion. */
     199             : 
     200        8915 :     instance = instance_id;
     201             : 
     202             :     /* Verify the magic number. */
     203             : 
     204        8915 :     gmpx_assert(instance->rinst_magic == GMPR_INSTANCE_MAGIC);
     205             : 
     206        8915 :     return instance;
     207             : }
     208             : 
     209             : 
     210             : /*
     211             :  * gmpr_instance_destroy
     212             :  *
     213             :  * Destroy an instance and all things associated with it.
     214             :  */
     215             : void
     216         125 : gmpr_instance_destroy (gmpr_instance *instance)
     217             : {
     218             :     gmp_proto inst_proto;
     219             :     task_thread *thread_ptr;
     220             :     boolean found_proto;
     221             : 
     222             :     /* Blast all clients on the instance. */
     223             : 
     224         125 :     gmpr_destroy_instance_clients(instance);
     225             : 
     226             :     /* Blast all interfaces on the instance. */
     227             : 
     228         125 :     gmpr_destroy_instance_intfs(instance);
     229             : 
     230         125 :     inst_proto = instance->rinst_proto;      /* Remember for a bit */
     231             : 
     232             :     /* Make some paranoia checks. */
     233             : 
     234         125 :     gmpx_assert(thread_circular_thread_empty(&instance->rinst_client_thread));
     235         125 :     gmpx_assert(
     236             :         thread_circular_thread_empty(&instance->rinst_startup_intf_thread));
     237         125 :     gmpx_assert(!gmpx_patricia_lookup_least(instance->rinst_intfs));
     238         125 :     gmpx_assert(
     239             :         !gmpx_patricia_lookup_least(instance->rinst_global_state_root));
     240             : 
     241             :     /* Toss the trees. */
     242             : 
     243         125 :     gmpx_patroot_destroy(instance->rinst_intfs);
     244         125 :     gmpx_patroot_destroy(instance->rinst_global_state_root);
     245             : 
     246             :     /* Toss the client ordinals. */
     247             : 
     248         125 :     ord_destroy_context(instance->rinst_ord_handle);
     249             : 
     250             :     /* Destroy the address catalog. */
     251             : 
     252         125 :     gmp_destroy_addr_catalog(&instance->rinst_addr_cat);
     253             : 
     254             :     /* Destroy the smear timer. */
     255             : 
     256         125 :     gmpx_destroy_timer(instance->rinst_smear_timer);
     257             : 
     258             :     /* Delink the block and free it. */
     259             : 
     260         125 :     thread_remove(&instance->rinst_thread);
     261         125 :     gmpx_free_block(gmpr_instance_tag, instance);
     262             : 
     263             :     /* If this was the last instance for a protocol, disable it. */
     264             : 
     265         125 :     found_proto = FALSE;
     266         125 :     FOR_ALL_CIRCULAR_THREAD_ENTRIES(&gmpr_global_instance_thread, thread_ptr) {
     267           0 :         instance = gmpr_thread_to_instance(thread_ptr);
     268           0 :         if (instance->rinst_proto == inst_proto) {
     269           0 :             found_proto = TRUE;
     270           0 :             break;
     271             :         }
     272             :     }
     273         125 :     if (!found_proto)
     274         125 :         gmpp_enab_disab_proto(GMP_ROLE_ROUTER, inst_proto, FALSE);
     275             :         
     276             :     /* If that was the last instance, deregister with the packet handler. */
     277             : 
     278         125 :     if (thread_circular_thread_empty(&gmpr_global_instance_thread))
     279         125 :         gmpp_deregister(GMP_ROLE_ROUTER);
     280         125 : }

Generated by: LCOV version 1.14