]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge remote-tracking branch 'origin/stable/3.0'
authorDonald Sharp <sharpd@cumulusnetworks.com>
Mon, 8 May 2017 20:51:21 +0000 (16:51 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Mon, 8 May 2017 20:51:21 +0000 (16:51 -0400)
30 files changed:
bgpd/bgp_evpn_vty.c
bgpd/bgp_mplsvpn.c
bgpd/bgp_routemap.c
bgpd/bgp_vty.c
bgpd/rfapi/bgp_rfapi_cfg.c
bgpd/rfapi/rfapi_vty.c
configure.ac
doc/Building_FRR_on_Ubuntu1604.md
lib/thread.c
lib/thread.h
ospfd/ospf_vty.c
pimd/pim_cmd.c
pimd/pim_iface.c
pimd/pim_ifchannel.c
pimd/pim_igmpv3.c
pimd/pim_join.c
pimd/pim_jp_agg.c
pimd/pim_msg.c
pimd/pim_nht.c
pimd/pim_nht.h
pimd/pim_oil.c
pimd/pim_oil.h
pimd/pim_rp.c
pimd/pim_rpf.c
pimd/pim_upstream.c
pimd/pim_vty.c
pimd/pim_zebra.c
zebra/debug.c
zebra/interface.c
zebra/zebra_vty.c

index 97ce7ee969cc4ecce7cf120b6e7f953afee07875..c133d7ba39df1139bce0b336e5b354bf6381be42 100644 (file)
@@ -300,10 +300,12 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd,
       "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);
@@ -339,10 +341,12 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags,
       "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);
@@ -365,12 +369,14 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes,
       "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) {
@@ -423,14 +429,17 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
       "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) {
@@ -499,12 +508,14 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes,
       "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) {
@@ -555,14 +566,17 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
       "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) {
@@ -644,10 +658,12 @@ DEFUN(show_ip_bgp_evpn_rd_overlay,
       "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);
index 88cde15e83381d17e109ccae2efa945ada6e076c..421b62fba0f494090d021801645dce5ef37a3429 100644 (file)
@@ -531,7 +531,7 @@ DEFUN (vpnv6_network,
   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);
index 9b5a7a5ebb0b01ea2a1882c4f7a8d32d94c1f02a..9b3a6a513ad5d1f65a70d5c9e1a5928aceb1d351 100644 (file)
@@ -4333,7 +4333,7 @@ DEFUN (no_set_ipv6_nexthop_global,
 #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"
@@ -4359,7 +4359,7 @@ DEFUN (set_vpn_nexthop,
 
 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"
@@ -4444,7 +4444,7 @@ DEFUN (no_set_ipx_vpn_nexthop,
                                    "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;
 }
index 31f7872de222c91ad0f516cee09d22e9f8317209..b41ffa6e5296dcd8493566d5aac84855d91b70eb 100644 (file)
@@ -342,7 +342,6 @@ bgp_vty_find_and_parse_afi_safi_bgp (struct vty *vty, struct cmd_token **argv, i
   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;
index aa48b4924afed9927fa40dfba5c4d73c3bf30a54..5ddccc906f1d4e793b18a0e1cb2ddb9f27cf074d 100644 (file)
@@ -2046,12 +2046,12 @@ DEFUN (vnc_nve_export_no_prefixlist,
   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);
@@ -2060,12 +2060,12 @@ DEFUN (vnc_nve_export_no_prefixlist,
   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); */
@@ -2146,12 +2146,12 @@ DEFUN (vnc_nve_export_no_routemap,
   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);
@@ -2161,12 +2161,12 @@ DEFUN (vnc_nve_export_no_routemap,
   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); */
index c52026e8effc42ab5436c032792965c651fe3f29..3de79dac04be126d5ee73efe08a0a36223527cbd 100644 (file)
@@ -2190,9 +2190,9 @@ register_add (
   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;
@@ -3906,7 +3906,7 @@ DEFUN (clear_vnc_nve_un,
   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;
index 9bdcfd1e65a8d6e3aab9f3b1ab6b1966c75ceed3..919902d938738241196cbfea30c64b75e08d38d6 100755 (executable)
@@ -362,7 +362,7 @@ if test "${enable_rr_semantics}" != "no" ; then
 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 ----------
index 8b8bbf4bb2e2bb860230eeb16e3e0aa5df2dc26b..09b5aa8b72cbf9bec8417accf46e296446f3a8c5 100644 (file)
@@ -14,7 +14,7 @@ Add packages:
 
     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)
 ---------------------------------------------
@@ -56,6 +56,7 @@ an example.)
         --enable-rtadv \
         --enable-tcp-zebra \
         --enable-fpm \
+       --enable-systemd=yes \
         --with-pkg-git-version \
         --with-pkg-extra-version=-MyOwnFRRVersion   
     make
@@ -136,13 +137,8 @@ For example.
     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.
index 74d498baf8e89d3c973d59e59711e8ac11922bd0..3fb28bce26f0e0961a530f3025619d6c77eeed46 100644 (file)
@@ -379,7 +379,7 @@ thread_master_create (void)
   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,
@@ -543,7 +543,7 @@ thread_master_free (struct thread_master *m)
   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);
@@ -644,7 +644,7 @@ thread_get (struct thread_master *m, u_char type,
   return thread;
 }
 
-#if defined (HAVE_POLL)
+#if defined (HAVE_POLL_CALL)
 
 #define fd_copy_fd_set(X) (X)
 
@@ -712,7 +712,7 @@ fd_select (struct thread_master *m, int size, thread_fd_set *read, thread_fd_set
    * 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
@@ -746,7 +746,7 @@ fd_select (struct thread_master *m, int size, thread_fd_set *read, thread_fd_set
 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);
@@ -756,7 +756,7 @@ fd_is_set (struct thread *thread, thread_fd_set *fdset, int pos)
 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);
 
@@ -783,7 +783,7 @@ funcname_thread_add_read_write (int dir, struct thread_master *m,
 
   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)
@@ -964,7 +964,7 @@ funcname_thread_add_event (struct thread_master *m,
 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)
@@ -1006,7 +1006,7 @@ thread_cancel (struct thread *thread)
   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);
@@ -1014,7 +1014,7 @@ thread_cancel (struct thread *thread)
       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);
@@ -1154,7 +1154,7 @@ thread_process_fds_helper (struct thread_master *m, struct thread *thread, threa
       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;
@@ -1162,7 +1162,7 @@ thread_process_fds_helper (struct thread_master *m, struct thread *thread, threa
   return 0;
 }
 
-#if defined(HAVE_POLL)
+#if defined(HAVE_POLL_CALL)
 
 /* check poll events */
 static void
@@ -1203,7 +1203,7 @@ check_pollfds(struct thread_master *m, fd_set *readfd, int num)
 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;
@@ -1298,7 +1298,7 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
       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);
index 18fd340ba5d18c41897633b6a2cb6b87fb7095cf..6fb6ad7c9d9eae0e7df3b390f6f410c80cc3f423 100644 (file)
@@ -51,7 +51,7 @@ struct pqueue;
  */
 typedef fd_set thread_fd_set;
 
-#if defined(HAVE_POLL)
+#if defined(HAVE_POLL_CALL)
 #include <poll.h>
 struct fd_handler
 {
index 9e577105ca58690e3897c153dcaa23b79cc6284c..4a7dbb9541908b042ea927ce4666d40d100c6260 100644 (file)
@@ -1539,7 +1539,7 @@ ospf_area_nssa_cmd_handler (struct vty *vty, int argc, struct cmd_token **argv,
       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,
index ee3538a05477a8234a43f8242734dd3a31854b9c..e476a32fb03e5912756c6dc53489783e2e43e928 100644 (file)
@@ -4031,7 +4031,7 @@ DEFUN (ip_ssmpingd,
   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) {
@@ -4061,7 +4061,7 @@ DEFUN (no_ip_ssmpingd,
   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) {
@@ -4113,6 +4113,7 @@ DEFUN (ip_pim_ecmp_rebalance,
        "Enable PIM ECMP \n"
        "Enable PIM ECMP Rebalance\n")
 {
+  qpim_ecmp_enable = 1;
   qpim_ecmp_rebalance_enable = 1;
 
   return CMD_SUCCESS;
@@ -5984,7 +5985,7 @@ DEFUN (no_ip_msdp_mesh_group_source,
        "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);
index 524f2ee0b356c1a61c9fc3f39201438a794b09ae..48a59344eb6f679d40c0800947d81972ad760973 100644 (file)
@@ -50,6 +50,8 @@ struct list *pim_ifchannel_list = NULL;
 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)
@@ -599,6 +601,35 @@ void pim_if_addr_add(struct connected *ifc)
       /* 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))
@@ -1527,6 +1558,9 @@ pim_if_connected_to_source (struct interface *ifp, struct in_addr src)
   struct connected *c;
   struct prefix p;
 
+  if (!ifp)
+    return 0;
+
   p.family = AF_INET;
   p.u.prefix4 = src;
   p.prefixlen = IPV4_MAX_BITLEN;
index d267ee9fb288d1786426d60361d59146e46ed0bc..f4fe609605bcd2dbedfe2baf0e1ab2bc7804054d 100644 (file)
@@ -145,6 +145,9 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
       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?
@@ -610,6 +613,7 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
       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 */
 
@@ -790,6 +794,16 @@ void pim_ifchannel_join_add(struct interface *ifp,
       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);
@@ -1083,8 +1097,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
          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);
@@ -1278,7 +1291,7 @@ pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t
               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);
                 }
             }
index 8c7083d83df21b85b116834104527292db169564..86509a20c4898b754b503abb0c5682cfb6f6cd2e 100644 (file)
@@ -357,10 +357,11 @@ void igmp_source_delete(struct igmp_source *source)
     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);
index a9ca349102297bd2e7859e7bb00284a861c02b05..828781a4670b511376491009154f30db7b00680d 100644 (file)
@@ -374,7 +374,7 @@ int pim_joinprune_send(struct pim_rpf *rpf,
                        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;
@@ -395,12 +395,13 @@ int pim_joinprune_send(struct pim_rpf *rpf,
       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))
     {
index ce4ddfd4a4a20baa4ba904982ad1fac49bd40ab8..46c6cbc6905ab4e966bb72b9e660b7a94b1ac8e4 100644 (file)
@@ -127,6 +127,10 @@ pim_jp_agg_get_interface_upstream_switch_list (struct pim_rpf *rpf)
   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)
@@ -323,7 +327,8 @@ pim_jp_agg_switch_interface (struct pim_rpf *orpf,
    */
 
   /* 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);
@@ -343,7 +348,7 @@ pim_jp_agg_single_upstream_send (struct pim_rpf *rpf,
   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;
 
index e19893f5dab4253f7de1970b64b4b77bbb270b98..a9e0130905859acbeae47fd4efe370acc42c4e06 100644 (file)
@@ -195,7 +195,9 @@ pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_jp_agg_group *sgs
           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
         {
index 98c98cdf24da1eb391d6d42f62e839da6a268a0a..c5f8d1d8268d07a6c6432663e07bd0efded33fde 100644 (file)
@@ -147,7 +147,9 @@ pim_nexthop_cache_add (struct pim_rpf *rpf_addr)
   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,
@@ -167,13 +169,6 @@ pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up,
   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);
@@ -213,8 +208,7 @@ pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up,
             {
               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);
@@ -271,11 +265,12 @@ pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *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))
@@ -284,8 +279,8 @@ pim_update_rp_nh (struct pim_nexthop_cache *pnc)
         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)
         {
@@ -298,7 +293,10 @@ pim_update_rp_nh (struct pim_nexthop_cache *pnc)
         }
     }
 
-  return 0;
+  if (ret)
+    return 0;
+
+  return 1;
 }
 
 /* This API is used to traverse nexthop cache of RPF addr
@@ -320,9 +318,9 @@ pim_resolve_upstream_nh (struct prefix *nht_p)
         {
           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;
@@ -333,9 +331,8 @@ pim_resolve_upstream_nh (struct prefix *nht_p)
                       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);
                     }
                 }
             }
@@ -368,18 +365,15 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc)
       /* 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);
             }
@@ -490,7 +484,7 @@ pim_compute_ecmp_hash (struct prefix * src, struct prefix * grp)
     }
 
   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];
@@ -519,49 +513,57 @@ pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc,
   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;
@@ -574,7 +576,7 @@ pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc,
        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)
@@ -582,8 +584,7 @@ pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc,
               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)
@@ -598,8 +599,7 @@ pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc,
               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)
@@ -617,9 +617,8 @@ pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc,
           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++;
@@ -639,30 +638,22 @@ pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc,
           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)
@@ -717,8 +708,7 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
             {
               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;
@@ -737,16 +727,6 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
   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.
@@ -774,9 +754,8 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
             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)
                 {
@@ -786,21 +765,16 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
                       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);
                     }
@@ -818,9 +792,10 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
             {
               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);
@@ -829,8 +804,7 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
               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)));
                 }
@@ -843,8 +817,7 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
               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)));
                 }
@@ -887,8 +860,7 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
     {
       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));
     }
@@ -925,10 +897,8 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
                   __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)
     {
@@ -939,13 +909,13 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
       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);
     }
 
@@ -960,8 +930,7 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
             {
               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)
@@ -976,8 +945,7 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
             {
               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)
@@ -987,8 +955,7 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
         }
       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))
@@ -1001,8 +968,7 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
                   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;
@@ -1018,8 +984,7 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
               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);
@@ -1041,3 +1006,67 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
   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;
+}
index b4b2d91e47a550fd0a0b46484bc454ceabc1d109..0ccc5399c3df42fa1fabdd0cc839067df97609bb 100644 (file)
@@ -65,5 +65,8 @@ int pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
                          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
index 2d4aa3febc40c7a8d401f25af5349857faec230a..7f5f3970ae6823bcb95fcf9904f929889fb6fc0f 100644 (file)
@@ -164,6 +164,7 @@ struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg,
       }
     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;
   }
 
@@ -188,6 +189,7 @@ struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg,
   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);
 
@@ -204,6 +206,7 @@ void pim_channel_oil_del(struct channel_oil *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);
 
index e90cd5fc19b87163b049c9856c6da8f559574659..a7bb23cd0ee9af45b61df9ecebac713d3cb34421 100644 (file)
@@ -79,6 +79,7 @@ struct channel_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;
index feddb8d8d54f9424cb2a521f6f2fb905d7afb577..cdc760e92df31dc7ab5174d8e27377308b9075fe 100644 (file)
@@ -281,7 +281,7 @@ pim_rp_check_interfaces (struct rp_info *rp_info)
 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;
@@ -741,7 +741,7 @@ pim_rp_g (struct in_addr group)
           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));
@@ -759,7 +759,7 @@ pim_rp_g (struct in_addr group)
               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 ();
@@ -972,8 +972,7 @@ pim_resolve_rp_nh (void)
             {
               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)
                     {
@@ -982,14 +981,15 @@ pim_resolve_rp_nh (void)
                         {
                           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);
                         }
                     }
                 }
index f454ac59c1ac476b55f5c1c201923b5894d56131..f46ebfb979b4712360c78f2a85abc80d6c00e40e 100644 (file)
@@ -240,8 +240,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old,
       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;
         }
index 1e31a3aba1e3459e200548632607ca833ee0200e..dd6eab9cfe8766bce4ce75d7ae4b8ae203d760f4 100644 (file)
@@ -162,8 +162,9 @@ pim_upstream_del(struct pim_upstream *up, const char *name)
   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;
 
@@ -215,6 +216,7 @@ pim_upstream_del(struct pim_upstream *up, const char *name)
   up->sources = NULL;
 
   list_delete (up->ifchannels);
+  up->ifchannels = NULL;
 
   /*
     notice that listnode_delete() can't be moved
@@ -242,7 +244,7 @@ pim_upstream_del(struct pim_upstream *up, const char *name)
     {
       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);
@@ -1016,14 +1018,17 @@ static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up)
   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
@@ -1217,7 +1222,7 @@ pim_upstream_is_sg_rpt (struct pim_upstream *up)
 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)
@@ -1242,8 +1247,7 @@ pim_upstream_set_sptbit (struct pim_upstream *up, struct 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))",
index 62d1f936ecf5aeaeaa4a1c8da0ed59edfa574fde..2d502d9aa901b8c9317e856a8fb0316008897e2d 100644 (file)
@@ -198,7 +198,16 @@ int pim_global_config_write(struct vty *vty)
                  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;
index 253ab7ab4429069f8b6e02f9ee59b25fff1f77d4..b2a7319bf1740bc856ecd99d307f7d7be3db2965 100644 (file)
@@ -53,7 +53,6 @@
 
 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,
@@ -449,7 +448,28 @@ pim_scan_individual_oil (struct channel_oil *c_oil, int in_vif_index)
   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)
@@ -537,12 +557,25 @@ void pim_scan_oil()
   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)
@@ -679,67 +712,6 @@ void igmp_anysource_forward_stop(struct igmp_group *group)
     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)
 {
@@ -853,6 +825,7 @@ void igmp_source_forward_start(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;
@@ -863,20 +836,23 @@ void igmp_source_forward_start(struct igmp_source *source)
     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);
           }
@@ -894,7 +870,7 @@ void igmp_source_forward_start(struct igmp_source *source)
           }
       }
     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)
       {
@@ -1075,7 +1051,6 @@ void pim_forward_start(struct pim_ifchannel *ch)
       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;
@@ -1086,8 +1061,7 @@ void pim_forward_start(struct pim_ifchannel *ch)
       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)
             {
@@ -1097,11 +1071,14 @@ void pim_forward_start(struct pim_ifchannel *ch)
               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
             {
@@ -1117,7 +1094,7 @@ void pim_forward_start(struct pim_ifchannel *ch)
             }
         }
       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)
         {
@@ -1133,8 +1110,10 @@ void pim_forward_start(struct pim_ifchannel *ch)
         }
       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)
index f21778276ef75af9653759eeb656b1eca721e934..a42d5aa3ef98763887c70bb74f19aea428db5e74 100644 (file)
@@ -173,11 +173,12 @@ DEFUN (debug_zebra_kernel_msgdump,
        "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;
 }
 
index c3d303736204c1539415d335d8ef9b158f022190..42e7c7bb1871bbf4bb8d706fbb65b11def946751 100644 (file)
@@ -1707,6 +1707,8 @@ link_param_cmd_set_float (struct interface *ifp, float *field,
 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);
index 35aa69cc97c18eb27011bac6ef844bdfeb10127b..1708138d83e4f38591e31e729a15cfb17f3d487b 100644 (file)
@@ -3338,7 +3338,7 @@ DEFUN (show_ipv6_mroute,
   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);