]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge remote-tracking branch 'origin/master' into EIGRP
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 26 Apr 2017 12:03:54 +0000 (08:03 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 26 Apr 2017 12:03:54 +0000 (08:03 -0400)
76 files changed:
README
bgpd/bgp_attr_evpn.c
bgpd/bgp_attr_evpn.h
bgpd/bgp_evpn.c
bgpd/bgp_evpn.h
bgpd/bgp_evpn_vty.c
bgpd/bgp_evpn_vty.h
bgpd/bgp_main.c
bgpd/bgp_route.c
bgpd/bgp_routemap.c
bgpd/bgp_vpn.c
bgpd/bgp_vpn.h
configure.ac
debian/changelog
doc/Building_FRR_on_Debian8.md
doc/Building_FRR_on_Fedora24.md
doc/Building_FRR_on_OpenBSD6.md
doc/Building_FRR_on_Ubuntu1204.md
doc/Building_FRR_on_Ubuntu1404.md
doc/Building_FRR_on_Ubuntu1604.md
doc/install.texi
lib/command_lex.l
lib/distribute.c
lib/libfrr.c
lib/libfrr.h
lib/module.c
lib/module.h
lib/pqueue.c
lib/pqueue.h
lib/privs.c
lib/zclient.c
nhrpd/nhrp_interface.c
nhrpd/nhrp_nhs.c
nhrpd/nhrp_peer.c
nhrpd/nhrp_vty.c
nhrpd/nhrpd.h
nhrpd/vici.c
ospf6d/ospf6_top.c
ospfd/ospf_vty.c
pimd/pim_cmd.c
pimd/pim_hello.c
pimd/pim_hello.h
pimd/pim_iface.c
pimd/pim_iface.h
pimd/pim_ifchannel.c
pimd/pim_mroute.c
pimd/pim_msg.h
pimd/pim_neighbor.c
pimd/pim_neighbor.h
pimd/pim_nht.c
pimd/pim_nht.h
pimd/pim_oil.c
pimd/pim_pim.c
pimd/pim_register.c
pimd/pim_rp.c
pimd/pim_rp.h
pimd/pim_rpf.c
pimd/pim_tlv.c
pimd/pim_tlv.h
pimd/pim_upstream.c
pimd/pim_upstream.h
pimd/pim_vty.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
pimd/pimd.c
pimd/pimd.h
ripd/rip_zebra.c
snapcraft/README.snap_build.md
snapcraft/README.usage.md
snapcraft/defaults/nhrpd.conf.default [new file with mode: 0644]
snapcraft/scripts/Makefile
snapcraft/scripts/nhrpd-service [new file with mode: 0644]
snapcraft/scripts/set-options [new file with mode: 0755]
snapcraft/scripts/zebra-service
snapcraft/snapcraft.yaml.in
vtysh/vtysh.c

diff --git a/README b/README
index a0aa8953677c455016f1960c29448d5854e6a918..7c6ef7034ec6390e41c68597bc99caa1b025a0f9 100644 (file)
--- a/README
+++ b/README
@@ -1,13 +1,13 @@
-Free Range Routing is free software that manages various IPv4 and IPv6 routing
+FRRouting is free software that manages various IPv4 and IPv6 routing
 protocols.
 
-Currently Free Range Routing supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1,
+Currently FRRouting supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1,
 RIPv2, RIPng, PIM-SM/MSDP and LDP as well as very early support for IS-IS.
 
 See the file REPORTING-BUGS to report bugs.
 
-Free Range Routing is free software. See the file COPYING for copying conditions.
+Free RRRouting is free software. See the file COPYING for copying conditions.
 
-Public email discussion can be found at https://lists.nox.tf/listinfo/frr
+Public email discussion can be found at https://lists.frrouting.org/listinfo
 
-Our public slack channel is at https://freerangerouting.slack.com
+Our public slack channel is at https://frrouting.slack.com
index be97ffda69d25f6493a4c9dadbebc9cade61f18a..5b24d4ec61318909f40d2ef0117afa8abbdabac3 100644 (file)
@@ -1,20 +1,20 @@
 /* Ethernet-VPN Attribute handling file
    Copyright (C) 2016 6WIND
 
-This file is part of Free Range Routing.
+This file is part of FRRouting.
 
-Free Range Routing is free software; you can redistribute it and/or modify it
+FRRouting is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
 Free Software Foundation; either version 2, or (at your option) any
 later version.
 
-Free Range Routing is distributed in the hope that it will be useful, but
+FRRouting is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with Free Range Routing; see the file COPYING.  If not, write to the Free
+along with FRRouting; see the file COPYING.  If not, write to the Free
 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
index e6da7e7080ab583b080138810ca0ccc08d748a25..4b7d24de18017745e8449b07306a5cb737dde762 100644 (file)
@@ -1,20 +1,20 @@
 /* E-VPN attribute handling structure file
    Copyright (C) 2016 6WIND
 
-This file is part of Free Range Routing.
+This file is part of FRRouting.
 
-Free Range Routing is free software; you can redistribute it and/or modify it
+FRRouting is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
 Free Software Foundation; either version 2, or (at your option) any
 later version.
 
-Free Range Routing is distributed in the hope that it will be useful, but
+FRRouting is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with Free Range Routing; see the file COPYING.  If not, write to the Free
+along with FRRouting; see the file COPYING.  If not, write to the Free
 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
index 1ab8e23236b9ceb256b5ff60da6205d96dca85ec..612f49f1cbdcb5dbca6c743c5e25f2811992e481 100644 (file)
@@ -1,20 +1,20 @@
 /* Ethernet-VPN Packet and vty Processing File
    Copyright (C) 2016 6WIND
 
-This file is part of Free Range Routing.
+This file is part of FRRouting.
 
-Free Range Routing is free software; you can redistribute it and/or modify it
+FRRouting is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
 Free Software Foundation; either version 2, or (at your option) any
 later version.
 
-Free Range Routing is distributed in the hope that it will be useful, but
+FRRouting is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with Free Range Routing; see the file COPYING.  If not, write to the Free
+along with FRRouting; see the file COPYING.  If not, write to the Free
 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
index 63c1a766ea6654ad2e42127322c4d06cbf5b9321..9b24bb066a18909112c809857418030822dfb460 100644 (file)
@@ -1,20 +1,20 @@
 /* E-VPN header for packet handling
    Copyright (C) 2016 6WIND
 
-This file is part of Free Range Routing.
+This file is part of FRRouting.
 
-Free Range Routing is free software; you can redistribute it and/or modify it
+FRRouting is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
 Free Software Foundation; either version 2, or (at your option) any
 later version.
 
-Free Range Routing is distributed in the hope that it will be useful, but
+FRRouting is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with Free Range Routing; see the file COPYING.  If not, write to the Free
+along with FRRouting; see the file COPYING.  If not, write to the Free
 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
index 1654265a7246bfccaaf3711c5354c0338eb91732..97ce7ee969cc4ecce7cf120b6e7f953afee07875 100644 (file)
@@ -1,20 +1,20 @@
 /* Ethernet-VPN Packet and vty Processing File
    Copyright (C) 2017 6WIND
 
-This file is part of Free Range Routing
+This file is part of FRRouting
 
-Free Range Routing is free software; you can redistribute it and/or modify it
+FRRouting is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
 Free Software Foundation; either version 2, or (at your option) any
 later version.
 
-Free Range Routing is distributed in the hope that it will be useful, but
+FRRouting is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with Free Range Routing; see the file COPYING.  If not, write to the Free
+along with FRRouting; see the file COPYING.  If not, write to the Free
 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
index 11e93a52812660a38ce865a9a4d6b478dbb4773e..68b5f5cfbf7a515fe0c873fc7cd8c752117e1c3c 100644 (file)
@@ -1,20 +1,20 @@
 /* EVPN VTY functions to EVPN
    Copyright (C) 2017 6WIND
 
-This file is part of Free Range Routing.
+This file is part of FRRouting.
 
-Free Range Routing is free software; you can redistribute it and/or modify it
+FRRouting is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
 Free Software Foundation; either version 2, or (at your option) any
 later version.
 
-Free Range Routing is distributed in the hope that it will be useful, but
+FRRouting is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with Free Range Routing; see the file COPYING.  If not, write to the Free
+along with FRRouting; see the file COPYING.  If not, write to the Free
 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
index 423c9453ebbff8b1f0d9003d051f078e0c9e97da..1773070fe3551f3f27d3067caec7fc48515d89ad 100644 (file)
@@ -66,6 +66,7 @@ static const struct option longopts[] =
   { "listenon",    required_argument, NULL, 'l'},
   { "retain",      no_argument,       NULL, 'r'},
   { "no_kernel",   no_argument,       NULL, 'n'},
+  { "skip_runas",  no_argument,       NULL, 'S'},
   { "ecmp",        required_argument, NULL, 'e'},
   { 0 }
 };
@@ -151,7 +152,8 @@ sigint (void)
   if (! retain_mode)
     {
       bgp_terminate ();
-      zprivs_terminate (&bgpd_privs);
+      if (bgpd_privs.user)      /* NULL if skip_runas flag set */
+        zprivs_terminate (&bgpd_privs);
     }
 
   bgp_exit (0);
@@ -363,6 +365,8 @@ main (int argc, char **argv)
 
   int bgp_port = BGP_PORT_DEFAULT;
   char *bgp_address = NULL;
+  int no_fib_flag = 0;
+  int skip_runas = 0;
 
   frr_preinit(&bgpd_di, argc, argv);
   frr_opt_add("p:l:rne:", longopts,
@@ -370,6 +374,7 @@ main (int argc, char **argv)
        "  -l, --listenon     Listen on specified address (implies -n)\n"
        "  -r, --retain       When program terminates, retain added route by bgpd.\n"
        "  -n, --no_kernel    Do not install route to kernel.\n"
+        "  -S, --skip_runas   Skip capabilities checks, and changing user and group IDs.\n"
        "  -e, --ecmp         Specify ECMP to use.\n");
 
   /* Command line argument treatment. */
@@ -389,7 +394,7 @@ main (int argc, char **argv)
          if (tmp_port <= 0 || tmp_port > 0xffff)
            bgp_port = BGP_PORT_DEFAULT;
          else
-           bm->port = tmp_port;
+           bgp_port = tmp_port;
          break;
         case 'e':
           multipath_num = atoi (optarg);
@@ -406,18 +411,25 @@ main (int argc, char **argv)
          bgp_address = optarg;
          /* listenon implies -n */
        case 'n':
-         bgp_option_set (BGP_OPT_NO_FIB);
+          no_fib_flag = 1;
+         break;
+       case 'S':
+          skip_runas = 1;
          break;
        default:
          frr_help_exit (1);
          break;
        }
     }
+  if (skip_runas)
+    memset (&bgpd_privs, 0, sizeof (bgpd_privs));
 
   /* BGP master init. */
   bgp_master_init (frr_init ());
   bm->port = bgp_port;
   bm->address = bgp_address;
+  if (no_fib_flag)
+    bgp_option_set (BGP_OPT_NO_FIB);
 
   /* Initializations. */
   bgp_vrf_init ();
