/* *------------------------------------------------------------------ * Copyright (c) 2017 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------ */ #include <igmp/igmp_ssm_range.h> typedef struct igmp_group_prefix_t { fib_prefix_t igp_prefix; igmp_group_prefix_type_t igp_type; } igmp_group_prefix_t; static igmp_group_prefix_t *igmp_group_prefixs; u8 * format_igmp_group_prefix_type (u8 * s, va_list * args) { igmp_group_prefix_type_t type = va_arg (*args, int); switch (type) { #define _(n,f) case IGMP_GROUP_PREFIX_TYPE_##f: return (format (s, "%s", #f)); foreach_igmp_group_prefix_type #undef _ } return format (s, "unknown:%d", type); } static int igmp_group_prefix_cmp (const igmp_group_prefix_t * gp1, const fib_prefix_t * p) { return (fib_prefix_cmp (&gp1->igp_prefix, p)); } void igmp_group_prefix_set (const fib_prefix_t * pfx, igmp_group_prefix_type_t type) { u32 pos; pos = vec_search_with_function (igmp_group_prefixs, pfx, igmp_group_prefix_cmp); if ((~0 == pos) && (IGMP_GROUP_PREFIX_TYPE_SSM == type)) { igmp_group_prefix_t gp = { .igp_prefix = *pfx, .igp_type = type, }; vec_add1 (igmp_group_prefixs, gp); } if ((~0 != pos) && (IGMP_GROUP_PREFIX_TYPE_ASM == type)) { vec_del1 (igmp_group_prefixs, pos); } } static void igmp_ssm_range_populate (void) { igmp_group_prefix_t *ssm_default; vec_add2 (igmp_group_prefixs, ssm_default, 1); ssm_default->igp_prefix.fp_addr.ip4.as_u32 = IGMP_SSM_DEFAULT; ssm_default->igp_prefix.fp_proto = FIB_PROTOCOL_IP4; ssm_default->igp_prefix.fp_len = 8; ssm_default->igp_type = IGMP_GROUP_PREFIX_TYPE_SSM; } igmp_group_prefix_type_t igmp_group_prefix_get_type (const ip46_address_t * gaddr) { igmp_group_prefix_t *igp; vec_foreach (igp, igmp_group_prefixs) { if (ip4_destination_matches_route (&ip4_main, &gaddr->ip4, &igp->igp_prefix.fp_addr.ip4, igp->igp_prefix.fp_len)) return (IGMP_GROUP_PREFIX_TYPE_SSM); } return (IGMP_GROUP_PREFIX_TYPE_ASM); } void igmp_ssm_range_walk (igmp_ssm_range_walk_t fn, void *ctx) { igmp_group_prefix_t *igp; vec_foreach (igp, igmp_group_prefixs) { if (WALK_STOP == fn (&igp->igp_prefix, igp->igp_type, ctx)) break; } } static clib_error_t * igmp_ssm_range_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { igmp_group_prefix_t *igp; vec_foreach (igp, igmp_group_prefixs) { vlib_cli_output (vm, "%U => %U", format_fib_prefix, &igp->igp_prefix, format_igmp_group_prefix_type, igp->igp_type); } return (NULL); } /* *INDENT-OFF* */ VLIB_CLI_COMMAND (igmp_show_timers_command, static) = { .path = "show igmp ssm-ranges", .short_help = "show igmp ssm-ranges", .function = igmp_ssm_range_show, }; /* *INDENT-ON* */ static clib_error_t * igmp_ssm_range_init (vlib_main_t * vm) { igmp_ssm_range_populate (); IGMP_DBG ("ssm-range-initialized"); return (0); } /* *INDENT-OFF* */ VLIB_INIT_FUNCTION (igmp_ssm_range_init) = { .runs_after = VLIB_INITS("igmp_init"), }; /* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */