Merge remote-tracking branch 'origin/master' into EIGRP

This commit is contained in:
Donald Sharp 2017-04-26 08:03:54 -04:00
commit 6aa210418e
76 changed files with 2111 additions and 541 deletions

10
README
View File

@ -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

View 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. */

View 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. */

View 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. */

View 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. */

View 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. */

View 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. */

View 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 ();

View 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;

View 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);
}

View 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. */

View 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. */

View File

@ -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)

27
debian/changelog vendored
View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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;

View 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"

View 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);

View 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 */

View 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);
}
}

View 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);

View 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);
}

View 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);

View 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))
{

View 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;

View 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)

View 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);
}
}

View 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;
}

View 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);
}

View 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);

View 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);

View 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);

View 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

View 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];
char neigh_sec_str[PREFIX2STR_BUFFER];
if (p->family != AF_INET)
continue;
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);

View 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;

View 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);

View 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)) {
if (PIM_IF_TEST_PIM(pim_ifp->options))
{
/* Interface has a valid primary address ? */
if (PIM_INADDR_ISNOT_ANY(pim_ifp->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);
}
}
/* 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;
}
} /* pim */
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;
}

View 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;
};

View 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;

View 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;
}

View File

@ -34,7 +34,11 @@
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

View 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];

View 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 */

View File

@ -39,12 +39,13 @@
#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;
}

View 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

View 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;

View 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;
}

View 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;

View 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);
}
}
}
}
}
}
}

View 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

View 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)
{
if (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;
pim_find_or_track_nexthop (&nht_p, up, NULL);
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;
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;
}
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 (pnc.nexthop_num)
{
//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));
}
}
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);

View 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);
}

View 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,

View 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)
{

View 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 */

View 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;

View 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;
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;
/* 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);
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)

View 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;

View 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)

View 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

View 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;

View 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.

View 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
<https://github.com/frrouting/frr.git>
Instructions for rebuilding the snap are in `README.snap_build.md`
Instructions for rebuilding the snap are in `snapcraft/README.snap_build.md`
*Please checkout the desired branch before following the instructions
as they may have changed between versions of FRR*
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`

View File

View 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/

View File

@ -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

40
snapcraft/scripts/set-options Executable file
View File

@ -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

View 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

View 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

View 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)