pimd: Allow SSM groups to co-exist with ASM groups.

SSM groups (232/8 or user configured SSM range) can exist in the same
multicast network as ASM groups. For such groups all RPT related state
machine operations have to be skipped as defined by section 4.8 of
RFC4601 -
1. Source registration is skipped for SSM groups. For SSM groups mroute
is setup on the FHR when a new multicast flow is rxed; however source
registration (i.e. pimreg join) is skipped. This will let the ASIC black
hole the traffic till a valid OIL is added to the mroute.
2. (*,G) IGMP registrations are ignored for SSM groups.

Sample output:
=============
fhr#  sh ip pim group-type
SSM group range : 232.0.0.0/8
fhr#  sh ip pim group-type 232.1.1.1
Group type: SSM
fhr#  sh ip pim group-type 239.1.1.1
Group type: ASM
fhr#

Sample config:
=============
fhr(config)# ip pim ssm prefix-list ssm-ranges
fhr(config)#

Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>

Ticket: CM-15344
Testing Done:
1. SSM/ASM source-registration/igmp-joins.
2. On the fly multicast group type changes.
3. pim-smoke.
This commit is contained in:
anuradhak 2017-03-17 11:51:13 -07:00
parent 7a6327c003
commit 15a5dafe44
18 changed files with 560 additions and 18 deletions

View File

@ -53,7 +53,7 @@ libpim_a_SOURCES = \
pim_ssmpingd.c pim_int.c pim_rp.c \
pim_static.c pim_br.c pim_register.c pim_routemap.c \
pim_msdp.c pim_msdp_socket.c pim_msdp_packet.c \
pim_jp_agg.c pim_nht.c
pim_jp_agg.c pim_nht.c pim_ssm.c
noinst_HEADERS = \
pim_memory.h \
@ -66,7 +66,7 @@ noinst_HEADERS = \
pim_igmp_join.h pim_ssmpingd.h pim_int.h pim_rp.h \
pim_static.h pim_br.h pim_register.h \
pim_msdp.h pim_msdp_socket.h pim_msdp_packet.h pim_nht.h \
pim_jp_agg.h
pim_jp_agg.h pim_ssm.h
pimd_SOURCES = \
pim_main.c $(libpim_a_SOURCES)

View File

@ -54,6 +54,7 @@
#include "pim_rp.h"
#include "pim_zlookup.h"
#include "pim_msdp.h"
#include "pim_ssm.h"
static struct cmd_node pim_global_node = {
PIM_NODE,
@ -3598,6 +3599,153 @@ DEFUN (no_ip_pim_rp_prefix_list,
return pim_no_rp_cmd_worker (vty, argv[4]->arg, NULL, argv[6]->arg);
}
static int
pim_ssm_cmd_worker (struct vty *vty, const char *plist)
{
int result = pim_ssm_range_set (VRF_DEFAULT, plist);
if (result == PIM_SSM_ERR_NONE)
return CMD_SUCCESS;
switch (result)
{
case PIM_SSM_ERR_NO_VRF:
vty_out (vty, "%% VRF doesn't exist%s", VTY_NEWLINE);
break;
case PIM_SSM_ERR_DUP:
vty_out (vty, "%% duplicate config%s", VTY_NEWLINE);
break;
default:
vty_out (vty, "%% ssm range config failed%s", VTY_NEWLINE);
}
return CMD_WARNING;
}
DEFUN (ip_pim_ssm_prefix_list,
ip_pim_ssm_prefix_list_cmd,
"ip pim ssm prefix-list WORD",
IP_STR
"pim multicast routing\n"
"Source Specific Multicast\n"
"group range prefix-list filter\n"
"Name of a prefix-list\n")
{
return pim_ssm_cmd_worker (vty, argv[0]->arg);
}
DEFUN (no_ip_pim_ssm_prefix_list,
no_ip_pim_ssm_prefix_list_cmd,
"no ip pim ssm prefix-list",
NO_STR
IP_STR
"pim multicast routing\n"
"Source Specific Multicast\n"
"group range prefix-list filter\n")
{
return pim_ssm_cmd_worker (vty, NULL);
}
DEFUN (no_ip_pim_ssm_prefix_list_name,
no_ip_pim_ssm_prefix_list_name_cmd,
"no ip pim ssm prefix-list WORD",
NO_STR
IP_STR
"pim multicast routing\n"
"Source Specific Multicast\n"
"group range prefix-list filter\n"
"Name of a prefix-list\n")
{
struct pim_ssm *ssm = pimg->ssm_info;
if (ssm->plist_name && !strcmp(ssm->plist_name, argv[0]->arg))
return pim_ssm_cmd_worker (vty, NULL);
vty_out (vty, "%% pim ssm prefix-list %s doesn't exist%s",
argv[0]->arg, VTY_NEWLINE);
return CMD_WARNING;
}
static void
ip_pim_ssm_show_group_range(struct vty *vty, u_char uj)
{
struct pim_ssm *ssm = pimg->ssm_info;
const char *range_str = ssm->plist_name?ssm->plist_name:PIM_SSM_STANDARD_RANGE;
if (uj)
{
json_object *json;
json = json_object_new_object();
json_object_string_add(json, "ssmGroups", range_str);
vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
json_object_free(json);
}
else
vty_out(vty, "SSM group range : %s%s", range_str, VTY_NEWLINE);
}
DEFUN (show_ip_pim_ssm_range,
show_ip_pim_ssm_range_cmd,
"show ip pim group-type [json]",
SHOW_STR
IP_STR
PIM_STR
"PIM group type\n"
"JavaScript Object Notation\n")
{
u_char uj = use_json(argc, argv);
ip_pim_ssm_show_group_range(vty, uj);
return CMD_SUCCESS;
}
static void
ip_pim_ssm_show_group_type(struct vty *vty, u_char uj, const char *group)
{
struct in_addr group_addr;
const char *type_str;
int result;
result = inet_pton(AF_INET, group, &group_addr);
if (result <= 0)
type_str = "invalid";
else
{
if (pim_is_group_224_4 (group_addr))
type_str = pim_is_grp_ssm (group_addr)?"SSM":"ASM";
else
type_str = "not-multicast";
}
if (uj)
{
json_object *json;
json = json_object_new_object();
json_object_string_add(json, "groupType", type_str);
vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
json_object_free(json);
}
else
vty_out(vty, "Group type : %s%s", type_str, VTY_NEWLINE);
}
DEFUN (show_ip_pim_group_type,
show_ip_pim_group_type_cmd,
"show ip pim group-type A.B.C.D [json]",
SHOW_STR
IP_STR
PIM_STR
"multicast group type\n"
"group address\n"
"JavaScript Object Notation\n")
{
u_char uj = use_json(argc, argv);
ip_pim_ssm_show_group_type(vty, uj, argv[0]->arg);
return CMD_SUCCESS;
}
DEFUN_HIDDEN (ip_multicast_routing,
ip_multicast_routing_cmd,
"ip multicast-routing",
@ -6029,6 +6177,9 @@ void pim_cmd_init()
install_element (CONFIG_NODE, &no_ip_pim_rp_cmd);
install_element (CONFIG_NODE, &ip_pim_rp_prefix_list_cmd);
install_element (CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd);
install_element (CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd);
install_element (CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
install_element (CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd);
install_element (CONFIG_NODE, &ip_pim_register_suppress_cmd);
install_element (CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
install_element (CONFIG_NODE, &ip_pim_joinprune_time_cmd);
@ -6186,6 +6337,8 @@ void pim_cmd_init()
install_element (VIEW_NODE, &show_ip_msdp_sa_detail_cmd);
install_element (VIEW_NODE, &show_ip_msdp_sa_sg_cmd);
install_element (VIEW_NODE, &show_ip_msdp_mesh_group_cmd);
install_element (VIEW_NODE, &show_ip_pim_ssm_range_cmd);
install_element (VIEW_NODE, &show_ip_pim_group_type_cmd);
install_element (INTERFACE_NODE, &interface_pim_use_source_cmd);
install_element (INTERFACE_NODE, &interface_no_pim_use_source_cmd);
}

View File

@ -41,6 +41,7 @@
#include "pim_macro.h"
#include "pim_oil.h"
#include "pim_upstream.h"
#include "pim_ssm.h"
int
pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2)
@ -966,6 +967,18 @@ pim_ifchannel_local_membership_add(struct interface *ifp,
if (!PIM_IF_TEST_PIM(pim_ifp->options))
return 0;
/* skip (*,G) ch creation if G is of type SSM */
if (sg->src.s_addr == INADDR_ANY)
{
if (pim_is_grp_ssm (sg->grp))
{
if (PIM_DEBUG_PIM_EVENTS)
zlog_debug("%s: local membership (S,G)=%s ignored as group is SSM",
__PRETTY_FUNCTION__, pim_str_sg_dump (sg));
return 1;
}
}
ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP);
if (!ch) {
return 0;

View File

@ -46,7 +46,6 @@
#include "pim_zebra.h"
#include "pim_msdp.h"
#include "pim_iface.h"
#include "pim_rp.h"
extern struct host host;
@ -120,8 +119,8 @@ int main(int argc, char** argv, char** envp) {
pim_vrf_init ();
access_list_init();
prefix_list_init ();
prefix_list_add_hook (pim_rp_prefix_list_update);
prefix_list_delete_hook (pim_rp_prefix_list_update);
prefix_list_add_hook (pim_prefix_list_update);
prefix_list_delete_hook (pim_prefix_list_update);
pim_route_map_init ();
pim_init();

View File

@ -51,3 +51,4 @@ DEFINE_MTYPE(PIMD, PIM_JP_AGG_GROUP, "PIM JP AGG Group")
DEFINE_MTYPE(PIMD, PIM_JP_AGG_SOURCE, "PIM JP AGG Source")
DEFINE_MTYPE(PIMD, PIM_PIM_INSTANCE, "PIM global state")
DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state")
DEFINE_MTYPE(PIMD, PIM_SSM_INFO, "PIM SSM configuration")

View File

@ -50,5 +50,6 @@ DECLARE_MTYPE(PIM_JP_AGG_GROUP)
DECLARE_MTYPE(PIM_JP_AGG_SOURCE)
DECLARE_MTYPE(PIM_PIM_INSTANCE)
DECLARE_MTYPE(PIM_NEXTHOP_CACHE)
DECLARE_MTYPE(PIM_SSM_INFO)
#endif /* _QUAGGA_PIM_MEMORY_H */

View File

@ -39,6 +39,7 @@
#include "pim_register.h"
#include "pim_ifchannel.h"
#include "pim_zlookup.h"
#include "pim_ssm.h"
/* GLOBAL VARS */
static struct thread *qpim_mroute_socket_reader = NULL;
@ -178,8 +179,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg
up->channel_oil->cc.pktcnt++;
PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM);
up->reg_state = PIM_REG_JOIN;
pim_register_join (up);
return 0;
}
@ -226,9 +226,18 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf)
* If we've received a register suppress
*/
if (!up->t_rs_timer)
pim_register_send((uint8_t *)buf + sizeof(struct ip),
ntohs (ip_hdr->ip_len) - sizeof (struct ip),
pim_ifp->primary_address, rpg, 0, up);
{
if (pim_is_grp_ssm (sg.grp))
{
if (PIM_DEBUG_PIM_REG)
zlog_debug ("%s register forward skipped as group is SSM",
pim_str_sg_dump (&sg));
return 0;
}
pim_register_send((uint8_t *)buf + sizeof(struct ip),
ntohs (ip_hdr->ip_len) - sizeof (struct ip),
pim_ifp->primary_address, rpg, 0, up);
}
return 0;
}
@ -442,8 +451,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf)
pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time);
up->channel_oil = oil;
up->channel_oil->cc.pktcnt++;
pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM);
up->reg_state = PIM_REG_JOIN;
pim_register_join (up);
pim_upstream_inherited_olist (up);
// Send the packet to the RP

View File

@ -43,9 +43,24 @@
#include "pim_zebra.h"
#include "pim_join.h"
#include "pim_util.h"
#include "pim_ssm.h"
struct thread *send_test_packet_timer = NULL;
void
pim_register_join (struct pim_upstream *up)
{
if (pim_is_grp_ssm (up->sg.grp))
{
if (PIM_DEBUG_PIM_EVENTS)
zlog_debug ("%s register setup skipped as group is SSM", up->sg_str);
return;
}
pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM);
up->reg_state = PIM_REG_JOIN;
}
void
pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg,
struct in_addr src, struct in_addr originator)

View File

@ -40,5 +40,6 @@ int pim_register_recv (struct interface *ifp,
void pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register, struct pim_upstream *up);
void pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, struct in_addr src, struct in_addr originator);
void pim_register_join (struct pim_upstream *up);
#endif

156
pimd/pim_ssm.c Normal file
View File

@ -0,0 +1,156 @@
/*
* IP SSM ranges for FRR
* Copyright (C) 2017 Cumulus Networks, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include <lib/linklist.h>
#include <lib/prefix.h>
#include <lib/vty.h>
#include <lib/vrf.h>
#include <lib/plist.h>
#include "pimd.h"
#include "pim_ssm.h"
#include "pim_zebra.h"
static void
pim_ssm_range_reevaluate (void)
{
/* 1. Setup register state for (S,G) entries if G has changed from SSM to
* ASM.
* 2. check existing (*,G) IGMP registrations to see if they are
* still ASM. if they are now SSM delete them.
* 3. Allow channel setup for IGMP (*,G) members if G is now ASM
* 4. I could tear down all (*,G), (S,G,rpt) states. But that is an
* unnecessary sladge hammer and may not be particularly useful as it is
* likely the SPT switchover has already happened for flows along such RPTs.
* As for the RPT states it seems that the best thing to do is let them age
* out gracefully. As long as the FHR and LHR do the right thing RPTs will
* disappear in time for SSM groups.
*/
pim_upstream_register_reevaluate ();
igmp_source_forward_reevaluate_all ();
}
void
pim_ssm_prefix_list_update (struct prefix_list *plist)
{
struct pim_ssm *ssm = pimg->ssm_info;
if (!ssm->plist_name || strcmp (ssm->plist_name, prefix_list_name (plist)))
{
/* not ours */
return;
}
pim_ssm_range_reevaluate ();
}
static int
pim_is_grp_standard_ssm (struct prefix *group)
{
static int first = 1;
static struct prefix group_ssm;
if (first)
{
str2prefix (PIM_SSM_STANDARD_RANGE, &group_ssm);
first = 0;
}
return prefix_match (&group_ssm, group);
}
int
pim_is_grp_ssm (struct in_addr group_addr)
{
struct pim_ssm *ssm;
struct prefix group;
struct prefix_list *plist;
memset (&group, 0, sizeof (group));
group.family = AF_INET;
group.u.prefix4 = group_addr;
group.prefixlen = 32;
ssm = pimg->ssm_info;
if (!ssm->plist_name)
{
return pim_is_grp_standard_ssm (&group);
}
plist = prefix_list_lookup (AFI_IP, ssm->plist_name);
if (!plist)
return 0;
return (prefix_list_apply (plist, &group) == PREFIX_PERMIT);
}
int
pim_ssm_range_set (vrf_id_t vrf_id, const char *plist_name)
{
struct pim_ssm *ssm;
int change = 0;
if (vrf_id != VRF_DEFAULT)
return PIM_SSM_ERR_NO_VRF;
ssm = pimg->ssm_info;
if (plist_name)
{
if (ssm->plist_name)
{
if (!strcmp (ssm->plist_name, plist_name))
return PIM_SSM_ERR_DUP;
XFREE (MTYPE_PIM_FILTER_NAME, ssm->plist_name);
}
ssm->plist_name = XSTRDUP (MTYPE_PIM_FILTER_NAME, plist_name);
change = 1;
}
else
{
if (ssm->plist_name)
{
change = 1;
XFREE (MTYPE_PIM_FILTER_NAME, ssm->plist_name);
}
}
if (change)
pim_ssm_range_reevaluate ();
return PIM_SSM_ERR_NONE;
}
void *
pim_ssm_init (vrf_id_t vrf_id)
{
struct pim_ssm *ssm;
ssm = XCALLOC (MTYPE_PIM_SSM_INFO, sizeof (*ssm));
ssm->vrf_id = vrf_id;
return ssm;
}
void
pim_ssm_terminate (struct pim_ssm *ssm)
{
if (ssm && ssm->plist_name)
XFREE (MTYPE_PIM_FILTER_NAME, ssm->plist_name);
}

44
pimd/pim_ssm.h Normal file
View File

@ -0,0 +1,44 @@
/*
* IP SSM ranges for FRR
* Copyright (C) 2017 Cumulus Networks, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef PIM_SSM_H
#define PIM_SSM_H
#define PIM_SSM_STANDARD_RANGE "232.0.0.0/8"
/* SSM error codes */
enum pim_ssm_err
{
PIM_SSM_ERR_NONE = 0,
PIM_SSM_ERR_NO_VRF = -1,
PIM_SSM_ERR_DUP = -2,
};
struct pim_ssm
{
vrf_id_t vrf_id;
char *plist_name; /* prefix list of group ranges */
};
void pim_ssm_prefix_list_update (struct prefix_list *plist);
int pim_is_grp_ssm (struct in_addr group_addr);
int pim_ssm_range_set (vrf_id_t vrf_id, const char *plist_name);
void *pim_ssm_init (vrf_id_t vrf_id);
void pim_ssm_terminate (struct pim_ssm *ssm);
#endif

View File

@ -53,6 +53,7 @@
#include "pim_msdp.h"
#include "pim_jp_agg.h"
#include "pim_nht.h"
#include "pim_ssm.h"
struct hash *pim_upstream_hash = NULL;
struct list *pim_upstream_list = NULL;
@ -476,6 +477,51 @@ pim_upstream_could_register (struct pim_upstream *up)
return 0;
}
/* Source registration is supressed for SSM groups. When the SSM range changes
* we re-revaluate register setup for existing upstream entries */
void
pim_upstream_register_reevaluate (void)
{
struct listnode *upnode;
struct pim_upstream *up;
for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, upnode, up))
{
/* If FHR is set CouldRegister is True. Also check if the flow
* is actually active; if it is not kat setup will trigger source
* registration whenever the flow becomes active. */
if (!PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) || !up->t_ka_timer)
continue;
if (pim_is_grp_ssm (up->sg.grp))
{
/* clear the register state for SSM groups */
if (up->reg_state != PIM_REG_NOINFO)
{
if (PIM_DEBUG_PIM_EVENTS)
zlog_debug ("Clear register for %s as G is now SSM",
up->sg_str);
/* remove regiface from the OIL if it is there*/
pim_channel_del_oif (up->channel_oil, pim_regiface,
PIM_OIF_FLAG_PROTO_PIM);
up->reg_state = PIM_REG_NOINFO;
}
}
else
{
/* register ASM sources with the RP */
if (up->reg_state == PIM_REG_NOINFO)
{
if (PIM_DEBUG_PIM_EVENTS)
zlog_debug ("Register %s as G is now ASM", up->sg_str);
pim_channel_add_oif (up->channel_oil, pim_regiface,
PIM_OIF_FLAG_PROTO_PIM);
up->reg_state = PIM_REG_JOIN;
}
}
}
}
void
pim_upstream_switch(struct pim_upstream *up,
enum pim_upstream_state new_state)
@ -507,9 +553,8 @@ pim_upstream_switch(struct pim_upstream *up,
PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
if (!old_fhr && PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags))
{
up->reg_state = PIM_REG_JOIN;
pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time);
pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM);
pim_register_join (up);
}
}
else
@ -1008,10 +1053,8 @@ static void pim_upstream_fhr_kat_start(struct pim_upstream *up)
zlog_debug ("kat started on %s; set fhr reg state to joined", up->sg_str);
PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
if (up->reg_state == PIM_REG_NOINFO) {
pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM);
up->reg_state = PIM_REG_JOIN;
}
if (up->reg_state == PIM_REG_NOINFO)
pim_register_join (up);
}
}

View File

@ -188,4 +188,5 @@ void pim_upstream_terminate (void);
void join_timer_start (struct pim_upstream *up);
int pim_upstream_compare (void *arg1, void *arg2);
void pim_upstream_register_reevaluate (void);
#endif /* PIM_UPSTREAM_H */

View File

@ -38,6 +38,7 @@
#include "pim_static.h"
#include "pim_rp.h"
#include "pim_msdp.h"
#include "pim_ssm.h"
int
pim_debug_config_write (struct vty *vty)
@ -145,6 +146,7 @@ pim_debug_config_write (struct vty *vty)
int pim_global_config_write(struct vty *vty)
{
int writes = 0;
struct pim_ssm *ssm = pimg->ssm_info;
writes += pim_msdp_config_write (vty);
@ -174,6 +176,12 @@ int pim_global_config_write(struct vty *vty)
qpim_packet_process, VTY_NEWLINE);
++writes;
}
if (ssm->plist_name)
{
vty_out (vty, "ip pim ssm prefix-list %s%s",
ssm->plist_name, VTY_NEWLINE);
++writes;
}
if (qpim_ssmpingd_list) {
struct listnode *node;

View File

@ -46,6 +46,7 @@
#include "pim_igmpv3.h"
#include "pim_jp_agg.h"
#include "pim_nht.h"
#include "pim_ssm.h"
#undef PIM_DEBUG_IFADDR_DUMP
#define PIM_DEBUG_IFADDR_DUMP
@ -896,6 +897,84 @@ static int del_oif(struct channel_oil *channel_oil,
return 0;
}
static void
igmp_source_forward_reevaluate_one(struct igmp_source *source)
{
struct prefix_sg sg;
struct igmp_group *group = source->source_group;
struct pim_ifchannel *ch;
if ((source->source_addr.s_addr != INADDR_ANY) ||
!IGMP_SOURCE_TEST_FORWARDING (source->source_flags))
return;
memset (&sg, 0, sizeof (struct prefix_sg));
sg.src = source->source_addr;
sg.grp = group->group_addr;
ch = pim_ifchannel_find (group->group_igmp_sock->interface, &sg);
if (pim_is_grp_ssm (group->group_addr))
{
/* If SSM group withdraw local membership */
if (ch && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE))
{
if (PIM_DEBUG_PIM_EVENTS)
zlog_debug ("local membership del for %s as G is now SSM",
pim_str_sg_dump (&sg));
pim_ifchannel_local_membership_del (group->group_igmp_sock->interface, &sg);
}
}
else
{
/* If ASM group add local membership */
if (!ch || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO))
{
if (PIM_DEBUG_PIM_EVENTS)
zlog_debug ("local membership add for %s as G is now ASM",
pim_str_sg_dump (&sg));
pim_ifchannel_local_membership_add (group->group_igmp_sock->interface, &sg);
}
}
}
void
igmp_source_forward_reevaluate_all(void)
{
struct listnode *ifnode;
struct interface *ifp;
for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp))
{
struct pim_interface *pim_ifp = ifp->info;
struct listnode *sock_node;
struct igmp_sock *igmp;
if (!pim_ifp)
continue;
/* scan igmp sockets */
for (ALL_LIST_ELEMENTS_RO (pim_ifp->igmp_socket_list, sock_node, igmp))
{
struct listnode *grpnode;
struct igmp_group *grp;
/* scan igmp groups */
for (ALL_LIST_ELEMENTS_RO (igmp->igmp_group_list, grpnode, grp))
{
struct listnode *srcnode;
struct igmp_source *src;
/* scan group sources */
for (ALL_LIST_ELEMENTS_RO (grp->group_source_list,
srcnode, src))
{
igmp_source_forward_reevaluate_one (src);
} /* scan group sources */
} /* scan igmp groups */
} /* scan igmp sockets */
} /* scan interfaces */
}
void igmp_source_forward_start(struct igmp_source *source)
{
struct igmp_group *group;

View File

@ -38,6 +38,7 @@ void igmp_anysource_forward_stop(struct igmp_group *group);
void igmp_source_forward_start(struct igmp_source *source);
void igmp_source_forward_stop(struct igmp_source *source);
void igmp_source_forward_reevaluate_all(void);
void pim_forward_start(struct pim_ifchannel *ch);
void pim_forward_stop(struct pim_ifchannel *ch);

View File

@ -41,6 +41,7 @@
#include "pim_ssmpingd.h"
#include "pim_static.h"
#include "pim_rp.h"
#include "pim_ssm.h"
#include "pim_zlookup.h"
#include "pim_nht.h"
@ -182,6 +183,13 @@ pim_rp_list_hash_clean (void *data)
list_delete_all_node (pnc->upstream_list);
}
void
pim_prefix_list_update (struct prefix_list *plist)
{
pim_rp_prefix_list_update (plist);
pim_ssm_prefix_list_update (plist);
}
static void
pim_instance_terminate (void)
{
@ -191,6 +199,7 @@ pim_instance_terminate (void)
hash_clean (pimg->rpf_hash, (void *) pim_rp_list_hash_clean);
hash_free (pimg->rpf_hash);
}
pim_ssm_terminate (pimg->ssm_info);
XFREE (MTYPE_PIM_PIM_INSTANCE, pimg);
}
@ -233,6 +242,11 @@ pim_instance_init (vrf_id_t vrf_id, afi_t afi)
if (PIM_DEBUG_ZEBRA)
zlog_debug ("%s: NHT rpf hash init ", __PRETTY_FUNCTION__);
pim->ssm_info = pim_ssm_init (vrf_id);
if (!pim->ssm_info) {
pim_instance_terminate ();
return NULL;
}
return pim;
}

View File

@ -24,6 +24,9 @@
#include <stdint.h>
#include "zebra.h"
#include "libfrr.h"
#include "prefix.h"
#include "vty.h"
#include "plist.h"
#include "pim_str.h"
#include "pim_memory.h"
@ -240,6 +243,7 @@ struct pim_instance
afi_t afi;
vrf_id_t vrf_id;
struct hash *rpf_hash;
void *ssm_info; /* per-vrf SSM configuration */
};
extern struct pim_instance *pimg; //Pim Global Instance
@ -250,5 +254,6 @@ void pim_terminate(void);
extern void pim_route_map_init (void);
extern void pim_route_map_terminate(void);
void pim_vrf_init (void);
void pim_prefix_list_update (struct prefix_list *plist);
#endif /* PIMD_H */