mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-27 13:46:45 +00:00
commit
2b5c7fa46d
@ -53,7 +53,7 @@ libpim_a_SOURCES = \
|
|||||||
pim_ssmpingd.c pim_int.c pim_rp.c \
|
pim_ssmpingd.c pim_int.c pim_rp.c \
|
||||||
pim_static.c pim_br.c pim_register.c pim_routemap.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_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 = \
|
noinst_HEADERS = \
|
||||||
pim_memory.h \
|
pim_memory.h \
|
||||||
@ -66,7 +66,7 @@ noinst_HEADERS = \
|
|||||||
pim_igmp_join.h pim_ssmpingd.h pim_int.h pim_rp.h \
|
pim_igmp_join.h pim_ssmpingd.h pim_int.h pim_rp.h \
|
||||||
pim_static.h pim_br.h pim_register.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_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 = \
|
pimd_SOURCES = \
|
||||||
pim_main.c $(libpim_a_SOURCES)
|
pim_main.c $(libpim_a_SOURCES)
|
||||||
|
168
pimd/pim_cmd.c
168
pimd/pim_cmd.c
@ -54,6 +54,7 @@
|
|||||||
#include "pim_rp.h"
|
#include "pim_rp.h"
|
||||||
#include "pim_zlookup.h"
|
#include "pim_zlookup.h"
|
||||||
#include "pim_msdp.h"
|
#include "pim_msdp.h"
|
||||||
|
#include "pim_ssm.h"
|
||||||
|
|
||||||
static struct cmd_node pim_global_node = {
|
static struct cmd_node pim_global_node = {
|
||||||
PIM_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);
|
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,
|
DEFUN_HIDDEN (ip_multicast_routing,
|
||||||
ip_multicast_routing_cmd,
|
ip_multicast_routing_cmd,
|
||||||
"ip multicast-routing",
|
"ip multicast-routing",
|
||||||
@ -4292,7 +4440,7 @@ DEFUN (interface_no_ip_pim_drprio,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pim_cmd_interface_add (struct interface *ifp, enum pim_interface_type itype)
|
pim_cmd_interface_add (struct interface *ifp)
|
||||||
{
|
{
|
||||||
struct pim_interface *pim_ifp = ifp->info;
|
struct pim_interface *pim_ifp = ifp->info;
|
||||||
|
|
||||||
@ -4306,14 +4454,12 @@ pim_cmd_interface_add (struct interface *ifp, enum pim_interface_type itype)
|
|||||||
PIM_IF_DO_PIM(pim_ifp->options);
|
PIM_IF_DO_PIM(pim_ifp->options);
|
||||||
}
|
}
|
||||||
|
|
||||||
pim_ifp->itype = itype;
|
|
||||||
pim_if_addr_add_all(ifp);
|
pim_if_addr_add_all(ifp);
|
||||||
pim_if_membership_refresh(ifp);
|
pim_if_membership_refresh(ifp);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN_HIDDEN (interface_ip_pim_ssm,
|
||||||
DEFUN (interface_ip_pim_ssm,
|
|
||||||
interface_ip_pim_ssm_cmd,
|
interface_ip_pim_ssm_cmd,
|
||||||
"ip pim ssm",
|
"ip pim ssm",
|
||||||
IP_STR
|
IP_STR
|
||||||
@ -4322,11 +4468,12 @@ DEFUN (interface_ip_pim_ssm,
|
|||||||
{
|
{
|
||||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||||
|
|
||||||
if (!pim_cmd_interface_add(ifp, PIM_INTERFACE_SSM)) {
|
if (!pim_cmd_interface_add(ifp)) {
|
||||||
vty_out(vty, "Could not enable PIM SSM on interface%s", VTY_NEWLINE);
|
vty_out(vty, "Could not enable PIM SM on interface%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vty_out(vty, "WARN: Enabled PIM SM on interface; configure PIM SSM range if needed%s", VTY_NEWLINE);
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4338,7 +4485,7 @@ DEFUN (interface_ip_pim_sm,
|
|||||||
IFACE_PIM_SM_STR)
|
IFACE_PIM_SM_STR)
|
||||||
{
|
{
|
||||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||||
if (!pim_cmd_interface_add(ifp, PIM_INTERFACE_SM)) {
|
if (!pim_cmd_interface_add(ifp)) {
|
||||||
vty_out(vty, "Could not enable PIM SM on interface%s", VTY_NEWLINE);
|
vty_out(vty, "Could not enable PIM SM on interface%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
@ -4374,7 +4521,7 @@ pim_cmd_interface_delete (struct interface *ifp)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (interface_no_ip_pim_ssm,
|
DEFUN_HIDDEN (interface_no_ip_pim_ssm,
|
||||||
interface_no_ip_pim_ssm_cmd,
|
interface_no_ip_pim_ssm_cmd,
|
||||||
"no ip pim ssm",
|
"no ip pim ssm",
|
||||||
NO_STR
|
NO_STR
|
||||||
@ -6029,6 +6176,9 @@ void pim_cmd_init()
|
|||||||
install_element (CONFIG_NODE, &no_ip_pim_rp_cmd);
|
install_element (CONFIG_NODE, &no_ip_pim_rp_cmd);
|
||||||
install_element (CONFIG_NODE, &ip_pim_rp_prefix_list_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_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, &ip_pim_register_suppress_cmd);
|
||||||
install_element (CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
|
install_element (CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
|
||||||
install_element (CONFIG_NODE, &ip_pim_joinprune_time_cmd);
|
install_element (CONFIG_NODE, &ip_pim_joinprune_time_cmd);
|
||||||
@ -6186,6 +6336,8 @@ void pim_cmd_init()
|
|||||||
install_element (VIEW_NODE, &show_ip_msdp_sa_detail_cmd);
|
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_sa_sg_cmd);
|
||||||
install_element (VIEW_NODE, &show_ip_msdp_mesh_group_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_pim_use_source_cmd);
|
||||||
install_element (INTERFACE_NODE, &interface_no_pim_use_source_cmd);
|
install_element (INTERFACE_NODE, &interface_no_pim_use_source_cmd);
|
||||||
}
|
}
|
||||||
|
@ -58,11 +58,6 @@ struct pim_iface_upstream_switch {
|
|||||||
struct list *us;
|
struct list *us;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum pim_interface_type {
|
|
||||||
PIM_INTERFACE_SSM,
|
|
||||||
PIM_INTERFACE_SM
|
|
||||||
};
|
|
||||||
|
|
||||||
enum pim_secondary_addr_flags {
|
enum pim_secondary_addr_flags {
|
||||||
PIM_SEC_ADDRF_NONE = 0,
|
PIM_SEC_ADDRF_NONE = 0,
|
||||||
PIM_SEC_ADDRF_STALE = (1 << 0)
|
PIM_SEC_ADDRF_STALE = (1 << 0)
|
||||||
@ -74,7 +69,6 @@ struct pim_secondary_addr {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct pim_interface {
|
struct pim_interface {
|
||||||
enum pim_interface_type itype;
|
|
||||||
uint32_t options; /* bit vector */
|
uint32_t options; /* bit vector */
|
||||||
ifindex_t mroute_vif_index;
|
ifindex_t mroute_vif_index;
|
||||||
struct in_addr primary_address; /* remember addr to detect change */
|
struct in_addr primary_address; /* remember addr to detect change */
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "pim_macro.h"
|
#include "pim_macro.h"
|
||||||
#include "pim_oil.h"
|
#include "pim_oil.h"
|
||||||
#include "pim_upstream.h"
|
#include "pim_upstream.h"
|
||||||
|
#include "pim_ssm.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2)
|
pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2)
|
||||||
@ -967,6 +968,18 @@ pim_ifchannel_local_membership_add(struct interface *ifp,
|
|||||||
if (!PIM_IF_TEST_PIM(pim_ifp->options))
|
if (!PIM_IF_TEST_PIM(pim_ifp->options))
|
||||||
return 0;
|
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);
|
ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP);
|
||||||
if (!ch) {
|
if (!ch) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -46,7 +46,6 @@
|
|||||||
#include "pim_zebra.h"
|
#include "pim_zebra.h"
|
||||||
#include "pim_msdp.h"
|
#include "pim_msdp.h"
|
||||||
#include "pim_iface.h"
|
#include "pim_iface.h"
|
||||||
#include "pim_rp.h"
|
|
||||||
|
|
||||||
extern struct host host;
|
extern struct host host;
|
||||||
|
|
||||||
@ -120,8 +119,8 @@ int main(int argc, char** argv, char** envp) {
|
|||||||
pim_vrf_init ();
|
pim_vrf_init ();
|
||||||
access_list_init();
|
access_list_init();
|
||||||
prefix_list_init ();
|
prefix_list_init ();
|
||||||
prefix_list_add_hook (pim_rp_prefix_list_update);
|
prefix_list_add_hook (pim_prefix_list_update);
|
||||||
prefix_list_delete_hook (pim_rp_prefix_list_update);
|
prefix_list_delete_hook (pim_prefix_list_update);
|
||||||
|
|
||||||
pim_route_map_init ();
|
pim_route_map_init ();
|
||||||
pim_init();
|
pim_init();
|
||||||
|
@ -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_JP_AGG_SOURCE, "PIM JP AGG Source")
|
||||||
DEFINE_MTYPE(PIMD, PIM_PIM_INSTANCE, "PIM global state")
|
DEFINE_MTYPE(PIMD, PIM_PIM_INSTANCE, "PIM global state")
|
||||||
DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state")
|
DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state")
|
||||||
|
DEFINE_MTYPE(PIMD, PIM_SSM_INFO, "PIM SSM configuration")
|
||||||
|
@ -50,5 +50,6 @@ DECLARE_MTYPE(PIM_JP_AGG_GROUP)
|
|||||||
DECLARE_MTYPE(PIM_JP_AGG_SOURCE)
|
DECLARE_MTYPE(PIM_JP_AGG_SOURCE)
|
||||||
DECLARE_MTYPE(PIM_PIM_INSTANCE)
|
DECLARE_MTYPE(PIM_PIM_INSTANCE)
|
||||||
DECLARE_MTYPE(PIM_NEXTHOP_CACHE)
|
DECLARE_MTYPE(PIM_NEXTHOP_CACHE)
|
||||||
|
DECLARE_MTYPE(PIM_SSM_INFO)
|
||||||
|
|
||||||
#endif /* _QUAGGA_PIM_MEMORY_H */
|
#endif /* _QUAGGA_PIM_MEMORY_H */
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "pim_register.h"
|
#include "pim_register.h"
|
||||||
#include "pim_ifchannel.h"
|
#include "pim_ifchannel.h"
|
||||||
#include "pim_zlookup.h"
|
#include "pim_zlookup.h"
|
||||||
|
#include "pim_ssm.h"
|
||||||
|
|
||||||
/* GLOBAL VARS */
|
/* GLOBAL VARS */
|
||||||
static struct thread *qpim_mroute_socket_reader = NULL;
|
static struct thread *qpim_mroute_socket_reader = NULL;
|
||||||
@ -127,8 +128,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg
|
|||||||
*/
|
*/
|
||||||
if ((pim_rpf_addr_is_inaddr_none (rpg)) ||
|
if ((pim_rpf_addr_is_inaddr_none (rpg)) ||
|
||||||
(!pim_ifp) ||
|
(!pim_ifp) ||
|
||||||
(!(PIM_I_am_DR(pim_ifp))) ||
|
(!(PIM_I_am_DR(pim_ifp))))
|
||||||
(pim_ifp->itype == PIM_INTERFACE_SSM))
|
|
||||||
{
|
{
|
||||||
if (PIM_DEBUG_MROUTE_DETAIL)
|
if (PIM_DEBUG_MROUTE_DETAIL)
|
||||||
zlog_debug ("%s: Interface is not configured correctly to handle incoming packet: Could be !DR, !pim_ifp, !SM, !RP",
|
zlog_debug ("%s: Interface is not configured correctly to handle incoming packet: Could be !DR, !pim_ifp, !SM, !RP",
|
||||||
@ -178,8 +178,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg
|
|||||||
|
|
||||||
up->channel_oil->cc.pktcnt++;
|
up->channel_oil->cc.pktcnt++;
|
||||||
PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
|
PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
|
||||||
pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM);
|
pim_register_join (up);
|
||||||
up->reg_state = PIM_REG_JOIN;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -214,8 +213,7 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf)
|
|||||||
|
|
||||||
if ((pim_rpf_addr_is_inaddr_none (rpg)) ||
|
if ((pim_rpf_addr_is_inaddr_none (rpg)) ||
|
||||||
(!pim_ifp) ||
|
(!pim_ifp) ||
|
||||||
(!(PIM_I_am_DR(pim_ifp))) ||
|
(!(PIM_I_am_DR(pim_ifp)))) {
|
||||||
(pim_ifp->itype == PIM_INTERFACE_SSM)) {
|
|
||||||
if (PIM_DEBUG_MROUTE) {
|
if (PIM_DEBUG_MROUTE) {
|
||||||
zlog_debug("%s: Failed Check send packet", __PRETTY_FUNCTION__);
|
zlog_debug("%s: Failed Check send packet", __PRETTY_FUNCTION__);
|
||||||
}
|
}
|
||||||
@ -226,9 +224,18 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf)
|
|||||||
* If we've received a register suppress
|
* If we've received a register suppress
|
||||||
*/
|
*/
|
||||||
if (!up->t_rs_timer)
|
if (!up->t_rs_timer)
|
||||||
|
{
|
||||||
|
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),
|
pim_register_send((uint8_t *)buf + sizeof(struct ip),
|
||||||
ntohs (ip_hdr->ip_len) - sizeof (struct ip),
|
ntohs (ip_hdr->ip_len) - sizeof (struct ip),
|
||||||
pim_ifp->primary_address, rpg, 0, up);
|
pim_ifp->primary_address, rpg, 0, up);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,8 +449,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf)
|
|||||||
pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time);
|
pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time);
|
||||||
up->channel_oil = oil;
|
up->channel_oil = oil;
|
||||||
up->channel_oil->cc.pktcnt++;
|
up->channel_oil->cc.pktcnt++;
|
||||||
pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM);
|
pim_register_join (up);
|
||||||
up->reg_state = PIM_REG_JOIN;
|
|
||||||
pim_upstream_inherited_olist (up);
|
pim_upstream_inherited_olist (up);
|
||||||
|
|
||||||
// Send the packet to the RP
|
// Send the packet to the RP
|
||||||
|
@ -43,9 +43,24 @@
|
|||||||
#include "pim_zebra.h"
|
#include "pim_zebra.h"
|
||||||
#include "pim_join.h"
|
#include "pim_join.h"
|
||||||
#include "pim_util.h"
|
#include "pim_util.h"
|
||||||
|
#include "pim_ssm.h"
|
||||||
|
|
||||||
struct thread *send_test_packet_timer = NULL;
|
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
|
void
|
||||||
pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg,
|
pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg,
|
||||||
struct in_addr src, struct in_addr originator)
|
struct in_addr src, struct in_addr originator)
|
||||||
|
@ -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_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_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
|
#endif
|
||||||
|
158
pimd/pim_ssm.c
Normal file
158
pimd/pim_ssm.c
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
* 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 <zebra.h>
|
||||||
|
|
||||||
|
#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
44
pimd/pim_ssm.h
Normal 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
|
@ -53,6 +53,7 @@
|
|||||||
#include "pim_msdp.h"
|
#include "pim_msdp.h"
|
||||||
#include "pim_jp_agg.h"
|
#include "pim_jp_agg.h"
|
||||||
#include "pim_nht.h"
|
#include "pim_nht.h"
|
||||||
|
#include "pim_ssm.h"
|
||||||
|
|
||||||
struct hash *pim_upstream_hash = NULL;
|
struct hash *pim_upstream_hash = NULL;
|
||||||
struct list *pim_upstream_list = NULL;
|
struct list *pim_upstream_list = NULL;
|
||||||
@ -476,6 +477,51 @@ pim_upstream_could_register (struct pim_upstream *up)
|
|||||||
return 0;
|
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
|
void
|
||||||
pim_upstream_switch(struct pim_upstream *up,
|
pim_upstream_switch(struct pim_upstream *up,
|
||||||
enum pim_upstream_state new_state)
|
enum pim_upstream_state new_state)
|
||||||
@ -507,9 +553,8 @@ pim_upstream_switch(struct pim_upstream *up,
|
|||||||
PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
|
PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
|
||||||
if (!old_fhr && PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(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_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
|
else
|
||||||
@ -1018,10 +1063,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);
|
zlog_debug ("kat started on %s; set fhr reg state to joined", up->sg_str);
|
||||||
|
|
||||||
PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
|
PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
|
||||||
if (up->reg_state == PIM_REG_NOINFO) {
|
if (up->reg_state == PIM_REG_NOINFO)
|
||||||
pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM);
|
pim_register_join (up);
|
||||||
up->reg_state = PIM_REG_JOIN;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,4 +192,5 @@ void pim_upstream_terminate (void);
|
|||||||
|
|
||||||
void join_timer_start (struct pim_upstream *up);
|
void join_timer_start (struct pim_upstream *up);
|
||||||
int pim_upstream_compare (void *arg1, void *arg2);
|
int pim_upstream_compare (void *arg1, void *arg2);
|
||||||
|
void pim_upstream_register_reevaluate (void);
|
||||||
#endif /* PIM_UPSTREAM_H */
|
#endif /* PIM_UPSTREAM_H */
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include "pim_static.h"
|
#include "pim_static.h"
|
||||||
#include "pim_rp.h"
|
#include "pim_rp.h"
|
||||||
#include "pim_msdp.h"
|
#include "pim_msdp.h"
|
||||||
|
#include "pim_ssm.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
pim_debug_config_write (struct vty *vty)
|
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 pim_global_config_write(struct vty *vty)
|
||||||
{
|
{
|
||||||
int writes = 0;
|
int writes = 0;
|
||||||
|
struct pim_ssm *ssm = pimg->ssm_info;
|
||||||
|
|
||||||
writes += pim_msdp_config_write (vty);
|
writes += pim_msdp_config_write (vty);
|
||||||
|
|
||||||
@ -174,6 +176,12 @@ int pim_global_config_write(struct vty *vty)
|
|||||||
qpim_packet_process, VTY_NEWLINE);
|
qpim_packet_process, VTY_NEWLINE);
|
||||||
++writes;
|
++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) {
|
if (qpim_ssmpingd_list) {
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
@ -206,11 +214,7 @@ int pim_interface_config_write(struct vty *vty)
|
|||||||
if (ifp->info) {
|
if (ifp->info) {
|
||||||
struct pim_interface *pim_ifp = ifp->info;
|
struct pim_interface *pim_ifp = ifp->info;
|
||||||
|
|
||||||
/* IF ip pim ssm */
|
|
||||||
if (PIM_IF_TEST_PIM(pim_ifp->options)) {
|
if (PIM_IF_TEST_PIM(pim_ifp->options)) {
|
||||||
if (pim_ifp->itype == PIM_INTERFACE_SSM)
|
|
||||||
vty_out(vty, " ip pim ssm%s", VTY_NEWLINE);
|
|
||||||
else
|
|
||||||
vty_out(vty, " ip pim sm%s", VTY_NEWLINE);
|
vty_out(vty, " ip pim sm%s", VTY_NEWLINE);
|
||||||
++writes;
|
++writes;
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "pim_igmpv3.h"
|
#include "pim_igmpv3.h"
|
||||||
#include "pim_jp_agg.h"
|
#include "pim_jp_agg.h"
|
||||||
#include "pim_nht.h"
|
#include "pim_nht.h"
|
||||||
|
#include "pim_ssm.h"
|
||||||
|
|
||||||
#undef PIM_DEBUG_IFADDR_DUMP
|
#undef PIM_DEBUG_IFADDR_DUMP
|
||||||
#define PIM_DEBUG_IFADDR_DUMP
|
#define PIM_DEBUG_IFADDR_DUMP
|
||||||
@ -760,6 +761,84 @@ static int fib_lookup_if_vif_index(struct in_addr addr)
|
|||||||
return vif_index;
|
return vif_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
void igmp_source_forward_start(struct igmp_source *source)
|
||||||
{
|
{
|
||||||
struct igmp_group *group;
|
struct igmp_group *group;
|
||||||
|
@ -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_start(struct igmp_source *source);
|
||||||
void igmp_source_forward_stop(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_start(struct pim_ifchannel *ch);
|
||||||
void pim_forward_stop(struct pim_ifchannel *ch);
|
void pim_forward_stop(struct pim_ifchannel *ch);
|
||||||
|
14
pimd/pimd.c
14
pimd/pimd.c
@ -41,6 +41,7 @@
|
|||||||
#include "pim_ssmpingd.h"
|
#include "pim_ssmpingd.h"
|
||||||
#include "pim_static.h"
|
#include "pim_static.h"
|
||||||
#include "pim_rp.h"
|
#include "pim_rp.h"
|
||||||
|
#include "pim_ssm.h"
|
||||||
#include "pim_zlookup.h"
|
#include "pim_zlookup.h"
|
||||||
#include "pim_nht.h"
|
#include "pim_nht.h"
|
||||||
|
|
||||||
@ -182,6 +183,13 @@ pim_rp_list_hash_clean (void *data)
|
|||||||
list_delete_all_node (pnc->upstream_list);
|
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
|
static void
|
||||||
pim_instance_terminate (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_clean (pimg->rpf_hash, (void *) pim_rp_list_hash_clean);
|
||||||
hash_free (pimg->rpf_hash);
|
hash_free (pimg->rpf_hash);
|
||||||
}
|
}
|
||||||
|
pim_ssm_terminate (pimg->ssm_info);
|
||||||
|
|
||||||
XFREE (MTYPE_PIM_PIM_INSTANCE, pimg);
|
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)
|
if (PIM_DEBUG_ZEBRA)
|
||||||
zlog_debug ("%s: NHT rpf hash init ", __PRETTY_FUNCTION__);
|
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;
|
return pim;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "zebra.h"
|
#include "zebra.h"
|
||||||
#include "libfrr.h"
|
#include "libfrr.h"
|
||||||
|
#include "prefix.h"
|
||||||
|
#include "vty.h"
|
||||||
|
#include "plist.h"
|
||||||
|
|
||||||
#include "pim_str.h"
|
#include "pim_str.h"
|
||||||
#include "pim_memory.h"
|
#include "pim_memory.h"
|
||||||
@ -240,6 +243,7 @@ struct pim_instance
|
|||||||
afi_t afi;
|
afi_t afi;
|
||||||
vrf_id_t vrf_id;
|
vrf_id_t vrf_id;
|
||||||
struct hash *rpf_hash;
|
struct hash *rpf_hash;
|
||||||
|
void *ssm_info; /* per-vrf SSM configuration */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct pim_instance *pimg; //Pim Global Instance
|
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_init (void);
|
||||||
extern void pim_route_map_terminate(void);
|
extern void pim_route_map_terminate(void);
|
||||||
void pim_vrf_init (void);
|
void pim_vrf_init (void);
|
||||||
|
void pim_prefix_list_update (struct prefix_list *plist);
|
||||||
|
|
||||||
#endif /* PIMD_H */
|
#endif /* PIMD_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user