]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: Revamp send of join/prune to actually set bits right.
authorDonald Sharp <sharpd@cumulusnetwroks.com>
Wed, 27 Jul 2016 20:33:41 +0000 (16:33 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 22 Dec 2016 01:26:04 +0000 (20:26 -0500)
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 <sharpd@cumulusnetworks.com>
pimd/pim_cmd.c
pimd/pim_join.c
pimd/pim_msg.c
pimd/pim_msg.h

index c089a3fd3f132eef63a0c55784453541639144cf..b94fb1c767aaa06a9d4cf1d4ded85f4f0fc41c14 100644 (file)
@@ -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
index 2806320c02acb9408c2fdb3c99a6da26dab746b6..732dd823ad5219145ee9fa30c6774567d56263f2 100644 (file)
@@ -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("<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,
-                                               sg->u.sg.grp);
-  if (!pim_msg_curr) {
-    char group_str[100];
-    pim_inet4_dump("<grp?>", 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("<src?>", 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,
index 2027d42119add62439a161385f3d92ad24c42e25..61fc480bf9a8458fc3ac75303aad191088343a6c 100644 (file)
 #include <zebra.h>
 
 #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("<dst?>", 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("<grp?>", 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("<src?>", 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;
+}
index 4a13040af6b56efff9be02611f46d11baa6fb37a..1bd8207cc1e5f7aa5e00ed24c58b1163c2d47203 100644 (file)
@@ -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 */