mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 23:54:45 +00:00
Merge pull request #2110 from msablic/pim_mtrace_group
pimd: adding querying of state to mtrace
This commit is contained in:
commit
97722e560e
@ -9,17 +9,22 @@ SYNOPSIS
|
|||||||
========
|
========
|
||||||
|PROGRAM| |synopsis-options-hv|
|
|PROGRAM| |synopsis-options-hv|
|
||||||
|
|
||||||
|PROGRAM| <multicast source>
|
|PROGRAM| <multicast source> [<multicast group>]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
===========
|
===========
|
||||||
|PROGRAM| is a program to initiate multicast traceroute, or "mtrace", queries.
|
|PROGRAM| is a program for initiating multicast traceroute, or "mtrace", queries.
|
||||||
|
|
||||||
The initial version of the program requires multicast source IP address and
|
It can initiate two types of mtrace queries: weak and group.
|
||||||
initiates a weak traceroute across the network. This tests whether the
|
|
||||||
interfaces towards the source are multicast enabled. The first query sent is a
|
Weak tests whether the interfaces towards the source are multicast enabled and is
|
||||||
full query, capable of crossing the network all the way to the source. If this
|
initiated by supplying only the multicast source address.
|
||||||
fails, hop-by-hop queries are initiated.
|
|
||||||
|
Group tests whether there is multicast routing protocol state for particular
|
||||||
|
multicast group and is initiated by supplying mutlicast source and group.
|
||||||
|
|
||||||
|
The first query sent is a full query, capable of crossing the network all the way
|
||||||
|
to the source. If this fails, hop-by-hop queries are initiated.
|
||||||
|
|
||||||
Hop-by-hop queries start by requesting only a response from the nearest router.
|
Hop-by-hop queries start by requesting only a response from the nearest router.
|
||||||
Following that, next query is extended to the next two routers, and so on...
|
Following that, next query is extended to the next two routers, and so on...
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "pim_igmp_mtrace.h"
|
#include "pim_igmp_mtrace.h"
|
||||||
|
|
||||||
#include "checksum.h"
|
#include "checksum.h"
|
||||||
|
#include "prefix.h"
|
||||||
#include "mtracebis_routeget.h"
|
#include "mtracebis_routeget.h"
|
||||||
|
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
@ -50,7 +51,8 @@
|
|||||||
static const char *progname;
|
static const char *progname;
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage : %s <multicast source>\n", progname);
|
fprintf(stderr, "Usage : %s <multicast source> [<multicast group>]\n",
|
||||||
|
progname);
|
||||||
}
|
}
|
||||||
static void version(void)
|
static void version(void)
|
||||||
{
|
{
|
||||||
@ -170,9 +172,21 @@ static void print_fwd_code(uint32_t fwd_code)
|
|||||||
static void print_rsp(struct igmp_mtrace_rsp *rsp)
|
static void print_rsp(struct igmp_mtrace_rsp *rsp)
|
||||||
{
|
{
|
||||||
print_host(rsp->outgoing);
|
print_host(rsp->outgoing);
|
||||||
if (rsp->fwd_code == 0) {
|
if (rsp->fwd_code == 0 || rsp->fwd_code == MTRACE_FWD_CODE_REACHED_RP) {
|
||||||
print_rtg_proto(rsp->rtg_proto);
|
print_rtg_proto(rsp->rtg_proto);
|
||||||
printf(" ");
|
printf(" ");
|
||||||
|
if (rsp->fwd_code == MTRACE_FWD_CODE_REACHED_RP)
|
||||||
|
printf("(RP) ");
|
||||||
|
if (rsp->rtg_proto == MTRACE_RTG_PROTO_PIM) {
|
||||||
|
switch (rsp->src_mask) {
|
||||||
|
case MTRACE_SRC_MASK_GROUP:
|
||||||
|
printf("(*,G) ");
|
||||||
|
break;
|
||||||
|
case MTRACE_SRC_MASK_SOURCE:
|
||||||
|
printf("(S,G) ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
print_fwd_ttl(rsp->fwd_ttl);
|
print_fwd_ttl(rsp->fwd_ttl);
|
||||||
} else {
|
} else {
|
||||||
print_fwd_code(rsp->fwd_code);
|
print_fwd_code(rsp->fwd_code);
|
||||||
@ -351,6 +365,7 @@ static bool check_end(struct igmp_mtrace *mtrace, int hops)
|
|||||||
int main(int argc, char *const argv[])
|
int main(int argc, char *const argv[])
|
||||||
{
|
{
|
||||||
struct in_addr mc_source;
|
struct in_addr mc_source;
|
||||||
|
struct in_addr mc_group;
|
||||||
struct in_addr iface_addr;
|
struct in_addr iface_addr;
|
||||||
struct in_addr gw_addr;
|
struct in_addr gw_addr;
|
||||||
struct in_addr mtrace_addr;
|
struct in_addr mtrace_addr;
|
||||||
@ -370,6 +385,7 @@ int main(int argc, char *const argv[])
|
|||||||
int i, j;
|
int i, j;
|
||||||
char ifname[IF_NAMESIZE];
|
char ifname[IF_NAMESIZE];
|
||||||
char mbuf[MTRACE_BUF_LEN];
|
char mbuf[MTRACE_BUF_LEN];
|
||||||
|
bool not_group;
|
||||||
|
|
||||||
mtrace_addr.s_addr = inet_addr("224.0.1.32");
|
mtrace_addr.s_addr = inet_addr("224.0.1.32");
|
||||||
|
|
||||||
@ -385,7 +401,7 @@ int main(int argc, char *const argv[])
|
|||||||
else
|
else
|
||||||
progname = argv[0];
|
progname = argv[0];
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2 && argc != 3) {
|
||||||
usage();
|
usage();
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -416,11 +432,28 @@ int main(int argc, char *const argv[])
|
|||||||
}
|
}
|
||||||
if (inet_pton(AF_INET, argv[1], &mc_source) != 1) {
|
if (inet_pton(AF_INET, argv[1], &mc_source) != 1) {
|
||||||
usage();
|
usage();
|
||||||
fprintf(stderr, "%s: %s not a valid IPv4 address\n", argv[0],
|
fprintf(stderr, "%s: %s is not a valid IPv4 address\n", argv[0],
|
||||||
argv[1]);
|
argv[1]);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mc_group.s_addr = 0;
|
||||||
|
not_group = false;
|
||||||
|
|
||||||
|
if (argc == 3) {
|
||||||
|
if (inet_pton(AF_INET, argv[2], &mc_group) != 1)
|
||||||
|
not_group = true;
|
||||||
|
if (!not_group && !IPV4_CLASS_DE(ntohl(mc_group.s_addr)))
|
||||||
|
not_group = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not_group) {
|
||||||
|
usage();
|
||||||
|
fprintf(stderr, "%s: %s is not a valid IPv4 group address\n",
|
||||||
|
argv[0], argv[2]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
ifindex = routeget(mc_source, &iface_addr, &gw_addr);
|
ifindex = routeget(mc_source, &iface_addr, &gw_addr);
|
||||||
if (ifindex < 0) {
|
if (ifindex < 0) {
|
||||||
fprintf(stderr, "%s: failed to get route to source %s\n",
|
fprintf(stderr, "%s: failed to get route to source %s\n",
|
||||||
@ -441,7 +474,7 @@ int main(int argc, char *const argv[])
|
|||||||
mtrace.type = PIM_IGMP_MTRACE_QUERY_REQUEST;
|
mtrace.type = PIM_IGMP_MTRACE_QUERY_REQUEST;
|
||||||
mtrace.hops = hops;
|
mtrace.hops = hops;
|
||||||
mtrace.checksum = 0;
|
mtrace.checksum = 0;
|
||||||
mtrace.grp_addr.s_addr = 0;
|
mtrace.grp_addr = mc_group;
|
||||||
mtrace.src_addr = mc_source;
|
mtrace.src_addr = mc_source;
|
||||||
mtrace.dst_addr = iface_addr;
|
mtrace.dst_addr = iface_addr;
|
||||||
mtrace.rsp_addr = unicast ? iface_addr : mtrace_addr;
|
mtrace.rsp_addr = unicast ? iface_addr : mtrace_addr;
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* based on draft-ietf-idmr-traceroute-ipm-07 */
|
||||||
|
|
||||||
#include <zebra.h>
|
#include <zebra.h>
|
||||||
|
|
||||||
#include "pimd.h"
|
#include "pimd.h"
|
||||||
@ -56,15 +58,131 @@ static struct in_addr mtrace_primary_address(struct interface *ifp)
|
|||||||
return any;
|
return any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool mtrace_fwd_info_weak(struct pim_instance *pim,
|
||||||
|
struct igmp_mtrace *mtracep,
|
||||||
|
struct igmp_mtrace_rsp *rspp,
|
||||||
|
struct interface **ifpp)
|
||||||
|
{
|
||||||
|
struct pim_nexthop nexthop;
|
||||||
|
struct interface *ifp_in;
|
||||||
|
struct in_addr nh_addr;
|
||||||
|
int ret;
|
||||||
|
char nexthop_str[INET_ADDRSTRLEN];
|
||||||
|
|
||||||
|
nh_addr.s_addr = 0;
|
||||||
|
|
||||||
|
memset(&nexthop, 0, sizeof(nexthop));
|
||||||
|
|
||||||
|
ret = pim_nexthop_lookup(pim, &nexthop, mtracep->src_addr, 1);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
if (PIM_DEBUG_MTRACE)
|
||||||
|
zlog_debug("mtrace not found neighbor");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PIM_DEBUG_MTRACE)
|
||||||
|
zlog_debug("mtrace pim_nexthop_lookup OK");
|
||||||
|
|
||||||
|
if (PIM_DEBUG_MTRACE)
|
||||||
|
zlog_warn("mtrace next_hop=%s",
|
||||||
|
inet_ntop(nexthop.mrib_nexthop_addr.family,
|
||||||
|
&nexthop.mrib_nexthop_addr.u.prefix,
|
||||||
|
nexthop_str, sizeof(nexthop_str)));
|
||||||
|
|
||||||
|
if (nexthop.mrib_nexthop_addr.family == AF_INET)
|
||||||
|
nh_addr = nexthop.mrib_nexthop_addr.u.prefix4;
|
||||||
|
|
||||||
|
ifp_in = nexthop.interface;
|
||||||
|
|
||||||
|
/* return interface for forwarding mtrace packets */
|
||||||
|
*ifpp = ifp_in;
|
||||||
|
|
||||||
|
/* 6.2.2. 4. Fill in the Incoming Interface Address... */
|
||||||
|
rspp->incoming = mtrace_primary_address(ifp_in);
|
||||||
|
rspp->prev_hop = nh_addr;
|
||||||
|
rspp->in_count = htonl(MTRACE_UNKNOWN_COUNT);
|
||||||
|
rspp->total = htonl(MTRACE_UNKNOWN_COUNT);
|
||||||
|
rspp->rtg_proto = MTRACE_RTG_PROTO_PIM;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mtrace_fwd_info(struct pim_instance *pim,
|
||||||
|
struct igmp_mtrace *mtracep,
|
||||||
|
struct igmp_mtrace_rsp *rspp,
|
||||||
|
struct interface **ifpp)
|
||||||
|
{
|
||||||
|
struct prefix_sg sg;
|
||||||
|
struct pim_upstream *up;
|
||||||
|
struct interface *ifp_in;
|
||||||
|
struct in_addr nh_addr;
|
||||||
|
uint32_t total;
|
||||||
|
char up_str[INET_ADDRSTRLEN];
|
||||||
|
|
||||||
|
memset(&sg, 0, sizeof(struct prefix_sg));
|
||||||
|
sg.src = mtracep->src_addr;
|
||||||
|
sg.grp = mtracep->grp_addr;
|
||||||
|
|
||||||
|
up = pim_upstream_find(pim, &sg);
|
||||||
|
|
||||||
|
if (!up) {
|
||||||
|
sg.src.s_addr = 0;
|
||||||
|
up = pim_upstream_find(pim, &sg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!up)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ifp_in = up->rpf.source_nexthop.interface;
|
||||||
|
nh_addr = up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4;
|
||||||
|
total = htonl(MTRACE_UNKNOWN_COUNT);
|
||||||
|
|
||||||
|
if (PIM_DEBUG_MTRACE)
|
||||||
|
zlog_debug("fwd_info: upstream next hop=%s",
|
||||||
|
inet_ntop(AF_INET, &(nh_addr), up_str,
|
||||||
|
sizeof(up_str)));
|
||||||
|
|
||||||
|
if (up->channel_oil)
|
||||||
|
total = up->channel_oil->cc.pktcnt;
|
||||||
|
|
||||||
|
/* return interface for forwarding mtrace packets */
|
||||||
|
*ifpp = ifp_in;
|
||||||
|
|
||||||
|
/* 6.2.2. 4. Fill in the Incoming Interface Address... */
|
||||||
|
rspp->incoming = mtrace_primary_address(ifp_in);
|
||||||
|
rspp->prev_hop = nh_addr;
|
||||||
|
rspp->in_count = htonl(MTRACE_UNKNOWN_COUNT);
|
||||||
|
rspp->total = total;
|
||||||
|
rspp->rtg_proto = MTRACE_RTG_PROTO_PIM;
|
||||||
|
|
||||||
|
/* 6.2.2. 4. Fill in ... S, and Src Mask */
|
||||||
|
if (sg.src.s_addr) {
|
||||||
|
rspp->s = 1;
|
||||||
|
rspp->src_mask = MTRACE_SRC_MASK_SOURCE;
|
||||||
|
} else {
|
||||||
|
rspp->s = 0;
|
||||||
|
rspp->src_mask = MTRACE_SRC_MASK_GROUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mtrace_rsp_set_fwd_code(struct igmp_mtrace_rsp *mtrace_rspp,
|
||||||
|
enum mtrace_fwd_code fwd_code)
|
||||||
|
{
|
||||||
|
if (mtrace_rspp->fwd_code == MTRACE_FWD_CODE_NO_ERROR)
|
||||||
|
mtrace_rspp->fwd_code = fwd_code;
|
||||||
|
}
|
||||||
|
|
||||||
static void mtrace_rsp_init(struct igmp_mtrace_rsp *mtrace_rspp)
|
static void mtrace_rsp_init(struct igmp_mtrace_rsp *mtrace_rspp)
|
||||||
{
|
{
|
||||||
mtrace_rspp->arrival = 0;
|
mtrace_rspp->arrival = 0;
|
||||||
mtrace_rspp->incoming.s_addr = 0;
|
mtrace_rspp->incoming.s_addr = 0;
|
||||||
mtrace_rspp->outgoing.s_addr = 0;
|
mtrace_rspp->outgoing.s_addr = 0;
|
||||||
mtrace_rspp->prev_hop.s_addr = 0;
|
mtrace_rspp->prev_hop.s_addr = 0;
|
||||||
mtrace_rspp->in_count = MTRACE_UNKNOWN_COUNT;
|
mtrace_rspp->in_count = htonl(MTRACE_UNKNOWN_COUNT);
|
||||||
mtrace_rspp->out_count = MTRACE_UNKNOWN_COUNT;
|
mtrace_rspp->out_count = htonl(MTRACE_UNKNOWN_COUNT);
|
||||||
mtrace_rspp->total = MTRACE_UNKNOWN_COUNT;
|
mtrace_rspp->total = htonl(MTRACE_UNKNOWN_COUNT);
|
||||||
mtrace_rspp->rtg_proto = 0;
|
mtrace_rspp->rtg_proto = 0;
|
||||||
mtrace_rspp->fwd_ttl = 0;
|
mtrace_rspp->fwd_ttl = 0;
|
||||||
mtrace_rspp->mbz = 0;
|
mtrace_rspp->mbz = 0;
|
||||||
@ -394,7 +512,6 @@ static int mtrace_forward_packet(struct pim_instance *pim, struct ip *ip_hdr)
|
|||||||
return mtrace_un_forward_packet(pim, ip_hdr, NULL);
|
return mtrace_un_forward_packet(pim, ip_hdr, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 6.5 Sending Traceroute Responses */
|
|
||||||
static int mtrace_send_mc_response(struct pim_instance *pim,
|
static int mtrace_send_mc_response(struct pim_instance *pim,
|
||||||
struct igmp_mtrace *mtracep,
|
struct igmp_mtrace *mtracep,
|
||||||
size_t mtrace_len)
|
size_t mtrace_len)
|
||||||
@ -439,6 +556,7 @@ static int mtrace_send_mc_response(struct pim_instance *pim,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 6.5 Sending Traceroute Responses */
|
||||||
static int mtrace_send_response(struct pim_instance *pim,
|
static int mtrace_send_response(struct pim_instance *pim,
|
||||||
struct igmp_mtrace *mtracep, size_t mtrace_len)
|
struct igmp_mtrace *mtracep, size_t mtrace_len)
|
||||||
{
|
{
|
||||||
@ -496,7 +614,6 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr,
|
|||||||
{
|
{
|
||||||
static uint32_t qry_id, qry_src;
|
static uint32_t qry_id, qry_src;
|
||||||
char mtrace_buf[MTRACE_HDR_SIZE + MTRACE_MAX_HOPS * MTRACE_RSP_SIZE];
|
char mtrace_buf[MTRACE_HDR_SIZE + MTRACE_MAX_HOPS * MTRACE_RSP_SIZE];
|
||||||
struct pim_nexthop nexthop;
|
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
struct interface *out_ifp;
|
struct interface *out_ifp;
|
||||||
struct pim_interface *pim_ifp;
|
struct pim_interface *pim_ifp;
|
||||||
@ -505,12 +622,13 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr,
|
|||||||
struct igmp_mtrace_rsp *rspp;
|
struct igmp_mtrace_rsp *rspp;
|
||||||
struct in_addr nh_addr;
|
struct in_addr nh_addr;
|
||||||
enum mtrace_fwd_code fwd_code = MTRACE_FWD_CODE_NO_ERROR;
|
enum mtrace_fwd_code fwd_code = MTRACE_FWD_CODE_NO_ERROR;
|
||||||
int ret;
|
|
||||||
size_t r_len;
|
size_t r_len;
|
||||||
int last_rsp_ind = 0;
|
int last_rsp_ind = 0;
|
||||||
size_t mtrace_len;
|
size_t mtrace_len;
|
||||||
uint16_t recv_checksum;
|
uint16_t recv_checksum;
|
||||||
uint16_t checksum;
|
uint16_t checksum;
|
||||||
|
bool reached_source;
|
||||||
|
bool fwd_info;
|
||||||
|
|
||||||
ifp = igmp->interface;
|
ifp = igmp->interface;
|
||||||
pim_ifp = ifp->info;
|
pim_ifp = ifp->info;
|
||||||
@ -575,6 +693,8 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr,
|
|||||||
}
|
}
|
||||||
/* Unicast query on wrong interface */
|
/* Unicast query on wrong interface */
|
||||||
fwd_code = MTRACE_FWD_CODE_WRONG_IF;
|
fwd_code = MTRACE_FWD_CODE_WRONG_IF;
|
||||||
|
if (PIM_DEBUG_MTRACE)
|
||||||
|
zlog_debug("Multicast query on wrong interface");
|
||||||
}
|
}
|
||||||
if (qry_id == mtracep->qry_id && qry_src == from.s_addr) {
|
if (qry_id == mtracep->qry_id && qry_src == from.s_addr) {
|
||||||
if (PIM_DEBUG_MTRACE)
|
if (PIM_DEBUG_MTRACE)
|
||||||
@ -619,16 +739,19 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr,
|
|||||||
|
|
||||||
/* 6.2.2. Normal Processing */
|
/* 6.2.2. Normal Processing */
|
||||||
|
|
||||||
/* 6.2.2. 1. */
|
/* 6.2.2. 1. If there is room in the current buffer? */
|
||||||
|
|
||||||
if (last_rsp_ind == MTRACE_MAX_HOPS) {
|
if (last_rsp_ind == MTRACE_MAX_HOPS) {
|
||||||
|
/* ...there was no room... */
|
||||||
mtracep->rsp[MTRACE_MAX_HOPS - 1].fwd_code =
|
mtracep->rsp[MTRACE_MAX_HOPS - 1].fwd_code =
|
||||||
MTRACE_FWD_CODE_NO_SPACE;
|
MTRACE_FWD_CODE_NO_SPACE;
|
||||||
return mtrace_send_response(pim_ifp->pim, mtracep,
|
return mtrace_send_response(pim_ifp->pim, mtracep,
|
||||||
igmp_msg_len);
|
igmp_msg_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculate new mtrace mtrace lenght with extra response */
|
/* ...insert new response block... */
|
||||||
|
|
||||||
|
/* calculate new mtrace lenght with extra response */
|
||||||
mtrace_len = igmp_msg_len + sizeof(struct igmp_mtrace_rsp);
|
mtrace_len = igmp_msg_len + sizeof(struct igmp_mtrace_rsp);
|
||||||
|
|
||||||
/* copy received query/request */
|
/* copy received query/request */
|
||||||
@ -643,84 +766,86 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr,
|
|||||||
/* initialize extra response field */
|
/* initialize extra response field */
|
||||||
mtrace_rsp_init(rspp);
|
mtrace_rsp_init(rspp);
|
||||||
|
|
||||||
|
/* carry over any error noted when receiving the query */
|
||||||
|
rspp->fwd_code = fwd_code;
|
||||||
|
|
||||||
|
/* ...and fill in Query Arrival Time... */
|
||||||
rspp->arrival = htonl(query_arrival_time());
|
rspp->arrival = htonl(query_arrival_time());
|
||||||
rspp->outgoing = pim_ifp->primary_address;
|
rspp->outgoing = pim_ifp->primary_address;
|
||||||
rspp->out_count = htonl(MTRACE_UNKNOWN_COUNT);
|
rspp->out_count = htonl(MTRACE_UNKNOWN_COUNT);
|
||||||
|
rspp->fwd_ttl = 1;
|
||||||
|
|
||||||
/* 6.2.2. 2. Attempt to determine forwarding information */
|
/* 6.2.2. 2. Attempt to determine the forwarding information... */
|
||||||
|
|
||||||
nh_addr.s_addr = 0;
|
if (mtracep->grp_addr.s_addr)
|
||||||
|
fwd_info = mtrace_fwd_info(pim, mtracep, rspp, &out_ifp);
|
||||||
memset(&nexthop, 0, sizeof(nexthop));
|
|
||||||
ret = pim_nexthop_lookup(pim, &nexthop, mtracep->src_addr, 1);
|
|
||||||
|
|
||||||
if (ret == 0) {
|
|
||||||
char nexthop_str[INET_ADDRSTRLEN];
|
|
||||||
|
|
||||||
if (PIM_DEBUG_MTRACE)
|
|
||||||
zlog_debug("mtrace pim_nexthop_lookup OK");
|
|
||||||
|
|
||||||
if (PIM_DEBUG_MTRACE)
|
|
||||||
zlog_warn("mtrace next_hop=%s",
|
|
||||||
inet_ntop(nexthop.mrib_nexthop_addr.family,
|
|
||||||
&nexthop.mrib_nexthop_addr.u.prefix,
|
|
||||||
nexthop_str, sizeof(nexthop_str)));
|
|
||||||
|
|
||||||
if (nexthop.mrib_nexthop_addr.family == AF_INET)
|
|
||||||
nh_addr = nexthop.mrib_nexthop_addr.u.prefix4;
|
|
||||||
}
|
|
||||||
/* 6.4 Forwarding Traceroute Requests: ... Otherwise, ... */
|
|
||||||
else {
|
|
||||||
if (PIM_DEBUG_MTRACE)
|
|
||||||
zlog_debug("mtrace not found neighbor");
|
|
||||||
if (!fwd_code)
|
|
||||||
rspp->fwd_code = MTRACE_FWD_CODE_NO_ROUTE;
|
|
||||||
else
|
else
|
||||||
rspp->fwd_code = fwd_code;
|
fwd_info = mtrace_fwd_info_weak(pim, mtracep, rspp, &out_ifp);
|
||||||
/* 6.5 Sending Traceroute Responses */
|
|
||||||
|
/* 6.2.2 3. If no forwarding information... */
|
||||||
|
if (!fwd_info) {
|
||||||
|
if (PIM_DEBUG_MTRACE)
|
||||||
|
zlog_debug("mtrace not found multicast state");
|
||||||
|
mtrace_rsp_set_fwd_code(rspp, MTRACE_FWD_CODE_NO_ROUTE);
|
||||||
|
/* 6.2.2. 3. forward the packet to requester */
|
||||||
return mtrace_send_response(pim, mtracep, mtrace_len);
|
return mtrace_send_response(pim, mtracep, mtrace_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
out_ifp = nexthop.interface;
|
nh_addr = rspp->prev_hop;
|
||||||
|
|
||||||
rspp->incoming = mtrace_primary_address(out_ifp);
|
reached_source = false;
|
||||||
rspp->prev_hop = nh_addr;
|
|
||||||
rspp->in_count = htonl(MTRACE_UNKNOWN_COUNT);
|
|
||||||
rspp->total = htonl(MTRACE_UNKNOWN_COUNT);
|
|
||||||
rspp->rtg_proto = MTRACE_RTG_PROTO_PIM;
|
|
||||||
rspp->fwd_ttl = 1;
|
|
||||||
rspp->s = 1;
|
|
||||||
rspp->src_mask = 32;
|
|
||||||
|
|
||||||
if (nh_addr.s_addr == 0) {
|
if (nh_addr.s_addr == 0) {
|
||||||
/* no pim? */
|
/* no pim? i.e. 7.5.3. No Previous Hop */
|
||||||
if (!out_ifp->info) {
|
if (!out_ifp->info) {
|
||||||
rspp->fwd_code = MTRACE_FWD_CODE_NO_MULTICAST;
|
if (PIM_DEBUG_MTRACE)
|
||||||
|
zlog_debug("mtrace not found incoming if w/ pim");
|
||||||
|
mtrace_rsp_set_fwd_code(rspp,
|
||||||
|
MTRACE_FWD_CODE_NO_MULTICAST);
|
||||||
return mtrace_send_response(pim, mtracep, mtrace_len);
|
return mtrace_send_response(pim, mtracep, mtrace_len);
|
||||||
}
|
}
|
||||||
/* reached source? */
|
/* reached source? i.e. 7.5.1 Arriving at source */
|
||||||
if (pim_if_connected_to_source(out_ifp, mtracep->src_addr)) {
|
if (pim_if_connected_to_source(out_ifp, mtracep->src_addr)) {
|
||||||
|
reached_source = true;
|
||||||
rspp->prev_hop = mtracep->src_addr;
|
rspp->prev_hop = mtracep->src_addr;
|
||||||
return mtrace_send_response(pim, mtracep, mtrace_len);
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* 6.4 Forwarding Traceroute Requests:
|
* 6.4 Forwarding Traceroute Requests:
|
||||||
* Previous-hop router not known
|
* Previous-hop router not known,
|
||||||
|
* packet is sent to an appropriate multicast address
|
||||||
*/
|
*/
|
||||||
inet_aton(MCAST_ALL_ROUTERS, &nh_addr);
|
inet_aton(MCAST_ALL_ROUTERS, &nh_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 6.2.2 8. If this router is the Rendez-vous Point */
|
||||||
|
if (pim_rp_i_am_rp(pim, mtracep->grp_addr)) {
|
||||||
|
mtrace_rsp_set_fwd_code(rspp, MTRACE_FWD_CODE_REACHED_RP);
|
||||||
|
/* 7.7.1. PIM-SM ...RP has not performed source-specific join */
|
||||||
|
if (rspp->src_mask == MTRACE_SRC_MASK_GROUP)
|
||||||
|
return mtrace_send_response(pim, mtracep, mtrace_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 6.4 Forwarding Traceroute Requests: the number of response
|
||||||
|
* blocks exceeds number of responses, so forward to the requester.
|
||||||
|
*/
|
||||||
if (mtracep->hops <= (last_rsp_ind + 1))
|
if (mtracep->hops <= (last_rsp_ind + 1))
|
||||||
return mtrace_send_response(pim, mtracep, mtrace_len);
|
return mtrace_send_response(pim, mtracep, mtrace_len);
|
||||||
|
|
||||||
|
/* 7.5.1. Arriving at source: terminate trace */
|
||||||
|
if (reached_source)
|
||||||
|
return mtrace_send_response(pim, mtracep, mtrace_len);
|
||||||
|
|
||||||
mtracep->checksum = 0;
|
mtracep->checksum = 0;
|
||||||
|
|
||||||
mtracep->checksum = in_cksum(mtrace_buf, mtrace_len);
|
mtracep->checksum = in_cksum(mtrace_buf, mtrace_len);
|
||||||
|
|
||||||
|
/* 6.4 Forwarding Traceroute Requests: response blocks less than req. */
|
||||||
return mtrace_send_packet(out_ifp, mtracep, mtrace_len, nh_addr,
|
return mtrace_send_packet(out_ifp, mtracep, mtrace_len, nh_addr,
|
||||||
mtracep->grp_addr);
|
mtracep->grp_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 6.3. Traceroute responses */
|
||||||
int igmp_mtrace_recv_response(struct igmp_sock *igmp, struct ip *ip_hdr,
|
int igmp_mtrace_recv_response(struct igmp_sock *igmp, struct ip *ip_hdr,
|
||||||
struct in_addr from, const char *from_str,
|
struct in_addr from, const char *from_str,
|
||||||
char *igmp_msg, int igmp_msg_len)
|
char *igmp_msg, int igmp_msg_len)
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
#define MTRACE_MAX_HOPS (255)
|
#define MTRACE_MAX_HOPS (255)
|
||||||
#define MTRACE_UNKNOWN_COUNT (0xffffffff)
|
#define MTRACE_UNKNOWN_COUNT (0xffffffff)
|
||||||
|
#define MTRACE_SRC_MASK_GROUP (0x3f) /* forwarding on group state (*,G) */
|
||||||
|
#define MTRACE_SRC_MASK_SOURCE (0x20) /* i.e. 32 forwarding on (S,G) */
|
||||||
|
|
||||||
enum mtrace_fwd_code {
|
enum mtrace_fwd_code {
|
||||||
MTRACE_FWD_CODE_NO_ERROR = 0x00,
|
MTRACE_FWD_CODE_NO_ERROR = 0x00,
|
||||||
|
@ -2793,14 +2793,15 @@ ALIAS(vtysh_traceroute, vtysh_traceroute_ip_cmd, "traceroute ip WORD",
|
|||||||
|
|
||||||
DEFUN (vtysh_mtrace,
|
DEFUN (vtysh_mtrace,
|
||||||
vtysh_mtrace_cmd,
|
vtysh_mtrace_cmd,
|
||||||
"mtrace WORD",
|
"mtrace WORD [WORD]",
|
||||||
"Multicast trace route to multicast source\n"
|
"Multicast trace route to multicast source\n"
|
||||||
"Multicast trace route to multicast source address\n")
|
"Multicast trace route to multicast source address\n"
|
||||||
|
"Multicast trace route for multicast group address\n")
|
||||||
{
|
{
|
||||||
int idx = 1;
|
if (argc == 2)
|
||||||
|
execute_command("mtracebis", 1, argv[1]->arg, NULL);
|
||||||
argv_find(argv, argc, "WORD", &idx);
|
else
|
||||||
execute_command("mtracebis", 1, argv[idx]->arg, NULL);
|
execute_command("mtracebis", 2, argv[1]->arg, argv[2]->arg);
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user