index 1fa3e8bc44af8de8ac49e6c921e2014eb463a337..32cf0bcb89cc414663b4327e5d4d75e02dd545e8 100644 (file)
@@ -8171,7 +8171,7 @@ bgp_show_lcommunity (struct vty *vty, struct bgp *bgp, int argc,
         buffer_putc (b, ' ');
       else
         {
-          if (strmatch (argv[i]->text, "<AA:BB:CC>"))
+          if (strmatch (argv[i]->text, "AA:BB:CC"))
             {
               first = 1;
               buffer_putstr (b, argv[i]->arg);
@@ -8187,7 +8187,7 @@ bgp_show_lcommunity (struct vty *vty, struct bgp *bgp, int argc,
   XFREE (MTYPE_TMP, str);
   if (! lcom)
     {
-      vty_out (vty, "%% Large-community malformed%s", VTY_NEWLINE);
+      vty_out (vty, "%% Large-community malformed%s", VTY_NEWLINE);
       return CMD_WARNING;
     }
 
@@ -8299,8 +8299,7 @@ DEFUN (show_ip_bgp_large_community,
      return CMD_WARNING;
    }
 
-  argv_find (argv, argc, "large-community", &idx);
-  if (strmatch(argv[idx+1]->text, "AA:BB:CC"))
+  if (argv_find (argv, argc, "AA:BB:CC", &idx))
     return bgp_show_lcommunity (vty, bgp, argc, argv, afi, safi, uj);
   else
     return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity_all, NULL, uj);
@@ -8563,8 +8562,6 @@ static int
 bgp_show_regexp (struct vty *vty, const char *regstr, afi_t afi,
                 safi_t safi, enum bgp_show_type type)
 {
-  return CMD_SUCCESS;
-
   regex_t *regex;
   int rc;
   
index bafc81eaf8a0408511f757b5352dec9c3cf6ddf2..9b5a7a5ebb0b01ea2a1882c4f7a8d32d94c1f02a 100644 (file)
@@ -1437,7 +1437,7 @@ route_set_aspath_prepend_compile (const char *arg)
 {
   unsigned int num;
 
-  if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num < 10)
+  if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num <= 10)
     return (void*)(uintptr_t)num;
 
   return route_aspath_compile(arg);
@@ -3677,12 +3677,12 @@ DEFUN (set_aspath_prepend_asn,
 
 DEFUN (set_aspath_prepend_lastas,
        set_aspath_prepend_lastas_cmd,
-       "set as-path prepend last-as (1-9)",
+       "set as-path prepend last-as (1-10)",
        SET_STR
        "Transform BGP AS_PATH attribute\n"
        "Prepend to the as-path\n"
        "Use the peer's AS-number\n"
-       "Number of times to insert")
+       "Number of times to insert\n")
 {
   return set_aspath_prepend_asn (self, vty, argc, argv);
 }
index edc5891d224dab8317357b1a4c2214fe6617e0d1..5b1b1b85b2c7c0cd3209f58310fda302839c435a 100644 (file)
@@ -1,20 +1,20 @@
 /* VPN Related functions
    Copyright (C) 2017 6WIND
 
-This file is part of Free Range Routing
+This file is part of FRRouting
 
-Free Range Routing is free software; you can redistribute it and/or modify it
+FRRouting is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
 Free Software Foundation; either version 2, or (at your option) any
 later version.
 
-Free Range Routing is distributed in the hope that it will be useful, but
+FRRouting is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with Free Range Routing; see the file COPYING.  If not, write to the Free
+along with FRRouting; see the file COPYING.  If not, write to the Free
 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
index a16914b65e7f7e0200afd952618ddc696c5b439f..dd53503bf313db25e916d817a1ab806c97653cf7 100644 (file)
@@ -1,20 +1,20 @@
 /* VPN common functions to MP-BGP
    Copyright (C) 2017 6WIND
 
-This file is part of Free Range Routing.
+This file is part of FRRouting.
 
-Free Range Routing is free software; you can redistribute it and/or modify it
+FRRouting is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
 Free Software Foundation; either version 2, or (at your option) any
 later version.
 
-Free Range Routing is distributed in the hope that it will be useful, but
+FRRouting is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with Free Range Routing; see the file COPYING.  If not, write to the Free
+along with FRRouting; see the file COPYING.  If not, write to the Free
 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
index ec5442d06596abf09d595330f826b267d316270b..f586e560edbcaadf67992ed5cae16d99c6ca780c 100755 (executable)
@@ -7,7 +7,7 @@
 ##
 AC_PREREQ(2.60)
 
-AC_INIT(frr, 2.1-dev, [https://github.com/frrouting/frr/issues])
+AC_INIT(frr, 3.1-dev, [https://github.com/frrouting/frr/issues])
 PACKAGE_URL="https://frrouting.org/"
 PACKAGE_FULLNAME="FRRouting"
 AC_SUBST(PACKAGE_FULLNAME)
index 8302af4b4cb9db4c96d7b04878150b7859ef498a..4ea86929fcbdcaacc005e37ede4e41da8bf9eb6b 100644 (file)
@@ -1,3 +1,30 @@
+frr (3.1-dev) Released; urgency=medium
+
+  * New Enabled: PIM draft Unnumbered
+
+ -- frr <frog@lists.frrouting.org> Wed, 5 Apr 2017 22:29:42 -0500
+
+frr (3.0) Released; urgency=medium
+
+  * New Enabled: BGP Shutdown Message
+  * New Enabled: BGP Large Community
+  * New Enabled: BGP RFC 7432 Partial Support w/ Ethernet VPN
+  * New Enabled: BGP EVPN RT-5
+  * New Enabled: LDP RFC 5561
+  * New Enabled: LDP RFC 5918
+  * New Enabled: LDP RFC 5919
+  * New Enabled: LDP RFC 6667
+  * New Enabled: LDP RFC 7473
+  * New Enabled: OSPF RFC 4552
+  * New Enabled: ISIS SPF Backoff draft
+  * New Enabled: PIM Unnumbered Interfaces
+  * New Enabled: PIM RFC 4611
+  * New Enabled: PIM Sparse Mode
+  * New Enabled: NHRP RFC 2332
+  * New Enabled: Label Manager
+
+ -- frr <frr@lists.nox.tf> Wed, 5 Apr 2017 22:23:42 -0500
+
 frr (2.1) Released; urgency=medium
 
   * Switchover to FRR
index b902033d5edef7cac392d6dc09112018904af9ae..a42ca6d781450dde5d518b41d02e5cdf882abfed 100644 (file)
@@ -31,9 +31,9 @@ any packages**
 
     sudo addgroup --system --gid 92 frr
     sudo addgroup --system --gid 85 frrvty
-    sudo adduser --system --ingroup frr --groups frrvty --home /var/run/frr/ \
-       --gecos "FRR FRRouting suite" --shell /bin/false frr
-    sudo usermode
+    sudo adduser --system --ingroup frr --home /var/run/frr/ \
+       --gecos "FRR suite" --shell /bin/false frr
+    sudo usermod -a -G frrvty frr
 
 ### Download Source, configure and compile it
 (You may prefer different options on configure statement. These are just
@@ -62,6 +62,7 @@ an example.)
         --enable-rtadv \
         --enable-tcp-zebra \
         --enable-fpm \
+        --enable-ldpd \
         --with-pkg-git-version \
         --with-pkg-extra-version=-MyOwnFRRVersion   
     make
@@ -69,6 +70,7 @@ an example.)
     sudo make install
 
 ### Create empty FRR configuration files
+
     sudo install -m 755 -o frr -g frr -d /var/log/frr
     sudo install -m 775 -o frr -g frrvty -d /etc/frr
     sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
@@ -79,6 +81,8 @@ an example.)
     sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
     sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
     sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
     sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
 
 ### Enable IP & IPv6 forwarding
@@ -94,4 +98,4 @@ other settings)
     #  based on Router Advertisements for this host
     net.ipv6.conf.all.forwarding=1
 
-**Reboot** or use `sysctl` to apply the same config to the running system
+**Reboot** or use `sysctl -p` to apply the same config to the running system
index 941126da420997c4aaa8fba3b9de00613edd1f83..1f5f12b9cc2074479758f7350b0aa0769bc1bce3 100644 (file)
@@ -70,6 +70,7 @@ them if you are not building on a x86_64 architecture
     sudo touch /etc/frr/ripngd.conf
     sudo touch /etc/frr/pimd.conf
     sudo touch /etc/frr/ldpd.conf
+    sudo touch /etc/frr/nhrpd.conf
     sudo chown -R frr:frr /etc/frr/
     sudo touch /etc/frr/vtysh.conf
     sudo chown frr:frrvt /etc/frr/vtysh.conf
@@ -111,7 +112,7 @@ Create a new file `/etc/modules-load.d/mpls.conf` with the following content:
     install -p -m 644 redhat/ospf6d.service /usr/lib/systemd/system/ospf6d.service
     install -p -m 644 redhat/ripngd.service /usr/lib/systemd/system/ripngd.service
     install -p -m 644 redhat/pimd.service /usr/lib/systemd/system/pimd.service
-    install -p -m 644 redhat/pimd.service /usr/lib/systemd/system/ldpd.service
+    install -p -m 644 redhat/ldpd.service /usr/lib/systemd/system/ldpd.service
     install -p -m 644 redhat/frr.sysconfig /etc/sysconfig/frr
     install -p -m 644 redhat/frr.logrotate /etc/logrotate.d/frr
 
index a59452a72b178a7f92e08bdd9f7c59d0c7a6dee3..c1b583664dad26568a0e38a0205fd86f0eae0257 100644 (file)
@@ -75,6 +75,7 @@ an example)
     sudo touch /etc/frr/ripngd.conf
     sudo touch /etc/frr/pimd.conf
     sudo touch /etc/frr/ldpd.conf
+    sudo touch /etc/frr/nhrpd.conf
     sudo chown -R _frr:_frr /etc/frr
     sudo touch /etc/frr/vtysh.conf
     sudo chown -R _frr:_frrvty /etc/frr/vtysh.conf
index 154907d9df39ba6f06f8e7d7b9765a7744620ed4..2d6ccffd9ffcf9d5d3a9ce8afd50b3ff70bc9955 100644 (file)
@@ -65,8 +65,9 @@ any packages**
 
     sudo groupadd -g 92 frr
     sudo groupadd -r -g 85 frrvty
-    sudo adduser --system --ingroup frr --groups frrvty --home /var/run/frr/ \
+    sudo adduser --system --ingroup frr --home /var/run/frr/ \
        --gecos "FRR suite" --shell /sbin/nologin frr
+    sudo usermod -a -G frrvty frr
 
 ### Download Source, configure and compile it
 (You may prefer different options on configure statement. These are just
@@ -101,22 +102,19 @@ an example.)
 
 ### Create empty FRR configuration files
 
-    sudo mkdir /var/log/frr
-    sudo chown frr:frr /var/log/frr
-    sudo mkdir /etc/frr
-    sudo touch /etc/frr/zebra.conf
-    sudo touch /etc/frr/bgpd.conf
-    sudo touch /etc/frr/ospfd.conf
-    sudo touch /etc/frr/ospf6d.conf
-    sudo touch /etc/frr/isisd.conf
-    sudo touch /etc/frr/ripd.conf
-    sudo touch /etc/frr/ripngd.conf
-    sudo touch /etc/frr/pimd.conf
-    sudo touch /etc/frr/ldpd.conf
-    sudo chown frr:frr /etc/frr/
-    sudo touch /etc/frr/vtysh.conf
-    sudo chown frr:frrvty /etc/frr/vtysh.conf
-    sudo chmod 640 /etc/frr/*.conf
+    sudo install -m 755 -o frr -g frr -d /var/log/frr
+    sudo install -m 775 -o frr -g frrvty -d /etc/frr
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
+    sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
 
 ### Enable IP & IPv6 forwarding
 
@@ -131,4 +129,4 @@ other settings)
     #  based on Router Advertisements for this host
     net.ipv6.conf.all.forwarding=1
 
-**Reboot** or use `sysctl` to apply the same config to the running system
+**Reboot** or use `sysctl -p` to apply the same config to the running system
index 33ef896a9ad68e73f7684c5ca5866d0b61fac096..5da423affc5cc827525f59813c003b4cbc4850ca 100644 (file)
@@ -25,8 +25,9 @@ any packages**
 
     sudo groupadd -g 92 frr
     sudo groupadd -r -g 85 frrvty
-    sudo adduser --system --ingroup frr --groups frrvty --home /var/run/frr/ \
+    sudo adduser --system --ingroup frr --home /var/run/frr/ \
        --gecos "FRR suite" --shell /sbin/nologin frr
+    sudo usermod -a -G frrvty frr
 
 ### Download Source, configure and compile it
 (You may prefer different options on configure statement. These are just 
@@ -53,6 +54,7 @@ an example.)
         --enable-rtadv \
         --enable-tcp-zebra \
         --enable-fpm \
+        --enable-ldpd \
         --with-pkg-git-version \
         --with-pkg-extra-version=-MyOwnFRRVersion   
     make
@@ -61,21 +63,19 @@ an example.)
 
 ### Create empty FRR configuration files
 
-    sudo mkdir /var/log/frr
-    sudo chown frr:frr /var/log/frr
-    sudo mkdir /etc/frr
-    sudo touch /etc/frr/zebra.conf
-    sudo touch /etc/frr/bgpd.conf
-    sudo touch /etc/frr/ospfd.conf
-    sudo touch /etc/frr/ospf6d.conf
-    sudo touch /etc/frr/isisd.conf
-    sudo touch /etc/frr/ripd.conf
-    sudo touch /etc/frr/ripngd.conf
-    sudo touch /etc/frr/pimd.conf
-    sudo chown frr:frr /etc/frr/
-    sudo touch /etc/frr/vtysh.conf
-    sudo chown frr:frrvty /etc/frr/vtysh.conf
-    sudo chmod 640 /etc/frr/*.conf
+    sudo install -m 755 -o frr -g frr -d /var/log/frr
+    sudo install -m 775 -o frr -g frrvty -d /etc/frr
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf    
+    sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
 
 ### Enable IP & IPv6 forwarding
 
@@ -90,4 +90,4 @@ other settings)
     #  based on Router Advertisements for this host
     net.ipv6.conf.all.forwarding=1
 
-**Reboot** or use `sysctl` to apply the same config to the running system
+**Reboot** or use `sysctl -p` to apply the same config to the running system
index 18724859fb0a5422547da9dcf328b09613e05c3c..70a8159cc1d09cef7fa56d0435c16f63e26928e9 100644 (file)
@@ -26,8 +26,9 @@ any packages**
 
     sudo groupadd -g 92 frr
     sudo groupadd -r -g 85 frrvty
-    sudo adduser --system --ingroup frr --groups frrvty --home /var/run/frr/ \
+    sudo adduser --system --ingroup frr --home /var/run/frr/ \
        --gecos "FRR suite" --shell /sbin/nologin frr
+    sudo usermod -a -G frrvty frr
 
 ### Download Source, configure and compile it
 (You may prefer different options on configure statement. These are just 
@@ -62,22 +63,19 @@ an example.)
 
 ### Create empty FRR configuration files
 
-    sudo mkdir /var/log/frr
-    sudo chown frr:frr /var/log/frr
-    sudo mkdir /etc/frr
-    sudo touch /etc/frr/zebra.conf
-    sudo touch /etc/frr/bgpd.conf
-    sudo touch /etc/frr/ospfd.conf
-    sudo touch /etc/frr/ospf6d.conf
-    sudo touch /etc/frr/isisd.conf
-    sudo touch /etc/frr/ripd.conf
-    sudo touch /etc/frr/ripngd.conf
-    sudo touch /etc/frr/pimd.conf
-    sudo touch /etc/frr/ldpd.conf
-    sudo chown frr:frr /etc/frr/
-    sudo touch /etc/frr/vtysh.conf
-    sudo chown frr:frrvty /etc/frr/vtysh.conf
-    sudo chmod 640 /etc/frr/*.conf
+    sudo install -m 755 -o frr -g frr -d /var/log/frr
+    sudo install -m 775 -o frr -g frrvty -d /etc/frr
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
+    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf    
+    sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
 
 ### Enable IP & IPv6 forwarding
 
@@ -111,4 +109,4 @@ Add the following lines to `/etc/modules-load.d/modules.conf`:
     mpls-router
     mpls-iptunnel
 
-**Reboot** or use `sysctl` to apply the same config to the running system
+**Reboot** or use `sysctl -p` to apply the same config to the running system
index b34f3168449fc9df26bca05f5505eced8caca4a4..d989928b8f394678032884e662a03c15937b44d3 100644 (file)
@@ -218,18 +218,14 @@ routing utility.  It contains @command{ifconfig}, @command{route},
 
 After configuring the software, you will need to compile it for your
 system. Simply issue the command @command{make} in the root of the source
-directory and the software will be compiled. If you have *any* problems
-at this stage, be certain to send a bug report @xref{Bug Reports}.
+directory and the software will be compiled. Cliff Note versions of
+different compilation examples can be found in the doc/Building_FRR_on_XXX.md
+files.  If you have *any* problems at this stage, be certain to send a
+bug report @xref{Bug Reports}.
 
 @example
-% ./configure
-.
-.
-.
-./configure output
-.
-.
-.
+% ./bootstrap.sh
+% ./configure <appropriate to your system>
 % make
 @end example
 @c A - End of node, Building the Software
index deec1757c28cf84049ceca2468c969f864cb0093..c020d193a12515b45671ae12c9cb6ff44ee01c84 100644 (file)
@@ -23,6 +23,9 @@
  */
 
 %{
+/* ignore harmless bug in old versions of flex */
+#pragma GCC diagnostic ignored "-Wsign-compare"
+
 #include "command_parse.h"
 
 #define YY_USER_ACTION yylloc->last_column += yyleng;
index 01c338f1773a6b8ee8687de3dd972d3485643190..f85994c9a889700931458ff9d243e2f2a1babf17 100644 (file)
@@ -254,6 +254,7 @@ DEFUN (distribute_list,
        distribute_list_cmd,
        "distribute-list [prefix] WORD <in|out> [WORD]",
        "Filter networks in routing updates\n"
+       "Specify a prefix\n"
        "Access-list name\n"
        "Filter incoming routing updates\n"
        "Filter outgoing routing updates\n"
@@ -316,7 +317,9 @@ DEFUN (no_distribute_list,
        no_distribute_list_cmd,
        "no [ipv6] distribute-list [prefix] WORD <in|out> [WORD]",
        NO_STR
+       "IPv6\n"
        "Filter networks in routing updates\n"
+       "Specify a prefix\n"
        "Access-list name\n"
        "Filter incoming routing updates\n"
        "Filter outgoing routing updates\n"
index 64f8be2ca6fbc4512ee24b1d14d1abdef44e1837..de83e14f0eb699c49ecf60371e7bd8e188025a92 100644 (file)
@@ -34,6 +34,7 @@ DEFINE_HOOK(frr_late_init, (struct thread_master *tm), (tm))
 
 const char frr_sysconfdir[] = SYSCONFDIR;
 const char frr_vtydir[] = DAEMON_VTY_DIR;
+const char frr_moduledir[] = MODULE_PATH;
 
 char config_default[256];
 static char pidfile_default[256];
@@ -61,7 +62,8 @@ static void opt_extend(const struct optspec *os)
 }
 
 
-#define OPTION_VTYSOCK 1000
+#define OPTION_VTYSOCK   1000
+#define OPTION_MODULEDIR 1002
 
 static const struct option lo_always[] = {
        { "help",        no_argument,       NULL, 'h' },
@@ -69,6 +71,7 @@ static const struct option lo_always[] = {
        { "daemon",      no_argument,       NULL, 'd' },
        { "module",      no_argument,       NULL, 'M' },
        { "vty_socket",  required_argument, NULL, OPTION_VTYSOCK },
+       { "moduledir",   required_argument, NULL, OPTION_MODULEDIR },
        { NULL }
 };
 static const struct optspec os_always = {
@@ -77,7 +80,8 @@ static const struct optspec os_always = {
        "  -v, --version      Print program version\n"
        "  -d, --daemon       Runs in daemon mode\n"
        "  -M, --module       Load specified module\n"
-       "      --vty_socket   Override vty socket path\n",
+       "      --vty_socket   Override vty socket path\n"
+       "      --moduledir    Override modules directory\n",
        lo_always
 };
 
@@ -193,6 +197,7 @@ struct option_chain {
        struct option_chain *next;
        const char *arg;
 };
+
 static struct option_chain *modules = NULL, **modnext = &modules;
 static int errors = 0;
 
@@ -277,6 +282,14 @@ static int frr_opt(int opt)
                }
                di->vty_sock_path = optarg;
                break;
+       case OPTION_MODULEDIR:
+               if (di->module_path) {
+                       fprintf(stderr, "----moduledir option specified more than once!\n");
+                       errors++;
+                       break;
+               }
+               di->module_path = optarg;
+               break;
        case 'u':
                if (di->flags & FRR_NO_PRIVSEP)
                        return 1;
@@ -319,6 +332,8 @@ struct thread_master *frr_init(void)
        struct option_chain *oc;
        struct frrmod_runtime *module;
        char moderr[256];
+       const char *dir;
+       dir = di->module_path ? di->module_path : frr_moduledir;
 
        srandom(time(NULL));
 
@@ -331,7 +346,7 @@ struct thread_master *frr_init(void)
        frrmod_init(di->module);
        while (modules) {
                modules = (oc = modules)->next;
-               module = frrmod_load(oc->arg, moderr, sizeof(moderr));
+               module = frrmod_load(oc->arg, dir, moderr, sizeof(moderr));
                if (!module) {
                        fprintf(stderr, "%s\n", moderr);
                        exit(1);
index a40fc34892616a41afeec0ec12692de089f51343..0cc7ad564b123f46f96c2b2843a1a44944773af1 100644 (file)
@@ -52,6 +52,7 @@ struct frr_daemon_info {
        const char *config_file;
        const char *pid_file;
        const char *vty_path;
+       const char *module_path;
 
        const char *proghelp;
        void (*printhelp)(FILE *target);
@@ -107,5 +108,6 @@ extern void frr_run(struct thread_master *master);
 extern char config_default[256];
 extern const char frr_sysconfdir[];
 extern const char frr_vtydir[];
+extern const char frr_moduledir[];
 
 #endif /* _ZEBRA_FRR_H */
index 4ebe3c0da2abb48e5dd891076b7de9148f327ab0..c7dd5538cd9cf5b9e5921ea756c5837629388bf4 100644 (file)
@@ -69,7 +69,7 @@ void frrmod_init(struct frrmod_runtime *modinfo)
 }
 
 struct frrmod_runtime *frrmod_load(const char *spec,
-               char *err, size_t err_len)
+               const char *dir, char *err, size_t err_len)
 {
        void *handle = NULL;
        char name[PATH_MAX], fullpath[PATH_MAX], *args;
@@ -84,12 +84,12 @@ struct frrmod_runtime *frrmod_load(const char *spec,
        if (!strchr(name, '/')) {
                if (!handle && execname) {
                        snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so",
-                                       MODULE_PATH, execname, name);
+                                       dir, execname, name);
                        handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
                }
                if (!handle) {
                        snprintf(fullpath, sizeof(fullpath), "%s/%s.so",
-                                       MODULE_PATH, name);
+                                       dir, name);
                        handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
                }
        }
index cb66e6097697a4395c85d806f43678d3cab28034..01819f91e120c6417f9ecd98f372023e49bca352 100644 (file)
@@ -95,7 +95,7 @@ extern struct frrmod_runtime *frrmod_list;
 
 extern void frrmod_init(struct frrmod_runtime *modinfo);
 extern struct frrmod_runtime *frrmod_load(const char *spec,
-               char *err, size_t err_len);
+               const char *dir, char *err, size_t err_len);
 #if 0
 /* not implemented yet */
 extern void frrmod_unload(struct frrmod_runtime *module);
index 0f870564dab7a032d4a77d63b3cb1746f68e8f86..fa502b462ae4d65adb936b33511979a47be56c01 100644 (file)
@@ -188,3 +188,11 @@ pqueue_remove_at (int index, struct pqueue *queue)
       trickle_down (index, queue);
     }
 }
+
+void
+pqueue_remove (void *data, struct pqueue *queue)
+{
+  for (int i = 0; i < queue->size; i++)
+    if (queue->array[i] == data)
+      pqueue_remove_at (i, queue);
+}
index 8bb6961d8641b295561a1ac2ff7d904ec4a07e71..b39fb92ee9829918695e02d2bc49be86d74800ec 100644 (file)
@@ -39,6 +39,7 @@ extern void pqueue_delete (struct pqueue *queue);
 extern void pqueue_enqueue (void *data, struct pqueue *queue);
 extern void *pqueue_dequeue (struct pqueue *queue);
 extern void pqueue_remove_at (int index, struct pqueue *queue);
+extern void pqueue_remove (void *data, struct pqueue *queue);
 
 extern void trickle_down (int index, struct pqueue *queue);
 extern void trickle_up (int index, struct pqueue *queue);
index decd4bb7db94319d81d1078e745fe46d08b342b2..767ab667e78e908eb44e8492caaac299ea241388 100644 (file)
@@ -769,6 +769,7 @@ zprivs_init(struct zebra_privs_t *zprivs)
         }
     }
 
+  zprivs_state.zsuid = geteuid(); /* initial uid */
   /* add groups only if we changed uid - otherwise skip */
   if ((ngroups) && (zprivs_state.zsuid != zprivs_state.zuid))
     {
index 71b95ae7dbadcc8e3e4cad14b7c28ae33eb5d264..d2a518631518a14cc921e2ab72d64817098b9c4b 100644 (file)
@@ -1486,7 +1486,9 @@ lm_label_manager_connect (struct zclient *zclient)
   vrf_id_t vrf_id;
   u_int16_t cmd;
 
-  zlog_debug ("Connecting to Label Manager");
+  if (zclient_debug)
+    zlog_debug ("Connecting to Label Manager");
+
   if (zclient->sock < 0)
     return -1;
 
@@ -1518,7 +1520,8 @@ lm_label_manager_connect (struct zclient *zclient)
       zclient->sock = -1;
       return -1;
     }
-  zlog_debug ("%s: Label manager connect request (%d bytes) sent", __func__, ret);
+  if (zclient_debug)
+    zlog_debug ("%s: Label manager connect request (%d bytes) sent", __func__, ret);
 
   /* read response */
   s = zclient->ibuf;
@@ -1532,8 +1535,9 @@ lm_label_manager_connect (struct zclient *zclient)
   }
   /* result */
   result = stream_getc(s);
-  zlog_debug ("%s: Label Manager connect response (%d bytes) received, result %u",
-              __func__, size, result);
+  if (zclient_debug)
+    zlog_debug ("%s: Label Manager connect response (%d bytes) received, result %u",
+                __func__, size, result);
 
   return (int)result;
 }
@@ -1564,7 +1568,9 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size,
   u_int16_t cmd;
   u_char response_keep;
 
-  zlog_debug ("Getting Label Chunk");
+  if (zclient_debug)
+    zlog_debug ("Getting Label Chunk");
+
   if (zclient->sock < 0)
     return -1;
 
@@ -1594,7 +1600,8 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size,
       zclient->sock = -1;
       return -1;
     }
-  zlog_debug ("%s: Label chunk request (%d bytes) sent", __func__, ret);
+  if (zclient_debug)
+    zlog_debug ("%s: Label chunk request (%d bytes) sent", __func__, ret);
 
   /* read response */
   s = zclient->ibuf;
@@ -1606,7 +1613,9 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size,
       zlog_err ("%s: Invalid Get Label Chunk Message Reply Header", __func__);
       return -1;
   }
-  zlog_debug ("%s: Label chunk response (%d bytes) received", __func__, size);
+  if (zclient_debug)
+    zlog_debug ("%s: Label chunk response (%d bytes) received", __func__, size);
+
   /* keep */
   response_keep = stream_getc(s);
   /* start and end labels */
@@ -1627,8 +1636,9 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size,
           return -1;
   }
 
-  zlog_debug ("Label Chunk assign: %u - %u (%u) ",
-              *start, *end, response_keep);
+  if (zclient_debug)
+    zlog_debug ("Label Chunk assign: %u - %u (%u) ",
+                *start, *end, response_keep);
 
   return 0;
 }
@@ -1647,7 +1657,9 @@ lm_release_label_chunk (struct zclient *zclient, uint32_t start, uint32_t end)
   int ret;
   struct stream *s;
 
-  zlog_debug ("Releasing Label Chunk");
+  if (zclient_debug)
+    zlog_debug ("Releasing Label Chunk");
+
   if (zclient->sock < 0)
     return -1;
 
index bbaa630cd5ec098e1a53ee0b0ca9ed84975fbc3e..58ad1675498da2c1af91be0fb8d0b584ea17eb3b 100644 (file)
@@ -393,6 +393,8 @@ void nhrp_interface_set_protection(struct interface *ifp, const char *profile, c
 
        if (nifp->ipsec_fallback_profile) free(nifp->ipsec_fallback_profile);
        nifp->ipsec_fallback_profile = fallback_profile ? strdup(fallback_profile) : NULL;
+
+       notifier_call(&nifp->notifier_list, NOTIFY_INTERFACE_ADDRESS_CHANGED);
 }
 
 void nhrp_interface_set_source(struct interface *ifp, const char *ifname)
index 10245d308a509845e71c1b2433f99f22c105977c..555c0d1de1fdd8fe72e78aed3d0a4c5f4ddd8320 100644 (file)
@@ -18,19 +18,6 @@ DEFINE_MTYPE_STATIC(NHRPD, NHRP_NHS, "NHRP next hop server")
 DEFINE_MTYPE_STATIC(NHRPD, NHRP_REGISTRATION, "NHRP registration entries")
 
 static int nhrp_nhs_resolve(struct thread *t);
-
-struct nhrp_registration {
-       struct list_head reglist_entry;
-       struct thread *t_register;
-       struct nhrp_nhs *nhs;
-       struct nhrp_reqid reqid;
-       unsigned int timeout;
-       unsigned mark : 1;
-       union sockunion proto_addr;
-       struct nhrp_peer *peer;
-       struct notifier_block peer_notifier;
-};
-
 static int nhrp_reg_send_req(struct thread *t);
 
 static void nhrp_reg_reply(struct nhrp_reqid *reqid, void *arg)
@@ -370,3 +357,18 @@ void nhrp_nhs_terminate(void)
                }
        }
 }
+
+void nhrp_nhs_foreach(struct interface *ifp, afi_t afi, void (*cb)(struct nhrp_nhs *, struct nhrp_registration *, void *), void *ctx)
+{
+       struct nhrp_interface *nifp = ifp->info;
+       struct nhrp_nhs *nhs;
+       struct nhrp_registration *reg;
+
+       list_for_each_entry(nhs, &nifp->afi[afi].nhslist_head, nhslist_entry) {
+               if (!list_empty(&nhs->reglist_head)) {
+                       list_for_each_entry(reg, &nhs->reglist_head, reglist_entry)
+                               cb(nhs, reg, ctx);
+               } else
+                       cb(nhs, 0, ctx);
+       }
+}
index 4c1d97a4898e51a9988f5bb91e1fb05ff437b57f..3cc91a90832886483017a414b666482c502d081d 100644 (file)
@@ -250,6 +250,8 @@ int nhrp_peer_check(struct nhrp_peer *p, int establish)
                return 0;
        if (p->requested)
                return 0;
+       if (!nifp->ipsec_profile)
+               return 0;
        if (sockunion_family(&vc->local.nbma) == AF_UNSPEC)
                return 0;
 
@@ -730,6 +732,15 @@ static void nhrp_packet_debug(struct zbuf *zb, const char *dir)
                reply ? buf[0] : buf[1]);
 }
 
+static int proto2afi(uint16_t proto)
+{
+       switch (proto) {
+       case ETH_P_IP: return AFI_IP;
+       case ETH_P_IPV6: return AFI_IP6;
+       }
+       return AF_UNSPEC;
+}
+
 struct nhrp_route_info {
        int local;
        struct interface *ifp;
@@ -749,7 +760,7 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb)
        const char *info = NULL;
        union sockunion *target_addr;
        unsigned paylen, extoff, extlen, realsize;
-       afi_t afi;
+       afi_t nbma_afi, proto_afi;
 
        debugf(NHRP_DEBUG_KERNEL, "PACKET: Recv %s -> %s",
                sockunion2str(&vc->remote.nbma, buf[0], sizeof buf[0]),
@@ -777,20 +788,21 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb)
        pp.hdr = hdr;
        pp.peer = p;
 
