From abbda2d481aa1959b3f93efe3eb27397e58a3c18 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Mon, 27 Jun 2016 08:31:57 -0700 Subject: [PATCH 1/5] zebra: resolved problem with show ip route vrf Repaired damage done by commit upstream, which changed the way show_ip_route is called to allow for multicast rpf table display. Matched the technique of the other callers to the new function. Ticket: CM-11345 Signed-off-by: Don Slice Reviewed By: Donald Sharp Testing Done: Manual testing and vrf-min --- zebra/zebra_vty.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 185f866916..e9090cbed2 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -2227,13 +2227,16 @@ do_show_ip_route(struct vty *vty, const char *vrf_name, safi_t safi) return CMD_SUCCESS; } -ALIAS (show_ip_route, +DEFUN (show_ip_route_vrf, show_ip_route_vrf_cmd, "show ip route " VRF_CMD_STR, SHOW_STR IP_STR "IP routing table\n" VRF_CMD_HELP_STR) +{ + return do_show_ip_route (vty, argv[0], SAFI_UNICAST); +} DEFUN (show_ip_nht, show_ip_nht_cmd, From 82f9fd9646a6798beeafb63e1e818f2d94989aea Mon Sep 17 00:00:00 2001 From: Dave Olson Date: Mon, 27 Jun 2016 09:10:46 -0700 Subject: [PATCH 2/5] Provide example on how to run sudo vtysh show commands without password Ticket: CM-4709 Reviewed By: dsharp Testing Done: Uncommented, ran show commands See the comments added, and in the bug. Set up for users in group quagga, with NOEXEC to not open security holes. --- cumulus/etc/sudoers.d/quagga_sudoers | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cumulus/etc/sudoers.d/quagga_sudoers b/cumulus/etc/sudoers.d/quagga_sudoers index 972966c6a8..4375d7e5fa 100644 --- a/cumulus/etc/sudoers.d/quagga_sudoers +++ b/cumulus/etc/sudoers.d/quagga_sudoers @@ -1 +1,15 @@ Defaults env_keep += VTYSH_PAGER + +# Allow user in group quagga to run vtysh show commands +# without a password by uncommenting the "%quagga" line below. + +# Subshell commands need to be disallowed, including +# preventing the user passing command line args like 'start-shell' +# Since vtysh allows minimum non-conflicting prefix'es, that means +# anything beginning with the string "st" in any arg. That's a bit +# restrictive. +# Instead, use NOEXEC, to prevent any exec'ed commands. + +Cmnd_Alias VTY_SHOW = /usr/bin/vtysh -c show * +# %quagga ALL = (root) NOPASSWD:NOEXEC: VTY_SHOW + From d3aded9982a2928f98d7b983593bae304efcf268 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 27 Jun 2016 12:54:30 -0400 Subject: [PATCH 3/5] pimd: Allow (*,G) to work properly. When the kernel looks up a *,G route it expects the incoming interface to be part of the outgoing interface ttl list. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index f85f422298..4bf490f456 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -524,6 +524,7 @@ int pim_mroute_del_vif(int vif_index) int pim_mroute_add(struct mfcctl *mc) { int err; + int orig; qpim_mroute_add_last = pim_time_monotonic_sec(); ++qpim_mroute_add_events; @@ -534,8 +535,22 @@ int pim_mroute_add(struct mfcctl *mc) return -1; } + /* The linux kernel *expects* the incoming + * vif to be part of the outgoing list + * in the case of a (*,G). + */ + if (mc->mfcc_origin.s_addr == INADDR_ANY) + { + orig = mc->mfcc_ttls[mc->mfcc_parent]; + mc->mfcc_ttls[mc->mfcc_parent] = 1; + } + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, mc, sizeof(*mc)); + + if (mc->mfcc_origin.s_addr == INADDR_ANY) + mc->mfcc_ttls[mc->mfcc_parent] = orig; + if (err) { int e = errno; zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s", From 8a67a996bc0e8d3ff0792e1c0b53313170545700 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 27 Jun 2016 15:06:46 -0400 Subject: [PATCH 4/5] pimd: Refactor pim_scan_oil Allow the workings of pim_scan_oil to be called on a per channel basis. Signed-off-by: Donald Sharp --- pimd/pim_zebra.c | 58 ++++++++++++++++++++++++++++-------------------- pimd/pim_zebra.h | 1 + 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index e947ff87c5..5918a5192d 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -383,19 +383,14 @@ static void scan_upstream_rpf_cache() } -void pim_scan_oil() +void +pim_scan_individual_oil (struct channel_oil *c_oil) { - struct listnode *node; - struct listnode *nextnode; - struct channel_oil *c_oil; + int old_vif_index; + int input_iface_vif_index = fib_lookup_if_vif_index(c_oil->oil.mfcc_origin); - qpim_scan_oil_last = pim_time_monotonic_sec(); - ++qpim_scan_oil_events; - - for (ALL_LIST_ELEMENTS(qpim_channel_oil_list, node, nextnode, c_oil)) { - int old_vif_index; - int input_iface_vif_index = fib_lookup_if_vif_index(c_oil->oil.mfcc_origin); - if (input_iface_vif_index < 1) { + if (input_iface_vif_index < 1) + { char source_str[100]; char group_str[100]; pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); @@ -403,15 +398,17 @@ void pim_scan_oil() zlog_warn("%s %s: could not find input interface for (S,G)=(%s,%s)", __FILE__, __PRETTY_FUNCTION__, source_str, group_str); - continue; + return; } - if (input_iface_vif_index == c_oil->oil.mfcc_parent) { + if (input_iface_vif_index == c_oil->oil.mfcc_parent) + { /* RPF unchanged */ - continue; + return; } - if (PIM_DEBUG_ZEBRA) { + if (PIM_DEBUG_ZEBRA) + { struct interface *old_iif = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); char source_str[100]; @@ -425,8 +422,9 @@ void pim_scan_oil() new_iif ? new_iif->name : "", input_iface_vif_index); } - /* new iif loops to existing oif ? */ - if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) { + /* new iif loops to existing oif ? */ + if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) + { struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); if (PIM_DEBUG_ZEBRA) { @@ -447,8 +445,10 @@ void pim_scan_oil() old_vif_index = c_oil->oil.mfcc_parent; c_oil->oil.mfcc_parent = input_iface_vif_index; + zlog_debug ("FF"); /* update kernel multicast forwarding cache (MFC) */ - if (pim_mroute_add(&c_oil->oil)) { + if (pim_mroute_add(&c_oil->oil)) + { /* just log warning */ struct interface *old_iif = pim_if_find_by_vif_index(old_vif_index); struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); @@ -457,14 +457,24 @@ void pim_scan_oil() pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); zlog_warn("%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - old_iif ? old_iif->name : "", c_oil->oil.mfcc_parent, - new_iif ? new_iif->name : "", input_iface_vif_index); - continue; + __FILE__, __PRETTY_FUNCTION__, + source_str, group_str, + old_iif ? old_iif->name : "", c_oil->oil.mfcc_parent, + new_iif ? new_iif->name : "", input_iface_vif_index); } +} - } /* for (qpim_channel_oil_list) */ +void pim_scan_oil() +{ + struct listnode *node; + struct listnode *nextnode; + struct channel_oil *c_oil; + + qpim_scan_oil_last = pim_time_monotonic_sec(); + ++qpim_scan_oil_events; + + for (ALL_LIST_ELEMENTS(qpim_channel_oil_list, node, nextnode, c_oil)) + pim_scan_individual_oil (c_oil); } static int on_rpf_cache_refresh(struct thread *t) diff --git a/pimd/pim_zebra.h b/pimd/pim_zebra.h index d624c86661..8e8f09551a 100644 --- a/pimd/pim_zebra.h +++ b/pimd/pim_zebra.h @@ -28,6 +28,7 @@ void pim_zebra_init(char *zebra_sock_path); +void pim_scan_individual_oil (struct channel_oil *c_oil); void pim_scan_oil(void); void igmp_anysource_forward_start(struct igmp_group *group); From 2ca35b3d73e8e3efe781990c4cf3f24853e477a5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 27 Jun 2016 14:51:04 -0400 Subject: [PATCH 5/5] pimd: When receiving the register packet, create the mroute When a RP receives the register packet, move the (*,G) to a (S,G) route and send the pim message upstream to the source. With this change the multicast packets are sent from the source to the interested parties. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 2 +- pimd/pim_register.c | 27 +++++++++++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 4bf490f456..624264b3b5 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -524,7 +524,7 @@ int pim_mroute_del_vif(int vif_index) int pim_mroute_add(struct mfcctl *mc) { int err; - int orig; + int orig = 0; qpim_mroute_add_last = pim_time_monotonic_sec(); ++qpim_mroute_add_events; diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 07f9652fe8..ce3ac1a433 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -35,6 +35,10 @@ #include "pim_register.h" #include "pim_upstream.h" #include "pim_br.h" +#include "pim_rpf.h" +#include "pim_oil.h" +#include "pim_zebra.h" +#include "pim_join.h" struct thread *send_test_packet_timer = NULL; @@ -250,10 +254,25 @@ pim_register_recv (struct interface *ifp, } if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) && - !(*bits & PIM_REGISTER_NR_BIT)) { - //decapsulate and forward the iner packet to - //inherited_olist(S,G,rpt) - } + !(*bits & PIM_REGISTER_NR_BIT)) + { + pim_rp_set_upstream_addr (&upstream->upstream_addr, source); + pim_nexthop_lookup (&upstream->rpf.source_nexthop, + upstream->upstream_addr, NULL); + upstream->rpf.source_nexthop.interface = ifp; + upstream->source_addr.s_addr = source.s_addr; + upstream->rpf.rpf_addr.s_addr = source.s_addr; + upstream->channel_oil->oil.mfcc_origin = source; + pim_scan_individual_oil (upstream->channel_oil); + pim_joinprune_send(upstream->rpf.source_nexthop.interface, + upstream->rpf.source_nexthop.mrib_nexthop_addr, + upstream->source_addr, + upstream->group_addr, + 1); + + //decapsulate and forward the iner packet to + //inherited_olist(S,G,rpt) + } } else { pim_register_stop_send(src_addr); }