summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pimd/pim_autorp.c1559
-rw-r--r--pimd/pim_autorp.h75
-rw-r--r--pimd/pimd.c4
3 files changed, 1218 insertions, 420 deletions
diff --git a/pimd/pim_autorp.c b/pimd/pim_autorp.c
index d36b792e39..3b46e7fb2b 100644
--- a/pimd/pim_autorp.c
+++ b/pimd/pim_autorp.c
@@ -19,6 +19,7 @@
#include "lib/json.h"
#include "pimd.h"
+#include "pim_util.h"
#include "pim_iface.h"
#include "pim_rp.h"
#include "pim_sock.h"
@@ -26,61 +27,90 @@
#include "pim_autorp.h"
DEFINE_MTYPE_STATIC(PIMD, PIM_AUTORP, "PIM AutoRP info");
-DEFINE_MTYPE_STATIC(PIMD, PIM_AUTORP_RP, "PIM AutoRP advertised RP info");
-DEFINE_MTYPE_STATIC(PIMD, PIM_AUTORP_CRP, "PIM AutoRP candidate RP info");
+DEFINE_MTYPE_STATIC(PIMD, PIM_AUTORP_RP, "PIM AutoRP discovered RP info");
DEFINE_MTYPE_STATIC(PIMD, PIM_AUTORP_ANNOUNCE, "PIM AutoRP announcement packet");
+DEFINE_MTYPE_STATIC(PIMD, PIM_AUTORP_GRPPFIX, "PIM AutoRP group prefix list");
static const char *PIM_AUTORP_ANNOUNCEMENT_GRP = "224.0.1.39";
static const char *PIM_AUTORP_DISCOVERY_GRP = "224.0.1.40";
static const in_port_t PIM_AUTORP_PORT = 496;
-static int pim_autorp_rp_cmp(const struct pim_autorp_rp *l,
- const struct pim_autorp_rp *r)
+static int pim_autorp_rp_cmp(const struct pim_autorp_rp *l, const struct pim_autorp_rp *r)
{
return pim_addr_cmp(l->addr, r->addr);
}
-DECLARE_SORTLIST_UNIQ(pim_autorp_rp, struct pim_autorp_rp, list,
- pim_autorp_rp_cmp);
+DECLARE_SORTLIST_UNIQ(pim_autorp_rp, struct pim_autorp_rp, item, pim_autorp_rp_cmp);
-static void pim_autorp_rp_free(struct pim_autorp_rp *rp)
+static int pim_autorp_grppfix_cmp(const struct pim_autorp_grppfix *l,
+ const struct pim_autorp_grppfix *r)
{
- event_cancel(&rp->hold_timer);
+ return prefix_cmp(&l->grp, &r->grp);
+}
- /* Clean up installed RP info */
- if (pim_rp_del(rp->autorp->pim, rp->addr, rp->grp,
- (strlen(rp->grplist) ? rp->grplist : NULL),
- RP_SRC_AUTORP))
- if (PIM_DEBUG_AUTORP)
- zlog_err("%s: Failed to delete RP %pI4", __func__,
- &rp->addr);
+DECLARE_SORTLIST_UNIQ(pim_autorp_grppfix, struct pim_autorp_grppfix, item, pim_autorp_grppfix_cmp);
- XFREE(MTYPE_PIM_AUTORP_RP, rp);
+static void pim_autorp_grppfix_free(struct pim_autorp_grppfix_head *head)
+{
+ struct pim_autorp_grppfix *grp;
+
+ while ((grp = pim_autorp_grppfix_pop(head)))
+ XFREE(MTYPE_PIM_AUTORP_GRPPFIX, grp);
}
-static void pim_autorp_rplist_free(struct pim_autorp_rp_head *head)
+static void pim_autorp_rp_free(struct pim_autorp_rp *rp, bool installed)
{
- struct pim_autorp_rp *rp;
+ event_cancel(&rp->hold_timer);
- while ((rp = pim_autorp_rp_pop(head)))
- pim_autorp_rp_free(rp);
+ /* Clean up installed RP info */
+ if (installed) {
+ if (pim_rp_del(rp->autorp->pim, rp->addr, rp->grp,
+ (strlen(rp->grplist) ? rp->grplist : NULL), RP_SRC_AUTORP)) {
+ zlog_warn("%s: Failed to delete RP %pI4", __func__, &rp->addr);
+ }
+
+ if (strlen(rp->grplist)) {
+ struct prefix_list *pl;
+
+ pl = prefix_list_lookup(AFI_IP, rp->grplist);
+ if (pl)
+ prefix_list_delete(pl);
+ }
+ }
+
+ pim_autorp_grppfix_free(&rp->grp_pfix_list);
+ pim_autorp_grppfix_fini(&rp->grp_pfix_list);
+
+ XFREE(MTYPE_PIM_AUTORP_RP, rp);
}
-static void pim_autorp_rplist_cfree(struct pim_autorp_rp_head *head)
+static void pim_autorp_rplist_free(struct pim_autorp_rp_head *head, bool installed)
{
struct pim_autorp_rp *rp;
while ((rp = pim_autorp_rp_pop(head)))
- XFREE(MTYPE_PIM_AUTORP_CRP, rp);
+ pim_autorp_rp_free(rp, installed);
}
static void pim_autorp_free(struct pim_autorp *autorp)
{
- pim_autorp_rplist_free(&(autorp->discovery_rp_list));
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Freeing PIM AutoRP", __func__);
+
+ pim_autorp_rplist_free(&(autorp->discovery_rp_list), true);
pim_autorp_rp_fini(&(autorp->discovery_rp_list));
- pim_autorp_rplist_cfree(&(autorp->candidate_rp_list));
+ pim_autorp_rplist_free(&(autorp->candidate_rp_list), false);
pim_autorp_rp_fini(&(autorp->candidate_rp_list));
+
+ pim_autorp_rplist_free(&(autorp->mapping_rp_list), false);
+ pim_autorp_rp_fini(&(autorp->mapping_rp_list));
+
+ pim_autorp_rplist_free(&(autorp->advertised_rp_list), false);
+ pim_autorp_rp_fini(&(autorp->advertised_rp_list));
+
+ if (autorp->announce_pkt)
+ XFREE(MTYPE_PIM_AUTORP_ANNOUNCE, autorp->announce_pkt);
}
static bool pim_autorp_join_groups(struct interface *ifp)
@@ -97,26 +127,22 @@ static bool pim_autorp_join_groups(struct interface *ifp)
inet_pton(PIM_AF, PIM_AUTORP_DISCOVERY_GRP, &grp);
if (pim_socket_join(autorp->sock, grp, pim_ifp->primary_address,
ifp->ifindex, pim_ifp)) {
- zlog_err("Failed to join group %pI4 on interface %s", &grp,
- ifp->name);
+ zlog_warn("Failed to join group %pI4 on interface %s", &grp, ifp->name);
return false;
}
- /* TODO: Future Mapping agent implementation
- * Join announcement group for AutoRP mapping agent
- * inet_pton(PIM_AF, PIM_AUTORP_ANNOUNCEMENT_GRP, &grp);
- * if (pim_socket_join(pim->autorp->sock, grp,
- * pim_ifp->primary_address,
- * ifp->ifindex, pim_ifp)) {
- * zlog_err("Failed to join group %pI4 on interface %s",
- * &grp, ifp->name);
- * return errno;
- * }
- */
+ zlog_info("%s: Joined AutoRP discovery group %pPA on interface %s", __func__, &grp,
+ ifp->name);
- if (PIM_DEBUG_AUTORP)
- zlog_debug("%s: Joined AutoRP groups on interface %s", __func__,
- ifp->name);
+ inet_pton(PIM_AF, PIM_AUTORP_ANNOUNCEMENT_GRP, &grp);
+ if (pim_socket_join(pim->autorp->sock, grp, pim_ifp->primary_address, ifp->ifindex,
+ pim_ifp)) {
+ zlog_warn("Failed to join group %pI4 on interface %s", &grp, ifp->name);
+ return errno;
+ }
+
+ zlog_info("%s: Joined AutoRP announcement group %pPA on interface %s", __func__, &grp,
+ ifp->name);
return true;
}
@@ -135,31 +161,26 @@ static bool pim_autorp_leave_groups(struct interface *ifp)
inet_pton(PIM_AF, PIM_AUTORP_DISCOVERY_GRP, &grp);
if (pim_socket_leave(autorp->sock, grp, pim_ifp->primary_address,
ifp->ifindex, pim_ifp)) {
- zlog_err("Failed to leave group %pI4 on interface %s", &grp,
- ifp->name);
+ zlog_warn("Failed to leave group %pI4 on interface %s", &grp, ifp->name);
return false;
}
- /* TODO: Future Mapping agent implementation
- * Leave announcement group for AutoRP mapping agent
- * inet_pton(PIM_AF, PIM_AUTORP_ANNOUNCEMENT_GRP, &grp);
- * if (pim_socket_leave(pim->autorp->sock, grp,
- * pim_ifp->primary_address,
- * ifp->ifindex, pim_ifp)) {
- * zlog_err("Failed to leave group %pI4 on interface %s",
- * &grp, ifp->name);
- * return errno;
- * }
- */
+ zlog_info("%s: Left AutoRP discovery group %pPA on interface %s", __func__, &grp, ifp->name);
- if (PIM_DEBUG_AUTORP)
- zlog_debug("%s: Left AutoRP groups on interface %s", __func__,
- ifp->name);
+ inet_pton(PIM_AF, PIM_AUTORP_ANNOUNCEMENT_GRP, &grp);
+ if (pim_socket_leave(pim->autorp->sock, grp, pim_ifp->primary_address, ifp->ifindex,
+ pim_ifp)) {
+ zlog_warn("Failed to leave group %pI4 on interface %s", &grp, ifp->name);
+ return errno;
+ }
+
+ zlog_info("%s: Left AutoRP announcement group %pPA on interface %s", __func__, &grp,
+ ifp->name);
return true;
}
-static bool pim_autorp_setup(struct pim_autorp *autorp)
+static bool pim_autorp_setup(int fd)
{
#if defined(HAVE_IP_PKTINFO)
int data;
@@ -170,35 +191,39 @@ static bool pim_autorp_setup(struct pim_autorp *autorp)
.sin_addr = { .s_addr = INADDR_ANY },
.sin_port = htons(PIM_AUTORP_PORT) };
- setsockopt_so_recvbuf(autorp->sock, 1024 * 1024 * 8);
+ setsockopt_so_recvbuf(fd, 1024 * 1024 * 8);
#if defined(HAVE_IP_PKTINFO)
/* Linux and Solaris IP_PKTINFO */
data = 1;
- if (setsockopt(autorp->sock, PIM_IPPROTO, IP_PKTINFO, &data, data_len)) {
- zlog_err("Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s",
- autorp->sock, errno, safe_strerror(errno));
+ if (setsockopt(fd, PIM_IPPROTO, IP_PKTINFO, &data, data_len)) {
+ zlog_warn("%s: Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", __func__,
+ fd, errno, safe_strerror(errno));
return false;
}
#endif
- if (set_nonblocking(autorp->sock) < 0) {
- zlog_err("Could not set non blocking on socket fd=%d: errno=%d: %s",
- autorp->sock, errno, safe_strerror(errno));
+ if (set_nonblocking(fd) < 0) {
+ zlog_warn("%s: Could not set non blocking on socket fd=%d: errno=%d: %s", __func__,
+ fd, errno, safe_strerror(errno));
+ return false;
+ }
+
+ if (sockopt_reuseaddr(fd)) {
+ zlog_warn("%s: Could not set reuse addr on socket fd=%d: errno=%d: %s", __func__,
+ fd, errno, safe_strerror(errno));
return false;
}
- if (sockopt_reuseaddr(autorp->sock)) {
- zlog_err("Could not set reuse addr on socket fd=%d: errno=%d: %s",
- autorp->sock, errno, safe_strerror(errno));
+ if (setsockopt_ipv4_multicast_loop(fd, 1) < 0) {
+ zlog_warn("%s: Could not enable multicast loopback on socket fd=%d: errno=%d: %s",
+ __func__, fd, errno, safe_strerror(errno));
return false;
}
- if (bind(autorp->sock, (const struct sockaddr *)&autorp_addr,
- sizeof(autorp_addr)) < 0) {
- zlog_err("Could not bind socket: %pSUp, fd=%d, errno=%d, %s",
- (union sockunion *)&autorp_addr, autorp->sock, errno,
- safe_strerror(errno));
+ if (bind(fd, (const struct sockaddr *)&autorp_addr, sizeof(autorp_addr)) < 0) {
+ zlog_warn("%s: Could not bind socket: %pSUp, fd=%d, errno=%d, %s", __func__,
+ (union sockunion *)&autorp_addr, fd, errno, safe_strerror(errno));
return false;
}
@@ -208,20 +233,148 @@ static bool pim_autorp_setup(struct pim_autorp *autorp)
return true;
}
-static bool pim_autorp_announcement(struct pim_autorp *autorp, uint8_t rpcnt,
- uint16_t holdtime, char *buf,
- size_t buf_size)
+static void autorp_ma_rp_holdtime(struct event *evt)
{
- /* TODO: Future Mapping agent implementation
- * Implement AutoRP mapping agent logic using received announcement messages
- */
+ /* Mapping agent RP hold time expired, remove the RP */
+ struct pim_autorp_rp *rp = EVENT_ARG(evt);
+
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: AutoRP hold time expired, RP removed from mapping agent: addr=%pI4, grp=%pFX, grplist=%s",
+ __func__, &rp->addr, &rp->grp,
+ (strlen(rp->grplist) ? rp->grplist : "NONE"));
+
+ pim_autorp_rp_del(&(rp->autorp->mapping_rp_list), rp);
+ pim_autorp_rp_free(rp, false);
+}
+
+static bool autorp_recv_announcement(struct pim_autorp *autorp, uint8_t rpcnt, uint16_t holdtime,
+ char *buf, size_t buf_size)
+{
+ int i, j;
+ struct autorp_pkt_rp *rp;
+ struct autorp_pkt_grp *grp;
+ size_t offset = 0;
+ pim_addr rp_addr;
+ struct pim_autorp_rp *ma_rp;
+ struct pim_autorp_rp *trp;
+
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Processing AutoRP Announcement (rpcnt=%u, holdtime=%u)", __func__,
+ rpcnt, holdtime);
+
+ for (i = 0; i < rpcnt; ++i) {
+ if ((buf_size - offset) < AUTORP_RPLEN) {
+ zlog_warn("%s: Failed to parse AutoRP Announcement RP, invalid buffer size (%u < %u)",
+ __func__, (uint32_t)(buf_size - offset), AUTORP_RPLEN);
+ return false;
+ }
+
+ rp = (struct autorp_pkt_rp *)(buf + offset);
+ offset += AUTORP_RPLEN;
+
+ rp_addr.s_addr = rp->addr;
+
+ /* Ignore RP's limited to PIM version 1 or with an unknown version */
+ if (rp->pimver == AUTORP_PIM_V1 || rp->pimver == AUTORP_PIM_VUNKNOWN) {
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Ignoring unsupported PIM version (%u) in AutoRP Announcement for RP %pI4",
+ __func__, rp->pimver, (in_addr_t *)&(rp->addr));
+ /* Update the offset to skip past the groups advertised for this RP */
+ offset += (AUTORP_GRPLEN * rp->grpcnt);
+ continue;
+ }
+
+ if (rp->grpcnt == 0) {
+ /* No groups?? */
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Announcement message has no groups for RP %pI4",
+ __func__, (in_addr_t *)&(rp->addr));
+ continue;
+ }
+
+ if ((buf_size - offset) < AUTORP_GRPLEN) {
+ zlog_warn("%s: Buffer underrun parsing groups for RP %pI4", __func__,
+ (in_addr_t *)&(rp->addr));
+ return false;
+ }
+
+ /* Store all announced RP's, calculate what to send in discovery when discovery is sent. */
+ ma_rp = XCALLOC(MTYPE_PIM_AUTORP_RP, sizeof(struct pim_autorp_rp));
+ memcpy(&(ma_rp->addr), &rp_addr, sizeof(pim_addr));
+ trp = pim_autorp_rp_add(&(autorp->mapping_rp_list), ma_rp);
+ if (trp == NULL) {
+ /* RP was brand new, finish initializing */
+ ma_rp->autorp = autorp;
+ ma_rp->holdtime = holdtime;
+ ma_rp->hold_timer = NULL;
+ ma_rp->grplist[0] = '\0';
+ memset(&(ma_rp->grp), 0, sizeof(ma_rp->grp));
+ pim_autorp_grppfix_init(&ma_rp->grp_pfix_list);
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: New candidate RP learned (%pPA)", __func__,
+ &rp_addr);
+ } else {
+ /* Returned an existing entry, free allocated RP */
+ XFREE(MTYPE_PIM_AUTORP_RP, ma_rp);
+ ma_rp = trp;
+ /* Free the existing group prefix list, in case the advertised groups changed */
+ pim_autorp_grppfix_free(&ma_rp->grp_pfix_list);
+ }
+
+ /* Cancel any existing timer and restart it */
+ event_cancel(&ma_rp->hold_timer);
+ if (holdtime > 0)
+ event_add_timer(router->master, autorp_ma_rp_holdtime, ma_rp,
+ ma_rp->holdtime, &(ma_rp->hold_timer));
+
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Parsing %u group(s) for candidate RP %pPA", __func__,
+ rp->grpcnt, &rp_addr);
+
+ for (j = 0; j < rp->grpcnt; ++j) {
+ /* grp is already pointing at the first group in the buffer */
+ struct pim_autorp_grppfix *lgrp;
+ struct pim_autorp_grppfix *tgrp;
+
+ if ((buf_size - offset) < AUTORP_GRPLEN) {
+ zlog_warn("%s: Failed parsing AutoRP announcement, RP(%pI4), invalid buffer size (%u < %u)",
+ __func__, &rp_addr, (uint32_t)(buf_size - offset),
+ AUTORP_GRPLEN);
+ return false;
+ }
+
+ grp = (struct autorp_pkt_grp *)(buf + offset);
+ offset += AUTORP_GRPLEN;
+
+ lgrp = XCALLOC(MTYPE_PIM_AUTORP_GRPPFIX, sizeof(struct pim_autorp_grppfix));
+ lgrp->grp.family = AF_INET;
+ lgrp->grp.prefixlen = grp->masklen;
+ lgrp->grp.u.prefix4.s_addr = grp->addr;
+ lgrp->negative = grp->negprefix;
+
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: %s%pFX added to candidate RP %pPA", __func__,
+ (lgrp->negative ? "!" : ""), &lgrp->grp, &rp_addr);
+
+ tgrp = pim_autorp_grppfix_add(&ma_rp->grp_pfix_list, lgrp);
+ if (tgrp != NULL) {
+ /* This should never happen but if there was an existing entry just free the
+ * allocated group prefix
+ */
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: %pFX was duplicated in AutoRP announcement",
+ __func__, &lgrp->grp);
+ XFREE(MTYPE_PIM_AUTORP_GRPPFIX, lgrp);
+ }
+ }
+ }
+
if (PIM_DEBUG_AUTORP)
- zlog_debug("%s: AutoRP processed announcement message",
- __func__);
+ zlog_debug("%s: AutoRP processed announcement message", __func__);
return true;
}
-static void autorp_rp_holdtime(struct event *evt)
+static void autorp_cand_rp_holdtime(struct event *evt)
{
/* RP hold time expired, remove the RP */
struct pim_autorp_rp *rp = EVENT_ARG(evt);
@@ -232,79 +385,320 @@ static void autorp_rp_holdtime(struct event *evt)
(strlen(rp->grplist) ? rp->grplist : "NONE"));
pim_autorp_rp_del(&(rp->autorp->discovery_rp_list), rp);
- pim_autorp_rp_free(rp);
+ pim_autorp_rp_free(rp, true);
}
-static bool pim_autorp_add_rp(struct pim_autorp *autorp, pim_addr rpaddr,
- struct prefix grp, char *listname,
- uint16_t holdtime)
+static bool pim_autorp_add_rp(struct pim_autorp *autorp, pim_addr rpaddr, struct prefix grp,
+ char *listname, uint16_t holdtime)
{
struct pim_autorp_rp *rp;
struct pim_autorp_rp *trp = NULL;
int ret;
ret = pim_rp_new(autorp->pim, rpaddr, grp, listname, RP_SRC_AUTORP);
+
/* There may not be a path to the RP right now, but that doesn't mean it failed to add the RP */
if (ret != PIM_SUCCESS && ret != PIM_RP_NO_PATH) {
- zlog_err("%s: Failed to add new RP addr=%pI4, grp=%pFX, grplist=%s",
- __func__, &rpaddr, &grp,
- (listname ? listname : "NONE"));
+ zlog_warn("%s: Failed to add active RP addr=%pI4, grp=%pFX, grplist=%s", __func__,
+ &rpaddr, &grp, (listname ? listname : "NONE"));
return false;
}
- if (PIM_DEBUG_AUTORP)
- zlog_debug("%s: Added new AutoRP learned RP addr=%pI4, grp=%pFX, grplist=%s",
- __func__, &rpaddr, &grp,
- (listname ? listname : "NONE"));
-
rp = XCALLOC(MTYPE_PIM_AUTORP_RP, sizeof(*rp));
rp->autorp = autorp;
memcpy(&(rp->addr), &rpaddr, sizeof(pim_addr));
- prefix_copy(&(rp->grp), &grp);
- if (listname)
- snprintf(rp->grplist, sizeof(rp->grplist), "%s", listname);
- else
- rp->grplist[0] = '\0';
-
- rp->holdtime = holdtime;
- rp->hold_timer = NULL;
trp = pim_autorp_rp_add(&(autorp->discovery_rp_list), rp);
if (trp == NULL) {
/* RP was brand new */
trp = pim_autorp_rp_find(&(autorp->discovery_rp_list),
(const struct pim_autorp_rp *)rp);
+ /* Make sure the timer is NULL so the cancel below doesn't mess up */
+ trp->hold_timer = NULL;
+ zlog_info("%s: Added new AutoRP learned RP addr=%pI4, grp=%pFX, grplist=%s",
+ __func__, &rpaddr, &grp, (listname ? listname : "NONE"));
} else {
- /* RP already existed */
+ /* RP already existed, free the temp one */
XFREE(MTYPE_PIM_AUTORP_RP, rp);
- event_cancel(&trp->hold_timer);
-
- /* We know the address matches, but these values may have changed */
- trp->holdtime = holdtime;
- prefix_copy(&(trp->grp), &grp);
- if (listname) {
- snprintf(trp->grplist, sizeof(trp->grplist), "%s",
- listname);
- } else {
- trp->grplist[0] = '\0';
- }
}
+ /* Cancel any existing timer before restarting it */
+ event_cancel(&trp->hold_timer);
+ trp->holdtime = holdtime;
+ prefix_copy(&(trp->grp), &grp);
+ if (listname)
+ snprintf(trp->grplist, sizeof(trp->grplist), "%s", listname);
+ else
+ trp->grplist[0] = '\0';
+
if (holdtime > 0) {
- event_add_timer(router->master, autorp_rp_holdtime, trp,
- holdtime, &(trp->hold_timer));
+ event_add_timer(router->master, autorp_cand_rp_holdtime, trp, holdtime,
+ &(trp->hold_timer));
if (PIM_DEBUG_AUTORP)
zlog_debug("%s: Started %u second hold timer for RP %pI4", __func__,
holdtime, &trp->addr);
- } else {
- /* If hold time is zero, make sure there doesn't exist a hold timer for it already */
- event_cancel(&trp->hold_timer);
}
return true;
}
-static bool pim_autorp_discovery(struct pim_autorp *autorp, uint8_t rpcnt,
- uint16_t holdtime, char *buf, size_t buf_size)
+static size_t autorp_build_disc_rps(struct pim_autorp *autorp, uint8_t *buf, size_t buf_sz,
+ size_t *sz)
+{
+ /* Header has already been added, fill in starting with the address of RP1
+ * buf_sz is the max size of the buf
+ * sz is the current size of the packet, update as buf is filled
+ * return the total number of RP's added
+ *
+ *
+ * We need to resolve the announced RP's following these rules:
+ * 1) Co-existence of longer and shorter group prefixes, from different RPs. E.g. when RP1
+ * announces 224.2.*.*, and RP2 announces 224.2.2.*, both are accepted;
+ * 2) For announcements for identical group prefixes from two different RPs, the one from the
+ * RP with the higher IP address is accepted;
+ * 3) No duplicates are sent to the AUTORP-DISCOVERY address. E.g. if an RP announces both
+ * 224.2.2.* and 224.2.*.*, the former group-prefix is not sent and only 224.2.*.* is sent
+ * to the AUTORP-DISCOVERY address.
+ *
+ *
+ * The approach to resolution, first loop the stored RP's and extract the group prefixes, stored
+ * in a sorted list, sorted from least specific to most 0.0.0.0/0 -> 239.255.255.255/32. Each
+ * group prefix will then store the RP advertising that group prefix, this will resolve 2.
+ * The next step is to then loop the group prefix list and store them back into a list sorted by
+ * RP address, where the least specific group address will be stored, resolving 3. 1 is more
+ * about what is allowed, and in the example above the different prefixes will be unique in the
+ * list of group prefixes, and when they go back into RP's, they are also from different RP's
+ * and will therefore be sent.
+ */
+
+ struct pim_autorp_rp *rp;
+ struct pim_autorp_rp *trp;
+ struct pim_autorp_grppfix *grp;
+ struct pim_autorp_grppfix *grp2;
+ struct pim_autorp_grppfix *tgrp;
+ struct pim_autorp_grppfix_head grplist;
+ bool skip = false;
+ size_t rpcnt = 0;
+ size_t bsz = 0;
+
+ /* Initialize the lists, grplist is temporary, disc rp list is stored long term for
+ * show output, so make sure it's empty
+ */
+ pim_autorp_grppfix_init(&grplist);
+ pim_autorp_rplist_free(&autorp->advertised_rp_list, false);
+
+ /* Loop the advertised RP's and their group prefixes and make a unique list of group prefixes,
+ * keeping just the highest IP RP for each group prefix
+ */
+ frr_each (pim_autorp_rp, &autorp->mapping_rp_list, rp) {
+ frr_each (pim_autorp_grppfix, &rp->grp_pfix_list, grp) {
+ grp2 = XCALLOC(MTYPE_PIM_AUTORP_GRPPFIX, sizeof(struct pim_autorp_grppfix));
+ prefix_copy(&grp2->grp, &grp->grp);
+ grp2->negative = grp->negative;
+ grp2->rp = rp->addr;
+ tgrp = pim_autorp_grppfix_add(&grplist, grp2);
+ if (tgrp != NULL) {
+ /* Returned an existing entry. Use the highest RP addr and free allocated object */
+ if (IPV4_ADDR_CMP(&tgrp->rp, &grp2->rp))
+ tgrp->rp = grp2->rp;
+ XFREE(MTYPE_PIM_AUTORP_GRPPFIX, grp2);
+ }
+ }
+ }
+
+ /* Now loop the unique group prefixes and put it back into an RP list */
+ frr_each (pim_autorp_grppfix, &grplist, grp) {
+ rp = XCALLOC(MTYPE_PIM_AUTORP_RP, sizeof(struct pim_autorp_rp));
+ rp->addr = grp->rp;
+ trp = pim_autorp_rp_add(&autorp->advertised_rp_list, rp);
+ if (trp == NULL) {
+ /* RP was brand new, finish initializing */
+ rp->autorp = NULL;
+ rp->holdtime = 0;
+ rp->hold_timer = NULL;
+ rp->grplist[0] = '\0';
+ memset(&(rp->grp), 0, sizeof(rp->grp));
+ pim_autorp_grppfix_init(&rp->grp_pfix_list);
+ } else {
+ /* Returned an existing entry, free allocated RP */
+ XFREE(MTYPE_PIM_AUTORP_RP, rp);
+ rp = trp;
+ }
+
+ /* Groups are in order from least specific to most, so go through the existing
+ * groups for this RP and see if the current group is within the prefix of one that
+ * is already in the list, if so, skip it, if not, add it
+ * If one is a positive match and the other is negative, then still include it.
+ */
+ skip = false;
+ frr_each (pim_autorp_grppfix, &rp->grp_pfix_list, grp2) {
+ if (prefix_match(&grp2->grp, &grp->grp) && grp->negative == grp2->negative) {
+ skip = true;
+ break;
+ }
+ }
+
+ if (skip)
+ continue;
+
+ /* add the group to the RP's group list */
+ grp2 = XCALLOC(MTYPE_PIM_AUTORP_GRPPFIX, sizeof(struct pim_autorp_grppfix));
+ prefix_copy(&grp2->grp, &grp->grp);
+ grp2->negative = grp->negative;
+ tgrp = pim_autorp_grppfix_add(&rp->grp_pfix_list, grp2);
+ assert(tgrp == NULL);
+ }
+
+ /* Done with temporary group prefix list, so free and finish */
+ pim_autorp_grppfix_free(&grplist);
+ pim_autorp_grppfix_fini(&grplist);
+
+ /* Now finally we can loop the disc rp list and build the packet */
+ frr_each (pim_autorp_rp, &autorp->advertised_rp_list, rp) {
+ struct autorp_pkt_rp *brp;
+ struct autorp_pkt_grp *bgrp;
+ size_t rp_sz;
+ size_t grpcnt;
+
+ grpcnt = pim_autorp_grppfix_count(&rp->grp_pfix_list);
+ rp_sz = sizeof(struct autorp_pkt_rp) + (grpcnt * sizeof(struct autorp_pkt_grp));
+ if (buf_sz < *sz + rp_sz) {
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Failed to pack AutoRP discovery packet, buffer overrun, (%u < %u)",
+ __func__, (uint32_t)buf_sz, (uint32_t)(*sz + rp_sz));
+ break;
+ }
+
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Add RP %pI4 (grpcnt=%u) to discovery message", __func__,
+ &rp->addr, (uint32_t)grpcnt);
+
+ rpcnt++;
+
+ brp = (struct autorp_pkt_rp *)(buf + bsz);
+ bsz += sizeof(struct autorp_pkt_rp);
+
+ /* Since this is an in_addr, assume it's already the right byte order */
+ brp->addr = rp->addr.s_addr;
+ brp->pimver = AUTORP_PIM_V2;
+ brp->reserved = 0;
+ brp->grpcnt = grpcnt;
+
+ frr_each (pim_autorp_grppfix, &rp->grp_pfix_list, grp) {
+ bgrp = (struct autorp_pkt_grp *)(buf + bsz);
+ bsz += sizeof(struct autorp_pkt_grp);
+
+ bgrp->addr = grp->grp.u.prefix4.s_addr;
+ bgrp->masklen = grp->grp.prefixlen;
+ bgrp->negprefix = grp->negative;
+
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Add group %s%pFX for RP %pI4 to discovery message",
+ __func__, (grp->negative ? "!" : ""), &grp->grp,
+ &rp->addr);
+ }
+
+ /* Update the size with this RP now that it is packed */
+ *sz += bsz;
+ }
+
+ return rpcnt;
+}
+
+static size_t autorp_build_disc_packet(struct pim_autorp *autorp, uint8_t *buf, size_t buf_sz)
+{
+ size_t sz = 0;
+ struct autorp_pkt_hdr *hdr;
+
+ if (buf_sz >= AUTORP_HDRLEN) {
+ hdr = (struct autorp_pkt_hdr *)buf;
+ hdr->version = AUTORP_VERSION;
+ hdr->type = AUTORP_DISCOVERY_TYPE;
+ hdr->holdtime = htons(autorp->discovery_holdtime);
+ hdr->reserved = 0;
+ sz += AUTORP_HDRLEN;
+ hdr->rpcnt = autorp_build_disc_rps(autorp, buf + sizeof(struct autorp_pkt_hdr),
+ (buf_sz - AUTORP_HDRLEN), &sz);
+ if (hdr->rpcnt == 0)
+ sz = 0;
+ }
+ return sz;
+}
+
+static void autorp_send_discovery(struct event *evt)
+{
+ struct pim_autorp *autorp = EVENT_ARG(evt);
+ struct sockaddr_in discGrp;
+ size_t disc_sz;
+ size_t buf_sz = 65535;
+ uint8_t buf[65535] = { 0 };
+
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: AutoRP sending discovery info", __func__);
+
+ /* Mark true, even if nothing is sent */
+ autorp->mapping_agent_active = true;
+ disc_sz = autorp_build_disc_packet(autorp, buf, buf_sz);
+
+ if (disc_sz > 0) {
+ discGrp.sin_family = AF_INET;
+ discGrp.sin_port = htons(PIM_AUTORP_PORT);
+ inet_pton(PIM_AF, PIM_AUTORP_DISCOVERY_GRP, &discGrp.sin_addr);
+
+ if (setsockopt(autorp->sock, IPPROTO_IP, IP_MULTICAST_TTL,
+ &(autorp->discovery_scope), sizeof(autorp->discovery_scope)) == 0) {
+ if (setsockopt(autorp->sock, IPPROTO_IP, IP_MULTICAST_IF,
+ &(autorp->mapping_agent_addrsel.run_addr),
+ sizeof(autorp->mapping_agent_addrsel.run_addr)) == 0) {
+ if (sendto(autorp->sock, buf, disc_sz, 0,
+ (struct sockaddr *)&discGrp, sizeof(discGrp)) > 0) {
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: AutoRP discovery message sent",
+ __func__);
+ } else if (PIM_DEBUG_AUTORP)
+ zlog_warn("%s: Failed to send AutoRP discovery message, errno=%d, %s",
+ __func__, errno, safe_strerror(errno));
+ } else if (PIM_DEBUG_AUTORP)
+ zlog_warn("%s: Failed to set Multicast Interface for sending AutoRP discovery message, errno=%d, %s",
+ __func__, errno, safe_strerror(errno));
+ } else if (PIM_DEBUG_AUTORP)
+ zlog_warn("%s: Failed to set Multicast TTL for sending AutoRP discovery message, errno=%d, %s",
+ __func__, errno, safe_strerror(errno));
+ }
+
+ /* Start the new timer for the entire send discovery interval */
+ event_add_timer(router->master, autorp_send_discovery, autorp, autorp->discovery_interval,
+ &(autorp->send_discovery_timer));
+}
+
+static void autorp_send_discovery_on(struct pim_autorp *autorp)
+{
+ int interval = 5;
+
+ /* Send the first discovery shortly after being enabled.
+ * If the configured interval is less than 5 seconds, then just use that.
+ */
+ if (interval > autorp->discovery_interval)
+ interval = autorp->discovery_interval;
+
+ if (autorp->send_discovery_timer)
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: AutoRP discovery sending enabled in %u seconds", __func__,
+ interval);
+
+ event_add_timer(router->master, autorp_send_discovery, autorp, interval,
+ &(autorp->send_discovery_timer));
+}
+
+static void autorp_send_discovery_off(struct pim_autorp *autorp)
+{
+ if (autorp->send_discovery_timer)
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: AutoRP discovery sending disabled", __func__);
+ event_cancel(&(autorp->send_discovery_timer));
+}
+
+static bool autorp_recv_discovery(struct pim_autorp *autorp, uint8_t rpcnt, uint16_t holdtime,
+ char *buf, size_t buf_size, pim_addr src)
{
int i, j;
struct autorp_pkt_rp *rp;
@@ -318,65 +712,122 @@ static bool pim_autorp_discovery(struct pim_autorp *autorp, uint8_t rpcnt,
int64_t seq = 1;
bool success = true;
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Received AutoRP discovery message (src=%pI4, rpcnt=%u, holdtime=%u)",
+ __func__, &src, rpcnt, holdtime);
+
+ if (autorp->send_rp_discovery &&
+ (pim_addr_cmp(autorp->mapping_agent_addrsel.run_addr, src) < 0)) {
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: AutoRP send discovery suppressed -- Discovery received with higher IP address",
+ __func__);
+
+ /* Cancel the existing send timer and restart for 3X the send discovery interval */
+ event_cancel(&(autorp->send_discovery_timer));
+ event_add_timer(router->master, autorp_send_discovery, autorp,
+ (autorp->discovery_interval * 3), &(autorp->send_discovery_timer));
+
+ /* Clear the last sent discovery RP's, since it is no longer valid */
+ pim_autorp_rplist_free(&autorp->advertised_rp_list, false);
+ /* Unset flag indicating we are active */
+ autorp->mapping_agent_active = false;
+ }
+
for (i = 0; i < rpcnt; ++i) {
- if ((buf_size - offset) < AUTORP_RPLEN)
+ if ((buf_size - offset) < AUTORP_RPLEN) {
+ zlog_warn("%s: Failed to parse AutoRP discovery message, invalid buffer size (%u < %u)",
+ __func__, (uint32_t)(buf_size - offset), AUTORP_RPLEN);
return false;
+ }
rp = (struct autorp_pkt_rp *)(buf + offset);
offset += AUTORP_RPLEN;
rp_addr.s_addr = rp->addr;
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Parsing RP %pI4 (grpcnt=%u)", __func__,
+ (in_addr_t *)&rp->addr, rp->grpcnt);
+
/* Ignore RP's limited to PIM version 1 or with an unknown version */
- if (rp->pimver == PIM_V1 || rp->pimver == PIM_VUNKNOWN) {
- zlog_warn("%s: Ignoring unsupported PIM version in AutoRP Discovery for RP %pI4",
- __func__, (in_addr_t *)&(rp->addr));
+ if (rp->pimver == AUTORP_PIM_V1 || rp->pimver == AUTORP_PIM_VUNKNOWN) {
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Ignoring unsupported PIM version in AutoRP Discovery for RP %pI4",
+ __func__, (in_addr_t *)&(rp->addr));
/* Update the offset to skip past the groups advertised for this RP */
offset += (AUTORP_GRPLEN * rp->grpcnt);
continue;
}
-
if (rp->grpcnt == 0) {
/* No groups?? */
- zlog_warn("%s: Discovery message has no groups for RP %pI4",
- __func__, (in_addr_t *)&(rp->addr));
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Discovery message has no groups for RP %pI4",
+ __func__, (in_addr_t *)&(rp->addr));
continue;
}
- if ((buf_size - offset) < AUTORP_GRPLEN) {
- zlog_warn("%s: Buffer underrun parsing groups for RP %pI4",
- __func__, (in_addr_t *)&(rp->addr));
+ /* Make sure there is enough buffer to parse all the groups */
+ if ((buf_size - offset) < (AUTORP_GRPLEN * rp->grpcnt)) {
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Buffer underrun parsing groups for RP %pI4 (%u < %u)",
+ __func__, (in_addr_t *)&(rp->addr),
+ (uint32_t)(buf_size - offset),
+ (uint32_t)(AUTORP_GRPLEN * rp->grpcnt));
return false;
}
+ /* Get the first group so we can check for a negative prefix */
+ /* Don't add to offset yet to make the multiple group loop easier */
grp = (struct autorp_pkt_grp *)(buf + offset);
- offset += AUTORP_GRPLEN;
if (rp->grpcnt == 1 && grp->negprefix == 0) {
/* Only one group with positive prefix, we can use the standard RP API */
+ offset += AUTORP_GRPLEN;
grppfix.family = AF_INET;
grppfix.prefixlen = grp->masklen;
grppfix.u.prefix4.s_addr = grp->addr;
- if (!pim_autorp_add_rp(autorp, rp_addr, grppfix, NULL,
- holdtime))
+
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Parsing group %s%pFX for RP %pI4", __func__,
+ (grp->negprefix ? "!" : ""), &grppfix,
+ (in_addr_t *)&rp->addr);
+
+ if (!pim_autorp_add_rp(autorp, rp_addr, grppfix, NULL, holdtime))
success = false;
} else {
- /* More than one grp, or the only group is a negative prefix, need to make a prefix list for this RP */
- snprintfrr(plname, sizeof(plname), "__AUTORP_%pI4__",
- &rp_addr);
+ /* More than one grp, or the only group is a negative prefix.
+ * Need to make a prefix list for this RP
+ */
+ snprintfrr(plname, sizeof(plname), "__AUTORP_%pI4__", &rp_addr);
+ pl = prefix_list_lookup(AFI_IP, plname);
+
+ if (pl) {
+ /* Existing prefix list found, delete it first */
+ /* TODO: Instead of deleting completely, maybe we can just clear it and re-add entries */
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Found existing prefix list %s, replacing it",
+ __func__, plname);
+ prefix_list_delete(pl);
+ }
+
+ /* Now get a new prefix list */
pl = prefix_list_get(AFI_IP, 0, plname);
for (j = 0; j < rp->grpcnt; ++j) {
- /* grp is already pointing at the first group in the buffer */
+ /* This will just set grp to the same pointer on the first loop, but offset will
+ * be updated correctly while parsing
+ */
+ grp = (struct autorp_pkt_grp *)(buf + offset);
+ offset += AUTORP_GRPLEN;
+
ple = prefix_list_entry_new();
ple->pl = pl;
ple->seq = seq;
seq += 5;
memset(&ple->prefix, 0, sizeof(ple->prefix));
prefix_list_entry_update_start(ple);
- ple->type = (grp->negprefix ? PREFIX_DENY
- : PREFIX_PERMIT);
+ ple->type = (grp->negprefix ? PREFIX_DENY : PREFIX_PERMIT);
ple->prefix.family = AF_INET;
ple->prefix.prefixlen = grp->masklen;
ple->prefix.u.prefix4.s_addr = grp->addr;
@@ -385,60 +836,59 @@ static bool pim_autorp_discovery(struct pim_autorp *autorp, uint8_t rpcnt,
ple->le = 32;
prefix_list_entry_update_finish(ple);
- if ((buf_size - offset) < AUTORP_GRPLEN)
- return false;
-
- grp = (struct autorp_pkt_grp *)(buf + offset);
- offset += AUTORP_GRPLEN;
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Parsing group %s%pFX for RP %pI4", __func__,
+ (grp->negprefix ? "!" : ""), &ple->prefix,
+ (in_addr_t *)&rp->addr);
}
- if (!pim_autorp_add_rp(autorp, rp_addr, grppfix, plname,
- holdtime))
+ if (!pim_autorp_add_rp(autorp, rp_addr, grppfix, plname, holdtime))
success = false;
}
}
- if (PIM_DEBUG_AUTORP)
- zlog_debug("%s: Processed AutoRP Discovery message", __func__);
-
return success;
}
-static bool pim_autorp_msg(struct pim_autorp *autorp, char *buf, size_t buf_size)
+static bool autorp_recv_msg(struct pim_autorp *autorp, char *buf, size_t buf_size, pim_addr src)
{
struct autorp_pkt_hdr *h;
- if (buf_size < AUTORP_HDRLEN)
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Received AutoRP message", __func__);
+
+ if (buf_size < AUTORP_HDRLEN) {
+ zlog_warn("%s: Invalid AutoRP Header size (%u < %u)", __func__, (uint32_t)buf_size,
+ AUTORP_HDRLEN);
return false;
+ }
h = (struct autorp_pkt_hdr *)buf;
- if (h->version != AUTORP_VERSION)
+ if (h->version != AUTORP_VERSION) {
+ zlog_warn("%s: Unsupported AutoRP version (%u != %u)", __func__, h->version,
+ AUTORP_VERSION);
return false;
+ }
- if (h->type == AUTORP_ANNOUNCEMENT_TYPE &&
- !pim_autorp_announcement(autorp, h->rpcnt, htons(h->holdtime),
- buf + AUTORP_HDRLEN,
- buf_size - AUTORP_HDRLEN))
- return false;
+ if (h->type == AUTORP_ANNOUNCEMENT_TYPE)
+ return autorp_recv_announcement(autorp, h->rpcnt, htons(h->holdtime),
+ buf + AUTORP_HDRLEN, buf_size - AUTORP_HDRLEN);
- if (h->type == AUTORP_DISCOVERY_TYPE &&
- !pim_autorp_discovery(autorp, h->rpcnt, htons(h->holdtime),
- buf + AUTORP_HDRLEN, buf_size - AUTORP_HDRLEN))
- return false;
+ if (h->type == AUTORP_DISCOVERY_TYPE)
+ return autorp_recv_discovery(autorp, h->rpcnt, htons(h->holdtime),
+ buf + AUTORP_HDRLEN, buf_size - AUTORP_HDRLEN, src);
- if (PIM_DEBUG_AUTORP)
- zlog_debug("%s: Processed AutoRP packet", __func__);
+ zlog_warn("%s: Unknown AutoRP message type (%u)", __func__, h->type);
- return true;
+ return false;
}
static void autorp_read(struct event *t);
static void autorp_read_on(struct pim_autorp *autorp)
{
- event_add_read(router->master, autorp_read, autorp, autorp->sock,
- &(autorp->read_event));
+ event_add_read(router->master, autorp_read, autorp, autorp->sock, &(autorp->read_event));
if (PIM_DEBUG_AUTORP)
zlog_debug("%s: AutoRP socket read enabled", __func__);
}
@@ -456,26 +906,35 @@ static void autorp_read(struct event *evt)
int fd = evt->u.fd;
char buf[10000];
int rd;
+ struct sockaddr_storage from;
+ socklen_t fromlen = sizeof(from);
+ pim_addr src;
if (PIM_DEBUG_AUTORP)
zlog_debug("%s: Reading from AutoRP socket", __func__);
while (1) {
- rd = pim_socket_recvfromto(fd, (uint8_t *)buf, sizeof(buf),
- NULL, NULL, NULL, NULL, NULL);
+ rd = pim_socket_recvfromto(fd, (uint8_t *)buf, sizeof(buf), &from, &fromlen, NULL,
+ NULL, NULL);
if (rd <= 0) {
if (errno == EINTR)
continue;
if (errno == EWOULDBLOCK || errno == EAGAIN)
break;
+ zlog_warn("%s: Failure reading rd=%d: fd=%d: errno=%d: %s", __func__, rd,
+ fd, errno, safe_strerror(errno));
+ goto err;
+ }
- zlog_warn("%s: Failure reading rd=%d: fd=%d: errno=%d: %s",
- __func__, rd, fd, errno, safe_strerror(errno));
+ if (from.ss_family == AF_INET)
+ src.s_addr = ((struct sockaddr_in *)&from)->sin_addr.s_addr;
+ else {
+ zlog_warn("%s: AutoRP message is not IPV4", __func__);
goto err;
}
- if (!pim_autorp_msg(autorp, buf, rd))
- zlog_err("%s: Failure parsing AutoRP message", __func__);
+ if (!autorp_recv_msg(autorp, buf, rd, src))
+ zlog_warn("%s: Failure parsing AutoRP message", __func__);
/* Keep reading until would block */
}
@@ -493,23 +952,23 @@ static bool pim_autorp_socket_enable(struct pim_autorp *autorp)
frr_with_privs (&pimd_privs) {
fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (fd < 0) {
- zlog_warn("Could not create autorp socket: errno=%d: %s",
- errno, safe_strerror(errno));
+ zlog_warn("Could not create autorp socket: errno=%d: %s", errno,
+ safe_strerror(errno));
return false;
}
- autorp->sock = fd;
- if (!pim_autorp_setup(autorp)) {
- zlog_warn("Could not setup autorp socket fd=%d: errno=%d: %s",
- fd, errno, safe_strerror(errno));
+ if (!pim_autorp_setup(fd)) {
+ zlog_warn("Could not setup autorp socket fd=%d: errno=%d: %s", fd, errno,
+ safe_strerror(errno));
close(fd);
- autorp->sock = -1;
return false;
}
}
+ autorp->sock = fd;
+
if (PIM_DEBUG_AUTORP)
- zlog_debug("%s: AutoRP socket enabled", __func__);
+ zlog_debug("%s: AutoRP socket enabled (fd=%u)", __func__, fd);
return true;
}
@@ -517,8 +976,8 @@ static bool pim_autorp_socket_enable(struct pim_autorp *autorp)
static bool pim_autorp_socket_disable(struct pim_autorp *autorp)
{
if (close(autorp->sock)) {
- zlog_warn("Failure closing autorp socket: fd=%d errno=%d: %s",
- autorp->sock, errno, safe_strerror(errno));
+ zlog_warn("Failure closing autorp socket: fd=%d errno=%d: %s", autorp->sock, errno,
+ safe_strerror(errno));
return false;
}
@@ -542,13 +1001,15 @@ static void autorp_send_announcement(struct event *evt)
announceGrp.sin_port = htons(PIM_AUTORP_PORT);
inet_pton(PIM_AF, PIM_AUTORP_ANNOUNCEMENT_GRP, &announceGrp.sin_addr);
- if (autorp->annouce_pkt_sz >= MIN_AUTORP_PKT_SZ) {
+ if (autorp->announce_pkt_sz >= MIN_AUTORP_PKT_SZ) {
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Sending AutoRP announcement", __func__);
+
if (setsockopt(autorp->sock, IPPROTO_IP, IP_MULTICAST_TTL,
- &(autorp->announce_scope),
- sizeof(autorp->announce_scope)) < 0) {
- if (PIM_DEBUG_AUTORP)
- zlog_err("%s: Failed to set Multicast TTL for sending AutoRP announcement message, errno=%d, %s",
- __func__, errno, safe_strerror(errno));
+ &(autorp->announce_scope), sizeof(autorp->announce_scope)) < 0) {
+ zlog_warn("%s: Failed to set Multicast TTL for sending AutoRP announcement message, errno=%d, %s",
+ __func__, errno, safe_strerror(errno));
+ return;
}
FOR_ALL_INTERFACES (autorp->pim->vrf, ifp) {
@@ -556,57 +1017,56 @@ static void autorp_send_announcement(struct event *evt)
/* Only send on active interfaces with full pim enabled, non-passive
* and have a primary address set.
*/
- if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
- pim_ifp && pim_ifp->pim_enable &&
- !pim_ifp->pim_passive_enable &&
+ if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) && pim_ifp &&
+ pim_ifp->pim_enable && !pim_ifp->pim_passive_enable &&
!pim_addr_is_any(pim_ifp->primary_address)) {
- if (setsockopt(autorp->sock, IPPROTO_IP,
- IP_MULTICAST_IF,
+ if (setsockopt(autorp->sock, IPPROTO_IP, IP_MULTICAST_IF,
&(pim_ifp->primary_address),
- sizeof(pim_ifp->primary_address)) <
- 0) {
- if (PIM_DEBUG_AUTORP)
- zlog_err("%s: Failed to set Multicast Interface for sending AutoRP announcement message, errno=%d, %s",
- __func__, errno,
- safe_strerror(errno));
+ sizeof(pim_ifp->primary_address)) < 0) {
+ zlog_warn("%s: Failed to set Multicast Interface for sending AutoRP announcement message, errno=%d, %s",
+ __func__, errno, safe_strerror(errno));
+ continue;
}
- if (sendto(autorp->sock, autorp->annouce_pkt,
- autorp->annouce_pkt_sz, 0,
+
+ if (sendto(autorp->sock, autorp->announce_pkt,
+ autorp->announce_pkt_sz, 0,
(struct sockaddr *)&announceGrp,
- sizeof(announceGrp)) <= 0) {
- if (PIM_DEBUG_AUTORP)
- zlog_err("%s: Failed to send AutoRP announcement message, errno=%d, %s",
- __func__, errno,
- safe_strerror(errno));
- }
+ sizeof(announceGrp)) <= 0)
+ zlog_warn("%s: Failed to send AutoRP announcement message, errno=%d, %s",
+ __func__, errno, safe_strerror(errno));
}
}
}
/* Start the new timer for the entire announce interval */
- event_add_timer(router->master, autorp_send_announcement, autorp,
- autorp->announce_interval, &(autorp->announce_timer));
+ event_add_timer(router->master, autorp_send_announcement, autorp, autorp->announce_interval,
+ &(autorp->announce_timer));
}
static void autorp_announcement_on(struct pim_autorp *autorp)
{
int interval = 5;
- if (interval > autorp->announce_interval) {
- /* If the configured interval is less than 5 seconds, then just use that */
+ /* Send the first announcement shortly after being enabled.
+ * If the configured interval is less than 5 seconds, then just use that.
+ */
+ if (interval > autorp->announce_interval)
interval = autorp->announce_interval;
- }
- event_add_timer(router->master, autorp_send_announcement, autorp,
- interval, &(autorp->announce_timer));
- if (PIM_DEBUG_AUTORP)
- zlog_debug("%s: AutoRP announcement sending enabled", __func__);
+
+ if (autorp->announce_timer == NULL)
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: AutoRP announcement sending enabled", __func__);
+
+ event_add_timer(router->master, autorp_send_announcement, autorp, interval,
+ &(autorp->announce_timer));
}
static void autorp_announcement_off(struct pim_autorp *autorp)
{
+ if (autorp->announce_timer != NULL)
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: AutoRP announcement sending disabled", __func__);
event_cancel(&(autorp->announce_timer));
- if (PIM_DEBUG_AUTORP)
- zlog_debug("%s: AutoRP announcement sending disabled", __func__);
}
/* Pack the groups of the RP
@@ -614,34 +1074,31 @@ static void autorp_announcement_off(struct pim_autorp *autorp)
* buf - Pointer to the buffer where to start packing groups
* returns - Total group count packed
*/
-static uint8_t pim_autorp_new_announcement_rp_grps(struct pim_autorp_rp *rp,
- uint8_t *buf)
+static uint8_t pim_autorp_new_announcement_rp_grps(struct pim_autorp_rp *rp, uint8_t *buf)
{
- struct prefix_list *plist;
- struct prefix_list_entry *ple;
struct autorp_pkt_grp *grpp = (struct autorp_pkt_grp *)buf;
uint8_t cnt = 0;
- in_addr_t taddr;
if (is_default_prefix(&(rp->grp))) {
/* No group so pack from the prefix list
* The grplist should be set and the prefix list exist with at least one group address
*/
+ struct prefix_list *plist;
+ struct prefix_list_entry *ple;
+
plist = prefix_list_lookup(AFI_IP, rp->grplist);
for (ple = plist->head; ple; ple = ple->next) {
- taddr = ntohl(ple->prefix.u.prefix4.s_addr);
- if ((taddr & 0xF0000000) == 0xE0000000) {
+ if (pim_addr_is_multicast(ple->prefix.u.prefix4) &&
+ ple->prefix.prefixlen >= 4) {
grpp->addr = ple->prefix.u.prefix4.s_addr;
grpp->masklen = ple->prefix.prefixlen;
- grpp->negprefix =
- (ple->type == PREFIX_PERMIT ? 0 : 1);
+ grpp->negprefix = (ple->type == PREFIX_PERMIT ? 0 : 1);
grpp->reserved = 0;
++cnt;
- grpp = (struct autorp_pkt_grp
- *)(buf +
- (sizeof(struct autorp_pkt_grp) *
- cnt));
+ grpp = (struct autorp_pkt_grp *)(buf +
+ (sizeof(struct autorp_pkt_grp) *
+ cnt));
}
}
@@ -661,20 +1118,16 @@ static uint8_t pim_autorp_new_announcement_rp_grps(struct pim_autorp_rp *rp,
* buf - Pointer to the buffer where to start packing the RP
* returns - Buffer pointer pointing to the start of the next RP
*/
-static uint8_t *pim_autorp_new_announcement_rp(struct pim_autorp_rp *rp,
- uint8_t *buf)
+static uint8_t *pim_autorp_new_announcement_rp(struct pim_autorp_rp *rp, uint8_t *buf)
{
struct autorp_pkt_rp *brp = (struct autorp_pkt_rp *)buf;
/* Since this is an in_addr, assume it's already the right byte order */
brp->addr = rp->addr.s_addr;
- brp->pimver = PIM_V2;
+ brp->pimver = AUTORP_PIM_V2;
brp->reserved = 0;
- brp->grpcnt =
- pim_autorp_new_announcement_rp_grps(rp,
- buf + sizeof(struct autorp_pkt_rp));
- return buf + sizeof(struct autorp_pkt_rp) +
- (brp->grpcnt * sizeof(struct autorp_pkt_grp));
+ brp->grpcnt = pim_autorp_new_announcement_rp_grps(rp, buf + sizeof(struct autorp_pkt_rp));
+ return buf + sizeof(struct autorp_pkt_rp) + (brp->grpcnt * sizeof(struct autorp_pkt_grp));
}
/* Pack the candidate RP's on the announcement packet
@@ -683,36 +1136,45 @@ static uint8_t *pim_autorp_new_announcement_rp(struct pim_autorp_rp *rp,
* bufsz - Output parameter to track size of packed bytes
* returns - Total count of RP's packed
*/
-static int pim_autorp_new_announcement_rps(struct pim_autorp *autorp,
- uint8_t *buf, uint16_t *bufsz)
+static int pim_autorp_new_announcement_rps(struct pim_autorp *autorp, uint8_t *buf, uint16_t *bufsz)
{
int cnt = 0;
struct pim_autorp_rp *rp;
/* Keep the original buffer pointer to calculate final size after packing */
uint8_t *obuf = buf;
- struct prefix_list *plist;
- struct prefix_list_entry *ple;
- in_addr_t taddr;
frr_each_safe (pim_autorp_rp, &(autorp->candidate_rp_list), rp) {
- /* We must have an rp address and either group or list in order to pack this RP, so skip this one */
+ /* We must have an rp address and either group or list in order to pack this RP,
+ * so skip this one
+ */
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: Evaluating AutoRP candidate %pI4, group range %pFX, group list %s",
+ __func__, &rp->addr, &rp->grp, rp->grplist);
+
if (pim_addr_is_any(rp->addr) ||
- (is_default_prefix(&(rp->grp)) && strlen(rp->grplist) == 0))
+ (is_default_prefix(&rp->grp) && strlen(rp->grplist) == 0))
continue;
- /* Group is net set, so list must be set, make sure the prefix list exists and has valid multicast groups */
- if (is_default_prefix(&(rp->grp))) {
+ /* Make sure that either group prefix is set, or that the prefix list exists and has at
+ * least one valid multicast prefix in it. Only multicast prefixes will be used.
+ */
+ if (is_default_prefix(&rp->grp)) {
+ struct prefix_list *plist;
+ struct prefix_list_entry *ple;
+
plist = prefix_list_lookup(AFI_IP, rp->grplist);
if (plist == NULL)
continue;
plist = prefix_list_lookup(AFI_IP, rp->grplist);
for (ple = plist->head; ple; ple = ple->next) {
- taddr = ntohl(ple->prefix.u.prefix4.s_addr);
- if ((taddr & 0xF0000000) == 0xE0000000)
+ if (pim_addr_is_multicast(ple->prefix.u.prefix4) &&
+ ple->prefix.prefixlen >= 4)
break;
}
- /* If we went through the entire list without finding a multicast prefix, then skip this RP */
+ /* If we went through the entire list without finding a multicast prefix,
+ * then skip this RP
+ */
if (ple == NULL)
continue;
}
@@ -721,6 +1183,10 @@ static int pim_autorp_new_announcement_rps(struct pim_autorp *autorp,
++cnt;
/* This will return the buffer pointer at the location to start packing the next RP */
buf = pim_autorp_new_announcement_rp(rp, buf);
+
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: AutoRP candidate %pI4 added to announcement", __func__,
+ &rp->addr);
}
if (cnt > 0)
@@ -729,7 +1195,9 @@ static int pim_autorp_new_announcement_rps(struct pim_autorp *autorp,
return cnt;
}
-/* Build the new announcement packet. If there is a packet to send, restart the send timer with a short wait */
+/* Build the new announcement packet. If there is a packet to send, restart the send timer
+ * with a short wait
+ */
static void pim_autorp_new_announcement(struct pim_instance *pim)
{
struct pim_autorp *autorp = pim->autorp;
@@ -739,70 +1207,87 @@ static void pim_autorp_new_announcement(struct pim_instance *pim)
/* First disable any existing send timer */
autorp_announcement_off(autorp);
- if (!autorp->annouce_pkt) {
- /*
- * First time building, allocate the space
- * Allocate the max packet size of 65536 so we don't need to resize later.
- * This should be ok since we are only allocating the memory once for a single packet (potentially per vrf)
- */
- autorp->annouce_pkt = XCALLOC(MTYPE_PIM_AUTORP_ANNOUNCE, 65536);
- }
+ /*
+ * First time building, allocate the space
+ * Allocate the max packet size of 65536 so we don't need to resize later.
+ * This should be ok since we are only allocating the memory once for a single packet
+ * (potentially per vrf)
+ */
+ if (!autorp->announce_pkt)
+ autorp->announce_pkt = XCALLOC(MTYPE_PIM_AUTORP_ANNOUNCE, 65536);
- autorp->annouce_pkt_sz = 0;
+ autorp->announce_pkt_sz = 0;
holdtime = autorp->announce_holdtime;
- if (holdtime == DEFAULT_ANNOUNCE_HOLDTIME)
+ if (holdtime == DEFAULT_AUTORP_ANNOUNCE_HOLDTIME)
holdtime = autorp->announce_interval * 3;
if (holdtime > UINT16_MAX)
holdtime = UINT16_MAX;
- hdr = (struct autorp_pkt_hdr *)autorp->annouce_pkt;
+ hdr = (struct autorp_pkt_hdr *)autorp->announce_pkt;
hdr->version = AUTORP_VERSION;
hdr->type = AUTORP_ANNOUNCEMENT_TYPE;
hdr->holdtime = htons((uint16_t)holdtime);
hdr->reserved = 0;
- hdr->rpcnt =
- pim_autorp_new_announcement_rps(autorp,
- autorp->annouce_pkt +
- sizeof(struct autorp_pkt_hdr),
- &(autorp->annouce_pkt_sz));
+ hdr->rpcnt = pim_autorp_new_announcement_rps(autorp,
+ autorp->announce_pkt +
+ sizeof(struct autorp_pkt_hdr),
+ &(autorp->announce_pkt_sz));
/* Still need to add on the size of the header */
- autorp->annouce_pkt_sz += sizeof(struct autorp_pkt_hdr);
+ autorp->announce_pkt_sz += sizeof(struct autorp_pkt_hdr);
/* Only turn on the announcement timer if we have a packet to send */
- if (autorp->annouce_pkt_sz >= MIN_AUTORP_PKT_SZ)
+ if (autorp->announce_pkt_sz >= MIN_AUTORP_PKT_SZ)
autorp_announcement_on(autorp);
}
+void pim_autorp_prefix_list_update(struct pim_instance *pim, struct prefix_list *plist)
+{
+ struct pim_autorp_rp *rp = NULL;
+ struct pim_autorp *autorp = NULL;
+
+ autorp = pim->autorp;
+ if (autorp == NULL)
+ return;
+
+ /* Search for a candidate RP using this prefix list */
+ frr_each_safe (pim_autorp_rp, &(autorp->candidate_rp_list), rp) {
+ if (strmatch(rp->grplist, plist->name))
+ break;
+ }
+
+ /* If we broke out of the loop early because we found a match, then rebuild the announcement */
+ if (rp != NULL)
+ pim_autorp_new_announcement(pim);
+}
+
bool pim_autorp_rm_candidate_rp(struct pim_instance *pim, pim_addr rpaddr)
{
struct pim_autorp *autorp = pim->autorp;
struct pim_autorp_rp *rp;
struct pim_autorp_rp find = { .addr = rpaddr };
- rp = pim_autorp_rp_find(&(autorp->candidate_rp_list),
- (const struct pim_autorp_rp *)&find);
+ rp = pim_autorp_rp_find(&(autorp->candidate_rp_list), (const struct pim_autorp_rp *)&find);
if (!rp)
return false;
pim_autorp_rp_del(&(autorp->candidate_rp_list), rp);
- pim_autorp_rp_free(rp);
+ pim_autorp_rp_free(rp, false);
pim_autorp_new_announcement(pim);
return true;
}
-void pim_autorp_add_candidate_rp_group(struct pim_instance *pim,
- pim_addr rpaddr, struct prefix group)
+void pim_autorp_add_candidate_rp_group(struct pim_instance *pim, pim_addr rpaddr,
+ struct prefix group)
{
struct pim_autorp *autorp = pim->autorp;
struct pim_autorp_rp *rp;
struct pim_autorp_rp find = { .addr = rpaddr };
- rp = pim_autorp_rp_find(&(autorp->candidate_rp_list),
- (const struct pim_autorp_rp *)&find);
+ rp = pim_autorp_rp_find(&(autorp->candidate_rp_list), (const struct pim_autorp_rp *)&find);
if (!rp) {
- rp = XCALLOC(MTYPE_PIM_AUTORP_CRP, sizeof(*rp));
+ rp = XCALLOC(MTYPE_PIM_AUTORP_RP, sizeof(*rp));
memset(rp, 0, sizeof(struct pim_autorp_rp));
rp->autorp = autorp;
memcpy(&(rp->addr), &rpaddr, sizeof(pim_addr));
@@ -817,15 +1302,13 @@ void pim_autorp_add_candidate_rp_group(struct pim_instance *pim,
pim_autorp_new_announcement(pim);
}
-bool pim_autorp_rm_candidate_rp_group(struct pim_instance *pim, pim_addr rpaddr,
- struct prefix group)
+bool pim_autorp_rm_candidate_rp_group(struct pim_instance *pim, pim_addr rpaddr, struct prefix group)
{
struct pim_autorp *autorp = pim->autorp;
struct pim_autorp_rp *rp;
struct pim_autorp_rp find = { .addr = rpaddr };
- rp = pim_autorp_rp_find(&(autorp->candidate_rp_list),
- (const struct pim_autorp_rp *)&find);
+ rp = pim_autorp_rp_find(&(autorp->candidate_rp_list), (const struct pim_autorp_rp *)&find);
if (!rp)
return false;
@@ -834,17 +1317,15 @@ bool pim_autorp_rm_candidate_rp_group(struct pim_instance *pim, pim_addr rpaddr,
return true;
}
-void pim_autorp_add_candidate_rp_plist(struct pim_instance *pim,
- pim_addr rpaddr, const char *plist)
+void pim_autorp_add_candidate_rp_plist(struct pim_instance *pim, pim_addr rpaddr, const char *plist)
{
struct pim_autorp *autorp = pim->autorp;
struct pim_autorp_rp *rp;
struct pim_autorp_rp find = { .addr = rpaddr };
- rp = pim_autorp_rp_find(&(autorp->candidate_rp_list),
- (const struct pim_autorp_rp *)&find);
+ rp = pim_autorp_rp_find(&(autorp->candidate_rp_list), (const struct pim_autorp_rp *)&find);
if (!rp) {
- rp = XCALLOC(MTYPE_PIM_AUTORP_CRP, sizeof(*rp));
+ rp = XCALLOC(MTYPE_PIM_AUTORP_RP, sizeof(*rp));
memset(rp, 0, sizeof(struct pim_autorp_rp));
rp->autorp = autorp;
memcpy(&(rp->addr), &rpaddr, sizeof(pim_addr));
@@ -859,15 +1340,13 @@ void pim_autorp_add_candidate_rp_plist(struct pim_instance *pim,
pim_autorp_new_announcement(pim);
}
-bool pim_autorp_rm_candidate_rp_plist(struct pim_instance *pim, pim_addr rpaddr,
- const char *plist)
+bool pim_autorp_rm_candidate_rp_plist(struct pim_instance *pim, pim_addr rpaddr, const char *plist)
{
struct pim_autorp *autorp = pim->autorp;
struct pim_autorp_rp *rp;
struct pim_autorp_rp find = { .addr = rpaddr };
- rp = pim_autorp_rp_find(&(autorp->candidate_rp_list),
- (const struct pim_autorp_rp *)&find);
+ rp = pim_autorp_rp_find(&(autorp->candidate_rp_list), (const struct pim_autorp_rp *)&find);
if (!rp)
return false;
@@ -880,7 +1359,7 @@ void pim_autorp_announce_scope(struct pim_instance *pim, uint8_t scope)
{
struct pim_autorp *autorp = pim->autorp;
- scope = (scope == 0 ? DEFAULT_ANNOUNCE_SCOPE : scope);
+ scope = (scope == 0 ? DEFAULT_AUTORP_ANNOUNCE_SCOPE : scope);
if (autorp->announce_scope != scope) {
autorp->announce_scope = scope;
pim_autorp_new_announcement(pim);
@@ -891,7 +1370,7 @@ void pim_autorp_announce_interval(struct pim_instance *pim, uint16_t interval)
{
struct pim_autorp *autorp = pim->autorp;
- interval = (interval == 0 ? DEFAULT_ANNOUNCE_INTERVAL : interval);
+ interval = (interval == 0 ? DEFAULT_AUTORP_ANNOUNCE_INTERVAL : interval);
if (autorp->announce_interval != interval) {
autorp->announce_interval = interval;
pim_autorp_new_announcement(pim);
@@ -908,6 +1387,16 @@ void pim_autorp_announce_holdtime(struct pim_instance *pim, int32_t holdtime)
}
}
+void pim_autorp_send_discovery_apply(struct pim_autorp *autorp)
+{
+ if (!autorp->mapping_agent_addrsel.run || !autorp->send_rp_discovery) {
+ autorp_send_discovery_off(autorp);
+ return;
+ }
+
+ autorp_send_discovery_on(autorp);
+}
+
void pim_autorp_add_ifp(struct interface *ifp)
{
/* Add a new interface for autorp
@@ -923,17 +1412,15 @@ void pim_autorp_add_ifp(struct interface *ifp)
struct pim_interface *pim_ifp;
pim_ifp = ifp->info;
- if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) && pim_ifp &&
- pim_ifp->pim_enable) {
+ if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) && pim_ifp && pim_ifp->pim_enable) {
pim = pim_ifp->pim;
if (pim && pim->autorp && pim->autorp->do_discovery) {
if (PIM_DEBUG_AUTORP)
zlog_debug("%s: Adding interface %s to AutoRP, joining AutoRP groups",
__func__, ifp->name);
- if (!pim_autorp_join_groups(ifp)) {
- zlog_err("Could not join AutoRP groups, errno=%d, %s",
- errno, safe_strerror(errno));
- }
+ if (!pim_autorp_join_groups(ifp))
+ zlog_warn("Could not join AutoRP groups, errno=%d, %s", errno,
+ safe_strerror(errno));
}
}
}
@@ -954,10 +1441,9 @@ void pim_autorp_rm_ifp(struct interface *ifp)
if (PIM_DEBUG_AUTORP)
zlog_debug("%s: Removing interface %s from AutoRP, leaving AutoRP groups",
__func__, ifp->name);
- if (!pim_autorp_leave_groups(ifp)) {
- zlog_err("Could not leave AutoRP groups, errno=%d, %s",
- errno, safe_strerror(errno));
- }
+ if (!pim_autorp_leave_groups(ifp))
+ zlog_warn("Could not leave AutoRP groups, errno=%d, %s", errno,
+ safe_strerror(errno));
}
}
}
@@ -1008,14 +1494,22 @@ void pim_autorp_init(struct pim_instance *pim)
autorp->read_event = NULL;
autorp->announce_timer = NULL;
autorp->do_discovery = false;
+ autorp->send_discovery_timer = NULL;
+ autorp->send_rp_discovery = false;
pim_autorp_rp_init(&(autorp->discovery_rp_list));
pim_autorp_rp_init(&(autorp->candidate_rp_list));
- autorp->announce_scope = DEFAULT_ANNOUNCE_SCOPE;
- autorp->announce_interval = DEFAULT_ANNOUNCE_INTERVAL;
- autorp->announce_holdtime = DEFAULT_ANNOUNCE_HOLDTIME;
+ pim_autorp_rp_init(&(autorp->mapping_rp_list));
+ pim_autorp_rp_init(&autorp->advertised_rp_list);
+ autorp->announce_scope = DEFAULT_AUTORP_ANNOUNCE_SCOPE;
+ autorp->announce_interval = DEFAULT_AUTORP_ANNOUNCE_INTERVAL;
+ autorp->announce_holdtime = DEFAULT_AUTORP_ANNOUNCE_HOLDTIME;
+ autorp->discovery_scope = DEFAULT_AUTORP_DISCOVERY_SCOPE;
+ autorp->discovery_interval = DEFAULT_AUTORP_DISCOVERY_INTERVAL;
+ autorp->discovery_holdtime = DEFAULT_AUTORP_DISCOVERY_HOLDTIME;
+ cand_addrsel_clear(&(autorp->mapping_agent_addrsel));
if (!pim_autorp_socket_enable(autorp)) {
- zlog_err("%s: AutoRP failed to initialize", __func__);
+ zlog_warn("%s: AutoRP failed to initialize", __func__);
return;
}
@@ -1032,24 +1526,20 @@ void pim_autorp_finish(struct pim_instance *pim)
struct pim_autorp *autorp = pim->autorp;
autorp_read_off(autorp);
+ autorp_announcement_off(autorp);
+ autorp_send_discovery_off(autorp);
pim_autorp_free(autorp);
- if (pim_autorp_socket_disable(autorp)) {
- if (PIM_DEBUG_AUTORP)
- zlog_debug("%s: AutoRP Finished", __func__);
- } else
- zlog_err("%s: AutoRP failed to finish", __func__);
-
+ pim_autorp_socket_disable(autorp);
XFREE(MTYPE_PIM_AUTORP, pim->autorp);
+
+ if (PIM_DEBUG_AUTORP)
+ zlog_debug("%s: AutoRP Finished", __func__);
}
int pim_autorp_config_write(struct pim_instance *pim, struct vty *vty)
{
struct pim_autorp_rp *rp;
struct pim_autorp *autorp = pim->autorp;
- char interval_str[16] = { 0 };
- char scope_str[16] = { 0 };
- char holdtime_str[32] = { 0 };
- char grp_str[64] = { 0 };
int writes = 0;
if (!autorp->do_discovery) {
@@ -1057,24 +1547,17 @@ int pim_autorp_config_write(struct pim_instance *pim, struct vty *vty)
++writes;
}
- if (autorp->announce_interval != DEFAULT_ANNOUNCE_INTERVAL) {
- snprintf(interval_str, sizeof(interval_str), " interval %u",
- autorp->announce_interval);
- }
-
- if (autorp->announce_scope != DEFAULT_ANNOUNCE_SCOPE) {
- snprintf(scope_str, sizeof(scope_str), " scope %u",
- autorp->announce_scope);
- }
-
- if (autorp->announce_holdtime != DEFAULT_ANNOUNCE_HOLDTIME) {
- snprintf(holdtime_str, sizeof(holdtime_str), " holdtime %u",
- autorp->announce_holdtime);
- }
-
- if (strlen(interval_str) || strlen(scope_str) || strlen(holdtime_str)) {
- vty_out(vty, " autorp announce%s%s%s\n", interval_str,
- scope_str, holdtime_str);
+ if (autorp->announce_interval != DEFAULT_AUTORP_ANNOUNCE_INTERVAL ||
+ autorp->announce_scope != DEFAULT_AUTORP_ANNOUNCE_SCOPE ||
+ autorp->announce_holdtime != DEFAULT_AUTORP_ANNOUNCE_HOLDTIME) {
+ vty_out(vty, " autorp announce");
+ if (autorp->announce_interval != DEFAULT_AUTORP_ANNOUNCE_INTERVAL)
+ vty_out(vty, " interval %u", autorp->announce_interval);
+ if (autorp->announce_scope != DEFAULT_AUTORP_ANNOUNCE_SCOPE)
+ vty_out(vty, " scope %u", autorp->announce_scope);
+ if (autorp->announce_holdtime != DEFAULT_AUTORP_ANNOUNCE_HOLDTIME)
+ vty_out(vty, " holdtime %u", autorp->announce_holdtime);
+ vty_out(vty, "\n");
++writes;
}
@@ -1084,83 +1567,371 @@ int pim_autorp_config_write(struct pim_instance *pim, struct vty *vty)
(is_default_prefix(&(rp->grp)) && strlen(rp->grplist) == 0))
continue;
- /* Don't make sure the prefix list has multicast groups, user may not have created it yet */
-
+ vty_out(vty, " autorp announce %pI4", &(rp->addr));
if (!is_default_prefix(&(rp->grp)))
- snprintfrr(grp_str, sizeof(grp_str), "%pFX", &(rp->grp));
+ vty_out(vty, " %pFX", &(rp->grp));
else
- snprintfrr(grp_str, sizeof(grp_str), "group-list %s",
- rp->grplist);
-
- vty_out(vty, " autorp announce %pI4 %s\n", &(rp->addr), grp_str);
+ vty_out(vty, " group-list %s", rp->grplist);
+ vty_out(vty, "\n");
++writes;
}
+ if (autorp->send_rp_discovery) {
+ if (autorp->mapping_agent_addrsel.cfg_enable) {
+ vty_out(vty, " autorp send-rp-discovery");
+ switch (autorp->mapping_agent_addrsel.cfg_mode) {
+ case CAND_ADDR_LO:
+ break;
+ case CAND_ADDR_ANY:
+ vty_out(vty, " source any");
+ break;
+ case CAND_ADDR_IFACE:
+ vty_out(vty, " source interface %s",
+ autorp->mapping_agent_addrsel.cfg_ifname);
+ break;
+ case CAND_ADDR_EXPLICIT:
+ vty_out(vty, " source address %pPA",
+ &autorp->mapping_agent_addrsel.cfg_addr);
+ break;
+ }
+ vty_out(vty, "\n");
+ ++writes;
+ }
+
+ if (autorp->discovery_interval != DEFAULT_AUTORP_DISCOVERY_INTERVAL ||
+ autorp->discovery_scope != DEFAULT_AUTORP_DISCOVERY_SCOPE ||
+ autorp->discovery_holdtime != DEFAULT_AUTORP_DISCOVERY_HOLDTIME) {
+ vty_out(vty, " autorp send-rp-discovery");
+ if (autorp->discovery_interval != DEFAULT_AUTORP_DISCOVERY_INTERVAL)
+ vty_out(vty, " interval %u", autorp->discovery_interval);
+ if (autorp->discovery_scope != DEFAULT_AUTORP_DISCOVERY_SCOPE)
+ vty_out(vty, " scope %u", autorp->discovery_scope);
+ if (autorp->discovery_holdtime != DEFAULT_AUTORP_DISCOVERY_HOLDTIME)
+ vty_out(vty, " holdtime %u", autorp->discovery_holdtime);
+ vty_out(vty, "\n");
+ ++writes;
+ }
+ }
+
return writes;
}
-void pim_autorp_show_autorp(struct vty *vty, struct pim_instance *pim,
- json_object *json)
+static void pim_autorp_show_autorp_json(struct pim_autorp *autorp, const char *component,
+ json_object *json, struct ttable *cand_table)
{
struct pim_autorp_rp *rp;
+
+ if (!component || strmatch(component, "discovery")) {
+ json_object *disc_obj;
+
+ disc_obj = json_object_new_object();
+ json_object_boolean_add(disc_obj, "enabled", autorp->do_discovery);
+ if (autorp->do_discovery) {
+ json_object *rplist_obj;
+
+ rplist_obj = json_object_new_object();
+ frr_each (pim_autorp_rp, &(autorp->discovery_rp_list), rp) {
+ json_object *rp_obj;
+ json_object *grp_arr;
+
+ rp_obj = json_object_new_object();
+ json_object_string_addf(rp_obj, "rpAddress", "%pI4", &rp->addr);
+ json_object_int_add(rp_obj, "holdtime", rp->holdtime);
+ grp_arr = json_object_new_array();
+
+ if (strlen(rp->grplist)) {
+ struct prefix_list *pl;
+ struct prefix_list_entry *ple;
+
+ pl = prefix_list_lookup(AFI_IP, rp->grplist);
+ if (pl == NULL)
+ continue;
+
+ for (ple = pl->head; ple != NULL; ple = ple->next) {
+ json_object *grp_obj;
+
+ grp_obj = json_object_new_object();
+ json_object_boolean_add(grp_obj, "negative",
+ ple->type == PREFIX_DENY);
+ json_object_string_addf(grp_obj, "prefix", "%pFX",
+ &ple->prefix);
+ json_object_array_add(grp_arr, grp_obj);
+ }
+ } else {
+ json_object *grp_obj;
+
+ grp_obj = json_object_new_object();
+ json_object_boolean_add(grp_obj, "negative", false);
+ json_object_string_addf(grp_obj, "prefix", "%pFX", &rp->grp);
+ json_object_array_add(grp_arr, grp_obj);
+ }
+
+ json_object_object_add(rp_obj, "groupRanges", grp_arr);
+ json_object_object_addf(rplist_obj, rp_obj, "%pI4", &rp->addr);
+ }
+ json_object_object_add(disc_obj, "rpList", rplist_obj);
+ }
+ json_object_object_add(json, "discovery", disc_obj);
+ }
+
+ if (!component || strmatch(component, "candidate")) {
+ json_object *announce_obj;
+
+ announce_obj = json_object_new_object();
+ json_object_boolean_add(announce_obj, "enabled",
+ pim_autorp_rp_count(&autorp->candidate_rp_list) > 0);
+ if (pim_autorp_rp_count(&autorp->candidate_rp_list) > 0) {
+ json_object_int_add(announce_obj, "scope", autorp->announce_scope);
+ json_object_int_add(announce_obj, "interval", autorp->announce_interval);
+ json_object_int_add(announce_obj, "holdtime",
+ (autorp->announce_holdtime ==
+ DEFAULT_AUTORP_ANNOUNCE_HOLDTIME
+ ? (autorp->announce_interval * 3)
+ : autorp->announce_holdtime));
+ json_object_object_add(announce_obj, "rpList",
+ ttable_json_with_json_text(cand_table, "sss",
+ "rpAddress|groupRange|prefixList"));
+ }
+ json_object_object_add(json, "announce", announce_obj);
+ }
+
+ if (!component || strmatch(component, "mapping-agent")) {
+ json_object *adv_obj;
+
+ adv_obj = json_object_new_object();
+ json_object_boolean_add(adv_obj, "enabled", autorp->send_rp_discovery);
+ if (autorp->send_rp_discovery) {
+ json_object *rplist_obj;
+
+ json_object_boolean_add(adv_obj, "active", autorp->mapping_agent_active);
+ json_object_int_add(adv_obj, "scope", autorp->discovery_scope);
+ json_object_int_add(adv_obj, "interval", autorp->discovery_interval);
+ json_object_int_add(adv_obj, "holdtime", autorp->discovery_holdtime);
+ switch (autorp->mapping_agent_addrsel.cfg_mode) {
+ case CAND_ADDR_LO:
+ json_object_string_add(adv_obj, "source", "loopback");
+ break;
+ case CAND_ADDR_ANY:
+ json_object_string_add(adv_obj, "source", "any");
+ break;
+ case CAND_ADDR_IFACE:
+ json_object_string_add(adv_obj, "source", "interface");
+ json_object_string_add(adv_obj, "interface",
+ autorp->mapping_agent_addrsel.cfg_ifname);
+ break;
+ case CAND_ADDR_EXPLICIT:
+ json_object_string_add(adv_obj, "source", "address");
+ break;
+ }
+ json_object_string_addf(adv_obj, "address", "%pPA",
+ &autorp->mapping_agent_addrsel.run_addr);
+
+ rplist_obj = json_object_new_object();
+ frr_each (pim_autorp_rp, &(autorp->advertised_rp_list), rp) {
+ json_object *rp_obj;
+ json_object *grp_arr;
+ struct pim_autorp_grppfix *grppfix;
+
+ rp_obj = json_object_new_object();
+ json_object_string_addf(rp_obj, "rpAddress", "%pI4", &rp->addr);
+ grp_arr = json_object_new_array();
+ frr_each (pim_autorp_grppfix, &rp->grp_pfix_list, grppfix) {
+ json_object *grp_obj;
+
+ grp_obj = json_object_new_object();
+ json_object_boolean_add(grp_obj, "negative",
+ grppfix->negative);
+ json_object_string_addf(grp_obj, "prefix", "%pFX",
+ &grppfix->grp);
+ json_object_array_add(grp_arr, grp_obj);
+ }
+ json_object_object_add(rp_obj, "groupRanges", grp_arr);
+ json_object_object_addf(rplist_obj, rp_obj, "%pI4", &rp->addr);
+ }
+ json_object_object_add(adv_obj, "rpList", rplist_obj);
+ }
+ json_object_object_add(json, "mapping-agent", adv_obj);
+ }
+}
+
+void pim_autorp_show_autorp(struct vty *vty, struct pim_instance *pim, const char *component,
+ json_object *json)
+{
struct pim_autorp *autorp = pim->autorp;
- struct ttable *tt = NULL;
- char *table = NULL;
- char grp_str[64] = { 0 };
- char plist_str[64] = { 0 };
- json_object *annouce_jobj;
-
- /* Prepare table. */
- tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
- ttable_add_row(tt, "RP address|group|prefix-list");
- tt->style.cell.rpad = 2;
- tt->style.corner = '+';
- ttable_restyle(tt);
+ struct pim_autorp_rp *rp;
+ struct ttable *cand_table = NULL;
+ struct ttable *adv_table = NULL;
+ struct ttable *disc_table = NULL;
+ char *tmp;
- frr_each_safe (pim_autorp_rp, &(autorp->candidate_rp_list), rp) {
- if (!is_default_prefix(&(rp->grp)))
- snprintfrr(grp_str, sizeof(grp_str), "%pFX", &(rp->grp));
- else
- snprintfrr(plist_str, sizeof(plist_str), "%s",
- rp->grplist);
+ if (autorp == NULL)
+ return;
- ttable_add_row(tt, "%pI4|%s|%s", &(rp->addr), grp_str,
- plist_str);
+ /* We may use the candidate table in the json output, so prepare it first. */
+ if (!component || strmatch(component, "candidate")) {
+ cand_table = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(cand_table, "RP address|Group Range|Prefix-List");
+ cand_table->style.cell.rpad = 2;
+ cand_table->style.corner = '+';
+ ttable_restyle(cand_table);
+
+ frr_each (pim_autorp_rp, &(autorp->candidate_rp_list), rp) {
+ if (strlen(rp->grplist))
+ ttable_add_row(cand_table, "%pI4|%s|%s", &(rp->addr), "-",
+ rp->grplist);
+ else
+ ttable_add_row(cand_table, "%pI4|%pFX|%s", &(rp->addr), &(rp->grp),
+ "-");
+ }
}
if (json) {
- json_object_boolean_add(json, "discoveryEnabled",
- autorp->do_discovery);
-
- annouce_jobj = json_object_new_object();
- json_object_int_add(annouce_jobj, "scope",
- autorp->announce_scope);
- json_object_int_add(annouce_jobj, "interval",
- autorp->announce_interval);
- json_object_int_add(annouce_jobj, "holdtime",
- autorp->announce_holdtime);
- json_object_object_add(annouce_jobj, "rpList",
- ttable_json_with_json_text(
- tt, "sss",
- "rpAddress|group|prefixList"));
-
- json_object_object_add(json, "announce", annouce_jobj);
- } else {
- vty_out(vty, "AutoRP Discovery is %sabled\n",
- (autorp->do_discovery ? "en" : "dis"));
- vty_out(vty, "AutoRP Candidate RPs\n");
- vty_out(vty, " interval %us, scope %u, holdtime %us\n",
- autorp->announce_interval, autorp->announce_scope,
- (autorp->announce_holdtime == DEFAULT_ANNOUNCE_HOLDTIME
- ? (autorp->announce_interval * 3)
- : autorp->announce_holdtime));
+ pim_autorp_show_autorp_json(autorp, component, json, cand_table);
+ if (cand_table)
+ ttable_del(cand_table);
+ return;
+ }
- vty_out(vty, "\n");
+ /* Prepare discovered RP's table. */
+ if (!component || strmatch(component, "discovery")) {
+ disc_table = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(disc_table, "RP address|Group Range");
+ disc_table->style.cell.rpad = 2;
+ disc_table->style.corner = '+';
+ ttable_restyle(disc_table);
+
+ frr_each (pim_autorp_rp, &(autorp->discovery_rp_list), rp) {
+ if (strlen(rp->grplist)) {
+ struct prefix_list *pl;
+ struct prefix_list_entry *ple;
+ bool first = true;
+
+ pl = prefix_list_lookup(AFI_IP, rp->grplist);
+
+ if (pl == NULL) {
+ ttable_add_row(disc_table,
+ "%pI4|failed to find prefix list %s",
+ &(rp->addr), rp->grplist);
+ continue;
+ }
- table = ttable_dump(tt, "\n");
- vty_out(vty, "%s\n", table);
- XFREE(MTYPE_TMP_TTABLE, table);
+ for (ple = pl->head; ple != NULL; ple = ple->next) {
+ if (first)
+ ttable_add_row(disc_table, "%pI4|%s%pFX",
+ &(rp->addr),
+ (ple->type == PREFIX_DENY ? "!"
+ : " "),
+ &ple->prefix);
+ else
+ ttable_add_row(disc_table, "%s|%s%pFX", " ",
+ (ple->type == PREFIX_DENY ? "!"
+ : " "),
+ &ple->prefix);
+ first = false;
+ }
+ } else
+ ttable_add_row(disc_table, "%pI4| %pFX", &(rp->addr), &(rp->grp));
+ }
+ }
+
+ /* Prepare discovery RP's table (mapping-agent). */
+ if (!component || strmatch(component, "mapping-agent")) {
+ adv_table = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(adv_table, "RP address|Group Range");
+ adv_table->style.cell.rpad = 2;
+ adv_table->style.corner = '+';
+ ttable_restyle(adv_table);
+
+ frr_each (pim_autorp_rp, &(autorp->advertised_rp_list), rp) {
+ struct pim_autorp_grppfix *grppfix;
+ bool first = true;
+
+ frr_each (pim_autorp_grppfix, &rp->grp_pfix_list, grppfix) {
+ if (first)
+ ttable_add_row(adv_table, "%pI4|%s%pFX", &rp->addr,
+ grppfix->negative ? "!" : " ", &grppfix->grp);
+ else
+ ttable_add_row(adv_table, "%s|%s%pFX", " ",
+ grppfix->negative ? "!" : " ", &grppfix->grp);
+ first = false;
+ }
+ }
+ }
+
+ if (!component || strmatch(component, "discovery")) {
+ vty_out(vty, "AutoRP Discovery is %sabled\n", (autorp->do_discovery ? "en" : "dis"));
+ if (autorp->do_discovery) {
+ tmp = ttable_dump(disc_table, "\n");
+ vty_out(vty, "\n");
+ vty_out(vty, "Discovered RP's (count=%u)\n",
+ (uint32_t)pim_autorp_rp_count(&autorp->discovery_rp_list));
+ vty_out(vty, "%s\n", tmp);
+ XFREE(MTYPE_TMP_TTABLE, tmp);
+ } else
+ vty_out(vty, "\n");
+ }
+
+ if (!component || strmatch(component, "candidate")) {
+ vty_out(vty, "AutoRP Announcement is %sabled\n",
+ (pim_autorp_rp_count(&autorp->candidate_rp_list) > 0 ? "en" : "dis"));
+ if (pim_autorp_rp_count(&autorp->candidate_rp_list) > 0) {
+ tmp = ttable_dump(cand_table, "\n");
+ vty_out(vty, " interval %us scope %u holdtime %us\n",
+ autorp->announce_interval, autorp->announce_scope,
+ (autorp->announce_holdtime == DEFAULT_AUTORP_ANNOUNCE_HOLDTIME
+ ? (autorp->announce_interval * 3)
+ : autorp->announce_holdtime));
+ vty_out(vty, "\n");
+ vty_out(vty, "Candidate RP's (count=%u)\n",
+ (uint32_t)pim_autorp_rp_count(&autorp->candidate_rp_list));
+ vty_out(vty, "%s\n", tmp);
+ XFREE(MTYPE_TMP_TTABLE, tmp);
+ } else
+ vty_out(vty, "\n");
+ }
+
+ if (!component || strmatch(component, "mapping-agent")) {
+ vty_out(vty, "AutoRP Mapping-Agent is %sabled\n",
+ (autorp->send_rp_discovery ? "en" : "dis"));
+ if (autorp->send_rp_discovery) {
+ vty_out(vty, " interval %us scope %u holdtime %us\n",
+ autorp->discovery_interval, autorp->discovery_scope,
+ autorp->discovery_holdtime);
+ vty_out(vty, " source %pPA", &autorp->mapping_agent_addrsel.run_addr);
+ switch (autorp->mapping_agent_addrsel.cfg_mode) {
+ case CAND_ADDR_LO:
+ vty_out(vty, " (loopback)");
+ break;
+ case CAND_ADDR_ANY:
+ vty_out(vty, " (any)");
+ break;
+ case CAND_ADDR_IFACE:
+ vty_out(vty, " (interface %s)",
+ autorp->mapping_agent_addrsel.cfg_ifname);
+ break;
+ case CAND_ADDR_EXPLICIT:
+ vty_out(vty, " (explicit address)");
+ break;
+ }
+ vty_out(vty, "\n");
+
+ if (autorp->mapping_agent_active) {
+ tmp = ttable_dump(adv_table, "\n");
+ vty_out(vty, "\n");
+ vty_out(vty, "Advertised RP's (count=%u)\n",
+ (uint32_t)pim_autorp_rp_count(&autorp->advertised_rp_list));
+ vty_out(vty, "%s\n", tmp);
+ XFREE(MTYPE_TMP_TTABLE, tmp);
+ } else
+ vty_out(vty, " Mapping agent is inactive\n");
+ } else
+ vty_out(vty, "\n");
}
- ttable_del(tt);
+ if (cand_table)
+ ttable_del(cand_table);
+ if (adv_table)
+ ttable_del(adv_table);
+ if (disc_table)
+ ttable_del(disc_table);
}
diff --git a/pimd/pim_autorp.h b/pimd/pim_autorp.h
index a0b029d00a..e4c6530109 100644
--- a/pimd/pim_autorp.h
+++ b/pimd/pim_autorp.h
@@ -14,16 +14,21 @@
#define AUTORP_VERSION 1
#define AUTORP_ANNOUNCEMENT_TYPE 1
#define AUTORP_DISCOVERY_TYPE 2
-#define PIM_VUNKNOWN 0
-#define PIM_V1 1
-#define PIM_V2 2
-#define PIM_V1_2 3
+#define AUTORP_PIM_VUNKNOWN 0
+#define AUTORP_PIM_V1 1
+#define AUTORP_PIM_V2 2
+#define AUTORP_PIM_V1_2 3
-#define DEFAULT_ANNOUNCE_INTERVAL 60
-#define DEFAULT_ANNOUNCE_SCOPE 31
-#define DEFAULT_ANNOUNCE_HOLDTIME -1
+#define DEFAULT_AUTORP_ANNOUNCE_INTERVAL 60
+#define DEFAULT_AUTORP_ANNOUNCE_SCOPE 31
+#define DEFAULT_AUTORP_ANNOUNCE_HOLDTIME -1
+
+#define DEFAULT_AUTORP_DISCOVERY_INTERVAL 60
+#define DEFAULT_AUTORP_DISCOVERY_SCOPE 31
+#define DEFAULT_AUTORP_DISCOVERY_HOLDTIME 180
PREDECL_SORTLIST_UNIQ(pim_autorp_rp);
+PREDECL_SORTLIST_UNIQ(pim_autorp_grppfix);
struct autorp_pkt_grp {
#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -79,7 +84,15 @@ struct pim_autorp_rp {
struct event *hold_timer;
struct prefix grp;
char grplist[32];
- struct pim_autorp_rp_item list;
+ struct pim_autorp_grppfix_head grp_pfix_list;
+ struct pim_autorp_rp_item item;
+};
+
+struct pim_autorp_grppfix {
+ struct prefix grp;
+ struct in_addr rp;
+ bool negative;
+ struct pim_autorp_grppfix_item item;
};
struct pim_autorp {
@@ -96,13 +109,18 @@ struct pim_autorp {
struct event *announce_timer;
/* Event for sending discovery packets*/
- /* struct event *discovery_timer; */
+ struct event *send_discovery_timer;
/* Flag enabling reading discovery packets */
bool do_discovery;
/* Flag enabling mapping agent (reading announcements and sending discovery)*/
- /* bool do_mapping; */
+ bool send_rp_discovery;
+
+ /* Flag indicating if we are sending discovery messages (true) or if a higher IP mapping
+ * agent preemptied our sending (false)
+ */
+ bool mapping_agent_active;
/* List of RP's in received discovery packets */
struct pim_autorp_rp_head discovery_rp_list;
@@ -111,7 +129,12 @@ struct pim_autorp {
struct pim_autorp_rp_head candidate_rp_list;
/* List of announced RP's to send in discovery packets */
- /* struct pim_autorp_rp_head mapping_rp_list; */
+ struct pim_autorp_rp_head mapping_rp_list;
+
+ /* List of the last advertised RP's, via mapping agent discovery
+ * This is only filled if a discovery message was sent
+ */
+ struct pim_autorp_rp_head advertised_rp_list;
/* Packet parameters for sending announcement packets */
uint8_t announce_scope;
@@ -119,32 +142,32 @@ struct pim_autorp {
int32_t announce_holdtime;
/* Pre-built announcement packet, only changes when configured RP's or packet parameters change */
- uint8_t *annouce_pkt;
- uint16_t annouce_pkt_sz;
-
- /* TODO: Packet parameters for sending discovery packets
- * int discovery_scope;
- * int discovery_interval;
- * int discovery_holdtime;
- */
+ uint8_t *announce_pkt;
+ uint16_t announce_pkt_sz;
+
+ /* Packet parameters for sending discovery packets */
+ uint8_t discovery_scope;
+ uint16_t discovery_interval;
+ uint16_t discovery_holdtime;
+ struct cand_addrsel mapping_agent_addrsel;
};
#define AUTORP_GRPLEN 6
#define AUTORP_RPLEN 6
#define AUTORP_HDRLEN 8
+void pim_autorp_prefix_list_update(struct pim_instance *pim, struct prefix_list *plist);
bool pim_autorp_rm_candidate_rp(struct pim_instance *pim, pim_addr rpaddr);
-void pim_autorp_add_candidate_rp_group(struct pim_instance *pim,
- pim_addr rpaddr, struct prefix group);
+void pim_autorp_add_candidate_rp_group(struct pim_instance *pim, pim_addr rpaddr,
+ struct prefix group);
bool pim_autorp_rm_candidate_rp_group(struct pim_instance *pim, pim_addr rpaddr,
struct prefix group);
-void pim_autorp_add_candidate_rp_plist(struct pim_instance *pim,
- pim_addr rpaddr, const char *plist);
-bool pim_autorp_rm_candidate_rp_plist(struct pim_instance *pim, pim_addr rpaddr,
- const char *plist);
+void pim_autorp_add_candidate_rp_plist(struct pim_instance *pim, pim_addr rpaddr, const char *plist);
+bool pim_autorp_rm_candidate_rp_plist(struct pim_instance *pim, pim_addr rpaddr, const char *plist);
void pim_autorp_announce_scope(struct pim_instance *pim, uint8_t scope);
void pim_autorp_announce_interval(struct pim_instance *pim, uint16_t interval);
void pim_autorp_announce_holdtime(struct pim_instance *pim, int32_t holdtime);
+void pim_autorp_send_discovery_apply(struct pim_autorp *autorp);
void pim_autorp_add_ifp(struct interface *ifp);
void pim_autorp_rm_ifp(struct interface *ifp);
void pim_autorp_start_discovery(struct pim_instance *pim);
@@ -152,7 +175,7 @@ void pim_autorp_stop_discovery(struct pim_instance *pim);
void pim_autorp_init(struct pim_instance *pim);
void pim_autorp_finish(struct pim_instance *pim);
int pim_autorp_config_write(struct pim_instance *pim, struct vty *vty);
-void pim_autorp_show_autorp(struct vty *vty, struct pim_instance *pim,
+void pim_autorp_show_autorp(struct vty *vty, struct pim_instance *pim, const char *component,
json_object *json);
#endif
diff --git a/pimd/pimd.c b/pimd/pimd.c
index db61974800..a390378a5a 100644
--- a/pimd/pimd.c
+++ b/pimd/pimd.c
@@ -35,6 +35,7 @@
#include "pim_zlookup.h"
#include "pim_zebra.h"
#include "pim_mlag.h"
+#include "pim_autorp.h"
#if MAXVIFS > 256
CPP_NOTICE("Work needs to be done to make this work properly via the pim mroute socket\n");
@@ -70,6 +71,9 @@ void pim_prefix_list_update(struct prefix_list *plist)
pim_rp_prefix_list_update(pim, plist);
pim_ssm_prefix_list_update(pim, plist);
pim_upstream_spt_prefix_list_update(pim, plist);
+#if PIM_IPV == 4
+ pim_autorp_prefix_list_update(pim, plist);
+#endif
}
}