-       afi = htons(hdr->afnum);
+       nbma_afi = htons(hdr->afnum);
+       proto_afi = proto2afi(htons(hdr->protocol_type));
        if (hdr->type > ZEBRA_NUM_OF(packet_types) ||
            hdr->version != NHRP_VERSION_RFC2332 ||
-           afi >= AFI_MAX ||
+           nbma_afi >= AFI_MAX || proto_afi == AF_UNSPEC ||
            packet_types[hdr->type].type == PACKET_UNKNOWN ||
            htons(hdr->packet_size) > realsize) {
-               zlog_info("From %s: error: packet type %d, version %d, AFI %d, size %d (real size %d)",
+               zlog_info("From %s: error: packet type %d, version %d, AFI %d, proto %x, size %d (real size %d)",
                           sockunion2str(&vc->remote.nbma, buf[0], sizeof buf[0]),
-                          (int) hdr->type, (int) hdr->version, (int) afi,
-                          (int) htons(hdr->packet_size),
-                          (int) realsize);
+                          (int) hdr->type, (int) hdr->version,
+                          (int) nbma_afi, (int) htons(hdr->protocol_type),
+                          (int) htons(hdr->packet_size), (int) realsize);
                goto drop;
        }
-       pp.if_ad = &((struct nhrp_interface *)ifp->info)->afi[afi];
+       pp.if_ad = &((struct nhrp_interface *)ifp->info)->afi[proto_afi];
 
        extoff = htons(hdr->extension_offset);
        if (extoff) {
@@ -806,7 +818,7 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb)
        extlen = zbuf_used(zb);
        zbuf_init(&pp.extensions, zbuf_pulln(zb, extlen), extlen, extlen);
 
-       if (!nifp->afi[afi].network_id) {
+       if (!nifp->afi[proto_afi].network_id) {
                info = "nhrp not enabled";
                goto drop;
        }
index 2e3164410c02bc0e9f68af5516f02cb57b698faf..9b8463fb548c4ad2e0d78775250f27acc5412b17 100644 (file)
@@ -504,6 +504,32 @@ DEFUN(if_nhrp_map, if_nhrp_map_cmd,
        return CMD_SUCCESS;
 }
 
+DEFUN(if_no_nhrp_map, if_no_nhrp_map_cmd,
+       "no " AFI_CMD " nhrp map <A.B.C.D|X:X::X:X>",
+       NO_STR
+       AFI_STR
+       NHRP_STR
+       "Nexthop Server configuration\n"
+       "IPv4 protocol address\n"
+       "IPv6 protocol address\n")
+{
+       VTY_DECLVAR_CONTEXT(interface,ifp);
+       afi_t afi = cmd_to_afi(argv[1]);
+       union sockunion proto_addr;
+       struct nhrp_cache *c;
+
+       if (str2sockunion(argv[4]->arg, &proto_addr) < 0 ||
+           afi2family(afi) != sockunion_family(&proto_addr))
+               return nhrp_vty_return(vty, NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH);
+
+       c = nhrp_cache_get(ifp, &proto_addr, 0);
+       if (!c || !c->map)
+               return nhrp_vty_return(vty, NHRP_ERR_ENTRY_NOT_FOUND);
+
+       nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL);
+       return CMD_SUCCESS;
+}
+
 DEFUN(if_nhrp_nhs, if_nhrp_nhs_cmd,
        AFI_CMD " nhrp nhs <A.B.C.D|X:X::X:X|dynamic> nbma <A.B.C.D|FQDN>",
        AFI_STR
@@ -592,6 +618,56 @@ static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx)
                VTY_NEWLINE);
 }
 
+static void show_ip_nhrp_nhs(struct nhrp_nhs *n, struct nhrp_registration *reg, void *pctx)
+{
+       struct info_ctx *ctx = pctx;
+       struct vty *vty = ctx->vty;
+       char buf[2][SU_ADDRSTRLEN];
+
+       if (!ctx->count) {
+               vty_out(vty, "%-8s %-24s %-16s %-16s%s",
+                       "Iface",
+                       "FQDN",
+                       "NBMA",
+                       "Protocol",
+                       VTY_NEWLINE);
+       }
+       ctx->count++;
+
+       vty_out(vty, "%-8s %-24s %-16s %-16s%s",
+               n->ifp->name,
+               n->nbma_fqdn,
+               (reg && reg->peer) ? sockunion2str(&reg->peer->vc->remote.nbma, buf[0], sizeof buf[0]) : "-",
+               sockunion2str(reg ? &reg->proto_addr : &n->proto_addr, buf[1], sizeof buf[1]),
+               VTY_NEWLINE);
+}
+
+static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx)
+{
+       struct info_ctx *ctx = pctx;
+       struct nhrp_cache *c;
+       struct vty *vty = ctx->vty;
+       char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN];
+
+       if (!ctx->count) {
+               vty_out(vty, "%-8s %-24s %-24s %s%s",
+                       "Type",
+                       "Prefix",
+                       "Via",
+                       "Identity",
+                       VTY_NEWLINE);
+       }
+       ctx->count++;
+
+       c = s->cache;
+       vty_out(ctx->vty, "%-8s %-24s %-24s %s%s",
+               nhrp_cache_type_str[s->type],
+               prefix2str(s->p, buf1, sizeof buf1),
+               c ? sockunion2str(&c->remote_addr, buf2, sizeof buf2) : "",
+               (c && c->cur.peer) ? c->cur.peer->vc->remote.id : "",
+               VTY_NEWLINE);
+}
+
 static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx)
 {
        struct info_ctx *ctx = pctx;
@@ -631,38 +707,13 @@ static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx)
        vty_out(ctx->vty, "%s", VTY_NEWLINE);
 }
 
-static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx)
-{
-       struct info_ctx *ctx = pctx;
-       struct nhrp_cache *c;
-       struct vty *vty = ctx->vty;
-       char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN];
-
-       if (!ctx->count) {
-               vty_out(vty, "%-8s %-24s %-24s %s%s",
-                       "Type",
-                       "Prefix",
-                       "Via",
-                       "Identity",
-                       VTY_NEWLINE);
-       }
-       ctx->count++;
-
-       c = s->cache;
-       vty_out(ctx->vty, "%-8s %-24s %-24s %s%s",
-               nhrp_cache_type_str[s->type],
-               prefix2str(s->p, buf1, sizeof buf1),
-               c ? sockunion2str(&c->remote_addr, buf2, sizeof buf2) : "",
-               (c && c->cur.peer) ? c->cur.peer->vc->remote.id : "",
-               VTY_NEWLINE);
-}
-
 DEFUN(show_ip_nhrp, show_ip_nhrp_cmd,
-       "show " AFI_CMD " nhrp [cache|shortcut|opennhrp]",
+       "show " AFI_CMD " nhrp [cache|nhs|shortcut|opennhrp]",
        SHOW_STR
        AFI_STR
        "NHRP information\n"
        "Forwarding cache information\n"
+       "Next hop server information\n"
        "Shortcut information\n"
        "opennhrpctl style cache dump\n")
 {
@@ -676,13 +727,16 @@ DEFUN(show_ip_nhrp, show_ip_nhrp_cmd,
        if (argc <= 3 || argv[3]->text[0] == 'c') {
                for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp))
                        nhrp_cache_foreach(ifp, show_ip_nhrp_cache, &ctx);
-       } else if (argv[3]->text[0] == 'o') {
+       } else if (argv[3]->text[0] == 'n') {
+               for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp))
+                       nhrp_nhs_foreach(ifp, ctx.afi, show_ip_nhrp_nhs, &ctx);
+       } else if (argv[3]->text[0] == 's') {
+               nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx);
+       } else {
                vty_out(vty, "Status: ok%s%s", VTY_NEWLINE, VTY_NEWLINE);
                ctx.count++;
                for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp))
                        nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx);
-       } else {
-               nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx);
        }
 
        if (!ctx.count) {
@@ -919,6 +973,7 @@ void nhrp_config_init(void)
        install_element(INTERFACE_NODE, &if_nhrp_reg_flags_cmd);
        install_element(INTERFACE_NODE, &if_no_nhrp_reg_flags_cmd);
        install_element(INTERFACE_NODE, &if_nhrp_map_cmd);
+       install_element(INTERFACE_NODE, &if_no_nhrp_map_cmd);
        install_element(INTERFACE_NODE, &if_nhrp_nhs_cmd);
        install_element(INTERFACE_NODE, &if_no_nhrp_nhs_cmd);
 }
index cd2b0d5580f6f9894c988c9a022fa76d04ec7937..9a4f26d57710999a0639ef6c18bfbe29f8185d36 100644 (file)
@@ -254,6 +254,18 @@ struct nhrp_nhs {
        struct list_head reglist_head;
 };
 
+struct nhrp_registration {
+       struct list_head reglist_entry;
+       struct thread *t_register;
+       struct nhrp_nhs *nhs;
+       struct nhrp_reqid reqid;
+       unsigned int timeout;
+       unsigned mark : 1;
+       union sockunion proto_addr;
+       struct nhrp_peer *peer;
+       struct notifier_block peer_notifier;
+};
+
 #define NHRP_IFF_SHORTCUT              0x0001
 #define NHRP_IFF_REDIRECT              0x0002
 #define NHRP_IFF_REG_NO_UNIQUE         0x0100
@@ -311,6 +323,7 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr,
 int nhrp_nhs_del(struct interface *ifp, afi_t afi, union sockunion *proto_addr, const char *nbma_fqdn);
 int nhrp_nhs_free(struct nhrp_nhs *nhs);
 void nhrp_nhs_terminate(void);
+void nhrp_nhs_foreach(struct interface *ifp, afi_t afi, void (*cb)(struct nhrp_nhs *, struct nhrp_registration *, void *), void *ctx);
 
 void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp);
 void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix *p, struct interface *ifp, const union sockunion *nexthop, uint32_t mtu);
index 507dd14a9c19553037636a276c7199e75148dbd5..5491bacf7c329d7cf8f7f9cbbdbbdc9394c6e615 100644 (file)
@@ -220,6 +220,23 @@ static void parse_sa_message(
        }
 }
 
+static void parse_cmd_response(
+       struct vici_message_ctx *ctx,
+       enum vici_type_t msgtype,
+       const struct blob *key, const struct blob *val)
+{
+       char buf[512];
+
+       switch (msgtype) {
+       case VICI_KEY_VALUE:
+               if (blob_equal(key, "errmsg") && blob2buf(val, buf, sizeof(buf)))
+                       zlog_err("VICI: strongSwan: %s", buf);
+               break;
+       default:
+               break;
+       }
+}
+
 static void vici_recv_sa(struct vici_conn *vici, struct zbuf *msg, int event)
 {
        char buf[32];
@@ -265,11 +282,14 @@ static void vici_recv_message(struct vici_conn *vici, struct zbuf *msg)
                else if (blob_equal(&name, "child-state-destroying"))
                        vici_recv_sa(vici, msg, 2);
                break;
+       case VICI_CMD_RESPONSE:
+               vici_parse_message(vici, msg, parse_cmd_response, 0);
+               break;
        case VICI_EVENT_UNKNOWN:
+       case VICI_CMD_UNKNOWN:
                zlog_err("VICI: StrongSwan does not support mandatory events (unpatched?)");
                break;
        case VICI_EVENT_CONFIRM:
-       case VICI_CMD_RESPONSE:
                break;
        default:
                zlog_notice("VICI: Unrecognized message type %d", msgtype);
@@ -449,9 +469,9 @@ void vici_request_vc(const char *profile, union sockunion *src, union sockunion
        vici_submit_request(
                vici, "initiate",
                VICI_KEY_VALUE, "child", strlen(profile), profile,
-               VICI_KEY_VALUE, "timeout", 2, "-1",
-               VICI_KEY_VALUE, "async", 1, "1",
-               VICI_KEY_VALUE, "init-limits", 1, prio ? "0" : "1",
+               VICI_KEY_VALUE, "timeout", (size_t) 2, "-1",
+               VICI_KEY_VALUE, "async", (size_t) 1, "1",
+               VICI_KEY_VALUE, "init-limits", (size_t) 1, prio ? "0" : "1",
                VICI_KEY_VALUE, "my-host", strlen(buf[0]), buf[0],
                VICI_KEY_VALUE, "other-host", strlen(buf[1]), buf[1],
                VICI_END);
index f2a1c8c2ecfbc65f0a88018f11f3645b920e6926..e592d3c4f9cde60e587cc7a4e069e007861a1d40 100644 (file)
@@ -315,6 +315,14 @@ DEFUN (no_router_ospf6,
        ROUTER_STR
        OSPF6_STR)
 {
+  if (ospf6 == NULL)
+    vty_out (vty, "OSPFv3 is not configured%s", VNL);
+  else
+    {
+      ospf6_delete (ospf6);
+      ospf6 = NULL;
+    }
+
   /* return to config node . */
   VTY_PUSH_CONTEXT_NULL(CONFIG_NODE);
 
index 49474df82626649fbb32591fe1d3354582bd6a8e..b4c456e0aa8532a62d09bb3ef2ee4be3d417dae3 100644 (file)
@@ -3557,7 +3557,7 @@ show_ip_ospf_interface_common (struct vty *vty, struct ospf *ospf, int argc,
                  VTY_NEWLINE, VTY_NEWLINE);
     }
 
-  if (argc == (iface_argv + 1))
+  if (argc == iface_argv)
     {
       /* Show All Interfaces.*/
       for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
@@ -3570,25 +3570,6 @@ show_ip_ospf_interface_common (struct vty *vty, struct ospf *ospf, int argc,
             }
         }
     }
-  else if (argv[iface_argv] && strcmp(argv[iface_argv]->arg, "json") == 0)
-    {
-      if (!use_json)
-       {
-         json = json_object_new_object();
-         json_interface_sub = json_object_new_object ();
-         use_json = 1;
-       }
-      /* Show All Interfaces. */
-      for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
-        {
-          if (ospf_oi_count(ifp))
-            {
-              show_ip_ospf_interface_sub (vty, ospf, ifp, json_interface_sub, use_json);
-             if (use_json)
-               json_object_object_add(json, ifp->name, json_interface_sub);
-           }
-       }
-    }
   else
     {
       /* Interface name is specified. */
@@ -3634,7 +3615,10 @@ DEFUN (show_ip_ospf_interface,
   if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running)
     return CMD_SUCCESS;
 
-  return show_ip_ospf_interface_common(vty, ospf, argc, argv, 0, uj);
+  if (uj)
+    argc--;
+
+  return show_ip_ospf_interface_common(vty, ospf, argc, argv, 4, uj);
 }
 
 DEFUN (show_ip_ospf_instance_interface,
@@ -3657,7 +3641,10 @@ DEFUN (show_ip_ospf_instance_interface,
   if ((ospf = ospf_lookup_instance (instance)) == NULL || !ospf->oi_running)
     return CMD_SUCCESS;
 
-  return show_ip_ospf_interface_common(vty, ospf, argc, argv, 1, uj);
+  if (uj)
+    argc--;
+
+  return show_ip_ospf_interface_common(vty, ospf, argc, argv, 5, uj);
 }
 
 static void
index 3c5a16ec68d38233641c287ca19fc573af8284bd..53a080a3ab308249c360806aeeee59200fc83269 100644 (file)
@@ -26,6 +26,8 @@
 #include "prefix.h"
 #include "zclient.h"
 #include "plist.h"
+#include "hash.h"
+#include "nexthop.h"
 
 #include "pimd.h"
 #include "pim_mroute.h"
@@ -55,6 +57,7 @@
 #include "pim_zlookup.h"
 #include "pim_msdp.h"
 #include "pim_ssm.h"
+#include "pim_nht.h"
 
 static struct cmd_node pim_global_node = {
   PIM_NODE,
@@ -817,6 +820,7 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch
     mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd);
 
     if (uj) {
+      char pbuf[PREFIX2STR_BUFFER];
       json_row = json_object_new_object();
       json_object_pim_ifp_add(json_row, ifp);
 
@@ -828,7 +832,10 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch
 
         sec_list = json_object_new_array();
         for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) {
-          json_object_array_add(sec_list, json_object_new_string(inet_ntoa(sec_addr->addr)));
+          json_object_array_add(sec_list,
+                                json_object_new_string(prefix2str(&sec_addr->addr,
+                                                                 pbuf,
+                                                                 sizeof(pbuf))));
         }
         json_object_object_add(json_row, "secondaryAddressList", sec_list);
       }
@@ -919,11 +926,14 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch
         vty_out(vty, "Use Source : %s%s", inet_ntoa(pim_ifp->update_source), VTY_NEWLINE);
       }
       if (pim_ifp->sec_addr_list) {
+        char pbuf[PREFIX2STR_BUFFER];
         vty_out(vty, "Address    : %s (primary)%s",
-                                    inet_ntoa(ifaddr), VTY_NEWLINE);
+                inet_ntoa(ifaddr), VTY_NEWLINE);
         for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) {
           vty_out(vty, "             %s%s",
-                                    inet_ntoa(sec_addr->addr), VTY_NEWLINE);
+                  prefix2str(&sec_addr->addr,
+                            pbuf,
+                            sizeof(pbuf)), VTY_NEWLINE);
         }
       } else {
         vty_out(vty, "Address    : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE);
@@ -1040,6 +1050,7 @@ static void pim_show_interfaces(struct vty *vty, u_char uj)
   struct pim_upstream *up;
   int fhr = 0;
   int pim_nbrs = 0;
+  int pim_ifchannels = 0;
   json_object *json = NULL;
   json_object *json_row = NULL;
   json_object *json_tmp;
@@ -1056,6 +1067,7 @@ static void pim_show_interfaces(struct vty *vty, u_char uj)
       continue;
 
     pim_nbrs = pim_ifp->pim_neighbor_list->count;
+    pim_ifchannels = pim_ifp->pim_ifchannel_list->count;
     fhr = 0;
 
     for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up))
@@ -1066,6 +1078,7 @@ static void pim_show_interfaces(struct vty *vty, u_char uj)
     json_row = json_object_new_object();
     json_object_pim_ifp_add(json_row, ifp);
     json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
+    json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
     json_object_int_add(json_row, "firstHopRouter", fhr);
     json_object_string_add(json_row, "pimDesignatedRouter", inet_ntoa(pim_ifp->pim_dr_addr));
 
@@ -1078,7 +1091,7 @@ static void pim_show_interfaces(struct vty *vty, u_char uj)
   if (uj) {
     vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
   } else {
-    vty_out(vty, "Interface  State          Address  PIM Nbrs           PIM DR  FHR%s", VTY_NEWLINE);
+    vty_out(vty, "Interface  State          Address  PIM Nbrs           PIM DR  FHR IfChannels%s", VTY_NEWLINE);
 
     json_object_object_foreach(json, key, val) {
       vty_out(vty, "%-9s  ", key);
@@ -1100,7 +1113,10 @@ static void pim_show_interfaces(struct vty *vty, u_char uj)
       }
 
       json_object_object_get_ex(val, "firstHopRouter", &json_tmp);
-      vty_out(vty, "%3d%s", json_object_get_int(json_tmp), VTY_NEWLINE);
+      vty_out(vty, "%3d  ", json_object_get_int(json_tmp));
+
+      json_object_object_get_ex(val, "pimIfChannels", &json_tmp);
+      vty_out(vty, "%9d%s", json_object_get_int(json_tmp), VTY_NEWLINE);
     }
   }
 
@@ -1608,13 +1624,9 @@ static void pim_show_neighbors_secondary(struct vty *vty)
                     neigh_src_str, sizeof(neigh_src_str));
 
       for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) {
-       char neigh_sec_str[INET_ADDRSTRLEN];
-
-       if (p->family != AF_INET)
-         continue;
+       char neigh_sec_str[PREFIX2STR_BUFFER];
 
-       pim_inet4_dump("<src?>", p->u.prefix4,
-                      neigh_sec_str, sizeof(neigh_sec_str));
+       prefix2str(p, neigh_sec_str, sizeof(neigh_sec_str));
 
        vty_out(vty, "%-9s %-15s %-15s %-15s%s",
                ifp->name,
@@ -2059,6 +2071,50 @@ static void pim_show_rpf(struct vty *vty, u_char uj)
   }
 }
 
