diff options
Diffstat (limited to 'pimd/pim_join.c')
| -rw-r--r-- | pimd/pim_join.c | 264 |
1 files changed, 110 insertions, 154 deletions
diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 6a5fb851d6..028f77f532 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,19 @@ #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" -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 +55,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 +146,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 +155,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 +168,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 +180,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 +195,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 +226,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 +239,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 +268,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,11 +292,12 @@ 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; @@ -270,16 +305,14 @@ int pim_joinprune_recv(struct interface *ifp, int pim_joinprune_send(struct interface *ifp, struct in_addr upstream_addr, - struct in_addr source_addr, - struct in_addr group_addr, + struct pim_upstream *up, int send_join) { 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 */ + uint8_t pim_msg[9000]; int pim_msg_size; - int remain; + + on_trace (__PRETTY_FUNCTION__, ifp, upstream_addr); zassert(ifp); @@ -292,31 +325,23 @@ int pim_joinprune_send(struct interface *ifp, 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)); + if (PIM_DEBUG_PIM_J_P) { + char dst_str[INET_ADDRSTRLEN]; 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", + zlog_debug("%s: sending %s(S,G)=%s to upstream=%s on interface %s", __PRETTY_FUNCTION__, send_join ? "Join" : "Prune", - source_str, group_str, dst_str, ifp->name); + up->sg_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)); + if (PIM_DEBUG_PIM_J_P) { + char dst_str[INET_ADDRSTRLEN]; 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", + zlog_debug("%s: %s(S,G)=%s: upstream=%s is myself on interface %s", __PRETTY_FUNCTION__, send_join ? "Join" : "Prune", - source_str, group_str, dst_str, ifp->name); + up->sg_str, dst_str, ifp->name); } return 0; } @@ -335,83 +360,14 @@ int pim_joinprune_send(struct interface *ifp, /* Build PIM message */ + pim_msg_size = pim_msg_join_prune_encode (pim_msg, 9000, send_join, + up, 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, - 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_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, + pim_ifp->primary_address, qpim_all_pim_routers_addr, pim_msg, pim_msg_size, |
