"Display information for a route distinguisher\n"
"VPN Route Distinguisher\n" JSON_STR)
{
- int idx_ext_community = 6;
+ int idx_ext_community = 0;
int ret;
struct prefix_rd prd;
+ argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
+
ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
if (!ret) {
vty_out(vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
"Display information for a route distinguisher\n"
"VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
{
- int idx_ext_community = 6;
+ int idx_ext_community = 0;
int ret;
struct prefix_rd prd;
+ argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
+
ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
if (!ret) {
vty_out(vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
"Neighbor to display information about\n"
"Display routes learned from neighbor\n" JSON_STR)
{
- int idx_ipv4 = 6;
+ int idx_ipv4 = 0;
union sockunion su;
struct peer *peer;
int ret;
u_char uj = use_json(argc, argv);
+ argv_find (argv, argc, "A.B.C.D", &idx_ipv4);
+
ret = str2sockunion(argv[idx_ipv4]->arg, &su);
if (ret < 0) {
if (uj) {
"Neighbor to display information about\n"
"Display routes learned from neighbor\n" JSON_STR)
{
- int idx_ext_community = 6;
- int idx_ipv4 = 8;
+ int idx_ext_community = 0;
+ int idx_ipv4 = 0;
int ret;
union sockunion su;
struct peer *peer;
struct prefix_rd prd;
u_char uj = use_json(argc, argv);
+ argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
+ argv_find (argv, argc, "A.B.C.D", &idx_ipv4);
+
ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
if (!ret) {
if (uj) {
"Neighbor to display information about\n"
"Display the routes advertised to a BGP neighbor\n" JSON_STR)
{
- int idx_ipv4 = 7;
+ int idx_ipv4 = 0;
int ret;
struct peer *peer;
union sockunion su;
u_char uj = use_json(argc, argv);
+ argv_find (argv, argc, "A.B.C.D", &idx_ipv4);
+
ret = str2sockunion(argv[idx_ipv4]->arg, &su);
if (ret < 0) {
if (uj) {
"Neighbor to display information about\n"
"Display the routes advertised to a BGP neighbor\n" JSON_STR)
{
- int idx_ext_community = 6;
- int idx_ipv4 = 8;
+ int idx_ext_community = 0;
+ int idx_ipv4 = 0;
int ret;
struct peer *peer;
struct prefix_rd prd;
union sockunion su;
u_char uj = use_json(argc, argv);
+ argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
+ argv_find (argv, argc, "A.B.C.D", &idx_ipv4);
+
ret = str2sockunion(argv[idx_ipv4]->arg, &su);
if (ret < 0) {
if (uj) {
"VPN Route Distinguisher\n"
"Display BGP Overlay Information for prefixes\n")
{
- int idx_ext_community = 6;
+ int idx_ext_community = 0;
int ret;
struct prefix_rd prd;
+ argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
+
ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
if (!ret) {
vty_out(vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
int idx_ext_community = 3;
int idx_word = 5;
int idx_word_2 = 7;
- if (argv[idx_word_2])
+ if (argc == 8)
return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
else
return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, NULL, 0, NULL, NULL, NULL, NULL);
#ifdef KEEP_OLD_VPN_COMMANDS
DEFUN (set_vpn_nexthop,
set_vpn_nexthop_cmd,
- "set <vpnv4|vpnv6> next-hop [A.B.C.D|X:X::X:X]",
+ "set <vpnv4|vpnv6> next-hop <A.B.C.D|X:X::X:X>",
SET_STR
"VPNv4 information\n"
"VPNv6 information\n"
DEFUN (no_set_vpn_nexthop,
no_set_vpn_nexthop_cmd,
- "no set vpn next-hop [A.B.C.D|X:X::X:X]",
+ "no set vpn next-hop <A.B.C.D|X:X::X:X>",
NO_STR
SET_STR
"VPN information\n"
"ip vpn next-hop", arg);
else
return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
- "ipv6 vpn next-hop", argv[idx_ip]->arg);
+ "ipv6 vpn next-hop", arg);
}
return CMD_SUCCESS;
}
if (argv_find (argv, argc, "view", idx) || argv_find (argv, argc, "vrf", idx))
{
vrf_name = argv[*idx + 1]->arg;
- *idx += 2;
if (strmatch (vrf_name, "all"))
*bgp = NULL;
if (argv[3]->arg[0] == 'b')
{
if (((argc > 6)
+ && hc->plist_export_bgp_name[afi]
&& !strcmp (argv[6]->arg, hc->plist_export_bgp_name[afi]))
|| (argc <= 6))
{
- if (hc->plist_export_bgp_name[afi])
- free (hc->plist_export_bgp_name[afi]);
+ free (hc->plist_export_bgp_name[afi]);
hc->plist_export_bgp_name[afi] = NULL;
hc->plist_export_bgp[afi] = NULL;
vnc_direct_bgp_reexport (bgp, afi);
else
{
if (((argc > 6)
+ && hc->plist_export_zebra_name[afi]
&& !strcmp (argv[6]->arg, hc->plist_export_zebra_name[afi]))
|| (argc <= 6))
{
- if (hc->plist_export_zebra_name[afi])
- free (hc->plist_export_zebra_name[afi]);
+ free (hc->plist_export_zebra_name[afi]);
hc->plist_export_zebra_name[afi] = NULL;
hc->plist_export_zebra[afi] = NULL;
/* TBD vnc_zebra_rh_reexport(bgp, afi); */
if (argv[3]->arg[0] == 'b')
{
if (((argc > 5)
+ && hc->routemap_export_bgp_name
&& !strcmp (argv[5]->arg, hc->routemap_export_bgp_name))
|| (argc <= 5))
{
- if (hc->routemap_export_bgp_name)
- free (hc->routemap_export_bgp_name);
+ free (hc->routemap_export_bgp_name);
hc->routemap_export_bgp_name = NULL;
hc->routemap_export_bgp = NULL;
vnc_direct_bgp_reexport (bgp, AFI_IP);
else
{
if (((argc > 5)
+ && hc->routemap_export_zebra_name
&& !strcmp (argv[5]->arg, hc->routemap_export_zebra_name))
|| (argc <= 5))
{
- if (hc->routemap_export_zebra_name)
- free (hc->routemap_export_zebra_name);
+ free (hc->routemap_export_zebra_name);
hc->routemap_export_zebra_name = NULL;
hc->routemap_export_zebra = NULL;
/* TBD vnc_zebra_rh_reexport(bgp, AFI_IP); */
int argc,
struct cmd_token **argv)
{
- const char *arg_prefix = carg_prefix->arg;
- const char *arg_vn = carg_vn->arg;
- const char *arg_un = carg_un->arg;
+ const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL;
+ const char *arg_vn = carg_vn ? carg_vn->arg : NULL;
+ const char *arg_un = carg_un ? carg_un->arg : NULL;
const char *arg_cost = carg_cost ? carg_cost->arg : NULL;
const char *arg_lifetime = carg_lifetime ? carg_lifetime->arg : NULL;
const char *arg_macaddr = carg_macaddr ? carg_macaddr->arg : NULL;
struct rfapi_local_reg_delete_arg cda;
int rc;
- if ((rc = parse_deleter_tokens (vty, NULL, NULL, NULL, argv[6], NULL, NULL, NULL, NULL, &cda)))
+ if ((rc = parse_deleter_tokens (vty, NULL, NULL, NULL, argv[4], NULL, NULL, NULL, NULL, &cda)))
return rc;
cda.vty = vty;
fi
if test "${enable_poll}" = "yes" ; then
- AC_DEFINE(HAVE_POLL,,Compile systemd support in)
+ AC_DEFINE(HAVE_POLL_CALL,,Compile systemd support in)
fi
dnl ----------
apt-get install git autoconf automake libtool make gawk libreadline-dev \
texinfo dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex \
- python-pytest libc-ares-dev python3-dev
+ python-pytest libc-ares-dev python3-dev libsystemd-dev
Get FRR, compile it and install it (from Git)
---------------------------------------------
--enable-rtadv \
--enable-tcp-zebra \
--enable-fpm \
+ --enable-systemd=yes \
--with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion
make
isisd=yes
### Enable the systemd serivce
-Edit `/etc/systemd/system/frr.service` and remove the line **OnFailure=heartbeat-failed@%n.service**
-For example.
+ - systemctl enable frr
- [Unit]
- Description=Cumulus Linux FRR
- After=syslog.target networking.service
- Â Â
### Start the systemd service
- systemctl start frr
- use `systemctl status frr` to check its status.
rv->spin = true;
rv->handle_signals = true;
-#if defined(HAVE_POLL)
+#if defined(HAVE_POLL_CALL)
rv->handler.pfdsize = rv->fd_limit;
rv->handler.pfdcount = 0;
rv->handler.pfds = XCALLOC (MTYPE_THREAD_MASTER,
thread_queue_free (m, m->background);
pthread_mutex_destroy (&m->mtx);
-#if defined(HAVE_POLL)
+#if defined(HAVE_POLL_CALL)
XFREE (MTYPE_THREAD_MASTER, m->handler.pfds);
#endif
XFREE (MTYPE_THREAD_MASTER, m);
return thread;
}
-#if defined (HAVE_POLL)
+#if defined (HAVE_POLL_CALL)
#define fd_copy_fd_set(X) (X)
* no event is detected. If the value is zero, the behavior is default.
*/
-#if defined(HAVE_POLL)
+#if defined(HAVE_POLL_CALL)
int timeout = -1;
if (timer_wait != NULL && m->selectpoll_timeout == 0) // use the default value
static int
fd_is_set (struct thread *thread, thread_fd_set *fdset, int pos)
{
-#if defined(HAVE_POLL)
+#if defined(HAVE_POLL_CALL)
return 1;
#else
return FD_ISSET (THREAD_FD (thread), fdset);
static int
fd_clear_read_write (struct thread *thread)
{
-#if !defined(HAVE_POLL)
+#if !defined(HAVE_POLL_CALL)
thread_fd_set *fdset = NULL;
int fd = THREAD_FD (thread);
pthread_mutex_lock (&m->mtx);
{
-#if defined (HAVE_POLL)
+#if defined (HAVE_POLL_CALL)
thread = generic_thread_add(m, func, arg, fd, dir, debugargpass);
#else
if (fd >= FD_SETSIZE)
static void
thread_cancel_read_or_write (struct thread *thread, short int state)
{
-#if defined(HAVE_POLL)
+#if defined(HAVE_POLL_CALL)
nfds_t i;
for (i=0;i<thread->master->handler.pfdcount;++i)
switch (thread->type)
{
case THREAD_READ:
-#if defined (HAVE_POLL)
+#if defined (HAVE_POLL_CALL)
thread_cancel_read_or_write (thread, POLLIN | POLLHUP);
#else
thread_cancel_read_or_write (thread, 0);
thread_array = thread->master->read;
break;
case THREAD_WRITE:
-#if defined (HAVE_POLL)
+#if defined (HAVE_POLL_CALL)
thread_cancel_read_or_write (thread, POLLOUT | POLLHUP);
#else
thread_cancel_read_or_write (thread, 0);
thread_delete_fd (thread_array, thread);
thread_list_add (&m->ready, thread);
thread->type = THREAD_READY;
-#if defined(HAVE_POLL)
+#if defined(HAVE_POLL_CALL)
thread->master->handler.pfds[pos].events &= ~(state);
#endif
return 1;
return 0;
}
-#if defined(HAVE_POLL)
+#if defined(HAVE_POLL_CALL)
/* check poll events */
static void
static void
thread_process_fds (struct thread_master *m, thread_fd_set *rset, thread_fd_set *wset, int num)
{
-#if defined (HAVE_POLL)
+#if defined (HAVE_POLL_CALL)
check_pollfds (m, rset, num);
#else
int ready = 0, index;
thread_process (&m->event);
/* Structure copy. */
-#if !defined(HAVE_POLL)
+#if !defined(HAVE_POLL_CALL)
readfd = fd_copy_fd_set(m->handler.readfd);
writefd = fd_copy_fd_set(m->handler.writefd);
exceptfd = fd_copy_fd_set(m->handler.exceptfd);
*/
typedef fd_set thread_fd_set;
-#if defined(HAVE_POLL)
+#if defined(HAVE_POLL_CALL)
#include <poll.h>
struct fd_handler
{
return CMD_WARNING;
}
- if (argc > 1)
+ if (argc > 3)
{
if (strncmp (argv[3]->text, "translate-c", 11) == 0)
ospf_area_nssa_translator_role_set (ospf, area_id,
int idx_ipv4 = 2;
int result;
struct in_addr source_addr;
- const char *source_str = (argc == idx_ipv4) ? argv[idx_ipv4]->arg : "0.0.0.0";
+ const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0";
result = inet_pton(AF_INET, source_str, &source_addr);
if (result <= 0) {
int idx_ipv4 = 3;
int result;
struct in_addr source_addr;
- const char *source_str = (argc == idx_ipv4) ? argv[idx_ipv4]->arg : "0.0.0.0";
+ const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0";
result = inet_pton(AF_INET, source_str, &source_addr);
if (result <= 0) {
"Enable PIM ECMP \n"
"Enable PIM ECMP Rebalance\n")
{
+ qpim_ecmp_enable = 1;
qpim_ecmp_rebalance_enable = 1;
return CMD_SUCCESS;
"mesh group source\n"
"mesh group local address\n")
{
- if (argc == 6)
+ if (argc == 7)
return ip_no_msdp_mesh_group_cmd_worker(vty, argv[6]->arg);
else
return ip_no_msdp_mesh_group_source_cmd_worker(vty, argv[4]->arg);
static int pim_iface_vif_index[MAXVIFS];
static void pim_if_igmp_join_del_all(struct interface *ifp);
+static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
+ struct in_addr group_addr, struct in_addr source_addr);
void
pim_if_init (void)
/* if addr new, add IGMP socket */
pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, ifp);
}
+
+ /* Replay Static IGMP groups */
+ if (pim_ifp->igmp_join_list)
+ {
+ struct listnode *node;
+ struct listnode *nextnode;
+ struct igmp_join *ij;
+ int join_fd;
+
+ for (ALL_LIST_ELEMENTS (pim_ifp->igmp_join_list, node, nextnode, ij))
+ {
+ /* Close socket and reopen with Source and Group */
+ close(ij->sock_fd);
+ join_fd = igmp_join_sock(ifp->name, ifp->ifindex, ij->group_addr, ij->source_addr);
+ if (join_fd < 0)
+ {
+ char group_str[INET_ADDRSTRLEN];
+ char source_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<grp?>", ij->group_addr, group_str, sizeof(group_str));
+ pim_inet4_dump("<src?>", ij->source_addr, source_str, sizeof(source_str));
+ zlog_warn("%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
+ __PRETTY_FUNCTION__,
+ group_str, source_str, ifp->name);
+ /* warning only */
+ }
+ else
+ ij->sock_fd = join_fd;
+ }
+ }
} /* igmp */
if (PIM_IF_TEST_PIM(pim_ifp->options))
struct connected *c;
struct prefix p;
+ if (!ifp)
+ return 0;
+
p.family = AF_INET;
p.u.prefix4 = src;
p.prefixlen = IPV4_MAX_BITLEN;
if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
mask = PIM_OIF_FLAG_PROTO_IGMP;
+ /* SGRpt entry could have empty oil */
+ if (ch->upstream->channel_oil)
+ pim_channel_del_oif (ch->upstream->channel_oil, ch->interface, mask);
pim_channel_del_oif (ch->upstream->channel_oil, ch->interface, mask);
/*
* Do we have any S,G's that are inheriting?
pim_ifp = ifp->info;
send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1);
+ //ch->ifjoin_state transition to NOINFO
ifjoin_to_noinfo(ch);
/* from here ch may have been deleted */
pim_upstream_inherited_olist (ch->upstream);
pim_forward_start(ch);
}
+ /*
+ * If we are going to be a LHR, we need to note it
+ */
+ if (ch->upstream->parent &&
+ (ch->upstream->parent->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) &&
+ !(ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_LHR))
+ {
+ pim_upstream_ref (ch->upstream, PIM_UPSTREAM_FLAG_MASK_SRC_LHR);
+ pim_upstream_keep_alive_timer_start (ch->upstream, qpim_keep_alive_time);
+ }
break;
case PIM_IFJOIN_JOIN:
zassert(!ch->t_ifjoin_prune_pending_timer);
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);
- if (c_oil->oil_size == 0)
- pim_upstream_del (child, __PRETTY_FUNCTION__);
+ /* Child node removal/ref count-- will happen as part of parent' delete_no_info */
}
}
delete_on_noinfo(orig);
if (up)
{
if (PIM_DEBUG_TRACE)
- zlog_debug ("%s: add inherit oif to up %s ", __PRETTY_FUNCTION__, up->sg_str);
+ zlog_debug ("%s: clearing SGRpt flag, add inherit oif to up %s ", __PRETTY_FUNCTION__, up->sg_str);
pim_channel_add_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR);
}
}
char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
- zlog_debug("Deleting IGMP source %s for group %s from socket %d interface %s",
+ zlog_debug("Deleting IGMP source %s for group %s from socket %d interface %s c_oil ref_count %d",
source_str, group_str,
group->group_igmp_sock->fd,
- group->group_igmp_sock->interface->name);
+ group->group_igmp_sock->interface->name,
+ source->source_channel_oil ? source->source_channel_oil->oil_ref_count : 0);
}
source_timer_off(group, source);
struct list *groups)
{
struct pim_jp_agg_group *group;
- struct pim_interface *pim_ifp;
+ struct pim_interface *pim_ifp = NULL;
struct pim_jp_groups *grp = NULL;
struct pim_jp *msg;
struct listnode *node, *nnode;
return -1;
}
- if (!pim_ifp) {
- zlog_warn("%s: multicast not enabled on interface %s",
+ if (!pim_ifp)
+ {
+ zlog_warn ("%s: multicast not enabled on interface %s",
__PRETTY_FUNCTION__,
rpf->source_nexthop.interface->name);
- return -1;
- }
+ return -1;
+ }
if (PIM_INADDR_IS_ANY(rpf->rpf_addr.u.prefix4))
{
struct pim_iface_upstream_switch *pius;
struct listnode *node, *nnode;
+ /* Old interface is pim disabled */
+ if (!pim_ifp)
+ return NULL;
+
for (ALL_LIST_ELEMENTS(pim_ifp->upstream_switch_list, node, nnode, pius))
{
if (pius->address.s_addr == rpf->rpf_addr.u.prefix4.s_addr)
*/
/* send Prune(S,G) to the old upstream neighbor */
- pim_jp_agg_add_group (opius->us, up, false);
+ if (opius)
+ pim_jp_agg_add_group (opius->us, up, false);
/* send Join(S,G) to the current upstream neighbor */
pim_jp_agg_add_group (npius->us, up, true);
static bool first = true;
/* skip JP upstream messages if source is directly connected */
- if (!rpf->source_nexthop.interface ||
+ if (!up || !rpf->source_nexthop.interface ||
pim_if_connected_to_source (rpf->source_nexthop.interface, up->sg.src))
return;
struct pim_rpf *rpf = pim_rp_g (source->up->sg.grp);
bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT | PIM_ENCODE_RPT_BIT;
stosend = rpf->rpf_addr.u.prefix4;
- up = source->up;
+ /* Only Send SGRpt in case of *,G Join */
+ if (source->is_join)
+ up = source->up;
}
else
{
return pnc;
}
-/* This API is used to Register an address with Zebra */
+/* This API is used to Register an address with Zebra
+ ret 1 means nexthop cache is found.
+*/
int
pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up,
struct rp_info *rp,
pnc = pim_nexthop_cache_find (&rpf);
if (!pnc)
{
- if (PIM_DEBUG_ZEBRA)
- {
- char buf[PREFIX2STR_BUFFER];
- prefix2str (&rpf.rpf_addr, buf, sizeof (buf));
- zlog_debug ("%s: NHT New PNC allocated for addr %s ",
- __PRETTY_FUNCTION__, buf);
- }
pnc = pim_nexthop_cache_add (&rpf);
if (pnc)
pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_REGISTER);
{
char buf[PREFIX2STR_BUFFER];
prefix2str (addr, buf, sizeof (buf));
- zlog_debug
- ("%s: Add upstream %s node to pnc cached list, rpf %s",
+ zlog_debug ("%s: Add upstream %s node to pnc cached list, rpf %s",
__PRETTY_FUNCTION__, up->sg_str, buf);
}
listnode_add_sort (pnc->upstream_list, up);
}
/* Update RP nexthop info based on Nexthop update received from Zebra.*/
-static int
+int
pim_update_rp_nh (struct pim_nexthop_cache *pnc)
{
struct listnode *node = NULL;
struct rp_info *rp_info = NULL;
+ int ret = 0;
/*Traverse RP list and update each RP Nexthop info */
for (ALL_LIST_ELEMENTS_RO (pnc->rp_list, node, rp_info))
continue;
//Compute PIM RPF using cached nexthop
- pim_ecmp_nexthop_search (pnc, &rp_info->rp.source_nexthop,
- &rp_info->rp.rpf_addr, &rp_info->group, 1);
+ ret = pim_ecmp_nexthop_search (pnc, &rp_info->rp.source_nexthop,
+ &rp_info->rp.rpf_addr, &rp_info->group, 1);
if (PIM_DEBUG_TRACE)
{
}
}
- return 0;
+ if (ret)
+ return 0;
+
+ return 1;
}
/* This API is used to traverse nexthop cache of RPF addr
{
if (nh_node->gate.ipv4.s_addr == 0)
{
- nbr =
- pim_neighbor_find_if (if_lookup_by_index
- (nh_node->ifindex, VRF_DEFAULT));
+ struct interface *ifp1 = if_lookup_by_index(nh_node->ifindex,
+ VRF_DEFAULT);
+ nbr = pim_neighbor_find_if (ifp1);
if (nbr)
{
nh_node->gate.ipv4 = nbr->source_addr;
pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, str1,
sizeof (str1));
pim_addr_dump ("<nht_addr?>", nht_p, str, sizeof (str));
- zlog_debug
- ("%s: addr %s new nexthop addr %s ifindex %d ",
- __PRETTY_FUNCTION__, str, str1, nh_node->ifindex);
+ zlog_debug ("%s: addr %s new nexthop addr %s interface %s",
+ __PRETTY_FUNCTION__, str, str1, ifp1->name);
}
}
}
/* update kernel multicast forwarding cache (MFC) */
if (up->channel_oil)
{
- vif_index =
- pim_if_find_vifindex_by_ifindex (up->rpf.
- source_nexthop.interface->
- ifindex);
+ ifindex_t ifindex = up->rpf.source_nexthop.interface->ifindex;
+ vif_index = pim_if_find_vifindex_by_ifindex (ifindex);
/* Pass Current selected NH vif index to mroute download */
if (vif_index)
pim_scan_individual_oil (up->channel_oil, vif_index);
else
{
if (PIM_DEBUG_ZEBRA)
- zlog_debug
- ("%s: NHT upstream %s channel_oil IIF %s vif_index is not valid",
+ zlog_debug ("%s: NHT upstream %s channel_oil IIF %s vif_index is not valid",
__PRETTY_FUNCTION__, up->sg_str,
up->rpf.source_nexthop.interface->name);
}
}
hash_val = jhash_2words (g, s, 101);
- if (PIM_DEBUG_TRACE)
+ if (PIM_DEBUG_PIM_TRACE_DETAIL)
{
char buf[PREFIX2STR_BUFFER];
char bufg[PREFIX2STR_BUFFER];
if (!pnc || !pnc->nexthop_num || !nexthop)
return -1;
- if (qpim_ecmp_enable)
+ //Current Nexthop is VALID, check to stay on the current path.
+ if (nexthop->interface && nexthop->interface->info &&
+ nexthop->mrib_nexthop_addr.u.prefix4.s_addr !=
+ PIM_NET_INADDR_ANY)
{
- //User configured knob to explicitly switch to new path.
+ /* User configured knob to explicitly switch
+ to new path is disabled or current path
+ metric is less than nexthop update.
+ */
+
if (qpim_ecmp_rebalance_enable == 0)
{
- //Current Nexthop is VALID then stay on the current path.
- if (nexthop->interface && nexthop->interface->info &&
- nexthop->mrib_nexthop_addr.u.prefix4.s_addr !=
- PIM_NET_INADDR_ANY)
+ uint8_t curr_route_valid = 0;
+ //Check if current nexthop is present in new updated Nexthop list.
+ //If the current nexthop is not valid, candidate to choose new Nexthop.
+ for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next)
+ curr_route_valid = (nexthop->interface->ifindex == nh_node->ifindex);
+
+ if (curr_route_valid &&
+ !pim_if_connected_to_source (nexthop->interface,
+ src->u.prefix4))
{
- if (neighbor_needed
- && !pim_if_connected_to_source (nexthop->interface,
- src->u.prefix4))
+ nbr = pim_neighbor_find (nexthop->interface,
+ nexthop->mrib_nexthop_addr.u.prefix4);
+ if (!nbr && !if_is_loopback (nexthop->interface))
{
- nbr = pim_neighbor_find (nexthop->interface,
- nexthop->mrib_nexthop_addr.
- u.prefix4);
- if (!nbr && !if_is_loopback (nexthop->interface))
- {
- if (PIM_DEBUG_TRACE)
- zlog_debug ("%s: current nexthop does not have nbr ",
- __PRETTY_FUNCTION__);
- }
- else
+ if (PIM_DEBUG_TRACE)
+ zlog_debug ("%s: current nexthop does not have nbr ",
+ __PRETTY_FUNCTION__);
+ }
+ else
+ {
+ if (PIM_DEBUG_TRACE)
{
- if (PIM_DEBUG_TRACE)
- {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump ("<addr?>", src->u.prefix4, src_str,
- sizeof (src_str));
- char grp_str[INET_ADDRSTRLEN];
- pim_inet4_dump ("<addr?>", grp->u.prefix4, grp_str,
- sizeof (grp_str));
- zlog_debug
- ("%s: %s %s current nexthop %d is valid, not choosing new path",
- __PRETTY_FUNCTION__, src_str, grp_str,
- nexthop->interface->ifindex);
- }
- return 0;
+ char src_str[INET_ADDRSTRLEN];
+ pim_inet4_dump ("<addr?>", src->u.prefix4, src_str,
+ sizeof (src_str));
+ char grp_str[INET_ADDRSTRLEN];
+ pim_inet4_dump ("<addr?>", grp->u.prefix4, grp_str,
+ sizeof (grp_str));
+ zlog_debug ("%s: (%s, %s) current nexthop %s is valid, skipping new path selection",
+ __PRETTY_FUNCTION__, src_str, grp_str,
+ nexthop->interface->name);
}
+ return 0;
}
}
}
+ }
+ if (qpim_ecmp_enable)
+ {
//PIM ECMP flag is enable then choose ECMP path.
hash_val = pim_compute_ecmp_hash (src, grp);
mod_val = hash_val % pnc->nexthop_num;
nh_node = nh_node->next)
{
first_ifindex = nh_node->ifindex;
- ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT);
+ ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT);
if (!ifp)
{
if (PIM_DEBUG_ZEBRA)
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump ("<addr?>", src->u.prefix4, addr_str,
sizeof (addr_str));
- zlog_debug
- ("%s %s: could not find interface for ifindex %d (address %s)",
+ zlog_debug ("%s %s: could not find interface for ifindex %d (address %s)",
__FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str);
}
if (nh_iter == mod_val)
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump ("<addr?>", src->u.prefix4, addr_str,
sizeof (addr_str));
- zlog_debug
- ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)",
+ zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)",
__PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str);
}
if (nh_iter == mod_val)
if (!nbr && !if_is_loopback (ifp))
{
if (PIM_DEBUG_ZEBRA)
- zlog_debug
- ("%s: pim nbr not found on input interface %s",
- __PRETTY_FUNCTION__, ifp->name);
+ zlog_debug ("%s: pim nbr not found on input interface %s",
+ __PRETTY_FUNCTION__, ifp->name);
if (nh_iter == mod_val)
mod_val++; //Select nexthpath
nh_iter++;
nexthop->last_lookup_time = pim_time_monotonic_usec ();
nexthop->nbr = nbr;
found = 1;
-
if (PIM_DEBUG_ZEBRA)
{
- char buf[NEXTHOP_STRLEN];
- char buf2[PREFIX2STR_BUFFER];
- char buf3[PREFIX2STR_BUFFER];
- char buf4[PREFIX2STR_BUFFER];
+ char buf[INET_ADDRSTRLEN];
+ char buf2[INET_ADDRSTRLEN];
+ char buf3[INET_ADDRSTRLEN];
pim_inet4_dump ("<src?>", src->u.prefix4, buf2, sizeof (buf2));
- if (grp)
- pim_inet4_dump ("<src?>", grp->u.prefix4, buf3,
- sizeof (buf3));
+ pim_inet4_dump ("<grp?>", grp->u.prefix4, buf3, sizeof (buf3));
pim_inet4_dump ("<rpf?>",
- nexthop->mrib_nexthop_addr.u.prefix4, buf4,
- sizeof (buf4));
- snprintf (buf, sizeof (buf), "%s if %u",
- inet_ntoa (nh_node->gate.ipv4), nh_node->ifindex);
- zlog_debug
- ("%s: NHT %s %s selected nhop interface %s nhop %s (%s) mod_val:%u iter:%d ecmp_enable:%d",
- __PRETTY_FUNCTION__, buf2, grp ? buf3 : " ", ifp->name,
- buf, buf4, mod_val, nh_iter, qpim_ecmp_enable);
+ nexthop->mrib_nexthop_addr.u.prefix4, buf,
+ sizeof (buf));
+ zlog_debug ("%s: (%s, %s) selected nhop interface %s addr %s mod_val %u iter %d ecmp %d",
+ __PRETTY_FUNCTION__, buf2, buf3, ifp->name,
+ buf, mod_val, nh_iter, qpim_ecmp_enable);
}
}
nh_iter++;
-
}
if (found)
{
char buf[PREFIX2STR_BUFFER];
prefix2str (&rpf.rpf_addr, buf, sizeof (buf));
- zlog_debug
- ("%s: Skipping NHT update, addr %s is not in local cached DB.",
+ zlog_debug ("%s: Skipping NHT update, addr %s is not in local cached DB.",
__PRETTY_FUNCTION__, buf);
}
return 0;
metric = stream_getl (s);
nexthop_num = stream_getc (s);
- if (PIM_DEBUG_TRACE)
- {
- char buf[PREFIX2STR_BUFFER];
- prefix2str (&p, buf, sizeof (buf));
- zlog_debug
- ("%s: NHT Update for %s nexthop_num %d vrf:%d upcount %d rpcount %d",
- __PRETTY_FUNCTION__, buf, nexthop_num, vrf_id,
- listcount (pnc->upstream_list), listcount (pnc->rp_list));
- }
-
if (nexthop_num)
{
pnc->nexthop_num = 0; //Only increment for pim enabled rpf.
case NEXTHOP_TYPE_IPV6_IFINDEX:
stream_get (&nexthop->gate.ipv6, s, 16);
nexthop->ifindex = stream_getl (s);
- nbr =
- pim_neighbor_find_if (if_lookup_by_index
- (nexthop->ifindex, VRF_DEFAULT));
+ struct interface *ifp1 = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT);
+ nbr = pim_neighbor_find_if (ifp1);
/* Overwrite with Nbr address as NH addr */
if (nbr)
{
char str[INET_ADDRSTRLEN];
pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, str,
sizeof (str));
- zlog_debug
- ("%s: NHT using pim nbr addr %s ifindex %d as rpf",
- __PRETTY_FUNCTION__, str, nexthop->ifindex);
+ zlog_debug ("%s: NHT using pim nbr addr %s interface %s as rpf",
+ __PRETTY_FUNCTION__, str, ifp1->name);
}
}
else
{
if (PIM_DEBUG_TRACE)
{
- struct interface *ifp1 =
- if_lookup_by_index (nexthop->ifindex,
- VRF_DEFAULT);
struct pim_interface *pim_ifp = ifp1->info;
- zlog_debug
- ("%s: NHT pim nbr not found on interface %s nbr count:%d ",
+ zlog_debug ("%s: NHT pim nbr not found on interface %s nbr count:%d ",
__PRETTY_FUNCTION__, ifp1->name,
pim_ifp->pim_neighbor_list->count);
}
{
char p_str[PREFIX2STR_BUFFER];
prefix2str (&p, p_str, sizeof (p_str));
- zlog_debug ("%s: NHT addr %s %d-nhop via %s type %d",
- __PRETTY_FUNCTION__, p_str, i + 1,
- inet_ntoa (nexthop->gate.ipv4), nexthop->type);
+ zlog_debug ("%s: NHT addr %s %d-nhop via %s type %d distance:%u metric:%u ",
+ __PRETTY_FUNCTION__, p_str, i + 1,
+ inet_ntoa (nexthop->gate.ipv4), nexthop->type, distance,
+ metric);
}
ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT);
if (PIM_DEBUG_ZEBRA)
{
char buf[NEXTHOP_STRLEN];
- zlog_debug
- ("%s: could not find interface for ifindex %d (addr %s)",
+ zlog_debug ("%s: could not find interface for ifindex %d (addr %s)",
__PRETTY_FUNCTION__, nexthop->ifindex,
nexthop2str (nexthop, buf, sizeof (buf)));
}
if (PIM_DEBUG_ZEBRA)
{
char buf[NEXTHOP_STRLEN];
- zlog_debug
- ("%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)",
+ zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)",
__PRETTY_FUNCTION__, ifp->name, nexthop->ifindex,
nexthop2str (nexthop, buf, sizeof (buf)));
}
{
char buf[PREFIX2STR_BUFFER];
prefix2str (&p, buf, sizeof (buf));
- zlog_debug
- ("%s: NHT Update for %s nexthop_num:%d pim nexthop_num %d vrf:%d up %d rp %d",
+ zlog_debug ("%s: NHT Update for %s num_nh %d num_pim_nh %d vrf:%d up %d rp %d",
__PRETTY_FUNCTION__, buf, nexthop_num, pnc->nexthop_num, vrf_id,
listcount (pnc->upstream_list), listcount (pnc->rp_list));
}
__PRETTY_FUNCTION__, addr_str, nexthop->last_lookup_time);
}
- memset (nexthop_tab, 0,
- sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM);
- num_ifindex =
- zclient_lookup_nexthop (nexthop_tab, MULTIPATH_NUM, addr,
+ memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM);
+ num_ifindex = zclient_lookup_nexthop (nexthop_tab, MULTIPATH_NUM, addr,
PIM_NEXTHOP_LOOKUP_MAX);
if (num_ifindex < 1)
{
return -1;
}
- //If PIM ECMP enable then choose ECMP path
+ //If PIM ECMP enable then choose ECMP path.
if (qpim_ecmp_enable)
{
hash_val = pim_compute_ecmp_hash (src, grp);
mod_val = hash_val % num_ifindex;
if (PIM_DEBUG_TRACE)
- zlog_debug ("%s: hash_val %u mod_val %u ",
+ zlog_debug ("%s: hash_val %u mod_val %u",
__PRETTY_FUNCTION__, hash_val, mod_val);
}
{
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str));
- zlog_debug
- ("%s %s: could not find interface for ifindex %d (address %s)",
+ zlog_debug ("%s %s: could not find interface for ifindex %d (address %s)",
__FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str);
}
if (i == mod_val)
{
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str));
- zlog_debug
- ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)",
+ zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)",
__PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str);
}
if (i == mod_val)
}
if (neighbor_needed && !pim_if_connected_to_source (ifp, addr))
{
- nbr =
- pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4);
+ nbr = pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4);
if (PIM_DEBUG_PIM_TRACE_DETAIL)
zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr);
if (!nbr && !if_is_loopback (ifp))
char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump ("<addr?>", addr, addr_str,
sizeof (addr_str));
- zlog_debug
- ("%s: NBR not found on input interface %s (RPF for source %s)",
+ zlog_debug ("%s: NBR not found on input interface %s (RPF for source %s)",
__PRETTY_FUNCTION__, ifp->name, addr_str);
}
continue;
pim_addr_dump ("<nexthop?>", &nexthop_tab[i].nexthop_addr,
nexthop_str, sizeof (nexthop_str));
pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str));
- zlog_debug
- ("%s %s: found nexthop %s for addr %s interface %s metric=%d pref=%d",
+ zlog_debug ("%s %s: found nhop %s for addr %s interface %s metric %d dist %d",
__FILE__, __PRETTY_FUNCTION__, nexthop_str, addr_str,
ifp->name, nexthop_tab[i].route_metric,
nexthop_tab[i].protocol_distance);
else
return -1;
}
+
+int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr,
+ struct prefix *src, struct prefix *grp)
+{
+ struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM];
+ int num_ifindex;
+ int vif_index;
+ ifindex_t first_ifindex;
+ uint32_t hash_val = 0, mod_val = 0;
+
+ memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM);
+ num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr,
+ PIM_NEXTHOP_LOOKUP_MAX);
+ if (num_ifindex < 1)
+ {
+ if (PIM_DEBUG_ZEBRA)
+ {
+ char addr_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
+ zlog_debug("%s %s: could not find nexthop ifindex for address %s",
+ __FILE__, __PRETTY_FUNCTION__,
+ addr_str);
+ }
+ return -1;
+ }
+
+ //If PIM ECMP enable then choose ECMP path.
+ if (qpim_ecmp_enable)
+ {
+ hash_val = pim_compute_ecmp_hash (src, grp);
+ mod_val = hash_val % num_ifindex;
+ if (PIM_DEBUG_TRACE)
+ zlog_debug ("%s: hash_val %u mod_val %u",
+ __PRETTY_FUNCTION__, hash_val, mod_val);
+ }
+
+ first_ifindex = nexthop_tab[mod_val].ifindex;
+
+ if (PIM_DEBUG_ZEBRA)
+ {
+ char addr_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str));
+ zlog_debug("%s %s: found nexthop ifindex=%d (interface %s) for address %s",
+ __FILE__, __PRETTY_FUNCTION__,
+ first_ifindex, ifindex2ifname(first_ifindex, VRF_DEFAULT), addr_str);
+ }
+
+ vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex);
+
+ if (vif_index < 0)
+ {
+ if (PIM_DEBUG_ZEBRA)
+ {
+ char addr_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
+ zlog_debug("%s %s: low vif_index=%d < 1 nexthop for address %s",
+ __FILE__, __PRETTY_FUNCTION__,
+ vif_index, addr_str);
+ }
+ return -2;
+ }
+
+ return vif_index;
+}
int neighbor_needed);
void pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc,
int command);
+int pim_update_rp_nh (struct pim_nexthop_cache *pnc);
void pim_resolve_upstream_nh (struct prefix *nht_p);
+int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr,
+ struct prefix *src, struct prefix *grp);
#endif
}
c_oil->oil.mfcc_parent = input_vif_index;
++c_oil->oil_ref_count;
+ c_oil->up = pim_upstream_find(sg); //channel might be present prior to upstream
return c_oil;
}
c_oil->oil.mfcc_parent = input_vif_index;
c_oil->oil_ref_count = 1;
c_oil->installed = 0;
+ c_oil->up = pim_upstream_find(sg);
listnode_add_sort(pim_channel_oil_list, c_oil);
* into pim_channel_oil_free() because the later is
* called by list_delete_all_node()
*/
+ c_oil->up = NULL;
listnode_delete(pim_channel_oil_list, c_oil);
hash_release (pim_channel_oil_hash, c_oil);
time_t oif_creation[MAXVIFS];
uint32_t oif_flags[MAXVIFS];
struct channel_counts cc;
+ struct pim_upstream *up;
};
extern struct list *pim_channel_oil_list;
int
pim_rp_new (const char *rp, const char *group_range, const char *plist)
{
- int result;
+ int result = 0;
struct rp_info *rp_info;
struct rp_info *rp_all;
struct prefix group_all;
char buf1[PREFIX2STR_BUFFER];
prefix2str (&nht_p, buf, sizeof (buf));
prefix2str (&rp_info->group, buf1, sizeof (buf1));
- zlog_debug ("%s: NHT Register RP addr %s grp %s with Zebra ",
+ zlog_debug ("%s: NHT Register RP addr %s grp %s with Zebra",
__PRETTY_FUNCTION__, buf, buf1);
}
memset (&pnc, 0, sizeof (struct pim_nexthop_cache));
char buf1[PREFIX2STR_BUFFER];
prefix2str (&nht_p, buf, sizeof (buf));
prefix2str (&g, buf1, sizeof (buf1));
- zlog_debug ("%s: NHT nexthop cache not found for RP %s grp %s",
+ zlog_debug ("%s: Nexthop cache not found for RP %s grp %s register with Zebra",
__PRETTY_FUNCTION__, buf, buf1);
}
pim_rpf_set_refresh_time ();
{
if (nh_node->gate.ipv4.s_addr == 0)
{
- nbr =
- pim_neighbor_find_if (if_lookup_by_index
+ nbr = pim_neighbor_find_if (if_lookup_by_index
(nh_node->ifindex, VRF_DEFAULT));
if (nbr)
{
{
char str[PREFIX_STRLEN];
char str1[INET_ADDRSTRLEN];
+ struct interface *ifp1 = if_lookup_by_index(nh_node->ifindex,
+ VRF_DEFAULT);
pim_inet4_dump ("<nht_nbr?>", nbr->source_addr,
str1, sizeof (str1));
pim_addr_dump ("<nht_addr?>", &nht_p, str,
sizeof (str));
- zlog_debug
- ("%s: addr %s new nexthop addr %s ifindex %d ",
+ zlog_debug ("%s: addr %s new nexthop addr %s interface %s",
__PRETTY_FUNCTION__, str, str1,
- nh_node->ifindex);
+ ifp1->name);
}
}
}
if (pim_ecmp_nexthop_lookup (&rpf->source_nexthop,
up->upstream_addr, &src, &grp,
!PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) &&
- !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->
- flags)))
+ !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags)))
{
return PIM_RPF_FAILURE;
}
struct prefix nht_p;
if (PIM_DEBUG_TRACE)
- zlog_debug ("%s(%s): Delete %s ref count: %d, flags: %d (Pre decrement)",
- __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count, up->flags);
+ zlog_debug ("%s(%s): Delete %s ref count: %d , flags: %d c_oil ref count %d (Pre decrement)",
+ __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count, up->flags,
+ up->channel_oil->oil_ref_count);
--up->ref_count;
up->sources = NULL;
list_delete (up->ifchannels);
+ up->ifchannels = NULL;
/*
notice that listnode_delete() can't be moved
{
char buf[PREFIX2STR_BUFFER];
prefix2str (&nht_p, buf, sizeof (buf));
- zlog_debug ("%s: Deregister upstream %s addr %s with Zebra",
+ zlog_debug ("%s: Deregister upstream %s addr %s with Zebra NHT",
__PRETTY_FUNCTION__, up->sg_str, buf);
}
pim_delete_tracked_nexthop (&nht_p, up, NULL);
struct pim_ifchannel *ch;
/* scan per-interface (S,G) state */
- for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
- pim_ifp = ch->interface->info;
- if (!pim_ifp)
- continue;
+ for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch))
+ {
+ if (!ch->interface)
+ continue;
+ pim_ifp = ch->interface->info;
+ if (!pim_ifp)
+ continue;
- pim_ifchannel_update_assert_tracking_desired(ch);
+ pim_ifchannel_update_assert_tracking_desired(ch);
- } /* scan iface channel list */
+ } /* scan iface channel list */
}
/* When kat is stopped CouldRegister goes to false so we need to
void
pim_upstream_set_sptbit (struct pim_upstream *up, struct interface *incoming)
{
- struct pim_rpf *grpf = NULL;
+ struct pim_upstream *starup = up->parent;
// iif == RPF_interfvace(S)
if (up->rpf.source_nexthop.interface != incoming)
}
// OR RPF_interface(S) != RPF_interface(RP(G))
- grpf = RP(up->sg.grp);
- if (!grpf || up->rpf.source_nexthop.interface != grpf->source_nexthop.interface)
+ if (!starup || up->rpf.source_nexthop.interface != starup->rpf.source_nexthop.interface)
{
if (PIM_DEBUG_TRACE)
zlog_debug ("%s: %s RPF_interface(S) != RPF_interface(RP(G))",
VTY_NEWLINE);
++writes;
}
-
+ if (qpim_ecmp_rebalance_enable)
+ {
+ vty_out (vty, "ip pim ecmp rebalance%s", VTY_NEWLINE);
+ ++writes;
+ }
+ else if (qpim_ecmp_enable)
+ {
+ vty_out (vty, "ip pim ecmp%s", VTY_NEWLINE);
+ ++writes;
+ }
if (qpim_ssmpingd_list) {
struct listnode *node;
struct ssmpingd_sock *ss;
static struct zclient *zclient = NULL;
-static int fib_lookup_if_vif_index(struct in_addr addr);
/* Router-id update message from zebra. */
static int pim_router_id_update_zebra(int command, struct zclient *zclient,
if (in_vif_index)
input_iface_vif_index = in_vif_index;
else
- input_iface_vif_index = fib_lookup_if_vif_index (vif_source);
+ {
+ struct prefix src, grp;
+
+ src.family = AF_INET;
+ src.prefixlen = IPV4_MAX_BITLEN;
+ src.u.prefix4 = vif_source;
+ grp.family = AF_INET;
+ grp.prefixlen = IPV4_MAX_BITLEN;
+ grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp;
+
+ if (PIM_DEBUG_ZEBRA)
+ {
+ char source_str[INET_ADDRSTRLEN];
+ char group_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
+ pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
+ zlog_debug ("%s: channel_oil (%s, %s) upstream info is not present.",
+ __PRETTY_FUNCTION__, source_str, group_str);
+ }
+ input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(vif_source, &src, &grp);
+ }
+
if (input_iface_vif_index < 1)
{
if (PIM_DEBUG_ZEBRA)
struct listnode *node;
struct listnode *nextnode;
struct channel_oil *c_oil;
+ ifindex_t ifindex;
+ int vif_index = 0;
qpim_scan_oil_last = pim_time_monotonic_sec();
++qpim_scan_oil_events;
for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil))
- pim_scan_individual_oil (c_oil, 0);
+ {
+ if (c_oil->up && c_oil->up->rpf.source_nexthop.interface)
+ {
+ ifindex = c_oil->up->rpf.source_nexthop.interface->ifindex;
+ vif_index = pim_if_find_vifindex_by_ifindex (ifindex);
+ /* Pass Current selected NH vif index to mroute download */
+ if (vif_index)
+ pim_scan_individual_oil (c_oil, vif_index);
+ }
+ else
+ pim_scan_individual_oil (c_oil, 0);
+ }
}
static int on_rpf_cache_refresh(struct thread *t)
igmp_source_forward_stop (source);
}
-static int fib_lookup_if_vif_index(struct in_addr addr)
-{
- struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM];
- int num_ifindex;
- int vif_index;
- ifindex_t first_ifindex;
-
- num_ifindex = zclient_lookup_nexthop(nexthop_tab,
- MULTIPATH_NUM, addr,
- PIM_NEXTHOP_LOOKUP_MAX);
- if (num_ifindex < 1) {
- if (PIM_DEBUG_ZEBRA)
- {
- char addr_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
- zlog_debug("%s %s: could not find nexthop ifindex for address %s",
- __FILE__, __PRETTY_FUNCTION__,
- addr_str);
- }
- return -1;
- }
-
- first_ifindex = nexthop_tab[0].ifindex;
-
- if (num_ifindex > 1) {
- if (PIM_DEBUG_ZEBRA)
- {
- char addr_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
- zlog_debug("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)",
- __FILE__, __PRETTY_FUNCTION__,
- num_ifindex, addr_str, first_ifindex);
- }
- /* debug warning only, do not return */
- }
-
- if (PIM_DEBUG_ZEBRA) {
- char addr_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str));
- zlog_debug("%s %s: found nexthop ifindex=%d (interface %s) for address %s",
- __FILE__, __PRETTY_FUNCTION__,
- first_ifindex, ifindex2ifname(first_ifindex, VRF_DEFAULT), addr_str);
- }
-
- vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex);
-
- if (vif_index < 0) {
- if (PIM_DEBUG_ZEBRA)
- {
- char addr_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
- zlog_debug("%s %s: low vif_index=%d < 1 nexthop for address %s",
- __FILE__, __PRETTY_FUNCTION__,
- vif_index, addr_str);
- }
- return -2;
- }
-
- return vif_index;
-}
-
static void
igmp_source_forward_reevaluate_one(struct igmp_source *source)
{
int ret = 0;
struct pim_nexthop_cache out_pnc;
struct pim_nexthop nexthop;
+ struct pim_upstream *up = NULL;
if (!pim_rp_set_upstream_addr (&vif_source, source->source_addr, sg.grp))
return;
nht_p.u.prefix4 = vif_source;
memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache));
+ src.family = AF_INET;
+ src.prefixlen = IPV4_MAX_BITLEN;
+ src.u.prefix4 = vif_source; //RP or Src address
+ grp.family = AF_INET;
+ grp.prefixlen = IPV4_MAX_BITLEN;
+ grp.u.prefix4 = sg.grp;
+
if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1)
{
if (out_pnc.nexthop_num)
{
- src.family = AF_INET;
- src.prefixlen = IPV4_MAX_BITLEN;
- src.u.prefix4 = vif_source; //RP or Src address
- grp.family = AF_INET;
- grp.prefixlen = IPV4_MAX_BITLEN;
- grp.u.prefix4 = sg.grp;
- memset (&nexthop, 0, sizeof (nexthop));
+ up = pim_upstream_find (&sg);
+ memset (&nexthop, 0, sizeof (struct pim_nexthop));
+ if (up)
+ memcpy (&nexthop, &up->rpf.source_nexthop, sizeof (struct pim_nexthop));
//Compute PIM RPF using Cached nexthop
- pim_ecmp_nexthop_search (&out_pnc, &nexthop,
- &src, &grp, 0);
+ pim_ecmp_nexthop_search (&out_pnc, &nexthop, &src, &grp, 0);
if (nexthop.interface)
input_iface_vif_index = pim_if_find_vifindex_by_ifindex (nexthop.interface->ifindex);
}
}
}
else
- input_iface_vif_index = fib_lookup_if_vif_index(vif_source);
+ input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(vif_source, &src, &grp);
if (PIM_DEBUG_ZEBRA)
{
struct prefix nht_p, src, grp;
int ret = 0;
struct pim_nexthop_cache out_pnc;
- struct pim_nexthop nexthop;
/* Register addr with Zebra NHT */
nht_p.family = AF_INET;
grp.u.prefix4 = up->sg.grp;
memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache));
- if ((ret =
- pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1)
+ if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1)
{
if (out_pnc.nexthop_num)
{
grp.family = AF_INET;
grp.prefixlen = IPV4_MAX_BITLEN;
grp.u.prefix4 = up->sg.grp;
- memset (&nexthop, 0, sizeof (nexthop));
//Compute PIM RPF using Cached nexthop
- pim_ecmp_nexthop_search (&out_pnc, &nexthop, &src, &grp, 0);
- input_iface_vif_index =
- pim_if_find_vifindex_by_ifindex (nexthop.interface->ifindex);
+ if (pim_ecmp_nexthop_search (&out_pnc, &up->rpf.source_nexthop, &src, &grp, 0) == 0)
+ input_iface_vif_index = pim_if_find_vifindex_by_ifindex (up->rpf.source_nexthop.interface->ifindex);
+ else
+ {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug ("%s: Nexthop selection failed for %s ", __PRETTY_FUNCTION__, up->sg_str);
+ }
}
else
{
}
}
else
- input_iface_vif_index = fib_lookup_if_vif_index (up->upstream_addr);
+ input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(up->upstream_addr, &src, &grp);
if (input_iface_vif_index < 1)
{
}
if (PIM_DEBUG_TRACE)
{
- zlog_debug ("%s: NHT entry %s update channel_oil vif_index %d ",
- __PRETTY_FUNCTION__, up->sg_str, input_iface_vif_index);
+ struct interface *in_intf = pim_if_find_by_vif_index (input_iface_vif_index);
+ zlog_debug ("%s: Update channel_oil IIF %s VIFI %d entry %s ",
+ __PRETTY_FUNCTION__, in_intf ? in_intf->name : "NIL",
+ input_iface_vif_index, up->sg_str);
}
up->channel_oil = pim_channel_oil_add (&up->sg, input_iface_vif_index);
if (!up->channel_oil)
"Dump raw netlink messages received\n"
"Dump raw netlink messages sent\n")
{
- int idx_recv_send = 4;
- if (argv[idx_recv_send]->arg && strncmp(argv[idx_recv_send]->arg, "recv", strlen(argv[idx_recv_send]->arg)) == 0)
+ int idx = 0;
+ if (argc == 4 || argv_find (argv, argc, "recv", &idx))
SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV);
- if (!argv[idx_recv_send]->arg || strncmp(argv[idx_recv_send]->arg, "send", strlen(argv[idx_recv_send]->arg)) == 0)
+ if (argc == 4 || argv_find (argv, argc, "send", &idx))
SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND);
+
return CMD_SUCCESS;
}
static void
link_param_cmd_unset (struct interface *ifp, uint32_t type)
{
+ if (ifp->link_params == NULL)
+ return;
/* Unset field */
UNSET_PARAM(ifp->link_params, type);
int first = 1;
vrf_id_t vrf_id = VRF_DEFAULT;
- if (strmatch(argv[3]->text, "vrf"))
+ if (argc == 5)
VRF_GET_ID (vrf_id, argv[4]->arg);
table = zebra_vrf_table (AFI_IP6, SAFI_MULTICAST, vrf_id);