+static int
+pim_print_pnc_cache_walkcb (struct hash_backet *backet, void *arg)
+{
+  struct pim_nexthop_cache *pnc = backet->data;
+  struct vty *vty = arg;
+  struct nexthop *nh_node = NULL;
+  ifindex_t first_ifindex;
+  struct interface *ifp = NULL;
+
+  if (!pnc)
+    return CMD_SUCCESS;
+
+  for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next)
+    {
+      first_ifindex = nh_node->ifindex;
+      ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT);
+
+      vty_out (vty, "%-15s ", inet_ntoa (pnc->rpf.rpf_addr.u.prefix4));
+      vty_out (vty, "%-14s ", ifp ? ifp->name : "NULL");
+      vty_out (vty, "%s ", inet_ntoa (nh_node->gate.ipv4));
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+static void
+pim_show_nexthop (struct vty *vty)
+{
+
+  if (pimg && !pimg->rpf_hash)
+    {
+      vty_out (vty, "no nexthop cache %s", VTY_NEWLINE);
+      return;
+    }
+
+  vty_out (vty, "Number of registered addresses: %lu %s",
+           pimg->rpf_hash->count, VTY_NEWLINE);
+  vty_out (vty, "Address         Interface      Nexthop%s", VTY_NEWLINE);
+  vty_out (vty, "-------------------------------------------%s", VTY_NEWLINE);
+
+  hash_walk (pimg->rpf_hash, pim_print_pnc_cache_walkcb, vty);
+
+}
+
 static void igmp_show_groups(struct vty *vty, u_char uj)
 {
   struct listnode  *ifnode;
@@ -2793,6 +2849,99 @@ DEFUN (show_ip_pim_rpf,
   return CMD_SUCCESS;
 }
 
+DEFUN (show_ip_pim_nexthop,
+       show_ip_pim_nexthop_cmd,
+       "show ip pim nexthop",
+       SHOW_STR
+       IP_STR
+       PIM_STR
+       "PIM cached nexthop rpf information\n")
+{
+  pim_show_nexthop (vty);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_pim_nexthop_lookup,
+       show_ip_pim_nexthop_lookup_cmd,
+       "show ip pim nexthop-lookup A.B.C.D A.B.C.D",
+       SHOW_STR
+       IP_STR
+       PIM_STR
+       "PIM cached nexthop rpf lookup\n"
+       "Source/RP address\n"
+       "Multicast Group address\n")
+{
+  struct pim_nexthop_cache pnc;
+  struct prefix nht_p;
+  int result = 0;
+  struct in_addr src_addr, grp_addr;
+  struct in_addr vif_source;
+  const char *addr_str, *addr_str1;
+  struct prefix grp;
+  struct pim_nexthop nexthop;
+  char nexthop_addr_str[PREFIX_STRLEN];
+  char grp_str[PREFIX_STRLEN];
+
+  addr_str = (const char *)argv[0];
+  result = inet_pton (AF_INET, addr_str, &src_addr);
+  if (result <= 0)
+    {
+      vty_out (vty, "Bad unicast address %s: errno=%d: %s%s",
+               addr_str, errno, safe_strerror (errno), VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (pim_is_group_224_4 (src_addr))
+    {
+      vty_out (vty, "Invalid argument. Expected Valid Source Address.%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  addr_str1 = (const char *)argv[1];
+  result = inet_pton (AF_INET, addr_str1, &grp_addr);
+  if (result <= 0)
+    {
+      vty_out (vty, "Bad unicast address %s: errno=%d: %s%s",
+               addr_str, errno, safe_strerror (errno), VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (!pim_is_group_224_4 (grp_addr))
+    {
+      vty_out (vty, "Invalid argument. Expected Valid Multicast Group Address.%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (!pim_rp_set_upstream_addr (&vif_source, src_addr, grp_addr))
+    return CMD_SUCCESS;
+
+  memset (&pnc, 0, sizeof (struct pim_nexthop_cache));
+  nht_p.family = AF_INET;
+  nht_p.prefixlen = IPV4_MAX_BITLEN;
+  nht_p.u.prefix4 = vif_source;
+  grp.family = AF_INET;
+  grp.prefixlen = IPV4_MAX_BITLEN;
+  grp.u.prefix4 = grp_addr;
+  memset (&nexthop, 0, sizeof (nexthop));
+
+  if ((pim_find_or_track_nexthop (&nht_p, NULL, NULL, &pnc)) == 1)
+    {
+      //Compute PIM RPF using Cached nexthop
+      pim_ecmp_nexthop_search (&pnc, &nexthop, &nht_p, &grp, 0);
+    }
+  else
+    pim_ecmp_nexthop_lookup (&nexthop, vif_source, &nht_p, &grp, 0);
+
+  pim_addr_dump ("<grp?>", &grp, grp_str, sizeof (grp_str));
+  pim_addr_dump ("<nexthop?>", &nexthop.mrib_nexthop_addr,
+                 nexthop_addr_str, sizeof (nexthop_addr_str));
+  vty_out (vty, "Group %s --- Nexthop %s Interface %s %s", grp_str,
+           nexthop_addr_str, nexthop.interface->name, VTY_NEWLINE);
+
+  return CMD_SUCCESS;
+}
+
 static void show_multicast_interfaces(struct vty *vty)
 {
   struct listnode  *node;
@@ -2871,15 +3020,17 @@ DEFUN (show_ip_multicast,
          PIM_MAX_USABLE_VIFS,
          VTY_NEWLINE);
 
-  vty_out(vty, "%s", VTY_NEWLINE);
-  vty_out(vty, "Upstream Join Timer: %d secs%s",
-         qpim_t_periodic,
-         VTY_NEWLINE);
-  vty_out(vty, "Join/Prune Holdtime: %d secs%s",
-         PIM_JP_HOLDTIME,
-         VTY_NEWLINE);
+  vty_out (vty, "%s", VTY_NEWLINE);
+  vty_out (vty, "Upstream Join Timer: %d secs%s",
+           qpim_t_periodic, VTY_NEWLINE);
+  vty_out (vty, "Join/Prune Holdtime: %d secs%s",
+           PIM_JP_HOLDTIME, VTY_NEWLINE);
+  vty_out (vty, "PIM ECMP: %s%s",
+           qpim_ecmp_enable ? "Enable" : "Disable", VTY_NEWLINE);
+  vty_out (vty, "PIM ECMP Rebalance: %s%s",
+           qpim_ecmp_rebalance_enable ? "Enable" : "Disable", VTY_NEWLINE);
 
-  vty_out(vty, "%s", VTY_NEWLINE);
+  vty_out (vty, "%s", VTY_NEWLINE);
 
   show_rpf_refresh_stats(vty, now, NULL);
 
@@ -3410,6 +3561,35 @@ pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const cha
   return CMD_SUCCESS;
 }
 
+DEFUN (ip_pim_spt_switchover_infinity,
+       ip_pim_spt_switchover_infinity_cmd,
+       "ip pim spt-switchover infinity-and-beyond",
+       IP_STR
+       PIM_STR
+       "SPT-Switchover\n"
+       "Never switch to SPT Tree\n")
+{
+  pimg->spt_switchover = PIM_SPT_INFINITY;
+
+  pim_upstream_remove_lhr_star_pimreg();
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_pim_spt_switchover_infinity,
+       no_ip_pim_spt_switchover_infinity_cmd,
+       "no ip pim spt-switchover infinity-and-beyond",
+       NO_STR
+       IP_STR
+       PIM_STR
+       "SPT_Switchover\n"
+       "Never switch to SPT Tree\n")
+{
+  pimg->spt_switchover = PIM_SPT_IMMEDIATE;
+
+  pim_upstream_add_lhr_star_pimreg();
+  return CMD_SUCCESS;
+}
+
 DEFUN (ip_pim_joinprune_time,
        ip_pim_joinprune_time_cmd,
        "ip pim join-prune-interval <60-600>",
@@ -3510,6 +3690,31 @@ DEFUN (no_ip_pim_packets,
   return CMD_SUCCESS;
 }
 
+DEFUN (ip_pim_v6_secondary,
+       ip_pim_v6_secondary_cmd,
+       "ip pim send-v6-secondary",
+       IP_STR
+       "pim multicast routing\n"
+       "Send v6 secondary addresses\n")
+{
+  pimg->send_v6_secondary = 1;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_pim_v6_secondary,
+       no_ip_pim_v6_secondary_cmd,
+       "no ip pim send-v6-secondary",
+       NO_STR
+       IP_STR
+       "pim multicast routing\n"
+       "Send v6 secondary addresses\n")
+{
+  pimg->send_v6_secondary = 0;
+
+  return CMD_SUCCESS;
+}
+
 DEFUN (ip_pim_rp,
        ip_pim_rp_cmd,
        "ip pim rp A.B.C.D [A.B.C.D/M]",
@@ -3577,10 +3782,10 @@ DEFUN (no_ip_pim_rp,
        "ip address of RP\n"
        "Group Address range to cover\n")
 {
-  int idx_ipv4 = 4;
+  int idx_ipv4 = 4, idx_group = 0;
 
-  if (argc == (idx_ipv4 + 1))
-    return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL);
+  if (argv_find (argv, argc, "A.B.C.D/M", &idx_group))
+    return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_group]->arg, NULL);
   else
     return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, NULL, NULL);
 }
@@ -3826,6 +4031,58 @@ DEFUN (no_ip_ssmpingd,
   return CMD_SUCCESS;
 }
 
+DEFUN (ip_pim_ecmp,
+       ip_pim_ecmp_cmd,
+       "ip pim ecmp",
+       IP_STR
+       "pim multicast routing\n"
+       "Enable PIM ECMP \n")
+{
+  qpim_ecmp_enable = 1;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_pim_ecmp,
+       no_ip_pim_ecmp_cmd,
+       "no ip pim ecmp",
+       NO_STR
+       IP_STR
+       "pim multicast routing\n"
+       "Disable PIM ECMP \n")
+{
+  qpim_ecmp_enable = 0;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (ip_pim_ecmp_rebalance,
+       ip_pim_ecmp_rebalance_cmd,
+       "ip pim ecmp rebalance",
+       IP_STR
+       "pim multicast routing\n"
+       "Enable PIM ECMP \n"
+       "Enable PIM ECMP Rebalance\n")
+{
+  qpim_ecmp_rebalance_enable = 1;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_pim_ecmp_rebalance,
+       no_ip_pim_ecmp_rebalance_cmd,
+       "no ip pim ecmp rebalance",
+       NO_STR
+       IP_STR
+       "pim multicast routing\n"
+       "Disable PIM ECMP \n"
+       "Disable PIM ECMP Rebalance\n")
+{
+  qpim_ecmp_rebalance_enable = 0;
+
+  return CMD_SUCCESS;
+}
+
 static int
 pim_cmd_igmp_start (struct vty *vty, struct interface *ifp)
 {
@@ -6149,13 +6406,16 @@ DEFUN (show_ip_msdp_sa_sg,
        "JavaScript Object Notation\n")
 {
   u_char uj = use_json(argc, argv);
-  if (uj)
-    argc--;
 
-  if (argc == 5)
-    ip_msdp_show_sa_sg(vty, argv[4]->arg, argv[5]->arg, uj);
-  else if (argc == 4)
-    ip_msdp_show_sa_addr(vty, argv[4]->arg, uj);
+  int idx = 0;
+  char *src_ip = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg : NULL;
+  char *grp_ip = idx < argc && argv_find (argv, argc, "A.B.C.D", &idx) ?
+                 argv[idx]->arg : NULL;
+
+  if (src_ip && grp_ip)
+    ip_msdp_show_sa_sg(vty, src_ip, grp_ip, uj);
+  else if (src_ip)
+    ip_msdp_show_sa_addr(vty, src_ip, uj);
   else
     ip_msdp_show_sa(vty, uj);
 
@@ -6181,16 +6441,24 @@ void pim_cmd_init()
   install_element (CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd);
   install_element (CONFIG_NODE, &ip_pim_register_suppress_cmd);
   install_element (CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
+  install_element (CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd);
+  install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
   install_element (CONFIG_NODE, &ip_pim_joinprune_time_cmd);
   install_element (CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
   install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd);
   install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd);
   install_element (CONFIG_NODE, &ip_pim_packets_cmd);
   install_element (CONFIG_NODE, &no_ip_pim_packets_cmd);
+  install_element (CONFIG_NODE, &ip_pim_v6_secondary_cmd);
+  install_element (CONFIG_NODE, &no_ip_pim_v6_secondary_cmd);
   install_element (CONFIG_NODE, &ip_ssmpingd_cmd);
   install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd); 
   install_element (CONFIG_NODE, &ip_msdp_peer_cmd);
   install_element (CONFIG_NODE, &no_ip_msdp_peer_cmd);
+  install_element (CONFIG_NODE, &ip_pim_ecmp_cmd);
+  install_element (CONFIG_NODE, &no_ip_pim_ecmp_cmd);
+  install_element (CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd);
+  install_element (CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd);
 
   install_element (INTERFACE_NODE, &interface_ip_igmp_cmd);
   install_element (INTERFACE_NODE, &interface_no_ip_igmp_cmd); 
@@ -6246,6 +6514,8 @@ void pim_cmd_init()
   install_element (VIEW_NODE, &show_ip_rib_cmd);
   install_element (VIEW_NODE, &show_ip_ssmpingd_cmd);
   install_element (VIEW_NODE, &show_debugging_pim_cmd);
+  install_element (VIEW_NODE, &show_ip_pim_nexthop_cmd);
+  install_element (VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd);
 
   install_element (ENABLE_NODE, &clear_ip_interfaces_cmd);
   install_element (ENABLE_NODE, &clear_ip_igmp_interfaces_cmd);
index 3d7ae4ad22bdc977bdd2b45848aab3157341b1a3..ee9433d7973b63e1be15d869f18397a6540dc04e 100644 (file)
@@ -428,15 +428,14 @@ int pim_hello_recv(struct interface *ifp,
   return 0;
 }
 
-int pim_hello_build_tlv(const char *ifname,
+int pim_hello_build_tlv(struct interface *ifp,
                        uint8_t *tlv_buf, int tlv_buf_size,
                        uint16_t holdtime,
                        uint32_t dr_priority,
                        uint32_t generation_id,
                        uint16_t propagation_delay,
                        uint16_t override_interval,
-                       int can_disable_join_suppression,
-                       struct list *ifconnected)
+                       int can_disable_join_suppression)
 {
   uint8_t *curr = tlv_buf;
   uint8_t *pastend = tlv_buf + tlv_buf_size;
@@ -454,7 +453,7 @@ int pim_hello_build_tlv(const char *ifname,
   if (!curr) {
     if (PIM_DEBUG_PIM_HELLO) {
       zlog_debug("%s: could not set PIM hello Holdtime option for interface %s",
-                __PRETTY_FUNCTION__, ifname);
+                __PRETTY_FUNCTION__, ifp->name);
     }
     return -1;
   }
@@ -468,7 +467,7 @@ int pim_hello_build_tlv(const char *ifname,
   if (!tmp) {
     if (PIM_DEBUG_PIM_HELLO) {
       zlog_debug("%s: could not set PIM LAN Prune Delay option for interface %s",
-                __PRETTY_FUNCTION__, ifname);
+                __PRETTY_FUNCTION__, ifp->name);
     }
     return -1;
   }
@@ -485,7 +484,7 @@ int pim_hello_build_tlv(const char *ifname,
   if (!curr) {
     if (PIM_DEBUG_PIM_HELLO) {
       zlog_debug("%s: could not set PIM hello DR Priority option for interface %s",
-                __PRETTY_FUNCTION__, ifname);
+                __PRETTY_FUNCTION__, ifp->name);
     }
     return -2;
   }
@@ -498,23 +497,38 @@ int pim_hello_build_tlv(const char *ifname,
   if (!curr) {
     if (PIM_DEBUG_PIM_HELLO) {
       zlog_debug("%s: could not set PIM hello Generation ID option for interface %s",
-                __PRETTY_FUNCTION__, ifname);
+                __PRETTY_FUNCTION__, ifp->name);
     }
     return -3;
   }
 
   /* Secondary Address List */
-  if (ifconnected) {
+  if (ifp->connected->count) {
     curr = pim_tlv_append_addrlist_ucast(curr,
                                         pastend,
-                                        ifconnected);
+                                        ifp->connected,
+                                         AF_INET);
     if (!curr) {
       if (PIM_DEBUG_PIM_HELLO) {
-       zlog_debug("%s: could not set PIM hello Secondary Address List option for interface %s",
-                 __PRETTY_FUNCTION__, ifname);
+       zlog_debug("%s: could not set PIM hello v4 Secondary Address List option for interface %s",
+                 __PRETTY_FUNCTION__, ifp->name);
       }
       return -4;
     }
+    if (pimg->send_v6_secondary)
+      {
+        curr = pim_tlv_append_addrlist_ucast(curr,
+                                             pastend,
+                                             ifp->connected,
+                                             AF_INET6);
+        if (!curr) {
+          if (PIM_DEBUG_PIM_HELLO) {
+            zlog_debug("%s: could not sent PIM hello v6 secondary Address List option for interface %s",
+                       __PRETTY_FUNCTION__, ifp->name);
+          }
+          return -4;
+        }
+      }
   }
 
   return curr - tlv_buf;
index 3a6d3361ba3b877de661a33744aa199feed9e88c..1f8b348bd77665a7d6b5c65251e6ef481d37ebdc 100644 (file)
@@ -29,15 +29,14 @@ int pim_hello_recv(struct interface *ifp,
                   struct in_addr src_addr,
                   uint8_t *tlv_buf, int tlv_buf_size);
 
-int pim_hello_build_tlv(const char *ifname,
+int pim_hello_build_tlv(struct interface *ifp,
                        uint8_t *tlv_buf, int tlv_buf_size,
                        uint16_t holdtime,
                        uint32_t dr_priority,
                        uint32_t generation_id,
                        uint16_t propagation_delay,
                        uint16_t override_interval,
-                       int can_disable_join_suppression,
-                       struct list *ifconnected);
+                       int can_disable_join_suppression);
 
 void pim_hello_require(struct interface *ifp);
 
index 086479643166c5b03bc7e145e0ac31da5d3117ef..524f2ee0b356c1a61c9fc3f39201438a794b09ae 100644 (file)
@@ -30,6 +30,7 @@
 #include "hash.h"
 
 #include "pimd.h"
+#include "pim_zebra.h"
 #include "pim_iface.h"
 #include "pim_igmp.h"
 #include "pim_mroute.h"
@@ -42,6 +43,7 @@
 #include "pim_time.h"
 #include "pim_ssmpingd.h"
 #include "pim_rp.h"
+#include "pim_nht.h"
 
 struct interface *pim_regiface = NULL;
 struct list *pim_ifchannel_list = NULL;
@@ -324,12 +326,29 @@ static int pim_sec_addr_comp(const void *p1, const void *p2)
   const struct pim_secondary_addr *sec1 = p1;
   const struct pim_secondary_addr *sec2 = p2;
 
-  if (ntohl(sec1->addr.s_addr) < ntohl(sec2->addr.s_addr))
+  if (sec1->addr.family == AF_INET &&
+      sec2->addr.family == AF_INET6)
     return -1;
 
-  if (ntohl(sec1->addr.s_addr) > ntohl(sec2->addr.s_addr))
+  if (sec1->addr.family == AF_INET6 &&
+      sec2->addr.family == AF_INET)
     return 1;
 
+  if (sec1->addr.family == AF_INET)
+    {
+      if (ntohl(sec1->addr.u.prefix4.s_addr) < ntohl(sec2->addr.u.prefix4.s_addr))
+        return -1;
+
+      if (ntohl(sec1->addr.u.prefix4.s_addr) > ntohl(sec2->addr.u.prefix4.s_addr))
+        return 1;
+    }
+  else
+    {
+      return memcmp (&sec1->addr.u.prefix6,
+                     &sec2->addr.u.prefix6,
+                     sizeof (struct in6_addr));
+    }
+
   return 0;
 }
 
@@ -339,7 +358,7 @@ static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)
 }
 
 static struct pim_secondary_addr *
-pim_sec_addr_find(struct pim_interface *pim_ifp, struct in_addr addr)
+pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr)
 {
   struct pim_secondary_addr *sec_addr;
   struct listnode *node;
@@ -349,7 +368,7 @@ pim_sec_addr_find(struct pim_interface *pim_ifp, struct in_addr addr)
   }
 
   for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
-    if (sec_addr->addr.s_addr == addr.s_addr) {
+    if (prefix_cmp(&sec_addr->addr, addr)) {
       return sec_addr;
     }
   }
@@ -364,7 +383,7 @@ static void pim_sec_addr_del(struct pim_interface *pim_ifp,
   pim_sec_addr_free(sec_addr);
 }
 
-static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct in_addr addr)
+static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr)
 {
   int changed = 0;
   struct pim_secondary_addr *sec_addr;
@@ -391,7 +410,7 @@ static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct in_addr addr)
   }
 
   changed = 1;
-  sec_addr->addr = addr;
+  sec_addr->addr = *addr;
   listnode_add_sort(pim_ifp->sec_addr_list, sec_addr);
 
   return changed;
@@ -433,10 +452,6 @@ static int pim_sec_addr_update(struct interface *ifp)
   for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
     struct prefix *p = ifc->address;
 
-    if (p->family != AF_INET) {
-      continue;
-    }
-
     if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
       continue;
     }
@@ -446,7 +461,7 @@ static int pim_sec_addr_update(struct interface *ifp)
       continue;
     }
 
-    if (pim_sec_addr_add(pim_ifp, p->u.prefix4)) {
+    if (pim_sec_addr_add(pim_ifp, p)) {
       changed = 1;
     }
   }
@@ -571,33 +586,55 @@ void pim_if_addr_add(struct connected *ifc)
 
   detect_address_change(ifp, 0, __PRETTY_FUNCTION__);
 
+  if (ifc->address->family != AF_INET)
+    return;
+
   if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
     struct igmp_sock *igmp;
 
     /* lookup IGMP socket */
     igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
-                                      ifaddr);
+                                       ifaddr);
     if (!igmp) {
       /* if addr new, add IGMP socket */
       pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, ifp);
     }
   } /* igmp */
 
