IGMP improvements
[vpp.git] / src / plugins / igmp / igmp_ssm_range.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2017 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_ssm_range.h>
19
20 typedef struct igmp_group_prefix_t
21 {
22   fib_prefix_t igp_prefix;
23   igmp_group_prefix_type_t igp_type;
24 } igmp_group_prefix_t;
25
26 static igmp_group_prefix_t *igmp_group_prefixs;
27
28 u8 *
29 format_igmp_group_prefix_type (u8 * s, va_list * args)
30 {
31   igmp_group_prefix_type_t type = va_arg (*args, int);
32
33   switch (type)
34     {
35 #define _(n,f) case IGMP_GROUP_PREFIX_TYPE_##f: return (format (s, "%s", #f));
36       foreach_igmp_group_prefix_type
37 #undef _
38     }
39   return format (s, "unknown:%d", type);
40 }
41
42 static int
43 igmp_group_prefix_cmp (const igmp_group_prefix_t * gp1,
44                        const fib_prefix_t * p)
45 {
46   return (fib_prefix_cmp (&gp1->igp_prefix, p));
47 }
48
49 void
50 igmp_group_prefix_set (const fib_prefix_t * pfx,
51                        igmp_group_prefix_type_t type)
52 {
53   u32 pos;
54
55   pos =
56     vec_search_with_function (igmp_group_prefixs, pfx, igmp_group_prefix_cmp);
57
58   if ((~0 == pos) && (IGMP_GROUP_PREFIX_TYPE_SSM == type))
59     {
60       igmp_group_prefix_t gp = {
61         .igp_prefix = *pfx,
62         .igp_type = type,
63       };
64
65       vec_add1 (igmp_group_prefixs, gp);
66     }
67   if ((~0 != pos) && (IGMP_GROUP_PREFIX_TYPE_ASM == type))
68     {
69       vec_del1 (igmp_group_prefixs, pos);
70     }
71 }
72
73 static void
74 igmp_ssm_range_populate (void)
75 {
76   igmp_group_prefix_t *ssm_default;
77
78   vec_add2 (igmp_group_prefixs, ssm_default, 1);
79
80   ssm_default->igp_prefix.fp_addr.ip4.as_u32 = IGMP_SSM_DEFAULT;
81   ssm_default->igp_prefix.fp_proto = FIB_PROTOCOL_IP4;
82   ssm_default->igp_prefix.fp_len = 8;
83   ssm_default->igp_type = IGMP_GROUP_PREFIX_TYPE_SSM;
84 }
85
86 igmp_group_prefix_type_t
87 igmp_group_prefix_get_type (const ip46_address_t * gaddr)
88 {
89   igmp_group_prefix_t *igp;
90
91   vec_foreach (igp, igmp_group_prefixs)
92   {
93     if (ip4_destination_matches_route (&ip4_main,
94                                        &gaddr->ip4,
95                                        &igp->igp_prefix.fp_addr.ip4,
96                                        igp->igp_prefix.fp_len))
97       return (IGMP_GROUP_PREFIX_TYPE_SSM);
98   }
99
100   return (IGMP_GROUP_PREFIX_TYPE_ASM);
101 }
102
103 void
104 igmp_ssm_range_walk (igmp_ssm_range_walk_t fn, void *ctx)
105 {
106   igmp_group_prefix_t *igp;
107
108   vec_foreach (igp, igmp_group_prefixs)
109   {
110     if (WALK_STOP == fn (&igp->igp_prefix, igp->igp_type, ctx))
111       break;
112   }
113 }
114
115 static clib_error_t *
116 igmp_ssm_range_show (vlib_main_t * vm,
117                      unformat_input_t * input, vlib_cli_command_t * cmd)
118 {
119   igmp_group_prefix_t *igp;
120
121   vec_foreach (igp, igmp_group_prefixs)
122   {
123     vlib_cli_output (vm, "%U => %U",
124                      format_fib_prefix, &igp->igp_prefix,
125                      format_igmp_group_prefix_type, igp->igp_type);
126   }
127   return (NULL);
128 }
129
130 /* *INDENT-OFF* */
131 VLIB_CLI_COMMAND (igmp_show_timers_command, static) = {
132   .path = "show igmp ssm-ranges",
133   .short_help = "show igmp ssm-ranges",
134   .function = igmp_ssm_range_show,
135 };
136 /* *INDENT-ON* */
137
138 static clib_error_t *
139 igmp_ssm_range_init (vlib_main_t * vm)
140 {
141   clib_error_t *error;
142
143   if ((error = vlib_call_init_function (vm, igmp_init)))
144     return error;
145
146   igmp_ssm_range_populate ();
147
148   IGMP_DBG ("ssm-range-initialized");
149
150   return (error);
151 }
152
153 VLIB_INIT_FUNCTION (igmp_ssm_range_init);
154
155
156 /*
157  * fd.io coding-style-patch-verification: ON
158  *
159  * Local Variables:
160  * eval: (c-set-style "gnu")
161  * End:
162  */