FD.io VPP  v18.10-32-g1161dda
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 *src, *srcs;
60  igmp_group_t *group;
61  ip46_address_t key = {
62  .ip4 = igmp_group->group_address,
63  };
64 
65  srcs = igmp_group_mk_source_list (igmp_group);
66  group = igmp_group_lookup (config, &key);
67 
68  IGMP_DBG (" ..group-update: %U (%U, %U)",
70  vnet_get_main (), config->sw_if_index,
72 
73  if (NULL == group)
74  {
75  group = igmp_group_alloc (config, &key, IGMP_FILTER_MODE_INCLUDE);
76  }
77 
78  /* create or update all sources */
79  vec_foreach (src, srcs)
80  {
81  igmp_group_src_update (group, src, IGMP_MODE_ROUTER);
82  }
83 
84  vec_free (srcs);
85 }
86 
87 static void
89  const igmp_membership_group_v3_t * igmp_group)
90 {
91  ip46_address_t *s, *srcs;
93  igmp_group_t *group;
94  ip46_address_t key = {
95  .ip4 = igmp_group->group_address,
96  };
97 
98  srcs = igmp_group_mk_source_list (igmp_group);
99  group = igmp_group_lookup (config, &key);
100 
101  IGMP_DBG (" ..group-block: %U (%U, %U)",
103  vnet_get_main (), config->sw_if_index,
105 
106  if (group)
107  {
108  igmp_src_t *src;
109  /*
110  * send a group+source specific query
111  */
112  igmp_pkt_build_query_init (&bq, config->sw_if_index);
113  igmp_pkt_query_v3_add_group (&bq, group, srcs);
115 
116  /*
117  * for each source left/blocked drop the source expire timer to the leave
118  * latency timer
119  */
120  vec_foreach (s, srcs)
121  {
122  src = igmp_src_lookup (group, s);
123  if (NULL != src)
124  igmp_src_blocked (src);
125  }
126  }
127  /*
128  * a block/leave from a group for which we have no state
129  */
130 
131  vec_free (srcs);
132 }
133 
134 static void
136  const igmp_membership_group_v3_t * igmp_group)
137 {
138  IGMP_DBG ("rx-group-report: %U",
140  vnet_get_main (), config->sw_if_index);
141 
142  switch (igmp_group->type)
143  {
144  case IGMP_MEMBERSHIP_GROUP_mode_is_include:
145  case IGMP_MEMBERSHIP_GROUP_change_to_include:
146  case IGMP_MEMBERSHIP_GROUP_allow_new_sources:
147  igmp_handle_group_update (config, igmp_group);
148  break;
149  case IGMP_MEMBERSHIP_GROUP_block_old_sources:
150  igmp_handle_group_block (config, igmp_group);
151  break;
152  case IGMP_MEMBERSHIP_GROUP_mode_is_exclude:
153  case IGMP_MEMBERSHIP_GROUP_change_to_exclude:
154  break;
155  /*
156  * all other types ignored
157  */
158  }
159 }
160 
161 void
163 {
164  const igmp_membership_group_v3_t *igmp_group;
165  igmp_config_t *config;
166  u16 n_groups, ii;
167 
168  config = igmp_config_lookup (args->sw_if_index);
169 
170  if (!config)
171  /*
172  * no IGMP config on the interface. quit
173  */
174  return;
175 
176  if (IGMP_MODE_HOST == config->mode)
177  {
178  /*
179  * Hosts need not listen to the reports of other hosts.
180  * we're done here
181  */
182  return;
183  }
184 
185  /*
186  * we validated this packet when we accepted it in the DP, so
187  * this number is safe to use
188  */
189  n_groups = clib_net_to_host_u16 (args->report[0].n_groups);
190  igmp_group = args->report[0].groups;
191 
192  for (ii = 0; ii < n_groups; ii++)
193  {
194  igmp_handle_group (config, igmp_group);
195 
196  igmp_group = group_cptr (igmp_group,
197  igmp_membership_group_v3_length (igmp_group));
198  }
199 }
200 
201 /*
202  * fd.io coding-style-patch-verification: ON
203  *
204  * Local Variables:
205  * eval: (c-set-style "gnu")
206  * End:
207  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:437
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
vl_api_address_t src
Definition: vxlan_gbp.api:33
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:516
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:56
void igmp_handle_report(const igmp_report_args_t *args)
Definition: igmp_report.c:162
#define NULL
Definition: clib.h:57
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:127
format_function_t format_vnet_sw_if_index_name
#define IGMP_DBG(...)
Definition: igmp.h:37
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:135
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:240
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:95
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
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:451
#define group_cptr(p, l)
Definition: igmp.h:57
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:43
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:55
void igmp_pkt_build_query_init(igmp_pkt_build_query_t *bq, u32 sw_if_index)
Definition: igmp_pkt.c:526
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:58
static void igmp_handle_group_block(igmp_config_t *config, const igmp_membership_group_v3_t *igmp_group)
Definition: igmp_report.c:88
IGMP source The representation of a specified source address with in multicast group.
Definition: igmp_src.h:41