-  if (PIM_IF_TEST_PIM(pim_ifp->options)) {
-
-    /* Interface has a valid primary address ? */
-    if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
-
-      /* Interface has a valid socket ? */
-      if (pim_ifp->pim_sock_fd < 0) {
-       if (pim_sock_add(ifp)) {
-         zlog_warn("Failure creating PIM socket for interface %s",
-                   ifp->name);
-       }
-      }
+  if (PIM_IF_TEST_PIM(pim_ifp->options))
+    {
 
-    }
-  } /* pim */
+      if (PIM_INADDR_ISNOT_ANY (pim_ifp->primary_address))
+        {
+
+          /* Interface has a valid socket ? */
+          if (pim_ifp->pim_sock_fd < 0)
+            {
+              if (pim_sock_add (ifp))
+                {
+                  zlog_warn ("Failure creating PIM socket for interface %s",
+                             ifp->name);
+                }
+            }
+          struct pim_nexthop_cache *pnc = NULL;
+          struct pim_rpf rpf;
+          struct zclient *zclient = NULL;
+
+          zclient = pim_zebra_zclient_get ();
+          /* RP config might come prior to (local RP's interface) IF UP event.
+             In this case, pnc would not have pim enabled nexthops.
+             Once Interface is UP and pim info is available, reregister
+             with RNH address to receive update and add the interface as nexthop. */
+          memset (&rpf, 0, sizeof (struct pim_rpf));
+          rpf.rpf_addr.family = AF_INET;
+          rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
+          rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4;
+          pnc = pim_nexthop_cache_find (&rpf);
+          if (pnc)
+            pim_sendmsg_zebra_rnh (zclient, pnc,
+                                   ZEBRA_NEXTHOP_REGISTER);
+        }
+    } /* pim */
 
     /*
       PIM or IGMP is enabled on interface, and there is at least one
@@ -675,14 +712,17 @@ void pim_if_addr_del(struct connected *ifc, int force_prim_as_any)
   ifp = ifc->ifp;
   zassert(ifp);
 
+  if (ifc->address->family != AF_INET)
+    return;
+
   if (PIM_DEBUG_ZEBRA) {
     char buf[BUFSIZ];
     prefix2str(ifc->address, buf, BUFSIZ);
     zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s",
-              __PRETTY_FUNCTION__,
-              ifp->name, ifp->ifindex, buf,
-              CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ?
-              "secondary" : "primary");
+               __PRETTY_FUNCTION__,
+               ifp->name, ifp->ifindex, buf,
+               CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ?
+               "secondary" : "primary");
   }
 
   detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__);
@@ -709,12 +749,9 @@ void pim_if_addr_add_all(struct interface *ifp)
     struct prefix *p = ifc->address;
     
     if (p->family != AF_INET)
-      {
-        v6_addrs++;
-        continue;
-      }
-
-    v4_addrs++;
+      v6_addrs++;
+    else
+      v4_addrs++;
     pim_if_addr_add(ifc);
   }
 
@@ -1105,6 +1142,7 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
   struct listnode *neighnode;
   struct pim_neighbor *neigh;
   struct pim_interface *pim_ifp;
+  struct prefix p;
 
   zassert(ifp);
 
@@ -1116,6 +1154,10 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
     return 0;
   }
 
+  p.family = AF_INET;
+  p.u.prefix4 = addr;
+  p.prefixlen = IPV4_MAX_PREFIXLEN;
+
   for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
 
     /* primary address ? */
@@ -1123,7 +1165,7 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
       return neigh;
 
     /* secondary address ? */
-    if (pim_neighbor_find_secondary(neigh, addr))
+    if (pim_neighbor_find_secondary(neigh, &p))
        return neigh;
   }
 
index e98c17fed287fc0e902400d60ed256425fce072a..c42c6910676dea57148cf9720268e59f669fed31 100644 (file)
@@ -64,7 +64,7 @@ enum pim_secondary_addr_flags {
 };
 
 struct pim_secondary_addr {
-  struct in_addr addr;
+  struct prefix addr;
   enum pim_secondary_addr_flags flags;
 };
 
index e6b4ba92a90810a2538178b31f068bf04546e6c0..ebd36f8782509c45fa47abaa3e4ab54156dd9afd 100644 (file)
@@ -1006,6 +1006,8 @@ pim_ifchannel_local_membership_add(struct interface *ifp,
              pim_upstream_switch (child, PIM_UPSTREAM_JOINED);
            }
         }
+      if (pimg->spt_switchover != PIM_SPT_INFINITY)
+        pim_channel_add_oif(up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
     }
 
   return 1;
index 2fb243b9bdbf91958f1a9f7c05d6d715c50ec0ac..ce2f98f318bcf6d58bcd9cb15586bd4c1f5a6ded 100644 (file)
@@ -178,6 +178,15 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg
 
   up->channel_oil->cc.pktcnt++;
   PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
+  // resolve mfcc_parent prior to mroute_add in channel_add_oif
+  if (up->channel_oil->oil.mfcc_parent >= MAXVIFS)
+    {
+      int vif_index = 0;
+      vif_index =
+        pim_if_find_vifindex_by_ifindex (up->rpf.source_nexthop.
+                                         interface->ifindex);
+      up->channel_oil->oil.mfcc_parent = vif_index;
+    }
   pim_register_join (up);
 
   return 0;
@@ -200,6 +209,30 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf)
 
   up = pim_upstream_find(&sg);
   if (!up) {
+    struct prefix_sg star = sg;
+    star.src.s_addr = INADDR_ANY;
+
+    up = pim_upstream_find(&star);
+
+    if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags))
+      {
+       up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, __PRETTY_FUNCTION__);
+        if (!up)
+          {
+            if (PIM_DEBUG_MROUTE)
+              zlog_debug ("%s: Unable to create upstream information for %s",
+                          __PRETTY_FUNCTION__, pim_str_sg_dump (&sg));
+            return 0;
+          }
+       pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time);
+       pim_upstream_inherited_olist (up);
+       pim_upstream_switch(up, PIM_UPSTREAM_JOINED);
+
+       if (PIM_DEBUG_MROUTE)
+         zlog_debug ("%s: Creating %s upstream on LHR",
+                     __PRETTY_FUNCTION__, up->sg_str);
+        return 0;
+      }
     if (PIM_DEBUG_MROUTE_DETAIL) {
       zlog_debug("%s: Unable to find upstream channel WHOLEPKT%s",
                 __PRETTY_FUNCTION__, pim_str_sg_dump (&sg));
@@ -858,9 +891,8 @@ int pim_mroute_del (struct channel_oil *c_oil, const char *name)
                  pim_channel_oil_dump (c_oil, buf, sizeof(buf)));
     }
 
-  /*reset incoming vifi and kernel installed flags*/
+  //Reset kernel installed flag
   c_oil->installed = 0;
-  c_oil->oil.mfcc_parent = MAXVIFS;
 
   return 0;
 }
index de663aa3b52007d2e0c7823bda21e3a5ce908a6c..e5676289b73f458d5e74fc02015c654b180cfa4e 100644 (file)
   From:
   http://www.iana.org/assignments/address-family-numbers
 */
-#define PIM_MSG_ADDRESS_FAMILY_IPV4 (1)
+enum pim_msg_address_family {
+  PIM_MSG_ADDRESS_FAMILY_RESERVED,
+  PIM_MSG_ADDRESS_FAMILY_IPV4,
+  PIM_MSG_ADDRESS_FAMILY_IPV6,
+};
 
 /*
  * Network Order pim_msg_hdr
index c1325df2605ec16f1cc1f9ad98a992dc6935b2f9..c04a6254851960344e9e9565800cd7abaf7fa982 100644 (file)
@@ -423,6 +423,31 @@ void pim_neighbor_free(struct pim_neighbor *neigh)
   XFREE(MTYPE_PIM_NEIGHBOR, neigh);
 }
 
+struct pim_neighbor *
+pim_neighbor_find_by_secondary (struct interface *ifp,
+                                struct prefix *src)
+{
+  struct pim_interface *pim_ifp;
+  struct listnode *node, *pnode;
+  struct pim_neighbor *neigh;
+  struct prefix *p;
+
+  pim_ifp = ifp->info;
+  if (!pim_ifp)
+    return NULL;
+
+  for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh))
+    {
+      for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, pnode, p))
+        {
+          if (prefix_same (p, src))
+            return neigh;
+        }
+    }
+
+  return NULL;
+}
+
 struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
                                       struct in_addr source_addr)
 {
@@ -502,6 +527,12 @@ struct pim_neighbor *pim_neighbor_add(struct interface *ifp,
 
   listnode_add(pim_ifp->pim_neighbor_list, neigh);
 
+  if (PIM_DEBUG_PIM_TRACE_DETAIL)
+    {
+      char str[INET_ADDRSTRLEN];
+      pim_inet4_dump("<nht_nbr?>", source_addr, str, sizeof (str));
+      zlog_debug ("%s: neighbor %s added ", __PRETTY_FUNCTION__, str);
+    }
   /*
     RFC 4601: 4.3.2.  DR Election
 
@@ -532,6 +563,14 @@ struct pim_neighbor *pim_neighbor_add(struct interface *ifp,
 
   pim_upstream_find_new_rpf();
 
+  /* RNH can send nexthop update prior to PIM neibhor UP
+     in that case nexthop cache would not consider this neighbor
+     as RPF.
+     Upon PIM neighbor UP, iterate all RPs and update
+     nexthop cache with this neighbor.
+   */
+  pim_resolve_rp_nh ();
+
   pim_rp_setup ();
 
   pim_neighbor_rpf_update();
@@ -669,7 +708,7 @@ void pim_neighbor_delete_all(struct interface *ifp,
 }
 
 struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh,
-                                          struct in_addr addr)
+                                          struct prefix *addr)
 {
   struct listnode *node;
   struct prefix   *p;
@@ -678,14 +717,11 @@ struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh,
     return 0;
 
   for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, node, p)) {
-    if (p->family == AF_INET) {
-      if (addr.s_addr == p->u.prefix4.s_addr) {
-       return p;
-      }
-    }
+    if (prefix_same (p, addr))
+      return p;
   }
 
-  return 0;
+  return NULL;
 }
 
 /*
@@ -729,7 +765,7 @@ static void delete_from_neigh_addr(struct interface *ifp,
     for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node,
                              neigh)) {
       {
-       struct prefix *p = pim_neighbor_find_secondary(neigh, addr->u.prefix4);
+       struct prefix *p = pim_neighbor_find_secondary(neigh, addr);
        if (p) {
          char addr_str[INET_ADDRSTRLEN];
          char this_neigh_str[INET_ADDRSTRLEN];
index 986721666eaaa63fe5b2d9f58288257260bb755a..e27920fdd8bf979e3e1e39a0b2a0826d899e3142 100644 (file)
@@ -50,7 +50,8 @@ void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime);
 void pim_neighbor_free(struct pim_neighbor *neigh);
 struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
                                       struct in_addr source_addr);
-
+struct pim_neighbor *pim_neighbor_find_by_secondary (struct interface *ifp,
+                                                     struct prefix *src);
 struct pim_neighbor *pim_neighbor_find_if (struct interface *ifp);
 
 
@@ -77,7 +78,7 @@ void pim_neighbor_update(struct pim_neighbor *neigh,
                         uint32_t dr_priority,
                         struct list *addr_list);
 struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh,
-                                          struct in_addr addr);
+                                          struct prefix *addr);
 int pim_if_dr_election(struct interface *ifp);
 
 #endif /* PIM_NEIGHBOR_H */
index fe96d01a06516dc507b1388ecc2752e2d193146d..23efd554ea0f2bbe294a0bf4d5b33be4c38f6409 100644 (file)
 #include "pim_join.h"
 #include "pim_jp_agg.h"
 #include "pim_zebra.h"
+#include "pim_zlookup.h"
 
 /**
  * pim_sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister
  *   command to Zebra.
  */
-static void
+void
 pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc,
                        int command)
 {
@@ -87,9 +88,9 @@ pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc,
     {
       char buf[PREFIX2STR_BUFFER];
       prefix2str (p, buf, sizeof (buf));
-      zlog_debug ("%s: NHT Addr %s %sregistered with Zebra ret:%d ",
-                  __PRETTY_FUNCTION__, buf,
-                  (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de", ret);
+      zlog_debug ("%s: NHT %sregistered addr %s with Zebra ret:%d ",
+                  __PRETTY_FUNCTION__,
+                  (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de", buf, ret);
     }
 
   return;
@@ -149,7 +150,8 @@ pim_nexthop_cache_add (struct pim_rpf *rpf_addr)
 /* This API is used to Register an address with Zebra */
 int
 pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up,
-                           struct rp_info *rp)
+                           struct rp_info *rp,
+                           struct pim_nexthop_cache *out_pnc)
 {
   struct pim_nexthop_cache *pnc = NULL;
   struct pim_rpf rpf;
@@ -174,11 +176,14 @@ pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up,
         }
       pnc = pim_nexthop_cache_add (&rpf);
       if (pnc)
-        pim_sendmsg_zebra_rnh (zclient, pnc,
-                               ZEBRA_NEXTHOP_REGISTER);
+        pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_REGISTER);
       else
         {
-          zlog_warn ("%s: pnc node allocation failed. ", __PRETTY_FUNCTION__);
+          char rpf_str[PREFIX_STRLEN];
+          pim_addr_dump ("<nht-pnc?>", addr, rpf_str, sizeof (rpf_str));
+          zlog_warn ("%s: pnc node allocation failed. addr %s ",
+                     __PRETTY_FUNCTION__, rpf_str);
+          return -1;
         }
     }
 
@@ -192,7 +197,7 @@ pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up,
               char rp_str[PREFIX_STRLEN];
               pim_addr_dump ("<rp?>", &rp->rp.rpf_addr, rp_str,
                              sizeof (rp_str));
-              zlog_debug ("%s: NHT add RP %s node to cached list",
+              zlog_debug ("%s: Add RP %s node to pnc cached list",
                           __PRETTY_FUNCTION__, rp_str);
             }
           listnode_add_sort (pnc->rp_list, rp);
@@ -209,15 +214,18 @@ pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up,
               char buf[PREFIX2STR_BUFFER];
               prefix2str (addr, buf, sizeof (buf));
               zlog_debug
-                ("%s: NHT add upstream %s node to cached list, rpf %s",
+                ("%s: Add upstream %s node to pnc cached list, rpf %s",
                  __PRETTY_FUNCTION__, up->sg_str, buf);
             }
           listnode_add_sort (pnc->upstream_list, up);
         }
     }
 
-  if (CHECK_FLAG (pnc->flags, PIM_NEXTHOP_VALID))
-    return 1;
+  if (pnc && CHECK_FLAG (pnc->flags, PIM_NEXTHOP_VALID))
+    {
+      memcpy (out_pnc, pnc, sizeof (struct pim_nexthop_cache));
+      return 1;
+    }
 
   return 0;
 }
@@ -249,8 +257,7 @@ pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up,
 
       if (pnc->rp_list->count == 0 && pnc->upstream_list->count == 0)
         {
-          pim_sendmsg_zebra_rnh (zclient, pnc,
-                                 ZEBRA_NEXTHOP_UNREGISTER);
+          pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_UNREGISTER);
 
           list_delete (pnc->rp_list);
           list_delete (pnc->upstream_list);
@@ -277,21 +284,16 @@ pim_update_rp_nh (struct pim_nexthop_cache *pnc)
       if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE)
         continue;
 
-      if (pim_nexthop_lookup (&rp_info->rp.source_nexthop,
-                              rp_info->rp.rpf_addr.u.prefix4, 1) != 0)
-        {
-          if (PIM_DEBUG_PIM_TRACE)
-            zlog_debug ("Unable to lookup nexthop for rp specified");
-          ret++;
-          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);
 
       if (PIM_DEBUG_TRACE)
         {
           char rp_str[PREFIX_STRLEN];
           pim_addr_dump ("<rp?>", &rp_info->rp.rpf_addr, rp_str,
                          sizeof (rp_str));
-          zlog_debug ("%s: NHT update nexthop for RP %s to interface %s ",
+          zlog_debug ("%s: NHT update, nexthop for RP %s is interface %s ",
                       __PRETTY_FUNCTION__, rp_str,
                       rp_info->rp.source_nexthop.interface->name);
         }
@@ -304,6 +306,48 @@ pim_update_rp_nh (struct pim_nexthop_cache *pnc)
 
 }
 
+/* This API is used to traverse nexthop cache of RPF addr
+   of upstream entry whose IPv4 nexthop address is in
+   unresolved state and due to event like pim neighbor
+   UP event if it can be resolved.
+*/
+void
+pim_resolve_upstream_nh (struct prefix *nht_p)
+{
+  struct nexthop *nh_node = NULL;
+  struct pim_nexthop_cache pnc;
+  struct pim_neighbor *nbr = NULL;
+
+  memset (&pnc, 0, sizeof (struct pim_nexthop_cache));
+  if ((pim_find_or_track_nexthop (nht_p, NULL, NULL, &pnc)) == 1)
+    {
+      for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next)
+        {
+          if (nh_node->gate.ipv4.s_addr == 0)
+            {
+              nbr =
+                pim_neighbor_find_if (if_lookup_by_index
+                                      (nh_node->ifindex, VRF_DEFAULT));
+              if (nbr)
+                {
+                  nh_node->gate.ipv4 = nbr->source_addr;
+                  if (PIM_DEBUG_TRACE)
+                    {
+                      char str[PREFIX_STRLEN];
+                      char str1[INET_ADDRSTRLEN];
+                      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);
+                    }
+                }
+            }
+        }
+    }
+}
+
 /* Update Upstream nexthop info based on Nexthop update received from Zebra.*/
 static int
 pim_update_upstream_nh (struct pim_nexthop_cache *pnc)
@@ -312,8 +356,8 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc)
   struct listnode     *ifnode;
   struct listnode     *up_nextnode;
   struct listnode     *node;
-  struct pim_upstream *up;
-  struct interface    *ifp;
+  struct pim_upstream *up = NULL;
+  struct interface    *ifp = NULL;
   int                 vif_index = 0;
 
   for (ALL_LIST_ELEMENTS (pnc->upstream_list, up_node, up_nextnode, up))
@@ -326,6 +370,26 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc)
       if (rpf_result == PIM_RPF_FAILURE)
         continue;
 
+      /* update kernel multicast forwarding cache (MFC) */
+      if (up->channel_oil)
+        {
+          vif_index =
+            pim_if_find_vifindex_by_ifindex (up->rpf.
+                                             source_nexthop.interface->
+                                             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",
+                   __PRETTY_FUNCTION__, up->sg_str,
+                   up->rpf.source_nexthop.interface->name);
+            }
+        }
+
       if (rpf_result == PIM_RPF_CHANGED)
         {
           struct pim_neighbor *nbr;
@@ -377,7 +441,7 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc)
              returning PIM_RPF_CHANGED ? */
           pim_upstream_update_join_desired (up);
 
-        } /* PIM_RPF_CHANGED */
+        }                       /* PIM_RPF_CHANGED */
 
       if (PIM_DEBUG_TRACE)
         {
@@ -386,26 +450,7 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc)
                       old.source_nexthop.interface->name,
                       up->rpf.source_nexthop.interface->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);
-          /* 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",
-                      __PRETTY_FUNCTION__, up->sg_str,
-                      up->rpf.source_nexthop.interface->name);
-            }
-        }
-
-    } /* for (pnc->upstream_list) */
+    }                           /* for (pnc->upstream_list) */
 
   for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp))
     if (ifp->info)
@@ -426,10 +471,209 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc)
   return 0;
 }
 
-/*
- * This API is used to parse Registered address nexthop update
- * coming from Zebra
- */
+uint32_t
+pim_compute_ecmp_hash (struct prefix * src, struct prefix * grp)
+{
+  uint32_t hash_val;
+  uint32_t s = 0, g = 0;
+
+  if ((!src))
+    return 0;
+
+  switch (src->family)
+    {
+    case AF_INET:
+      {
+        s = src->u.prefix4.s_addr;
+        s = s == 0 ? 1 : s;
+        if (grp)
+          g = grp->u.prefix4.s_addr;
+      }
+      break;
+    default:
+      break;
+    }
+
+  hash_val = jhash_2words (g, s, 101);
+  if (PIM_DEBUG_TRACE)
+    {
+      char buf[PREFIX2STR_BUFFER];
+      char bufg[PREFIX2STR_BUFFER];
+      prefix2str (src, buf, sizeof (buf));
+      if (grp)
+        prefix2str (grp, bufg, sizeof (bufg));
+      zlog_debug ("%s: addr %s %s hash_val %u", __PRETTY_FUNCTION__, buf,
+                  grp ? bufg : "", hash_val);
+
+    }
+  return hash_val;
+}
+
+int
+pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc,
+                         struct pim_nexthop *nexthop, struct prefix *src,
+                         struct prefix *grp, int neighbor_needed)
+{
+  struct pim_neighbor *nbr = NULL;
+  struct nexthop *nh_node = NULL;
+  ifindex_t first_ifindex;
+  struct interface *ifp = NULL;
+  uint32_t hash_val = 0, mod_val = 0;
+  uint8_t nh_iter = 0, found = 0;
+
+  if (!pnc || !pnc->nexthop_num || !nexthop)
+    return -1;
+
+  if (qpim_ecmp_enable)
+    {
+      //User configured knob to explicitly switch to new path.
+      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)
+            {
+              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))
+                    {
+                      if (PIM_DEBUG_TRACE)
+                        zlog_debug ("%s: current nexthop does not have nbr ",
+                                    __PRETTY_FUNCTION__);
+                    }
+                  else
+                    {
+                      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;
+                    }
+                }
+            }
+        }
+      //PIM ECMP flag is enable then choose ECMP path.
+      hash_val = pim_compute_ecmp_hash (src, grp);
+      mod_val = hash_val % pnc->nexthop_num;
+      if (PIM_DEBUG_TRACE)
+        zlog_debug ("%s: hash_val %u mod_val %u ",
+                    __PRETTY_FUNCTION__, hash_val, mod_val);
+    }
+
+  for (nh_node = pnc->nexthop; nh_node && (found == 0);
+       nh_node = nh_node->next)
+    {
+      first_ifindex = nh_node->ifindex;
+      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)",
+                 __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str);
+            }
+          if (nh_iter == mod_val)
+            mod_val++;          //Select nexthpath
+          nh_iter++;
+          continue;
+        }
+      if (!ifp->info)
+        {
+          if (PIM_DEBUG_ZEBRA)
+            {
+              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)",
+                 __PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str);
+            }
+          if (nh_iter == mod_val)
+            mod_val++;          //Select nexthpath
+          nh_iter++;
+          continue;
+        }
+
+      if (neighbor_needed
+          && !pim_if_connected_to_source (ifp, src->u.prefix4))
+        {
+          nbr = pim_neighbor_find (ifp, nh_node->gate.ipv4);
+          if (PIM_DEBUG_PIM_TRACE_DETAIL)
+            zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr);
+          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);
+              if (nh_iter == mod_val)
+                mod_val++;      //Select nexthpath
+              nh_iter++;
+              continue;
+            }
+        }
+
+      if (nh_iter == mod_val)
+        {
+          nexthop->interface                    = ifp;
+          nexthop->mrib_nexthop_addr.family     = AF_INET;
+          nexthop->mrib_nexthop_addr.prefixlen  = IPV4_MAX_BITLEN;
+          nexthop->mrib_nexthop_addr.u.prefix4  = nh_node->gate.ipv4;
+          nexthop->mrib_metric_preference       = pnc->distance;
+          nexthop->mrib_route_metric            = pnc->metric;
+          nexthop->last_lookup                  = src->u.prefix4;
+          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];
+              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 ("<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);
+            }
+        }
+      nh_iter++;
+
+    }
+
+  return 0;
+}
+
+/* This API is used to parse Registered address nexthop update coming from Zebra */
 int
 pim_parse_nexthop_update (int command, struct zclient *zclient,
                           zebra_size_t length, vrf_id_t vrf_id)
