From: Donald Sharp Date: Wed, 27 Jul 2016 20:33:41 +0000 (-0400) Subject: pimd: Revamp send of join/prune to actually set bits right. X-Git-Tag: frr-3.0-branchpoint~64^2~10^2~340 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=346cffe31ef871d7876aacafea9cf4086146f110;p=matthieu%2Ffrr.git pimd: Revamp send of join/prune to actually set bits right. When a *,G report is sent, the RPT and WC bits are set as well as the source is the RP address for the group. If this routers idea of the RP for this group is different than the idea of the RP from the sender than that particular *,G can be dropped. Ticket: CM-12031 Signed-off-by: Donald Sharp --- diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index c089a3fd3f..b94fb1c767 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4474,7 +4474,6 @@ static int recv_joinprune(struct vty *vty, uint8_t buf[1000]; const uint8_t *buf_pastend = buf + sizeof(buf); uint8_t *pim_msg; - uint8_t *pim_msg_curr; int pim_msg_size; struct ip *ip_hdr; size_t ip_hlen; /* ip header length in bytes */ @@ -4491,9 +4490,6 @@ static int recv_joinprune(struct vty *vty, const char *ifname; struct interface *ifp; int result; - int remain; - uint16_t num_joined; - uint16_t num_pruned; /* Find interface */ ifname = argv[0]->arg; @@ -4557,87 +4553,9 @@ static int recv_joinprune(struct vty *vty, */ pim_msg = buf + ip_hlen; - /* skip room for pim header */ - pim_msg_curr = pim_msg + PIM_MSG_HEADER_LEN; - - remain = buf_pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_ucast(pim_msg_curr, - remain, - neigh_dst_addr); - if (!pim_msg_curr) { - vty_out(vty, "Failure encoding destination address %s: space left=%d%s", - neigh_dst_str, remain, VTY_NEWLINE); - return CMD_WARNING; - } - - remain = buf_pastend - pim_msg_curr; - if (remain < 4) { - vty_out(vty, "Group will not fit: space left=%d%s", - remain, VTY_NEWLINE); - return CMD_WARNING; - } - - *pim_msg_curr = 0; /* reserved */ - ++pim_msg_curr; - *pim_msg_curr = 1; /* number of groups */ - ++pim_msg_curr; - *((uint16_t *) pim_msg_curr) = htons(neigh_holdtime); - ++pim_msg_curr; - ++pim_msg_curr; - - remain = buf_pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr, - remain, - group_addr); - if (!pim_msg_curr) { - vty_out(vty, "Failure encoding group address %s: space left=%d%s", - group_str, remain, VTY_NEWLINE); - return CMD_WARNING; - } - - remain = buf_pastend - pim_msg_curr; - if (remain < 4) { - vty_out(vty, "Sources will not fit: space left=%d%s", - remain, VTY_NEWLINE); - return CMD_WARNING; - } - - if (src_is_join) { - num_joined = 1; - num_pruned = 0; - } - else { - num_joined = 0; - num_pruned = 1; - } - - /* number of joined sources */ - *((uint16_t *) pim_msg_curr) = htons(num_joined); - ++pim_msg_curr; - ++pim_msg_curr; - - /* number of pruned sources */ - *((uint16_t *) pim_msg_curr) = htons(num_pruned); - ++pim_msg_curr; - ++pim_msg_curr; - - remain = buf_pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_source(pim_msg_curr, - remain, - source_addr, - PIM_ENCODE_SPARSE_BIT); - if (!pim_msg_curr) { - vty_out(vty, "Failure encoding source address %s: space left=%d%s", - source_str, remain, VTY_NEWLINE); - return CMD_WARNING; - } - - /* Add PIM header */ - - pim_msg_size = pim_msg_curr - pim_msg; - - pim_msg_build_header(pim_msg, pim_msg_size, - PIM_MSG_TYPE_JOIN_PRUNE); + pim_msg_size = pim_msg_join_prune_encode (pim_msg, buf_pastend - pim_msg, src_is_join, + source_addr, group_addr, neigh_dst_addr, + neigh_holdtime); /* "Receive" message diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 2806320c02..732dd823ad 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -75,7 +75,26 @@ static void recv_join(struct interface *ifp, source_flags & PIM_WILDCARD_BIT_MASK, up_str, holdtime, neigh_str, ifp->name); } - + + /* + * If the RPT and WC are set it's a (*,G) + * and the source is the RP + */ + if ((source_flags & PIM_RPT_BIT_MASK) && + (source_flags & PIM_WILDCARD_BIT_MASK)) + { + struct pim_rpf *rp = RP (sg.u.sg.grp); + + /* + * If the RP sent in the message is not + * our RP for the group, drop the message + */ + if (sg.u.sg.src.s_addr != rp->rpf_addr.s_addr) + return; + + sg.u.sg.src.s_addr = INADDR_ANY; + } + /* Restart join expiry timer */ pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, &sg, source_flags, holdtime); @@ -318,10 +337,7 @@ int pim_joinprune_send(struct interface *ifp, { struct pim_interface *pim_ifp; uint8_t pim_msg[1000]; - const uint8_t *pastend = pim_msg + sizeof(pim_msg); - uint8_t *pim_msg_curr = pim_msg + PIM_MSG_HEADER_LEN; /* room for pim header */ int pim_msg_size; - int remain; on_trace (__PRETTY_FUNCTION__, ifp, upstream_addr); @@ -371,82 +387,12 @@ int pim_joinprune_send(struct interface *ifp, /* Build PIM message */ + pim_msg_size = pim_msg_join_prune_encode (pim_msg, 1000, send_join, + sg->u.sg.src, sg->u.sg.grp, + upstream_addr, PIM_JP_HOLDTIME); - remain = pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_ucast(pim_msg_curr, - remain, - upstream_addr); - if (!pim_msg_curr) { - char dst_str[100]; - pim_inet4_dump("", upstream_addr, dst_str, sizeof(dst_str)); - zlog_warn("%s: failure encoding destination address %s: space left=%d", - __PRETTY_FUNCTION__, dst_str, remain); - return -3; - } - - remain = pastend - pim_msg_curr; - if (remain < 4) { - zlog_warn("%s: group will not fit: space left=%d", - __PRETTY_FUNCTION__, remain); - return -4; - } - - *pim_msg_curr = 0; /* reserved */ - ++pim_msg_curr; - *pim_msg_curr = 1; /* number of groups */ - ++pim_msg_curr; - *((uint16_t *) pim_msg_curr) = htons(PIM_JP_HOLDTIME); - ++pim_msg_curr; - ++pim_msg_curr; - - remain = pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr, - remain, - sg->u.sg.grp); - if (!pim_msg_curr) { - char group_str[100]; - pim_inet4_dump("", sg->u.sg.grp, group_str, sizeof(group_str)); - zlog_warn("%s: failure encoding group address %s: space left=%d", - __PRETTY_FUNCTION__, group_str, remain); - return -5; - } - - remain = pastend - pim_msg_curr; - if (remain < 4) { - zlog_warn("%s: sources will not fit: space left=%d", - __PRETTY_FUNCTION__, remain); - return -6; - } - - /* number of joined sources */ - *((uint16_t *) pim_msg_curr) = htons(send_join ? 1 : 0); - ++pim_msg_curr; - ++pim_msg_curr; - - /* number of pruned sources */ - *((uint16_t *) pim_msg_curr) = htons(send_join ? 0 : 1); - ++pim_msg_curr; - ++pim_msg_curr; - - remain = pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_source(pim_msg_curr, - remain, - sg->u.sg.src, - PIM_ENCODE_SPARSE_BIT); - if (!pim_msg_curr) { - char source_str[100]; - pim_inet4_dump("", sg->u.sg.src, source_str, sizeof(source_str)); - zlog_warn("%s: failure encoding source address %s: space left=%d", - __PRETTY_FUNCTION__, source_str, remain); - return -7; - } - - /* Add PIM header */ - - pim_msg_size = pim_msg_curr - pim_msg; - - pim_msg_build_header(pim_msg, pim_msg_size, - PIM_MSG_TYPE_JOIN_PRUNE); + if (pim_msg_size < 0) + return pim_msg_size; if (pim_msg_send(pim_ifp->pim_sock_fd, qpim_all_pim_routers_addr, diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 2027d42119..61fc480bf9 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -22,11 +22,13 @@ #include #include "if.h" +#include "log.h" #include "pimd.h" #include "pim_pim.h" #include "pim_msg.h" #include "pim_util.h" +#include "pim_str.h" void pim_msg_build_header(uint8_t *pim_msg, int pim_msg_size, uint8_t pim_msg_type) @@ -105,3 +107,95 @@ pim_msg_addr_encode_ipv4_source(uint8_t *buf, int buf_size, return buf + ENCODED_IPV4_SOURCE_SIZE; } + +int +pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, + struct in_addr source, struct in_addr group, + struct in_addr upstream, int holdtime) +{ + uint8_t *pim_msg = buf; + uint8_t *pim_msg_curr = buf + PIM_MSG_HEADER_LEN; + uint8_t *end = buf + buf_size; + struct in_addr stosend; + uint8_t bits; + int remain; + + remain = end - pim_msg_curr; + pim_msg_curr = pim_msg_addr_encode_ipv4_ucast (pim_msg_curr, buf_size - PIM_MSG_HEADER_LEN, upstream); + if (!pim_msg_curr) { + char dst_str[100]; + pim_inet4_dump("", upstream, dst_str, sizeof(dst_str)); + zlog_warn("%s: failure encoding destination address %s: space left=%d", + __PRETTY_FUNCTION__, dst_str, remain); + return -3; + } + + remain = end - pim_msg_curr; + if (remain < 4) { + zlog_warn("%s: group will not fit: space left=%d", + __PRETTY_FUNCTION__, remain); + return -4; + } + + *pim_msg_curr = 0; /* reserved */ + ++pim_msg_curr; + *pim_msg_curr = 1; /* number of groups */ + ++pim_msg_curr; + + *((uint16_t *) pim_msg_curr) = htons(holdtime); + ++pim_msg_curr; + ++pim_msg_curr; + + remain = end - pim_msg_curr; + pim_msg_curr = pim_msg_addr_encode_ipv4_group (pim_msg_curr, remain, + group); + if (!pim_msg_curr) { + char group_str[100]; + pim_inet4_dump("", group, group_str, sizeof(group_str)); + zlog_warn("%s: failure encoding group address %s: space left=%d", + __PRETTY_FUNCTION__, group_str, remain); + return -5; + } + + remain = end - pim_msg_curr; + if (remain < 4) { + zlog_warn("%s: sources will not fit: space left=%d", + __PRETTY_FUNCTION__, remain); + return -6; + } + + /* number of joined sources */ + *((uint16_t *) pim_msg_curr) = htons(is_join ? 1 : 0); + ++pim_msg_curr; + ++pim_msg_curr; + + /* number of pruned sources */ + *((uint16_t *) pim_msg_curr) = htons(is_join ? 0 : 1); + ++pim_msg_curr; + ++pim_msg_curr; + + remain = end - pim_msg_curr; + if (source.s_addr == INADDR_ANY) + { + bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT | PIM_ENCODE_RPT_BIT; + stosend = qpim_rp.rpf_addr; + } + else + { + bits = PIM_ENCODE_SPARSE_BIT; + stosend = source; + } + pim_msg_curr = pim_msg_addr_encode_ipv4_source (pim_msg_curr, remain, stosend, bits); + if (!pim_msg_curr) { + char source_str[100]; + pim_inet4_dump("", source, source_str, sizeof(source_str)); + zlog_warn("%s: failure encoding source address %s: space left=%d", + __PRETTY_FUNCTION__, source_str, remain); + return -7; + } + + remain = pim_msg_curr - pim_msg; + pim_msg_build_header (pim_msg, remain, PIM_MSG_TYPE_JOIN_PRUNE); + + return remain; +} diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h index 4a13040af6..1bd8207cc1 100644 --- a/pimd/pim_msg.h +++ b/pimd/pim_msg.h @@ -53,4 +53,8 @@ uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, struct in_addr addr, uint8_t bits); + +int pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, + struct in_addr source, struct in_addr group, + struct in_addr upstream, int holdtime); #endif /* PIM_MSG_H */