FD.io VPP  v19.04-6-g6f05f72
Vector Packet Processing
igmp_report.c
Go to the documentation of this file.
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_report.h>
19 #include <igmp/igmp_pkt.h>
20 
21 static ip46_address_t *
23 {
24  ip46_address_t *srcs = NULL;
25  const ip4_address_t *s;
26  u16 ii, n;
27 
28  /*
29  * we validated this packet when we accepted it in the DP, so
30  * this number is safe to use
31  */
32  n = clib_net_to_host_u16 (r->n_src_addresses);
33 
34  if (0 == n)
35  {
36  /* a (*,G) join has no source address specified */
37  vec_validate (srcs, 0);
38  srcs[0].ip4.as_u32 = 0;
39  }
40  else
41  {
42  vec_validate (srcs, n - 1);
43  s = r->src_addresses;
44 
45  for (ii = 0; ii < n; ii++)
46  {
47  srcs[ii].ip4 = *s;
48  s++;
49  }
50  }
51 
52  return (srcs);
53 }
54 
55 static void
57  const igmp_membership_group_v3_t * igmp_group)
58 {
59  ip46_address_t key = {
60  .ip4 = igmp_group->group_address,
61  };
62  u16 n;
63 
64  /*
65  * treat an exclude all sources as a *,G join
66  */
67  n = clib_net_to_host_u16 (igmp_group->n_src_addresses);
68 
69  if (0 == n)
70  {
71  ip46_address_t *src, *srcs;
72  igmp_group_t *group;
73 
74  group = igmp_group_lookup (config, &key);
75  srcs = igmp_group_mk_source_list (igmp_group);
76 
77  IGMP_DBG (" ..group-update: %U (*, %U)",
79  vnet_get_main (), config->sw_if_index, format_igmp_key, &key);
80 
81  if (NULL == group)
82  {
83  group = igmp_group_alloc (config, &key, IGMP_FILTER_MODE_INCLUDE);
84  }
85  vec_foreach (src, srcs)
86  {
87  igmp_group_src_update (group, src, IGMP_MODE_ROUTER);
88  }
89 
90  vec_free (srcs);
91  }
92  else
93  {
94  IGMP_DBG (" ..group-update: %U (*, %U) source exclude ignored",
96  vnet_get_main (), config->sw_if_index, format_igmp_key, &key);
97  }
98 }
99 
100 static void
102  const igmp_membership_group_v3_t * igmp_group)
103 {
104  ip46_address_t *s, *srcs;
106  igmp_group_t *group;
107  ip46_address_t key = {
108  .ip4 = igmp_group->group_address,
109  };
110 
111  srcs = igmp_group_mk_source_list (igmp_group);
112  group = igmp_group_lookup (config, &key);
113 
114  IGMP_DBG (" ..group-block: %U (%U, %U)",
116  vnet_get_main (), config->sw_if_index,
118 
119  if (group)
120  {
121  igmp_src_t *src;
122  /*
123  * send a group+source specific query
124  */
125  igmp_pkt_build_query_init (&bq, config->sw_if_index);
126  igmp_pkt_query_v3_add_group (&bq, group, srcs);
128 
129  /*
130  * for each source left/blocked drop the source expire timer to the leave
131  * latency timer
132  */
133  vec_foreach (s, srcs)
134  {
135  src = igmp_src_lookup (group, s);
136  if (NULL != src)
137  igmp_src_blocked (src);
138  }
139  }
140  /*
141  * a block/leave from a group for which we have no state
142  */
143 
144  vec_free (srcs);
145 }
146 
147 static void
149  const igmp_membership_group_v3_t * igmp_group)
150 {
151  ip46_address_t *src, *srcs;
152  igmp_group_t *group;
153  ip46_address_t key = {
154  .ip4 = igmp_group->group_address,
155  };
156 
157  /*
158  * treat a TO_INC({}) as a (*,G) leave
159  */
160  if (0 == clib_net_to_host_u16 (igmp_group->n_src_addresses))
161  {
162  return (igmp_handle_group_block (config, igmp_group));
163  }
164 
165  srcs = igmp_group_mk_source_list (igmp_group);
166  group = igmp_group_lookup (config, &key);
167 
168  IGMP_DBG (" ..group-update: %U (%U, %U)",
170  vnet_get_main (), config->sw_if_index,
172 
173  if (NULL == group)
174  {
175  group = igmp_group_alloc (config, &key, IGMP_FILTER_MODE_INCLUDE);
176  }
177 
178  /* create or update all sources */
179  vec_foreach (src, srcs)
180  {
181  igmp_group_src_update (group, src, IGMP_MODE_ROUTER);
182  }
183 
184  vec_free (srcs);
185 }
186 
187 static void
189  const igmp_membership_group_v3_t * igmp_group)
190 {
191  IGMP_DBG ("rx-group-report: %U",
193  vnet_get_main (), config->sw_if_index);
194 
195  switch (igmp_group->type)
196  {
197  case IGMP_MEMBERSHIP_GROUP_mode_is_include:
198  case IGMP_MEMBERSHIP_GROUP_change_to_include:
199  case IGMP_MEMBERSHIP_GROUP_allow_new_sources:
200  igmp_handle_group_update (config, igmp_group);
201  break;
202  case IGMP_MEMBERSHIP_GROUP_block_old_sources:
203  igmp_handle_group_block (config, igmp_group);
204  break;
205  case IGMP_MEMBERSHIP_GROUP_mode_is_exclude:
206  case IGMP_MEMBERSHIP_GROUP_change_to_exclude:
207  igmp_handle_group_exclude (config, igmp_group);
208  break;
209  /*
210  * all other types ignored
211  */
212  }
213 }
214 
215 void
217 {
218  const igmp_membership_group_v3_t *igmp_group;
219  igmp_config_t *config;
220  u16 n_groups, ii;
221 
222  config = igmp_config_lookup (args->sw_if_index);
223 
224  if (!config)
225  /*
226  * no IGMP config on the interface. quit
227  */
228  return;
229 
230  if (IGMP_MODE_HOST == config->mode)
231  {
232  /*
233  * Hosts need not listen to the reports of other hosts.
234  * we're done here
235  */
236  return;
237  }
238 
239  /*
240  * we validated this packet when we accepted it in the DP, so
241  * this number is safe to use
242  */
243  n_groups = clib_net_to_host_u16 (args->report[0].n_groups);
244  igmp_group = args->report[0].groups;
245 
246  for (ii = 0; ii < n_groups; ii++)
247  {
248  igmp_handle_group (config, igmp_group);
249 
250  igmp_group = group_cptr (igmp_group,
251  igmp_membership_group_v3_length (igmp_group));
252  }
253 
254  igmp_proxy_device_merge_config (config, 0);
255 }
256 
257 /*
258  * fd.io coding-style-patch-verification: ON
259  *
260  * Local Variables:
261  * eval: (c-set-style "gnu")
262  * End:
263  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
u8 * format_igmp_src_addr_list(u8 *s, va_list *args)
Definition: igmp_format.c:186
igmp_membership_group_v3_type_t type
Definition: igmp_packet.h:149
u8 * format_igmp_key(u8 *s, va_list *args)
Definition: igmp_format.c:203
void igmp_pkt_query_v3_send(igmp_pkt_build_query_t *bq)
Definition: igmp_pkt.c:513
igmp_membership_group_v3_t groups[0]
Definition: igmp_packet.h:189
igmp_group_t * igmp_group_lookup(igmp_config_t *config, const igmp_key_t *key)
igmp group lookup
Definition: igmp_config.c:76
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static void igmp_handle_group_update(igmp_config_t *config, const igmp_membership_group_v3_t *igmp_group)
Definition: igmp_report.c:148
void igmp_handle_report(const igmp_report_args_t *args)
Definition: igmp_report.c:216
#define NULL
Definition: clib.h:58
void igmp_proxy_device_merge_config(igmp_config_t *config, u8 block)
Definition: igmp_proxy.c:358
igmp_src_t * igmp_group_src_update(igmp_group_t *group, const igmp_key_t *skey, igmp_mode_t mode)
Definition: igmp_group.c:45
void igmp_src_blocked(igmp_src_t *src)
Definition: igmp_src.c:129
format_function_t format_vnet_sw_if_index_name
#define IGMP_DBG(...)
Definition: igmp.h:38
igmp_membership_report_v3_t report[0]
Definition: igmp_report.h:26
static void igmp_handle_group(igmp_config_t *config, const igmp_membership_group_v3_t *igmp_group)
Definition: igmp_report.c:188
igmp_config_t * igmp_config_lookup(u32 sw_if_index)
igmp config lookup
Definition: igmp_config.c:45
unsigned short u16
Definition: types.h:57
igmp_src_t * igmp_src_lookup(igmp_group_t *group, const igmp_key_t *key)
igmp group lookup
Definition: igmp_group.c:257
vl_api_ip4_address_t src
Definition: ipsec_gre.api:38
A copy of the report message sent from the worker to the main thread.
Definition: igmp_report.h:23
igmp_group_t * igmp_group_alloc(igmp_config_t *config, const igmp_key_t *gkey, igmp_filter_mode_t mode)
Definition: igmp_group.c:103
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
void igmp_pkt_query_v3_add_group(igmp_pkt_build_query_t *bq, const igmp_group_t *group, const ip46_address_t *srcs)
Definition: igmp_pkt.c:448
#define group_cptr(p, l)
Definition: igmp.h:58
static ip46_address_t * igmp_group_mk_source_list(const igmp_membership_group_v3_t *r)
Definition: igmp_report.c:22
ip4_address_t group_address
Definition: igmp_packet.h:158
IGMP interface configuration.
Definition: igmp_config.h:47
static u32 igmp_membership_group_v3_length(const igmp_membership_group_v3_t *g)
Definition: igmp_packet.h:164
IGMP group A multicast group address for which reception has been requested.
Definition: igmp_group.h:56
typedef key
Definition: ipsec.api:244
void igmp_pkt_build_query_init(igmp_pkt_build_query_t *bq, u32 sw_if_index)
Definition: igmp_pkt.c:523
ip4_address_t src_addresses[0]
Definition: igmp_packet.h:160
#define vec_foreach(var, vec)
Vector iterator.
igmp_mode_t mode
Definition: igmp_config.h:62
static void igmp_handle_group_block(igmp_config_t *config, const igmp_membership_group_v3_t *igmp_group)
Definition: igmp_report.c:101
IGMP source The representation of a specified source address with in multicast group.
Definition: igmp_src.h:41
static void igmp_handle_group_exclude(igmp_config_t *config, const igmp_membership_group_v3_t *igmp_group)
Definition: igmp_report.c:56