@@ -437,7 +681,6 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
   struct stream *s;
   struct prefix p;
   struct nexthop *nexthop;
-  struct nexthop *oldnh;
   struct nexthop *nhlist_head = NULL;
   struct nexthop *nhlist_tail = NULL;
   uint32_t metric, distance;
@@ -476,8 +719,9 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
             {
               char buf[PREFIX2STR_BUFFER];
               prefix2str (&rpf.rpf_addr, buf, sizeof (buf));
-              zlog_debug ("%s: NHT addr %s is not in local cached DB.",
-                          __PRETTY_FUNCTION__, buf);
+              zlog_debug
+                ("%s: Skipping NHT update, addr %s is not in local cached DB.",
+                 __PRETTY_FUNCTION__, buf);
             }
           return 0;
         }
@@ -490,7 +734,7 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
       return 0;
     }
 
-  pnc->last_update = pim_time_monotonic_sec ();
+  pnc->last_update = pim_time_monotonic_usec ();
   distance = stream_getc (s);
   metric = stream_getl (s);
   nexthop_num = stream_getc (s);
@@ -499,17 +743,15 @@ 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 vrf:%d upcount %d rpcount %d",
-                  __PRETTY_FUNCTION__, buf, nexthop_num, vrf_id,
-                  listcount (pnc->upstream_list), listcount (pnc->rp_list));
+      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->flags |= PIM_NEXTHOP_VALID;
-      pnc->distance = distance;
-      pnc->metric = metric;
-      pnc->nexthop_num = nexthop_num;
+      pnc->nexthop_num = 0;     //Only increment for pim enabled rpf.
 
       for (i = 0; i < nexthop_num; i++)
         {
@@ -539,7 +781,34 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
                                       (nexthop->ifindex, VRF_DEFAULT));
               /* Overwrite with Nbr address as NH addr */
               if (nbr)
-                nexthop->gate.ipv4 = nbr->source_addr;
+                {
+                  nexthop->gate.ipv4 = nbr->source_addr;
+                  if (PIM_DEBUG_TRACE)
+                    {
+                      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);
+                    }
+                }
+              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 ",
+                         __PRETTY_FUNCTION__, ifp1->name,
+                         pim_ifp->pim_neighbor_list->count);
+                    }
+                  //Mark nexthop address to 0 until PIM Nbr is resolved.
+                  nexthop->gate.ipv4.s_addr = PIM_NET_INADDR_ANY;
+                }
 
               break;
             default:
@@ -562,9 +831,10 @@ 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)",
-                         __PRETTY_FUNCTION__,
-                         nexthop->ifindex, nexthop2str (nexthop, buf, sizeof (buf)));
+                  zlog_debug
+                    ("%s: could not find interface for ifindex %d (addr %s)",
+                     __PRETTY_FUNCTION__, nexthop->ifindex,
+                     nexthop2str (nexthop, buf, sizeof (buf)));
                 }
               nexthop_free (nexthop);
               continue;
@@ -594,14 +864,18 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
               nhlist_tail = nexthop;
               nhlist_head = nexthop;
             }
-
-          for (oldnh = pnc->nexthop; oldnh; oldnh = oldnh->next)
-            if (nexthop_same_no_recurse (oldnh, nexthop))
-              break;
+          //Only keep track of nexthops which are PIM enabled.
+          pnc->nexthop_num++;
         }
       /* Reset existing pnc->nexthop before assigning new list */
       nexthops_free (pnc->nexthop);
       pnc->nexthop = nhlist_head;
+      if (pnc->nexthop_num)
+        {
+          pnc->flags |= PIM_NEXTHOP_VALID;
+          pnc->distance = distance;
+          pnc->metric = metric;
+        }
     }
   else
     {
@@ -611,6 +885,16 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
       pnc->nexthop = NULL;
     }
 
+  if (PIM_DEBUG_TRACE)
+    {
+      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",
+         __PRETTY_FUNCTION__, buf, nexthop_num, pnc->nexthop_num, vrf_id,
+         listcount (pnc->upstream_list), listcount (pnc->rp_list));
+    }
+
   pim_rpf_set_refresh_time ();
 
   if (listcount (pnc->rp_list))
@@ -620,3 +904,142 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
 
   return 0;
 }
+
+int
+pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
+                         struct prefix *src, struct prefix *grp,
+                         int neighbor_needed)
+{
+  struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM];
+  struct pim_neighbor *nbr = NULL;
+  int num_ifindex;
+  struct interface *ifp;
+  int first_ifindex;
+  int found = 0;
+  uint8_t i = 0;
+  uint32_t hash_val = 0, mod_val = 0;
+
+  if (PIM_DEBUG_TRACE)
+    {
+      char addr_str[INET_ADDRSTRLEN];
+      pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str));
+      zlog_debug ("%s: Looking up: %s, last lookup time: %lld",
+                  __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,
+                            PIM_NEXTHOP_LOOKUP_MAX);
+  if (num_ifindex < 1)
+    {
+      char addr_str[INET_ADDRSTRLEN];
+      pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str));
+      zlog_warn ("%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);
+    }
+
+  while (!found && (i < num_ifindex))
+    {
+      first_ifindex = nexthop_tab[i].ifindex;
+
+      ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT);
+      if (!ifp)
+        {
+          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 interface for ifindex %d (address %s)",
+                 __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str);
+            }
+          if (i == mod_val)
+            mod_val++;
+          i++;
+          continue;
+        }
+
+      if (!ifp->info)
+        {
+          if (PIM_DEBUG_ZEBRA)
+            {
+              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)",
+                 __PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str);
+            }
+          if (i == mod_val)
+            mod_val++;
+          i++;
+          continue;
+        }
+      if (neighbor_needed && !pim_if_connected_to_source (ifp, addr))
+        {
+          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))
+            {
+              if (i == mod_val)
+                mod_val++;
+              i++;
+              if (PIM_DEBUG_ZEBRA)
+                {
+                  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)",
+                     __PRETTY_FUNCTION__, ifp->name, addr_str);
+                }
+              continue;
+            }
+        }
+
+      if (i == mod_val)
+        {
+          if (PIM_DEBUG_ZEBRA)
+            {
+              char nexthop_str[PREFIX_STRLEN];
+              char addr_str[INET_ADDRSTRLEN];
+              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",
+                 __FILE__, __PRETTY_FUNCTION__, nexthop_str, addr_str,
+                 ifp->name, nexthop_tab[i].route_metric,
+                 nexthop_tab[i].protocol_distance);
+            }
+          /* update nextop data */
+          nexthop->interface                = ifp;
+          nexthop->mrib_nexthop_addr        = nexthop_tab[i].nexthop_addr;
+          nexthop->mrib_metric_preference   = nexthop_tab[i].protocol_distance;
+          nexthop->mrib_route_metric        = nexthop_tab[i].route_metric;
+          nexthop->last_lookup              = addr;
+          nexthop->last_lookup_time         = pim_time_monotonic_usec();
+          nexthop->nbr                      = nbr;
+          found                             = 1;
+        }
+      i++;
+    }
+  if (found)
+    return 0;
+  else
+    return -1;
+}
index 5348ec3704a6a875f39fff1e06fca05017c3fdfb..b4b2d91e47a550fd0a0b46484bc454ceabc1d109 100644 (file)
@@ -51,10 +51,19 @@ struct pim_nexthop_cache
 int pim_parse_nexthop_update (int command, struct zclient *zclient,
                               zebra_size_t length, vrf_id_t vrf_id);
 int pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up,
-                               struct rp_info *rp);
+                               struct rp_info *rp, struct pim_nexthop_cache *out_pnc);
 void pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up,
                                  struct rp_info *rp);
 struct pim_nexthop_cache *pim_nexthop_cache_add (struct pim_rpf *rpf_addr);
 struct pim_nexthop_cache *pim_nexthop_cache_find (struct pim_rpf *rpf);
-
+uint32_t pim_compute_ecmp_hash (struct prefix *src, struct prefix *grp);
+int pim_ecmp_nexthop_search (struct pim_nexthop_cache * pnc,
+                         struct pim_nexthop *nexthop, struct prefix *src,
+                         struct prefix *grp, int neighbor_needed);
+int pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
+                         struct prefix *src, struct prefix *grp,
+                         int neighbor_needed);
+void pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc,
+                          int command);
+void pim_resolve_upstream_nh (struct prefix *nht_p);
 #endif
index 2701079053d147b4b42d9a61219663a46401a047..2d4aa3febc40c7a8d401f25af5349857faec230a 100644 (file)
@@ -289,10 +289,10 @@ pim_channel_del_oif (struct channel_oil *channel_oil,
       char source_str[INET_ADDRSTRLEN];
       pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
       pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
-      zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d",
+      zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u IIF:%d OIF=%s vif_index=%d",
                 __FILE__, __PRETTY_FUNCTION__,
                 source_str, group_str,
-                proto_mask, oif->name, pim_ifp->mroute_vif_index);
+                proto_mask, channel_oil->oil.mfcc_parent ,oif->name, pim_ifp->mroute_vif_index);
     }
 
   return 0;
index b2f858b7d96c87c758cfcf567d4c68e2623021ea..9886cd6ad29ab23fc59f986b0f59047efa0b217b 100644 (file)
@@ -627,7 +627,7 @@ static int hello_send(struct interface *ifp,
               listcount(ifp->connected));
   }
 
-  pim_tlv_size = pim_hello_build_tlv(ifp->name,
+  pim_tlv_size = pim_hello_build_tlv(ifp,
                                     pim_msg + PIM_PIM_MIN_LEN,
                                     sizeof(pim_msg) - PIM_PIM_MIN_LEN,
                                     holdtime,
@@ -635,8 +635,7 @@ static int hello_send(struct interface *ifp,
                                     pim_ifp->pim_generation_id,
                                     pim_ifp->pim_propagation_delay_msec,
                                     pim_ifp->pim_override_interval_msec,
-                                    PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options),
-                                    ifp->connected);
+                                    PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options));
   if (pim_tlv_size < 0) {
     return -1;
   }
index 65a3e8714f87481060e7636e6dc5c1f0e380f705..12f8dd53f268683cd52af94f2888a0399d8f8f32 100644 (file)
@@ -187,6 +187,15 @@ pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct
     return;
   }
 
+  if (PIM_DEBUG_PIM_REG)
+    {
+      char rp_str[INET_ADDRSTRLEN];
+      strcpy (rp_str, inet_ntoa (rpg->rpf_addr.u.prefix4));
+      zlog_debug ("%s: Sending %s %sRegister Packet to %s on %s",
+              __PRETTY_FUNCTION__, up->sg_str,
+              null_register ? "NULL " : "", rp_str, ifp->name);
+    }
+
   memset(buffer, 0, 10000);
   b1 = buffer + PIM_MSG_HEADER_LEN;
   *b1 |= null_register << 6;
index 78bbd14405566540d67434e2c9e7aa33fef64711..1dd5dae303cfc2ead9b49c6e378afdb36898a61f 100644 (file)
@@ -30,6 +30,7 @@
 #include "vty.h"
 #include "vrf.h"
 #include "plist.h"
+#include "nexthop.h"
 
 #include "pimd.h"
 #include "pim_vty.h"
@@ -249,7 +250,7 @@ pim_rp_check_interface_addrs(struct rp_info *rp_info,
   }
 
   for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
-    if (sec_addr->addr.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) {
+    if (prefix_same(&sec_addr->addr, &rp_info->rp.rpf_addr)) {
       return 1;
     }
   }
@@ -280,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, ret = 0;
   struct rp_info *rp_info;
   struct rp_info *rp_all;
   struct prefix group_all;
@@ -288,6 +289,7 @@ pim_rp_new (const char *rp, const char *group_range, const char *plist)
   struct rp_info *tmp_rp_info;
   char buffer[BUFSIZ];
   struct prefix nht_p;
+  struct pim_nexthop_cache pnc;
 
   rp_info = XCALLOC (MTYPE_PIM_RP, sizeof (*rp_info));
   if (!rp_info)
@@ -387,21 +389,31 @@ pim_rp_new (const char *rp, const char *group_range, const char *plist)
           /* Register addr with Zebra NHT */
           nht_p.family = AF_INET;
           nht_p.prefixlen = IPV4_MAX_BITLEN;
-          nht_p.u.prefix4 = rp_all->rp.rpf_addr.u.prefix4;
+          nht_p.u.prefix4 = rp_all->rp.rpf_addr.u.prefix4;      //RP address
           if (PIM_DEBUG_PIM_TRACE)
             {
               char buf[PREFIX2STR_BUFFER];
+              char buf1[PREFIX2STR_BUFFER];
               prefix2str (&nht_p, buf, sizeof (buf));
-              zlog_debug ("%s: NHT Register rp_all addr %s with NHT ",
-                        __PRETTY_FUNCTION__, buf);
+              prefix2str (&rp_all->group, buf1, sizeof (buf1));
+              zlog_debug ("%s: NHT Register rp_all addr %s grp %s ",
+                          __PRETTY_FUNCTION__, buf, buf1);
+            }
+          memset (&pnc, 0, sizeof (struct pim_nexthop_cache));
+          if ((ret =
+               pim_find_or_track_nexthop (&nht_p, NULL, rp_all, &pnc)) == 1)
+            {
+              //Compute PIM RPF using Cached nexthop
+              pim_ecmp_nexthop_search (&pnc, &rp_all->rp.source_nexthop,
+                                       &nht_p, &rp_all->group, 1);
+            }
+          else
+            {
+              if (pim_nexthop_lookup (&rp_all->rp.source_nexthop, rp_all->rp.rpf_addr.u.prefix4, 1) != 0)
+                return PIM_RP_NO_PATH;
             }
-          pim_find_or_track_nexthop (&nht_p, NULL, rp_all);
-
-          if (pim_nexthop_lookup (&rp_all->rp.source_nexthop, rp_all->rp.rpf_addr.u.prefix4, 1) != 0)
-            return PIM_RP_NO_PATH;
-
           pim_rp_check_interfaces (rp_all);
-         pim_rp_refresh_group_to_rp_mapping();
+          pim_rp_refresh_group_to_rp_mapping ();
           return PIM_SUCCESS;
         }
 
@@ -451,13 +463,25 @@ pim_rp_new (const char *rp, const char *group_range, const char *plist)
   if (PIM_DEBUG_PIM_TRACE)
     {
       char buf[PREFIX2STR_BUFFER];
+      char buf1[PREFIX2STR_BUFFER];
       prefix2str (&nht_p, buf, sizeof (buf));
-      zlog_debug ("%s: NHT Register RP addr %s with Zebra ", __PRETTY_FUNCTION__, buf);
+      prefix2str (&rp_info->group, buf1, sizeof (buf1));
+      zlog_debug ("%s: NHT Register RP addr %s grp %s with Zebra ",
+                  __PRETTY_FUNCTION__, buf, buf1);
     }
-  pim_find_or_track_nexthop (&nht_p, NULL, rp_info);
 
-  if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0)
-    return PIM_RP_NO_PATH;
+  memset (&pnc, 0, sizeof (struct pim_nexthop_cache));
+  if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1)
+    {
+      //Compute PIM RPF using Cached nexthop
+      pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop,
+                               &nht_p, &rp_info->group, 1);
+    }
+  else
+    {
+      if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0)
+        return PIM_RP_NO_PATH;
+    }
 
   pim_rp_check_interfaces (rp_info);
   pim_rp_refresh_group_to_rp_mapping ();
@@ -509,7 +533,8 @@ pim_rp_del (const char *rp, const char *group_range, const char *plist)
     {
       char buf[PREFIX2STR_BUFFER];
       prefix2str (&nht_p, buf, sizeof (buf));
-      zlog_debug ("%s: Deregister RP addr %s with NHT ", __PRETTY_FUNCTION__, buf);
+      zlog_debug ("%s: Deregister RP addr %s with Zebra ", __PRETTY_FUNCTION__,
+                  buf);
     }
   pim_delete_tracked_nexthop (&nht_p, NULL, rp_info);
 
@@ -535,17 +560,39 @@ pim_rp_setup (void)
   struct listnode *node;
   struct rp_info *rp_info;
   int ret = 0;
+  struct prefix nht_p;
+  struct pim_nexthop_cache pnc;
 
   for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
     {
       if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE)
         continue;
 
-      if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0)
+      nht_p.family = AF_INET;
+      nht_p.prefixlen = IPV4_MAX_BITLEN;
+      nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
+      memset (&pnc, 0, sizeof (struct pim_nexthop_cache));
+      if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1)
         {
-         if (PIM_DEBUG_PIM_TRACE)
-           zlog_debug ("Unable to lookup nexthop for rp specified");
-          ret++;
+          //Compute PIM RPF using Cached nexthop
+          pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop,
+                                   &nht_p, &rp_info->group, 1);
+        }
+      else
+        {
+          if (PIM_DEBUG_ZEBRA)
+            {
+              char buf[PREFIX2STR_BUFFER];
+              prefix2str (&nht_p, buf, sizeof (buf));
+              zlog_debug ("%s: NHT Local Nexthop not found for RP %s ",
+                          __PRETTY_FUNCTION__, buf);
+            }
+          if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0)
+            {
+              if (PIM_DEBUG_PIM_TRACE)
+                zlog_debug ("Unable to lookup nexthop for rp specified");
+              ret++;
+            }
         }
     }
 
@@ -680,7 +727,43 @@ pim_rp_g (struct in_addr group)
 
   if (rp_info)
     {
-      pim_nexthop_lookup(&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1);
+      int ret = 0;
+      struct prefix nht_p;
+      struct pim_nexthop_cache pnc;
+      /* Register addr with Zebra NHT */
+      nht_p.family = AF_INET;
+      nht_p.prefixlen = IPV4_MAX_BITLEN;
+      nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
+      if (PIM_DEBUG_PIM_TRACE)
+        {
+          char buf[PREFIX2STR_BUFFER];
+          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 ",
+                      __PRETTY_FUNCTION__, buf, buf1);
+        }
+      memset (&pnc, 0, sizeof (struct pim_nexthop_cache));
+      if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1)
+        {
+          //Compute PIM RPF using Cached nexthop
+          pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop,
+                                   &nht_p, &rp_info->group, 1);
+        }
+      else
+        {
+          if (PIM_DEBUG_ZEBRA)
+            {
+              char buf[PREFIX2STR_BUFFER];
+              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",
+                          __PRETTY_FUNCTION__, buf, buf1);
+            }
+          pim_rpf_set_refresh_time ();
+          pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1);
+        }
       return (&rp_info->rp);
     }
 
@@ -862,3 +945,54 @@ pim_rp_show_information (struct vty *vty, u_char uj)
     json_object_free(json);
   }
 }
