IGMP: Improved handling of (*,G) join and leave
Change-Id: I48a92035b58d83420eb3eed3f05a75ba283543c2 Signed-off-by: Neale Ranns <nranns@cisco.com>
This commit is contained in:

committed by
Damjan Marion

parent
3206bb15aa
commit
0f7af53e73
@ -53,29 +53,35 @@ igmp_group_mk_source_list (const igmp_membership_group_v3_t * r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
igmp_handle_group_update (igmp_config_t * config,
|
igmp_handle_group_exclude (igmp_config_t * config,
|
||||||
const igmp_membership_group_v3_t * igmp_group)
|
const igmp_membership_group_v3_t * igmp_group)
|
||||||
{
|
{
|
||||||
ip46_address_t *src, *srcs;
|
|
||||||
igmp_group_t *group;
|
|
||||||
ip46_address_t key = {
|
ip46_address_t key = {
|
||||||
.ip4 = igmp_group->group_address,
|
.ip4 = igmp_group->group_address,
|
||||||
};
|
};
|
||||||
|
u16 n;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* treat an exclude all sources as a *,G join
|
||||||
|
*/
|
||||||
|
n = clib_net_to_host_u16 (igmp_group->n_src_addresses);
|
||||||
|
|
||||||
|
if (0 == n)
|
||||||
|
{
|
||||||
|
ip46_address_t *src, *srcs;
|
||||||
|
igmp_group_t *group;
|
||||||
|
|
||||||
srcs = igmp_group_mk_source_list (igmp_group);
|
|
||||||
group = igmp_group_lookup (config, &key);
|
group = igmp_group_lookup (config, &key);
|
||||||
|
srcs = igmp_group_mk_source_list (igmp_group);
|
||||||
|
|
||||||
IGMP_DBG (" ..group-update: %U (%U, %U)",
|
IGMP_DBG (" ..group-update: %U (*, %U)",
|
||||||
format_vnet_sw_if_index_name,
|
format_vnet_sw_if_index_name,
|
||||||
vnet_get_main (), config->sw_if_index,
|
vnet_get_main (), config->sw_if_index, format_igmp_key, &key);
|
||||||
format_igmp_key, &key, format_igmp_src_addr_list, srcs);
|
|
||||||
|
|
||||||
if (NULL == group)
|
if (NULL == group)
|
||||||
{
|
{
|
||||||
group = igmp_group_alloc (config, &key, IGMP_FILTER_MODE_INCLUDE);
|
group = igmp_group_alloc (config, &key, IGMP_FILTER_MODE_INCLUDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create or update all sources */
|
|
||||||
vec_foreach (src, srcs)
|
vec_foreach (src, srcs)
|
||||||
{
|
{
|
||||||
igmp_group_src_update (group, src, IGMP_MODE_ROUTER);
|
igmp_group_src_update (group, src, IGMP_MODE_ROUTER);
|
||||||
@ -83,6 +89,13 @@ igmp_handle_group_update (igmp_config_t * config,
|
|||||||
|
|
||||||
vec_free (srcs);
|
vec_free (srcs);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IGMP_DBG (" ..group-update: %U (*, %U) source exclude ignored",
|
||||||
|
format_vnet_sw_if_index_name,
|
||||||
|
vnet_get_main (), config->sw_if_index, format_igmp_key, &key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
igmp_handle_group_block (igmp_config_t * config,
|
igmp_handle_group_block (igmp_config_t * config,
|
||||||
@ -131,6 +144,46 @@ igmp_handle_group_block (igmp_config_t * config,
|
|||||||
vec_free (srcs);
|
vec_free (srcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
igmp_handle_group_update (igmp_config_t * config,
|
||||||
|
const igmp_membership_group_v3_t * igmp_group)
|
||||||
|
{
|
||||||
|
ip46_address_t *src, *srcs;
|
||||||
|
igmp_group_t *group;
|
||||||
|
ip46_address_t key = {
|
||||||
|
.ip4 = igmp_group->group_address,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* treat a TO_INC({}) as a (*,G) leave
|
||||||
|
*/
|
||||||
|
if (0 == clib_net_to_host_u16 (igmp_group->n_src_addresses))
|
||||||
|
{
|
||||||
|
return (igmp_handle_group_block (config, igmp_group));
|
||||||
|
}
|
||||||
|
|
||||||
|
srcs = igmp_group_mk_source_list (igmp_group);
|
||||||
|
group = igmp_group_lookup (config, &key);
|
||||||
|
|
||||||
|
IGMP_DBG (" ..group-update: %U (%U, %U)",
|
||||||
|
format_vnet_sw_if_index_name,
|
||||||
|
vnet_get_main (), config->sw_if_index,
|
||||||
|
format_igmp_key, &key, format_igmp_src_addr_list, srcs);
|
||||||
|
|
||||||
|
if (NULL == group)
|
||||||
|
{
|
||||||
|
group = igmp_group_alloc (config, &key, IGMP_FILTER_MODE_INCLUDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create or update all sources */
|
||||||
|
vec_foreach (src, srcs)
|
||||||
|
{
|
||||||
|
igmp_group_src_update (group, src, IGMP_MODE_ROUTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec_free (srcs);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
igmp_handle_group (igmp_config_t * config,
|
igmp_handle_group (igmp_config_t * config,
|
||||||
const igmp_membership_group_v3_t * igmp_group)
|
const igmp_membership_group_v3_t * igmp_group)
|
||||||
@ -151,6 +204,7 @@ igmp_handle_group (igmp_config_t * config,
|
|||||||
break;
|
break;
|
||||||
case IGMP_MEMBERSHIP_GROUP_mode_is_exclude:
|
case IGMP_MEMBERSHIP_GROUP_mode_is_exclude:
|
||||||
case IGMP_MEMBERSHIP_GROUP_change_to_exclude:
|
case IGMP_MEMBERSHIP_GROUP_change_to_exclude:
|
||||||
|
igmp_handle_group_exclude (config, igmp_group);
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
* all other types ignored
|
* all other types ignored
|
||||||
|
@ -629,7 +629,7 @@ class TestIgmp(VppTestCase):
|
|||||||
self.assertFalse(self.vapi.igmp_dump())
|
self.assertFalse(self.vapi.igmp_dump())
|
||||||
|
|
||||||
#
|
#
|
||||||
# A (*,G) host report
|
# a TO_EX({}) / IN_EX({}) is treated like a (*,G) join
|
||||||
#
|
#
|
||||||
p_j = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
p_j = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||||
IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1,
|
IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1,
|
||||||
@ -637,13 +637,78 @@ class TestIgmp(VppTestCase):
|
|||||||
option="router_alert")]) /
|
option="router_alert")]) /
|
||||||
IGMPv3(type="Version 3 Membership Report") /
|
IGMPv3(type="Version 3 Membership Report") /
|
||||||
IGMPv3mr(numgrp=1) /
|
IGMPv3mr(numgrp=1) /
|
||||||
IGMPv3gr(rtype="Allow New Sources", maddr="239.1.1.2"))
|
IGMPv3gr(rtype="Change To Exclude Mode", maddr="239.1.1.2"))
|
||||||
|
|
||||||
self.send(self.pg0, p_j)
|
self.send(self.pg0, p_j)
|
||||||
|
|
||||||
self.assertTrue(wait_for_igmp_event(self, 1, self.pg0,
|
self.assertTrue(wait_for_igmp_event(self, 1, self.pg0,
|
||||||
"239.1.1.2", "0.0.0.0", 1))
|
"239.1.1.2", "0.0.0.0", 1))
|
||||||
|
|
||||||
|
p_j = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||||
|
IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1,
|
||||||
|
options=[IPOption(copy_flag=1, optclass="control",
|
||||||
|
option="router_alert")]) /
|
||||||
|
IGMPv3(type="Version 3 Membership Report") /
|
||||||
|
IGMPv3mr(numgrp=1) /
|
||||||
|
IGMPv3gr(rtype="Mode Is Exclude", maddr="239.1.1.3"))
|
||||||
|
|
||||||
|
self.send(self.pg0, p_j)
|
||||||
|
|
||||||
|
self.assertTrue(wait_for_igmp_event(self, 1, self.pg0,
|
||||||
|
"239.1.1.3", "0.0.0.0", 1))
|
||||||
|
|
||||||
|
#
|
||||||
|
# A 'allow sourcees' for {} should be ignored as it should
|
||||||
|
# never be sent.
|
||||||
|
#
|
||||||
|
p_j = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||||
|
IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1,
|
||||||
|
options=[IPOption(copy_flag=1, optclass="control",
|
||||||
|
option="router_alert")]) /
|
||||||
|
IGMPv3(type="Version 3 Membership Report") /
|
||||||
|
IGMPv3mr(numgrp=1) /
|
||||||
|
IGMPv3gr(rtype="Allow New Sources", maddr="239.1.1.4"))
|
||||||
|
|
||||||
|
self.send(self.pg0, p_j)
|
||||||
|
|
||||||
|
dump = self.vapi.igmp_dump(self.pg0.sw_if_index)
|
||||||
|
self.assertTrue(find_igmp_state(dump, self.pg0,
|
||||||
|
"239.1.1.2", "0.0.0.0"))
|
||||||
|
self.assertTrue(find_igmp_state(dump, self.pg0,
|
||||||
|
"239.1.1.3", "0.0.0.0"))
|
||||||
|
self.assertFalse(find_igmp_state(dump, self.pg0,
|
||||||
|
"239.1.1.4", "0.0.0.0"))
|
||||||
|
|
||||||
|
#
|
||||||
|
# a TO_IN({}) and IS_IN({}) are treated like a (*,G) leave
|
||||||
|
#
|
||||||
|
self.vapi.cli("set logging class igmp level debug")
|
||||||
|
p_l = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||||
|
IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1,
|
||||||
|
options=[IPOption(copy_flag=1, optclass="control",
|
||||||
|
option="router_alert")]) /
|
||||||
|
IGMPv3(type="Version 3 Membership Report") /
|
||||||
|
IGMPv3mr(numgrp=1) /
|
||||||
|
IGMPv3gr(rtype="Change To Include Mode", maddr="239.1.1.2"))
|
||||||
|
|
||||||
|
self.send(self.pg0, p_l)
|
||||||
|
self.assertTrue(wait_for_igmp_event(self, 2, self.pg0,
|
||||||
|
"239.1.1.2", "0.0.0.0", 0))
|
||||||
|
|
||||||
|
p_l = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||||
|
IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1,
|
||||||
|
options=[IPOption(copy_flag=1, optclass="control",
|
||||||
|
option="router_alert")]) /
|
||||||
|
IGMPv3(type="Version 3 Membership Report") /
|
||||||
|
IGMPv3mr(numgrp=1) /
|
||||||
|
IGMPv3gr(rtype="Mode Is Include", maddr="239.1.1.3"))
|
||||||
|
|
||||||
|
self.send(self.pg0, p_l)
|
||||||
|
|
||||||
|
self.assertTrue(wait_for_igmp_event(self, 2, self.pg0,
|
||||||
|
"239.1.1.3", "0.0.0.0", 0))
|
||||||
|
self.assertFalse(self.vapi.igmp_dump(self.pg0.sw_if_index))
|
||||||
|
|
||||||
#
|
#
|
||||||
# disable router config
|
# disable router config
|
||||||
#
|
#
|
||||||
|
Reference in New Issue
Block a user