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

This commit is contained in:
Donald Sharp 2017-04-26 07:50:02 -04:00
commit c05f73e0f4
51 changed files with 1700 additions and 407 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,6 +152,7 @@ sigint (void)
if (! retain_mode)
{
bgp_terminate ();
if (bgpd_privs.user) /* NULL if skip_runas flag set */
zprivs_terminate (&bgpd_privs);
}
@ -365,6 +367,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,
@ -372,6 +376,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. */
@ -391,7 +396,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);
@ -408,18 +413,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

@ -8424,7 +8424,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);
@ -8440,7 +8440,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;
}
@ -8554,8 +8554,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);
@ -8818,8 +8817,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

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

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

@ -1531,7 +1531,9 @@ lm_label_manager_connect (struct zclient *zclient)
vrf_id_t vrf_id;
u_int16_t cmd;
if (zclient_debug)
zlog_debug ("Connecting to Label Manager");
if (zclient->sock < 0)
return -1;
@ -1563,6 +1565,7 @@ lm_label_manager_connect (struct zclient *zclient)
zclient->sock = -1;
return -1;
}
if (zclient_debug)
zlog_debug ("%s: Label manager connect request (%d bytes) sent", __func__, ret);
/* read response */
@ -1577,6 +1580,7 @@ lm_label_manager_connect (struct zclient *zclient)
}
/* result */
result = stream_getc(s);
if (zclient_debug)
zlog_debug ("%s: Label Manager connect response (%d bytes) received, result %u",
__func__, size, result);
@ -1609,7 +1613,9 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size,
u_int16_t cmd;
u_char response_keep;
if (zclient_debug)
zlog_debug ("Getting Label Chunk");
if (zclient->sock < 0)
return -1;
@ -1639,6 +1645,7 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size,
zclient->sock = -1;
return -1;
}
if (zclient_debug)
zlog_debug ("%s: Label chunk request (%d bytes) sent", __func__, ret);
/* read response */
@ -1651,7 +1658,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;
}
if (zclient_debug)
zlog_debug ("%s: Label chunk response (%d bytes) received", __func__, size);
/* keep */
response_keep = stream_getc(s);
/* start and end labels */
@ -1672,6 +1681,7 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size,
return -1;
}
if (zclient_debug)
zlog_debug ("Label Chunk assign: %u - %u (%u) ",
*start, *end, response_keep);
@ -1692,7 +1702,9 @@ lm_release_label_chunk (struct zclient *zclient, uint32_t start, uint32_t end)
int ret;
struct stream *s;
if (zclient_debug)
zlog_debug ("Releasing Label Chunk");
if (zclient->sock < 0)
return -1;

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);
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;
@ -2873,11 +3022,13 @@ DEFUN (show_ip_multicast,
vty_out (vty, "%s", VTY_NEWLINE);
vty_out (vty, "Upstream Join Timer: %d secs%s",
qpim_t_periodic,
VTY_NEWLINE);
qpim_t_periodic, VTY_NEWLINE);
vty_out (vty, "Join/Prune Holdtime: %d secs%s",
PIM_JP_HOLDTIME,
VTY_NEWLINE);
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);
@ -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,6 +586,9 @@ 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;
@ -583,19 +601,38 @@ void pim_if_addr_add(struct connected *ifc)
}
} /* 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)) {
if (pim_ifp->pim_sock_fd < 0)
{
if (pim_sock_add (ifp))
{
zlog_warn ("Failure creating PIM socket for interface %s",
ifp->name);
}
}
struct pim_nexthop_cache *pnc = NULL;
struct pim_rpf rpf;
struct zclient *zclient = NULL;
zclient = pim_zebra_zclient_get ();
/* RP config might come prior to (local RP's interface) IF UP event.
In this case, pnc would not have pim enabled nexthops.
Once Interface is UP and pim info is available, reregister
with RNH address to receive update and add the interface as nexthop. */
memset (&rpf, 0, sizeof (struct pim_rpf));
rpf.rpf_addr.family = AF_INET;
rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4;
pnc = pim_nexthop_cache_find (&rpf);
if (pnc)
pim_sendmsg_zebra_rnh (zclient, pnc,
ZEBRA_NEXTHOP_REGISTER);
}
} /* pim */
@ -675,6 +712,9 @@ 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);
@ -709,11 +749,8 @@ void pim_if_addr_add_all(struct interface *ifp)
struct prefix *p = ifc->address;
if (p->family != AF_INET)
{
v6_addrs++;
continue;
}
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) {
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))
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;
@ -386,25 +450,6 @@ 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 (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp))
@ -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,7 +719,8 @@ 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.",
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",
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;
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,19 +389,29 @@ 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);
}
pim_find_or_track_nexthop (&nht_p, NULL, rp_all);
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_rp_check_interfaces (rp_all);
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);
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,12 +560,33 @@ 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;
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)
{
//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)
@ -548,6 +594,7 @@ pim_rp_setup (void)
ret++;
}
}
}
if (ret)
return 0;
@ -680,7 +727,43 @@ pim_rp_g (struct in_addr group)
if (rp_info)
{
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,16 +193,18 @@ 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 (PIM_DEBUG_ZEBRA)
if (is_new && PIM_DEBUG_ZEBRA)
{
char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<source?>", up->upstream_addr, source_str, sizeof(source_str));
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);
}
@ -207,15 +212,37 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old,
nht_p.family = AF_INET;
nht_p.prefixlen = IPV4_MAX_BITLEN;
nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
pim_find_or_track_nexthop (&nht_p, up, NULL);
}
if (pim_nexthop_lookup(&rpf->source_nexthop,
up->upstream_addr,
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))) {
!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,9 +252,15 @@ 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)
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;
option_len += 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)
{
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,7 +240,7 @@ pim_upstream_del(struct pim_upstream *up, const char *name)
{
char buf[PREFIX2STR_BUFFER];
prefix2str (&nht_p, buf, sizeof (buf));
zlog_debug ("%s: Deregister upstream %s upstream addr %s with NHT ",
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;
}
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,
@ -1103,6 +1122,11 @@ pim_upstream_keep_alive_timer (struct thread *t)
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,7 +1657,8 @@ pim_upstream_sg_running (void *arg)
return;
}
if (pim_upstream_kat_start_ok(up)) {
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))
@ -1647,6 +1672,8 @@ pim_upstream_sg_running (void *arg)
}
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)
{
@ -1655,6 +1682,42 @@ pim_upstream_sg_running (void *arg)
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,6 +1051,7 @@ 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];
@ -1027,9 +1066,61 @@ void pim_forward_start(struct pim_ifchannel *ch)
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) {
/* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
as part of mroute_del called by pim_forward_stop.
*/
if (!up->channel_oil ||
(up->channel_oil && up->channel_oil->oil.mfcc_parent >= MAXVIFS))
{
struct prefix nht_p, src, grp;
int ret = 0;
struct pim_nexthop_cache out_pnc;
struct pim_nexthop nexthop;
/* Register addr with Zebra NHT */
nht_p.family = AF_INET;
nht_p.prefixlen = IPV4_MAX_BITLEN;
nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
grp.family = AF_INET;
grp.prefixlen = IPV4_MAX_BITLEN;
grp.u.prefix4 = up->sg.grp;
memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache));
if ((ret =
pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1)
{
if (out_pnc.nexthop_num)
{
src.family = AF_INET;
src.prefixlen = IPV4_MAX_BITLEN;
src.u.prefix4 = up->upstream_addr; //RP or Src address
grp.family = AF_INET;
grp.prefixlen = IPV4_MAX_BITLEN;
grp.u.prefix4 = up->sg.grp;
memset (&nexthop, 0, sizeof (nexthop));
//Compute PIM RPF using Cached nexthop
pim_ecmp_nexthop_search (&out_pnc, &nexthop, &src, &grp, 0);
input_iface_vif_index =
pim_if_find_vifindex_by_ifindex (nexthop.interface->ifindex);
}
else
{
if (PIM_DEBUG_ZEBRA)
{
char buf1[INET_ADDRSTRLEN];
char buf2[INET_ADDRSTRLEN];
pim_inet4_dump("<source?>", nht_p.u.prefix4, buf1, sizeof(buf1));
pim_inet4_dump("<source?>", grp.u.prefix4, buf2, sizeof(buf2));
zlog_debug ("%s: NHT pnc is NULL for addr %s grp %s" ,
__PRETTY_FUNCTION__, buf1, buf2);
}
}
}
else
input_iface_vif_index = fib_lookup_if_vif_index (up->upstream_addr);
if (input_iface_vif_index < 1)
{
if (PIM_DEBUG_PIM_TRACE)
{
char source_str[INET_ADDRSTRLEN];
@ -1040,14 +1131,17 @@ void pim_forward_start(struct pim_ifchannel *ch)
}
return;
}
up->channel_oil = pim_channel_oil_add(&up->sg,
input_iface_vif_index);
if (!up->channel_oil) {
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);
__FILE__, __PRETTY_FUNCTION__, up->sg_str);
return;
}
}

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,8 +252,23 @@ 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);
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)
{

View File

@ -75,6 +75,8 @@ 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;
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;
@ -116,6 +118,9 @@ pim_vrf_enable (struct vrf *vrf)
*/
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

@ -1242,9 +1242,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;
}