+
+void
+pim_resolve_rp_nh (void)
+{
+  struct listnode *node = NULL;
+  struct rp_info *rp_info = NULL;
+  struct nexthop *nh_node = NULL;
+  struct prefix nht_p;
+  struct pim_nexthop_cache pnc;
+  struct pim_neighbor *nbr = NULL;
+
+  for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
+    {
+      if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE)
+        continue;
+
+      nht_p.family = AF_INET;
+      nht_p.prefixlen = IPV4_MAX_BITLEN;
+      nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
+      memset (&pnc, 0, sizeof (struct pim_nexthop_cache));
+      if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1)
+        {
+          for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next)
+            {
+              if (nh_node->gate.ipv4.s_addr == 0)
+                {
+                  nbr =
+                    pim_neighbor_find_if (if_lookup_by_index
+                                          (nh_node->ifindex, VRF_DEFAULT));
+                  if (nbr)
+                    {
+                      nh_node->gate.ipv4 = nbr->source_addr;
+                      if (PIM_DEBUG_TRACE)
+                        {
+                          char str[PREFIX_STRLEN];
+                          char str1[INET_ADDRSTRLEN];
+                          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);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
index 84ab9be4824978b09a9687d0a539c20d961813c1..df18c998d69a4e760f5f7275909ba42e253e7bcc 100644 (file)
@@ -61,6 +61,6 @@ struct pim_rpf *pim_rp_g (struct in_addr group);
 #define RP(G)       pim_rp_g ((G))
 
 void pim_rp_show_information (struct vty *vty, u_char uj);
-
+void pim_resolve_rp_nh (void);
 int pim_rp_list_cmp (void *v1, void *v2);
 #endif
index 400048738a6a32da0e8c9abbaf2898866cae9354..0f5fab0d93596fa81721638322e02ba5aa14578e 100644 (file)
@@ -67,11 +67,14 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei
        {
          char addr_str[INET_ADDRSTRLEN];
          pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
-         zlog_debug ("%s: Using last lookup for %s at %lld, %lld",
+          char nexthop_str[PREFIX_STRLEN];
+          pim_addr_dump("<nexthop?>", &nexthop->mrib_nexthop_addr,
+                            nexthop_str, sizeof(nexthop_str));
+          zlog_debug ("%s: Using last lookup for %s at %lld, %lld addr%s",
                      __PRETTY_FUNCTION__,
                      addr_str,
                      nexthop->last_lookup_time,
-                     last_route_change_time);
+                     last_route_change_time, nexthop_str);
        }
       nexthop_lookups_avoided++;
       return 0;
@@ -190,32 +193,56 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old,
   struct pim_rpf     *rpf = &up->rpf;
   struct pim_rpf     saved;
   struct prefix     nht_p;
+  struct pim_nexthop_cache pnc;
+  int ret = 0;
+  struct prefix src, grp;
 
   saved.source_nexthop = rpf->source_nexthop;
   saved.rpf_addr = rpf->rpf_addr;
 
-  if (is_new)
+  if (is_new && PIM_DEBUG_ZEBRA)
+    {
+      char source_str[INET_ADDRSTRLEN];
+      pim_inet4_dump ("<source?>", up->upstream_addr, source_str,
+                      sizeof (source_str));
+      zlog_debug ("%s: NHT Register upstream %s addr %s with Zebra.",
+                  __PRETTY_FUNCTION__, up->sg_str, source_str);
+    }
+  /* Register addr with Zebra NHT */
+  nht_p.family = AF_INET;
+  nht_p.prefixlen = IPV4_MAX_BITLEN;
+  nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
+
+  src.family = AF_INET;
+  src.prefixlen = IPV4_MAX_BITLEN;
+  src.u.prefix4 = up->upstream_addr;    //RP or Src address
+  grp.family = AF_INET;
+  grp.prefixlen = IPV4_MAX_BITLEN;
+  grp.u.prefix4 = up->sg.grp;
+  memset (&pnc, 0, sizeof (struct pim_nexthop_cache));
+  if ((ret = pim_find_or_track_nexthop (&nht_p, up, NULL, &pnc)) == 1)
     {
-      if (PIM_DEBUG_ZEBRA)
+      if (pnc.nexthop_num)
         {
-          char source_str[INET_ADDRSTRLEN];
-          pim_inet4_dump("<source?>", up->upstream_addr, source_str, sizeof(source_str));
-          zlog_debug ("%s: NHT Register upstream %s addr %s with Zebra.",
-                __PRETTY_FUNCTION__, up->sg_str, source_str);
+          //Compute PIM RPF using Cached nexthop
+          pim_ecmp_nexthop_search (&pnc, &up->rpf.source_nexthop,
+                                   &src, &grp,
+                                   !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) &&
+                                   !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->
+                                                                     flags));
         }
-      /* Register addr with Zebra NHT */
-      nht_p.family = AF_INET;
-      nht_p.prefixlen = IPV4_MAX_BITLEN;
-      nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
-      pim_find_or_track_nexthop (&nht_p, up, NULL);
     }
-
-  if (pim_nexthop_lookup(&rpf->source_nexthop,
-                         up->upstream_addr,
-                         !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) && 
-                         !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))) {
-    return PIM_RPF_FAILURE;
-  }
+  else
+    {
+      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)))
+        {
+          return PIM_RPF_FAILURE;
+        }
+   }
 
   rpf->rpf_addr.family = AF_INET;
   rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up);
index 5223f60e1b223aa6be5769ce42e1b22e7ca8d05d..259ed44c714de11767994c9d148b912822eca4b0 100644 (file)
@@ -94,6 +94,7 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf,
 }
 
 #define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr))
+#define ucast_ipv6_encoding_len (2 + sizeof(struct in6_addr))
 
 /*
  * An Encoded-Unicast address takes the following format:
@@ -135,6 +136,14 @@ pim_encode_addr_ucast (uint8_t *buf, struct prefix *p)
       memcpy (buf, &p->u.prefix4, sizeof (struct in_addr));
       return ucast_ipv4_encoding_len;
       break;
+    case AF_INET6:
+      *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV6;
+      ++buf;
+      *(uint8_t *)buf = 0;
+      ++buf;
+      memcpy (buf, &p->u.prefix6, sizeof (struct in6_addr));
+      return ucast_ipv6_encoding_len;
+      break;
     default:
       return 0;
       break;
@@ -216,12 +225,13 @@ pim_encode_addr_group (uint8_t *buf, afi_t afi, int bidir, int scope, struct in_
 
 uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
                                       const uint8_t *buf_pastend,
-                                      struct list *ifconnected)
+                                      struct list *ifconnected,
+                                       int family)
 {
   struct listnode *node;
   uint16_t option_len = 0;
-
   uint8_t *curr;
+  size_t uel;
 
   node = listhead(ifconnected);
 
@@ -230,8 +240,10 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
     return buf;
   }
 
-  /* Skip first address (primary) */
-  node = listnextnode(node);
+  if (family == AF_INET)
+    uel = ucast_ipv4_encoding_len;
+  else
+    uel = ucast_ipv6_encoding_len;
 
   /* Scan secondary address list */
   curr = buf + 4; /* skip T and L */
@@ -240,8 +252,14 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
     struct prefix *p = ifc->address;
     int l_encode;
 
-    if ((curr + ucast_ipv4_encoding_len) > buf_pastend)
-      return 0;
+    if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
+      continue;
+
+    if ((curr + uel) > buf_pastend)
+          return 0;
+
+    if (p->family != family)
+      continue;
 
     l_encode = pim_encode_addr_ucast (curr, p);
     curr += l_encode;
@@ -251,7 +269,7 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
   if (PIM_DEBUG_PIM_TRACE_DETAIL) {
     zlog_debug("%s: number of encoded secondary unicast IPv4 addresses: %zu",
               __PRETTY_FUNCTION__,
-              option_len / ucast_ipv4_encoding_len);
+              option_len / uel);
   }
 
   if (option_len < 1) {
@@ -491,9 +509,23 @@ pim_parse_addr_ucast (struct prefix *p,
 
     p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
     memcpy(&p->u.prefix4, addr, sizeof(struct in_addr));
-
+    p->prefixlen = IPV4_MAX_PREFIXLEN;
     addr += sizeof(struct in_addr);
 
+    break;
+  case PIM_MSG_ADDRESS_FAMILY_IPV6:
+    if ((addr + sizeof(struct in6_addr)) > pastend) {
+      zlog_warn ("%s: IPv6 unicast address overflow: left=%zd needed %zu",
+                 __PRETTY_FUNCTION__,
+                 pastend - addr, sizeof(struct in6_addr));
+      return -3;
+    }
+
+    p->family = AF_INET6;
+    p->prefixlen = IPV6_MAX_PREFIXLEN;
+    memcpy(&p->u.prefix6, addr, sizeof(struct in6_addr));
+    addr += sizeof(struct in6_addr);
+
     break;
   default:
     {
@@ -706,6 +738,8 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
                     addr_str, src_str, ifname);
        }
        break;
+      case AF_INET6:
+        break;
       default:
        {
          char src_str[INET_ADDRSTRLEN];
@@ -759,8 +793,7 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
        FREE_ADDR_LIST(*hello_option_addr_list);
        return -3;
       }
-      p->family = tmp.family;
-      p->u.prefix4 = tmp.u.prefix4;
+      prefix_copy(p, &tmp);
       listnode_add(*hello_option_addr_list, p);
     }
 
index 9c4ebc9f0f86d5468e31d4cf5341096ce6bc43e2..7e0a8a147f9e9ea8f0ea293ab60af23b1f4a0e0e 100644 (file)
@@ -80,7 +80,8 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf,
                               uint32_t option_value);
 uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
                                       const uint8_t *buf_pastend,
-                                      struct list *ifconnected);
+                                      struct list *ifconnected,
+                                       int family);
 
 int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr,
                           pim_hello_options *hello_options,
index 172d0d21c985f97086f3165d39880e510f0499ea..71634ebfe546211bef2dc6ccd1d3e1b28b8bf6a7 100644 (file)
@@ -198,7 +198,20 @@ pim_upstream_del(struct pim_upstream *up, const char *name)
   upstream_channel_oil_detach(up);
 
   if (up->sources)
-    list_delete (up->sources);
+    {
+      struct listnode *node, *nnode;
+      struct pim_upstream *child;
+      for (ALL_LIST_ELEMENTS (up->sources, node, nnode, child))
+       {
+         if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(child->flags))
+           {
+             PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(child->flags);
+             pim_upstream_del(child, __PRETTY_FUNCTION__);
+           }
+       }
+
+      list_delete (up->sources);
+    }
   up->sources = NULL;
 
   /*
@@ -227,8 +240,8 @@ 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 upstream addr %s with NHT ",
-                __PRETTY_FUNCTION__, up->sg_str, buf);
+      zlog_debug ("%s: Deregister upstream %s addr %s with Zebra",
+                  __PRETTY_FUNCTION__, up->sg_str, buf);
     }
   pim_delete_tracked_nexthop (&nht_p, up, NULL);
 
@@ -694,10 +707,12 @@ pim_upstream_new (struct prefix_sg *sg,
     return NULL;
   }
 
-  pim_ifp = up->rpf.source_nexthop.interface->info;
-  if (pim_ifp)
-    up->channel_oil = pim_channel_oil_add(&up->sg, pim_ifp->mroute_vif_index);
-
+  if (up->rpf.source_nexthop.interface)
+    {
+      pim_ifp = up->rpf.source_nexthop.interface->info;
+      if (pim_ifp)
+        up->channel_oil = pim_channel_oil_add(&up->sg, pim_ifp->mroute_vif_index);
+    }
   listnode_add_sort(pim_upstream_list, up);
 
   if (PIM_DEBUG_TRACE)
@@ -768,10 +783,14 @@ struct pim_upstream *pim_upstream_add(struct prefix_sg *sg,
   if (PIM_DEBUG_TRACE)
     {
       if (up)
-       zlog_debug("%s(%s): %s, found: %d: ref_count: %d",
+        {
+          char buf[PREFIX2STR_BUFFER];
+          prefix2str (&up->rpf.rpf_addr, buf, sizeof (buf));
+         zlog_debug("%s(%s): %s, iif %s found: %d: ref_count: %d",
                   __PRETTY_FUNCTION__, name,
-                  up->sg_str, found,
+                  up->sg_str, buf, found,
                   up->ref_count);
+        }
       else
        zlog_debug("%s(%s): (%s) failure to create",
                   __PRETTY_FUNCTION__, name,
@@ -1083,26 +1102,31 @@ pim_upstream_keep_alive_timer (struct thread *t)
   up->t_ka_timer = NULL;
 
   if (I_am_RP (up->sg.grp))
-  {
-    pim_br_clear_pmbr (&up->sg);
-    /*
-     * We need to do more here :)
-     * But this is the start.
-     */
-  }
+    {
+      pim_br_clear_pmbr (&up->sg);
+      /*
+       * We need to do more here :)
+       * But this is the start.
+       */
+    }
 
   /* source is no longer active - pull the SA from MSDP's cache */
   pim_msdp_sa_local_del(&up->sg);
 
   /* if entry was created because of activity we need to deref it */
   if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags))
-  {
-    pim_upstream_fhr_kat_expiry(up);
-    if (PIM_DEBUG_TRACE)
-      zlog_debug ("kat expired on %s; remove stream reference", up->sg_str);
-    PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags);
-    pim_upstream_del(up, __PRETTY_FUNCTION__);
-  }
+    {
+      pim_upstream_fhr_kat_expiry(up);
+      if (PIM_DEBUG_TRACE)
+       zlog_debug ("kat expired on %s; remove stream reference", up->sg_str);
+      PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags);
+      pim_upstream_del(up, __PRETTY_FUNCTION__);
+    }
+  else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags))
+    {
+      PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags);
+      pim_upstream_del(up, __PRETTY_FUNCTION__);
+    }
 
   return 0;
 }
@@ -1633,28 +1657,67 @@ pim_upstream_sg_running (void *arg)
       return;
     }
 
-  if (pim_upstream_kat_start_ok(up)) {
-    /* Add a source reference to the stream if
-     * one doesn't already exist */
-    if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags))
+  if (pim_upstream_kat_start_ok(up))
     {
-      if (PIM_DEBUG_TRACE)
-        zlog_debug ("source reference created on kat restart %s", up->sg_str);
+      /* Add a source reference to the stream if
+       * one doesn't already exist */
+      if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags))
+       {
+         if (PIM_DEBUG_TRACE)
+           zlog_debug ("source reference created on kat restart %s", up->sg_str);
 
-      pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM);
-      PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags);
-      pim_upstream_fhr_kat_start(up);
+         pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM);
+         PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags);
+         pim_upstream_fhr_kat_start(up);
+       }
+      pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time);
     }
+  else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags))
     pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time);
-  }
 
   if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE)
-  {
-    pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface);
-  }
+    {
+      pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface);
+    }
   return;
 }
 
+void
+pim_upstream_add_lhr_star_pimreg (void)
+{
+  struct pim_upstream *up;
+  struct listnode *node;
+
+  for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up))
+    {
+      if (up->sg.src.s_addr != INADDR_ANY)
+        continue;
+
+      if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))
+        continue;
+
+      pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+    }
+}
+
+void
+pim_upstream_remove_lhr_star_pimreg (void)
+{
+  struct pim_upstream *up;
+  struct listnode *node;
+
+  for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up))
+    {
+      if (up->sg.src.s_addr != INADDR_ANY)
+        continue;
+
+      if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))
+        continue;
+
+      pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+    }
+}
+
 void
 pim_upstream_init (void)
 {
index 6f7556f323e84746950a8312036ecf7e93b20c7f..a1af4483acd703695705ace44c8b66ef7e328fcd 100644 (file)
@@ -34,6 +34,8 @@
 #define PIM_UPSTREAM_FLAG_MASK_SRC_STREAM              (1 << 5)
 #define PIM_UPSTREAM_FLAG_MASK_SRC_MSDP                (1 << 6)
 #define PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE       (1 << 7)
+#define PIM_UPSTREAM_FLAG_MASK_SRC_LHR                 (1 << 8)
+#define PIM_UPSTREAM_FLAG_ALL 0xFFFFFFFF
 
 #define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
 #define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
@@ -43,6 +45,7 @@
 #define PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
 #define PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
 #define PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
+#define PIM_UPSTREAM_FLAG_TEST_SRC_LHR(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
 
 #define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
 #define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
@@ -52,6 +55,7 @@
 #define PIM_UPSTREAM_FLAG_SET_SRC_STREAM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
 #define PIM_UPSTREAM_FLAG_SET_SRC_MSDP(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
 #define PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
+#define PIM_UPSTREAM_FLAG_SET_SRC_LHR(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
 
 #define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
 #define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
@@ -61,6 +65,7 @@
 #define PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
 #define PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
 #define PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
+#define PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
 
 enum pim_upstream_state {
   PIM_UPSTREAM_NOTJOINED,
@@ -193,4 +198,7 @@ void pim_upstream_terminate (void);
 void join_timer_start (struct pim_upstream *up);
 int pim_upstream_compare (void *arg1, void *arg2);
 void pim_upstream_register_reevaluate (void);
+
+void pim_upstream_add_lhr_star_pimreg (void);
+void pim_upstream_remove_lhr_star_pimreg (void);
 #endif /* PIM_UPSTREAM_H */
index f4bfcc5ce004b414d045e9701b5637a86e490982..ea67039c02ae8a80f9557b18c98aaddb30fba4eb 100644 (file)
@@ -150,6 +150,12 @@ int pim_global_config_write(struct vty *vty)
 
   writes += pim_msdp_config_write (vty);
 
+  if (!pimg->send_v6_secondary)
+    {
+      vty_out (vty, "no ip pim send-v6-secondary%s", VTY_NEWLINE);
+      ++writes;
+    }
+
   writes += pim_rp_config_write (vty);
 
   if (qpim_register_suppress_time != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT)
@@ -182,6 +188,12 @@ int pim_global_config_write(struct vty *vty)
                ssm->plist_name, VTY_NEWLINE);
       ++writes;
     }
+  if (pimg->spt_switchover == PIM_SPT_INFINITY)
+    {
+      vty_out (vty, "ip pim spt-switchover infinity-and-beyond%s",
+               VTY_NEWLINE);
+      ++writes;
+    }
 
   if (qpim_ssmpingd_list) {
     struct listnode *node;
index 4e18c478d6a184c9f5efbe324ccdc935a8285aae..253ab7ab4429069f8b6e02f9ee59b25fff1f77d4 100644 (file)
@@ -258,31 +258,11 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient,
 #endif
   }
 
-  if (p->family != AF_INET)
-    {
-      struct listnode *cnode;
-      struct connected *conn;
-      int v4addrs = 0;
-
-      for (ALL_LIST_ELEMENTS_RO (c->ifp->connected, cnode, conn))
-        {
-          if (conn->address->family == AF_INET)
-           v4addrs++;
-        }
-      if (!v4addrs && pim_ifp) 
-       {
-         pim_ifp->primary_address = pim_find_primary_addr (c->ifp);
-         pim_if_addr_add_all (c->ifp);
-          pim_if_add_vif (c->ifp);
-       }
-      return 0;
-    }
-
   if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
     /* trying to add primary address */
 
     struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
-    if (primary_addr.s_addr != p->u.prefix4.s_addr) {
+    if (p->family != AF_INET || primary_addr.s_addr != p->u.prefix4.s_addr) {
       if (PIM_DEBUG_ZEBRA) {
        /* but we had a primary address already */
 
@@ -372,6 +352,12 @@ static void scan_upstream_rpf_cache()
   for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) {
     enum pim_rpf_result rpf_result;
     struct pim_rpf      old;
+    struct prefix nht_p;
+
+    nht_p.family = AF_INET;
+    nht_p.prefixlen = IPV4_MAX_BITLEN;
+    nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
+    pim_resolve_upstream_nh (&nht_p);
 
     old.source_nexthop.interface = up->rpf.source_nexthop.interface;
     old.source_nexthop.nbr       = up->rpf.source_nexthop.nbr;
@@ -574,7 +560,8 @@ static int on_rpf_cache_refresh(struct thread *t)
   qpim_rpf_cache_refresh_last = pim_time_monotonic_sec();
   ++qpim_rpf_cache_refresh_events;
 
-  pim_rp_setup ();
+  //It is called as part of pim_neighbor_add
+  //pim_rp_setup ();
   return 0;
 }
 
@@ -836,6 +823,7 @@ void igmp_source_forward_start(struct igmp_source *source)
   struct igmp_group *group;
   struct prefix_sg sg;
   int result;
+  int input_iface_vif_index = 0;
 
   memset (&sg, 0, sizeof (struct prefix_sg));
   sg.src = source->source_addr;
@@ -861,11 +849,61 @@ void igmp_source_forward_start(struct igmp_source *source)
   if (!source->source_channel_oil) {
     struct in_addr vif_source;
     struct pim_interface *pim_oif;
+    struct prefix nht_p, src, grp;
+    int ret = 0;
+    struct pim_nexthop_cache out_pnc;
+    struct pim_nexthop nexthop;
 
     if (!pim_rp_set_upstream_addr (&vif_source, source->source_addr, sg.grp))
       return;
 
-    int input_iface_vif_index = fib_lookup_if_vif_index(vif_source);
+    /* Register addr with Zebra NHT */
+    nht_p.family = AF_INET;
+    nht_p.prefixlen = IPV4_MAX_BITLEN;
+    nht_p.u.prefix4 = vif_source;
+    memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache));
+
+    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));
+            //Compute PIM RPF using Cached nexthop
+            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
+          {
+            if (PIM_DEBUG_ZEBRA)
+              {
+                char buf1[INET_ADDRSTRLEN];
+                char buf2[INET_ADDRSTRLEN];
+                pim_inet4_dump("<source?>", nht_p.u.prefix4, buf1, sizeof(buf1));
+                pim_inet4_dump("<source?>", grp.u.prefix4, buf2, sizeof(buf2));
+                zlog_debug ("%s: NHT Nexthop not found for addr %s grp %s" ,
+                          __PRETTY_FUNCTION__, buf1, buf2);
+              }
+          }
+      }
+    else
+      input_iface_vif_index = fib_lookup_if_vif_index(vif_source);
+
+    if (PIM_DEBUG_ZEBRA)
+      {
+        char buf2[INET_ADDRSTRLEN];
+        pim_inet4_dump("<source?>", vif_source, buf2, sizeof(buf2));
+        zlog_debug ("%s: NHT %s vif_source %s vif_index:%d ", __PRETTY_FUNCTION__,
+            pim_str_sg_dump (&sg), buf2, input_iface_vif_index);
+      }
+
     if (input_iface_vif_index < 1) {
       if (PIM_DEBUG_IGMP_TRACE)
        {
@@ -1013,49 +1051,105 @@ void pim_forward_start(struct pim_ifchannel *ch)
 {
   struct pim_upstream *up = ch->upstream;
   uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
+  int input_iface_vif_index =  0;
 
   if (PIM_DEBUG_PIM_TRACE) {
     char source_str[INET_ADDRSTRLEN];
-    char group_str[INET_ADDRSTRLEN]; 
+    char group_str[INET_ADDRSTRLEN];
     char upstream_str[INET_ADDRSTRLEN];
 
     pim_inet4_dump("<source?>", ch->sg.src, source_str, sizeof(source_str));
     pim_inet4_dump("<group?>", ch->sg.grp, group_str, sizeof(group_str));
     pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str, sizeof(upstream_str));
-    zlog_debug("%s: (S,G)=(%s,%s) oif=%s(%s)",
+    zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)",
               __PRETTY_FUNCTION__,
               source_str, group_str, ch->interface->name, upstream_str);
   }
 
-  if (!up->channel_oil) {
-    int input_iface_vif_index = fib_lookup_if_vif_index(up->upstream_addr);
-    if (input_iface_vif_index < 1) {
-      if (PIM_DEBUG_PIM_TRACE)
-       {
-         char source_str[INET_ADDRSTRLEN];
-         pim_inet4_dump("<source?>", up->sg.src, source_str, sizeof(source_str));
-         zlog_debug("%s %s: could not find input interface for source %s",
-                    __FILE__, __PRETTY_FUNCTION__,
-                    source_str);
-       }
-      return;
-    }
+  /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
+     as part of mroute_del called by pim_forward_stop.
+  */
+  if (!up->channel_oil ||
+      (up->channel_oil && up->channel_oil->oil.mfcc_parent >= MAXVIFS))
+    {
+      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;
+      nht_p.prefixlen = IPV4_MAX_BITLEN;
+      nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
+      grp.family = AF_INET;
+      grp.prefixlen = IPV4_MAX_BITLEN;
+      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 (out_pnc.nexthop_num)
+            {
+              src.family = AF_INET;
+              src.prefixlen = IPV4_MAX_BITLEN;
+              src.u.prefix4 = up->upstream_addr; //RP or Src address
+              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);
+            }
+          else
+            {
+              if (PIM_DEBUG_ZEBRA)
+                {
+                  char buf1[INET_ADDRSTRLEN];
+                  char buf2[INET_ADDRSTRLEN];
+                  pim_inet4_dump("<source?>", nht_p.u.prefix4, buf1, sizeof(buf1));
+                  pim_inet4_dump("<source?>", grp.u.prefix4, buf2, sizeof(buf2));
+                  zlog_debug ("%s: NHT pnc is NULL for addr %s grp %s" ,
+                          __PRETTY_FUNCTION__, buf1, buf2);
+                }
+            }
+        }
+      else
+          input_iface_vif_index = fib_lookup_if_vif_index (up->upstream_addr);
 
-    up->channel_oil = pim_channel_oil_add(&up->sg,
-                                         input_iface_vif_index);
-    if (!up->channel_oil) {
-      if (PIM_DEBUG_PIM_TRACE)
-       zlog_debug("%s %s: could not create OIL for channel (S,G)=%s",
-                  __FILE__, __PRETTY_FUNCTION__,
-                  up->sg_str);
-      return;
+      if (input_iface_vif_index < 1)
+        {
+          if (PIM_DEBUG_PIM_TRACE)
+            {
+              char source_str[INET_ADDRSTRLEN];
+              pim_inet4_dump("<source?>", up->sg.src, source_str, sizeof(source_str));
+              zlog_debug("%s %s: could not find input interface for source %s",
+                      __FILE__, __PRETTY_FUNCTION__,
+                      source_str);
+            }
+          return;
+        }
+      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);
+        }
+      up->channel_oil = pim_channel_oil_add (&up->sg, input_iface_vif_index);
+      if (!up->channel_oil)
+        {
+          if (PIM_DEBUG_PIM_TRACE)
+            zlog_debug ("%s %s: could not create OIL for channel (S,G)=%s",
+                        __FILE__, __PRETTY_FUNCTION__, up->sg_str);
+          return;
+        }
     }
