diff options
author | Neale Ranns <nranns@cisco.com> | 2018-06-07 23:48:20 -0700 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2018-07-09 21:10:53 +0000 |
commit | 947ea6222dad1ef04595c34273e9231395aef443 (patch) | |
tree | 8990854b2901ff8cc2241b9abfc99b0b4b54d517 /src/plugins/igmp/igmp.h | |
parent | dd47ecadcf63772a6037a1bb3715772d80e87f51 (diff) |
IGMP improvements
- Enable/Disable an interface for IGMP
- improve logging
- refactor common code
- no orphaned timers
- IGMP state changes in main thread only
- Large groups split over multiple state-change reports
- SSM range configuration API.
- more tests
Change-Id: If5674f1044e7e97274a711f47807c9ba689d7b9a
Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/plugins/igmp/igmp.h')
-rw-r--r-- | src/plugins/igmp/igmp.h | 497 |
1 files changed, 92 insertions, 405 deletions
diff --git a/src/plugins/igmp/igmp.h b/src/plugins/igmp/igmp.h index b8759ffa3b1..bf123ddbb79 100644 --- a/src/plugins/igmp/igmp.h +++ b/src/plugins/igmp/igmp.h @@ -23,436 +23,123 @@ #include <vlibapi/api_helper_macros.h> #include <vnet/ip/igmp_packet.h> #include <vnet/adj/adj_mcast.h> +#include <igmp/igmp_types.h> #include <igmp/igmp_format.h> +#include <igmp/igmp_timer.h> +#include <igmp/igmp_group.h> +#include <igmp/igmp_config.h> -#define IGMP_QUERY_TIMER (60) -#define IGMP_SRC_TIMER (3 * IGMP_QUERY_TIMER) +/** + * RFC 3376 Section 8.1 + */ #define IGMP_DEFAULT_ROBUSTNESS_VARIABLE (2) -#define ENABLE_IGMP_DBG 0 +#define IGMP_DBG(...) \ + vlib_log_debug (igmp_main.logger, __VA_ARGS__); -#if ENABLE_IGMP_DBG == 1 -#define IGMP_DBG(...) clib_warning(__VA_ARGS__) +/** + * General Query address - 224.0.0.1 + * Membership Report address - 224.0.0.22 + * SSM default range 232/8 + */ +#if CLIB_ARCH_IS_BIG_ENDIAN +#define IGMP_GENERAL_QUERY_ADDRESS (0xE0000001) +#define IGMP_MEMBERSHIP_REPORT_ADDRESS (0xE0000016) +#define IGMP_SSM_DEFAULT (0xE8000000) #else -#define IGMP_DBG(...) -#endif /* ENABLE_IGMP_DBG */ - -/** General Query address - 224.0.0.1 */ -#define IGMP_GENERAL_QUERY_ADDRESS (0xE0000001) -/** Membership Report address - 224.0.0.22 */ -#define IGMP_MEMBERSHIP_REPORT_ADDRESS (0xE0000016) +#define IGMP_GENERAL_QUERY_ADDRESS (0x010000E0) +#define IGMP_MEMBERSHIP_REPORT_ADDRESS (0x160000E0) +#define IGMP_SSM_DEFAULT (0x000000E8) +#endif /** helper macro to get igmp mebership group from pointer plus offset */ -#define group_ptr(p, l) ((igmp_membership_group_v3_t *)((char*)p + l)) - -#define foreach_igmp_config_flag \ - _(0, QUERY_RESP_RECVED, "query_response_received") \ - _(1, CAN_SEND_REPORT, "can_send_report") \ - _(2, CLI_API_CONFIGURED, "cli/api") - -typedef enum -{ -#define _(a,b,c) IGMP_CONFIG_FLAG_##b = (1 << a), - foreach_igmp_config_flag -#undef _ -} igmp_config_flag_t; - -enum -{ - IGMP_PROCESS_EVENT_UPDATE_TIMER = 1, -} igmp_process_event_t; - -/*! Igmp versions */ -typedef enum -{ - IGMP_V1, - IGMP_V2, - IGMP_V3, -} igmp_ver_t; - -struct igmp_config_t_; - -typedef struct igmp_config_t_ igmp_config_t; - -struct igmp_group_t_; - -typedef struct igmp_group_t_ igmp_group_t; - -/** \brief create message - @param b - vlib buffer - @param config - igmp configuration - @param group - igmp group - - Populate supplied bufefr with IGMP message. -*/ -typedef void (create_msg_t) (vlib_buffer_t * b, igmp_config_t * config, - igmp_group_t * group); - -/** \brief igmp key - @param data - key data - @param group_type - membership group type -*/ -typedef struct -{ - u64 data[2]; /*!< ip46_address_t.as_u64 */ - u64 group_type; /*!< zero in case of source key */ -} igmp_key_t; - -/** \brief igmp source - @param addr - ip4/6 source address - @param exp_time - expiration time - @param key - pointer to key -*/ -typedef struct -{ - ip46_address_t addr; - - f64 exp_time; - - igmp_key_t *key; -} igmp_src_t; - -/** \brief igmp group - @param addr - ip4/6 group address - @param exp_time - expiration time - @param key - pointer to key - @param type - membership group type - @param n_srcs - number of sources - @param flags - igmp group flags - @param igmp_src_by_key - source by key hash - @param srcs - pool of sources -*/ -typedef struct igmp_group_t_ -{ - ip46_address_t addr; - - f64 exp_time; - - igmp_key_t *key; - - igmp_membership_group_v3_type_t type; +#define group_ptr(p, l) ((igmp_membership_group_v3_t *)((u8*)(p) + (l))) +#define group_cptr(p, l) ((const igmp_membership_group_v3_t *)((u8*)(p) + (l))) - u16 n_srcs; - - u8 flags; -/** reponse to query was received */ -#define IGMP_GROUP_FLAG_QUERY_RESP_RECVED (1 << 0) - - uword *igmp_src_by_key; - igmp_src_t *srcs; -} igmp_group_t; - -/** \brief igmp configuration - @param sw_if_index - interface sw_if_index - @param adj_index - adjacency index - @param next_create_msg - specify next igmp message - @param igmp_ver - igmp version - @param robustness_var - robustness variable - @param flags - igmp configuration falgs - @param igmp_group_by_key - group by key hash - @param groups - pool of groups -*/ -typedef struct igmp_config_t_ -{ - u32 sw_if_index; - - adj_index_t adj_index; - - create_msg_t *next_create_msg; - - igmp_ver_t igmp_ver; - - u8 robustness_var; - - u8 flags; - - uword *igmp_group_by_key; - - igmp_group_t *groups; -} igmp_config_t; - -struct igmp_timer_t_; - -typedef struct igmp_timer_t_ igmp_timer_t; - -typedef struct -{ - u8 *name; - igmp_type_t type; -} igmp_type_info_t; - -typedef struct -{ - u8 *name; - igmp_membership_group_v3_type_t type; -} igmp_report_type_info_t; - -/** \brief igmp main - @param msg_id_base - API message ID base - @param igmp_api_client_by_client_index - get api client by client_index - @param api_clients - pool of api clients registered for join/leave notifications - @param igmp_config_by_sw_if_index - get config index by config key - @param configs - pool of igmp configurations - @param buffers - buffer cache - @param timers - pool of igmp timers - @param type_infos - igmp type info - @param report_type_infos - igmp report type info - @param type_info_by_type - - @param report_type_info_by_report_type - - @param general_query_address - 224.0.0.1 - @param membership_report_address - 224.0.0.22 -*/ +/** + * collection of data related to IGMP + */ typedef struct igmp_main_t_ { + /** + * API base message ID + */ u16 msg_id_base; uword *igmp_api_client_by_client_index; + /** + * API client registered for events + */ vpe_client_registration_t *api_clients; - uword *igmp_config_by_sw_if_index; + /** + * per-interface DB of configs + */ + u32 *igmp_config_by_sw_if_index; - igmp_config_t *configs; + /** + * the number of igmp configs for each mfib_index (VRF) + */ + u32 *n_configs_per_mfib_index; - igmp_timer_t *timers; + /** + * logger - VLIB log class + */ + vlib_log_class_t logger; - igmp_type_info_t *type_infos; - igmp_report_type_info_t *report_type_infos; + /** + * pool of configs + */ + igmp_config_t *configs; - uword *type_info_by_type; - uword *report_type_info_by_report_type; + /** + * pool of groups + */ + igmp_group_t *groups; + /** + * pool of sources + */ + igmp_src_t *srcs; } igmp_main_t; extern igmp_main_t igmp_main; -/** \brief igmp timer function - @param vm - vlib main - @param rt - vlib runtime node - @param im - igmp main - @param timer - igmp timer -*/ -typedef void (igmp_timer_function_t) (vlib_main_t * vm, - vlib_node_runtime_t * rt, - igmp_main_t * im, igmp_timer_t * timer); - -/** \brief igmp timer - @param exp_time - expiration time - @param func - function to call on timer expiration - @param sw_if_index - interface sw_if_index - @param data - custom data -*/ -typedef struct igmp_timer_t_ -{ - f64 exp_time; - igmp_timer_function_t *func; - - u32 sw_if_index; - void *data; -} igmp_timer_t; - -extern vlib_node_registration_t igmp_timer_process_node; -extern vlib_node_registration_t igmp_input_node; -extern vlib_node_registration_t igmp_parse_query_node; -extern vlib_node_registration_t igmp_parse_report_node; - -/** \brief igmp listen - @param vm - vlib main - @param enable - 0 == remove (S,G), else add (S,G) - @param sw_if_index - interface sw_if_index - @param saddr - source address - @param gaddr - group address - @param flags - igmp configuration flags - - Add/del (S,G) on an interface. If user configured, - send a status change report from the interface. - If a report was received on interface notify registered api clients. -*/ -int igmp_listen (vlib_main_t * vm, u8 enable, u32 sw_if_index, - ip46_address_t saddr, ip46_address_t gaddr, u8 flags); - -/** \brief igmp clear config - @param config - igmp configuration - - Clear all (S,G)s on specified config and remove this config from pool. -*/ -void igmp_clear_config (igmp_config_t * config); - -/** \brief igmp clear group - @param config - igmp configuration - @param group - the group to be removed - - Remove this group from interface (specified by configuration). -*/ -void igmp_clear_group (igmp_config_t * config, igmp_group_t * group); - -/** \brief igmp sort timers - @param timers - pool of igmp timers - - Sort igmp timers, so that the first to expire is at end. -*/ -void igmp_sort_timers (igmp_timer_t * timers); - -/** \brief igmp create int timer - @param time - expiration time (at this time the timer will expire) - @param sw_if_index - interface sw_if_index - @param func - function to all after timer expiration - - - Creates new interface timer. Delayed reports, query msg, query resp. -*/ -void igmp_create_int_timer (f64 time, u32 sw_if_index, - igmp_timer_function_t * func); - -/** \brief igmp create group timer - @param time - expiration time (at this time the timer will expire) - @param sw_if_index - interface sw_if_index - @param gkey - key to find the group by - @param func - function to all after timer expiration - - Creates new group timer. -*/ -void igmp_create_group_timer (f64 time, u32 sw_if_index, igmp_key_t * gkey, - igmp_timer_function_t * func); - -/** \brief igmp create group timer - @param time - expiration time (at this time the timer will expire) - @param sw_if_index - interface sw_if_index - @param gkey - key to find the group by - @param skey - key to find the source by - @param func - function to all after timer expiration - - Creates new source timer. -*/ -void igmp_create_src_timer (f64 time, u32 sw_if_index, igmp_key_t * gkey, - igmp_key_t * skey, igmp_timer_function_t * func); - -/** \brief igmp send query (igmp_timer_function_t) - - Send an igmp query. - If the timer holds group key, send Group-Specific query, - else send General query. -*/ -void igmp_send_query (vlib_main_t * vm, vlib_node_runtime_t * rt, - igmp_main_t * im, igmp_timer_t * timer); - -/** \brief igmp query response expiration (igmp_timer_function_t) - - If a response to a query didn't come in time, remove (S,G)s. -*/ -void igmp_query_resp_exp (vlib_main_t * vm, vlib_node_runtime_t * rt, - igmp_main_t * im, igmp_timer_t * timer); - -/** \brief igmp send report (igmp_timer_function_t) - - Send igmp membership report. -*/ -void igmp_send_report (vlib_main_t * vm, vlib_node_runtime_t * rt, - igmp_main_t * im, igmp_timer_t * timer); - -/** \brief igmp send state changed (igmp_timer_function_t) - - Send report if an (S,G) filter has changed. -*/ -void igmp_send_state_changed (vlib_main_t * vm, vlib_node_runtime_t * rt, - igmp_main_t * im, igmp_timer_t * timer); - -/** \brief igmp source expiration (igmp_timer_function_t) - - Remove expired (S,G) from group. -*/ -void igmp_src_exp (vlib_main_t * vm, vlib_node_runtime_t * rt, - igmp_main_t * im, igmp_timer_t * timer); - -static inline igmp_type_info_t * -igmp_get_type_info (igmp_main_t * im, u32 type) -{ - uword *p; - - p = hash_get (im->type_info_by_type, type); - return p ? vec_elt_at_index (im->type_infos, p[0]) : 0; -} - -static inline igmp_report_type_info_t * -igmp_get_report_type_info (igmp_main_t * im, u8 report_type) -{ - uword *p; - - p = hash_get (im->report_type_info_by_report_type, report_type); - return p ? vec_elt_at_index (im->report_type_infos, p[0]) : 0; -} - -/** \brief igmp event - @param im - igmp main - @param config - igmp configuration - @param group - igmp group - @param src - source - - Notify registered api clients of (S,G) filter update. -*/ -void igmp_event (igmp_main_t * im, igmp_config_t * config, - igmp_group_t * group, igmp_src_t * src); - -typedef enum -{ - IGMP_NEXT_IP4_REWRITE_MCAST_NODE, - IGMP_NEXT_IP6_REWRITE_MCAST_NODE, - IGMP_N_NEXT, -} igmp_next_t; - -/** \brief igmp config lookup - @param im - igmp main - @param sw_if_index - interface sw_if_index -*/ -always_inline igmp_config_t * -igmp_config_lookup (igmp_main_t * im, u32 sw_if_index) -{ - uword *p; - igmp_config_t *config = NULL; - - p = hash_get (im->igmp_config_by_sw_if_index, sw_if_index); - if (p) - config = vec_elt_at_index (im->configs, p[0]); - - return config; -} - -/** \brief igmp group lookup - @param config - igmp configuration - @param key - igmp key -*/ -always_inline igmp_group_t * -igmp_group_lookup (igmp_config_t * config, igmp_key_t * key) -{ - uword *p; - igmp_group_t *group = NULL; - if (!config) - return NULL; - - p = hash_get_mem (config->igmp_group_by_key, key); - if (p) - group = vec_elt_at_index (config->groups, p[0]); - - return group; -} - -/** \brief igmp group lookup - @param group - igmp group - @param key - igmp key -*/ -always_inline igmp_src_t * -igmp_src_lookup (igmp_group_t * group, igmp_key_t * key) -{ - uword *p; - igmp_src_t *src = NULL; - if (!group) - return NULL; - - p = hash_get_mem (group->igmp_src_by_key, key); - if (p) - src = vec_elt_at_index (group->srcs, p[0]); - - return src; -} +/** + * @brief IGMP interface enable/disable + * @param sw_if_index - Interface + * @param enable - enable/disable + * @param mode - Host or router + */ +int igmp_enable_disable (u32 sw_if_index, u8 enable, igmp_mode_t mode); + +/** + * @brief igmp listen + * Called by a host to request reception of multicast packets + * @param vm - vlib main + * @param filter - Filter mode + * @param sw_if_index - interface sw_if_index + * @param saddr - source address + * @param gaddr - group address + * + * Add/del (S,G) on an interface. + * send a status change report from the interface. + */ +int igmp_listen (vlib_main_t * vm, + igmp_filter_mode_t filter, + u32 sw_if_index, + const ip46_address_t * saddr, const ip46_address_t * gaddr); + +/** + * @brief Send an IGMP event to listening parties + * @param filter mode + * @param sw_if_index + * @param saddr + * @param gaddr + */ +void igmp_event (igmp_filter_mode_t filter, + u32 sw_if_index, + const ip46_address_t * saddr, const ip46_address_t * gaddr); #endif /* _IGMP_H_ */ |