mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-27 11:44:16 +00:00
commit
0b4cbacad9
@ -3416,6 +3416,33 @@ pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const cha
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pim_cmd_spt_switchover (enum pim_spt_switchover spt, const char *plist)
|
||||||
|
{
|
||||||
|
pimg->spt.switchover = spt;
|
||||||
|
|
||||||
|
switch (pimg->spt.switchover)
|
||||||
|
{
|
||||||
|
case PIM_SPT_IMMEDIATE:
|
||||||
|
if (pimg->spt.plist)
|
||||||
|
XFREE (MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist);
|
||||||
|
|
||||||
|
pim_upstream_add_lhr_star_pimreg ();
|
||||||
|
break;
|
||||||
|
case PIM_SPT_INFINITY:
|
||||||
|
pim_upstream_remove_lhr_star_pimreg (plist);
|
||||||
|
|
||||||
|
if (pimg->spt.plist)
|
||||||
|
XFREE (MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist);
|
||||||
|
|
||||||
|
if (plist)
|
||||||
|
pimg->spt.plist = XSTRDUP (MTYPE_PIM_SPT_PLIST_NAME, plist);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
DEFUN (ip_pim_spt_switchover_infinity,
|
DEFUN (ip_pim_spt_switchover_infinity,
|
||||||
ip_pim_spt_switchover_infinity_cmd,
|
ip_pim_spt_switchover_infinity_cmd,
|
||||||
"ip pim spt-switchover infinity-and-beyond",
|
"ip pim spt-switchover infinity-and-beyond",
|
||||||
@ -3424,10 +3451,20 @@ DEFUN (ip_pim_spt_switchover_infinity,
|
|||||||
"SPT-Switchover\n"
|
"SPT-Switchover\n"
|
||||||
"Never switch to SPT Tree\n")
|
"Never switch to SPT Tree\n")
|
||||||
{
|
{
|
||||||
pimg->spt_switchover = PIM_SPT_INFINITY;
|
return pim_cmd_spt_switchover (PIM_SPT_INFINITY, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
pim_upstream_remove_lhr_star_pimreg();
|
DEFUN (ip_pim_spt_switchover_infinity_plist,
|
||||||
return CMD_SUCCESS;
|
ip_pim_spt_switchover_infinity_plist_cmd,
|
||||||
|
"ip pim spt-switchover infinity-and-beyond prefix-list WORD",
|
||||||
|
IP_STR
|
||||||
|
PIM_STR
|
||||||
|
"SPT-Switchover\n"
|
||||||
|
"Never switch to SPT Tree\n"
|
||||||
|
"Prefix-List to control which groups to switch\n"
|
||||||
|
"Prefix-List name\n")
|
||||||
|
{
|
||||||
|
return pim_cmd_spt_switchover (PIM_SPT_INFINITY, argv[5]->arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (no_ip_pim_spt_switchover_infinity,
|
DEFUN (no_ip_pim_spt_switchover_infinity,
|
||||||
@ -3439,10 +3476,21 @@ DEFUN (no_ip_pim_spt_switchover_infinity,
|
|||||||
"SPT_Switchover\n"
|
"SPT_Switchover\n"
|
||||||
"Never switch to SPT Tree\n")
|
"Never switch to SPT Tree\n")
|
||||||
{
|
{
|
||||||
pimg->spt_switchover = PIM_SPT_IMMEDIATE;
|
return pim_cmd_spt_switchover (PIM_SPT_IMMEDIATE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
pim_upstream_add_lhr_star_pimreg();
|
DEFUN (no_ip_pim_spt_switchover_infinity_plist,
|
||||||
return CMD_SUCCESS;
|
no_ip_pim_spt_switchover_infinity_plist_cmd,
|
||||||
|
"no ip pim spt-switchover infinity-and-beyond prefix-list WORD",
|
||||||
|
NO_STR
|
||||||
|
IP_STR
|
||||||
|
PIM_STR
|
||||||
|
"SPT_Switchover\n"
|
||||||
|
"Never switch to SPT Tree\n"
|
||||||
|
"Prefix-List to control which groups to switch\n"
|
||||||
|
"Prefix-List name\n")
|
||||||
|
{
|
||||||
|
return pim_cmd_spt_switchover (PIM_SPT_IMMEDIATE, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (ip_pim_joinprune_time,
|
DEFUN (ip_pim_joinprune_time,
|
||||||
@ -6217,7 +6265,9 @@ void pim_cmd_init()
|
|||||||
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_spt_switchover_infinity_cmd);
|
install_element (CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd);
|
||||||
|
install_element (CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
|
||||||
install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
|
install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
|
||||||
|
install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd);
|
||||||
install_element (CONFIG_NODE, &ip_pim_joinprune_time_cmd);
|
install_element (CONFIG_NODE, &ip_pim_joinprune_time_cmd);
|
||||||
install_element (CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
|
install_element (CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
|
||||||
install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd);
|
install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "vrf.h"
|
#include "vrf.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "jhash.h"
|
#include "jhash.h"
|
||||||
|
#include "prefix.h"
|
||||||
|
|
||||||
#include "pimd.h"
|
#include "pimd.h"
|
||||||
#include "pim_str.h"
|
#include "pim_str.h"
|
||||||
@ -49,6 +50,15 @@ pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2)
|
|||||||
struct pim_interface *pim_ifp1;
|
struct pim_interface *pim_ifp1;
|
||||||
struct pim_interface *pim_ifp2;
|
struct pim_interface *pim_ifp2;
|
||||||
|
|
||||||
|
pim_ifp1 = ch1->interface->info;
|
||||||
|
pim_ifp2 = ch2->interface->info;
|
||||||
|
|
||||||
|
if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr))
|
if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -61,20 +71,6 @@ pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2)
|
|||||||
if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr))
|
if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
pim_ifp1 = ch1->interface->info;
|
|
||||||
pim_ifp2 = ch2->interface->info;
|
|
||||||
if (ntohl(pim_ifp1->primary_address.s_addr) < ntohl(pim_ifp2->primary_address.s_addr))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (ntohl(pim_ifp1->primary_address.s_addr) > ntohl(pim_ifp2->primary_address.s_addr))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,6 +170,8 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
|
|||||||
if (ch->sources)
|
if (ch->sources)
|
||||||
list_delete (ch->sources);
|
list_delete (ch->sources);
|
||||||
|
|
||||||
|
listnode_delete(ch->upstream->ifchannels, ch);
|
||||||
|
|
||||||
if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) {
|
if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) {
|
||||||
pim_upstream_update_join_desired(ch->upstream);
|
pim_upstream_update_join_desired(ch->upstream);
|
||||||
}
|
}
|
||||||
@ -568,6 +566,8 @@ pim_ifchannel_add(struct interface *ifp,
|
|||||||
ch = hash_get (pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern);
|
ch = hash_get (pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern);
|
||||||
listnode_add_sort(pim_ifchannel_list, ch);
|
listnode_add_sort(pim_ifchannel_list, ch);
|
||||||
|
|
||||||
|
listnode_add_sort(up->ifchannels, ch);
|
||||||
|
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -958,7 +958,7 @@ int
|
|||||||
pim_ifchannel_local_membership_add(struct interface *ifp,
|
pim_ifchannel_local_membership_add(struct interface *ifp,
|
||||||
struct prefix_sg *sg)
|
struct prefix_sg *sg)
|
||||||
{
|
{
|
||||||
struct pim_ifchannel *ch;
|
struct pim_ifchannel *ch, *starch;
|
||||||
struct pim_interface *pim_ifp;
|
struct pim_interface *pim_ifp;
|
||||||
|
|
||||||
/* PIM enabled on interface? */
|
/* PIM enabled on interface? */
|
||||||
@ -993,21 +993,41 @@ pim_ifchannel_local_membership_add(struct interface *ifp,
|
|||||||
struct pim_upstream *child;
|
struct pim_upstream *child;
|
||||||
struct listnode *up_node;
|
struct listnode *up_node;
|
||||||
|
|
||||||
|
starch = ch;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child))
|
for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child))
|
||||||
{
|
{
|
||||||
if (PIM_DEBUG_EVENTS)
|
if (PIM_DEBUG_EVENTS)
|
||||||
zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s",
|
zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s",
|
||||||
__FILE__, __PRETTY_FUNCTION__,
|
__FILE__, __PRETTY_FUNCTION__,
|
||||||
child->sg_str, ifp->name, up->sg_str);
|
child->sg_str, ifp->name, up->sg_str);
|
||||||
|
|
||||||
if (pim_upstream_evaluate_join_desired_interface (child, ch))
|
ch = pim_ifchannel_find (ifp, &child->sg);
|
||||||
{
|
if (pim_upstream_evaluate_join_desired_interface (child, ch, starch))
|
||||||
pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
|
{
|
||||||
pim_upstream_switch (child, PIM_UPSTREAM_JOINED);
|
pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
|
||||||
}
|
pim_upstream_switch (child, PIM_UPSTREAM_JOINED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pimg->spt_switchover != PIM_SPT_INFINITY)
|
|
||||||
pim_channel_add_oif(up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
|
if (pimg->spt.switchover == PIM_SPT_INFINITY)
|
||||||
|
{
|
||||||
|
if (pimg->spt.plist)
|
||||||
|
{
|
||||||
|
struct prefix_list *plist = prefix_list_lookup (AFI_IP, pimg->spt.plist);
|
||||||
|
struct prefix g;
|
||||||
|
g.family = AF_INET;
|
||||||
|
g.prefixlen = IPV4_MAX_PREFIXLEN;
|
||||||
|
g.u.prefix4 = up->sg.grp;
|
||||||
|
|
||||||
|
if (prefix_list_apply (plist, &g) == PREFIX_DENY)
|
||||||
|
{
|
||||||
|
pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -1016,7 +1036,7 @@ pim_ifchannel_local_membership_add(struct interface *ifp,
|
|||||||
void pim_ifchannel_local_membership_del(struct interface *ifp,
|
void pim_ifchannel_local_membership_del(struct interface *ifp,
|
||||||
struct prefix_sg *sg)
|
struct prefix_sg *sg)
|
||||||
{
|
{
|
||||||
struct pim_ifchannel *ch;
|
struct pim_ifchannel *starch, *ch, *orig;
|
||||||
struct pim_interface *pim_ifp;
|
struct pim_interface *pim_ifp;
|
||||||
|
|
||||||
/* PIM enabled on interface? */
|
/* PIM enabled on interface? */
|
||||||
@ -1026,7 +1046,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
|
|||||||
if (!PIM_IF_TEST_PIM(pim_ifp->options))
|
if (!PIM_IF_TEST_PIM(pim_ifp->options))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ch = pim_ifchannel_find(ifp, sg);
|
orig = ch = pim_ifchannel_find(ifp, sg);
|
||||||
if (!ch)
|
if (!ch)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1036,9 +1056,11 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
|
|||||||
{
|
{
|
||||||
struct pim_upstream *up = pim_upstream_find (sg);
|
struct pim_upstream *up = pim_upstream_find (sg);
|
||||||
struct pim_upstream *child;
|
struct pim_upstream *child;
|
||||||
struct listnode *up_node;
|
struct listnode *up_node, *up_nnode;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child))
|
starch = ch;
|
||||||
|
|
||||||
|
for (ALL_LIST_ELEMENTS (up->sources, up_node, up_nnode, child))
|
||||||
{
|
{
|
||||||
struct channel_oil *c_oil = child->channel_oil;
|
struct channel_oil *c_oil = child->channel_oil;
|
||||||
struct pim_ifchannel *chchannel = pim_ifchannel_find (ifp, &child->sg);
|
struct pim_ifchannel *chchannel = pim_ifchannel_find (ifp, &child->sg);
|
||||||
@ -1049,7 +1071,8 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
|
|||||||
__FILE__, __PRETTY_FUNCTION__,
|
__FILE__, __PRETTY_FUNCTION__,
|
||||||
up->sg_str, ifp->name, child->sg_str);
|
up->sg_str, ifp->name, child->sg_str);
|
||||||
|
|
||||||
if (c_oil && !pim_upstream_evaluate_join_desired_interface (child, ch))
|
ch = pim_ifchannel_find (ifp, &child->sg);
|
||||||
|
if (c_oil && !pim_upstream_evaluate_join_desired_interface (child, ch, starch))
|
||||||
pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
|
pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1059,9 +1082,12 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
|
|||||||
*/
|
*/
|
||||||
if (!chchannel && c_oil && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index])
|
if (!chchannel && c_oil && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index])
|
||||||
pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
|
pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
|
||||||
|
|
||||||
|
if (c_oil->oil_size == 0)
|
||||||
|
pim_upstream_del (child, __PRETTY_FUNCTION__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete_on_noinfo(ch);
|
delete_on_noinfo(orig);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch)
|
void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch)
|
||||||
|
@ -52,3 +52,4 @@ 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")
|
DEFINE_MTYPE(PIMD, PIM_SSM_INFO, "PIM SSM configuration")
|
||||||
|
DEFINE_MTYPE(PIMD, PIM_SPT_PLIST_NAME, "PIM SPT Prefix List Name")
|
||||||
|
@ -51,5 +51,6 @@ 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)
|
DECLARE_MTYPE(PIM_SSM_INFO)
|
||||||
|
DECLARE_MTYPE(PIM_SPT_PLIST_NAME);
|
||||||
|
|
||||||
#endif /* _QUAGGA_PIM_MEMORY_H */
|
#endif /* _QUAGGA_PIM_MEMORY_H */
|
||||||
|
@ -214,6 +214,8 @@ pim_upstream_del(struct pim_upstream *up, const char *name)
|
|||||||
}
|
}
|
||||||
up->sources = NULL;
|
up->sources = NULL;
|
||||||
|
|
||||||
|
list_delete (up->ifchannels);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
notice that listnode_delete() can't be moved
|
notice that listnode_delete() can't be moved
|
||||||
into pim_upstream_free() because the later is
|
into pim_upstream_free() because the later is
|
||||||
@ -439,18 +441,10 @@ static void forward_on(struct pim_upstream *up)
|
|||||||
{
|
{
|
||||||
struct listnode *chnode;
|
struct listnode *chnode;
|
||||||
struct listnode *chnextnode;
|
struct listnode *chnextnode;
|
||||||
struct pim_interface *pim_ifp;
|
struct pim_ifchannel *ch = NULL;
|
||||||
struct pim_ifchannel *ch;
|
|
||||||
|
|
||||||
/* scan (S,G) state */
|
/* scan (S,G) state */
|
||||||
for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
|
for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
|
||||||
pim_ifp = ch->interface->info;
|
|
||||||
if (!pim_ifp)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (ch->upstream != up)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (pim_macro_chisin_oiflist(ch))
|
if (pim_macro_chisin_oiflist(ch))
|
||||||
pim_forward_start(ch);
|
pim_forward_start(ch);
|
||||||
|
|
||||||
@ -461,17 +455,10 @@ static void forward_off(struct pim_upstream *up)
|
|||||||
{
|
{
|
||||||
struct listnode *chnode;
|
struct listnode *chnode;
|
||||||
struct listnode *chnextnode;
|
struct listnode *chnextnode;
|
||||||
struct pim_interface *pim_ifp;
|
|
||||||
struct pim_ifchannel *ch;
|
struct pim_ifchannel *ch;
|
||||||
|
|
||||||
/* scan per-interface (S,G) state */
|
/* scan per-interface (S,G) state */
|
||||||
for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
|
for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
|
||||||
pim_ifp = ch->interface->info;
|
|
||||||
if (!pim_ifp)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (ch->upstream != up)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
pim_forward_stop(ch);
|
pim_forward_stop(ch);
|
||||||
|
|
||||||
@ -673,6 +660,9 @@ pim_upstream_new (struct prefix_sg *sg,
|
|||||||
up->rpf.rpf_addr.family = AF_INET;
|
up->rpf.rpf_addr.family = AF_INET;
|
||||||
up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY;
|
up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY;
|
||||||
|
|
||||||
|
up->ifchannels = list_new();
|
||||||
|
up->ifchannels->cmp = (int (*)(void *, void *))pim_ifchannel_compare;
|
||||||
|
|
||||||
if (up->sg.src.s_addr != INADDR_ANY)
|
if (up->sg.src.s_addr != INADDR_ANY)
|
||||||
wheel_add_item (pim_upstream_sg_wheel, up);
|
wheel_add_item (pim_upstream_sg_wheel, up);
|
||||||
|
|
||||||
@ -794,38 +784,34 @@ struct pim_upstream *pim_upstream_add(struct prefix_sg *sg,
|
|||||||
return up;
|
return up;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Passed in up must be the upstream for ch. starch is NULL if no
|
||||||
|
* information
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up,
|
pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up,
|
||||||
struct pim_ifchannel *ch)
|
struct pim_ifchannel *ch,
|
||||||
|
struct pim_ifchannel *starch)
|
||||||
{
|
{
|
||||||
struct pim_upstream *parent = up->parent;
|
if (ch)
|
||||||
|
|
||||||
if (ch->upstream == up)
|
|
||||||
{
|
{
|
||||||
if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
|
if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!pim_macro_ch_lost_assert(ch) && pim_macro_chisin_joins_or_include(ch))
|
if (!pim_macro_ch_lost_assert(ch) && pim_macro_chisin_joins_or_include(ch))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* joins (*,G)
|
* joins (*,G)
|
||||||
*/
|
*/
|
||||||
if (parent && ch->upstream == parent)
|
if (starch)
|
||||||
{
|
{
|
||||||
struct listnode *ch_node;
|
if (PIM_IF_FLAG_TEST_S_G_RPT (starch->upstream->flags))
|
||||||
struct pim_ifchannel *child;
|
return 0;
|
||||||
for (ALL_LIST_ELEMENTS_RO (ch->sources, ch_node, child))
|
|
||||||
{
|
if (!pim_macro_ch_lost_assert (starch) && pim_macro_chisin_joins_or_include (starch))
|
||||||
if (child->upstream == up)
|
return 1;
|
||||||
{
|
|
||||||
if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!pim_macro_ch_lost_assert (ch) && pim_macro_chisin_joins_or_include (ch))
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -856,20 +842,28 @@ pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up,
|
|||||||
*/
|
*/
|
||||||
int pim_upstream_evaluate_join_desired(struct pim_upstream *up)
|
int pim_upstream_evaluate_join_desired(struct pim_upstream *up)
|
||||||
{
|
{
|
||||||
struct listnode *chnode;
|
struct interface *ifp;
|
||||||
struct listnode *chnextnode;
|
struct listnode *node;
|
||||||
struct pim_interface *pim_ifp;
|
struct pim_ifchannel *ch, *starch;
|
||||||
struct pim_ifchannel *ch;
|
struct pim_upstream *starup = up->parent;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* scan per-interface (S,G) state */
|
for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
|
||||||
for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch))
|
|
||||||
{
|
{
|
||||||
pim_ifp = ch->interface->info;
|
if (!ifp->info)
|
||||||
if (!pim_ifp)
|
continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
ret += pim_upstream_evaluate_join_desired_interface (up, ch);
|
ch = pim_ifchannel_find (ifp, &up->sg);
|
||||||
|
|
||||||
|
if (starup)
|
||||||
|
starch = pim_ifchannel_find (ifp, &starup->sg);
|
||||||
|
else
|
||||||
|
starch = NULL;
|
||||||
|
|
||||||
|
if (!ch && !starch)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret += pim_upstream_evaluate_join_desired_interface (up, ch, starch);
|
||||||
} /* scan iface channel list */
|
} /* scan iface channel list */
|
||||||
|
|
||||||
return ret; /* false */
|
return ret; /* false */
|
||||||
@ -956,18 +950,9 @@ void pim_upstream_rpf_interface_changed(struct pim_upstream *up,
|
|||||||
struct listnode *chnode;
|
struct listnode *chnode;
|
||||||
struct listnode *chnextnode;
|
struct listnode *chnextnode;
|
||||||
struct pim_ifchannel *ch;
|
struct pim_ifchannel *ch;
|
||||||
struct pim_interface *pim_ifp;
|
|
||||||
|
|
||||||
/* search all ifchannels */
|
/* search all ifchannels */
|
||||||
for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
|
for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
|
||||||
|
|
||||||
pim_ifp = ch->interface->info;
|
|
||||||
if (!pim_ifp)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (ch->upstream != up)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) {
|
if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) {
|
||||||
if (
|
if (
|
||||||
/* RPF_interface(S) was NOT I */
|
/* RPF_interface(S) was NOT I */
|
||||||
@ -988,18 +973,10 @@ void pim_upstream_update_could_assert(struct pim_upstream *up)
|
|||||||
{
|
{
|
||||||
struct listnode *chnode;
|
struct listnode *chnode;
|
||||||
struct listnode *chnextnode;
|
struct listnode *chnextnode;
|
||||||
struct pim_interface *pim_ifp;
|
|
||||||
struct pim_ifchannel *ch;
|
struct pim_ifchannel *ch;
|
||||||
|
|
||||||
/* scan per-interface (S,G) state */
|
/* scan per-interface (S,G) state */
|
||||||
for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
|
for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
|
||||||
pim_ifp = ch->interface->info;
|
|
||||||
if (!pim_ifp)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (ch->upstream != up)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
pim_ifchannel_update_could_assert(ch);
|
pim_ifchannel_update_could_assert(ch);
|
||||||
} /* scan iface channel list */
|
} /* scan iface channel list */
|
||||||
}
|
}
|
||||||
@ -1008,18 +985,10 @@ void pim_upstream_update_my_assert_metric(struct pim_upstream *up)
|
|||||||
{
|
{
|
||||||
struct listnode *chnode;
|
struct listnode *chnode;
|
||||||
struct listnode *chnextnode;
|
struct listnode *chnextnode;
|
||||||
struct pim_interface *pim_ifp;
|
|
||||||
struct pim_ifchannel *ch;
|
struct pim_ifchannel *ch;
|
||||||
|
|
||||||
/* scan per-interface (S,G) state */
|
/* scan per-interface (S,G) state */
|
||||||
for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
|
for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
|
||||||
pim_ifp = ch->interface->info;
|
|
||||||
if (!pim_ifp)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (ch->upstream != up)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
pim_ifchannel_update_my_assert_metric(ch);
|
pim_ifchannel_update_my_assert_metric(ch);
|
||||||
|
|
||||||
} /* scan iface channel list */
|
} /* scan iface channel list */
|
||||||
@ -1033,14 +1002,11 @@ static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up)
|
|||||||
struct pim_ifchannel *ch;
|
struct pim_ifchannel *ch;
|
||||||
|
|
||||||
/* scan per-interface (S,G) state */
|
/* scan per-interface (S,G) state */
|
||||||
for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
|
for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
|
||||||
pim_ifp = ch->interface->info;
|
pim_ifp = ch->interface->info;
|
||||||
if (!pim_ifp)
|
if (!pim_ifp)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ch->upstream != up)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
pim_ifchannel_update_assert_tracking_desired(ch);
|
pim_ifchannel_update_assert_tracking_desired(ch);
|
||||||
|
|
||||||
} /* scan iface channel list */
|
} /* scan iface channel list */
|
||||||
@ -1210,11 +1176,10 @@ pim_upstream_is_sg_rpt (struct pim_upstream *up)
|
|||||||
struct listnode *chnode;
|
struct listnode *chnode;
|
||||||
struct pim_ifchannel *ch;
|
struct pim_ifchannel *ch;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, chnode, ch))
|
for (ALL_LIST_ELEMENTS_RO(up->ifchannels, chnode, ch))
|
||||||
{
|
{
|
||||||
if ((ch->upstream == up) &&
|
if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
|
||||||
(PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)))
|
return 1;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1433,31 +1398,42 @@ pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_regist
|
|||||||
int
|
int
|
||||||
pim_upstream_inherited_olist_decide (struct pim_upstream *up)
|
pim_upstream_inherited_olist_decide (struct pim_upstream *up)
|
||||||
{
|
{
|
||||||
struct pim_interface *pim_ifp;
|
struct interface *ifp;
|
||||||
struct listnode *chnextnode;
|
struct pim_interface *pim_ifp = NULL;
|
||||||
struct pim_ifchannel *ch;
|
struct pim_ifchannel *ch, *starch;
|
||||||
struct listnode *chnode;
|
struct listnode *node;
|
||||||
|
struct pim_upstream *starup = up->parent;
|
||||||
int output_intf = 0;
|
int output_intf = 0;
|
||||||
|
|
||||||
pim_ifp = up->rpf.source_nexthop.interface->info;
|
pim_ifp = up->rpf.source_nexthop.interface->info;
|
||||||
if (pim_ifp && !up->channel_oil)
|
if (pim_ifp && !up->channel_oil)
|
||||||
up->channel_oil = pim_channel_oil_add (&up->sg, pim_ifp->mroute_vif_index);
|
up->channel_oil = pim_channel_oil_add (&up->sg, pim_ifp->mroute_vif_index);
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS (pim_ifchannel_list, chnode, chnextnode, ch))
|
for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
|
||||||
{
|
{
|
||||||
pim_ifp = ch->interface->info;
|
if (!ifp->info)
|
||||||
if (!pim_ifp)
|
continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
if (pim_upstream_evaluate_join_desired_interface (up, ch))
|
ch = pim_ifchannel_find (ifp, &up->sg);
|
||||||
{
|
|
||||||
|
if (starup)
|
||||||
|
starch = pim_ifchannel_find (ifp, &starup->sg);
|
||||||
|
else
|
||||||
|
starch = NULL;
|
||||||
|
|
||||||
|
if (!ch && !starch)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (pim_upstream_evaluate_join_desired_interface (up, ch, starch))
|
||||||
|
{
|
||||||
int flag = PIM_OIF_FLAG_PROTO_PIM;
|
int flag = PIM_OIF_FLAG_PROTO_PIM;
|
||||||
|
|
||||||
if (ch->sg.src.s_addr == INADDR_ANY && ch->upstream != up)
|
if (!ch)
|
||||||
flag = PIM_OIF_FLAG_PROTO_STAR;
|
flag = PIM_OIF_FLAG_PROTO_STAR;
|
||||||
pim_channel_add_oif (up->channel_oil, ch->interface, flag);
|
|
||||||
output_intf++;
|
pim_channel_add_oif (up->channel_oil, ifp, flag);
|
||||||
}
|
output_intf++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return output_intf;
|
return output_intf;
|
||||||
@ -1695,10 +1671,41 @@ pim_upstream_add_lhr_star_pimreg (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pim_upstream_remove_lhr_star_pimreg (void)
|
pim_upstream_spt_prefix_list_update (struct prefix_list *pl)
|
||||||
|
{
|
||||||
|
const char *pname = prefix_list_name (pl);
|
||||||
|
|
||||||
|
if (pimg->spt.plist && strcmp (pimg->spt.plist, pname) == 0)
|
||||||
|
{
|
||||||
|
pim_upstream_remove_lhr_star_pimreg (pname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nlist -> The new prefix list
|
||||||
|
*
|
||||||
|
* Per Group Application of pimreg to the OIL
|
||||||
|
* If the prefix list tells us DENY then
|
||||||
|
* we need to Switchover to SPT immediate
|
||||||
|
* so add the pimreg.
|
||||||
|
* If the prefix list tells us to ACCEPT than
|
||||||
|
* we need to Never do the SPT so remove
|
||||||
|
* the interface
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
pim_upstream_remove_lhr_star_pimreg (const char *nlist)
|
||||||
{
|
{
|
||||||
struct pim_upstream *up;
|
struct pim_upstream *up;
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
|
struct prefix_list *np;
|
||||||
|
struct prefix g;
|
||||||
|
enum prefix_list_type apply_new;
|
||||||
|
|
||||||
|
np = prefix_list_lookup (AFI_IP, nlist);
|
||||||
|
|
||||||
|
g.family = AF_INET;
|
||||||
|
g.prefixlen = IPV4_MAX_PREFIXLEN;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up))
|
for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up))
|
||||||
{
|
{
|
||||||
@ -1708,7 +1715,17 @@ pim_upstream_remove_lhr_star_pimreg (void)
|
|||||||
if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))
|
if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
|
if (!nlist)
|
||||||
|
{
|
||||||
|
pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
g.u.prefix4 = up->sg.grp;
|
||||||
|
apply_new = prefix_list_apply (np, &g);
|
||||||
|
if (apply_new == PREFIX_DENY)
|
||||||
|
pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
|
||||||
|
else
|
||||||
|
pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +100,7 @@ struct pim_upstream {
|
|||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
struct channel_oil *channel_oil;
|
struct channel_oil *channel_oil;
|
||||||
struct list *sources;
|
struct list *sources;
|
||||||
|
struct list *ifchannels;
|
||||||
|
|
||||||
enum pim_upstream_state join_state;
|
enum pim_upstream_state join_state;
|
||||||
enum pim_reg_state reg_state;
|
enum pim_reg_state reg_state;
|
||||||
@ -149,7 +150,8 @@ struct pim_upstream *pim_upstream_del(struct pim_upstream *up, const char *name)
|
|||||||
|
|
||||||
int pim_upstream_evaluate_join_desired(struct pim_upstream *up);
|
int pim_upstream_evaluate_join_desired(struct pim_upstream *up);
|
||||||
int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up,
|
int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up,
|
||||||
struct pim_ifchannel *ch);
|
struct pim_ifchannel *ch,
|
||||||
|
struct pim_ifchannel *starch);
|
||||||
void pim_upstream_update_join_desired(struct pim_upstream *up);
|
void pim_upstream_update_join_desired(struct pim_upstream *up);
|
||||||
|
|
||||||
void pim_upstream_join_suppress(struct pim_upstream *up,
|
void pim_upstream_join_suppress(struct pim_upstream *up,
|
||||||
@ -200,5 +202,7 @@ int pim_upstream_compare (void *arg1, void *arg2);
|
|||||||
void pim_upstream_register_reevaluate (void);
|
void pim_upstream_register_reevaluate (void);
|
||||||
|
|
||||||
void pim_upstream_add_lhr_star_pimreg (void);
|
void pim_upstream_add_lhr_star_pimreg (void);
|
||||||
void pim_upstream_remove_lhr_star_pimreg (void);
|
void pim_upstream_remove_lhr_star_pimreg (const char *nlist);
|
||||||
|
|
||||||
|
void pim_upstream_spt_prefix_list_update (struct prefix_list *pl);
|
||||||
#endif /* PIM_UPSTREAM_H */
|
#endif /* PIM_UPSTREAM_H */
|
||||||
|
@ -182,10 +182,14 @@ int pim_global_config_write(struct vty *vty)
|
|||||||
ssm->plist_name, VTY_NEWLINE);
|
ssm->plist_name, VTY_NEWLINE);
|
||||||
++writes;
|
++writes;
|
||||||
}
|
}
|
||||||
if (pimg->spt_switchover == PIM_SPT_INFINITY)
|
if (pimg->spt.switchover == PIM_SPT_INFINITY)
|
||||||
{
|
{
|
||||||
vty_out (vty, "ip pim spt-switchover infinity-and-beyond%s",
|
if (pimg->spt.plist)
|
||||||
VTY_NEWLINE);
|
vty_out (vty, "ip pim spt-switchover infinity-and-beyond prefix-list %s%s",
|
||||||
|
pimg->spt.plist, VTY_NEWLINE);
|
||||||
|
else
|
||||||
|
vty_out (vty, "ip pim spt-switchover infinity-and-beyond%s",
|
||||||
|
VTY_NEWLINE);
|
||||||
++writes;
|
++writes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +194,7 @@ pim_prefix_list_update (struct prefix_list *plist)
|
|||||||
{
|
{
|
||||||
pim_rp_prefix_list_update (plist);
|
pim_rp_prefix_list_update (plist);
|
||||||
pim_ssm_prefix_list_update (plist);
|
pim_ssm_prefix_list_update (plist);
|
||||||
|
pim_upstream_spt_prefix_list_update (plist);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -249,7 +250,9 @@ pim_instance_init (vrf_id_t vrf_id, afi_t afi)
|
|||||||
pim->vrf_id = vrf_id;
|
pim->vrf_id = vrf_id;
|
||||||
pim->afi = afi;
|
pim->afi = afi;
|
||||||
|
|
||||||
pim->spt_switchover = PIM_SPT_IMMEDIATE;
|
pim->spt.switchover = PIM_SPT_IMMEDIATE;
|
||||||
|
pim->spt.plist = NULL;
|
||||||
|
|
||||||
pim->rpf_hash = hash_create_size (256, pim_rpf_hash_key, pim_rpf_equal);
|
pim->rpf_hash = hash_create_size (256, pim_rpf_hash_key, pim_rpf_equal);
|
||||||
|
|
||||||
if (PIM_DEBUG_ZEBRA)
|
if (PIM_DEBUG_ZEBRA)
|
||||||
|
@ -248,7 +248,10 @@ struct pim_instance
|
|||||||
afi_t afi;
|
afi_t afi;
|
||||||
vrf_id_t vrf_id;
|
vrf_id_t vrf_id;
|
||||||
|
|
||||||
enum pim_spt_switchover spt_switchover;
|
struct {
|
||||||
|
enum pim_spt_switchover switchover;
|
||||||
|
char *plist;
|
||||||
|
} spt;
|
||||||
|
|
||||||
struct hash *rpf_hash;
|
struct hash *rpf_hash;
|
||||||
void *ssm_info; /* per-vrf SSM configuration */
|
void *ssm_info; /* per-vrf SSM configuration */
|
||||||
|
Loading…
Reference in New Issue
Block a user