diff options
Diffstat (limited to 'pimd/pim_join.c')
| -rw-r--r-- | pimd/pim_join.c | 482 |
1 files changed, 295 insertions, 187 deletions
diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 6a5fb851d6..c19468da6f 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -23,6 +23,8 @@ #include "log.h" #include "prefix.h" #include "if.h" +#include "vty.h" +#include "plist.h" #include "pimd.h" #include "pim_str.h" @@ -30,15 +32,20 @@ #include "pim_msg.h" #include "pim_pim.h" #include "pim_join.h" +#include "pim_oil.h" #include "pim_iface.h" #include "pim_hello.h" #include "pim_ifchannel.h" +#include "pim_rpf.h" +#include "pim_rp.h" +#include "pim_jp_agg.h" -static void on_trace(const char *label, - struct interface *ifp, struct in_addr src) +static void +on_trace (const char *label, + struct interface *ifp, struct in_addr src) { if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("<src?>", src, src_str, sizeof(src_str)); zlog_debug("%s: from %s on %s", label, src_str, ifp->name); @@ -49,58 +56,81 @@ static void recv_join(struct interface *ifp, struct pim_neighbor *neigh, uint16_t holdtime, struct in_addr upstream, - struct in_addr group, - struct in_addr source, + struct prefix_sg *sg, uint8_t source_flags) { if (PIM_DEBUG_PIM_TRACE) { - char up_str[100]; - char src_str[100]; - char grp_str[100]; - char neigh_str[100]; + char up_str[INET_ADDRSTRLEN]; + char neigh_str[INET_ADDRSTRLEN]; pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); - pim_inet4_dump("<src?>", source, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", group, grp_str, sizeof(grp_str)); pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str, sizeof(neigh_str)); - zlog_warn("%s: join (S,G)=(%s,%s) rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", + zlog_warn("%s: join (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", __PRETTY_FUNCTION__, - src_str, grp_str, + pim_str_sg_dump (sg), source_flags & PIM_RPT_BIT_MASK, 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->grp); + + /* + * If the RP sent in the message is not + * our RP for the group, drop the message + */ + if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) + return; + + sg->src.s_addr = INADDR_ANY; + } + /* Restart join expiry timer */ pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, - source, group, source_flags, holdtime); + sg, source_flags, holdtime); + } static void recv_prune(struct interface *ifp, struct pim_neighbor *neigh, uint16_t holdtime, struct in_addr upstream, - struct in_addr group, - struct in_addr source, + struct prefix_sg *sg, uint8_t source_flags) { if (PIM_DEBUG_PIM_TRACE) { - char up_str[100]; - char src_str[100]; - char grp_str[100]; - char neigh_str[100]; + char up_str[INET_ADDRSTRLEN]; + char neigh_str[INET_ADDRSTRLEN]; pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); - pim_inet4_dump("<src?>", source, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", group, grp_str, sizeof(grp_str)); pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str, sizeof(neigh_str)); - zlog_warn("%s: prune (S,G)=(%s,%s) rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", + zlog_warn("%s: prune (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", __PRETTY_FUNCTION__, - src_str, grp_str, + pim_str_sg_dump (sg), source_flags & PIM_RPT_BIT_MASK, source_flags & PIM_WILDCARD_BIT_MASK, up_str, holdtime, neigh_str, ifp->name); } - - pim_ifchannel_prune(ifp, upstream, source, group, source_flags, holdtime); + + if ((source_flags & PIM_RPT_BIT_MASK) && + (source_flags & PIM_WILDCARD_BIT_MASK)) + { + struct pim_rpf *rp = RP (sg->grp); + + // Ignoring Prune *,G's at the moment. + if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) + return; + + sg->src.s_addr = INADDR_ANY; + } + + pim_ifchannel_prune(ifp, upstream, sg, source_flags, holdtime); + } int pim_joinprune_recv(struct interface *ifp, @@ -117,8 +147,6 @@ int pim_joinprune_recv(struct interface *ifp, int remain; int group; - on_trace(__PRETTY_FUNCTION__, ifp, src_addr); - buf = tlv_buf; pastend = tlv_buf + tlv_buf_size; @@ -128,7 +156,7 @@ int pim_joinprune_recv(struct interface *ifp, addr_offset = pim_parse_addr_ucast (&msg_upstream_addr, buf, pastend - buf); if (addr_offset < 1) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", __PRETTY_FUNCTION__, @@ -141,8 +169,8 @@ int pim_joinprune_recv(struct interface *ifp, Check upstream address family */ if (msg_upstream_addr.family != AF_INET) { - if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; + if (PIM_DEBUG_PIM_J_P) { + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: ignoring join/prune directed to unexpected addr family=%d from %s on %s", __PRETTY_FUNCTION__, @@ -153,7 +181,7 @@ int pim_joinprune_recv(struct interface *ifp, remain = pastend - buf; if (remain < 4) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: short join/prune message buffer for group list: size=%d minimum=%d from %s on %s", __PRETTY_FUNCTION__, @@ -168,28 +196,29 @@ int pim_joinprune_recv(struct interface *ifp, ++buf; ++buf; - if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; - char upstream_str[100]; + if (PIM_DEBUG_PIM_J_P) { + char src_str[INET_ADDRSTRLEN]; + char upstream_str[INET_ADDRSTRLEN]; pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); pim_inet4_dump("<addr?>", msg_upstream_addr.u.prefix4, upstream_str, sizeof(upstream_str)); - zlog_warn("%s: join/prune upstream=%s groups=%d holdtime=%d from %s on %s", - __PRETTY_FUNCTION__, - upstream_str, msg_num_groups, msg_holdtime, - src_str, ifp->name); + zlog_debug ("%s: join/prune upstream=%s groups=%d holdtime=%d from %s on %s", + __PRETTY_FUNCTION__, + upstream_str, msg_num_groups, msg_holdtime, + src_str, ifp->name); } /* Scan groups */ for (group = 0; group < msg_num_groups; ++group) { - struct prefix msg_group_addr; - struct prefix msg_source_addr; + struct prefix_sg sg; uint8_t msg_source_flags; uint16_t msg_num_joined_sources; uint16_t msg_num_pruned_sources; int source; + struct pim_ifchannel *ch = NULL; - addr_offset = pim_parse_addr_group (&msg_group_addr, + memset (&sg, 0, sizeof (struct prefix_sg)); + addr_offset = pim_parse_addr_group (&sg, buf, pastend - buf); if (addr_offset < 1) { return -5; @@ -198,7 +227,7 @@ int pim_joinprune_recv(struct interface *ifp, remain = pastend - buf; if (remain < 4) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: short join/prune buffer for source list: size=%d minimum=%d from %s on %s", __PRETTY_FUNCTION__, @@ -211,25 +240,25 @@ int pim_joinprune_recv(struct interface *ifp, msg_num_pruned_sources = ntohs(*(const uint16_t *) buf); buf += 2; - if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; - char upstream_str[100]; - char group_str[100]; + if (PIM_DEBUG_PIM_J_P) { + char src_str[INET_ADDRSTRLEN]; + char upstream_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); pim_inet4_dump("<addr?>", msg_upstream_addr.u.prefix4, upstream_str, sizeof(upstream_str)); - pim_inet4_dump("<grp?>", msg_group_addr.u.prefix4, + pim_inet4_dump("<grp?>", sg.grp, group_str, sizeof(group_str)); - zlog_warn("%s: join/prune upstream=%s group=%s/%d join_src=%d prune_src=%d from %s on %s", + zlog_warn("%s: join/prune upstream=%s group=%s/32 join_src=%d prune_src=%d from %s on %s", __PRETTY_FUNCTION__, - upstream_str, group_str, msg_group_addr.prefixlen, + upstream_str, group_str, msg_num_joined_sources, msg_num_pruned_sources, src_str, ifp->name); } /* Scan joined sources */ for (source = 0; source < msg_num_joined_sources; ++source) { - addr_offset = pim_parse_addr_source (&msg_source_addr, + addr_offset = pim_parse_addr_source (&sg, &msg_source_flags, buf, pastend - buf); if (addr_offset < 1) { @@ -240,14 +269,20 @@ int pim_joinprune_recv(struct interface *ifp, recv_join(ifp, neigh, msg_holdtime, msg_upstream_addr.u.prefix4, - msg_group_addr.u.prefix4, - msg_source_addr.u.prefix4, + &sg, msg_source_flags); + + if (sg.src.s_addr == INADDR_ANY) + { + ch = pim_ifchannel_find (ifp, &sg); + if (ch) + pim_ifchannel_set_star_g_join_state (ch, 0); + } } /* Scan pruned sources */ for (source = 0; source < msg_num_pruned_sources; ++source) { - addr_offset = pim_parse_addr_source (&msg_source_addr, + addr_offset = pim_parse_addr_source (&sg, &msg_source_flags, buf, pastend - buf); if (addr_offset < 1) { @@ -258,68 +293,120 @@ int pim_joinprune_recv(struct interface *ifp, recv_prune(ifp, neigh, msg_holdtime, msg_upstream_addr.u.prefix4, - msg_group_addr.u.prefix4, - msg_source_addr.u.prefix4, + &sg, msg_source_flags); } - + if (ch) + pim_ifchannel_set_star_g_join_state (ch, 1); + ch = NULL; } /* scan groups */ return 0; } -int pim_joinprune_send(struct interface *ifp, - struct in_addr upstream_addr, - struct in_addr source_addr, - struct in_addr group_addr, - int send_join) +/* + * J/P Message Format + * + * While the RFC clearly states that this is 32 bits wide, it + * is cheating. These fields: + * Encoded-Unicast format (6 bytes MIN) + * Encoded-Group format (8 bytes MIN) + * Encoded-Source format (8 bytes MIN) + * are *not* 32 bits wide. + * + * Nor does the RFC explicitly call out the size for: + * Reserved (1 byte) + * Num Groups (1 byte) + * Holdtime (2 bytes) + * Number of Joined Sources (2 bytes) + * Number of Pruned Sources (2 bytes) + * + * This leads to a missleading representation from casual + * reading and making assumptions. Be careful! + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |PIM Ver| Type | Reserved | Checksum | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Upstream Neighbor Address (Encoded-Unicast format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | Num groups | Holdtime | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Multicast Group Address 1 (Encoded-Group format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Number of Joined Sources | Number of Pruned Sources | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Joined Source Address 1 (Encoded-Source format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | . | + * | . | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Joined Source Address n (Encoded-Source format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Pruned Source Address 1 (Encoded-Source format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | . | + * | . | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Pruned Source Address n (Encoded-Source format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Multicast Group Address m (Encoded-Group format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Number of Joined Sources | Number of Pruned Sources | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Joined Source Address 1 (Encoded-Source format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | . | + * | . | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Joined Source Address n (Encoded-Source format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Pruned Source Address 1 (Encoded-Source format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | . | + * | . | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Pruned Source Address n (Encoded-Source format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +int pim_joinprune_send(struct pim_rpf *rpf, + struct list *groups) { + struct pim_jp_agg_group *group; 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; + struct pim_jp_groups *grp = NULL; + struct pim_jp *msg; + struct listnode *node, *nnode; + uint8_t pim_msg[10000]; + uint8_t *curr_ptr = pim_msg; + bool new_packet = true; + size_t packet_left = 0; + size_t packet_size = 0; + size_t group_size = 0; - zassert(ifp); + on_trace (__PRETTY_FUNCTION__, rpf->source_nexthop.interface, rpf->rpf_addr.u.prefix4); - pim_ifp = ifp->info; + pim_ifp = rpf->source_nexthop.interface->info; if (!pim_ifp) { zlog_warn("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ifp->name); + __PRETTY_FUNCTION__, + rpf->source_nexthop.interface->name); return -1; } - if (PIM_DEBUG_PIM_TRACE) { - char source_str[100]; - char group_str[100]; - char dst_str[100]; - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<dst?>", upstream_addr, dst_str, sizeof(dst_str)); - zlog_debug("%s: sending %s(S,G)=(%s,%s) to upstream=%s on interface %s", - __PRETTY_FUNCTION__, - send_join ? "Join" : "Prune", - source_str, group_str, dst_str, ifp->name); - } - - if (PIM_INADDR_IS_ANY(upstream_addr)) { - if (PIM_DEBUG_PIM_TRACE) { - char source_str[100]; - char group_str[100]; - char dst_str[100]; - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<dst?>", upstream_addr, dst_str, sizeof(dst_str)); - zlog_debug("%s: %s(S,G)=(%s,%s): upstream=%s is myself on interface %s", - __PRETTY_FUNCTION__, - send_join ? "Join" : "Prune", - source_str, group_str, dst_str, ifp->name); + if (PIM_INADDR_IS_ANY(rpf->rpf_addr.u.prefix4)) + { + if (PIM_DEBUG_PIM_J_P) { + char dst_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, dst_str, sizeof(dst_str)); + zlog_debug("%s: upstream=%s is myself on interface %s", + __PRETTY_FUNCTION__, + dst_str, rpf->source_nexthop.interface->name); + } + return 0; } - return 0; - } /* RFC 4601: 4.3.1. Sending Hello Messages @@ -330,96 +417,117 @@ int pim_joinprune_send(struct interface *ifp, relevant Hello message without waiting for the Hello Timer to expire, followed by the Join/Prune or Assert message. */ - pim_hello_require(ifp); - - /* - Build PIM message - */ - - 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("<dst?>", 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, - group_addr); - if (!pim_msg_curr) { - char group_str[100]; - pim_inet4_dump("<grp?>", group_addr, 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, - source_addr); - if (!pim_msg_curr) { - char source_str[100]; - pim_inet4_dump("<src?>", source_addr, 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_hello_require(rpf->source_nexthop.interface); + + for (ALL_LIST_ELEMENTS(groups, node, nnode, group)) + { + if (new_packet) + { + msg = (struct pim_jp *)pim_msg; + + memset(msg, 0, sizeof (*msg)); + + pim_msg_addr_encode_ipv4_ucast ((uint8_t *)&msg->addr, rpf->rpf_addr.u.prefix4); + msg->reserved = 0; + msg->holdtime = htons(PIM_JP_HOLDTIME); + + new_packet = false; + + grp = &msg->groups[0]; + curr_ptr = (uint8_t *)grp; + packet_size = sizeof (struct pim_msg_header); + packet_size += sizeof (struct pim_encoded_ipv4_unicast); + packet_size += 4; // reserved (1) + groups (1) + holdtime (2) + + packet_left = rpf->source_nexthop.interface->mtu - 24; + packet_left -= packet_size; + } + if (PIM_DEBUG_PIM_J_P) { + char dst_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, dst_str, sizeof(dst_str)); + pim_inet4_dump("<grp?>", group->group, grp_str, sizeof(grp_str)); + zlog_debug("%s: sending (G)=%s to upstream=%s on interface %s", + __PRETTY_FUNCTION__, + grp_str, dst_str, rpf->source_nexthop.interface->name); + } - pim_msg_build_header(pim_msg, pim_msg_size, - PIM_MSG_TYPE_JOIN_PRUNE); + group_size = pim_msg_get_jp_group_size (group->sources); + if (group_size > packet_left) + { + pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE); + if (pim_msg_send(pim_ifp->pim_sock_fd, + pim_ifp->primary_address, + qpim_all_pim_routers_addr, + pim_msg, + packet_size, + rpf->source_nexthop.interface->name)) { + zlog_warn("%s: could not send PIM message on interface %s", + __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name); + } + + msg = (struct pim_jp *)pim_msg; + memset(msg, 0, sizeof (*msg)); + + pim_msg_addr_encode_ipv4_ucast ((uint8_t *)&msg->addr, rpf->rpf_addr.u.prefix4); + msg->reserved = 0; + msg->holdtime = htons(PIM_JP_HOLDTIME); + + new_packet = false; + + grp = &msg->groups[0]; + curr_ptr = (uint8_t *)grp; + packet_size = sizeof (struct pim_msg_header); + packet_size += sizeof (struct pim_encoded_ipv4_unicast); + packet_size += 4; // reserved (1) + groups (1) + holdtime (2) + + packet_left = rpf->source_nexthop.interface->mtu - 24; + packet_left -= packet_size; + } + + msg->num_groups++; + /* + Build PIM message + */ + + curr_ptr += group_size; + packet_left -= group_size; + packet_size += group_size; + zlog_debug ("\tpl: %zd ps: %zd", packet_left, packet_size); + pim_msg_build_jp_groups (grp, group); + + grp = (struct pim_jp_groups *)curr_ptr; + if (packet_left < sizeof (struct pim_jp_groups) || msg->num_groups == 255) + { + pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE); + if (pim_msg_send(pim_ifp->pim_sock_fd, + pim_ifp->primary_address, + qpim_all_pim_routers_addr, + pim_msg, + packet_size, + rpf->source_nexthop.interface->name)) { + zlog_warn("%s: could not send PIM message on interface %s", + __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name); + } + + new_packet = true; + } + } - if (pim_msg_send(pim_ifp->pim_sock_fd, - qpim_all_pim_routers_addr, - pim_msg, - pim_msg_size, - ifp->name)) { - zlog_warn("%s: could not send PIM message on interface %s", - __PRETTY_FUNCTION__, ifp->name); - return -8; - } + if (!new_packet) + { + //msg->num_groups = htons (msg->num_groups); + pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE); + if (pim_msg_send(pim_ifp->pim_sock_fd, + pim_ifp->primary_address, + qpim_all_pim_routers_addr, + pim_msg, + packet_size, + rpf->source_nexthop.interface->name)) { + zlog_warn("%s: could not send PIM message on interface %s", + __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name); + } + } return 0; } |