-  }
 
   if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
     mask = PIM_OIF_FLAG_PROTO_IGMP;
 
-  pim_channel_add_oif(up->channel_oil, ch->interface, mask);
+  pim_channel_add_oif (up->channel_oil, ch->interface, mask);
 }
 
 void pim_forward_stop(struct pim_ifchannel *ch)
index f77990ab5ab81faa3b7e05ec34f850ce65e330aa..27bd1370438a5593ca67cb36d67f1cea2fd93749 100644 (file)
@@ -222,6 +222,7 @@ static int zclient_read_nexthop(struct zclient *zlookup,
   for (i = 0; i < nexthop_num; ++i) {
     enum nexthop_types_t nexthop_type;
     struct pim_neighbor *nbr;
+    struct prefix p;
 
     nexthop_type = stream_getc(s);
     if (num_ifindex >= tab_size) {
@@ -251,9 +252,24 @@ static int zclient_read_nexthop(struct zclient *zlookup,
       break;
     case NEXTHOP_TYPE_IPV6_IFINDEX:
       nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET6;
-      stream_get (&nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, s, 16);
+      stream_get (&nexthop_tab[num_ifindex].nexthop_addr.u.prefix6,
+                 s,
+                 sizeof(struct in6_addr));
       nexthop_tab[num_ifindex].ifindex = stream_getl (s);
-      nbr = pim_neighbor_find_if (if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT));
+
+      p.family = AF_INET6;
+      p.prefixlen = IPV6_MAX_PREFIXLEN;
+      memcpy (&p.u.prefix6,
+             &nexthop_tab[num_ifindex].nexthop_addr.u.prefix6,
+             sizeof(struct in6_addr));
+
+      /*
+       * If we are sending v6 secondary assume we receive v6 secondary
+       */
+      if (pimg->send_v6_secondary)
+        nbr = pim_neighbor_find_by_secondary(if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT), &p);
+      else
+        nbr = pim_neighbor_find_if (if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT));
       if (nbr)
         {
           nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET;
index bdbd251e209722581d7f44539524863db9404312..7b100ffa4e8e9d21f82e48a84501b832f389277a 100644 (file)
@@ -75,7 +75,9 @@ unsigned int              qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD;
 signed int                qpim_rp_keep_alive_time = 0;
 int64_t                   qpim_nexthop_lookups = 0;
 int                       qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS;
-struct pim_instance          *pimg = NULL;
+uint8_t                   qpim_ecmp_enable = 0;
+uint8_t                   qpim_ecmp_rebalance_enable = 0;
+struct pim_instance       *pimg = NULL;
 
 int32_t qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT;
 int32_t qpim_register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT;
@@ -115,7 +117,10 @@ pim_vrf_enable (struct vrf *vrf)
            * We will crash and burn otherwise
            */
           exit(1);
-        }
+      }
+
+    pimg->send_v6_secondary = 1;
+
     }
   return 0;
 }
@@ -249,6 +254,7 @@ pim_instance_init (vrf_id_t vrf_id, afi_t afi)
   pim->vrf_id = vrf_id;
   pim->afi = afi;
 
+  pim->spt_switchover = PIM_SPT_IMMEDIATE;
   pim->rpf_hash = hash_create_size (256, pim_rpf_hash_key, pim_rpf_equal);
 
   if (PIM_DEBUG_ZEBRA)
index 69aee28f8f86cbca70ee5edd902978e9e1d53fca..0db7a7ad165b24b767d163c52f67f5adf4474ab9 100644 (file)
@@ -155,6 +155,9 @@ struct list              *qpim_static_route_list; /* list of routes added static
 extern unsigned int       qpim_keep_alive_time;
 extern signed int         qpim_rp_keep_alive_time;
 extern int                qpim_packet_process;
+extern uint8_t            qpim_ecmp_enable;
+extern uint8_t            qpim_ecmp_rebalance_enable;
+
 #define PIM_DEFAULT_PACKET_PROCESS 3
 
 #define PIM_JP_HOLDTIME (qpim_t_periodic * 7 / 2)
@@ -237,13 +240,24 @@ extern int32_t qpim_register_probe_time;
 #define PIM_DONT_DEBUG_MSDP_PACKETS        (qpim_debugs &= ~PIM_MASK_MSDP_PACKETS)
 #define PIM_DONT_DEBUG_MSDP_INTERNAL       (qpim_debugs &= ~PIM_MASK_MSDP_INTERNAL)
 
+enum pim_spt_switchover {
+  PIM_SPT_IMMEDIATE,
+  PIM_SPT_INFINITY,
+};
+
 /* Per VRF PIM DB */
 struct pim_instance
 {
   afi_t afi;
   vrf_id_t vrf_id;
+
+  enum pim_spt_switchover spt_switchover;
+
   struct hash *rpf_hash;
+
   void *ssm_info; /* per-vrf SSM configuration */
+  
+  int send_v6_secondary;
 };
 
 extern struct pim_instance *pimg; //Pim Global Instance
index 7fa3baea7e2ef76f38d5d7b76b86687b45d61de3..578c513c78ba89c69628596312b7d710d63eb09c 100644 (file)
@@ -339,7 +339,7 @@ DEFUN (rip_redistribute_type,
 
   for(i = 0; redist_type[i].str; i++) 
     {
-      if (strncmp (redist_type[i].str, argv[2]->arg, 
+      if (strncmp (redist_type[i].str, argv[1]->arg, 
                   redist_type[i].str_min_len) == 0) 
        {
          zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, 
@@ -348,7 +348,7 @@ DEFUN (rip_redistribute_type,
        }
     }
 
-  vty_out(vty, "Invalid type %s%s", argv[2]->arg,
+  vty_out(vty, "Invalid type %s%s", argv[1]->arg,
          VTY_NEWLINE);
 
   return CMD_WARNING;
@@ -365,7 +365,7 @@ DEFUN (no_rip_redistribute_type,
 
   for (i = 0; redist_type[i].str; i++) 
     {
-      if (strncmp(redist_type[i].str, argv[3]->arg, 
+      if (strncmp(redist_type[i].str, argv[2]->arg, 
                  redist_type[i].str_min_len) == 0) 
        {
          rip_metric_unset (redist_type[i].type, DONT_CARE_METRIC_RIP);
@@ -375,7 +375,7 @@ DEFUN (no_rip_redistribute_type,
         }
     }
 
-  vty_out(vty, "Invalid type %s%s", argv[3]->arg,
+  vty_out(vty, "Invalid type %s%s", argv[2]->arg,
          VTY_NEWLINE);
 
   return CMD_WARNING;
index c4db51bd6aa02a717fd54b2694b6c1d7a6ecd79b..e1f2ce82da350e65c3222db06e52cbfecde89349 100644 (file)
@@ -47,8 +47,10 @@ Installing the snap
 
     Connect the priviledged `network-control` plug to the snap:
 
-        snap connect frr:network-control ubuntu-core:network-control
+        snap connect frr:network-control core:network-control
 
+See README.usage.md for more details on setting up and using the snap
+        
 DONE.
 
 The Snap will be auto-started and running. 
index aaff59438aec660eee5af0ad75c210c4a9ac9c47..537147303a82344ada20552d5849bc60de4d0929 100644 (file)
@@ -3,7 +3,7 @@ Using the FRRouting Snap
 
 After installing the Snap, the priviledged plug need to be connected:
 
-    snap connect frr:network-control ubuntu-core:network-control
+    snap connect frr:network-control core:network-control
 
 Enabling/Disabling FRRouting Daemons
 -------------------------------------------
@@ -30,6 +30,8 @@ Commands defined by this snap
        options
 - `frr.readme`:
        Returns this document `cat README_usage.md`
+- `frr.set`:
+       Allows to enable `FPM` module. See FPM section below
 
 and for debugging defined at this time (May get removed later - do not 
 depend on them). These are mainly intended to debug the Snap
@@ -53,25 +55,88 @@ depend on them). These are mainly intended to debug the Snap
 - `frr.ldpd-debug`:
     Starts ldpd daemon in foreground
 
+MPLS (LDP)
+----------
+The MPLS forwarding requires a Linux Kernel version 4.5 or newer and
+specific MPLS kernel modules loaded. It will be auto-detected by
+FRR. You can check the detected setup with the `show mpls status`
+command from within `frr.vtysh`
+
+The following kernel modules `mpls-router` and `mpls-iptunnel`
+need to be loaded. On Ubuntu 16.04, this can be done by editing 
+'/etc/modules-load.d/modules.conf' and add the following lines:
+
+       # Load MPLS Kernel Modules
+       mpls-router
+       mpls-iptunnel
+
+For other distributions, please check the documentation on loading
+modules. You need to either reboot or use `modprobe` to manually load
+the modules as well before MPLS will be available.
+
+In addition to this, the MPLS Label-Processing needs to be enabled
+with `sysctl` on the required interfaces. Assuming the interfaces
+are named `eth0`, `eth1` and `eth2`, then the additional lines in
+`/etc/sysctl.conf` will enable it on a Ubuntu 16.04 system:
+
+       # Enable MPLS Label processing on all interfaces
+       net.mpls.conf.eth0.input=1
+       net.mpls.conf.eth1.input=1
+       net.mpls.conf.eth2.input=1
+       net.mpls.platform_labels=100000
+
+These settings require either a reboot or a manual configuration with
+`sysctl` as well.
+
+FPM Module
+----------
+The `frr.set` allows to turn FPM module on or off.
+
+    frr.set fpm {disable|protobuf|netlink}
+    
+    Disables FPM or enables FPM with selected mode
+
+By default, the FPM module is disabled, but installed with netlink and
+protobuf support. To enable the FPM module, use the `frr.set fpm protobuf`
+or `frr.set fpm netlink` command. The command will only enable the mode
+for the next restart of zebra. Please reboot or restart zebra after
+changing the mode to become effective.
+
 FAQ
 ---
 - frr.vtysh displays `--MORE--` on long output. How to suppress this?
     - Define `VTYSH_PAGER` to `cat` (default is `more`). (Ie add 
       `export VTYSH_PAGER=cat` to the end of your `.profile`)
 
+- ospfd / ospf6d are not running after installation
+       - Installing a new snap starts the daemons, but at this time they
+         may not have the required priviledged access. Make sure you 
+         issue the `snap connect` command as given above (can be verified
+         with `snap interfaces`) and **THEN** restart the daemons (or
+         reboot the system). 
+         This is a limitation of any snap package at this time which
+         requires priviledged interfaces (ie to manipulate routing tables)
+       
 Sourcecode available
 ====================
 
 The source for this SNAP is available as part of the FRRouting
-Source Code Distribution. 
+Source Code Distribution under `GPLv2 or later`
+
+<https://github.com/frrouting/frr.git>
+
+Instructions for rebuilding the snap are in `snapcraft/README.snap_build.md`
 
-    https://github.com/frrouting/frr.git
+*Please checkout the desired branch before following the instructions
+as they may have changed between versions of FRR*
 
-Instructions for rebuilding the snap are in `README.snap_build.md`
+Official Webpage for FRR
+========================
+
+Official webpage for FRR is at <https://www.frrouting.org/>
 
 Feedback welcome
 ================
 
 Please send Feedback about this snap to Martin Winter at 
 `mwinter@opensourcerouting.org`
-
diff --git a/snapcraft/defaults/nhrpd.conf.default b/snapcraft/defaults/nhrpd.conf.default
new file mode 100644 (file)
index 0000000..e69de29
index 00984c2afa1c2b5391165421227410765dd52b57..2a60d4d6522642a1493ead01dd0c203baaacdf83 100644 (file)
@@ -11,4 +11,5 @@ install:
        install -D -m 0755 isisd-service $(DESTDIR)/bin/
        install -D -m 0755 pimd-service $(DESTDIR)/bin/
        install -D -m 0755 ldpd-service $(DESTDIR)/bin/
-
+       install -D -m 0755 nhrpd-service $(DESTDIR)/bin/
+       install -D -m 0755 set-options $(DESTDIR)/bin/
diff --git a/snapcraft/scripts/nhrpd-service b/snapcraft/scripts/nhrpd-service
new file mode 100644 (file)
index 0000000..a3ba5e3
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+set -e -x
+
+if ! [ -e $SNAP_DATA/nhrpd.conf ]; then
+    cp $SNAP/etc/frr/nhrpd.conf.default $SNAP_DATA/nhrpd.conf
+fi
+exec $SNAP/sbin/nhrpd \
+    -f $SNAP_DATA/nhrpd.conf \
+    --pid_file $SNAP_DATA/nhrpd.pid \
+    --socket $SNAP_DATA/zsock \
+    --vty_socket $SNAP_DATA
diff --git a/snapcraft/scripts/set-options b/snapcraft/scripts/set-options
new file mode 100755 (executable)
index 0000000..e76e321
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+set -e
+
+case $1 in
+    fpm) 
+        case $2 in
+            disable)
+                rm -f $SNAP_DATA/fpm.conf
+                echo "FPM module disabled. Please restart FRR"
+                ;;
+            protobuf)
+                echo "-M fpm:protobuf" > $SNAP_DATA/fpm.conf
+                echo "FPM enabled and set to protobuf mode. Please restart FRR"
+                ;;
+            netlink)
+                echo "-M fpm:netlink" > $SNAP_DATA/fpm.conf
+                echo "FPM enabled and set to netlink mode. Please restart FRR"
+                ;;
+            *)
+                echo "Usage:"
+                echo "    ${SNAP_NAME}.set fpm {disable|protobuf|netlink}"
+                echo ""
+                echo "    Disables FPM module or enables it with specified mode"
+                echo "    Mode will be saved for next restart of zebra, but zebra"
+                echo "    is not automatically restarted"               
+                exit 1
+                ;;
+        esac
+        ;;
+    *)
+        echo "Usage:"
+        echo "    ${SNAP_NAME}.set fpm {disable|protobuf|netlink}"
+        echo ""
+        echo "    Disables FPM or enables FPM with selected mode"
+        exit 1
+        ;;
+esac
+
+exit 0
index 9119a4055d4559a7fedb8b8655f3236bf1a4ccbe..2ee131f9e5bc0efcc4bc0fcd83d0e0c28d6d008d 100644 (file)
@@ -8,9 +8,13 @@ fi
 if ! [ -e $SNAP_DATA/vtysh.conf ]; then
     cp $SNAP/etc/frr/vtysh.conf.default $SNAP_DATA/vtysh.conf
 fi
+EXTRA_OPTIONS=""
+if [ -e $SNAP_DATA/fpm.conf ]; then
+       EXTRA_OPTIONS="`cat $SNAP_DATA/fpm.conf`"
+fi
 exec $SNAP/sbin/zebra \
     -f $SNAP_DATA/zebra.conf \
     --pid_file $SNAP_DATA/zebra.pid \
     --socket $SNAP_DATA/zsock \
-    --vty_socket $SNAP_DATA
-
+    --vty_socket $SNAP_DATA \
+    --moduledir $SNAP/lib/frr/modules $EXTRA_OPTIONS
index a20a1d0392f297ec8524878e5f16532463104b5a..b5fb24a36163d92cb9b9b801bb6e39703e44ca32 100644 (file)
@@ -83,6 +83,15 @@ apps:
             - network
             - network-bind
             - network-control
+    nhrpd:
+        command: bin/nhrpd-service
+        daemon: simple
+        plugs:
+            - network
+            - network-bind
+            - network-control
+    set:
+        command: bin/set-options
     zebra-debug:
         command: sbin/zebra -f $SNAP_DATA/zebra.conf --pid_file $SNAP_DATA/zebra.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA
         plugs:
@@ -132,12 +141,18 @@ apps:
             - network-bind
             - network-control
     ldpd-debug:
-        command: sbin/ldpd -f $SNAP_DATA/pimd.conf --pid_file $SNAP_DATA/pimd.pid --socket $SNAP_DATA/zsock --ctl_socket $SNAP_DATA --vty_socket $SNAP_DATA
+        command: sbin/ldpd -f $SNAP_DATA/ldpd.conf --pid_file $SNAP_DATA/ldpd.pid --socket $SNAP_DATA/zsock --ctl_socket $SNAP_DATA --vty_socket $SNAP_DATA
         plugs:
             - network
             - network-bind
             - network-control
-
+    nhrpd-debug:
+        command: sbin/nhrpd -f $SNAP_DATA/nhrpd.conf --pid_file $SNAP_DATA/nhrpd.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA
+        plugs:
+            - network
+            - network-bind
+            - network-control
+            
 parts:
     frr: 
         build-packages: 
@@ -148,7 +163,6 @@ parts:
            - gawk
            - libreadline-dev
            - texinfo
-           - dejagnu
            - libncurses5-dev
            - texlive-latex-base
            - texlive-generic-recommended
@@ -161,6 +175,11 @@ parts:
            - chrpath
            - pkg-config
            - libjson-c-dev
+           - libc-ares-dev
+           - bison
+           - flex
+           - python3-dev
+           - protobuf-c-compiler
         stage-packages:
            - coreutils
            - iproute2
@@ -192,6 +211,8 @@ parts:
             - --enable-group=root
             - --enable-pimd
             - --enable-ldpd
+            - --enable-fpm
+            - --enable-protobuf
             - --enable-configfile-mask=0640
             - --enable-logfile-mask=0640 
             - --localstatedir=/var/run
@@ -212,6 +233,7 @@ parts:
             ripd.conf.default: etc/frr/ripd.conf.default
             ripngd.conf.default: etc/frr/ripngd.conf.default
             ldpd.conf.default: etc/frr/ldpd.conf.default
+            nhrpd.conf.default: etc/frr/nhrpd.conf.default
             vtysh.conf.default: etc/frr/vtysh.conf.default
     frr-scripts:
         plugin: make
index 0473b244a72bbd9df8db2f00df4c246553eeb9ec..0af17abeae2d7c2c2e0377016bde61d8078664a2 100644 (file)
@@ -1228,9 +1228,7 @@ DEFUNSH (VTYSH_BGPD,
          "Layer2 VPN Address family\n"
          "Ethernet Virtual Private Network Subsequent Address Family\n")
 {
-#if defined(HAVE_EVPN)
   vty->node = BGP_EVPN_NODE;
-#endif /* HAVE_EVPN */
   return CMD_SUCCESS;
 }
 
@@ -2203,7 +2201,7 @@ DEFUNSH (VTYSH_ALL,
 DEFUNSH (VTYSH_ALL,
         vtysh_log_syslog,
         vtysh_log_syslog_cmd,
-        "log syslog <emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>",
+        "log syslog [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
         "Logging control\n"
         "Set syslog logging level\n"
          LOG_LEVEL_DESC)