summaryrefslogtreecommitdiff
path: root/pimd/pim_join.c
diff options
context:
space:
mode:
Diffstat (limited to 'pimd/pim_join.c')
-rw-r--r--pimd/pim_join.c482
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;
}