diff options
author | whitespace / reindent <invalid@invalid.invalid> | 2017-07-17 14:03:14 +0200 |
---|---|---|
committer | whitespace / reindent <invalid@invalid.invalid> | 2017-07-17 14:04:07 +0200 |
commit | d62a17aedeb0eebdba98238874bb13d62c48dbf9 (patch) | |
tree | 3b319b1d61c8b85b4d1f06adf8b844bb8a9b5107 /pimd | |
parent | *: add indent control files (diff) | |
download | frr-d62a17aedeb0eebdba98238874bb13d62c48dbf9.tar.xz frr-d62a17aedeb0eebdba98238874bb13d62c48dbf9.zip |
*: reindentreindent-master-after
indent.py `git ls-files | pcregrep '\.[ch]$' | pcregrep -v '^(ldpd|babeld|nhrpd)/'`
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'pimd')
81 files changed, 25935 insertions, 25405 deletions
diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 37515cee5..f68c252a3 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -42,283 +42,280 @@ static void assert_action_a2(struct pim_ifchannel *ch, static void assert_action_a6(struct pim_ifchannel *ch, struct pim_assert_metric winner_metric); -void pim_ifassert_winner_set(struct pim_ifchannel *ch, - enum pim_ifassert_state new_state, - struct in_addr winner, - struct pim_assert_metric winner_metric) +void pim_ifassert_winner_set(struct pim_ifchannel *ch, + enum pim_ifassert_state new_state, + struct in_addr winner, + struct pim_assert_metric winner_metric) { - int winner_changed = (ch->ifassert_winner.s_addr != winner.s_addr); - int metric_changed = !pim_assert_metric_match(&ch->ifassert_winner_metric, - &winner_metric); - - if (PIM_DEBUG_PIM_EVENTS) { - if (ch->ifassert_state != new_state) { - zlog_debug("%s: (S,G)=%s assert state changed from %s to %s on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, - pim_ifchannel_ifassert_name(ch->ifassert_state), - pim_ifchannel_ifassert_name(new_state), - ch->interface->name); - } - - if (winner_changed) { - char was_str[INET_ADDRSTRLEN]; - char winner_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<was?>", ch->ifassert_winner, was_str, sizeof(was_str)); - pim_inet4_dump("<winner?>", winner, winner_str, sizeof(winner_str)); - zlog_debug("%s: (S,G)=%s assert winner changed from %s to %s on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, - was_str, winner_str, ch->interface->name); - } - } /* PIM_DEBUG_PIM_EVENTS */ - - ch->ifassert_state = new_state; - ch->ifassert_winner = winner; - ch->ifassert_winner_metric = winner_metric; - ch->ifassert_creation = pim_time_monotonic_sec(); - - if (winner_changed || metric_changed) { - pim_upstream_update_join_desired(ch->upstream); - pim_ifchannel_update_could_assert(ch); - pim_ifchannel_update_assert_tracking_desired(ch); - } + int winner_changed = (ch->ifassert_winner.s_addr != winner.s_addr); + int metric_changed = !pim_assert_metric_match( + &ch->ifassert_winner_metric, &winner_metric); + + if (PIM_DEBUG_PIM_EVENTS) { + if (ch->ifassert_state != new_state) { + zlog_debug( + "%s: (S,G)=%s assert state changed from %s to %s on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, + pim_ifchannel_ifassert_name(ch->ifassert_state), + pim_ifchannel_ifassert_name(new_state), + ch->interface->name); + } + + if (winner_changed) { + char was_str[INET_ADDRSTRLEN]; + char winner_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<was?>", ch->ifassert_winner, was_str, + sizeof(was_str)); + pim_inet4_dump("<winner?>", winner, winner_str, + sizeof(winner_str)); + zlog_debug( + "%s: (S,G)=%s assert winner changed from %s to %s on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, was_str, + winner_str, ch->interface->name); + } + } /* PIM_DEBUG_PIM_EVENTS */ + + ch->ifassert_state = new_state; + ch->ifassert_winner = winner; + ch->ifassert_winner_metric = winner_metric; + ch->ifassert_creation = pim_time_monotonic_sec(); + + if (winner_changed || metric_changed) { + pim_upstream_update_join_desired(ch->upstream); + pim_ifchannel_update_could_assert(ch); + pim_ifchannel_update_assert_tracking_desired(ch); + } } -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[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src, src_str, sizeof(src_str)); - zlog_debug("%s: from %s on %s", - label, src_str, ifp->name); - } + if (PIM_DEBUG_PIM_TRACE) { + 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); + } } static int preferred_assert(const struct pim_ifchannel *ch, const struct pim_assert_metric *recv_metric) { - return pim_assert_metric_better(recv_metric, - &ch->ifassert_winner_metric); + return pim_assert_metric_better(recv_metric, + &ch->ifassert_winner_metric); } static int acceptable_assert(const struct pim_assert_metric *my_metric, const struct pim_assert_metric *recv_metric) { - return pim_assert_metric_better(recv_metric, - my_metric); + return pim_assert_metric_better(recv_metric, my_metric); } static int inferior_assert(const struct pim_assert_metric *my_metric, const struct pim_assert_metric *recv_metric) { - return pim_assert_metric_better(my_metric, - recv_metric); + return pim_assert_metric_better(my_metric, recv_metric); } static int cancel_assert(const struct pim_assert_metric *recv_metric) { - return (recv_metric->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX) - && - (recv_metric->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX); + return (recv_metric->metric_preference + == PIM_ASSERT_METRIC_PREFERENCE_MAX) + && (recv_metric->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX); } -static void if_could_assert_do_a1(const char *caller, - struct pim_ifchannel *ch) +static void if_could_assert_do_a1(const char *caller, struct pim_ifchannel *ch) { - if (PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { - if (assert_action_a1(ch)) { - zlog_warn("%s: %s: (S,G)=%s assert_action_a1 failure on interface %s", - __PRETTY_FUNCTION__, caller, - ch->sg_str, ch->interface->name); - /* log warning only */ - } - } + if (PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { + if (assert_action_a1(ch)) { + zlog_warn( + "%s: %s: (S,G)=%s assert_action_a1 failure on interface %s", + __PRETTY_FUNCTION__, caller, ch->sg_str, + ch->interface->name); + /* log warning only */ + } + } } -static int dispatch_assert(struct interface *ifp, - struct in_addr source_addr, +static int dispatch_assert(struct interface *ifp, struct in_addr source_addr, struct in_addr group_addr, struct pim_assert_metric recv_metric) { - struct pim_ifchannel *ch; - struct prefix_sg sg; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = source_addr; - sg.grp = group_addr; - ch = pim_ifchannel_add(ifp, &sg, 0); - if (!ch) { - zlog_warn("%s: (S,G)=%s failure creating channel on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), ifp->name); - return -1; - } - - switch (ch->ifassert_state) { - case PIM_IFASSERT_NOINFO: - if (recv_metric.rpt_bit_flag) { - /* RPT bit set */ - if_could_assert_do_a1(__PRETTY_FUNCTION__, ch); - } - else { - /* RPT bit clear */ - if (inferior_assert(&ch->ifassert_my_metric, &recv_metric)) { - if_could_assert_do_a1(__PRETTY_FUNCTION__, ch); - } - else if (acceptable_assert(&ch->ifassert_my_metric, &recv_metric)) { - if (PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags)) { - assert_action_a6(ch, recv_metric); - } - } - } - break; - case PIM_IFASSERT_I_AM_WINNER: - if (preferred_assert(ch, &recv_metric)) { - assert_action_a2(ch, recv_metric); - } - else { - if (inferior_assert(&ch->ifassert_my_metric, &recv_metric)) { - assert_action_a3(ch); - } - } - break; - case PIM_IFASSERT_I_AM_LOSER: - if (recv_metric.ip_address.s_addr == ch->ifassert_winner.s_addr) { - /* Assert from current winner */ - - if (cancel_assert(&recv_metric)) { - assert_action_a5(ch); - } - else { - if (inferior_assert(&ch->ifassert_my_metric, &recv_metric)) { - assert_action_a5(ch); - } - else if (acceptable_assert(&ch->ifassert_my_metric, &recv_metric)) { - if (!recv_metric.rpt_bit_flag) { - assert_action_a2(ch, recv_metric); - } - } - } - } - else if (preferred_assert(ch, &recv_metric)) { - assert_action_a2(ch, recv_metric); - } - break; - default: - { - zlog_warn("%s: (S,G)=%s invalid assert state %d on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->ifassert_state, ifp->name); - } - return -2; - } - - return 0; + struct pim_ifchannel *ch; + struct prefix_sg sg; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = source_addr; + sg.grp = group_addr; + ch = pim_ifchannel_add(ifp, &sg, 0); + if (!ch) { + zlog_warn( + "%s: (S,G)=%s failure creating channel on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), ifp->name); + return -1; + } + + switch (ch->ifassert_state) { + case PIM_IFASSERT_NOINFO: + if (recv_metric.rpt_bit_flag) { + /* RPT bit set */ + if_could_assert_do_a1(__PRETTY_FUNCTION__, ch); + } else { + /* RPT bit clear */ + if (inferior_assert(&ch->ifassert_my_metric, + &recv_metric)) { + if_could_assert_do_a1(__PRETTY_FUNCTION__, ch); + } else if (acceptable_assert(&ch->ifassert_my_metric, + &recv_metric)) { + if (PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED( + ch->flags)) { + assert_action_a6(ch, recv_metric); + } + } + } + break; + case PIM_IFASSERT_I_AM_WINNER: + if (preferred_assert(ch, &recv_metric)) { + assert_action_a2(ch, recv_metric); + } else { + if (inferior_assert(&ch->ifassert_my_metric, + &recv_metric)) { + assert_action_a3(ch); + } + } + break; + case PIM_IFASSERT_I_AM_LOSER: + if (recv_metric.ip_address.s_addr + == ch->ifassert_winner.s_addr) { + /* Assert from current winner */ + + if (cancel_assert(&recv_metric)) { + assert_action_a5(ch); + } else { + if (inferior_assert(&ch->ifassert_my_metric, + &recv_metric)) { + assert_action_a5(ch); + } else if (acceptable_assert( + &ch->ifassert_my_metric, + &recv_metric)) { + if (!recv_metric.rpt_bit_flag) { + assert_action_a2(ch, + recv_metric); + } + } + } + } else if (preferred_assert(ch, &recv_metric)) { + assert_action_a2(ch, recv_metric); + } + break; + default: { + zlog_warn( + "%s: (S,G)=%s invalid assert state %d on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ch->ifassert_state, + ifp->name); + } + return -2; + } + + return 0; } -int pim_assert_recv(struct interface *ifp, - struct pim_neighbor *neigh, - struct in_addr src_addr, - uint8_t *buf, int buf_size) +int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh, + struct in_addr src_addr, uint8_t *buf, int buf_size) { - struct prefix_sg sg; - struct prefix msg_source_addr; - struct pim_assert_metric msg_metric; - int offset; - uint8_t *curr; - int curr_size; - struct pim_interface *pim_ifp = NULL; - - on_trace(__PRETTY_FUNCTION__, ifp, src_addr); - - curr = buf; - curr_size = buf_size; - - /* - Parse assert group addr - */ - memset (&sg, 0, sizeof (struct prefix_sg)); - offset = pim_parse_addr_group (&sg, curr, curr_size); - if (offset < 1) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: pim_parse_addr_group() failure: from %s on %s", - __PRETTY_FUNCTION__, - src_str, ifp->name); - return -1; - } - curr += offset; - curr_size -= offset; - - /* - Parse assert source addr - */ - offset = pim_parse_addr_ucast (&msg_source_addr, curr, curr_size); - if (offset < 1) { - 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__, - src_str, ifp->name); - return -2; - } - curr += offset; - curr_size -= offset; - - if (curr_size != 8) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: preference/metric size is not 8: size=%d from %s on interface %s", - __PRETTY_FUNCTION__, - curr_size, - src_str, ifp->name); - return -3; - } - - /* - Parse assert metric preference - */ - - msg_metric.metric_preference = pim_read_uint32_host(curr); - - msg_metric.rpt_bit_flag = msg_metric.metric_preference & 0x80000000; /* save highest bit */ - msg_metric.metric_preference &= ~0x80000000; /* clear highest bit */ - - curr += 4; - - /* - Parse assert route metric - */ - - msg_metric.route_metric = pim_read_uint32_host(curr); - - if (PIM_DEBUG_PIM_TRACE) { - char neigh_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<neigh?>", src_addr, neigh_str, sizeof(neigh_str)); - pim_inet4_dump("<src?>", msg_source_addr.u.prefix4, source_str, sizeof(source_str)); - pim_inet4_dump("<grp?>", sg.grp, group_str, sizeof(group_str)); - zlog_debug("%s: from %s on %s: (S,G)=(%s,%s) pref=%u metric=%u rpt_bit=%u", - __PRETTY_FUNCTION__, neigh_str, ifp->name, - source_str, group_str, - msg_metric.metric_preference, - msg_metric.route_metric, - PIM_FORCE_BOOLEAN(msg_metric.rpt_bit_flag)); - } - - msg_metric.ip_address = src_addr; - - pim_ifp = ifp->info; - zassert(pim_ifp); - ++pim_ifp->pim_ifstat_assert_recv; - - return dispatch_assert(ifp, - msg_source_addr.u.prefix4, - sg.grp, - msg_metric); + struct prefix_sg sg; + struct prefix msg_source_addr; + struct pim_assert_metric msg_metric; + int offset; + uint8_t *curr; + int curr_size; + struct pim_interface *pim_ifp = NULL; + + on_trace(__PRETTY_FUNCTION__, ifp, src_addr); + + curr = buf; + curr_size = buf_size; + + /* + Parse assert group addr + */ + memset(&sg, 0, sizeof(struct prefix_sg)); + offset = pim_parse_addr_group(&sg, curr, curr_size); + if (offset < 1) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + zlog_warn("%s: pim_parse_addr_group() failure: from %s on %s", + __PRETTY_FUNCTION__, src_str, ifp->name); + return -1; + } + curr += offset; + curr_size -= offset; + + /* + Parse assert source addr + */ + offset = pim_parse_addr_ucast(&msg_source_addr, curr, curr_size); + if (offset < 1) { + 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__, src_str, ifp->name); + return -2; + } + curr += offset; + curr_size -= offset; + + if (curr_size != 8) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + zlog_warn( + "%s: preference/metric size is not 8: size=%d from %s on interface %s", + __PRETTY_FUNCTION__, curr_size, src_str, ifp->name); + return -3; + } + + /* + Parse assert metric preference + */ + + msg_metric.metric_preference = pim_read_uint32_host(curr); + + msg_metric.rpt_bit_flag = msg_metric.metric_preference + & 0x80000000; /* save highest bit */ + msg_metric.metric_preference &= ~0x80000000; /* clear highest bit */ + + curr += 4; + + /* + Parse assert route metric + */ + + msg_metric.route_metric = pim_read_uint32_host(curr); + + if (PIM_DEBUG_PIM_TRACE) { + char neigh_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<neigh?>", src_addr, neigh_str, + sizeof(neigh_str)); + pim_inet4_dump("<src?>", msg_source_addr.u.prefix4, source_str, + sizeof(source_str)); + pim_inet4_dump("<grp?>", sg.grp, group_str, sizeof(group_str)); + zlog_debug( + "%s: from %s on %s: (S,G)=(%s,%s) pref=%u metric=%u rpt_bit=%u", + __PRETTY_FUNCTION__, neigh_str, ifp->name, source_str, + group_str, msg_metric.metric_preference, + msg_metric.route_metric, + PIM_FORCE_BOOLEAN(msg_metric.rpt_bit_flag)); + } + + msg_metric.ip_address = src_addr; + + pim_ifp = ifp->info; + zassert(pim_ifp); + ++pim_ifp->pim_ifstat_assert_recv; + + return dispatch_assert(ifp, msg_source_addr.u.prefix4, sg.grp, + msg_metric); } /* @@ -335,167 +332,164 @@ int pim_assert_recv(struct interface *ifp, int pim_assert_metric_better(const struct pim_assert_metric *m1, const struct pim_assert_metric *m2) { - if (m1->rpt_bit_flag < m2->rpt_bit_flag) - return 1; - if (m1->rpt_bit_flag > m2->rpt_bit_flag) - return 0; - - if (m1->metric_preference < m2->metric_preference) - return 1; - if (m1->metric_preference > m2->metric_preference) - return 0; - - if (m1->route_metric < m2->route_metric) - return 1; - if (m1->route_metric > m2->route_metric) - return 0; - - return ntohl(m1->ip_address.s_addr) > ntohl(m2->ip_address.s_addr); + if (m1->rpt_bit_flag < m2->rpt_bit_flag) + return 1; + if (m1->rpt_bit_flag > m2->rpt_bit_flag) + return 0; + + if (m1->metric_preference < m2->metric_preference) + return 1; + if (m1->metric_preference > m2->metric_preference) + return 0; + + if (m1->route_metric < m2->route_metric) + return 1; + if (m1->route_metric > m2->route_metric) + return 0; + + return ntohl(m1->ip_address.s_addr) > ntohl(m2->ip_address.s_addr); } int pim_assert_metric_match(const struct pim_assert_metric *m1, const struct pim_assert_metric *m2) { - if (m1->rpt_bit_flag != m2->rpt_bit_flag) - return 0; - if (m1->metric_preference != m2->metric_preference) - return 0; - if (m1->route_metric != m2->route_metric) - return 0; - - return m1->ip_address.s_addr == m2->ip_address.s_addr; + if (m1->rpt_bit_flag != m2->rpt_bit_flag) + return 0; + if (m1->metric_preference != m2->metric_preference) + return 0; + if (m1->route_metric != m2->route_metric) + return 0; + + return m1->ip_address.s_addr == m2->ip_address.s_addr; } -int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, - struct interface *ifp, - struct in_addr group_addr, - struct in_addr source_addr, - uint32_t metric_preference, - uint32_t route_metric, +int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, struct interface *ifp, + struct in_addr group_addr, struct in_addr source_addr, + uint32_t metric_preference, uint32_t route_metric, uint32_t rpt_bit_flag) { - uint8_t *buf_pastend = pim_msg + buf_size; - uint8_t *pim_msg_curr; - int pim_msg_size; - int remain; - - pim_msg_curr = pim_msg + PIM_MSG_HEADER_LEN; /* skip room for pim header */ - - /* Encode group */ - remain = buf_pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr, group_addr); - if (!pim_msg_curr) { - char group_str[INET_ADDRSTRLEN]; - 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 -1; - } - - /* Encode source */ - remain = buf_pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_ucast(pim_msg_curr, source_addr); - if (!pim_msg_curr) { - char source_str[INET_ADDRSTRLEN]; - 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 -2; - } - - /* Metric preference */ - pim_write_uint32(pim_msg_curr, rpt_bit_flag ? - metric_preference | 0x80000000 : - metric_preference); - pim_msg_curr += 4; - - /* Route metric */ - pim_write_uint32(pim_msg_curr, route_metric); - pim_msg_curr += 4; - - /* - Add PIM header - */ - pim_msg_size = pim_msg_curr - pim_msg; - pim_msg_build_header(pim_msg, pim_msg_size, - PIM_MSG_TYPE_ASSERT); - - return pim_msg_size; + uint8_t *buf_pastend = pim_msg + buf_size; + uint8_t *pim_msg_curr; + int pim_msg_size; + int remain; + + pim_msg_curr = + pim_msg + PIM_MSG_HEADER_LEN; /* skip room for pim header */ + + /* Encode group */ + remain = buf_pastend - pim_msg_curr; + pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr, group_addr); + if (!pim_msg_curr) { + char group_str[INET_ADDRSTRLEN]; + 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 -1; + } + + /* Encode source */ + remain = buf_pastend - pim_msg_curr; + pim_msg_curr = + pim_msg_addr_encode_ipv4_ucast(pim_msg_curr, source_addr); + if (!pim_msg_curr) { + char source_str[INET_ADDRSTRLEN]; + 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 -2; + } + + /* Metric preference */ + pim_write_uint32(pim_msg_curr, + rpt_bit_flag ? metric_preference | 0x80000000 + : metric_preference); + pim_msg_curr += 4; + + /* Route metric */ + pim_write_uint32(pim_msg_curr, route_metric); + pim_msg_curr += 4; + + /* + Add PIM header + */ + pim_msg_size = pim_msg_curr - pim_msg; + pim_msg_build_header(pim_msg, pim_msg_size, PIM_MSG_TYPE_ASSERT); + + return pim_msg_size; } static int pim_assert_do(struct pim_ifchannel *ch, struct pim_assert_metric metric) { - struct interface *ifp; - struct pim_interface *pim_ifp; - uint8_t pim_msg[1000]; - int pim_msg_size; - - ifp = ch->interface; - if (!ifp) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s: channel%s has no associated interface!", - __PRETTY_FUNCTION__, ch->sg_str); - return -1; - } - pim_ifp = ifp->info; - if (!pim_ifp) { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s: channel %s pim not enabled on interface: %s", - __PRETTY_FUNCTION__, ch->sg_str, ifp->name); - return -1; - } - - pim_msg_size = pim_assert_build_msg(pim_msg, sizeof(pim_msg), ifp, - ch->sg.grp, ch->sg.src, - metric.metric_preference, - metric.route_metric, - metric.rpt_bit_flag); - if (pim_msg_size < 1) { - zlog_warn("%s: failure building PIM assert message: msg_size=%d", - __PRETTY_FUNCTION__, pim_msg_size); - return -2; - } - - /* - RFC 4601: 4.3.1. Sending Hello Messages - - Thus, if a router needs to send a Join/Prune or Assert message on - an interface on which it has not yet sent a Hello message with the - currently configured IP address, then it MUST immediately send the - relevant Hello message without waiting for the Hello Timer to - expire, followed by the Join/Prune or Assert message. - */ - pim_hello_require(ifp); - - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: to %s: (S,G)=%s pref=%u metric=%u rpt_bit=%u", - __PRETTY_FUNCTION__, - ifp->name, ch->sg_str, - metric.metric_preference, - metric.route_metric, - PIM_FORCE_BOOLEAN(metric.rpt_bit_flag)); - } - ++pim_ifp->pim_ifstat_assert_send; - - if (pim_msg_send(pim_ifp->pim_sock_fd, - pim_ifp->primary_address, - qpim_all_pim_routers_addr, - pim_msg, - pim_msg_size, - ifp->name)) { - zlog_warn("%s: could not send PIM message on interface %s", - __PRETTY_FUNCTION__, ifp->name); - return -3; - } - - return 0; + struct interface *ifp; + struct pim_interface *pim_ifp; + uint8_t pim_msg[1000]; + int pim_msg_size; + + ifp = ch->interface; + if (!ifp) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: channel%s has no associated interface!", + __PRETTY_FUNCTION__, ch->sg_str); + return -1; + } + pim_ifp = ifp->info; + if (!pim_ifp) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s: channel %s pim not enabled on interface: %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + return -1; + } + + pim_msg_size = + pim_assert_build_msg(pim_msg, sizeof(pim_msg), ifp, ch->sg.grp, + ch->sg.src, metric.metric_preference, + metric.route_metric, metric.rpt_bit_flag); + if (pim_msg_size < 1) { + zlog_warn( + "%s: failure building PIM assert message: msg_size=%d", + __PRETTY_FUNCTION__, pim_msg_size); + return -2; + } + + /* + RFC 4601: 4.3.1. Sending Hello Messages + + Thus, if a router needs to send a Join/Prune or Assert message on + an interface on which it has not yet sent a Hello message with the + currently configured IP address, then it MUST immediately send the + relevant Hello message without waiting for the Hello Timer to + expire, followed by the Join/Prune or Assert message. + */ + pim_hello_require(ifp); + + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: to %s: (S,G)=%s pref=%u metric=%u rpt_bit=%u", + __PRETTY_FUNCTION__, ifp->name, ch->sg_str, + metric.metric_preference, metric.route_metric, + PIM_FORCE_BOOLEAN(metric.rpt_bit_flag)); + } + ++pim_ifp->pim_ifstat_assert_send; + + if (pim_msg_send(pim_ifp->pim_sock_fd, pim_ifp->primary_address, + qpim_all_pim_routers_addr, pim_msg, pim_msg_size, + ifp->name)) { + zlog_warn("%s: could not send PIM message on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return -3; + } + + return 0; } int pim_assert_send(struct pim_ifchannel *ch) { - return pim_assert_do(ch, ch->ifassert_my_metric); + return pim_assert_do(ch, ch->ifassert_my_metric); } /* @@ -506,82 +500,82 @@ int pim_assert_send(struct pim_ifchannel *ch) */ static int pim_assert_cancel(struct pim_ifchannel *ch) { - struct pim_assert_metric metric; + struct pim_assert_metric metric; - metric.rpt_bit_flag = 0; - metric.metric_preference = PIM_ASSERT_METRIC_PREFERENCE_MAX; - metric.route_metric = PIM_ASSERT_ROUTE_METRIC_MAX; - metric.ip_address = ch->sg.src; + metric.rpt_bit_flag = 0; + metric.metric_preference = PIM_ASSERT_METRIC_PREFERENCE_MAX; + metric.route_metric = PIM_ASSERT_ROUTE_METRIC_MAX; + metric.ip_address = ch->sg.src; - return pim_assert_do(ch, metric); + return pim_assert_do(ch, metric); } static int on_assert_timer(struct thread *t) { - struct pim_ifchannel *ch; - struct interface *ifp; - - ch = THREAD_ARG(t); - - ifp = ch->interface; - - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: (S,G)=%s timer expired on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - } - - ch->t_ifassert_timer = NULL; - - switch (ch->ifassert_state) { - case PIM_IFASSERT_I_AM_WINNER: - assert_action_a3(ch); - break; - case PIM_IFASSERT_I_AM_LOSER: - assert_action_a5(ch); - break; - default: - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_warn("%s: (S,G)=%s invalid assert state %d on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->ifassert_state, ifp->name); - } - } - - return 0; + struct pim_ifchannel *ch; + struct interface *ifp; + + ch = THREAD_ARG(t); + + ifp = ch->interface; + + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: (S,G)=%s timer expired on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + } + + ch->t_ifassert_timer = NULL; + + switch (ch->ifassert_state) { + case PIM_IFASSERT_I_AM_WINNER: + assert_action_a3(ch); + break; + case PIM_IFASSERT_I_AM_LOSER: + assert_action_a5(ch); + break; + default: { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn( + "%s: (S,G)=%s invalid assert state %d on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, + ch->ifassert_state, ifp->name); + } + } + + return 0; } static void assert_timer_off(struct pim_ifchannel *ch) { - if (PIM_DEBUG_PIM_TRACE) { - if (ch->t_ifassert_timer) { - zlog_debug("%s: (S,G)=%s cancelling timer on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->interface->name); - } - } - THREAD_OFF(ch->t_ifassert_timer); + if (PIM_DEBUG_PIM_TRACE) { + if (ch->t_ifassert_timer) { + zlog_debug( + "%s: (S,G)=%s cancelling timer on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, + ch->interface->name); + } + } + THREAD_OFF(ch->t_ifassert_timer); } -static void pim_assert_timer_set(struct pim_ifchannel *ch, - int interval) +static void pim_assert_timer_set(struct pim_ifchannel *ch, int interval) { - assert_timer_off(ch); + assert_timer_off(ch); - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: (S,G)=%s starting %u sec timer on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, interval, ch->interface->name); - } + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: (S,G)=%s starting %u sec timer on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, interval, + ch->interface->name); + } - thread_add_timer(master, on_assert_timer, ch, interval, - &ch->t_ifassert_timer); + thread_add_timer(master, on_assert_timer, ch, interval, + &ch->t_ifassert_timer); } static void pim_assert_timer_reset(struct pim_ifchannel *ch) { - pim_assert_timer_set(ch, PIM_ASSERT_TIME - PIM_ASSERT_OVERRIDE_INTERVAL); + pim_assert_timer_set(ch, + PIM_ASSERT_TIME - PIM_ASSERT_OVERRIDE_INTERVAL); } /* @@ -596,38 +590,37 @@ static void pim_assert_timer_reset(struct pim_ifchannel *ch) */ int assert_action_a1(struct pim_ifchannel *ch) { - struct interface *ifp = ch->interface; - struct pim_interface *pim_ifp; - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: (S,G)=%s multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - return -1; /* must return since pim_ifp is used below */ - } - - /* Switch to I_AM_WINNER before performing action_a3 below */ - pim_ifassert_winner_set(ch, PIM_IFASSERT_I_AM_WINNER, - pim_ifp->primary_address, - pim_macro_spt_assert_metric(&ch->upstream->rpf, - pim_ifp->primary_address)); - - if (assert_action_a3(ch)) { - zlog_warn("%s: (S,G)=%s assert_action_a3 failure on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - /* warning only */ - } - - if (ch->ifassert_state != PIM_IFASSERT_I_AM_WINNER) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_warn("%s: channel%s not in expected PIM_IFASSERT_I_AM_WINNER state", - __PRETTY_FUNCTION__, ch->sg_str); - } - - return 0; + struct interface *ifp = ch->interface; + struct pim_interface *pim_ifp; + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: (S,G)=%s multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + return -1; /* must return since pim_ifp is used below */ + } + + /* Switch to I_AM_WINNER before performing action_a3 below */ + pim_ifassert_winner_set( + ch, PIM_IFASSERT_I_AM_WINNER, pim_ifp->primary_address, + pim_macro_spt_assert_metric(&ch->upstream->rpf, + pim_ifp->primary_address)); + + if (assert_action_a3(ch)) { + zlog_warn( + "%s: (S,G)=%s assert_action_a3 failure on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + /* warning only */ + } + + if (ch->ifassert_state != PIM_IFASSERT_I_AM_WINNER) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn( + "%s: channel%s not in expected PIM_IFASSERT_I_AM_WINNER state", + __PRETTY_FUNCTION__, ch->sg_str); + } + + return 0; } /* @@ -636,24 +629,23 @@ int assert_action_a1(struct pim_ifchannel *ch) (S,G) Assert State machine Actions A2: Store new assert winner as AssertWinner(S,G,I) and assert - winner metric as AssertWinnerMetric(S,G,I). - Set Assert Timer to Assert_Time. + winner metric as AssertWinnerMetric(S,G,I). + Set Assert Timer to Assert_Time. */ static void assert_action_a2(struct pim_ifchannel *ch, struct pim_assert_metric winner_metric) { - pim_ifassert_winner_set(ch, PIM_IFASSERT_I_AM_LOSER, - winner_metric.ip_address, - winner_metric); - - pim_assert_timer_set(ch, PIM_ASSERT_TIME); - - if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_warn("%s: channel%s not in expected PIM_IFASSERT_I_AM_LOSER state", - __PRETTY_FUNCTION__, ch->sg_str); - } + pim_ifassert_winner_set(ch, PIM_IFASSERT_I_AM_LOSER, + winner_metric.ip_address, winner_metric); + + pim_assert_timer_set(ch, PIM_ASSERT_TIME); + + if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn( + "%s: channel%s not in expected PIM_IFASSERT_I_AM_LOSER state", + __PRETTY_FUNCTION__, ch->sg_str); + } } /* @@ -666,24 +658,23 @@ static void assert_action_a2(struct pim_ifchannel *ch, */ static int assert_action_a3(struct pim_ifchannel *ch) { - if (ch->ifassert_state != PIM_IFASSERT_I_AM_WINNER) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_warn("%s: channel%s expected to be in PIM_IFASSERT_I_AM_WINNER state", - __PRETTY_FUNCTION__, ch->sg_str); - return -1; - } - - pim_assert_timer_reset(ch); - - if (pim_assert_send(ch)) { - zlog_warn("%s: (S,G)=%s failure sending assert on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->interface->name); - return -1; - } - - return 0; + if (ch->ifassert_state != PIM_IFASSERT_I_AM_WINNER) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn( + "%s: channel%s expected to be in PIM_IFASSERT_I_AM_WINNER state", + __PRETTY_FUNCTION__, ch->sg_str); + return -1; + } + + pim_assert_timer_reset(ch); + + if (pim_assert_send(ch)) { + zlog_warn("%s: (S,G)=%s failure sending assert on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); + return -1; + } + + return 0; } /* @@ -692,27 +683,26 @@ static int assert_action_a3(struct pim_ifchannel *ch) (S,G) Assert State machine Actions A4: Send AssertCancel(S,G). - Delete assert info (AssertWinner(S,G,I) and - AssertWinnerMetric(S,G,I) will then return their default - values). + Delete assert info (AssertWinner(S,G,I) and + AssertWinnerMetric(S,G,I) will then return their default + values). */ void assert_action_a4(struct pim_ifchannel *ch) { - if (pim_assert_cancel(ch)) { - zlog_warn("%s: failure sending AssertCancel%s on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->interface->name); - /* log warning only */ - } - - assert_action_a5(ch); - - if (ch->ifassert_state != PIM_IFASSERT_NOINFO) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_warn("%s: channel%s not in PIM_IFASSERT_NOINFO state as expected", - __PRETTY_FUNCTION__, ch->sg_str); - } + if (pim_assert_cancel(ch)) { + zlog_warn("%s: failure sending AssertCancel%s on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); + /* log warning only */ + } + + assert_action_a5(ch); + + if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn( + "%s: channel%s not in PIM_IFASSERT_NOINFO state as expected", + __PRETTY_FUNCTION__, ch->sg_str); + } } /* @@ -725,13 +715,13 @@ void assert_action_a4(struct pim_ifchannel *ch) */ void assert_action_a5(struct pim_ifchannel *ch) { - reset_ifassert_state(ch); - if (ch->ifassert_state != PIM_IFASSERT_NOINFO) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_warn("%s: channel%s not in PIM_IFSSERT_NOINFO state as expected", - __PRETTY_FUNCTION__, ch->sg_str); - } + reset_ifassert_state(ch); + if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn( + "%s: channel%s not in PIM_IFSSERT_NOINFO state as expected", + __PRETTY_FUNCTION__, ch->sg_str); + } } /* @@ -740,29 +730,28 @@ void assert_action_a5(struct pim_ifchannel *ch) (S,G) Assert State machine Actions A6: Store new assert winner as AssertWinner(S,G,I) and assert - winner metric as AssertWinnerMetric(S,G,I). - Set Assert Timer to Assert_Time. - If (I is RPF_interface(S)) AND (UpstreamJPState(S,G) == true) - set SPTbit(S,G) to TRUE. + winner metric as AssertWinnerMetric(S,G,I). + Set Assert Timer to Assert_Time. + If (I is RPF_interface(S)) AND (UpstreamJPState(S,G) == true) + set SPTbit(S,G) to TRUE. */ static void assert_action_a6(struct pim_ifchannel *ch, struct pim_assert_metric winner_metric) { - assert_action_a2(ch, winner_metric); - - /* - If (I is RPF_interface(S)) AND (UpstreamJPState(S,G) == true) set - SPTbit(S,G) to TRUE. - */ - if (ch->upstream->rpf.source_nexthop.interface == ch->interface) - if (ch->upstream->join_state == PIM_UPSTREAM_JOINED) - ch->upstream->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - - if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) - { - if(PIM_DEBUG_PIM_EVENTS) - zlog_warn("%s: channel%s not in PIM_IFASSERT_I_AM_LOSER state as expected", - __PRETTY_FUNCTION__, ch->sg_str); - } + assert_action_a2(ch, winner_metric); + + /* + If (I is RPF_interface(S)) AND (UpstreamJPState(S,G) == true) set + SPTbit(S,G) to TRUE. + */ + if (ch->upstream->rpf.source_nexthop.interface == ch->interface) + if (ch->upstream->join_state == PIM_UPSTREAM_JOINED) + ch->upstream->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + + if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn( + "%s: channel%s not in PIM_IFASSERT_I_AM_LOSER state as expected", + __PRETTY_FUNCTION__, ch->sg_str); + } } - diff --git a/pimd/pim_assert.h b/pimd/pim_assert.h index b2fc11523..63fda3fe3 100644 --- a/pimd/pim_assert.h +++ b/pimd/pim_assert.h @@ -40,27 +40,22 @@ #define PIM_ASSERT_METRIC_PREFERENCE_MAX (0xFFFFFFFF) #define PIM_ASSERT_ROUTE_METRIC_MAX (0xFFFFFFFF) -void pim_ifassert_winner_set(struct pim_ifchannel *ch, - enum pim_ifassert_state new_state, - struct in_addr winner, - struct pim_assert_metric winner_metric); +void pim_ifassert_winner_set(struct pim_ifchannel *ch, + enum pim_ifassert_state new_state, + struct in_addr winner, + struct pim_assert_metric winner_metric); -int pim_assert_recv(struct interface *ifp, - struct pim_neighbor *neigh, - struct in_addr src_addr, - uint8_t *buf, int buf_size); +int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh, + struct in_addr src_addr, uint8_t *buf, int buf_size); int pim_assert_metric_better(const struct pim_assert_metric *m1, const struct pim_assert_metric *m2); int pim_assert_metric_match(const struct pim_assert_metric *m1, const struct pim_assert_metric *m2); -int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, - struct interface *ifp, - struct in_addr group_addr, - struct in_addr source_addr, - uint32_t metric_preference, - uint32_t route_metric, +int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, struct interface *ifp, + struct in_addr group_addr, struct in_addr source_addr, + uint32_t metric_preference, uint32_t route_metric, uint32_t rpt_bit_flag); int pim_assert_send(struct pim_ifchannel *ch); diff --git a/pimd/pim_bfd.c b/pimd/pim_bfd.c index af8a8e2c5..e4c50a18b 100644 --- a/pimd/pim_bfd.c +++ b/pimd/pim_bfd.c @@ -38,101 +38,94 @@ /* * pim_bfd_write_config - Write the interface BFD configuration. */ -void -pim_bfd_write_config (struct vty *vty, struct interface *ifp) +void pim_bfd_write_config(struct vty *vty, struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - struct bfd_info *bfd_info = NULL; - - if (!pim_ifp) - return; - - bfd_info = (struct bfd_info *) pim_ifp->bfd_info; - if (!bfd_info) - return; - - if (CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG)) - vty_out (vty, " ip pim bfd %d %d %d\n", - bfd_info->detect_mult, bfd_info->required_min_rx, - bfd_info->desired_min_tx); - else - vty_out (vty, " ip pim bfd\n"); + struct pim_interface *pim_ifp = ifp->info; + struct bfd_info *bfd_info = NULL; + + if (!pim_ifp) + return; + + bfd_info = (struct bfd_info *)pim_ifp->bfd_info; + if (!bfd_info) + return; + + if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) + vty_out(vty, " ip pim bfd %d %d %d\n", bfd_info->detect_mult, + bfd_info->required_min_rx, bfd_info->desired_min_tx); + else + vty_out(vty, " ip pim bfd\n"); } /* * pim_bfd_show_info - Show BFD info structure */ -void -pim_bfd_show_info (struct vty *vty, void *bfd_info, json_object * json_obj, - u_char use_json, int param_only) +void pim_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, + u_char use_json, int param_only) { - if (param_only) - bfd_show_param (vty, (struct bfd_info *) bfd_info, 1, 0, use_json, - json_obj); - else - bfd_show_info (vty, (struct bfd_info *) bfd_info, 0, 1, use_json, - json_obj); + if (param_only) + bfd_show_param(vty, (struct bfd_info *)bfd_info, 1, 0, use_json, + json_obj); + else + bfd_show_info(vty, (struct bfd_info *)bfd_info, 0, 1, use_json, + json_obj); } /* * pim_bfd_info_nbr_create - Create/update BFD information for a neighbor. */ -void -pim_bfd_info_nbr_create (struct pim_interface *pim_ifp, - struct pim_neighbor *neigh) +void pim_bfd_info_nbr_create(struct pim_interface *pim_ifp, + struct pim_neighbor *neigh) { - struct bfd_info *nbr_bfd_info = NULL; + struct bfd_info *nbr_bfd_info = NULL; - /* Check if Pim Interface BFD is enabled */ - if (!pim_ifp || !pim_ifp->bfd_info) - return; + /* Check if Pim Interface BFD is enabled */ + if (!pim_ifp || !pim_ifp->bfd_info) + return; - if (!neigh->bfd_info) - neigh->bfd_info = bfd_info_create (); + if (!neigh->bfd_info) + neigh->bfd_info = bfd_info_create(); - if (!neigh->bfd_info) - return; + if (!neigh->bfd_info) + return; - nbr_bfd_info = (struct bfd_info *) neigh->bfd_info; - nbr_bfd_info->detect_mult = pim_ifp->bfd_info->detect_mult; - nbr_bfd_info->desired_min_tx = pim_ifp->bfd_info->desired_min_tx; - nbr_bfd_info->required_min_rx = pim_ifp->bfd_info->required_min_rx; + nbr_bfd_info = (struct bfd_info *)neigh->bfd_info; + nbr_bfd_info->detect_mult = pim_ifp->bfd_info->detect_mult; + nbr_bfd_info->desired_min_tx = pim_ifp->bfd_info->desired_min_tx; + nbr_bfd_info->required_min_rx = pim_ifp->bfd_info->required_min_rx; } /* * pim_bfd_info_free - Free BFD info structure */ -void -pim_bfd_info_free (void **bfd_info) +void pim_bfd_info_free(void **bfd_info) { - bfd_info_free ((struct bfd_info **) bfd_info); + bfd_info_free((struct bfd_info **)bfd_info); } -static void -pim_bfd_reg_dereg_nbr (struct pim_neighbor *nbr, int command) +static void pim_bfd_reg_dereg_nbr(struct pim_neighbor *nbr, int command) { - struct pim_interface *pim_ifp = NULL; - struct bfd_info *bfd_info = NULL; - struct zclient *zclient = NULL; - - zclient = pim_zebra_zclient_get (); - - if (!nbr) - return; - pim_ifp = nbr->interface->info; - bfd_info = (struct bfd_info *) pim_ifp->bfd_info; - if (!bfd_info) - return; - if (PIM_DEBUG_PIM_TRACE) - { - char str[INET_ADDRSTRLEN]; - pim_inet4_dump ("<bfd_nbr?>", nbr->source_addr, str, sizeof (str)); - zlog_debug ("%s Nbr %s %s with BFD", __PRETTY_FUNCTION__, str, - bfd_get_command_dbg_str (command)); - } - bfd_peer_sendmsg (zclient, bfd_info, AF_INET, - &nbr->source_addr, NULL, nbr->interface->name, - 0, 0, command, 0, VRF_DEFAULT); + struct pim_interface *pim_ifp = NULL; + struct bfd_info *bfd_info = NULL; + struct zclient *zclient = NULL; + + zclient = pim_zebra_zclient_get(); + + if (!nbr) + return; + pim_ifp = nbr->interface->info; + bfd_info = (struct bfd_info *)pim_ifp->bfd_info; + if (!bfd_info) + return; + if (PIM_DEBUG_PIM_TRACE) { + char str[INET_ADDRSTRLEN]; + pim_inet4_dump("<bfd_nbr?>", nbr->source_addr, str, + sizeof(str)); + zlog_debug("%s Nbr %s %s with BFD", __PRETTY_FUNCTION__, str, + bfd_get_command_dbg_str(command)); + } + bfd_peer_sendmsg(zclient, bfd_info, AF_INET, &nbr->source_addr, NULL, + nbr->interface->name, 0, 0, command, 0, VRF_DEFAULT); } /* @@ -141,75 +134,68 @@ pim_bfd_reg_dereg_nbr (struct pim_neighbor *nbr, int command) * zebra for starting/stopping the monitoring of * the neighbor rechahability. */ -int -pim_bfd_reg_dereg_all_nbr (struct interface *ifp, int command) +int pim_bfd_reg_dereg_all_nbr(struct interface *ifp, int command) { - struct pim_interface *pim_ifp = NULL; - struct listnode *node = NULL; - struct pim_neighbor *neigh = NULL; - - pim_ifp = ifp->info; - if (!pim_ifp) - return -1; - if (!pim_ifp->bfd_info) - return -1; - - for (ALL_LIST_ELEMENTS_RO (pim_ifp->pim_neighbor_list, node, neigh)) - { - if (command != ZEBRA_BFD_DEST_DEREGISTER) - pim_bfd_info_nbr_create (pim_ifp, neigh); - else - bfd_info_free ((struct bfd_info **) &neigh->bfd_info); - - pim_bfd_reg_dereg_nbr (neigh, command); - } - - return 0; + struct pim_interface *pim_ifp = NULL; + struct listnode *node = NULL; + struct pim_neighbor *neigh = NULL; + + pim_ifp = ifp->info; + if (!pim_ifp) + return -1; + if (!pim_ifp->bfd_info) + return -1; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { + if (command != ZEBRA_BFD_DEST_DEREGISTER) + pim_bfd_info_nbr_create(pim_ifp, neigh); + else + bfd_info_free((struct bfd_info **)&neigh->bfd_info); + + pim_bfd_reg_dereg_nbr(neigh, command); + } + + return 0; } /* * pim_bfd_trigger_event - Neighbor is registered/deregistered with BFD when * neighbor state is changed to/from 2way. */ -void -pim_bfd_trigger_event (struct pim_interface *pim_ifp, struct pim_neighbor *nbr, uint8_t nbr_up) +void pim_bfd_trigger_event(struct pim_interface *pim_ifp, + struct pim_neighbor *nbr, uint8_t nbr_up) { - if (nbr_up) - { - pim_bfd_info_nbr_create (pim_ifp, nbr); - pim_bfd_reg_dereg_nbr (nbr, ZEBRA_BFD_DEST_REGISTER); - } - else - { - pim_bfd_info_free ((void *)&nbr->bfd_info); - pim_bfd_reg_dereg_nbr (nbr, ZEBRA_BFD_DEST_DEREGISTER); - } + if (nbr_up) { + pim_bfd_info_nbr_create(pim_ifp, nbr); + pim_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_REGISTER); + } else { + pim_bfd_info_free((void *)&nbr->bfd_info); + pim_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_DEREGISTER); + } } /* * pim_bfd_if_param_set - Set the configured BFD paramter values for * interface. */ -void -pim_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx, - u_int32_t min_tx, u_int8_t detect_mult, int defaults) +void pim_bfd_if_param_set(struct interface *ifp, u_int32_t min_rx, + u_int32_t min_tx, u_int8_t detect_mult, int defaults) { - struct pim_interface *pim_ifp = ifp->info; - int command = 0; - - if (!pim_ifp) - return; - bfd_set_param ((struct bfd_info **) &(pim_ifp->bfd_info), min_rx, min_tx, - detect_mult, defaults, &command); - - if (pim_ifp->bfd_info) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: interface %s has bfd_info", __PRETTY_FUNCTION__, - ifp->name); - } - if (command) - pim_bfd_reg_dereg_all_nbr (ifp, command); + struct pim_interface *pim_ifp = ifp->info; + int command = 0; + + if (!pim_ifp) + return; + bfd_set_param((struct bfd_info **)&(pim_ifp->bfd_info), min_rx, min_tx, + detect_mult, defaults, &command); + + if (pim_ifp->bfd_info) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: interface %s has bfd_info", + __PRETTY_FUNCTION__, ifp->name); + } + if (command) + pim_bfd_reg_dereg_all_nbr(ifp, command); } @@ -219,145 +205,133 @@ pim_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx, * connectivity if the BFD status changed to * down. */ -static int -pim_bfd_interface_dest_update (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int pim_bfd_interface_dest_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp = NULL; - struct pim_interface *pim_ifp = NULL; - struct prefix p; - int status; - char msg[100]; - int old_status; - struct bfd_info *bfd_info = NULL; - struct timeval tv; - struct listnode *neigh_node = NULL; - struct listnode *neigh_nextnode = NULL; - struct pim_neighbor *neigh = NULL; - - ifp = bfd_get_peer_info (zclient->ibuf, &p, NULL, &status, vrf_id); - - if ((ifp == NULL) || (p.family != AF_INET)) - return 0; - - pim_ifp = ifp->info; - if (!pim_ifp) - return 0; - - if (!pim_ifp->bfd_info) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: pim interface %s BFD is disabled ", __PRETTY_FUNCTION__, - ifp->name); - return 0; - } - - if (PIM_DEBUG_PIM_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&p, buf, sizeof (buf)); - zlog_debug ("%s: interface %s bfd destination %s %s", - __PRETTY_FUNCTION__, ifp->name, buf, - bfd_get_status_str (status)); - } - - for (ALL_LIST_ELEMENTS (pim_ifp->pim_neighbor_list, neigh_node, - neigh_nextnode, neigh)) - { - /* Check neigh address matches with BFD address */ - if (neigh->source_addr.s_addr != p.u.prefix4.s_addr) - continue; - - bfd_info = (struct bfd_info *) neigh->bfd_info; - if (bfd_info->status == status) - { - if (PIM_DEBUG_PIM_TRACE) - { - char str[INET_ADDRSTRLEN]; - pim_inet4_dump ("<nht_nbr?>", neigh->source_addr, str, - sizeof (str)); - zlog_debug ("%s: bfd status is same for nbr %s", - __PRETTY_FUNCTION__, str); - } - continue; - } - old_status = bfd_info->status; - bfd_info->status = status; - monotime(&tv); - bfd_info->last_update = tv.tv_sec; - - if (PIM_DEBUG_PIM_TRACE) - { - zlog_debug ("%s: status %s old_status %s", __PRETTY_FUNCTION__, - bfd_get_status_str (status), - bfd_get_status_str (old_status)); - } - if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) - { - snprintf (msg, sizeof (msg), "BFD Session Expired"); - pim_neighbor_delete (ifp, neigh, msg); - } - } - return 0; + struct interface *ifp = NULL; + struct pim_interface *pim_ifp = NULL; + struct prefix p; + int status; + char msg[100]; + int old_status; + struct bfd_info *bfd_info = NULL; + struct timeval tv; + struct listnode *neigh_node = NULL; + struct listnode *neigh_nextnode = NULL; + struct pim_neighbor *neigh = NULL; + + ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status, vrf_id); + + if ((ifp == NULL) || (p.family != AF_INET)) + return 0; + + pim_ifp = ifp->info; + if (!pim_ifp) + return 0; + + if (!pim_ifp->bfd_info) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: pim interface %s BFD is disabled ", + __PRETTY_FUNCTION__, ifp->name); + return 0; + } + + if (PIM_DEBUG_PIM_TRACE) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&p, buf, sizeof(buf)); + zlog_debug("%s: interface %s bfd destination %s %s", + __PRETTY_FUNCTION__, ifp->name, buf, + bfd_get_status_str(status)); + } + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node, + neigh_nextnode, neigh)) { + /* Check neigh address matches with BFD address */ + if (neigh->source_addr.s_addr != p.u.prefix4.s_addr) + continue; + + bfd_info = (struct bfd_info *)neigh->bfd_info; + if (bfd_info->status == status) { + if (PIM_DEBUG_PIM_TRACE) { + char str[INET_ADDRSTRLEN]; + pim_inet4_dump("<nht_nbr?>", neigh->source_addr, + str, sizeof(str)); + zlog_debug("%s: bfd status is same for nbr %s", + __PRETTY_FUNCTION__, str); + } + continue; + } + old_status = bfd_info->status; + bfd_info->status = status; + monotime(&tv); + bfd_info->last_update = tv.tv_sec; + + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: status %s old_status %s", + __PRETTY_FUNCTION__, + bfd_get_status_str(status), + bfd_get_status_str(old_status)); + } + if ((status == BFD_STATUS_DOWN) + && (old_status == BFD_STATUS_UP)) { + snprintf(msg, sizeof(msg), "BFD Session Expired"); + pim_neighbor_delete(ifp, neigh, msg); + } + } + return 0; } /* * pim_bfd_nbr_replay - Replay all the neighbors that have BFD enabled * to zebra */ -static int -pim_bfd_nbr_replay (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int pim_bfd_nbr_replay(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp = NULL; - struct pim_interface *pim_ifp = NULL; - struct pim_neighbor *neigh = NULL; - struct listnode *node; - struct listnode *neigh_node; - struct listnode *neigh_nextnode; - - /* Send the client registration */ - bfd_client_sendmsg (zclient, ZEBRA_BFD_CLIENT_REGISTER); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - for (ALL_LIST_ELEMENTS (pim_ifp->pim_neighbor_list, neigh_node, - neigh_nextnode, neigh)) - { - if (!neigh->bfd_info) - continue; - if (PIM_DEBUG_PIM_TRACE) - { - char str[INET_ADDRSTRLEN]; - pim_inet4_dump ("<bfd_nbr?>", neigh->source_addr, str, - sizeof (str)); - zlog_debug ("%s: Replaying Pim Neigh %s to BFD", - __PRETTY_FUNCTION__, str); - } - pim_bfd_reg_dereg_nbr (neigh, ZEBRA_BFD_DEST_UPDATE); - - } - } - return 0; + struct interface *ifp = NULL; + struct pim_interface *pim_ifp = NULL; + struct pim_neighbor *neigh = NULL; + struct listnode *node; + struct listnode *neigh_node; + struct listnode *neigh_nextnode; + + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node, + neigh_nextnode, neigh)) { + if (!neigh->bfd_info) + continue; + if (PIM_DEBUG_PIM_TRACE) { + char str[INET_ADDRSTRLEN]; + pim_inet4_dump("<bfd_nbr?>", neigh->source_addr, + str, sizeof(str)); + zlog_debug("%s: Replaying Pim Neigh %s to BFD", + __PRETTY_FUNCTION__, str); + } + pim_bfd_reg_dereg_nbr(neigh, ZEBRA_BFD_DEST_UPDATE); + } + } + return 0; } -void -pim_bfd_init (void) +void pim_bfd_init(void) { - struct zclient *zclient = NULL; + struct zclient *zclient = NULL; - zclient = pim_zebra_zclient_get (); + zclient = pim_zebra_zclient_get(); - bfd_gbl_init (); + bfd_gbl_init(); - zclient->interface_bfd_dest_update = pim_bfd_interface_dest_update; - zclient->bfd_dest_replay = pim_bfd_nbr_replay; + zclient->interface_bfd_dest_update = pim_bfd_interface_dest_update; + zclient->bfd_dest_replay = pim_bfd_nbr_replay; } diff --git a/pimd/pim_bfd.h b/pimd/pim_bfd.h index 23f286b86..316d3c1e2 100644 --- a/pimd/pim_bfd.h +++ b/pimd/pim_bfd.h @@ -25,18 +25,16 @@ #include "if.h" -void pim_bfd_init (void); -void pim_bfd_write_config (struct vty *vty, struct interface *ifp); -void -pim_bfd_show_info (struct vty *vty, void *bfd_info, json_object * json_obj, - u_char use_json, int param_only); -void -pim_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx, - u_int32_t min_tx, u_int8_t detect_mult, int defaults); -int pim_bfd_reg_dereg_all_nbr (struct interface *ifp, int command); -void -pim_bfd_trigger_event (struct pim_interface *pim_ifp, struct pim_neighbor *nbr, uint8_t nbr_up); -void -pim_bfd_info_nbr_create (struct pim_interface *pim_ifp, struct pim_neighbor *neigh); +void pim_bfd_init(void); +void pim_bfd_write_config(struct vty *vty, struct interface *ifp); +void pim_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, + u_char use_json, int param_only); +void pim_bfd_if_param_set(struct interface *ifp, u_int32_t min_rx, + u_int32_t min_tx, u_int8_t detect_mult, int defaults); +int pim_bfd_reg_dereg_all_nbr(struct interface *ifp, int command); +void pim_bfd_trigger_event(struct pim_interface *pim_ifp, + struct pim_neighbor *nbr, uint8_t nbr_up); +void pim_bfd_info_nbr_create(struct pim_interface *pim_ifp, + struct pim_neighbor *neigh); void pim_bfd_info_free(void **bfd_info); #endif /* _PIM_BFD_H */ diff --git a/pimd/pim_br.c b/pimd/pim_br.c index 19a0293c4..f297b0591 100644 --- a/pimd/pim_br.c +++ b/pimd/pim_br.c @@ -29,83 +29,80 @@ #include "linklist.h" struct pim_br { - struct prefix_sg sg; - struct in_addr pmbr; + struct prefix_sg sg; + struct in_addr pmbr; }; -struct in_addr pim_br_unknown = { .s_addr = 0 }; +struct in_addr pim_br_unknown = {.s_addr = 0}; static struct list *pim_br_list = NULL; -struct in_addr -pim_br_get_pmbr (struct prefix_sg *sg) +struct in_addr pim_br_get_pmbr(struct prefix_sg *sg) { - struct listnode *node; - struct pim_br *pim_br; + struct listnode *node; + struct pim_br *pim_br; - for (ALL_LIST_ELEMENTS_RO (pim_br_list, node, pim_br)) { - if (sg->src.s_addr == pim_br->sg.src.s_addr && - sg->grp.s_addr == pim_br->sg.grp.s_addr) - return pim_br->pmbr; - } + for (ALL_LIST_ELEMENTS_RO(pim_br_list, node, pim_br)) { + if (sg->src.s_addr == pim_br->sg.src.s_addr + && sg->grp.s_addr == pim_br->sg.grp.s_addr) + return pim_br->pmbr; + } - return pim_br_unknown; + return pim_br_unknown; } -void -pim_br_set_pmbr (struct prefix_sg *sg, struct in_addr br) +void pim_br_set_pmbr(struct prefix_sg *sg, struct in_addr br) { - struct listnode *node, *next; - struct pim_br *pim_br; + struct listnode *node, *next; + struct pim_br *pim_br; - for (ALL_LIST_ELEMENTS (pim_br_list, node, next, pim_br)) { - if (sg->src.s_addr == pim_br->sg.src.s_addr && - sg->grp.s_addr == pim_br->sg.grp.s_addr) - break; - } + for (ALL_LIST_ELEMENTS(pim_br_list, node, next, pim_br)) { + if (sg->src.s_addr == pim_br->sg.src.s_addr + && sg->grp.s_addr == pim_br->sg.grp.s_addr) + break; + } - if (!pim_br) { - pim_br = XCALLOC(MTYPE_PIM_BR, sizeof (*pim_br)); - if (!pim_br) { - zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_br)); - return; - } + if (!pim_br) { + pim_br = XCALLOC(MTYPE_PIM_BR, sizeof(*pim_br)); + if (!pim_br) { + zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_br)); + return; + } - pim_br->sg = *sg; + pim_br->sg = *sg; - listnode_add(pim_br_list, pim_br); - } + listnode_add(pim_br_list, pim_br); + } - pim_br->pmbr = br; + pim_br->pmbr = br; } /* * Remove the (S,G) from the stored values */ -void -pim_br_clear_pmbr (struct prefix_sg *sg) +void pim_br_clear_pmbr(struct prefix_sg *sg) { - struct listnode *node, *next; - struct pim_br *pim_br; + struct listnode *node, *next; + struct pim_br *pim_br; - for (ALL_LIST_ELEMENTS (pim_br_list, node, next, pim_br)) { - if (sg->src.s_addr == pim_br->sg.src.s_addr && - sg->grp.s_addr == pim_br->sg.grp.s_addr) - break; - } + for (ALL_LIST_ELEMENTS(pim_br_list, node, next, pim_br)) { + if (sg->src.s_addr == pim_br->sg.src.s_addr + && sg->grp.s_addr == pim_br->sg.grp.s_addr) + break; + } - if (!pim_br) - return; + if (!pim_br) + return; - listnode_delete (pim_br_list, pim_br); + listnode_delete(pim_br_list, pim_br); } -void pim_br_init (void) +void pim_br_init(void) { - pim_br_list = list_new(); - if (!pim_br_list) { - zlog_err("%s: Failure to create pim_br_list", - __PRETTY_FUNCTION__); - return; - } + pim_br_list = list_new(); + if (!pim_br_list) { + zlog_err("%s: Failure to create pim_br_list", + __PRETTY_FUNCTION__); + return; + } } diff --git a/pimd/pim_br.h b/pimd/pim_br.h index 345dd011e..836ff5ee8 100644 --- a/pimd/pim_br.h +++ b/pimd/pim_br.h @@ -20,12 +20,12 @@ #ifndef PIM_BR_H #define PIM_BR_H -struct in_addr pim_br_get_pmbr (struct prefix_sg *sg); +struct in_addr pim_br_get_pmbr(struct prefix_sg *sg); -void pim_br_set_pmbr (struct prefix_sg *sg, struct in_addr value); -void pim_br_clear_pmbr (struct prefix_sg *sg); +void pim_br_set_pmbr(struct prefix_sg *sg, struct in_addr value); +void pim_br_clear_pmbr(struct prefix_sg *sg); -void pim_br_init (void); +void pim_br_init(void); extern struct in_addr pim_br_unknown; diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 88c43104c..1c9fe40c2 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -61,37 +61,28 @@ #include "bfd.h" static struct cmd_node pim_global_node = { - PIM_NODE, - "", - 1 /* vtysh ? yes */ + PIM_NODE, "", 1 /* vtysh ? yes */ }; static struct cmd_node interface_node = { - INTERFACE_NODE, - "%s(config-if)# ", - 1 /* vtysh ? yes */ + INTERFACE_NODE, "%s(config-if)# ", 1 /* vtysh ? yes */ }; -static struct cmd_node debug_node = -{ - DEBUG_NODE, - "", - 1 -}; +static struct cmd_node debug_node = {DEBUG_NODE, "", 1}; static void pim_if_membership_clear(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - if (PIM_IF_TEST_PIM(pim_ifp->options) && - PIM_IF_TEST_IGMP(pim_ifp->options)) { - return; - } + if (PIM_IF_TEST_PIM(pim_ifp->options) + && PIM_IF_TEST_IGMP(pim_ifp->options)) { + return; + } - pim_ifchannel_membership_clear(ifp); + pim_ifchannel_membership_clear(ifp); } /* @@ -105,2492 +96,2953 @@ static void pim_if_membership_clear(struct interface *ifp) */ static void pim_if_membership_refresh(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *sock_node; - struct igmp_sock *igmp; + struct pim_interface *pim_ifp; + struct listnode *sock_node; + struct igmp_sock *igmp; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - if (!PIM_IF_TEST_PIM(pim_ifp->options)) - return; - if (!PIM_IF_TEST_IGMP(pim_ifp->options)) - return; + if (!PIM_IF_TEST_PIM(pim_ifp->options)) + return; + if (!PIM_IF_TEST_IGMP(pim_ifp->options)) + return; - /* - First clear off membership from all PIM (S,G) entries on the - interface - */ + /* + First clear off membership from all PIM (S,G) entries on the + interface + */ - pim_ifchannel_membership_clear(ifp); + pim_ifchannel_membership_clear(ifp); - /* - Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on - the interface - */ + /* + Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on + the interface + */ - /* scan igmp sockets */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - struct listnode *grpnode; - struct igmp_group *grp; - - /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { - struct listnode *srcnode; - struct igmp_source *src; - - /* scan group sources */ - for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) { + /* scan igmp sockets */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { + struct listnode *grpnode; + struct igmp_group *grp; - if (IGMP_SOURCE_TEST_FORWARDING(src->source_flags)) { - struct prefix_sg sg; + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, + grp)) { + struct listnode *srcnode; + struct igmp_source *src; - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = src->source_addr; - sg.grp = grp->group_addr; - pim_ifchannel_local_membership_add(ifp, &sg); - } - - } /* scan group sources */ - } /* scan igmp groups */ - } /* scan igmp sockets */ + /* scan group sources */ + for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, + srcnode, src)) { + + if (IGMP_SOURCE_TEST_FORWARDING( + src->source_flags)) { + struct prefix_sg sg; + + memset(&sg, 0, + sizeof(struct prefix_sg)); + sg.src = src->source_addr; + sg.grp = grp->group_addr; + pim_ifchannel_local_membership_add(ifp, + &sg); + } - /* - Finally delete every PIM (S,G) entry lacking all state info - */ + } /* scan group sources */ + } /* scan igmp groups */ + } /* scan igmp sockets */ - pim_ifchannel_delete_on_noinfo(ifp); + /* + Finally delete every PIM (S,G) entry lacking all state info + */ + pim_ifchannel_delete_on_noinfo(ifp); } static void pim_show_assert(struct vty *vty) { - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - struct listnode *ch_node; - struct in_addr ifaddr; - time_t now; - - now = pim_time_monotonic_sec(); - - vty_out (vty, - "Interface Address Source Group State Winner Uptime Timer\n"); - - for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - char winner_str[INET_ADDRSTRLEN]; - char uptime[10]; - char timer[10]; - - pim_ifp = ch->interface->info; - - if (!pim_ifp) - continue; - - ifaddr = pim_ifp->primary_address; - - pim_inet4_dump("<ch_src?>", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("<ch_grp?>", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - pim_inet4_dump("<assrt_win?>", ch->ifassert_winner, - winner_str, sizeof(winner_str)); - - pim_time_uptime(uptime, sizeof(uptime), now - ch->ifassert_creation); - pim_time_timer_to_mmss(timer, sizeof(timer), - ch->t_ifassert_timer); - - vty_out (vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n", - ch->interface->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - pim_ifchannel_ifassert_name(ch->ifassert_state), - winner_str, - uptime, - timer); - } /* scan interface channels */ + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + struct listnode *ch_node; + struct in_addr ifaddr; + time_t now; + + now = pim_time_monotonic_sec(); + + vty_out(vty, + "Interface Address Source Group State Winner Uptime Timer\n"); + + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char winner_str[INET_ADDRSTRLEN]; + char uptime[10]; + char timer[10]; + + pim_ifp = ch->interface->info; + + if (!pim_ifp) + continue; + + ifaddr = pim_ifp->primary_address; + + pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, + sizeof(ch_src_str)); + pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, + sizeof(ch_grp_str)); + pim_inet4_dump("<assrt_win?>", ch->ifassert_winner, winner_str, + sizeof(winner_str)); + + pim_time_uptime(uptime, sizeof(uptime), + now - ch->ifassert_creation); + pim_time_timer_to_mmss(timer, sizeof(timer), + ch->t_ifassert_timer); + + vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n", + ch->interface->name, inet_ntoa(ifaddr), ch_src_str, + ch_grp_str, + pim_ifchannel_ifassert_name(ch->ifassert_state), + winner_str, uptime, timer); + } /* scan interface channels */ } static void pim_show_assert_internal(struct vty *vty) { - struct pim_interface *pim_ifp; - struct listnode *ch_node; - struct pim_ifchannel *ch; - struct in_addr ifaddr; - - vty_out (vty, - "CA: CouldAssert\n" - "ECA: Evaluate CouldAssert\n" - "ATD: AssertTrackingDesired\n" - "eATD: Evaluate AssertTrackingDesired\n\n"); - - vty_out (vty, - "Interface Address Source Group CA eCA ATD eATD\n"); - - for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - pim_ifp = ch->interface->info; - - if (!pim_ifp) - continue; - - ifaddr = pim_ifp->primary_address; - - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("<ch_src?>", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("<ch_grp?>", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - vty_out (vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n", - ch->interface->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no", - pim_macro_ch_could_assert_eval(ch) ? "yes" : "no", - PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags) ? "yes" : "no", - pim_macro_assert_tracking_desired_eval(ch) ? "yes" : "no"); - } /* scan interface channels */ + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; + struct in_addr ifaddr; + + vty_out(vty, + "CA: CouldAssert\n" + "ECA: Evaluate CouldAssert\n" + "ATD: AssertTrackingDesired\n" + "eATD: Evaluate AssertTrackingDesired\n\n"); + + vty_out(vty, + "Interface Address Source Group CA eCA ATD eATD\n"); + + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + pim_ifp = ch->interface->info; + + if (!pim_ifp) + continue; + + ifaddr = pim_ifp->primary_address; + + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, + sizeof(ch_src_str)); + pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, + sizeof(ch_grp_str)); + vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n", + ch->interface->name, inet_ntoa(ifaddr), ch_src_str, + ch_grp_str, + PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no", + pim_macro_ch_could_assert_eval(ch) ? "yes" : "no", + PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags) + ? "yes" + : "no", + pim_macro_assert_tracking_desired_eval(ch) ? "yes" + : "no"); + } /* scan interface channels */ } static void pim_show_assert_metric(struct vty *vty) { - struct pim_interface *pim_ifp; - struct listnode *ch_node; - struct pim_ifchannel *ch; - struct in_addr ifaddr; + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; + struct in_addr ifaddr; - vty_out (vty, - "Interface Address Source Group RPT Pref Metric Address \n"); + vty_out(vty, + "Interface Address Source Group RPT Pref Metric Address \n"); - for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - pim_ifp = ch->interface->info; + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + pim_ifp = ch->interface->info; - if (!pim_ifp) - continue; + if (!pim_ifp) + continue; - ifaddr = pim_ifp->primary_address; + ifaddr = pim_ifp->primary_address; - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - char addr_str[INET_ADDRSTRLEN]; - struct pim_assert_metric am; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char addr_str[INET_ADDRSTRLEN]; + struct pim_assert_metric am; - am = pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address); + am = pim_macro_spt_assert_metric(&ch->upstream->rpf, + pim_ifp->primary_address); - pim_inet4_dump("<ch_src?>", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("<ch_grp?>", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - pim_inet4_dump("<addr?>", am.ip_address, - addr_str, sizeof(addr_str)); + pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, + sizeof(ch_src_str)); + pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, + sizeof(ch_grp_str)); + pim_inet4_dump("<addr?>", am.ip_address, addr_str, + sizeof(addr_str)); - vty_out (vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s\n", - ch->interface->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - am.rpt_bit_flag ? "yes" : "no", - am.metric_preference, - am.route_metric, - addr_str); - } /* scan interface channels */ + vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s\n", + ch->interface->name, inet_ntoa(ifaddr), ch_src_str, + ch_grp_str, am.rpt_bit_flag ? "yes" : "no", + am.metric_preference, am.route_metric, addr_str); + } /* scan interface channels */ } static void pim_show_assert_winner_metric(struct vty *vty) { - struct pim_interface *pim_ifp; - struct listnode *ch_node; - struct pim_ifchannel *ch; - struct in_addr ifaddr; - - vty_out (vty, - "Interface Address Source Group RPT Pref Metric Address \n"); + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; + struct in_addr ifaddr; + + vty_out(vty, + "Interface Address Source Group RPT Pref Metric Address \n"); + + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + pim_ifp = ch->interface->info; - for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - pim_ifp = ch->interface->info; - - if (!pim_ifp) - continue; + if (!pim_ifp) + continue; - ifaddr = pim_ifp->primary_address; + ifaddr = pim_ifp->primary_address; - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - char addr_str[INET_ADDRSTRLEN]; - struct pim_assert_metric *am; - char pref_str[5]; - char metr_str[7]; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char addr_str[INET_ADDRSTRLEN]; + struct pim_assert_metric *am; + char pref_str[5]; + char metr_str[7]; - am = &ch->ifassert_winner_metric; + am = &ch->ifassert_winner_metric; - pim_inet4_dump("<ch_src?>", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("<ch_grp?>", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - pim_inet4_dump("<addr?>", am->ip_address, - addr_str, sizeof(addr_str)); + pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, + sizeof(ch_src_str)); + pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, + sizeof(ch_grp_str)); + pim_inet4_dump("<addr?>", am->ip_address, addr_str, + sizeof(addr_str)); - if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX) - snprintf(pref_str, sizeof(pref_str), "INFI"); - else - snprintf(pref_str, sizeof(pref_str), "%4u", am->metric_preference); + if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX) + snprintf(pref_str, sizeof(pref_str), "INFI"); + else + snprintf(pref_str, sizeof(pref_str), "%4u", + am->metric_preference); - if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX) - snprintf(metr_str, sizeof(metr_str), "INFI"); - else - snprintf(metr_str, sizeof(metr_str), "%6u", am->route_metric); + if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX) + snprintf(metr_str, sizeof(metr_str), "INFI"); + else + snprintf(metr_str, sizeof(metr_str), "%6u", + am->route_metric); - vty_out (vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n", - ch->interface->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - am->rpt_bit_flag ? "yes" : "no", - pref_str, - metr_str, - addr_str); - } /* scan interface channels */ + vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n", + ch->interface->name, inet_ntoa(ifaddr), ch_src_str, + ch_grp_str, am->rpt_bit_flag ? "yes" : "no", pref_str, + metr_str, addr_str); + } /* scan interface channels */ } -static void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp) +static void json_object_pim_ifp_add(struct json_object *json, + struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - json_object_string_add(json, "name", ifp->name); - json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down"); - json_object_string_add(json, "address", inet_ntoa(pim_ifp->primary_address)); - json_object_int_add(json, "index", ifp->ifindex); + pim_ifp = ifp->info; + json_object_string_add(json, "name", ifp->name); + json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down"); + json_object_string_add(json, "address", + inet_ntoa(pim_ifp->primary_address)); + json_object_int_add(json, "index", ifp->ifindex); - if (if_is_multicast(ifp)) - json_object_boolean_true_add(json, "flagMulticast"); + if (if_is_multicast(ifp)) + json_object_boolean_true_add(json, "flagMulticast"); - if (if_is_broadcast(ifp)) - json_object_boolean_true_add(json, "flagBroadcast"); + if (if_is_broadcast(ifp)) + json_object_boolean_true_add(json, "flagBroadcast"); - if (ifp->flags & IFF_ALLMULTI) - json_object_boolean_true_add(json, "flagAllMulticast"); + if (ifp->flags & IFF_ALLMULTI) + json_object_boolean_true_add(json, "flagAllMulticast"); - if (ifp->flags & IFF_PROMISC) - json_object_boolean_true_add(json, "flagPromiscuous"); + if (ifp->flags & IFF_PROMISC) + json_object_boolean_true_add(json, "flagPromiscuous"); - if (PIM_IF_IS_DELETED(ifp)) - json_object_boolean_true_add(json, "flagDeleted"); + if (PIM_IF_IS_DELETED(ifp)) + json_object_boolean_true_add(json, "flagDeleted"); - if (pim_if_lan_delay_enabled(ifp)) - json_object_boolean_true_add(json, "lanDelayEnabled"); + if (pim_if_lan_delay_enabled(ifp)) + json_object_boolean_true_add(json, "lanDelayEnabled"); } static void pim_show_membership(struct vty *vty, u_char uj) { - struct pim_interface *pim_ifp; - struct listnode *ch_node; - struct pim_ifchannel *ch; - enum json_type type; - json_object *json = NULL; - json_object *json_iface = NULL; - json_object *json_row = NULL; - json_object *json_tmp = NULL; - - json = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - - pim_ifp = ch->interface->info; - - if (!pim_ifp) - continue; - - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("<ch_src?>", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("<ch_grp?>", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - - json_object_object_get_ex(json, ch->interface->name, &json_iface); - - if (!json_iface) { - json_iface = json_object_new_object(); - json_object_pim_ifp_add(json_iface, ch->interface); - json_object_object_add(json, ch->interface->name, json_iface); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", ch_src_str); - json_object_string_add(json_row, "group", ch_grp_str); - json_object_string_add(json_row, "localMembership", - ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ? "NOINFO" : "INCLUDE"); - json_object_object_add(json_iface, ch_grp_str, json_row); - } /* scan interface channels */ - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - } else { - vty_out (vty, - "Interface Address Source Group Membership\n"); - - /* - * Example of the json data we are traversing - * - * { - * "swp3":{ - * "name":"swp3", - * "state":"up", - * "address":"10.1.20.1", - * "index":5, - * "flagMulticast":true, - * "flagBroadcast":true, - * "lanDelayEnabled":true, - * "226.10.10.10":{ - * "source":"*", - * "group":"226.10.10.10", - * "localMembership":"INCLUDE" - * } - * } - * } - */ - - /* foreach interface */ - json_object_object_foreach(json, key, val) { - - /* Find all of the keys where the val is an object. In the example - * above the only one is 226.10.10.10 - */ - json_object_object_foreach(val, if_field_key, if_field_val) { - type = json_object_get_type(if_field_val); - - if (type == json_type_object) { - vty_out(vty, "%-9s ", key); - - json_object_object_get_ex(val, "address", &json_tmp); - vty_out(vty, "%-15s ", json_object_get_string(json_tmp)); - - json_object_object_get_ex(if_field_val, "source", &json_tmp); - vty_out(vty, "%-15s ", json_object_get_string(json_tmp)); - - /* Group */ - vty_out(vty, "%-15s ", if_field_key); - - json_object_object_get_ex(if_field_val, "localMembership", &json_tmp); - vty_out (vty, "%-10s\n", json_object_get_string(json_tmp)); - } - } - } - } - - json_object_free(json); -} - -static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp, int mloop) -{ - vty_out (vty, "Flags\n"); - vty_out (vty, "-----\n"); - vty_out (vty, "All Multicast : %s\n", - (ifp->flags & IFF_ALLMULTI) ? "yes" : "no"); - vty_out (vty, "Broadcast : %s\n", - if_is_broadcast(ifp) ? "yes" : "no"); - vty_out (vty, "Deleted : %s\n", - PIM_IF_IS_DELETED(ifp) ? "yes" : "no"); - vty_out (vty, "Interface Index : %d\n", ifp->ifindex); - vty_out (vty, "Multicast : %s\n", - if_is_multicast(ifp) ? "yes" : "no"); - vty_out (vty, "Multicast Loop : %d\n", mloop); - vty_out (vty, "Promiscuous : %s\n", - (ifp->flags & IFF_PROMISC) ? "yes" : "no"); - vty_out (vty, "\n"); - vty_out (vty, "\n"); + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; + enum json_type type; + json_object *json = NULL; + json_object *json_iface = NULL; + json_object *json_row = NULL; + json_object *json_tmp = NULL; + + json = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + + pim_ifp = ch->interface->info; + + if (!pim_ifp) + continue; + + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, + sizeof(ch_src_str)); + pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, + sizeof(ch_grp_str)); + + json_object_object_get_ex(json, ch->interface->name, + &json_iface); + + if (!json_iface) { + json_iface = json_object_new_object(); + json_object_pim_ifp_add(json_iface, ch->interface); + json_object_object_add(json, ch->interface->name, + json_iface); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", ch_src_str); + json_object_string_add(json_row, "group", ch_grp_str); + json_object_string_add( + json_row, "localMembership", + ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO + ? "NOINFO" + : "INCLUDE"); + json_object_object_add(json_iface, ch_grp_str, json_row); + } /* scan interface channels */ + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + } else { + vty_out(vty, + "Interface Address Source Group Membership\n"); + + /* + * Example of the json data we are traversing + * + * { + * "swp3":{ + * "name":"swp3", + * "state":"up", + * "address":"10.1.20.1", + * "index":5, + * "flagMulticast":true, + * "flagBroadcast":true, + * "lanDelayEnabled":true, + * "226.10.10.10":{ + * "source":"*", + * "group":"226.10.10.10", + * "localMembership":"INCLUDE" + * } + * } + * } + */ + + /* foreach interface */ + json_object_object_foreach(json, key, val) + { + + /* Find all of the keys where the val is an object. In + * the example + * above the only one is 226.10.10.10 + */ + json_object_object_foreach(val, if_field_key, + if_field_val) + { + type = json_object_get_type(if_field_val); + + if (type == json_type_object) { + vty_out(vty, "%-9s ", key); + + json_object_object_get_ex( + val, "address", &json_tmp); + vty_out(vty, "%-15s ", + json_object_get_string( + json_tmp)); + + json_object_object_get_ex(if_field_val, + "source", + &json_tmp); + vty_out(vty, "%-15s ", + json_object_get_string( + json_tmp)); + + /* Group */ + vty_out(vty, "%-15s ", if_field_key); + + json_object_object_get_ex( + if_field_val, "localMembership", + &json_tmp); + vty_out(vty, "%-10s\n", + json_object_get_string( + json_tmp)); + } + } + } + } + + json_object_free(json); +} + +static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp, + int mloop) +{ + vty_out(vty, "Flags\n"); + vty_out(vty, "-----\n"); + vty_out(vty, "All Multicast : %s\n", + (ifp->flags & IFF_ALLMULTI) ? "yes" : "no"); + vty_out(vty, "Broadcast : %s\n", + if_is_broadcast(ifp) ? "yes" : "no"); + vty_out(vty, "Deleted : %s\n", + PIM_IF_IS_DELETED(ifp) ? "yes" : "no"); + vty_out(vty, "Interface Index : %d\n", ifp->ifindex); + vty_out(vty, "Multicast : %s\n", + if_is_multicast(ifp) ? "yes" : "no"); + vty_out(vty, "Multicast Loop : %d\n", mloop); + vty_out(vty, "Promiscuous : %s\n", + (ifp->flags & IFF_PROMISC) ? "yes" : "no"); + vty_out(vty, "\n"); + vty_out(vty, "\n"); } static void igmp_show_interfaces(struct vty *vty, u_char uj) { - struct listnode *node; - struct interface *ifp; - time_t now; - json_object *json = NULL; - json_object *json_row = NULL; - - now = pim_time_monotonic_sec(); - - if (uj) - json = json_object_new_object(); - else - vty_out (vty, - "Interface State Address V Querier Query Timer Uptime\n"); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp; - struct listnode *sock_node; - struct igmp_sock *igmp; - - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char uptime[10]; - char query_hhmmss[10]; - - pim_time_uptime(uptime, sizeof(uptime), now - igmp->sock_creation); - pim_time_timer_to_hhmmss(query_hhmmss, sizeof(query_hhmmss), igmp->t_igmp_query_timer); - - if (uj) { - json_row = json_object_new_object(); - json_object_pim_ifp_add(json_row, ifp); - json_object_string_add(json_row, "upTime", uptime); - json_object_int_add(json_row, "version", pim_ifp->igmp_version); - - if (igmp->t_igmp_query_timer) { - json_object_boolean_true_add(json_row, "querier"); - json_object_string_add(json_row, "queryTimer", query_hhmmss); - } - - json_object_object_add(json, ifp->name, json_row); - - } else { - vty_out (vty, "%-9s %5s %15s %d %7s %11s %8s\n", - ifp->name, - if_is_up(ifp) ? "up" : "down", - inet_ntoa(igmp->ifaddr), - pim_ifp->igmp_version, - igmp->t_igmp_query_timer ? "local" : "other", - query_hhmmss, - uptime); - } - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } -} - -static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, u_char uj) -{ - struct igmp_sock *igmp; - struct interface *ifp; - struct listnode *node; - struct listnode *sock_node; - struct pim_interface *pim_ifp; - char uptime[10]; - char query_hhmmss[10]; - char other_hhmmss[10]; - int found_ifname = 0; - int sqi; - int mloop; - long gmi_msec; /* Group Membership Interval */ - long lmqt_msec; - long ohpi_msec; - long oqpi_msec; /* Other Querier Present Interval */ - long qri_msec; - time_t now; - - json_object *json = NULL; - json_object *json_row = NULL; - - if (uj) - json = json_object_new_object(); - - now = pim_time_monotonic_sec(); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name)) - continue; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - found_ifname = 1; - pim_time_uptime(uptime, sizeof(uptime), now - igmp->sock_creation); - pim_time_timer_to_hhmmss(query_hhmmss, sizeof(query_hhmmss), igmp->t_igmp_query_timer); - pim_time_timer_to_hhmmss(other_hhmmss, sizeof(other_hhmmss), igmp->t_other_querier_timer); - - gmi_msec = PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec); - - sqi = PIM_IGMP_SQI(pim_ifp->igmp_default_query_interval); - - oqpi_msec = PIM_IGMP_OQPI_MSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec); - - lmqt_msec = PIM_IGMP_LMQT_MSEC(pim_ifp->igmp_query_max_response_time_dsec, - igmp->querier_robustness_variable); - - ohpi_msec = PIM_IGMP_OHPI_DSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec) * 100; - - qri_msec = pim_ifp->igmp_query_max_response_time_dsec * 100; - mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); - - if (uj) { - json_row = json_object_new_object(); - json_object_pim_ifp_add(json_row, ifp); - json_object_string_add(json_row, "upTime", uptime); - json_object_string_add(json_row, "querier", igmp->t_igmp_query_timer ? "local" : "other"); - json_object_int_add(json_row, "queryStartCount", igmp->startup_query_count); - json_object_string_add(json_row, "queryQueryTimer", query_hhmmss); - json_object_string_add(json_row, "queryOtherTimer", other_hhmmss); - json_object_int_add(json_row, "version", pim_ifp->igmp_version); - json_object_int_add(json_row, "timerGroupMembershipIntervalMsec", gmi_msec); - json_object_int_add(json_row, "timerLastMemberQueryMsec", lmqt_msec); - json_object_int_add(json_row, "timerOlderHostPresentIntervalMsec", ohpi_msec); - json_object_int_add(json_row, "timerOtherQuerierPresentIntervalMsec", oqpi_msec); - json_object_int_add(json_row, "timerQueryInterval", igmp->querier_query_interval); - json_object_int_add(json_row, "timerQueryResponseIntervalMsec", qri_msec); - json_object_int_add(json_row, "timerRobustnessVariable", igmp->querier_robustness_variable); - json_object_int_add(json_row, "timerStartupQueryInterval", sqi); - - json_object_object_add(json, ifp->name, json_row); - - } else { - vty_out (vty, "Interface : %s\n", ifp->name); - vty_out (vty, "State : %s\n", if_is_up(ifp) ? "up" : "down"); - vty_out (vty, "Address : %s\n", - inet_ntoa(pim_ifp->primary_address)); - vty_out (vty, "Uptime : %s\n", uptime); - vty_out (vty, "Version : %d\n", pim_ifp->igmp_version); - vty_out (vty, "\n"); - vty_out (vty, "\n"); - - vty_out (vty, "Querier\n"); - vty_out (vty, "-------\n"); - vty_out (vty, "Querier : %s\n", - igmp->t_igmp_query_timer ? "local" : "other"); - vty_out (vty, "Start Count : %d\n", igmp->startup_query_count); - vty_out (vty, "Query Timer : %s\n", query_hhmmss); - vty_out (vty, "Other Timer : %s\n", other_hhmmss); - vty_out (vty, "\n"); - vty_out (vty, "\n"); - - vty_out (vty, "Timers\n"); - vty_out (vty, "------\n"); - vty_out (vty, "Group Membership Interval : %lis\n", - gmi_msec / 1000); - vty_out (vty, "Last Member Query Time : %lis\n", - lmqt_msec / 1000); - vty_out (vty, "Older Host Present Interval : %lis\n", - ohpi_msec / 1000); - vty_out (vty, "Other Querier Present Interval : %lis\n", - oqpi_msec / 1000); - vty_out (vty, "Query Interval : %ds\n", - igmp->querier_query_interval); - vty_out (vty, "Query Response Interval : %lis\n", - qri_msec / 1000); - vty_out (vty, "Robustness Variable : %d\n", - igmp->querier_robustness_variable); - vty_out (vty, "Startup Query Interval : %ds\n", sqi); - vty_out (vty, "\n"); - vty_out (vty, "\n"); - - pim_print_ifp_flags(vty, ifp, mloop); - } - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } else { - if (!found_ifname) - vty_out (vty, "%% No such interface\n"); - } + struct listnode *node; + struct interface *ifp; + time_t now; + json_object *json = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Interface State Address V Querier Query Timer Uptime\n"); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct pim_interface *pim_ifp; + struct listnode *sock_node; + struct igmp_sock *igmp; + + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, + igmp)) { + char uptime[10]; + char query_hhmmss[10]; + + pim_time_uptime(uptime, sizeof(uptime), + now - igmp->sock_creation); + pim_time_timer_to_hhmmss(query_hhmmss, + sizeof(query_hhmmss), + igmp->t_igmp_query_timer); + + if (uj) { + json_row = json_object_new_object(); + json_object_pim_ifp_add(json_row, ifp); + json_object_string_add(json_row, "upTime", + uptime); + json_object_int_add(json_row, "version", + pim_ifp->igmp_version); + + if (igmp->t_igmp_query_timer) { + json_object_boolean_true_add(json_row, + "querier"); + json_object_string_add(json_row, + "queryTimer", + query_hhmmss); + } + + json_object_object_add(json, ifp->name, + json_row); + + } else { + vty_out(vty, + "%-9s %5s %15s %d %7s %11s %8s\n", + ifp->name, + if_is_up(ifp) ? "up" : "down", + inet_ntoa(igmp->ifaddr), + pim_ifp->igmp_version, + igmp->t_igmp_query_timer ? "local" + : "other", + query_hhmmss, uptime); + } + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, + u_char uj) +{ + struct igmp_sock *igmp; + struct interface *ifp; + struct listnode *node; + struct listnode *sock_node; + struct pim_interface *pim_ifp; + char uptime[10]; + char query_hhmmss[10]; + char other_hhmmss[10]; + int found_ifname = 0; + int sqi; + int mloop; + long gmi_msec; /* Group Membership Interval */ + long lmqt_msec; + long ohpi_msec; + long oqpi_msec; /* Other Querier Present Interval */ + long qri_msec; + time_t now; + + json_object *json = NULL; + json_object *json_row = NULL; + + if (uj) + json = json_object_new_object(); + + now = pim_time_monotonic_sec(); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name)) + continue; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, + igmp)) { + found_ifname = 1; + pim_time_uptime(uptime, sizeof(uptime), + now - igmp->sock_creation); + pim_time_timer_to_hhmmss(query_hhmmss, + sizeof(query_hhmmss), + igmp->t_igmp_query_timer); + pim_time_timer_to_hhmmss(other_hhmmss, + sizeof(other_hhmmss), + igmp->t_other_querier_timer); + + gmi_msec = PIM_IGMP_GMI_MSEC( + igmp->querier_robustness_variable, + igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec); + + sqi = PIM_IGMP_SQI( + pim_ifp->igmp_default_query_interval); + + oqpi_msec = PIM_IGMP_OQPI_MSEC( + igmp->querier_robustness_variable, + igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec); + + lmqt_msec = PIM_IGMP_LMQT_MSEC( + pim_ifp->igmp_query_max_response_time_dsec, + igmp->querier_robustness_variable); + + ohpi_msec = + PIM_IGMP_OHPI_DSEC( + igmp->querier_robustness_variable, + igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec) + * 100; + + qri_msec = pim_ifp->igmp_query_max_response_time_dsec + * 100; + mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); + + if (uj) { + json_row = json_object_new_object(); + json_object_pim_ifp_add(json_row, ifp); + json_object_string_add(json_row, "upTime", + uptime); + json_object_string_add(json_row, "querier", + igmp->t_igmp_query_timer + ? "local" + : "other"); + json_object_int_add(json_row, "queryStartCount", + igmp->startup_query_count); + json_object_string_add(json_row, + "queryQueryTimer", + query_hhmmss); + json_object_string_add(json_row, + "queryOtherTimer", + other_hhmmss); + json_object_int_add(json_row, "version", + pim_ifp->igmp_version); + json_object_int_add( + json_row, + "timerGroupMembershipIntervalMsec", + gmi_msec); + json_object_int_add(json_row, + "timerLastMemberQueryMsec", + lmqt_msec); + json_object_int_add( + json_row, + "timerOlderHostPresentIntervalMsec", + ohpi_msec); + json_object_int_add( + json_row, + "timerOtherQuerierPresentIntervalMsec", + oqpi_msec); + json_object_int_add( + json_row, "timerQueryInterval", + igmp->querier_query_interval); + json_object_int_add( + json_row, + "timerQueryResponseIntervalMsec", + qri_msec); + json_object_int_add( + json_row, "timerRobustnessVariable", + igmp->querier_robustness_variable); + json_object_int_add(json_row, + "timerStartupQueryInterval", + sqi); + + json_object_object_add(json, ifp->name, + json_row); + + } else { + vty_out(vty, "Interface : %s\n", ifp->name); + vty_out(vty, "State : %s\n", + if_is_up(ifp) ? "up" : "down"); + vty_out(vty, "Address : %s\n", + inet_ntoa(pim_ifp->primary_address)); + vty_out(vty, "Uptime : %s\n", uptime); + vty_out(vty, "Version : %d\n", + pim_ifp->igmp_version); + vty_out(vty, "\n"); + vty_out(vty, "\n"); + + vty_out(vty, "Querier\n"); + vty_out(vty, "-------\n"); + vty_out(vty, "Querier : %s\n", + igmp->t_igmp_query_timer ? "local" + : "other"); + vty_out(vty, "Start Count : %d\n", + igmp->startup_query_count); + vty_out(vty, "Query Timer : %s\n", + query_hhmmss); + vty_out(vty, "Other Timer : %s\n", + other_hhmmss); + vty_out(vty, "\n"); + vty_out(vty, "\n"); + + vty_out(vty, "Timers\n"); + vty_out(vty, "------\n"); + vty_out(vty, + "Group Membership Interval : %lis\n", + gmi_msec / 1000); + vty_out(vty, + "Last Member Query Time : %lis\n", + lmqt_msec / 1000); + vty_out(vty, + "Older Host Present Interval : %lis\n", + ohpi_msec / 1000); + vty_out(vty, + "Other Querier Present Interval : %lis\n", + oqpi_msec / 1000); + vty_out(vty, + "Query Interval : %ds\n", + igmp->querier_query_interval); + vty_out(vty, + "Query Response Interval : %lis\n", + qri_msec / 1000); + vty_out(vty, + "Robustness Variable : %d\n", + igmp->querier_robustness_variable); + vty_out(vty, + "Startup Query Interval : %ds\n", + sqi); + vty_out(vty, "\n"); + vty_out(vty, "\n"); + + pim_print_ifp_flags(vty, ifp, mloop); + } + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + if (!found_ifname) + vty_out(vty, "%% No such interface\n"); + } } static void igmp_show_interface_join(struct vty *vty) { - struct listnode *node; - struct interface *ifp; - time_t now; - - now = pim_time_monotonic_sec(); - - vty_out (vty, - "Interface Address Source Group Socket Uptime \n"); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp; - struct listnode *join_node; - struct igmp_join *ij; - struct in_addr pri_addr; - char pri_addr_str[INET_ADDRSTRLEN]; - - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (!pim_ifp->igmp_join_list) - continue; - - pri_addr = pim_find_primary_addr(ifp); - pim_inet4_dump("<pri?>", pri_addr, pri_addr_str, sizeof(pri_addr_str)); - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, join_node, ij)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - char uptime[10]; - - pim_time_uptime(uptime, sizeof(uptime), now - ij->sock_creation); - pim_inet4_dump("<grp?>", ij->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", ij->source_addr, source_str, sizeof(source_str)); - - vty_out (vty, "%-9s %-15s %-15s %-15s %6d %8s\n", - ifp->name, - pri_addr_str, - source_str, - group_str, - ij->sock_fd, - uptime); - } /* for (pim_ifp->igmp_join_list) */ - - } /* for (iflist) */ - -} - -static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_char uj) -{ - struct in_addr ifaddr; - struct interface *ifp; - struct listnode *neighnode; - struct listnode*node; - struct listnode *upnode; - struct pim_interface *pim_ifp; - struct pim_neighbor *neigh; - struct pim_upstream *up; - time_t now; - char dr_str[INET_ADDRSTRLEN]; - char dr_uptime[10]; - char expire[10]; - char grp_str[INET_ADDRSTRLEN]; - char hello_period[10]; - char hello_timer[10]; - char neigh_src_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; - char stat_uptime[10]; - char uptime[10]; - int mloop; - int found_ifname = 0; - int print_header; - json_object *json = NULL; - json_object *json_row = NULL; - json_object *json_pim_neighbor = NULL; - json_object *json_pim_neighbors = NULL; - json_object *json_group = NULL; - json_object *json_group_source = NULL; - json_object *json_fhr_sources = NULL; - struct pim_secondary_addr *sec_addr; - struct listnode *sec_node; - - now = pim_time_monotonic_sec(); - - if (uj) - json = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name)) - continue; - - found_ifname = 1; - ifaddr = pim_ifp->primary_address; - pim_inet4_dump("<dr?>", pim_ifp->pim_dr_addr, dr_str, sizeof(dr_str)); - pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now, pim_ifp->pim_dr_election_last); - pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer), pim_ifp->t_pim_hello_timer); - pim_time_mmss(hello_period, sizeof(hello_period), pim_ifp->pim_hello_period); - pim_time_uptime(stat_uptime, sizeof(stat_uptime), now - pim_ifp->pim_ifstat_start); - mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); - - if (uj) { - char pbuf[PREFIX2STR_BUFFER]; - json_row = json_object_new_object(); - json_object_pim_ifp_add(json_row, ifp); - - if (pim_ifp->update_source.s_addr != INADDR_ANY) { - json_object_string_add(json_row, "useSource", inet_ntoa(pim_ifp->update_source)); - } - if (pim_ifp->sec_addr_list) { - json_object *sec_list = NULL; - - sec_list = json_object_new_array(); - for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) { - json_object_array_add(sec_list, - json_object_new_string(prefix2str(&sec_addr->addr, - pbuf, - sizeof(pbuf)))); - } - json_object_object_add(json_row, "secondaryAddressList", sec_list); - } - - // PIM neighbors - if (pim_ifp->pim_neighbor_list->count) { - json_pim_neighbors = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - json_pim_neighbor = json_object_new_object(); - pim_inet4_dump("<src?>", neigh->source_addr, neigh_src_str, sizeof(neigh_src_str)); - pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); - pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); - - json_object_string_add(json_pim_neighbor, "address", neigh_src_str); - json_object_string_add(json_pim_neighbor, "upTime", uptime); - json_object_string_add(json_pim_neighbor, "holdtime", expire); - - json_object_object_add(json_pim_neighbors, neigh_src_str, json_pim_neighbor); - } - - json_object_object_add(json_row, "neighbors", json_pim_neighbors); - } - - json_object_string_add(json_row, "drAddress", dr_str); - json_object_int_add(json_row, "drPriority", pim_ifp->pim_dr_priority); - json_object_string_add(json_row, "drUptime", dr_uptime); - json_object_int_add(json_row, "drElections", pim_ifp->pim_dr_election_count); - json_object_int_add(json_row, "drChanges", pim_ifp->pim_dr_election_changes); - - // FHR - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { - if (ifp == up->rpf.source_nexthop.interface) { - if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) { - if (!json_fhr_sources) { - json_fhr_sources = json_object_new_object(); - } - - pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); - pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); - - /* Does this group live in json_fhr_sources? If not create it. */ - json_object_object_get_ex(json_fhr_sources, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json_fhr_sources, grp_str, json_group); - } - - json_group_source = json_object_new_object(); - json_object_string_add(json_group_source, "source", src_str); - json_object_string_add(json_group_source, "group", grp_str); - json_object_string_add(json_group_source, "upTime", uptime); - json_object_object_add(json_group, src_str, json_group_source); - } - } - } - - if (json_fhr_sources) { - json_object_object_add(json_row, "firstHopRouter", json_fhr_sources); - } - - json_object_int_add(json_row, "helloPeriod", pim_ifp->pim_hello_period); - json_object_string_add(json_row, "helloTimer", hello_timer); - json_object_string_add(json_row, "helloStatStart", stat_uptime); - json_object_int_add(json_row, "helloReceived", pim_ifp->pim_ifstat_hello_recv); - json_object_int_add(json_row, "helloReceivedFailed", pim_ifp->pim_ifstat_hello_recvfail); - json_object_int_add(json_row, "helloSend", pim_ifp->pim_ifstat_hello_sent); - json_object_int_add(json_row, "hellosendFailed", pim_ifp->pim_ifstat_hello_sendfail); - json_object_int_add(json_row, "helloGenerationId", pim_ifp->pim_generation_id); - json_object_int_add(json_row, "flagMulticastLoop", mloop); - - json_object_int_add(json_row, "effectivePropagationDelay", pim_if_effective_propagation_delay_msec(ifp)); - json_object_int_add(json_row, "effectiveOverrideInterval", pim_if_effective_override_interval_msec(ifp)); - json_object_int_add(json_row, "joinPruneOverrideInterval", pim_if_jp_override_interval_msec(ifp)); - - json_object_int_add(json_row, "propagationDelay", pim_ifp->pim_propagation_delay_msec); - json_object_int_add(json_row, "propagationDelayHighest", pim_ifp->pim_neighbors_highest_propagation_delay_msec); - json_object_int_add(json_row, "overrideInterval", pim_ifp->pim_override_interval_msec); - json_object_int_add(json_row, "overrideIntervalHighest", pim_ifp->pim_neighbors_highest_override_interval_msec); - json_object_object_add(json, ifp->name, json_row); - - } else { - vty_out (vty, "Interface : %s\n", ifp->name); - vty_out (vty, "State : %s\n", if_is_up(ifp) ? "up" : "down"); - if (pim_ifp->update_source.s_addr != INADDR_ANY) { - vty_out (vty, "Use Source : %s\n", inet_ntoa(pim_ifp->update_source)); - } - if (pim_ifp->sec_addr_list) { - char pbuf[PREFIX2STR_BUFFER]; - vty_out (vty, "Address : %s (primary)\n", - inet_ntoa(ifaddr)); - for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) { - vty_out (vty, " %s\n", - prefix2str(&sec_addr->addr, pbuf, sizeof(pbuf))); - } - } else { - vty_out (vty, "Address : %s\n", inet_ntoa(ifaddr)); - } - vty_out (vty, "\n"); - - // PIM neighbors - print_header = 1; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - - if (print_header) { - vty_out (vty, "PIM Neighbors\n"); - vty_out (vty, "-------------\n"); - print_header = 0; - } - - pim_inet4_dump("<src?>", neigh->source_addr, neigh_src_str, sizeof(neigh_src_str)); - pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); - pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); - vty_out (vty, "%-15s : up for %s, holdtime expires in %s\n", neigh_src_str, uptime, - expire); - } - - if (!print_header) { - vty_out (vty, "\n"); - vty_out (vty, "\n"); - } - - vty_out (vty, "Designated Router\n"); - vty_out (vty, "-----------------\n"); - vty_out (vty, "Address : %s\n", dr_str); - vty_out (vty, "Priority : %d\n", pim_ifp->pim_dr_priority); - vty_out (vty, "Uptime : %s\n", dr_uptime); - vty_out (vty, "Elections : %d\n", pim_ifp->pim_dr_election_count); - vty_out (vty, "Changes : %d\n", pim_ifp->pim_dr_election_changes); - vty_out (vty, "\n"); - vty_out (vty, "\n"); - - // FHR - print_header = 1; - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { - if (strcmp(ifp->name, up->rpf.source_nexthop.interface->name) == 0) { - if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) { - - if (print_header) { - vty_out (vty, "FHR - First Hop Router\n"); - vty_out (vty, "----------------------\n"); - print_header = 0; - } - - pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); - pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); - vty_out (vty, "%s : %s is a source, uptime is %s\n", grp_str, src_str, - uptime); - } - } - } - - if (!print_header) { - vty_out (vty, "\n"); - vty_out (vty, "\n"); - } - - vty_out (vty, "Hellos\n"); - vty_out (vty, "------\n"); - vty_out (vty, "Period : %d\n", pim_ifp->pim_hello_period); - vty_out (vty, "Timer : %s\n", hello_timer); - vty_out (vty, "StatStart : %s\n", stat_uptime); - vty_out (vty, "Receive : %d\n", pim_ifp->pim_ifstat_hello_recv); - vty_out (vty, "Receive Failed : %d\n", - pim_ifp->pim_ifstat_hello_recvfail); - vty_out (vty, "Send : %d\n", pim_ifp->pim_ifstat_hello_sent); - vty_out (vty, "Send Failed : %d\n", - pim_ifp->pim_ifstat_hello_sendfail); - vty_out (vty, "Generation ID : %08x\n", pim_ifp->pim_generation_id); - vty_out (vty, "\n"); - vty_out (vty, "\n"); - - pim_print_ifp_flags(vty, ifp, mloop); - - vty_out (vty, "Join Prune Interval\n"); - vty_out (vty, "-------------------\n"); - vty_out (vty, "LAN Delay : %s\n", - pim_if_lan_delay_enabled(ifp) ? "yes" : "no"); - vty_out (vty, "Effective Propagation Delay : %d msec\n", - pim_if_effective_propagation_delay_msec(ifp)); - vty_out (vty, "Effective Override Interval : %d msec\n", - pim_if_effective_override_interval_msec(ifp)); - vty_out (vty, "Join Prune Override Interval : %d msec\n", - pim_if_jp_override_interval_msec(ifp)); - vty_out (vty, "\n"); - vty_out (vty, "\n"); - - vty_out (vty, "LAN Prune Delay\n"); - vty_out (vty, "---------------\n"); - vty_out (vty, "Propagation Delay : %d msec\n", - pim_ifp->pim_propagation_delay_msec); - vty_out (vty, "Propagation Delay (Highest) : %d msec\n", - pim_ifp->pim_neighbors_highest_propagation_delay_msec); - vty_out (vty, "Override Interval : %d msec\n", - pim_ifp->pim_override_interval_msec); - vty_out (vty, "Override Interval (Highest) : %d msec\n", - pim_ifp->pim_neighbors_highest_override_interval_msec); - vty_out (vty, "\n"); - vty_out (vty, "\n"); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } else { - if (!found_ifname) - vty_out (vty, "%% No such interface\n"); - } + struct listnode *node; + struct interface *ifp; + time_t now; + + now = pim_time_monotonic_sec(); + + vty_out(vty, + "Interface Address Source Group Socket Uptime \n"); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct pim_interface *pim_ifp; + struct listnode *join_node; + struct igmp_join *ij; + struct in_addr pri_addr; + char pri_addr_str[INET_ADDRSTRLEN]; + + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (!pim_ifp->igmp_join_list) + continue; + + pri_addr = pim_find_primary_addr(ifp); + pim_inet4_dump("<pri?>", pri_addr, pri_addr_str, + sizeof(pri_addr_str)); + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, join_node, + ij)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + char uptime[10]; + + pim_time_uptime(uptime, sizeof(uptime), + now - ij->sock_creation); + pim_inet4_dump("<grp?>", ij->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", ij->source_addr, source_str, + sizeof(source_str)); + + vty_out(vty, "%-9s %-15s %-15s %-15s %6d %8s\n", + ifp->name, pri_addr_str, source_str, group_str, + ij->sock_fd, uptime); + } /* for (pim_ifp->igmp_join_list) */ + + } /* for (iflist) */ +} + +static void pim_show_interfaces_single(struct vty *vty, const char *ifname, + u_char uj) +{ + struct in_addr ifaddr; + struct interface *ifp; + struct listnode *neighnode; + struct listnode *node; + struct listnode *upnode; + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; + struct pim_upstream *up; + time_t now; + char dr_str[INET_ADDRSTRLEN]; + char dr_uptime[10]; + char expire[10]; + char grp_str[INET_ADDRSTRLEN]; + char hello_period[10]; + char hello_timer[10]; + char neigh_src_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + char stat_uptime[10]; + char uptime[10]; + int mloop; + int found_ifname = 0; + int print_header; + json_object *json = NULL; + json_object *json_row = NULL; + json_object *json_pim_neighbor = NULL; + json_object *json_pim_neighbors = NULL; + json_object *json_group = NULL; + json_object *json_group_source = NULL; + json_object *json_fhr_sources = NULL; + struct pim_secondary_addr *sec_addr; + struct listnode *sec_node; + + now = pim_time_monotonic_sec(); + + if (uj) + json = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name)) + continue; + + found_ifname = 1; + ifaddr = pim_ifp->primary_address; + pim_inet4_dump("<dr?>", pim_ifp->pim_dr_addr, dr_str, + sizeof(dr_str)); + pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now, + pim_ifp->pim_dr_election_last); + pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer), + pim_ifp->t_pim_hello_timer); + pim_time_mmss(hello_period, sizeof(hello_period), + pim_ifp->pim_hello_period); + pim_time_uptime(stat_uptime, sizeof(stat_uptime), + now - pim_ifp->pim_ifstat_start); + mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); + + if (uj) { + char pbuf[PREFIX2STR_BUFFER]; + json_row = json_object_new_object(); + json_object_pim_ifp_add(json_row, ifp); + + if (pim_ifp->update_source.s_addr != INADDR_ANY) { + json_object_string_add( + json_row, "useSource", + inet_ntoa(pim_ifp->update_source)); + } + if (pim_ifp->sec_addr_list) { + json_object *sec_list = NULL; + + sec_list = json_object_new_array(); + for (ALL_LIST_ELEMENTS_RO( + pim_ifp->sec_addr_list, sec_node, + sec_addr)) { + json_object_array_add( + sec_list, + json_object_new_string( + prefix2str( + &sec_addr->addr, + pbuf, + sizeof(pbuf)))); + } + json_object_object_add(json_row, + "secondaryAddressList", + sec_list); + } + + // PIM neighbors + if (pim_ifp->pim_neighbor_list->count) { + json_pim_neighbors = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO( + pim_ifp->pim_neighbor_list, + neighnode, neigh)) { + json_pim_neighbor = + json_object_new_object(); + pim_inet4_dump("<src?>", + neigh->source_addr, + neigh_src_str, + sizeof(neigh_src_str)); + pim_time_uptime(uptime, sizeof(uptime), + now - neigh->creation); + pim_time_timer_to_hhmmss( + expire, sizeof(expire), + neigh->t_expire_timer); + + json_object_string_add( + json_pim_neighbor, "address", + neigh_src_str); + json_object_string_add( + json_pim_neighbor, "upTime", + uptime); + json_object_string_add( + json_pim_neighbor, "holdtime", + expire); + + json_object_object_add( + json_pim_neighbors, + neigh_src_str, + json_pim_neighbor); + } + + json_object_object_add(json_row, "neighbors", + json_pim_neighbors); + } + + json_object_string_add(json_row, "drAddress", dr_str); + json_object_int_add(json_row, "drPriority", + pim_ifp->pim_dr_priority); + json_object_string_add(json_row, "drUptime", dr_uptime); + json_object_int_add(json_row, "drElections", + pim_ifp->pim_dr_election_count); + json_object_int_add(json_row, "drChanges", + pim_ifp->pim_dr_election_changes); + + // FHR + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, + up)) { + if (ifp == up->rpf.source_nexthop.interface) { + if (up->flags + & PIM_UPSTREAM_FLAG_MASK_FHR) { + if (!json_fhr_sources) { + json_fhr_sources = + json_object_new_object(); + } + + pim_inet4_dump("<src?>", + up->sg.src, + src_str, + sizeof(src_str)); + pim_inet4_dump("<grp?>", + up->sg.grp, + grp_str, + sizeof(grp_str)); + pim_time_uptime( + uptime, sizeof(uptime), + now - up->state_transition); + + /* Does this group live in + * json_fhr_sources? If not + * create it. */ + json_object_object_get_ex( + json_fhr_sources, + grp_str, &json_group); + + if (!json_group) { + json_group = + json_object_new_object(); + json_object_object_add( + json_fhr_sources, + grp_str, + json_group); + } + + json_group_source = + json_object_new_object(); + json_object_string_add( + json_group_source, + "source", src_str); + json_object_string_add( + json_group_source, + "group", grp_str); + json_object_string_add( + json_group_source, + "upTime", uptime); + json_object_object_add( + json_group, src_str, + json_group_source); + } + } + } + + if (json_fhr_sources) { + json_object_object_add(json_row, + "firstHopRouter", + json_fhr_sources); + } + + json_object_int_add(json_row, "helloPeriod", + pim_ifp->pim_hello_period); + json_object_string_add(json_row, "helloTimer", + hello_timer); + json_object_string_add(json_row, "helloStatStart", + stat_uptime); + json_object_int_add(json_row, "helloReceived", + pim_ifp->pim_ifstat_hello_recv); + json_object_int_add(json_row, "helloReceivedFailed", + pim_ifp->pim_ifstat_hello_recvfail); + json_object_int_add(json_row, "helloSend", + pim_ifp->pim_ifstat_hello_sent); + json_object_int_add(json_row, "hellosendFailed", + pim_ifp->pim_ifstat_hello_sendfail); + json_object_int_add(json_row, "helloGenerationId", + pim_ifp->pim_generation_id); + json_object_int_add(json_row, "flagMulticastLoop", + mloop); + + json_object_int_add( + json_row, "effectivePropagationDelay", + pim_if_effective_propagation_delay_msec(ifp)); + json_object_int_add( + json_row, "effectiveOverrideInterval", + pim_if_effective_override_interval_msec(ifp)); + json_object_int_add( + json_row, "joinPruneOverrideInterval", + pim_if_jp_override_interval_msec(ifp)); + + json_object_int_add( + json_row, "propagationDelay", + pim_ifp->pim_propagation_delay_msec); + json_object_int_add( + json_row, "propagationDelayHighest", + pim_ifp->pim_neighbors_highest_propagation_delay_msec); + json_object_int_add( + json_row, "overrideInterval", + pim_ifp->pim_override_interval_msec); + json_object_int_add( + json_row, "overrideIntervalHighest", + pim_ifp->pim_neighbors_highest_override_interval_msec); + json_object_object_add(json, ifp->name, json_row); + + } else { + vty_out(vty, "Interface : %s\n", ifp->name); + vty_out(vty, "State : %s\n", + if_is_up(ifp) ? "up" : "down"); + if (pim_ifp->update_source.s_addr != INADDR_ANY) { + vty_out(vty, "Use Source : %s\n", + inet_ntoa(pim_ifp->update_source)); + } + if (pim_ifp->sec_addr_list) { + char pbuf[PREFIX2STR_BUFFER]; + vty_out(vty, "Address : %s (primary)\n", + inet_ntoa(ifaddr)); + for (ALL_LIST_ELEMENTS_RO( + pim_ifp->sec_addr_list, sec_node, + sec_addr)) { + vty_out(vty, " %s\n", + prefix2str(&sec_addr->addr, + pbuf, sizeof(pbuf))); + } + } else { + vty_out(vty, "Address : %s\n", + inet_ntoa(ifaddr)); + } + vty_out(vty, "\n"); + + // PIM neighbors + print_header = 1; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, + neighnode, neigh)) { + + if (print_header) { + vty_out(vty, "PIM Neighbors\n"); + vty_out(vty, "-------------\n"); + print_header = 0; + } + + pim_inet4_dump("<src?>", neigh->source_addr, + neigh_src_str, + sizeof(neigh_src_str)); + pim_time_uptime(uptime, sizeof(uptime), + now - neigh->creation); + pim_time_timer_to_hhmmss(expire, sizeof(expire), + neigh->t_expire_timer); + vty_out(vty, + "%-15s : up for %s, holdtime expires in %s\n", + neigh_src_str, uptime, expire); + } + + if (!print_header) { + vty_out(vty, "\n"); + vty_out(vty, "\n"); + } + + vty_out(vty, "Designated Router\n"); + vty_out(vty, "-----------------\n"); + vty_out(vty, "Address : %s\n", dr_str); + vty_out(vty, "Priority : %d\n", + pim_ifp->pim_dr_priority); + vty_out(vty, "Uptime : %s\n", dr_uptime); + vty_out(vty, "Elections : %d\n", + pim_ifp->pim_dr_election_count); + vty_out(vty, "Changes : %d\n", + pim_ifp->pim_dr_election_changes); + vty_out(vty, "\n"); + vty_out(vty, "\n"); + + // FHR + print_header = 1; + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, + up)) { + if (strcmp(ifp->name, + up->rpf.source_nexthop + .interface->name) + == 0) { + if (up->flags + & PIM_UPSTREAM_FLAG_MASK_FHR) { + + if (print_header) { + vty_out(vty, + "FHR - First Hop Router\n"); + vty_out(vty, + "----------------------\n"); + print_header = 0; + } + + pim_inet4_dump("<src?>", + up->sg.src, + src_str, + sizeof(src_str)); + pim_inet4_dump("<grp?>", + up->sg.grp, + grp_str, + sizeof(grp_str)); + pim_time_uptime( + uptime, sizeof(uptime), + now - up->state_transition); + vty_out(vty, + "%s : %s is a source, uptime is %s\n", + grp_str, src_str, + uptime); + } + } + } + + if (!print_header) { + vty_out(vty, "\n"); + vty_out(vty, "\n"); + } + + vty_out(vty, "Hellos\n"); + vty_out(vty, "------\n"); + vty_out(vty, "Period : %d\n", + pim_ifp->pim_hello_period); + vty_out(vty, "Timer : %s\n", hello_timer); + vty_out(vty, "StatStart : %s\n", stat_uptime); + vty_out(vty, "Receive : %d\n", + pim_ifp->pim_ifstat_hello_recv); + vty_out(vty, "Receive Failed : %d\n", + pim_ifp->pim_ifstat_hello_recvfail); + vty_out(vty, "Send : %d\n", + pim_ifp->pim_ifstat_hello_sent); + vty_out(vty, "Send Failed : %d\n", + pim_ifp->pim_ifstat_hello_sendfail); + vty_out(vty, "Generation ID : %08x\n", + pim_ifp->pim_generation_id); + vty_out(vty, "\n"); + vty_out(vty, "\n"); + + pim_print_ifp_flags(vty, ifp, mloop); + + vty_out(vty, "Join Prune Interval\n"); + vty_out(vty, "-------------------\n"); + vty_out(vty, "LAN Delay : %s\n", + pim_if_lan_delay_enabled(ifp) ? "yes" : "no"); + vty_out(vty, "Effective Propagation Delay : %d msec\n", + pim_if_effective_propagation_delay_msec(ifp)); + vty_out(vty, "Effective Override Interval : %d msec\n", + pim_if_effective_override_interval_msec(ifp)); + vty_out(vty, "Join Prune Override Interval : %d msec\n", + pim_if_jp_override_interval_msec(ifp)); + vty_out(vty, "\n"); + vty_out(vty, "\n"); + + vty_out(vty, "LAN Prune Delay\n"); + vty_out(vty, "---------------\n"); + vty_out(vty, "Propagation Delay : %d msec\n", + pim_ifp->pim_propagation_delay_msec); + vty_out(vty, "Propagation Delay (Highest) : %d msec\n", + pim_ifp->pim_neighbors_highest_propagation_delay_msec); + vty_out(vty, "Override Interval : %d msec\n", + pim_ifp->pim_override_interval_msec); + vty_out(vty, "Override Interval (Highest) : %d msec\n", + pim_ifp->pim_neighbors_highest_override_interval_msec); + vty_out(vty, "\n"); + vty_out(vty, "\n"); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + if (!found_ifname) + vty_out(vty, "%% No such interface\n"); + } } static void pim_show_interfaces(struct vty *vty, u_char uj) { - struct interface *ifp; - struct listnode *node; - struct listnode *upnode; - struct pim_interface *pim_ifp; - struct pim_upstream *up; - int fhr = 0; - int pim_nbrs = 0; - int pim_ifchannels = 0; - json_object *json = NULL; - json_object *json_row = NULL; - json_object *json_tmp; - - json = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - pim_nbrs = pim_ifp->pim_neighbor_list->count; - pim_ifchannels = pim_ifp->pim_ifchannel_list->count; - fhr = 0; - - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) - if (ifp == up->rpf.source_nexthop.interface) - if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) - fhr++; - - json_row = json_object_new_object(); - json_object_pim_ifp_add(json_row, ifp); - json_object_int_add(json_row, "pimNeighbors", pim_nbrs); - json_object_int_add(json_row, "pimIfChannels", pim_ifchannels); - json_object_int_add(json_row, "firstHopRouter", fhr); - json_object_string_add(json_row, "pimDesignatedRouter", inet_ntoa(pim_ifp->pim_dr_addr)); - - if (pim_ifp->pim_dr_addr.s_addr == pim_ifp->primary_address.s_addr) - json_object_boolean_true_add(json_row, "pimDesignatedRouterLocal"); - - json_object_object_add(json, ifp->name, json_row); - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - } else { - vty_out (vty, - "Interface State Address PIM Nbrs PIM DR FHR IfChannels\n"); - - json_object_object_foreach(json, key, val) { - vty_out(vty, "%-9s ", key); - - json_object_object_get_ex(val, "state", &json_tmp); - vty_out(vty, "%5s ", json_object_get_string(json_tmp)); - - json_object_object_get_ex(val, "address", &json_tmp); - vty_out(vty, "%15s ", json_object_get_string(json_tmp)); - - json_object_object_get_ex(val, "pimNeighbors", &json_tmp); - vty_out(vty, "%8d ", json_object_get_int(json_tmp)); - - if (json_object_object_get_ex(val, "pimDesignatedRouterLocal", &json_tmp)) { - vty_out(vty, "%15s ", "local"); - } else { - json_object_object_get_ex(val, "pimDesignatedRouter", &json_tmp); - vty_out(vty, "%15s ", json_object_get_string(json_tmp)); - } - - json_object_object_get_ex(val, "firstHopRouter", &json_tmp); - vty_out(vty, "%3d ", json_object_get_int(json_tmp)); - - json_object_object_get_ex(val, "pimIfChannels", &json_tmp); - vty_out (vty, "%9d\n", json_object_get_int(json_tmp)); - } - } - - json_object_free(json); -} - -static void pim_show_interface_traffic (struct vty *vty, u_char uj) -{ - struct interface *ifp = NULL; - struct pim_interface *pim_ifp = NULL; - struct listnode *node = NULL; - json_object *json = NULL; - json_object *json_row = NULL; - - if (uj) - json = json_object_new_object (); - else - { - vty_out (vty, "\n"); - vty_out (vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n", "Interface", - " HELLO", " JOIN", " PRUNE", " REGISTER", - " REGISTER-STOP", " ASSERT"); - vty_out (vty, - "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", - "", " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", - " Rx/Tx", " Rx/Tx"); - vty_out (vty, - "---------------------------------------------------------------------------------------------------------------\n"); - } - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - if (uj) - { - json_row = json_object_new_object (); - json_object_pim_ifp_add (json_row, ifp); - json_object_int_add (json_row, "helloRx", pim_ifp->pim_ifstat_hello_recv); - json_object_int_add (json_row, "helloTx", pim_ifp->pim_ifstat_hello_sent); - json_object_int_add (json_row, "joinRx", pim_ifp->pim_ifstat_join_recv); - json_object_int_add (json_row, "joinTx", pim_ifp->pim_ifstat_join_send); - json_object_int_add (json_row, "registerRx", pim_ifp->pim_ifstat_reg_recv); - json_object_int_add (json_row, "registerTx", pim_ifp->pim_ifstat_reg_recv); - json_object_int_add (json_row, "registerStopRx", pim_ifp->pim_ifstat_reg_stop_recv); - json_object_int_add (json_row, "registerStopTx", pim_ifp->pim_ifstat_reg_stop_send); - json_object_int_add (json_row, "assertRx", pim_ifp->pim_ifstat_assert_recv); - json_object_int_add (json_row, "assertTx", pim_ifp->pim_ifstat_assert_send); - - json_object_object_add (json, ifp->name, json_row); - } - else - { - vty_out (vty, - "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n", - ifp->name, pim_ifp->pim_ifstat_hello_recv, - pim_ifp->pim_ifstat_hello_sent, pim_ifp->pim_ifstat_join_recv, - pim_ifp->pim_ifstat_join_send, pim_ifp->pim_ifstat_prune_recv, - pim_ifp->pim_ifstat_prune_send, pim_ifp->pim_ifstat_reg_recv, - pim_ifp->pim_ifstat_reg_send, - pim_ifp->pim_ifstat_reg_stop_recv, - pim_ifp->pim_ifstat_reg_stop_send, - pim_ifp->pim_ifstat_assert_recv, - pim_ifp->pim_ifstat_assert_send); - } - } - if (uj) - { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free (json); - } -} - -static void pim_show_interface_traffic_single (struct vty *vty, const char *ifname, u_char uj) -{ - struct interface *ifp = NULL; - struct pim_interface *pim_ifp = NULL; - struct listnode *node = NULL; - json_object *json = NULL; - json_object *json_row = NULL; - uint8_t found_ifname = 0; - - if (uj) - json = json_object_new_object (); - else - { - vty_out (vty, "\n"); - vty_out (vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n", "Interface", - " HELLO", " JOIN", " PRUNE", " REGISTER", - " REGISTER-STOP", " ASSERT"); - vty_out (vty, - "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", - "", " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", - " Rx/Tx", " Rx/Tx"); - vty_out (vty, - "---------------------------------------------------------------------------------------------------------------\n"); - } - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - if (strcmp (ifname, ifp->name)) - continue; - - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - found_ifname = 1; - if (uj) - { - json_row = json_object_new_object (); - json_object_pim_ifp_add (json_row, ifp); - json_object_int_add (json_row, "helloRx", pim_ifp->pim_ifstat_hello_recv); - json_object_int_add (json_row, "helloTx", pim_ifp->pim_ifstat_hello_sent); - json_object_int_add (json_row, "joinRx", pim_ifp->pim_ifstat_join_recv); - json_object_int_add (json_row, "joinTx", pim_ifp->pim_ifstat_join_send); - json_object_int_add (json_row, "registerRx", pim_ifp->pim_ifstat_reg_recv); - json_object_int_add (json_row, "registerTx", pim_ifp->pim_ifstat_reg_recv); - json_object_int_add (json_row, "registerStopRx", pim_ifp->pim_ifstat_reg_stop_recv); - json_object_int_add (json_row, "registerStopTx", pim_ifp->pim_ifstat_reg_stop_send); - json_object_int_add (json_row, "assertRx", pim_ifp->pim_ifstat_assert_recv); - json_object_int_add (json_row, "assertTx", pim_ifp->pim_ifstat_assert_send); - - json_object_object_add (json, ifp->name, json_row); - } - else - { - vty_out (vty, - "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n", - ifp->name, pim_ifp->pim_ifstat_hello_recv, - pim_ifp->pim_ifstat_hello_sent, pim_ifp->pim_ifstat_join_recv, - pim_ifp->pim_ifstat_join_send, pim_ifp->pim_ifstat_prune_recv, - pim_ifp->pim_ifstat_prune_send, pim_ifp->pim_ifstat_reg_recv, - pim_ifp->pim_ifstat_reg_send, - pim_ifp->pim_ifstat_reg_stop_recv, - pim_ifp->pim_ifstat_reg_stop_send, - pim_ifp->pim_ifstat_assert_recv, - pim_ifp->pim_ifstat_assert_send); - } - } - if (uj) - { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free (json); - } - else - { - if (!found_ifname) - vty_out (vty, "%% No such interface\n"); - } + struct interface *ifp; + struct listnode *node; + struct listnode *upnode; + struct pim_interface *pim_ifp; + struct pim_upstream *up; + int fhr = 0; + int pim_nbrs = 0; + int pim_ifchannels = 0; + json_object *json = NULL; + json_object *json_row = NULL; + json_object *json_tmp; + + json = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + pim_nbrs = pim_ifp->pim_neighbor_list->count; + pim_ifchannels = pim_ifp->pim_ifchannel_list->count; + fhr = 0; + + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) + if (ifp == up->rpf.source_nexthop.interface) + if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) + fhr++; + + json_row = json_object_new_object(); + json_object_pim_ifp_add(json_row, ifp); + json_object_int_add(json_row, "pimNeighbors", pim_nbrs); + json_object_int_add(json_row, "pimIfChannels", pim_ifchannels); + json_object_int_add(json_row, "firstHopRouter", fhr); + json_object_string_add(json_row, "pimDesignatedRouter", + inet_ntoa(pim_ifp->pim_dr_addr)); + + if (pim_ifp->pim_dr_addr.s_addr + == pim_ifp->primary_address.s_addr) + json_object_boolean_true_add( + json_row, "pimDesignatedRouterLocal"); + + json_object_object_add(json, ifp->name, json_row); + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + } else { + vty_out(vty, + "Interface State Address PIM Nbrs PIM DR FHR IfChannels\n"); + + json_object_object_foreach(json, key, val) + { + vty_out(vty, "%-9s ", key); + + json_object_object_get_ex(val, "state", &json_tmp); + vty_out(vty, "%5s ", json_object_get_string(json_tmp)); + + json_object_object_get_ex(val, "address", &json_tmp); + vty_out(vty, "%15s ", + json_object_get_string(json_tmp)); + + json_object_object_get_ex(val, "pimNeighbors", + &json_tmp); + vty_out(vty, "%8d ", json_object_get_int(json_tmp)); + + if (json_object_object_get_ex( + val, "pimDesignatedRouterLocal", + &json_tmp)) { + vty_out(vty, "%15s ", "local"); + } else { + json_object_object_get_ex( + val, "pimDesignatedRouter", &json_tmp); + vty_out(vty, "%15s ", + json_object_get_string(json_tmp)); + } + + json_object_object_get_ex(val, "firstHopRouter", + &json_tmp); + vty_out(vty, "%3d ", json_object_get_int(json_tmp)); + + json_object_object_get_ex(val, "pimIfChannels", + &json_tmp); + vty_out(vty, "%9d\n", json_object_get_int(json_tmp)); + } + } + + json_object_free(json); +} + +static void pim_show_interface_traffic(struct vty *vty, u_char uj) +{ + struct interface *ifp = NULL; + struct pim_interface *pim_ifp = NULL; + struct listnode *node = NULL; + json_object *json = NULL; + json_object *json_row = NULL; + + if (uj) + json = json_object_new_object(); + else { + vty_out(vty, "\n"); + vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n", + "Interface", " HELLO", " JOIN", " PRUNE", + " REGISTER", " REGISTER-STOP", " ASSERT"); + vty_out(vty, "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", "", + " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", + " Rx/Tx", " Rx/Tx"); + vty_out(vty, + "---------------------------------------------------------------------------------------------------------------\n"); + } + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + if (uj) { + json_row = json_object_new_object(); + json_object_pim_ifp_add(json_row, ifp); + json_object_int_add(json_row, "helloRx", + pim_ifp->pim_ifstat_hello_recv); + json_object_int_add(json_row, "helloTx", + pim_ifp->pim_ifstat_hello_sent); + json_object_int_add(json_row, "joinRx", + pim_ifp->pim_ifstat_join_recv); + json_object_int_add(json_row, "joinTx", + pim_ifp->pim_ifstat_join_send); + json_object_int_add(json_row, "registerRx", + pim_ifp->pim_ifstat_reg_recv); + json_object_int_add(json_row, "registerTx", + pim_ifp->pim_ifstat_reg_recv); + json_object_int_add(json_row, "registerStopRx", + pim_ifp->pim_ifstat_reg_stop_recv); + json_object_int_add(json_row, "registerStopTx", + pim_ifp->pim_ifstat_reg_stop_send); + json_object_int_add(json_row, "assertRx", + pim_ifp->pim_ifstat_assert_recv); + json_object_int_add(json_row, "assertTx", + pim_ifp->pim_ifstat_assert_send); + + json_object_object_add(json, ifp->name, json_row); + } else { + vty_out(vty, + "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n", + ifp->name, pim_ifp->pim_ifstat_hello_recv, + pim_ifp->pim_ifstat_hello_sent, + pim_ifp->pim_ifstat_join_recv, + pim_ifp->pim_ifstat_join_send, + pim_ifp->pim_ifstat_prune_recv, + pim_ifp->pim_ifstat_prune_send, + pim_ifp->pim_ifstat_reg_recv, + pim_ifp->pim_ifstat_reg_send, + pim_ifp->pim_ifstat_reg_stop_recv, + pim_ifp->pim_ifstat_reg_stop_send, + pim_ifp->pim_ifstat_assert_recv, + pim_ifp->pim_ifstat_assert_send); + } + } + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void pim_show_interface_traffic_single(struct vty *vty, + const char *ifname, u_char uj) +{ + struct interface *ifp = NULL; + struct pim_interface *pim_ifp = NULL; + struct listnode *node = NULL; + json_object *json = NULL; + json_object *json_row = NULL; + uint8_t found_ifname = 0; + + if (uj) + json = json_object_new_object(); + else { + vty_out(vty, "\n"); + vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n", + "Interface", " HELLO", " JOIN", " PRUNE", + " REGISTER", " REGISTER-STOP", " ASSERT"); + vty_out(vty, "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", "", + " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", + " Rx/Tx", " Rx/Tx"); + vty_out(vty, + "---------------------------------------------------------------------------------------------------------------\n"); + } + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + if (strcmp(ifname, ifp->name)) + continue; + + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + found_ifname = 1; + if (uj) { + json_row = json_object_new_object(); + json_object_pim_ifp_add(json_row, ifp); + json_object_int_add(json_row, "helloRx", + pim_ifp->pim_ifstat_hello_recv); + json_object_int_add(json_row, "helloTx", + pim_ifp->pim_ifstat_hello_sent); + json_object_int_add(json_row, "joinRx", + pim_ifp->pim_ifstat_join_recv); + json_object_int_add(json_row, "joinTx", + pim_ifp->pim_ifstat_join_send); + json_object_int_add(json_row, "registerRx", + pim_ifp->pim_ifstat_reg_recv); + json_object_int_add(json_row, "registerTx", + pim_ifp->pim_ifstat_reg_recv); + json_object_int_add(json_row, "registerStopRx", + pim_ifp->pim_ifstat_reg_stop_recv); + json_object_int_add(json_row, "registerStopTx", + pim_ifp->pim_ifstat_reg_stop_send); + json_object_int_add(json_row, "assertRx", + pim_ifp->pim_ifstat_assert_recv); + json_object_int_add(json_row, "assertTx", + pim_ifp->pim_ifstat_assert_send); + + json_object_object_add(json, ifp->name, json_row); + } else { + vty_out(vty, + "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n", + ifp->name, pim_ifp->pim_ifstat_hello_recv, + pim_ifp->pim_ifstat_hello_sent, + pim_ifp->pim_ifstat_join_recv, + pim_ifp->pim_ifstat_join_send, + pim_ifp->pim_ifstat_prune_recv, + pim_ifp->pim_ifstat_prune_send, + pim_ifp->pim_ifstat_reg_recv, + pim_ifp->pim_ifstat_reg_send, + pim_ifp->pim_ifstat_reg_stop_recv, + pim_ifp->pim_ifstat_reg_stop_send, + pim_ifp->pim_ifstat_assert_recv, + pim_ifp->pim_ifstat_assert_send); + } + } + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + if (!found_ifname) + vty_out(vty, "%% No such interface\n"); + } } static void pim_show_join(struct vty *vty, u_char uj) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - struct listnode *ch_node; - struct pim_ifchannel *ch; - time_t now; - json_object *json = NULL; - json_object *json_iface = NULL; - json_object *json_row = NULL; - json_object *json_grp = NULL; - - now = pim_time_monotonic_sec(); - - if (uj) - json = json_object_new_object(); - else - vty_out (vty, - "Interface Address Source Group State Uptime Expire Prune\n"); - - for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - - pim_ifp = ch->interface->info; - - if (!pim_ifp) - continue; - - ifaddr = pim_ifp->primary_address; - - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - char uptime[10]; - char expire[10]; - char prune[10]; - - pim_inet4_dump("<ch_src?>", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("<ch_grp?>", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - - pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation); - pim_time_timer_to_mmss(expire, sizeof(expire), - ch->t_ifjoin_expiry_timer); - pim_time_timer_to_mmss(prune, sizeof(prune), - ch->t_ifjoin_prune_pending_timer); - - if (uj) { - json_object_object_get_ex(json, ch->interface->name, &json_iface); - - if (!json_iface) { - json_iface = json_object_new_object(); - json_object_pim_ifp_add(json_iface, ch->interface); - json_object_object_add(json, ch->interface->name, json_iface); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", ch_src_str); - json_object_string_add(json_row, "group", ch_grp_str); - json_object_string_add(json_row, "upTime", uptime); - json_object_string_add(json_row, "expire", expire); - json_object_string_add(json_row, "prune", prune); - json_object_string_add(json_row, "channelJoinName", - pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags)); - if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) - json_object_int_add(json_row, "SGRpt", 1); - - json_object_object_get_ex(json_iface, ch_grp_str, &json_grp); - if (!json_grp) - { - json_grp = json_object_new_object(); - json_object_object_add(json_grp, ch_src_str, json_row); - json_object_object_add(json_iface, ch_grp_str, json_grp); - } - else - json_object_object_add(json_grp, ch_src_str, json_row); - } else { - vty_out (vty, "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s\n", - ch->interface->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), - uptime, - expire, - prune); - } - } /* scan interface channels */ - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } -} - -static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, u_char uj) -{ - struct listnode *node; - struct listnode *neighnode; - struct interface *ifp; - struct pim_interface *pim_ifp; - struct pim_neighbor *neigh; - time_t now; - int found_neighbor = 0; - int option_address_list; - int option_dr_priority; - int option_generation_id; - int option_holdtime; - int option_lan_prune_delay; - int option_t_bit; - char uptime[10]; - char expire[10]; - char neigh_src_str[INET_ADDRSTRLEN]; - - json_object *json = NULL; - json_object *json_ifp = NULL; - json_object *json_row = NULL; - - now = pim_time_monotonic_sec(); - - if (uj) - json = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - pim_inet4_dump("<src?>", neigh->source_addr, - neigh_src_str, sizeof(neigh_src_str)); - - /* - * The user can specify either the interface name or the PIM neighbor IP. - * If this pim_ifp matches neither then skip. - */ - if (strcmp(neighbor, "detail") && - strcmp(neighbor, ifp->name) && - strcmp(neighbor, neigh_src_str)) - continue; - - found_neighbor = 1; - pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); - pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); - - option_address_list = 0; - option_dr_priority = 0; - option_generation_id = 0; - option_holdtime = 0; - option_lan_prune_delay = 0; - option_t_bit = 0; - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_ADDRESS_LIST)) - option_address_list = 1; - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY)) - option_dr_priority = 1; - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID)) - option_generation_id = 1; - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_HOLDTIME)) - option_holdtime = 1; - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY)) - option_lan_prune_delay = 1; - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)) - option_t_bit = 1; - - if (uj) { - - /* Does this ifp live in json? If not create it. */ - json_object_object_get_ex(json, ifp->name, &json_ifp); - - if (!json_ifp) { - json_ifp = json_object_new_object(); - json_object_pim_ifp_add(json_ifp, ifp); - json_object_object_add(json, ifp->name, json_ifp); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "interface", ifp->name); - json_object_string_add(json_row, "address", neigh_src_str); - json_object_string_add(json_row, "upTime", uptime); - json_object_string_add(json_row, "holdtime", expire); - json_object_int_add(json_row, "drPriority", neigh->dr_priority); - json_object_int_add(json_row, "generationId", neigh->generation_id); - - if (option_address_list) - json_object_boolean_true_add(json_row, "helloOptionAddressList"); - - if (option_dr_priority) - json_object_boolean_true_add(json_row, "helloOptionDrPriority"); - - if (option_generation_id) - json_object_boolean_true_add(json_row, "helloOptionGenerationId"); - - if (option_holdtime) - json_object_boolean_true_add(json_row, "helloOptionHoldtime"); - - if (option_lan_prune_delay) - json_object_boolean_true_add(json_row, "helloOptionLanPruneDelay"); - - if (option_t_bit) - json_object_boolean_true_add(json_row, "helloOptionTBit"); - - json_object_object_add(json_ifp, neigh_src_str, json_row); - - } else { - vty_out (vty, "Interface : %s\n", ifp->name); - vty_out (vty, "Neighbor : %s\n", neigh_src_str); - vty_out (vty, " Uptime : %s\n", uptime); - vty_out (vty, " Holdtime : %s\n", expire); - vty_out (vty, " DR Priority : %d\n", - neigh->dr_priority); - vty_out (vty, " Generation ID : %08x\n", - neigh->generation_id); - vty_out (vty, " Override Interval (msec) : %d\n", - neigh->override_interval_msec); - vty_out (vty, " Propagation Delay (msec) : %d\n", - neigh->propagation_delay_msec); - vty_out (vty, " Hello Option - Address List : %s\n", - option_address_list ? "yes" : "no"); - vty_out (vty, " Hello Option - DR Priority : %s\n", - option_dr_priority ? "yes" : "no"); - vty_out (vty, " Hello Option - Generation ID : %s\n", - option_generation_id ? "yes" : "no"); - vty_out (vty, " Hello Option - Holdtime : %s\n", - option_holdtime ? "yes" : "no"); - vty_out (vty, " Hello Option - LAN Prune Delay : %s\n", - option_lan_prune_delay ? "yes" : "no"); - vty_out (vty, " Hello Option - T-bit : %s\n", - option_t_bit ? "yes" : "no"); - pim_bfd_show_info (vty, neigh->bfd_info, json_ifp, uj, 0); - vty_out (vty, "\n"); - } - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } else { - { - if (!found_neighbor) - vty_out (vty, "%% No such interface or neighbor\n"); - } - } -} - -static void -pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_char uj) -{ - struct channel_oil *c_oil; - struct listnode *node; - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_ifp_in = NULL; - json_object *json_ifp_out = NULL; - json_object *json_source = NULL; - time_t now; - int first_oif; - now = pim_time_monotonic_sec(); - - if (uj) { - json = json_object_new_object(); - } else { - vty_out(vty, "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G)"); - vty_out (vty, "\nInstalled Source Group IIF OIL\n"); - } - - for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - char grp_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; - char in_ifname[INTERFACE_NAMSIZ+1]; - char out_ifname[INTERFACE_NAMSIZ+1]; - int oif_vif_index; - struct interface *ifp_in; - first_oif = 1; - - pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, sizeof(grp_str)); - pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str, sizeof(src_str)); - ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); - - if (ifp_in) - strcpy(in_ifname, ifp_in->name); - else - strcpy(in_ifname, "<iif?>"); - - if (src_or_group) - { - if (strcmp(src_or_group, src_str) && strcmp(src_or_group, grp_str)) - continue; - - if (group && strcmp(group, grp_str)) - continue; - } - - if (uj) { - - /* Find the group, create it if it doesn't exist */ - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - /* Find the source nested under the group, create it if it doesn't exist */ - json_object_object_get_ex(json_group, src_str, &json_source); - - if (!json_source) { - json_source = json_object_new_object(); - json_object_object_add(json_group, src_str, json_source); - } - - /* Find the inbound interface nested under the source, create it if it doesn't exist */ - json_object_object_get_ex(json_source, in_ifname, &json_ifp_in); - - if (!json_ifp_in) { - json_ifp_in = json_object_new_object(); - json_object_object_add(json_source, in_ifname, json_ifp_in); - json_object_int_add (json_source, "Installed", c_oil->installed); - json_object_int_add (json_source, "RefCount", c_oil->oil_ref_count); - json_object_int_add (json_source, "OilListSize", c_oil->oil_size); - json_object_int_add (json_source, "OilRescan", c_oil->oil_inherited_rescan); - json_object_int_add (json_source, "LastUsed", c_oil->cc.lastused); - json_object_int_add (json_source, "PacketCount", c_oil->cc.pktcnt); - json_object_int_add (json_source, "ByteCount", c_oil->cc.bytecnt); - json_object_int_add (json_source, "WrongInterface", c_oil->cc.wrong_if); - } - } else { - vty_out(vty, "%-9d %-15s %-15s %-7s ", - c_oil->installed, - src_str, - grp_str, - ifp_in->name); - } - - for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { - struct interface *ifp_out; - char oif_uptime[10]; - int ttl; - - ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; - if (ttl < 1) - continue; - - ifp_out = pim_if_find_by_vif_index(oif_vif_index); - pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - c_oil->oif_creation[oif_vif_index]); - - if (ifp_out) - strcpy(out_ifname, ifp_out->name); - else - strcpy(out_ifname, "<oif?>"); - - if (uj) { - json_ifp_out = json_object_new_object(); - json_object_string_add(json_ifp_out, "source", src_str); - json_object_string_add(json_ifp_out, "group", grp_str); - json_object_string_add(json_ifp_out, "inboundInterface", in_ifname); - json_object_string_add(json_ifp_out, "outboundInterface", out_ifname); - json_object_int_add(json_ifp_out, "installed", c_oil->installed); - - json_object_object_add(json_ifp_in, out_ifname, json_ifp_out); - } else { - if (first_oif) - { - first_oif = 0; - vty_out(vty, "%s(%c%c%c%c)", out_ifname, - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) ? 'I' : ' ', - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) ? 'J' : ' ', - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) ? 'S' : ' ', - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) ? '*' : ' '); - } - else - vty_out(vty, ", %s(%c%c%c%c)", out_ifname, - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) ? 'I' : ' ', - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) ? 'J' : ' ', - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) ? 'S' : ' ', - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) ? '*' : ' ' ); - } - } - - if (!uj) - vty_out (vty, "\n"); - } - - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } else { - vty_out (vty, "\n"); - } + struct pim_interface *pim_ifp; + struct in_addr ifaddr; + struct listnode *ch_node; + struct pim_ifchannel *ch; + time_t now; + json_object *json = NULL; + json_object *json_iface = NULL; + json_object *json_row = NULL; + json_object *json_grp = NULL; + + now = pim_time_monotonic_sec(); + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Interface Address Source Group State Uptime Expire Prune\n"); + + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + + pim_ifp = ch->interface->info; + + if (!pim_ifp) + continue; + + ifaddr = pim_ifp->primary_address; + + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char uptime[10]; + char expire[10]; + char prune[10]; + + pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, + sizeof(ch_src_str)); + pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, + sizeof(ch_grp_str)); + + pim_time_uptime_begin(uptime, sizeof(uptime), now, + ch->ifjoin_creation); + pim_time_timer_to_mmss(expire, sizeof(expire), + ch->t_ifjoin_expiry_timer); + pim_time_timer_to_mmss(prune, sizeof(prune), + ch->t_ifjoin_prune_pending_timer); + + if (uj) { + json_object_object_get_ex(json, ch->interface->name, + &json_iface); + + if (!json_iface) { + json_iface = json_object_new_object(); + json_object_pim_ifp_add(json_iface, + ch->interface); + json_object_object_add( + json, ch->interface->name, json_iface); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", ch_src_str); + json_object_string_add(json_row, "group", ch_grp_str); + json_object_string_add(json_row, "upTime", uptime); + json_object_string_add(json_row, "expire", expire); + json_object_string_add(json_row, "prune", prune); + json_object_string_add( + json_row, "channelJoinName", + pim_ifchannel_ifjoin_name(ch->ifjoin_state, + ch->flags)); + if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) + json_object_int_add(json_row, "SGRpt", 1); + + json_object_object_get_ex(json_iface, ch_grp_str, + &json_grp); + if (!json_grp) { + json_grp = json_object_new_object(); + json_object_object_add(json_grp, ch_src_str, + json_row); + json_object_object_add(json_iface, ch_grp_str, + json_grp); + } else + json_object_object_add(json_grp, ch_src_str, + json_row); + } else { + vty_out(vty, + "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s\n", + ch->interface->name, inet_ntoa(ifaddr), + ch_src_str, ch_grp_str, + pim_ifchannel_ifjoin_name(ch->ifjoin_state, + ch->flags), + uptime, expire, prune); + } + } /* scan interface channels */ + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, + u_char uj) +{ + struct listnode *node; + struct listnode *neighnode; + struct interface *ifp; + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; + time_t now; + int found_neighbor = 0; + int option_address_list; + int option_dr_priority; + int option_generation_id; + int option_holdtime; + int option_lan_prune_delay; + int option_t_bit; + char uptime[10]; + char expire[10]; + char neigh_src_str[INET_ADDRSTRLEN]; + + json_object *json = NULL; + json_object *json_ifp = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + + if (uj) + json = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, + neigh)) { + pim_inet4_dump("<src?>", neigh->source_addr, + neigh_src_str, sizeof(neigh_src_str)); + + /* + * The user can specify either the interface name or the + * PIM neighbor IP. + * If this pim_ifp matches neither then skip. + */ + if (strcmp(neighbor, "detail") + && strcmp(neighbor, ifp->name) + && strcmp(neighbor, neigh_src_str)) + continue; + + found_neighbor = 1; + pim_time_uptime(uptime, sizeof(uptime), + now - neigh->creation); + pim_time_timer_to_hhmmss(expire, sizeof(expire), + neigh->t_expire_timer); + + option_address_list = 0; + option_dr_priority = 0; + option_generation_id = 0; + option_holdtime = 0; + option_lan_prune_delay = 0; + option_t_bit = 0; + + if (PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_ADDRESS_LIST)) + option_address_list = 1; + + if (PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_DR_PRIORITY)) + option_dr_priority = 1; + + if (PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_GENERATION_ID)) + option_generation_id = 1; + + if (PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_HOLDTIME)) + option_holdtime = 1; + + if (PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY)) + option_lan_prune_delay = 1; + + if (PIM_OPTION_IS_SET( + neigh->hello_options, + PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)) + option_t_bit = 1; + + if (uj) { + + /* Does this ifp live in json? If not create + * it. */ + json_object_object_get_ex(json, ifp->name, + &json_ifp); + + if (!json_ifp) { + json_ifp = json_object_new_object(); + json_object_pim_ifp_add(json_ifp, ifp); + json_object_object_add(json, ifp->name, + json_ifp); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "interface", + ifp->name); + json_object_string_add(json_row, "address", + neigh_src_str); + json_object_string_add(json_row, "upTime", + uptime); + json_object_string_add(json_row, "holdtime", + expire); + json_object_int_add(json_row, "drPriority", + neigh->dr_priority); + json_object_int_add(json_row, "generationId", + neigh->generation_id); + + if (option_address_list) + json_object_boolean_true_add( + json_row, + "helloOptionAddressList"); + + if (option_dr_priority) + json_object_boolean_true_add( + json_row, + "helloOptionDrPriority"); + + if (option_generation_id) + json_object_boolean_true_add( + json_row, + "helloOptionGenerationId"); + + if (option_holdtime) + json_object_boolean_true_add( + json_row, + "helloOptionHoldtime"); + + if (option_lan_prune_delay) + json_object_boolean_true_add( + json_row, + "helloOptionLanPruneDelay"); + + if (option_t_bit) + json_object_boolean_true_add( + json_row, "helloOptionTBit"); + + json_object_object_add(json_ifp, neigh_src_str, + json_row); + + } else { + vty_out(vty, "Interface : %s\n", ifp->name); + vty_out(vty, "Neighbor : %s\n", neigh_src_str); + vty_out(vty, + " Uptime : %s\n", + uptime); + vty_out(vty, + " Holdtime : %s\n", + expire); + vty_out(vty, + " DR Priority : %d\n", + neigh->dr_priority); + vty_out(vty, + " Generation ID : %08x\n", + neigh->generation_id); + vty_out(vty, + " Override Interval (msec) : %d\n", + neigh->override_interval_msec); + vty_out(vty, + " Propagation Delay (msec) : %d\n", + neigh->propagation_delay_msec); + vty_out(vty, + " Hello Option - Address List : %s\n", + option_address_list ? "yes" : "no"); + vty_out(vty, + " Hello Option - DR Priority : %s\n", + option_dr_priority ? "yes" : "no"); + vty_out(vty, + " Hello Option - Generation ID : %s\n", + option_generation_id ? "yes" : "no"); + vty_out(vty, + " Hello Option - Holdtime : %s\n", + option_holdtime ? "yes" : "no"); + vty_out(vty, + " Hello Option - LAN Prune Delay : %s\n", + option_lan_prune_delay ? "yes" : "no"); + vty_out(vty, + " Hello Option - T-bit : %s\n", + option_t_bit ? "yes" : "no"); + pim_bfd_show_info(vty, neigh->bfd_info, + json_ifp, uj, 0); + vty_out(vty, "\n"); + } + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + { + if (!found_neighbor) + vty_out(vty, + "%% No such interface or neighbor\n"); + } + } +} + +static void pim_show_state(struct vty *vty, const char *src_or_group, + const char *group, u_char uj) +{ + struct channel_oil *c_oil; + struct listnode *node; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_ifp_in = NULL; + json_object *json_ifp_out = NULL; + json_object *json_source = NULL; + time_t now; + int first_oif; + now = pim_time_monotonic_sec(); + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, + "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G)"); + vty_out(vty, + "\nInstalled Source Group IIF OIL\n"); + } + + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { + char grp_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + char in_ifname[INTERFACE_NAMSIZ + 1]; + char out_ifname[INTERFACE_NAMSIZ + 1]; + int oif_vif_index; + struct interface *ifp_in; + first_oif = 1; + + pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, + sizeof(grp_str)); + pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str, + sizeof(src_str)); + ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); + + if (ifp_in) + strcpy(in_ifname, ifp_in->name); + else + strcpy(in_ifname, "<iif?>"); + + if (src_or_group) { + if (strcmp(src_or_group, src_str) + && strcmp(src_or_group, grp_str)) + continue; + + if (group && strcmp(group, grp_str)) + continue; + } + + if (uj) { + + /* Find the group, create it if it doesn't exist */ + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + /* Find the source nested under the group, create it if + * it doesn't exist */ + json_object_object_get_ex(json_group, src_str, + &json_source); + + if (!json_source) { + json_source = json_object_new_object(); + json_object_object_add(json_group, src_str, + json_source); + } + + /* Find the inbound interface nested under the source, + * create it if it doesn't exist */ + json_object_object_get_ex(json_source, in_ifname, + &json_ifp_in); + + if (!json_ifp_in) { + json_ifp_in = json_object_new_object(); + json_object_object_add(json_source, in_ifname, + json_ifp_in); + json_object_int_add(json_source, "Installed", + c_oil->installed); + json_object_int_add(json_source, "RefCount", + c_oil->oil_ref_count); + json_object_int_add(json_source, "OilListSize", + c_oil->oil_size); + json_object_int_add( + json_source, "OilRescan", + c_oil->oil_inherited_rescan); + json_object_int_add(json_source, "LastUsed", + c_oil->cc.lastused); + json_object_int_add(json_source, "PacketCount", + c_oil->cc.pktcnt); + json_object_int_add(json_source, "ByteCount", + c_oil->cc.bytecnt); + json_object_int_add(json_source, + "WrongInterface", + c_oil->cc.wrong_if); + } + } else { + vty_out(vty, "%-9d %-15s %-15s %-7s ", + c_oil->installed, src_str, grp_str, + ifp_in->name); + } + + for (oif_vif_index = 0; oif_vif_index < MAXVIFS; + ++oif_vif_index) { + struct interface *ifp_out; + char oif_uptime[10]; + int ttl; + + ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; + if (ttl < 1) + continue; + + ifp_out = pim_if_find_by_vif_index(oif_vif_index); + pim_time_uptime( + oif_uptime, sizeof(oif_uptime), + now - c_oil->oif_creation[oif_vif_index]); + + if (ifp_out) + strcpy(out_ifname, ifp_out->name); + else + strcpy(out_ifname, "<oif?>"); + + if (uj) { + json_ifp_out = json_object_new_object(); + json_object_string_add(json_ifp_out, "source", + src_str); + json_object_string_add(json_ifp_out, "group", + grp_str); + json_object_string_add(json_ifp_out, + "inboundInterface", + in_ifname); + json_object_string_add(json_ifp_out, + "outboundInterface", + out_ifname); + json_object_int_add(json_ifp_out, "installed", + c_oil->installed); + + json_object_object_add(json_ifp_in, out_ifname, + json_ifp_out); + } else { + if (first_oif) { + first_oif = 0; + vty_out(vty, "%s(%c%c%c%c)", out_ifname, + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_IGMP) + ? 'I' + : ' ', + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_PIM) + ? 'J' + : ' ', + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_SOURCE) + ? 'S' + : ' ', + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_STAR) + ? '*' + : ' '); + } else + vty_out(vty, ", %s(%c%c%c%c)", + out_ifname, + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_IGMP) + ? 'I' + : ' ', + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_PIM) + ? 'J' + : ' ', + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_SOURCE) + ? 'S' + : ' ', + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_STAR) + ? '*' + : ' '); + } + } + + if (!uj) + vty_out(vty, "\n"); + } + + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + vty_out(vty, "\n"); + } } static void pim_show_neighbors(struct vty *vty, u_char uj) { - struct listnode *node; - struct listnode *neighnode; - struct interface *ifp; - struct pim_interface *pim_ifp; - struct pim_neighbor *neigh; - time_t now; - char uptime[10]; - char expire[10]; - char neigh_src_str[INET_ADDRSTRLEN]; - json_object *json = NULL; - json_object *json_ifp_rows = NULL; - json_object *json_row = NULL; - - now = pim_time_monotonic_sec(); - - if (uj) { - json = json_object_new_object(); - } else { - vty_out (vty, "Interface Neighbor Uptime Holdtime DR Pri\n"); - } - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - if (uj) - json_ifp_rows = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - pim_inet4_dump("<src?>", neigh->source_addr, - neigh_src_str, sizeof(neigh_src_str)); - pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); - pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); - - if (uj) { - json_row = json_object_new_object(); - json_object_string_add(json_row, "interface", ifp->name); - json_object_string_add(json_row, "neighbor", neigh_src_str); - json_object_string_add(json_row, "upTime", uptime); - json_object_string_add(json_row, "holdTime", expire); - json_object_int_add(json_row, "holdTimeMax", neigh->holdtime); - json_object_int_add(json_row, "drPriority", neigh->dr_priority); - json_object_object_add(json_ifp_rows, neigh_src_str, json_row); - - } else { - vty_out (vty, "%-9s %15s %8s %8s %6d\n", - ifp->name, - neigh_src_str, - uptime, - expire, - neigh->dr_priority); - } - } - - if (uj) { - json_object_object_add(json, ifp->name, json_ifp_rows); - json_ifp_rows = NULL; - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + struct listnode *node; + struct listnode *neighnode; + struct interface *ifp; + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; + time_t now; + char uptime[10]; + char expire[10]; + char neigh_src_str[INET_ADDRSTRLEN]; + json_object *json = NULL; + json_object *json_ifp_rows = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, + "Interface Neighbor Uptime Holdtime DR Pri\n"); + } + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + if (uj) + json_ifp_rows = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, + neigh)) { + pim_inet4_dump("<src?>", neigh->source_addr, + neigh_src_str, sizeof(neigh_src_str)); + pim_time_uptime(uptime, sizeof(uptime), + now - neigh->creation); + pim_time_timer_to_hhmmss(expire, sizeof(expire), + neigh->t_expire_timer); + + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "interface", + ifp->name); + json_object_string_add(json_row, "neighbor", + neigh_src_str); + json_object_string_add(json_row, "upTime", + uptime); + json_object_string_add(json_row, "holdTime", + expire); + json_object_int_add(json_row, "holdTimeMax", + neigh->holdtime); + json_object_int_add(json_row, "drPriority", + neigh->dr_priority); + json_object_object_add(json_ifp_rows, + neigh_src_str, json_row); + + } else { + vty_out(vty, "%-9s %15s %8s %8s %6d\n", + ifp->name, neigh_src_str, uptime, + expire, neigh->dr_priority); + } + } + + if (uj) { + json_object_object_add(json, ifp->name, json_ifp_rows); + json_ifp_rows = NULL; + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } static void pim_show_neighbors_secondary(struct vty *vty) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - vty_out (vty, - "Interface Address Neighbor Secondary \n"); + vty_out(vty, + "Interface Address Neighbor Secondary \n"); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - struct listnode *neighnode; - struct pim_neighbor *neigh; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct pim_interface *pim_ifp; + struct in_addr ifaddr; + struct listnode *neighnode; + struct pim_neighbor *neigh; - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; + pim_ifp = ifp->info; - if (pim_ifp->pim_sock_fd < 0) - continue; + if (!pim_ifp) + continue; - ifaddr = pim_ifp->primary_address; + if (pim_ifp->pim_sock_fd < 0) + continue; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - char neigh_src_str[INET_ADDRSTRLEN]; - struct listnode *prefix_node; - struct prefix *p; + ifaddr = pim_ifp->primary_address; - if (!neigh->prefix_list) - continue; + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, + neigh)) { + char neigh_src_str[INET_ADDRSTRLEN]; + struct listnode *prefix_node; + struct prefix *p; - pim_inet4_dump("<src?>", neigh->source_addr, - neigh_src_str, sizeof(neigh_src_str)); + if (!neigh->prefix_list) + continue; - for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) { - char neigh_sec_str[PREFIX2STR_BUFFER]; + pim_inet4_dump("<src?>", neigh->source_addr, + neigh_src_str, sizeof(neigh_src_str)); - prefix2str(p, neigh_sec_str, sizeof(neigh_sec_str)); + for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, + prefix_node, p)) { + char neigh_sec_str[PREFIX2STR_BUFFER]; - vty_out (vty, "%-9s %-15s %-15s %-15s\n", - ifp->name, - inet_ntoa(ifaddr), - neigh_src_str, - neigh_sec_str); - } - } - } + prefix2str(p, neigh_sec_str, + sizeof(neigh_sec_str)); + + vty_out(vty, "%-9s %-15s %-15s %-15s\n", + ifp->name, inet_ntoa(ifaddr), + neigh_src_str, neigh_sec_str); + } + } + } } -static void -json_object_pim_upstream_add (json_object *json, struct pim_upstream *up) +static void json_object_pim_upstream_add(json_object *json, + struct pim_upstream *up) { - if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) - json_object_boolean_true_add(json, "drJoinDesired"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) - json_object_boolean_true_add(json, "drJoinDesiredUpdated"); + if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) + json_object_boolean_true_add(json, "drJoinDesired"); - if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) - json_object_boolean_true_add(json, "firstHopRouter"); + if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) + json_object_boolean_true_add(json, "drJoinDesiredUpdated"); - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) - json_object_boolean_true_add(json, "sourceIgmp"); + if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) + json_object_boolean_true_add(json, "firstHopRouter"); - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM) - json_object_boolean_true_add(json, "sourcePim"); + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + json_object_boolean_true_add(json, "sourceIgmp"); - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) - json_object_boolean_true_add(json, "sourceStream"); + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM) + json_object_boolean_true_add(json, "sourcePim"); - /* XXX: need to print ths flag in the plain text display as well */ - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) - json_object_boolean_true_add(json, "sourceMsdp"); -} + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) + json_object_boolean_true_add(json, "sourceStream"); -static const char * -pim_upstream_state2brief_str (enum pim_upstream_state join_state, char *state_str) -{ - switch (join_state) - { - case PIM_UPSTREAM_NOTJOINED: - strcpy (state_str, "NotJ"); - break; - case PIM_UPSTREAM_JOINED: - strcpy (state_str, "J"); - break; - default: - strcpy (state_str, "Unk"); - } - return state_str; + /* XXX: need to print ths flag in the plain text display as well */ + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) + json_object_boolean_true_add(json, "sourceMsdp"); } static const char * -pim_reg_state2brief_str (enum pim_reg_state reg_state, char *state_str) -{ - switch (reg_state) - { - case PIM_REG_NOINFO: - strcpy (state_str, "RegNI"); - break; - case PIM_REG_JOIN: - strcpy (state_str, "RegJ"); - break; - case PIM_REG_JOIN_PENDING: - case PIM_REG_PRUNE: - strcpy (state_str, "RegP"); - break; - default: - strcpy (state_str, "Unk"); - } - return state_str; +pim_upstream_state2brief_str(enum pim_upstream_state join_state, + char *state_str) +{ + switch (join_state) { + case PIM_UPSTREAM_NOTJOINED: + strcpy(state_str, "NotJ"); + break; + case PIM_UPSTREAM_JOINED: + strcpy(state_str, "J"); + break; + default: + strcpy(state_str, "Unk"); + } + return state_str; +} + +static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state, + char *state_str) +{ + switch (reg_state) { + case PIM_REG_NOINFO: + strcpy(state_str, "RegNI"); + break; + case PIM_REG_JOIN: + strcpy(state_str, "RegJ"); + break; + case PIM_REG_JOIN_PENDING: + case PIM_REG_PRUNE: + strcpy(state_str, "RegP"); + break; + default: + strcpy(state_str, "Unk"); + } + return state_str; } static void pim_show_upstream(struct vty *vty, u_char uj) { - struct listnode *upnode; - struct pim_upstream *up; - time_t now; - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_row = NULL; - - now = pim_time_monotonic_sec(); - - if (uj) - json = json_object_new_object(); - else - vty_out (vty, - "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n"); - - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - char uptime[10]; - char join_timer[10]; - char rs_timer[10]; - char ka_timer[10]; - char msdp_reg_timer[10]; - char state_str[PIM_REG_STATE_STR_LEN]; - - pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); - pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); - pim_time_timer_to_hhmmss (join_timer, sizeof(join_timer), up->t_join_timer); - - /* - * If we have a J/P timer for the neighbor display that - */ - if (!up->t_join_timer) - { - struct pim_neighbor *nbr; - - nbr = pim_neighbor_find (up->rpf.source_nexthop.interface, - up->rpf.rpf_addr.u.prefix4); - if (nbr) - pim_time_timer_to_hhmmss (join_timer, sizeof(join_timer), nbr->jp_timer); - } - - pim_time_timer_to_hhmmss (rs_timer, sizeof (rs_timer), up->t_rs_timer); - pim_time_timer_to_hhmmss (ka_timer, sizeof (ka_timer), up->t_ka_timer); - pim_time_timer_to_hhmmss (msdp_reg_timer, sizeof (msdp_reg_timer), up->t_msdp_reg_timer); - - pim_upstream_state2brief_str (up->join_state, state_str); - if (up->reg_state != PIM_REG_NOINFO) { - char tmp_str[PIM_REG_STATE_STR_LEN]; - - sprintf (state_str + strlen (state_str), ",%s", - pim_reg_state2brief_str (up->reg_state, tmp_str)); - } - - if (uj) { - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - json_row = json_object_new_object(); - json_object_pim_upstream_add(json_row, up); - json_object_string_add(json_row, "inboundInterface", up->rpf.source_nexthop.interface->name); - json_object_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - json_object_string_add(json_row, "state", state_str); - json_object_string_add(json_row, "joinState", pim_upstream_state2str (up->join_state)); - json_object_string_add(json_row, "regState", pim_reg_state2str (up->reg_state, state_str)); - json_object_string_add(json_row, "upTime", uptime); - json_object_string_add(json_row, "joinTimer", join_timer); - json_object_string_add(json_row, "resetTimer", rs_timer); - json_object_string_add(json_row, "keepaliveTimer", ka_timer); - json_object_string_add(json_row, "msdpRegTimer", msdp_reg_timer); - json_object_int_add(json_row, "refCount", up->ref_count); - json_object_int_add(json_row, "sptBit", up->sptbit); - json_object_object_add(json_group, src_str, json_row); - } else { - vty_out (vty, "%-10s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n", - up->rpf.source_nexthop.interface->name, - src_str, - grp_str, - state_str, - uptime, - join_timer, - rs_timer, - ka_timer, - up->ref_count); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + struct listnode *upnode; + struct pim_upstream *up; + time_t now; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n"); + + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char uptime[10]; + char join_timer[10]; + char rs_timer[10]; + char ka_timer[10]; + char msdp_reg_timer[10]; + char state_str[PIM_REG_STATE_STR_LEN]; + + pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); + pim_time_uptime(uptime, sizeof(uptime), + now - up->state_transition); + pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer), + up->t_join_timer); + + /* + * If we have a J/P timer for the neighbor display that + */ + if (!up->t_join_timer) { + struct pim_neighbor *nbr; + + nbr = pim_neighbor_find( + up->rpf.source_nexthop.interface, + up->rpf.rpf_addr.u.prefix4); + if (nbr) + pim_time_timer_to_hhmmss(join_timer, + sizeof(join_timer), + nbr->jp_timer); + } + + pim_time_timer_to_hhmmss(rs_timer, sizeof(rs_timer), + up->t_rs_timer); + pim_time_timer_to_hhmmss(ka_timer, sizeof(ka_timer), + up->t_ka_timer); + pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer), + up->t_msdp_reg_timer); + + pim_upstream_state2brief_str(up->join_state, state_str); + if (up->reg_state != PIM_REG_NOINFO) { + char tmp_str[PIM_REG_STATE_STR_LEN]; + + sprintf(state_str + strlen(state_str), ",%s", + pim_reg_state2brief_str(up->reg_state, + tmp_str)); + } + + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + json_row = json_object_new_object(); + json_object_pim_upstream_add(json_row, up); + json_object_string_add( + json_row, "inboundInterface", + up->rpf.source_nexthop.interface->name); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "state", state_str); + json_object_string_add( + json_row, "joinState", + pim_upstream_state2str(up->join_state)); + json_object_string_add( + json_row, "regState", + pim_reg_state2str(up->reg_state, state_str)); + json_object_string_add(json_row, "upTime", uptime); + json_object_string_add(json_row, "joinTimer", + join_timer); + json_object_string_add(json_row, "resetTimer", + rs_timer); + json_object_string_add(json_row, "keepaliveTimer", + ka_timer); + json_object_string_add(json_row, "msdpRegTimer", + msdp_reg_timer); + json_object_int_add(json_row, "refCount", + up->ref_count); + json_object_int_add(json_row, "sptBit", up->sptbit); + json_object_object_add(json_group, src_str, json_row); + } else { + vty_out(vty, + "%-10s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n", + up->rpf.source_nexthop.interface->name, src_str, + grp_str, state_str, uptime, join_timer, + rs_timer, ka_timer, up->ref_count); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } static void pim_show_join_desired(struct vty *vty, u_char uj) { - struct listnode *chnode; - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_row = NULL; - - if (uj) - json = json_object_new_object(); - else - vty_out (vty, - "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n"); - - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, chnode, ch)) { - /* scan all interfaces */ - pim_ifp = ch->interface->info; - if (!pim_ifp) - continue; - - struct pim_upstream *up = ch->upstream; - - pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); - - if (uj) { - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - json_row = json_object_new_object(); - json_object_pim_upstream_add(json_row, up); - json_object_string_add(json_row, "interface", ch->interface->name); - json_object_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - - if (pim_macro_ch_lost_assert(ch)) - json_object_boolean_true_add(json_row, "lostAssert"); - - if (pim_macro_chisin_joins(ch)) - json_object_boolean_true_add(json_row, "joins"); - - if (pim_macro_chisin_pim_include(ch)) - json_object_boolean_true_add(json_row, "pimInclude"); - - if (pim_upstream_evaluate_join_desired(up)) - json_object_boolean_true_add(json_row, "evaluateJoinDesired"); - - json_object_object_add(json_group, src_str, json_row); - - } else { - vty_out (vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n", - ch->interface->name, - src_str, - grp_str, - pim_macro_ch_lost_assert(ch) ? "yes" : "no", - pim_macro_chisin_joins(ch) ? "yes" : "no", - pim_macro_chisin_pim_include(ch) ? "yes" : "no", - PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags) ? "yes" : "no", - pim_upstream_evaluate_join_desired(up) ? "yes" : "no"); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + struct listnode *chnode; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n"); + + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, chnode, ch)) { + /* scan all interfaces */ + pim_ifp = ch->interface->info; + if (!pim_ifp) + continue; + + struct pim_upstream *up = ch->upstream; + + pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); + + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + json_row = json_object_new_object(); + json_object_pim_upstream_add(json_row, up); + json_object_string_add(json_row, "interface", + ch->interface->name); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + + if (pim_macro_ch_lost_assert(ch)) + json_object_boolean_true_add(json_row, + "lostAssert"); + + if (pim_macro_chisin_joins(ch)) + json_object_boolean_true_add(json_row, "joins"); + + if (pim_macro_chisin_pim_include(ch)) + json_object_boolean_true_add(json_row, + "pimInclude"); + + if (pim_upstream_evaluate_join_desired(up)) + json_object_boolean_true_add( + json_row, "evaluateJoinDesired"); + + json_object_object_add(json_group, src_str, json_row); + + } else { + vty_out(vty, + "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n", + ch->interface->name, src_str, grp_str, + pim_macro_ch_lost_assert(ch) ? "yes" : "no", + pim_macro_chisin_joins(ch) ? "yes" : "no", + pim_macro_chisin_pim_include(ch) ? "yes" : "no", + PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED( + up->flags) + ? "yes" + : "no", + pim_upstream_evaluate_join_desired(up) ? "yes" + : "no"); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } static void pim_show_upstream_rpf(struct vty *vty, u_char uj) { - struct listnode *upnode; - struct pim_upstream *up; - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_row = NULL; - - if (uj) - json = json_object_new_object(); - else - vty_out (vty, - "Source Group RpfIface RibNextHop RpfAddress \n"); - - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - char rpf_nexthop_str[PREFIX_STRLEN]; - char rpf_addr_str[PREFIX_STRLEN]; - struct pim_rpf *rpf; - const char *rpf_ifname; - - rpf = &up->rpf; - - pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); - pim_addr_dump("<nexthop?>", &rpf->source_nexthop.mrib_nexthop_addr, rpf_nexthop_str, sizeof(rpf_nexthop_str)); - pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); - - rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>"; - - if (uj) { - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - json_row = json_object_new_object(); - json_object_pim_upstream_add(json_row, up); - json_object_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - json_object_string_add(json_row, "rpfInterface", rpf_ifname); - json_object_string_add(json_row, "ribNexthop", rpf_nexthop_str); - json_object_string_add(json_row, "rpfAddress", rpf_addr_str); - json_object_object_add(json_group, src_str, json_row); - } else { - vty_out (vty, "%-15s %-15s %-8s %-15s %-15s\n", - src_str, - grp_str, - rpf_ifname, - rpf_nexthop_str, - rpf_addr_str); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } -} - -static void show_rpf_refresh_stats(struct vty *vty, time_t now, json_object *json) -{ - char refresh_uptime[10]; - - pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now, qpim_rpf_cache_refresh_last); - - if (json) { - json_object_int_add(json, "rpfCacheRefreshDelayMsecs", qpim_rpf_cache_refresh_delay_msec); - json_object_int_add(json, "rpfCacheRefreshTimer", pim_time_timer_remain_msec(qpim_rpf_cache_refresher)); - json_object_int_add(json, "rpfCacheRefreshRequests", qpim_rpf_cache_refresh_requests); - json_object_int_add(json, "rpfCacheRefreshEvents", qpim_rpf_cache_refresh_events); - json_object_string_add(json, "rpfCacheRefreshLast", refresh_uptime); - json_object_int_add(json, "nexthopLookups", qpim_nexthop_lookups); - json_object_int_add(json, "nexthopLookupsAvoided", nexthop_lookups_avoided); - } else { - vty_out (vty, - "RPF Cache Refresh Delay: %ld msecs\n" - "RPF Cache Refresh Timer: %ld msecs\n" - "RPF Cache Refresh Requests: %lld\n" - "RPF Cache Refresh Events: %lld\n" - "RPF Cache Refresh Last: %s\n" - "Nexthop Lookups: %lld\n" - "Nexthop Lookups Avoided: %lld\n", - qpim_rpf_cache_refresh_delay_msec, - pim_time_timer_remain_msec(qpim_rpf_cache_refresher), - (long long)qpim_rpf_cache_refresh_requests, - (long long)qpim_rpf_cache_refresh_events, - refresh_uptime, - (long long) qpim_nexthop_lookups, - (long long)nexthop_lookups_avoided); - } + struct listnode *upnode; + struct pim_upstream *up; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Source Group RpfIface RibNextHop RpfAddress \n"); + + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char rpf_nexthop_str[PREFIX_STRLEN]; + char rpf_addr_str[PREFIX_STRLEN]; + struct pim_rpf *rpf; + const char *rpf_ifname; + + rpf = &up->rpf; + + pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); + pim_addr_dump("<nexthop?>", + &rpf->source_nexthop.mrib_nexthop_addr, + rpf_nexthop_str, sizeof(rpf_nexthop_str)); + pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str, + sizeof(rpf_addr_str)); + + rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>"; + + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + json_row = json_object_new_object(); + json_object_pim_upstream_add(json_row, up); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "rpfInterface", + rpf_ifname); + json_object_string_add(json_row, "ribNexthop", + rpf_nexthop_str); + json_object_string_add(json_row, "rpfAddress", + rpf_addr_str); + json_object_object_add(json_group, src_str, json_row); + } else { + vty_out(vty, "%-15s %-15s %-8s %-15s %-15s\n", src_str, + grp_str, rpf_ifname, rpf_nexthop_str, + rpf_addr_str); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void show_rpf_refresh_stats(struct vty *vty, time_t now, + json_object *json) +{ + char refresh_uptime[10]; + + pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now, + qpim_rpf_cache_refresh_last); + + if (json) { + json_object_int_add(json, "rpfCacheRefreshDelayMsecs", + qpim_rpf_cache_refresh_delay_msec); + json_object_int_add( + json, "rpfCacheRefreshTimer", + pim_time_timer_remain_msec(qpim_rpf_cache_refresher)); + json_object_int_add(json, "rpfCacheRefreshRequests", + qpim_rpf_cache_refresh_requests); + json_object_int_add(json, "rpfCacheRefreshEvents", + qpim_rpf_cache_refresh_events); + json_object_string_add(json, "rpfCacheRefreshLast", + refresh_uptime); + json_object_int_add(json, "nexthopLookups", + qpim_nexthop_lookups); + json_object_int_add(json, "nexthopLookupsAvoided", + nexthop_lookups_avoided); + } else { + vty_out(vty, + "RPF Cache Refresh Delay: %ld msecs\n" + "RPF Cache Refresh Timer: %ld msecs\n" + "RPF Cache Refresh Requests: %lld\n" + "RPF Cache Refresh Events: %lld\n" + "RPF Cache Refresh Last: %s\n" + "Nexthop Lookups: %lld\n" + "Nexthop Lookups Avoided: %lld\n", + qpim_rpf_cache_refresh_delay_msec, + pim_time_timer_remain_msec(qpim_rpf_cache_refresher), + (long long)qpim_rpf_cache_refresh_requests, + (long long)qpim_rpf_cache_refresh_events, + refresh_uptime, (long long)qpim_nexthop_lookups, + (long long)nexthop_lookups_avoided); + } } static void show_scan_oil_stats(struct vty *vty, time_t now) { - char uptime_scan_oil[10]; - char uptime_mroute_add[10]; - char uptime_mroute_del[10]; + char uptime_scan_oil[10]; + char uptime_mroute_add[10]; + char uptime_mroute_del[10]; - pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now, qpim_scan_oil_last); - pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now, qpim_mroute_add_last); - pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now, qpim_mroute_del_last); + pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now, + qpim_scan_oil_last); + pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now, + qpim_mroute_add_last); + pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now, + qpim_mroute_del_last); - vty_out (vty, - "Scan OIL - Last: %s Events: %lld\n" - "MFC Add - Last: %s Events: %lld\n" - "MFC Del - Last: %s Events: %lld\n", - uptime_scan_oil, (long long) qpim_scan_oil_events, - uptime_mroute_add, (long long) qpim_mroute_add_events, - uptime_mroute_del, (long long)qpim_mroute_del_events); + vty_out(vty, + "Scan OIL - Last: %s Events: %lld\n" + "MFC Add - Last: %s Events: %lld\n" + "MFC Del - Last: %s Events: %lld\n", + uptime_scan_oil, (long long)qpim_scan_oil_events, + uptime_mroute_add, (long long)qpim_mroute_add_events, + uptime_mroute_del, (long long)qpim_mroute_del_events); } static void pim_show_rpf(struct vty *vty, u_char uj) { - struct listnode *up_node; - struct pim_upstream *up; - time_t now = pim_time_monotonic_sec(); - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_row = NULL; - - if (uj) { - json = json_object_new_object(); - show_rpf_refresh_stats(vty, now, json); - } else { - show_rpf_refresh_stats(vty, now, json); - vty_out (vty, "\n"); - vty_out (vty, - "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n"); - } - - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - char rpf_addr_str[PREFIX_STRLEN]; - char rib_nexthop_str[PREFIX_STRLEN]; - const char *rpf_ifname; - struct pim_rpf *rpf = &up->rpf; - - pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); - pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); - pim_addr_dump("<nexthop?>", &rpf->source_nexthop.mrib_nexthop_addr, rib_nexthop_str, sizeof(rib_nexthop_str)); - - rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>"; - - if (uj) { - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - json_object_string_add(json_row, "rpfInterface", rpf_ifname); - json_object_string_add(json_row, "rpfAddress", rpf_addr_str); - json_object_string_add(json_row, "ribNexthop", rib_nexthop_str); - json_object_int_add(json_row, "routeMetric", rpf->source_nexthop.mrib_route_metric); - json_object_int_add(json_row, "routePreference", rpf->source_nexthop.mrib_metric_preference); - json_object_object_add(json_group, src_str, json_row); - - } else { - vty_out (vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d\n", - src_str, - grp_str, - rpf_ifname, - rpf_addr_str, - rib_nexthop_str, - rpf->source_nexthop.mrib_route_metric, - rpf->source_nexthop.mrib_metric_preference); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } -} - -static int -pim_print_pnc_cache_walkcb (struct hash_backet *backet, void *arg) -{ - struct pim_nexthop_cache *pnc = backet->data; - struct vty *vty = arg; - struct nexthop *nh_node = NULL; - ifindex_t first_ifindex; - struct interface *ifp = NULL; - - if (!pnc) - return CMD_SUCCESS; - - for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) - { - first_ifindex = nh_node->ifindex; - ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT); - - vty_out (vty, "%-15s ", inet_ntoa (pnc->rpf.rpf_addr.u.prefix4)); - vty_out (vty, "%-14s ", ifp ? ifp->name : "NULL"); - vty_out (vty, "%s ", inet_ntoa (nh_node->gate.ipv4)); - vty_out (vty, "\n"); - } - return CMD_SUCCESS; -} - -static void -pim_show_nexthop (struct vty *vty) -{ - - if (pimg && !pimg->rpf_hash) - { - vty_out (vty, "no nexthop cache \n"); - return; - } - - vty_out (vty, "Number of registered addresses: %lu \n", - pimg->rpf_hash->count); - vty_out (vty, "Address Interface Nexthop\n"); - vty_out (vty, "-------------------------------------------\n"); - - hash_walk (pimg->rpf_hash, pim_print_pnc_cache_walkcb, vty); + struct listnode *up_node; + struct pim_upstream *up; + time_t now = pim_time_monotonic_sec(); + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + if (uj) { + json = json_object_new_object(); + show_rpf_refresh_stats(vty, now, json); + } else { + show_rpf_refresh_stats(vty, now, json); + vty_out(vty, "\n"); + vty_out(vty, + "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n"); + } + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char rpf_addr_str[PREFIX_STRLEN]; + char rib_nexthop_str[PREFIX_STRLEN]; + const char *rpf_ifname; + struct pim_rpf *rpf = &up->rpf; + + pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); + pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str, + sizeof(rpf_addr_str)); + pim_addr_dump("<nexthop?>", + &rpf->source_nexthop.mrib_nexthop_addr, + rib_nexthop_str, sizeof(rib_nexthop_str)); + + rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>"; + + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "rpfInterface", + rpf_ifname); + json_object_string_add(json_row, "rpfAddress", + rpf_addr_str); + json_object_string_add(json_row, "ribNexthop", + rib_nexthop_str); + json_object_int_add( + json_row, "routeMetric", + rpf->source_nexthop.mrib_route_metric); + json_object_int_add( + json_row, "routePreference", + rpf->source_nexthop.mrib_metric_preference); + json_object_object_add(json_group, src_str, json_row); + + } else { + vty_out(vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d\n", + src_str, grp_str, rpf_ifname, rpf_addr_str, + rib_nexthop_str, + rpf->source_nexthop.mrib_route_metric, + rpf->source_nexthop.mrib_metric_preference); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } -static void igmp_show_groups(struct vty *vty, u_char uj) +static int pim_print_pnc_cache_walkcb(struct hash_backet *backet, void *arg) { - struct listnode *ifnode; - struct interface *ifp; - time_t now; - json_object *json = NULL; - json_object *json_iface = NULL; - json_object *json_row = NULL; - - now = pim_time_monotonic_sec(); - - if (uj) - json = json_object_new_object(); - else - vty_out (vty, - "Interface Address Group Mode Timer Srcs V Uptime \n"); - - /* scan interfaces */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *sock_node; - struct igmp_sock *igmp; - - if (!pim_ifp) - continue; - - /* scan igmp sockets */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char ifaddr_str[INET_ADDRSTRLEN]; - struct listnode *grpnode; - struct igmp_group *grp; - - pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - - /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { - char group_str[INET_ADDRSTRLEN]; - char hhmmss[10]; - char uptime[10]; + struct pim_nexthop_cache *pnc = backet->data; + struct vty *vty = arg; + struct nexthop *nh_node = NULL; + ifindex_t first_ifindex; + struct interface *ifp = NULL; + + if (!pnc) + return CMD_SUCCESS; + + for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) { + first_ifindex = nh_node->ifindex; + ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); + + vty_out(vty, "%-15s ", inet_ntoa(pnc->rpf.rpf_addr.u.prefix4)); + vty_out(vty, "%-14s ", ifp ? ifp->name : "NULL"); + vty_out(vty, "%s ", inet_ntoa(nh_node->gate.ipv4)); + vty_out(vty, "\n"); + } + return CMD_SUCCESS; +} + +static void pim_show_nexthop(struct vty *vty) +{ + + if (pimg && !pimg->rpf_hash) { + vty_out(vty, "no nexthop cache \n"); + return; + } + + vty_out(vty, "Number of registered addresses: %lu \n", + pimg->rpf_hash->count); + vty_out(vty, "Address Interface Nexthop\n"); + vty_out(vty, "-------------------------------------------\n"); - pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str)); - pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss), grp->t_group_timer); - pim_time_uptime(uptime, sizeof(uptime), now - grp->group_creation); - - if (uj) { - json_object_object_get_ex(json, ifp->name, &json_iface); - - if (!json_iface) { - json_iface = json_object_new_object(); - json_object_pim_ifp_add(json_iface, ifp); - json_object_object_add(json, ifp->name, json_iface); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", ifaddr_str); - json_object_string_add(json_row, "group", group_str); - - if (grp->igmp_version == 3) - json_object_string_add(json_row, "mode", grp->group_filtermode_isexcl ? "EXCLUDE" : "INCLUDE"); - - json_object_string_add(json_row, "timer", hhmmss); - json_object_int_add(json_row, "sourcesCount", grp->group_source_list ? listcount(grp->group_source_list) : 0); - json_object_int_add(json_row, "version", grp->igmp_version); - json_object_string_add(json_row, "uptime", uptime); - json_object_object_add(json_iface, group_str, json_row); - - } else { - vty_out (vty, "%-9s %-15s %-15s %4s %8s %4d %d %8s\n", - ifp->name, - ifaddr_str, - group_str, - grp->igmp_version == 3 ? (grp->group_filtermode_isexcl ? "EXCL" : "INCL") : "----", - hhmmss, - grp->group_source_list ? listcount(grp->group_source_list) : 0, - grp->igmp_version, - uptime); - } - } /* scan igmp groups */ - } /* scan igmp sockets */ - } /* scan interfaces */ - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + hash_walk(pimg->rpf_hash, pim_print_pnc_cache_walkcb, vty); +} + +static void igmp_show_groups(struct vty *vty, u_char uj) +{ + struct listnode *ifnode; + struct interface *ifp; + time_t now; + json_object *json = NULL; + json_object *json_iface = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Interface Address Group Mode Timer Srcs V Uptime \n"); + + /* scan interfaces */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + struct pim_interface *pim_ifp = ifp->info; + struct listnode *sock_node; + struct igmp_sock *igmp; + + if (!pim_ifp) + continue; + + /* scan igmp sockets */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, + igmp)) { + char ifaddr_str[INET_ADDRSTRLEN]; + struct listnode *grpnode; + struct igmp_group *grp; + + pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, + grpnode, grp)) { + char group_str[INET_ADDRSTRLEN]; + char hhmmss[10]; + char uptime[10]; + + pim_inet4_dump("<group?>", grp->group_addr, + group_str, sizeof(group_str)); + pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss), + grp->t_group_timer); + pim_time_uptime(uptime, sizeof(uptime), + now - grp->group_creation); + + if (uj) { + json_object_object_get_ex( + json, ifp->name, &json_iface); + + if (!json_iface) { + json_iface = + json_object_new_object(); + json_object_pim_ifp_add( + json_iface, ifp); + json_object_object_add( + json, ifp->name, + json_iface); + } + + json_row = json_object_new_object(); + json_object_string_add( + json_row, "source", ifaddr_str); + json_object_string_add( + json_row, "group", group_str); + + if (grp->igmp_version == 3) + json_object_string_add( + json_row, "mode", + grp->group_filtermode_isexcl + ? "EXCLUDE" + : "INCLUDE"); + + json_object_string_add(json_row, + "timer", hhmmss); + json_object_int_add( + json_row, "sourcesCount", + grp->group_source_list + ? listcount( + grp->group_source_list) + : 0); + json_object_int_add(json_row, "version", + grp->igmp_version); + json_object_string_add( + json_row, "uptime", uptime); + json_object_object_add(json_iface, + group_str, + json_row); + + } else { + vty_out(vty, + "%-9s %-15s %-15s %4s %8s %4d %d %8s\n", + ifp->name, ifaddr_str, + group_str, + grp->igmp_version == 3 + ? (grp->group_filtermode_isexcl + ? "EXCL" + : "INCL") + : "----", + hhmmss, + grp->group_source_list + ? listcount( + grp->group_source_list) + : 0, + grp->igmp_version, uptime); + } + } /* scan igmp groups */ + } /* scan igmp sockets */ + } /* scan interfaces */ + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } static void igmp_show_group_retransmission(struct vty *vty) { - struct listnode *ifnode; - struct interface *ifp; - - vty_out (vty, - "Interface Address Group RetTimer Counter RetSrcs\n"); - - /* scan interfaces */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *sock_node; - struct igmp_sock *igmp; - - if (!pim_ifp) - continue; - - /* scan igmp sockets */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char ifaddr_str[INET_ADDRSTRLEN]; - struct listnode *grpnode; - struct igmp_group *grp; - - pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - - /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { - char group_str[INET_ADDRSTRLEN]; - char grp_retr_mmss[10]; - struct listnode *src_node; - struct igmp_source *src; - int grp_retr_sources = 0; - - pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str)); - pim_time_timer_to_mmss(grp_retr_mmss, sizeof(grp_retr_mmss), grp->t_group_query_retransmit_timer); - - - /* count group sources with retransmission state */ - for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node, src)) { - if (src->source_query_retransmit_count > 0) { - ++grp_retr_sources; - } - } - - vty_out (vty, "%-9s %-15s %-15s %-8s %7d %7d\n", - ifp->name, - ifaddr_str, - group_str, - grp_retr_mmss, - grp->group_specific_query_retransmit_count, - grp_retr_sources); - - } /* scan igmp groups */ - } /* scan igmp sockets */ - } /* scan interfaces */ + struct listnode *ifnode; + struct interface *ifp; + + vty_out(vty, + "Interface Address Group RetTimer Counter RetSrcs\n"); + + /* scan interfaces */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + struct pim_interface *pim_ifp = ifp->info; + struct listnode *sock_node; + struct igmp_sock *igmp; + + if (!pim_ifp) + continue; + + /* scan igmp sockets */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, + igmp)) { + char ifaddr_str[INET_ADDRSTRLEN]; + struct listnode *grpnode; + struct igmp_group *grp; + + pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, + grpnode, grp)) { + char group_str[INET_ADDRSTRLEN]; + char grp_retr_mmss[10]; + struct listnode *src_node; + struct igmp_source *src; + int grp_retr_sources = 0; + + pim_inet4_dump("<group?>", grp->group_addr, + group_str, sizeof(group_str)); + pim_time_timer_to_mmss( + grp_retr_mmss, sizeof(grp_retr_mmss), + grp->t_group_query_retransmit_timer); + + + /* count group sources with retransmission state + */ + for (ALL_LIST_ELEMENTS_RO( + grp->group_source_list, src_node, + src)) { + if (src->source_query_retransmit_count + > 0) { + ++grp_retr_sources; + } + } + + vty_out(vty, "%-9s %-15s %-15s %-8s %7d %7d\n", + ifp->name, ifaddr_str, group_str, + grp_retr_mmss, + grp->group_specific_query_retransmit_count, + grp_retr_sources); + + } /* scan igmp groups */ + } /* scan igmp sockets */ + } /* scan interfaces */ } static void igmp_show_sources(struct vty *vty) { - struct listnode *ifnode; - struct interface *ifp; - time_t now; - - now = pim_time_monotonic_sec(); - - vty_out (vty, - "Interface Address Group Source Timer Fwd Uptime \n"); - - /* scan interfaces */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *sock_node; - struct igmp_sock *igmp; - - if (!pim_ifp) - continue; - - /* scan igmp sockets */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char ifaddr_str[INET_ADDRSTRLEN]; - struct listnode *grpnode; - struct igmp_group *grp; - - pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - - /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { - char group_str[INET_ADDRSTRLEN]; - struct listnode *srcnode; - struct igmp_source *src; - - pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str)); - - /* scan group sources */ - for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) { - char source_str[INET_ADDRSTRLEN]; - char mmss[10]; - char uptime[10]; - - pim_inet4_dump("<source?>", src->source_addr, source_str, sizeof(source_str)); - - pim_time_timer_to_mmss(mmss, sizeof(mmss), src->t_source_timer); - - pim_time_uptime(uptime, sizeof(uptime), now - src->source_creation); - - vty_out (vty, "%-9s %-15s %-15s %-15s %5s %3s %8s\n", - ifp->name, - ifaddr_str, - group_str, - source_str, - mmss, - IGMP_SOURCE_TEST_FORWARDING(src->source_flags) ? "Y" : "N", - uptime); - - } /* scan group sources */ - } /* scan igmp groups */ - } /* scan igmp sockets */ - } /* scan interfaces */ + struct listnode *ifnode; + struct interface *ifp; + time_t now; + + now = pim_time_monotonic_sec(); + + vty_out(vty, + "Interface Address Group Source Timer Fwd Uptime \n"); + + /* scan interfaces */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + struct pim_interface *pim_ifp = ifp->info; + struct listnode *sock_node; + struct igmp_sock *igmp; + + if (!pim_ifp) + continue; + + /* scan igmp sockets */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, + igmp)) { + char ifaddr_str[INET_ADDRSTRLEN]; + struct listnode *grpnode; + struct igmp_group *grp; + + pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, + grpnode, grp)) { + char group_str[INET_ADDRSTRLEN]; + struct listnode *srcnode; + struct igmp_source *src; + + pim_inet4_dump("<group?>", grp->group_addr, + group_str, sizeof(group_str)); + + /* scan group sources */ + for (ALL_LIST_ELEMENTS_RO( + grp->group_source_list, srcnode, + src)) { + char source_str[INET_ADDRSTRLEN]; + char mmss[10]; + char uptime[10]; + + pim_inet4_dump( + "<source?>", src->source_addr, + source_str, sizeof(source_str)); + + pim_time_timer_to_mmss( + mmss, sizeof(mmss), + src->t_source_timer); + + pim_time_uptime( + uptime, sizeof(uptime), + now - src->source_creation); + + vty_out(vty, + "%-9s %-15s %-15s %-15s %5s %3s %8s\n", + ifp->name, ifaddr_str, + group_str, source_str, mmss, + IGMP_SOURCE_TEST_FORWARDING( + src->source_flags) + ? "Y" + : "N", + uptime); + + } /* scan group sources */ + } /* scan igmp groups */ + } /* scan igmp sockets */ + } /* scan interfaces */ } static void igmp_show_source_retransmission(struct vty *vty) { - struct listnode *ifnode; - struct interface *ifp; - - vty_out (vty, - "Interface Address Group Source Counter\n"); - - /* scan interfaces */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *sock_node; - struct igmp_sock *igmp; - - if (!pim_ifp) - continue; - - /* scan igmp sockets */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char ifaddr_str[INET_ADDRSTRLEN]; - struct listnode *grpnode; - struct igmp_group *grp; - - pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - - /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { - char group_str[INET_ADDRSTRLEN]; - struct listnode *srcnode; - struct igmp_source *src; - - pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str)); - - /* scan group sources */ - for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) { - char source_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("<source?>", src->source_addr, source_str, sizeof(source_str)); - - vty_out (vty, "%-9s %-15s %-15s %-15s %7d\n", - ifp->name, - ifaddr_str, - group_str, - source_str, - src->source_query_retransmit_count); - - } /* scan group sources */ - } /* scan igmp groups */ - } /* scan igmp sockets */ - } /* scan interfaces */ + struct listnode *ifnode; + struct interface *ifp; + + vty_out(vty, + "Interface Address Group Source Counter\n"); + + /* scan interfaces */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + struct pim_interface *pim_ifp = ifp->info; + struct listnode *sock_node; + struct igmp_sock *igmp; + + if (!pim_ifp) + continue; + + /* scan igmp sockets */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, + igmp)) { + char ifaddr_str[INET_ADDRSTRLEN]; + struct listnode *grpnode; + struct igmp_group *grp; + + pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, + grpnode, grp)) { + char group_str[INET_ADDRSTRLEN]; + struct listnode *srcnode; + struct igmp_source *src; + + pim_inet4_dump("<group?>", grp->group_addr, + group_str, sizeof(group_str)); + + /* scan group sources */ + for (ALL_LIST_ELEMENTS_RO( + grp->group_source_list, srcnode, + src)) { + char source_str[INET_ADDRSTRLEN]; + + pim_inet4_dump( + "<source?>", src->source_addr, + source_str, sizeof(source_str)); + + vty_out(vty, + "%-9s %-15s %-15s %-15s %7d\n", + ifp->name, ifaddr_str, + group_str, source_str, + src->source_query_retransmit_count); + + } /* scan group sources */ + } /* scan igmp groups */ + } /* scan igmp sockets */ + } /* scan interfaces */ } static void clear_igmp_interfaces() { - struct listnode *ifnode; - struct listnode *ifnextnode; - struct interface *ifp; + struct listnode *ifnode; + struct listnode *ifnextnode; + struct interface *ifp; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - pim_if_addr_del_all_igmp(ifp); - } + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, + ifp)) { + pim_if_addr_del_all_igmp(ifp); + } - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - pim_if_addr_add_all(ifp); - } + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, + ifp)) { + pim_if_addr_add_all(ifp); + } } static void clear_pim_interfaces() { - struct listnode *ifnode; - struct listnode *ifnextnode; - struct interface *ifp; + struct listnode *ifnode; + struct listnode *ifnextnode; + struct interface *ifp; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - if (ifp->info) { - pim_neighbor_delete_all(ifp, "interface cleared"); - } - } + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, + ifp)) { + if (ifp->info) { + pim_neighbor_delete_all(ifp, "interface cleared"); + } + } } static void clear_interfaces() { - clear_igmp_interfaces(); - clear_pim_interfaces(); + clear_igmp_interfaces(); + clear_pim_interfaces(); } DEFUN (clear_ip_interfaces, @@ -2600,9 +3052,9 @@ DEFUN (clear_ip_interfaces, IP_STR "Reset interfaces\n") { - clear_interfaces(); + clear_interfaces(); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (clear_ip_igmp_interfaces, @@ -2613,47 +3065,51 @@ DEFUN (clear_ip_igmp_interfaces, CLEAR_IP_IGMP_STR "Reset IGMP interfaces\n") { - clear_igmp_interfaces(); + clear_igmp_interfaces(); - return CMD_SUCCESS; + return CMD_SUCCESS; } static void mroute_add_all() { - struct listnode *node; - struct channel_oil *c_oil; - - for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) { - /* just log warning */ - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str); - } - } + struct listnode *node; + struct channel_oil *c_oil; + + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { + if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) { + /* just log warning */ + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC", + __FILE__, __PRETTY_FUNCTION__, source_str, + group_str); + } + } } static void mroute_del_all() { - struct listnode *node; - struct channel_oil *c_oil; - - for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - if (pim_mroute_del(c_oil, __PRETTY_FUNCTION__)) { - /* just log warning */ - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str); - } - } + struct listnode *node; + struct channel_oil *c_oil; + + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { + if (pim_mroute_del(c_oil, __PRETTY_FUNCTION__)) { + /* just log warning */ + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC", + __FILE__, __PRETTY_FUNCTION__, source_str, + group_str); + } + } } DEFUN (clear_ip_mroute, @@ -2663,10 +3119,10 @@ DEFUN (clear_ip_mroute, IP_STR "Reset multicast routes\n") { - mroute_del_all(); - mroute_add_all(); + mroute_del_all(); + mroute_add_all(); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (clear_ip_pim_interfaces, @@ -2677,9 +3133,9 @@ DEFUN (clear_ip_pim_interfaces, CLEAR_IP_PIM_STR "Reset PIM interfaces\n") { - clear_pim_interfaces(); + clear_pim_interfaces(); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (clear_ip_pim_interface_traffic, @@ -2691,34 +3147,33 @@ DEFUN (clear_ip_pim_interface_traffic, "Reset PIM interfaces\n" "Reset Protocol Packet counters\n") { - struct listnode *ifnode = NULL; - struct listnode *ifnextnode = NULL; - struct interface *ifp = NULL; - struct pim_interface *pim_ifp = NULL; - - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) - { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - pim_ifp->pim_ifstat_hello_recv = 0; - pim_ifp->pim_ifstat_hello_sent = 0; - pim_ifp->pim_ifstat_join_recv = 0; - pim_ifp->pim_ifstat_join_send = 0; - pim_ifp->pim_ifstat_prune_recv = 0; - pim_ifp->pim_ifstat_prune_send = 0; - pim_ifp->pim_ifstat_reg_recv = 0; - pim_ifp->pim_ifstat_reg_send = 0; - pim_ifp->pim_ifstat_reg_stop_recv = 0; - pim_ifp->pim_ifstat_reg_stop_send = 0; - pim_ifp->pim_ifstat_assert_recv = 0; - pim_ifp->pim_ifstat_assert_send = 0; - - } + struct listnode *ifnode = NULL; + struct listnode *ifnextnode = NULL; + struct interface *ifp = NULL; + struct pim_interface *pim_ifp = NULL; + + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, + ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + pim_ifp->pim_ifstat_hello_recv = 0; + pim_ifp->pim_ifstat_hello_sent = 0; + pim_ifp->pim_ifstat_join_recv = 0; + pim_ifp->pim_ifstat_join_send = 0; + pim_ifp->pim_ifstat_prune_recv = 0; + pim_ifp->pim_ifstat_prune_send = 0; + pim_ifp->pim_ifstat_reg_recv = 0; + pim_ifp->pim_ifstat_reg_send = 0; + pim_ifp->pim_ifstat_reg_stop_recv = 0; + pim_ifp->pim_ifstat_reg_stop_send = 0; + pim_ifp->pim_ifstat_assert_recv = 0; + pim_ifp->pim_ifstat_assert_send = 0; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (clear_ip_pim_oil, @@ -2729,9 +3184,9 @@ DEFUN (clear_ip_pim_oil, CLEAR_IP_PIM_STR "Rescan PIM OIL (output interface list)\n") { - pim_scan_oil(); + pim_scan_oil(); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_igmp_interface, @@ -2745,16 +3200,16 @@ DEFUN (show_ip_igmp_interface, "interface name\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - int idx = 0; + u_char uj = use_json(argc, argv); + int idx = 0; - if (argv_find(argv, argc, "detail", &idx) || - argv_find(argv, argc, "WORD", &idx)) - igmp_show_interfaces_single(vty, argv[idx]->arg, uj); - else - igmp_show_interfaces(vty, uj); + if (argv_find(argv, argc, "detail", &idx) + || argv_find(argv, argc, "WORD", &idx)) + igmp_show_interfaces_single(vty, argv[idx]->arg, uj); + else + igmp_show_interfaces(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_igmp_join, @@ -2765,9 +3220,9 @@ DEFUN (show_ip_igmp_join, IGMP_STR "IGMP static join information\n") { - igmp_show_interface_join(vty); + igmp_show_interface_join(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_igmp_groups, @@ -2779,10 +3234,10 @@ DEFUN (show_ip_igmp_groups, IGMP_GROUP_STR "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - igmp_show_groups(vty, uj); + u_char uj = use_json(argc, argv); + igmp_show_groups(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_igmp_groups_retransmissions, @@ -2794,9 +3249,9 @@ DEFUN (show_ip_igmp_groups_retransmissions, IGMP_GROUP_STR "IGMP group retransmissions\n") { - igmp_show_group_retransmission(vty); + igmp_show_group_retransmission(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_igmp_sources, @@ -2807,9 +3262,9 @@ DEFUN (show_ip_igmp_sources, IGMP_STR IGMP_SOURCE_STR) { - igmp_show_sources(vty); + igmp_show_sources(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_igmp_sources_retransmissions, @@ -2821,9 +3276,9 @@ DEFUN (show_ip_igmp_sources_retransmissions, IGMP_SOURCE_STR "IGMP source retransmissions\n") { - igmp_show_source_retransmission(vty); + igmp_show_source_retransmission(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_assert, @@ -2834,9 +3289,9 @@ DEFUN (show_ip_pim_assert, PIM_STR "PIM interface assert\n") { - pim_show_assert(vty); + pim_show_assert(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_assert_internal, @@ -2847,9 +3302,9 @@ DEFUN (show_ip_pim_assert_internal, PIM_STR "PIM interface internal assert state\n") { - pim_show_assert_internal(vty); + pim_show_assert_internal(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_assert_metric, @@ -2860,9 +3315,9 @@ DEFUN (show_ip_pim_assert_metric, PIM_STR "PIM interface assert metric\n") { - pim_show_assert_metric(vty); + pim_show_assert_metric(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_assert_winner_metric, @@ -2873,9 +3328,9 @@ DEFUN (show_ip_pim_assert_winner_metric, PIM_STR "PIM interface assert winner metric\n") { - pim_show_assert_winner_metric(vty); + pim_show_assert_winner_metric(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_interface, @@ -2889,17 +3344,17 @@ DEFUN (show_ip_pim_interface, "interface name\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - int idx = 0; + u_char uj = use_json(argc, argv); + int idx = 0; - if (argv_find(argv, argc, "WORD", &idx) || - argv_find(argv, argc, "detail", &idx)) - pim_show_interfaces_single(vty, argv[idx]->arg, uj); + if (argv_find(argv, argc, "WORD", &idx) + || argv_find(argv, argc, "detail", &idx)) + pim_show_interfaces_single(vty, argv[idx]->arg, uj); - else - pim_show_interfaces(vty, uj); + else + pim_show_interfaces(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_join, @@ -2911,10 +3366,10 @@ DEFUN (show_ip_pim_join, "PIM interface join information\n" JSON_STR) { - u_char uj = use_json(argc, argv); - pim_show_join(vty, uj); + u_char uj = use_json(argc, argv); + pim_show_join(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_local_membership, @@ -2926,10 +3381,10 @@ DEFUN (show_ip_pim_local_membership, "PIM interface local-membership\n" JSON_STR) { - u_char uj = use_json(argc, argv); - pim_show_membership(vty, uj); + u_char uj = use_json(argc, argv); + pim_show_membership(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_neighbor, @@ -2943,16 +3398,16 @@ DEFUN (show_ip_pim_neighbor, "Name of interface or neighbor\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - int idx = 0; + u_char uj = use_json(argc, argv); + int idx = 0; - if (argv_find(argv, argc, "detail", &idx) || - argv_find(argv, argc, "WORD", &idx)) - pim_show_neighbors_single(vty, argv[idx]->arg, uj); - else - pim_show_neighbors(vty, uj); + if (argv_find(argv, argc, "detail", &idx) + || argv_find(argv, argc, "WORD", &idx)) + pim_show_neighbors_single(vty, argv[idx]->arg, uj); + else + pim_show_neighbors(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_secondary, @@ -2963,9 +3418,9 @@ DEFUN (show_ip_pim_secondary, PIM_STR "PIM neighbor addresses\n") { - pim_show_neighbors_secondary(vty); + pim_show_neighbors_secondary(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_state, @@ -2979,23 +3434,21 @@ DEFUN (show_ip_pim_state, "Multicast address\n" "JavaScript Object Notation\n") { - const char *src_or_group = NULL; - const char *group = NULL; - u_char uj = use_json(argc, argv); - if (uj) - argc--; + const char *src_or_group = NULL; + const char *group = NULL; + u_char uj = use_json(argc, argv); + if (uj) + argc--; - if (argc == 6) - { - src_or_group = argv[4]->arg; - group = argv[5]->arg; - } - else if (argc == 5) - src_or_group = argv[4]->arg; + if (argc == 6) { + src_or_group = argv[4]->arg; + group = argv[5]->arg; + } else if (argc == 5) + src_or_group = argv[4]->arg; - pim_show_state(vty, src_or_group, group, uj); + pim_show_state(vty, src_or_group, group, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_upstream, @@ -3007,10 +3460,10 @@ DEFUN (show_ip_pim_upstream, "PIM upstream information\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - pim_show_upstream(vty, uj); + u_char uj = use_json(argc, argv); + pim_show_upstream(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_upstream_join_desired, @@ -3022,10 +3475,10 @@ DEFUN (show_ip_pim_upstream_join_desired, "PIM upstream join-desired\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - pim_show_join_desired(vty, uj); + u_char uj = use_json(argc, argv); + pim_show_join_desired(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_upstream_rpf, @@ -3037,10 +3490,10 @@ DEFUN (show_ip_pim_upstream_rpf, "PIM upstream source rpf\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - pim_show_upstream_rpf(vty, uj); + u_char uj = use_json(argc, argv); + pim_show_upstream_rpf(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_rp, @@ -3052,10 +3505,10 @@ DEFUN (show_ip_pim_rp, "PIM RP information\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - pim_rp_show_information (vty, uj); + u_char uj = use_json(argc, argv); + pim_rp_show_information(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_rpf, @@ -3067,10 +3520,10 @@ DEFUN (show_ip_pim_rpf, "PIM cached source rpf information\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - pim_show_rpf(vty, uj); + u_char uj = use_json(argc, argv); + pim_show_rpf(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_nexthop, @@ -3081,9 +3534,9 @@ DEFUN (show_ip_pim_nexthop, PIM_STR "PIM cached nexthop rpf information\n") { - pim_show_nexthop (vty); + pim_show_nexthop(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_nexthop_lookup, @@ -3096,75 +3549,70 @@ DEFUN (show_ip_pim_nexthop_lookup, "Source/RP address\n" "Multicast Group address\n") { - struct pim_nexthop_cache pnc; - struct prefix nht_p; - int result = 0; - struct in_addr src_addr, grp_addr; - struct in_addr vif_source; - const char *addr_str, *addr_str1; - struct prefix grp; - struct pim_nexthop nexthop; - char nexthop_addr_str[PREFIX_STRLEN]; - char grp_str[PREFIX_STRLEN]; - - addr_str = argv[4]->arg; - result = inet_pton (AF_INET, addr_str, &src_addr); - if (result <= 0) - { - vty_out (vty, "Bad unicast address %s: errno=%d: %s\n", - addr_str, errno, safe_strerror(errno)); - return CMD_WARNING; - } - - if (pim_is_group_224_4 (src_addr)) - { - vty_out (vty, "Invalid argument. Expected Valid Source Address.\n"); - return CMD_WARNING; - } - - addr_str1 = argv[5]->arg; - result = inet_pton (AF_INET, addr_str1, &grp_addr); - if (result <= 0) - { - vty_out (vty, "Bad unicast address %s: errno=%d: %s\n", - addr_str, errno, safe_strerror(errno)); - return CMD_WARNING; - } - - if (!pim_is_group_224_4 (grp_addr)) - { - vty_out (vty, - "Invalid argument. Expected Valid Multicast Group Address.\n"); - return CMD_WARNING; - } - - if (!pim_rp_set_upstream_addr (&vif_source, src_addr, grp_addr)) - return CMD_SUCCESS; - - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = vif_source; - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = grp_addr; - memset (&nexthop, 0, sizeof (nexthop)); - - if ((pim_find_or_track_nexthop (&nht_p, NULL, NULL, &pnc)) == 1) - { - //Compute PIM RPF using Cached nexthop - pim_ecmp_nexthop_search (&pnc, &nexthop, &nht_p, &grp, 0); - } - else - pim_ecmp_nexthop_lookup (&nexthop, vif_source, &nht_p, &grp, 0); - - pim_addr_dump ("<grp?>", &grp, grp_str, sizeof (grp_str)); - pim_addr_dump ("<nexthop?>", &nexthop.mrib_nexthop_addr, - nexthop_addr_str, sizeof (nexthop_addr_str)); - vty_out (vty, "Group %s --- Nexthop %s Interface %s \n", grp_str, - nexthop_addr_str, nexthop.interface->name); - - return CMD_SUCCESS; + struct pim_nexthop_cache pnc; + struct prefix nht_p; + int result = 0; + struct in_addr src_addr, grp_addr; + struct in_addr vif_source; + const char *addr_str, *addr_str1; + struct prefix grp; + struct pim_nexthop nexthop; + char nexthop_addr_str[PREFIX_STRLEN]; + char grp_str[PREFIX_STRLEN]; + + addr_str = argv[4]->arg; + result = inet_pton(AF_INET, addr_str, &src_addr); + if (result <= 0) { + vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str, + errno, safe_strerror(errno)); + return CMD_WARNING; + } + + if (pim_is_group_224_4(src_addr)) { + vty_out(vty, + "Invalid argument. Expected Valid Source Address.\n"); + return CMD_WARNING; + } + + addr_str1 = argv[5]->arg; + result = inet_pton(AF_INET, addr_str1, &grp_addr); + if (result <= 0) { + vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str, + errno, safe_strerror(errno)); + return CMD_WARNING; + } + + if (!pim_is_group_224_4(grp_addr)) { + vty_out(vty, + "Invalid argument. Expected Valid Multicast Group Address.\n"); + return CMD_WARNING; + } + + if (!pim_rp_set_upstream_addr(&vif_source, src_addr, grp_addr)) + return CMD_SUCCESS; + + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = vif_source; + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = grp_addr; + memset(&nexthop, 0, sizeof(nexthop)); + + if ((pim_find_or_track_nexthop(&nht_p, NULL, NULL, &pnc)) == 1) { + // Compute PIM RPF using Cached nexthop + pim_ecmp_nexthop_search(&pnc, &nexthop, &nht_p, &grp, 0); + } else + pim_ecmp_nexthop_lookup(&nexthop, vif_source, &nht_p, &grp, 0); + + pim_addr_dump("<grp?>", &grp, grp_str, sizeof(grp_str)); + pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr, + nexthop_addr_str, sizeof(nexthop_addr_str)); + vty_out(vty, "Group %s --- Nexthop %s Interface %s \n", grp_str, + nexthop_addr_str, nexthop.interface->name); + + return CMD_SUCCESS; } DEFUN (show_ip_pim_interface_traffic, @@ -3178,61 +3626,56 @@ DEFUN (show_ip_pim_interface_traffic, "Interface name\n" "JavaScript Object Notation\n") { - u_char uj = use_json (argc, argv); - int idx = 0; + u_char uj = use_json(argc, argv); + int idx = 0; - if (argv_find(argv, argc, "WORD", &idx)) - pim_show_interface_traffic_single (vty, argv[idx]->arg, uj); - else - pim_show_interface_traffic (vty, uj); + if (argv_find(argv, argc, "WORD", &idx)) + pim_show_interface_traffic_single(vty, argv[idx]->arg, uj); + else + pim_show_interface_traffic(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } static void show_multicast_interfaces(struct vty *vty) { - struct listnode *node; - struct interface *ifp; - - vty_out (vty, "\n"); - - vty_out (vty, - "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut\n"); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - struct sioc_vif_req vreq; - - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - memset(&vreq, 0, sizeof(vreq)); - vreq.vifi = pim_ifp->mroute_vif_index; - - if (ioctl(qpim_mroute_socket_fd, SIOCGETVIFCNT, &vreq)) { - zlog_warn("ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s\n", - (unsigned long)SIOCGETVIFCNT, - ifp->name, - pim_ifp->mroute_vif_index, - errno, - safe_strerror(errno)); - } - - ifaddr = pim_ifp->primary_address; - - vty_out (vty, "%-9s %-15s %3d %3d %7lu %7lu %10lu %10lu\n", - ifp->name, - inet_ntoa(ifaddr), - ifp->ifindex, - pim_ifp->mroute_vif_index, - (unsigned long) vreq.icount, - (unsigned long) vreq.ocount, - (unsigned long) vreq.ibytes, - (unsigned long)vreq.obytes); - } + struct listnode *node; + struct interface *ifp; + + vty_out(vty, "\n"); + + vty_out(vty, + "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut\n"); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct pim_interface *pim_ifp; + struct in_addr ifaddr; + struct sioc_vif_req vreq; + + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + memset(&vreq, 0, sizeof(vreq)); + vreq.vifi = pim_ifp->mroute_vif_index; + + if (ioctl(qpim_mroute_socket_fd, SIOCGETVIFCNT, &vreq)) { + zlog_warn( + "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s\n", + (unsigned long)SIOCGETVIFCNT, ifp->name, + pim_ifp->mroute_vif_index, errno, + safe_strerror(errno)); + } + + ifaddr = pim_ifp->primary_address; + + vty_out(vty, "%-9s %-15s %3d %3d %7lu %7lu %10lu %10lu\n", + ifp->name, inet_ntoa(ifaddr), ifp->ifindex, + pim_ifp->mroute_vif_index, (unsigned long)vreq.icount, + (unsigned long)vreq.ocount, (unsigned long)vreq.ibytes, + (unsigned long)vreq.obytes); + } } DEFUN (show_ip_multicast, @@ -3242,327 +3685,364 @@ DEFUN (show_ip_multicast, IP_STR "Multicast global information\n") { - time_t now = pim_time_monotonic_sec(); + time_t now = pim_time_monotonic_sec(); - char uptime[10]; + char uptime[10]; + + vty_out(vty, "Mroute socket descriptor: %d\n", qpim_mroute_socket_fd); - vty_out (vty, "Mroute socket descriptor: %d\n", - qpim_mroute_socket_fd); + pim_time_uptime(uptime, sizeof(uptime), + now - qpim_mroute_socket_creation); + vty_out(vty, "Mroute socket uptime: %s\n", uptime); - pim_time_uptime(uptime, sizeof(uptime), now - qpim_mroute_socket_creation); - vty_out (vty, "Mroute socket uptime: %s\n", - uptime); + vty_out(vty, "\n"); - vty_out (vty, "\n"); + pim_zebra_zclient_update(vty); + pim_zlookup_show_ip_multicast(vty); - pim_zebra_zclient_update (vty); - pim_zlookup_show_ip_multicast (vty); + vty_out(vty, "\n"); + vty_out(vty, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS); - vty_out (vty, "\n"); - vty_out (vty, "Maximum highest VifIndex: %d\n", - PIM_MAX_USABLE_VIFS); + vty_out(vty, "\n"); + vty_out(vty, "Upstream Join Timer: %d secs\n", qpim_t_periodic); + vty_out(vty, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME); + vty_out(vty, "PIM ECMP: %s\n", qpim_ecmp_enable ? "Enable" : "Disable"); + vty_out(vty, "PIM ECMP Rebalance: %s\n", + qpim_ecmp_rebalance_enable ? "Enable" : "Disable"); - vty_out (vty, "\n"); - vty_out (vty, "Upstream Join Timer: %d secs\n", - qpim_t_periodic); - vty_out (vty, "Join/Prune Holdtime: %d secs\n", - PIM_JP_HOLDTIME); - vty_out (vty, "PIM ECMP: %s\n", - qpim_ecmp_enable ? "Enable" : "Disable"); - vty_out (vty, "PIM ECMP Rebalance: %s\n", - qpim_ecmp_rebalance_enable ? "Enable" : "Disable"); + vty_out(vty, "\n"); - vty_out (vty, "\n"); + show_rpf_refresh_stats(vty, now, NULL); - show_rpf_refresh_stats(vty, now, NULL); + vty_out(vty, "\n"); - vty_out (vty, "\n"); + show_scan_oil_stats(vty, now); - show_scan_oil_stats(vty, now); + show_multicast_interfaces(vty); - show_multicast_interfaces(vty); - - return CMD_SUCCESS; + return CMD_SUCCESS; } static void show_mroute(struct vty *vty, u_char uj) { - struct listnode *node; - struct channel_oil *c_oil; - struct static_route *s_route; - time_t now; - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_source = NULL; - json_object *json_oil = NULL; - json_object *json_ifp_out = NULL; - int found_oif = 0; - int first = 1; - char grp_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; - char in_ifname[INTERFACE_NAMSIZ+1]; - char out_ifname[INTERFACE_NAMSIZ+1]; - int oif_vif_index; - struct interface *ifp_in; - char proto[100]; - - if (uj) { - json = json_object_new_object(); - } else { - vty_out (vty, - "Source Group Proto Input Output TTL Uptime\n"); - } - - now = pim_time_monotonic_sec(); - - /* print list of PIM and IGMP routes */ - for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - found_oif = 0; - first = 1; - if (!c_oil->installed && !uj) - continue; - - pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, sizeof(grp_str)); - pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str, sizeof(src_str)); - ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); - - if (ifp_in) - strcpy(in_ifname, ifp_in->name); - else - strcpy(in_ifname, "<iif?>"); - - if (uj) { - - /* Find the group, create it if it doesn't exist */ - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - /* Find the source nested under the group, create it if it doesn't exist */ - json_object_object_get_ex(json_group, src_str, &json_source); - - if (!json_source) { - json_source = json_object_new_object(); - json_object_object_add(json_group, src_str, json_source); - } - - /* Find the inbound interface nested under the source, create it if it doesn't exist */ - json_object_int_add(json_source, "installed", c_oil->installed); - json_object_int_add(json_source, "refCount", c_oil->oil_ref_count); - json_object_int_add(json_source, "oilSize", c_oil->oil_size); - json_object_int_add(json_source, "OilInheritedRescan", c_oil->oil_inherited_rescan); - json_object_string_add(json_source, "iif", in_ifname); - json_oil = NULL; - } - - for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { - struct interface *ifp_out; - char oif_uptime[10]; - int ttl; - - ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; - if (ttl < 1) - continue; - - ifp_out = pim_if_find_by_vif_index(oif_vif_index); - pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - c_oil->oif_creation[oif_vif_index]); - found_oif = 1; - - if (ifp_out) - strcpy(out_ifname, ifp_out->name); - else - strcpy(out_ifname, "<oif?>"); - - if (uj) { - json_ifp_out = json_object_new_object(); - json_object_string_add(json_ifp_out, "source", src_str); - json_object_string_add(json_ifp_out, "group", grp_str); - - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) - json_object_boolean_true_add(json_ifp_out, "protocolPim"); - - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) - json_object_boolean_true_add(json_ifp_out, "protocolIgmp"); - - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) - json_object_boolean_true_add(json_ifp_out, "protocolSource"); - - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) - json_object_boolean_true_add(json_ifp_out, "protocolInherited"); - - json_object_string_add(json_ifp_out, "inboundInterface", in_ifname); - json_object_int_add(json_ifp_out, "iVifI", c_oil->oil.mfcc_parent); - json_object_string_add(json_ifp_out, "outboundInterface", out_ifname); - json_object_int_add(json_ifp_out, "oVifI", oif_vif_index); - json_object_int_add(json_ifp_out, "ttl", ttl); - json_object_string_add(json_ifp_out, "upTime", oif_uptime); - if (!json_oil) { - json_oil = json_object_new_object(); - json_object_object_add(json_source, "oil", json_oil); - } - json_object_object_add(json_oil, out_ifname, json_ifp_out); - } else { - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) { - strcpy(proto, "PIM"); - } - - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) { - strcpy(proto, "IGMP"); - } - - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) { - strcpy(proto, "SRC"); - } - - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) { - strcpy(proto, "STAR"); - } - - vty_out (vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", - src_str, - grp_str, - proto, - in_ifname, - out_ifname, - ttl, - oif_uptime); - - if (first) - { - src_str[0] = '\0'; - grp_str[0] = '\0'; - in_ifname[0] = '\0'; - first = 0; - } - } - } - - if (!uj && !found_oif) { - vty_out (vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", - src_str, - grp_str, - "none", - in_ifname, - "none", - 0, - "--:--:--"); - } - } - - /* Print list of static routes */ - for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - first = 1; - - if (!s_route->c_oil.installed) - continue; - - pim_inet4_dump("<group?>", s_route->group, grp_str, sizeof(grp_str)); - pim_inet4_dump("<source?>", s_route->source, src_str, sizeof(src_str)); - ifp_in = pim_if_find_by_vif_index(s_route->iif); - found_oif = 0; - - if (ifp_in) - strcpy(in_ifname, ifp_in->name); - else - strcpy(in_ifname, "<iif?>"); - - if (uj) { - - /* Find the group, create it if it doesn't exist */ - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - /* Find the source nested under the group, create it if it doesn't exist */ - json_object_object_get_ex(json_group, src_str, &json_source); - - if (!json_source) { - json_source = json_object_new_object(); - json_object_object_add(json_group, src_str, json_source); - } - - json_object_string_add(json_source, "iif", in_ifname); - json_oil = NULL; - } else { - strcpy(proto, "STATIC"); - } - - for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { - struct interface *ifp_out; - char oif_uptime[10]; - int ttl; - - ttl = s_route->oif_ttls[oif_vif_index]; - if (ttl < 1) - continue; - - ifp_out = pim_if_find_by_vif_index(oif_vif_index); - pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - s_route->c_oil.oif_creation[oif_vif_index]); - found_oif = 1; - - if (ifp_out) - strcpy(out_ifname, ifp_out->name); - else - strcpy(out_ifname, "<oif?>"); - - if (uj) { - json_ifp_out = json_object_new_object(); - json_object_string_add(json_ifp_out, "source", src_str); - json_object_string_add(json_ifp_out, "group", grp_str); - json_object_boolean_true_add(json_ifp_out, "protocolStatic"); - json_object_string_add(json_ifp_out, "inboundInterface", in_ifname); - json_object_int_add(json_ifp_out, "iVifI", s_route->c_oil.oil.mfcc_parent); - json_object_string_add(json_ifp_out, "outboundInterface", out_ifname); - json_object_int_add(json_ifp_out, "oVifI", oif_vif_index); - json_object_int_add(json_ifp_out, "ttl", ttl); - json_object_string_add(json_ifp_out, "upTime", oif_uptime); - if (!json_oil) { - json_oil = json_object_new_object(); - json_object_object_add(json_source, "oil", json_oil); - } - json_object_object_add(json_oil, out_ifname, json_ifp_out); - } else { - vty_out (vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", - src_str, - grp_str, - proto, - in_ifname, - out_ifname, - ttl, - oif_uptime); - if (first) - { - src_str[0] = '\0'; - grp_str[0] = '\0'; - in_ifname[0] = '\0'; - first = 0; - } - } - } - - if (!uj && !found_oif) { - vty_out (vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", - src_str, - grp_str, - proto, - in_ifname, - "none", - 0, - "--:--:--"); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + struct listnode *node; + struct channel_oil *c_oil; + struct static_route *s_route; + time_t now; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_source = NULL; + json_object *json_oil = NULL; + json_object *json_ifp_out = NULL; + int found_oif = 0; + int first = 1; + char grp_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + char in_ifname[INTERFACE_NAMSIZ + 1]; + char out_ifname[INTERFACE_NAMSIZ + 1]; + int oif_vif_index; + struct interface *ifp_in; + char proto[100]; + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, + "Source Group Proto Input Output TTL Uptime\n"); + } + + now = pim_time_monotonic_sec(); + + /* print list of PIM and IGMP routes */ + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { + found_oif = 0; + first = 1; + if (!c_oil->installed && !uj) + continue; + + pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, + sizeof(grp_str)); + pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str, + sizeof(src_str)); + ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); + + if (ifp_in) + strcpy(in_ifname, ifp_in->name); + else + strcpy(in_ifname, "<iif?>"); + + if (uj) { + + /* Find the group, create it if it doesn't exist */ + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + /* Find the source nested under the group, create it if + * it doesn't exist */ + json_object_object_get_ex(json_group, src_str, + &json_source); + + if (!json_source) { + json_source = json_object_new_object(); + json_object_object_add(json_group, src_str, + json_source); + } + + /* Find the inbound interface nested under the source, + * create it if it doesn't exist */ + json_object_int_add(json_source, "installed", + c_oil->installed); + json_object_int_add(json_source, "refCount", + c_oil->oil_ref_count); + json_object_int_add(json_source, "oilSize", + c_oil->oil_size); + json_object_int_add(json_source, "OilInheritedRescan", + c_oil->oil_inherited_rescan); + json_object_string_add(json_source, "iif", in_ifname); + json_oil = NULL; + } + + for (oif_vif_index = 0; oif_vif_index < MAXVIFS; + ++oif_vif_index) { + struct interface *ifp_out; + char oif_uptime[10]; + int ttl; + + ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; + if (ttl < 1) + continue; + + ifp_out = pim_if_find_by_vif_index(oif_vif_index); + pim_time_uptime( + oif_uptime, sizeof(oif_uptime), + now - c_oil->oif_creation[oif_vif_index]); + found_oif = 1; + + if (ifp_out) + strcpy(out_ifname, ifp_out->name); + else + strcpy(out_ifname, "<oif?>"); + + if (uj) { + json_ifp_out = json_object_new_object(); + json_object_string_add(json_ifp_out, "source", + src_str); + json_object_string_add(json_ifp_out, "group", + grp_str); + + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_PIM) + json_object_boolean_true_add( + json_ifp_out, "protocolPim"); + + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_IGMP) + json_object_boolean_true_add( + json_ifp_out, "protocolIgmp"); + + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_SOURCE) + json_object_boolean_true_add( + json_ifp_out, "protocolSource"); + + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_STAR) + json_object_boolean_true_add( + json_ifp_out, + "protocolInherited"); + + json_object_string_add(json_ifp_out, + "inboundInterface", + in_ifname); + json_object_int_add(json_ifp_out, "iVifI", + c_oil->oil.mfcc_parent); + json_object_string_add(json_ifp_out, + "outboundInterface", + out_ifname); + json_object_int_add(json_ifp_out, "oVifI", + oif_vif_index); + json_object_int_add(json_ifp_out, "ttl", ttl); + json_object_string_add(json_ifp_out, "upTime", + oif_uptime); + if (!json_oil) { + json_oil = json_object_new_object(); + json_object_object_add(json_source, + "oil", json_oil); + } + json_object_object_add(json_oil, out_ifname, + json_ifp_out); + } else { + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_PIM) { + strcpy(proto, "PIM"); + } + + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_IGMP) { + strcpy(proto, "IGMP"); + } + + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_SOURCE) { + strcpy(proto, "SRC"); + } + + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_STAR) { + strcpy(proto, "STAR"); + } + + vty_out(vty, + "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", + src_str, grp_str, proto, in_ifname, + out_ifname, ttl, oif_uptime); + + if (first) { + src_str[0] = '\0'; + grp_str[0] = '\0'; + in_ifname[0] = '\0'; + first = 0; + } + } + } + + if (!uj && !found_oif) { + vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", + src_str, grp_str, "none", in_ifname, "none", 0, + "--:--:--"); + } + } + + /* Print list of static routes */ + for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { + first = 1; + + if (!s_route->c_oil.installed) + continue; + + pim_inet4_dump("<group?>", s_route->group, grp_str, + sizeof(grp_str)); + pim_inet4_dump("<source?>", s_route->source, src_str, + sizeof(src_str)); + ifp_in = pim_if_find_by_vif_index(s_route->iif); + found_oif = 0; + + if (ifp_in) + strcpy(in_ifname, ifp_in->name); + else + strcpy(in_ifname, "<iif?>"); + + if (uj) { + + /* Find the group, create it if it doesn't exist */ + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + /* Find the source nested under the group, create it if + * it doesn't exist */ + json_object_object_get_ex(json_group, src_str, + &json_source); + + if (!json_source) { + json_source = json_object_new_object(); + json_object_object_add(json_group, src_str, + json_source); + } + + json_object_string_add(json_source, "iif", in_ifname); + json_oil = NULL; + } else { + strcpy(proto, "STATIC"); + } + + for (oif_vif_index = 0; oif_vif_index < MAXVIFS; + ++oif_vif_index) { + struct interface *ifp_out; + char oif_uptime[10]; + int ttl; + + ttl = s_route->oif_ttls[oif_vif_index]; + if (ttl < 1) + continue; + + ifp_out = pim_if_find_by_vif_index(oif_vif_index); + pim_time_uptime( + oif_uptime, sizeof(oif_uptime), + now + - s_route->c_oil + .oif_creation[oif_vif_index]); + found_oif = 1; + + if (ifp_out) + strcpy(out_ifname, ifp_out->name); + else + strcpy(out_ifname, "<oif?>"); + + if (uj) { + json_ifp_out = json_object_new_object(); + json_object_string_add(json_ifp_out, "source", + src_str); + json_object_string_add(json_ifp_out, "group", + grp_str); + json_object_boolean_true_add(json_ifp_out, + "protocolStatic"); + json_object_string_add(json_ifp_out, + "inboundInterface", + in_ifname); + json_object_int_add( + json_ifp_out, "iVifI", + s_route->c_oil.oil.mfcc_parent); + json_object_string_add(json_ifp_out, + "outboundInterface", + out_ifname); + json_object_int_add(json_ifp_out, "oVifI", + oif_vif_index); + json_object_int_add(json_ifp_out, "ttl", ttl); + json_object_string_add(json_ifp_out, "upTime", + oif_uptime); + if (!json_oil) { + json_oil = json_object_new_object(); + json_object_object_add(json_source, + "oil", json_oil); + } + json_object_object_add(json_oil, out_ifname, + json_ifp_out); + } else { + vty_out(vty, + "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", + src_str, grp_str, proto, in_ifname, + out_ifname, ttl, oif_uptime); + if (first) { + src_str[0] = '\0'; + grp_str[0] = '\0'; + in_ifname[0] = '\0'; + first = 0; + } + } + } + + if (!uj && !found_oif) { + vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", + src_str, grp_str, proto, in_ifname, "none", 0, + "--:--:--"); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } DEFUN (show_ip_mroute, @@ -3573,65 +4053,63 @@ DEFUN (show_ip_mroute, MROUTE_STR JSON_STR) { - u_char uj = use_json(argc, argv); - show_mroute(vty, uj); - return CMD_SUCCESS; + u_char uj = use_json(argc, argv); + show_mroute(vty, uj); + return CMD_SUCCESS; } static void show_mroute_count(struct vty *vty) { - struct listnode *node; - struct channel_oil *c_oil; - struct static_route *s_route; + struct listnode *node; + struct channel_oil *c_oil; + struct static_route *s_route; - vty_out (vty, "\n"); - - vty_out (vty, - "Source Group LastUsed Packets Bytes WrongIf \n"); + vty_out(vty, "\n"); - /* Print PIM and IGMP route counts */ - for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; + vty_out(vty, + "Source Group LastUsed Packets Bytes WrongIf \n"); - if (!c_oil->installed) - continue; + /* Print PIM and IGMP route counts */ + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; - pim_mroute_update_counters (c_oil); + if (!c_oil->installed) + continue; - pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); + pim_mroute_update_counters(c_oil); - vty_out (vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n", - source_str, - group_str, - c_oil->cc.lastused/100, - c_oil->cc.pktcnt, - c_oil->cc.bytecnt, - c_oil->cc.wrong_if); - } + pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, + sizeof(group_str)); + pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); - /* Print static route counts */ - for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; + vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n", + source_str, group_str, c_oil->cc.lastused / 100, + c_oil->cc.pktcnt, c_oil->cc.bytecnt, + c_oil->cc.wrong_if); + } + + /* Print static route counts */ + for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; - if (!s_route->c_oil.installed) - continue; + if (!s_route->c_oil.installed) + continue; - pim_mroute_update_counters (&s_route->c_oil); + pim_mroute_update_counters(&s_route->c_oil); - pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str)); + pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, + source_str, sizeof(source_str)); - vty_out (vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n", - source_str, - group_str, - s_route->c_oil.cc.lastused, - s_route->c_oil.cc.pktcnt, - s_route->c_oil.cc.bytecnt, - s_route->c_oil.cc.wrong_if); - } + vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n", + source_str, group_str, s_route->c_oil.cc.lastused, + s_route->c_oil.cc.pktcnt, s_route->c_oil.cc.bytecnt, + s_route->c_oil.cc.wrong_if); + } } DEFUN (show_ip_mroute_count, @@ -3642,8 +4120,8 @@ DEFUN (show_ip_mroute_count, MROUTE_STR "Route and packet count data\n") { - show_mroute_count(vty); - return CMD_SUCCESS; + show_mroute_count(vty); + return CMD_SUCCESS; } DEFUN (show_ip_rib, @@ -3654,83 +4132,82 @@ DEFUN (show_ip_rib, RIB_STR "Unicast address\n") { - int idx_ipv4 = 3; - struct in_addr addr; - const char *addr_str; - struct pim_nexthop nexthop; - char nexthop_addr_str[PREFIX_STRLEN]; - int result; - - memset (&nexthop, 0, sizeof (nexthop)); - addr_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, addr_str, &addr); - if (result <= 0) { - vty_out (vty, "Bad unicast address %s: errno=%d: %s\n", - addr_str, errno, safe_strerror(errno)); - return CMD_WARNING; - } + int idx_ipv4 = 3; + struct in_addr addr; + const char *addr_str; + struct pim_nexthop nexthop; + char nexthop_addr_str[PREFIX_STRLEN]; + int result; + + memset(&nexthop, 0, sizeof(nexthop)); + addr_str = argv[idx_ipv4]->arg; + result = inet_pton(AF_INET, addr_str, &addr); + if (result <= 0) { + vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str, + errno, safe_strerror(errno)); + return CMD_WARNING; + } - if (pim_nexthop_lookup(&nexthop, addr, 0)) { - vty_out (vty, "Failure querying RIB nexthop for unicast address %s\n", - addr_str); - return CMD_WARNING; - } + if (pim_nexthop_lookup(&nexthop, addr, 0)) { + vty_out(vty, + "Failure querying RIB nexthop for unicast address %s\n", + addr_str); + return CMD_WARNING; + } - vty_out (vty, - "Address NextHop Interface Metric Preference\n"); + vty_out(vty, + "Address NextHop Interface Metric Preference\n"); - pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr, - nexthop_addr_str, sizeof(nexthop_addr_str)); + pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr, + nexthop_addr_str, sizeof(nexthop_addr_str)); - vty_out (vty, "%-15s %-15s %-9s %6d %10d\n", - addr_str, - nexthop_addr_str, - nexthop.interface ? nexthop.interface->name : "<ifname?>", - nexthop.mrib_route_metric, - nexthop.mrib_metric_preference); + vty_out(vty, "%-15s %-15s %-9s %6d %10d\n", addr_str, nexthop_addr_str, + nexthop.interface ? nexthop.interface->name : "<ifname?>", + nexthop.mrib_route_metric, nexthop.mrib_metric_preference); - return CMD_SUCCESS; + return CMD_SUCCESS; } static void show_ssmpingd(struct vty *vty) { - struct listnode *node; - struct ssmpingd_sock *ss; - time_t now; + struct listnode *node; + struct ssmpingd_sock *ss; + time_t now; - vty_out (vty, - "Source Socket Address Port Uptime Requests\n"); + vty_out(vty, + "Source Socket Address Port Uptime Requests\n"); - if (!qpim_ssmpingd_list) - return; + if (!qpim_ssmpingd_list) + return; - now = pim_time_monotonic_sec(); + now = pim_time_monotonic_sec(); - for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) { - char source_str[INET_ADDRSTRLEN]; - char ss_uptime[10]; - struct sockaddr_in bind_addr; - socklen_t len = sizeof(bind_addr); - char bind_addr_str[INET_ADDRSTRLEN]; + for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) { + char source_str[INET_ADDRSTRLEN]; + char ss_uptime[10]; + struct sockaddr_in bind_addr; + socklen_t len = sizeof(bind_addr); + char bind_addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str)); + pim_inet4_dump("<src?>", ss->source_addr, source_str, + sizeof(source_str)); - if (pim_socket_getsockname(ss->sock_fd, (struct sockaddr *) &bind_addr, &len)) { - vty_out (vty, "%% Failure reading socket name for ssmpingd source %s on fd=%d\n", - source_str, ss->sock_fd); - } + if (pim_socket_getsockname( + ss->sock_fd, (struct sockaddr *)&bind_addr, &len)) { + vty_out(vty, + "%% Failure reading socket name for ssmpingd source %s on fd=%d\n", + source_str, ss->sock_fd); + } - pim_inet4_dump("<addr?>", bind_addr.sin_addr, bind_addr_str, sizeof(bind_addr_str)); - pim_time_uptime(ss_uptime, sizeof(ss_uptime), now - ss->creation); + pim_inet4_dump("<addr?>", bind_addr.sin_addr, bind_addr_str, + sizeof(bind_addr_str)); + pim_time_uptime(ss_uptime, sizeof(ss_uptime), + now - ss->creation); - vty_out (vty, "%-15s %6d %-15s %5d %8s %8lld\n", - source_str, - ss->sock_fd, - bind_addr_str, - ntohs(bind_addr.sin_port), - ss_uptime, - (long long)ss->requests); - } + vty_out(vty, "%-15s %6d %-15s %5d %8s %8lld\n", source_str, + ss->sock_fd, bind_addr_str, ntohs(bind_addr.sin_port), + ss_uptime, (long long)ss->requests); + } } DEFUN (show_ip_ssmpingd, @@ -3740,89 +4217,82 @@ DEFUN (show_ip_ssmpingd, IP_STR SHOW_SSMPINGD_STR) { - show_ssmpingd(vty); - return CMD_SUCCESS; + show_ssmpingd(vty); + return CMD_SUCCESS; } -static int -pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const char *plist) +static int pim_rp_cmd_worker(struct vty *vty, const char *rp, const char *group, + const char *plist) { - int result; + int result; - result = pim_rp_new (rp, group, plist); + result = pim_rp_new(rp, group, plist); - if (result == PIM_MALLOC_FAIL) - { - vty_out (vty, "%% Out of memory\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_MALLOC_FAIL) { + vty_out(vty, "%% Out of memory\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_GROUP_BAD_ADDRESS) - { - vty_out (vty, "%% Bad group address specified: %s\n", group); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_GROUP_BAD_ADDRESS) { + vty_out(vty, "%% Bad group address specified: %s\n", group); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_RP_BAD_ADDRESS) - { - vty_out (vty, "%% Bad RP address specified: %s\n", rp); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_RP_BAD_ADDRESS) { + vty_out(vty, "%% Bad RP address specified: %s\n", rp); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_RP_NO_PATH) - { - vty_out (vty, "%% No Path to RP address specified: %s\n", rp); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_RP_NO_PATH) { + vty_out(vty, "%% No Path to RP address specified: %s\n", rp); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_GROUP_OVERLAP) - { - vty_out (vty, "%% Group range specified cannot overlap\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_GROUP_OVERLAP) { + vty_out(vty, "%% Group range specified cannot overlap\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_GROUP_PFXLIST_OVERLAP) - { - vty_out (vty, - "%% This group is already covered by a RP prefix-list\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_GROUP_PFXLIST_OVERLAP) { + vty_out(vty, + "%% This group is already covered by a RP prefix-list\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_RP_PFXLIST_IN_USE) - { - vty_out (vty, - "%% The same prefix-list cannot be applied to multiple RPs\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_RP_PFXLIST_IN_USE) { + vty_out(vty, + "%% The same prefix-list cannot be applied to multiple RPs\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -pim_cmd_spt_switchover (enum pim_spt_switchover spt, const char *plist) +static int pim_cmd_spt_switchover(enum pim_spt_switchover spt, + const char *plist) { - pimg->spt.switchover = spt; + pimg->spt.switchover = spt; - switch (pimg->spt.switchover) - { - case PIM_SPT_IMMEDIATE: - if (pimg->spt.plist) - XFREE (MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist); + switch (pimg->spt.switchover) { + case PIM_SPT_IMMEDIATE: + if (pimg->spt.plist) + XFREE(MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist); - pim_upstream_add_lhr_star_pimreg (); - break; - case PIM_SPT_INFINITY: - pim_upstream_remove_lhr_star_pimreg (plist); + pim_upstream_add_lhr_star_pimreg(); + break; + case PIM_SPT_INFINITY: + pim_upstream_remove_lhr_star_pimreg(plist); - if (pimg->spt.plist) - XFREE (MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist); + if (pimg->spt.plist) + XFREE(MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist); - if (plist) - pimg->spt.plist = XSTRDUP (MTYPE_PIM_SPT_PLIST_NAME, plist); - break; - } + if (plist) + pimg->spt.plist = + XSTRDUP(MTYPE_PIM_SPT_PLIST_NAME, plist); + break; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_pim_spt_switchover_infinity, @@ -3833,7 +4303,7 @@ DEFUN (ip_pim_spt_switchover_infinity, "SPT-Switchover\n" "Never switch to SPT Tree\n") { - return pim_cmd_spt_switchover (PIM_SPT_INFINITY, NULL); + return pim_cmd_spt_switchover(PIM_SPT_INFINITY, NULL); } DEFUN (ip_pim_spt_switchover_infinity_plist, @@ -3846,7 +4316,7 @@ DEFUN (ip_pim_spt_switchover_infinity_plist, "Prefix-List to control which groups to switch\n" "Prefix-List name\n") { - return pim_cmd_spt_switchover (PIM_SPT_INFINITY, argv[5]->arg); + return pim_cmd_spt_switchover(PIM_SPT_INFINITY, argv[5]->arg); } DEFUN (no_ip_pim_spt_switchover_infinity, @@ -3858,7 +4328,7 @@ DEFUN (no_ip_pim_spt_switchover_infinity, "SPT_Switchover\n" "Never switch to SPT Tree\n") { - return pim_cmd_spt_switchover (PIM_SPT_IMMEDIATE, NULL); + return pim_cmd_spt_switchover(PIM_SPT_IMMEDIATE, NULL); } DEFUN (no_ip_pim_spt_switchover_infinity_plist, @@ -3872,7 +4342,7 @@ DEFUN (no_ip_pim_spt_switchover_infinity_plist, "Prefix-List to control which groups to switch\n" "Prefix-List name\n") { - return pim_cmd_spt_switchover (PIM_SPT_IMMEDIATE, NULL); + return pim_cmd_spt_switchover(PIM_SPT_IMMEDIATE, NULL); } DEFUN (ip_pim_joinprune_time, @@ -3883,8 +4353,8 @@ DEFUN (ip_pim_joinprune_time, "Join Prune Send Interval\n" "Seconds\n") { - qpim_t_periodic = atoi(argv[3]->arg); - return CMD_SUCCESS; + qpim_t_periodic = atoi(argv[3]->arg); + return CMD_SUCCESS; } DEFUN (no_ip_pim_joinprune_time, @@ -3896,8 +4366,8 @@ DEFUN (no_ip_pim_joinprune_time, "Join Prune Send Interval\n" "Seconds\n") { - qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; - return CMD_SUCCESS; + qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; + return CMD_SUCCESS; } DEFUN (ip_pim_register_suppress, @@ -3908,8 +4378,8 @@ DEFUN (ip_pim_register_suppress, "Register Suppress Timer\n" "Seconds\n") { - qpim_register_suppress_time = atoi (argv[3]->arg); - return CMD_SUCCESS; + qpim_register_suppress_time = atoi(argv[3]->arg); + return CMD_SUCCESS; } DEFUN (no_ip_pim_register_suppress, @@ -3921,8 +4391,8 @@ DEFUN (no_ip_pim_register_suppress, "Register Suppress Timer\n" "Seconds\n") { - qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; - return CMD_SUCCESS; + qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; + return CMD_SUCCESS; } DEFUN (ip_pim_keep_alive, @@ -3933,8 +4403,8 @@ DEFUN (ip_pim_keep_alive, "Keep alive Timer\n" "Seconds\n") { - qpim_keep_alive_time = atoi (argv[3]->arg); - return CMD_SUCCESS; + qpim_keep_alive_time = atoi(argv[3]->arg); + return CMD_SUCCESS; } DEFUN (no_ip_pim_keep_alive, @@ -3946,8 +4416,8 @@ DEFUN (no_ip_pim_keep_alive, "Keep alive Timer\n" "Seconds\n") { - qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; - return CMD_SUCCESS; + qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; + return CMD_SUCCESS; } DEFUN (ip_pim_packets, @@ -3958,8 +4428,8 @@ DEFUN (ip_pim_packets, "packets to process at one time per fd\n" "Number of packets\n") { - qpim_packet_process = atoi (argv[3]->arg); - return CMD_SUCCESS; + qpim_packet_process = atoi(argv[3]->arg); + return CMD_SUCCESS; } DEFUN (no_ip_pim_packets, @@ -3971,8 +4441,8 @@ DEFUN (no_ip_pim_packets, "packets to process at one time per fd\n" "Number of packets\n") { - qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; - return CMD_SUCCESS; + qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; + return CMD_SUCCESS; } DEFUN (ip_pim_v6_secondary, @@ -3982,9 +4452,9 @@ DEFUN (ip_pim_v6_secondary, "pim multicast routing\n" "Send v6 secondary addresses\n") { - pimg->send_v6_secondary = 1; + pimg->send_v6_secondary = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_pim_v6_secondary, @@ -3995,9 +4465,9 @@ DEFUN (no_ip_pim_v6_secondary, "pim multicast routing\n" "Send v6 secondary addresses\n") { - pimg->send_v6_secondary = 0; + pimg->send_v6_secondary = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_pim_rp, @@ -4009,13 +4479,13 @@ DEFUN (ip_pim_rp, "ip address of RP\n" "Group Address range to cover\n") { - int idx_ipv4 = 3; - - if (argc == (idx_ipv4 + 1)) - return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, NULL, NULL); - else - return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL); + int idx_ipv4 = 3; + if (argc == (idx_ipv4 + 1)) + return pim_rp_cmd_worker(vty, argv[idx_ipv4]->arg, NULL, NULL); + else + return pim_rp_cmd_worker(vty, argv[idx_ipv4]->arg, + argv[idx_ipv4 + 1]->arg, NULL); } DEFUN (ip_pim_rp_prefix_list, @@ -4028,34 +4498,30 @@ DEFUN (ip_pim_rp_prefix_list, "group prefix-list filter\n" "Name of a prefix-list\n") { - return pim_rp_cmd_worker (vty, argv[3]->arg, NULL, argv[5]->arg); + return pim_rp_cmd_worker(vty, argv[3]->arg, NULL, argv[5]->arg); } -static int -pim_no_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, - const char *plist) +static int pim_no_rp_cmd_worker(struct vty *vty, const char *rp, + const char *group, const char *plist) { - int result = pim_rp_del (rp, group, plist); + int result = pim_rp_del(rp, group, plist); - if (result == PIM_GROUP_BAD_ADDRESS) - { - vty_out (vty, "%% Bad group address specified: %s\n", group); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_GROUP_BAD_ADDRESS) { + vty_out(vty, "%% Bad group address specified: %s\n", group); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_RP_BAD_ADDRESS) - { - vty_out (vty, "%% Bad RP address specified: %s\n", rp); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_RP_BAD_ADDRESS) { + vty_out(vty, "%% Bad RP address specified: %s\n", rp); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_RP_NOT_FOUND) - { - vty_out (vty, "%% Unable to find specified RP\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_RP_NOT_FOUND) { + vty_out(vty, "%% Unable to find specified RP\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_pim_rp, @@ -4068,12 +4534,14 @@ DEFUN (no_ip_pim_rp, "ip address of RP\n" "Group Address range to cover\n") { - int idx_ipv4 = 4, idx_group = 0; + int idx_ipv4 = 4, idx_group = 0; - if (argv_find (argv, argc, "A.B.C.D/M", &idx_group)) - return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_group]->arg, NULL); - else - return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, NULL, NULL); + if (argv_find(argv, argc, "A.B.C.D/M", &idx_group)) + return pim_no_rp_cmd_worker(vty, argv[idx_ipv4]->arg, + argv[idx_group]->arg, NULL); + else + return pim_no_rp_cmd_worker(vty, argv[idx_ipv4]->arg, NULL, + NULL); } DEFUN (no_ip_pim_rp_prefix_list, @@ -4087,30 +4555,28 @@ DEFUN (no_ip_pim_rp_prefix_list, "group prefix-list filter\n" "Name of a prefix-list\n") { - return pim_no_rp_cmd_worker (vty, argv[4]->arg, NULL, argv[6]->arg); + return pim_no_rp_cmd_worker(vty, argv[4]->arg, NULL, argv[6]->arg); } -static int -pim_ssm_cmd_worker (struct vty *vty, const char *plist) +static int pim_ssm_cmd_worker(struct vty *vty, const char *plist) { - int result = pim_ssm_range_set (VRF_DEFAULT, plist); + int result = pim_ssm_range_set(VRF_DEFAULT, plist); - if (result == PIM_SSM_ERR_NONE) - return CMD_SUCCESS; + if (result == PIM_SSM_ERR_NONE) + return CMD_SUCCESS; - switch (result) - { - case PIM_SSM_ERR_NO_VRF: - vty_out (vty, "%% VRF doesn't exist\n"); - break; - case PIM_SSM_ERR_DUP: - vty_out (vty, "%% duplicate config\n"); - break; - default: - vty_out (vty, "%% ssm range config failed\n"); - } + switch (result) { + case PIM_SSM_ERR_NO_VRF: + vty_out(vty, "%% VRF doesn't exist\n"); + break; + case PIM_SSM_ERR_DUP: + vty_out(vty, "%% duplicate config\n"); + break; + default: + vty_out(vty, "%% ssm range config failed\n"); + } - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (ip_pim_ssm_prefix_list, @@ -4122,7 +4588,7 @@ DEFUN (ip_pim_ssm_prefix_list, "group range prefix-list filter\n" "Name of a prefix-list\n") { - return pim_ssm_cmd_worker (vty, argv[0]->arg); + return pim_ssm_cmd_worker(vty, argv[0]->arg); } DEFUN (no_ip_pim_ssm_prefix_list, @@ -4134,7 +4600,7 @@ DEFUN (no_ip_pim_ssm_prefix_list, "Source Specific Multicast\n" "group range prefix-list filter\n") { - return pim_ssm_cmd_worker (vty, NULL); + return pim_ssm_cmd_worker(vty, NULL); } DEFUN (no_ip_pim_ssm_prefix_list_name, @@ -4147,34 +4613,31 @@ DEFUN (no_ip_pim_ssm_prefix_list_name, "group range prefix-list filter\n" "Name of a prefix-list\n") { - struct pim_ssm *ssm = pimg->ssm_info; + struct pim_ssm *ssm = pimg->ssm_info; - if (ssm->plist_name && !strcmp(ssm->plist_name, argv[0]->arg)) - return pim_ssm_cmd_worker (vty, NULL); + if (ssm->plist_name && !strcmp(ssm->plist_name, argv[0]->arg)) + return pim_ssm_cmd_worker(vty, NULL); - vty_out (vty, "%% pim ssm prefix-list %s doesn't exist\n", - argv[0]->arg); + vty_out(vty, "%% pim ssm prefix-list %s doesn't exist\n", argv[0]->arg); - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING_CONFIG_FAILED; } -static void -ip_pim_ssm_show_group_range(struct vty *vty, u_char uj) +static void ip_pim_ssm_show_group_range(struct vty *vty, u_char uj) { - struct pim_ssm *ssm = pimg->ssm_info; - const char *range_str = ssm->plist_name?ssm->plist_name:PIM_SSM_STANDARD_RANGE; + struct pim_ssm *ssm = pimg->ssm_info; + const char *range_str = + ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE; - if (uj) - { - json_object *json; - json = json_object_new_object(); - json_object_string_add(json, "ssmGroups", range_str); - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - vty_out (vty, "SSM group range : %s\n", range_str); + if (uj) { + json_object *json; + json = json_object_new_object(); + json_object_string_add(json, "ssmGroups", range_str); + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "SSM group range : %s\n", range_str); } DEFUN (show_ip_pim_ssm_range, @@ -4186,41 +4649,38 @@ DEFUN (show_ip_pim_ssm_range, "PIM group type\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - ip_pim_ssm_show_group_range(vty, uj); + u_char uj = use_json(argc, argv); + ip_pim_ssm_show_group_range(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -ip_pim_ssm_show_group_type(struct vty *vty, u_char uj, const char *group) +static void ip_pim_ssm_show_group_type(struct vty *vty, u_char uj, + const char *group) { - struct in_addr group_addr; - const char *type_str; - int result; + struct in_addr group_addr; + const char *type_str; + int result; - result = inet_pton(AF_INET, group, &group_addr); - if (result <= 0) - type_str = "invalid"; - else - { - if (pim_is_group_224_4 (group_addr)) - type_str = pim_is_grp_ssm (group_addr)?"SSM":"ASM"; - else - type_str = "not-multicast"; - } + result = inet_pton(AF_INET, group, &group_addr); + if (result <= 0) + type_str = "invalid"; + else { + if (pim_is_group_224_4(group_addr)) + type_str = pim_is_grp_ssm(group_addr) ? "SSM" : "ASM"; + else + type_str = "not-multicast"; + } - if (uj) - { - json_object *json; - json = json_object_new_object(); - json_object_string_add(json, "groupType", type_str); - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - vty_out (vty, "Group type : %s\n", type_str); + if (uj) { + json_object *json; + json = json_object_new_object(); + json_object_string_add(json, "groupType", type_str); + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "Group type : %s\n", type_str); } DEFUN (show_ip_pim_group_type, @@ -4233,10 +4693,10 @@ DEFUN (show_ip_pim_group_type, "group address\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - ip_pim_ssm_show_group_type(vty, uj, argv[0]->arg); + u_char uj = use_json(argc, argv); + ip_pim_ssm_show_group_type(vty, uj, argv[0]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (ip_multicast_routing, @@ -4245,7 +4705,7 @@ DEFUN_HIDDEN (ip_multicast_routing, IP_STR "Enable IP multicast forwarding\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (no_ip_multicast_routing, @@ -4255,9 +4715,9 @@ DEFUN_HIDDEN (no_ip_multicast_routing, IP_STR "Enable IP multicast forwarding\n") { - vty_out (vty, - "Command is Disabled and will be removed in a future version\n"); - return CMD_SUCCESS; + vty_out(vty, + "Command is Disabled and will be removed in a future version\n"); + return CMD_SUCCESS; } DEFUN (ip_ssmpingd, @@ -4267,26 +4727,26 @@ DEFUN (ip_ssmpingd, CONF_SSMPINGD_STR "Source address\n") { - int idx_ipv4 = 2; - int result; - struct in_addr source_addr; - const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0"; + int idx_ipv4 = 2; + int result; + struct in_addr source_addr; + const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0"; - result = inet_pton(AF_INET, source_str, &source_addr); - if (result <= 0) { - vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", - source_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + result = inet_pton(AF_INET, source_str, &source_addr); + if (result <= 0) { + vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", + source_str, errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - result = pim_ssmpingd_start(source_addr); - if (result) { - vty_out (vty, "%% Failure starting ssmpingd for source %s: %d\n", - source_str, result); - return CMD_WARNING_CONFIG_FAILED; - } + result = pim_ssmpingd_start(source_addr); + if (result) { + vty_out(vty, "%% Failure starting ssmpingd for source %s: %d\n", + source_str, result); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_ssmpingd, @@ -4297,26 +4757,26 @@ DEFUN (no_ip_ssmpingd, CONF_SSMPINGD_STR "Source address\n") { - int idx_ipv4 = 3; - int result; - struct in_addr source_addr; - const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0"; + int idx_ipv4 = 3; + int result; + struct in_addr source_addr; + const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0"; - result = inet_pton(AF_INET, source_str, &source_addr); - if (result <= 0) { - vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", - source_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + result = inet_pton(AF_INET, source_str, &source_addr); + if (result <= 0) { + vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", + source_str, errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - result = pim_ssmpingd_stop(source_addr); - if (result) { - vty_out (vty, "%% Failure stopping ssmpingd for source %s: %d\n", - source_str, result); - return CMD_WARNING_CONFIG_FAILED; - } + result = pim_ssmpingd_stop(source_addr); + if (result) { + vty_out(vty, "%% Failure stopping ssmpingd for source %s: %d\n", + source_str, result); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_pim_ecmp, @@ -4326,9 +4786,9 @@ DEFUN (ip_pim_ecmp, "pim multicast routing\n" "Enable PIM ECMP \n") { - qpim_ecmp_enable = 1; + qpim_ecmp_enable = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_pim_ecmp, @@ -4339,9 +4799,9 @@ DEFUN (no_ip_pim_ecmp, "pim multicast routing\n" "Disable PIM ECMP \n") { - qpim_ecmp_enable = 0; + qpim_ecmp_enable = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_pim_ecmp_rebalance, @@ -4352,10 +4812,10 @@ DEFUN (ip_pim_ecmp_rebalance, "Enable PIM ECMP \n" "Enable PIM ECMP Rebalance\n") { - qpim_ecmp_enable = 1; - qpim_ecmp_rebalance_enable = 1; + qpim_ecmp_enable = 1; + qpim_ecmp_rebalance_enable = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_pim_ecmp_rebalance, @@ -4367,48 +4827,41 @@ DEFUN (no_ip_pim_ecmp_rebalance, "Disable PIM ECMP \n" "Disable PIM ECMP Rebalance\n") { - qpim_ecmp_rebalance_enable = 0; + qpim_ecmp_rebalance_enable = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -pim_cmd_igmp_start (struct vty *vty, struct interface *ifp) +static int pim_cmd_igmp_start(struct vty *vty, struct interface *ifp) { - struct pim_interface *pim_ifp; - uint8_t need_startup = 0; + struct pim_interface *pim_ifp; + uint8_t need_startup = 0; - pim_ifp = ifp->info; + pim_ifp = ifp->info; - if (!pim_ifp) - { - pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */); - if (!pim_ifp) - { - vty_out (vty, "Could not enable IGMP on interface %s\n", - ifp->name); - return CMD_WARNING_CONFIG_FAILED; - } - need_startup = 1; - } - else - { - if (!PIM_IF_TEST_IGMP(pim_ifp->options)) - { - PIM_IF_DO_IGMP(pim_ifp->options); - need_startup = 1; - } - } + if (!pim_ifp) { + pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */); + if (!pim_ifp) { + vty_out(vty, "Could not enable IGMP on interface %s\n", + ifp->name); + return CMD_WARNING_CONFIG_FAILED; + } + need_startup = 1; + } else { + if (!PIM_IF_TEST_IGMP(pim_ifp->options)) { + PIM_IF_DO_IGMP(pim_ifp->options); + need_startup = 1; + } + } - /* 'ip igmp' executed multiple times, with need_startup - avoid multiple if add all and membership refresh */ - if (need_startup) - { - pim_if_addr_add_all(ifp); - pim_if_membership_refresh(ifp); - } + /* 'ip igmp' executed multiple times, with need_startup + avoid multiple if add all and membership refresh */ + if (need_startup) { + pim_if_addr_add_all(ifp); + pim_if_membership_refresh(ifp); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_ip_igmp, @@ -4417,9 +4870,9 @@ DEFUN (interface_ip_igmp, IP_STR IFACE_IGMP_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - return pim_cmd_igmp_start(vty, ifp); + return pim_cmd_igmp_start(vty, ifp); } DEFUN (interface_no_ip_igmp, @@ -4429,23 +4882,23 @@ DEFUN (interface_no_ip_igmp, IP_STR IFACE_IGMP_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - return CMD_SUCCESS; + if (!pim_ifp) + return CMD_SUCCESS; - PIM_IF_DONT_IGMP(pim_ifp->options); + PIM_IF_DONT_IGMP(pim_ifp->options); - pim_if_membership_clear(ifp); + pim_if_membership_clear(ifp); - pim_if_addr_del_all_igmp(ifp); + pim_if_addr_del_all_igmp(ifp); - if (!PIM_IF_TEST_PIM(pim_ifp->options)) { - pim_if_delete(ifp); - } + if (!PIM_IF_TEST_PIM(pim_ifp->options)) { + pim_if_delete(ifp); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_ip_igmp_join, @@ -4457,41 +4910,42 @@ DEFUN (interface_ip_igmp_join, "Multicast group address\n" "Source address\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_ipv4 = 3; - int idx_ipv4_2 = 4; - const char *group_str; - const char *source_str; - struct in_addr group_addr; - struct in_addr source_addr; - int result; - - /* Group address */ - group_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, group_str, &group_addr); - if (result <= 0) { - vty_out (vty, "Bad group address %s: errno=%d: %s\n", - group_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Source address */ - source_str = argv[idx_ipv4_2]->arg; - result = inet_pton(AF_INET, source_str, &source_addr); - if (result <= 0) { - vty_out (vty, "Bad source address %s: errno=%d: %s\n", - source_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - result = pim_if_igmp_join_add(ifp, group_addr, source_addr); - if (result) { - vty_out (vty, "%% Failure joining IGMP group %s source %s on interface %s: %d\n", - group_str, source_str, ifp->name, result); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = 3; + int idx_ipv4_2 = 4; + const char *group_str; + const char *source_str; + struct in_addr group_addr; + struct in_addr source_addr; + int result; + + /* Group address */ + group_str = argv[idx_ipv4]->arg; + result = inet_pton(AF_INET, group_str, &group_addr); + if (result <= 0) { + vty_out(vty, "Bad group address %s: errno=%d: %s\n", group_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Source address */ + source_str = argv[idx_ipv4_2]->arg; + result = inet_pton(AF_INET, source_str, &source_addr); + if (result <= 0) { + vty_out(vty, "Bad source address %s: errno=%d: %s\n", + source_str, errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + result = pim_if_igmp_join_add(ifp, group_addr, source_addr); + if (result) { + vty_out(vty, + "%% Failure joining IGMP group %s source %s on interface %s: %d\n", + group_str, source_str, ifp->name, result); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (interface_no_ip_igmp_join, @@ -4504,41 +4958,42 @@ DEFUN (interface_no_ip_igmp_join, "Multicast group address\n" "Source address\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - const char *group_str; - const char *source_str; - struct in_addr group_addr; - struct in_addr source_addr; - int result; - - /* Group address */ - group_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, group_str, &group_addr); - if (result <= 0) { - vty_out (vty, "Bad group address %s: errno=%d: %s\n", - group_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Source address */ - source_str = argv[idx_ipv4_2]->arg; - result = inet_pton(AF_INET, source_str, &source_addr); - if (result <= 0) { - vty_out (vty, "Bad source address %s: errno=%d: %s\n", - source_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - result = pim_if_igmp_join_del(ifp, group_addr, source_addr); - if (result) { - vty_out (vty, "%% Failure leaving IGMP group %s source %s on interface %s: %d\n", - group_str, source_str, ifp->name, result); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = 4; + int idx_ipv4_2 = 5; + const char *group_str; + const char *source_str; + struct in_addr group_addr; + struct in_addr source_addr; + int result; + + /* Group address */ + group_str = argv[idx_ipv4]->arg; + result = inet_pton(AF_INET, group_str, &group_addr); + if (result <= 0) { + vty_out(vty, "Bad group address %s: errno=%d: %s\n", group_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Source address */ + source_str = argv[idx_ipv4_2]->arg; + result = inet_pton(AF_INET, source_str, &source_addr); + if (result <= 0) { + vty_out(vty, "Bad source address %s: errno=%d: %s\n", + source_str, errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + result = pim_if_igmp_join_del(ifp, group_addr, source_addr); + if (result) { + vty_out(vty, + "%% Failure leaving IGMP group %s source %s on interface %s: %d\n", + group_str, source_str, ifp->name, result); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } /* @@ -4548,125 +5003,127 @@ DEFUN (interface_no_ip_igmp_join, */ static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp) { - struct interface *ifp; - struct pim_interface *pim_ifp; + struct interface *ifp; + struct pim_interface *pim_ifp; - zassert(igmp); + zassert(igmp); - /* other querier present? */ + /* other querier present? */ - if (igmp->t_other_querier_timer) - return; + if (igmp->t_other_querier_timer) + return; - /* this is the querier */ + /* this is the querier */ - zassert(igmp->interface); - zassert(igmp->interface->info); + zassert(igmp->interface); + zassert(igmp->interface->info); - ifp = igmp->interface; - pim_ifp = ifp->info; + ifp = igmp->interface; + pim_ifp = ifp->info; - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("%s: Querier %s on %s reconfig query_interval=%d", - __PRETTY_FUNCTION__, - ifaddr_str, - ifp->name, - pim_ifp->igmp_default_query_interval); - } + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug("%s: Querier %s on %s reconfig query_interval=%d", + __PRETTY_FUNCTION__, ifaddr_str, ifp->name, + pim_ifp->igmp_default_query_interval); + } - /* - igmp_startup_mode_on() will reset QQI: + /* + igmp_startup_mode_on() will reset QQI: - igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; - */ - igmp_startup_mode_on(igmp); + igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; + */ + igmp_startup_mode_on(igmp); } static void igmp_sock_query_reschedule(struct igmp_sock *igmp) { - if (igmp->t_igmp_query_timer) { - /* other querier present */ - zassert(igmp->t_igmp_query_timer); - zassert(!igmp->t_other_querier_timer); + if (igmp->t_igmp_query_timer) { + /* other querier present */ + zassert(igmp->t_igmp_query_timer); + zassert(!igmp->t_other_querier_timer); - pim_igmp_general_query_off(igmp); - pim_igmp_general_query_on(igmp); + pim_igmp_general_query_off(igmp); + pim_igmp_general_query_on(igmp); - zassert(igmp->t_igmp_query_timer); - zassert(!igmp->t_other_querier_timer); - } - else { - /* this is the querier */ + zassert(igmp->t_igmp_query_timer); + zassert(!igmp->t_other_querier_timer); + } else { + /* this is the querier */ - zassert(!igmp->t_igmp_query_timer); - zassert(igmp->t_other_querier_timer); + zassert(!igmp->t_igmp_query_timer); + zassert(igmp->t_other_querier_timer); - pim_igmp_other_querier_timer_off(igmp); - pim_igmp_other_querier_timer_on(igmp); + pim_igmp_other_querier_timer_off(igmp); + pim_igmp_other_querier_timer_on(igmp); - zassert(!igmp->t_igmp_query_timer); - zassert(igmp->t_other_querier_timer); - } + zassert(!igmp->t_igmp_query_timer); + zassert(igmp->t_other_querier_timer); + } } static void change_query_interval(struct pim_interface *pim_ifp, int query_interval) { - struct listnode *sock_node; - struct igmp_sock *igmp; + struct listnode *sock_node; + struct igmp_sock *igmp; - pim_ifp->igmp_default_query_interval = query_interval; + pim_ifp->igmp_default_query_interval = query_interval; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - igmp_sock_query_interval_reconfig(igmp); - igmp_sock_query_reschedule(igmp); - } + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { + igmp_sock_query_interval_reconfig(igmp); + igmp_sock_query_reschedule(igmp); + } } static void change_query_max_response_time(struct pim_interface *pim_ifp, int query_max_response_time_dsec) { - struct listnode *sock_node; - struct igmp_sock *igmp; - - pim_ifp->igmp_query_max_response_time_dsec = query_max_response_time_dsec; - - /* - Below we modify socket/group/source timers in order to quickly - reflect the change. Otherwise, those timers would eventually catch - up. - */ - - /* scan all sockets */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - struct listnode *grp_node; - struct igmp_group *grp; - - /* reschedule socket general query */ - igmp_sock_query_reschedule(igmp); - - /* scan socket groups */ - for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node, grp)) { - struct listnode *src_node; - struct igmp_source *src; - - /* reset group timers for groups in EXCLUDE mode */ - if (grp->group_filtermode_isexcl) { - igmp_group_reset_gmi(grp); - } - - /* scan group sources */ - for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node, src)) { - - /* reset source timers for sources with running timers */ - if (src->t_source_timer) { - igmp_source_reset_gmi(igmp, grp, src); + struct listnode *sock_node; + struct igmp_sock *igmp; + + pim_ifp->igmp_query_max_response_time_dsec = + query_max_response_time_dsec; + + /* + Below we modify socket/group/source timers in order to quickly + reflect the change. Otherwise, those timers would eventually catch + up. + */ + + /* scan all sockets */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { + struct listnode *grp_node; + struct igmp_group *grp; + + /* reschedule socket general query */ + igmp_sock_query_reschedule(igmp); + + /* scan socket groups */ + for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node, + grp)) { + struct listnode *src_node; + struct igmp_source *src; + + /* reset group timers for groups in EXCLUDE mode */ + if (grp->group_filtermode_isexcl) { + igmp_group_reset_gmi(grp); + } + + /* scan group sources */ + for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, + src_node, src)) { + + /* reset source timers for sources with running + * timers */ + if (src->t_source_timer) { + igmp_source_reset_gmi(igmp, grp, src); + } + } + } } - } - } - } } #define IGMP_QUERY_INTERVAL_MIN (1) @@ -4680,49 +5137,50 @@ DEFUN (interface_ip_igmp_query_interval, IFACE_IGMP_QUERY_INTERVAL_STR "Query interval in seconds\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; - int query_interval; - int query_interval_dsec; - int ret; - - if (!pim_ifp) { - ret = pim_cmd_igmp_start(vty, ifp); - if (ret != CMD_SUCCESS) - return ret; - pim_ifp = ifp->info; - } - - query_interval = atoi(argv[3]->arg); - query_interval_dsec = 10 * query_interval; - - /* - It seems we don't need to check bounds since command.c does it - already, but we verify them anyway for extra safety. - */ - if (query_interval < IGMP_QUERY_INTERVAL_MIN) { - vty_out (vty, "General query interval %d lower than minimum %d\n", - query_interval, - IGMP_QUERY_INTERVAL_MIN); - return CMD_WARNING_CONFIG_FAILED; - } - if (query_interval > IGMP_QUERY_INTERVAL_MAX) { - vty_out (vty, "General query interval %d higher than maximum %d\n", - query_interval, - IGMP_QUERY_INTERVAL_MAX); - return CMD_WARNING_CONFIG_FAILED; - } - - if (query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) { - vty_out (vty, - "Can't set general query interval %d dsec <= query max response time %d dsec.\n", - query_interval_dsec,pim_ifp->igmp_query_max_response_time_dsec); - return CMD_WARNING_CONFIG_FAILED; - } - - change_query_interval(pim_ifp, query_interval); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + int query_interval; + int query_interval_dsec; + int ret; + + if (!pim_ifp) { + ret = pim_cmd_igmp_start(vty, ifp); + if (ret != CMD_SUCCESS) + return ret; + pim_ifp = ifp->info; + } + + query_interval = atoi(argv[3]->arg); + query_interval_dsec = 10 * query_interval; + + /* + It seems we don't need to check bounds since command.c does it + already, but we verify them anyway for extra safety. + */ + if (query_interval < IGMP_QUERY_INTERVAL_MIN) { + vty_out(vty, + "General query interval %d lower than minimum %d\n", + query_interval, IGMP_QUERY_INTERVAL_MIN); + return CMD_WARNING_CONFIG_FAILED; + } + if (query_interval > IGMP_QUERY_INTERVAL_MAX) { + vty_out(vty, + "General query interval %d higher than maximum %d\n", + query_interval, IGMP_QUERY_INTERVAL_MAX); + return CMD_WARNING_CONFIG_FAILED; + } + + if (query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) { + vty_out(vty, + "Can't set general query interval %d dsec <= query max response time %d dsec.\n", + query_interval_dsec, + pim_ifp->igmp_query_max_response_time_dsec); + return CMD_WARNING_CONFIG_FAILED; + } + + change_query_interval(pim_ifp, query_interval); + + return CMD_SUCCESS; } DEFUN (interface_no_ip_igmp_query_interval, @@ -4733,26 +5191,27 @@ DEFUN (interface_no_ip_igmp_query_interval, IFACE_IGMP_STR IFACE_IGMP_QUERY_INTERVAL_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; - int default_query_interval_dsec; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + int default_query_interval_dsec; - if (!pim_ifp) - return CMD_SUCCESS; + if (!pim_ifp) + return CMD_SUCCESS; - default_query_interval_dsec = IGMP_GENERAL_QUERY_INTERVAL * 10; + default_query_interval_dsec = IGMP_GENERAL_QUERY_INTERVAL * 10; - if (default_query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) { - vty_out (vty, - "Can't set default general query interval %d dsec <= query max response time %d dsec.\n", - default_query_interval_dsec, - pim_ifp->igmp_query_max_response_time_dsec); - return CMD_WARNING_CONFIG_FAILED; - } + if (default_query_interval_dsec + <= pim_ifp->igmp_query_max_response_time_dsec) { + vty_out(vty, + "Can't set default general query interval %d dsec <= query max response time %d dsec.\n", + default_query_interval_dsec, + pim_ifp->igmp_query_max_response_time_dsec); + return CMD_WARNING_CONFIG_FAILED; + } - change_query_interval(pim_ifp, IGMP_GENERAL_QUERY_INTERVAL); + change_query_interval(pim_ifp, IGMP_GENERAL_QUERY_INTERVAL); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_ip_igmp_version, @@ -4763,37 +5222,36 @@ DEFUN (interface_ip_igmp_version, "IGMP version\n" "IGMP version number\n") { - VTY_DECLVAR_CONTEXT(interface,ifp); - struct pim_interface *pim_ifp = ifp->info; - int igmp_version, old_version = 0; - int ret; - - if (!pim_ifp) - { - ret = pim_cmd_igmp_start(vty, ifp); - if (ret != CMD_SUCCESS) - return ret; - pim_ifp = ifp->info; - } - - igmp_version = atoi(argv[3]->arg); - old_version = pim_ifp->igmp_version; - pim_ifp->igmp_version = igmp_version; - - //Check if IGMP is Enabled otherwise, enable on interface - if (!PIM_IF_TEST_IGMP (pim_ifp->options)) - { - PIM_IF_DO_IGMP(pim_ifp->options); - pim_if_addr_add_all(ifp); - pim_if_membership_refresh(ifp); - old_version = igmp_version; //avoid refreshing membership again. - } - /* Current and new version is different refresh existing - membership. Going from 3 -> 2 or 2 -> 3. */ - if (old_version != igmp_version) - pim_if_membership_refresh(ifp); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + int igmp_version, old_version = 0; + int ret; + + if (!pim_ifp) { + ret = pim_cmd_igmp_start(vty, ifp); + if (ret != CMD_SUCCESS) + return ret; + pim_ifp = ifp->info; + } + + igmp_version = atoi(argv[3]->arg); + old_version = pim_ifp->igmp_version; + pim_ifp->igmp_version = igmp_version; + + // Check if IGMP is Enabled otherwise, enable on interface + if (!PIM_IF_TEST_IGMP(pim_ifp->options)) { + PIM_IF_DO_IGMP(pim_ifp->options); + pim_if_addr_add_all(ifp); + pim_if_membership_refresh(ifp); + old_version = igmp_version; // avoid refreshing membership + // again. + } + /* Current and new version is different refresh existing + membership. Going from 3 -> 2 or 2 -> 3. */ + if (old_version != igmp_version) + pim_if_membership_refresh(ifp); + + return CMD_SUCCESS; } DEFUN (interface_no_ip_igmp_version, @@ -4805,15 +5263,15 @@ DEFUN (interface_no_ip_igmp_version, "IGMP version\n" "IGMP version number\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - return CMD_SUCCESS; + if (!pim_ifp) + return CMD_SUCCESS; - pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; + pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; - return CMD_SUCCESS; + return CMD_SUCCESS; } #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10) @@ -4827,30 +5285,32 @@ DEFUN (interface_ip_igmp_query_max_response_time, IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR "Query response value in deci-seconds\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; - int query_max_response_time; - int ret; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + int query_max_response_time; + int ret; - if (!pim_ifp) { - ret = pim_cmd_igmp_start(vty, ifp); - if (ret != CMD_SUCCESS) - return ret; - pim_ifp = ifp->info; - } + if (!pim_ifp) { + ret = pim_cmd_igmp_start(vty, ifp); + if (ret != CMD_SUCCESS) + return ret; + pim_ifp = ifp->info; + } - query_max_response_time = atoi(argv[3]->arg); + query_max_response_time = atoi(argv[3]->arg); - if (query_max_response_time >= pim_ifp->igmp_default_query_interval * 10) { - vty_out (vty, - "Can't set query max response time %d sec >= general query interval %d sec\n", - query_max_response_time,pim_ifp->igmp_default_query_interval); - return CMD_WARNING_CONFIG_FAILED; - } + if (query_max_response_time + >= pim_ifp->igmp_default_query_interval * 10) { + vty_out(vty, + "Can't set query max response time %d sec >= general query interval %d sec\n", + query_max_response_time, + pim_ifp->igmp_default_query_interval); + return CMD_WARNING_CONFIG_FAILED; + } - change_query_max_response_time(pim_ifp, query_max_response_time); + change_query_max_response_time(pim_ifp, query_max_response_time); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_no_ip_igmp_query_max_response_time, @@ -4862,15 +5322,16 @@ DEFUN (interface_no_ip_igmp_query_max_response_time, IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR "Time for response in deci-seconds\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - return CMD_SUCCESS; + if (!pim_ifp) + return CMD_SUCCESS; - change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); + change_query_max_response_time(pim_ifp, + IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); - return CMD_SUCCESS; + return CMD_SUCCESS; } #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10) @@ -4884,33 +5345,34 @@ DEFUN_HIDDEN (interface_ip_igmp_query_max_response_time_dsec, IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR "Query response value in deciseconds\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; - int query_max_response_time_dsec; - int default_query_interval_dsec; - int ret; - - if (!pim_ifp) { - ret = pim_cmd_igmp_start(vty, ifp); - if (ret != CMD_SUCCESS) - return ret; - pim_ifp = ifp->info; - } + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + int query_max_response_time_dsec; + int default_query_interval_dsec; + int ret; + + if (!pim_ifp) { + ret = pim_cmd_igmp_start(vty, ifp); + if (ret != CMD_SUCCESS) + return ret; + pim_ifp = ifp->info; + } - query_max_response_time_dsec = atoi(argv[4]->arg); + query_max_response_time_dsec = atoi(argv[4]->arg); - default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval; + default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval; - if (query_max_response_time_dsec >= default_query_interval_dsec) { - vty_out (vty, - "Can't set query max response time %d dsec >= general query interval %d dsec\n", - query_max_response_time_dsec,default_query_interval_dsec); - return CMD_WARNING_CONFIG_FAILED; - } + if (query_max_response_time_dsec >= default_query_interval_dsec) { + vty_out(vty, + "Can't set query max response time %d dsec >= general query interval %d dsec\n", + query_max_response_time_dsec, + default_query_interval_dsec); + return CMD_WARNING_CONFIG_FAILED; + } - change_query_max_response_time(pim_ifp, query_max_response_time_dsec); + change_query_max_response_time(pim_ifp, query_max_response_time_dsec); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec, @@ -4921,15 +5383,16 @@ DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec, IFACE_IGMP_STR IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - return CMD_SUCCESS; + if (!pim_ifp) + return CMD_SUCCESS; - change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); + change_query_max_response_time(pim_ifp, + IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_ip_pim_drprio, @@ -4940,26 +5403,26 @@ DEFUN (interface_ip_pim_drprio, "Set the Designated Router Election Priority\n" "Value of the new DR Priority\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_number = 3; - struct pim_interface *pim_ifp = ifp->info; - uint32_t old_dr_prio; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_number = 3; + struct pim_interface *pim_ifp = ifp->info; + uint32_t old_dr_prio; - if (!pim_ifp) { - vty_out (vty, "Please enable PIM on interface, first\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!pim_ifp) { + vty_out(vty, "Please enable PIM on interface, first\n"); + return CMD_WARNING_CONFIG_FAILED; + } - old_dr_prio = pim_ifp->pim_dr_priority; + old_dr_prio = pim_ifp->pim_dr_priority; - pim_ifp->pim_dr_priority = strtol(argv[idx_number]->arg, NULL, 10); + pim_ifp->pim_dr_priority = strtol(argv[idx_number]->arg, NULL, 10); - if (old_dr_prio != pim_ifp->pim_dr_priority) { - if (pim_if_dr_election(ifp)) - pim_hello_restart_now(ifp); - } + if (old_dr_prio != pim_ifp->pim_dr_priority) { + if (pim_if_dr_election(ifp)) + pim_hello_restart_now(ifp); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_no_ip_pim_drprio, @@ -4971,41 +5434,39 @@ DEFUN (interface_no_ip_pim_drprio, "Revert the Designated Router Priority to default\n" "Old Value of the Priority\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) { - vty_out (vty, "Pim not enabled on this interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!pim_ifp) { + vty_out(vty, "Pim not enabled on this interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) { - pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY; - if (pim_if_dr_election(ifp)) - pim_hello_restart_now(ifp); - } + if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) { + pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY; + if (pim_if_dr_election(ifp)) + pim_hello_restart_now(ifp); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -pim_cmd_interface_add (struct interface *ifp) +static int pim_cmd_interface_add(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) { - pim_ifp = pim_if_new(ifp, 0 /* igmp=false */, 1 /* pim=true */); - if (!pim_ifp) { - return 0; - } - } - else { - PIM_IF_DO_PIM(pim_ifp->options); - } + if (!pim_ifp) { + pim_ifp = pim_if_new(ifp, 0 /* igmp=false */, 1 /* pim=true */); + if (!pim_ifp) { + return 0; + } + } else { + PIM_IF_DO_PIM(pim_ifp->options); + } - pim_if_addr_add_all(ifp); - pim_if_membership_refresh(ifp); - return 1; + pim_if_addr_add_all(ifp); + pim_if_membership_refresh(ifp); + return 1; } DEFUN_HIDDEN (interface_ip_pim_ssm, @@ -5015,16 +5476,17 @@ DEFUN_HIDDEN (interface_ip_pim_ssm, PIM_STR IFACE_PIM_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - if (!pim_cmd_interface_add(ifp)) { - vty_out (vty, "Could not enable PIM SM on interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!pim_cmd_interface_add(ifp)) { + vty_out(vty, "Could not enable PIM SM on interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } - vty_out(vty, "WARN: Enabled PIM SM on interface; configure PIM SSM " - "range if needed\n"); - return CMD_SUCCESS; + vty_out(vty, + "WARN: Enabled PIM SM on interface; configure PIM SSM " + "range if needed\n"); + return CMD_SUCCESS; } DEFUN (interface_ip_pim_sm, @@ -5034,41 +5496,40 @@ DEFUN (interface_ip_pim_sm, PIM_STR IFACE_PIM_SM_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - if (!pim_cmd_interface_add(ifp)) { - vty_out (vty, "Could not enable PIM SM on interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(interface, ifp); + if (!pim_cmd_interface_add(ifp)) { + vty_out(vty, "Could not enable PIM SM on interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } - pim_if_create_pimreg(); + pim_if_create_pimreg(); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -pim_cmd_interface_delete (struct interface *ifp) +static int pim_cmd_interface_delete(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - return 1; + if (!pim_ifp) + return 1; - PIM_IF_DONT_PIM(pim_ifp->options); + PIM_IF_DONT_PIM(pim_ifp->options); - pim_if_membership_clear(ifp); + pim_if_membership_clear(ifp); - /* - pim_sock_delete() removes all neighbors from - pim_ifp->pim_neighbor_list. - */ - pim_sock_delete(ifp, "pim unconfigured on interface"); + /* + pim_sock_delete() removes all neighbors from + pim_ifp->pim_neighbor_list. + */ + pim_sock_delete(ifp, "pim unconfigured on interface"); - if (!PIM_IF_TEST_IGMP(pim_ifp->options)) { - pim_if_addr_del_all(ifp); - pim_if_delete(ifp); - } + if (!PIM_IF_TEST_IGMP(pim_ifp->options)) { + pim_if_addr_del_all(ifp); + pim_if_delete(ifp); + } - return 1; + return 1; } DEFUN_HIDDEN (interface_no_ip_pim_ssm, @@ -5079,13 +5540,13 @@ DEFUN_HIDDEN (interface_no_ip_pim_ssm, PIM_STR IFACE_PIM_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - if (!pim_cmd_interface_delete(ifp)) { - vty_out (vty, "Unable to delete interface information\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(interface, ifp); + if (!pim_cmd_interface_delete(ifp)) { + vty_out(vty, "Unable to delete interface information\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_no_ip_pim_sm, @@ -5096,13 +5557,13 @@ DEFUN (interface_no_ip_pim_sm, PIM_STR IFACE_PIM_SM_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - if (!pim_cmd_interface_delete(ifp)) { - vty_out (vty, "Unable to delete interface information\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(interface, ifp); + if (!pim_cmd_interface_delete(ifp)) { + vty_out(vty, "Unable to delete interface information\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_ip_mroute, @@ -5113,40 +5574,39 @@ DEFUN (interface_ip_mroute, "Outgoing interface name\n" "Group address\n") { - VTY_DECLVAR_CONTEXT(interface, iif); - int idx_interface = 2; - int idx_ipv4 = 3; - struct interface *oif; - const char *oifname; - const char *grp_str; - struct in_addr grp_addr; - struct in_addr src_addr; - int result; - - oifname = argv[idx_interface]->arg; - oif = if_lookup_by_name(oifname, VRF_DEFAULT); - if (!oif) { - vty_out (vty, "No such interface name %s\n", - oifname); - return CMD_WARNING_CONFIG_FAILED; - } - - grp_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, grp_str, &grp_addr); - if (result <= 0) { - vty_out (vty, "Bad group address %s: errno=%d: %s\n", - grp_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - src_addr.s_addr = INADDR_ANY; - - if (pim_static_add(iif, oif, grp_addr, src_addr)) { - vty_out (vty, "Failed to add route\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, iif); + int idx_interface = 2; + int idx_ipv4 = 3; + struct interface *oif; + const char *oifname; + const char *grp_str; + struct in_addr grp_addr; + struct in_addr src_addr; + int result; + + oifname = argv[idx_interface]->arg; + oif = if_lookup_by_name(oifname, VRF_DEFAULT); + if (!oif) { + vty_out(vty, "No such interface name %s\n", oifname); + return CMD_WARNING_CONFIG_FAILED; + } + + grp_str = argv[idx_ipv4]->arg; + result = inet_pton(AF_INET, grp_str, &grp_addr); + if (result <= 0) { + vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + src_addr.s_addr = INADDR_ANY; + + if (pim_static_add(iif, oif, grp_addr, src_addr)) { + vty_out(vty, "Failed to add route\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (interface_ip_mroute_source, @@ -5158,48 +5618,47 @@ DEFUN (interface_ip_mroute_source, "Group address\n" "Source address\n") { - VTY_DECLVAR_CONTEXT(interface, iif); - int idx_interface = 2; - int idx_ipv4 = 3; - int idx_ipv4_2 = 4; - struct interface *oif; - const char *oifname; - const char *grp_str; - struct in_addr grp_addr; - const char *src_str; - struct in_addr src_addr; - int result; - - oifname = argv[idx_interface]->arg; - oif = if_lookup_by_name(oifname, VRF_DEFAULT); - if (!oif) { - vty_out (vty, "No such interface name %s\n", - oifname); - return CMD_WARNING_CONFIG_FAILED; - } - - grp_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, grp_str, &grp_addr); - if (result <= 0) { - vty_out (vty, "Bad group address %s: errno=%d: %s\n", - grp_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - src_str = argv[idx_ipv4_2]->arg; - result = inet_pton(AF_INET, src_str, &src_addr); - if (result <= 0) { - vty_out (vty, "Bad source address %s: errno=%d: %s\n", - src_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - if (pim_static_add(iif, oif, grp_addr, src_addr)) { - vty_out (vty, "Failed to add route\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, iif); + int idx_interface = 2; + int idx_ipv4 = 3; + int idx_ipv4_2 = 4; + struct interface *oif; + const char *oifname; + const char *grp_str; + struct in_addr grp_addr; + const char *src_str; + struct in_addr src_addr; + int result; + + oifname = argv[idx_interface]->arg; + oif = if_lookup_by_name(oifname, VRF_DEFAULT); + if (!oif) { + vty_out(vty, "No such interface name %s\n", oifname); + return CMD_WARNING_CONFIG_FAILED; + } + + grp_str = argv[idx_ipv4]->arg; + result = inet_pton(AF_INET, grp_str, &grp_addr); + if (result <= 0) { + vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + src_str = argv[idx_ipv4_2]->arg; + result = inet_pton(AF_INET, src_str, &src_addr); + if (result <= 0) { + vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + if (pim_static_add(iif, oif, grp_addr, src_addr)) { + vty_out(vty, "Failed to add route\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (interface_no_ip_mroute, @@ -5211,40 +5670,39 @@ DEFUN (interface_no_ip_mroute, "Outgoing interface name\n" "Group Address\n") { - VTY_DECLVAR_CONTEXT(interface, iif); - int idx_interface = 3; - int idx_ipv4 = 4; - struct interface *oif; - const char *oifname; - const char *grp_str; - struct in_addr grp_addr; - struct in_addr src_addr; - int result; - - oifname = argv[idx_interface]->arg; - oif = if_lookup_by_name(oifname, VRF_DEFAULT); - if (!oif) { - vty_out (vty, "No such interface name %s\n", - oifname); - return CMD_WARNING_CONFIG_FAILED; - } - - grp_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, grp_str, &grp_addr); - if (result <= 0) { - vty_out (vty, "Bad group address %s: errno=%d: %s\n", - grp_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - src_addr.s_addr = INADDR_ANY; - - if (pim_static_del(iif, oif, grp_addr, src_addr)) { - vty_out (vty, "Failed to remove route\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, iif); + int idx_interface = 3; + int idx_ipv4 = 4; + struct interface *oif; + const char *oifname; + const char *grp_str; + struct in_addr grp_addr; + struct in_addr src_addr; + int result; + + oifname = argv[idx_interface]->arg; + oif = if_lookup_by_name(oifname, VRF_DEFAULT); + if (!oif) { + vty_out(vty, "No such interface name %s\n", oifname); + return CMD_WARNING_CONFIG_FAILED; + } + + grp_str = argv[idx_ipv4]->arg; + result = inet_pton(AF_INET, grp_str, &grp_addr); + if (result <= 0) { + vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + src_addr.s_addr = INADDR_ANY; + + if (pim_static_del(iif, oif, grp_addr, src_addr)) { + vty_out(vty, "Failed to remove route\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (interface_no_ip_mroute_source, @@ -5257,48 +5715,47 @@ DEFUN (interface_no_ip_mroute_source, "Group Address\n" "Source Address\n") { - VTY_DECLVAR_CONTEXT(interface, iif); - int idx_interface = 3; - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - struct interface *oif; - const char *oifname; - const char *grp_str; - struct in_addr grp_addr; - const char *src_str; - struct in_addr src_addr; - int result; - - oifname = argv[idx_interface]->arg; - oif = if_lookup_by_name(oifname, VRF_DEFAULT); - if (!oif) { - vty_out (vty, "No such interface name %s\n", - oifname); - return CMD_WARNING_CONFIG_FAILED; - } - - grp_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, grp_str, &grp_addr); - if (result <= 0) { - vty_out (vty, "Bad group address %s: errno=%d: %s\n", - grp_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - src_str = argv[idx_ipv4_2]->arg; - result = inet_pton(AF_INET, src_str, &src_addr); - if (result <= 0) { - vty_out (vty, "Bad source address %s: errno=%d: %s\n", - src_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - if (pim_static_del(iif, oif, grp_addr, src_addr)) { - vty_out (vty, "Failed to remove route\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, iif); + int idx_interface = 3; + int idx_ipv4 = 4; + int idx_ipv4_2 = 5; + struct interface *oif; + const char *oifname; + const char *grp_str; + struct in_addr grp_addr; + const char *src_str; + struct in_addr src_addr; + int result; + + oifname = argv[idx_interface]->arg; + oif = if_lookup_by_name(oifname, VRF_DEFAULT); + if (!oif) { + vty_out(vty, "No such interface name %s\n", oifname); + return CMD_WARNING_CONFIG_FAILED; + } + + grp_str = argv[idx_ipv4]->arg; + result = inet_pton(AF_INET, grp_str, &grp_addr); + if (result <= 0) { + vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + src_str = argv[idx_ipv4_2]->arg; + result = inet_pton(AF_INET, src_str, &src_addr); + if (result <= 0) { + vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + if (pim_static_del(iif, oif, grp_addr, src_addr)) { + vty_out(vty, "Failed to remove route\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (interface_ip_pim_hello, @@ -5310,31 +5767,29 @@ DEFUN (interface_ip_pim_hello, IFACE_PIM_HELLO_TIME_STR IFACE_PIM_HELLO_HOLD_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_time = 3; - int idx_hold = 4; - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_time = 3; + int idx_hold = 4; + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - { - if (!pim_cmd_interface_add(ifp)) - { - vty_out (vty, "Could not enable PIM SM on interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } + if (!pim_ifp) { + if (!pim_cmd_interface_add(ifp)) { + vty_out(vty, "Could not enable PIM SM on interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } - pim_ifp = ifp->info; - pim_ifp->pim_hello_period = strtol(argv[idx_time]->arg, NULL, 10); + pim_ifp = ifp->info; + pim_ifp->pim_hello_period = strtol(argv[idx_time]->arg, NULL, 10); - if (argc == idx_hold + 1) - pim_ifp->pim_default_holdtime = strtol(argv[idx_hold]->arg, NULL, 10); + if (argc == idx_hold + 1) + pim_ifp->pim_default_holdtime = + strtol(argv[idx_hold]->arg, NULL, 10); - return CMD_SUCCESS; + return CMD_SUCCESS; } - DEFUN (interface_no_ip_pim_hello, interface_no_ip_pim_hello_cmd, "no ip pim hello [(1-180) (1-180)]", @@ -5345,18 +5800,18 @@ DEFUN (interface_no_ip_pim_hello, IFACE_PIM_HELLO_TIME_STR IFACE_PIM_HELLO_HOLD_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) { - vty_out (vty, "Pim not enabled on this interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!pim_ifp) { + vty_out(vty, "Pim not enabled on this interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } - pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD; - pim_ifp->pim_default_holdtime = -1; + pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD; + pim_ifp->pim_default_holdtime = -1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_igmp, @@ -5365,10 +5820,10 @@ DEFUN (debug_igmp, DEBUG_STR DEBUG_IGMP_STR) { - PIM_DO_DEBUG_IGMP_EVENTS; - PIM_DO_DEBUG_IGMP_PACKETS; - PIM_DO_DEBUG_IGMP_TRACE; - return CMD_SUCCESS; + PIM_DO_DEBUG_IGMP_EVENTS; + PIM_DO_DEBUG_IGMP_PACKETS; + PIM_DO_DEBUG_IGMP_TRACE; + return CMD_SUCCESS; } DEFUN (no_debug_igmp, @@ -5378,10 +5833,10 @@ DEFUN (no_debug_igmp, DEBUG_STR DEBUG_IGMP_STR) { - PIM_DONT_DEBUG_IGMP_EVENTS; - PIM_DONT_DEBUG_IGMP_PACKETS; - PIM_DONT_DEBUG_IGMP_TRACE; - return CMD_SUCCESS; + PIM_DONT_DEBUG_IGMP_EVENTS; + PIM_DONT_DEBUG_IGMP_PACKETS; + PIM_DONT_DEBUG_IGMP_TRACE; + return CMD_SUCCESS; } @@ -5392,8 +5847,8 @@ DEFUN (debug_igmp_events, DEBUG_IGMP_STR DEBUG_IGMP_EVENTS_STR) { - PIM_DO_DEBUG_IGMP_EVENTS; - return CMD_SUCCESS; + PIM_DO_DEBUG_IGMP_EVENTS; + return CMD_SUCCESS; } DEFUN (no_debug_igmp_events, @@ -5404,8 +5859,8 @@ DEFUN (no_debug_igmp_events, DEBUG_IGMP_STR DEBUG_IGMP_EVENTS_STR) { - PIM_DONT_DEBUG_IGMP_EVENTS; - return CMD_SUCCESS; + PIM_DONT_DEBUG_IGMP_EVENTS; + return CMD_SUCCESS; } @@ -5416,8 +5871,8 @@ DEFUN (debug_igmp_packets, DEBUG_IGMP_STR DEBUG_IGMP_PACKETS_STR) { - PIM_DO_DEBUG_IGMP_PACKETS; - return CMD_SUCCESS; + PIM_DO_DEBUG_IGMP_PACKETS; + return CMD_SUCCESS; } DEFUN (no_debug_igmp_packets, @@ -5428,8 +5883,8 @@ DEFUN (no_debug_igmp_packets, DEBUG_IGMP_STR DEBUG_IGMP_PACKETS_STR) { - PIM_DONT_DEBUG_IGMP_PACKETS; - return CMD_SUCCESS; + PIM_DONT_DEBUG_IGMP_PACKETS; + return CMD_SUCCESS; } @@ -5440,8 +5895,8 @@ DEFUN (debug_igmp_trace, DEBUG_IGMP_STR DEBUG_IGMP_TRACE_STR) { - PIM_DO_DEBUG_IGMP_TRACE; - return CMD_SUCCESS; + PIM_DO_DEBUG_IGMP_TRACE; + return CMD_SUCCESS; } DEFUN (no_debug_igmp_trace, @@ -5452,8 +5907,8 @@ DEFUN (no_debug_igmp_trace, DEBUG_IGMP_STR DEBUG_IGMP_TRACE_STR) { - PIM_DONT_DEBUG_IGMP_TRACE; - return CMD_SUCCESS; + PIM_DONT_DEBUG_IGMP_TRACE; + return CMD_SUCCESS; } @@ -5463,8 +5918,8 @@ DEFUN (debug_mroute, DEBUG_STR DEBUG_MROUTE_STR) { - PIM_DO_DEBUG_MROUTE; - return CMD_SUCCESS; + PIM_DO_DEBUG_MROUTE; + return CMD_SUCCESS; } DEFUN (debug_mroute_detail, @@ -5474,8 +5929,8 @@ DEFUN (debug_mroute_detail, DEBUG_MROUTE_STR "detailed\n") { - PIM_DO_DEBUG_MROUTE_DETAIL; - return CMD_SUCCESS; + PIM_DO_DEBUG_MROUTE_DETAIL; + return CMD_SUCCESS; } DEFUN (no_debug_mroute, @@ -5485,8 +5940,8 @@ DEFUN (no_debug_mroute, DEBUG_STR DEBUG_MROUTE_STR) { - PIM_DONT_DEBUG_MROUTE; - return CMD_SUCCESS; + PIM_DONT_DEBUG_MROUTE; + return CMD_SUCCESS; } DEFUN (no_debug_mroute_detail, @@ -5497,8 +5952,8 @@ DEFUN (no_debug_mroute_detail, DEBUG_MROUTE_STR "detailed\n") { - PIM_DONT_DEBUG_MROUTE_DETAIL; - return CMD_SUCCESS; + PIM_DONT_DEBUG_MROUTE_DETAIL; + return CMD_SUCCESS; } DEFUN (debug_static, @@ -5507,8 +5962,8 @@ DEFUN (debug_static, DEBUG_STR DEBUG_STATIC_STR) { - PIM_DO_DEBUG_STATIC; - return CMD_SUCCESS; + PIM_DO_DEBUG_STATIC; + return CMD_SUCCESS; } DEFUN (no_debug_static, @@ -5518,8 +5973,8 @@ DEFUN (no_debug_static, DEBUG_STR DEBUG_STATIC_STR) { - PIM_DONT_DEBUG_STATIC; - return CMD_SUCCESS; + PIM_DONT_DEBUG_STATIC; + return CMD_SUCCESS; } @@ -5529,12 +5984,12 @@ DEFUN (debug_pim, DEBUG_STR DEBUG_PIM_STR) { - PIM_DO_DEBUG_PIM_EVENTS; - PIM_DO_DEBUG_PIM_PACKETS; - PIM_DO_DEBUG_PIM_TRACE; - PIM_DO_DEBUG_MSDP_EVENTS; - PIM_DO_DEBUG_MSDP_PACKETS; - return CMD_SUCCESS; + PIM_DO_DEBUG_PIM_EVENTS; + PIM_DO_DEBUG_PIM_PACKETS; + PIM_DO_DEBUG_PIM_TRACE; + PIM_DO_DEBUG_MSDP_EVENTS; + PIM_DO_DEBUG_MSDP_PACKETS; + return CMD_SUCCESS; } DEFUN (no_debug_pim, @@ -5544,16 +5999,16 @@ DEFUN (no_debug_pim, DEBUG_STR DEBUG_PIM_STR) { - PIM_DONT_DEBUG_PIM_EVENTS; - PIM_DONT_DEBUG_PIM_PACKETS; - PIM_DONT_DEBUG_PIM_TRACE; - PIM_DONT_DEBUG_MSDP_EVENTS; - PIM_DONT_DEBUG_MSDP_PACKETS; + PIM_DONT_DEBUG_PIM_EVENTS; + PIM_DONT_DEBUG_PIM_PACKETS; + PIM_DONT_DEBUG_PIM_TRACE; + PIM_DONT_DEBUG_MSDP_EVENTS; + PIM_DONT_DEBUG_MSDP_PACKETS; - PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND; - PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV; + PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND; + PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -5564,8 +6019,8 @@ DEFUN (debug_pim_events, DEBUG_PIM_STR DEBUG_PIM_EVENTS_STR) { - PIM_DO_DEBUG_PIM_EVENTS; - return CMD_SUCCESS; + PIM_DO_DEBUG_PIM_EVENTS; + return CMD_SUCCESS; } DEFUN (no_debug_pim_events, @@ -5576,8 +6031,8 @@ DEFUN (no_debug_pim_events, DEBUG_PIM_STR DEBUG_PIM_EVENTS_STR) { - PIM_DONT_DEBUG_PIM_EVENTS; - return CMD_SUCCESS; + PIM_DONT_DEBUG_PIM_EVENTS; + return CMD_SUCCESS; } DEFUN (debug_pim_packets, @@ -5590,28 +6045,21 @@ DEFUN (debug_pim_packets, DEBUG_PIM_J_P_PACKETS_STR DEBUG_PIM_PIM_REG_PACKETS_STR) { - int idx = 0; - if (argv_find (argv, argc, "hello", &idx)) - { - PIM_DO_DEBUG_PIM_HELLO; - vty_out (vty, "PIM Hello debugging is on\n"); - } - else if (argv_find (argv, argc ,"joins", &idx)) - { - PIM_DO_DEBUG_PIM_J_P; - vty_out (vty, "PIM Join/Prune debugging is on\n"); - } - else if (argv_find (argv, argc, "register", &idx)) - { - PIM_DO_DEBUG_PIM_REG; - vty_out (vty, "PIM Register debugging is on\n"); - } - else - { - PIM_DO_DEBUG_PIM_PACKETS; - vty_out (vty, "PIM Packet debugging is on \n"); - } - return CMD_SUCCESS; + int idx = 0; + if (argv_find(argv, argc, "hello", &idx)) { + PIM_DO_DEBUG_PIM_HELLO; + vty_out(vty, "PIM Hello debugging is on\n"); + } else if (argv_find(argv, argc, "joins", &idx)) { + PIM_DO_DEBUG_PIM_J_P; + vty_out(vty, "PIM Join/Prune debugging is on\n"); + } else if (argv_find(argv, argc, "register", &idx)) { + PIM_DO_DEBUG_PIM_REG; + vty_out(vty, "PIM Register debugging is on\n"); + } else { + PIM_DO_DEBUG_PIM_PACKETS; + vty_out(vty, "PIM Packet debugging is on \n"); + } + return CMD_SUCCESS; } DEFUN (no_debug_pim_packets, @@ -5625,26 +6073,20 @@ DEFUN (no_debug_pim_packets, DEBUG_PIM_J_P_PACKETS_STR DEBUG_PIM_PIM_REG_PACKETS_STR) { - int idx = 0; - if (argv_find (argv, argc,"hello",&idx)) - { - PIM_DONT_DEBUG_PIM_HELLO; - vty_out (vty, "PIM Hello debugging is off \n"); - } - else if (argv_find (argv, argc, "joins", &idx)) - { - PIM_DONT_DEBUG_PIM_J_P; - vty_out (vty, "PIM Join/Prune debugging is off \n"); - } - else if (argv_find (argv, argc, "register", &idx)) - { - PIM_DONT_DEBUG_PIM_REG; - vty_out (vty, "PIM Register debugging is off\n"); - } - else - PIM_DONT_DEBUG_PIM_PACKETS; - - return CMD_SUCCESS; + int idx = 0; + if (argv_find(argv, argc, "hello", &idx)) { + PIM_DONT_DEBUG_PIM_HELLO; + vty_out(vty, "PIM Hello debugging is off \n"); + } else if (argv_find(argv, argc, "joins", &idx)) { + PIM_DONT_DEBUG_PIM_J_P; + vty_out(vty, "PIM Join/Prune debugging is off \n"); + } else if (argv_find(argv, argc, "register", &idx)) { + PIM_DONT_DEBUG_PIM_REG; + vty_out(vty, "PIM Register debugging is off\n"); + } else + PIM_DONT_DEBUG_PIM_PACKETS; + + return CMD_SUCCESS; } @@ -5656,8 +6098,8 @@ DEFUN (debug_pim_packetdump_send, DEBUG_PIM_PACKETDUMP_STR DEBUG_PIM_PACKETDUMP_SEND_STR) { - PIM_DO_DEBUG_PIM_PACKETDUMP_SEND; - return CMD_SUCCESS; + PIM_DO_DEBUG_PIM_PACKETDUMP_SEND; + return CMD_SUCCESS; } DEFUN (no_debug_pim_packetdump_send, @@ -5669,8 +6111,8 @@ DEFUN (no_debug_pim_packetdump_send, DEBUG_PIM_PACKETDUMP_STR DEBUG_PIM_PACKETDUMP_SEND_STR) { - PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND; - return CMD_SUCCESS; + PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND; + return CMD_SUCCESS; } @@ -5682,8 +6124,8 @@ DEFUN (debug_pim_packetdump_recv, DEBUG_PIM_PACKETDUMP_STR DEBUG_PIM_PACKETDUMP_RECV_STR) { - PIM_DO_DEBUG_PIM_PACKETDUMP_RECV; - return CMD_SUCCESS; + PIM_DO_DEBUG_PIM_PACKETDUMP_RECV; + return CMD_SUCCESS; } DEFUN (no_debug_pim_packetdump_recv, @@ -5695,8 +6137,8 @@ DEFUN (no_debug_pim_packetdump_recv, DEBUG_PIM_PACKETDUMP_STR DEBUG_PIM_PACKETDUMP_RECV_STR) { - PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV; - return CMD_SUCCESS; + PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV; + return CMD_SUCCESS; } @@ -5707,8 +6149,8 @@ DEFUN (debug_pim_trace, DEBUG_PIM_STR DEBUG_PIM_TRACE_STR) { - PIM_DO_DEBUG_PIM_TRACE; - return CMD_SUCCESS; + PIM_DO_DEBUG_PIM_TRACE; + return CMD_SUCCESS; } DEFUN (no_debug_pim_trace, @@ -5719,8 +6161,8 @@ DEFUN (no_debug_pim_trace, DEBUG_PIM_STR DEBUG_PIM_TRACE_STR) { - PIM_DONT_DEBUG_PIM_TRACE; - return CMD_SUCCESS; + PIM_DONT_DEBUG_PIM_TRACE; + return CMD_SUCCESS; } @@ -5730,8 +6172,8 @@ DEFUN (debug_ssmpingd, DEBUG_STR DEBUG_SSMPINGD_STR) { - PIM_DO_DEBUG_SSMPINGD; - return CMD_SUCCESS; + PIM_DO_DEBUG_SSMPINGD; + return CMD_SUCCESS; } DEFUN (no_debug_ssmpingd, @@ -5741,8 +6183,8 @@ DEFUN (no_debug_ssmpingd, DEBUG_STR DEBUG_SSMPINGD_STR) { - PIM_DONT_DEBUG_SSMPINGD; - return CMD_SUCCESS; + PIM_DONT_DEBUG_SSMPINGD; + return CMD_SUCCESS; } @@ -5753,8 +6195,8 @@ DEFUN (debug_pim_zebra, DEBUG_PIM_STR DEBUG_PIM_ZEBRA_STR) { - PIM_DO_DEBUG_ZEBRA; - return CMD_SUCCESS; + PIM_DO_DEBUG_ZEBRA; + return CMD_SUCCESS; } DEFUN (no_debug_pim_zebra, @@ -5765,8 +6207,8 @@ DEFUN (no_debug_pim_zebra, DEBUG_PIM_STR DEBUG_PIM_ZEBRA_STR) { - PIM_DONT_DEBUG_ZEBRA; - return CMD_SUCCESS; + PIM_DONT_DEBUG_ZEBRA; + return CMD_SUCCESS; } @@ -5776,9 +6218,9 @@ DEFUN (debug_msdp, DEBUG_STR DEBUG_MSDP_STR) { - PIM_DO_DEBUG_MSDP_EVENTS; - PIM_DO_DEBUG_MSDP_PACKETS; - return CMD_SUCCESS; + PIM_DO_DEBUG_MSDP_EVENTS; + PIM_DO_DEBUG_MSDP_PACKETS; + return CMD_SUCCESS; } DEFUN (no_debug_msdp, @@ -5788,16 +6230,13 @@ DEFUN (no_debug_msdp, DEBUG_STR DEBUG_MSDP_STR) { - PIM_DONT_DEBUG_MSDP_EVENTS; - PIM_DONT_DEBUG_MSDP_PACKETS; - return CMD_SUCCESS; + PIM_DONT_DEBUG_MSDP_EVENTS; + PIM_DONT_DEBUG_MSDP_PACKETS; + return CMD_SUCCESS; } -ALIAS (no_debug_msdp, - undebug_msdp_cmd, - "undebug msdp", - UNDEBUG_STR - DEBUG_MSDP_STR) +ALIAS(no_debug_msdp, undebug_msdp_cmd, "undebug msdp", + UNDEBUG_STR DEBUG_MSDP_STR) DEFUN (debug_msdp_events, debug_msdp_events_cmd, @@ -5806,8 +6245,8 @@ DEFUN (debug_msdp_events, DEBUG_MSDP_STR DEBUG_MSDP_EVENTS_STR) { - PIM_DO_DEBUG_MSDP_EVENTS; - return CMD_SUCCESS; + PIM_DO_DEBUG_MSDP_EVENTS; + return CMD_SUCCESS; } DEFUN (no_debug_msdp_events, @@ -5818,16 +6257,12 @@ DEFUN (no_debug_msdp_events, DEBUG_MSDP_STR DEBUG_MSDP_EVENTS_STR) { - PIM_DONT_DEBUG_MSDP_EVENTS; - return CMD_SUCCESS; + PIM_DONT_DEBUG_MSDP_EVENTS; + return CMD_SUCCESS; } -ALIAS (no_debug_msdp_events, - undebug_msdp_events_cmd, - "undebug msdp events", - UNDEBUG_STR - DEBUG_MSDP_STR - DEBUG_MSDP_EVENTS_STR) +ALIAS(no_debug_msdp_events, undebug_msdp_events_cmd, "undebug msdp events", + UNDEBUG_STR DEBUG_MSDP_STR DEBUG_MSDP_EVENTS_STR) DEFUN (debug_msdp_packets, debug_msdp_packets_cmd, @@ -5836,8 +6271,8 @@ DEFUN (debug_msdp_packets, DEBUG_MSDP_STR DEBUG_MSDP_PACKETS_STR) { - PIM_DO_DEBUG_MSDP_PACKETS; - return CMD_SUCCESS; + PIM_DO_DEBUG_MSDP_PACKETS; + return CMD_SUCCESS; } DEFUN (no_debug_msdp_packets, @@ -5848,16 +6283,12 @@ DEFUN (no_debug_msdp_packets, DEBUG_MSDP_STR DEBUG_MSDP_PACKETS_STR) { - PIM_DONT_DEBUG_MSDP_PACKETS; - return CMD_SUCCESS; + PIM_DONT_DEBUG_MSDP_PACKETS; + return CMD_SUCCESS; } -ALIAS (no_debug_msdp_packets, - undebug_msdp_packets_cmd, - "undebug msdp packets", - UNDEBUG_STR - DEBUG_MSDP_STR - DEBUG_MSDP_PACKETS_STR) +ALIAS(no_debug_msdp_packets, undebug_msdp_packets_cmd, "undebug msdp packets", + UNDEBUG_STR DEBUG_MSDP_STR DEBUG_MSDP_PACKETS_STR) DEFUN (show_debugging_pim, show_debugging_pim_cmd, @@ -5866,39 +6297,38 @@ DEFUN (show_debugging_pim, DEBUG_STR PIM_STR) { - pim_debug_config_write(vty); - return CMD_SUCCESS; + pim_debug_config_write(vty); + return CMD_SUCCESS; } -static int -interface_pim_use_src_cmd_worker(struct vty *vty, const char *source) +static int interface_pim_use_src_cmd_worker(struct vty *vty, const char *source) { - int result; - struct in_addr source_addr; - VTY_DECLVAR_CONTEXT(interface, ifp); + int result; + struct in_addr source_addr; + VTY_DECLVAR_CONTEXT(interface, ifp); - result = inet_pton(AF_INET, source, &source_addr); - if (result <= 0) { - vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", - source, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + result = inet_pton(AF_INET, source, &source_addr); + if (result <= 0) { + vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", source, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - result = pim_update_source_set(ifp, source_addr); - switch (result) { - case PIM_SUCCESS: - break; - case PIM_IFACE_NOT_FOUND: - vty_out (vty, "Pim not enabled on this interface\n"); - break; - case PIM_UPDATE_SOURCE_DUP: - vty_out (vty, "%% Source already set to %s\n", source); - break; - default: - vty_out (vty, "%% Source set failed\n"); - } + result = pim_update_source_set(ifp, source_addr); + switch (result) { + case PIM_SUCCESS: + break; + case PIM_IFACE_NOT_FOUND: + vty_out(vty, "Pim not enabled on this interface\n"); + break; + case PIM_UPDATE_SOURCE_DUP: + vty_out(vty, "%% Source already set to %s\n", source); + break; + default: + vty_out(vty, "%% Source set failed\n"); + } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } DEFUN (interface_pim_use_source, @@ -5909,7 +6339,7 @@ DEFUN (interface_pim_use_source, "Configure primary IP address\n" "source ip address\n") { - return interface_pim_use_src_cmd_worker (vty, argv[3]->arg); + return interface_pim_use_src_cmd_worker(vty, argv[3]->arg); } DEFUN (interface_no_pim_use_source, @@ -5920,7 +6350,7 @@ DEFUN (interface_no_pim_use_source, "pim multicast routing\n" "Delete source IP address\n") { - return interface_pim_use_src_cmd_worker (vty, "0.0.0.0"); + return interface_pim_use_src_cmd_worker(vty, "0.0.0.0"); } DEFUN (ip_pim_bfd, @@ -5930,19 +6360,19 @@ DEFUN (ip_pim_bfd, PIM_STR "Enables BFD support\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; - struct bfd_info *bfd_info = NULL; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + struct bfd_info *bfd_info = NULL; - if (!pim_ifp) - return CMD_SUCCESS; - bfd_info = pim_ifp->bfd_info; + if (!pim_ifp) + return CMD_SUCCESS; + bfd_info = pim_ifp->bfd_info; - if (!bfd_info || !CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG)) - pim_bfd_if_param_set (ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, - BFD_DEF_DETECT_MULT, 1); + if (!bfd_info || !CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) + pim_bfd_if_param_set(ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, + BFD_DEF_DETECT_MULT, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_pim_bfd, @@ -5953,19 +6383,18 @@ DEFUN (no_ip_pim_bfd, PIM_STR "Disables BFD support\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - return CMD_SUCCESS; + if (!pim_ifp) + return CMD_SUCCESS; - if (pim_ifp->bfd_info) - { - pim_bfd_reg_dereg_all_nbr (ifp, ZEBRA_BFD_DEST_DEREGISTER); - bfd_info_free (&(pim_ifp->bfd_info)); - } + if (pim_ifp->bfd_info) { + pim_bfd_reg_dereg_all_nbr(ifp, ZEBRA_BFD_DEST_DEREGISTER); + bfd_info_free(&(pim_ifp->bfd_info)); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_pim_bfd_param, @@ -5978,77 +6407,74 @@ DEFUN (ip_pim_bfd_param, "Required min receive interval\n" "Desired min transmit interval\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_number = 3; - int idx_number_2 = 4; - int idx_number_3 = 5; - u_int32_t rx_val; - u_int32_t tx_val; - u_int8_t dm_val; - int ret; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_number = 3; + int idx_number_2 = 4; + int idx_number_3 = 5; + u_int32_t rx_val; + u_int32_t tx_val; + u_int8_t dm_val; + int ret; - if ((ret = bfd_validate_param (vty, argv[idx_number]->arg, - argv[idx_number_2]->arg, - argv[idx_number_3]->arg, - &dm_val, &rx_val, &tx_val)) != CMD_SUCCESS) - return ret; + if ((ret = bfd_validate_param( + vty, argv[idx_number]->arg, argv[idx_number_2]->arg, + argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val)) + != CMD_SUCCESS) + return ret; - pim_bfd_if_param_set (ifp, rx_val, tx_val, dm_val, 0); + pim_bfd_if_param_set(ifp, rx_val, tx_val, dm_val, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } -ALIAS (no_ip_pim_bfd, - no_ip_pim_bfd_param_cmd, - "no ip pim bfd (2-255) (50-60000) (50-60000)", - NO_STR - IP_STR - PIM_STR - "Enables BFD support\n" - "Detect Multiplier\n" - "Required min receive interval\n" - "Desired min transmit interval\n") +ALIAS(no_ip_pim_bfd, no_ip_pim_bfd_param_cmd, + "no ip pim bfd (2-255) (50-60000) (50-60000)", NO_STR IP_STR PIM_STR + "Enables BFD support\n" + "Detect Multiplier\n" + "Required min receive interval\n" + "Desired min transmit interval\n") + +static int ip_msdp_peer_cmd_worker(struct vty *vty, const char *peer, + const char *local) +{ + enum pim_msdp_err result; + struct in_addr peer_addr; + struct in_addr local_addr; + + result = inet_pton(AF_INET, peer, &peer_addr); + if (result <= 0) { + vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + result = inet_pton(AF_INET, local, &local_addr); + if (result <= 0) { + vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", local, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } -static int -ip_msdp_peer_cmd_worker (struct vty *vty, const char *peer, const char *local) -{ - enum pim_msdp_err result; - struct in_addr peer_addr; - struct in_addr local_addr; - - result = inet_pton(AF_INET, peer, &peer_addr); - if (result <= 0) { - vty_out (vty, "%% Bad peer address %s: errno=%d: %s\n", - peer, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - result = inet_pton(AF_INET, local, &local_addr); - if (result <= 0) { - vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", - local, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - result = pim_msdp_peer_add(peer_addr, local_addr, "default", NULL/* mp_p */); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_OOM: - vty_out (vty, "%% Out of memory\n"); - break; - case PIM_MSDP_ERR_PEER_EXISTS: - vty_out (vty, "%% Peer exists\n"); - break; - case PIM_MSDP_ERR_MAX_MESH_GROUPS: - vty_out (vty, "%% Only one mesh-group allowed currently\n"); - break; - default: - vty_out (vty, "%% peer add failed\n"); - } - - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + result = pim_msdp_peer_add(peer_addr, local_addr, "default", + NULL /* mp_p */); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_OOM: + vty_out(vty, "%% Out of memory\n"); + break; + case PIM_MSDP_ERR_PEER_EXISTS: + vty_out(vty, "%% Peer exists\n"); + break; + case PIM_MSDP_ERR_MAX_MESH_GROUPS: + vty_out(vty, "%% Only one mesh-group allowed currently\n"); + break; + default: + vty_out(vty, "%% peer add failed\n"); + } + + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } DEFUN_HIDDEN (ip_msdp_peer, @@ -6061,34 +6487,33 @@ DEFUN_HIDDEN (ip_msdp_peer, "Source address for TCP connection\n" "local ip address\n") { - return ip_msdp_peer_cmd_worker (vty, argv[3]->arg, argv[5]->arg); + return ip_msdp_peer_cmd_worker(vty, argv[3]->arg, argv[5]->arg); } -static int -ip_no_msdp_peer_cmd_worker (struct vty *vty, const char *peer) +static int ip_no_msdp_peer_cmd_worker(struct vty *vty, const char *peer) { - enum pim_msdp_err result; - struct in_addr peer_addr; + enum pim_msdp_err result; + struct in_addr peer_addr; - result = inet_pton(AF_INET, peer, &peer_addr); - if (result <= 0) { - vty_out (vty, "%% Bad peer address %s: errno=%d: %s\n", - peer, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + result = inet_pton(AF_INET, peer, &peer_addr); + if (result <= 0) { + vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - result = pim_msdp_peer_del(peer_addr); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_NO_PEER: - vty_out (vty, "%% Peer does not exist\n"); - break; - default: - vty_out (vty, "%% peer del failed\n"); - } + result = pim_msdp_peer_del(peer_addr); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_PEER: + vty_out(vty, "%% Peer does not exist\n"); + break; + default: + vty_out(vty, "%% peer del failed\n"); + } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } DEFUN_HIDDEN (no_ip_msdp_peer, @@ -6100,40 +6525,40 @@ DEFUN_HIDDEN (no_ip_msdp_peer, "Delete MSDP peer\n" "peer ip address\n") { - return ip_no_msdp_peer_cmd_worker (vty, argv[4]->arg); + return ip_no_msdp_peer_cmd_worker(vty, argv[4]->arg); } -static int -ip_msdp_mesh_group_member_cmd_worker(struct vty *vty, const char *mg, const char *mbr) +static int ip_msdp_mesh_group_member_cmd_worker(struct vty *vty, const char *mg, + const char *mbr) { - enum pim_msdp_err result; - struct in_addr mbr_ip; + enum pim_msdp_err result; + struct in_addr mbr_ip; - result = inet_pton(AF_INET, mbr, &mbr_ip); - if (result <= 0) { - vty_out (vty, "%% Bad member address %s: errno=%d: %s\n", - mbr, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + result = inet_pton(AF_INET, mbr, &mbr_ip); + if (result <= 0) { + vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - result = pim_msdp_mg_mbr_add(mg, mbr_ip); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_OOM: - vty_out (vty, "%% Out of memory\n"); - break; - case PIM_MSDP_ERR_MG_MBR_EXISTS: - vty_out (vty, "%% mesh-group member exists\n"); - break; - case PIM_MSDP_ERR_MAX_MESH_GROUPS: - vty_out (vty, "%% Only one mesh-group allowed currently\n"); - break; - default: - vty_out (vty, "%% member add failed\n"); - } + result = pim_msdp_mg_mbr_add(mg, mbr_ip); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_OOM: + vty_out(vty, "%% Out of memory\n"); + break; + case PIM_MSDP_ERR_MG_MBR_EXISTS: + vty_out(vty, "%% mesh-group member exists\n"); + break; + case PIM_MSDP_ERR_MAX_MESH_GROUPS: + vty_out(vty, "%% Only one mesh-group allowed currently\n"); + break; + default: + vty_out(vty, "%% member add failed\n"); + } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } DEFUN (ip_msdp_mesh_group_member, @@ -6146,37 +6571,39 @@ DEFUN (ip_msdp_mesh_group_member, "mesh group member\n" "peer ip address\n") { - return ip_msdp_mesh_group_member_cmd_worker(vty, argv[3]->arg, argv[5]->arg); + return ip_msdp_mesh_group_member_cmd_worker(vty, argv[3]->arg, + argv[5]->arg); } -static int -ip_no_msdp_mesh_group_member_cmd_worker(struct vty *vty, const char *mg, const char *mbr) +static int ip_no_msdp_mesh_group_member_cmd_worker(struct vty *vty, + const char *mg, + const char *mbr) { - enum pim_msdp_err result; - struct in_addr mbr_ip; + enum pim_msdp_err result; + struct in_addr mbr_ip; - result = inet_pton(AF_INET, mbr, &mbr_ip); - if (result <= 0) { - vty_out (vty, "%% Bad member address %s: errno=%d: %s\n", - mbr, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + result = inet_pton(AF_INET, mbr, &mbr_ip); + if (result <= 0) { + vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - result = pim_msdp_mg_mbr_del(mg, mbr_ip); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_NO_MG: - vty_out (vty, "%% mesh-group does not exist\n"); - break; - case PIM_MSDP_ERR_NO_MG_MBR: - vty_out (vty, "%% mesh-group member does not exist\n"); - break; - default: - vty_out (vty, "%% mesh-group member del failed\n"); - } + result = pim_msdp_mg_mbr_del(mg, mbr_ip); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_MG: + vty_out(vty, "%% mesh-group does not exist\n"); + break; + case PIM_MSDP_ERR_NO_MG_MBR: + vty_out(vty, "%% mesh-group member does not exist\n"); + break; + default: + vty_out(vty, "%% mesh-group member del failed\n"); + } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } DEFUN (no_ip_msdp_mesh_group_member, no_ip_msdp_mesh_group_member_cmd, @@ -6189,37 +6616,38 @@ DEFUN (no_ip_msdp_mesh_group_member, "mesh group member\n" "peer ip address\n") { - return ip_no_msdp_mesh_group_member_cmd_worker(vty, argv[4]->arg, argv[6]->arg); + return ip_no_msdp_mesh_group_member_cmd_worker(vty, argv[4]->arg, + argv[6]->arg); } -static int -ip_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg, const char *src) +static int ip_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg, + const char *src) { - enum pim_msdp_err result; - struct in_addr src_ip; + enum pim_msdp_err result; + struct in_addr src_ip; - result = inet_pton(AF_INET, src, &src_ip); - if (result <= 0) { - vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", - src, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + result = inet_pton(AF_INET, src, &src_ip); + if (result <= 0) { + vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", src, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - result = pim_msdp_mg_src_add(mg, src_ip); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_OOM: - vty_out (vty, "%% Out of memory\n"); - break; - case PIM_MSDP_ERR_MAX_MESH_GROUPS: - vty_out (vty, "%% Only one mesh-group allowed currently\n"); - break; - default: - vty_out (vty, "%% source add failed\n"); - } + result = pim_msdp_mg_src_add(mg, src_ip); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_OOM: + vty_out(vty, "%% Out of memory\n"); + break; + case PIM_MSDP_ERR_MAX_MESH_GROUPS: + vty_out(vty, "%% Only one mesh-group allowed currently\n"); + break; + default: + vty_out(vty, "%% source add failed\n"); + } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } @@ -6233,45 +6661,45 @@ DEFUN (ip_msdp_mesh_group_source, "mesh group local address\n" "source ip address for the TCP connection\n") { - return ip_msdp_mesh_group_source_cmd_worker(vty, argv[3]->arg, argv[5]->arg); + return ip_msdp_mesh_group_source_cmd_worker(vty, argv[3]->arg, + argv[5]->arg); } -static int -ip_no_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg) +static int ip_no_msdp_mesh_group_source_cmd_worker(struct vty *vty, + const char *mg) { - enum pim_msdp_err result; + enum pim_msdp_err result; - result = pim_msdp_mg_src_del(mg); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_NO_MG: - vty_out (vty, "%% mesh-group does not exist\n"); - break; - default: - vty_out (vty, "%% mesh-group source del failed\n"); - } + result = pim_msdp_mg_src_del(mg); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_MG: + vty_out(vty, "%% mesh-group does not exist\n"); + break; + default: + vty_out(vty, "%% mesh-group source del failed\n"); + } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } -static int -ip_no_msdp_mesh_group_cmd_worker(struct vty *vty, const char *mg) +static int ip_no_msdp_mesh_group_cmd_worker(struct vty *vty, const char *mg) { - enum pim_msdp_err result; + enum pim_msdp_err result; - result = pim_msdp_mg_del(mg); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_NO_MG: - vty_out (vty, "%% mesh-group does not exist\n"); - break; - default: - vty_out (vty, "%% mesh-group source del failed\n"); - } + result = pim_msdp_mg_del(mg); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_MG: + vty_out(vty, "%% mesh-group does not exist\n"); + break; + default: + vty_out(vty, "%% mesh-group source del failed\n"); + } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } DEFUN (no_ip_msdp_mesh_group_source, @@ -6285,86 +6713,87 @@ DEFUN (no_ip_msdp_mesh_group_source, "mesh group source\n" "mesh group local address\n") { - if (argc == 7) - return ip_no_msdp_mesh_group_cmd_worker(vty, argv[6]->arg); - else - return ip_no_msdp_mesh_group_source_cmd_worker(vty, argv[4]->arg); -} - -static void -print_empty_json_obj(struct vty *vty) -{ - json_object *json; - json = json_object_new_object(); - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); -} - -static void -ip_msdp_show_mesh_group(struct vty *vty, u_char uj) -{ - struct listnode *mbrnode; - struct pim_msdp_mg_mbr *mbr; - struct pim_msdp_mg *mg = msdp->mg; - char mbr_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; - char state_str[PIM_MSDP_STATE_STRLEN]; - enum pim_msdp_peer_state state; - json_object *json = NULL; - json_object *json_mg_row = NULL; - json_object *json_members = NULL; - json_object *json_row = NULL; - - if (!mg) { - if (uj) - print_empty_json_obj(vty); - return; - } - - pim_inet4_dump("<source?>", mg->src_ip, src_str, sizeof(src_str)); - if (uj) { - json = json_object_new_object(); - /* currently there is only one mesh group but we should still make - * it a dict with mg-name as key */ - json_mg_row = json_object_new_object(); - json_object_string_add(json_mg_row, "name", mg->mesh_group_name); - json_object_string_add(json_mg_row, "source", src_str); - } else { - vty_out (vty, "Mesh group : %s\n", mg->mesh_group_name); - vty_out (vty, " Source : %s\n", src_str); - vty_out (vty, " Member State\n"); - } - - for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { - pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); - if (mbr->mp) { - state = mbr->mp->state; - } else { - state = PIM_MSDP_DISABLED; - } - pim_msdp_state_dump(state, state_str, sizeof(state_str)); - if (uj) { - json_row = json_object_new_object(); - json_object_string_add(json_row, "member", mbr_str); - json_object_string_add(json_row, "state", state_str); - if (!json_members) { - json_members = json_object_new_object(); - json_object_object_add(json_mg_row, "members", json_members); - } - json_object_object_add(json_members, mbr_str, json_row); - } else { - vty_out (vty, " %-15s %11s\n", - mbr_str, state_str); - } - } - - if (uj) { - json_object_object_add(json, mg->mesh_group_name, json_mg_row); - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + if (argc == 7) + return ip_no_msdp_mesh_group_cmd_worker(vty, argv[6]->arg); + else + return ip_no_msdp_mesh_group_source_cmd_worker(vty, + argv[4]->arg); +} + +static void print_empty_json_obj(struct vty *vty) +{ + json_object *json; + json = json_object_new_object(); + vty_out(vty, "%s\n", + json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); +} + +static void ip_msdp_show_mesh_group(struct vty *vty, u_char uj) +{ + struct listnode *mbrnode; + struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg = msdp->mg; + char mbr_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + char state_str[PIM_MSDP_STATE_STRLEN]; + enum pim_msdp_peer_state state; + json_object *json = NULL; + json_object *json_mg_row = NULL; + json_object *json_members = NULL; + json_object *json_row = NULL; + + if (!mg) { + if (uj) + print_empty_json_obj(vty); + return; + } + + pim_inet4_dump("<source?>", mg->src_ip, src_str, sizeof(src_str)); + if (uj) { + json = json_object_new_object(); + /* currently there is only one mesh group but we should still + * make + * it a dict with mg-name as key */ + json_mg_row = json_object_new_object(); + json_object_string_add(json_mg_row, "name", + mg->mesh_group_name); + json_object_string_add(json_mg_row, "source", src_str); + } else { + vty_out(vty, "Mesh group : %s\n", mg->mesh_group_name); + vty_out(vty, " Source : %s\n", src_str); + vty_out(vty, " Member State\n"); + } + + for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { + pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); + if (mbr->mp) { + state = mbr->mp->state; + } else { + state = PIM_MSDP_DISABLED; + } + pim_msdp_state_dump(state, state_str, sizeof(state_str)); + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "member", mbr_str); + json_object_string_add(json_row, "state", state_str); + if (!json_members) { + json_members = json_object_new_object(); + json_object_object_add(json_mg_row, "members", + json_members); + } + json_object_object_add(json_members, mbr_str, json_row); + } else { + vty_out(vty, " %-15s %11s\n", mbr_str, state_str); + } + } + + if (uj) { + json_object_object_add(json, mg->mesh_group_name, json_mg_row); + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } DEFUN (show_ip_msdp_mesh_group, @@ -6376,151 +6805,168 @@ DEFUN (show_ip_msdp_mesh_group, "MSDP mesh-group information\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - ip_msdp_show_mesh_group(vty, uj); - - return CMD_SUCCESS; -} - -static void -ip_msdp_show_peers(struct vty *vty, u_char uj) -{ - struct listnode *mpnode; - struct pim_msdp_peer *mp; - char peer_str[INET_ADDRSTRLEN]; - char local_str[INET_ADDRSTRLEN]; - char state_str[PIM_MSDP_STATE_STRLEN]; - char timebuf[PIM_MSDP_UPTIME_STRLEN]; - int64_t now; - json_object *json = NULL; - json_object *json_row = NULL; - - - if (uj) { - json = json_object_new_object(); - } else { - vty_out (vty, - "Peer Local State Uptime SaCnt\n"); - } - - for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { - if (mp->state == PIM_MSDP_ESTABLISHED) { - now = pim_time_monotonic_sec(); - pim_time_uptime(timebuf, sizeof(timebuf), now - mp->uptime); - } else { - strcpy(timebuf, "-"); - } - pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str)); - pim_inet4_dump("<local?>", mp->local, local_str, sizeof(local_str)); - pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); - if (uj) { - json_row = json_object_new_object(); - json_object_string_add(json_row, "peer", peer_str); - json_object_string_add(json_row, "local", local_str); - json_object_string_add(json_row, "state", state_str); - json_object_string_add(json_row, "upTime", timebuf); - json_object_int_add(json_row, "saCount", mp->sa_cnt); - json_object_object_add(json, peer_str, json_row); - } else { - vty_out (vty, "%-15s %15s %11s %8s %6d\n", - peer_str, local_str, state_str, - timebuf, mp->sa_cnt); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } -} - -static void -ip_msdp_show_peers_detail(struct vty *vty, const char *peer, u_char uj) -{ - struct listnode *mpnode; - struct pim_msdp_peer *mp; - char peer_str[INET_ADDRSTRLEN]; - char local_str[INET_ADDRSTRLEN]; - char state_str[PIM_MSDP_STATE_STRLEN]; - char timebuf[PIM_MSDP_UPTIME_STRLEN]; - char katimer[PIM_MSDP_TIMER_STRLEN]; - char crtimer[PIM_MSDP_TIMER_STRLEN]; - char holdtimer[PIM_MSDP_TIMER_STRLEN]; - int64_t now; - json_object *json = NULL; - json_object *json_row = NULL; - - if (uj) { - json = json_object_new_object(); - } - - for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { - pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str)); - if (strcmp(peer, "detail") && - strcmp(peer, peer_str)) - continue; - - if (mp->state == PIM_MSDP_ESTABLISHED) { - now = pim_time_monotonic_sec(); - pim_time_uptime(timebuf, sizeof(timebuf), now - mp->uptime); - } else { - strcpy(timebuf, "-"); - } - pim_inet4_dump("<local?>", mp->local, local_str, sizeof(local_str)); - pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); - pim_time_timer_to_hhmmss(katimer, sizeof(katimer), mp->ka_timer); - pim_time_timer_to_hhmmss(crtimer, sizeof(crtimer), mp->cr_timer); - pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer), mp->hold_timer); - - if (uj) { - json_row = json_object_new_object(); - json_object_string_add(json_row, "peer", peer_str); - json_object_string_add(json_row, "local", local_str); - json_object_string_add(json_row, "meshGroupName", mp->mesh_group_name); - json_object_string_add(json_row, "state", state_str); - json_object_string_add(json_row, "upTime", timebuf); - json_object_string_add(json_row, "keepAliveTimer", katimer); - json_object_string_add(json_row, "connRetryTimer", crtimer); - json_object_string_add(json_row, "holdTimer", holdtimer); - json_object_string_add(json_row, "lastReset", mp->last_reset); - json_object_int_add(json_row, "connAttempts", mp->conn_attempts); - json_object_int_add(json_row, "establishedChanges", mp->est_flaps); - json_object_int_add(json_row, "saCount", mp->sa_cnt); - json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt); - json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt); - json_object_int_add(json_row, "saSent", mp->sa_tx_cnt); - json_object_int_add(json_row, "saRcvd", mp->sa_rx_cnt); - json_object_object_add(json, peer_str, json_row); - } else { - vty_out (vty, "Peer : %s\n", peer_str); - vty_out (vty, " Local : %s\n", local_str); - vty_out (vty, " Mesh Group : %s\n", mp->mesh_group_name); - vty_out (vty, " State : %s\n", state_str); - vty_out (vty, " Uptime : %s\n", timebuf); - - vty_out (vty, " Keepalive Timer : %s\n", katimer); - vty_out (vty, " Conn Retry Timer : %s\n", crtimer); - vty_out (vty, " Hold Timer : %s\n", holdtimer); - vty_out (vty, " Last Reset : %s\n", mp->last_reset); - vty_out (vty, " Conn Attempts : %d\n", mp->conn_attempts); - vty_out (vty, " Established Changes : %d\n", mp->est_flaps); - vty_out (vty, " SA Count : %d\n", mp->sa_cnt); - vty_out (vty, " Statistics :\n"); - vty_out (vty, " Sent Rcvd\n"); - vty_out (vty, " Keepalives : %10d %10d\n", - mp->ka_tx_cnt, mp->ka_rx_cnt); - vty_out (vty, " SAs : %10d %10d\n", - mp->sa_tx_cnt, mp->sa_rx_cnt); - vty_out (vty, "\n"); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + u_char uj = use_json(argc, argv); + ip_msdp_show_mesh_group(vty, uj); + + return CMD_SUCCESS; +} + +static void ip_msdp_show_peers(struct vty *vty, u_char uj) +{ + struct listnode *mpnode; + struct pim_msdp_peer *mp; + char peer_str[INET_ADDRSTRLEN]; + char local_str[INET_ADDRSTRLEN]; + char state_str[PIM_MSDP_STATE_STRLEN]; + char timebuf[PIM_MSDP_UPTIME_STRLEN]; + int64_t now; + json_object *json = NULL; + json_object *json_row = NULL; + + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, + "Peer Local State Uptime SaCnt\n"); + } + + for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { + if (mp->state == PIM_MSDP_ESTABLISHED) { + now = pim_time_monotonic_sec(); + pim_time_uptime(timebuf, sizeof(timebuf), + now - mp->uptime); + } else { + strcpy(timebuf, "-"); + } + pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str)); + pim_inet4_dump("<local?>", mp->local, local_str, + sizeof(local_str)); + pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "peer", peer_str); + json_object_string_add(json_row, "local", local_str); + json_object_string_add(json_row, "state", state_str); + json_object_string_add(json_row, "upTime", timebuf); + json_object_int_add(json_row, "saCount", mp->sa_cnt); + json_object_object_add(json, peer_str, json_row); + } else { + vty_out(vty, "%-15s %15s %11s %8s %6d\n", peer_str, + local_str, state_str, timebuf, mp->sa_cnt); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void ip_msdp_show_peers_detail(struct vty *vty, const char *peer, + u_char uj) +{ + struct listnode *mpnode; + struct pim_msdp_peer *mp; + char peer_str[INET_ADDRSTRLEN]; + char local_str[INET_ADDRSTRLEN]; + char state_str[PIM_MSDP_STATE_STRLEN]; + char timebuf[PIM_MSDP_UPTIME_STRLEN]; + char katimer[PIM_MSDP_TIMER_STRLEN]; + char crtimer[PIM_MSDP_TIMER_STRLEN]; + char holdtimer[PIM_MSDP_TIMER_STRLEN]; + int64_t now; + json_object *json = NULL; + json_object *json_row = NULL; + + if (uj) { + json = json_object_new_object(); + } + + for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { + pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str)); + if (strcmp(peer, "detail") && strcmp(peer, peer_str)) + continue; + + if (mp->state == PIM_MSDP_ESTABLISHED) { + now = pim_time_monotonic_sec(); + pim_time_uptime(timebuf, sizeof(timebuf), + now - mp->uptime); + } else { + strcpy(timebuf, "-"); + } + pim_inet4_dump("<local?>", mp->local, local_str, + sizeof(local_str)); + pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); + pim_time_timer_to_hhmmss(katimer, sizeof(katimer), + mp->ka_timer); + pim_time_timer_to_hhmmss(crtimer, sizeof(crtimer), + mp->cr_timer); + pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer), + mp->hold_timer); + + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "peer", peer_str); + json_object_string_add(json_row, "local", local_str); + json_object_string_add(json_row, "meshGroupName", + mp->mesh_group_name); + json_object_string_add(json_row, "state", state_str); + json_object_string_add(json_row, "upTime", timebuf); + json_object_string_add(json_row, "keepAliveTimer", + katimer); + json_object_string_add(json_row, "connRetryTimer", + crtimer); + json_object_string_add(json_row, "holdTimer", + holdtimer); + json_object_string_add(json_row, "lastReset", + mp->last_reset); + json_object_int_add(json_row, "connAttempts", + mp->conn_attempts); + json_object_int_add(json_row, "establishedChanges", + mp->est_flaps); + json_object_int_add(json_row, "saCount", mp->sa_cnt); + json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt); + json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt); + json_object_int_add(json_row, "saSent", mp->sa_tx_cnt); + json_object_int_add(json_row, "saRcvd", mp->sa_rx_cnt); + json_object_object_add(json, peer_str, json_row); + } else { + vty_out(vty, "Peer : %s\n", peer_str); + vty_out(vty, " Local : %s\n", local_str); + vty_out(vty, " Mesh Group : %s\n", + mp->mesh_group_name); + vty_out(vty, " State : %s\n", state_str); + vty_out(vty, " Uptime : %s\n", timebuf); + + vty_out(vty, " Keepalive Timer : %s\n", katimer); + vty_out(vty, " Conn Retry Timer : %s\n", crtimer); + vty_out(vty, " Hold Timer : %s\n", holdtimer); + vty_out(vty, " Last Reset : %s\n", + mp->last_reset); + vty_out(vty, " Conn Attempts : %d\n", + mp->conn_attempts); + vty_out(vty, " Established Changes : %d\n", + mp->est_flaps); + vty_out(vty, " SA Count : %d\n", + mp->sa_cnt); + vty_out(vty, " Statistics :\n"); + vty_out(vty, + " Sent Rcvd\n"); + vty_out(vty, " Keepalives : %10d %10d\n", + mp->ka_tx_cnt, mp->ka_rx_cnt); + vty_out(vty, " SAs : %10d %10d\n", + mp->sa_tx_cnt, mp->sa_rx_cnt); + vty_out(vty, "\n"); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } DEFUN (show_ip_msdp_peer_detail, @@ -6534,181 +6980,183 @@ DEFUN (show_ip_msdp_peer_detail, "peer ip address\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - if (uj) - argc--; - - if (argc > 4) - ip_msdp_show_peers_detail(vty, argv[4]->arg, uj); - else - ip_msdp_show_peers(vty, uj); - - return CMD_SUCCESS; -} - -static void -ip_msdp_show_sa(struct vty *vty, u_char uj) -{ - struct listnode *sanode; - struct pim_msdp_sa *sa; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - char rp_str[INET_ADDRSTRLEN]; - char timebuf[PIM_MSDP_UPTIME_STRLEN]; - char spt_str[8]; - char local_str[8]; - int64_t now; - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_row = NULL; - - if (uj) { - json = json_object_new_object(); - } else { - vty_out (vty, - "Source Group RP Local SPT Uptime\n"); - } - - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - now = pim_time_monotonic_sec(); - pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); - pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); - if (sa->flags & PIM_MSDP_SAF_PEER) { - pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str)); - if (sa->up) { - strcpy(spt_str, "yes"); - } else { - strcpy(spt_str, "no"); - } - } else { - strcpy(rp_str, "-"); - strcpy(spt_str, "-"); - } - if (sa->flags & PIM_MSDP_SAF_LOCAL) { - strcpy(local_str, "yes"); - } else { - strcpy(local_str, "no"); - } - if (uj) { - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - json_object_string_add(json_row, "rp", rp_str); - json_object_string_add(json_row, "local", local_str); - json_object_string_add(json_row, "sptSetup", spt_str); - json_object_string_add(json_row, "upTime", timebuf); - json_object_object_add(json_group, src_str, json_row); - } else { - vty_out (vty, "%-15s %15s %15s %5c %3c %8s\n", - src_str, grp_str, rp_str, local_str[0], spt_str[0], timebuf); - } - } - - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } -} - -static void -ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, const char *src_str, - const char *grp_str, struct vty *vty, - u_char uj, json_object *json) -{ - char rp_str[INET_ADDRSTRLEN]; - char peer_str[INET_ADDRSTRLEN]; - char timebuf[PIM_MSDP_UPTIME_STRLEN]; - char spt_str[8]; - char local_str[8]; - char statetimer[PIM_MSDP_TIMER_STRLEN]; - int64_t now; - json_object *json_group = NULL; - json_object *json_row = NULL; - - now = pim_time_monotonic_sec(); - pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); - if (sa->flags & PIM_MSDP_SAF_PEER) { - pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str)); - pim_inet4_dump("<peer?>", sa->peer, peer_str, sizeof(peer_str)); - if (sa->up) { - strcpy(spt_str, "yes"); - } else { - strcpy(spt_str, "no"); - } - } else { - strcpy(rp_str, "-"); - strcpy(peer_str, "-"); - strcpy(spt_str, "-"); - } - if (sa->flags & PIM_MSDP_SAF_LOCAL) { - strcpy(local_str, "yes"); - } else { - strcpy(local_str, "no"); - } - pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer), sa->sa_state_timer); - if (uj) { - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - json_object_string_add(json_row, "rp", rp_str); - json_object_string_add(json_row, "local", local_str); - json_object_string_add(json_row, "sptSetup", spt_str); - json_object_string_add(json_row, "upTime", timebuf); - json_object_string_add(json_row, "stateTimer", statetimer); - json_object_object_add(json_group, src_str, json_row); - } else { - vty_out (vty, "SA : %s\n", sa->sg_str); - vty_out (vty, " RP : %s\n", rp_str); - vty_out (vty, " Peer : %s\n", peer_str); - vty_out (vty, " Local : %s\n", local_str); - vty_out (vty, " SPT Setup : %s\n", spt_str); - vty_out (vty, " Uptime : %s\n", timebuf); - vty_out (vty, " State Timer : %s\n", statetimer); - vty_out (vty, "\n"); - } -} - -static void -ip_msdp_show_sa_detail(struct vty *vty, u_char uj) -{ - struct listnode *sanode; - struct pim_msdp_sa *sa; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - json_object *json = NULL; - - if (uj) { - json = json_object_new_object(); - } - - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); - ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + u_char uj = use_json(argc, argv); + if (uj) + argc--; + + if (argc > 4) + ip_msdp_show_peers_detail(vty, argv[4]->arg, uj); + else + ip_msdp_show_peers(vty, uj); + + return CMD_SUCCESS; +} + +static void ip_msdp_show_sa(struct vty *vty, u_char uj) +{ + struct listnode *sanode; + struct pim_msdp_sa *sa; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char rp_str[INET_ADDRSTRLEN]; + char timebuf[PIM_MSDP_UPTIME_STRLEN]; + char spt_str[8]; + char local_str[8]; + int64_t now; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, + "Source Group RP Local SPT Uptime\n"); + } + + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + now = pim_time_monotonic_sec(); + pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); + pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); + if (sa->flags & PIM_MSDP_SAF_PEER) { + pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str)); + if (sa->up) { + strcpy(spt_str, "yes"); + } else { + strcpy(spt_str, "no"); + } + } else { + strcpy(rp_str, "-"); + strcpy(spt_str, "-"); + } + if (sa->flags & PIM_MSDP_SAF_LOCAL) { + strcpy(local_str, "yes"); + } else { + strcpy(local_str, "no"); + } + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "rp", rp_str); + json_object_string_add(json_row, "local", local_str); + json_object_string_add(json_row, "sptSetup", spt_str); + json_object_string_add(json_row, "upTime", timebuf); + json_object_object_add(json_group, src_str, json_row); + } else { + vty_out(vty, "%-15s %15s %15s %5c %3c %8s\n", + src_str, grp_str, rp_str, local_str[0], + spt_str[0], timebuf); + } + } + + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, + const char *src_str, + const char *grp_str, struct vty *vty, + u_char uj, json_object *json) +{ + char rp_str[INET_ADDRSTRLEN]; + char peer_str[INET_ADDRSTRLEN]; + char timebuf[PIM_MSDP_UPTIME_STRLEN]; + char spt_str[8]; + char local_str[8]; + char statetimer[PIM_MSDP_TIMER_STRLEN]; + int64_t now; + json_object *json_group = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); + if (sa->flags & PIM_MSDP_SAF_PEER) { + pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str)); + pim_inet4_dump("<peer?>", sa->peer, peer_str, sizeof(peer_str)); + if (sa->up) { + strcpy(spt_str, "yes"); + } else { + strcpy(spt_str, "no"); + } + } else { + strcpy(rp_str, "-"); + strcpy(peer_str, "-"); + strcpy(spt_str, "-"); + } + if (sa->flags & PIM_MSDP_SAF_LOCAL) { + strcpy(local_str, "yes"); + } else { + strcpy(local_str, "no"); + } + pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer), + sa->sa_state_timer); + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, json_group); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "rp", rp_str); + json_object_string_add(json_row, "local", local_str); + json_object_string_add(json_row, "sptSetup", spt_str); + json_object_string_add(json_row, "upTime", timebuf); + json_object_string_add(json_row, "stateTimer", statetimer); + json_object_object_add(json_group, src_str, json_row); + } else { + vty_out(vty, "SA : %s\n", sa->sg_str); + vty_out(vty, " RP : %s\n", rp_str); + vty_out(vty, " Peer : %s\n", peer_str); + vty_out(vty, " Local : %s\n", local_str); + vty_out(vty, " SPT Setup : %s\n", spt_str); + vty_out(vty, " Uptime : %s\n", timebuf); + vty_out(vty, " State Timer : %s\n", statetimer); + vty_out(vty, "\n"); + } +} + +static void ip_msdp_show_sa_detail(struct vty *vty, u_char uj) +{ + struct listnode *sanode; + struct pim_msdp_sa *sa; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + json_object *json = NULL; + + if (uj) { + json = json_object_new_object(); + } + + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); + ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, + json); + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } DEFUN (show_ip_msdp_sa_detail, @@ -6721,66 +7169,67 @@ DEFUN (show_ip_msdp_sa_detail, "Detailed output\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - ip_msdp_show_sa_detail(vty, uj); + u_char uj = use_json(argc, argv); + ip_msdp_show_sa_detail(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -ip_msdp_show_sa_addr(struct vty *vty, const char *addr, u_char uj) +static void ip_msdp_show_sa_addr(struct vty *vty, const char *addr, u_char uj) { - struct listnode *sanode; - struct pim_msdp_sa *sa; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - json_object *json = NULL; + struct listnode *sanode; + struct pim_msdp_sa *sa; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + json_object *json = NULL; - if (uj) { - json = json_object_new_object(); - } + if (uj) { + json = json_object_new_object(); + } - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); - if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) { - ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); - } - } + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); + if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) { + ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, + uj, json); + } + } - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } -static void -ip_msdp_show_sa_sg(struct vty *vty, const char *src, const char *grp, u_char uj) +static void ip_msdp_show_sa_sg(struct vty *vty, const char *src, + const char *grp, u_char uj) { - struct listnode *sanode; - struct pim_msdp_sa *sa; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - json_object *json = NULL; + struct listnode *sanode; + struct pim_msdp_sa *sa; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + json_object *json = NULL; - if (uj) { - json = json_object_new_object(); - } + if (uj) { + json = json_object_new_object(); + } - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); - if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) { - ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); - } - } + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); + if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) { + ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, + uj, json); + } + } - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } DEFUN (show_ip_msdp_sa_sg, @@ -6794,218 +7243,227 @@ DEFUN (show_ip_msdp_sa_sg, "group ip\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); + u_char uj = use_json(argc, argv); - int idx = 0; - char *src_ip = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg : NULL; - char *grp_ip = idx < argc && argv_find (argv, argc, "A.B.C.D", &idx) ? - argv[idx]->arg : NULL; + int idx = 0; + char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg + : NULL; + char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx) + ? argv[idx]->arg + : NULL; - if (src_ip && grp_ip) - ip_msdp_show_sa_sg(vty, src_ip, grp_ip, uj); - else if (src_ip) - ip_msdp_show_sa_addr(vty, src_ip, uj); - else - ip_msdp_show_sa(vty, uj); + if (src_ip && grp_ip) + ip_msdp_show_sa_sg(vty, src_ip, grp_ip, uj); + else if (src_ip) + ip_msdp_show_sa_addr(vty, src_ip, uj); + else + ip_msdp_show_sa(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } void pim_cmd_init() { - install_node (&pim_global_node, pim_global_config_write); /* PIM_NODE */ - install_node (&interface_node, pim_interface_config_write); /* INTERFACE_NODE */ - if_cmd_init (); - - install_node (&debug_node, pim_debug_config_write); - - install_element (CONFIG_NODE, &ip_multicast_routing_cmd); - install_element (CONFIG_NODE, &no_ip_multicast_routing_cmd); - install_element (CONFIG_NODE, &ip_pim_rp_cmd); - install_element (CONFIG_NODE, &no_ip_pim_rp_cmd); - install_element (CONFIG_NODE, &ip_pim_rp_prefix_list_cmd); - install_element (CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd); - install_element (CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd); - install_element (CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd); - install_element (CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd); - install_element (CONFIG_NODE, &ip_pim_register_suppress_cmd); - install_element (CONFIG_NODE, &no_ip_pim_register_suppress_cmd); - install_element (CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd); - install_element (CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd); - install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd); - install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd); - install_element (CONFIG_NODE, &ip_pim_joinprune_time_cmd); - install_element (CONFIG_NODE, &no_ip_pim_joinprune_time_cmd); - install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd); - install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd); - install_element (CONFIG_NODE, &ip_pim_packets_cmd); - install_element (CONFIG_NODE, &no_ip_pim_packets_cmd); - install_element (CONFIG_NODE, &ip_pim_v6_secondary_cmd); - install_element (CONFIG_NODE, &no_ip_pim_v6_secondary_cmd); - install_element (CONFIG_NODE, &ip_ssmpingd_cmd); - install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd); - install_element (CONFIG_NODE, &ip_msdp_peer_cmd); - install_element (CONFIG_NODE, &no_ip_msdp_peer_cmd); - install_element (CONFIG_NODE, &ip_pim_ecmp_cmd); - install_element (CONFIG_NODE, &no_ip_pim_ecmp_cmd); - install_element (CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd); - install_element (CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd); - - install_element (INTERFACE_NODE, &interface_ip_igmp_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_igmp_cmd); - install_element (INTERFACE_NODE, &interface_ip_igmp_join_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_igmp_join_cmd); - install_element (INTERFACE_NODE, &interface_ip_igmp_version_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_igmp_version_cmd); - install_element (INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_interval_cmd); - install_element (INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_max_response_time_cmd); - install_element (INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_dsec_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_max_response_time_dsec_cmd); - install_element (INTERFACE_NODE, &interface_ip_pim_ssm_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd); - install_element (INTERFACE_NODE, &interface_ip_pim_sm_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_pim_sm_cmd); - install_element (INTERFACE_NODE, &interface_ip_pim_drprio_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd); - install_element (INTERFACE_NODE, &interface_ip_pim_hello_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_pim_hello_cmd); - - // Static mroutes NEB - install_element (INTERFACE_NODE, &interface_ip_mroute_cmd); - install_element (INTERFACE_NODE, &interface_ip_mroute_source_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_mroute_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_mroute_source_cmd); - - install_element (VIEW_NODE, &show_ip_igmp_interface_cmd); - install_element (VIEW_NODE, &show_ip_igmp_join_cmd); - install_element (VIEW_NODE, &show_ip_igmp_groups_cmd); - install_element (VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd); - install_element (VIEW_NODE, &show_ip_igmp_sources_cmd); - install_element (VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd); - install_element (VIEW_NODE, &show_ip_pim_assert_cmd); - install_element (VIEW_NODE, &show_ip_pim_assert_internal_cmd); - install_element (VIEW_NODE, &show_ip_pim_assert_metric_cmd); - install_element (VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd); - install_element (VIEW_NODE, &show_ip_pim_interface_traffic_cmd); - install_element (VIEW_NODE, &show_ip_pim_interface_cmd); - install_element (VIEW_NODE, &show_ip_pim_join_cmd); - install_element (VIEW_NODE, &show_ip_pim_local_membership_cmd); - install_element (VIEW_NODE, &show_ip_pim_neighbor_cmd); - install_element (VIEW_NODE, &show_ip_pim_rpf_cmd); - install_element (VIEW_NODE, &show_ip_pim_secondary_cmd); - install_element (VIEW_NODE, &show_ip_pim_state_cmd); - install_element (VIEW_NODE, &show_ip_pim_upstream_cmd); - install_element (VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd); - install_element (VIEW_NODE, &show_ip_pim_upstream_rpf_cmd); - install_element (VIEW_NODE, &show_ip_pim_rp_cmd); - install_element (VIEW_NODE, &show_ip_multicast_cmd); - install_element (VIEW_NODE, &show_ip_mroute_cmd); - install_element (VIEW_NODE, &show_ip_mroute_count_cmd); - install_element (VIEW_NODE, &show_ip_rib_cmd); - install_element (VIEW_NODE, &show_ip_ssmpingd_cmd); - install_element (VIEW_NODE, &show_debugging_pim_cmd); - install_element (VIEW_NODE, &show_ip_pim_nexthop_cmd); - install_element (VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd); - - install_element (ENABLE_NODE, &clear_ip_interfaces_cmd); - install_element (ENABLE_NODE, &clear_ip_igmp_interfaces_cmd); - install_element (ENABLE_NODE, &clear_ip_mroute_cmd); - install_element (ENABLE_NODE, &clear_ip_pim_interfaces_cmd); - install_element (ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd); - install_element (ENABLE_NODE, &clear_ip_pim_oil_cmd); - - install_element (ENABLE_NODE, &debug_igmp_cmd); - install_element (ENABLE_NODE, &no_debug_igmp_cmd); - install_element (ENABLE_NODE, &debug_igmp_events_cmd); - install_element (ENABLE_NODE, &no_debug_igmp_events_cmd); - install_element (ENABLE_NODE, &debug_igmp_packets_cmd); - install_element (ENABLE_NODE, &no_debug_igmp_packets_cmd); - install_element (ENABLE_NODE, &debug_igmp_trace_cmd); - install_element (ENABLE_NODE, &no_debug_igmp_trace_cmd); - install_element (ENABLE_NODE, &debug_mroute_cmd); - install_element (ENABLE_NODE, &debug_mroute_detail_cmd); - install_element (ENABLE_NODE, &no_debug_mroute_cmd); - install_element (ENABLE_NODE, &no_debug_mroute_detail_cmd); - install_element (ENABLE_NODE, &debug_static_cmd); - install_element (ENABLE_NODE, &no_debug_static_cmd); - install_element (ENABLE_NODE, &debug_pim_cmd); - install_element (ENABLE_NODE, &no_debug_pim_cmd); - install_element (ENABLE_NODE, &debug_pim_events_cmd); - install_element (ENABLE_NODE, &no_debug_pim_events_cmd); - install_element (ENABLE_NODE, &debug_pim_packets_cmd); - install_element (ENABLE_NODE, &no_debug_pim_packets_cmd); - install_element (ENABLE_NODE, &debug_pim_packetdump_send_cmd); - install_element (ENABLE_NODE, &no_debug_pim_packetdump_send_cmd); - install_element (ENABLE_NODE, &debug_pim_packetdump_recv_cmd); - install_element (ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd); - install_element (ENABLE_NODE, &debug_pim_trace_cmd); - install_element (ENABLE_NODE, &no_debug_pim_trace_cmd); - install_element (ENABLE_NODE, &debug_ssmpingd_cmd); - install_element (ENABLE_NODE, &no_debug_ssmpingd_cmd); - install_element (ENABLE_NODE, &debug_pim_zebra_cmd); - install_element (ENABLE_NODE, &no_debug_pim_zebra_cmd); - install_element (ENABLE_NODE, &debug_msdp_cmd); - install_element (ENABLE_NODE, &no_debug_msdp_cmd); - install_element (ENABLE_NODE, &undebug_msdp_cmd); - install_element (ENABLE_NODE, &debug_msdp_events_cmd); - install_element (ENABLE_NODE, &no_debug_msdp_events_cmd); - install_element (ENABLE_NODE, &undebug_msdp_events_cmd); - install_element (ENABLE_NODE, &debug_msdp_packets_cmd); - install_element (ENABLE_NODE, &no_debug_msdp_packets_cmd); - install_element (ENABLE_NODE, &undebug_msdp_packets_cmd); - - install_element (CONFIG_NODE, &debug_igmp_cmd); - install_element (CONFIG_NODE, &no_debug_igmp_cmd); - install_element (CONFIG_NODE, &debug_igmp_events_cmd); - install_element (CONFIG_NODE, &no_debug_igmp_events_cmd); - install_element (CONFIG_NODE, &debug_igmp_packets_cmd); - install_element (CONFIG_NODE, &no_debug_igmp_packets_cmd); - install_element (CONFIG_NODE, &debug_igmp_trace_cmd); - install_element (CONFIG_NODE, &no_debug_igmp_trace_cmd); - install_element (CONFIG_NODE, &debug_mroute_cmd); - install_element (CONFIG_NODE, &debug_mroute_detail_cmd); - install_element (CONFIG_NODE, &no_debug_mroute_cmd); - install_element (CONFIG_NODE, &no_debug_mroute_detail_cmd); - install_element (CONFIG_NODE, &debug_static_cmd); - install_element (CONFIG_NODE, &no_debug_static_cmd); - install_element (CONFIG_NODE, &debug_pim_cmd); - install_element (CONFIG_NODE, &no_debug_pim_cmd); - install_element (CONFIG_NODE, &debug_pim_events_cmd); - install_element (CONFIG_NODE, &no_debug_pim_events_cmd); - install_element (CONFIG_NODE, &debug_pim_packets_cmd); - install_element (CONFIG_NODE, &no_debug_pim_packets_cmd); - install_element (CONFIG_NODE, &debug_pim_trace_cmd); - install_element (CONFIG_NODE, &no_debug_pim_trace_cmd); - install_element (CONFIG_NODE, &debug_ssmpingd_cmd); - install_element (CONFIG_NODE, &no_debug_ssmpingd_cmd); - install_element (CONFIG_NODE, &debug_pim_zebra_cmd); - install_element (CONFIG_NODE, &no_debug_pim_zebra_cmd); - install_element (CONFIG_NODE, &debug_msdp_cmd); - install_element (CONFIG_NODE, &no_debug_msdp_cmd); - install_element (CONFIG_NODE, &undebug_msdp_cmd); - install_element (CONFIG_NODE, &debug_msdp_events_cmd); - install_element (CONFIG_NODE, &no_debug_msdp_events_cmd); - install_element (CONFIG_NODE, &undebug_msdp_events_cmd); - install_element (CONFIG_NODE, &debug_msdp_packets_cmd); - install_element (CONFIG_NODE, &no_debug_msdp_packets_cmd); - install_element (CONFIG_NODE, &undebug_msdp_packets_cmd); - install_element (CONFIG_NODE, &ip_msdp_mesh_group_member_cmd); - install_element (CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd); - install_element (CONFIG_NODE, &ip_msdp_mesh_group_source_cmd); - install_element (CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd); - install_element (VIEW_NODE, &show_ip_msdp_peer_detail_cmd); - install_element (VIEW_NODE, &show_ip_msdp_sa_detail_cmd); - install_element (VIEW_NODE, &show_ip_msdp_sa_sg_cmd); - install_element (VIEW_NODE, &show_ip_msdp_mesh_group_cmd); - install_element (VIEW_NODE, &show_ip_pim_ssm_range_cmd); - install_element (VIEW_NODE, &show_ip_pim_group_type_cmd); - install_element (INTERFACE_NODE, &interface_pim_use_source_cmd); - install_element (INTERFACE_NODE, &interface_no_pim_use_source_cmd); - /* Install BFD command */ - install_element (INTERFACE_NODE, &ip_pim_bfd_cmd); - install_element (INTERFACE_NODE, &ip_pim_bfd_param_cmd); - install_element (INTERFACE_NODE, &no_ip_pim_bfd_cmd); - install_element (INTERFACE_NODE, &no_ip_pim_bfd_param_cmd); + install_node(&pim_global_node, pim_global_config_write); /* PIM_NODE */ + install_node(&interface_node, + pim_interface_config_write); /* INTERFACE_NODE */ + if_cmd_init(); + + install_node(&debug_node, pim_debug_config_write); + + install_element(CONFIG_NODE, &ip_multicast_routing_cmd); + install_element(CONFIG_NODE, &no_ip_multicast_routing_cmd); + install_element(CONFIG_NODE, &ip_pim_rp_cmd); + install_element(CONFIG_NODE, &no_ip_pim_rp_cmd); + install_element(CONFIG_NODE, &ip_pim_rp_prefix_list_cmd); + install_element(CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd); + install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd); + install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd); + install_element(CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd); + install_element(CONFIG_NODE, &ip_pim_register_suppress_cmd); + install_element(CONFIG_NODE, &no_ip_pim_register_suppress_cmd); + install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd); + install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd); + install_element(CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd); + install_element(CONFIG_NODE, + &no_ip_pim_spt_switchover_infinity_plist_cmd); + install_element(CONFIG_NODE, &ip_pim_joinprune_time_cmd); + install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd); + install_element(CONFIG_NODE, &ip_pim_keep_alive_cmd); + install_element(CONFIG_NODE, &no_ip_pim_keep_alive_cmd); + install_element(CONFIG_NODE, &ip_pim_packets_cmd); + install_element(CONFIG_NODE, &no_ip_pim_packets_cmd); + install_element(CONFIG_NODE, &ip_pim_v6_secondary_cmd); + install_element(CONFIG_NODE, &no_ip_pim_v6_secondary_cmd); + install_element(CONFIG_NODE, &ip_ssmpingd_cmd); + install_element(CONFIG_NODE, &no_ip_ssmpingd_cmd); + install_element(CONFIG_NODE, &ip_msdp_peer_cmd); + install_element(CONFIG_NODE, &no_ip_msdp_peer_cmd); + install_element(CONFIG_NODE, &ip_pim_ecmp_cmd); + install_element(CONFIG_NODE, &no_ip_pim_ecmp_cmd); + install_element(CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd); + install_element(CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd); + + install_element(INTERFACE_NODE, &interface_ip_igmp_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd); + install_element(INTERFACE_NODE, &interface_ip_igmp_join_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_igmp_join_cmd); + install_element(INTERFACE_NODE, &interface_ip_igmp_version_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_igmp_version_cmd); + install_element(INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd); + install_element(INTERFACE_NODE, + &interface_no_ip_igmp_query_interval_cmd); + install_element(INTERFACE_NODE, + &interface_ip_igmp_query_max_response_time_cmd); + install_element(INTERFACE_NODE, + &interface_no_ip_igmp_query_max_response_time_cmd); + install_element(INTERFACE_NODE, + &interface_ip_igmp_query_max_response_time_dsec_cmd); + install_element(INTERFACE_NODE, + &interface_no_ip_igmp_query_max_response_time_dsec_cmd); + install_element(INTERFACE_NODE, &interface_ip_pim_ssm_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd); + install_element(INTERFACE_NODE, &interface_ip_pim_sm_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_pim_sm_cmd); + install_element(INTERFACE_NODE, &interface_ip_pim_drprio_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd); + install_element(INTERFACE_NODE, &interface_ip_pim_hello_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_pim_hello_cmd); + + // Static mroutes NEB + install_element(INTERFACE_NODE, &interface_ip_mroute_cmd); + install_element(INTERFACE_NODE, &interface_ip_mroute_source_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_mroute_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_mroute_source_cmd); + + install_element(VIEW_NODE, &show_ip_igmp_interface_cmd); + install_element(VIEW_NODE, &show_ip_igmp_join_cmd); + install_element(VIEW_NODE, &show_ip_igmp_groups_cmd); + install_element(VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd); + install_element(VIEW_NODE, &show_ip_igmp_sources_cmd); + install_element(VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd); + install_element(VIEW_NODE, &show_ip_pim_assert_cmd); + install_element(VIEW_NODE, &show_ip_pim_assert_internal_cmd); + install_element(VIEW_NODE, &show_ip_pim_assert_metric_cmd); + install_element(VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd); + install_element(VIEW_NODE, &show_ip_pim_interface_traffic_cmd); + install_element(VIEW_NODE, &show_ip_pim_interface_cmd); + install_element(VIEW_NODE, &show_ip_pim_join_cmd); + install_element(VIEW_NODE, &show_ip_pim_local_membership_cmd); + install_element(VIEW_NODE, &show_ip_pim_neighbor_cmd); + install_element(VIEW_NODE, &show_ip_pim_rpf_cmd); + install_element(VIEW_NODE, &show_ip_pim_secondary_cmd); + install_element(VIEW_NODE, &show_ip_pim_state_cmd); + install_element(VIEW_NODE, &show_ip_pim_upstream_cmd); + install_element(VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd); + install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd); + install_element(VIEW_NODE, &show_ip_pim_rp_cmd); + install_element(VIEW_NODE, &show_ip_multicast_cmd); + install_element(VIEW_NODE, &show_ip_mroute_cmd); + install_element(VIEW_NODE, &show_ip_mroute_count_cmd); + install_element(VIEW_NODE, &show_ip_rib_cmd); + install_element(VIEW_NODE, &show_ip_ssmpingd_cmd); + install_element(VIEW_NODE, &show_debugging_pim_cmd); + install_element(VIEW_NODE, &show_ip_pim_nexthop_cmd); + install_element(VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd); + + install_element(ENABLE_NODE, &clear_ip_interfaces_cmd); + install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd); + install_element(ENABLE_NODE, &clear_ip_mroute_cmd); + install_element(ENABLE_NODE, &clear_ip_pim_interfaces_cmd); + install_element(ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd); + install_element(ENABLE_NODE, &clear_ip_pim_oil_cmd); + + install_element(ENABLE_NODE, &debug_igmp_cmd); + install_element(ENABLE_NODE, &no_debug_igmp_cmd); + install_element(ENABLE_NODE, &debug_igmp_events_cmd); + install_element(ENABLE_NODE, &no_debug_igmp_events_cmd); + install_element(ENABLE_NODE, &debug_igmp_packets_cmd); + install_element(ENABLE_NODE, &no_debug_igmp_packets_cmd); + install_element(ENABLE_NODE, &debug_igmp_trace_cmd); + install_element(ENABLE_NODE, &no_debug_igmp_trace_cmd); + install_element(ENABLE_NODE, &debug_mroute_cmd); + install_element(ENABLE_NODE, &debug_mroute_detail_cmd); + install_element(ENABLE_NODE, &no_debug_mroute_cmd); + install_element(ENABLE_NODE, &no_debug_mroute_detail_cmd); + install_element(ENABLE_NODE, &debug_static_cmd); + install_element(ENABLE_NODE, &no_debug_static_cmd); + install_element(ENABLE_NODE, &debug_pim_cmd); + install_element(ENABLE_NODE, &no_debug_pim_cmd); + install_element(ENABLE_NODE, &debug_pim_events_cmd); + install_element(ENABLE_NODE, &no_debug_pim_events_cmd); + install_element(ENABLE_NODE, &debug_pim_packets_cmd); + install_element(ENABLE_NODE, &no_debug_pim_packets_cmd); + install_element(ENABLE_NODE, &debug_pim_packetdump_send_cmd); + install_element(ENABLE_NODE, &no_debug_pim_packetdump_send_cmd); + install_element(ENABLE_NODE, &debug_pim_packetdump_recv_cmd); + install_element(ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd); + install_element(ENABLE_NODE, &debug_pim_trace_cmd); + install_element(ENABLE_NODE, &no_debug_pim_trace_cmd); + install_element(ENABLE_NODE, &debug_ssmpingd_cmd); + install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd); + install_element(ENABLE_NODE, &debug_pim_zebra_cmd); + install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd); + install_element(ENABLE_NODE, &debug_msdp_cmd); + install_element(ENABLE_NODE, &no_debug_msdp_cmd); + install_element(ENABLE_NODE, &undebug_msdp_cmd); + install_element(ENABLE_NODE, &debug_msdp_events_cmd); + install_element(ENABLE_NODE, &no_debug_msdp_events_cmd); + install_element(ENABLE_NODE, &undebug_msdp_events_cmd); + install_element(ENABLE_NODE, &debug_msdp_packets_cmd); + install_element(ENABLE_NODE, &no_debug_msdp_packets_cmd); + install_element(ENABLE_NODE, &undebug_msdp_packets_cmd); + + install_element(CONFIG_NODE, &debug_igmp_cmd); + install_element(CONFIG_NODE, &no_debug_igmp_cmd); + install_element(CONFIG_NODE, &debug_igmp_events_cmd); + install_element(CONFIG_NODE, &no_debug_igmp_events_cmd); + install_element(CONFIG_NODE, &debug_igmp_packets_cmd); + install_element(CONFIG_NODE, &no_debug_igmp_packets_cmd); + install_element(CONFIG_NODE, &debug_igmp_trace_cmd); + install_element(CONFIG_NODE, &no_debug_igmp_trace_cmd); + install_element(CONFIG_NODE, &debug_mroute_cmd); + install_element(CONFIG_NODE, &debug_mroute_detail_cmd); + install_element(CONFIG_NODE, &no_debug_mroute_cmd); + install_element(CONFIG_NODE, &no_debug_mroute_detail_cmd); + install_element(CONFIG_NODE, &debug_static_cmd); + install_element(CONFIG_NODE, &no_debug_static_cmd); + install_element(CONFIG_NODE, &debug_pim_cmd); + install_element(CONFIG_NODE, &no_debug_pim_cmd); + install_element(CONFIG_NODE, &debug_pim_events_cmd); + install_element(CONFIG_NODE, &no_debug_pim_events_cmd); + install_element(CONFIG_NODE, &debug_pim_packets_cmd); + install_element(CONFIG_NODE, &no_debug_pim_packets_cmd); + install_element(CONFIG_NODE, &debug_pim_trace_cmd); + install_element(CONFIG_NODE, &no_debug_pim_trace_cmd); + install_element(CONFIG_NODE, &debug_ssmpingd_cmd); + install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd); + install_element(CONFIG_NODE, &debug_pim_zebra_cmd); + install_element(CONFIG_NODE, &no_debug_pim_zebra_cmd); + install_element(CONFIG_NODE, &debug_msdp_cmd); + install_element(CONFIG_NODE, &no_debug_msdp_cmd); + install_element(CONFIG_NODE, &undebug_msdp_cmd); + install_element(CONFIG_NODE, &debug_msdp_events_cmd); + install_element(CONFIG_NODE, &no_debug_msdp_events_cmd); + install_element(CONFIG_NODE, &undebug_msdp_events_cmd); + install_element(CONFIG_NODE, &debug_msdp_packets_cmd); + install_element(CONFIG_NODE, &no_debug_msdp_packets_cmd); + install_element(CONFIG_NODE, &undebug_msdp_packets_cmd); + install_element(CONFIG_NODE, &ip_msdp_mesh_group_member_cmd); + install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd); + install_element(CONFIG_NODE, &ip_msdp_mesh_group_source_cmd); + install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd); + install_element(VIEW_NODE, &show_ip_msdp_peer_detail_cmd); + install_element(VIEW_NODE, &show_ip_msdp_sa_detail_cmd); + install_element(VIEW_NODE, &show_ip_msdp_sa_sg_cmd); + install_element(VIEW_NODE, &show_ip_msdp_mesh_group_cmd); + install_element(VIEW_NODE, &show_ip_pim_ssm_range_cmd); + install_element(VIEW_NODE, &show_ip_pim_group_type_cmd); + install_element(INTERFACE_NODE, &interface_pim_use_source_cmd); + install_element(INTERFACE_NODE, &interface_no_pim_use_source_cmd); + /* Install BFD command */ + install_element(INTERFACE_NODE, &ip_pim_bfd_cmd); + install_element(INTERFACE_NODE, &ip_pim_bfd_param_cmd); + install_element(INTERFACE_NODE, &no_ip_pim_bfd_cmd); + install_element(INTERFACE_NODE, &no_ip_pim_bfd_param_cmd); } diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c index 0c08cfa46..2592514f3 100644 --- a/pimd/pim_hello.c +++ b/pimd/pim_hello.c @@ -32,71 +32,66 @@ #include "pim_neighbor.h" #include "pim_upstream.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[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src, src_str, sizeof(src_str)); - zlog_debug("%s: from %s on %s", - label, src_str, ifp->name); - } + if (PIM_DEBUG_PIM_TRACE) { + 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); + } } static void tlv_trace_bool(const char *label, const char *tlv_name, const char *ifname, struct in_addr src_addr, int isset, int value) { - if (isset) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello option from %s on interface %s: %s=%d", - label, - src_str, ifname, - tlv_name, value); - } + if (isset) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + zlog_debug( + "%s: PIM hello option from %s on interface %s: %s=%d", + label, src_str, ifname, tlv_name, value); + } } static void tlv_trace_uint16(const char *label, const char *tlv_name, const char *ifname, struct in_addr src_addr, int isset, uint16_t value) { - if (isset) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello option from %s on interface %s: %s=%u", - label, - src_str, ifname, - tlv_name, value); - } + if (isset) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + zlog_debug( + "%s: PIM hello option from %s on interface %s: %s=%u", + label, src_str, ifname, tlv_name, value); + } } static void tlv_trace_uint32(const char *label, const char *tlv_name, const char *ifname, struct in_addr src_addr, int isset, uint32_t value) { - if (isset) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello option from %s on interface %s: %s=%u", - label, - src_str, ifname, - tlv_name, value); - } + if (isset) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + zlog_debug( + "%s: PIM hello option from %s on interface %s: %s=%u", + label, src_str, ifname, tlv_name, value); + } } static void tlv_trace_uint32_hex(const char *label, const char *tlv_name, const char *ifname, struct in_addr src_addr, int isset, uint32_t value) { - if (isset) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello option from %s on interface %s: %s=%08x", - label, - src_str, ifname, - tlv_name, value); - } + if (isset) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + zlog_debug( + "%s: PIM hello option from %s on interface %s: %s=%08x", + label, src_str, ifname, tlv_name, value); + } } #if 0 @@ -119,418 +114,423 @@ static void tlv_trace_list(const char *label, const char *tlv_name, const char *ifname, struct in_addr src_addr, int isset, struct list *addr_list) { - if (isset) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello option from %s on interface %s: %s size=%d list=%p", - label, - src_str, ifname, - tlv_name, - addr_list ? ((int) listcount(addr_list)) : -1, - (void *) addr_list); - } + if (isset) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + zlog_debug( + "%s: PIM hello option from %s on interface %s: %s size=%d list=%p", + label, src_str, ifname, tlv_name, + addr_list ? ((int)listcount(addr_list)) : -1, + (void *)addr_list); + } } -#define FREE_ADDR_LIST \ - if (hello_option_addr_list) { \ - list_delete(hello_option_addr_list); \ - } +#define FREE_ADDR_LIST \ + if (hello_option_addr_list) { \ + list_delete(hello_option_addr_list); \ + } -#define FREE_ADDR_LIST_THEN_RETURN(code) \ -{ \ - FREE_ADDR_LIST \ - return (code); \ -} +#define FREE_ADDR_LIST_THEN_RETURN(code) \ + { \ + FREE_ADDR_LIST \ + return (code); \ + } -int pim_hello_recv(struct interface *ifp, - struct in_addr src_addr, +int pim_hello_recv(struct interface *ifp, struct in_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size) { - struct pim_interface *pim_ifp; - struct pim_neighbor *neigh; - uint8_t *tlv_curr; - uint8_t *tlv_pastend; - pim_hello_options hello_options = 0; /* bit array recording options found */ - uint16_t hello_option_holdtime = 0; - uint16_t hello_option_propagation_delay = 0; - uint16_t hello_option_override_interval = 0; - uint32_t hello_option_dr_priority = 0; - uint32_t hello_option_generation_id = 0; - struct list *hello_option_addr_list = 0; - - if (PIM_DEBUG_PIM_HELLO) - on_trace(__PRETTY_FUNCTION__, ifp, src_addr); - - pim_ifp = ifp->info; - zassert(pim_ifp); - - ++pim_ifp->pim_ifstat_hello_recv; - - /* - Parse PIM hello TLVs - */ - zassert(tlv_buf_size >= 0); - tlv_curr = tlv_buf; - tlv_pastend = tlv_buf + tlv_buf_size; - - while (tlv_curr < tlv_pastend) { - uint16_t option_type; - uint16_t option_len; - int remain = tlv_pastend - tlv_curr; - - if (remain < PIM_TLV_MIN_SIZE) { - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: short PIM hello TLV size=%d < min=%d from %s on interface %s", - __PRETTY_FUNCTION__, - remain, PIM_TLV_MIN_SIZE, - src_str, ifp->name); - } - FREE_ADDR_LIST_THEN_RETURN(-1); - } - - option_type = PIM_TLV_GET_TYPE(tlv_curr); - tlv_curr += PIM_TLV_TYPE_SIZE; - option_len = PIM_TLV_GET_LENGTH(tlv_curr); - tlv_curr += PIM_TLV_LENGTH_SIZE; - - if ((tlv_curr + option_len) > tlv_pastend) { - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: long PIM hello TLV type=%d length=%d > left=%td from %s on interface %s", - __PRETTY_FUNCTION__, - option_type, option_len, tlv_pastend - tlv_curr, - src_str, ifp->name); - } - FREE_ADDR_LIST_THEN_RETURN(-2); - } - - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: parse left_size=%d: PIM hello TLV type=%d length=%d from %s on %s", - __PRETTY_FUNCTION__, - remain, - option_type, option_len, - src_str, ifp->name); - } - - switch (option_type) { - case PIM_MSG_OPTION_TYPE_HOLDTIME: - if (pim_tlv_parse_holdtime(ifp->name, src_addr, - &hello_options, - &hello_option_holdtime, - option_len, - tlv_curr)) { - FREE_ADDR_LIST_THEN_RETURN(-3); - } - break; - case PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY: - if (pim_tlv_parse_lan_prune_delay(ifp->name, src_addr, - &hello_options, - &hello_option_propagation_delay, - &hello_option_override_interval, - option_len, - tlv_curr)) { - FREE_ADDR_LIST_THEN_RETURN(-4); - } - break; - case PIM_MSG_OPTION_TYPE_DR_PRIORITY: - if (pim_tlv_parse_dr_priority(ifp->name, src_addr, - &hello_options, - &hello_option_dr_priority, - option_len, + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; + uint8_t *tlv_curr; + uint8_t *tlv_pastend; + pim_hello_options hello_options = + 0; /* bit array recording options found */ + uint16_t hello_option_holdtime = 0; + uint16_t hello_option_propagation_delay = 0; + uint16_t hello_option_override_interval = 0; + uint32_t hello_option_dr_priority = 0; + uint32_t hello_option_generation_id = 0; + struct list *hello_option_addr_list = 0; + + if (PIM_DEBUG_PIM_HELLO) + on_trace(__PRETTY_FUNCTION__, ifp, src_addr); + + pim_ifp = ifp->info; + zassert(pim_ifp); + + ++pim_ifp->pim_ifstat_hello_recv; + + /* + Parse PIM hello TLVs + */ + zassert(tlv_buf_size >= 0); + tlv_curr = tlv_buf; + tlv_pastend = tlv_buf + tlv_buf_size; + + while (tlv_curr < tlv_pastend) { + uint16_t option_type; + uint16_t option_len; + int remain = tlv_pastend - tlv_curr; + + if (remain < PIM_TLV_MIN_SIZE) { + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: short PIM hello TLV size=%d < min=%d from %s on interface %s", + __PRETTY_FUNCTION__, remain, + PIM_TLV_MIN_SIZE, src_str, ifp->name); + } + FREE_ADDR_LIST_THEN_RETURN(-1); + } + + option_type = PIM_TLV_GET_TYPE(tlv_curr); + tlv_curr += PIM_TLV_TYPE_SIZE; + option_len = PIM_TLV_GET_LENGTH(tlv_curr); + tlv_curr += PIM_TLV_LENGTH_SIZE; + + if ((tlv_curr + option_len) > tlv_pastend) { + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: long PIM hello TLV type=%d length=%d > left=%td from %s on interface %s", + __PRETTY_FUNCTION__, option_type, + option_len, tlv_pastend - tlv_curr, + src_str, ifp->name); + } + FREE_ADDR_LIST_THEN_RETURN(-2); + } + + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: parse left_size=%d: PIM hello TLV type=%d length=%d from %s on %s", + __PRETTY_FUNCTION__, remain, option_type, + option_len, src_str, ifp->name); + } + + switch (option_type) { + case PIM_MSG_OPTION_TYPE_HOLDTIME: + if (pim_tlv_parse_holdtime(ifp->name, src_addr, + &hello_options, + &hello_option_holdtime, + option_len, tlv_curr)) { + FREE_ADDR_LIST_THEN_RETURN(-3); + } + break; + case PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY: + if (pim_tlv_parse_lan_prune_delay( + ifp->name, src_addr, &hello_options, + &hello_option_propagation_delay, + &hello_option_override_interval, option_len, tlv_curr)) { - FREE_ADDR_LIST_THEN_RETURN(-5); - } - break; - case PIM_MSG_OPTION_TYPE_GENERATION_ID: - if (pim_tlv_parse_generation_id(ifp->name, src_addr, - &hello_options, - &hello_option_generation_id, - option_len, - tlv_curr)) { - FREE_ADDR_LIST_THEN_RETURN(-6); - } - break; - case PIM_MSG_OPTION_TYPE_ADDRESS_LIST: - if (pim_tlv_parse_addr_list(ifp->name, src_addr, - &hello_options, - &hello_option_addr_list, - option_len, - tlv_curr)) { - return -7; - } - break; - case PIM_MSG_OPTION_TYPE_DM_STATE_REFRESH: - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: ignoring PIM hello dense-mode state refresh TLV option type=%d length=%d from %s on interface %s", - __PRETTY_FUNCTION__, - option_type, option_len, - src_str, ifp->name); - } - break; - default: - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: ignoring unknown PIM hello TLV type=%d length=%d from %s on interface %s", - __PRETTY_FUNCTION__, - option_type, option_len, - src_str, ifp->name); - } - } - - tlv_curr += option_len; - } + FREE_ADDR_LIST_THEN_RETURN(-4); + } + break; + case PIM_MSG_OPTION_TYPE_DR_PRIORITY: + if (pim_tlv_parse_dr_priority(ifp->name, src_addr, + &hello_options, + &hello_option_dr_priority, + option_len, tlv_curr)) { + FREE_ADDR_LIST_THEN_RETURN(-5); + } + break; + case PIM_MSG_OPTION_TYPE_GENERATION_ID: + if (pim_tlv_parse_generation_id( + ifp->name, src_addr, &hello_options, + &hello_option_generation_id, option_len, + tlv_curr)) { + FREE_ADDR_LIST_THEN_RETURN(-6); + } + break; + case PIM_MSG_OPTION_TYPE_ADDRESS_LIST: + if (pim_tlv_parse_addr_list(ifp->name, src_addr, + &hello_options, + &hello_option_addr_list, + option_len, tlv_curr)) { + return -7; + } + break; + case PIM_MSG_OPTION_TYPE_DM_STATE_REFRESH: + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: ignoring PIM hello dense-mode state refresh TLV option type=%d length=%d from %s on interface %s", + __PRETTY_FUNCTION__, option_type, + option_len, src_str, ifp->name); + } + break; + default: + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: ignoring unknown PIM hello TLV type=%d length=%d from %s on interface %s", + __PRETTY_FUNCTION__, option_type, + option_len, src_str, ifp->name); + } + } + + tlv_curr += option_len; + } - /* - Check received PIM hello options - */ - - if (PIM_DEBUG_PIM_HELLO) { - tlv_trace_uint16(__PRETTY_FUNCTION__, "holdtime", - ifp->name, src_addr, - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME), - hello_option_holdtime); - tlv_trace_uint16(__PRETTY_FUNCTION__, "propagation_delay", - ifp->name, src_addr, - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY), - hello_option_propagation_delay); - tlv_trace_uint16(__PRETTY_FUNCTION__, "override_interval", - ifp->name, src_addr, - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY), - hello_option_override_interval); - tlv_trace_bool(__PRETTY_FUNCTION__, "can_disable_join_suppression", - ifp->name, src_addr, - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY), - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)); - tlv_trace_uint32(__PRETTY_FUNCTION__, "dr_priority", - ifp->name, src_addr, - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_DR_PRIORITY), - hello_option_dr_priority); - tlv_trace_uint32_hex(__PRETTY_FUNCTION__, "generation_id", - ifp->name, src_addr, - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_GENERATION_ID), - hello_option_generation_id); - tlv_trace_list(__PRETTY_FUNCTION__, "address_list", - ifp->name, src_addr, - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_ADDRESS_LIST), - hello_option_addr_list); - } + /* + Check received PIM hello options + */ - if (!PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello missing holdtime from %s on interface %s", - __PRETTY_FUNCTION__, - src_str, ifp->name); - } - } + if (PIM_DEBUG_PIM_HELLO) { + tlv_trace_uint16(__PRETTY_FUNCTION__, "holdtime", ifp->name, + src_addr, + PIM_OPTION_IS_SET(hello_options, + PIM_OPTION_MASK_HOLDTIME), + hello_option_holdtime); + tlv_trace_uint16( + __PRETTY_FUNCTION__, "propagation_delay", ifp->name, + src_addr, + PIM_OPTION_IS_SET(hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY), + hello_option_propagation_delay); + tlv_trace_uint16( + __PRETTY_FUNCTION__, "override_interval", ifp->name, + src_addr, + PIM_OPTION_IS_SET(hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY), + hello_option_override_interval); + tlv_trace_bool( + __PRETTY_FUNCTION__, "can_disable_join_suppression", + ifp->name, src_addr, + PIM_OPTION_IS_SET(hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY), + PIM_OPTION_IS_SET( + hello_options, + PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)); + tlv_trace_uint32(__PRETTY_FUNCTION__, "dr_priority", ifp->name, + src_addr, + PIM_OPTION_IS_SET(hello_options, + PIM_OPTION_MASK_DR_PRIORITY), + hello_option_dr_priority); + tlv_trace_uint32_hex( + __PRETTY_FUNCTION__, "generation_id", ifp->name, + src_addr, + PIM_OPTION_IS_SET(hello_options, + PIM_OPTION_MASK_GENERATION_ID), + hello_option_generation_id); + tlv_trace_list(__PRETTY_FUNCTION__, "address_list", ifp->name, + src_addr, + PIM_OPTION_IS_SET(hello_options, + PIM_OPTION_MASK_ADDRESS_LIST), + hello_option_addr_list); + } - /* - New neighbor? - */ - - neigh = pim_neighbor_find(ifp, src_addr); - if (!neigh) { - /* Add as new neighbor */ - - neigh = pim_neighbor_add(ifp, src_addr, - hello_options, - hello_option_holdtime, - hello_option_propagation_delay, - hello_option_override_interval, - hello_option_dr_priority, - hello_option_generation_id, - hello_option_addr_list, - PIM_NEIGHBOR_SEND_DELAY); - if (!neigh) { - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: failure creating PIM neighbor %s on interface %s", - __PRETTY_FUNCTION__, - src_str, ifp->name); - } - FREE_ADDR_LIST_THEN_RETURN(-8); - } - - /* actual addr list has been saved under neighbor */ - return 0; - } + if (!PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: PIM hello missing holdtime from %s on interface %s", + __PRETTY_FUNCTION__, src_str, ifp->name); + } + } - /* - Received generation ID ? - */ - - if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_GENERATION_ID)) { - /* GenID mismatch ? */ - if (!PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID) || - (hello_option_generation_id != neigh->generation_id)) { - /* GenID mismatch, then replace neighbor */ - - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: GenId mismatch new=%08x old=%08x: replacing neighbor %s on %s", - __PRETTY_FUNCTION__, - hello_option_generation_id, - neigh->generation_id, - src_str, ifp->name); - } - - pim_upstream_rpf_genid_changed(neigh->source_addr); - - pim_neighbor_delete(ifp, neigh, "GenID mismatch"); - neigh = pim_neighbor_add(ifp, src_addr, - hello_options, - hello_option_holdtime, - hello_option_propagation_delay, - hello_option_override_interval, - hello_option_dr_priority, - hello_option_generation_id, - hello_option_addr_list, - PIM_NEIGHBOR_SEND_NOW); - if (!neigh) { - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: failure re-creating PIM neighbor %s on interface %s", - __PRETTY_FUNCTION__, - src_str, ifp->name); + /* + New neighbor? + */ + + neigh = pim_neighbor_find(ifp, src_addr); + if (!neigh) { + /* Add as new neighbor */ + + neigh = pim_neighbor_add( + ifp, src_addr, hello_options, hello_option_holdtime, + hello_option_propagation_delay, + hello_option_override_interval, + hello_option_dr_priority, hello_option_generation_id, + hello_option_addr_list, PIM_NEIGHBOR_SEND_DELAY); + if (!neigh) { + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, + sizeof(src_str)); + zlog_warn( + "%s: failure creating PIM neighbor %s on interface %s", + __PRETTY_FUNCTION__, src_str, + ifp->name); + } + FREE_ADDR_LIST_THEN_RETURN(-8); + } + + /* actual addr list has been saved under neighbor */ + return 0; } - FREE_ADDR_LIST_THEN_RETURN(-9); - } - /* actual addr list is saved under neighbor */ - return 0; - - } /* GenId mismatch: replace neighbor */ - - } /* GenId received */ - - /* - Update existing neighbor - */ - - pim_neighbor_update(neigh, - hello_options, - hello_option_holdtime, - hello_option_dr_priority, - hello_option_addr_list); - /* actual addr list is saved under neighbor */ - return 0; + + /* + Received generation ID ? + */ + + if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_GENERATION_ID)) { + /* GenID mismatch ? */ + if (!PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_GENERATION_ID) + || (hello_option_generation_id != neigh->generation_id)) { + /* GenID mismatch, then replace neighbor */ + + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: GenId mismatch new=%08x old=%08x: replacing neighbor %s on %s", + __PRETTY_FUNCTION__, + hello_option_generation_id, + neigh->generation_id, src_str, + ifp->name); + } + + pim_upstream_rpf_genid_changed(neigh->source_addr); + + pim_neighbor_delete(ifp, neigh, "GenID mismatch"); + neigh = pim_neighbor_add(ifp, src_addr, hello_options, + hello_option_holdtime, + hello_option_propagation_delay, + hello_option_override_interval, + hello_option_dr_priority, + hello_option_generation_id, + hello_option_addr_list, + PIM_NEIGHBOR_SEND_NOW); + if (!neigh) { + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, + src_str, + sizeof(src_str)); + zlog_debug( + "%s: failure re-creating PIM neighbor %s on interface %s", + __PRETTY_FUNCTION__, src_str, + ifp->name); + } + FREE_ADDR_LIST_THEN_RETURN(-9); + } + /* actual addr list is saved under neighbor */ + return 0; + + } /* GenId mismatch: replace neighbor */ + + } /* GenId received */ + + /* + Update existing neighbor + */ + + pim_neighbor_update(neigh, hello_options, hello_option_holdtime, + hello_option_dr_priority, hello_option_addr_list); + /* actual addr list is saved under neighbor */ + return 0; } -int pim_hello_build_tlv(struct interface *ifp, - uint8_t *tlv_buf, int tlv_buf_size, - uint16_t holdtime, - uint32_t dr_priority, - uint32_t generation_id, - uint16_t propagation_delay, - uint16_t override_interval, +int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf, + int tlv_buf_size, uint16_t holdtime, + uint32_t dr_priority, uint32_t generation_id, + uint16_t propagation_delay, uint16_t override_interval, int can_disable_join_suppression) { - uint8_t *curr = tlv_buf; - uint8_t *pastend = tlv_buf + tlv_buf_size; - uint8_t *tmp; - - /* - * Append options - */ - - /* Holdtime */ - curr = pim_tlv_append_uint16(curr, - pastend, - PIM_MSG_OPTION_TYPE_HOLDTIME, - holdtime); - if (!curr) { - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not set PIM hello Holdtime option for interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return -1; - } + uint8_t *curr = tlv_buf; + uint8_t *pastend = tlv_buf + tlv_buf_size; + uint8_t *tmp; + + /* + * Append options + */ + + /* Holdtime */ + curr = pim_tlv_append_uint16(curr, pastend, + PIM_MSG_OPTION_TYPE_HOLDTIME, holdtime); + if (!curr) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug( + "%s: could not set PIM hello Holdtime option for interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -1; + } - /* LAN Prune Delay */ - tmp = pim_tlv_append_2uint16(curr, - pastend, - PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY, - propagation_delay, - override_interval); - if (!tmp) { - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not set PIM LAN Prune Delay option for interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return -1; - } - if (can_disable_join_suppression) { - *((uint8_t*)(curr) + 4) |= 0x80; /* enable T bit */ - } - curr = tmp; - - /* DR Priority */ - curr = pim_tlv_append_uint32(curr, - pastend, - PIM_MSG_OPTION_TYPE_DR_PRIORITY, - dr_priority); - if (!curr) { - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not set PIM hello DR Priority option for interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return -2; - } + /* LAN Prune Delay */ + tmp = pim_tlv_append_2uint16(curr, pastend, + PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY, + propagation_delay, override_interval); + if (!tmp) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug( + "%s: could not set PIM LAN Prune Delay option for interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -1; + } + if (can_disable_join_suppression) { + *((uint8_t *)(curr) + 4) |= 0x80; /* enable T bit */ + } + curr = tmp; + + /* DR Priority */ + curr = pim_tlv_append_uint32( + curr, pastend, PIM_MSG_OPTION_TYPE_DR_PRIORITY, dr_priority); + if (!curr) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug( + "%s: could not set PIM hello DR Priority option for interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -2; + } - /* Generation ID */ - curr = pim_tlv_append_uint32(curr, - pastend, - PIM_MSG_OPTION_TYPE_GENERATION_ID, - generation_id); - if (!curr) { - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not set PIM hello Generation ID option for interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return -3; - } + /* Generation ID */ + curr = pim_tlv_append_uint32(curr, pastend, + PIM_MSG_OPTION_TYPE_GENERATION_ID, + generation_id); + if (!curr) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug( + "%s: could not set PIM hello Generation ID option for interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -3; + } - /* Secondary Address List */ - if (ifp->connected->count) { - curr = pim_tlv_append_addrlist_ucast(curr, - pastend, - ifp->connected, - AF_INET); - if (!curr) { - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not set PIM hello v4 Secondary Address List option for interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return -4; - } - if (pimg->send_v6_secondary) - { - curr = pim_tlv_append_addrlist_ucast(curr, - pastend, - ifp->connected, - AF_INET6); - if (!curr) { - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not sent PIM hello v6 secondary Address List option for interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return -4; - } - } - } + /* Secondary Address List */ + if (ifp->connected->count) { + curr = pim_tlv_append_addrlist_ucast(curr, pastend, + ifp->connected, AF_INET); + if (!curr) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug( + "%s: could not set PIM hello v4 Secondary Address List option for interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -4; + } + if (pimg->send_v6_secondary) { + curr = pim_tlv_append_addrlist_ucast( + curr, pastend, ifp->connected, AF_INET6); + if (!curr) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug( + "%s: could not sent PIM hello v6 secondary Address List option for interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -4; + } + } + } - return curr - tlv_buf; + return curr - tlv_buf; } /* @@ -544,16 +544,16 @@ int pim_hello_build_tlv(struct interface *ifp, */ void pim_hello_require(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - zassert(ifp); + zassert(ifp); - pim_ifp = ifp->info; + pim_ifp = ifp->info; - zassert(pim_ifp); + zassert(pim_ifp); - if (pim_ifp->pim_ifstat_hello_sent) - return; + if (pim_ifp->pim_ifstat_hello_sent) + return; - pim_hello_restart_now(ifp); /* Send hello and restart timer */ + pim_hello_restart_now(ifp); /* Send hello and restart timer */ } diff --git a/pimd/pim_hello.h b/pimd/pim_hello.h index ff799b20f..df41f97d9 100644 --- a/pimd/pim_hello.h +++ b/pimd/pim_hello.h @@ -24,17 +24,13 @@ #include "if.h" -int pim_hello_recv(struct interface *ifp, - struct in_addr src_addr, +int pim_hello_recv(struct interface *ifp, struct in_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size); -int pim_hello_build_tlv(struct interface *ifp, - uint8_t *tlv_buf, int tlv_buf_size, - uint16_t holdtime, - uint32_t dr_priority, - uint32_t generation_id, - uint16_t propagation_delay, - uint16_t override_interval, +int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf, + int tlv_buf_size, uint16_t holdtime, + uint32_t dr_priority, uint32_t generation_id, + uint16_t propagation_delay, uint16_t override_interval, int can_disable_join_suppression); void pim_hello_require(struct interface *ifp); diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index f4125af9b..820162524 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -50,907 +50,919 @@ static int pim_iface_vif_index[MAXVIFS]; static void pim_if_igmp_join_del_all(struct interface *ifp); static int igmp_join_sock(const char *ifname, ifindex_t ifindex, - struct in_addr group_addr, struct in_addr source_addr); + struct in_addr group_addr, + struct in_addr source_addr); -void -pim_if_init (void) +void pim_if_init(void) { - int i; + int i; - for (i = 0; i < MAXVIFS; i++) - pim_iface_vif_index[i] = 0; + for (i = 0; i < MAXVIFS; i++) + pim_iface_vif_index[i] = 0; - pim_ifchannel_list = list_new(); - pim_ifchannel_list->cmp = (int (*)(void *, void *))pim_ifchannel_compare; + pim_ifchannel_list = list_new(); + pim_ifchannel_list->cmp = + (int (*)(void *, void *))pim_ifchannel_compare; } -void -pim_if_terminate (void) +void pim_if_terminate(void) { - if (pim_ifchannel_list) - list_free (pim_ifchannel_list); + if (pim_ifchannel_list) + list_free(pim_ifchannel_list); } static void *if_list_clean(struct pim_interface *pim_ifp) { - if (pim_ifp->igmp_join_list) { - list_delete(pim_ifp->igmp_join_list); - } + if (pim_ifp->igmp_join_list) { + list_delete(pim_ifp->igmp_join_list); + } - if (pim_ifp->igmp_socket_list) { - list_delete(pim_ifp->igmp_socket_list); - } + if (pim_ifp->igmp_socket_list) { + list_delete(pim_ifp->igmp_socket_list); + } - if (pim_ifp->pim_neighbor_list) { - list_delete(pim_ifp->pim_neighbor_list); - } + if (pim_ifp->pim_neighbor_list) { + list_delete(pim_ifp->pim_neighbor_list); + } - if (pim_ifp->upstream_switch_list) - list_delete(pim_ifp->upstream_switch_list); + if (pim_ifp->upstream_switch_list) + list_delete(pim_ifp->upstream_switch_list); - if (pim_ifp->pim_ifchannel_list) { - list_delete(pim_ifp->pim_ifchannel_list); - } + if (pim_ifp->pim_ifchannel_list) { + list_delete(pim_ifp->pim_ifchannel_list); + } - if (pim_ifp->pim_ifchannel_hash) - hash_free(pim_ifp->pim_ifchannel_hash); + if (pim_ifp->pim_ifchannel_hash) + hash_free(pim_ifp->pim_ifchannel_hash); - XFREE(MTYPE_PIM_INTERFACE, pim_ifp); + XFREE(MTYPE_PIM_INTERFACE, pim_ifp); - return 0; + return 0; } struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) { - struct pim_interface *pim_ifp; - - zassert(ifp); - zassert(!ifp->info); - - pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp)); - if (!pim_ifp) { - zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp)); - return 0; - } - - pim_ifp->options = 0; - pim_ifp->mroute_vif_index = -1; - - pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; - pim_ifp->igmp_default_robustness_variable = IGMP_DEFAULT_ROBUSTNESS_VARIABLE; - pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL; - pim_ifp->igmp_query_max_response_time_dsec = IGMP_QUERY_MAX_RESPONSE_TIME_DSEC; - pim_ifp->igmp_specific_query_max_response_time_dsec = IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC; - - /* - RFC 3376: 8.3. Query Response Interval - The number of seconds represented by the [Query Response Interval] - must be less than the [Query Interval]. - */ - zassert(pim_ifp->igmp_query_max_response_time_dsec < pim_ifp->igmp_default_query_interval); - - if (pim) - PIM_IF_DO_PIM(pim_ifp->options); - if (igmp) - PIM_IF_DO_IGMP(pim_ifp->options); - - PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options); - - pim_ifp->igmp_join_list = NULL; - pim_ifp->igmp_socket_list = NULL; - pim_ifp->pim_neighbor_list = NULL; - pim_ifp->upstream_switch_list = NULL; - pim_ifp->pim_ifchannel_list = NULL; - pim_ifp->pim_ifchannel_hash = NULL; - pim_ifp->pim_generation_id = 0; - - /* list of struct igmp_sock */ - pim_ifp->igmp_socket_list = list_new(); - if (!pim_ifp->igmp_socket_list) { - zlog_err("%s %s: failure: igmp_socket_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } - pim_ifp->igmp_socket_list->del = (void (*)(void *)) igmp_sock_free; - - /* list of struct pim_neighbor */ - pim_ifp->pim_neighbor_list = list_new(); - if (!pim_ifp->pim_neighbor_list) { - zlog_err("%s %s: failure: pim_neighbor_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } - pim_ifp->pim_neighbor_list->del = (void (*)(void *)) pim_neighbor_free; - - pim_ifp->upstream_switch_list = list_new(); - if (!pim_ifp->upstream_switch_list) { - zlog_err("%s %s: failure: upstream_switch_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } - - /* list of struct pim_ifchannel */ - pim_ifp->pim_ifchannel_list = list_new(); - if (!pim_ifp->pim_ifchannel_list) { - zlog_err("%s %s: failure: pim_ifchannel_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } - pim_ifp->pim_ifchannel_list->del = (void (*)(void *)) pim_ifchannel_free; - pim_ifp->pim_ifchannel_list->cmp = (int (*)(void *, void *)) pim_ifchannel_compare; - - pim_ifp->pim_ifchannel_hash = hash_create (pim_ifchannel_hash_key, - pim_ifchannel_equal, NULL); - - ifp->info = pim_ifp; - - pim_sock_reset(ifp); - - pim_if_add_vif(ifp); - - return pim_ifp; + struct pim_interface *pim_ifp; + + zassert(ifp); + zassert(!ifp->info); + + pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp)); + if (!pim_ifp) { + zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp)); + return 0; + } + + pim_ifp->options = 0; + pim_ifp->mroute_vif_index = -1; + + pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; + pim_ifp->igmp_default_robustness_variable = + IGMP_DEFAULT_ROBUSTNESS_VARIABLE; + pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL; + pim_ifp->igmp_query_max_response_time_dsec = + IGMP_QUERY_MAX_RESPONSE_TIME_DSEC; + pim_ifp->igmp_specific_query_max_response_time_dsec = + IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC; + + /* + RFC 3376: 8.3. Query Response Interval + The number of seconds represented by the [Query Response Interval] + must be less than the [Query Interval]. + */ + zassert(pim_ifp->igmp_query_max_response_time_dsec + < pim_ifp->igmp_default_query_interval); + + if (pim) + PIM_IF_DO_PIM(pim_ifp->options); + if (igmp) + PIM_IF_DO_IGMP(pim_ifp->options); + + PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options); + + pim_ifp->igmp_join_list = NULL; + pim_ifp->igmp_socket_list = NULL; + pim_ifp->pim_neighbor_list = NULL; + pim_ifp->upstream_switch_list = NULL; + pim_ifp->pim_ifchannel_list = NULL; + pim_ifp->pim_ifchannel_hash = NULL; + pim_ifp->pim_generation_id = 0; + + /* list of struct igmp_sock */ + pim_ifp->igmp_socket_list = list_new(); + if (!pim_ifp->igmp_socket_list) { + zlog_err("%s %s: failure: igmp_socket_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return if_list_clean(pim_ifp); + } + pim_ifp->igmp_socket_list->del = (void (*)(void *))igmp_sock_free; + + /* list of struct pim_neighbor */ + pim_ifp->pim_neighbor_list = list_new(); + if (!pim_ifp->pim_neighbor_list) { + zlog_err("%s %s: failure: pim_neighbor_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return if_list_clean(pim_ifp); + } + pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free; + + pim_ifp->upstream_switch_list = list_new(); + if (!pim_ifp->upstream_switch_list) { + zlog_err("%s %s: failure: upstream_switch_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return if_list_clean(pim_ifp); + } + + /* list of struct pim_ifchannel */ + pim_ifp->pim_ifchannel_list = list_new(); + if (!pim_ifp->pim_ifchannel_list) { + zlog_err("%s %s: failure: pim_ifchannel_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return if_list_clean(pim_ifp); + } + pim_ifp->pim_ifchannel_list->del = (void (*)(void *))pim_ifchannel_free; + pim_ifp->pim_ifchannel_list->cmp = + (int (*)(void *, void *))pim_ifchannel_compare; + + pim_ifp->pim_ifchannel_hash = + hash_create(pim_ifchannel_hash_key, pim_ifchannel_equal, NULL); + + ifp->info = pim_ifp; + + pim_sock_reset(ifp); + + pim_if_add_vif(ifp); + + return pim_ifp; } void pim_if_delete(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - zassert(ifp); - pim_ifp = ifp->info; - zassert(pim_ifp); + zassert(ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - if (pim_ifp->igmp_join_list) { - pim_if_igmp_join_del_all(ifp); - } + if (pim_ifp->igmp_join_list) { + pim_if_igmp_join_del_all(ifp); + } - pim_ifchannel_delete_all (ifp); - igmp_sock_delete_all (ifp); + pim_ifchannel_delete_all(ifp); + igmp_sock_delete_all(ifp); - pim_neighbor_delete_all (ifp, "Interface removed from configuration"); + pim_neighbor_delete_all(ifp, "Interface removed from configuration"); - pim_if_del_vif(ifp); + pim_if_del_vif(ifp); - list_delete(pim_ifp->igmp_socket_list); - list_delete(pim_ifp->pim_neighbor_list); - list_delete(pim_ifp->upstream_switch_list); - list_delete(pim_ifp->pim_ifchannel_list); + list_delete(pim_ifp->igmp_socket_list); + list_delete(pim_ifp->pim_neighbor_list); + list_delete(pim_ifp->upstream_switch_list); + list_delete(pim_ifp->pim_ifchannel_list); - hash_free (pim_ifp->pim_ifchannel_hash); + hash_free(pim_ifp->pim_ifchannel_hash); - XFREE(MTYPE_PIM_INTERFACE, pim_ifp); + XFREE(MTYPE_PIM_INTERFACE, pim_ifp); - ifp->info = NULL; + ifp->info = NULL; } void pim_if_update_could_assert(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - pim_ifchannel_update_could_assert(ch); - } + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + pim_ifchannel_update_could_assert(ch); + } } static void pim_if_update_my_assert_metric(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - pim_ifchannel_update_my_assert_metric(ch); - } + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + pim_ifchannel_update_my_assert_metric(ch); + } } static void pim_addr_change(struct interface *ifp) { - struct pim_interface *pim_ifp; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes -- Done TODO T30 */ - pim_if_update_join_desired(pim_ifp); /* depends on DR */ - pim_if_update_could_assert(ifp); /* depends on DR */ - pim_if_update_my_assert_metric(ifp); /* depends on could_assert */ - pim_if_update_assert_tracking_desired(ifp); /* depends on DR, join_desired */ - - /* - RFC 4601: 4.3.1. Sending Hello Messages - - 1) Before an interface goes down or changes primary IP address, a - Hello message with a zero HoldTime should be sent immediately - (with the old IP address if the IP address changed). - -- FIXME See CAVEAT C13 - - 2) After an interface has changed its IP address, it MUST send a - Hello message with its new IP address. - -- DONE below - - 3) If an interface changes one of its secondary IP addresses, a - Hello message with an updated Address_List option and a non-zero - HoldTime should be sent immediately. - -- FIXME See TODO T31 - */ - pim_ifp->pim_ifstat_hello_sent = 0; /* reset hello counter */ - if (pim_ifp->pim_sock_fd < 0) - return; - pim_hello_restart_now(ifp); /* send hello and restart timer */ + struct pim_interface *pim_ifp; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes -- + Done TODO T30 */ + pim_if_update_join_desired(pim_ifp); /* depends on DR */ + pim_if_update_could_assert(ifp); /* depends on DR */ + pim_if_update_my_assert_metric(ifp); /* depends on could_assert */ + pim_if_update_assert_tracking_desired( + ifp); /* depends on DR, join_desired */ + + /* + RFC 4601: 4.3.1. Sending Hello Messages + + 1) Before an interface goes down or changes primary IP address, a + Hello message with a zero HoldTime should be sent immediately + (with the old IP address if the IP address changed). + -- FIXME See CAVEAT C13 + + 2) After an interface has changed its IP address, it MUST send a + Hello message with its new IP address. + -- DONE below + + 3) If an interface changes one of its secondary IP addresses, a + Hello message with an updated Address_List option and a non-zero + HoldTime should be sent immediately. + -- FIXME See TODO T31 + */ + pim_ifp->pim_ifstat_hello_sent = 0; /* reset hello counter */ + if (pim_ifp->pim_sock_fd < 0) + return; + pim_hello_restart_now(ifp); /* send hello and restart timer */ } static int detect_primary_address_change(struct interface *ifp, int force_prim_as_any, const char *caller) { - struct pim_interface *pim_ifp = ifp->info; - struct in_addr new_prim_addr; - int changed; - - if (force_prim_as_any) - new_prim_addr.s_addr = INADDR_ANY; - else - new_prim_addr = pim_find_primary_addr(ifp); - - changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr; - - if (PIM_DEBUG_ZEBRA) { - char new_prim_str[INET_ADDRSTRLEN]; - char old_prim_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<new?>", new_prim_addr, new_prim_str, sizeof(new_prim_str)); - pim_inet4_dump("<old?>", pim_ifp->primary_address, old_prim_str, sizeof(old_prim_str)); - zlog_debug("%s: old=%s new=%s on interface %s: %s", - __PRETTY_FUNCTION__, - old_prim_str, new_prim_str, ifp->name, - changed ? "changed" : "unchanged"); - } - - if (changed) { - pim_ifp->primary_address = new_prim_addr; - } - - return changed; + struct pim_interface *pim_ifp = ifp->info; + struct in_addr new_prim_addr; + int changed; + + if (force_prim_as_any) + new_prim_addr.s_addr = INADDR_ANY; + else + new_prim_addr = pim_find_primary_addr(ifp); + + changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr; + + if (PIM_DEBUG_ZEBRA) { + char new_prim_str[INET_ADDRSTRLEN]; + char old_prim_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<new?>", new_prim_addr, new_prim_str, + sizeof(new_prim_str)); + pim_inet4_dump("<old?>", pim_ifp->primary_address, old_prim_str, + sizeof(old_prim_str)); + zlog_debug("%s: old=%s new=%s on interface %s: %s", + __PRETTY_FUNCTION__, old_prim_str, new_prim_str, + ifp->name, changed ? "changed" : "unchanged"); + } + + if (changed) { + pim_ifp->primary_address = new_prim_addr; + } + + return changed; } static int pim_sec_addr_comp(const void *p1, const void *p2) { - const struct pim_secondary_addr *sec1 = p1; - const struct pim_secondary_addr *sec2 = p2; - - if (sec1->addr.family == AF_INET && - sec2->addr.family == AF_INET6) - return -1; - - if (sec1->addr.family == AF_INET6 && - sec2->addr.family == AF_INET) - return 1; - - if (sec1->addr.family == AF_INET) - { - if (ntohl(sec1->addr.u.prefix4.s_addr) < ntohl(sec2->addr.u.prefix4.s_addr)) - return -1; - - if (ntohl(sec1->addr.u.prefix4.s_addr) > ntohl(sec2->addr.u.prefix4.s_addr)) - return 1; - } - else - { - return memcmp (&sec1->addr.u.prefix6, - &sec2->addr.u.prefix6, - sizeof (struct in6_addr)); - } - - return 0; + const struct pim_secondary_addr *sec1 = p1; + const struct pim_secondary_addr *sec2 = p2; + + if (sec1->addr.family == AF_INET && sec2->addr.family == AF_INET6) + return -1; + + if (sec1->addr.family == AF_INET6 && sec2->addr.family == AF_INET) + return 1; + + if (sec1->addr.family == AF_INET) { + if (ntohl(sec1->addr.u.prefix4.s_addr) + < ntohl(sec2->addr.u.prefix4.s_addr)) + return -1; + + if (ntohl(sec1->addr.u.prefix4.s_addr) + > ntohl(sec2->addr.u.prefix4.s_addr)) + return 1; + } else { + return memcmp(&sec1->addr.u.prefix6, &sec2->addr.u.prefix6, + sizeof(struct in6_addr)); + } + + return 0; } static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr) { - XFREE(MTYPE_PIM_SEC_ADDR, sec_addr); + XFREE(MTYPE_PIM_SEC_ADDR, sec_addr); } static struct pim_secondary_addr * pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr) { - struct pim_secondary_addr *sec_addr; - struct listnode *node; + struct pim_secondary_addr *sec_addr; + struct listnode *node; - if (!pim_ifp->sec_addr_list) { - return NULL; - } + if (!pim_ifp->sec_addr_list) { + return NULL; + } - for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { - if (prefix_cmp(&sec_addr->addr, addr)) { - return sec_addr; - } - } + for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { + if (prefix_cmp(&sec_addr->addr, addr)) { + return sec_addr; + } + } - return NULL; + return NULL; } static void pim_sec_addr_del(struct pim_interface *pim_ifp, - struct pim_secondary_addr *sec_addr) + struct pim_secondary_addr *sec_addr) { - listnode_delete(pim_ifp->sec_addr_list, sec_addr); - pim_sec_addr_free(sec_addr); + listnode_delete(pim_ifp->sec_addr_list, sec_addr); + pim_sec_addr_free(sec_addr); } static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr) { - int changed = 0; - struct pim_secondary_addr *sec_addr; - - sec_addr = pim_sec_addr_find(pim_ifp, addr); - if (sec_addr) { - sec_addr->flags &= ~PIM_SEC_ADDRF_STALE; - return changed; - } - - if (!pim_ifp->sec_addr_list) { - pim_ifp->sec_addr_list = list_new(); - pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free; - pim_ifp->sec_addr_list->cmp = (int (*)(void *, void *))pim_sec_addr_comp; - } - - sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr)); - if (!sec_addr) { - if (list_isempty(pim_ifp->sec_addr_list)) { - list_free(pim_ifp->sec_addr_list); - pim_ifp->sec_addr_list = NULL; - } - return changed; - } - - changed = 1; - sec_addr->addr = *addr; - listnode_add_sort(pim_ifp->sec_addr_list, sec_addr); - - return changed; + int changed = 0; + struct pim_secondary_addr *sec_addr; + + sec_addr = pim_sec_addr_find(pim_ifp, addr); + if (sec_addr) { + sec_addr->flags &= ~PIM_SEC_ADDRF_STALE; + return changed; + } + + if (!pim_ifp->sec_addr_list) { + pim_ifp->sec_addr_list = list_new(); + pim_ifp->sec_addr_list->del = + (void (*)(void *))pim_sec_addr_free; + pim_ifp->sec_addr_list->cmp = + (int (*)(void *, void *))pim_sec_addr_comp; + } + + sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr)); + if (!sec_addr) { + if (list_isempty(pim_ifp->sec_addr_list)) { + list_free(pim_ifp->sec_addr_list); + pim_ifp->sec_addr_list = NULL; + } + return changed; + } + + changed = 1; + sec_addr->addr = *addr; + listnode_add_sort(pim_ifp->sec_addr_list, sec_addr); + + return changed; } static int pim_sec_addr_del_all(struct pim_interface *pim_ifp) { - int changed = 0; - - if (!pim_ifp->sec_addr_list) { - return changed; - } - if (!list_isempty(pim_ifp->sec_addr_list)) { - changed = 1; - /* remove all nodes and free up the list itself */ - list_delete_all_node(pim_ifp->sec_addr_list); - list_free(pim_ifp->sec_addr_list); - pim_ifp->sec_addr_list = NULL; - } - - return changed; + int changed = 0; + + if (!pim_ifp->sec_addr_list) { + return changed; + } + if (!list_isempty(pim_ifp->sec_addr_list)) { + changed = 1; + /* remove all nodes and free up the list itself */ + list_delete_all_node(pim_ifp->sec_addr_list); + list_free(pim_ifp->sec_addr_list); + pim_ifp->sec_addr_list = NULL; + } + + return changed; } static int pim_sec_addr_update(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; - struct pim_secondary_addr *sec_addr; - int changed = 0; - - if (pim_ifp->sec_addr_list) { - for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { - sec_addr->flags |= PIM_SEC_ADDRF_STALE; - } - } - - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { - struct prefix *p = ifc->address; - - if (PIM_INADDR_IS_ANY(p->u.prefix4)) { - continue; - } - - if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) { - /* don't add the primary address into the secondary address list */ - continue; - } - - if (pim_sec_addr_add(pim_ifp, p)) { - changed = 1; - } - } - - if (pim_ifp->sec_addr_list) { - /* Drop stale entries */ - for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode, sec_addr)) { - if (sec_addr->flags & PIM_SEC_ADDRF_STALE) { - pim_sec_addr_del(pim_ifp, sec_addr); - changed = 1; - } - } - - /* If the list went empty free it up */ - if (list_isempty(pim_ifp->sec_addr_list)) { - list_free(pim_ifp->sec_addr_list); - pim_ifp->sec_addr_list = NULL; - } - } - - return changed; + struct pim_interface *pim_ifp = ifp->info; + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + struct pim_secondary_addr *sec_addr; + int changed = 0; + + if (pim_ifp->sec_addr_list) { + for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, + sec_addr)) { + sec_addr->flags |= PIM_SEC_ADDRF_STALE; + } + } + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + struct prefix *p = ifc->address; + + if (PIM_INADDR_IS_ANY(p->u.prefix4)) { + continue; + } + + if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) { + /* don't add the primary address into the secondary + * address list */ + continue; + } + + if (pim_sec_addr_add(pim_ifp, p)) { + changed = 1; + } + } + + if (pim_ifp->sec_addr_list) { + /* Drop stale entries */ + for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode, + sec_addr)) { + if (sec_addr->flags & PIM_SEC_ADDRF_STALE) { + pim_sec_addr_del(pim_ifp, sec_addr); + changed = 1; + } + } + + /* If the list went empty free it up */ + if (list_isempty(pim_ifp->sec_addr_list)) { + list_free(pim_ifp->sec_addr_list); + pim_ifp->sec_addr_list = NULL; + } + } + + return changed; } static int detect_secondary_address_change(struct interface *ifp, - int force_prim_as_any, - const char *caller) + int force_prim_as_any, + const char *caller) { - struct pim_interface *pim_ifp = ifp->info; - int changed = 0; - - if (force_prim_as_any) { - /* if primary address is being forced to zero just flush the - * secondary address list */ - changed = pim_sec_addr_del_all(pim_ifp); - } else { - /* re-evaluate the secondary address list */ - changed = pim_sec_addr_update(ifp); - } - - return changed; + struct pim_interface *pim_ifp = ifp->info; + int changed = 0; + + if (force_prim_as_any) { + /* if primary address is being forced to zero just flush the + * secondary address list */ + changed = pim_sec_addr_del_all(pim_ifp); + } else { + /* re-evaluate the secondary address list */ + changed = pim_sec_addr_update(ifp); + } + + return changed; } -static void detect_address_change(struct interface *ifp, - int force_prim_as_any, - const char *caller) +static void detect_address_change(struct interface *ifp, int force_prim_as_any, + const char *caller) { - int changed = 0; - struct pim_interface *pim_ifp; + int changed = 0; + struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - if (!pim_ifp) - return; + pim_ifp = ifp->info; + if (!pim_ifp) + return; - if (detect_primary_address_change(ifp, force_prim_as_any, caller)) { - changed = 1; - } + if (detect_primary_address_change(ifp, force_prim_as_any, caller)) { + changed = 1; + } - if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) { - changed = 1; - } + if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) { + changed = 1; + } - if (changed) { - if (!PIM_IF_TEST_PIM(pim_ifp->options)) { - return; - } + if (changed) { + if (!PIM_IF_TEST_PIM(pim_ifp->options)) { + return; + } - pim_addr_change(ifp); - } + pim_addr_change(ifp); + } - /* XXX: if we have unnumbered interfaces we need to run detect address - * address change on all of them when the lo address changes */ + /* XXX: if we have unnumbered interfaces we need to run detect address + * address change on all of them when the lo address changes */ } int pim_update_source_set(struct interface *ifp, struct in_addr source) { - struct pim_interface *pim_ifp = ifp->info; + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) { - return PIM_IFACE_NOT_FOUND; - } + if (!pim_ifp) { + return PIM_IFACE_NOT_FOUND; + } - if (pim_ifp->update_source.s_addr == source.s_addr) { - return PIM_UPDATE_SOURCE_DUP; - } + if (pim_ifp->update_source.s_addr == source.s_addr) { + return PIM_UPDATE_SOURCE_DUP; + } - pim_ifp->update_source = source; - detect_address_change(ifp, 0 /* force_prim_as_any */, - __PRETTY_FUNCTION__); + pim_ifp->update_source = source; + detect_address_change(ifp, 0 /* force_prim_as_any */, + __PRETTY_FUNCTION__); - return PIM_SUCCESS; + return PIM_SUCCESS; } void pim_if_addr_add(struct connected *ifc) { - struct pim_interface *pim_ifp; - struct interface *ifp; - struct in_addr ifaddr; - - zassert(ifc); - - ifp = ifc->ifp; - zassert(ifp); - pim_ifp = ifp->info; - if (!pim_ifp) - return; - - if (!if_is_operative(ifp)) - return; - - if (PIM_DEBUG_ZEBRA) { - char buf[BUFSIZ]; - prefix2str(ifc->address, buf, BUFSIZ); - zlog_debug("%s: %s ifindex=%d connected IP address %s %s", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, buf, - CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? - "secondary" : "primary"); - } - - ifaddr = ifc->address->u.prefix4; - - detect_address_change(ifp, 0, __PRETTY_FUNCTION__); - - if (ifc->address->family != AF_INET) - return; - - if (PIM_IF_TEST_IGMP(pim_ifp->options)) { - struct igmp_sock *igmp; - - /* lookup IGMP socket */ - igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, - ifaddr); - if (!igmp) { - /* if addr new, add IGMP socket */ - pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, ifp); - } - - /* Replay Static IGMP groups */ - if (pim_ifp->igmp_join_list) - { - struct listnode *node; - struct listnode *nextnode; - struct igmp_join *ij; - int join_fd; - - for (ALL_LIST_ELEMENTS (pim_ifp->igmp_join_list, node, nextnode, ij)) - { - /* Close socket and reopen with Source and Group */ - close(ij->sock_fd); - join_fd = igmp_join_sock(ifp->name, ifp->ifindex, ij->group_addr, ij->source_addr); - if (join_fd < 0) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", ij->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", ij->source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - /* warning only */ - } - else - ij->sock_fd = join_fd; - } - } - } /* igmp */ - - if (PIM_IF_TEST_PIM(pim_ifp->options)) - { - - if (PIM_INADDR_ISNOT_ANY (pim_ifp->primary_address)) - { - - /* Interface has a valid socket ? */ - if (pim_ifp->pim_sock_fd < 0) - { - if (pim_sock_add (ifp)) - { - zlog_warn ("Failure creating PIM socket for interface %s", - ifp->name); - } - } - struct pim_nexthop_cache *pnc = NULL; - struct pim_rpf rpf; - struct zclient *zclient = NULL; - - zclient = pim_zebra_zclient_get (); - /* RP config might come prior to (local RP's interface) IF UP event. - In this case, pnc would not have pim enabled nexthops. - Once Interface is UP and pim info is available, reregister - with RNH address to receive update and add the interface as nexthop. */ - memset (&rpf, 0, sizeof (struct pim_rpf)); - rpf.rpf_addr.family = AF_INET; - rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN; - rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4; - pnc = pim_nexthop_cache_find (&rpf); - if (pnc) - pim_sendmsg_zebra_rnh (zclient, pnc, - ZEBRA_NEXTHOP_REGISTER); - } - } /* pim */ - - /* - PIM or IGMP is enabled on interface, and there is at least one - address assigned, then try to create a vif_index. - */ - if (pim_ifp->mroute_vif_index < 0) { - pim_if_add_vif(ifp); - } - pim_ifchannel_scan_forward_start (ifp); + struct pim_interface *pim_ifp; + struct interface *ifp; + struct in_addr ifaddr; + + zassert(ifc); + + ifp = ifc->ifp; + zassert(ifp); + pim_ifp = ifp->info; + if (!pim_ifp) + return; + + if (!if_is_operative(ifp)) + return; + + if (PIM_DEBUG_ZEBRA) { + char buf[BUFSIZ]; + prefix2str(ifc->address, buf, BUFSIZ); + zlog_debug("%s: %s ifindex=%d connected IP address %s %s", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf, + CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) + ? "secondary" + : "primary"); + } + + ifaddr = ifc->address->u.prefix4; + + detect_address_change(ifp, 0, __PRETTY_FUNCTION__); + + if (ifc->address->family != AF_INET) + return; + + if (PIM_IF_TEST_IGMP(pim_ifp->options)) { + struct igmp_sock *igmp; + + /* lookup IGMP socket */ + igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, + ifaddr); + if (!igmp) { + /* if addr new, add IGMP socket */ + pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, + ifp); + } + + /* Replay Static IGMP groups */ + if (pim_ifp->igmp_join_list) { + struct listnode *node; + struct listnode *nextnode; + struct igmp_join *ij; + int join_fd; + + for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, + nextnode, ij)) { + /* Close socket and reopen with Source and Group + */ + close(ij->sock_fd); + join_fd = igmp_join_sock( + ifp->name, ifp->ifindex, ij->group_addr, + ij->source_addr); + if (join_fd < 0) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", ij->group_addr, + group_str, + sizeof(group_str)); + pim_inet4_dump( + "<src?>", ij->source_addr, + source_str, sizeof(source_str)); + zlog_warn( + "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, + source_str, ifp->name); + /* warning only */ + } else + ij->sock_fd = join_fd; + } + } + } /* igmp */ + + if (PIM_IF_TEST_PIM(pim_ifp->options)) { + + if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + + /* Interface has a valid socket ? */ + if (pim_ifp->pim_sock_fd < 0) { + if (pim_sock_add(ifp)) { + zlog_warn( + "Failure creating PIM socket for interface %s", + ifp->name); + } + } + struct pim_nexthop_cache *pnc = NULL; + struct pim_rpf rpf; + struct zclient *zclient = NULL; + + zclient = pim_zebra_zclient_get(); + /* RP config might come prior to (local RP's interface) + IF UP event. + In this case, pnc would not have pim enabled + nexthops. + Once Interface is UP and pim info is available, + reregister + with RNH address to receive update and add the + interface as nexthop. */ + memset(&rpf, 0, sizeof(struct pim_rpf)); + rpf.rpf_addr.family = AF_INET; + rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN; + rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4; + pnc = pim_nexthop_cache_find(&rpf); + if (pnc) + pim_sendmsg_zebra_rnh(zclient, pnc, + ZEBRA_NEXTHOP_REGISTER); + } + } /* pim */ + + /* + PIM or IGMP is enabled on interface, and there is at least one + address assigned, then try to create a vif_index. + */ + if (pim_ifp->mroute_vif_index < 0) { + pim_if_add_vif(ifp); + } + pim_ifchannel_scan_forward_start(ifp); } static void pim_if_addr_del_igmp(struct connected *ifc) { - struct pim_interface *pim_ifp = ifc->ifp->info; - struct igmp_sock *igmp; - struct in_addr ifaddr; - - if (ifc->address->family != AF_INET) { - /* non-IPv4 address */ - return; - } - - if (!pim_ifp) { - /* IGMP not enabled on interface */ - return; - } - - ifaddr = ifc->address->u.prefix4; - - /* lookup IGMP socket */ - igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, - ifaddr); - if (igmp) { - /* if addr found, del IGMP socket */ - igmp_sock_delete(igmp); - } + struct pim_interface *pim_ifp = ifc->ifp->info; + struct igmp_sock *igmp; + struct in_addr ifaddr; + + if (ifc->address->family != AF_INET) { + /* non-IPv4 address */ + return; + } + + if (!pim_ifp) { + /* IGMP not enabled on interface */ + return; + } + + ifaddr = ifc->address->u.prefix4; + + /* lookup IGMP socket */ + igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr); + if (igmp) { + /* if addr found, del IGMP socket */ + igmp_sock_delete(igmp); + } } static void pim_if_addr_del_pim(struct connected *ifc) { - struct pim_interface *pim_ifp = ifc->ifp->info; - - if (ifc->address->family != AF_INET) { - /* non-IPv4 address */ - return; - } - - if (!pim_ifp) { - /* PIM not enabled on interface */ - return; - } - - if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { - /* Interface keeps a valid primary address */ - return; - } - - if (pim_ifp->pim_sock_fd < 0) { - /* Interface does not hold a valid socket any longer */ - return; - } - - /* - pim_sock_delete() closes the socket, stops read and timer threads, - and kills all neighbors. - */ - pim_sock_delete(ifc->ifp, "last address has been removed from interface"); -} + struct pim_interface *pim_ifp = ifc->ifp->info; -void pim_if_addr_del(struct connected *ifc, int force_prim_as_any) -{ - struct interface *ifp; + if (ifc->address->family != AF_INET) { + /* non-IPv4 address */ + return; + } - zassert(ifc); - ifp = ifc->ifp; - zassert(ifp); + if (!pim_ifp) { + /* PIM not enabled on interface */ + return; + } + + if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + /* Interface keeps a valid primary address */ + return; + } - if (ifc->address->family != AF_INET) - return; + if (pim_ifp->pim_sock_fd < 0) { + /* Interface does not hold a valid socket any longer */ + return; + } - if (PIM_DEBUG_ZEBRA) { - char buf[BUFSIZ]; - prefix2str(ifc->address, buf, BUFSIZ); - zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, buf, - CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? - "secondary" : "primary"); - } + /* + pim_sock_delete() closes the socket, stops read and timer threads, + and kills all neighbors. + */ + pim_sock_delete(ifc->ifp, + "last address has been removed from interface"); +} - detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__); +void pim_if_addr_del(struct connected *ifc, int force_prim_as_any) +{ + struct interface *ifp; + + zassert(ifc); + ifp = ifc->ifp; + zassert(ifp); + + if (ifc->address->family != AF_INET) + return; + + if (PIM_DEBUG_ZEBRA) { + char buf[BUFSIZ]; + prefix2str(ifc->address, buf, BUFSIZ); + zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf, + CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) + ? "secondary" + : "primary"); + } - pim_if_addr_del_igmp(ifc); - pim_if_addr_del_pim(ifc); + detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__); + + pim_if_addr_del_igmp(ifc); + pim_if_addr_del_pim(ifc); } void pim_if_addr_add_all(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; - int v4_addrs = 0; - int v6_addrs = 0; - struct pim_interface *pim_ifp = ifp->info; - - - /* PIM/IGMP enabled ? */ - if (!pim_ifp) - return; - - for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - v6_addrs++; - else - v4_addrs++; - pim_if_addr_add(ifc); - } - - if (!v4_addrs && v6_addrs && !if_is_loopback (ifp)) - { - if (PIM_IF_TEST_PIM(pim_ifp->options)) { - - /* Interface has a valid primary address ? */ - if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + int v4_addrs = 0; + int v6_addrs = 0; + struct pim_interface *pim_ifp = ifp->info; + + + /* PIM/IGMP enabled ? */ + if (!pim_ifp) + return; + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) + v6_addrs++; + else + v4_addrs++; + pim_if_addr_add(ifc); + } - /* Interface has a valid socket ? */ - if (pim_ifp->pim_sock_fd < 0) { - if (pim_sock_add(ifp)) { - zlog_warn("Failure creating PIM socket for interface %s", - ifp->name); - } - } - - } - } /* pim */ - } - /* - * PIM or IGMP is enabled on interface, and there is at least one - * address assigned, then try to create a vif_index. - */ - if (pim_ifp->mroute_vif_index < 0) { - pim_if_add_vif(ifp); - } - pim_ifchannel_scan_forward_start (ifp); - - pim_rp_setup(); - pim_rp_check_on_if_add(pim_ifp); + if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) { + if (PIM_IF_TEST_PIM(pim_ifp->options)) { + + /* Interface has a valid primary address ? */ + if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + + /* Interface has a valid socket ? */ + if (pim_ifp->pim_sock_fd < 0) { + if (pim_sock_add(ifp)) { + zlog_warn( + "Failure creating PIM socket for interface %s", + ifp->name); + } + } + } + } /* pim */ + } + /* + * PIM or IGMP is enabled on interface, and there is at least one + * address assigned, then try to create a vif_index. + */ + if (pim_ifp->mroute_vif_index < 0) { + pim_if_add_vif(ifp); + } + pim_ifchannel_scan_forward_start(ifp); + + pim_rp_setup(); + pim_rp_check_on_if_add(pim_ifp); } void pim_if_addr_del_all(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + + /* PIM/IGMP enabled ? */ + if (!ifp->info) + return; - /* PIM/IGMP enabled ? */ - if (!ifp->info) - return; + for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { + struct prefix *p = ifc->address; - for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - continue; + if (p->family != AF_INET) + continue; - pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */); - } + pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */); + } - pim_rp_setup(); - pim_i_am_rp_re_evaluate(); + pim_rp_setup(); + pim_i_am_rp_re_evaluate(); } void pim_if_addr_del_all_igmp(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; - - /* PIM/IGMP enabled ? */ - if (!ifp->info) - return; - - for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - continue; - - pim_if_addr_del_igmp(ifc); - } + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + + /* PIM/IGMP enabled ? */ + if (!ifp->info) + return; + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) + continue; + + pim_if_addr_del_igmp(ifc); + } } void pim_if_addr_del_all_pim(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; - - /* PIM/IGMP enabled ? */ - if (!ifp->info) - return; - - for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - continue; - - pim_if_addr_del_pim(ifc); - } + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + + /* PIM/IGMP enabled ? */ + if (!ifp->info) + return; + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) + continue; + + pim_if_addr_del_pim(ifc); + } } -struct in_addr -pim_find_primary_addr (struct interface *ifp) +struct in_addr pim_find_primary_addr(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct in_addr addr; - int v4_addrs = 0; - int v6_addrs = 0; - struct pim_interface *pim_ifp = ifp->info; - - if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { - return pim_ifp->update_source; - } - - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - { - v6_addrs++; - continue; - } - - if (PIM_INADDR_IS_ANY(p->u.prefix4)) { - zlog_warn("%s: null IPv4 address connected to interface %s", - __PRETTY_FUNCTION__, ifp->name); - continue; - } - - v4_addrs++; - - if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) - continue; - - return p->u.prefix4; - } - - /* - * If we have no v4_addrs and v6 is configured - * We probably are using unnumbered - * So let's grab the loopbacks v4 address - * and use that as the primary address - */ - if (!v4_addrs && v6_addrs && !if_is_loopback (ifp)) - { - struct interface *lo_ifp; - lo_ifp = if_lookup_by_name ("lo", VRF_DEFAULT); - if (lo_ifp) - return pim_find_primary_addr (lo_ifp); - } - - addr.s_addr = PIM_NET_INADDR_ANY; - - return addr; + struct connected *ifc; + struct listnode *node; + struct in_addr addr; + int v4_addrs = 0; + int v6_addrs = 0; + struct pim_interface *pim_ifp = ifp->info; + + if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { + return pim_ifp->update_source; + } + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) { + v6_addrs++; + continue; + } + + if (PIM_INADDR_IS_ANY(p->u.prefix4)) { + zlog_warn( + "%s: null IPv4 address connected to interface %s", + __PRETTY_FUNCTION__, ifp->name); + continue; + } + + v4_addrs++; + + if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) + continue; + + return p->u.prefix4; + } + + /* + * If we have no v4_addrs and v6 is configured + * We probably are using unnumbered + * So let's grab the loopbacks v4 address + * and use that as the primary address + */ + if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) { + struct interface *lo_ifp; + lo_ifp = if_lookup_by_name("lo", VRF_DEFAULT); + if (lo_ifp) + return pim_find_primary_addr(lo_ifp); + } + + addr.s_addr = PIM_NET_INADDR_ANY; + + return addr; } -static int -pim_iface_next_vif_index (struct interface *ifp) +static int pim_iface_next_vif_index(struct interface *ifp) { - int i; - /* - * The pimreg vif is always going to be in index 0 - * of the table. - */ - if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) - return 0; - - for (i = 1 ; i < MAXVIFS; i++) - { - if (pim_iface_vif_index[i] == 0) - return i; - } - return MAXVIFS; + int i; + /* + * The pimreg vif is always going to be in index 0 + * of the table. + */ + if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) + return 0; + + for (i = 1; i < MAXVIFS; i++) { + if (pim_iface_vif_index[i] == 0) + return i; + } + return MAXVIFS; } /* @@ -960,130 +972,131 @@ pim_iface_next_vif_index (struct interface *ifp) */ int pim_if_add_vif(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - struct in_addr ifaddr; - unsigned char flags = 0; - - zassert(pim_ifp); - - if (pim_ifp->mroute_vif_index > 0) { - zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d", - __PRETTY_FUNCTION__, - pim_ifp->mroute_vif_index, ifp->name, ifp->ifindex); - return -1; - } - - if (ifp->ifindex < 0) { - zlog_warn("%s: ifindex=%d < 1 on interface %s", - __PRETTY_FUNCTION__, - ifp->ifindex, ifp->name); - return -2; - } - - ifaddr = pim_ifp->primary_address; - if (ifp->ifindex != PIM_OIF_PIM_REGISTER_VIF && PIM_INADDR_IS_ANY(ifaddr)) { - zlog_warn("%s: could not get address for interface %s ifindex=%d", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex); - return -4; - } - - pim_ifp->mroute_vif_index = pim_iface_next_vif_index (ifp); - - if (pim_ifp->mroute_vif_index >= MAXVIFS) - { - zlog_warn("%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s", - __PRETTY_FUNCTION__, - MAXVIFS, ifp->name); - return -3; - } - - if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) - flags = VIFF_REGISTER; + struct pim_interface *pim_ifp = ifp->info; + struct in_addr ifaddr; + unsigned char flags = 0; + + zassert(pim_ifp); + + if (pim_ifp->mroute_vif_index > 0) { + zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d", + __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index, + ifp->name, ifp->ifindex); + return -1; + } + + if (ifp->ifindex < 0) { + zlog_warn("%s: ifindex=%d < 1 on interface %s", + __PRETTY_FUNCTION__, ifp->ifindex, ifp->name); + return -2; + } + + ifaddr = pim_ifp->primary_address; + if (ifp->ifindex != PIM_OIF_PIM_REGISTER_VIF + && PIM_INADDR_IS_ANY(ifaddr)) { + zlog_warn( + "%s: could not get address for interface %s ifindex=%d", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex); + return -4; + } + + pim_ifp->mroute_vif_index = pim_iface_next_vif_index(ifp); + + if (pim_ifp->mroute_vif_index >= MAXVIFS) { + zlog_warn( + "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s", + __PRETTY_FUNCTION__, MAXVIFS, ifp->name); + return -3; + } + + if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) + flags = VIFF_REGISTER; #ifdef VIFF_USE_IFINDEX - else - flags = VIFF_USE_IFINDEX; + else + flags = VIFF_USE_IFINDEX; #endif - if (pim_mroute_add_vif(ifp, ifaddr, flags)) { - /* pim_mroute_add_vif reported error */ - return -5; - } + if (pim_mroute_add_vif(ifp, ifaddr, flags)) { + /* pim_mroute_add_vif reported error */ + return -5; + } - pim_iface_vif_index[pim_ifp->mroute_vif_index] = 1; - return 0; + pim_iface_vif_index[pim_ifp->mroute_vif_index] = 1; + return 0; } int pim_if_del_vif(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; + struct pim_interface *pim_ifp = ifp->info; - if (pim_ifp->mroute_vif_index < 1) { - zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d", - __PRETTY_FUNCTION__, - pim_ifp->mroute_vif_index, ifp->name, ifp->ifindex); - return -1; - } + if (pim_ifp->mroute_vif_index < 1) { + zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d", + __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index, + ifp->name, ifp->ifindex); + return -1; + } - pim_mroute_del_vif(pim_ifp->mroute_vif_index); + pim_mroute_del_vif(pim_ifp->mroute_vif_index); - /* - Update vif_index - */ - pim_iface_vif_index[pim_ifp->mroute_vif_index] = 0; + /* + Update vif_index + */ + pim_iface_vif_index[pim_ifp->mroute_vif_index] = 0; - pim_ifp->mroute_vif_index = -1; + pim_ifp->mroute_vif_index = -1; - return 0; + return 0; } void pim_if_add_vif_all() { - struct listnode *ifnode; - struct listnode *ifnextnode; - struct interface *ifp; + struct listnode *ifnode; + struct listnode *ifnextnode; + struct interface *ifp; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - if (!ifp->info) - continue; + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, + ifp)) { + if (!ifp->info) + continue; - pim_if_add_vif(ifp); - } + pim_if_add_vif(ifp); + } } void pim_if_del_vif_all() { - struct listnode *ifnode; - struct listnode *ifnextnode; - struct interface *ifp; + struct listnode *ifnode; + struct listnode *ifnextnode; + struct interface *ifp; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - if (!ifp->info) - continue; + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, + ifp)) { + if (!ifp->info) + continue; - pim_if_del_vif(ifp); - } + pim_if_del_vif(ifp); + } } struct interface *pim_if_find_by_vif_index(ifindex_t vif_index) { - struct listnode *ifnode; - struct interface *ifp; + struct listnode *ifnode; + struct interface *ifp; - if (vif_index == 0) - return if_lookup_by_name ("pimreg", VRF_DEFAULT); + if (vif_index == 0) + return if_lookup_by_name("pimreg", VRF_DEFAULT); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - if (ifp->info) { - struct pim_interface *pim_ifp; - pim_ifp = ifp->info; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + if (ifp->info) { + struct pim_interface *pim_ifp; + pim_ifp = ifp->info; - if (vif_index == pim_ifp->mroute_vif_index) - return ifp; - } - } + if (vif_index == pim_ifp->mroute_vif_index) + return ifp; + } + } - return 0; + return 0; } /* @@ -1091,69 +1104,67 @@ struct interface *pim_if_find_by_vif_index(ifindex_t vif_index) */ int pim_if_find_vifindex_by_ifindex(ifindex_t ifindex) { - struct pim_interface *pim_ifp; - struct interface *ifp; + struct pim_interface *pim_ifp; + struct interface *ifp; - ifp = if_lookup_by_index (ifindex, VRF_DEFAULT); - if (!ifp || !ifp->info) - return -1; - pim_ifp = ifp->info; + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + if (!ifp || !ifp->info) + return -1; + pim_ifp = ifp->info; - return pim_ifp->mroute_vif_index; + return pim_ifp->mroute_vif_index; } int pim_if_lan_delay_enabled(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - zassert(pim_ifp); - zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0); + pim_ifp = ifp->info; + zassert(pim_ifp); + zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0); - return pim_ifp->pim_number_of_nonlandelay_neighbors == 0; + return pim_ifp->pim_number_of_nonlandelay_neighbors == 0; } uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp) { - if (pim_if_lan_delay_enabled(ifp)) { - struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - return pim_ifp->pim_neighbors_highest_propagation_delay_msec; - } - else { - return PIM_DEFAULT_PROPAGATION_DELAY_MSEC; - } + if (pim_if_lan_delay_enabled(ifp)) { + struct pim_interface *pim_ifp; + pim_ifp = ifp->info; + return pim_ifp->pim_neighbors_highest_propagation_delay_msec; + } else { + return PIM_DEFAULT_PROPAGATION_DELAY_MSEC; + } } uint16_t pim_if_effective_override_interval_msec(struct interface *ifp) { - if (pim_if_lan_delay_enabled(ifp)) { - struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - return pim_ifp->pim_neighbors_highest_override_interval_msec; - } - else { - return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC; - } + if (pim_if_lan_delay_enabled(ifp)) { + struct pim_interface *pim_ifp; + pim_ifp = ifp->info; + return pim_ifp->pim_neighbors_highest_override_interval_msec; + } else { + return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC; + } } int pim_if_t_override_msec(struct interface *ifp) { - int effective_override_interval_msec; - int t_override_msec; + int effective_override_interval_msec; + int t_override_msec; - effective_override_interval_msec = - pim_if_effective_override_interval_msec(ifp); + effective_override_interval_msec = + pim_if_effective_override_interval_msec(ifp); - t_override_msec = random() % (effective_override_interval_msec + 1); + t_override_msec = random() % (effective_override_interval_msec + 1); - return t_override_msec; + return t_override_msec; } uint16_t pim_if_jp_override_interval_msec(struct interface *ifp) { - return pim_if_effective_propagation_delay_msec(ifp) + - pim_if_effective_override_interval_msec(ifp); + return pim_if_effective_propagation_delay_msec(ifp) + + pim_if_effective_override_interval_msec(ifp); } /* @@ -1168,294 +1179,303 @@ uint16_t pim_if_jp_override_interval_msec(struct interface *ifp) struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, struct in_addr addr) { - struct listnode *neighnode; - struct pim_neighbor *neigh; - struct pim_interface *pim_ifp; - struct prefix p; - - zassert(ifp); - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return 0; - } - - p.family = AF_INET; - p.u.prefix4 = addr; - p.prefixlen = IPV4_MAX_PREFIXLEN; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - - /* primary address ? */ - if (neigh->source_addr.s_addr == addr.s_addr) - return neigh; - - /* secondary address ? */ - if (pim_neighbor_find_secondary(neigh, &p)) - return neigh; - } - - if (PIM_DEBUG_PIM_TRACE) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s: neighbor not found for address %s on interface %s", - __PRETTY_FUNCTION__, - addr_str, ifp->name); - } - - return NULL; + struct listnode *neighnode; + struct pim_neighbor *neigh; + struct pim_interface *pim_ifp; + struct prefix p; + + zassert(ifp); + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return 0; + } + + p.family = AF_INET; + p.u.prefix4 = addr; + p.prefixlen = IPV4_MAX_PREFIXLEN; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, + neigh)) { + + /* primary address ? */ + if (neigh->source_addr.s_addr == addr.s_addr) + return neigh; + + /* secondary address ? */ + if (pim_neighbor_find_secondary(neigh, &p)) + return neigh; + } + + if (PIM_DEBUG_PIM_TRACE) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); + zlog_debug( + "%s: neighbor not found for address %s on interface %s", + __PRETTY_FUNCTION__, addr_str, ifp->name); + } + + return NULL; } long pim_if_t_suppressed_msec(struct interface *ifp) { - struct pim_interface *pim_ifp; - long t_suppressed_msec; - uint32_t ramount = 0; + struct pim_interface *pim_ifp; + long t_suppressed_msec; + uint32_t ramount = 0; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - /* join suppression disabled ? */ - if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)) - return 0; + /* join suppression disabled ? */ + if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)) + return 0; - /* t_suppressed = t_periodic * rand(1.1, 1.4) */ - ramount = 1100 + (random() % (1400 - 1100 + 1)); - t_suppressed_msec = qpim_t_periodic * ramount; + /* t_suppressed = t_periodic * rand(1.1, 1.4) */ + ramount = 1100 + (random() % (1400 - 1100 + 1)); + t_suppressed_msec = qpim_t_periodic * ramount; - return t_suppressed_msec; + return t_suppressed_msec; } static void igmp_join_free(struct igmp_join *ij) { - XFREE(MTYPE_PIM_IGMP_JOIN, ij); + XFREE(MTYPE_PIM_IGMP_JOIN, ij); } static struct igmp_join *igmp_join_find(struct list *join_list, struct in_addr group_addr, struct in_addr source_addr) { - struct listnode *node; - struct igmp_join *ij; + struct listnode *node; + struct igmp_join *ij; - zassert(join_list); + zassert(join_list); - for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) { - if ((group_addr.s_addr == ij->group_addr.s_addr) && - (source_addr.s_addr == ij->source_addr.s_addr)) - return ij; - } + for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) { + if ((group_addr.s_addr == ij->group_addr.s_addr) + && (source_addr.s_addr == ij->source_addr.s_addr)) + return ij; + } - return 0; + return 0; } -static int igmp_join_sock(const char *ifname, - ifindex_t ifindex, - struct in_addr group_addr, - struct in_addr source_addr) +static int igmp_join_sock(const char *ifname, ifindex_t ifindex, + struct in_addr group_addr, struct in_addr source_addr) { - int join_fd; + int join_fd; - join_fd = pim_socket_raw(IPPROTO_IGMP); - if (join_fd < 0) { - return -1; - } + join_fd = pim_socket_raw(IPPROTO_IGMP); + if (join_fd < 0) { + return -1; + } - if (pim_socket_join_source(join_fd, ifindex, group_addr, source_addr, ifname)) { - close(join_fd); - return -2; - } + if (pim_socket_join_source(join_fd, ifindex, group_addr, source_addr, + ifname)) { + close(join_fd); + return -2; + } - return join_fd; + return join_fd; } static struct igmp_join *igmp_join_new(struct interface *ifp, struct in_addr group_addr, struct in_addr source_addr) { - struct pim_interface *pim_ifp; - struct igmp_join *ij; - int join_fd; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr, source_addr); - if (join_fd < 0) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - return 0; - } - - ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij)); - if (!ij) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_err("%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - sizeof(*ij), group_str, source_str, ifp->name); - close(join_fd); - return 0; - } - - ij->sock_fd = join_fd; - ij->group_addr = group_addr; - ij->source_addr = source_addr; - ij->sock_creation = pim_time_monotonic_sec(); - - listnode_add(pim_ifp->igmp_join_list, ij); - - return ij; + struct pim_interface *pim_ifp; + struct igmp_join *ij; + int join_fd; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr, + source_addr); + if (join_fd < 0) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, source_str, ifp->name); + return 0; + } + + ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij)); + if (!ij) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_err( + "%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, sizeof(*ij), group_str, source_str, + ifp->name); + close(join_fd); + return 0; + } + + ij->sock_fd = join_fd; + ij->group_addr = group_addr; + ij->source_addr = source_addr; + ij->sock_creation = pim_time_monotonic_sec(); + + listnode_add(pim_ifp->igmp_join_list, ij); + + return ij; } -int pim_if_igmp_join_add(struct interface *ifp, - struct in_addr group_addr, +int pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr, struct in_addr source_addr) { - struct pim_interface *pim_ifp; - struct igmp_join *ij; - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return -1; - } - - if (!pim_ifp->igmp_join_list) { - pim_ifp->igmp_join_list = list_new(); - if (!pim_ifp->igmp_join_list) { - zlog_err("%s %s: failure: igmp_join_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return -2; - } - pim_ifp->igmp_join_list->del = (void (*)(void *)) igmp_join_free; - } - - ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); - if (ij) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: can't re-join existing IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - return -3; - } - - ij = igmp_join_new(ifp, group_addr, source_addr); - if (!ij) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: igmp_join_new() failure for IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - return -4; - } - - if (PIM_DEBUG_IGMP_EVENTS) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_debug("%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s", - __PRETTY_FUNCTION__, - source_str, group_str, ifp->name); - } - - return 0; -} + struct pim_interface *pim_ifp; + struct igmp_join *ij; + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return -1; + } + + if (!pim_ifp->igmp_join_list) { + pim_ifp->igmp_join_list = list_new(); + if (!pim_ifp->igmp_join_list) { + zlog_err("%s %s: failure: igmp_join_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return -2; + } + pim_ifp->igmp_join_list->del = (void (*)(void *))igmp_join_free; + } + + ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); + if (ij) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: can't re-join existing IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, source_str, ifp->name); + return -3; + } + + ij = igmp_join_new(ifp, group_addr, source_addr); + if (!ij) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: igmp_join_new() failure for IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, source_str, ifp->name); + return -4; + } + + if (PIM_DEBUG_IGMP_EVENTS) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_debug( + "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s", + __PRETTY_FUNCTION__, source_str, group_str, ifp->name); + } + return 0; +} -int pim_if_igmp_join_del(struct interface *ifp, - struct in_addr group_addr, +int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr, struct in_addr source_addr) { - struct pim_interface *pim_ifp; - struct igmp_join *ij; - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return -1; - } - - if (!pim_ifp->igmp_join_list) { - zlog_warn("%s: no IGMP join on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return -2; - } - - ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); - if (!ij) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: could not find IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - return -3; - } - - if (close(ij->sock_fd)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s", - __PRETTY_FUNCTION__, - ij->sock_fd, group_str, source_str, ifp->name, errno, safe_strerror(errno)); - /* warning only */ - } - listnode_delete(pim_ifp->igmp_join_list, ij); - igmp_join_free(ij); - if (listcount(pim_ifp->igmp_join_list) < 1) { - list_delete(pim_ifp->igmp_join_list); - pim_ifp->igmp_join_list = 0; - } - - return 0; + struct pim_interface *pim_ifp; + struct igmp_join *ij; + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return -1; + } + + if (!pim_ifp->igmp_join_list) { + zlog_warn("%s: no IGMP join on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return -2; + } + + ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); + if (!ij) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: could not find IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, source_str, ifp->name); + return -3; + } + + if (close(ij->sock_fd)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s", + __PRETTY_FUNCTION__, ij->sock_fd, group_str, source_str, + ifp->name, errno, safe_strerror(errno)); + /* warning only */ + } + listnode_delete(pim_ifp->igmp_join_list, ij); + igmp_join_free(ij); + if (listcount(pim_ifp->igmp_join_list) < 1) { + list_delete(pim_ifp->igmp_join_list); + pim_ifp->igmp_join_list = 0; + } + + return 0; } static void pim_if_igmp_join_del_all(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *nextnode; - struct igmp_join *ij; - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return; - } - - if (!pim_ifp->igmp_join_list) - return; - - for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij)) - pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr); + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *nextnode; + struct igmp_join *ij; + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return; + } + + if (!pim_ifp->igmp_join_list) + return; + + for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij)) + pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr); } /* @@ -1475,63 +1495,66 @@ static void pim_if_igmp_join_del_all(struct interface *ifp) void pim_if_assert_on_neighbor_down(struct interface *ifp, struct in_addr neigh_addr) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - /* Is (S,G,I) assert loser ? */ - if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) - continue; - /* Dead neighbor was winner ? */ - if (ch->ifassert_winner.s_addr != neigh_addr.s_addr) - continue; - - assert_action_a5(ch); - } + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + /* Is (S,G,I) assert loser ? */ + if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) + continue; + /* Dead neighbor was winner ? */ + if (ch->ifassert_winner.s_addr != neigh_addr.s_addr) + continue; + + assert_action_a5(ch); + } } void pim_if_update_join_desired(struct pim_interface *pim_ifp) { - struct listnode *ch_node; - struct pim_ifchannel *ch; + struct listnode *ch_node; + struct pim_ifchannel *ch; - /* clear off flag from interface's upstreams */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(ch->upstream->flags); - } + /* clear off flag from interface's upstreams */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { + PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED( + ch->upstream->flags); + } - /* scan per-interface (S,G,I) state on this I interface */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - struct pim_upstream *up = ch->upstream; + /* scan per-interface (S,G,I) state on this I interface */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { + struct pim_upstream *up = ch->upstream; - if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags)) - continue; + if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags)) + continue; - /* update join_desired for the global (S,G) state */ - pim_upstream_update_join_desired(up); - PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags); - } + /* update join_desired for the global (S,G) state */ + pim_upstream_update_join_desired(up); + PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags); + } } void pim_if_update_assert_tracking_desired(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; - - pim_ifp = ifp->info; - if (!pim_ifp) - return; - - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - pim_ifchannel_update_assert_tracking_desired(ch); - } + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; + + pim_ifp = ifp->info; + if (!pim_ifp) + return; + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + pim_ifchannel_update_assert_tracking_desired(ch); + } } /* @@ -1539,52 +1562,48 @@ void pim_if_update_assert_tracking_desired(struct interface *ifp) * The pimreg is a special interface that we have that is not * quite an inteface but a VIF is created for it. */ -void pim_if_create_pimreg (void) +void pim_if_create_pimreg(void) { - if (!pim_regiface) { - pim_regiface = if_create("pimreg", strlen("pimreg"), VRF_DEFAULT); - pim_regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF; + if (!pim_regiface) { + pim_regiface = + if_create("pimreg", strlen("pimreg"), VRF_DEFAULT); + pim_regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF; - pim_if_new(pim_regiface, 0, 0); - } + pim_if_new(pim_regiface, 0, 0); + } } -int -pim_if_connected_to_source (struct interface *ifp, struct in_addr src) +int pim_if_connected_to_source(struct interface *ifp, struct in_addr src) { - struct listnode *cnode; - struct connected *c; - struct prefix p; - - if (!ifp) - return 0; - - p.family = AF_INET; - p.u.prefix4 = src; - p.prefixlen = IPV4_MAX_BITLEN; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) - { - if ((c->address->family == AF_INET) && - prefix_match (CONNECTED_PREFIX (c), &p)) - { - return 1; - } - } - - return 0; + struct listnode *cnode; + struct connected *c; + struct prefix p; + + if (!ifp) + return 0; + + p.family = AF_INET; + p.u.prefix4 = src; + p.prefixlen = IPV4_MAX_BITLEN; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { + if ((c->address->family == AF_INET) + && prefix_match(CONNECTED_PREFIX(c), &p)) { + return 1; + } + } + + return 0; } -struct interface * -pim_if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id) +struct interface *pim_if_lookup_address_vrf(struct in_addr src, vrf_id_t vrf_id) { - struct listnode *ifnode; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist(vrf_id), ifnode, ifp)) - { - if (pim_if_connected_to_source (ifp, src) && ifp->info) - return ifp; - } - return NULL; + struct listnode *ifnode; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) { + if (pim_if_connected_to_source(ifp, src) && ifp->info) + return ifp; + } + return NULL; } diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index a1c2b692f..e742e68f6 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -56,81 +56,86 @@ #define PIM_I_am_DR(pim_ifp) (pim_ifp)->pim_dr_addr.s_addr == (pim_ifp)->primary_address.s_addr struct pim_iface_upstream_switch { - struct in_addr address; - struct list *us; + struct in_addr address; + struct list *us; }; enum pim_secondary_addr_flags { - PIM_SEC_ADDRF_NONE = 0, - PIM_SEC_ADDRF_STALE = (1 << 0) + PIM_SEC_ADDRF_NONE = 0, + PIM_SEC_ADDRF_STALE = (1 << 0) }; struct pim_secondary_addr { - struct prefix addr; - enum pim_secondary_addr_flags flags; + struct prefix addr; + enum pim_secondary_addr_flags flags; }; struct pim_interface { - uint32_t options; /* bit vector */ - ifindex_t mroute_vif_index; - struct in_addr primary_address; /* remember addr to detect change */ - struct list *sec_addr_list; /* list of struct pim_secondary_addr */ - struct in_addr update_source; /* user can statically set the primary - * address of the interface */ - - int igmp_version; /* IGMP version */ - int igmp_default_robustness_variable; /* IGMPv3 QRV */ - int igmp_default_query_interval; /* IGMPv3 secs between general queries */ - int igmp_query_max_response_time_dsec; /* IGMPv3 Max Response Time in dsecs for general queries */ - int igmp_specific_query_max_response_time_dsec; /* IGMPv3 Max Response Time in dsecs for specific queries */ - struct list *igmp_socket_list; /* list of struct igmp_sock */ - struct list *igmp_join_list; /* list of struct igmp_join */ - - int pim_sock_fd; /* PIM socket file descriptor */ - struct thread *t_pim_sock_read; /* thread for reading PIM socket */ - int64_t pim_sock_creation; /* timestamp of PIM socket creation */ - - struct thread *t_pim_hello_timer; - int pim_hello_period; - int pim_default_holdtime; - int pim_triggered_hello_delay; - uint32_t pim_generation_id; - uint16_t pim_propagation_delay_msec; /* config */ - uint16_t pim_override_interval_msec; /* config */ - struct list *pim_neighbor_list; /* list of struct pim_neighbor */ - struct list *upstream_switch_list; - struct list *pim_ifchannel_list; /* list of struct pim_ifchannel */ - struct hash *pim_ifchannel_hash; - - /* neighbors without lan_delay */ - int pim_number_of_nonlandelay_neighbors; - uint16_t pim_neighbors_highest_propagation_delay_msec; - uint16_t pim_neighbors_highest_override_interval_msec; - - /* DR Election */ - int64_t pim_dr_election_last; /* timestamp */ - int pim_dr_election_count; - int pim_dr_election_changes; - struct in_addr pim_dr_addr; - uint32_t pim_dr_priority; /* config */ - int pim_dr_num_nondrpri_neighbors; /* neighbors without dr_pri */ - - int64_t pim_ifstat_start; /* start timestamp for stats */ - uint32_t pim_ifstat_hello_sent; - uint32_t pim_ifstat_hello_sendfail; - uint32_t pim_ifstat_hello_recv; - uint32_t pim_ifstat_hello_recvfail; - uint32_t pim_ifstat_join_recv; - uint32_t pim_ifstat_join_send; - uint32_t pim_ifstat_prune_recv; - uint32_t pim_ifstat_prune_send; - uint32_t pim_ifstat_reg_recv; - uint32_t pim_ifstat_reg_send; - uint32_t pim_ifstat_reg_stop_recv; - uint32_t pim_ifstat_reg_stop_send; - uint32_t pim_ifstat_assert_recv; - uint32_t pim_ifstat_assert_send; - struct bfd_info *bfd_info; + uint32_t options; /* bit vector */ + ifindex_t mroute_vif_index; + struct in_addr primary_address; /* remember addr to detect change */ + struct list *sec_addr_list; /* list of struct pim_secondary_addr */ + struct in_addr update_source; /* user can statically set the primary + * address of the interface */ + + int igmp_version; /* IGMP version */ + int igmp_default_robustness_variable; /* IGMPv3 QRV */ + int + igmp_default_query_interval; /* IGMPv3 secs between general + queries */ + int igmp_query_max_response_time_dsec; /* IGMPv3 Max Response Time in + dsecs for general queries */ + int igmp_specific_query_max_response_time_dsec; /* IGMPv3 Max Response + Time in dsecs for + specific queries */ + struct list *igmp_socket_list; /* list of struct igmp_sock */ + struct list *igmp_join_list; /* list of struct igmp_join */ + + int pim_sock_fd; /* PIM socket file descriptor */ + struct thread *t_pim_sock_read; /* thread for reading PIM socket */ + int64_t pim_sock_creation; /* timestamp of PIM socket creation */ + + struct thread *t_pim_hello_timer; + int pim_hello_period; + int pim_default_holdtime; + int pim_triggered_hello_delay; + uint32_t pim_generation_id; + uint16_t pim_propagation_delay_msec; /* config */ + uint16_t pim_override_interval_msec; /* config */ + struct list *pim_neighbor_list; /* list of struct pim_neighbor */ + struct list *upstream_switch_list; + struct list *pim_ifchannel_list; /* list of struct pim_ifchannel */ + struct hash *pim_ifchannel_hash; + + /* neighbors without lan_delay */ + int pim_number_of_nonlandelay_neighbors; + uint16_t pim_neighbors_highest_propagation_delay_msec; + uint16_t pim_neighbors_highest_override_interval_msec; + + /* DR Election */ + int64_t pim_dr_election_last; /* timestamp */ + int pim_dr_election_count; + int pim_dr_election_changes; + struct in_addr pim_dr_addr; + uint32_t pim_dr_priority; /* config */ + int pim_dr_num_nondrpri_neighbors; /* neighbors without dr_pri */ + + int64_t pim_ifstat_start; /* start timestamp for stats */ + uint32_t pim_ifstat_hello_sent; + uint32_t pim_ifstat_hello_sendfail; + uint32_t pim_ifstat_hello_recv; + uint32_t pim_ifstat_hello_recvfail; + uint32_t pim_ifstat_join_recv; + uint32_t pim_ifstat_join_send; + uint32_t pim_ifstat_prune_recv; + uint32_t pim_ifstat_prune_send; + uint32_t pim_ifstat_reg_recv; + uint32_t pim_ifstat_reg_send; + uint32_t pim_ifstat_reg_stop_recv; + uint32_t pim_ifstat_reg_stop_send; + uint32_t pim_ifstat_assert_recv; + uint32_t pim_ifstat_assert_send; + struct bfd_info *bfd_info; }; extern struct interface *pim_regiface; @@ -139,16 +144,16 @@ extern struct list *pim_ifchannel_list; if default_holdtime is set (>= 0), use it; otherwise default_holdtime is 3.5 * hello_period */ -#define PIM_IF_DEFAULT_HOLDTIME(pim_ifp) \ - (((pim_ifp)->pim_default_holdtime < 0) ? \ - ((pim_ifp)->pim_hello_period * 7 / 2) : \ - ((pim_ifp)->pim_default_holdtime)) +#define PIM_IF_DEFAULT_HOLDTIME(pim_ifp) \ + (((pim_ifp)->pim_default_holdtime < 0) \ + ? ((pim_ifp)->pim_hello_period * 7 / 2) \ + : ((pim_ifp)->pim_default_holdtime)) void pim_if_init(void); -void pim_if_terminate (void); +void pim_if_terminate(void); struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim); -void pim_if_delete(struct interface *ifp); +void pim_if_delete(struct interface *ifp); void pim_if_addr_add(struct connected *ifc); void pim_if_addr_del(struct connected *ifc, int force_prim_as_any); void pim_if_addr_add_all(struct interface *ifp); @@ -156,7 +161,8 @@ void pim_if_addr_del_all(struct interface *ifp); void pim_if_addr_del_all_igmp(struct interface *ifp); void pim_if_addr_del_all_pim(struct interface *ifp); -struct interface *pim_if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id); +struct interface *pim_if_lookup_address_vrf(struct in_addr src, + vrf_id_t vrf_id); int pim_if_add_vif(struct interface *ifp); int pim_if_del_vif(struct interface *ifp); @@ -178,11 +184,9 @@ int pim_if_t_override_msec(struct interface *ifp); struct in_addr pim_find_primary_addr(struct interface *ifp); -int pim_if_igmp_join_add(struct interface *ifp, - struct in_addr group_addr, +int pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr, struct in_addr source_addr); -int pim_if_igmp_join_del(struct interface *ifp, - struct in_addr group_addr, +int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr, struct in_addr source_addr); void pim_if_update_could_assert(struct interface *ifp); @@ -199,7 +203,7 @@ void pim_if_update_assert_tracking_desired(struct interface *ifp); void pim_if_create_pimreg(void); -int pim_if_connected_to_source (struct interface *ifp, struct in_addr src); +int pim_if_connected_to_source(struct interface *ifp, struct in_addr src); int pim_update_source_set(struct interface *ifp, struct in_addr source); #endif /* PIM_IFACE_H */ diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 021722dfc..d4916518e 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -43,34 +43,33 @@ #include "pim_upstream.h" #include "pim_ssm.h" -int -pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) +int pim_ifchannel_compare(struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) { - struct pim_interface *pim_ifp1; - struct pim_interface *pim_ifp2; + struct pim_interface *pim_ifp1; + struct pim_interface *pim_ifp2; - pim_ifp1 = ch1->interface->info; - pim_ifp2 = ch2->interface->info; + pim_ifp1 = ch1->interface->info; + pim_ifp2 = ch2->interface->info; - if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index) - return -1; + if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index) + return -1; - if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index) - return 1; + if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index) + return 1; - if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr)) - return -1; + if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr)) + return -1; - if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr)) - return 1; + if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr)) + return 1; - if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr)) - return -1; + if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr)) + return -1; - if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr)) - return 1; + if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr)) + return 1; - return 0; + return 0; } /* @@ -78,20 +77,18 @@ pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) * remove the parent pointer from * those pointing at us */ -static void -pim_ifchannel_remove_children (struct pim_ifchannel *ch) +static void pim_ifchannel_remove_children(struct pim_ifchannel *ch) { - struct pim_ifchannel *child; + struct pim_ifchannel *child; - if (!ch->sources) - return; + if (!ch->sources) + return; - while (!list_isempty (ch->sources)) - { - child = listnode_head (ch->sources); - child->parent = NULL; - listnode_delete (ch->sources, child); - } + while (!list_isempty(ch->sources)) { + child = listnode_head(ch->sources); + child->parent = NULL; + listnode_delete(ch->sources, child); + } } /* @@ -99,284 +96,302 @@ pim_ifchannel_remove_children (struct pim_ifchannel *ch) * find all the children that would point * at us. */ -static void -pim_ifchannel_find_new_children (struct pim_ifchannel *ch) +static void pim_ifchannel_find_new_children(struct pim_ifchannel *ch) { - struct pim_interface *pim_ifp = ch->interface->info; - struct pim_ifchannel *child; - struct listnode *ch_node; - - // Basic Sanity that we are not being silly - if ((ch->sg.src.s_addr != INADDR_ANY) && - (ch->sg.grp.s_addr != INADDR_ANY)) - return; - - if ((ch->sg.src.s_addr == INADDR_ANY) && - (ch->sg.grp.s_addr == INADDR_ANY)) - return; - - for (ALL_LIST_ELEMENTS_RO (pim_ifp->pim_ifchannel_list, ch_node, child)) - { - if ((ch->sg.grp.s_addr != INADDR_ANY) && - (child->sg.grp.s_addr == ch->sg.grp.s_addr) && - (child != ch)) - { - child->parent = ch; - listnode_add_sort (ch->sources, child); + struct pim_interface *pim_ifp = ch->interface->info; + struct pim_ifchannel *child; + struct listnode *ch_node; + + // Basic Sanity that we are not being silly + if ((ch->sg.src.s_addr != INADDR_ANY) + && (ch->sg.grp.s_addr != INADDR_ANY)) + return; + + if ((ch->sg.src.s_addr == INADDR_ANY) + && (ch->sg.grp.s_addr == INADDR_ANY)) + return; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, + child)) { + if ((ch->sg.grp.s_addr != INADDR_ANY) + && (child->sg.grp.s_addr == ch->sg.grp.s_addr) + && (child != ch)) { + child->parent = ch; + listnode_add_sort(ch->sources, child); + } } - } } void pim_ifchannel_free(struct pim_ifchannel *ch) { - XFREE(MTYPE_PIM_IFCHANNEL, ch); + XFREE(MTYPE_PIM_IFCHANNEL, ch); } void pim_ifchannel_delete(struct pim_ifchannel *ch) { - struct pim_interface *pim_ifp; - - pim_ifp = ch->interface->info; - - if (ch->upstream->channel_oil) - { - uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; - if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) - mask = PIM_OIF_FLAG_PROTO_IGMP; - - /* SGRpt entry could have empty oil */ - if (ch->upstream->channel_oil) - pim_channel_del_oif (ch->upstream->channel_oil, ch->interface, mask); - /* - * Do we have any S,G's that are inheriting? - * Nuke from on high too. - */ - if (ch->upstream->sources) - { - struct pim_upstream *child; - struct listnode *up_node; - - for (ALL_LIST_ELEMENTS_RO (ch->upstream->sources, up_node, child)) - pim_channel_del_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); + struct pim_interface *pim_ifp; + + pim_ifp = ch->interface->info; + + if (ch->upstream->channel_oil) { + uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; + if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + mask = PIM_OIF_FLAG_PROTO_IGMP; + + /* SGRpt entry could have empty oil */ + if (ch->upstream->channel_oil) + pim_channel_del_oif(ch->upstream->channel_oil, + ch->interface, mask); + /* + * Do we have any S,G's that are inheriting? + * Nuke from on high too. + */ + if (ch->upstream->sources) { + struct pim_upstream *child; + struct listnode *up_node; + + for (ALL_LIST_ELEMENTS_RO(ch->upstream->sources, + up_node, child)) + pim_channel_del_oif(child->channel_oil, + ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + } + } + + /* + * When this channel is removed + * we need to find all our children + * and make sure our pointers are fixed + */ + pim_ifchannel_remove_children(ch); + + if (ch->sources) + list_delete(ch->sources); + + listnode_delete(ch->upstream->ifchannels, ch); + + if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) { + pim_upstream_update_join_desired(ch->upstream); } - } - - /* - * When this channel is removed - * we need to find all our children - * and make sure our pointers are fixed - */ - pim_ifchannel_remove_children (ch); - - if (ch->sources) - list_delete (ch->sources); - - listnode_delete(ch->upstream->ifchannels, ch); - - if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) { - pim_upstream_update_join_desired(ch->upstream); - } - - /* upstream is common across ifchannels, check if upstream's - ifchannel list is empty before deleting upstream_del - ref count will take care of it. - */ - pim_upstream_del(ch->upstream, __PRETTY_FUNCTION__); - ch->upstream = NULL; - - THREAD_OFF(ch->t_ifjoin_expiry_timer); - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - THREAD_OFF(ch->t_ifassert_timer); - - if (ch->parent) - { - listnode_delete (ch->parent->sources, ch); - ch->parent = NULL; - } - /* - notice that listnode_delete() can't be moved - into pim_ifchannel_free() because the later is - called by list_delete_all_node() - */ - listnode_delete(pim_ifp->pim_ifchannel_list, ch); - hash_release(pim_ifp->pim_ifchannel_hash, ch); - listnode_delete(pim_ifchannel_list, ch); - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: ifchannel entry %s is deleted ", __PRETTY_FUNCTION__, ch->sg_str); - - pim_ifchannel_free(ch); + + /* upstream is common across ifchannels, check if upstream's + ifchannel list is empty before deleting upstream_del + ref count will take care of it. + */ + pim_upstream_del(ch->upstream, __PRETTY_FUNCTION__); + ch->upstream = NULL; + + THREAD_OFF(ch->t_ifjoin_expiry_timer); + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + THREAD_OFF(ch->t_ifassert_timer); + + if (ch->parent) { + listnode_delete(ch->parent->sources, ch); + ch->parent = NULL; + } + /* + notice that listnode_delete() can't be moved + into pim_ifchannel_free() because the later is + called by list_delete_all_node() + */ + listnode_delete(pim_ifp->pim_ifchannel_list, ch); + hash_release(pim_ifp->pim_ifchannel_hash, ch); + listnode_delete(pim_ifchannel_list, ch); + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: ifchannel entry %s is deleted ", + __PRETTY_FUNCTION__, ch->sg_str); + + pim_ifchannel_free(ch); } -void -pim_ifchannel_delete_all (struct interface *ifp) +void pim_ifchannel_delete_all(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *ifchannel_node; - struct listnode *ifchannel_nextnode; - struct pim_ifchannel *ifchannel; - - pim_ifp = ifp->info; - if (!pim_ifp) - return; - - for (ALL_LIST_ELEMENTS (pim_ifp->pim_ifchannel_list, ifchannel_node, - ifchannel_nextnode, ifchannel)) - { - pim_ifchannel_delete (ifchannel); - } + struct pim_interface *pim_ifp; + struct listnode *ifchannel_node; + struct listnode *ifchannel_nextnode; + struct pim_ifchannel *ifchannel; + + pim_ifp = ifp->info; + if (!pim_ifp) + return; + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, ifchannel_node, + ifchannel_nextnode, ifchannel)) { + pim_ifchannel_delete(ifchannel); + } } - + static void delete_on_noinfo(struct pim_ifchannel *ch) { - if (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO && - ch->ifjoin_state == PIM_IFJOIN_NOINFO && - ch->t_ifjoin_expiry_timer == NULL) - pim_ifchannel_delete(ch); - + if (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO + && ch->ifjoin_state == PIM_IFJOIN_NOINFO + && ch->t_ifjoin_expiry_timer == NULL) + pim_ifchannel_delete(ch); } -void pim_ifchannel_ifjoin_switch(const char *caller, - struct pim_ifchannel *ch, +void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch, enum pim_ifjoin_state new_state) { - enum pim_ifjoin_state old_state = ch->ifjoin_state; - - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug ("PIM_IFCHANNEL(%s): %s is switching from %s to %s", - ch->interface->name, - ch->sg_str, - pim_ifchannel_ifjoin_name (ch->ifjoin_state, ch->flags), - pim_ifchannel_ifjoin_name (new_state, 0)); - - - if (old_state == new_state) { - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("%s calledby %s: non-transition on state %d (%s)", - __PRETTY_FUNCTION__, caller, new_state, - pim_ifchannel_ifjoin_name(new_state, 0)); - } - return; - } - - ch->ifjoin_state = new_state; - - if (ch->sg.src.s_addr == INADDR_ANY) - { - struct pim_upstream *up = ch->upstream; - struct pim_upstream *child; - struct listnode *up_node; - - if (up) - { - if (ch->ifjoin_state == PIM_IFJOIN_NOINFO) - { - for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) - { - struct channel_oil *c_oil = child->channel_oil; - struct pim_interface *pim_ifp = ch->interface->info; - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s %s: Prune(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - child->sg_str, up->sg_str); - if (!c_oil) - continue; - - if (!pim_upstream_evaluate_join_desired (child)) - { - pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); - pim_upstream_update_join_desired (child); - } - - /* - * If the S,G has no if channel and the c_oil still - * has output here then the *,G was supplying the implied - * if channel. So remove it. - * I think this is dead code now. is it? - */ - if (!ch && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) - pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); + enum pim_ifjoin_state old_state = ch->ifjoin_state; + + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "PIM_IFCHANNEL(%s): %s is switching from %s to %s", + ch->interface->name, ch->sg_str, + pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), + pim_ifchannel_ifjoin_name(new_state, 0)); + + + if (old_state == new_state) { + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug( + "%s calledby %s: non-transition on state %d (%s)", + __PRETTY_FUNCTION__, caller, new_state, + pim_ifchannel_ifjoin_name(new_state, 0)); } - } - if (ch->ifjoin_state == PIM_IFJOIN_JOIN) - { - for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s %s: Join(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - child->sg_str, up->sg_str); - - if (pim_upstream_evaluate_join_desired (child)) - { - pim_channel_add_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); - pim_upstream_update_join_desired (child); - } + return; + } + + ch->ifjoin_state = new_state; + + if (ch->sg.src.s_addr == INADDR_ANY) { + struct pim_upstream *up = ch->upstream; + struct pim_upstream *child; + struct listnode *up_node; + + if (up) { + if (ch->ifjoin_state == PIM_IFJOIN_NOINFO) { + for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, + child)) { + struct channel_oil *c_oil = + child->channel_oil; + struct pim_interface *pim_ifp = + ch->interface->info; + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s %s: Prune(S,G)=%s from %s", + __FILE__, + __PRETTY_FUNCTION__, + child->sg_str, + up->sg_str); + if (!c_oil) + continue; + + if (!pim_upstream_evaluate_join_desired( + child)) { + pim_channel_del_oif( + c_oil, ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + pim_upstream_update_join_desired( + child); + } + + /* + * If the S,G has no if channel and the + * c_oil still + * has output here then the *,G was + * supplying the implied + * if channel. So remove it. + * I think this is dead code now. is it? + */ + if (!ch + && c_oil->oil.mfcc_ttls + [pim_ifp->mroute_vif_index]) + pim_channel_del_oif( + c_oil, ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + } + } + if (ch->ifjoin_state == PIM_IFJOIN_JOIN) { + for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, + child)) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s %s: Join(S,G)=%s from %s", + __FILE__, + __PRETTY_FUNCTION__, + child->sg_str, + up->sg_str); + + if (pim_upstream_evaluate_join_desired( + child)) { + pim_channel_add_oif( + child->channel_oil, + ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + pim_upstream_update_join_desired( + child); + } + } + } } - } } - } - /* Transition to/from NOINFO ? */ - if ((old_state == PIM_IFJOIN_NOINFO) || - (new_state == PIM_IFJOIN_NOINFO)) { - - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("PIM_IFCHANNEL_%s: (S,G)=%s on interface %s", - ((new_state == PIM_IFJOIN_NOINFO) ? "DOWN" : "UP"), - ch->sg_str, ch->interface->name); - } - - /* - Record uptime of state transition to/from NOINFO - */ - ch->ifjoin_creation = pim_time_monotonic_sec(); - - pim_upstream_update_join_desired(ch->upstream); - pim_ifchannel_update_could_assert(ch); - pim_ifchannel_update_assert_tracking_desired(ch); - } + /* Transition to/from NOINFO ? */ + if ((old_state == PIM_IFJOIN_NOINFO) + || (new_state == PIM_IFJOIN_NOINFO)) { + + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug("PIM_IFCHANNEL_%s: (S,G)=%s on interface %s", + ((new_state == PIM_IFJOIN_NOINFO) ? "DOWN" + : "UP"), + ch->sg_str, ch->interface->name); + } + + /* + Record uptime of state transition to/from NOINFO + */ + ch->ifjoin_creation = pim_time_monotonic_sec(); + + pim_upstream_update_join_desired(ch->upstream); + pim_ifchannel_update_could_assert(ch); + pim_ifchannel_update_assert_tracking_desired(ch); + } } const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, - int flags) + int flags) { - switch (ifjoin_state) { - case PIM_IFJOIN_NOINFO: - if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) - return "SGRpt"; - else - return "NOINFO"; - break; - case PIM_IFJOIN_JOIN: - return "JOIN"; - break; - case PIM_IFJOIN_PRUNE: - return "PRUNE"; - break; - case PIM_IFJOIN_PRUNE_PENDING: - return "PRUNEP"; - break; - case PIM_IFJOIN_PRUNE_TMP: - return "PRUNET"; - break; - case PIM_IFJOIN_PRUNE_PENDING_TMP: - return "PRUNEPT"; - break; - } - - return "ifjoin_bad_state"; + switch (ifjoin_state) { + case PIM_IFJOIN_NOINFO: + if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) + return "SGRpt"; + else + return "NOINFO"; + break; + case PIM_IFJOIN_JOIN: + return "JOIN"; + break; + case PIM_IFJOIN_PRUNE: + return "PRUNE"; + break; + case PIM_IFJOIN_PRUNE_PENDING: + return "PRUNEP"; + break; + case PIM_IFJOIN_PRUNE_TMP: + return "PRUNET"; + break; + case PIM_IFJOIN_PRUNE_PENDING_TMP: + return "PRUNEPT"; + break; + } + + return "ifjoin_bad_state"; } const char *pim_ifchannel_ifassert_name(enum pim_ifassert_state ifassert_state) { - switch (ifassert_state) { - case PIM_IFASSERT_NOINFO: return "NOINFO"; - case PIM_IFASSERT_I_AM_WINNER: return "WINNER"; - case PIM_IFASSERT_I_AM_LOSER: return "LOSER"; - } + switch (ifassert_state) { + case PIM_IFASSERT_NOINFO: + return "NOINFO"; + case PIM_IFASSERT_I_AM_WINNER: + return "WINNER"; + case PIM_IFASSERT_I_AM_LOSER: + return "LOSER"; + } - return "ifassert_bad_state"; + return "ifassert_bad_state"; } /* @@ -387,88 +402,85 @@ const char *pim_ifchannel_ifassert_name(enum pim_ifassert_state ifassert_state) */ void reset_ifassert_state(struct pim_ifchannel *ch) { - struct in_addr any = { .s_addr = INADDR_ANY }; + struct in_addr any = {.s_addr = INADDR_ANY}; - THREAD_OFF(ch->t_ifassert_timer); + THREAD_OFF(ch->t_ifassert_timer); - pim_ifassert_winner_set(ch, - PIM_IFASSERT_NOINFO, - any, - qpim_infinite_assert_metric); + pim_ifassert_winner_set(ch, PIM_IFASSERT_NOINFO, any, + qpim_infinite_assert_metric); } struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, struct prefix_sg *sg) { - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - struct pim_ifchannel lookup; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + struct pim_ifchannel lookup; - pim_ifp = ifp->info; + pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (sg), - ifp->name); - return NULL; - } + if (!pim_ifp) { + zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name); + return NULL; + } - lookup.sg = *sg; - ch = hash_lookup (pim_ifp->pim_ifchannel_hash, &lookup); + lookup.sg = *sg; + ch = hash_lookup(pim_ifp->pim_ifchannel_hash, &lookup); - return ch; + return ch; } static void ifmembership_set(struct pim_ifchannel *ch, enum pim_ifmembership membership) { - if (ch->local_ifmembership == membership) - return; - - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("%s: (S,G)=%s membership now is %s on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, - membership == PIM_IFMEMBERSHIP_INCLUDE ? "INCLUDE" : "NOINFO", - ch->interface->name); - } - - ch->local_ifmembership = membership; - - pim_upstream_update_join_desired(ch->upstream); - pim_ifchannel_update_could_assert(ch); - pim_ifchannel_update_assert_tracking_desired(ch); + if (ch->local_ifmembership == membership) + return; + + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug("%s: (S,G)=%s membership now is %s on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, + membership == PIM_IFMEMBERSHIP_INCLUDE ? "INCLUDE" + : "NOINFO", + ch->interface->name); + } + + ch->local_ifmembership = membership; + + pim_upstream_update_join_desired(ch->upstream); + pim_ifchannel_update_could_assert(ch); + pim_ifchannel_update_assert_tracking_desired(ch); } void pim_ifchannel_membership_clear(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *ch_node; - struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); - } + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { + ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); + } } void pim_ifchannel_delete_on_noinfo(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - delete_on_noinfo(ch); - } + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + delete_on_noinfo(ch); + } } /* @@ -477,682 +489,687 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp) * If we are passed a *,G, find the *,* ifchannel * if we have it. */ -static struct pim_ifchannel * -pim_ifchannel_find_parent (struct pim_ifchannel *ch) +static struct pim_ifchannel *pim_ifchannel_find_parent(struct pim_ifchannel *ch) { - struct prefix_sg parent_sg = ch->sg; - struct pim_ifchannel *parent = NULL; - - // (S,G) - if ((parent_sg.src.s_addr != INADDR_ANY) && - (parent_sg.grp.s_addr != INADDR_ANY)) - { - parent_sg.src.s_addr = INADDR_ANY; - parent = pim_ifchannel_find (ch->interface, &parent_sg); - - if (parent) - listnode_add (parent->sources, ch); - return parent; - } - - return NULL; + struct prefix_sg parent_sg = ch->sg; + struct pim_ifchannel *parent = NULL; + + // (S,G) + if ((parent_sg.src.s_addr != INADDR_ANY) + && (parent_sg.grp.s_addr != INADDR_ANY)) { + parent_sg.src.s_addr = INADDR_ANY; + parent = pim_ifchannel_find(ch->interface, &parent_sg); + + if (parent) + listnode_add(parent->sources, ch); + return parent; + } + + return NULL; } -struct pim_ifchannel * -pim_ifchannel_add(struct interface *ifp, - struct prefix_sg *sg, int flags) +struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, + struct prefix_sg *sg, int flags) { - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - struct pim_upstream *up; - - ch = pim_ifchannel_find(ifp, sg); - if (ch) - return ch; - - pim_ifp = ifp->info; - - up = pim_upstream_add(sg, NULL, flags, __PRETTY_FUNCTION__); - if (!up) { - zlog_err("%s: could not attach upstream (S,G)=%s on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (sg), ifp->name); - return NULL; - } - - ch = XCALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch)); - if (!ch) { - zlog_warn("%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s", - __PRETTY_FUNCTION__, - up->sg_str, ifp->name); - - pim_upstream_del (up, __PRETTY_FUNCTION__); - return NULL; - } - - ch->flags = 0; - ch->upstream = up; - ch->interface = ifp; - ch->sg = *sg; - pim_str_sg_set (sg, ch->sg_str); - ch->parent = pim_ifchannel_find_parent (ch); - if (ch->sg.src.s_addr == INADDR_ANY) - { - ch->sources = list_new (); - ch->sources->cmp = (int (*)(void *, void *))pim_ifchannel_compare; - } - else - ch->sources = NULL; - - pim_ifchannel_find_new_children (ch); - ch->local_ifmembership = PIM_IFMEMBERSHIP_NOINFO; - - ch->ifjoin_state = PIM_IFJOIN_NOINFO; - ch->t_ifjoin_expiry_timer = NULL; - ch->t_ifjoin_prune_pending_timer = NULL; - ch->ifjoin_creation = 0; - - ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch); - ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval (ch); - - ch->ifassert_winner.s_addr = 0; - - /* Assert state */ - ch->t_ifassert_timer = NULL; - ch->ifassert_state = PIM_IFASSERT_NOINFO; - reset_ifassert_state(ch); - if (pim_macro_ch_could_assert_eval(ch)) - PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); - else - PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); - - if (pim_macro_assert_tracking_desired_eval(ch)) - PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); - else - PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); - - /* Attach to list */ - listnode_add_sort(pim_ifp->pim_ifchannel_list, ch); - ch = hash_get (pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern); - listnode_add_sort(pim_ifchannel_list, ch); - - listnode_add_sort(up->ifchannels, ch); - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: ifchannel %s is created ", __PRETTY_FUNCTION__, ch->sg_str); - - return ch; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + struct pim_upstream *up; + + ch = pim_ifchannel_find(ifp, sg); + if (ch) + return ch; + + pim_ifp = ifp->info; + + up = pim_upstream_add(sg, NULL, flags, __PRETTY_FUNCTION__); + if (!up) { + zlog_err( + "%s: could not attach upstream (S,G)=%s on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name); + return NULL; + } + + ch = XCALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch)); + if (!ch) { + zlog_warn( + "%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s", + __PRETTY_FUNCTION__, up->sg_str, ifp->name); + + pim_upstream_del(up, __PRETTY_FUNCTION__); + return NULL; + } + + ch->flags = 0; + ch->upstream = up; + ch->interface = ifp; + ch->sg = *sg; + pim_str_sg_set(sg, ch->sg_str); + ch->parent = pim_ifchannel_find_parent(ch); + if (ch->sg.src.s_addr == INADDR_ANY) { + ch->sources = list_new(); + ch->sources->cmp = + (int (*)(void *, void *))pim_ifchannel_compare; + } else + ch->sources = NULL; + + pim_ifchannel_find_new_children(ch); + ch->local_ifmembership = PIM_IFMEMBERSHIP_NOINFO; + + ch->ifjoin_state = PIM_IFJOIN_NOINFO; + ch->t_ifjoin_expiry_timer = NULL; + ch->t_ifjoin_prune_pending_timer = NULL; + ch->ifjoin_creation = 0; + + ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch); + ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval(ch); + + ch->ifassert_winner.s_addr = 0; + + /* Assert state */ + ch->t_ifassert_timer = NULL; + ch->ifassert_state = PIM_IFASSERT_NOINFO; + reset_ifassert_state(ch); + if (pim_macro_ch_could_assert_eval(ch)) + PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); + else + PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); + + if (pim_macro_assert_tracking_desired_eval(ch)) + PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); + else + PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); + + /* Attach to list */ + listnode_add_sort(pim_ifp->pim_ifchannel_list, ch); + ch = hash_get(pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern); + listnode_add_sort(pim_ifchannel_list, ch); + + listnode_add_sort(up->ifchannels, ch); + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: ifchannel %s is created ", __PRETTY_FUNCTION__, + ch->sg_str); + + return ch; } static void ifjoin_to_noinfo(struct pim_ifchannel *ch, bool ch_del) { - pim_forward_stop(ch); - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); - if (ch_del) - delete_on_noinfo(ch); + pim_forward_stop(ch); + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); + if (ch_del) + delete_on_noinfo(ch); } static int on_ifjoin_expiry_timer(struct thread *t) { - struct pim_ifchannel *ch; + struct pim_ifchannel *ch; - ch = THREAD_ARG(t); + ch = THREAD_ARG(t); - ifjoin_to_noinfo(ch, true); - /* ch may have been deleted */ + ifjoin_to_noinfo(ch, true); + /* ch may have been deleted */ - return 0; + return 0; } static int on_ifjoin_prune_pending_timer(struct thread *t) { - struct pim_ifchannel *ch; - int send_prune_echo; /* boolean */ - struct interface *ifp; - struct pim_interface *pim_ifp; - - ch = THREAD_ARG(t); - - if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) - { - /* Send PruneEcho(S,G) ? */ - ifp = ch->interface; - pim_ifp = ifp->info; - send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); - - if (send_prune_echo) - { - struct pim_rpf rpf; - - rpf.source_nexthop.interface = ifp; - rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address; - pim_jp_agg_single_upstream_send(&rpf, ch->upstream, 0); - } - /* If SGRpt flag is set on ifchannel, Trigger SGRpt - message on RP path upon prune timer expiry. - */ - if (PIM_IF_FLAG_TEST_S_G_RPT (ch->flags)) - { - if (ch->upstream) - pim_upstream_update_join_desired(ch->upstream); - /* - ch->ifjoin_state transition to NOINFO state - ch_del is set to 0 for not deleteing from here. - Holdtime expiry (ch_del set to 1) delete the entry. - */ - ifjoin_to_noinfo(ch, false); - } - else - ifjoin_to_noinfo(ch, true); - /* from here ch may have been deleted */ - } - else - { - zlog_warn("%s: IFCHANNEL%s Prune Pending Timer Popped while in %s state", - __PRETTY_FUNCTION__, pim_str_sg_dump (&ch->sg), - pim_ifchannel_ifjoin_name (ch->ifjoin_state, ch->flags)); - } - - return 0; + struct pim_ifchannel *ch; + int send_prune_echo; /* boolean */ + struct interface *ifp; + struct pim_interface *pim_ifp; + + ch = THREAD_ARG(t); + + if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) { + /* Send PruneEcho(S,G) ? */ + ifp = ch->interface; + pim_ifp = ifp->info; + send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); + + if (send_prune_echo) { + struct pim_rpf rpf; + + rpf.source_nexthop.interface = ifp; + rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address; + pim_jp_agg_single_upstream_send(&rpf, ch->upstream, 0); + } + /* If SGRpt flag is set on ifchannel, Trigger SGRpt + message on RP path upon prune timer expiry. + */ + if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) { + if (ch->upstream) + pim_upstream_update_join_desired(ch->upstream); + /* + ch->ifjoin_state transition to NOINFO state + ch_del is set to 0 for not deleteing from here. + Holdtime expiry (ch_del set to 1) delete the entry. + */ + ifjoin_to_noinfo(ch, false); + } else + ifjoin_to_noinfo(ch, true); + /* from here ch may have been deleted */ + } else { + zlog_warn( + "%s: IFCHANNEL%s Prune Pending Timer Popped while in %s state", + __PRETTY_FUNCTION__, pim_str_sg_dump(&ch->sg), + pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags)); + } + + return 0; } -static void check_recv_upstream(int is_join, - struct interface *recv_ifp, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, - int holdtime) +static void check_recv_upstream(int is_join, struct interface *recv_ifp, + struct in_addr upstream, struct prefix_sg *sg, + uint8_t source_flags, int holdtime) { - struct pim_upstream *up; - - /* Upstream (S,G) in Joined state ? */ - up = pim_upstream_find(sg); - if (!up) - return; - if (up->join_state != PIM_UPSTREAM_JOINED) - return; - - /* Upstream (S,G) in Joined state */ - - if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { - /* RPF'(S,G) not found */ - zlog_warn("%s %s: RPF'%s not found", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str); - return; - } - - /* upstream directed to RPF'(S,G) ? */ - if (upstream.s_addr != up->rpf.rpf_addr.u.prefix4.s_addr) { - char up_str[INET_ADDRSTRLEN]; - char rpf_str[PREFIX_STRLEN]; - pim_inet4_dump("<up?>", upstream, up_str, sizeof(up_str)); - pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); - zlog_warn("%s %s: (S,G)=%s upstream=%s not directed to RPF'(S,G)=%s on interface %s", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str, - up_str, rpf_str, recv_ifp->name); - return; - } - /* upstream directed to RPF'(S,G) */ - - if (is_join) { - /* Join(S,G) to RPF'(S,G) */ - pim_upstream_join_suppress(up, up->rpf.rpf_addr.u.prefix4, holdtime); - return; - } - - /* Prune to RPF'(S,G) */ - - if (source_flags & PIM_RPT_BIT_MASK) { - if (source_flags & PIM_WILDCARD_BIT_MASK) { - /* Prune(*,G) to RPF'(S,G) */ - pim_upstream_join_timer_decrease_to_t_override("Prune(*,G)", up); - return; - } - - /* Prune(S,G,rpt) to RPF'(S,G) */ - pim_upstream_join_timer_decrease_to_t_override("Prune(S,G,rpt)", up); - return; - } - - /* Prune(S,G) to RPF'(S,G) */ - pim_upstream_join_timer_decrease_to_t_override("Prune(S,G)", up); + struct pim_upstream *up; + + /* Upstream (S,G) in Joined state ? */ + up = pim_upstream_find(sg); + if (!up) + return; + if (up->join_state != PIM_UPSTREAM_JOINED) + return; + + /* Upstream (S,G) in Joined state */ + + if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { + /* RPF'(S,G) not found */ + zlog_warn("%s %s: RPF'%s not found", __FILE__, + __PRETTY_FUNCTION__, up->sg_str); + return; + } + + /* upstream directed to RPF'(S,G) ? */ + if (upstream.s_addr != up->rpf.rpf_addr.u.prefix4.s_addr) { + char up_str[INET_ADDRSTRLEN]; + char rpf_str[PREFIX_STRLEN]; + pim_inet4_dump("<up?>", upstream, up_str, sizeof(up_str)); + pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str, + sizeof(rpf_str)); + zlog_warn( + "%s %s: (S,G)=%s upstream=%s not directed to RPF'(S,G)=%s on interface %s", + __FILE__, __PRETTY_FUNCTION__, up->sg_str, up_str, + rpf_str, recv_ifp->name); + return; + } + /* upstream directed to RPF'(S,G) */ + + if (is_join) { + /* Join(S,G) to RPF'(S,G) */ + pim_upstream_join_suppress(up, up->rpf.rpf_addr.u.prefix4, + holdtime); + return; + } + + /* Prune to RPF'(S,G) */ + + if (source_flags & PIM_RPT_BIT_MASK) { + if (source_flags & PIM_WILDCARD_BIT_MASK) { + /* Prune(*,G) to RPF'(S,G) */ + pim_upstream_join_timer_decrease_to_t_override( + "Prune(*,G)", up); + return; + } + + /* Prune(S,G,rpt) to RPF'(S,G) */ + pim_upstream_join_timer_decrease_to_t_override("Prune(S,G,rpt)", + up); + return; + } + + /* Prune(S,G) to RPF'(S,G) */ + pim_upstream_join_timer_decrease_to_t_override("Prune(S,G)", up); } -static int -nonlocal_upstream(int is_join, - struct interface *recv_ifp, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, - uint16_t holdtime) +static int nonlocal_upstream(int is_join, struct interface *recv_ifp, + struct in_addr upstream, struct prefix_sg *sg, + uint8_t source_flags, uint16_t holdtime) { - struct pim_interface *recv_pim_ifp; - int is_local; /* boolean */ - - recv_pim_ifp = recv_ifp->info; - zassert(recv_pim_ifp); - - is_local = (upstream.s_addr == recv_pim_ifp->primary_address.s_addr); - - if (is_local) - return 0; - - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - char up_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); - zlog_warn("%s: recv %s (S,G)=%s to non-local upstream=%s on %s", - __PRETTY_FUNCTION__, - is_join ? "join" : "prune", - pim_str_sg_dump (sg), - up_str, recv_ifp->name); - } - - /* - * Since recv upstream addr was not directed to our primary - * address, check if we should react to it in any way. - */ - check_recv_upstream(is_join, recv_ifp, upstream, sg, - source_flags, holdtime); - - return 1; /* non-local */ + struct pim_interface *recv_pim_ifp; + int is_local; /* boolean */ + + recv_pim_ifp = recv_ifp->info; + zassert(recv_pim_ifp); + + is_local = (upstream.s_addr == recv_pim_ifp->primary_address.s_addr); + + if (is_local) + return 0; + + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + char up_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); + zlog_warn("%s: recv %s (S,G)=%s to non-local upstream=%s on %s", + __PRETTY_FUNCTION__, is_join ? "join" : "prune", + pim_str_sg_dump(sg), up_str, recv_ifp->name); + } + + /* + * Since recv upstream addr was not directed to our primary + * address, check if we should react to it in any way. + */ + check_recv_upstream(is_join, recv_ifp, upstream, sg, source_flags, + holdtime); + + return 1; /* non-local */ } -void pim_ifchannel_join_add(struct interface *ifp, - struct in_addr neigh_addr, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, - uint16_t holdtime) +void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, + struct in_addr upstream, struct prefix_sg *sg, + uint8_t source_flags, uint16_t holdtime) { - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - - if (nonlocal_upstream(1 /* join */, ifp, upstream, - sg, source_flags, holdtime)) { - return; - } - - ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); - if (!ch) - return; - - /* - RFC 4601: 4.6.1. (S,G) Assert Message State Machine - - Transitions from "I am Assert Loser" State - - Receive Join(S,G) on Interface I - - We receive a Join(S,G) that has the Upstream Neighbor Address - field set to my primary IP address on interface I. The action is - to transition to NoInfo state, delete this (S,G) assert state - (Actions A5 below), and allow the normal PIM Join/Prune mechanisms - to operate. - - Notice: The nonlocal_upstream() test above ensures the upstream - address of the join message is our primary address. - */ - if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { - char neigh_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<neigh?>", neigh_addr, neigh_str, sizeof(neigh_str)); - zlog_warn("%s: Assert Loser recv Join%s from %s on %s", - __PRETTY_FUNCTION__, - ch->sg_str, neigh_str, ifp->name); - - assert_action_a5(ch); - } - - pim_ifp = ifp->info; - zassert(pim_ifp); - - switch (ch->ifjoin_state) { - case PIM_IFJOIN_NOINFO: - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); - if (pim_macro_chisin_oiflist(ch)) { - pim_upstream_inherited_olist (ch->upstream); - pim_forward_start(ch); - } - /* - * If we are going to be a LHR, we need to note it - */ - if (ch->upstream->parent && - (ch->upstream->parent->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) && - !(ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)) - { - pim_upstream_ref (ch->upstream, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, __PRETTY_FUNCTION__); - pim_upstream_keep_alive_timer_start (ch->upstream, qpim_keep_alive_time); - } - break; - case PIM_IFJOIN_JOIN: - zassert(!ch->t_ifjoin_prune_pending_timer); - - /* - In the JOIN state ch->t_ifjoin_expiry_timer may be NULL due to a - previously received join message with holdtime=0xFFFF. - */ - if (ch->t_ifjoin_expiry_timer) { - unsigned long remain = - thread_timer_remain_second(ch->t_ifjoin_expiry_timer); - if (remain > holdtime) { + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + + if (nonlocal_upstream(1 /* join */, ifp, upstream, sg, source_flags, + holdtime)) { + return; + } + + ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); + if (!ch) + return; + /* - RFC 4601: 4.5.3. Receiving (S,G) Join/Prune Messages + RFC 4601: 4.6.1. (S,G) Assert Message State Machine + + Transitions from "I am Assert Loser" State - Transitions from Join State + Receive Join(S,G) on Interface I - The (S,G) downstream state machine on interface I remains in - Join state, and the Expiry Timer (ET) is restarted, set to - maximum of its current value and the HoldTime from the - triggering Join/Prune message. + We receive a Join(S,G) that has the Upstream Neighbor Address + field set to my primary IP address on interface I. The action is + to transition to NoInfo state, delete this (S,G) assert state + (Actions A5 below), and allow the normal PIM Join/Prune mechanisms + to operate. - Conclusion: Do not change the ET if the current value is - higher than the received join holdtime. + Notice: The nonlocal_upstream() test above ensures the upstream + address of the join message is our primary address. */ - return; - } - } - THREAD_OFF(ch->t_ifjoin_expiry_timer); - break; - case PIM_IFJOIN_PRUNE: - if (source_flags & PIM_ENCODE_RPT_BIT) - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); - break; - case PIM_IFJOIN_PRUNE_PENDING: - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - if (source_flags & PIM_ENCODE_RPT_BIT) - { - THREAD_OFF(ch->t_ifjoin_expiry_timer); - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); - } - else - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); - break; - case PIM_IFJOIN_PRUNE_TMP: - break; - case PIM_IFJOIN_PRUNE_PENDING_TMP: - break; - } - - if (holdtime != 0xFFFF) { - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - } + if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { + char neigh_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<neigh?>", neigh_addr, neigh_str, + sizeof(neigh_str)); + zlog_warn("%s: Assert Loser recv Join%s from %s on %s", + __PRETTY_FUNCTION__, ch->sg_str, neigh_str, + ifp->name); + + assert_action_a5(ch); + } + + pim_ifp = ifp->info; + zassert(pim_ifp); + + switch (ch->ifjoin_state) { + case PIM_IFJOIN_NOINFO: + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_JOIN); + if (pim_macro_chisin_oiflist(ch)) { + pim_upstream_inherited_olist(ch->upstream); + pim_forward_start(ch); + } + /* + * If we are going to be a LHR, we need to note it + */ + if (ch->upstream->parent && (ch->upstream->parent->flags + & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + && !(ch->upstream->flags + & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)) { + pim_upstream_ref(ch->upstream, + PIM_UPSTREAM_FLAG_MASK_SRC_LHR, + __PRETTY_FUNCTION__); + pim_upstream_keep_alive_timer_start( + ch->upstream, qpim_keep_alive_time); + } + break; + case PIM_IFJOIN_JOIN: + zassert(!ch->t_ifjoin_prune_pending_timer); + + /* + In the JOIN state ch->t_ifjoin_expiry_timer may be NULL due to + a + previously received join message with holdtime=0xFFFF. + */ + if (ch->t_ifjoin_expiry_timer) { + unsigned long remain = thread_timer_remain_second( + ch->t_ifjoin_expiry_timer); + if (remain > holdtime) { + /* + RFC 4601: 4.5.3. Receiving (S,G) Join/Prune + Messages + + Transitions from Join State + + The (S,G) downstream state machine on + interface I remains in + Join state, and the Expiry Timer (ET) is + restarted, set to + maximum of its current value and the HoldTime + from the + triggering Join/Prune message. + + Conclusion: Do not change the ET if the + current value is + higher than the received join holdtime. + */ + return; + } + } + THREAD_OFF(ch->t_ifjoin_expiry_timer); + break; + case PIM_IFJOIN_PRUNE: + if (source_flags & PIM_ENCODE_RPT_BIT) + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_NOINFO); + break; + case PIM_IFJOIN_PRUNE_PENDING: + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + if (source_flags & PIM_ENCODE_RPT_BIT) { + THREAD_OFF(ch->t_ifjoin_expiry_timer); + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_NOINFO); + } else + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_JOIN); + break; + case PIM_IFJOIN_PRUNE_TMP: + break; + case PIM_IFJOIN_PRUNE_PENDING_TMP: + break; + } + + if (holdtime != 0xFFFF) { + thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, + &ch->t_ifjoin_expiry_timer); + } } -void pim_ifchannel_prune(struct interface *ifp, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, +void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream, + struct prefix_sg *sg, uint8_t source_flags, uint16_t holdtime) { - struct pim_ifchannel *ch; - struct pim_interface *pim_ifp; - int jp_override_interval_msec; - - if (nonlocal_upstream(0 /* prune */, ifp, upstream, - sg, source_flags, holdtime)) { - return; - } - - ch = pim_ifchannel_find (ifp, sg); - if (!ch && !(source_flags & PIM_ENCODE_RPT_BIT)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Received prune with no relevant ifchannel %s(%s) state: %d", - __PRETTY_FUNCTION__, ifp->name, pim_str_sg_dump (sg), source_flags); - return; - } - - ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); - if (!ch) - return; - - pim_ifp = ifp->info; - - switch (ch->ifjoin_state) { - case PIM_IFJOIN_NOINFO: - if (source_flags & PIM_ENCODE_RPT_BIT) - { - if (!(source_flags & PIM_ENCODE_WC_BIT)) - PIM_IF_FLAG_SET_S_G_RPT(ch->flags); - - ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; - if (listcount(pim_ifp->pim_neighbor_list) > 1) - jp_override_interval_msec = pim_if_jp_override_interval_msec(ifp); - else - jp_override_interval_msec = 0; /* schedule to expire immediately */ - /* If we called ifjoin_prune() directly instead, care should - be taken not to use "ch" afterwards since it would be - deleted. */ + struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + int jp_override_interval_msec; - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - THREAD_OFF(ch->t_ifjoin_expiry_timer); - thread_add_timer_msec(master, on_ifjoin_prune_pending_timer, ch, - jp_override_interval_msec, - &ch->t_ifjoin_prune_pending_timer); - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - pim_upstream_update_join_desired(ch->upstream); - } - break; - case PIM_IFJOIN_PRUNE_PENDING: - /* nothing to do */ - break; - case PIM_IFJOIN_JOIN: - THREAD_OFF(ch->t_ifjoin_expiry_timer); - - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_PRUNE_PENDING); - - if (listcount(pim_ifp->pim_neighbor_list) > 1) - jp_override_interval_msec = pim_if_jp_override_interval_msec(ifp); - else - jp_override_interval_msec = 0; /* schedule to expire immediately */ - /* If we called ifjoin_prune() directly instead, care should - be taken not to use "ch" afterwards since it would be - deleted. */ - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - thread_add_timer_msec(master, on_ifjoin_prune_pending_timer, ch, - jp_override_interval_msec, - &ch->t_ifjoin_prune_pending_timer); - break; - case PIM_IFJOIN_PRUNE: - if (source_flags & PIM_ENCODE_RPT_BIT) - { - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - } - break; - case PIM_IFJOIN_PRUNE_TMP: - if (source_flags & PIM_ENCODE_RPT_BIT) - { - ch->ifjoin_state = PIM_IFJOIN_PRUNE; - THREAD_OFF(ch->t_ifjoin_expiry_timer); - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - } - break; - case PIM_IFJOIN_PRUNE_PENDING_TMP: - if (source_flags & PIM_ENCODE_RPT_BIT) - { - ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; - THREAD_OFF(ch->t_ifjoin_expiry_timer); - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - } - break; - } + if (nonlocal_upstream(0 /* prune */, ifp, upstream, sg, source_flags, + holdtime)) { + return; + } + + ch = pim_ifchannel_find(ifp, sg); + if (!ch && !(source_flags & PIM_ENCODE_RPT_BIT)) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Received prune with no relevant ifchannel %s(%s) state: %d", + __PRETTY_FUNCTION__, ifp->name, + pim_str_sg_dump(sg), source_flags); + return; + } + + ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); + if (!ch) + return; + + pim_ifp = ifp->info; + + switch (ch->ifjoin_state) { + case PIM_IFJOIN_NOINFO: + if (source_flags & PIM_ENCODE_RPT_BIT) { + if (!(source_flags & PIM_ENCODE_WC_BIT)) + PIM_IF_FLAG_SET_S_G_RPT(ch->flags); + + ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; + if (listcount(pim_ifp->pim_neighbor_list) > 1) + jp_override_interval_msec = + pim_if_jp_override_interval_msec(ifp); + else + jp_override_interval_msec = + 0; /* schedule to expire immediately */ + /* If we called ifjoin_prune() directly instead, care + should + be taken not to use "ch" afterwards since it would be + deleted. */ + + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + THREAD_OFF(ch->t_ifjoin_expiry_timer); + thread_add_timer_msec( + master, on_ifjoin_prune_pending_timer, ch, + jp_override_interval_msec, + &ch->t_ifjoin_prune_pending_timer); + thread_add_timer(master, on_ifjoin_expiry_timer, ch, + holdtime, &ch->t_ifjoin_expiry_timer); + pim_upstream_update_join_desired(ch->upstream); + } + break; + case PIM_IFJOIN_PRUNE_PENDING: + /* nothing to do */ + break; + case PIM_IFJOIN_JOIN: + THREAD_OFF(ch->t_ifjoin_expiry_timer); + + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_PRUNE_PENDING); + + if (listcount(pim_ifp->pim_neighbor_list) > 1) + jp_override_interval_msec = + pim_if_jp_override_interval_msec(ifp); + else + jp_override_interval_msec = + 0; /* schedule to expire immediately */ + /* If we called ifjoin_prune() directly instead, care should + be taken not to use "ch" afterwards since it would be + deleted. */ + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + thread_add_timer_msec(master, on_ifjoin_prune_pending_timer, ch, + jp_override_interval_msec, + &ch->t_ifjoin_prune_pending_timer); + break; + case PIM_IFJOIN_PRUNE: + if (source_flags & PIM_ENCODE_RPT_BIT) { + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + thread_add_timer(master, on_ifjoin_expiry_timer, ch, + holdtime, &ch->t_ifjoin_expiry_timer); + } + break; + case PIM_IFJOIN_PRUNE_TMP: + if (source_flags & PIM_ENCODE_RPT_BIT) { + ch->ifjoin_state = PIM_IFJOIN_PRUNE; + THREAD_OFF(ch->t_ifjoin_expiry_timer); + thread_add_timer(master, on_ifjoin_expiry_timer, ch, + holdtime, &ch->t_ifjoin_expiry_timer); + } + break; + case PIM_IFJOIN_PRUNE_PENDING_TMP: + if (source_flags & PIM_ENCODE_RPT_BIT) { + ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; + THREAD_OFF(ch->t_ifjoin_expiry_timer); + thread_add_timer(master, on_ifjoin_expiry_timer, ch, + holdtime, &ch->t_ifjoin_expiry_timer); + } + break; + } } -int -pim_ifchannel_local_membership_add(struct interface *ifp, - struct prefix_sg *sg) +int pim_ifchannel_local_membership_add(struct interface *ifp, + struct prefix_sg *sg) { - struct pim_ifchannel *ch, *starch; - struct pim_interface *pim_ifp; - - /* PIM enabled on interface? */ - pim_ifp = ifp->info; - if (!pim_ifp) - return 0; - if (!PIM_IF_TEST_PIM(pim_ifp->options)) - return 0; - - /* skip (*,G) ch creation if G is of type SSM */ - if (sg->src.s_addr == INADDR_ANY) - { - if (pim_is_grp_ssm (sg->grp)) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug("%s: local membership (S,G)=%s ignored as group is SSM", - __PRETTY_FUNCTION__, pim_str_sg_dump (sg)); - return 1; - } - } - - ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP); - if (!ch) { - return 0; - } - - ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE); - - if (sg->src.s_addr == INADDR_ANY) - { - struct pim_upstream *up = pim_upstream_find (sg); - struct pim_upstream *child; - struct listnode *up_node; - - starch = ch; - - for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) - { - if (PIM_DEBUG_EVENTS) - zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s", - __FILE__, __PRETTY_FUNCTION__, - child->sg_str, ifp->name, up->sg_str); - - ch = pim_ifchannel_find (ifp, &child->sg); - if (pim_upstream_evaluate_join_desired_interface (child, ch, starch)) - { - pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); - pim_upstream_switch (child, PIM_UPSTREAM_JOINED); - } - } - - if (pimg->spt.switchover == PIM_SPT_INFINITY) - { - if (pimg->spt.plist) - { - struct prefix_list *plist = prefix_list_lookup (AFI_IP, pimg->spt.plist); - struct prefix g; - g.family = AF_INET; - g.prefixlen = IPV4_MAX_PREFIXLEN; - g.u.prefix4 = up->sg.grp; - - if (prefix_list_apply (plist, &g) == PREFIX_DENY) - { - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); - } - } - } - else - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); - } - - return 1; + struct pim_ifchannel *ch, *starch; + struct pim_interface *pim_ifp; + + /* PIM enabled on interface? */ + pim_ifp = ifp->info; + if (!pim_ifp) + return 0; + if (!PIM_IF_TEST_PIM(pim_ifp->options)) + return 0; + + /* skip (*,G) ch creation if G is of type SSM */ + if (sg->src.s_addr == INADDR_ANY) { + if (pim_is_grp_ssm(sg->grp)) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "%s: local membership (S,G)=%s ignored as group is SSM", + __PRETTY_FUNCTION__, + pim_str_sg_dump(sg)); + return 1; + } + } + + ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP); + if (!ch) { + return 0; + } + + ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE); + + if (sg->src.s_addr == INADDR_ANY) { + struct pim_upstream *up = pim_upstream_find(sg); + struct pim_upstream *child; + struct listnode *up_node; + + starch = ch; + + for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, child)) { + if (PIM_DEBUG_EVENTS) + zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s", + __FILE__, __PRETTY_FUNCTION__, + child->sg_str, ifp->name, + up->sg_str); + + ch = pim_ifchannel_find(ifp, &child->sg); + if (pim_upstream_evaluate_join_desired_interface( + child, ch, starch)) { + pim_channel_add_oif(child->channel_oil, ifp, + PIM_OIF_FLAG_PROTO_STAR); + pim_upstream_switch(child, PIM_UPSTREAM_JOINED); + } + } + + if (pimg->spt.switchover == PIM_SPT_INFINITY) { + if (pimg->spt.plist) { + struct prefix_list *plist = prefix_list_lookup( + AFI_IP, pimg->spt.plist); + struct prefix g; + g.family = AF_INET; + g.prefixlen = IPV4_MAX_PREFIXLEN; + g.u.prefix4 = up->sg.grp; + + if (prefix_list_apply(plist, &g) + == PREFIX_DENY) { + pim_channel_add_oif( + up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_IGMP); + } + } + } else + pim_channel_add_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_IGMP); + } + + return 1; } void pim_ifchannel_local_membership_del(struct interface *ifp, struct prefix_sg *sg) { - struct pim_ifchannel *starch, *ch, *orig; - struct pim_interface *pim_ifp; - - /* PIM enabled on interface? */ - pim_ifp = ifp->info; - if (!pim_ifp) - return; - if (!PIM_IF_TEST_PIM(pim_ifp->options)) - return; - - orig = ch = pim_ifchannel_find(ifp, sg); - if (!ch) - return; - - ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); - - if (sg->src.s_addr == INADDR_ANY) - { - struct pim_upstream *up = pim_upstream_find (sg); - struct pim_upstream *child; - struct listnode *up_node, *up_nnode; - - starch = ch; - - for (ALL_LIST_ELEMENTS (up->sources, up_node, up_nnode, child)) - { - struct channel_oil *c_oil = child->channel_oil; - struct pim_ifchannel *chchannel = pim_ifchannel_find (ifp, &child->sg); - struct pim_interface *pim_ifp = ifp->info; - - if (PIM_DEBUG_EVENTS) - zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str, ifp->name, child->sg_str); - - ch = pim_ifchannel_find (ifp, &child->sg); - if (c_oil && !pim_upstream_evaluate_join_desired_interface (child, ch, starch)) - pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); - - /* - * If the S,G has no if channel and the c_oil still - * has output here then the *,G was supplying the implied - * if channel. So remove it. - */ - if (!chchannel && c_oil && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) - pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); - - /* Child node removal/ref count-- will happen as part of parent' delete_no_info */ - } - } - delete_on_noinfo(orig); + struct pim_ifchannel *starch, *ch, *orig; + struct pim_interface *pim_ifp; + + /* PIM enabled on interface? */ + pim_ifp = ifp->info; + if (!pim_ifp) + return; + if (!PIM_IF_TEST_PIM(pim_ifp->options)) + return; + + orig = ch = pim_ifchannel_find(ifp, sg); + if (!ch) + return; + + ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); + + if (sg->src.s_addr == INADDR_ANY) { + struct pim_upstream *up = pim_upstream_find(sg); + struct pim_upstream *child; + struct listnode *up_node, *up_nnode; + + starch = ch; + + for (ALL_LIST_ELEMENTS(up->sources, up_node, up_nnode, child)) { + struct channel_oil *c_oil = child->channel_oil; + struct pim_ifchannel *chchannel = + pim_ifchannel_find(ifp, &child->sg); + struct pim_interface *pim_ifp = ifp->info; + + if (PIM_DEBUG_EVENTS) + zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s", + __FILE__, __PRETTY_FUNCTION__, + up->sg_str, ifp->name, + child->sg_str); + + ch = pim_ifchannel_find(ifp, &child->sg); + if (c_oil + && !pim_upstream_evaluate_join_desired_interface( + child, ch, starch)) + pim_channel_del_oif(c_oil, ifp, + PIM_OIF_FLAG_PROTO_STAR); + + /* + * If the S,G has no if channel and the c_oil still + * has output here then the *,G was supplying the + * implied + * if channel. So remove it. + */ + if (!chchannel && c_oil + && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) + pim_channel_del_oif(c_oil, ifp, + PIM_OIF_FLAG_PROTO_STAR); + + /* Child node removal/ref count-- will happen as part of + * parent' delete_no_info */ + } + } + delete_on_noinfo(orig); } void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch) { - int old_couldassert = PIM_FORCE_BOOLEAN(PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)); - int new_couldassert = PIM_FORCE_BOOLEAN(pim_macro_ch_could_assert_eval(ch)); - - if (new_couldassert == old_couldassert) - return; - - if (PIM_DEBUG_PIM_EVENTS) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); - zlog_debug("%s: CouldAssert(%s,%s,%s) changed from %d to %d", - __PRETTY_FUNCTION__, - src_str, grp_str, ch->interface->name, - old_couldassert, new_couldassert); - } - - if (new_couldassert) { - /* CouldAssert(S,G,I) switched from FALSE to TRUE */ - PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); - } - else { - /* CouldAssert(S,G,I) switched from TRUE to FALSE */ - PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); - - if (ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER) { - assert_action_a4(ch); - } - } - - pim_ifchannel_update_my_assert_metric(ch); + int old_couldassert = + PIM_FORCE_BOOLEAN(PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)); + int new_couldassert = + PIM_FORCE_BOOLEAN(pim_macro_ch_could_assert_eval(ch)); + + if (new_couldassert == old_couldassert) + return; + + if (PIM_DEBUG_PIM_EVENTS) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); + zlog_debug("%s: CouldAssert(%s,%s,%s) changed from %d to %d", + __PRETTY_FUNCTION__, src_str, grp_str, + ch->interface->name, old_couldassert, + new_couldassert); + } + + if (new_couldassert) { + /* CouldAssert(S,G,I) switched from FALSE to TRUE */ + PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); + } else { + /* CouldAssert(S,G,I) switched from TRUE to FALSE */ + PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); + + if (ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER) { + assert_action_a4(ch); + } + } + + pim_ifchannel_update_my_assert_metric(ch); } /* @@ -1165,72 +1182,75 @@ void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch) */ void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch) { - struct pim_assert_metric my_metric_new = pim_macro_ch_my_assert_metric_eval(ch); - - if (pim_assert_metric_match(&my_metric_new, &ch->ifassert_my_metric)) - return; - - if (PIM_DEBUG_PIM_EVENTS) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - char old_addr_str[INET_ADDRSTRLEN]; - char new_addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); - pim_inet4_dump("<old_addr?>", ch->ifassert_my_metric.ip_address, old_addr_str, sizeof(old_addr_str)); - pim_inet4_dump("<new_addr?>", my_metric_new.ip_address, new_addr_str, sizeof(new_addr_str)); - zlog_debug("%s: my_assert_metric(%s,%s,%s) changed from %u,%u,%u,%s to %u,%u,%u,%s", - __PRETTY_FUNCTION__, - src_str, grp_str, ch->interface->name, - ch->ifassert_my_metric.rpt_bit_flag, - ch->ifassert_my_metric.metric_preference, - ch->ifassert_my_metric.route_metric, - old_addr_str, - my_metric_new.rpt_bit_flag, - my_metric_new.metric_preference, - my_metric_new.route_metric, - new_addr_str); - } - - ch->ifassert_my_metric = my_metric_new; - - if (pim_assert_metric_better(&ch->ifassert_my_metric, - &ch->ifassert_winner_metric)) { - assert_action_a5(ch); - } + struct pim_assert_metric my_metric_new = + pim_macro_ch_my_assert_metric_eval(ch); + + if (pim_assert_metric_match(&my_metric_new, &ch->ifassert_my_metric)) + return; + + if (PIM_DEBUG_PIM_EVENTS) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char old_addr_str[INET_ADDRSTRLEN]; + char new_addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); + pim_inet4_dump("<old_addr?>", ch->ifassert_my_metric.ip_address, + old_addr_str, sizeof(old_addr_str)); + pim_inet4_dump("<new_addr?>", my_metric_new.ip_address, + new_addr_str, sizeof(new_addr_str)); + zlog_debug( + "%s: my_assert_metric(%s,%s,%s) changed from %u,%u,%u,%s to %u,%u,%u,%s", + __PRETTY_FUNCTION__, src_str, grp_str, + ch->interface->name, + ch->ifassert_my_metric.rpt_bit_flag, + ch->ifassert_my_metric.metric_preference, + ch->ifassert_my_metric.route_metric, old_addr_str, + my_metric_new.rpt_bit_flag, + my_metric_new.metric_preference, + my_metric_new.route_metric, new_addr_str); + } + + ch->ifassert_my_metric = my_metric_new; + + if (pim_assert_metric_better(&ch->ifassert_my_metric, + &ch->ifassert_winner_metric)) { + assert_action_a5(ch); + } } void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch) { - int old_atd = PIM_FORCE_BOOLEAN(PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags)); - int new_atd = PIM_FORCE_BOOLEAN(pim_macro_assert_tracking_desired_eval(ch)); - - if (new_atd == old_atd) - return; - - if (PIM_DEBUG_PIM_EVENTS) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); - zlog_debug("%s: AssertTrackingDesired(%s,%s,%s) changed from %d to %d", - __PRETTY_FUNCTION__, - src_str, grp_str, ch->interface->name, - old_atd, new_atd); - } - - if (new_atd) { - /* AssertTrackingDesired(S,G,I) switched from FALSE to TRUE */ - PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); - } - else { - /* AssertTrackingDesired(S,G,I) switched from TRUE to FALSE */ - PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); - - if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { - assert_action_a5(ch); - } - } + int old_atd = PIM_FORCE_BOOLEAN( + PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags)); + int new_atd = + PIM_FORCE_BOOLEAN(pim_macro_assert_tracking_desired_eval(ch)); + + if (new_atd == old_atd) + return; + + if (PIM_DEBUG_PIM_EVENTS) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); + zlog_debug( + "%s: AssertTrackingDesired(%s,%s,%s) changed from %d to %d", + __PRETTY_FUNCTION__, src_str, grp_str, + ch->interface->name, old_atd, new_atd); + } + + if (new_atd) { + /* AssertTrackingDesired(S,G,I) switched from FALSE to TRUE */ + PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); + } else { + /* AssertTrackingDesired(S,G,I) switched from TRUE to FALSE */ + PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); + + if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { + assert_action_a5(ch); + } + } } /* @@ -1239,36 +1259,34 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch) * their upstream out that way and turn on forwarding * for that ifchannel then. */ -void -pim_ifchannel_scan_forward_start (struct interface *new_ifp) +void pim_ifchannel_scan_forward_start(struct interface *new_ifp) { - struct listnode *ifnode; - struct interface *ifp; - struct pim_interface *new_pim_ifp = new_ifp->info; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) - { - struct pim_interface *loop_pim_ifp = ifp->info; - struct listnode *ch_node; - struct pim_ifchannel *ch; - - if (!loop_pim_ifp) - continue; - - if (new_pim_ifp == loop_pim_ifp) - continue; - - for (ALL_LIST_ELEMENTS_RO (loop_pim_ifp->pim_ifchannel_list, ch_node, ch)) - { - if (ch->ifjoin_state == PIM_IFJOIN_JOIN) - { - struct pim_upstream *up = ch->upstream; - if ((!up->channel_oil) && - (up->rpf.source_nexthop.interface == new_ifp)) - pim_forward_start (ch); - } - } - } + struct listnode *ifnode; + struct interface *ifp; + struct pim_interface *new_pim_ifp = new_ifp->info; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + struct pim_interface *loop_pim_ifp = ifp->info; + struct listnode *ch_node; + struct pim_ifchannel *ch; + + if (!loop_pim_ifp) + continue; + + if (new_pim_ifp == loop_pim_ifp) + continue; + + for (ALL_LIST_ELEMENTS_RO(loop_pim_ifp->pim_ifchannel_list, + ch_node, ch)) { + if (ch->ifjoin_state == PIM_IFJOIN_JOIN) { + struct pim_upstream *up = ch->upstream; + if ((!up->channel_oil) + && (up->rpf.source_nexthop + .interface == new_ifp)) + pim_forward_start(ch); + } + } + } } /* @@ -1278,87 +1296,89 @@ pim_ifchannel_scan_forward_start (struct interface *new_ifp) * reception of a *,G join as well, when * we get End of Message */ -void -pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join, uint8_t starg_alone) +void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, + uint8_t source_flags, uint8_t join, + uint8_t starg_alone) { - struct pim_ifchannel *child; - struct listnode *ch_node; - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: %s %s eom: %d join %u", __PRETTY_FUNCTION__, - pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), - ch->sg_str, eom, join); - if (!ch->sources) - return; - - for (ALL_LIST_ELEMENTS_RO (ch->sources, ch_node, child)) - { - /* Only *,G Join received and no (SG-RPT) prune. - eom = 1, only (W,G) join_alone is true, WC and RPT are set. - Scan all S,G associated to G and if any SG-RPT - remove the SG-RPT flag. - */ - if (eom && starg_alone && (source_flags & PIM_RPT_BIT_MASK) && - (source_flags & PIM_WILDCARD_BIT_MASK)) - { - if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) - { - struct pim_upstream *up = child->upstream; - - PIM_IF_FLAG_UNSET_S_G_RPT(child->flags); - if (up) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: SGRpt flag is cleared, add inherit oif to up %s", - __PRETTY_FUNCTION__, up->sg_str); - pim_channel_add_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, child, PIM_IFJOIN_JOIN); - } - } - } - - if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) - continue; - - switch (child->ifjoin_state) - { - case PIM_IFJOIN_NOINFO: - case PIM_IFJOIN_JOIN: - break; - case PIM_IFJOIN_PRUNE: - if (!eom) - child->ifjoin_state = PIM_IFJOIN_PRUNE_TMP; - break; - case PIM_IFJOIN_PRUNE_PENDING: - if (!eom) - child->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING_TMP; - break; - case PIM_IFJOIN_PRUNE_TMP: - case PIM_IFJOIN_PRUNE_PENDING_TMP: - if (eom) - child->ifjoin_state = PIM_IFJOIN_NOINFO; - break; + struct pim_ifchannel *child; + struct listnode *ch_node; + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s: %s %s eom: %d join %u", __PRETTY_FUNCTION__, + pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), + ch->sg_str, eom, join); + if (!ch->sources) + return; + + for (ALL_LIST_ELEMENTS_RO(ch->sources, ch_node, child)) { + /* Only *,G Join received and no (SG-RPT) prune. + eom = 1, only (W,G) join_alone is true, WC and RPT are set. + Scan all S,G associated to G and if any SG-RPT + remove the SG-RPT flag. + */ + if (eom && starg_alone && (source_flags & PIM_RPT_BIT_MASK) + && (source_flags & PIM_WILDCARD_BIT_MASK)) { + if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) { + struct pim_upstream *up = child->upstream; + + PIM_IF_FLAG_UNSET_S_G_RPT(child->flags); + if (up) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: SGRpt flag is cleared, add inherit oif to up %s", + __PRETTY_FUNCTION__, + up->sg_str); + pim_channel_add_oif( + up->channel_oil, ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + pim_ifchannel_ifjoin_switch( + __PRETTY_FUNCTION__, child, + PIM_IFJOIN_JOIN); + } + } + } + + if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) + continue; + + switch (child->ifjoin_state) { + case PIM_IFJOIN_NOINFO: + case PIM_IFJOIN_JOIN: + break; + case PIM_IFJOIN_PRUNE: + if (!eom) + child->ifjoin_state = PIM_IFJOIN_PRUNE_TMP; + break; + case PIM_IFJOIN_PRUNE_PENDING: + if (!eom) + child->ifjoin_state = + PIM_IFJOIN_PRUNE_PENDING_TMP; + break; + case PIM_IFJOIN_PRUNE_TMP: + case PIM_IFJOIN_PRUNE_PENDING_TMP: + if (eom) + child->ifjoin_state = PIM_IFJOIN_NOINFO; + break; + } } - } } -unsigned int -pim_ifchannel_hash_key (void *arg) +unsigned int pim_ifchannel_hash_key(void *arg) { - struct pim_ifchannel *ch = (struct pim_ifchannel *)arg; + struct pim_ifchannel *ch = (struct pim_ifchannel *)arg; - return jhash_2words (ch->sg.src.s_addr, ch->sg.grp.s_addr, 0); + return jhash_2words(ch->sg.src.s_addr, ch->sg.grp.s_addr, 0); } -int -pim_ifchannel_equal (const void *arg1, const void *arg2) +int pim_ifchannel_equal(const void *arg1, const void *arg2) { - const struct pim_ifchannel *ch1 = (const struct pim_ifchannel *)arg1; - const struct pim_ifchannel *ch2 = (const struct pim_ifchannel *)arg2; + const struct pim_ifchannel *ch1 = (const struct pim_ifchannel *)arg1; + const struct pim_ifchannel *ch2 = (const struct pim_ifchannel *)arg2; - if ((ch1->sg.grp.s_addr == ch2->sg.grp.s_addr) && - (ch1->sg.src.s_addr == ch2->sg.src.s_addr)) - return 1; + if ((ch1->sg.grp.s_addr == ch2->sg.grp.s_addr) + && (ch1->sg.src.s_addr == ch2->sg.src.s_addr)) + return 1; - return 0; + return 0; } diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 455493a5b..2260fd451 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -28,31 +28,29 @@ struct pim_ifchannel; #include "pim_upstream.h" -enum pim_ifmembership { - PIM_IFMEMBERSHIP_NOINFO, - PIM_IFMEMBERSHIP_INCLUDE -}; +enum pim_ifmembership { PIM_IFMEMBERSHIP_NOINFO, PIM_IFMEMBERSHIP_INCLUDE }; enum pim_ifjoin_state { - PIM_IFJOIN_NOINFO, - PIM_IFJOIN_JOIN, - PIM_IFJOIN_PRUNE, - PIM_IFJOIN_PRUNE_PENDING, - PIM_IFJOIN_PRUNE_TMP, - PIM_IFJOIN_PRUNE_PENDING_TMP, + PIM_IFJOIN_NOINFO, + PIM_IFJOIN_JOIN, + PIM_IFJOIN_PRUNE, + PIM_IFJOIN_PRUNE_PENDING, + PIM_IFJOIN_PRUNE_TMP, + PIM_IFJOIN_PRUNE_PENDING_TMP, }; enum pim_ifassert_state { - PIM_IFASSERT_NOINFO, - PIM_IFASSERT_I_AM_WINNER, - PIM_IFASSERT_I_AM_LOSER + PIM_IFASSERT_NOINFO, + PIM_IFASSERT_I_AM_WINNER, + PIM_IFASSERT_I_AM_LOSER }; struct pim_assert_metric { - uint32_t rpt_bit_flag; - uint32_t metric_preference; - uint32_t route_metric; - struct in_addr ip_address; /* neighbor router that sourced the Assert message */ + uint32_t rpt_bit_flag; + uint32_t metric_preference; + uint32_t route_metric; + struct in_addr ip_address; /* neighbor router that sourced the Assert + message */ }; /* @@ -82,63 +80,58 @@ struct pim_assert_metric { Per-interface (S,G) state */ struct pim_ifchannel { - struct pim_ifchannel *parent; - struct list *sources; - struct prefix_sg sg; - char sg_str[PIM_SG_LEN]; - struct interface *interface; /* backpointer to interface */ - uint32_t flags; - - /* IGMPv3 determined interface has local members for (S,G) ? */ - enum pim_ifmembership local_ifmembership; - - /* Per-interface (S,G) Join/Prune State (Section 4.1.4 of RFC4601) */ - enum pim_ifjoin_state ifjoin_state; - struct thread *t_ifjoin_expiry_timer; - struct thread *t_ifjoin_prune_pending_timer; - int64_t ifjoin_creation; /* Record uptime of ifjoin state */ - - /* Per-interface (S,G) Assert State (Section 4.6.1 of RFC4601) */ - enum pim_ifassert_state ifassert_state; - struct thread *t_ifassert_timer; - struct in_addr ifassert_winner; - struct pim_assert_metric ifassert_winner_metric; - int64_t ifassert_creation; /* Record uptime of ifassert state */ - struct pim_assert_metric ifassert_my_metric; - - /* Upstream (S,G) state */ - struct pim_upstream *upstream; + struct pim_ifchannel *parent; + struct list *sources; + struct prefix_sg sg; + char sg_str[PIM_SG_LEN]; + struct interface *interface; /* backpointer to interface */ + uint32_t flags; + + /* IGMPv3 determined interface has local members for (S,G) ? */ + enum pim_ifmembership local_ifmembership; + + /* Per-interface (S,G) Join/Prune State (Section 4.1.4 of RFC4601) */ + enum pim_ifjoin_state ifjoin_state; + struct thread *t_ifjoin_expiry_timer; + struct thread *t_ifjoin_prune_pending_timer; + int64_t ifjoin_creation; /* Record uptime of ifjoin state */ + + /* Per-interface (S,G) Assert State (Section 4.6.1 of RFC4601) */ + enum pim_ifassert_state ifassert_state; + struct thread *t_ifassert_timer; + struct in_addr ifassert_winner; + struct pim_assert_metric ifassert_winner_metric; + int64_t ifassert_creation; /* Record uptime of ifassert state */ + struct pim_assert_metric ifassert_my_metric; + + /* Upstream (S,G) state */ + struct pim_upstream *upstream; }; void pim_ifchannel_free(struct pim_ifchannel *ch); void pim_ifchannel_delete(struct pim_ifchannel *ch); -void pim_ifchannel_delete_all (struct interface *ifp); +void pim_ifchannel_delete_all(struct interface *ifp); void pim_ifchannel_membership_clear(struct interface *ifp); void pim_ifchannel_delete_on_noinfo(struct interface *ifp); struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, struct prefix_sg *sg); struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, struct prefix_sg *sg, int flags); -void pim_ifchannel_join_add(struct interface *ifp, - struct in_addr neigh_addr, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, - uint16_t holdtime); -void pim_ifchannel_prune(struct interface *ifp, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, +void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, + struct in_addr upstream, struct prefix_sg *sg, + uint8_t source_flags, uint16_t holdtime); +void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream, + struct prefix_sg *sg, uint8_t source_flags, uint16_t holdtime); int pim_ifchannel_local_membership_add(struct interface *ifp, struct prefix_sg *sg); void pim_ifchannel_local_membership_del(struct interface *ifp, struct prefix_sg *sg); -void pim_ifchannel_ifjoin_switch(const char *caller, - struct pim_ifchannel *ch, +void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch, enum pim_ifjoin_state new_state); -const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, int flags); +const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, + int flags); const char *pim_ifchannel_ifassert_name(enum pim_ifassert_state ifassert_state); int pim_ifchannel_isin_oiflist(struct pim_ifchannel *ch); @@ -149,11 +142,13 @@ void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch); void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch); void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch); -void pim_ifchannel_scan_forward_start (struct interface *new_ifp); -void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join, uint8_t starg_alone); +void pim_ifchannel_scan_forward_start(struct interface *new_ifp); +void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, + uint8_t source_flags, uint8_t join, + uint8_t starg_alone); -int pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2); +int pim_ifchannel_compare(struct pim_ifchannel *ch1, struct pim_ifchannel *ch2); -unsigned int pim_ifchannel_hash_key (void *arg); -int pim_ifchannel_equal (const void *arg1, const void *arg2); +unsigned int pim_ifchannel_hash_key(void *arg); +int pim_ifchannel_equal(const void *arg1, const void *arg2); #endif /* PIM_IFCHANNEL_H */ diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index ae5f365b8..c693f30ac 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -43,62 +43,66 @@ static int pim_igmp_general_query(struct thread *t); /* This socket is used for TXing IGMP packets only, IGMP RX happens * in pim_mroute_msg() */ -static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp, uint32_t pim_options) +static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp, + uint32_t pim_options) { - int fd; - int join = 0; - struct in_addr group; - - fd = pim_socket_mcast(IPPROTO_IGMP, ifaddr, ifp, 1); - - if (fd < 0) - return -1; - - if (PIM_IF_TEST_IGMP_LISTEN_ALLROUTERS(pim_options)) { - if (inet_aton(PIM_ALL_ROUTERS, &group)) { - if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) - ++join; - } - else { - zlog_warn("%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), - PIM_ALL_ROUTERS, errno, safe_strerror(errno)); - } - } - - /* - IGMP routers periodically send IGMP general queries to AllSystems=224.0.0.1 - IGMP routers must receive general queries for querier election. - */ - if (inet_aton(PIM_ALL_SYSTEMS, &group)) { - if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) - ++join; - } - else { - zlog_warn("%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), - PIM_ALL_SYSTEMS, errno, safe_strerror(errno)); - } - - if (inet_aton(PIM_ALL_IGMP_ROUTERS, &group)) { - if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) { - ++join; - } - } - else { - zlog_warn("%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), - PIM_ALL_IGMP_ROUTERS, errno, safe_strerror(errno)); - } - - if (!join) { - zlog_err("IGMP socket fd=%d could not join any group on interface address %s", - fd, inet_ntoa(ifaddr)); - close(fd); - fd = -1; - } - - return fd; + int fd; + int join = 0; + struct in_addr group; + + fd = pim_socket_mcast(IPPROTO_IGMP, ifaddr, ifp, 1); + + if (fd < 0) + return -1; + + if (PIM_IF_TEST_IGMP_LISTEN_ALLROUTERS(pim_options)) { + if (inet_aton(PIM_ALL_ROUTERS, &group)) { + if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) + ++join; + } else { + zlog_warn( + "%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, fd, + inet_ntoa(ifaddr), PIM_ALL_ROUTERS, errno, + safe_strerror(errno)); + } + } + + /* + IGMP routers periodically send IGMP general queries to + AllSystems=224.0.0.1 + IGMP routers must receive general queries for querier election. + */ + if (inet_aton(PIM_ALL_SYSTEMS, &group)) { + if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) + ++join; + } else { + zlog_warn( + "%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), + PIM_ALL_SYSTEMS, errno, safe_strerror(errno)); + } + + if (inet_aton(PIM_ALL_IGMP_ROUTERS, &group)) { + if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) { + ++join; + } + } else { + zlog_warn( + "%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), + PIM_ALL_IGMP_ROUTERS, errno, safe_strerror(errno)); + } + + if (!join) { + zlog_err( + "IGMP socket fd=%d could not join any group on interface address %s", + fd, inet_ntoa(ifaddr)); + close(fd); + fd = -1; + } + + return fd; } #undef IGMP_SOCK_DUMP @@ -106,828 +110,834 @@ static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp, uint32_t #ifdef IGMP_SOCK_DUMP static void igmp_sock_dump(array_t *igmp_sock_array) { - int size = array_size(igmp_sock_array); - for (int i = 0; i < size; ++i) { - - struct igmp_sock *igmp = array_get(igmp_sock_array, i); - - zlog_debug("%s %s: [%d/%d] igmp_addr=%s fd=%d", - __FILE__, __PRETTY_FUNCTION__, - i, size, - inet_ntoa(igmp->ifaddr), - igmp->fd); - } + int size = array_size(igmp_sock_array); + for (int i = 0; i < size; ++i) { + + struct igmp_sock *igmp = array_get(igmp_sock_array, i); + + zlog_debug("%s %s: [%d/%d] igmp_addr=%s fd=%d", __FILE__, + __PRETTY_FUNCTION__, i, size, + inet_ntoa(igmp->ifaddr), igmp->fd); + } } #endif struct igmp_sock *pim_igmp_sock_lookup_ifaddr(struct list *igmp_sock_list, struct in_addr ifaddr) { - struct listnode *sock_node; - struct igmp_sock *igmp; + struct listnode *sock_node; + struct igmp_sock *igmp; #ifdef IGMP_SOCK_DUMP - igmp_sock_dump(igmp_sock_list); + igmp_sock_dump(igmp_sock_list); #endif - for (ALL_LIST_ELEMENTS_RO(igmp_sock_list, sock_node, igmp)) - if (ifaddr.s_addr == igmp->ifaddr.s_addr) - return igmp; + for (ALL_LIST_ELEMENTS_RO(igmp_sock_list, sock_node, igmp)) + if (ifaddr.s_addr == igmp->ifaddr.s_addr) + return igmp; - return 0; + return 0; } -struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, - int fd) +struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, int fd) { - struct listnode *sock_node; - struct igmp_sock *igmp; + struct listnode *sock_node; + struct igmp_sock *igmp; - for (ALL_LIST_ELEMENTS_RO(igmp_sock_list, sock_node, igmp)) - if (fd == igmp->fd) - return igmp; + for (ALL_LIST_ELEMENTS_RO(igmp_sock_list, sock_node, igmp)) + if (fd == igmp->fd) + return igmp; - return 0; + return 0; } static int pim_igmp_other_querier_expire(struct thread *t) { - struct igmp_sock *igmp; - - igmp = THREAD_ARG(t); - - zassert(!igmp->t_igmp_query_timer); - - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("%s: Querier %s resuming", - __PRETTY_FUNCTION__, - ifaddr_str); - } - - /* - We are the current querier, then - re-start sending general queries. - RFC 2236 - sec 7 Other Querier - present timer expired (Send General - Query, Set Gen. Query. timer) - */ - pim_igmp_general_query(t); - - return 0; + struct igmp_sock *igmp; + + igmp = THREAD_ARG(t); + + zassert(!igmp->t_igmp_query_timer); + + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug("%s: Querier %s resuming", __PRETTY_FUNCTION__, + ifaddr_str); + } + + /* + We are the current querier, then + re-start sending general queries. + RFC 2236 - sec 7 Other Querier + present timer expired (Send General + Query, Set Gen. Query. timer) + */ + pim_igmp_general_query(t); + + return 0; } void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp) { - long other_querier_present_interval_msec; - struct pim_interface *pim_ifp; - - zassert(igmp); - zassert(igmp->interface); - zassert(igmp->interface->info); - - pim_ifp = igmp->interface->info; - - if (igmp->t_other_querier_timer) { - /* - There is other querier present already, - then reset the other-querier-present timer. - */ - - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("Querier %s resetting TIMER event for Other-Querier-Present", - ifaddr_str); - } - THREAD_OFF(igmp->t_other_querier_timer); - } - else { - /* - We are the current querier, then stop sending general queries: - igmp->t_igmp_query_timer = NULL; - */ - pim_igmp_general_query_off(igmp); - } - - /* - Since this socket is starting the other-querier-present timer, - there should not be periodic query timer for this socket. - */ - zassert(!igmp->t_igmp_query_timer); - - /* - RFC 3376: 8.5. Other Querier Present Interval - - The Other Querier Present Interval is the length of time that must - pass before a multicast router decides that there is no longer - another multicast router which should be the querier. This value - MUST be ((the Robustness Variable) times (the Query Interval)) plus - (one half of one Query Response Interval). - - other_querier_present_interval_msec = \ - igmp->querier_robustness_variable * \ - 1000 * igmp->querier_query_interval + \ - 100 * (pim_ifp->query_max_response_time_dsec >> 1); - */ - other_querier_present_interval_msec = - PIM_IGMP_OQPI_MSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec); - - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("Querier %s scheduling %ld.%03ld sec TIMER event for Other-Querier-Present", - ifaddr_str, - other_querier_present_interval_msec / 1000, - other_querier_present_interval_msec % 1000); - } - - thread_add_timer_msec(master, pim_igmp_other_querier_expire, igmp, - other_querier_present_interval_msec, - &igmp->t_other_querier_timer); + long other_querier_present_interval_msec; + struct pim_interface *pim_ifp; + + zassert(igmp); + zassert(igmp->interface); + zassert(igmp->interface->info); + + pim_ifp = igmp->interface->info; + + if (igmp->t_other_querier_timer) { + /* + There is other querier present already, + then reset the other-querier-present timer. + */ + + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug( + "Querier %s resetting TIMER event for Other-Querier-Present", + ifaddr_str); + } + THREAD_OFF(igmp->t_other_querier_timer); + } else { + /* + We are the current querier, then stop sending general queries: + igmp->t_igmp_query_timer = NULL; + */ + pim_igmp_general_query_off(igmp); + } + + /* + Since this socket is starting the other-querier-present timer, + there should not be periodic query timer for this socket. + */ + zassert(!igmp->t_igmp_query_timer); + + /* + RFC 3376: 8.5. Other Querier Present Interval + + The Other Querier Present Interval is the length of time that must + pass before a multicast router decides that there is no longer + another multicast router which should be the querier. This value + MUST be ((the Robustness Variable) times (the Query Interval)) plus + (one half of one Query Response Interval). + + other_querier_present_interval_msec = \ + igmp->querier_robustness_variable * \ + 1000 * igmp->querier_query_interval + \ + 100 * (pim_ifp->query_max_response_time_dsec >> 1); + */ + other_querier_present_interval_msec = PIM_IGMP_OQPI_MSEC( + igmp->querier_robustness_variable, igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec); + + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug( + "Querier %s scheduling %ld.%03ld sec TIMER event for Other-Querier-Present", + ifaddr_str, other_querier_present_interval_msec / 1000, + other_querier_present_interval_msec % 1000); + } + + thread_add_timer_msec(master, pim_igmp_other_querier_expire, igmp, + other_querier_present_interval_msec, + &igmp->t_other_querier_timer); } void pim_igmp_other_querier_timer_off(struct igmp_sock *igmp) { - zassert(igmp); - - if (PIM_DEBUG_IGMP_TRACE) { - if (igmp->t_other_querier_timer) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("IGMP querier %s fd=%d cancelling other-querier-present TIMER event on %s", - ifaddr_str, igmp->fd, igmp->interface->name); - } - } - THREAD_OFF(igmp->t_other_querier_timer); + zassert(igmp); + + if (PIM_DEBUG_IGMP_TRACE) { + if (igmp->t_other_querier_timer) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug( + "IGMP querier %s fd=%d cancelling other-querier-present TIMER event on %s", + ifaddr_str, igmp->fd, igmp->interface->name); + } + } + THREAD_OFF(igmp->t_other_querier_timer); } -static int -igmp_recv_query(struct igmp_sock *igmp, int query_version, - int max_resp_code, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) +static int igmp_recv_query(struct igmp_sock *igmp, int query_version, + int max_resp_code, struct in_addr from, + const char *from_str, char *igmp_msg, + int igmp_msg_len) { - struct interface *ifp; - struct pim_interface *pim_ifp; - struct in_addr group_addr; - uint16_t recv_checksum; - uint16_t checksum; - - memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - - ifp = igmp->interface; - pim_ifp = ifp->info; - - recv_checksum = *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET); - - /* for computing checksum */ - *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; - - checksum = in_cksum(igmp_msg, igmp_msg_len); - if (checksum != recv_checksum) { - zlog_warn("Recv IGMP query v%d from %s on %s: checksum mismatch: received=%x computed=%x", - query_version, from_str, ifp->name, recv_checksum, checksum); - return -1; - } - - /* RFC 3376 defines some guidelines on operating in backwards compatibility - * with older versions of IGMP but there are some gaps in the logic: - * - * - once we drop from say version 3 to version 2 we will never go back to - * version 3 even if the node that TXed an IGMP v2 query upgrades to v3 - * - * - The node with the lowest IP is the querier so we will only know to drop - * from v3 to v2 if the node that is the querier is also the one that is - * running igmp v2. If a non-querier only supports igmp v2 we will have - * no way of knowing. - * - * For now we will simplify things and inform the user that they need to - * configure all PIM routers to use the same version of IGMP. - */ - if (query_version != pim_ifp->igmp_version) { - zlog_warn("Recv IGMP query v%d from %s on %s but we are using v%d, please " - "configure all PIM routers on this subnet to use the same " - "IGMP version", - query_version, from_str, ifp->name, pim_ifp->igmp_version); - return 0; - } - - if (PIM_DEBUG_IGMP_PACKETS) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); - zlog_debug("Recv IGMP query v%d from %s on %s for group %s", - query_version, from_str, ifp->name, group_str); - } - - /* - RFC 3376: 6.6.2. Querier Election - - When a router receives a query with a lower IP address, it sets - the Other-Querier-Present timer to Other Querier Present Interval - and ceases to send queries on the network if it was the previously - elected querier. - */ - if (ntohl(from.s_addr) < ntohl(igmp->ifaddr.s_addr)) { - - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("%s: local address %s (%u) lost querier election to %s (%u)", - ifp->name, - ifaddr_str, ntohl(igmp->ifaddr.s_addr), - from_str, ntohl(from.s_addr)); - } - - pim_igmp_other_querier_timer_on(igmp); - } - - /* IGMP version 3 is the only one where we process the RXed query */ - if (query_version == 3) { - igmp_v3_recv_query(igmp, from_str, igmp_msg); - } - - return 0; + struct interface *ifp; + struct pim_interface *pim_ifp; + struct in_addr group_addr; + uint16_t recv_checksum; + uint16_t checksum; + + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + + ifp = igmp->interface; + pim_ifp = ifp->info; + + recv_checksum = *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET); + + /* for computing checksum */ + *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; + + checksum = in_cksum(igmp_msg, igmp_msg_len); + if (checksum != recv_checksum) { + zlog_warn( + "Recv IGMP query v%d from %s on %s: checksum mismatch: received=%x computed=%x", + query_version, from_str, ifp->name, recv_checksum, + checksum); + return -1; + } + + /* RFC 3376 defines some guidelines on operating in backwards + * compatibility + * with older versions of IGMP but there are some gaps in the logic: + * + * - once we drop from say version 3 to version 2 we will never go back + * to + * version 3 even if the node that TXed an IGMP v2 query upgrades to + * v3 + * + * - The node with the lowest IP is the querier so we will only know to + * drop + * from v3 to v2 if the node that is the querier is also the one that + * is + * running igmp v2. If a non-querier only supports igmp v2 we will + * have + * no way of knowing. + * + * For now we will simplify things and inform the user that they need to + * configure all PIM routers to use the same version of IGMP. + */ + if (query_version != pim_ifp->igmp_version) { + zlog_warn( + "Recv IGMP query v%d from %s on %s but we are using v%d, please " + "configure all PIM routers on this subnet to use the same " + "IGMP version", + query_version, from_str, ifp->name, + pim_ifp->igmp_version); + return 0; + } + + if (PIM_DEBUG_IGMP_PACKETS) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group_addr, group_str, + sizeof(group_str)); + zlog_debug("Recv IGMP query v%d from %s on %s for group %s", + query_version, from_str, ifp->name, group_str); + } + + /* + RFC 3376: 6.6.2. Querier Election + + When a router receives a query with a lower IP address, it sets + the Other-Querier-Present timer to Other Querier Present Interval + and ceases to send queries on the network if it was the previously + elected querier. + */ + if (ntohl(from.s_addr) < ntohl(igmp->ifaddr.s_addr)) { + + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug( + "%s: local address %s (%u) lost querier election to %s (%u)", + ifp->name, ifaddr_str, + ntohl(igmp->ifaddr.s_addr), from_str, + ntohl(from.s_addr)); + } + + pim_igmp_other_querier_timer_on(igmp); + } + + /* IGMP version 3 is the only one where we process the RXed query */ + if (query_version == 3) { + igmp_v3_recv_query(igmp, from_str, igmp_msg); + } + + return 0; } -static void on_trace(const char *label, - struct interface *ifp, struct in_addr from) +static void on_trace(const char *label, struct interface *ifp, + struct in_addr from) { - if (PIM_DEBUG_IGMP_TRACE) { - char from_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<from?>", from, from_str, sizeof(from_str)); - zlog_debug("%s: from %s on %s", - label, from_str, ifp->name); - } + if (PIM_DEBUG_IGMP_TRACE) { + char from_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<from?>", from, from_str, sizeof(from_str)); + zlog_debug("%s: from %s on %s", label, from_str, ifp->name); + } } -static int -igmp_v1_recv_report (struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) +static int igmp_v1_recv_report(struct igmp_sock *igmp, struct in_addr from, + const char *from_str, char *igmp_msg, + int igmp_msg_len) { - struct interface *ifp = igmp->interface; - struct igmp_group *group; - struct in_addr group_addr; + struct interface *ifp = igmp->interface; + struct igmp_group *group; + struct in_addr group_addr; - on_trace(__PRETTY_FUNCTION__, igmp->interface, from); + on_trace(__PRETTY_FUNCTION__, igmp->interface, from); - if (igmp_msg_len != IGMP_V12_MSG_SIZE) { - zlog_warn("Recv IGMP report v1 from %s on %s: size=%d other than correct=%d", - from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); - return -1; - } + if (igmp_msg_len != IGMP_V12_MSG_SIZE) { + zlog_warn( + "Recv IGMP report v1 from %s on %s: size=%d other than correct=%d", + from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); + return -1; + } - if (PIM_DEBUG_IGMP_TRACE) { - zlog_warn("%s %s: FIXME WRITEME", - __FILE__, __PRETTY_FUNCTION__); - } + if (PIM_DEBUG_IGMP_TRACE) { + zlog_warn("%s %s: FIXME WRITEME", __FILE__, + __PRETTY_FUNCTION__); + } - memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return -1; - } + /* non-existant group is created as INCLUDE {empty} */ + group = igmp_add_group_by_addr(igmp, group_addr); + if (!group) { + return -1; + } - group->last_igmp_v1_report_dsec = pim_time_monotonic_dsec(); + group->last_igmp_v1_report_dsec = pim_time_monotonic_dsec(); - return 0; + return 0; } int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len) { - struct ip *ip_hdr; - size_t ip_hlen; /* ip header length in bytes */ - char *igmp_msg; - int igmp_msg_len; - int msg_type; - char from_str[INET_ADDRSTRLEN]; - char to_str[INET_ADDRSTRLEN]; - - if (len < sizeof(*ip_hdr)) { - zlog_warn("IGMP packet size=%zu shorter than minimum=%zu", - len, sizeof(*ip_hdr)); - return -1; - } - - ip_hdr = (struct ip *) buf; - - pim_inet4_dump("<src?>", ip_hdr->ip_src, from_str , sizeof(from_str)); - pim_inet4_dump("<dst?>", ip_hdr->ip_dst, to_str , sizeof(to_str)); - - ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ - - if (PIM_DEBUG_IGMP_PACKETS) { - zlog_debug("Recv IP packet from %s to %s on %s: size=%zu ip_header_size=%zu ip_proto=%d", - from_str, to_str, igmp->interface->name, len, ip_hlen, ip_hdr->ip_p); - } - - igmp_msg = buf + ip_hlen; - msg_type = *igmp_msg; - igmp_msg_len = len - ip_hlen; - - if (PIM_DEBUG_IGMP_PACKETS) { - zlog_debug("Recv IGMP packet from %s to %s on %s: ttl=%d msg_type=%d msg_size=%d", - from_str, to_str, igmp->interface->name, ip_hdr->ip_ttl, msg_type, - igmp_msg_len); - } - - if (igmp_msg_len < PIM_IGMP_MIN_LEN) { - zlog_warn("IGMP message size=%d shorter than minimum=%d", - igmp_msg_len, PIM_IGMP_MIN_LEN); - return -1; - } - - switch (msg_type) { - case PIM_IGMP_MEMBERSHIP_QUERY: - { - int max_resp_code = igmp_msg[1]; - int query_version; - - /* - RFC 3376: 7.1. Query Version Distinctions - IGMPv1 Query: length = 8 octets AND Max Resp Code field is zero - IGMPv2 Query: length = 8 octets AND Max Resp Code field is non-zero - IGMPv3 Query: length >= 12 octets - */ - - if (igmp_msg_len == 8) { - query_version = max_resp_code ? 2 : 1; - } - else if (igmp_msg_len >= 12) { - query_version = 3; - } - else { - zlog_warn("Unknown IGMP query version"); - return -1; - } + struct ip *ip_hdr; + size_t ip_hlen; /* ip header length in bytes */ + char *igmp_msg; + int igmp_msg_len; + int msg_type; + char from_str[INET_ADDRSTRLEN]; + char to_str[INET_ADDRSTRLEN]; + + if (len < sizeof(*ip_hdr)) { + zlog_warn("IGMP packet size=%zu shorter than minimum=%zu", len, + sizeof(*ip_hdr)); + return -1; + } + + ip_hdr = (struct ip *)buf; + + pim_inet4_dump("<src?>", ip_hdr->ip_src, from_str, sizeof(from_str)); + pim_inet4_dump("<dst?>", ip_hdr->ip_dst, to_str, sizeof(to_str)); + + ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ - return igmp_recv_query(igmp, query_version, max_resp_code, - ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); - } + if (PIM_DEBUG_IGMP_PACKETS) { + zlog_debug( + "Recv IP packet from %s to %s on %s: size=%zu ip_header_size=%zu ip_proto=%d", + from_str, to_str, igmp->interface->name, len, ip_hlen, + ip_hdr->ip_p); + } + + igmp_msg = buf + ip_hlen; + msg_type = *igmp_msg; + igmp_msg_len = len - ip_hlen; + + if (PIM_DEBUG_IGMP_PACKETS) { + zlog_debug( + "Recv IGMP packet from %s to %s on %s: ttl=%d msg_type=%d msg_size=%d", + from_str, to_str, igmp->interface->name, ip_hdr->ip_ttl, + msg_type, igmp_msg_len); + } - case PIM_IGMP_V3_MEMBERSHIP_REPORT: - return igmp_v3_recv_report(igmp, ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); + if (igmp_msg_len < PIM_IGMP_MIN_LEN) { + zlog_warn("IGMP message size=%d shorter than minimum=%d", + igmp_msg_len, PIM_IGMP_MIN_LEN); + return -1; + } + + switch (msg_type) { + case PIM_IGMP_MEMBERSHIP_QUERY: { + int max_resp_code = igmp_msg[1]; + int query_version; + + /* + RFC 3376: 7.1. Query Version Distinctions + IGMPv1 Query: length = 8 octets AND Max Resp Code field is + zero + IGMPv2 Query: length = 8 octets AND Max Resp Code field is + non-zero + IGMPv3 Query: length >= 12 octets + */ + + if (igmp_msg_len == 8) { + query_version = max_resp_code ? 2 : 1; + } else if (igmp_msg_len >= 12) { + query_version = 3; + } else { + zlog_warn("Unknown IGMP query version"); + return -1; + } + + return igmp_recv_query(igmp, query_version, max_resp_code, + ip_hdr->ip_src, from_str, igmp_msg, + igmp_msg_len); + } - case PIM_IGMP_V2_MEMBERSHIP_REPORT: - return igmp_v2_recv_report(igmp, ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); + case PIM_IGMP_V3_MEMBERSHIP_REPORT: + return igmp_v3_recv_report(igmp, ip_hdr->ip_src, from_str, + igmp_msg, igmp_msg_len); - case PIM_IGMP_V1_MEMBERSHIP_REPORT: - return igmp_v1_recv_report(igmp, ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); + case PIM_IGMP_V2_MEMBERSHIP_REPORT: + return igmp_v2_recv_report(igmp, ip_hdr->ip_src, from_str, + igmp_msg, igmp_msg_len); - case PIM_IGMP_V2_LEAVE_GROUP: - return igmp_v2_recv_leave(igmp, ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); - } + case PIM_IGMP_V1_MEMBERSHIP_REPORT: + return igmp_v1_recv_report(igmp, ip_hdr->ip_src, from_str, + igmp_msg, igmp_msg_len); - zlog_warn("Ignoring unsupported IGMP message type: %d", msg_type); + case PIM_IGMP_V2_LEAVE_GROUP: + return igmp_v2_recv_leave(igmp, ip_hdr->ip_src, from_str, + igmp_msg, igmp_msg_len); + } - return -1; + zlog_warn("Ignoring unsupported IGMP message type: %d", msg_type); + + return -1; } void pim_igmp_general_query_on(struct igmp_sock *igmp) { - struct pim_interface *pim_ifp; - int startup_mode; - int query_interval; - - /* - Since this socket is starting as querier, - there should not exist a timer for other-querier-present. - */ - zassert(!igmp->t_other_querier_timer); - pim_ifp = igmp->interface->info; - zassert(pim_ifp); - - /* - RFC 3376: 8.6. Startup Query Interval - - The Startup Query Interval is the interval between General Queries - sent by a Querier on startup. Default: 1/4 the Query Interval. - The first one should be sent out immediately instead of 125/4 - seconds from now. - */ - startup_mode = igmp->startup_query_count > 0; - if (startup_mode) { - /* - * If this is the first time we are sending a query on a - * newly configured igmp interface send it out in 1 second - * just to give the entire world a tiny bit of time to settle - * else the query interval is: - * query_interval = pim_ifp->igmp_default_query_interval >> 2; - */ - if (igmp->startup_query_count == igmp->querier_robustness_variable) - query_interval = 1; - else - query_interval = PIM_IGMP_SQI(pim_ifp->igmp_default_query_interval); - - --igmp->startup_query_count; - } - else { - query_interval = igmp->querier_query_interval; - } - - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("Querier %s scheduling %d-second (%s) TIMER event for IGMP query on fd=%d", - ifaddr_str, - query_interval, - startup_mode ? "startup" : "non-startup", - igmp->fd); - } - igmp->t_igmp_query_timer = NULL; - thread_add_timer(master, pim_igmp_general_query, igmp, query_interval, - &igmp->t_igmp_query_timer); + struct pim_interface *pim_ifp; + int startup_mode; + int query_interval; + + /* + Since this socket is starting as querier, + there should not exist a timer for other-querier-present. + */ + zassert(!igmp->t_other_querier_timer); + pim_ifp = igmp->interface->info; + zassert(pim_ifp); + + /* + RFC 3376: 8.6. Startup Query Interval + + The Startup Query Interval is the interval between General Queries + sent by a Querier on startup. Default: 1/4 the Query Interval. + The first one should be sent out immediately instead of 125/4 + seconds from now. + */ + startup_mode = igmp->startup_query_count > 0; + if (startup_mode) { + /* + * If this is the first time we are sending a query on a + * newly configured igmp interface send it out in 1 second + * just to give the entire world a tiny bit of time to settle + * else the query interval is: + * query_interval = pim_ifp->igmp_default_query_interval >> 2; + */ + if (igmp->startup_query_count + == igmp->querier_robustness_variable) + query_interval = 1; + else + query_interval = PIM_IGMP_SQI( + pim_ifp->igmp_default_query_interval); + + --igmp->startup_query_count; + } else { + query_interval = igmp->querier_query_interval; + } + + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug( + "Querier %s scheduling %d-second (%s) TIMER event for IGMP query on fd=%d", + ifaddr_str, query_interval, + startup_mode ? "startup" : "non-startup", igmp->fd); + } + igmp->t_igmp_query_timer = NULL; + thread_add_timer(master, pim_igmp_general_query, igmp, query_interval, + &igmp->t_igmp_query_timer); } void pim_igmp_general_query_off(struct igmp_sock *igmp) { - zassert(igmp); - - if (PIM_DEBUG_IGMP_TRACE) { - if (igmp->t_igmp_query_timer) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("IGMP querier %s fd=%d cancelling query TIMER event on %s", - ifaddr_str, igmp->fd, igmp->interface->name); - } - } - THREAD_OFF(igmp->t_igmp_query_timer); + zassert(igmp); + + if (PIM_DEBUG_IGMP_TRACE) { + if (igmp->t_igmp_query_timer) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug( + "IGMP querier %s fd=%d cancelling query TIMER event on %s", + ifaddr_str, igmp->fd, igmp->interface->name); + } + } + THREAD_OFF(igmp->t_igmp_query_timer); } /* Issue IGMP general query */ static int pim_igmp_general_query(struct thread *t) { - struct igmp_sock *igmp; - struct in_addr dst_addr; - struct in_addr group_addr; - struct pim_interface *pim_ifp; - int query_buf_size; - - igmp = THREAD_ARG(t); - - zassert(igmp->interface); - zassert(igmp->interface->info); - - pim_ifp = igmp->interface->info; - - if (pim_ifp->igmp_version == 3) { - query_buf_size = PIM_IGMP_BUFSIZE_WRITE; - } else { - query_buf_size = IGMP_V12_MSG_SIZE; - } - - char query_buf[query_buf_size]; - - /* - RFC3376: 4.1.12. IP Destination Addresses for Queries - - In IGMPv3, General Queries are sent with an IP destination address - of 224.0.0.1, the all-systems multicast address. Group-Specific - and Group-and-Source-Specific Queries are sent with an IP - destination address equal to the multicast address of interest. - */ - - dst_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); - group_addr.s_addr = PIM_NET_INADDR_ANY; - - if (PIM_DEBUG_IGMP_TRACE) { - char querier_str[INET_ADDRSTRLEN]; - char dst_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<querier?>", igmp->ifaddr, querier_str, - sizeof(querier_str)); - pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); - zlog_debug("Querier %s issuing IGMP general query to %s on %s", - querier_str, dst_str, igmp->interface->name); - } - - igmp_send_query (pim_ifp->igmp_version, - 0 /* igmp_group */, - igmp->fd, - igmp->interface->name, - query_buf, - sizeof(query_buf), - 0 /* num_sources */, - dst_addr, - group_addr, - pim_ifp->igmp_query_max_response_time_dsec, - 1 /* s_flag: always set for general queries */, - igmp->querier_robustness_variable, - igmp->querier_query_interval); - - pim_igmp_general_query_on(igmp); - - return 0; + struct igmp_sock *igmp; + struct in_addr dst_addr; + struct in_addr group_addr; + struct pim_interface *pim_ifp; + int query_buf_size; + + igmp = THREAD_ARG(t); + + zassert(igmp->interface); + zassert(igmp->interface->info); + + pim_ifp = igmp->interface->info; + + if (pim_ifp->igmp_version == 3) { + query_buf_size = PIM_IGMP_BUFSIZE_WRITE; + } else { + query_buf_size = IGMP_V12_MSG_SIZE; + } + + char query_buf[query_buf_size]; + + /* + RFC3376: 4.1.12. IP Destination Addresses for Queries + + In IGMPv3, General Queries are sent with an IP destination address + of 224.0.0.1, the all-systems multicast address. Group-Specific + and Group-and-Source-Specific Queries are sent with an IP + destination address equal to the multicast address of interest. + */ + + dst_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); + group_addr.s_addr = PIM_NET_INADDR_ANY; + + if (PIM_DEBUG_IGMP_TRACE) { + char querier_str[INET_ADDRSTRLEN]; + char dst_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<querier?>", igmp->ifaddr, querier_str, + sizeof(querier_str)); + pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); + zlog_debug("Querier %s issuing IGMP general query to %s on %s", + querier_str, dst_str, igmp->interface->name); + } + + igmp_send_query(pim_ifp->igmp_version, 0 /* igmp_group */, igmp->fd, + igmp->interface->name, query_buf, sizeof(query_buf), + 0 /* num_sources */, dst_addr, group_addr, + pim_ifp->igmp_query_max_response_time_dsec, + 1 /* s_flag: always set for general queries */, + igmp->querier_robustness_variable, + igmp->querier_query_interval); + + pim_igmp_general_query_on(igmp); + + return 0; } static void sock_close(struct igmp_sock *igmp) { - pim_igmp_other_querier_timer_off(igmp); - pim_igmp_general_query_off(igmp); - - if (PIM_DEBUG_IGMP_TRACE_DETAIL) { - if (igmp->t_igmp_read) { - zlog_debug("Cancelling READ event on IGMP socket %s fd=%d on interface %s", - inet_ntoa(igmp->ifaddr), igmp->fd, - igmp->interface->name); - } - } - THREAD_OFF(igmp->t_igmp_read); - - if (close(igmp->fd)) { - zlog_err("Failure closing IGMP socket %s fd=%d on interface %s: errno=%d: %s", - inet_ntoa(igmp->ifaddr), igmp->fd, igmp->interface->name, - errno, safe_strerror(errno)); - } - - if (PIM_DEBUG_IGMP_TRACE_DETAIL) { - zlog_debug("Deleted IGMP socket %s fd=%d on interface %s", - inet_ntoa(igmp->ifaddr), igmp->fd, igmp->interface->name); - } + pim_igmp_other_querier_timer_off(igmp); + pim_igmp_general_query_off(igmp); + + if (PIM_DEBUG_IGMP_TRACE_DETAIL) { + if (igmp->t_igmp_read) { + zlog_debug( + "Cancelling READ event on IGMP socket %s fd=%d on interface %s", + inet_ntoa(igmp->ifaddr), igmp->fd, + igmp->interface->name); + } + } + THREAD_OFF(igmp->t_igmp_read); + + if (close(igmp->fd)) { + zlog_err( + "Failure closing IGMP socket %s fd=%d on interface %s: errno=%d: %s", + inet_ntoa(igmp->ifaddr), igmp->fd, + igmp->interface->name, errno, safe_strerror(errno)); + } + + if (PIM_DEBUG_IGMP_TRACE_DETAIL) { + zlog_debug("Deleted IGMP socket %s fd=%d on interface %s", + inet_ntoa(igmp->ifaddr), igmp->fd, + igmp->interface->name); + } } void igmp_startup_mode_on(struct igmp_sock *igmp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - pim_ifp = igmp->interface->info; + pim_ifp = igmp->interface->info; - /* - RFC 3376: 8.7. Startup Query Count + /* + RFC 3376: 8.7. Startup Query Count - The Startup Query Count is the number of Queries sent out on - startup, separated by the Startup Query Interval. Default: the - Robustness Variable. - */ - igmp->startup_query_count = igmp->querier_robustness_variable; + The Startup Query Count is the number of Queries sent out on + startup, separated by the Startup Query Interval. Default: the + Robustness Variable. + */ + igmp->startup_query_count = igmp->querier_robustness_variable; - /* - Since we're (re)starting, reset QQI to default Query Interval - */ - igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; + /* + Since we're (re)starting, reset QQI to default Query Interval + */ + igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; } static void igmp_group_free(struct igmp_group *group) { - list_free(group->group_source_list); + list_free(group->group_source_list); - XFREE(MTYPE_PIM_IGMP_GROUP, group); + XFREE(MTYPE_PIM_IGMP_GROUP, group); } static void igmp_group_delete(struct igmp_group *group) { - struct listnode *src_node; - struct listnode *src_nextnode; - struct igmp_source *src; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("Deleting IGMP group %s from socket %d interface %s", - group_str, - group->group_igmp_sock->fd, - group->group_igmp_sock->interface->name); - } - - for (ALL_LIST_ELEMENTS(group->group_source_list, src_node, src_nextnode, src)) { - igmp_source_delete(src); - } - - if (group->t_group_query_retransmit_timer) { - THREAD_OFF(group->t_group_query_retransmit_timer); - } - - group_timer_off(group); - listnode_delete(group->group_igmp_sock->igmp_group_list, group); - hash_release (group->group_igmp_sock->igmp_group_hash, group); - - igmp_group_free(group); + struct listnode *src_node; + struct listnode *src_nextnode; + struct igmp_source *src; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug("Deleting IGMP group %s from socket %d interface %s", + group_str, group->group_igmp_sock->fd, + group->group_igmp_sock->interface->name); + } + + for (ALL_LIST_ELEMENTS(group->group_source_list, src_node, src_nextnode, + src)) { + igmp_source_delete(src); + } + + if (group->t_group_query_retransmit_timer) { + THREAD_OFF(group->t_group_query_retransmit_timer); + } + + group_timer_off(group); + listnode_delete(group->group_igmp_sock->igmp_group_list, group); + hash_release(group->group_igmp_sock->igmp_group_hash, group); + + igmp_group_free(group); } void igmp_group_delete_empty_include(struct igmp_group *group) { - zassert(!group->group_filtermode_isexcl); - zassert(!listcount(group->group_source_list)); + zassert(!group->group_filtermode_isexcl); + zassert(!listcount(group->group_source_list)); - igmp_group_delete(group); + igmp_group_delete(group); } void igmp_sock_free(struct igmp_sock *igmp) { - zassert(!igmp->t_igmp_read); - zassert(!igmp->t_igmp_query_timer); - zassert(!igmp->t_other_querier_timer); - zassert(igmp->igmp_group_list); - zassert(!listcount(igmp->igmp_group_list)); + zassert(!igmp->t_igmp_read); + zassert(!igmp->t_igmp_query_timer); + zassert(!igmp->t_other_querier_timer); + zassert(igmp->igmp_group_list); + zassert(!listcount(igmp->igmp_group_list)); - list_free(igmp->igmp_group_list); - hash_free(igmp->igmp_group_hash); + list_free(igmp->igmp_group_list); + hash_free(igmp->igmp_group_hash); - XFREE(MTYPE_PIM_IGMP_SOCKET, igmp); + XFREE(MTYPE_PIM_IGMP_SOCKET, igmp); } void igmp_sock_delete(struct igmp_sock *igmp) { - struct pim_interface *pim_ifp; - struct listnode *grp_node; - struct listnode *grp_nextnode; - struct igmp_group *grp; - - for (ALL_LIST_ELEMENTS(igmp->igmp_group_list, grp_node, grp_nextnode, grp)) { - igmp_group_delete(grp); - } + struct pim_interface *pim_ifp; + struct listnode *grp_node; + struct listnode *grp_nextnode; + struct igmp_group *grp; + + for (ALL_LIST_ELEMENTS(igmp->igmp_group_list, grp_node, grp_nextnode, + grp)) { + igmp_group_delete(grp); + } - sock_close(igmp); + sock_close(igmp); - pim_ifp = igmp->interface->info; + pim_ifp = igmp->interface->info; - listnode_delete(pim_ifp->igmp_socket_list, igmp); + listnode_delete(pim_ifp->igmp_socket_list, igmp); - igmp_sock_free(igmp); + igmp_sock_free(igmp); } -void -igmp_sock_delete_all (struct interface *ifp) +void igmp_sock_delete_all(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *igmp_node, *igmp_nextnode; - struct igmp_sock *igmp; + struct pim_interface *pim_ifp; + struct listnode *igmp_node, *igmp_nextnode; + struct igmp_sock *igmp; - pim_ifp = ifp->info; + pim_ifp = ifp->info; - for (ALL_LIST_ELEMENTS (pim_ifp->igmp_socket_list, igmp_node, - igmp_nextnode, igmp)) - { - igmp_sock_delete(igmp); - } + for (ALL_LIST_ELEMENTS(pim_ifp->igmp_socket_list, igmp_node, + igmp_nextnode, igmp)) { + igmp_sock_delete(igmp); + } } -static unsigned int -igmp_group_hash_key (void *arg) +static unsigned int igmp_group_hash_key(void *arg) { - struct igmp_group *group = (struct igmp_group *)arg; + struct igmp_group *group = (struct igmp_group *)arg; - return jhash_1word(group->group_addr.s_addr, 0); + return jhash_1word(group->group_addr.s_addr, 0); } -static int -igmp_group_hash_equal (const void *arg1, const void *arg2) +static int igmp_group_hash_equal(const void *arg1, const void *arg2) { - const struct igmp_group *g1 = (const struct igmp_group *)arg1; - const struct igmp_group *g2 = (const struct igmp_group *)arg2; + const struct igmp_group *g1 = (const struct igmp_group *)arg1; + const struct igmp_group *g2 = (const struct igmp_group *)arg2; - if (g1->group_addr.s_addr == g2->group_addr.s_addr) - return 1; + if (g1->group_addr.s_addr == g2->group_addr.s_addr) + return 1; - return 0; + return 0; } -static struct igmp_sock *igmp_sock_new(int fd, - struct in_addr ifaddr, +static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr, struct interface *ifp) { - struct pim_interface *pim_ifp; - struct igmp_sock *igmp; - - pim_ifp = ifp->info; - - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("Creating IGMP socket fd=%d for address %s on interface %s", - fd, inet_ntoa(ifaddr), ifp->name); - } - - igmp = XCALLOC(MTYPE_PIM_IGMP_SOCKET, sizeof(*igmp)); - if (!igmp) { - zlog_warn("%s %s: XCALLOC() failure", - __FILE__, __PRETTY_FUNCTION__); - return 0; - } - - igmp->igmp_group_list = list_new(); - if (!igmp->igmp_group_list) { - zlog_err("%s %s: failure: igmp_group_list = list_new()", - __FILE__, __PRETTY_FUNCTION__); - return 0; - } - igmp->igmp_group_list->del = (void (*)(void *)) igmp_group_free; - - igmp->igmp_group_hash = hash_create (igmp_group_hash_key, - igmp_group_hash_equal, NULL); - - igmp->fd = fd; - igmp->interface = ifp; - igmp->ifaddr = ifaddr; - igmp->t_igmp_read = NULL; - igmp->t_igmp_query_timer = NULL; - igmp->t_other_querier_timer = NULL; /* no other querier present */ - igmp->querier_robustness_variable = pim_ifp->igmp_default_robustness_variable; - igmp->sock_creation = pim_time_monotonic_sec(); - - /* - igmp_startup_mode_on() will reset QQI: - - igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; - */ - igmp_startup_mode_on(igmp); - pim_igmp_general_query_on(igmp); - - return igmp; + struct pim_interface *pim_ifp; + struct igmp_sock *igmp; + + pim_ifp = ifp->info; + + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "Creating IGMP socket fd=%d for address %s on interface %s", + fd, inet_ntoa(ifaddr), ifp->name); + } + + igmp = XCALLOC(MTYPE_PIM_IGMP_SOCKET, sizeof(*igmp)); + if (!igmp) { + zlog_warn("%s %s: XCALLOC() failure", __FILE__, + __PRETTY_FUNCTION__); + return 0; + } + + igmp->igmp_group_list = list_new(); + if (!igmp->igmp_group_list) { + zlog_err("%s %s: failure: igmp_group_list = list_new()", + __FILE__, __PRETTY_FUNCTION__); + return 0; + } + igmp->igmp_group_list->del = (void (*)(void *))igmp_group_free; + + igmp->igmp_group_hash = + hash_create(igmp_group_hash_key, igmp_group_hash_equal, NULL); + + igmp->fd = fd; + igmp->interface = ifp; + igmp->ifaddr = ifaddr; + igmp->t_igmp_read = NULL; + igmp->t_igmp_query_timer = NULL; + igmp->t_other_querier_timer = NULL; /* no other querier present */ + igmp->querier_robustness_variable = + pim_ifp->igmp_default_robustness_variable; + igmp->sock_creation = pim_time_monotonic_sec(); + + /* + igmp_startup_mode_on() will reset QQI: + + igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; + */ + igmp_startup_mode_on(igmp); + pim_igmp_general_query_on(igmp); + + return igmp; } -static void igmp_read_on (struct igmp_sock *igmp); +static void igmp_read_on(struct igmp_sock *igmp); -static int -pim_igmp_read (struct thread *t) +static int pim_igmp_read(struct thread *t) { - uint8_t buf[10000]; - struct igmp_sock *igmp = (struct igmp_sock *)THREAD_ARG(t); - struct sockaddr_in from; - struct sockaddr_in to; - socklen_t fromlen = sizeof(from); - socklen_t tolen = sizeof(to); - ifindex_t ifindex = -1; - int cont = 1; - int len; - - while (cont) - { - len = pim_socket_recvfromto(igmp->fd, buf, sizeof(buf), - &from, &fromlen, - &to, &tolen, - &ifindex); - if (len < 0) - { - if (errno == EINTR) - continue; - if (errno == EWOULDBLOCK || errno == EAGAIN) - break; - - goto done; + uint8_t buf[10000]; + struct igmp_sock *igmp = (struct igmp_sock *)THREAD_ARG(t); + struct sockaddr_in from; + struct sockaddr_in to; + socklen_t fromlen = sizeof(from); + socklen_t tolen = sizeof(to); + ifindex_t ifindex = -1; + int cont = 1; + int len; + + while (cont) { + len = pim_socket_recvfromto(igmp->fd, buf, sizeof(buf), &from, + &fromlen, &to, &tolen, &ifindex); + if (len < 0) { + if (errno == EINTR) + continue; + if (errno == EWOULDBLOCK || errno == EAGAIN) + break; + + goto done; + } } - } - done: - igmp_read_on(igmp); - return 0; +done: + igmp_read_on(igmp); + return 0; } -static void -igmp_read_on (struct igmp_sock *igmp) +static void igmp_read_on(struct igmp_sock *igmp) { - if (PIM_DEBUG_IGMP_TRACE_DETAIL) { - zlog_debug("Scheduling READ event on IGMP socket fd=%d", - igmp->fd); - } - igmp->t_igmp_read = NULL; - thread_add_read(master, pim_igmp_read, igmp, igmp->fd, &igmp->t_igmp_read); - + if (PIM_DEBUG_IGMP_TRACE_DETAIL) { + zlog_debug("Scheduling READ event on IGMP socket fd=%d", + igmp->fd); + } + igmp->t_igmp_read = NULL; + thread_add_read(master, pim_igmp_read, igmp, igmp->fd, + &igmp->t_igmp_read); } struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, struct in_addr ifaddr, struct interface *ifp) { - struct pim_interface *pim_ifp; - struct igmp_sock *igmp; - int fd; + struct pim_interface *pim_ifp; + struct igmp_sock *igmp; + int fd; - pim_ifp = ifp->info; + pim_ifp = ifp->info; - fd = igmp_sock_open(ifaddr, ifp, pim_ifp->options); - if (fd < 0) { - zlog_warn("Could not open IGMP socket for %s on %s", - inet_ntoa(ifaddr), ifp->name); - return 0; - } + fd = igmp_sock_open(ifaddr, ifp, pim_ifp->options); + if (fd < 0) { + zlog_warn("Could not open IGMP socket for %s on %s", + inet_ntoa(ifaddr), ifp->name); + return 0; + } - igmp = igmp_sock_new(fd, ifaddr, ifp); - if (!igmp) { - zlog_err("%s %s: igmp_sock_new() failure", - __FILE__, __PRETTY_FUNCTION__); - close(fd); - return 0; - } + igmp = igmp_sock_new(fd, ifaddr, ifp); + if (!igmp) { + zlog_err("%s %s: igmp_sock_new() failure", __FILE__, + __PRETTY_FUNCTION__); + close(fd); + return 0; + } - igmp_read_on (igmp); + igmp_read_on(igmp); - listnode_add(igmp_sock_list, igmp); + listnode_add(igmp_sock_list, igmp); #ifdef IGMP_SOCK_DUMP - igmp_sock_dump(igmp_sock_array); + igmp_sock_dump(igmp_sock_array); #endif - return igmp; + return igmp; } /* @@ -946,210 +956,203 @@ struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, */ static int igmp_group_timer(struct thread *t) { - struct igmp_group *group; + struct igmp_group *group; - group = THREAD_ARG(t); + group = THREAD_ARG(t); - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("%s: Timer for group %s on interface %s", - __PRETTY_FUNCTION__, - group_str, group->group_igmp_sock->interface->name); - } + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug("%s: Timer for group %s on interface %s", + __PRETTY_FUNCTION__, group_str, + group->group_igmp_sock->interface->name); + } - zassert(group->group_filtermode_isexcl); + zassert(group->group_filtermode_isexcl); - group->group_filtermode_isexcl = 0; + group->group_filtermode_isexcl = 0; - /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ - igmp_anysource_forward_stop(group); + /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ + igmp_anysource_forward_stop(group); - igmp_source_delete_expired(group->group_source_list); + igmp_source_delete_expired(group->group_source_list); - zassert(!group->group_filtermode_isexcl); + zassert(!group->group_filtermode_isexcl); - /* - RFC 3376: 6.2.2. Definition of Group Timers + /* + RFC 3376: 6.2.2. Definition of Group Timers - If there are no more source records for the group, delete group - record. - */ - if (listcount(group->group_source_list) < 1) { - igmp_group_delete_empty_include(group); - } + If there are no more source records for the group, delete group + record. + */ + if (listcount(group->group_source_list) < 1) { + igmp_group_delete_empty_include(group); + } - return 0; + return 0; } static void group_timer_off(struct igmp_group *group) { - if (!group->t_group_timer) - return; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("Cancelling TIMER event for group %s on %s", - group_str, group->group_igmp_sock->interface->name); - } - THREAD_OFF(group->t_group_timer); + if (!group->t_group_timer) + return; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug("Cancelling TIMER event for group %s on %s", + group_str, group->group_igmp_sock->interface->name); + } + THREAD_OFF(group->t_group_timer); } -void igmp_group_timer_on(struct igmp_group *group, - long interval_msec, const char *ifname) +void igmp_group_timer_on(struct igmp_group *group, long interval_msec, + const char *ifname) { - group_timer_off(group); - - if (PIM_DEBUG_IGMP_EVENTS) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("Scheduling %ld.%03ld sec TIMER event for group %s on %s", - interval_msec / 1000, - interval_msec % 1000, - group_str, ifname); - } - - /* - RFC 3376: 6.2.2. Definition of Group Timers - - The group timer is only used when a group is in EXCLUDE mode and - it represents the time for the *filter-mode* of the group to - expire and switch to INCLUDE mode. - */ - zassert(group->group_filtermode_isexcl); - - thread_add_timer_msec(master, igmp_group_timer, group, interval_msec, - &group->t_group_timer); + group_timer_off(group); + + if (PIM_DEBUG_IGMP_EVENTS) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "Scheduling %ld.%03ld sec TIMER event for group %s on %s", + interval_msec / 1000, interval_msec % 1000, group_str, + ifname); + } + + /* + RFC 3376: 6.2.2. Definition of Group Timers + + The group timer is only used when a group is in EXCLUDE mode and + it represents the time for the *filter-mode* of the group to + expire and switch to INCLUDE mode. + */ + zassert(group->group_filtermode_isexcl); + + thread_add_timer_msec(master, igmp_group_timer, group, interval_msec, + &group->t_group_timer); } -struct igmp_group * -find_group_by_addr (struct igmp_sock *igmp, - struct in_addr group_addr) +struct igmp_group *find_group_by_addr(struct igmp_sock *igmp, + struct in_addr group_addr) { - struct igmp_group lookup; + struct igmp_group lookup; - lookup.group_addr.s_addr = group_addr.s_addr; + lookup.group_addr.s_addr = group_addr.s_addr; - return hash_lookup(igmp->igmp_group_hash, &lookup); + return hash_lookup(igmp->igmp_group_hash, &lookup); } struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, struct in_addr group_addr) { - struct igmp_group *group; - - group = find_group_by_addr(igmp, group_addr); - if (group) { - return group; - } - - if (!pim_is_group_224_4 (group_addr)) - { - zlog_warn("%s: Group Specified is not part of 224.0.0.0/4", - __PRETTY_FUNCTION__); - return NULL; - } - - if (pim_is_group_224_0_0_0_24 (group_addr)) - { - zlog_warn("%s: Group specified is part of 224.0.0.0/24", - __PRETTY_FUNCTION__); - return NULL; - } - /* - Non-existant group is created as INCLUDE {empty}: - - RFC 3376 - 5.1. Action on Change of Interface State - - If no interface state existed for that multicast address before - the change (i.e., the change consisted of creating a new - per-interface record), or if no state exists after the change - (i.e., the change consisted of deleting a per-interface record), - then the "non-existent" state is considered to have a filter mode - of INCLUDE and an empty source list. - */ - - group = XCALLOC(MTYPE_PIM_IGMP_GROUP, sizeof(*group)); - if (!group) { - zlog_warn("%s %s: XCALLOC() failure", - __FILE__, __PRETTY_FUNCTION__); - return NULL; /* error, not found, could not create */ - } - - group->group_source_list = list_new(); - if (!group->group_source_list) { - zlog_warn("%s %s: list_new() failure", - __FILE__, __PRETTY_FUNCTION__); - XFREE(MTYPE_PIM_IGMP_GROUP, group); /* discard group */ - return NULL; /* error, not found, could not initialize */ - } - group->group_source_list->del = (void (*)(void *)) igmp_source_free; - - group->t_group_timer = NULL; - group->t_group_query_retransmit_timer = NULL; - group->group_specific_query_retransmit_count = 0; - group->group_addr = group_addr; - group->group_igmp_sock = igmp; - group->last_igmp_v1_report_dsec = -1; - group->last_igmp_v2_report_dsec = -1; - group->group_creation = pim_time_monotonic_sec(); - group->igmp_version = IGMP_DEFAULT_VERSION; - - /* initialize new group as INCLUDE {empty} */ - group->group_filtermode_isexcl = 0; /* 0=INCLUDE, 1=EXCLUDE */ - - listnode_add(igmp->igmp_group_list, group); - group = hash_get (igmp->igmp_group_hash, group, hash_alloc_intern); - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("Creating new IGMP group %s on socket %d interface %s", - group_str, igmp->fd, igmp->interface->name); - } - - /* - RFC 3376: 6.2.2. Definition of Group Timers - - The group timer is only used when a group is in EXCLUDE mode and - it represents the time for the *filter-mode* of the group to - expire and switch to INCLUDE mode. - */ - zassert(!group->group_filtermode_isexcl); /* INCLUDE mode */ - zassert(!group->t_group_timer); /* group timer == 0 */ - - /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ - igmp_anysource_forward_stop(group); - - return group; + struct igmp_group *group; + + group = find_group_by_addr(igmp, group_addr); + if (group) { + return group; + } + + if (!pim_is_group_224_4(group_addr)) { + zlog_warn("%s: Group Specified is not part of 224.0.0.0/4", + __PRETTY_FUNCTION__); + return NULL; + } + + if (pim_is_group_224_0_0_0_24(group_addr)) { + zlog_warn("%s: Group specified is part of 224.0.0.0/24", + __PRETTY_FUNCTION__); + return NULL; + } + /* + Non-existant group is created as INCLUDE {empty}: + + RFC 3376 - 5.1. Action on Change of Interface State + + If no interface state existed for that multicast address before + the change (i.e., the change consisted of creating a new + per-interface record), or if no state exists after the change + (i.e., the change consisted of deleting a per-interface record), + then the "non-existent" state is considered to have a filter mode + of INCLUDE and an empty source list. + */ + + group = XCALLOC(MTYPE_PIM_IGMP_GROUP, sizeof(*group)); + if (!group) { + zlog_warn("%s %s: XCALLOC() failure", __FILE__, + __PRETTY_FUNCTION__); + return NULL; /* error, not found, could not create */ + } + + group->group_source_list = list_new(); + if (!group->group_source_list) { + zlog_warn("%s %s: list_new() failure", __FILE__, + __PRETTY_FUNCTION__); + XFREE(MTYPE_PIM_IGMP_GROUP, group); /* discard group */ + return NULL; /* error, not found, could not initialize */ + } + group->group_source_list->del = (void (*)(void *))igmp_source_free; + + group->t_group_timer = NULL; + group->t_group_query_retransmit_timer = NULL; + group->group_specific_query_retransmit_count = 0; + group->group_addr = group_addr; + group->group_igmp_sock = igmp; + group->last_igmp_v1_report_dsec = -1; + group->last_igmp_v2_report_dsec = -1; + group->group_creation = pim_time_monotonic_sec(); + group->igmp_version = IGMP_DEFAULT_VERSION; + + /* initialize new group as INCLUDE {empty} */ + group->group_filtermode_isexcl = 0; /* 0=INCLUDE, 1=EXCLUDE */ + + listnode_add(igmp->igmp_group_list, group); + group = hash_get(igmp->igmp_group_hash, group, hash_alloc_intern); + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "Creating new IGMP group %s on socket %d interface %s", + group_str, igmp->fd, igmp->interface->name); + } + + /* + RFC 3376: 6.2.2. Definition of Group Timers + + The group timer is only used when a group is in EXCLUDE mode and + it represents the time for the *filter-mode* of the group to + expire and switch to INCLUDE mode. + */ + zassert(!group->group_filtermode_isexcl); /* INCLUDE mode */ + zassert(!group->t_group_timer); /* group timer == 0 */ + + /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ + igmp_anysource_forward_stop(group); + + return group; } -void -igmp_send_query (int igmp_version, - struct igmp_group *group, - int fd, - const char *ifname, - char *query_buf, - int query_buf_size, - int num_sources, - struct in_addr dst_addr, - struct in_addr group_addr, - int query_max_response_time_dsec, - uint8_t s_flag, - uint8_t querier_robustness_variable, - uint16_t querier_query_interval) +void igmp_send_query(int igmp_version, struct igmp_group *group, int fd, + const char *ifname, char *query_buf, int query_buf_size, + int num_sources, struct in_addr dst_addr, + struct in_addr group_addr, + int query_max_response_time_dsec, uint8_t s_flag, + uint8_t querier_robustness_variable, + uint16_t querier_query_interval) { - if (igmp_version == 3) { - igmp_v3_send_query (group, fd, ifname, query_buf, - query_buf_size, num_sources, - dst_addr, group_addr, - query_max_response_time_dsec, s_flag, - querier_robustness_variable, - querier_query_interval); - } else if (igmp_version == 2) { - igmp_v2_send_query (group, fd, ifname, query_buf, - dst_addr, group_addr, - query_max_response_time_dsec); - } + if (igmp_version == 3) { + igmp_v3_send_query(group, fd, ifname, query_buf, query_buf_size, + num_sources, dst_addr, group_addr, + query_max_response_time_dsec, s_flag, + querier_robustness_variable, + querier_query_interval); + } else if (igmp_version == 2) { + igmp_v2_send_query(group, fd, ifname, query_buf, dst_addr, + group_addr, query_max_response_time_dsec); + } } diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h index 2f36094bd..275f25f63 100644 --- a/pimd/pim_igmp.h +++ b/pimd/pim_igmp.h @@ -41,8 +41,8 @@ #define IGMP_V3_REPORT_HEADER_SIZE (8) #define IGMP_V3_GROUP_RECORD_MIN_SIZE (8) -#define IGMP_V3_MSG_MIN_SIZE (IGMP_V3_REPORT_HEADER_SIZE + \ - IGMP_V3_GROUP_RECORD_MIN_SIZE) +#define IGMP_V3_MSG_MIN_SIZE \ + (IGMP_V3_REPORT_HEADER_SIZE + IGMP_V3_GROUP_RECORD_MIN_SIZE) #define IGMP_V12_MSG_SIZE (8) #define IGMP_V3_GROUP_RECORD_TYPE_OFFSET (0) @@ -67,40 +67,40 @@ #define IGMP_DEFAULT_VERSION (3) struct igmp_join { - struct in_addr group_addr; - struct in_addr source_addr; - int sock_fd; - time_t sock_creation; + struct in_addr group_addr; + struct in_addr source_addr; + int sock_fd; + time_t sock_creation; }; struct igmp_sock { - int fd; - struct interface *interface; - struct in_addr ifaddr; - time_t sock_creation; - - struct thread *t_igmp_read; /* read: IGMP sockets */ - struct thread *t_igmp_query_timer; /* timer: issue IGMP general queries */ - struct thread *t_other_querier_timer; /* timer: other querier present */ - - int querier_query_interval; /* QQI */ - int querier_robustness_variable; /* QRV */ - int startup_query_count; - - struct list *igmp_group_list; /* list of struct igmp_group */ - struct hash *igmp_group_hash; + int fd; + struct interface *interface; + struct in_addr ifaddr; + time_t sock_creation; + + struct thread *t_igmp_read; /* read: IGMP sockets */ + struct thread + *t_igmp_query_timer; /* timer: issue IGMP general queries */ + struct thread *t_other_querier_timer; /* timer: other querier present */ + + int querier_query_interval; /* QQI */ + int querier_robustness_variable; /* QRV */ + int startup_query_count; + + struct list *igmp_group_list; /* list of struct igmp_group */ + struct hash *igmp_group_hash; }; struct igmp_sock *pim_igmp_sock_lookup_ifaddr(struct list *igmp_sock_list, struct in_addr ifaddr); -struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, - int fd); +struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, int fd); struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, struct in_addr ifaddr, struct interface *ifp); void igmp_sock_delete(struct igmp_sock *igmp); void igmp_sock_free(struct igmp_sock *igmp); -void igmp_sock_delete_all (struct interface *ifp); +void igmp_sock_delete_all(struct interface *ifp); int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len); void pim_igmp_general_query_on(struct igmp_sock *igmp); @@ -122,52 +122,53 @@ void pim_igmp_other_querier_timer_off(struct igmp_sock *igmp); #define IGMP_SOURCE_DONT_SEND(flags) ((flags) &= ~IGMP_SOURCE_MASK_SEND) struct igmp_source { - struct in_addr source_addr; - struct thread *t_source_timer; - struct igmp_group *source_group; /* back pointer */ - time_t source_creation; - uint32_t source_flags; - struct channel_oil *source_channel_oil; - - /* - RFC 3376: 6.6.3.2. Building and Sending Group and Source Specific Queries - */ - int source_query_retransmit_count; + struct in_addr source_addr; + struct thread *t_source_timer; + struct igmp_group *source_group; /* back pointer */ + time_t source_creation; + uint32_t source_flags; + struct channel_oil *source_channel_oil; + + /* + RFC 3376: 6.6.3.2. Building and Sending Group and Source Specific + Queries + */ + int source_query_retransmit_count; }; struct igmp_group { - /* - RFC 3376: 6.2.2. Definition of Group Timers - - The group timer is only used when a group is in EXCLUDE mode and it - represents the time for the *filter-mode* of the group to expire and - switch to INCLUDE mode. - */ - struct thread *t_group_timer; - - /* Shared between group-specific and - group-and-source-specific retransmissions */ - struct thread *t_group_query_retransmit_timer; - - /* Counter exclusive for group-specific retransmissions - (not used by group-and-source-specific retransmissions, - since sources have their counters) */ - int group_specific_query_retransmit_count; - - /* compatibility mode - igmp v1, v2 or v3 */ - int igmp_version; - - struct in_addr group_addr; - int group_filtermode_isexcl; /* 0=INCLUDE, 1=EXCLUDE */ - struct list *group_source_list; /* list of struct igmp_source */ - time_t group_creation; - struct igmp_sock *group_igmp_sock; /* back pointer */ - int64_t last_igmp_v1_report_dsec; - int64_t last_igmp_v2_report_dsec; + /* + RFC 3376: 6.2.2. Definition of Group Timers + + The group timer is only used when a group is in EXCLUDE mode and it + represents the time for the *filter-mode* of the group to expire and + switch to INCLUDE mode. + */ + struct thread *t_group_timer; + + /* Shared between group-specific and + group-and-source-specific retransmissions */ + struct thread *t_group_query_retransmit_timer; + + /* Counter exclusive for group-specific retransmissions + (not used by group-and-source-specific retransmissions, + since sources have their counters) */ + int group_specific_query_retransmit_count; + + /* compatibility mode - igmp v1, v2 or v3 */ + int igmp_version; + + struct in_addr group_addr; + int group_filtermode_isexcl; /* 0=INCLUDE, 1=EXCLUDE */ + struct list *group_source_list; /* list of struct igmp_source */ + time_t group_creation; + struct igmp_sock *group_igmp_sock; /* back pointer */ + int64_t last_igmp_v1_report_dsec; + int64_t last_igmp_v2_report_dsec; }; -struct igmp_group *find_group_by_addr (struct igmp_sock *igmp, - struct in_addr group_addr); +struct igmp_group *find_group_by_addr(struct igmp_sock *igmp, + struct in_addr group_addr); struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, struct in_addr group_addr); @@ -175,24 +176,17 @@ void igmp_group_delete_empty_include(struct igmp_group *group); void igmp_startup_mode_on(struct igmp_sock *igmp); -void igmp_group_timer_on(struct igmp_group *group, - long interval_msec, const char *ifname); - -struct igmp_source * -source_new (struct igmp_group *group, - struct in_addr src_addr); - -void igmp_send_query(int igmp_version, - struct igmp_group *group, - int fd, - const char *ifname, - char *query_buf, - int query_buf_size, - int num_sources, - struct in_addr dst_addr, - struct in_addr group_addr, - int query_max_response_time_dsec, - uint8_t s_flag, - uint8_t querier_robustness_variable, - uint16_t querier_query_interval); +void igmp_group_timer_on(struct igmp_group *group, long interval_msec, + const char *ifname); + +struct igmp_source *source_new(struct igmp_group *group, + struct in_addr src_addr); + +void igmp_send_query(int igmp_version, struct igmp_group *group, int fd, + const char *ifname, char *query_buf, int query_buf_size, + int num_sources, struct in_addr dst_addr, + struct in_addr group_addr, + int query_max_response_time_dsec, uint8_t s_flag, + uint8_t querier_robustness_variable, + uint16_t querier_query_interval); #endif /* PIM_IGMP_H */ diff --git a/pimd/pim_igmp_join.h b/pimd/pim_igmp_join.h index 31fc1b047..abee08006 100644 --- a/pimd/pim_igmp_join.h +++ b/pimd/pim_igmp_join.h @@ -28,11 +28,10 @@ #ifndef MCAST_JOIN_SOURCE_GROUP #define MCAST_JOIN_SOURCE_GROUP 46 -struct group_source_req -{ - uint32_t gsr_interface; - struct sockaddr_storage gsr_group; - struct sockaddr_storage gsr_source; +struct group_source_req { + uint32_t gsr_interface; + struct sockaddr_storage gsr_group; + struct sockaddr_storage gsr_source; }; #endif @@ -40,29 +39,29 @@ static int pim_igmp_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr, struct in_addr source_addr) { - struct group_source_req req; - struct sockaddr_in group; - struct sockaddr_in source; + struct group_source_req req; + struct sockaddr_in group; + struct sockaddr_in source; - memset(&req, 0, sizeof(req)); - memset(&group, 0, sizeof(group)); - group.sin_family = AF_INET; - group.sin_addr = group_addr; - group.sin_port = htons(0); - memcpy(&req.gsr_group, &group, sizeof(struct sockaddr_in)); + memset(&req, 0, sizeof(req)); + memset(&group, 0, sizeof(group)); + group.sin_family = AF_INET; + group.sin_addr = group_addr; + group.sin_port = htons(0); + memcpy(&req.gsr_group, &group, sizeof(struct sockaddr_in)); - memset(&source, 0, sizeof(source)); - source.sin_family = AF_INET; - source.sin_addr = source_addr; - source.sin_port = htons(0); - memcpy(&req.gsr_source, &source, sizeof(struct sockaddr_in)); + memset(&source, 0, sizeof(source)); + source.sin_family = AF_INET; + source.sin_addr = source_addr; + source.sin_port = htons(0); + memcpy(&req.gsr_source, &source, sizeof(struct sockaddr_in)); - req.gsr_interface = ifindex; + req.gsr_interface = ifindex; - return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, - &req, sizeof(req)); + return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, &req, + sizeof(req)); - return 0; + return 0; } #endif /* PIM_IGMP_JOIN_H */ diff --git a/pimd/pim_igmpv2.c b/pimd/pim_igmpv2.c index d4b3010d3..efa36e618 100644 --- a/pimd/pim_igmpv2.c +++ b/pimd/pim_igmpv2.c @@ -29,161 +29,161 @@ #include "pim_util.h" -static void -on_trace (const char *label, - struct interface *ifp, struct in_addr from) +static void on_trace(const char *label, struct interface *ifp, + struct in_addr from) { - if (PIM_DEBUG_IGMP_TRACE) { - char from_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<from?>", from, from_str, sizeof(from_str)); - zlog_debug("%s: from %s on %s", - label, from_str, ifp->name); - } + if (PIM_DEBUG_IGMP_TRACE) { + char from_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<from?>", from, from_str, sizeof(from_str)); + zlog_debug("%s: from %s on %s", label, from_str, ifp->name); + } } -void -igmp_v2_send_query (struct igmp_group *group, - int fd, - const char *ifname, - char *query_buf, - struct in_addr dst_addr, - struct in_addr group_addr, - int query_max_response_time_dsec) +void igmp_v2_send_query(struct igmp_group *group, int fd, const char *ifname, + char *query_buf, struct in_addr dst_addr, + struct in_addr group_addr, + int query_max_response_time_dsec) { - ssize_t msg_size = 8; - uint8_t max_resp_code; - ssize_t sent; - struct sockaddr_in to; - socklen_t tolen; - uint16_t checksum; - - /* max_resp_code must be non-zero else this will look like an IGMP v1 query */ - max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); - zassert(max_resp_code > 0); - - query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY; - query_buf[1] = max_resp_code; - *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = 0; /* for computing checksum */ - memcpy(query_buf+4, &group_addr, sizeof(struct in_addr)); - - checksum = in_cksum(query_buf, msg_size); - *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; - - if (PIM_DEBUG_IGMP_PACKETS) { - char dst_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); - pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); - zlog_debug("Send IGMPv2 QUERY to %s on %s for group %s", - dst_str, ifname, group_str); - } - - memset(&to, 0, sizeof(to)); - to.sin_family = AF_INET; - to.sin_addr = dst_addr; - tolen = sizeof(to); - - sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, - (struct sockaddr *)&to, tolen); - if (sent != (ssize_t) msg_size) { - char dst_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); - pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); - if (sent < 0) { - zlog_warn("Send IGMPv2 QUERY failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s", - dst_str, ifname, group_str, msg_size, errno, safe_strerror(errno)); - } - else { - zlog_warn("Send IGMPv2 QUERY failed due to %s on %s: group=%s msg_size=%zd: sent=%zd", - dst_str, ifname, group_str, msg_size, sent); - } - return; - } + ssize_t msg_size = 8; + uint8_t max_resp_code; + ssize_t sent; + struct sockaddr_in to; + socklen_t tolen; + uint16_t checksum; + + /* max_resp_code must be non-zero else this will look like an IGMP v1 + * query */ + max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); + zassert(max_resp_code > 0); + + query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY; + query_buf[1] = max_resp_code; + *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = + 0; /* for computing checksum */ + memcpy(query_buf + 4, &group_addr, sizeof(struct in_addr)); + + checksum = in_cksum(query_buf, msg_size); + *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; + + if (PIM_DEBUG_IGMP_PACKETS) { + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); + pim_inet4_dump("<group?>", group_addr, group_str, + sizeof(group_str)); + zlog_debug("Send IGMPv2 QUERY to %s on %s for group %s", + dst_str, ifname, group_str); + } + + memset(&to, 0, sizeof(to)); + to.sin_family = AF_INET; + to.sin_addr = dst_addr; + tolen = sizeof(to); + + sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, + (struct sockaddr *)&to, tolen); + if (sent != (ssize_t)msg_size) { + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); + pim_inet4_dump("<group?>", group_addr, group_str, + sizeof(group_str)); + if (sent < 0) { + zlog_warn( + "Send IGMPv2 QUERY failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s", + dst_str, ifname, group_str, msg_size, errno, + safe_strerror(errno)); + } else { + zlog_warn( + "Send IGMPv2 QUERY failed due to %s on %s: group=%s msg_size=%zd: sent=%zd", + dst_str, ifname, group_str, msg_size, sent); + } + return; + } } -int -igmp_v2_recv_report (struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) +int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from, + const char *from_str, char *igmp_msg, int igmp_msg_len) { - struct interface *ifp = igmp->interface; - struct in_addr group_addr; - char group_str[INET_ADDRSTRLEN]; - - on_trace(__PRETTY_FUNCTION__, igmp->interface, from); - - if (igmp_msg_len != IGMP_V12_MSG_SIZE) { - zlog_warn("Recv IGMPv2 REPORT from %s on %s: size=%d other than correct=%d", - from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); - return -1; - } - - memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - - if (PIM_DEBUG_IGMP_PACKETS) { - pim_inet4_dump("<dst?>", group_addr, group_str, sizeof(group_str)); - zlog_debug("Recv IGMPv2 REPORT from %s on %s for %s", - from_str, ifp->name, group_str); - } - - /* - * RFC 3376 - * 7.3.2. In the Presence of Older Version Group Members - * - * When Group Compatibility Mode is IGMPv2, a router internally - * translates the following IGMPv2 messages for that group to their - * IGMPv3 equivalents: - * - * IGMPv2 Message IGMPv3 Equivalent - * -------------- ----------------- - * Report IS_EX( {} ) - * Leave TO_IN( {} ) - */ - igmpv3_report_isex (igmp, from, group_addr, 0, NULL, 1); - - return 0; + struct interface *ifp = igmp->interface; + struct in_addr group_addr; + char group_str[INET_ADDRSTRLEN]; + + on_trace(__PRETTY_FUNCTION__, igmp->interface, from); + + if (igmp_msg_len != IGMP_V12_MSG_SIZE) { + zlog_warn( + "Recv IGMPv2 REPORT from %s on %s: size=%d other than correct=%d", + from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); + return -1; + } + + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + + if (PIM_DEBUG_IGMP_PACKETS) { + pim_inet4_dump("<dst?>", group_addr, group_str, + sizeof(group_str)); + zlog_debug("Recv IGMPv2 REPORT from %s on %s for %s", from_str, + ifp->name, group_str); + } + + /* + * RFC 3376 + * 7.3.2. In the Presence of Older Version Group Members + * + * When Group Compatibility Mode is IGMPv2, a router internally + * translates the following IGMPv2 messages for that group to their + * IGMPv3 equivalents: + * + * IGMPv2 Message IGMPv3 Equivalent + * -------------- ----------------- + * Report IS_EX( {} ) + * Leave TO_IN( {} ) + */ + igmpv3_report_isex(igmp, from, group_addr, 0, NULL, 1); + + return 0; } -int -igmp_v2_recv_leave (struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) +int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from, + const char *from_str, char *igmp_msg, int igmp_msg_len) { - struct interface *ifp = igmp->interface; - struct in_addr group_addr; - char group_str[INET_ADDRSTRLEN]; - - on_trace(__PRETTY_FUNCTION__, igmp->interface, from); - - if (igmp_msg_len != IGMP_V12_MSG_SIZE) { - zlog_warn("Recv IGMPv2 LEAVE from %s on %s: size=%d other than correct=%d", - from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); - return -1; - } - - memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - - if (PIM_DEBUG_IGMP_PACKETS) { - pim_inet4_dump("<dst?>", group_addr, group_str, sizeof(group_str)); - zlog_debug("Recv IGMPv2 LEAVE from %s on %s for %s", - from_str, ifp->name, group_str); - } - - /* - * RFC 3376 - * 7.3.2. In the Presence of Older Version Group Members - * - * When Group Compatibility Mode is IGMPv2, a router internally - * translates the following IGMPv2 messages for that group to their - * IGMPv3 equivalents: - * - * IGMPv2 Message IGMPv3 Equivalent - * -------------- ----------------- - * Report IS_EX( {} ) - * Leave TO_IN( {} ) - */ - igmpv3_report_toin (igmp, from, group_addr, 0, NULL); - - return 0; + struct interface *ifp = igmp->interface; + struct in_addr group_addr; + char group_str[INET_ADDRSTRLEN]; + + on_trace(__PRETTY_FUNCTION__, igmp->interface, from); + + if (igmp_msg_len != IGMP_V12_MSG_SIZE) { + zlog_warn( + "Recv IGMPv2 LEAVE from %s on %s: size=%d other than correct=%d", + from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); + return -1; + } + + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + + if (PIM_DEBUG_IGMP_PACKETS) { + pim_inet4_dump("<dst?>", group_addr, group_str, + sizeof(group_str)); + zlog_debug("Recv IGMPv2 LEAVE from %s on %s for %s", from_str, + ifp->name, group_str); + } + + /* + * RFC 3376 + * 7.3.2. In the Presence of Older Version Group Members + * + * When Group Compatibility Mode is IGMPv2, a router internally + * translates the following IGMPv2 messages for that group to their + * IGMPv3 equivalents: + * + * IGMPv2 Message IGMPv3 Equivalent + * -------------- ----------------- + * Report IS_EX( {} ) + * Leave TO_IN( {} ) + */ + igmpv3_report_toin(igmp, from, group_addr, 0, NULL); + + return 0; } diff --git a/pimd/pim_igmpv2.h b/pimd/pim_igmpv2.h index fa8d16394..f0a6fdc5f 100644 --- a/pimd/pim_igmpv2.h +++ b/pimd/pim_igmpv2.h @@ -21,20 +21,15 @@ #ifndef PIM_IGMPV2_H #define PIM_IGMPV2_H -void igmp_v2_send_query (struct igmp_group *group, - int fd, - const char *ifname, - char *query_buf, - struct in_addr dst_addr, - struct in_addr group_addr, - int query_max_response_time_dsec); +void igmp_v2_send_query(struct igmp_group *group, int fd, const char *ifname, + char *query_buf, struct in_addr dst_addr, + struct in_addr group_addr, + int query_max_response_time_dsec); -int igmp_v2_recv_report (struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len); +int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from, + const char *from_str, char *igmp_msg, int igmp_msg_len); -int igmp_v2_recv_leave (struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len); +int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from, + const char *from_str, char *igmp_msg, int igmp_msg_len); #endif /* PIM_IGMPV2_H */ diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index ad37ad876..880d840ea 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -39,269 +39,270 @@ static void group_query_send(struct igmp_group *group); static void source_query_send_by_flag(struct igmp_group *group, int num_sources_tosend); -static void on_trace(const char *label, - struct interface *ifp, struct in_addr from, - struct in_addr group_addr, +static void on_trace(const char *label, struct interface *ifp, + struct in_addr from, struct in_addr group_addr, int num_sources, struct in_addr *sources) { - if (PIM_DEBUG_IGMP_TRACE) { - char from_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; + if (PIM_DEBUG_IGMP_TRACE) { + char from_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<from?>", from, from_str, sizeof(from_str)); - pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); + pim_inet4_dump("<from?>", from, from_str, sizeof(from_str)); + pim_inet4_dump("<group?>", group_addr, group_str, + sizeof(group_str)); - zlog_debug("%s: from %s on %s: group=%s sources=%d", - label, from_str, ifp->name, group_str, num_sources); - } + zlog_debug("%s: from %s on %s: group=%s sources=%d", label, + from_str, ifp->name, group_str, num_sources); + } } void igmp_group_reset_gmi(struct igmp_group *group) { - long group_membership_interval_msec; - struct pim_interface *pim_ifp; - struct igmp_sock *igmp; - struct interface *ifp; - - igmp = group->group_igmp_sock; - ifp = igmp->interface; - pim_ifp = ifp->info; - - /* - RFC 3376: 8.4. Group Membership Interval - - The Group Membership Interval is the amount of time that must pass - before a multicast router decides there are no more members of a - group or a particular source on a network. - - This value MUST be ((the Robustness Variable) times (the Query - Interval)) plus (one Query Response Interval). - - group_membership_interval_msec = querier_robustness_variable * - (1000 * querier_query_interval) + - 100 * query_response_interval_dsec; - */ - group_membership_interval_msec = - PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec); - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("Resetting group %s timer to GMI=%ld.%03ld sec on %s", - group_str, - group_membership_interval_msec / 1000, - group_membership_interval_msec % 1000, - ifp->name); - } - - /* - RFC 3376: 6.2.2. Definition of Group Timers - - The group timer is only used when a group is in EXCLUDE mode and - it represents the time for the *filter-mode* of the group to - expire and switch to INCLUDE mode. - */ - zassert(group->group_filtermode_isexcl); - - igmp_group_timer_on(group, group_membership_interval_msec, ifp->name); + long group_membership_interval_msec; + struct pim_interface *pim_ifp; + struct igmp_sock *igmp; + struct interface *ifp; + + igmp = group->group_igmp_sock; + ifp = igmp->interface; + pim_ifp = ifp->info; + + /* + RFC 3376: 8.4. Group Membership Interval + + The Group Membership Interval is the amount of time that must pass + before a multicast router decides there are no more members of a + group or a particular source on a network. + + This value MUST be ((the Robustness Variable) times (the Query + Interval)) plus (one Query Response Interval). + + group_membership_interval_msec = querier_robustness_variable * + (1000 * querier_query_interval) + + 100 * query_response_interval_dsec; + */ + group_membership_interval_msec = PIM_IGMP_GMI_MSEC( + igmp->querier_robustness_variable, igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec); + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "Resetting group %s timer to GMI=%ld.%03ld sec on %s", + group_str, group_membership_interval_msec / 1000, + group_membership_interval_msec % 1000, ifp->name); + } + + /* + RFC 3376: 6.2.2. Definition of Group Timers + + The group timer is only used when a group is in EXCLUDE mode and + it represents the time for the *filter-mode* of the group to + expire and switch to INCLUDE mode. + */ + zassert(group->group_filtermode_isexcl); + + igmp_group_timer_on(group, group_membership_interval_msec, ifp->name); } static int igmp_source_timer(struct thread *t) { - struct igmp_source *source; - struct igmp_group *group; - - source = THREAD_ARG(t); - - group = source->source_group; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); - zlog_debug("%s: Source timer expired for group %s source %s on %s", - __PRETTY_FUNCTION__, - group_str, source_str, - group->group_igmp_sock->interface->name); - } - - /* - RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules - - Group - Filter-Mode Source Timer Value Action - ----------- ------------------ ------ - INCLUDE TIMER == 0 Suggest to stop forwarding - traffic from source and - remove source record. If - there are no more source - records for the group, delete - group record. - - EXCLUDE TIMER == 0 Suggest to not forward - traffic from source - (DO NOT remove record) - - Source timer switched from (T > 0) to (T == 0): disable forwarding. - */ - - if (group->group_filtermode_isexcl) { - /* EXCLUDE mode */ - - igmp_source_forward_stop(source); - } - else { - /* INCLUDE mode */ - - /* igmp_source_delete() will stop forwarding source */ - igmp_source_delete(source); - - /* - If there are no more source records for the group, delete group - record. - */ - if (!listcount(group->group_source_list)) { - igmp_group_delete_empty_include(group); - } - } - - return 0; + struct igmp_source *source; + struct igmp_group *group; + + source = THREAD_ARG(t); + + group = source->source_group; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<source?>", source->source_addr, source_str, + sizeof(source_str)); + zlog_debug( + "%s: Source timer expired for group %s source %s on %s", + __PRETTY_FUNCTION__, group_str, source_str, + group->group_igmp_sock->interface->name); + } + + /* + RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules + + Group + Filter-Mode Source Timer Value Action + ----------- ------------------ ------ + INCLUDE TIMER == 0 Suggest to stop forwarding + traffic from source and + remove source record. If + there are no more source + records for the group, delete + group record. + + EXCLUDE TIMER == 0 Suggest to not forward + traffic from source + (DO NOT remove record) + + Source timer switched from (T > 0) to (T == 0): disable forwarding. + */ + + if (group->group_filtermode_isexcl) { + /* EXCLUDE mode */ + + igmp_source_forward_stop(source); + } else { + /* INCLUDE mode */ + + /* igmp_source_delete() will stop forwarding source */ + igmp_source_delete(source); + + /* + If there are no more source records for the group, delete + group + record. + */ + if (!listcount(group->group_source_list)) { + igmp_group_delete_empty_include(group); + } + } + + return 0; } static void source_timer_off(struct igmp_group *group, struct igmp_source *source) { - if (!source->t_source_timer) - return; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); - zlog_debug("Cancelling TIMER event for group %s source %s on %s", - group_str, source_str, - group->group_igmp_sock->interface->name); - } - - THREAD_OFF(source->t_source_timer); + if (!source->t_source_timer) + return; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<source?>", source->source_addr, source_str, + sizeof(source_str)); + zlog_debug( + "Cancelling TIMER event for group %s source %s on %s", + group_str, source_str, + group->group_igmp_sock->interface->name); + } + + THREAD_OFF(source->t_source_timer); } static void igmp_source_timer_on(struct igmp_group *group, - struct igmp_source *source, - long interval_msec) + struct igmp_source *source, long interval_msec) { - source_timer_off(group, source); - - if (PIM_DEBUG_IGMP_EVENTS) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); - zlog_debug("Scheduling %ld.%03ld sec TIMER event for group %s source %s on %s", - interval_msec / 1000, - interval_msec % 1000, - group_str, source_str, - group->group_igmp_sock->interface->name); - } - - thread_add_timer_msec(master, igmp_source_timer, source, interval_msec, - &source->t_source_timer); - - /* - RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules - - Source timer switched from (T == 0) to (T > 0): enable forwarding. - */ - igmp_source_forward_start(source); + source_timer_off(group, source); + + if (PIM_DEBUG_IGMP_EVENTS) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<source?>", source->source_addr, source_str, + sizeof(source_str)); + zlog_debug( + "Scheduling %ld.%03ld sec TIMER event for group %s source %s on %s", + interval_msec / 1000, interval_msec % 1000, group_str, + source_str, group->group_igmp_sock->interface->name); + } + + thread_add_timer_msec(master, igmp_source_timer, source, interval_msec, + &source->t_source_timer); + + /* + RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules + + Source timer switched from (T == 0) to (T > 0): enable forwarding. + */ + igmp_source_forward_start(source); } -void igmp_source_reset_gmi(struct igmp_sock *igmp, - struct igmp_group *group, +void igmp_source_reset_gmi(struct igmp_sock *igmp, struct igmp_group *group, struct igmp_source *source) { - long group_membership_interval_msec; - struct pim_interface *pim_ifp; - struct interface *ifp; - - ifp = igmp->interface; - pim_ifp = ifp->info; - - group_membership_interval_msec = - PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec); - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); - - zlog_debug("Resetting source %s timer to GMI=%ld.%03ld sec for group %s on %s", - source_str, - group_membership_interval_msec / 1000, - group_membership_interval_msec % 1000, - group_str, - ifp->name); - } - - igmp_source_timer_on(group, source, - group_membership_interval_msec); + long group_membership_interval_msec; + struct pim_interface *pim_ifp; + struct interface *ifp; + + ifp = igmp->interface; + pim_ifp = ifp->info; + + group_membership_interval_msec = PIM_IGMP_GMI_MSEC( + igmp->querier_robustness_variable, igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec); + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<source?>", source->source_addr, source_str, + sizeof(source_str)); + + zlog_debug( + "Resetting source %s timer to GMI=%ld.%03ld sec for group %s on %s", + source_str, group_membership_interval_msec / 1000, + group_membership_interval_msec % 1000, group_str, + ifp->name); + } + + igmp_source_timer_on(group, source, group_membership_interval_msec); } static void source_mark_delete_flag(struct igmp_group *group) { - struct listnode *src_node; - struct igmp_source *src; + struct listnode *src_node; + struct igmp_source *src; - for (ALL_LIST_ELEMENTS_RO (group->group_source_list, src_node, src)) { - IGMP_SOURCE_DO_DELETE(src->source_flags); - } + for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { + IGMP_SOURCE_DO_DELETE(src->source_flags); + } } -static void source_mark_send_flag (struct igmp_group *group) +static void source_mark_send_flag(struct igmp_group *group) { - struct listnode *src_node; - struct igmp_source *src; + struct listnode *src_node; + struct igmp_source *src; - for (ALL_LIST_ELEMENTS_RO (group->group_source_list, src_node, src)) { - IGMP_SOURCE_DO_SEND(src->source_flags); - } + for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { + IGMP_SOURCE_DO_SEND(src->source_flags); + } } -static int source_mark_send_flag_by_timer (struct igmp_group *group) +static int source_mark_send_flag_by_timer(struct igmp_group *group) { - struct listnode *src_node; - struct igmp_source *src; - int num_marked_sources = 0; - - for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { - /* Is source timer running? */ - if (src->t_source_timer) { - IGMP_SOURCE_DO_SEND(src->source_flags); - ++num_marked_sources; - } - else { - IGMP_SOURCE_DONT_SEND(src->source_flags); - } - } - - return num_marked_sources; + struct listnode *src_node; + struct igmp_source *src; + int num_marked_sources = 0; + + for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { + /* Is source timer running? */ + if (src->t_source_timer) { + IGMP_SOURCE_DO_SEND(src->source_flags); + ++num_marked_sources; + } else { + IGMP_SOURCE_DONT_SEND(src->source_flags); + } + } + + return num_marked_sources; } static void source_clear_send_flag(struct list *source_list) { - struct listnode *src_node; - struct igmp_source *src; + struct listnode *src_node; + struct igmp_source *src; - for (ALL_LIST_ELEMENTS_RO(source_list, src_node, src)) { - IGMP_SOURCE_DONT_SEND(src->source_flags); - } + for (ALL_LIST_ELEMENTS_RO(source_list, src_node, src)) { + IGMP_SOURCE_DONT_SEND(src->source_flags); + } } /* @@ -309,27 +310,27 @@ static void source_clear_send_flag(struct list *source_list) */ static void group_exclude_fwd_anysrc_ifempty(struct igmp_group *group) { - zassert(group->group_filtermode_isexcl); + zassert(group->group_filtermode_isexcl); - if (listcount(group->group_source_list) < 1) { - igmp_anysource_forward_start(group); - } + if (listcount(group->group_source_list) < 1) { + igmp_anysource_forward_start(group); + } } void igmp_source_free(struct igmp_source *source) { - /* make sure there is no source timer running */ - zassert(!source->t_source_timer); + /* make sure there is no source timer running */ + zassert(!source->t_source_timer); - XFREE(MTYPE_PIM_IGMP_GROUP_SOURCE, source); + XFREE(MTYPE_PIM_IGMP_GROUP_SOURCE, source); } static void source_channel_oil_detach(struct igmp_source *source) { - if (source->source_channel_oil) { - pim_channel_oil_del(source->source_channel_oil); - source->source_channel_oil = NULL; - } + if (source->source_channel_oil) { + pim_channel_oil_del(source->source_channel_oil); + source->source_channel_oil = NULL; + } } /* @@ -338,662 +339,659 @@ static void source_channel_oil_detach(struct igmp_source *source) */ void igmp_source_delete(struct igmp_source *source) { - struct igmp_group *group; - struct in_addr src; - - group = source->source_group; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); - zlog_debug("Deleting IGMP source %s for group %s from socket %d interface %s c_oil ref_count %d", - source_str, group_str, - group->group_igmp_sock->fd, - group->group_igmp_sock->interface->name, - source->source_channel_oil ? source->source_channel_oil->oil_ref_count : 0); - } - - source_timer_off(group, source); - igmp_source_forward_stop(source); - - /* sanity check that forwarding has been disabled */ - if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: forwarding=ON(!) IGMP source %s for group %s from socket %d interface %s", - __PRETTY_FUNCTION__, - source_str, group_str, - group->group_igmp_sock->fd, - group->group_igmp_sock->interface->name); - /* warning only */ - } - - source_channel_oil_detach(source); - - /* - notice that listnode_delete() can't be moved - into igmp_source_free() because the later is - called by list_delete_all_node() - */ - listnode_delete(group->group_source_list, source); - - src.s_addr = source->source_addr.s_addr; - igmp_source_free(source); - - /* Group source list is empty and current source is * then - *,G group going away so do not trigger start */ - if (group->group_filtermode_isexcl && - (listcount (group->group_source_list) != 0) && - src.s_addr != INADDR_ANY) - { - group_exclude_fwd_anysrc_ifempty (group); - } + struct igmp_group *group; + struct in_addr src; + + group = source->source_group; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<source?>", source->source_addr, source_str, + sizeof(source_str)); + zlog_debug( + "Deleting IGMP source %s for group %s from socket %d interface %s c_oil ref_count %d", + source_str, group_str, group->group_igmp_sock->fd, + group->group_igmp_sock->interface->name, + source->source_channel_oil + ? source->source_channel_oil->oil_ref_count + : 0); + } + + source_timer_off(group, source); + igmp_source_forward_stop(source); + + /* sanity check that forwarding has been disabled */ + if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<source?>", source->source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: forwarding=ON(!) IGMP source %s for group %s from socket %d interface %s", + __PRETTY_FUNCTION__, source_str, group_str, + group->group_igmp_sock->fd, + group->group_igmp_sock->interface->name); + /* warning only */ + } + + source_channel_oil_detach(source); + + /* + notice that listnode_delete() can't be moved + into igmp_source_free() because the later is + called by list_delete_all_node() + */ + listnode_delete(group->group_source_list, source); + + src.s_addr = source->source_addr.s_addr; + igmp_source_free(source); + + /* Group source list is empty and current source is * then + *,G group going away so do not trigger start */ + if (group->group_filtermode_isexcl + && (listcount(group->group_source_list) != 0) + && src.s_addr != INADDR_ANY) { + group_exclude_fwd_anysrc_ifempty(group); + } } static void source_delete_by_flag(struct list *source_list) { - struct listnode *src_node; - struct listnode *src_nextnode; - struct igmp_source *src; - - for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src)) - if (IGMP_SOURCE_TEST_DELETE(src->source_flags)) - igmp_source_delete(src); + struct listnode *src_node; + struct listnode *src_nextnode; + struct igmp_source *src; + + for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src)) + if (IGMP_SOURCE_TEST_DELETE(src->source_flags)) + igmp_source_delete(src); } void igmp_source_delete_expired(struct list *source_list) { - struct listnode *src_node; - struct listnode *src_nextnode; - struct igmp_source *src; - - for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src)) - if (!src->t_source_timer) - igmp_source_delete(src); + struct listnode *src_node; + struct listnode *src_nextnode; + struct igmp_source *src; + + for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src)) + if (!src->t_source_timer) + igmp_source_delete(src); } struct igmp_source *igmp_find_source_by_addr(struct igmp_group *group, struct in_addr src_addr) { - struct listnode *src_node; - struct igmp_source *src; + struct listnode *src_node; + struct igmp_source *src; - for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) - if (src_addr.s_addr == src->source_addr.s_addr) - return src; + for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) + if (src_addr.s_addr == src->source_addr.s_addr) + return src; - return 0; + return 0; } -struct igmp_source * -source_new (struct igmp_group *group, - struct in_addr src_addr) +struct igmp_source *source_new(struct igmp_group *group, + struct in_addr src_addr) { - struct igmp_source *src; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", src_addr, source_str, sizeof(source_str)); - zlog_debug("Creating new IGMP source %s for group %s on socket %d interface %s", - source_str, group_str, - group->group_igmp_sock->fd, - group->group_igmp_sock->interface->name); - } - - src = XCALLOC(MTYPE_PIM_IGMP_GROUP_SOURCE, sizeof(*src)); - if (!src) { - zlog_warn("%s %s: XCALLOC() failure", - __FILE__, __PRETTY_FUNCTION__); - return 0; /* error, not found, could not create */ - } - - src->t_source_timer = NULL; - src->source_group = group; /* back pointer */ - src->source_addr = src_addr; - src->source_creation = pim_time_monotonic_sec(); - src->source_flags = 0; - src->source_query_retransmit_count = 0; - src->source_channel_oil = NULL; - - listnode_add(group->group_source_list, src); - - /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ - igmp_anysource_forward_stop(group); - - return src; + struct igmp_source *src; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<source?>", src_addr, source_str, + sizeof(source_str)); + zlog_debug( + "Creating new IGMP source %s for group %s on socket %d interface %s", + source_str, group_str, group->group_igmp_sock->fd, + group->group_igmp_sock->interface->name); + } + + src = XCALLOC(MTYPE_PIM_IGMP_GROUP_SOURCE, sizeof(*src)); + if (!src) { + zlog_warn("%s %s: XCALLOC() failure", __FILE__, + __PRETTY_FUNCTION__); + return 0; /* error, not found, could not create */ + } + + src->t_source_timer = NULL; + src->source_group = group; /* back pointer */ + src->source_addr = src_addr; + src->source_creation = pim_time_monotonic_sec(); + src->source_flags = 0; + src->source_query_retransmit_count = 0; + src->source_channel_oil = NULL; + + listnode_add(group->group_source_list, src); + + /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ + igmp_anysource_forward_stop(group); + + return src; } static struct igmp_source *add_source_by_addr(struct igmp_sock *igmp, struct igmp_group *group, struct in_addr src_addr) { - struct igmp_source *src; + struct igmp_source *src; - src = igmp_find_source_by_addr(group, src_addr); - if (src) { - return src; - } + src = igmp_find_source_by_addr(group, src_addr); + if (src) { + return src; + } - src = source_new(group, src_addr); - if (!src) { - return 0; - } + src = source_new(group, src_addr); + if (!src) { + return 0; + } - return src; + return src; } static void allow(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources) + struct in_addr group_addr, int num_sources, + struct in_addr *sources) { - struct igmp_source *source; - struct igmp_group *group; - int i; - - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return; - } - - /* scan received sources */ - for (i = 0; i < num_sources; ++i) { - struct in_addr *src_addr; - - src_addr = sources + i; - - source = add_source_by_addr(igmp, group, *src_addr); - if (!source) { - continue; - } - - /* - RFC 3376: 6.4.1. Reception of Current-State Records - - When receiving IS_IN reports for groups in EXCLUDE mode is - sources should be moved from set with (timers = 0) to set with - (timers > 0). - - igmp_source_reset_gmi() below, resetting the source timers to - GMI, accomplishes this. - */ - igmp_source_reset_gmi(igmp, group, source); - - } /* scan received sources */ - - if ((num_sources == 0) && - (group->group_filtermode_isexcl) && - (listcount (group->group_source_list) == 1)) - { - struct in_addr star = { .s_addr = INADDR_ANY }; - - source = igmp_find_source_by_addr (group, star); - if (source) - igmp_source_reset_gmi (igmp, group, source); - } + struct igmp_source *source; + struct igmp_group *group; + int i; + + /* non-existant group is created as INCLUDE {empty} */ + group = igmp_add_group_by_addr(igmp, group_addr); + if (!group) { + return; + } + + /* scan received sources */ + for (i = 0; i < num_sources; ++i) { + struct in_addr *src_addr; + + src_addr = sources + i; + + source = add_source_by_addr(igmp, group, *src_addr); + if (!source) { + continue; + } + + /* + RFC 3376: 6.4.1. Reception of Current-State Records + + When receiving IS_IN reports for groups in EXCLUDE mode is + sources should be moved from set with (timers = 0) to set with + (timers > 0). + + igmp_source_reset_gmi() below, resetting the source timers to + GMI, accomplishes this. + */ + igmp_source_reset_gmi(igmp, group, source); + + } /* scan received sources */ + + if ((num_sources == 0) && (group->group_filtermode_isexcl) + && (listcount(group->group_source_list) == 1)) { + struct in_addr star = {.s_addr = INADDR_ANY}; + + source = igmp_find_source_by_addr(group, star); + if (source) + igmp_source_reset_gmi(igmp, group, source); + } } void igmpv3_report_isin(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources) + struct in_addr group_addr, int num_sources, + struct in_addr *sources) { - on_trace(__PRETTY_FUNCTION__, - igmp->interface, from, group_addr, num_sources, sources); + on_trace(__PRETTY_FUNCTION__, igmp->interface, from, group_addr, + num_sources, sources); - allow(igmp, from, group_addr, num_sources, sources); + allow(igmp, from, group_addr, num_sources, sources); } -static void isex_excl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void isex_excl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - struct igmp_source *source; - int i; - - /* EXCLUDE mode */ - zassert(group->group_filtermode_isexcl); - - /* E.1: set deletion flag for known sources (X,Y) */ - source_mark_delete_flag (group); - - /* scan received sources (A) */ - for (i = 0; i < num_sources; ++i) { - struct in_addr *src_addr; - - src_addr = sources + i; - - /* E.2: lookup reported source from (A) in (X,Y) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (source) { - /* E.3: if found, clear deletion flag: (X*A) or (Y*A) */ - IGMP_SOURCE_DONT_DELETE(source->source_flags); - } - else { - /* E.4: if not found, create source with timer=GMI: (A-X-Y) */ - source = source_new(group, *src_addr); - if (!source) { - /* ugh, internal malloc failure, skip source */ - continue; - } - zassert(!source->t_source_timer); /* timer == 0 */ - igmp_source_reset_gmi(group->group_igmp_sock, group, source); - zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ - } - - } /* scan received sources */ - - /* - * If we are in isexcl mode and num_sources == 0 - * than that means we have a *,g entry that - * needs to be handled - */ - if (group->group_filtermode_isexcl && num_sources == 0) - { - struct in_addr star = { .s_addr = INADDR_ANY }; - source = igmp_find_source_by_addr (group, star); - if (source) - { - IGMP_SOURCE_DONT_DELETE(source->source_flags); - igmp_source_reset_gmi (group->group_igmp_sock, group, source); - } - } - - /* E.5: delete all sources marked with deletion flag: (X-A) and (Y-A) */ - source_delete_by_flag(group->group_source_list); + struct igmp_source *source; + int i; + + /* EXCLUDE mode */ + zassert(group->group_filtermode_isexcl); + + /* E.1: set deletion flag for known sources (X,Y) */ + source_mark_delete_flag(group); + + /* scan received sources (A) */ + for (i = 0; i < num_sources; ++i) { + struct in_addr *src_addr; + + src_addr = sources + i; + + /* E.2: lookup reported source from (A) in (X,Y) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (source) { + /* E.3: if found, clear deletion flag: (X*A) or (Y*A) */ + IGMP_SOURCE_DONT_DELETE(source->source_flags); + } else { + /* E.4: if not found, create source with timer=GMI: + * (A-X-Y) */ + source = source_new(group, *src_addr); + if (!source) { + /* ugh, internal malloc failure, skip source */ + continue; + } + zassert(!source->t_source_timer); /* timer == 0 */ + igmp_source_reset_gmi(group->group_igmp_sock, group, + source); + zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ + } + + } /* scan received sources */ + + /* + * If we are in isexcl mode and num_sources == 0 + * than that means we have a *,g entry that + * needs to be handled + */ + if (group->group_filtermode_isexcl && num_sources == 0) { + struct in_addr star = {.s_addr = INADDR_ANY}; + source = igmp_find_source_by_addr(group, star); + if (source) { + IGMP_SOURCE_DONT_DELETE(source->source_flags); + igmp_source_reset_gmi(group->group_igmp_sock, group, + source); + } + } + + /* E.5: delete all sources marked with deletion flag: (X-A) and (Y-A) */ + source_delete_by_flag(group->group_source_list); } -static void isex_incl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void isex_incl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - int i; - - /* INCLUDE mode */ - zassert(!group->group_filtermode_isexcl); - - /* I.1: set deletion flag for known sources (A) */ - source_mark_delete_flag (group); - - /* scan received sources (B) */ - for (i = 0; i < num_sources; ++i) { - struct igmp_source *source; - struct in_addr *src_addr; - - src_addr = sources + i; - - /* I.2: lookup reported source (B) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (source) { - /* I.3: if found, clear deletion flag (A*B) */ - IGMP_SOURCE_DONT_DELETE(source->source_flags); - } - else { - /* I.4: if not found, create source with timer=0 (B-A) */ - source = source_new(group, *src_addr); - if (!source) { - /* ugh, internal malloc failure, skip source */ - continue; - } - zassert(!source->t_source_timer); /* (B-A) timer=0 */ - } - - } /* scan received sources */ - - /* I.5: delete all sources marked with deletion flag (A-B) */ - source_delete_by_flag(group->group_source_list); - - group->group_filtermode_isexcl = 1; /* boolean=true */ - - zassert(group->group_filtermode_isexcl); - - group_exclude_fwd_anysrc_ifempty(group); + int i; + + /* INCLUDE mode */ + zassert(!group->group_filtermode_isexcl); + + /* I.1: set deletion flag for known sources (A) */ + source_mark_delete_flag(group); + + /* scan received sources (B) */ + for (i = 0; i < num_sources; ++i) { + struct igmp_source *source; + struct in_addr *src_addr; + + src_addr = sources + i; + + /* I.2: lookup reported source (B) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (source) { + /* I.3: if found, clear deletion flag (A*B) */ + IGMP_SOURCE_DONT_DELETE(source->source_flags); + } else { + /* I.4: if not found, create source with timer=0 (B-A) + */ + source = source_new(group, *src_addr); + if (!source) { + /* ugh, internal malloc failure, skip source */ + continue; + } + zassert(!source->t_source_timer); /* (B-A) timer=0 */ + } + + } /* scan received sources */ + + /* I.5: delete all sources marked with deletion flag (A-B) */ + source_delete_by_flag(group->group_source_list); + + group->group_filtermode_isexcl = 1; /* boolean=true */ + + zassert(group->group_filtermode_isexcl); + + group_exclude_fwd_anysrc_ifempty(group); } void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources, - int from_igmp_v2_report) + struct in_addr group_addr, int num_sources, + struct in_addr *sources, int from_igmp_v2_report) { - struct interface *ifp = igmp->interface; - struct igmp_group *group; - - on_trace(__PRETTY_FUNCTION__, - ifp, from, group_addr, num_sources, sources); - - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return; - } - - /* So we can display how we learned the group in our show command output */ - if (from_igmp_v2_report) - group->igmp_version = 2; - - if (group->group_filtermode_isexcl) { - /* EXCLUDE mode */ - isex_excl(group, num_sources, sources); - } - else { - /* INCLUDE mode */ - isex_incl(group, num_sources, sources); - zassert(group->group_filtermode_isexcl); - } - - zassert(group->group_filtermode_isexcl); - - igmp_group_reset_gmi(group); + struct interface *ifp = igmp->interface; + struct igmp_group *group; + + on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, + sources); + + /* non-existant group is created as INCLUDE {empty} */ + group = igmp_add_group_by_addr(igmp, group_addr); + if (!group) { + return; + } + + /* So we can display how we learned the group in our show command output + */ + if (from_igmp_v2_report) + group->igmp_version = 2; + + if (group->group_filtermode_isexcl) { + /* EXCLUDE mode */ + isex_excl(group, num_sources, sources); + } else { + /* INCLUDE mode */ + isex_incl(group, num_sources, sources); + zassert(group->group_filtermode_isexcl); + } + + zassert(group->group_filtermode_isexcl); + + igmp_group_reset_gmi(group); } -static void toin_incl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void toin_incl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - struct igmp_sock *igmp = group->group_igmp_sock; - int num_sources_tosend = listcount(group->group_source_list); - int i; - - /* Set SEND flag for all known sources (A) */ - source_mark_send_flag (group); - - /* Scan received sources (B) */ - for (i = 0; i < num_sources; ++i) { - struct igmp_source *source; - struct in_addr *src_addr; - - src_addr = sources + i; - - /* Lookup reported source (B) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (source) { - /* If found, clear SEND flag (A*B) */ - IGMP_SOURCE_DONT_SEND(source->source_flags); - --num_sources_tosend; - } - else { - /* If not found, create new source */ - source = source_new(group, *src_addr); - if (!source) { - /* ugh, internal malloc failure, skip source */ - continue; - } - } - - /* (B)=GMI */ - igmp_source_reset_gmi(igmp, group, source); - } - - /* Send sources marked with SEND flag: Q(G,A-B) */ - if (num_sources_tosend > 0) { - source_query_send_by_flag(group, num_sources_tosend); - } + struct igmp_sock *igmp = group->group_igmp_sock; + int num_sources_tosend = listcount(group->group_source_list); + int i; + + /* Set SEND flag for all known sources (A) */ + source_mark_send_flag(group); + + /* Scan received sources (B) */ + for (i = 0; i < num_sources; ++i) { + struct igmp_source *source; + struct in_addr *src_addr; + + src_addr = sources + i; + + /* Lookup reported source (B) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (source) { + /* If found, clear SEND flag (A*B) */ + IGMP_SOURCE_DONT_SEND(source->source_flags); + --num_sources_tosend; + } else { + /* If not found, create new source */ + source = source_new(group, *src_addr); + if (!source) { + /* ugh, internal malloc failure, skip source */ + continue; + } + } + + /* (B)=GMI */ + igmp_source_reset_gmi(igmp, group, source); + } + + /* Send sources marked with SEND flag: Q(G,A-B) */ + if (num_sources_tosend > 0) { + source_query_send_by_flag(group, num_sources_tosend); + } } -static void toin_excl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void toin_excl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - struct igmp_sock *igmp = group->group_igmp_sock; - int num_sources_tosend; - int i; - - /* Set SEND flag for X (sources with timer > 0) */ - num_sources_tosend = source_mark_send_flag_by_timer (group); - - /* Scan received sources (A) */ - for (i = 0; i < num_sources; ++i) { - struct igmp_source *source; - struct in_addr *src_addr; - - src_addr = sources + i; - - /* Lookup reported source (A) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (source) { - if (source->t_source_timer) { - /* If found and timer running, clear SEND flag (X*A) */ - IGMP_SOURCE_DONT_SEND(source->source_flags); - --num_sources_tosend; - } - } - else { - /* If not found, create new source */ - source = source_new(group, *src_addr); - if (!source) { - /* ugh, internal malloc failure, skip source */ - continue; - } - } - - /* (A)=GMI */ - igmp_source_reset_gmi(igmp, group, source); - } - - /* Send sources marked with SEND flag: Q(G,X-A) */ - if (num_sources_tosend > 0) { - source_query_send_by_flag(group, num_sources_tosend); - } - - /* Send Q(G) */ - group_query_send(group); + struct igmp_sock *igmp = group->group_igmp_sock; + int num_sources_tosend; + int i; + + /* Set SEND flag for X (sources with timer > 0) */ + num_sources_tosend = source_mark_send_flag_by_timer(group); + + /* Scan received sources (A) */ + for (i = 0; i < num_sources; ++i) { + struct igmp_source *source; + struct in_addr *src_addr; + + src_addr = sources + i; + + /* Lookup reported source (A) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (source) { + if (source->t_source_timer) { + /* If found and timer running, clear SEND flag + * (X*A) */ + IGMP_SOURCE_DONT_SEND(source->source_flags); + --num_sources_tosend; + } + } else { + /* If not found, create new source */ + source = source_new(group, *src_addr); + if (!source) { + /* ugh, internal malloc failure, skip source */ + continue; + } + } + + /* (A)=GMI */ + igmp_source_reset_gmi(igmp, group, source); + } + + /* Send sources marked with SEND flag: Q(G,X-A) */ + if (num_sources_tosend > 0) { + source_query_send_by_flag(group, num_sources_tosend); + } + + /* Send Q(G) */ + group_query_send(group); } void igmpv3_report_toin(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources) + struct in_addr group_addr, int num_sources, + struct in_addr *sources) { - struct interface *ifp = igmp->interface; - struct igmp_group *group; - - on_trace(__PRETTY_FUNCTION__, - ifp, from, group_addr, num_sources, sources); - - /* - * If the requested filter mode is INCLUDE *and* the requested source - * list is empty, then the entry corresponding to the requested - * interface and multicast address is deleted if present. If no such - * entry is present, the request is ignored. - */ - if (num_sources) - { - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return; - } - } - else - { - group = find_group_by_addr (igmp, group_addr); - if (!group) - return; - } - - if (group->group_filtermode_isexcl) { - /* EXCLUDE mode */ - toin_excl(group, num_sources, sources); - } - else { - /* INCLUDE mode */ - toin_incl(group, num_sources, sources); - } + struct interface *ifp = igmp->interface; + struct igmp_group *group; + + on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, + sources); + + /* + * If the requested filter mode is INCLUDE *and* the requested source + * list is empty, then the entry corresponding to the requested + * interface and multicast address is deleted if present. If no such + * entry is present, the request is ignored. + */ + if (num_sources) { + /* non-existant group is created as INCLUDE {empty} */ + group = igmp_add_group_by_addr(igmp, group_addr); + if (!group) { + return; + } + } else { + group = find_group_by_addr(igmp, group_addr); + if (!group) + return; + } + + if (group->group_filtermode_isexcl) { + /* EXCLUDE mode */ + toin_excl(group, num_sources, sources); + } else { + /* INCLUDE mode */ + toin_incl(group, num_sources, sources); + } } -static void toex_incl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void toex_incl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - int num_sources_tosend = 0; - int i; - - zassert(!group->group_filtermode_isexcl); - - /* Set DELETE flag for all known sources (A) */ - source_mark_delete_flag (group); - - /* Clear off SEND flag from all known sources (A) */ - source_clear_send_flag(group->group_source_list); - - /* Scan received sources (B) */ - for (i = 0; i < num_sources; ++i) { - struct igmp_source *source; - struct in_addr *src_addr; - - src_addr = sources + i; - - /* Lookup reported source (B) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (source) { - /* If found, clear deletion flag: (A*B) */ - IGMP_SOURCE_DONT_DELETE(source->source_flags); - /* and set SEND flag (A*B) */ - IGMP_SOURCE_DO_SEND(source->source_flags); - ++num_sources_tosend; - } - else { - /* If source not found, create source with timer=0: (B-A)=0 */ - source = source_new(group, *src_addr); - if (!source) { - /* ugh, internal malloc failure, skip source */ - continue; - } - zassert(!source->t_source_timer); /* (B-A) timer=0 */ - } - - } /* Scan received sources (B) */ - - group->group_filtermode_isexcl = 1; /* boolean=true */ - - /* Delete all sources marked with DELETE flag (A-B) */ - source_delete_by_flag(group->group_source_list); - - /* Send sources marked with SEND flag: Q(G,A*B) */ - if (num_sources_tosend > 0) { - source_query_send_by_flag(group, num_sources_tosend); - } - - zassert(group->group_filtermode_isexcl); - - group_exclude_fwd_anysrc_ifempty(group); + int num_sources_tosend = 0; + int i; + + zassert(!group->group_filtermode_isexcl); + + /* Set DELETE flag for all known sources (A) */ + source_mark_delete_flag(group); + + /* Clear off SEND flag from all known sources (A) */ + source_clear_send_flag(group->group_source_list); + + /* Scan received sources (B) */ + for (i = 0; i < num_sources; ++i) { + struct igmp_source *source; + struct in_addr *src_addr; + + src_addr = sources + i; + + /* Lookup reported source (B) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (source) { + /* If found, clear deletion flag: (A*B) */ + IGMP_SOURCE_DONT_DELETE(source->source_flags); + /* and set SEND flag (A*B) */ + IGMP_SOURCE_DO_SEND(source->source_flags); + ++num_sources_tosend; + } else { + /* If source not found, create source with timer=0: + * (B-A)=0 */ + source = source_new(group, *src_addr); + if (!source) { + /* ugh, internal malloc failure, skip source */ + continue; + } + zassert(!source->t_source_timer); /* (B-A) timer=0 */ + } + + } /* Scan received sources (B) */ + + group->group_filtermode_isexcl = 1; /* boolean=true */ + + /* Delete all sources marked with DELETE flag (A-B) */ + source_delete_by_flag(group->group_source_list); + + /* Send sources marked with SEND flag: Q(G,A*B) */ + if (num_sources_tosend > 0) { + source_query_send_by_flag(group, num_sources_tosend); + } + + zassert(group->group_filtermode_isexcl); + + group_exclude_fwd_anysrc_ifempty(group); } -static void toex_excl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void toex_excl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - int num_sources_tosend = 0; - int i; - - /* set DELETE flag for all known sources (X,Y) */ - source_mark_delete_flag (group); - - /* clear off SEND flag from all known sources (X,Y) */ - source_clear_send_flag(group->group_source_list); - - if (num_sources == 0) - { - struct igmp_source *source; - struct in_addr any = { .s_addr = INADDR_ANY }; - - source = igmp_find_source_by_addr (group, any); - if (source) - IGMP_SOURCE_DONT_DELETE(source->source_flags); - } - - /* scan received sources (A) */ - for (i = 0; i < num_sources; ++i) { - struct igmp_source *source; - struct in_addr *src_addr; - - src_addr = sources + i; - - /* lookup reported source (A) in known sources (X,Y) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (source) { - /* if found, clear off DELETE flag from reported source (A) */ - IGMP_SOURCE_DONT_DELETE(source->source_flags); - } - else { - /* if not found, create source with Group Timer: (A-X-Y)=Group Timer */ - long group_timer_msec; - source = source_new(group, *src_addr); - if (!source) { - /* ugh, internal malloc failure, skip source */ - continue; - } - - zassert(!source->t_source_timer); /* timer == 0 */ - group_timer_msec = igmp_group_timer_remain_msec(group); - igmp_source_timer_on(group, source, group_timer_msec); - zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ - - /* make sure source is created with DELETE flag unset */ - zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); - } - - /* make sure reported source has DELETE flag unset */ - zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); - - if (source->t_source_timer) { - /* if source timer>0 mark SEND flag: Q(G,A-Y) */ - IGMP_SOURCE_DO_SEND(source->source_flags); - ++num_sources_tosend; - } - - } /* scan received sources (A) */ - - /* - delete all sources marked with DELETE flag: - Delete (X-A) - Delete (Y-A) - */ - source_delete_by_flag(group->group_source_list); - - /* send sources marked with SEND flag: Q(G,A-Y) */ - if (num_sources_tosend > 0) { - source_query_send_by_flag(group, num_sources_tosend); - } + int num_sources_tosend = 0; + int i; + + /* set DELETE flag for all known sources (X,Y) */ + source_mark_delete_flag(group); + + /* clear off SEND flag from all known sources (X,Y) */ + source_clear_send_flag(group->group_source_list); + + if (num_sources == 0) { + struct igmp_source *source; + struct in_addr any = {.s_addr = INADDR_ANY}; + + source = igmp_find_source_by_addr(group, any); + if (source) + IGMP_SOURCE_DONT_DELETE(source->source_flags); + } + + /* scan received sources (A) */ + for (i = 0; i < num_sources; ++i) { + struct igmp_source *source; + struct in_addr *src_addr; + + src_addr = sources + i; + + /* lookup reported source (A) in known sources (X,Y) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (source) { + /* if found, clear off DELETE flag from reported source + * (A) */ + IGMP_SOURCE_DONT_DELETE(source->source_flags); + } else { + /* if not found, create source with Group Timer: + * (A-X-Y)=Group Timer */ + long group_timer_msec; + source = source_new(group, *src_addr); + if (!source) { + /* ugh, internal malloc failure, skip source */ + continue; + } + + zassert(!source->t_source_timer); /* timer == 0 */ + group_timer_msec = igmp_group_timer_remain_msec(group); + igmp_source_timer_on(group, source, group_timer_msec); + zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ + + /* make sure source is created with DELETE flag unset */ + zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); + } + + /* make sure reported source has DELETE flag unset */ + zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); + + if (source->t_source_timer) { + /* if source timer>0 mark SEND flag: Q(G,A-Y) */ + IGMP_SOURCE_DO_SEND(source->source_flags); + ++num_sources_tosend; + } + + } /* scan received sources (A) */ + + /* + delete all sources marked with DELETE flag: + Delete (X-A) + Delete (Y-A) + */ + source_delete_by_flag(group->group_source_list); + + /* send sources marked with SEND flag: Q(G,A-Y) */ + if (num_sources_tosend > 0) { + source_query_send_by_flag(group, num_sources_tosend); + } } void igmpv3_report_toex(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources) + struct in_addr group_addr, int num_sources, + struct in_addr *sources) { - struct interface *ifp = igmp->interface; - struct igmp_group *group; - - on_trace(__PRETTY_FUNCTION__, - ifp, from, group_addr, num_sources, sources); - - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return; - } - - if (group->group_filtermode_isexcl) { - /* EXCLUDE mode */ - toex_excl(group, num_sources, sources); - } - else { - /* INCLUDE mode */ - toex_incl(group, num_sources, sources); - zassert(group->group_filtermode_isexcl); - } - zassert(group->group_filtermode_isexcl); - - /* Group Timer=GMI */ - igmp_group_reset_gmi(group); + struct interface *ifp = igmp->interface; + struct igmp_group *group; + + on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, + sources); + + /* non-existant group is created as INCLUDE {empty} */ + group = igmp_add_group_by_addr(igmp, group_addr); + if (!group) { + return; + } + + if (group->group_filtermode_isexcl) { + /* EXCLUDE mode */ + toex_excl(group, num_sources, sources); + } else { + /* INCLUDE mode */ + toex_incl(group, num_sources, sources); + zassert(group->group_filtermode_isexcl); + } + zassert(group->group_filtermode_isexcl); + + /* Group Timer=GMI */ + igmp_group_reset_gmi(group); } void igmpv3_report_allow(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources) + struct in_addr group_addr, int num_sources, + struct in_addr *sources) { - on_trace(__PRETTY_FUNCTION__, - igmp->interface, from, group_addr, num_sources, sources); + on_trace(__PRETTY_FUNCTION__, igmp->interface, from, group_addr, + num_sources, sources); - allow(igmp, from, group_addr, num_sources, sources); + allow(igmp, from, group_addr, num_sources, sources); } /* @@ -1005,67 +1003,64 @@ void igmpv3_report_allow(struct igmp_sock *igmp, struct in_addr from, */ static void group_retransmit_group(struct igmp_group *group) { - struct igmp_sock *igmp; - struct pim_interface *pim_ifp; - long lmqc; /* Last Member Query Count */ - long lmqi_msec; /* Last Member Query Interval */ - long lmqt_msec; /* Last Member Query Time */ - int s_flag; - int query_buf_size; - - igmp = group->group_igmp_sock; - pim_ifp = igmp->interface->info; - - if (pim_ifp->igmp_version == 3) { - query_buf_size = PIM_IGMP_BUFSIZE_WRITE; - } else { - query_buf_size = IGMP_V12_MSG_SIZE; - } - - char query_buf[query_buf_size]; - - lmqc = igmp->querier_robustness_variable; - lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; - lmqt_msec = lmqc * lmqi_msec; - - /* - RFC3376: 6.6.3.1. Building and Sending Group Specific Queries - - When transmitting a group specific query, if the group timer is - larger than LMQT, the "Suppress Router-Side Processing" bit is set - in the query message. - */ - s_flag = igmp_group_timer_remain_msec(group) > lmqt_msec; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("retransmit_group_specific_query: group %s on %s: s_flag=%d count=%d", - group_str, igmp->interface->name, s_flag, - group->group_specific_query_retransmit_count); - } - - /* - RFC3376: 4.1.12. IP Destination Addresses for Queries - - Group-Specific and Group-and-Source-Specific Queries are sent with - an IP destination address equal to the multicast address of - interest. - */ - - igmp_send_query(pim_ifp->igmp_version, - group, - igmp->fd, - igmp->interface->name, - query_buf, - sizeof(query_buf), - 0 /* num_sources_tosend */, - group->group_addr /* dst_addr */, - group->group_addr /* group_addr */, - pim_ifp->igmp_specific_query_max_response_time_dsec, - s_flag, - igmp->querier_robustness_variable, - igmp->querier_query_interval); + struct igmp_sock *igmp; + struct pim_interface *pim_ifp; + long lmqc; /* Last Member Query Count */ + long lmqi_msec; /* Last Member Query Interval */ + long lmqt_msec; /* Last Member Query Time */ + int s_flag; + int query_buf_size; + + igmp = group->group_igmp_sock; + pim_ifp = igmp->interface->info; + + if (pim_ifp->igmp_version == 3) { + query_buf_size = PIM_IGMP_BUFSIZE_WRITE; + } else { + query_buf_size = IGMP_V12_MSG_SIZE; + } + + char query_buf[query_buf_size]; + + lmqc = igmp->querier_robustness_variable; + lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; + lmqt_msec = lmqc * lmqi_msec; + + /* + RFC3376: 6.6.3.1. Building and Sending Group Specific Queries + + When transmitting a group specific query, if the group timer is + larger than LMQT, the "Suppress Router-Side Processing" bit is set + in the query message. + */ + s_flag = igmp_group_timer_remain_msec(group) > lmqt_msec; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "retransmit_group_specific_query: group %s on %s: s_flag=%d count=%d", + group_str, igmp->interface->name, s_flag, + group->group_specific_query_retransmit_count); + } + + /* + RFC3376: 4.1.12. IP Destination Addresses for Queries + + Group-Specific and Group-and-Source-Specific Queries are sent with + an IP destination address equal to the multicast address of + interest. + */ + + igmp_send_query(pim_ifp->igmp_version, group, igmp->fd, + igmp->interface->name, query_buf, sizeof(query_buf), + 0 /* num_sources_tosend */, + group->group_addr /* dst_addr */, + group->group_addr /* group_addr */, + pim_ifp->igmp_specific_query_max_response_time_dsec, + s_flag, igmp->querier_robustness_variable, + igmp->querier_query_interval); } /* @@ -1083,205 +1078,214 @@ static void group_retransmit_group(struct igmp_group *group) static int group_retransmit_sources(struct igmp_group *group, int send_with_sflag_set) { - struct igmp_sock *igmp; - struct pim_interface *pim_ifp; - long lmqc; /* Last Member Query Count */ - long lmqi_msec; /* Last Member Query Interval */ - long lmqt_msec; /* Last Member Query Time */ - char query_buf1[PIM_IGMP_BUFSIZE_WRITE]; /* 1 = with s_flag set */ - char query_buf2[PIM_IGMP_BUFSIZE_WRITE]; /* 2 = with s_flag clear */ - int query_buf1_max_sources; - int query_buf2_max_sources; - struct in_addr *source_addr1; - struct in_addr *source_addr2; - int num_sources_tosend1; - int num_sources_tosend2; - struct listnode *src_node; - struct igmp_source *src; - int num_retransmit_sources_left = 0; - - source_addr1 = (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET); - source_addr2 = (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET); - - igmp = group->group_igmp_sock; - pim_ifp = igmp->interface->info; - - lmqc = igmp->querier_robustness_variable; - lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; - lmqt_msec = lmqc * lmqi_msec; - - /* Scan all group sources */ - for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { - - /* Source has retransmission state? */ - if (src->source_query_retransmit_count < 1) - continue; - - if (--src->source_query_retransmit_count > 0) { - ++num_retransmit_sources_left; - } - - /* Copy source address into appropriate query buffer */ - if (igmp_source_timer_remain_msec(src) > lmqt_msec) { - *source_addr1 = src->source_addr; - ++source_addr1; - } - else { - *source_addr2 = src->source_addr; - ++source_addr2; - } - - } - - num_sources_tosend1 = source_addr1 - (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET); - num_sources_tosend2 = source_addr2 - (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET); - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("retransmit_grp&src_specific_query: group %s on %s: srcs_with_sflag=%d srcs_wo_sflag=%d will_send_sflag=%d retransmit_src_left=%d", - group_str, igmp->interface->name, - num_sources_tosend1, - num_sources_tosend2, - send_with_sflag_set, - num_retransmit_sources_left); - } - - if (num_sources_tosend1 > 0) { - /* - Send group-and-source-specific query with s_flag set and all - sources with timers greater than LMQT. - */ - - if (send_with_sflag_set) { - - query_buf1_max_sources = (sizeof(query_buf1) - IGMP_V3_SOURCES_OFFSET) >> 2; - if (num_sources_tosend1 > query_buf1_max_sources) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - zlog_warn("%s: group %s on %s: s_flag=1 unable to fit %d sources into buf_size=%zu (max_sources=%d)", - __PRETTY_FUNCTION__, group_str, igmp->interface->name, - num_sources_tosend1, sizeof(query_buf1), query_buf1_max_sources); - } - else { - /* - RFC3376: 4.1.12. IP Destination Addresses for Queries - - Group-Specific and Group-and-Source-Specific Queries are sent with - an IP destination address equal to the multicast address of - interest. - */ - - igmp_send_query(pim_ifp->igmp_version, - group, - igmp->fd, - igmp->interface->name, - query_buf1, - sizeof(query_buf1), - num_sources_tosend1, - group->group_addr, - group->group_addr, - pim_ifp->igmp_specific_query_max_response_time_dsec, - 1 /* s_flag */, - igmp->querier_robustness_variable, - igmp->querier_query_interval); - } - - } /* send_with_sflag_set */ - - } - - if (num_sources_tosend2 > 0) { - /* - Send group-and-source-specific query with s_flag clear and all - sources with timers lower or equal to LMQT. - */ - - query_buf2_max_sources = (sizeof(query_buf2) - IGMP_V3_SOURCES_OFFSET) >> 2; - if (num_sources_tosend2 > query_buf2_max_sources) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - zlog_warn("%s: group %s on %s: s_flag=0 unable to fit %d sources into buf_size=%zu (max_sources=%d)", - __PRETTY_FUNCTION__, group_str, igmp->interface->name, - num_sources_tosend2, sizeof(query_buf2), query_buf2_max_sources); - } - else { - /* - RFC3376: 4.1.12. IP Destination Addresses for Queries - - Group-Specific and Group-and-Source-Specific Queries are sent with - an IP destination address equal to the multicast address of - interest. - */ - - igmp_send_query(pim_ifp->igmp_version, - group, - igmp->fd, - igmp->interface->name, - query_buf2, - sizeof(query_buf2), - num_sources_tosend2, - group->group_addr, - group->group_addr, - pim_ifp->igmp_specific_query_max_response_time_dsec, - 0 /* s_flag */, - igmp->querier_robustness_variable, - igmp->querier_query_interval); - } - } - - return num_retransmit_sources_left; + struct igmp_sock *igmp; + struct pim_interface *pim_ifp; + long lmqc; /* Last Member Query Count */ + long lmqi_msec; /* Last Member Query Interval */ + long lmqt_msec; /* Last Member Query Time */ + char query_buf1[PIM_IGMP_BUFSIZE_WRITE]; /* 1 = with s_flag set */ + char query_buf2[PIM_IGMP_BUFSIZE_WRITE]; /* 2 = with s_flag clear */ + int query_buf1_max_sources; + int query_buf2_max_sources; + struct in_addr *source_addr1; + struct in_addr *source_addr2; + int num_sources_tosend1; + int num_sources_tosend2; + struct listnode *src_node; + struct igmp_source *src; + int num_retransmit_sources_left = 0; + + source_addr1 = (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET); + source_addr2 = (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET); + + igmp = group->group_igmp_sock; + pim_ifp = igmp->interface->info; + + lmqc = igmp->querier_robustness_variable; + lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; + lmqt_msec = lmqc * lmqi_msec; + + /* Scan all group sources */ + for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { + + /* Source has retransmission state? */ + if (src->source_query_retransmit_count < 1) + continue; + + if (--src->source_query_retransmit_count > 0) { + ++num_retransmit_sources_left; + } + + /* Copy source address into appropriate query buffer */ + if (igmp_source_timer_remain_msec(src) > lmqt_msec) { + *source_addr1 = src->source_addr; + ++source_addr1; + } else { + *source_addr2 = src->source_addr; + ++source_addr2; + } + } + + num_sources_tosend1 = + source_addr1 + - (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET); + num_sources_tosend2 = + source_addr2 + - (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET); + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "retransmit_grp&src_specific_query: group %s on %s: srcs_with_sflag=%d srcs_wo_sflag=%d will_send_sflag=%d retransmit_src_left=%d", + group_str, igmp->interface->name, num_sources_tosend1, + num_sources_tosend2, send_with_sflag_set, + num_retransmit_sources_left); + } + + if (num_sources_tosend1 > 0) { + /* + Send group-and-source-specific query with s_flag set and all + sources with timers greater than LMQT. + */ + + if (send_with_sflag_set) { + + query_buf1_max_sources = + (sizeof(query_buf1) - IGMP_V3_SOURCES_OFFSET) + >> 2; + if (num_sources_tosend1 > query_buf1_max_sources) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, + group_str, sizeof(group_str)); + zlog_warn( + "%s: group %s on %s: s_flag=1 unable to fit %d sources into buf_size=%zu (max_sources=%d)", + __PRETTY_FUNCTION__, group_str, + igmp->interface->name, + num_sources_tosend1, sizeof(query_buf1), + query_buf1_max_sources); + } else { + /* + RFC3376: 4.1.12. IP Destination Addresses for + Queries + + Group-Specific and Group-and-Source-Specific + Queries are sent with + an IP destination address equal to the + multicast address of + interest. + */ + + igmp_send_query( + pim_ifp->igmp_version, group, igmp->fd, + igmp->interface->name, query_buf1, + sizeof(query_buf1), num_sources_tosend1, + group->group_addr, group->group_addr, + pim_ifp->igmp_specific_query_max_response_time_dsec, + 1 /* s_flag */, + igmp->querier_robustness_variable, + igmp->querier_query_interval); + } + + } /* send_with_sflag_set */ + } + + if (num_sources_tosend2 > 0) { + /* + Send group-and-source-specific query with s_flag clear and all + sources with timers lower or equal to LMQT. + */ + + query_buf2_max_sources = + (sizeof(query_buf2) - IGMP_V3_SOURCES_OFFSET) >> 2; + if (num_sources_tosend2 > query_buf2_max_sources) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + zlog_warn( + "%s: group %s on %s: s_flag=0 unable to fit %d sources into buf_size=%zu (max_sources=%d)", + __PRETTY_FUNCTION__, group_str, + igmp->interface->name, num_sources_tosend2, + sizeof(query_buf2), query_buf2_max_sources); + } else { + /* + RFC3376: 4.1.12. IP Destination Addresses for Queries + + Group-Specific and Group-and-Source-Specific Queries + are sent with + an IP destination address equal to the multicast + address of + interest. + */ + + igmp_send_query( + pim_ifp->igmp_version, group, igmp->fd, + igmp->interface->name, query_buf2, + sizeof(query_buf2), num_sources_tosend2, + group->group_addr, group->group_addr, + pim_ifp->igmp_specific_query_max_response_time_dsec, + 0 /* s_flag */, + igmp->querier_robustness_variable, + igmp->querier_query_interval); + } + } + + return num_retransmit_sources_left; } static int igmp_group_retransmit(struct thread *t) { - struct igmp_group *group; - int num_retransmit_sources_left; - int send_with_sflag_set; /* boolean */ - - group = THREAD_ARG(t); - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("group_retransmit_timer: group %s on %s", - group_str, group->group_igmp_sock->interface->name); - } - - /* Retransmit group-specific queries? (RFC3376: 6.6.3.1) */ - if (group->group_specific_query_retransmit_count > 0) { - - /* Retransmit group-specific queries (RFC3376: 6.6.3.1) */ - group_retransmit_group(group); - --group->group_specific_query_retransmit_count; - - /* - RFC3376: 6.6.3.2 - If a group specific query is scheduled to be transmitted at the - same time as a group and source specific query for the same group, - then transmission of the group and source specific message with the - "Suppress Router-Side Processing" bit set may be suppressed. - */ - send_with_sflag_set = 0; /* boolean=false */ - } - else { - send_with_sflag_set = 1; /* boolean=true */ - } - - /* Retransmit group-and-source-specific queries (RFC3376: 6.6.3.2) */ - num_retransmit_sources_left = group_retransmit_sources(group, - send_with_sflag_set); - - /* - Keep group retransmit timer running if there is any retransmit - counter pending - */ - if ((num_retransmit_sources_left > 0) || - (group->group_specific_query_retransmit_count > 0)) { - group_retransmit_timer_on(group); - } - - return 0; + struct igmp_group *group; + int num_retransmit_sources_left; + int send_with_sflag_set; /* boolean */ + + group = THREAD_ARG(t); + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug("group_retransmit_timer: group %s on %s", group_str, + group->group_igmp_sock->interface->name); + } + + /* Retransmit group-specific queries? (RFC3376: 6.6.3.1) */ + if (group->group_specific_query_retransmit_count > 0) { + + /* Retransmit group-specific queries (RFC3376: 6.6.3.1) */ + group_retransmit_group(group); + --group->group_specific_query_retransmit_count; + + /* + RFC3376: 6.6.3.2 + If a group specific query is scheduled to be transmitted at + the + same time as a group and source specific query for the same + group, + then transmission of the group and source specific message + with the + "Suppress Router-Side Processing" bit set may be suppressed. + */ + send_with_sflag_set = 0; /* boolean=false */ + } else { + send_with_sflag_set = 1; /* boolean=true */ + } + + /* Retransmit group-and-source-specific queries (RFC3376: 6.6.3.2) */ + num_retransmit_sources_left = + group_retransmit_sources(group, send_with_sflag_set); + + /* + Keep group retransmit timer running if there is any retransmit + counter pending + */ + if ((num_retransmit_sources_left > 0) + || (group->group_specific_query_retransmit_count > 0)) { + group_retransmit_timer_on(group); + } + + return 0; } /* @@ -1291,42 +1295,42 @@ static int igmp_group_retransmit(struct thread *t) */ static void group_retransmit_timer_on(struct igmp_group *group) { - struct igmp_sock *igmp; - struct pim_interface *pim_ifp; - long lmqi_msec; /* Last Member Query Interval */ - - /* if group retransmit timer is running, do nothing */ - if (group->t_group_query_retransmit_timer) { - return; - } - - igmp = group->group_igmp_sock; - pim_ifp = igmp->interface->info; - - lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("Scheduling %ld.%03ld sec retransmit timer for group %s on %s", - lmqi_msec / 1000, - lmqi_msec % 1000, - group_str, - igmp->interface->name); - } - - thread_add_timer_msec(master, igmp_group_retransmit, group, lmqi_msec, - &group->t_group_query_retransmit_timer); + struct igmp_sock *igmp; + struct pim_interface *pim_ifp; + long lmqi_msec; /* Last Member Query Interval */ + + /* if group retransmit timer is running, do nothing */ + if (group->t_group_query_retransmit_timer) { + return; + } + + igmp = group->group_igmp_sock; + pim_ifp = igmp->interface->info; + + lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "Scheduling %ld.%03ld sec retransmit timer for group %s on %s", + lmqi_msec / 1000, lmqi_msec % 1000, group_str, + igmp->interface->name); + } + + thread_add_timer_msec(master, igmp_group_retransmit, group, lmqi_msec, + &group->t_group_query_retransmit_timer); } static long igmp_group_timer_remain_msec(struct igmp_group *group) { - return pim_time_timer_remain_msec(group->t_group_timer); + return pim_time_timer_remain_msec(group->t_group_timer); } static long igmp_source_timer_remain_msec(struct igmp_source *source) { - return pim_time_timer_remain_msec(source->t_source_timer); + return pim_time_timer_remain_msec(source->t_source_timer); } /* @@ -1334,21 +1338,22 @@ static long igmp_source_timer_remain_msec(struct igmp_source *source) */ static void group_query_send(struct igmp_group *group) { - long lmqc; /* Last Member Query Count */ + long lmqc; /* Last Member Query Count */ - lmqc = group->group_igmp_sock->querier_robustness_variable; + lmqc = group->group_igmp_sock->querier_robustness_variable; - /* lower group timer to lmqt */ - igmp_group_timer_lower_to_lmqt(group); + /* lower group timer to lmqt */ + igmp_group_timer_lower_to_lmqt(group); - /* reset retransmission counter */ - group->group_specific_query_retransmit_count = lmqc; + /* reset retransmission counter */ + group->group_specific_query_retransmit_count = lmqc; - /* immediately send group specific query (decrease retransmit counter by 1)*/ - group_retransmit_group(group); + /* immediately send group specific query (decrease retransmit counter by + * 1)*/ + group_retransmit_group(group); - /* make sure group retransmit timer is running */ - group_retransmit_timer_on(group); + /* make sure group retransmit timer is running */ + group_retransmit_timer_on(group); } /* @@ -1357,612 +1362,674 @@ static void group_query_send(struct igmp_group *group) static void source_query_send_by_flag(struct igmp_group *group, int num_sources_tosend) { - struct igmp_sock *igmp; - struct pim_interface *pim_ifp; - struct listnode *src_node; - struct igmp_source *src; - long lmqc; /* Last Member Query Count */ - long lmqi_msec; /* Last Member Query Interval */ - long lmqt_msec; /* Last Member Query Time */ - - zassert(num_sources_tosend > 0); - - igmp = group->group_igmp_sock; - pim_ifp = igmp->interface->info; - - lmqc = igmp->querier_robustness_variable; - lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; - lmqt_msec = lmqc * lmqi_msec; - - /* - RFC3376: 6.6.3.2. Building and Sending Group and Source Specific Queries - - (...) for each of the sources in X of group G, with source timer larger - than LMQT: - o Set number of retransmissions for each source to [Last Member - Query Count]. - o Lower source timer to LMQT. - */ - for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { - if (IGMP_SOURCE_TEST_SEND(src->source_flags)) { - /* source "src" in X of group G */ - if (igmp_source_timer_remain_msec(src) > lmqt_msec) { - src->source_query_retransmit_count = lmqc; - igmp_source_timer_lower_to_lmqt(src); - } - } - } - - /* send group-and-source specific queries */ - group_retransmit_sources(group, 1 /* send_with_sflag_set=true */); - - /* make sure group retransmit timer is running */ - group_retransmit_timer_on(group); + struct igmp_sock *igmp; + struct pim_interface *pim_ifp; + struct listnode *src_node; + struct igmp_source *src; + long lmqc; /* Last Member Query Count */ + long lmqi_msec; /* Last Member Query Interval */ + long lmqt_msec; /* Last Member Query Time */ + + zassert(num_sources_tosend > 0); + + igmp = group->group_igmp_sock; + pim_ifp = igmp->interface->info; + + lmqc = igmp->querier_robustness_variable; + lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; + lmqt_msec = lmqc * lmqi_msec; + + /* + RFC3376: 6.6.3.2. Building and Sending Group and Source Specific + Queries + + (...) for each of the sources in X of group G, with source timer + larger + than LMQT: + o Set number of retransmissions for each source to [Last Member + Query Count]. + o Lower source timer to LMQT. + */ + for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { + if (IGMP_SOURCE_TEST_SEND(src->source_flags)) { + /* source "src" in X of group G */ + if (igmp_source_timer_remain_msec(src) > lmqt_msec) { + src->source_query_retransmit_count = lmqc; + igmp_source_timer_lower_to_lmqt(src); + } + } + } + + /* send group-and-source specific queries */ + group_retransmit_sources(group, 1 /* send_with_sflag_set=true */); + + /* make sure group retransmit timer is running */ + group_retransmit_timer_on(group); } -static void block_excl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void block_excl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - int num_sources_tosend = 0; - int i; - - /* 1. clear off SEND flag from all known sources (X,Y) */ - source_clear_send_flag(group->group_source_list); - - /* 2. scan received sources (A) */ - for (i = 0; i < num_sources; ++i) { - struct igmp_source *source; - struct in_addr *src_addr; - - src_addr = sources + i; - - /* lookup reported source (A) in known sources (X,Y) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (!source) { - /* 3: if not found, create source with Group Timer: (A-X-Y)=Group Timer */ - long group_timer_msec; - source = source_new(group, *src_addr); - if (!source) { - /* ugh, internal malloc failure, skip source */ - continue; - } - - zassert(!source->t_source_timer); /* timer == 0 */ - group_timer_msec = igmp_group_timer_remain_msec(group); - igmp_source_timer_on(group, source, group_timer_msec); - zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ - } - - if (source->t_source_timer) { - /* 4. if source timer>0 mark SEND flag: Q(G,A-Y) */ - IGMP_SOURCE_DO_SEND(source->source_flags); - ++num_sources_tosend; - } - } - - /* 5. send sources marked with SEND flag: Q(G,A-Y) */ - if (num_sources_tosend > 0) { - source_query_send_by_flag(group, num_sources_tosend); - } + int num_sources_tosend = 0; + int i; + + /* 1. clear off SEND flag from all known sources (X,Y) */ + source_clear_send_flag(group->group_source_list); + + /* 2. scan received sources (A) */ + for (i = 0; i < num_sources; ++i) { + struct igmp_source *source; + struct in_addr *src_addr; + + src_addr = sources + i; + + /* lookup reported source (A) in known sources (X,Y) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (!source) { + /* 3: if not found, create source with Group Timer: + * (A-X-Y)=Group Timer */ + long group_timer_msec; + source = source_new(group, *src_addr); + if (!source) { + /* ugh, internal malloc failure, skip source */ + continue; + } + + zassert(!source->t_source_timer); /* timer == 0 */ + group_timer_msec = igmp_group_timer_remain_msec(group); + igmp_source_timer_on(group, source, group_timer_msec); + zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ + } + + if (source->t_source_timer) { + /* 4. if source timer>0 mark SEND flag: Q(G,A-Y) */ + IGMP_SOURCE_DO_SEND(source->source_flags); + ++num_sources_tosend; + } + } + + /* 5. send sources marked with SEND flag: Q(G,A-Y) */ + if (num_sources_tosend > 0) { + source_query_send_by_flag(group, num_sources_tosend); + } } -static void block_incl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void block_incl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - int num_sources_tosend = 0; - int i; - - /* 1. clear off SEND flag from all known sources (B) */ - source_clear_send_flag(group->group_source_list); - - /* 2. scan received sources (A) */ - for (i = 0; i < num_sources; ++i) { - struct igmp_source *source; - struct in_addr *src_addr; - - src_addr = sources + i; - - /* lookup reported source (A) in known sources (B) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (source) { - /* 3. if found (A*B), mark SEND flag: Q(G,A*B) */ - IGMP_SOURCE_DO_SEND(source->source_flags); - ++num_sources_tosend; - } - } - - /* 4. send sources marked with SEND flag: Q(G,A*B) */ - if (num_sources_tosend > 0) { - source_query_send_by_flag(group, num_sources_tosend); - } + int num_sources_tosend = 0; + int i; + + /* 1. clear off SEND flag from all known sources (B) */ + source_clear_send_flag(group->group_source_list); + + /* 2. scan received sources (A) */ + for (i = 0; i < num_sources; ++i) { + struct igmp_source *source; + struct in_addr *src_addr; + + src_addr = sources + i; + + /* lookup reported source (A) in known sources (B) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (source) { + /* 3. if found (A*B), mark SEND flag: Q(G,A*B) */ + IGMP_SOURCE_DO_SEND(source->source_flags); + ++num_sources_tosend; + } + } + + /* 4. send sources marked with SEND flag: Q(G,A*B) */ + if (num_sources_tosend > 0) { + source_query_send_by_flag(group, num_sources_tosend); + } } void igmpv3_report_block(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources) + struct in_addr group_addr, int num_sources, + struct in_addr *sources) { - struct interface *ifp = igmp->interface; - struct igmp_group *group; - - on_trace(__PRETTY_FUNCTION__, - ifp, from, group_addr, num_sources, sources); - - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return; - } - - if (group->group_filtermode_isexcl) { - /* EXCLUDE mode */ - block_excl(group, num_sources, sources); - } - else { - /* INCLUDE mode */ - block_incl(group, num_sources, sources); - } + struct interface *ifp = igmp->interface; + struct igmp_group *group; + + on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, + sources); + + /* non-existant group is created as INCLUDE {empty} */ + group = igmp_add_group_by_addr(igmp, group_addr); + if (!group) { + return; + } + + if (group->group_filtermode_isexcl) { + /* EXCLUDE mode */ + block_excl(group, num_sources, sources); + } else { + /* INCLUDE mode */ + block_incl(group, num_sources, sources); + } } void igmp_group_timer_lower_to_lmqt(struct igmp_group *group) { - struct igmp_sock *igmp; - struct interface *ifp; - struct pim_interface *pim_ifp; - char *ifname; - int lmqi_dsec; /* Last Member Query Interval */ - int lmqc; /* Last Member Query Count */ - int lmqt_msec; /* Last Member Query Time */ - - /* - RFC 3376: 6.2.2. Definition of Group Timers - - The group timer is only used when a group is in EXCLUDE mode and - it represents the time for the *filter-mode* of the group to - expire and switch to INCLUDE mode. - */ - if (!group->group_filtermode_isexcl) { - return; - } - - igmp = group->group_igmp_sock; - ifp = igmp->interface; - pim_ifp = ifp->info; - ifname = ifp->name; - - lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec; - lmqc = igmp->querier_robustness_variable; - lmqt_msec = PIM_IGMP_LMQT_MSEC(lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */ - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("%s: group %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec", - __PRETTY_FUNCTION__, - group_str, ifname, - lmqc, lmqi_dsec, lmqt_msec); - } - - zassert(group->group_filtermode_isexcl); - - igmp_group_timer_on(group, lmqt_msec, ifname); + struct igmp_sock *igmp; + struct interface *ifp; + struct pim_interface *pim_ifp; + char *ifname; + int lmqi_dsec; /* Last Member Query Interval */ + int lmqc; /* Last Member Query Count */ + int lmqt_msec; /* Last Member Query Time */ + + /* + RFC 3376: 6.2.2. Definition of Group Timers + + The group timer is only used when a group is in EXCLUDE mode and + it represents the time for the *filter-mode* of the group to + expire and switch to INCLUDE mode. + */ + if (!group->group_filtermode_isexcl) { + return; + } + + igmp = group->group_igmp_sock; + ifp = igmp->interface; + pim_ifp = ifp->info; + ifname = ifp->name; + + lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec; + lmqc = igmp->querier_robustness_variable; + lmqt_msec = PIM_IGMP_LMQT_MSEC( + lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */ + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "%s: group %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec", + __PRETTY_FUNCTION__, group_str, ifname, lmqc, lmqi_dsec, + lmqt_msec); + } + + zassert(group->group_filtermode_isexcl); + + igmp_group_timer_on(group, lmqt_msec, ifname); } void igmp_source_timer_lower_to_lmqt(struct igmp_source *source) { - struct igmp_group *group; - struct igmp_sock *igmp; - struct interface *ifp; - struct pim_interface *pim_ifp; - char *ifname; - int lmqi_dsec; /* Last Member Query Interval */ - int lmqc; /* Last Member Query Count */ - int lmqt_msec; /* Last Member Query Time */ - - group = source->source_group; - igmp = group->group_igmp_sock; - ifp = igmp->interface; - pim_ifp = ifp->info; - ifname = ifp->name; - - lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec; - lmqc = igmp->querier_robustness_variable; - lmqt_msec = PIM_IGMP_LMQT_MSEC(lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */ - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); - zlog_debug("%s: group %s source %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec", - __PRETTY_FUNCTION__, - group_str, source_str, ifname, - lmqc, lmqi_dsec, lmqt_msec); - } - - igmp_source_timer_on(group, source, lmqt_msec); + struct igmp_group *group; + struct igmp_sock *igmp; + struct interface *ifp; + struct pim_interface *pim_ifp; + char *ifname; + int lmqi_dsec; /* Last Member Query Interval */ + int lmqc; /* Last Member Query Count */ + int lmqt_msec; /* Last Member Query Time */ + + group = source->source_group; + igmp = group->group_igmp_sock; + ifp = igmp->interface; + pim_ifp = ifp->info; + ifname = ifp->name; + + lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec; + lmqc = igmp->querier_robustness_variable; + lmqt_msec = PIM_IGMP_LMQT_MSEC( + lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */ + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<source?>", source->source_addr, source_str, + sizeof(source_str)); + zlog_debug( + "%s: group %s source %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec", + __PRETTY_FUNCTION__, group_str, source_str, ifname, + lmqc, lmqi_dsec, lmqt_msec); + } + + igmp_source_timer_on(group, source, lmqt_msec); } -void -igmp_v3_send_query (struct igmp_group *group, - int fd, - const char *ifname, - char *query_buf, - int query_buf_size, - int num_sources, - struct in_addr dst_addr, - struct in_addr group_addr, - int query_max_response_time_dsec, - uint8_t s_flag, - uint8_t querier_robustness_variable, - uint16_t querier_query_interval) +void igmp_v3_send_query(struct igmp_group *group, int fd, const char *ifname, + char *query_buf, int query_buf_size, int num_sources, + struct in_addr dst_addr, struct in_addr group_addr, + int query_max_response_time_dsec, uint8_t s_flag, + uint8_t querier_robustness_variable, + uint16_t querier_query_interval) { - ssize_t msg_size; - uint8_t max_resp_code; - uint8_t qqic; - ssize_t sent; - struct sockaddr_in to; - socklen_t tolen; - uint16_t checksum; - - zassert(num_sources >= 0); - - msg_size = IGMP_V3_SOURCES_OFFSET + (num_sources << 2); - if (msg_size > query_buf_size) { - zlog_err("%s %s: unable to send: msg_size=%zd larger than query_buf_size=%d", - __FILE__, __PRETTY_FUNCTION__, - msg_size, query_buf_size); - return; - } - - s_flag = PIM_FORCE_BOOLEAN(s_flag); - zassert((s_flag == 0) || (s_flag == 1)); - - max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); - qqic = igmp_msg_encode16to8(querier_query_interval); - - /* - RFC 3376: 4.1.6. QRV (Querier's Robustness Variable) - - If non-zero, the QRV field contains the [Robustness Variable] - value used by the querier, i.e., the sender of the Query. If the - querier's [Robustness Variable] exceeds 7, the maximum value of - the QRV field, the QRV is set to zero. - */ - if (querier_robustness_variable > 7) { - querier_robustness_variable = 0; - } - - query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY; - query_buf[1] = max_resp_code; - *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = 0; /* for computing checksum */ - memcpy(query_buf+4, &group_addr, sizeof(struct in_addr)); - - query_buf[8] = (s_flag << 3) | querier_robustness_variable; - query_buf[9] = qqic; - *(uint16_t *)(query_buf + IGMP_V3_NUMSOURCES_OFFSET) = htons(num_sources); - - checksum = in_cksum(query_buf, msg_size); - *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; - - if (PIM_DEBUG_IGMP_PACKETS) { - char dst_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); - pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); - zlog_debug("Send IGMPv3 query to %s on %s for group %s, sources=%d msg_size=%zd s_flag=%x QRV=%u QQI=%u QQIC=%02x", - dst_str, ifname, group_str, - num_sources, msg_size, s_flag, querier_robustness_variable, - querier_query_interval, qqic); - } - - memset(&to, 0, sizeof(to)); - to.sin_family = AF_INET; - to.sin_addr = dst_addr; - tolen = sizeof(to); - - sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, - (struct sockaddr *)&to, tolen); - if (sent != (ssize_t) msg_size) { - char dst_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); - pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); - if (sent < 0) { - zlog_warn("Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s", - dst_str, ifname, group_str, msg_size, errno, safe_strerror(errno)); - } - else { - zlog_warn("Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: sent=%zd", - dst_str, ifname, group_str, msg_size, sent); - } - return; - } - - /* - s_flag sanity test: s_flag must be set for general queries - - RFC 3376: 6.6.1. Timer Updates - - When a router sends or receives a query with a clear Suppress - Router-Side Processing flag, it must update its timers to reflect - the correct timeout values for the group or sources being queried. - - General queries don't trigger timer update. - */ - if (!s_flag) { - /* general query? */ - if (PIM_INADDR_IS_ANY(group_addr)) { - char dst_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); - pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); - zlog_warn("%s: to %s on %s: group=%s sources=%d: s_flag is clear for general query!", - __PRETTY_FUNCTION__, - dst_str, ifname, group_str, num_sources); - } - } + ssize_t msg_size; + uint8_t max_resp_code; + uint8_t qqic; + ssize_t sent; + struct sockaddr_in to; + socklen_t tolen; + uint16_t checksum; + + zassert(num_sources >= 0); + + msg_size = IGMP_V3_SOURCES_OFFSET + (num_sources << 2); + if (msg_size > query_buf_size) { + zlog_err( + "%s %s: unable to send: msg_size=%zd larger than query_buf_size=%d", + __FILE__, __PRETTY_FUNCTION__, msg_size, + query_buf_size); + return; + } + + s_flag = PIM_FORCE_BOOLEAN(s_flag); + zassert((s_flag == 0) || (s_flag == 1)); + + max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); + qqic = igmp_msg_encode16to8(querier_query_interval); + + /* + RFC 3376: 4.1.6. QRV (Querier's Robustness Variable) + + If non-zero, the QRV field contains the [Robustness Variable] + value used by the querier, i.e., the sender of the Query. If the + querier's [Robustness Variable] exceeds 7, the maximum value of + the QRV field, the QRV is set to zero. + */ + if (querier_robustness_variable > 7) { + querier_robustness_variable = 0; + } + + query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY; + query_buf[1] = max_resp_code; + *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = + 0; /* for computing checksum */ + memcpy(query_buf + 4, &group_addr, sizeof(struct in_addr)); + + query_buf[8] = (s_flag << 3) | querier_robustness_variable; + query_buf[9] = qqic; + *(uint16_t *)(query_buf + IGMP_V3_NUMSOURCES_OFFSET) = + htons(num_sources); + + checksum = in_cksum(query_buf, msg_size); + *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; + + if (PIM_DEBUG_IGMP_PACKETS) { + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); + pim_inet4_dump("<group?>", group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "Send IGMPv3 query to %s on %s for group %s, sources=%d msg_size=%zd s_flag=%x QRV=%u QQI=%u QQIC=%02x", + dst_str, ifname, group_str, num_sources, msg_size, + s_flag, querier_robustness_variable, + querier_query_interval, qqic); + } + + memset(&to, 0, sizeof(to)); + to.sin_family = AF_INET; + to.sin_addr = dst_addr; + tolen = sizeof(to); + + sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, + (struct sockaddr *)&to, tolen); + if (sent != (ssize_t)msg_size) { + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); + pim_inet4_dump("<group?>", group_addr, group_str, + sizeof(group_str)); + if (sent < 0) { + zlog_warn( + "Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s", + dst_str, ifname, group_str, msg_size, errno, + safe_strerror(errno)); + } else { + zlog_warn( + "Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: sent=%zd", + dst_str, ifname, group_str, msg_size, sent); + } + return; + } + + /* + s_flag sanity test: s_flag must be set for general queries + + RFC 3376: 6.6.1. Timer Updates + + When a router sends or receives a query with a clear Suppress + Router-Side Processing flag, it must update its timers to reflect + the correct timeout values for the group or sources being queried. + + General queries don't trigger timer update. + */ + if (!s_flag) { + /* general query? */ + if (PIM_INADDR_IS_ANY(group_addr)) { + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<dst?>", dst_addr, dst_str, + sizeof(dst_str)); + pim_inet4_dump("<group?>", group_addr, group_str, + sizeof(group_str)); + zlog_warn( + "%s: to %s on %s: group=%s sources=%d: s_flag is clear for general query!", + __PRETTY_FUNCTION__, dst_str, ifname, group_str, + num_sources); + } + } } -void -igmp_v3_recv_query (struct igmp_sock *igmp, const char *from_str, char *igmp_msg) +void igmp_v3_recv_query(struct igmp_sock *igmp, const char *from_str, + char *igmp_msg) { - struct interface *ifp; - struct pim_interface *pim_ifp; - struct in_addr group_addr; - uint8_t resv_s_qrv = 0; - uint8_t s_flag = 0; - uint8_t qrv = 0; - int i; - - memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - ifp = igmp->interface; - pim_ifp = ifp->info; - - /* - * RFC 3376: 4.1.6. QRV (Querier's Robustness Variable) - * - * Routers adopt the QRV value from the most recently received Query - * as their own [Robustness Variable] value, unless that most - * recently received QRV was zero, in which case the receivers use - * the default [Robustness Variable] value specified in section 8.1 - * or a statically configured value. - */ - resv_s_qrv = igmp_msg[8]; - qrv = 7 & resv_s_qrv; - igmp->querier_robustness_variable = qrv ? qrv : pim_ifp->igmp_default_robustness_variable; - - /* - * RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) - * - * Multicast routers that are not the current querier adopt the QQI - * value from the most recently received Query as their own [Query - * Interval] value, unless that most recently received QQI was zero, - * in which case the receiving routers use the default. - */ - if (igmp->t_other_querier_timer) { - /* other querier present */ - uint8_t qqic; - uint16_t qqi; - qqic = igmp_msg[9]; - qqi = igmp_msg_decode8to16(qqic); - igmp->querier_query_interval = qqi ? qqi : pim_ifp->igmp_default_query_interval; - - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("Querier %s new query interval is %s QQI=%u sec (recv QQIC=%02x from %s)", - ifaddr_str, - qqi ? "recv-non-default" : "default", - igmp->querier_query_interval, - qqic, - from_str); - } - } - - /* - * RFC 3376: 6.6.1. Timer Updates - * - * When a router sends or receives a query with a clear Suppress - * Router-Side Processing flag, it must update its timers to reflect - * the correct timeout values for the group or sources being queried. - * - * General queries don't trigger timer update. - */ - s_flag = (1 << 3) & resv_s_qrv; - - if (!s_flag) { - /* s_flag is clear */ - - if (PIM_INADDR_IS_ANY(group_addr)) { - /* this is a general query */ - /* log that general query should have the s_flag set */ - zlog_warn("General IGMP query v3 from %s on %s: Suppress Router-Side Processing flag is clear", - from_str, ifp->name); - } else { - struct igmp_group *group; - - /* this is a non-general query: perform timer updates */ - - group = find_group_by_addr(igmp, group_addr); - if (group) { - int recv_num_sources = ntohs(*(uint16_t *)(igmp_msg + IGMP_V3_NUMSOURCES_OFFSET)); - - /* - * RFC 3376: 6.6.1. Timer Updates - * Query Q(G,A): Source Timer for sources in A are lowered to LMQT - * Query Q(G): Group Timer is lowered to LMQT - */ - if (recv_num_sources < 1) { - /* Query Q(G): Group Timer is lowered to LMQT */ - - igmp_group_timer_lower_to_lmqt(group); - } else { - /* Query Q(G,A): Source Timer for sources in A are lowered to LMQT */ - - /* Scan sources in query and lower their timers to LMQT */ - struct in_addr *sources = (struct in_addr *)(igmp_msg + IGMP_V3_SOURCES_OFFSET); - for (i = 0; i < recv_num_sources; ++i) { - struct in_addr src_addr; - struct igmp_source *src; - memcpy(&src_addr, sources + i, sizeof(struct in_addr)); - src = igmp_find_source_by_addr(group, src_addr); - if (src) { - igmp_source_timer_lower_to_lmqt(src); - } - } - } - } else { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); - zlog_warn("IGMP query v3 from %s on %s: could not find group %s for timer update", - from_str, ifp->name, group_str); - } - } - } /* s_flag is clear: timer updates */ + struct interface *ifp; + struct pim_interface *pim_ifp; + struct in_addr group_addr; + uint8_t resv_s_qrv = 0; + uint8_t s_flag = 0; + uint8_t qrv = 0; + int i; + + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + ifp = igmp->interface; + pim_ifp = ifp->info; + + /* + * RFC 3376: 4.1.6. QRV (Querier's Robustness Variable) + * + * Routers adopt the QRV value from the most recently received Query + * as their own [Robustness Variable] value, unless that most + * recently received QRV was zero, in which case the receivers use + * the default [Robustness Variable] value specified in section 8.1 + * or a statically configured value. + */ + resv_s_qrv = igmp_msg[8]; + qrv = 7 & resv_s_qrv; + igmp->querier_robustness_variable = + qrv ? qrv : pim_ifp->igmp_default_robustness_variable; + + /* + * RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) + * + * Multicast routers that are not the current querier adopt the QQI + * value from the most recently received Query as their own [Query + * Interval] value, unless that most recently received QQI was zero, + * in which case the receiving routers use the default. + */ + if (igmp->t_other_querier_timer) { + /* other querier present */ + uint8_t qqic; + uint16_t qqi; + qqic = igmp_msg[9]; + qqi = igmp_msg_decode8to16(qqic); + igmp->querier_query_interval = + qqi ? qqi : pim_ifp->igmp_default_query_interval; + + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug( + "Querier %s new query interval is %s QQI=%u sec (recv QQIC=%02x from %s)", + ifaddr_str, + qqi ? "recv-non-default" : "default", + igmp->querier_query_interval, qqic, from_str); + } + } + + /* + * RFC 3376: 6.6.1. Timer Updates + * + * When a router sends or receives a query with a clear Suppress + * Router-Side Processing flag, it must update its timers to reflect + * the correct timeout values for the group or sources being queried. + * + * General queries don't trigger timer update. + */ + s_flag = (1 << 3) & resv_s_qrv; + + if (!s_flag) { + /* s_flag is clear */ + + if (PIM_INADDR_IS_ANY(group_addr)) { + /* this is a general query */ + /* log that general query should have the s_flag set */ + zlog_warn( + "General IGMP query v3 from %s on %s: Suppress Router-Side Processing flag is clear", + from_str, ifp->name); + } else { + struct igmp_group *group; + + /* this is a non-general query: perform timer updates */ + + group = find_group_by_addr(igmp, group_addr); + if (group) { + int recv_num_sources = ntohs(*( + uint16_t + *)(igmp_msg + + IGMP_V3_NUMSOURCES_OFFSET)); + + /* + * RFC 3376: 6.6.1. Timer Updates + * Query Q(G,A): Source Timer for sources in A + * are lowered to LMQT + * Query Q(G): Group Timer is lowered to LMQT + */ + if (recv_num_sources < 1) { + /* Query Q(G): Group Timer is lowered to + * LMQT */ + + igmp_group_timer_lower_to_lmqt(group); + } else { + /* Query Q(G,A): Source Timer for + * sources in A are lowered to LMQT */ + + /* Scan sources in query and lower their + * timers to LMQT */ + struct in_addr *sources = + (struct in_addr + *)(igmp_msg + + IGMP_V3_SOURCES_OFFSET); + for (i = 0; i < recv_num_sources; ++i) { + struct in_addr src_addr; + struct igmp_source *src; + memcpy(&src_addr, sources + i, + sizeof(struct in_addr)); + src = igmp_find_source_by_addr( + group, src_addr); + if (src) { + igmp_source_timer_lower_to_lmqt( + src); + } + } + } + } else { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", group_addr, + group_str, sizeof(group_str)); + zlog_warn( + "IGMP query v3 from %s on %s: could not find group %s for timer update", + from_str, ifp->name, group_str); + } + } + } /* s_flag is clear: timer updates */ } -int -igmp_v3_recv_report (struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) +int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from, + const char *from_str, char *igmp_msg, int igmp_msg_len) { - uint16_t recv_checksum; - uint16_t checksum; - int num_groups; - uint8_t *group_record; - uint8_t *report_pastend = (uint8_t *) igmp_msg + igmp_msg_len; - struct interface *ifp = igmp->interface; - int i; - int local_ncb = 0; - - if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) { - zlog_warn("Recv IGMP report v3 from %s on %s: size=%d shorter than minimum=%d", - from_str, ifp->name, igmp_msg_len, IGMP_V3_MSG_MIN_SIZE); - return -1; - } - - recv_checksum = *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET); - - /* for computing checksum */ - *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; - - checksum = in_cksum(igmp_msg, igmp_msg_len); - if (checksum != recv_checksum) { - zlog_warn("Recv IGMP report v3 from %s on %s: checksum mismatch: received=%x computed=%x", - from_str, ifp->name, recv_checksum, checksum); - return -1; - } - - num_groups = ntohs(*(uint16_t *) (igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET)); - if (num_groups < 1) { - zlog_warn("Recv IGMP report v3 from %s on %s: missing group records", - from_str, ifp->name); - return -1; - } - - if (PIM_DEBUG_IGMP_PACKETS) { - zlog_debug("Recv IGMP report v3 from %s on %s: size=%d checksum=%x groups=%d", - from_str, ifp->name, igmp_msg_len, checksum, num_groups); - } - - group_record = (uint8_t *) igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET; - - /* Scan groups */ - for (i = 0; i < num_groups; ++i) { - struct in_addr rec_group; - uint8_t *sources; - uint8_t *src; - int rec_type; - int rec_auxdatalen; - int rec_num_sources; - int j; - struct prefix lncb; - struct prefix g; - - if ((group_record + IGMP_V3_GROUP_RECORD_MIN_SIZE) > report_pastend) { - zlog_warn("Recv IGMP report v3 from %s on %s: group record beyond report end", - from_str, ifp->name); - return -1; - } - - rec_type = group_record[IGMP_V3_GROUP_RECORD_TYPE_OFFSET]; - rec_auxdatalen = group_record[IGMP_V3_GROUP_RECORD_AUXDATALEN_OFFSET]; - rec_num_sources = ntohs(* (uint16_t *) (group_record + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET)); - - memcpy(&rec_group, group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET, sizeof(struct in_addr)); - - if (PIM_DEBUG_IGMP_PACKETS) { - zlog_debug("Recv IGMP report v3 from %s on %s: record=%d type=%d auxdatalen=%d sources=%d group=%s", - from_str, ifp->name, i, rec_type, rec_auxdatalen, rec_num_sources, inet_ntoa(rec_group)); - } - - /* Scan sources */ - - sources = group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET; - - for (j = 0, src = sources; j < rec_num_sources; ++j, src += 4) { - - if ((src + 4) > report_pastend) { - zlog_warn("Recv IGMP report v3 from %s on %s: group source beyond report end", - from_str, ifp->name); - return -1; - } - - if (PIM_DEBUG_IGMP_PACKETS) { - char src_str[200]; - - if (!inet_ntop(AF_INET, src, src_str , sizeof(src_str))) - sprintf(src_str, "<source?>"); - - zlog_debug("Recv IGMP report v3 from %s on %s: record=%d group=%s source=%s", - from_str, ifp->name, i, inet_ntoa(rec_group), src_str); - } - } /* for (sources) */ - - - lncb.family = AF_INET; - lncb.u.prefix4.s_addr = 0x000000E0; - lncb.prefixlen = 24; - - g.family = AF_INET; - g.u.prefix4 = rec_group; - g.prefixlen = 32; - /* - * If we receive a igmp report with the group in 224.0.0.0/24 - * then we should ignore it - */ - if (prefix_match(&lncb, &g)) - local_ncb = 1; - - if (!local_ncb) - switch (rec_type) { - case IGMP_GRP_REC_TYPE_MODE_IS_INCLUDE: - igmpv3_report_isin(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - case IGMP_GRP_REC_TYPE_MODE_IS_EXCLUDE: - igmpv3_report_isex(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources, 0); - break; - case IGMP_GRP_REC_TYPE_CHANGE_TO_INCLUDE_MODE: - igmpv3_report_toin(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - case IGMP_GRP_REC_TYPE_CHANGE_TO_EXCLUDE_MODE: - igmpv3_report_toex(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - case IGMP_GRP_REC_TYPE_ALLOW_NEW_SOURCES: - igmpv3_report_allow(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - case IGMP_GRP_REC_TYPE_BLOCK_OLD_SOURCES: - igmpv3_report_block(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - default: - zlog_warn("Recv IGMP report v3 from %s on %s: unknown record type: type=%d", - from_str, ifp->name, rec_type); - } - - group_record += 8 + (rec_num_sources << 2) + (rec_auxdatalen << 2); - local_ncb = 0; - - } /* for (group records) */ - - return 0; + uint16_t recv_checksum; + uint16_t checksum; + int num_groups; + uint8_t *group_record; + uint8_t *report_pastend = (uint8_t *)igmp_msg + igmp_msg_len; + struct interface *ifp = igmp->interface; + int i; + int local_ncb = 0; + + if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) { + zlog_warn( + "Recv IGMP report v3 from %s on %s: size=%d shorter than minimum=%d", + from_str, ifp->name, igmp_msg_len, + IGMP_V3_MSG_MIN_SIZE); + return -1; + } + + recv_checksum = *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET); + + /* for computing checksum */ + *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; + + checksum = in_cksum(igmp_msg, igmp_msg_len); + if (checksum != recv_checksum) { + zlog_warn( + "Recv IGMP report v3 from %s on %s: checksum mismatch: received=%x computed=%x", + from_str, ifp->name, recv_checksum, checksum); + return -1; + } + + num_groups = ntohs( + *(uint16_t *)(igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET)); + if (num_groups < 1) { + zlog_warn( + "Recv IGMP report v3 from %s on %s: missing group records", + from_str, ifp->name); + return -1; + } + + if (PIM_DEBUG_IGMP_PACKETS) { + zlog_debug( + "Recv IGMP report v3 from %s on %s: size=%d checksum=%x groups=%d", + from_str, ifp->name, igmp_msg_len, checksum, + num_groups); + } + + group_record = (uint8_t *)igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET; + + /* Scan groups */ + for (i = 0; i < num_groups; ++i) { + struct in_addr rec_group; + uint8_t *sources; + uint8_t *src; + int rec_type; + int rec_auxdatalen; + int rec_num_sources; + int j; + struct prefix lncb; + struct prefix g; + + if ((group_record + IGMP_V3_GROUP_RECORD_MIN_SIZE) + > report_pastend) { + zlog_warn( + "Recv IGMP report v3 from %s on %s: group record beyond report end", + from_str, ifp->name); + return -1; + } + + rec_type = group_record[IGMP_V3_GROUP_RECORD_TYPE_OFFSET]; + rec_auxdatalen = + group_record[IGMP_V3_GROUP_RECORD_AUXDATALEN_OFFSET]; + rec_num_sources = ntohs(*( + uint16_t *)(group_record + + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET)); + + memcpy(&rec_group, + group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET, + sizeof(struct in_addr)); + + if (PIM_DEBUG_IGMP_PACKETS) { + zlog_debug( + "Recv IGMP report v3 from %s on %s: record=%d type=%d auxdatalen=%d sources=%d group=%s", + from_str, ifp->name, i, rec_type, + rec_auxdatalen, rec_num_sources, + inet_ntoa(rec_group)); + } + + /* Scan sources */ + + sources = group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET; + + for (j = 0, src = sources; j < rec_num_sources; ++j, src += 4) { + + if ((src + 4) > report_pastend) { + zlog_warn( + "Recv IGMP report v3 from %s on %s: group source beyond report end", + from_str, ifp->name); + return -1; + } + + if (PIM_DEBUG_IGMP_PACKETS) { + char src_str[200]; + + if (!inet_ntop(AF_INET, src, src_str, + sizeof(src_str))) + sprintf(src_str, "<source?>"); + + zlog_debug( + "Recv IGMP report v3 from %s on %s: record=%d group=%s source=%s", + from_str, ifp->name, i, + inet_ntoa(rec_group), src_str); + } + } /* for (sources) */ + + + lncb.family = AF_INET; + lncb.u.prefix4.s_addr = 0x000000E0; + lncb.prefixlen = 24; + + g.family = AF_INET; + g.u.prefix4 = rec_group; + g.prefixlen = 32; + /* + * If we receive a igmp report with the group in 224.0.0.0/24 + * then we should ignore it + */ + if (prefix_match(&lncb, &g)) + local_ncb = 1; + + if (!local_ncb) + switch (rec_type) { + case IGMP_GRP_REC_TYPE_MODE_IS_INCLUDE: + igmpv3_report_isin(igmp, from, rec_group, + rec_num_sources, + (struct in_addr *)sources); + break; + case IGMP_GRP_REC_TYPE_MODE_IS_EXCLUDE: + igmpv3_report_isex( + igmp, from, rec_group, rec_num_sources, + (struct in_addr *)sources, 0); + break; + case IGMP_GRP_REC_TYPE_CHANGE_TO_INCLUDE_MODE: + igmpv3_report_toin(igmp, from, rec_group, + rec_num_sources, + (struct in_addr *)sources); + break; + case IGMP_GRP_REC_TYPE_CHANGE_TO_EXCLUDE_MODE: + igmpv3_report_toex(igmp, from, rec_group, + rec_num_sources, + (struct in_addr *)sources); + break; + case IGMP_GRP_REC_TYPE_ALLOW_NEW_SOURCES: + igmpv3_report_allow(igmp, from, rec_group, + rec_num_sources, + (struct in_addr *)sources); + break; + case IGMP_GRP_REC_TYPE_BLOCK_OLD_SOURCES: + igmpv3_report_block(igmp, from, rec_group, + rec_num_sources, + (struct in_addr *)sources); + break; + default: + zlog_warn( + "Recv IGMP report v3 from %s on %s: unknown record type: type=%d", + from_str, ifp->name, rec_type); + } + + group_record += + 8 + (rec_num_sources << 2) + (rec_auxdatalen << 2); + local_ncb = 0; + + } /* for (group records) */ + + return 0; } diff --git a/pimd/pim_igmpv3.h b/pimd/pim_igmpv3.h index 99f7b84b8..6abaef6e2 100644 --- a/pimd/pim_igmpv3.h +++ b/pimd/pim_igmpv3.h @@ -52,8 +52,7 @@ #define PIM_IGMP_OHPI_DSEC(qrv,qqi,qri_dsec) ((qrv) * (10 * (qqi)) + (qri_dsec)) void igmp_group_reset_gmi(struct igmp_group *group); -void igmp_source_reset_gmi(struct igmp_sock *igmp, - struct igmp_group *group, +void igmp_source_reset_gmi(struct igmp_sock *igmp, struct igmp_group *group, struct igmp_source *source); void igmp_source_free(struct igmp_source *source); @@ -61,24 +60,23 @@ void igmp_source_delete(struct igmp_source *source); void igmp_source_delete_expired(struct list *source_list); void igmpv3_report_isin(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources); + struct in_addr group_addr, int num_sources, + struct in_addr *sources); void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources, - int from_igmp_v2_report); + struct in_addr group_addr, int num_sources, + struct in_addr *sources, int from_igmp_v2_report); void igmpv3_report_toin(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources); + struct in_addr group_addr, int num_sources, + struct in_addr *sources); void igmpv3_report_toex(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources); + struct in_addr group_addr, int num_sources, + struct in_addr *sources); void igmpv3_report_allow(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources); + struct in_addr group_addr, int num_sources, + struct in_addr *sources); void igmpv3_report_block(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources); + struct in_addr group_addr, int num_sources, + struct in_addr *sources); void igmp_group_timer_lower_to_lmqt(struct igmp_group *group); void igmp_source_timer_lower_to_lmqt(struct igmp_source *source); @@ -86,24 +84,17 @@ void igmp_source_timer_lower_to_lmqt(struct igmp_source *source); struct igmp_source *igmp_find_source_by_addr(struct igmp_group *group, struct in_addr src_addr); -void igmp_v3_send_query (struct igmp_group *group, - int fd, - const char *ifname, - char *query_buf, - int query_buf_size, - int num_sources, - struct in_addr dst_addr, - struct in_addr group_addr, - int query_max_response_time_dsec, - uint8_t s_flag, - uint8_t querier_robustness_variable, - uint16_t querier_query_interval); - -void igmp_v3_recv_query (struct igmp_sock *igmp, const char *from_str, - char *igmp_msg); - -int igmp_v3_recv_report (struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len); +void igmp_v3_send_query(struct igmp_group *group, int fd, const char *ifname, + char *query_buf, int query_buf_size, int num_sources, + struct in_addr dst_addr, struct in_addr group_addr, + int query_max_response_time_dsec, uint8_t s_flag, + uint8_t querier_robustness_variable, + uint16_t querier_query_interval); + +void igmp_v3_recv_query(struct igmp_sock *igmp, const char *from_str, + char *igmp_msg); + +int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from, + const char *from_str, char *igmp_msg, int igmp_msg_len); #endif /* PIM_IGMPV3_H */ diff --git a/pimd/pim_int.c b/pimd/pim_int.c index 577bf15c6..377839906 100644 --- a/pimd/pim_int.c +++ b/pimd/pim_int.c @@ -27,18 +27,18 @@ uint32_t pim_read_uint32_host(const uint8_t *buf) { - uint32_t val; - memcpy(&val, buf, sizeof(val)); - /* val is in netorder */ - val = ntohl(val); - /* val is in hostorder */ - return val; + uint32_t val; + memcpy(&val, buf, sizeof(val)); + /* val is in netorder */ + val = ntohl(val); + /* val is in hostorder */ + return val; } void pim_write_uint32(uint8_t *buf, uint32_t val_host) { - /* val_host is in host order */ - val_host = htonl(val_host); - /* val_host is in netorder */ - memcpy(buf, &val_host, sizeof(val_host)); + /* val_host is in host order */ + val_host = htonl(val_host); + /* val_host is in netorder */ + memcpy(buf, &val_host, sizeof(val_host)); } diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 35deecfd8..9bc5c2d9c 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -39,301 +39,295 @@ #include "pim_rp.h" #include "pim_jp_agg.h" -static void -on_trace (const char *label, - struct interface *ifp, struct in_addr src) +static void on_trace(const char *label, struct interface *ifp, + struct in_addr src) { - if (PIM_DEBUG_PIM_TRACE) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src, src_str, sizeof(src_str)); - zlog_debug("%s: from %s on %s", - label, src_str, ifp->name); - } + if (PIM_DEBUG_PIM_TRACE) { + 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); + } } -static void recv_join(struct interface *ifp, - struct pim_neighbor *neigh, - uint16_t holdtime, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags) +static void recv_join(struct interface *ifp, struct pim_neighbor *neigh, + uint16_t holdtime, struct in_addr upstream, + struct prefix_sg *sg, uint8_t source_flags) { - struct pim_interface *pim_ifp = NULL; - - if (PIM_DEBUG_PIM_TRACE) { - char up_str[INET_ADDRSTRLEN]; - char neigh_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); - pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str, sizeof(neigh_str)); - zlog_warn("%s: join (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", - __PRETTY_FUNCTION__, - 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_ifp = ifp->info; - zassert(pim_ifp); - - ++pim_ifp->pim_ifstat_join_recv; - - /* - * 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, - sg, source_flags, holdtime); - + struct pim_interface *pim_ifp = NULL; + + if (PIM_DEBUG_PIM_TRACE) { + char up_str[INET_ADDRSTRLEN]; + char neigh_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); + pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str, + sizeof(neigh_str)); + zlog_warn( + "%s: join (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", + __PRETTY_FUNCTION__, 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_ifp = ifp->info; + zassert(pim_ifp); + + ++pim_ifp->pim_ifstat_join_recv; + + /* + * 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, sg, + source_flags, holdtime); } -static void recv_prune(struct interface *ifp, - struct pim_neighbor *neigh, - uint16_t holdtime, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags) +static void recv_prune(struct interface *ifp, struct pim_neighbor *neigh, + uint16_t holdtime, struct in_addr upstream, + struct prefix_sg *sg, uint8_t source_flags) { - struct pim_interface *pim_ifp = NULL; - - if (PIM_DEBUG_PIM_TRACE) { - char up_str[INET_ADDRSTRLEN]; - char neigh_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); - pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str, sizeof(neigh_str)); - zlog_warn("%s: prune (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", - __PRETTY_FUNCTION__, - 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_ifp = ifp->info; - zassert(pim_ifp); - - ++pim_ifp->pim_ifstat_prune_recv; - - 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); - + struct pim_interface *pim_ifp = NULL; + + if (PIM_DEBUG_PIM_TRACE) { + char up_str[INET_ADDRSTRLEN]; + char neigh_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); + pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str, + sizeof(neigh_str)); + zlog_warn( + "%s: prune (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", + __PRETTY_FUNCTION__, 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_ifp = ifp->info; + zassert(pim_ifp); + + ++pim_ifp->pim_ifstat_prune_recv; + + 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, - struct pim_neighbor *neigh, - struct in_addr src_addr, - uint8_t *tlv_buf, int tlv_buf_size) +int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, + struct in_addr src_addr, uint8_t *tlv_buf, + int tlv_buf_size) { - struct prefix msg_upstream_addr; - uint8_t msg_num_groups; - uint16_t msg_holdtime; - int addr_offset; - uint8_t *buf; - uint8_t *pastend; - int remain; - int group; - - buf = tlv_buf; - pastend = tlv_buf + tlv_buf_size; - - /* - Parse ucast addr - */ - addr_offset = pim_parse_addr_ucast (&msg_upstream_addr, - buf, pastend - buf); - if (addr_offset < 1) { - 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__, - src_str, ifp->name); - return -1; - } - buf += addr_offset; - - /* - Check upstream address family - */ - if (msg_upstream_addr.family != AF_INET) { - 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__, - msg_upstream_addr.family, src_str, ifp->name); - } - return -2; - } - - remain = pastend - buf; - if (remain < 4) { - 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__, - remain, 4, src_str, ifp->name); - return -4; - } - - ++buf; /* skip reserved byte */ - msg_num_groups = *(const uint8_t *) buf; - ++buf; - msg_holdtime = ntohs(*(const uint16_t *) buf); - ++buf; - ++buf; - - 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_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_sg sg; - uint8_t msg_source_flags; - uint16_t msg_num_joined_sources; - uint16_t msg_num_pruned_sources; - int source; - struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL; - uint8_t starg_alone = 0; - - memset (&sg, 0, sizeof (struct prefix_sg)); - addr_offset = pim_parse_addr_group (&sg, - buf, pastend - buf); - if (addr_offset < 1) { - return -5; - } - buf += addr_offset; - - remain = pastend - buf; - if (remain < 4) { - 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__, - remain, 4, src_str, ifp->name); - return -6; - } - - msg_num_joined_sources = ntohs(*(const uint16_t *) buf); - buf += 2; - msg_num_pruned_sources = ntohs(*(const uint16_t *) buf); - buf += 2; - - 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?>", sg.grp, - group_str, sizeof(group_str)); - 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_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 (&sg, - &msg_source_flags, - buf, pastend - buf); - if (addr_offset < 1) { - return -7; - } - - buf += addr_offset; - - recv_join(ifp, neigh, msg_holdtime, - msg_upstream_addr.u.prefix4, - &sg, - msg_source_flags); - - if (sg.src.s_addr == INADDR_ANY) - { - starg_alone = 1; - starg_ch = pim_ifchannel_find (ifp, &sg); - if (starg_ch) - pim_ifchannel_set_star_g_join_state (starg_ch, 0, msg_source_flags, 1, starg_alone); - } - } - - /* Scan pruned sources */ - for (source = 0; source < msg_num_pruned_sources; ++source) { - addr_offset = pim_parse_addr_source (&sg, - &msg_source_flags, - buf, pastend - buf); - if (addr_offset < 1) { - return -8; - } - - sg_ch = pim_ifchannel_find (ifp, &sg); - - buf += addr_offset; - starg_alone = 0; - recv_prune(ifp, neigh, msg_holdtime, - msg_upstream_addr.u.prefix4, - &sg, - msg_source_flags); - - /* Received SG-RPT Prune delete oif from specific S,G */ - if (starg_ch && sg_ch && (msg_source_flags & PIM_RPT_BIT_MASK) - && !(msg_source_flags & PIM_WILDCARD_BIT_MASK)) - { - struct pim_upstream *up = sg_ch->upstream; - PIM_IF_FLAG_SET_S_G_RPT(sg_ch->flags); - if (up) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: SGRpt flag is set, del inherit oif from up %s", - __PRETTY_FUNCTION__, up->sg_str); - pim_channel_del_oif (up->channel_oil, starg_ch->interface, PIM_OIF_FLAG_PROTO_STAR); - } - } - } - if (starg_ch) - pim_ifchannel_set_star_g_join_state (starg_ch, 1, msg_source_flags, 0, starg_alone); - starg_ch = NULL; - } /* scan groups */ - - return 0; + struct prefix msg_upstream_addr; + uint8_t msg_num_groups; + uint16_t msg_holdtime; + int addr_offset; + uint8_t *buf; + uint8_t *pastend; + int remain; + int group; + + buf = tlv_buf; + pastend = tlv_buf + tlv_buf_size; + + /* + Parse ucast addr + */ + addr_offset = + pim_parse_addr_ucast(&msg_upstream_addr, buf, pastend - buf); + if (addr_offset < 1) { + 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__, src_str, ifp->name); + return -1; + } + buf += addr_offset; + + /* + Check upstream address family + */ + if (msg_upstream_addr.family != AF_INET) { + 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__, msg_upstream_addr.family, + src_str, ifp->name); + } + return -2; + } + + remain = pastend - buf; + if (remain < 4) { + 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__, remain, 4, src_str, ifp->name); + return -4; + } + + ++buf; /* skip reserved byte */ + msg_num_groups = *(const uint8_t *)buf; + ++buf; + msg_holdtime = ntohs(*(const uint16_t *)buf); + ++buf; + ++buf; + + 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_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_sg sg; + uint8_t msg_source_flags; + uint16_t msg_num_joined_sources; + uint16_t msg_num_pruned_sources; + int source; + struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL; + uint8_t starg_alone = 0; + + memset(&sg, 0, sizeof(struct prefix_sg)); + addr_offset = pim_parse_addr_group(&sg, buf, pastend - buf); + if (addr_offset < 1) { + return -5; + } + buf += addr_offset; + + remain = pastend - buf; + if (remain < 4) { + 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__, remain, 4, src_str, + ifp->name); + return -6; + } + + msg_num_joined_sources = ntohs(*(const uint16_t *)buf); + buf += 2; + msg_num_pruned_sources = ntohs(*(const uint16_t *)buf); + buf += 2; + + 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?>", sg.grp, group_str, + sizeof(group_str)); + 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_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( + &sg, &msg_source_flags, buf, pastend - buf); + if (addr_offset < 1) { + return -7; + } + + buf += addr_offset; + + recv_join(ifp, neigh, msg_holdtime, + msg_upstream_addr.u.prefix4, &sg, + msg_source_flags); + + if (sg.src.s_addr == INADDR_ANY) { + starg_alone = 1; + starg_ch = pim_ifchannel_find(ifp, &sg); + if (starg_ch) + pim_ifchannel_set_star_g_join_state( + starg_ch, 0, msg_source_flags, + 1, starg_alone); + } + } + + /* Scan pruned sources */ + for (source = 0; source < msg_num_pruned_sources; ++source) { + addr_offset = pim_parse_addr_source( + &sg, &msg_source_flags, buf, pastend - buf); + if (addr_offset < 1) { + return -8; + } + + sg_ch = pim_ifchannel_find(ifp, &sg); + + buf += addr_offset; + starg_alone = 0; + recv_prune(ifp, neigh, msg_holdtime, + msg_upstream_addr.u.prefix4, &sg, + msg_source_flags); + + /* Received SG-RPT Prune delete oif from specific S,G */ + if (starg_ch && sg_ch + && (msg_source_flags & PIM_RPT_BIT_MASK) + && !(msg_source_flags & PIM_WILDCARD_BIT_MASK)) { + struct pim_upstream *up = sg_ch->upstream; + PIM_IF_FLAG_SET_S_G_RPT(sg_ch->flags); + if (up) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: SGRpt flag is set, del inherit oif from up %s", + __PRETTY_FUNCTION__, + up->sg_str); + pim_channel_del_oif( + up->channel_oil, + starg_ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + } + } + } + if (starg_ch) + pim_ifchannel_set_star_g_join_state( + starg_ch, 1, msg_source_flags, 0, starg_alone); + starg_ch = NULL; + } /* scan groups */ + + return 0; } /* @@ -402,177 +396,187 @@ int pim_joinprune_recv(struct interface *ifp, * | Pruned Source Address n (Encoded-Source format) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -int pim_joinprune_send(struct pim_rpf *rpf, - struct list *groups) +int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups) { - struct pim_jp_agg_group *group; - struct pim_interface *pim_ifp = NULL; - struct pim_jp_groups *grp = NULL; - struct pim_jp *msg; - struct listnode *node, *nnode; - uint8_t pim_msg[10000]; - uint8_t *curr_ptr = pim_msg; - bool new_packet = true; - size_t packet_left = 0; - size_t packet_size = 0; - size_t group_size = 0; - - on_trace (__PRETTY_FUNCTION__, rpf->source_nexthop.interface, rpf->rpf_addr.u.prefix4); - - if (rpf->source_nexthop.interface) - pim_ifp = rpf->source_nexthop.interface->info; - else - { - zlog_warn ("%s: RPF interface is not present", __PRETTY_FUNCTION__); - return -1; - } - - if (!pim_ifp) - { - zlog_warn ("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - rpf->source_nexthop.interface->name); - return -1; - } - - if (PIM_INADDR_IS_ANY(rpf->rpf_addr.u.prefix4)) - { - if (PIM_DEBUG_PIM_J_P) { - char dst_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, dst_str, sizeof(dst_str)); - zlog_debug("%s: upstream=%s is myself on interface %s", - __PRETTY_FUNCTION__, - dst_str, rpf->source_nexthop.interface->name); - } - return 0; - } - - /* - RFC 4601: 4.3.1. Sending Hello Messages - - Thus, if a router needs to send a Join/Prune or Assert message on - an interface on which it has not yet sent a Hello message with the - currently configured IP address, then it MUST immediately send the - relevant Hello message without waiting for the Hello Timer to - expire, followed by the Join/Prune or Assert message. - */ - pim_hello_require(rpf->source_nexthop.interface); - - for (ALL_LIST_ELEMENTS(groups, node, nnode, group)) - { - if (new_packet) - { - msg = (struct pim_jp *)pim_msg; - - memset(msg, 0, sizeof (*msg)); - - pim_msg_addr_encode_ipv4_ucast ((uint8_t *)&msg->addr, rpf->rpf_addr.u.prefix4); - msg->reserved = 0; - msg->holdtime = htons(PIM_JP_HOLDTIME); - - new_packet = false; - - grp = &msg->groups[0]; - curr_ptr = (uint8_t *)grp; - packet_size = sizeof (struct pim_msg_header); - packet_size += sizeof (struct pim_encoded_ipv4_unicast); - packet_size += 4; // reserved (1) + groups (1) + holdtime (2) - - packet_left = rpf->source_nexthop.interface->mtu - 24; - packet_left -= packet_size; - } - if (PIM_DEBUG_PIM_J_P) { - char dst_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, dst_str, sizeof(dst_str)); - pim_inet4_dump("<grp?>", group->group, grp_str, sizeof(grp_str)); - zlog_debug("%s: sending (G)=%s to upstream=%s on interface %s", - __PRETTY_FUNCTION__, - grp_str, dst_str, rpf->source_nexthop.interface->name); - } - - group_size = pim_msg_get_jp_group_size (group->sources); - if (group_size > packet_left) - { - pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE); - if (pim_msg_send(pim_ifp->pim_sock_fd, - pim_ifp->primary_address, - qpim_all_pim_routers_addr, - pim_msg, - packet_size, - rpf->source_nexthop.interface->name)) { - zlog_warn("%s: could not send PIM message on interface %s", - __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name); - } - - msg = (struct pim_jp *)pim_msg; - memset(msg, 0, sizeof (*msg)); - - pim_msg_addr_encode_ipv4_ucast ((uint8_t *)&msg->addr, rpf->rpf_addr.u.prefix4); - msg->reserved = 0; - msg->holdtime = htons(PIM_JP_HOLDTIME); - - new_packet = false; - - grp = &msg->groups[0]; - curr_ptr = (uint8_t *)grp; - packet_size = sizeof (struct pim_msg_header); - packet_size += sizeof (struct pim_encoded_ipv4_unicast); - packet_size += 4; // reserved (1) + groups (1) + holdtime (2) - - packet_left = rpf->source_nexthop.interface->mtu - 24; - packet_left -= packet_size; - } - - msg->num_groups++; - /* - Build PIM message - */ - - curr_ptr += group_size; - packet_left -= group_size; - packet_size += group_size; - pim_msg_build_jp_groups (grp, group, group_size); - - pim_ifp->pim_ifstat_join_send += ntohs(grp->joins); - pim_ifp->pim_ifstat_prune_send += ntohs(grp->prunes); - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: interface %s num_joins %u num_prunes %u", __PRETTY_FUNCTION__, - rpf->source_nexthop.interface->name, ntohs(grp->joins), ntohs (grp->prunes)); - - grp = (struct pim_jp_groups *)curr_ptr; - if (packet_left < sizeof (struct pim_jp_groups) || msg->num_groups == 255) - { - pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE); - if (pim_msg_send(pim_ifp->pim_sock_fd, - pim_ifp->primary_address, - qpim_all_pim_routers_addr, - pim_msg, - packet_size, - rpf->source_nexthop.interface->name)) { - zlog_warn("%s: could not send PIM message on interface %s", - __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name); - } - - new_packet = true; - } - } - - - if (!new_packet) - { - //msg->num_groups = htons (msg->num_groups); - pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE); - if (pim_msg_send(pim_ifp->pim_sock_fd, - pim_ifp->primary_address, - qpim_all_pim_routers_addr, - pim_msg, - packet_size, - rpf->source_nexthop.interface->name)) { - zlog_warn("%s: could not send PIM message on interface %s", - __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name); - } - } - return 0; + struct pim_jp_agg_group *group; + struct pim_interface *pim_ifp = NULL; + struct pim_jp_groups *grp = NULL; + struct pim_jp *msg; + struct listnode *node, *nnode; + uint8_t pim_msg[10000]; + uint8_t *curr_ptr = pim_msg; + bool new_packet = true; + size_t packet_left = 0; + size_t packet_size = 0; + size_t group_size = 0; + + on_trace(__PRETTY_FUNCTION__, rpf->source_nexthop.interface, + rpf->rpf_addr.u.prefix4); + + if (rpf->source_nexthop.interface) + pim_ifp = rpf->source_nexthop.interface->info; + else { + zlog_warn("%s: RPF interface is not present", + __PRETTY_FUNCTION__); + return -1; + } + + if (!pim_ifp) { + zlog_warn("%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, + rpf->source_nexthop.interface->name); + return -1; + } + + if (PIM_INADDR_IS_ANY(rpf->rpf_addr.u.prefix4)) { + if (PIM_DEBUG_PIM_J_P) { + char dst_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, + dst_str, sizeof(dst_str)); + zlog_debug("%s: upstream=%s is myself on interface %s", + __PRETTY_FUNCTION__, dst_str, + rpf->source_nexthop.interface->name); + } + return 0; + } + + /* + RFC 4601: 4.3.1. Sending Hello Messages + + Thus, if a router needs to send a Join/Prune or Assert message on + an interface on which it has not yet sent a Hello message with the + currently configured IP address, then it MUST immediately send the + relevant Hello message without waiting for the Hello Timer to + expire, followed by the Join/Prune or Assert message. + */ + pim_hello_require(rpf->source_nexthop.interface); + + for (ALL_LIST_ELEMENTS(groups, node, nnode, group)) { + if (new_packet) { + msg = (struct pim_jp *)pim_msg; + + memset(msg, 0, sizeof(*msg)); + + pim_msg_addr_encode_ipv4_ucast((uint8_t *)&msg->addr, + rpf->rpf_addr.u.prefix4); + msg->reserved = 0; + msg->holdtime = htons(PIM_JP_HOLDTIME); + + new_packet = false; + + grp = &msg->groups[0]; + curr_ptr = (uint8_t *)grp; + packet_size = sizeof(struct pim_msg_header); + packet_size += sizeof(struct pim_encoded_ipv4_unicast); + packet_size += + 4; // reserved (1) + groups (1) + holdtime (2) + + packet_left = rpf->source_nexthop.interface->mtu - 24; + packet_left -= packet_size; + } + if (PIM_DEBUG_PIM_J_P) { + char dst_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, + dst_str, sizeof(dst_str)); + pim_inet4_dump("<grp?>", group->group, grp_str, + sizeof(grp_str)); + zlog_debug( + "%s: sending (G)=%s to upstream=%s on interface %s", + __PRETTY_FUNCTION__, grp_str, dst_str, + rpf->source_nexthop.interface->name); + } + + group_size = pim_msg_get_jp_group_size(group->sources); + if (group_size > packet_left) { + pim_msg_build_header(pim_msg, packet_size, + PIM_MSG_TYPE_JOIN_PRUNE); + if (pim_msg_send(pim_ifp->pim_sock_fd, + pim_ifp->primary_address, + qpim_all_pim_routers_addr, pim_msg, + packet_size, + rpf->source_nexthop.interface->name)) { + zlog_warn( + "%s: could not send PIM message on interface %s", + __PRETTY_FUNCTION__, + rpf->source_nexthop.interface->name); + } + + msg = (struct pim_jp *)pim_msg; + memset(msg, 0, sizeof(*msg)); + + pim_msg_addr_encode_ipv4_ucast((uint8_t *)&msg->addr, + rpf->rpf_addr.u.prefix4); + msg->reserved = 0; + msg->holdtime = htons(PIM_JP_HOLDTIME); + + new_packet = false; + + grp = &msg->groups[0]; + curr_ptr = (uint8_t *)grp; + packet_size = sizeof(struct pim_msg_header); + packet_size += sizeof(struct pim_encoded_ipv4_unicast); + packet_size += + 4; // reserved (1) + groups (1) + holdtime (2) + + packet_left = rpf->source_nexthop.interface->mtu - 24; + packet_left -= packet_size; + } + + msg->num_groups++; + /* + Build PIM message + */ + + curr_ptr += group_size; + packet_left -= group_size; + packet_size += group_size; + pim_msg_build_jp_groups(grp, group, group_size); + + pim_ifp->pim_ifstat_join_send += ntohs(grp->joins); + pim_ifp->pim_ifstat_prune_send += ntohs(grp->prunes); + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s: interface %s num_joins %u num_prunes %u", + __PRETTY_FUNCTION__, + rpf->source_nexthop.interface->name, + ntohs(grp->joins), ntohs(grp->prunes)); + + grp = (struct pim_jp_groups *)curr_ptr; + if (packet_left < sizeof(struct pim_jp_groups) + || msg->num_groups == 255) { + pim_msg_build_header(pim_msg, packet_size, + PIM_MSG_TYPE_JOIN_PRUNE); + if (pim_msg_send(pim_ifp->pim_sock_fd, + pim_ifp->primary_address, + qpim_all_pim_routers_addr, pim_msg, + packet_size, + rpf->source_nexthop.interface->name)) { + zlog_warn( + "%s: could not send PIM message on interface %s", + __PRETTY_FUNCTION__, + rpf->source_nexthop.interface->name); + } + + new_packet = true; + } + } + + + if (!new_packet) { + // msg->num_groups = htons (msg->num_groups); + pim_msg_build_header(pim_msg, packet_size, + PIM_MSG_TYPE_JOIN_PRUNE); + if (pim_msg_send(pim_ifp->pim_sock_fd, pim_ifp->primary_address, + qpim_all_pim_routers_addr, pim_msg, + packet_size, + rpf->source_nexthop.interface->name)) { + zlog_warn( + "%s: could not send PIM message on interface %s", + __PRETTY_FUNCTION__, + rpf->source_nexthop.interface->name); + } + } + return 0; } diff --git a/pimd/pim_join.h b/pimd/pim_join.h index 6dc1b3e8f..5d28f2ba3 100644 --- a/pimd/pim_join.h +++ b/pimd/pim_join.h @@ -26,12 +26,10 @@ #include "pim_neighbor.h" -int pim_joinprune_recv(struct interface *ifp, - struct pim_neighbor *neigh, - struct in_addr src_addr, - uint8_t *tlv_buf, int tlv_buf_size); +int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, + struct in_addr src_addr, uint8_t *tlv_buf, + int tlv_buf_size); -int pim_joinprune_send(struct pim_rpf *nexthop, - struct list *groups); +int pim_joinprune_send(struct pim_rpf *nexthop, struct list *groups); #endif /* PIM_JOIN_H */ diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c index 25530f40b..16d55d7bf 100644 --- a/pimd/pim_jp_agg.c +++ b/pimd/pim_jp_agg.c @@ -30,65 +30,63 @@ #include "pim_join.h" #include "pim_iface.h" -void -pim_jp_agg_group_list_free (struct pim_jp_agg_group *jag) +void pim_jp_agg_group_list_free(struct pim_jp_agg_group *jag) { - list_delete(jag->sources); + list_delete(jag->sources); - XFREE (MTYPE_PIM_JP_AGG_GROUP, jag); + XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); } -static void -pim_jp_agg_src_free (struct pim_jp_sources *js) +static void pim_jp_agg_src_free(struct pim_jp_sources *js) { - struct pim_upstream *up = js->up; - - /* - * When we are being called here, we know - * that the neighbor is going away start - * the normal j/p timer so that it can - * pick this shit back up when the - * nbr comes back alive - */ - if (up) - join_timer_start(js->up); - XFREE (MTYPE_PIM_JP_AGG_SOURCE, js); + struct pim_upstream *up = js->up; + + /* + * When we are being called here, we know + * that the neighbor is going away start + * the normal j/p timer so that it can + * pick this shit back up when the + * nbr comes back alive + */ + if (up) + join_timer_start(js->up); + XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); } -int -pim_jp_agg_group_list_cmp (void *arg1, void *arg2) +int pim_jp_agg_group_list_cmp(void *arg1, void *arg2) { - const struct pim_jp_agg_group *jag1 = (const struct pim_jp_agg_group *)arg1; - const struct pim_jp_agg_group *jag2 = (const struct pim_jp_agg_group *)arg2; + const struct pim_jp_agg_group *jag1 = + (const struct pim_jp_agg_group *)arg1; + const struct pim_jp_agg_group *jag2 = + (const struct pim_jp_agg_group *)arg2; - if (jag1->group.s_addr < jag2->group.s_addr) - return -1; + if (jag1->group.s_addr < jag2->group.s_addr) + return -1; - if (jag1->group.s_addr > jag2->group.s_addr) - return 1; + if (jag1->group.s_addr > jag2->group.s_addr) + return 1; - return 0; + return 0; } -static int -pim_jp_agg_src_cmp (void *arg1, void *arg2) +static int pim_jp_agg_src_cmp(void *arg1, void *arg2) { - const struct pim_jp_sources *js1 = (const struct pim_jp_sources *)arg1; - const struct pim_jp_sources *js2 = (const struct pim_jp_sources *)arg2; + const struct pim_jp_sources *js1 = (const struct pim_jp_sources *)arg1; + const struct pim_jp_sources *js2 = (const struct pim_jp_sources *)arg2; - if (js1->is_join && !js2->is_join) - return -1; + if (js1->is_join && !js2->is_join) + return -1; - if (!js1->is_join && js2->is_join) - return 1; + if (!js1->is_join && js2->is_join) + return 1; - if ((uint32_t)js1->up->sg.src.s_addr < (uint32_t)js2->up->sg.src.s_addr) - return -1; + if ((uint32_t)js1->up->sg.src.s_addr < (uint32_t)js2->up->sg.src.s_addr) + return -1; - if ((uint32_t)js1->up->sg.src.s_addr > (uint32_t)js2->up->sg.src.s_addr) - return 1; + if ((uint32_t)js1->up->sg.src.s_addr > (uint32_t)js2->up->sg.src.s_addr) + return 1; - return 0; + return 0; } /* @@ -97,119 +95,107 @@ pim_jp_agg_src_cmp (void *arg1, void *arg2) * figuring out where to send prunes * and joins. */ -void -pim_jp_agg_clear_group (struct list *group) +void pim_jp_agg_clear_group(struct list *group) { - struct listnode *gnode, *gnnode; - struct listnode *snode, *snnode; - struct pim_jp_agg_group *jag; - struct pim_jp_sources *js; - - for (ALL_LIST_ELEMENTS(group, gnode, gnnode, jag)) - { - for (ALL_LIST_ELEMENTS(jag->sources, snode, snnode, js)) - { - listnode_delete(jag->sources, js); - js->up = NULL; - XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); - } - jag->sources = NULL; - listnode_delete(group, jag); - XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); - } + struct listnode *gnode, *gnnode; + struct listnode *snode, *snnode; + struct pim_jp_agg_group *jag; + struct pim_jp_sources *js; + + for (ALL_LIST_ELEMENTS(group, gnode, gnnode, jag)) { + for (ALL_LIST_ELEMENTS(jag->sources, snode, snnode, js)) { + listnode_delete(jag->sources, js); + js->up = NULL; + XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); + } + jag->sources = NULL; + listnode_delete(group, jag); + XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); + } } static struct pim_iface_upstream_switch * -pim_jp_agg_get_interface_upstream_switch_list (struct pim_rpf *rpf) +pim_jp_agg_get_interface_upstream_switch_list(struct pim_rpf *rpf) { - struct pim_interface *pim_ifp = rpf->source_nexthop.interface->info; - struct pim_iface_upstream_switch *pius; - struct listnode *node, *nnode; - - /* Old interface is pim disabled */ - if (!pim_ifp) - return NULL; - - for (ALL_LIST_ELEMENTS(pim_ifp->upstream_switch_list, node, nnode, pius)) - { - if (pius->address.s_addr == rpf->rpf_addr.u.prefix4.s_addr) - break; - } - - if (!pius) - { - pius = XCALLOC(MTYPE_PIM_JP_AGG_GROUP, sizeof (struct pim_iface_upstream_switch)); - pius->address.s_addr = rpf->rpf_addr.u.prefix4.s_addr; - pius->us = list_new(); - listnode_add_sort (pim_ifp->upstream_switch_list, pius); - } - - return pius; + struct pim_interface *pim_ifp = rpf->source_nexthop.interface->info; + struct pim_iface_upstream_switch *pius; + struct listnode *node, *nnode; + + /* Old interface is pim disabled */ + if (!pim_ifp) + return NULL; + + for (ALL_LIST_ELEMENTS(pim_ifp->upstream_switch_list, node, nnode, + pius)) { + if (pius->address.s_addr == rpf->rpf_addr.u.prefix4.s_addr) + break; + } + + if (!pius) { + pius = XCALLOC(MTYPE_PIM_JP_AGG_GROUP, + sizeof(struct pim_iface_upstream_switch)); + pius->address.s_addr = rpf->rpf_addr.u.prefix4.s_addr; + pius->us = list_new(); + listnode_add_sort(pim_ifp->upstream_switch_list, pius); + } + + return pius; } -void -pim_jp_agg_remove_group (struct list *group, struct pim_upstream *up) +void pim_jp_agg_remove_group(struct list *group, struct pim_upstream *up) { - struct listnode *node, *nnode; - struct pim_jp_agg_group *jag = NULL; - struct pim_jp_sources *js = NULL; - - for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) - { - if (jag->group.s_addr == up->sg.grp.s_addr) - break; - } - - if (!jag) - return; - - for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) - { - if (js->up == up) - break; - } - - if (js) - { - js->up = NULL; - listnode_delete(jag->sources, js); - XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); - } - - if (jag->sources->count == 0) - { - list_delete(jag->sources); - jag->sources = NULL; - listnode_delete(group, jag); - XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); - } - + struct listnode *node, *nnode; + struct pim_jp_agg_group *jag = NULL; + struct pim_jp_sources *js = NULL; + + for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) { + if (jag->group.s_addr == up->sg.grp.s_addr) + break; + } + + if (!jag) + return; + + for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) { + if (js->up == up) + break; + } + + if (js) { + js->up = NULL; + listnode_delete(jag->sources, js); + XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); + } + + if (jag->sources->count == 0) { + list_delete(jag->sources); + jag->sources = NULL; + listnode_delete(group, jag); + XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); + } } -int -pim_jp_agg_is_in_list (struct list *group, struct pim_upstream *up) +int pim_jp_agg_is_in_list(struct list *group, struct pim_upstream *up) { - struct listnode *node, *nnode; - struct pim_jp_agg_group *jag = NULL; - struct pim_jp_sources *js = NULL; + struct listnode *node, *nnode; + struct pim_jp_agg_group *jag = NULL; + struct pim_jp_sources *js = NULL; - for (ALL_LIST_ELEMENTS (group, node, nnode, jag)) - { - if (jag->group.s_addr == up->sg.grp.s_addr) - break; - } + for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) { + if (jag->group.s_addr == up->sg.grp.s_addr) + break; + } - if (!jag) - return 0; + if (!jag) + return 0; - for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) - { - if (js->up == up) - return 1; - } + for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) { + if (js->up == up) + return 1; + } - return 0; - } + return 0; +} //#define PIM_JP_AGG_DEBUG 1 /* @@ -224,148 +210,137 @@ pim_jp_agg_is_in_list (struct list *group, struct pim_upstream *up) * can be safely compiled out in real * builds */ -void -pim_jp_agg_upstream_verification (struct pim_upstream *up, bool ignore) +void pim_jp_agg_upstream_verification(struct pim_upstream *up, bool ignore) { #ifdef PIM_JP_AGG_DEBUG - struct listnode *node; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *nnode; - - if (ignore && ifp == up->rpf.source_nexthop.interface) - continue; - - if (pim_ifp) - { - struct pim_neighbor *neigh; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, nnode, neigh)) - { - assert (!pim_jp_agg_is_in_list(neigh->upstream_jp_agg, up)); - } - } - } + struct listnode *node; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct pim_interface *pim_ifp = ifp->info; + struct listnode *nnode; + + if (ignore && ifp == up->rpf.source_nexthop.interface) + continue; + + if (pim_ifp) { + struct pim_neighbor *neigh; + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, + nnode, neigh)) { + assert(!pim_jp_agg_is_in_list( + neigh->upstream_jp_agg, up)); + } + } + } #else - return; + return; #endif } -void -pim_jp_agg_add_group (struct list *group, struct pim_upstream *up, bool is_join) +void pim_jp_agg_add_group(struct list *group, struct pim_upstream *up, + bool is_join) { - struct listnode *node, *nnode; - struct pim_jp_agg_group *jag = NULL; - struct pim_jp_sources *js = NULL; - - for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) - { - if (jag->group.s_addr == up->sg.grp.s_addr) - break; - } - - if (!jag) - { - jag = XCALLOC(MTYPE_PIM_JP_AGG_GROUP, sizeof (struct pim_jp_agg_group)); - jag->group.s_addr = up->sg.grp.s_addr; - jag->sources = list_new(); - jag->sources->cmp = pim_jp_agg_src_cmp; - jag->sources->del = (void (*)(void *))pim_jp_agg_src_free; - listnode_add_sort (group, jag); - } - - for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) - { - if (js->up == up) - break; - } - - if (!js) - { - js = XCALLOC(MTYPE_PIM_JP_AGG_SOURCE, sizeof (struct pim_jp_sources)); - js->up = up; - js->is_join = is_join; - listnode_add_sort (jag->sources, js); - } - else - { - if (js->is_join != is_join) - { - listnode_delete(jag->sources, js); - js->is_join = is_join; - listnode_add_sort (jag->sources, js); - } - } + struct listnode *node, *nnode; + struct pim_jp_agg_group *jag = NULL; + struct pim_jp_sources *js = NULL; + + for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) { + if (jag->group.s_addr == up->sg.grp.s_addr) + break; + } + + if (!jag) { + jag = XCALLOC(MTYPE_PIM_JP_AGG_GROUP, + sizeof(struct pim_jp_agg_group)); + jag->group.s_addr = up->sg.grp.s_addr; + jag->sources = list_new(); + jag->sources->cmp = pim_jp_agg_src_cmp; + jag->sources->del = (void (*)(void *))pim_jp_agg_src_free; + listnode_add_sort(group, jag); + } + + for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) { + if (js->up == up) + break; + } + + if (!js) { + js = XCALLOC(MTYPE_PIM_JP_AGG_SOURCE, + sizeof(struct pim_jp_sources)); + js->up = up; + js->is_join = is_join; + listnode_add_sort(jag->sources, js); + } else { + if (js->is_join != is_join) { + listnode_delete(jag->sources, js); + js->is_join = is_join; + listnode_add_sort(jag->sources, js); + } + } } -void -pim_jp_agg_switch_interface (struct pim_rpf *orpf, - struct pim_rpf *nrpf, - struct pim_upstream *up) +void pim_jp_agg_switch_interface(struct pim_rpf *orpf, struct pim_rpf *nrpf, + struct pim_upstream *up) { - struct pim_iface_upstream_switch *opius; - struct pim_iface_upstream_switch *npius; - - opius = pim_jp_agg_get_interface_upstream_switch_list(orpf); - npius = pim_jp_agg_get_interface_upstream_switch_list(nrpf); - - /* - * RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages - * - * Transitions from Joined State - * - * RPF'(S,G) changes not due to an Assert - * - * The upstream (S,G) state machine remains in Joined - * state. Send Join(S,G) to the new upstream neighbor, which is - * the new value of RPF'(S,G). Send Prune(S,G) to the old - * upstream neighbor, which is the old value of RPF'(S,G). Set - * the Join Timer (JT) to expire after t_periodic seconds. - */ - - /* send Prune(S,G) to the old upstream neighbor */ - if (opius) - pim_jp_agg_add_group (opius->us, up, false); - - /* send Join(S,G) to the current upstream neighbor */ - pim_jp_agg_add_group (npius->us, up, true); - + struct pim_iface_upstream_switch *opius; + struct pim_iface_upstream_switch *npius; + + opius = pim_jp_agg_get_interface_upstream_switch_list(orpf); + npius = pim_jp_agg_get_interface_upstream_switch_list(nrpf); + + /* + * RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages + * + * Transitions from Joined State + * + * RPF'(S,G) changes not due to an Assert + * + * The upstream (S,G) state machine remains in Joined + * state. Send Join(S,G) to the new upstream neighbor, which is + * the new value of RPF'(S,G). Send Prune(S,G) to the old + * upstream neighbor, which is the old value of RPF'(S,G). Set + * the Join Timer (JT) to expire after t_periodic seconds. + */ + + /* send Prune(S,G) to the old upstream neighbor */ + if (opius) + pim_jp_agg_add_group(opius->us, up, false); + + /* send Join(S,G) to the current upstream neighbor */ + pim_jp_agg_add_group(npius->us, up, true); } -void -pim_jp_agg_single_upstream_send (struct pim_rpf *rpf, - struct pim_upstream *up, - bool is_join) +void pim_jp_agg_single_upstream_send(struct pim_rpf *rpf, + struct pim_upstream *up, bool is_join) { - static struct list *groups = NULL; - static struct pim_jp_agg_group jag; - static struct pim_jp_sources js; + static struct list *groups = NULL; + static struct pim_jp_agg_group jag; + static struct pim_jp_sources js; - static bool first = true; + static bool first = true; - /* skip JP upstream messages if source is directly connected */ - if (!up || !rpf->source_nexthop.interface || - pim_if_connected_to_source (rpf->source_nexthop.interface, up->sg.src)) - return; + /* skip JP upstream messages if source is directly connected */ + if (!up || !rpf->source_nexthop.interface || pim_if_connected_to_source( + rpf->source_nexthop + .interface, + up->sg.src)) + return; - if (first) - { - groups = list_new(); + if (first) { + groups = list_new(); - jag.sources = list_new(); + jag.sources = list_new(); - listnode_add(groups, &jag); - listnode_add(jag.sources, &js); + listnode_add(groups, &jag); + listnode_add(jag.sources, &js); - first = false; - } + first = false; + } - jag.group.s_addr = up->sg.grp.s_addr; - js.up = up; - js.is_join = is_join; + jag.group.s_addr = up->sg.grp.s_addr; + js.up = up; + js.is_join = is_join; - pim_joinprune_send(rpf, groups); + pim_joinprune_send(rpf, groups); } diff --git a/pimd/pim_jp_agg.h b/pimd/pim_jp_agg.h index c3955f32f..aa21aa981 100644 --- a/pimd/pim_jp_agg.h +++ b/pimd/pim_jp_agg.h @@ -20,35 +20,31 @@ #ifndef __PIM_JP_AGG_H__ #define __PIM_JP_AGG_H__ -struct pim_jp_sources -{ - struct pim_upstream *up; - int is_join; +struct pim_jp_sources { + struct pim_upstream *up; + int is_join; }; -struct pim_jp_agg_group -{ - struct in_addr group; - struct list *sources; +struct pim_jp_agg_group { + struct in_addr group; + struct list *sources; }; -void pim_jp_agg_upstream_verification (struct pim_upstream *up, bool ignore); -int pim_jp_agg_is_in_list (struct list *group, struct pim_upstream *up); +void pim_jp_agg_upstream_verification(struct pim_upstream *up, bool ignore); +int pim_jp_agg_is_in_list(struct list *group, struct pim_upstream *up); -void pim_jp_agg_group_list_free (struct pim_jp_agg_group *jag); -int pim_jp_agg_group_list_cmp (void *arg1, void *arg2); +void pim_jp_agg_group_list_free(struct pim_jp_agg_group *jag); +int pim_jp_agg_group_list_cmp(void *arg1, void *arg2); -void pim_jp_agg_clear_group (struct list *group); -void pim_jp_agg_remove_group (struct list *group, struct pim_upstream *up); +void pim_jp_agg_clear_group(struct list *group); +void pim_jp_agg_remove_group(struct list *group, struct pim_upstream *up); -void pim_jp_agg_add_group (struct list *group, - struct pim_upstream *up, bool is_join); +void pim_jp_agg_add_group(struct list *group, struct pim_upstream *up, + bool is_join); -void pim_jp_agg_switch_interface (struct pim_rpf *orpf, - struct pim_rpf *nrpf, - struct pim_upstream *up); +void pim_jp_agg_switch_interface(struct pim_rpf *orpf, struct pim_rpf *nrpf, + struct pim_upstream *up); -void pim_jp_agg_single_upstream_send (struct pim_rpf *rpf, - struct pim_upstream *up, - bool is_join); +void pim_jp_agg_single_upstream_send(struct pim_rpf *rpf, + struct pim_upstream *up, bool is_join); #endif diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c index 1f3b29554..13f4240db 100644 --- a/pimd/pim_macro.c +++ b/pimd/pim_macro.c @@ -39,20 +39,19 @@ */ static int downstream_jpstate_isjoined(const struct pim_ifchannel *ch) { - switch (ch->ifjoin_state) - { - case PIM_IFJOIN_NOINFO: - case PIM_IFJOIN_PRUNE: - case PIM_IFJOIN_PRUNE_TMP: - case PIM_IFJOIN_PRUNE_PENDING_TMP: - return 0; - break; - case PIM_IFJOIN_JOIN: - case PIM_IFJOIN_PRUNE_PENDING: - return 1; - break; - } - return 0; + switch (ch->ifjoin_state) { + case PIM_IFJOIN_NOINFO: + case PIM_IFJOIN_PRUNE: + case PIM_IFJOIN_PRUNE_TMP: + case PIM_IFJOIN_PRUNE_PENDING_TMP: + return 0; + break; + case PIM_IFJOIN_JOIN: + case PIM_IFJOIN_PRUNE_PENDING: + return 1; + break; + } + return 0; } /* @@ -63,8 +62,8 @@ static int downstream_jpstate_isjoined(const struct pim_ifchannel *ch) */ static int local_receiver_include(const struct pim_ifchannel *ch) { - /* local_receiver_include(S,G,I) ? */ - return ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE; + /* local_receiver_include(S,G,I) ? */ + return ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE; } /* @@ -75,13 +74,13 @@ static int local_receiver_include(const struct pim_ifchannel *ch) joins(S,G) = { all interfaces I such that - DownstreamJPState(S,G,I) is either Join or Prune-Pending } + DownstreamJPState(S,G,I) is either Join or Prune-Pending } DownstreamJPState(S,G,I) is either Join or Prune-Pending ? */ int pim_macro_chisin_joins(const struct pim_ifchannel *ch) { - return downstream_jpstate_isjoined(ch); + return downstream_jpstate_isjoined(ch); } /* @@ -92,16 +91,16 @@ int pim_macro_chisin_joins(const struct pim_ifchannel *ch) lost_assert(S,G) = { all interfaces I such that - lost_assert(S,G,I) == TRUE } + lost_assert(S,G,I) == TRUE } bool lost_assert(S,G,I) { if ( RPF_interface(S) == I ) { - return FALSE + return FALSE } else { - return ( AssertWinner(S,G,I) != NULL AND - AssertWinner(S,G,I) != me AND - (AssertWinnerMetric(S,G,I) is better - than spt_assert_metric(S,I) ) + return ( AssertWinner(S,G,I) != NULL AND + AssertWinner(S,G,I) != me AND + (AssertWinnerMetric(S,G,I) is better + than spt_assert_metric(S,I) ) } } @@ -110,42 +109,40 @@ int pim_macro_chisin_joins(const struct pim_ifchannel *ch) */ int pim_macro_ch_lost_assert(const struct pim_ifchannel *ch) { - struct interface *ifp; - struct pim_interface *pim_ifp; - struct pim_assert_metric spt_assert_metric; - - ifp = ch->interface; - if (!ifp) { - zlog_warn("%s: (S,G)=%s: null interface", - __PRETTY_FUNCTION__, - ch->sg_str); - return 0; /* false */ - } - - /* RPF_interface(S) == I ? */ - if (ch->upstream->rpf.source_nexthop.interface == ifp) - return 0; /* false */ - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - return 0; /* false */ - } - - if (PIM_INADDR_IS_ANY(ch->ifassert_winner)) - return 0; /* false */ - - /* AssertWinner(S,G,I) == me ? */ - if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) - return 0; /* false */ - - spt_assert_metric = pim_macro_spt_assert_metric(&ch->upstream->rpf, - pim_ifp->primary_address); - - return pim_assert_metric_better(&ch->ifassert_winner_metric, - &spt_assert_metric); + struct interface *ifp; + struct pim_interface *pim_ifp; + struct pim_assert_metric spt_assert_metric; + + ifp = ch->interface; + if (!ifp) { + zlog_warn("%s: (S,G)=%s: null interface", __PRETTY_FUNCTION__, + ch->sg_str); + return 0; /* false */ + } + + /* RPF_interface(S) == I ? */ + if (ch->upstream->rpf.source_nexthop.interface == ifp) + return 0; /* false */ + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + return 0; /* false */ + } + + if (PIM_INADDR_IS_ANY(ch->ifassert_winner)) + return 0; /* false */ + + /* AssertWinner(S,G,I) == me ? */ + if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) + return 0; /* false */ + + spt_assert_metric = pim_macro_spt_assert_metric( + &ch->upstream->rpf, pim_ifp->primary_address); + + return pim_assert_metric_better(&ch->ifassert_winner_metric, + &spt_assert_metric); } /* @@ -153,47 +150,44 @@ int pim_macro_ch_lost_assert(const struct pim_ifchannel *ch) pim_include(S,G) = { all interfaces I such that: - ( (I_am_DR( I ) AND lost_assert(S,G,I) == FALSE ) - OR AssertWinner(S,G,I) == me ) - AND local_receiver_include(S,G,I) } + ( (I_am_DR( I ) AND lost_assert(S,G,I) == FALSE ) + OR AssertWinner(S,G,I) == me ) + AND local_receiver_include(S,G,I) } AssertWinner(S,G,I) is the IP source address of the Assert(S,G) packet that won an Assert. */ int pim_macro_chisin_pim_include(const struct pim_ifchannel *ch) { - struct pim_interface *pim_ifp = ch->interface->info; - - if (!pim_ifp) { - zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->interface->name); - return 0; /* false */ - } - - /* local_receiver_include(S,G,I) ? */ - if (!local_receiver_include(ch)) - return 0; /* false */ - - /* OR AssertWinner(S,G,I) == me ? */ - if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) - return 1; /* true */ - - return ( - /* I_am_DR( I ) ? */ - PIM_I_am_DR(pim_ifp) - && - /* lost_assert(S,G,I) == FALSE ? */ - (!pim_macro_ch_lost_assert(ch)) - ); + struct pim_interface *pim_ifp = ch->interface->info; + + if (!pim_ifp) { + zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); + return 0; /* false */ + } + + /* local_receiver_include(S,G,I) ? */ + if (!local_receiver_include(ch)) + return 0; /* false */ + + /* OR AssertWinner(S,G,I) == me ? */ + if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) + return 1; /* true */ + + return ( + /* I_am_DR( I ) ? */ + PIM_I_am_DR(pim_ifp) && + /* lost_assert(S,G,I) == FALSE ? */ + (!pim_macro_ch_lost_assert(ch))); } int pim_macro_chisin_joins_or_include(const struct pim_ifchannel *ch) { - if (pim_macro_chisin_joins(ch)) - return 1; /* true */ + if (pim_macro_chisin_joins(ch)) + return 1; /* true */ - return pim_macro_chisin_pim_include(ch); + return pim_macro_chisin_pim_include(ch); } /* @@ -203,9 +197,9 @@ int pim_macro_chisin_joins_or_include(const struct pim_ifchannel *ch) SPTbit(S,G)==TRUE AND (RPF_interface(S) != I) AND (I in ( ( joins(*,*,RP(G)) (+) joins(*,G) (-) prunes(S,G,rpt) ) - (+) ( pim_include(*,G) (-) pim_exclude(S,G) ) - (-) lost_assert(*,G) - (+) joins(S,G) (+) pim_include(S,G) ) ) + (+) ( pim_include(*,G) (-) pim_exclude(S,G) ) + (-) lost_assert(*,G) + (+) joins(S,G) (+) pim_include(S,G) ) ) CouldAssert(S,G,I) is true for downstream interfaces that would be in the inherited_olist(S,G) if (S,G) assert information was not taken @@ -225,25 +219,25 @@ int pim_macro_chisin_joins_or_include(const struct pim_ifchannel *ch) */ int pim_macro_ch_could_assert_eval(const struct pim_ifchannel *ch) { - struct interface *ifp; + struct interface *ifp; - ifp = ch->interface; - if (!ifp) { - zlog_warn("%s: (S,G)=%s: null interface", - __PRETTY_FUNCTION__, ch->sg_str); - return 0; /* false */ - } + ifp = ch->interface; + if (!ifp) { + zlog_warn("%s: (S,G)=%s: null interface", __PRETTY_FUNCTION__, + ch->sg_str); + return 0; /* false */ + } - /* SPTbit(S,G) == TRUE */ - if (ch->upstream->sptbit == PIM_UPSTREAM_SPTBIT_FALSE) - return 0; /* false */ + /* SPTbit(S,G) == TRUE */ + if (ch->upstream->sptbit == PIM_UPSTREAM_SPTBIT_FALSE) + return 0; /* false */ - /* RPF_interface(S) != I ? */ - if (ch->upstream->rpf.source_nexthop.interface == ifp) - return 0; /* false */ + /* RPF_interface(S) != I ? */ + if (ch->upstream->rpf.source_nexthop.interface == ifp) + return 0; /* false */ - /* I in joins(S,G) (+) pim_include(S,G) ? */ - return pim_macro_chisin_joins_or_include(ch); + /* I in joins(S,G) (+) pim_include(S,G) ? */ + return pim_macro_chisin_joins_or_include(ch); } /* @@ -260,14 +254,14 @@ int pim_macro_ch_could_assert_eval(const struct pim_ifchannel *ch) struct pim_assert_metric pim_macro_spt_assert_metric(const struct pim_rpf *rpf, struct in_addr ifaddr) { - struct pim_assert_metric metric; + struct pim_assert_metric metric; - metric.rpt_bit_flag = 0; - metric.metric_preference = rpf->source_nexthop.mrib_metric_preference; - metric.route_metric = rpf->source_nexthop.mrib_route_metric; - metric.ip_address = ifaddr; + metric.rpt_bit_flag = 0; + metric.metric_preference = rpf->source_nexthop.mrib_metric_preference; + metric.route_metric = rpf->source_nexthop.mrib_route_metric; + metric.ip_address = ifaddr; - return metric; + return metric; } /* @@ -287,24 +281,26 @@ struct pim_assert_metric pim_macro_spt_assert_metric(const struct pim_rpf *rpf, } } */ -struct pim_assert_metric pim_macro_ch_my_assert_metric_eval(const struct pim_ifchannel *ch) +struct pim_assert_metric +pim_macro_ch_my_assert_metric_eval(const struct pim_ifchannel *ch) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - pim_ifp = ch->interface->info; + pim_ifp = ch->interface->info; - if (pim_ifp) { - if (PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { - return pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address); - } - } + if (pim_ifp) { + if (PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { + return pim_macro_spt_assert_metric( + &ch->upstream->rpf, pim_ifp->primary_address); + } + } - return qpim_infinite_assert_metric; + return qpim_infinite_assert_metric; } /* RFC 4601 4.2. Data Packet Forwarding Rules - + Macro: inherited_olist(S,G) = inherited_olist(S,G,rpt) (+) @@ -312,10 +308,10 @@ struct pim_assert_metric pim_macro_ch_my_assert_metric_eval(const struct pim_ifc */ static int pim_macro_chisin_inherited_olist(const struct pim_ifchannel *ch) { - if (pim_macro_ch_lost_assert(ch)) - return 0; /* false */ + if (pim_macro_ch_lost_assert(ch)) + return 0; /* false */ - return pim_macro_chisin_joins_or_include(ch); + return pim_macro_chisin_joins_or_include(ch); } /* @@ -324,7 +320,7 @@ static int pim_macro_chisin_inherited_olist(const struct pim_ifchannel *ch) Additionally, the Packet forwarding rules of Section 4.2 can be simplified in a PIM-SSM-only router: - + iif is the incoming interface of the packet. oiflist = NULL if (iif == RPF_interface(S) AND UpstreamJPState(S,G) == Joined) { @@ -334,7 +330,7 @@ static int pim_macro_chisin_inherited_olist(const struct pim_ifchannel *ch) } oiflist = oiflist (-) iif forward packet on all interfaces in oiflist - + Macro: inherited_olist(S,G) = joins(S,G) (+) pim_include(S,G) (-) lost_assert(S,G) @@ -349,16 +345,16 @@ static int pim_macro_chisin_inherited_olist(const struct pim_ifchannel *ch) */ int pim_macro_chisin_oiflist(const struct pim_ifchannel *ch) { - if (ch->upstream->join_state == PIM_UPSTREAM_NOTJOINED) { - /* oiflist is NULL */ - return 0; /* false */ - } + if (ch->upstream->join_state == PIM_UPSTREAM_NOTJOINED) { + /* oiflist is NULL */ + return 0; /* false */ + } - /* oiflist = oiflist (-) iif */ - if (ch->interface == ch->upstream->rpf.source_nexthop.interface) - return 0; /* false */ + /* oiflist = oiflist (-) iif */ + if (ch->interface == ch->upstream->rpf.source_nexthop.interface) + return 0; /* false */ - return pim_macro_chisin_inherited_olist(ch); + return pim_macro_chisin_inherited_olist(ch); } /* @@ -380,45 +376,45 @@ int pim_macro_chisin_oiflist(const struct pim_ifchannel *ch) */ int pim_macro_assert_tracking_desired_eval(const struct pim_ifchannel *ch) { - struct pim_interface *pim_ifp; - struct interface *ifp; - - ifp = ch->interface; - if (!ifp) { - zlog_warn("%s: (S,G)=%s: null interface", - __PRETTY_FUNCTION__, ch->sg_str); - return 0; /* false */ - } - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); - return 0; /* false */ - } - - /* I in joins(S,G) ? */ - if (pim_macro_chisin_joins(ch)) - return 1; /* true */ - - /* local_receiver_include(S,G,I) ? */ - if (local_receiver_include(ch)) { - /* I_am_DR(I) ? */ - if (PIM_I_am_DR(pim_ifp)) - return 1; /* true */ - - /* AssertWinner(S,G,I) == me ? */ - if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) - return 1; /* true */ - } - - /* RPF_interface(S) == I ? */ - if (ch->upstream->rpf.source_nexthop.interface == ifp) { - /* JoinDesired(S,G) ? */ - if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(ch->upstream->flags)) - return 1; /* true */ - } - - return 0; /* false */ + struct pim_interface *pim_ifp; + struct interface *ifp; + + ifp = ch->interface; + if (!ifp) { + zlog_warn("%s: (S,G)=%s: null interface", __PRETTY_FUNCTION__, + ch->sg_str); + return 0; /* false */ + } + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); + return 0; /* false */ + } + + /* I in joins(S,G) ? */ + if (pim_macro_chisin_joins(ch)) + return 1; /* true */ + + /* local_receiver_include(S,G,I) ? */ + if (local_receiver_include(ch)) { + /* I_am_DR(I) ? */ + if (PIM_I_am_DR(pim_ifp)) + return 1; /* true */ + + /* AssertWinner(S,G,I) == me ? */ + if (ch->ifassert_winner.s_addr + == pim_ifp->primary_address.s_addr) + return 1; /* true */ + } + + /* RPF_interface(S) == I ? */ + if (ch->upstream->rpf.source_nexthop.interface == ifp) { + /* JoinDesired(S,G) ? */ + if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(ch->upstream->flags)) + return 1; /* true */ + } + + return 0; /* false */ } - diff --git a/pimd/pim_macro.h b/pimd/pim_macro.h index e07b2ece9..f310e244e 100644 --- a/pimd/pim_macro.h +++ b/pimd/pim_macro.h @@ -34,7 +34,8 @@ int pim_macro_chisin_joins_or_include(const struct pim_ifchannel *ch); int pim_macro_ch_could_assert_eval(const struct pim_ifchannel *ch); struct pim_assert_metric pim_macro_spt_assert_metric(const struct pim_rpf *rpf, struct in_addr ifaddr); -struct pim_assert_metric pim_macro_ch_my_assert_metric_eval(const struct pim_ifchannel *ch); +struct pim_assert_metric +pim_macro_ch_my_assert_metric_eval(const struct pim_ifchannel *ch); int pim_macro_chisin_oiflist(const struct pim_ifchannel *ch); int pim_macro_assert_tracking_desired_eval(const struct pim_ifchannel *ch); diff --git a/pimd/pim_main.c b/pimd/pim_main.c index a80059535..b8e6d8ad3 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -20,7 +20,7 @@ #include <zebra.h> #include "log.h" -#include "privs.h" +#include "privs.h" #include "version.h" #include <getopt.h> #include "command.h" @@ -49,115 +49,109 @@ extern struct host host; -struct option longopts[] = { - { 0 } -}; +struct option longopts[] = {{0}}; /* pimd privileges */ -zebra_capabilities_t _caps_p [] = -{ - ZCAP_NET_ADMIN, - ZCAP_SYS_ADMIN, - ZCAP_NET_RAW, - ZCAP_BIND, +zebra_capabilities_t _caps_p[] = { + ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN, ZCAP_NET_RAW, ZCAP_BIND, }; /* pimd privileges to run with */ -struct zebra_privs_t pimd_privs = -{ +struct zebra_privs_t pimd_privs = { #if defined(FRR_USER) && defined(FRR_GROUP) - .user = FRR_USER, - .group = FRR_GROUP, + .user = FRR_USER, + .group = FRR_GROUP, #endif #ifdef VTY_GROUP - .vty_group = VTY_GROUP, + .vty_group = VTY_GROUP, #endif - .caps_p = _caps_p, - .cap_num_p = sizeof(_caps_p)/sizeof(_caps_p[0]), - .cap_num_i = 0 -}; - -FRR_DAEMON_INFO(pimd, PIM, - .vty_port = PIMD_VTY_PORT, - - .proghelp = "Implementation of the PIM routing protocol.", - - .signals = pimd_signals, - .n_signals = 4 /* XXX array_size(pimd_signals) XXX*/, + .caps_p = _caps_p, + .cap_num_p = sizeof(_caps_p) / sizeof(_caps_p[0]), + .cap_num_i = 0}; - .privs = &pimd_privs, -) +FRR_DAEMON_INFO(pimd, PIM, .vty_port = PIMD_VTY_PORT, + .proghelp = "Implementation of the PIM routing protocol.", -int main(int argc, char** argv, char** envp) { - frr_preinit(&pimd_di, argc, argv); - frr_opt_add("", longopts, ""); + .signals = pimd_signals, + .n_signals = 4 /* XXX array_size(pimd_signals) XXX*/, - /* this while just reads the options */ - while (1) { - int opt; + .privs = &pimd_privs, ) - opt = frr_getopt(argc, argv, NULL); - if (opt == EOF) - break; - - switch (opt) { - case 0: - break; - default: - frr_help_exit (1); - break; - } - } - - master = frr_init(); - - /* - * Initializations - */ - pim_vrf_init (); - access_list_init(); - prefix_list_init (); - prefix_list_add_hook (pim_prefix_list_update); - prefix_list_delete_hook (pim_prefix_list_update); - - pim_route_map_init (); - pim_init(); - pim_msdp_init (master); - - /* - * Initialize zclient "update" and "lookup" sockets - */ - pim_zebra_init(); - pim_bfd_init (); - - frr_config_fork(); +int main(int argc, char **argv, char **envp) +{ + frr_preinit(&pimd_di, argc, argv); + frr_opt_add("", longopts, ""); + + /* this while just reads the options */ + while (1) { + int opt; + + opt = frr_getopt(argc, argv, NULL); + + if (opt == EOF) + break; + + switch (opt) { + case 0: + break; + default: + frr_help_exit(1); + break; + } + } + + master = frr_init(); + + /* + * Initializations + */ + pim_vrf_init(); + access_list_init(); + prefix_list_init(); + prefix_list_add_hook(pim_prefix_list_update); + prefix_list_delete_hook(pim_prefix_list_update); + + pim_route_map_init(); + pim_init(); + pim_msdp_init(master); + + /* + * Initialize zclient "update" and "lookup" sockets + */ + pim_zebra_init(); + pim_bfd_init(); + + frr_config_fork(); #ifdef PIM_DEBUG_BYDEFAULT - zlog_notice("PIM_DEBUG_BYDEFAULT: Enabling all debug commands"); - PIM_DO_DEBUG_PIM_EVENTS; - PIM_DO_DEBUG_PIM_PACKETS; - PIM_DO_DEBUG_PIM_TRACE; - PIM_DO_DEBUG_IGMP_EVENTS; - PIM_DO_DEBUG_IGMP_PACKETS; - PIM_DO_DEBUG_IGMP_TRACE; - PIM_DO_DEBUG_ZEBRA; + zlog_notice("PIM_DEBUG_BYDEFAULT: Enabling all debug commands"); + PIM_DO_DEBUG_PIM_EVENTS; + PIM_DO_DEBUG_PIM_PACKETS; + PIM_DO_DEBUG_PIM_TRACE; + PIM_DO_DEBUG_IGMP_EVENTS; + PIM_DO_DEBUG_IGMP_PACKETS; + PIM_DO_DEBUG_IGMP_TRACE; + PIM_DO_DEBUG_ZEBRA; #endif #ifdef PIM_CHECK_RECV_IFINDEX_SANITY - zlog_notice("PIM_CHECK_RECV_IFINDEX_SANITY: will match sock/recv ifindex"); + zlog_notice( + "PIM_CHECK_RECV_IFINDEX_SANITY: will match sock/recv ifindex"); #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH - zlog_notice("PIM_REPORT_RECV_IFINDEX_MISMATCH: will report sock/recv ifindex mismatch"); + zlog_notice( + "PIM_REPORT_RECV_IFINDEX_MISMATCH: will report sock/recv ifindex mismatch"); #endif #endif #ifdef PIM_UNEXPECTED_KERNEL_UPCALL - zlog_notice("PIM_UNEXPECTED_KERNEL_UPCALL: report unexpected kernel upcall"); + zlog_notice( + "PIM_UNEXPECTED_KERNEL_UPCALL: report unexpected kernel upcall"); #endif - frr_run(master); + frr_run(master); - /* never reached */ - return 0; + /* never reached */ + return 0; } diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c index d18b7f0c8..dff16c416 100644 --- a/pimd/pim_memory.c +++ b/pimd/pim_memory.c @@ -26,29 +26,29 @@ #include "pim_memory.h" DEFINE_MGROUP(PIMD, "pimd") -DEFINE_MTYPE(PIMD, PIM_CHANNEL_OIL, "PIM SSM (S,G) channel OIL") -DEFINE_MTYPE(PIMD, PIM_INTERFACE, "PIM interface") -DEFINE_MTYPE(PIMD, PIM_IGMP_JOIN, "PIM interface IGMP static join") -DEFINE_MTYPE(PIMD, PIM_IGMP_SOCKET, "PIM interface IGMP socket") -DEFINE_MTYPE(PIMD, PIM_IGMP_GROUP, "PIM interface IGMP group") +DEFINE_MTYPE(PIMD, PIM_CHANNEL_OIL, "PIM SSM (S,G) channel OIL") +DEFINE_MTYPE(PIMD, PIM_INTERFACE, "PIM interface") +DEFINE_MTYPE(PIMD, PIM_IGMP_JOIN, "PIM interface IGMP static join") +DEFINE_MTYPE(PIMD, PIM_IGMP_SOCKET, "PIM interface IGMP socket") +DEFINE_MTYPE(PIMD, PIM_IGMP_GROUP, "PIM interface IGMP group") DEFINE_MTYPE(PIMD, PIM_IGMP_GROUP_SOURCE, "PIM interface IGMP source") -DEFINE_MTYPE(PIMD, PIM_NEIGHBOR, "PIM interface neighbor") -DEFINE_MTYPE(PIMD, PIM_IFCHANNEL, "PIM interface (S,G) state") -DEFINE_MTYPE(PIMD, PIM_UPSTREAM, "PIM upstream (S,G) state") -DEFINE_MTYPE(PIMD, PIM_SSMPINGD, "PIM sspimgd socket") -DEFINE_MTYPE(PIMD, PIM_STATIC_ROUTE, "PIM Static Route") -DEFINE_MTYPE(PIMD, PIM_BR, "PIM Bridge Router info") -DEFINE_MTYPE(PIMD, PIM_RP, "PIM RP info") -DEFINE_MTYPE(PIMD, PIM_FILTER_NAME, "PIM RP filter info") -DEFINE_MTYPE(PIMD, PIM_MSDP_PEER, "PIM MSDP peer") -DEFINE_MTYPE(PIMD, PIM_MSDP_MG_NAME, "PIM MSDP mesh-group name") -DEFINE_MTYPE(PIMD, PIM_MSDP_SA, "PIM MSDP source-active cache") -DEFINE_MTYPE(PIMD, PIM_MSDP_MG, "PIM MSDP mesh group") -DEFINE_MTYPE(PIMD, PIM_MSDP_MG_MBR, "PIM MSDP mesh group mbr") -DEFINE_MTYPE(PIMD, PIM_SEC_ADDR, "PIM secondary address") -DEFINE_MTYPE(PIMD, PIM_JP_AGG_GROUP, "PIM JP AGG Group") -DEFINE_MTYPE(PIMD, PIM_JP_AGG_SOURCE, "PIM JP AGG Source") -DEFINE_MTYPE(PIMD, PIM_PIM_INSTANCE, "PIM global state") -DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state") -DEFINE_MTYPE(PIMD, PIM_SSM_INFO, "PIM SSM configuration") -DEFINE_MTYPE(PIMD, PIM_SPT_PLIST_NAME, "PIM SPT Prefix List Name") +DEFINE_MTYPE(PIMD, PIM_NEIGHBOR, "PIM interface neighbor") +DEFINE_MTYPE(PIMD, PIM_IFCHANNEL, "PIM interface (S,G) state") +DEFINE_MTYPE(PIMD, PIM_UPSTREAM, "PIM upstream (S,G) state") +DEFINE_MTYPE(PIMD, PIM_SSMPINGD, "PIM sspimgd socket") +DEFINE_MTYPE(PIMD, PIM_STATIC_ROUTE, "PIM Static Route") +DEFINE_MTYPE(PIMD, PIM_BR, "PIM Bridge Router info") +DEFINE_MTYPE(PIMD, PIM_RP, "PIM RP info") +DEFINE_MTYPE(PIMD, PIM_FILTER_NAME, "PIM RP filter info") +DEFINE_MTYPE(PIMD, PIM_MSDP_PEER, "PIM MSDP peer") +DEFINE_MTYPE(PIMD, PIM_MSDP_MG_NAME, "PIM MSDP mesh-group name") +DEFINE_MTYPE(PIMD, PIM_MSDP_SA, "PIM MSDP source-active cache") +DEFINE_MTYPE(PIMD, PIM_MSDP_MG, "PIM MSDP mesh group") +DEFINE_MTYPE(PIMD, PIM_MSDP_MG_MBR, "PIM MSDP mesh group mbr") +DEFINE_MTYPE(PIMD, PIM_SEC_ADDR, "PIM secondary address") +DEFINE_MTYPE(PIMD, PIM_JP_AGG_GROUP, "PIM JP AGG Group") +DEFINE_MTYPE(PIMD, PIM_JP_AGG_SOURCE, "PIM JP AGG Source") +DEFINE_MTYPE(PIMD, PIM_PIM_INSTANCE, "PIM global state") +DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state") +DEFINE_MTYPE(PIMD, PIM_SSM_INFO, "PIM SSM configuration") +DEFINE_MTYPE(PIMD, PIM_SPT_PLIST_NAME, "PIM SPT Prefix List Name") diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 01747268a..a92b01ca0 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -47,358 +47,360 @@ static void mroute_read_on(void); static int pim_mroute_set(int fd, int enable) { - int err; - int opt = enable ? MRT_INIT : MRT_DONE; - socklen_t opt_len = sizeof(opt); - int rcvbuf = 1024 * 1024 * 8; - long flags; - - err = setsockopt(fd, IPPROTO_IP, opt, &opt, opt_len); - if (err) { - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - fd, enable ? "MRT_INIT" : "MRT_DONE", opt, errno, safe_strerror(errno)); - return -1; - } - - err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); - if (err) { - zlog_warn("%s: failure: setsockopt(fd=%d, SOL_SOCKET, %d): errno=%d: %s", - __PRETTY_FUNCTION__, fd, rcvbuf, errno, safe_strerror(errno)); - } - - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) - { - zlog_warn("Could not get flags on socket fd:%d %d %s", - fd, errno, safe_strerror(errno)); - close (fd); - return -1; - } - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) - { - zlog_warn("Could not set O_NONBLOCK on socket fd:%d %d %s", - fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } + int err; + int opt = enable ? MRT_INIT : MRT_DONE; + socklen_t opt_len = sizeof(opt); + int rcvbuf = 1024 * 1024 * 8; + long flags; + + err = setsockopt(fd, IPPROTO_IP, opt, &opt, opt_len); + if (err) { + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, fd, + enable ? "MRT_INIT" : "MRT_DONE", opt, errno, + safe_strerror(errno)); + return -1; + } - if (enable) - { + err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); + if (err) { + zlog_warn( + "%s: failure: setsockopt(fd=%d, SOL_SOCKET, %d): errno=%d: %s", + __PRETTY_FUNCTION__, fd, rcvbuf, errno, + safe_strerror(errno)); + } + + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) { + zlog_warn("Could not get flags on socket fd:%d %d %s", fd, + errno, safe_strerror(errno)); + close(fd); + return -1; + } + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { + zlog_warn("Could not set O_NONBLOCK on socket fd:%d %d %s", fd, + errno, safe_strerror(errno)); + close(fd); + return -1; + } + + if (enable) { #if defined linux - int upcalls = IGMPMSG_WRVIFWHOLE; - opt = MRT_PIM; - - err = setsockopt (fd, IPPROTO_IP, opt, &upcalls, sizeof (upcalls)); - if (err) - { - zlog_warn ("Failure to register for VIFWHOLE and WRONGVIF upcalls %d %s", - errno, safe_strerror (errno)); - return -1; - } + int upcalls = IGMPMSG_WRVIFWHOLE; + opt = MRT_PIM; + + err = setsockopt(fd, IPPROTO_IP, opt, &upcalls, + sizeof(upcalls)); + if (err) { + zlog_warn( + "Failure to register for VIFWHOLE and WRONGVIF upcalls %d %s", + errno, safe_strerror(errno)); + return -1; + } #else - zlog_warn ("PIM-SM will not work properly on this platform, until the ability to receive the WRVIFWHOLE upcall"); + zlog_warn( + "PIM-SM will not work properly on this platform, until the ability to receive the WRVIFWHOLE upcall"); #endif - } - - return 0; + } + + return 0; } static const char *igmpmsgtype2str[IGMPMSG_WRVIFWHOLE + 1] = { - "<unknown_upcall?>", - "NOCACHE", - "WRONGVIF", - "WHOLEPKT", - "WRVIFWHOLE" }; - -static int -pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg) + "<unknown_upcall?>", "NOCACHE", "WRONGVIF", "WHOLEPKT", "WRVIFWHOLE"}; + +static int pim_mroute_msg_nocache(int fd, struct interface *ifp, + const struct igmpmsg *msg) { - struct pim_interface *pim_ifp = ifp->info; - struct pim_upstream *up; - struct pim_rpf *rpg; - struct prefix_sg sg; - - rpg = RP(msg->im_dst); - /* - * If the incoming interface is unknown OR - * the Interface type is SSM we don't need to - * do anything here - */ - if ((pim_rpf_addr_is_inaddr_none (rpg)) || - (!pim_ifp) || - (!(PIM_I_am_DR(pim_ifp)))) - { - if (PIM_DEBUG_MROUTE_DETAIL) - zlog_debug ("%s: Interface is not configured correctly to handle incoming packet: Could be !DR, !pim_ifp, !SM, !RP", - __PRETTY_FUNCTION__); - return 0; - } + struct pim_interface *pim_ifp = ifp->info; + struct pim_upstream *up; + struct pim_rpf *rpg; + struct prefix_sg sg; + + rpg = RP(msg->im_dst); + /* + * If the incoming interface is unknown OR + * the Interface type is SSM we don't need to + * do anything here + */ + if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp) + || (!(PIM_I_am_DR(pim_ifp)))) { + if (PIM_DEBUG_MROUTE_DETAIL) + zlog_debug( + "%s: Interface is not configured correctly to handle incoming packet: Could be !DR, !pim_ifp, !SM, !RP", + __PRETTY_FUNCTION__); + return 0; + } - /* - * If we've received a multicast packet that isn't connected to - * us - */ - if (!pim_if_connected_to_source (ifp, msg->im_src)) - { - if (PIM_DEBUG_MROUTE_DETAIL) - zlog_debug ("%s: Received incoming packet that doesn't originate on our seg", - __PRETTY_FUNCTION__); - return 0; - } + /* + * If we've received a multicast packet that isn't connected to + * us + */ + if (!pim_if_connected_to_source(ifp, msg->im_src)) { + if (PIM_DEBUG_MROUTE_DETAIL) + zlog_debug( + "%s: Received incoming packet that doesn't originate on our seg", + __PRETTY_FUNCTION__); + return 0; + } - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = msg->im_src; - sg.grp = msg->im_dst; + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = msg->im_src; + sg.grp = msg->im_dst; + + up = pim_upstream_find_or_add(&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, + __PRETTY_FUNCTION__); + if (!up) { + if (PIM_DEBUG_MROUTE) { + zlog_debug( + "%s: Failure to add upstream information for %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); + } + return 0; + } - up = pim_upstream_find_or_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); - if (!up) - { - if (PIM_DEBUG_MROUTE) - { - zlog_debug("%s: Failure to add upstream information for %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg)); - } - return 0; - } + /* + * I moved this debug till after the actual add because + * I want to take advantage of the up->sg_str being filled in. + */ + if (PIM_DEBUG_MROUTE) { + zlog_debug("%s: Adding a Route %s for WHOLEPKT consumption", + __PRETTY_FUNCTION__, up->sg_str); + } - /* - * I moved this debug till after the actual add because - * I want to take advantage of the up->sg_str being filled in. - */ - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: Adding a Route %s for WHOLEPKT consumption", - __PRETTY_FUNCTION__, up->sg_str); - } - - PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - - up->channel_oil->cc.pktcnt++; - PIM_UPSTREAM_FLAG_SET_FHR(up->flags); - // resolve mfcc_parent prior to mroute_add in channel_add_oif - if (up->channel_oil->oil.mfcc_parent >= MAXVIFS) - { - int vif_index = 0; - vif_index = - pim_if_find_vifindex_by_ifindex (up->rpf.source_nexthop. - interface->ifindex); - up->channel_oil->oil.mfcc_parent = vif_index; - } - pim_register_join (up); + PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); + pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); + + up->channel_oil->cc.pktcnt++; + PIM_UPSTREAM_FLAG_SET_FHR(up->flags); + // resolve mfcc_parent prior to mroute_add in channel_add_oif + if (up->channel_oil->oil.mfcc_parent >= MAXVIFS) { + int vif_index = 0; + vif_index = pim_if_find_vifindex_by_ifindex( + up->rpf.source_nexthop.interface->ifindex); + up->channel_oil->oil.mfcc_parent = vif_index; + } + pim_register_join(up); - return 0; + return 0; } -static int -pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf) +static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp, + const char *buf) { - struct pim_interface *pim_ifp; - struct prefix_sg sg; - struct pim_rpf *rpg; - const struct ip *ip_hdr; - struct pim_upstream *up; - - ip_hdr = (const struct ip *)buf; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = ip_hdr->ip_src; - sg.grp = ip_hdr->ip_dst; - - up = pim_upstream_find(&sg); - if (!up) { - struct prefix_sg star = sg; - star.src.s_addr = INADDR_ANY; - - up = pim_upstream_find(&star); - - if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) - { - up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, __PRETTY_FUNCTION__); - if (!up) - { - if (PIM_DEBUG_MROUTE) - zlog_debug ("%s: Unable to create upstream information for %s", - __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); - return 0; - } - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - pim_upstream_inherited_olist (up); - pim_upstream_switch(up, PIM_UPSTREAM_JOINED); - - if (PIM_DEBUG_MROUTE) - zlog_debug ("%s: Creating %s upstream on LHR", - __PRETTY_FUNCTION__, up->sg_str); - return 0; - } - if (PIM_DEBUG_MROUTE_DETAIL) { - zlog_debug("%s: Unable to find upstream channel WHOLEPKT%s", - __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); - } - return 0; - } + struct pim_interface *pim_ifp; + struct prefix_sg sg; + struct pim_rpf *rpg; + const struct ip *ip_hdr; + struct pim_upstream *up; + + ip_hdr = (const struct ip *)buf; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = ip_hdr->ip_src; + sg.grp = ip_hdr->ip_dst; + + up = pim_upstream_find(&sg); + if (!up) { + struct prefix_sg star = sg; + star.src.s_addr = INADDR_ANY; + + up = pim_upstream_find(&star); + + if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) { + up = pim_upstream_add(&sg, ifp, + PIM_UPSTREAM_FLAG_MASK_SRC_LHR, + __PRETTY_FUNCTION__); + if (!up) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: Unable to create upstream information for %s", + __PRETTY_FUNCTION__, + pim_str_sg_dump(&sg)); + return 0; + } + pim_upstream_keep_alive_timer_start( + up, qpim_keep_alive_time); + pim_upstream_inherited_olist(up); + pim_upstream_switch(up, PIM_UPSTREAM_JOINED); + + if (PIM_DEBUG_MROUTE) + zlog_debug("%s: Creating %s upstream on LHR", + __PRETTY_FUNCTION__, up->sg_str); + return 0; + } + if (PIM_DEBUG_MROUTE_DETAIL) { + zlog_debug( + "%s: Unable to find upstream channel WHOLEPKT%s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); + } + return 0; + } - pim_ifp = up->rpf.source_nexthop.interface->info; + pim_ifp = up->rpf.source_nexthop.interface->info; - rpg = RP(sg.grp); + rpg = RP(sg.grp); - if ((pim_rpf_addr_is_inaddr_none (rpg)) || - (!pim_ifp) || - (!(PIM_I_am_DR(pim_ifp)))) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: Failed Check send packet", __PRETTY_FUNCTION__); - } - return 0; - } + if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp) + || (!(PIM_I_am_DR(pim_ifp)))) { + if (PIM_DEBUG_MROUTE) { + zlog_debug("%s: Failed Check send packet", + __PRETTY_FUNCTION__); + } + return 0; + } - /* - * If we've received a register suppress - */ - if (!up->t_rs_timer) - { - if (pim_is_grp_ssm (sg.grp)) - { - if (PIM_DEBUG_PIM_REG) - zlog_debug ("%s register forward skipped as group is SSM", - pim_str_sg_dump (&sg)); - return 0; - } - pim_register_send((uint8_t *)buf + sizeof(struct ip), - ntohs (ip_hdr->ip_len) - sizeof (struct ip), - pim_ifp->primary_address, rpg, 0, up); - } - return 0; + /* + * If we've received a register suppress + */ + if (!up->t_rs_timer) { + if (pim_is_grp_ssm(sg.grp)) { + if (PIM_DEBUG_PIM_REG) + zlog_debug( + "%s register forward skipped as group is SSM", + pim_str_sg_dump(&sg)); + return 0; + } + pim_register_send((uint8_t *)buf + sizeof(struct ip), + ntohs(ip_hdr->ip_len) - sizeof(struct ip), + pim_ifp->primary_address, rpg, 0, up); + } + return 0; } -static int -pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *msg) +static int pim_mroute_msg_wrongvif(int fd, struct interface *ifp, + const struct igmpmsg *msg) { - struct pim_ifchannel *ch; - struct pim_interface *pim_ifp; - struct prefix_sg sg; + struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct prefix_sg sg; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = msg->im_src; + sg.grp = msg->im_dst; + + /* + Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. + + RFC 4601 4.8.2. PIM-SSM-Only Routers + + iif is the incoming interface of the packet. + if (iif is in inherited_olist(S,G)) { + send Assert(S,G) on iif + } + */ + + if (!ifp) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF (S,G)=%s could not find input interface for input_vif_index=%d", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + msg->im_vif); + return -1; + } - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = msg->im_src; - sg.grp = msg->im_dst; + pim_ifp = ifp->info; + if (!pim_ifp) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF (S,G)=%s multicast not enabled on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + ifp->name); + return -2; + } - /* - Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. + ch = pim_ifchannel_find(ifp, &sg); + if (!ch) { + struct prefix_sg star_g = sg; + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF (S,G)=%s could not find channel on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + ifp->name); + + star_g.src.s_addr = INADDR_ANY; + ch = pim_ifchannel_find(ifp, &star_g); + if (!ch) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF (*,G)=%s could not find channel on interface %s", + __PRETTY_FUNCTION__, + pim_str_sg_dump(&star_g), ifp->name); + return -3; + } + } - RFC 4601 4.8.2. PIM-SSM-Only Routers + /* + RFC 4601: 4.6.1. (S,G) Assert Message State Machine + + Transitions from NoInfo State + + An (S,G) data packet arrives on interface I, AND + CouldAssert(S,G,I)==TRUE An (S,G) data packet arrived on an + downstream interface that is in our (S,G) outgoing interface + list. We optimistically assume that we will be the assert + winner for this (S,G), and so we transition to the "I am Assert + Winner" state and perform Actions A1 (below), which will + initiate the assert negotiation for (S,G). + */ + + if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { + if (PIM_DEBUG_MROUTE) { + zlog_debug( + "%s: WRONGVIF (S,G)=%s channel is not on Assert NoInfo state for interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + } + return -4; + } - iif is the incoming interface of the packet. - if (iif is in inherited_olist(S,G)) { - send Assert(S,G) on iif - } - */ - - if (!ifp) { - if (PIM_DEBUG_MROUTE) - zlog_debug("%s: WRONGVIF (S,G)=%s could not find input interface for input_vif_index=%d", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), msg->im_vif); - return -1; - } - - pim_ifp = ifp->info; - if (!pim_ifp) { - if (PIM_DEBUG_MROUTE) - zlog_debug("%s: WRONGVIF (S,G)=%s multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), ifp->name); - return -2; - } - - ch = pim_ifchannel_find(ifp, &sg); - if (!ch) { - struct prefix_sg star_g = sg; - if (PIM_DEBUG_MROUTE) - zlog_debug("%s: WRONGVIF (S,G)=%s could not find channel on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump(&sg), ifp->name); - - star_g.src.s_addr = INADDR_ANY; - ch = pim_ifchannel_find(ifp, &star_g); - if (!ch) { - if (PIM_DEBUG_MROUTE) - zlog_debug("%s: WRONGVIF (*,G)=%s could not find channel on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump(&star_g), ifp->name); - return -3; - } - } - - /* - RFC 4601: 4.6.1. (S,G) Assert Message State Machine - - Transitions from NoInfo State - - An (S,G) data packet arrives on interface I, AND - CouldAssert(S,G,I)==TRUE An (S,G) data packet arrived on an - downstream interface that is in our (S,G) outgoing interface - list. We optimistically assume that we will be the assert - winner for this (S,G), and so we transition to the "I am Assert - Winner" state and perform Actions A1 (below), which will - initiate the assert negotiation for (S,G). - */ - - if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=%s channel is not on Assert NoInfo state for interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - } - return -4; - } - - if (!PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=%s interface %s is not downstream for channel", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - } - return -5; - } - - if (assert_action_a1(ch)) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=%s assert_action_a1 failure on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - } - return -6; - } + if (!PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { + if (PIM_DEBUG_MROUTE) { + zlog_debug( + "%s: WRONGVIF (S,G)=%s interface %s is not downstream for channel", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + } + return -5; + } + + if (assert_action_a1(ch)) { + if (PIM_DEBUG_MROUTE) { + zlog_debug( + "%s: WRONGVIF (S,G)=%s assert_action_a1 failure on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + } + return -6; + } - return 0; + return 0; } -static int -pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) +static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, + const char *buf) { - const struct ip *ip_hdr = (const struct ip *)buf; - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - struct pim_upstream *up; - struct prefix_sg star_g; - struct prefix_sg sg; - struct channel_oil *oil; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = ip_hdr->ip_src; - sg.grp = ip_hdr->ip_dst; - - ch = pim_ifchannel_find(ifp, &sg); - if (ch) - { - if (PIM_DEBUG_MROUTE) - zlog_debug ("WRVIFWHOLE (S,G)=%s found ifchannel on interface %s", - ch->sg_str, ifp->name); - return -1; - } + const struct ip *ip_hdr = (const struct ip *)buf; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + struct pim_upstream *up; + struct prefix_sg star_g; + struct prefix_sg sg; + struct channel_oil *oil; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = ip_hdr->ip_src; + sg.grp = ip_hdr->ip_dst; + + ch = pim_ifchannel_find(ifp, &sg); + if (ch) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "WRVIFWHOLE (S,G)=%s found ifchannel on interface %s", + ch->sg_str, ifp->name); + return -1; + } - star_g = sg; - star_g.src.s_addr = INADDR_ANY; + star_g = sg; + star_g.src.s_addr = INADDR_ANY; #if 0 ch = pim_ifchannel_find(ifp, &star_g); if (ch) @@ -410,290 +412,313 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) } #endif - up = pim_upstream_find (&sg); - if (up) - { - struct pim_upstream *parent; - struct pim_nexthop source; - struct pim_rpf *rpf = RP (sg.grp); - if (!rpf || !rpf->source_nexthop.interface) - return 0; - - /* - * If we have received a WRVIFWHOLE and are at this - * point, we could be receiving the packet on the *,G - * tree, let's check and if so we can safely drop - * it. - */ - parent = pim_upstream_find (&star_g); - if (parent && parent->rpf.source_nexthop.interface == ifp) - return 0; - - pim_ifp = rpf->source_nexthop.interface->info; - - memset (&source, 0, sizeof (source)); - /* - * If we are the fhr that means we are getting a callback during - * the pimreg period, so I believe we can ignore this packet - */ - if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) - { - //No if channel, but upstream we are at the RP. - if (pim_nexthop_lookup (&source, up->upstream_register, 0) == 0) - pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); - if (!up->channel_oil) - up->channel_oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); - pim_upstream_inherited_olist (up); - if (!up->channel_oil->installed) - pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); - pim_upstream_set_sptbit (up, ifp); - } - else - { - if (I_am_RP (up->sg.grp)) - { - if (pim_nexthop_lookup (&source, up->upstream_register, 0) == 0) - pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - } - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - pim_upstream_inherited_olist (up); - pim_mroute_msg_wholepkt (fd, ifp, buf); - } - return 0; - } + up = pim_upstream_find(&sg); + if (up) { + struct pim_upstream *parent; + struct pim_nexthop source; + struct pim_rpf *rpf = RP(sg.grp); + if (!rpf || !rpf->source_nexthop.interface) + return 0; + + /* + * If we have received a WRVIFWHOLE and are at this + * point, we could be receiving the packet on the *,G + * tree, let's check and if so we can safely drop + * it. + */ + parent = pim_upstream_find(&star_g); + if (parent && parent->rpf.source_nexthop.interface == ifp) + return 0; + + pim_ifp = rpf->source_nexthop.interface->info; + + memset(&source, 0, sizeof(source)); + /* + * If we are the fhr that means we are getting a callback during + * the pimreg period, so I believe we can ignore this packet + */ + if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) { + // No if channel, but upstream we are at the RP. + if (pim_nexthop_lookup(&source, up->upstream_register, + 0) + == 0) + pim_register_stop_send(source.interface, &sg, + pim_ifp->primary_address, + up->upstream_register); + if (!up->channel_oil) + up->channel_oil = pim_channel_oil_add( + &sg, pim_ifp->mroute_vif_index); + pim_upstream_inherited_olist(up); + if (!up->channel_oil->installed) + pim_mroute_add(up->channel_oil, + __PRETTY_FUNCTION__); + pim_upstream_set_sptbit(up, ifp); + } else { + if (I_am_RP(up->sg.grp)) { + if (pim_nexthop_lookup(&source, + up->upstream_register, 0) + == 0) + pim_register_stop_send( + source.interface, &sg, + pim_ifp->primary_address, + up->upstream_register); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + } + pim_upstream_keep_alive_timer_start( + up, qpim_keep_alive_time); + pim_upstream_inherited_olist(up); + pim_mroute_msg_wholepkt(fd, ifp, buf); + } + return 0; + } - pim_ifp = ifp->info; - oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); - if (!oil->installed) - pim_mroute_add (oil, __PRETTY_FUNCTION__); - if (pim_if_connected_to_source (ifp, sg.src)) - { - up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); - if (!up) - { - if (PIM_DEBUG_MROUTE) - zlog_debug ("%s: WRONGVIF%s unable to create upstream on interface", - pim_str_sg_dump (&sg), ifp->name); - return -2; - } - PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - up->channel_oil = oil; - up->channel_oil->cc.pktcnt++; - pim_register_join (up); - pim_upstream_inherited_olist (up); - - // Send the packet to the RP - pim_mroute_msg_wholepkt (fd, ifp, buf); - } + pim_ifp = ifp->info; + oil = pim_channel_oil_add(&sg, pim_ifp->mroute_vif_index); + if (!oil->installed) + pim_mroute_add(oil, __PRETTY_FUNCTION__); + if (pim_if_connected_to_source(ifp, sg.src)) { + up = pim_upstream_add(&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, + __PRETTY_FUNCTION__); + if (!up) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF%s unable to create upstream on interface", + pim_str_sg_dump(&sg), ifp->name); + return -2; + } + PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); + pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); + up->channel_oil = oil; + up->channel_oil->cc.pktcnt++; + pim_register_join(up); + pim_upstream_inherited_olist(up); + + // Send the packet to the RP + pim_mroute_msg_wholepkt(fd, ifp, buf); + } - return 0; + return 0; } int pim_mroute_msg(int fd, const char *buf, int buf_size) { - struct interface *ifp; - struct pim_interface *pim_ifp; - const struct ip *ip_hdr; - const struct igmpmsg *msg; - char ip_src_str[INET_ADDRSTRLEN] = ""; - char ip_dst_str[INET_ADDRSTRLEN] = ""; - char src_str[INET_ADDRSTRLEN] = "<src?>"; - char grp_str[INET_ADDRSTRLEN] = "<grp?>"; - struct in_addr ifaddr; - struct igmp_sock *igmp; - - ip_hdr = (const struct ip *) buf; - - if (ip_hdr->ip_p == IPPROTO_IGMP) { - - /* We have the IP packet but we do not know which interface this packet was - * received on. Find the interface that is on the same subnet as the source - * of the IP packet. - */ - ifp = pim_if_lookup_address_vrf (ip_hdr->ip_src, VRF_DEFAULT); - - if (!ifp) { - if (PIM_DEBUG_MROUTE_DETAIL) { - pim_inet4_dump("<src?>", ip_hdr->ip_src, ip_src_str, sizeof(ip_src_str)); - pim_inet4_dump("<dst?>", ip_hdr->ip_dst, ip_dst_str, sizeof(ip_dst_str)); - - zlog_warn("%s: igmp kernel upcall could not find usable interface for %s -> %s", - __PRETTY_FUNCTION__, - ip_src_str, - ip_dst_str); - } - return 0; - } - pim_ifp = ifp->info; - ifaddr = pim_find_primary_addr(ifp); - igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr); - - if (PIM_DEBUG_MROUTE) { - pim_inet4_dump("<src?>", ip_hdr->ip_src, ip_src_str, sizeof(ip_src_str)); - pim_inet4_dump("<dst?>", ip_hdr->ip_dst, ip_dst_str, sizeof(ip_dst_str)); - - zlog_warn("%s: igmp kernel upcall on %s(%p) for %s -> %s", - __PRETTY_FUNCTION__, ifp->name, igmp, ip_src_str, ip_dst_str); - } - if (igmp) - pim_igmp_packet(igmp, (char *)buf, buf_size); - - } else if (ip_hdr->ip_p) { - if (PIM_DEBUG_MROUTE_DETAIL) { - pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", ip_hdr->ip_dst, grp_str, sizeof(grp_str)); - zlog_debug("%s: no kernel upcall proto=%d src: %s dst: %s msg_size=%d", - __PRETTY_FUNCTION__, ip_hdr->ip_p, src_str, grp_str, buf_size); - } - - } else { - msg = (const struct igmpmsg *) buf; - - ifp = pim_if_find_by_vif_index(msg->im_vif); - - if (!ifp) - return 0; - if (PIM_DEBUG_MROUTE) { - pim_inet4_dump("<src?>", msg->im_src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", msg->im_dst, grp_str, sizeof(grp_str)); - zlog_warn("%s: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d size=%d", - __PRETTY_FUNCTION__, - igmpmsgtype2str[msg->im_msgtype], - msg->im_msgtype, - ip_hdr->ip_p, - fd, - src_str, - grp_str, - ifp->name, - msg->im_vif, buf_size); - } - - switch (msg->im_msgtype) { - case IGMPMSG_WRONGVIF: - return pim_mroute_msg_wrongvif(fd, ifp, msg); - break; - case IGMPMSG_NOCACHE: - return pim_mroute_msg_nocache(fd, ifp, msg); - break; - case IGMPMSG_WHOLEPKT: - return pim_mroute_msg_wholepkt(fd, ifp, (const char *)msg); - break; - case IGMPMSG_WRVIFWHOLE: - return pim_mroute_msg_wrvifwhole (fd, ifp, (const char *)msg); - break; - default: - break; - } - } + struct interface *ifp; + struct pim_interface *pim_ifp; + const struct ip *ip_hdr; + const struct igmpmsg *msg; + char ip_src_str[INET_ADDRSTRLEN] = ""; + char ip_dst_str[INET_ADDRSTRLEN] = ""; + char src_str[INET_ADDRSTRLEN] = "<src?>"; + char grp_str[INET_ADDRSTRLEN] = "<grp?>"; + struct in_addr ifaddr; + struct igmp_sock *igmp; + + ip_hdr = (const struct ip *)buf; + + if (ip_hdr->ip_p == IPPROTO_IGMP) { + + /* We have the IP packet but we do not know which interface this + * packet was + * received on. Find the interface that is on the same subnet as + * the source + * of the IP packet. + */ + ifp = pim_if_lookup_address_vrf(ip_hdr->ip_src, VRF_DEFAULT); + + if (!ifp) { + if (PIM_DEBUG_MROUTE_DETAIL) { + pim_inet4_dump("<src?>", ip_hdr->ip_src, + ip_src_str, sizeof(ip_src_str)); + pim_inet4_dump("<dst?>", ip_hdr->ip_dst, + ip_dst_str, sizeof(ip_dst_str)); + + zlog_warn( + "%s: igmp kernel upcall could not find usable interface for %s -> %s", + __PRETTY_FUNCTION__, ip_src_str, + ip_dst_str); + } + return 0; + } + pim_ifp = ifp->info; + ifaddr = pim_find_primary_addr(ifp); + igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, + ifaddr); + + if (PIM_DEBUG_MROUTE) { + pim_inet4_dump("<src?>", ip_hdr->ip_src, ip_src_str, + sizeof(ip_src_str)); + pim_inet4_dump("<dst?>", ip_hdr->ip_dst, ip_dst_str, + sizeof(ip_dst_str)); + + zlog_warn( + "%s: igmp kernel upcall on %s(%p) for %s -> %s", + __PRETTY_FUNCTION__, ifp->name, igmp, + ip_src_str, ip_dst_str); + } + if (igmp) + pim_igmp_packet(igmp, (char *)buf, buf_size); + + } else if (ip_hdr->ip_p) { + if (PIM_DEBUG_MROUTE_DETAIL) { + pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, + sizeof(src_str)); + pim_inet4_dump("<grp?>", ip_hdr->ip_dst, grp_str, + sizeof(grp_str)); + zlog_debug( + "%s: no kernel upcall proto=%d src: %s dst: %s msg_size=%d", + __PRETTY_FUNCTION__, ip_hdr->ip_p, src_str, + grp_str, buf_size); + } + + } else { + msg = (const struct igmpmsg *)buf; + + ifp = pim_if_find_by_vif_index(msg->im_vif); + + if (!ifp) + return 0; + if (PIM_DEBUG_MROUTE) { + pim_inet4_dump("<src?>", msg->im_src, src_str, + sizeof(src_str)); + pim_inet4_dump("<grp?>", msg->im_dst, grp_str, + sizeof(grp_str)); + zlog_warn( + "%s: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d size=%d", + __PRETTY_FUNCTION__, + igmpmsgtype2str[msg->im_msgtype], + msg->im_msgtype, ip_hdr->ip_p, fd, src_str, + grp_str, ifp->name, msg->im_vif, buf_size); + } + + switch (msg->im_msgtype) { + case IGMPMSG_WRONGVIF: + return pim_mroute_msg_wrongvif(fd, ifp, msg); + break; + case IGMPMSG_NOCACHE: + return pim_mroute_msg_nocache(fd, ifp, msg); + break; + case IGMPMSG_WHOLEPKT: + return pim_mroute_msg_wholepkt(fd, ifp, + (const char *)msg); + break; + case IGMPMSG_WRVIFWHOLE: + return pim_mroute_msg_wrvifwhole(fd, ifp, + (const char *)msg); + break; + default: + break; + } + } - return 0; + return 0; } static int mroute_read(struct thread *t) { - static long long count; - char buf[10000]; - int result = 0; - int cont = 1; - int fd; - int rd; - - fd = THREAD_FD(t); - - while (cont) - { - rd = read(fd, buf, sizeof(buf)); - if (rd < 0) { - if (errno == EINTR) - continue; - if (errno == EWOULDBLOCK || errno == EAGAIN) - break; - - if (PIM_DEBUG_MROUTE) - zlog_warn("%s: failure reading fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - goto done; - } - - result = pim_mroute_msg(fd, buf, rd); - - count++; - if (count % qpim_packet_process == 0) - cont = 0; - } - /* Keep reading */ - done: - mroute_read_on(); + static long long count; + char buf[10000]; + int result = 0; + int cont = 1; + int fd; + int rd; + + fd = THREAD_FD(t); + + while (cont) { + rd = read(fd, buf, sizeof(buf)); + if (rd < 0) { + if (errno == EINTR) + continue; + if (errno == EWOULDBLOCK || errno == EAGAIN) + break; + + if (PIM_DEBUG_MROUTE) + zlog_warn( + "%s: failure reading fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, + safe_strerror(errno)); + goto done; + } + + result = pim_mroute_msg(fd, buf, rd); + + count++; + if (count % qpim_packet_process == 0) + cont = 0; + } +/* Keep reading */ +done: + mroute_read_on(); - return result; + return result; } static void mroute_read_on() { - thread_add_read(master, mroute_read, 0, qpim_mroute_socket_fd, - &qpim_mroute_socket_reader); + thread_add_read(master, mroute_read, 0, qpim_mroute_socket_fd, + &qpim_mroute_socket_reader); } static void mroute_read_off() { - THREAD_OFF(qpim_mroute_socket_reader); + THREAD_OFF(qpim_mroute_socket_reader); } int pim_mroute_socket_enable() { - int fd; + int fd; - if ( pimd_privs.change (ZPRIVS_RAISE) ) - zlog_err ("pim_mroute_socket_enable: could not raise privs, %s", - safe_strerror (errno) ); + if (pimd_privs.change(ZPRIVS_RAISE)) + zlog_err("pim_mroute_socket_enable: could not raise privs, %s", + safe_strerror(errno)); - fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); + fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); - if ( pimd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("pim_mroute_socket_enable: could not lower privs, %s", - safe_strerror (errno) ); + if (pimd_privs.change(ZPRIVS_LOWER)) + zlog_err("pim_mroute_socket_enable: could not lower privs, %s", + safe_strerror(errno)); - if (fd < 0) { - zlog_warn("Could not create mroute socket: errno=%d: %s", - errno, safe_strerror(errno)); - return -2; - } + if (fd < 0) { + zlog_warn("Could not create mroute socket: errno=%d: %s", errno, + safe_strerror(errno)); + return -2; + } - if (pim_mroute_set(fd, 1)) { - zlog_warn("Could not enable mroute on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return -3; - } + if (pim_mroute_set(fd, 1)) { + zlog_warn( + "Could not enable mroute on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return -3; + } - qpim_mroute_socket_fd = fd; + qpim_mroute_socket_fd = fd; - qpim_mroute_socket_creation = pim_time_monotonic_sec(); - mroute_read_on(); + qpim_mroute_socket_creation = pim_time_monotonic_sec(); + mroute_read_on(); - return 0; + return 0; } int pim_mroute_socket_disable() { - if (pim_mroute_set(qpim_mroute_socket_fd, 0)) { - zlog_warn("Could not disable mroute on socket fd=%d: errno=%d: %s", - qpim_mroute_socket_fd, errno, safe_strerror(errno)); - return -2; - } - - if (close(qpim_mroute_socket_fd)) { - zlog_warn("Failure closing mroute socket: fd=%d errno=%d: %s", - qpim_mroute_socket_fd, errno, safe_strerror(errno)); - return -3; - } - - mroute_read_off(); - qpim_mroute_socket_fd = -1; - - return 0; + if (pim_mroute_set(qpim_mroute_socket_fd, 0)) { + zlog_warn( + "Could not disable mroute on socket fd=%d: errno=%d: %s", + qpim_mroute_socket_fd, errno, safe_strerror(errno)); + return -2; + } + + if (close(qpim_mroute_socket_fd)) { + zlog_warn("Failure closing mroute socket: fd=%d errno=%d: %s", + qpim_mroute_socket_fd, errno, safe_strerror(errno)); + return -3; + } + + mroute_read_off(); + qpim_mroute_socket_fd = -1; + + return 0; } /* @@ -701,249 +726,248 @@ int pim_mroute_socket_disable() would be used for multicast forwarding, a corresponding multicast interface must be added to the kernel. */ -int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned char flags) +int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, + unsigned char flags) { - struct pim_interface *pim_ifp = ifp->info; - struct vifctl vc; - int err; + struct pim_interface *pim_ifp = ifp->info; + struct vifctl vc; + int err; - memset(&vc, 0, sizeof(vc)); - vc.vifc_vifi = pim_ifp->mroute_vif_index; + memset(&vc, 0, sizeof(vc)); + vc.vifc_vifi = pim_ifp->mroute_vif_index; #ifdef VIFF_USE_IFINDEX - vc.vifc_lcl_ifindex = ifp->ifindex; + vc.vifc_lcl_ifindex = ifp->ifindex; #else - if (ifaddr.s_addr == INADDR_ANY) { - zlog_warn("%s: unnumbered interfaces are not supported on this platform", - __PRETTY_FUNCTION__); - return -1; - } - memcpy(&vc.vifc_lcl_addr, &ifaddr, sizeof(vc.vifc_lcl_addr)); + if (ifaddr.s_addr == INADDR_ANY) { + zlog_warn( + "%s: unnumbered interfaces are not supported on this platform", + __PRETTY_FUNCTION__); + return -1; + } + memcpy(&vc.vifc_lcl_addr, &ifaddr, sizeof(vc.vifc_lcl_addr)); #endif - vc.vifc_flags = flags; - vc.vifc_threshold = PIM_MROUTE_MIN_TTL; - vc.vifc_rate_limit = 0; - -#ifdef PIM_DVMRP_TUNNEL - if (vc.vifc_flags & VIFF_TUNNEL) { - memcpy(&vc.vifc_rmt_addr, &vif_remote_addr, sizeof(vc.vifc_rmt_addr)); - } + vc.vifc_flags = flags; + vc.vifc_threshold = PIM_MROUTE_MIN_TTL; + vc.vifc_rate_limit = 0; + +#ifdef PIM_DVMRP_TUNNEL + if (vc.vifc_flags & VIFF_TUNNEL) { + memcpy(&vc.vifc_rmt_addr, &vif_remote_addr, + sizeof(vc.vifc_rmt_addr)); + } #endif - err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_VIF, (void*) &vc, sizeof(vc)); - if (err) { - char ifaddr_str[INET_ADDRSTRLEN]; + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_VIF, + (void *)&vc, sizeof(vc)); + if (err) { + char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", ifaddr, ifaddr_str, sizeof(ifaddr_str)); + pim_inet4_dump("<ifaddr?>", ifaddr, ifaddr_str, + sizeof(ifaddr_str)); - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_VIF,vif_index=%d,ifaddr=%s,flag=%d): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - qpim_mroute_socket_fd, ifp->ifindex, ifaddr_str, flags, - errno, safe_strerror(errno)); - return -2; - } + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_VIF,vif_index=%d,ifaddr=%s,flag=%d): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, + ifp->ifindex, ifaddr_str, flags, errno, + safe_strerror(errno)); + return -2; + } - return 0; + return 0; } int pim_mroute_del_vif(int vif_index) { - struct vifctl vc; - int err; - - if (PIM_DEBUG_MROUTE) - { - struct interface *ifp = pim_if_find_by_vif_index (vif_index); - zlog_debug ("%s %s: Del Vif %d (%s) ", __FILE__, - __PRETTY_FUNCTION__, vif_index, ifp ? ifp->name : "NULL"); - } - - memset(&vc, 0, sizeof(vc)); - vc.vifc_vifi = vif_index; + struct vifctl vc; + int err; + + if (PIM_DEBUG_MROUTE) { + struct interface *ifp = pim_if_find_by_vif_index(vif_index); + zlog_debug("%s %s: Del Vif %d (%s) ", __FILE__, + __PRETTY_FUNCTION__, vif_index, + ifp ? ifp->name : "NULL"); + } - err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_VIF, (void*) &vc, sizeof(vc)); - if (err) { - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_VIF,vif_index=%d): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - qpim_mroute_socket_fd, vif_index, - errno, safe_strerror(errno)); - return -2; - } + memset(&vc, 0, sizeof(vc)); + vc.vifc_vifi = vif_index; + + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_VIF, + (void *)&vc, sizeof(vc)); + if (err) { + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_VIF,vif_index=%d): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, + vif_index, errno, safe_strerror(errno)); + return -2; + } - return 0; + return 0; } int pim_mroute_add(struct channel_oil *c_oil, const char *name) { - int err; - int orig = 0; - int orig_iif_vif = 0; - - qpim_mroute_add_last = pim_time_monotonic_sec(); - ++qpim_mroute_add_events; - - /* Do not install route if incoming interface is undefined. */ - if (c_oil->oil.mfcc_parent >= MAXVIFS) - { - if (PIM_DEBUG_MROUTE) - { - char buf[1000]; - zlog_debug("%s(%s) %s Attempting to add vifi that is invalid to mroute table", - __PRETTY_FUNCTION__, name, pim_channel_oil_dump (c_oil, buf, sizeof(buf))); - } - return -2; - } - - /* The linux kernel *expects* the incoming - * vif to be part of the outgoing list - * in the case of a (*,G). - */ - if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) - { - orig = c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent]; - c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1; - } + int err; + int orig = 0; + int orig_iif_vif = 0; + + qpim_mroute_add_last = pim_time_monotonic_sec(); + ++qpim_mroute_add_events; + + /* Do not install route if incoming interface is undefined. */ + if (c_oil->oil.mfcc_parent >= MAXVIFS) { + if (PIM_DEBUG_MROUTE) { + char buf[1000]; + zlog_debug( + "%s(%s) %s Attempting to add vifi that is invalid to mroute table", + __PRETTY_FUNCTION__, name, + pim_channel_oil_dump(c_oil, buf, sizeof(buf))); + } + return -2; + } - /* - * If we have an unresolved cache entry for the S,G - * it is owned by the pimreg for the incoming IIF - * So set pimreg as the IIF temporarily to cause - * the packets to be forwarded. Then set it - * to the correct IIF afterwords. - */ - if (!c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY && - c_oil->oil.mfcc_parent != 0) - { - orig_iif_vif = c_oil->oil.mfcc_parent; - c_oil->oil.mfcc_parent = 0; - } - err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, - &c_oil->oil, sizeof(c_oil->oil)); + /* The linux kernel *expects* the incoming + * vif to be part of the outgoing list + * in the case of a (*,G). + */ + if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) { + orig = c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent]; + c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1; + } - if (!err && !c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY && - orig_iif_vif != 0) - { - c_oil->oil.mfcc_parent = orig_iif_vif; - err = setsockopt (qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, - &c_oil->oil, sizeof (c_oil->oil)); - } + /* + * If we have an unresolved cache entry for the S,G + * it is owned by the pimreg for the incoming IIF + * So set pimreg as the IIF temporarily to cause + * the packets to be forwarded. Then set it + * to the correct IIF afterwords. + */ + if (!c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY + && c_oil->oil.mfcc_parent != 0) { + orig_iif_vif = c_oil->oil.mfcc_parent; + c_oil->oil.mfcc_parent = 0; + } + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, + &c_oil->oil, sizeof(c_oil->oil)); + + if (!err && !c_oil->installed + && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY + && orig_iif_vif != 0) { + c_oil->oil.mfcc_parent = orig_iif_vif; + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, + &c_oil->oil, sizeof(c_oil->oil)); + } - if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) - c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig; + if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) + c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig; - if (err) { - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - qpim_mroute_socket_fd, - errno, safe_strerror(errno)); - return -2; - } + if (err) { + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, + errno, safe_strerror(errno)); + return -2; + } - if (PIM_DEBUG_MROUTE) - { - char buf[1000]; - zlog_debug("%s(%s), Added Route: %s", - __PRETTY_FUNCTION__, name, - pim_channel_oil_dump (c_oil, buf, sizeof(buf))); - } + if (PIM_DEBUG_MROUTE) { + char buf[1000]; + zlog_debug("%s(%s), Added Route: %s", __PRETTY_FUNCTION__, name, + pim_channel_oil_dump(c_oil, buf, sizeof(buf))); + } - c_oil->installed = 1; - return 0; + c_oil->installed = 1; + return 0; } -int pim_mroute_del (struct channel_oil *c_oil, const char *name) +int pim_mroute_del(struct channel_oil *c_oil, const char *name) { - int err; - - qpim_mroute_del_last = pim_time_monotonic_sec(); - ++qpim_mroute_del_events; + int err; + + qpim_mroute_del_last = pim_time_monotonic_sec(); + ++qpim_mroute_del_events; + + if (!c_oil->installed) { + if (PIM_DEBUG_MROUTE) { + char buf[1000]; + zlog_debug( + "%s %s: vifi %d for route is %s not installed, do not need to send del req. ", + __FILE__, __PRETTY_FUNCTION__, + c_oil->oil.mfcc_parent, + pim_channel_oil_dump(c_oil, buf, sizeof(buf))); + } + return -2; + } - if (!c_oil->installed) - { - if (PIM_DEBUG_MROUTE) - { - char buf[1000]; - zlog_debug("%s %s: vifi %d for route is %s not installed, do not need to send del req. ", - __FILE__, __PRETTY_FUNCTION__, c_oil->oil.mfcc_parent, - pim_channel_oil_dump (c_oil, buf, sizeof(buf))); - } - return -2; - } + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, + &c_oil->oil, sizeof(c_oil->oil)); + if (err) { + if (PIM_DEBUG_MROUTE) + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, + qpim_mroute_socket_fd, errno, + safe_strerror(errno)); + return -2; + } - err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, &c_oil->oil, sizeof(c_oil->oil)); - if (err) { - if (PIM_DEBUG_MROUTE) - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - qpim_mroute_socket_fd, - errno, safe_strerror(errno)); - return -2; - } - - if (PIM_DEBUG_MROUTE) - { - char buf[1000]; - zlog_debug("%s(%s), Deleted Route: %s", - __PRETTY_FUNCTION__, name, - pim_channel_oil_dump (c_oil, buf, sizeof(buf))); - } + if (PIM_DEBUG_MROUTE) { + char buf[1000]; + zlog_debug("%s(%s), Deleted Route: %s", __PRETTY_FUNCTION__, + name, pim_channel_oil_dump(c_oil, buf, sizeof(buf))); + } - //Reset kernel installed flag - c_oil->installed = 0; + // Reset kernel installed flag + c_oil->installed = 0; - return 0; + return 0; } -void -pim_mroute_update_counters (struct channel_oil *c_oil) +void pim_mroute_update_counters(struct channel_oil *c_oil) { - struct sioc_sg_req sgreq; - - c_oil->cc.oldpktcnt = c_oil->cc.pktcnt; - c_oil->cc.oldbytecnt = c_oil->cc.bytecnt; - c_oil->cc.oldwrong_if = c_oil->cc.wrong_if; - - if (!c_oil->installed) - { - c_oil->cc.lastused = 100 * qpim_keep_alive_time; - if (PIM_DEBUG_MROUTE) - { - struct prefix_sg sg; - - sg.src = c_oil->oil.mfcc_origin; - sg.grp = c_oil->oil.mfcc_mcastgrp; - if (PIM_DEBUG_MROUTE) - zlog_debug("Channel(%s) is not installed no need to collect data from kernel", - pim_str_sg_dump (&sg)); + struct sioc_sg_req sgreq; + + c_oil->cc.oldpktcnt = c_oil->cc.pktcnt; + c_oil->cc.oldbytecnt = c_oil->cc.bytecnt; + c_oil->cc.oldwrong_if = c_oil->cc.wrong_if; + + if (!c_oil->installed) { + c_oil->cc.lastused = 100 * qpim_keep_alive_time; + if (PIM_DEBUG_MROUTE) { + struct prefix_sg sg; + + sg.src = c_oil->oil.mfcc_origin; + sg.grp = c_oil->oil.mfcc_mcastgrp; + if (PIM_DEBUG_MROUTE) + zlog_debug( + "Channel(%s) is not installed no need to collect data from kernel", + pim_str_sg_dump(&sg)); + } + return; } - return; - } - - memset (&sgreq, 0, sizeof(sgreq)); - sgreq.src = c_oil->oil.mfcc_origin; - sgreq.grp = c_oil->oil.mfcc_mcastgrp; - - pim_zlookup_sg_statistics (c_oil); - if (ioctl (qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) - { - if (PIM_DEBUG_MROUTE) - { - struct prefix_sg sg; - sg.src = c_oil->oil.mfcc_origin; - sg.grp = c_oil->oil.mfcc_mcastgrp; - - zlog_warn ("ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s): errno=%d: %s", - (unsigned long)SIOCGETSGCNT, - pim_str_sg_dump (&sg), - errno, - safe_strerror(errno)); + memset(&sgreq, 0, sizeof(sgreq)); + sgreq.src = c_oil->oil.mfcc_origin; + sgreq.grp = c_oil->oil.mfcc_mcastgrp; + + pim_zlookup_sg_statistics(c_oil); + if (ioctl(qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) { + if (PIM_DEBUG_MROUTE) { + struct prefix_sg sg; + + sg.src = c_oil->oil.mfcc_origin; + sg.grp = c_oil->oil.mfcc_mcastgrp; + + zlog_warn( + "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s): errno=%d: %s", + (unsigned long)SIOCGETSGCNT, + pim_str_sg_dump(&sg), errno, + safe_strerror(errno)); + } + return; } - return; - } - c_oil->cc.pktcnt = sgreq.pktcnt; - c_oil->cc.bytecnt = sgreq.bytecnt; - c_oil->cc.wrong_if = sgreq.wrong_if; + c_oil->cc.pktcnt = sgreq.pktcnt; + c_oil->cc.bytecnt = sgreq.bytecnt; + c_oil->cc.wrong_if = sgreq.wrong_if; - return; + return; } diff --git a/pimd/pim_mroute.h b/pimd/pim_mroute.h index 36dce8e61..eb6c40b67 100644 --- a/pimd/pim_mroute.h +++ b/pimd/pim_mroute.h @@ -73,25 +73,25 @@ typedef unsigned short vifi_t; #ifndef HAVE_STRUCT_VIFCTL struct vifctl { - vifi_t vifc_vifi; /* Index of VIF */ - unsigned char vifc_flags; /* VIFF_ flags */ - unsigned char vifc_threshold; /* ttl limit */ - unsigned int vifc_rate_limit; /* Rate limiter values (NI) */ - struct in_addr vifc_lcl_addr; /* Our address */ - struct in_addr vifc_rmt_addr; /* IPIP tunnel addr */ + vifi_t vifc_vifi; /* Index of VIF */ + unsigned char vifc_flags; /* VIFF_ flags */ + unsigned char vifc_threshold; /* ttl limit */ + unsigned int vifc_rate_limit; /* Rate limiter values (NI) */ + struct in_addr vifc_lcl_addr; /* Our address */ + struct in_addr vifc_rmt_addr; /* IPIP tunnel addr */ }; #endif #ifndef HAVE_STRUCT_MFCCTL struct mfcctl { - struct in_addr mfcc_origin; /* Origin of mcast */ - struct in_addr mfcc_mcastgrp; /* Group in question */ - vifi_t mfcc_parent; /* Where it arrived */ - unsigned char mfcc_ttls[MAXVIFS]; /* Where it is going */ - unsigned int mfcc_pkt_cnt; /* pkt count for src-grp */ - unsigned int mfcc_byte_cnt; - unsigned int mfcc_wrong_if; - int mfcc_expire; + struct in_addr mfcc_origin; /* Origin of mcast */ + struct in_addr mfcc_mcastgrp; /* Group in question */ + vifi_t mfcc_parent; /* Where it arrived */ + unsigned char mfcc_ttls[MAXVIFS]; /* Where it is going */ + unsigned int mfcc_pkt_cnt; /* pkt count for src-grp */ + unsigned int mfcc_byte_cnt; + unsigned int mfcc_wrong_if; + int mfcc_expire; }; #endif @@ -107,11 +107,11 @@ struct mfcctl { */ #ifndef HAVE_STRUCT_SIOC_SG_REQ struct sioc_sg_req { - struct in_addr src; - struct in_addr grp; - unsigned long pktcnt; - unsigned long bytecnt; - unsigned long wrong_if; + struct in_addr src; + struct in_addr grp; + unsigned long pktcnt; + unsigned long bytecnt; + unsigned long wrong_if; }; #endif @@ -126,11 +126,11 @@ struct sioc_sg_req { */ #ifndef HAVE_STRUCT_SIOC_VIF_REQ struct sioc_vif_req { - vifi_t vifi; /* Which iface */ - unsigned long icount; /* In packets */ - unsigned long ocount; /* Out packets */ - unsigned long ibytes; /* In bytes */ - unsigned long obytes; /* Out bytes */ + vifi_t vifi; /* Which iface */ + unsigned long icount; /* In packets */ + unsigned long ocount; /* Out packets */ + unsigned long ibytes; /* In bytes */ + unsigned long obytes; /* Out bytes */ }; #endif @@ -144,14 +144,13 @@ struct sioc_vif_req { #endif #ifndef HAVE_STRUCT_IGMPMSG -struct igmpmsg -{ - uint32_t unused1,unused2; - unsigned char im_msgtype; /* What is this */ - unsigned char im_mbz; /* Must be zero */ - unsigned char im_vif; /* Interface (this ought to be a vifi_t!) */ - unsigned char unused3; - struct in_addr im_src,im_dst; +struct igmpmsg { + uint32_t unused1, unused2; + unsigned char im_msgtype; /* What is this */ + unsigned char im_mbz; /* Must be zero */ + unsigned char im_vif; /* Interface (this ought to be a vifi_t!) */ + unsigned char unused3; + struct in_addr im_src, im_dst; }; #endif #endif @@ -167,7 +166,8 @@ struct igmpmsg int pim_mroute_socket_enable(void); int pim_mroute_socket_disable(void); -int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned char flags); +int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, + unsigned char flags); int pim_mroute_del_vif(int vif_index); int pim_mroute_add(struct channel_oil *c_oil, const char *name); @@ -175,5 +175,5 @@ int pim_mroute_del(struct channel_oil *c_oil, const char *name); int pim_mroute_msg(int fd, const char *buf, int buf_size); -void pim_mroute_update_counters (struct channel_oil *c_oil); +void pim_mroute_update_counters(struct channel_oil *c_oil); #endif /* PIM_MROUTE_H */ diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 170692e7f..0f653e70a 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -47,119 +47,119 @@ struct pim_msdp pim_msdp, *msdp = &pim_msdp; static void pim_msdp_peer_listen(struct pim_msdp_peer *mp); static void pim_msdp_peer_cr_timer_setup(struct pim_msdp_peer *mp, bool start); static void pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start); -static void pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, bool start); +static void pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, + bool start); static void pim_msdp_peer_free(struct pim_msdp_peer *mp); static void pim_msdp_enable(void); static void pim_msdp_sa_adv_timer_setup(bool start); -static void pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags); +static void pim_msdp_sa_deref(struct pim_msdp_sa *sa, + enum pim_msdp_sa_flags flags); static int pim_msdp_mg_mbr_comp(const void *p1, const void *p2); static void pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr); -static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, struct pim_msdp_mg_mbr *mbr); +static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, + struct pim_msdp_mg_mbr *mbr); /************************ SA cache management ******************************/ -static void -pim_msdp_sa_timer_expiry_log(struct pim_msdp_sa *sa, const char *timer_str) +static void pim_msdp_sa_timer_expiry_log(struct pim_msdp_sa *sa, + const char *timer_str) { - zlog_debug("MSDP SA %s %s timer expired", sa->sg_str, timer_str); + zlog_debug("MSDP SA %s %s timer expired", sa->sg_str, timer_str); } /* RFC-3618:Sec-5.1 - global active source advertisement timer */ -static int -pim_msdp_sa_adv_timer_cb(struct thread *t) +static int pim_msdp_sa_adv_timer_cb(struct thread *t) { - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA advertisment timer expired"); - } + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA advertisment timer expired"); + } - pim_msdp_sa_adv_timer_setup(true /* start */); - pim_msdp_pkt_sa_tx(); - return 0; + pim_msdp_sa_adv_timer_setup(true /* start */); + pim_msdp_pkt_sa_tx(); + return 0; } -static void -pim_msdp_sa_adv_timer_setup(bool start) +static void pim_msdp_sa_adv_timer_setup(bool start) { - THREAD_OFF(msdp->sa_adv_timer); - if (start) { - thread_add_timer(msdp->master, pim_msdp_sa_adv_timer_cb, NULL, - PIM_MSDP_SA_ADVERTISMENT_TIME, &msdp->sa_adv_timer); - } + THREAD_OFF(msdp->sa_adv_timer); + if (start) { + thread_add_timer(msdp->master, pim_msdp_sa_adv_timer_cb, NULL, + PIM_MSDP_SA_ADVERTISMENT_TIME, + &msdp->sa_adv_timer); + } } /* RFC-3618:Sec-5.3 - SA cache state timer */ -static int -pim_msdp_sa_state_timer_cb(struct thread *t) +static int pim_msdp_sa_state_timer_cb(struct thread *t) { - struct pim_msdp_sa *sa; + struct pim_msdp_sa *sa; - sa = THREAD_ARG(t); + sa = THREAD_ARG(t); - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_sa_timer_expiry_log(sa, "state"); - } + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_sa_timer_expiry_log(sa, "state"); + } - pim_msdp_sa_deref(sa, PIM_MSDP_SAF_PEER); - return 0; + pim_msdp_sa_deref(sa, PIM_MSDP_SAF_PEER); + return 0; } -static void -pim_msdp_sa_state_timer_setup(struct pim_msdp_sa *sa, bool start) +static void pim_msdp_sa_state_timer_setup(struct pim_msdp_sa *sa, bool start) { - THREAD_OFF(sa->sa_state_timer); - if (start) { - thread_add_timer(msdp->master, pim_msdp_sa_state_timer_cb, sa, - PIM_MSDP_SA_HOLD_TIME, &sa->sa_state_timer); - } + THREAD_OFF(sa->sa_state_timer); + if (start) { + thread_add_timer(msdp->master, pim_msdp_sa_state_timer_cb, sa, + PIM_MSDP_SA_HOLD_TIME, &sa->sa_state_timer); + } } -static void -pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa) +static void pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa) { - struct pim_upstream *up = sa->up; - if (!up) { - return; - } + struct pim_upstream *up = sa->up; + if (!up) { + return; + } - sa->up = NULL; - if (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags)) { - PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(up->flags); - sa->flags |= PIM_MSDP_SAF_UP_DEL_IN_PROG; - pim_upstream_del(up, __PRETTY_FUNCTION__); - sa->flags &= ~PIM_MSDP_SAF_UP_DEL_IN_PROG; - } + sa->up = NULL; + if (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags)) { + PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(up->flags); + sa->flags |= PIM_MSDP_SAF_UP_DEL_IN_PROG; + pim_upstream_del(up, __PRETTY_FUNCTION__); + sa->flags &= ~PIM_MSDP_SAF_UP_DEL_IN_PROG; + } - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s de-referenced SPT", sa->sg_str); - } + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s de-referenced SPT", sa->sg_str); + } } -static bool -pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa, struct pim_upstream *xg_up) +static bool pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa, + struct pim_upstream *xg_up) { - if (!(sa->flags & PIM_MSDP_SAF_PEER)) { - /* SA should have been rxed from a peer */ - return false; - } - /* check if we are RP */ - if (!I_am_RP(sa->sg.grp)) { - return false; - } + if (!(sa->flags & PIM_MSDP_SAF_PEER)) { + /* SA should have been rxed from a peer */ + return false; + } + /* check if we are RP */ + if (!I_am_RP(sa->sg.grp)) { + return false; + } - /* check if we have a (*, G) with a non-empty immediate OIL */ - if (!xg_up) { - struct prefix_sg sg; + /* check if we have a (*, G) with a non-empty immediate OIL */ + if (!xg_up) { + struct prefix_sg sg; - memset(&sg, 0, sizeof(sg)); - sg.grp = sa->sg.grp; + memset(&sg, 0, sizeof(sg)); + sg.grp = sa->sg.grp; - xg_up = pim_upstream_find(&sg); - } - if (!xg_up || (xg_up->join_state != PIM_UPSTREAM_JOINED)) { - /* join desired will be true for such (*, G) entries so we will - * just look at join_state and let the PIM state machine do the rest of - * the magic */ - return false; - } + xg_up = pim_upstream_find(&sg); + } + if (!xg_up || (xg_up->join_state != PIM_UPSTREAM_JOINED)) { + /* join desired will be true for such (*, G) entries so we will + * just look at join_state and let the PIM state machine do the + * rest of + * the magic */ + return false; + } - return true; + return true; } /* Upstream add evaluation needs to happen everytime - @@ -170,164 +170,164 @@ pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa, struct pim_upstream *xg_up) * (considering #4); but just in case an entry gets nuked without * upstream state transition * */ -static void -pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa, - struct pim_upstream *xg_up, const char *ctx) -{ - struct pim_upstream *up; - - if (!pim_msdp_sa_upstream_add_ok(sa, xg_up)) { - pim_msdp_sa_upstream_del(sa); - return; - } - - if (sa->up) { - /* nothing to do */ - return; - } - - up = pim_upstream_find(&sa->sg); - if (up && (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags))) { - /* somehow we lost track of the upstream ptr? best log it */ - sa->up = up; - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s SPT reference missing", sa->sg_str); - } - return; - } - - /* RFC3618: "RP triggers a (S, G) join event towards the data source - * as if a JP message was rxed addressed to the RP itself." */ - up = pim_upstream_add(&sa->sg, NULL /* iif */, - PIM_UPSTREAM_FLAG_MASK_SRC_MSDP, - __PRETTY_FUNCTION__); - - sa->up = up; - if (up) { - /* update inherited oil */ - pim_upstream_inherited_olist(up); - /* should we also start the kat in parallel? we will need it when the - * SA ages out */ - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s referenced SPT", sa->sg_str); - } - } else { - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s SPT reference failed", sa->sg_str); - } - } +static void pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa, + struct pim_upstream *xg_up, + const char *ctx) +{ + struct pim_upstream *up; + + if (!pim_msdp_sa_upstream_add_ok(sa, xg_up)) { + pim_msdp_sa_upstream_del(sa); + return; + } + + if (sa->up) { + /* nothing to do */ + return; + } + + up = pim_upstream_find(&sa->sg); + if (up && (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags))) { + /* somehow we lost track of the upstream ptr? best log it */ + sa->up = up; + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s SPT reference missing", + sa->sg_str); + } + return; + } + + /* RFC3618: "RP triggers a (S, G) join event towards the data source + * as if a JP message was rxed addressed to the RP itself." */ + up = pim_upstream_add(&sa->sg, NULL /* iif */, + PIM_UPSTREAM_FLAG_MASK_SRC_MSDP, + __PRETTY_FUNCTION__); + + sa->up = up; + if (up) { + /* update inherited oil */ + pim_upstream_inherited_olist(up); + /* should we also start the kat in parallel? we will need it + * when the + * SA ages out */ + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s referenced SPT", sa->sg_str); + } + } else { + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s SPT reference failed", + sa->sg_str); + } + } } /* release all mem associated with a sa */ -static void -pim_msdp_sa_free(struct pim_msdp_sa *sa) +static void pim_msdp_sa_free(struct pim_msdp_sa *sa) { - XFREE(MTYPE_PIM_MSDP_SA, sa); + XFREE(MTYPE_PIM_MSDP_SA, sa); } -static struct pim_msdp_sa * -pim_msdp_sa_new(struct prefix_sg *sg, struct in_addr rp) +static struct pim_msdp_sa *pim_msdp_sa_new(struct prefix_sg *sg, + struct in_addr rp) { - struct pim_msdp_sa *sa; + struct pim_msdp_sa *sa; - sa = XCALLOC(MTYPE_PIM_MSDP_SA, sizeof(*sa)); - if (!sa) { - zlog_err("%s: PIM XCALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*sa)); - return NULL; - } + sa = XCALLOC(MTYPE_PIM_MSDP_SA, sizeof(*sa)); + if (!sa) { + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, + sizeof(*sa)); + return NULL; + } - sa->sg = *sg; - pim_str_sg_set(sg, sa->sg_str); - sa->rp = rp; - sa->uptime = pim_time_monotonic_sec(); + sa->sg = *sg; + pim_str_sg_set(sg, sa->sg_str); + sa->rp = rp; + sa->uptime = pim_time_monotonic_sec(); - /* insert into misc tables for easy access */ - sa = hash_get(msdp->sa_hash, sa, hash_alloc_intern); - if (!sa) { - zlog_err("%s: PIM hash get failure", __PRETTY_FUNCTION__); - pim_msdp_sa_free(sa); - return NULL; - } - listnode_add_sort(msdp->sa_list, sa); + /* insert into misc tables for easy access */ + sa = hash_get(msdp->sa_hash, sa, hash_alloc_intern); + if (!sa) { + zlog_err("%s: PIM hash get failure", __PRETTY_FUNCTION__); + pim_msdp_sa_free(sa); + return NULL; + } + listnode_add_sort(msdp->sa_list, sa); - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s created", sa->sg_str); - } + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s created", sa->sg_str); + } - return sa; + return sa; } -static struct pim_msdp_sa * -pim_msdp_sa_find(struct prefix_sg *sg) +static struct pim_msdp_sa *pim_msdp_sa_find(struct prefix_sg *sg) { - struct pim_msdp_sa lookup; + struct pim_msdp_sa lookup; - lookup.sg = *sg; - return hash_lookup(msdp->sa_hash, &lookup); + lookup.sg = *sg; + return hash_lookup(msdp->sa_hash, &lookup); } -static struct pim_msdp_sa * -pim_msdp_sa_add(struct prefix_sg *sg, struct in_addr rp) +static struct pim_msdp_sa *pim_msdp_sa_add(struct prefix_sg *sg, + struct in_addr rp) { - struct pim_msdp_sa *sa; + struct pim_msdp_sa *sa; - sa = pim_msdp_sa_find(sg); - if (sa) { - return sa; - } + sa = pim_msdp_sa_find(sg); + if (sa) { + return sa; + } - return pim_msdp_sa_new(sg, rp); + return pim_msdp_sa_new(sg, rp); } -static void -pim_msdp_sa_del(struct pim_msdp_sa * sa) +static void pim_msdp_sa_del(struct pim_msdp_sa *sa) { - /* this is somewhat redundant - still want to be careful not to leave - * stale upstream references */ - pim_msdp_sa_upstream_del(sa); + /* this is somewhat redundant - still want to be careful not to leave + * stale upstream references */ + pim_msdp_sa_upstream_del(sa); - /* stop timers */ - pim_msdp_sa_state_timer_setup(sa, false /* start */); + /* stop timers */ + pim_msdp_sa_state_timer_setup(sa, false /* start */); - /* remove the entry from various tables */ - listnode_delete(msdp->sa_list, sa); - hash_release(msdp->sa_hash, sa); + /* remove the entry from various tables */ + listnode_delete(msdp->sa_list, sa); + hash_release(msdp->sa_hash, sa); - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s deleted", sa->sg_str); - } + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s deleted", sa->sg_str); + } - /* free up any associated memory */ - pim_msdp_sa_free(sa); + /* free up any associated memory */ + pim_msdp_sa_free(sa); } -static void -pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, struct pim_msdp_peer *mp, struct in_addr rp) +static void pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, + struct pim_msdp_peer *mp, struct in_addr rp) { - struct pim_msdp_peer *old_mp; + struct pim_msdp_peer *old_mp; - /* optimize the "no change" case as it will happen - * frequently/periodically */ - if (mp && (sa->peer.s_addr == mp->peer.s_addr)) { - return; - } + /* optimize the "no change" case as it will happen + * frequently/periodically */ + if (mp && (sa->peer.s_addr == mp->peer.s_addr)) { + return; + } - /* any time the peer ip changes also update the rp address */ - if (PIM_INADDR_ISNOT_ANY(sa->peer)) { - old_mp = pim_msdp_peer_find(sa->peer); - if (old_mp && old_mp->sa_cnt) { - --old_mp->sa_cnt; - } - } + /* any time the peer ip changes also update the rp address */ + if (PIM_INADDR_ISNOT_ANY(sa->peer)) { + old_mp = pim_msdp_peer_find(sa->peer); + if (old_mp && old_mp->sa_cnt) { + --old_mp->sa_cnt; + } + } - if (mp) { - ++mp->sa_cnt; - sa->peer = mp->peer; - } else { - sa->peer.s_addr = PIM_NET_INADDR_ANY; - } - sa->rp = rp; + if (mp) { + ++mp->sa_cnt; + sa->peer = mp->peer; + } else { + sa->peer.s_addr = PIM_NET_INADDR_ANY; + } + sa->rp = rp; } /* When a local active-source is removed there is no way to withdraw the @@ -335,88 +335,93 @@ pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, struct pim_msdp_peer *mp, struct * not be sent in supsequent SA updates. Peers will consequently timeout the * SA. * Similarly a "peer-added" SA is never explicitly deleted. It is simply - * aged out overtime if not seen in the SA updates from the peers. + * aged out overtime if not seen in the SA updates from the peers. * XXX: should we provide a knob to drop entries learnt from a peer when the * peer goes down? */ -static void -pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags) -{ - bool update_up = false; - - if ((sa->flags &PIM_MSDP_SAF_LOCAL)) { - if (flags & PIM_MSDP_SAF_LOCAL) { - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s local reference removed", sa->sg_str); - } - if (msdp->local_cnt) - --msdp->local_cnt; - } - } - - if ((sa->flags &PIM_MSDP_SAF_PEER)) { - if (flags & PIM_MSDP_SAF_PEER) { - struct in_addr rp; - - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s peer reference removed", sa->sg_str); - } - pim_msdp_sa_state_timer_setup(sa, false /* start */); - rp.s_addr = INADDR_ANY; - pim_msdp_sa_peer_ip_set(sa, NULL /* mp */, rp); - /* if peer ref was removed we need to remove the msdp reference on the - * msdp entry */ - update_up = true; - } - } - - sa->flags &= ~flags; - if (update_up) { - pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "sa-deref"); - } - - if (!(sa->flags & PIM_MSDP_SAF_REF)) { - pim_msdp_sa_del(sa); - } -} - -void -pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, - struct in_addr rp) -{ - struct pim_msdp_sa *sa; - - sa = pim_msdp_sa_add(sg, rp); - if (!sa) { - return; - } - - /* reference it */ - if (mp) { - if (!(sa->flags & PIM_MSDP_SAF_PEER)) { - sa->flags |= PIM_MSDP_SAF_PEER; - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s added by peer", sa->sg_str); - } - } - pim_msdp_sa_peer_ip_set(sa, mp, rp); - /* start/re-start the state timer to prevent cache expiry */ - pim_msdp_sa_state_timer_setup(sa, true /* start */); - /* We re-evaluate SA "SPT-trigger" everytime we hear abt it from a - * peer. XXX: If this becomes too much of a periodic overhead we - * can make it event based */ - pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "peer-ref"); - } else { - if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { - sa->flags |= PIM_MSDP_SAF_LOCAL; - ++msdp->local_cnt; - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s added locally", sa->sg_str); - } - /* send an immediate SA update to peers */ - pim_msdp_pkt_sa_tx_one(sa); - } - sa->flags &= ~PIM_MSDP_SAF_STALE; - } +static void pim_msdp_sa_deref(struct pim_msdp_sa *sa, + enum pim_msdp_sa_flags flags) +{ + bool update_up = false; + + if ((sa->flags & PIM_MSDP_SAF_LOCAL)) { + if (flags & PIM_MSDP_SAF_LOCAL) { + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s local reference removed", + sa->sg_str); + } + if (msdp->local_cnt) + --msdp->local_cnt; + } + } + + if ((sa->flags & PIM_MSDP_SAF_PEER)) { + if (flags & PIM_MSDP_SAF_PEER) { + struct in_addr rp; + + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s peer reference removed", + sa->sg_str); + } + pim_msdp_sa_state_timer_setup(sa, false /* start */); + rp.s_addr = INADDR_ANY; + pim_msdp_sa_peer_ip_set(sa, NULL /* mp */, rp); + /* if peer ref was removed we need to remove the msdp + * reference on the + * msdp entry */ + update_up = true; + } + } + + sa->flags &= ~flags; + if (update_up) { + pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "sa-deref"); + } + + if (!(sa->flags & PIM_MSDP_SAF_REF)) { + pim_msdp_sa_del(sa); + } +} + +void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, + struct in_addr rp) +{ + struct pim_msdp_sa *sa; + + sa = pim_msdp_sa_add(sg, rp); + if (!sa) { + return; + } + + /* reference it */ + if (mp) { + if (!(sa->flags & PIM_MSDP_SAF_PEER)) { + sa->flags |= PIM_MSDP_SAF_PEER; + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s added by peer", + sa->sg_str); + } + } + pim_msdp_sa_peer_ip_set(sa, mp, rp); + /* start/re-start the state timer to prevent cache expiry */ + pim_msdp_sa_state_timer_setup(sa, true /* start */); + /* We re-evaluate SA "SPT-trigger" everytime we hear abt it from + * a + * peer. XXX: If this becomes too much of a periodic overhead we + * can make it event based */ + pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "peer-ref"); + } else { + if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { + sa->flags |= PIM_MSDP_SAF_LOCAL; + ++msdp->local_cnt; + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s added locally", + sa->sg_str); + } + /* send an immediate SA update to peers */ + pim_msdp_pkt_sa_tx_one(sa); + } + sa->flags &= ~PIM_MSDP_SAF_STALE; + } } /* The following criteria must be met to originate an SA from the MSDP @@ -431,93 +436,100 @@ pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, * b. We rxed a pim register (null or data encapsulated) within the last * (3 * (1.5 * register_suppression_timer))). */ -static bool -pim_msdp_sa_local_add_ok(struct pim_upstream *up) +static bool pim_msdp_sa_local_add_ok(struct pim_upstream *up) { - if (!(msdp->flags & PIM_MSDPF_ENABLE)) { - return false; - } + if (!(msdp->flags & PIM_MSDPF_ENABLE)) { + return false; + } - if (!up->t_ka_timer) { - /* stream is not active */ - return false; - } + if (!up->t_ka_timer) { + /* stream is not active */ + return false; + } - if (!I_am_RP(up->sg.grp)) { - /* we are not RP for the group */ - return false; - } + if (!I_am_RP(up->sg.grp)) { + /* we are not RP for the group */ + return false; + } - /* we are the FHR-DR for this stream or we are RP and have seen registers - * from a FHR for this source */ - if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) || up->t_msdp_reg_timer) { - return true; - } + /* we are the FHR-DR for this stream or we are RP and have seen + * registers + * from a FHR for this source */ + if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) || up->t_msdp_reg_timer) { + return true; + } - return false; + return false; } -static void -pim_msdp_sa_local_add(struct prefix_sg *sg) +static void pim_msdp_sa_local_add(struct prefix_sg *sg) { - struct in_addr rp; - rp.s_addr = 0; - pim_msdp_sa_ref(NULL /* mp */, sg, rp); + struct in_addr rp; + rp.s_addr = 0; + pim_msdp_sa_ref(NULL /* mp */, sg, rp); } -void -pim_msdp_sa_local_del(struct prefix_sg *sg) +void pim_msdp_sa_local_del(struct prefix_sg *sg) { - struct pim_msdp_sa *sa; + struct pim_msdp_sa *sa; - sa = pim_msdp_sa_find(sg); - if (sa) { - pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); - } + sa = pim_msdp_sa_find(sg); + if (sa) { + pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); + } } /* we need to be very cautious with this API as SA del too can trigger an * upstream del and we will get stuck in a simple loop */ -static void -pim_msdp_sa_local_del_on_up_del(struct prefix_sg *sg) -{ - struct pim_msdp_sa *sa; - - sa = pim_msdp_sa_find(sg); - if (sa) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP local sa %s del on up del", sa->sg_str); - } - - /* if there is no local reference escape */ - if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP local sa %s del; no local ref", sa->sg_str); - } - return; - } - - if (sa->flags & PIM_MSDP_SAF_UP_DEL_IN_PROG) { - /* MSDP is the one that triggered the upstream del. if this happens - * we most certainly have a bug in the PIM upstream state machine. We - * will not have a local reference unless the KAT is running. And if the - * KAT is running there MUST be an additional source-stream reference to - * the flow. Accounting for such cases requires lot of changes; perhaps - * address this in the next release? - XXX */ - zlog_err("MSDP sa %s SPT teardown is causing the local entry to be removed", sa->sg_str); - return; - } - - /* we are dropping the sa on upstream del we should not have an - * upstream reference */ - if (sa->up) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP local sa %s del; up non-NULL", sa->sg_str); - } - sa->up = NULL; - } - pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); - } +static void pim_msdp_sa_local_del_on_up_del(struct prefix_sg *sg) +{ + struct pim_msdp_sa *sa; + + sa = pim_msdp_sa_find(sg); + if (sa) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP local sa %s del on up del", + sa->sg_str); + } + + /* if there is no local reference escape */ + if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP local sa %s del; no local ref", + sa->sg_str); + } + return; + } + + if (sa->flags & PIM_MSDP_SAF_UP_DEL_IN_PROG) { + /* MSDP is the one that triggered the upstream del. if + * this happens + * we most certainly have a bug in the PIM upstream + * state machine. We + * will not have a local reference unless the KAT is + * running. And if the + * KAT is running there MUST be an additional + * source-stream reference to + * the flow. Accounting for such cases requires lot of + * changes; perhaps + * address this in the next release? - XXX */ + zlog_err( + "MSDP sa %s SPT teardown is causing the local entry to be removed", + sa->sg_str); + return; + } + + /* we are dropping the sa on upstream del we should not have an + * upstream reference */ + if (sa->up) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP local sa %s del; up non-NULL", + sa->sg_str); + } + sa->up = NULL; + } + pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); + } } /* Local SA qualification needs to be re-evaluated when - @@ -529,1072 +541,1045 @@ pim_msdp_sa_local_del_on_up_del(struct prefix_sg *sg) * FHR is also the RP. * 4. When msdp_reg timer is started or stopped */ -void -pim_msdp_sa_local_update(struct pim_upstream *up) +void pim_msdp_sa_local_update(struct pim_upstream *up) { - if (pim_msdp_sa_local_add_ok(up)) { - pim_msdp_sa_local_add(&up->sg); - } else { - pim_msdp_sa_local_del(&up->sg); - } + if (pim_msdp_sa_local_add_ok(up)) { + pim_msdp_sa_local_add(&up->sg); + } else { + pim_msdp_sa_local_del(&up->sg); + } } -static void -pim_msdp_sa_local_setup(void) +static void pim_msdp_sa_local_setup(void) { - struct pim_upstream *up; - struct listnode *up_node; + struct pim_upstream *up; + struct listnode *up_node; - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { - pim_msdp_sa_local_update(up); - } + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { + pim_msdp_sa_local_update(up); + } } /* whenever the RP changes we need to re-evaluate the "local" SA-cache */ /* XXX: needs to be tested */ -void -pim_msdp_i_am_rp_changed(void) -{ - struct listnode *sanode; - struct listnode *nextnode; - struct pim_msdp_sa *sa; - - if (!(msdp->flags & PIM_MSDPF_ENABLE)) { - /* if the feature is not enabled do nothing */ - return; - } - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP i_am_rp changed"); - } - - /* mark all local entries as stale */ - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - if (sa->flags & PIM_MSDP_SAF_LOCAL) { - sa->flags |= PIM_MSDP_SAF_STALE; - } - } - - /* re-setup local SA entries */ - pim_msdp_sa_local_setup(); - - for (ALL_LIST_ELEMENTS(msdp->sa_list, sanode, nextnode, sa)) { - /* purge stale SA entries */ - if (sa->flags & PIM_MSDP_SAF_STALE) { - /* clear the stale flag; the entry may be kept even after - * "local-deref" */ - sa->flags &= ~PIM_MSDP_SAF_STALE; - /* sa_deref can end up freeing the sa; so don't access contents after */ - pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); - } else { - /* if the souce is still active check if we can influence SPT */ - pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "rp-change"); - } - } +void pim_msdp_i_am_rp_changed(void) +{ + struct listnode *sanode; + struct listnode *nextnode; + struct pim_msdp_sa *sa; + + if (!(msdp->flags & PIM_MSDPF_ENABLE)) { + /* if the feature is not enabled do nothing */ + return; + } + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP i_am_rp changed"); + } + + /* mark all local entries as stale */ + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + if (sa->flags & PIM_MSDP_SAF_LOCAL) { + sa->flags |= PIM_MSDP_SAF_STALE; + } + } + + /* re-setup local SA entries */ + pim_msdp_sa_local_setup(); + + for (ALL_LIST_ELEMENTS(msdp->sa_list, sanode, nextnode, sa)) { + /* purge stale SA entries */ + if (sa->flags & PIM_MSDP_SAF_STALE) { + /* clear the stale flag; the entry may be kept even + * after + * "local-deref" */ + sa->flags &= ~PIM_MSDP_SAF_STALE; + /* sa_deref can end up freeing the sa; so don't access + * contents after */ + pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); + } else { + /* if the souce is still active check if we can + * influence SPT */ + pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, + "rp-change"); + } + } } /* We track the join state of (*, G) entries. If G has sources in the SA-cache * we need to setup or teardown SPT when the JoinDesired status changes for * (*, G) */ -void -pim_msdp_up_join_state_changed(struct pim_upstream *xg_up) -{ - struct listnode *sanode; - struct pim_msdp_sa *sa; - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP join state changed for %s", xg_up->sg_str); - } - - /* If this is not really an XG entry just move on */ - if ((xg_up->sg.src.s_addr != INADDR_ANY) || - (xg_up->sg.grp.s_addr == INADDR_ANY)) { - return; - } - - /* XXX: Need to maintain SAs per-group to avoid all this unnecessary - * walking */ - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - if (sa->sg.grp.s_addr != xg_up->sg.grp.s_addr) { - continue; - } - pim_msdp_sa_upstream_update(sa, xg_up, "up-jp-change"); - } -} - -static void -pim_msdp_up_xg_del(struct prefix_sg *sg) -{ - struct listnode *sanode; - struct pim_msdp_sa *sa; - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP %s del", pim_str_sg_dump(sg)); - } - - /* If this is not really an XG entry just move on */ - if ((sg->src.s_addr != INADDR_ANY) || - (sg->grp.s_addr == INADDR_ANY)) { - return; - } - - /* XXX: Need to maintain SAs per-group to avoid all this unnecessary - * walking */ - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - if (sa->sg.grp.s_addr != sg->grp.s_addr) { - continue; - } - pim_msdp_sa_upstream_update(sa, NULL /* xg */, "up-jp-change"); - } -} - -void -pim_msdp_up_del(struct prefix_sg *sg) -{ - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP up %s del", pim_str_sg_dump(sg)); - } - if (sg->src.s_addr == INADDR_ANY) { - pim_msdp_up_xg_del(sg); - } else { - pim_msdp_sa_local_del_on_up_del(sg); - } +void pim_msdp_up_join_state_changed(struct pim_upstream *xg_up) +{ + struct listnode *sanode; + struct pim_msdp_sa *sa; + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP join state changed for %s", xg_up->sg_str); + } + + /* If this is not really an XG entry just move on */ + if ((xg_up->sg.src.s_addr != INADDR_ANY) + || (xg_up->sg.grp.s_addr == INADDR_ANY)) { + return; + } + + /* XXX: Need to maintain SAs per-group to avoid all this unnecessary + * walking */ + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + if (sa->sg.grp.s_addr != xg_up->sg.grp.s_addr) { + continue; + } + pim_msdp_sa_upstream_update(sa, xg_up, "up-jp-change"); + } +} + +static void pim_msdp_up_xg_del(struct prefix_sg *sg) +{ + struct listnode *sanode; + struct pim_msdp_sa *sa; + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP %s del", pim_str_sg_dump(sg)); + } + + /* If this is not really an XG entry just move on */ + if ((sg->src.s_addr != INADDR_ANY) || (sg->grp.s_addr == INADDR_ANY)) { + return; + } + + /* XXX: Need to maintain SAs per-group to avoid all this unnecessary + * walking */ + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + if (sa->sg.grp.s_addr != sg->grp.s_addr) { + continue; + } + pim_msdp_sa_upstream_update(sa, NULL /* xg */, "up-jp-change"); + } +} + +void pim_msdp_up_del(struct prefix_sg *sg) +{ + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP up %s del", pim_str_sg_dump(sg)); + } + if (sg->src.s_addr == INADDR_ANY) { + pim_msdp_up_xg_del(sg); + } else { + pim_msdp_sa_local_del_on_up_del(sg); + } } /* sa hash and peer list helpers */ -static unsigned int -pim_msdp_sa_hash_key_make(void *p) +static unsigned int pim_msdp_sa_hash_key_make(void *p) { - struct pim_msdp_sa *sa = p; + struct pim_msdp_sa *sa = p; - return (jhash_2words(sa->sg.src.s_addr, sa->sg.grp.s_addr, 0)); + return (jhash_2words(sa->sg.src.s_addr, sa->sg.grp.s_addr, 0)); } -static int -pim_msdp_sa_hash_eq(const void *p1, const void *p2) +static int pim_msdp_sa_hash_eq(const void *p1, const void *p2) { - const struct pim_msdp_sa *sa1 = p1; - const struct pim_msdp_sa *sa2 = p2; + const struct pim_msdp_sa *sa1 = p1; + const struct pim_msdp_sa *sa2 = p2; - return ((sa1->sg.src.s_addr == sa2->sg.src.s_addr) && - (sa1->sg.grp.s_addr == sa2->sg.grp.s_addr)); + return ((sa1->sg.src.s_addr == sa2->sg.src.s_addr) + && (sa1->sg.grp.s_addr == sa2->sg.grp.s_addr)); } -static int -pim_msdp_sa_comp(const void *p1, const void *p2) +static int pim_msdp_sa_comp(const void *p1, const void *p2) { - const struct pim_msdp_sa *sa1 = p1; - const struct pim_msdp_sa *sa2 = p2; + const struct pim_msdp_sa *sa1 = p1; + const struct pim_msdp_sa *sa2 = p2; - if (ntohl(sa1->sg.grp.s_addr) < ntohl(sa2->sg.grp.s_addr)) - return -1; + if (ntohl(sa1->sg.grp.s_addr) < ntohl(sa2->sg.grp.s_addr)) + return -1; - if (ntohl(sa1->sg.grp.s_addr) > ntohl(sa2->sg.grp.s_addr)) - return 1; + if (ntohl(sa1->sg.grp.s_addr) > ntohl(sa2->sg.grp.s_addr)) + return 1; - if (ntohl(sa1->sg.src.s_addr) < ntohl(sa2->sg.src.s_addr)) - return -1; + if (ntohl(sa1->sg.src.s_addr) < ntohl(sa2->sg.src.s_addr)) + return -1; - if (ntohl(sa1->sg.src.s_addr) > ntohl(sa2->sg.src.s_addr)) - return 1; + if (ntohl(sa1->sg.src.s_addr) > ntohl(sa2->sg.src.s_addr)) + return 1; - return 0; + return 0; } /* RFC-3618:Sec-10.1.3 - Peer-RPF forwarding */ /* XXX: this can use a bit of refining and extensions */ -bool -pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp) +bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp) { - if (mp->peer.s_addr == rp.s_addr) { - return true; - } + if (mp->peer.s_addr == rp.s_addr) { + return true; + } - return false; + return false; } - + /************************ Peer session management **************************/ -char * -pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, int buf_size) -{ - switch (state) { - case PIM_MSDP_DISABLED: - snprintf(buf, buf_size, "%s", "disabled"); - break; - case PIM_MSDP_INACTIVE: - snprintf(buf, buf_size, "%s", "inactive"); - break; - case PIM_MSDP_LISTEN: - snprintf(buf, buf_size, "%s", "listen"); - break; - case PIM_MSDP_CONNECTING: - snprintf(buf, buf_size, "%s", "connecting"); - break; - case PIM_MSDP_ESTABLISHED: - snprintf(buf, buf_size, "%s", "established"); - break; - default: - snprintf(buf, buf_size, "unk-%d", state); - } - return buf; -} - -char * -pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, bool long_format) -{ - char peer_str[INET_ADDRSTRLEN]; - char local_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str)); - if (long_format) { - pim_inet4_dump("<local?>", mp->local, local_str, sizeof(local_str)); - snprintf(buf, buf_size, "MSDP peer %s local %s mg %s", - peer_str, local_str, mp->mesh_group_name); - } else { - snprintf(buf, buf_size, "MSDP peer %s", peer_str); - } - - return buf; -} - -static void -pim_msdp_peer_state_chg_log(struct pim_msdp_peer *mp) -{ - char state_str[PIM_MSDP_STATE_STRLEN]; - - pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); - zlog_debug("MSDP peer %s state chg to %s", mp->key_str, state_str); +char *pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, + int buf_size) +{ + switch (state) { + case PIM_MSDP_DISABLED: + snprintf(buf, buf_size, "%s", "disabled"); + break; + case PIM_MSDP_INACTIVE: + snprintf(buf, buf_size, "%s", "inactive"); + break; + case PIM_MSDP_LISTEN: + snprintf(buf, buf_size, "%s", "listen"); + break; + case PIM_MSDP_CONNECTING: + snprintf(buf, buf_size, "%s", "connecting"); + break; + case PIM_MSDP_ESTABLISHED: + snprintf(buf, buf_size, "%s", "established"); + break; + default: + snprintf(buf, buf_size, "unk-%d", state); + } + return buf; +} + +char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, + bool long_format) +{ + char peer_str[INET_ADDRSTRLEN]; + char local_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str)); + if (long_format) { + pim_inet4_dump("<local?>", mp->local, local_str, + sizeof(local_str)); + snprintf(buf, buf_size, "MSDP peer %s local %s mg %s", peer_str, + local_str, mp->mesh_group_name); + } else { + snprintf(buf, buf_size, "MSDP peer %s", peer_str); + } + + return buf; +} + +static void pim_msdp_peer_state_chg_log(struct pim_msdp_peer *mp) +{ + char state_str[PIM_MSDP_STATE_STRLEN]; + + pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); + zlog_debug("MSDP peer %s state chg to %s", mp->key_str, state_str); } /* MSDP Connection State Machine actions (defined in RFC-3618:Sec-11.2) */ /* 11.2.A2: active peer - start connect retry timer; when the timer fires * a tcp connection will be made */ -static void -pim_msdp_peer_connect(struct pim_msdp_peer *mp) +static void pim_msdp_peer_connect(struct pim_msdp_peer *mp) { - mp->state = PIM_MSDP_CONNECTING; - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_state_chg_log(mp); - } + mp->state = PIM_MSDP_CONNECTING; + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } - pim_msdp_peer_cr_timer_setup(mp, true /* start */); + pim_msdp_peer_cr_timer_setup(mp, true /* start */); } /* 11.2.A3: passive peer - just listen for connections */ -static void -pim_msdp_peer_listen(struct pim_msdp_peer *mp) +static void pim_msdp_peer_listen(struct pim_msdp_peer *mp) { - mp->state = PIM_MSDP_LISTEN; - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_state_chg_log(mp); - } + mp->state = PIM_MSDP_LISTEN; + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } - /* this is interntionally asymmetric i.e. we set up listen-socket when the - * first listening peer is configured; but don't bother tearing it down when - * all the peers go down */ - pim_msdp_sock_listen(); + /* this is interntionally asymmetric i.e. we set up listen-socket when + * the + * first listening peer is configured; but don't bother tearing it down + * when + * all the peers go down */ + pim_msdp_sock_listen(); } /* 11.2.A4 and 11.2.A5: transition active or passive peer to * established state */ -void -pim_msdp_peer_established(struct pim_msdp_peer *mp) +void pim_msdp_peer_established(struct pim_msdp_peer *mp) { - if (mp->state != PIM_MSDP_ESTABLISHED) { - ++mp->est_flaps; - } + if (mp->state != PIM_MSDP_ESTABLISHED) { + ++mp->est_flaps; + } - mp->state = PIM_MSDP_ESTABLISHED; - mp->uptime = pim_time_monotonic_sec(); + mp->state = PIM_MSDP_ESTABLISHED; + mp->uptime = pim_time_monotonic_sec(); - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_state_chg_log(mp); - } + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } - /* stop retry timer on active peers */ - pim_msdp_peer_cr_timer_setup(mp, false /* start */); + /* stop retry timer on active peers */ + pim_msdp_peer_cr_timer_setup(mp, false /* start */); - /* send KA; start KA and hold timers */ - pim_msdp_pkt_ka_tx(mp); - pim_msdp_peer_ka_timer_setup(mp, true /* start */); - pim_msdp_peer_hold_timer_setup(mp, true /* start */); + /* send KA; start KA and hold timers */ + pim_msdp_pkt_ka_tx(mp); + pim_msdp_peer_ka_timer_setup(mp, true /* start */); + pim_msdp_peer_hold_timer_setup(mp, true /* start */); - pim_msdp_pkt_sa_tx_to_one_peer(mp); + pim_msdp_pkt_sa_tx_to_one_peer(mp); - PIM_MSDP_PEER_WRITE_ON(mp); - PIM_MSDP_PEER_READ_ON(mp); + PIM_MSDP_PEER_WRITE_ON(mp); + PIM_MSDP_PEER_READ_ON(mp); } /* 11.2.A6, 11.2.A7 and 11.2.A8: shutdown the peer tcp connection */ -void -pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state) -{ - if (chg_state) { - if (mp->state == PIM_MSDP_ESTABLISHED) { - ++mp->est_flaps; - } - mp->state = PIM_MSDP_INACTIVE; - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_state_chg_log(mp); - } - } - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_peer_stop_tcp_conn", mp->key_str); - } - /* stop read and write threads */ - PIM_MSDP_PEER_READ_OFF(mp); - PIM_MSDP_PEER_WRITE_OFF(mp); - - /* reset buffers */ - mp->packet_size = 0; - if (mp->ibuf) - stream_reset(mp->ibuf); - if (mp->obuf) - stream_fifo_clean(mp->obuf); - - /* stop all peer timers */ - pim_msdp_peer_ka_timer_setup(mp, false /* start */); - pim_msdp_peer_cr_timer_setup(mp, false /* start */); - pim_msdp_peer_hold_timer_setup(mp, false /* start */); - - /* close connection */ - if (mp->fd >= 0) { - close(mp->fd); - mp->fd = -1; - } +void pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state) +{ + if (chg_state) { + if (mp->state == PIM_MSDP_ESTABLISHED) { + ++mp->est_flaps; + } + mp->state = PIM_MSDP_INACTIVE; + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } + } + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_msdp_peer_stop_tcp_conn", + mp->key_str); + } + /* stop read and write threads */ + PIM_MSDP_PEER_READ_OFF(mp); + PIM_MSDP_PEER_WRITE_OFF(mp); + + /* reset buffers */ + mp->packet_size = 0; + if (mp->ibuf) + stream_reset(mp->ibuf); + if (mp->obuf) + stream_fifo_clean(mp->obuf); + + /* stop all peer timers */ + pim_msdp_peer_ka_timer_setup(mp, false /* start */); + pim_msdp_peer_cr_timer_setup(mp, false /* start */); + pim_msdp_peer_hold_timer_setup(mp, false /* start */); + + /* close connection */ + if (mp->fd >= 0) { + close(mp->fd); + mp->fd = -1; + } } /* RFC-3618:Sec-5.6 - stop the peer tcp connection and startover */ -void -pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str) +void pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str) { - if (PIM_DEBUG_EVENTS) { - zlog_debug("MSDP peer %s tcp reset %s", mp->key_str, rc_str); - snprintf(mp->last_reset, sizeof(mp->last_reset), "%s", rc_str); - } + if (PIM_DEBUG_EVENTS) { + zlog_debug("MSDP peer %s tcp reset %s", mp->key_str, rc_str); + snprintf(mp->last_reset, sizeof(mp->last_reset), "%s", rc_str); + } - /* close the connection and transition to listening or connecting */ - pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); - if (PIM_MSDP_PEER_IS_LISTENER(mp)) { - pim_msdp_peer_listen(mp); - } else { - pim_msdp_peer_connect(mp); - } + /* close the connection and transition to listening or connecting */ + pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); + if (PIM_MSDP_PEER_IS_LISTENER(mp)) { + pim_msdp_peer_listen(mp); + } else { + pim_msdp_peer_connect(mp); + } } -static void -pim_msdp_peer_timer_expiry_log(struct pim_msdp_peer *mp, const char *timer_str) +static void pim_msdp_peer_timer_expiry_log(struct pim_msdp_peer *mp, + const char *timer_str) { - zlog_debug("MSDP peer %s %s timer expired", mp->key_str, timer_str); + zlog_debug("MSDP peer %s %s timer expired", mp->key_str, timer_str); } /* RFC-3618:Sec-5.4 - peer hold timer */ -static int -pim_msdp_peer_hold_timer_cb(struct thread *t) +static int pim_msdp_peer_hold_timer_cb(struct thread *t) { - struct pim_msdp_peer *mp; + struct pim_msdp_peer *mp; - mp = THREAD_ARG(t); + mp = THREAD_ARG(t); - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_timer_expiry_log(mp, "hold"); - } + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_timer_expiry_log(mp, "hold"); + } - if (mp->state != PIM_MSDP_ESTABLISHED) { - return 0; - } + if (mp->state != PIM_MSDP_ESTABLISHED) { + return 0; + } - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_state_chg_log(mp); - } - pim_msdp_peer_reset_tcp_conn(mp, "ht-expired"); - return 0; + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } + pim_msdp_peer_reset_tcp_conn(mp, "ht-expired"); + return 0; } -static void -pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, bool start) +static void pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, bool start) { - THREAD_OFF(mp->hold_timer); - if (start) { - thread_add_timer(msdp->master, pim_msdp_peer_hold_timer_cb, mp, - PIM_MSDP_PEER_HOLD_TIME, &mp->hold_timer); - } + THREAD_OFF(mp->hold_timer); + if (start) { + thread_add_timer(msdp->master, pim_msdp_peer_hold_timer_cb, mp, + PIM_MSDP_PEER_HOLD_TIME, &mp->hold_timer); + } } /* RFC-3618:Sec-5.5 - peer keepalive timer */ -static int -pim_msdp_peer_ka_timer_cb(struct thread *t) +static int pim_msdp_peer_ka_timer_cb(struct thread *t) { - struct pim_msdp_peer *mp; + struct pim_msdp_peer *mp; - mp = THREAD_ARG(t); + mp = THREAD_ARG(t); - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_timer_expiry_log(mp, "ka"); - } + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_timer_expiry_log(mp, "ka"); + } - pim_msdp_pkt_ka_tx(mp); - pim_msdp_peer_ka_timer_setup(mp, true /* start */); - return 0; + pim_msdp_pkt_ka_tx(mp); + pim_msdp_peer_ka_timer_setup(mp, true /* start */); + return 0; } -static void -pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start) +static void pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start) { - THREAD_OFF(mp->ka_timer); - if (start) { - thread_add_timer(msdp->master, pim_msdp_peer_ka_timer_cb, mp, - PIM_MSDP_PEER_KA_TIME, &mp->ka_timer); - } + THREAD_OFF(mp->ka_timer); + if (start) { + thread_add_timer(msdp->master, pim_msdp_peer_ka_timer_cb, mp, + PIM_MSDP_PEER_KA_TIME, &mp->ka_timer); + } } -static void -pim_msdp_peer_active_connect(struct pim_msdp_peer *mp) +static void pim_msdp_peer_active_connect(struct pim_msdp_peer *mp) { - int rc; - ++mp->conn_attempts; - rc = pim_msdp_sock_connect(mp); + int rc; + ++mp->conn_attempts; + rc = pim_msdp_sock_connect(mp); - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_peer_active_connect: %d", mp->key_str, rc); - } + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_msdp_peer_active_connect: %d", + mp->key_str, rc); + } - switch (rc) { - case connect_error: - case -1: - /* connect failed restart the connect-retry timer */ - pim_msdp_peer_cr_timer_setup(mp, true /* start */); - break; + switch (rc) { + case connect_error: + case -1: + /* connect failed restart the connect-retry timer */ + pim_msdp_peer_cr_timer_setup(mp, true /* start */); + break; - case connect_success: - /* connect was sucessful move to established */ - pim_msdp_peer_established(mp); - break; + case connect_success: + /* connect was sucessful move to established */ + pim_msdp_peer_established(mp); + break; - case connect_in_progress: - /* for NB content we need to wait till sock is readable or - * writeable */ - PIM_MSDP_PEER_WRITE_ON(mp); - PIM_MSDP_PEER_READ_ON(mp); - /* also restart connect-retry timer to reset the socket if connect is - * not sucessful */ - pim_msdp_peer_cr_timer_setup(mp, true /* start */); - break; - } + case connect_in_progress: + /* for NB content we need to wait till sock is readable or + * writeable */ + PIM_MSDP_PEER_WRITE_ON(mp); + PIM_MSDP_PEER_READ_ON(mp); + /* also restart connect-retry timer to reset the socket if + * connect is + * not sucessful */ + pim_msdp_peer_cr_timer_setup(mp, true /* start */); + break; + } } /* RFC-3618:Sec-5.6 - connection retry on active peer */ -static int -pim_msdp_peer_cr_timer_cb(struct thread *t) +static int pim_msdp_peer_cr_timer_cb(struct thread *t) { - struct pim_msdp_peer *mp; + struct pim_msdp_peer *mp; - mp = THREAD_ARG(t); + mp = THREAD_ARG(t); - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_timer_expiry_log(mp, "connect-retry"); - } + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_timer_expiry_log(mp, "connect-retry"); + } - if (mp->state != PIM_MSDP_CONNECTING || PIM_MSDP_PEER_IS_LISTENER(mp)) { - return 0; - } + if (mp->state != PIM_MSDP_CONNECTING || PIM_MSDP_PEER_IS_LISTENER(mp)) { + return 0; + } - pim_msdp_peer_active_connect(mp); - return 0; + pim_msdp_peer_active_connect(mp); + return 0; } -static void -pim_msdp_peer_cr_timer_setup(struct pim_msdp_peer *mp, bool start) +static void pim_msdp_peer_cr_timer_setup(struct pim_msdp_peer *mp, bool start) { - THREAD_OFF(mp->cr_timer); - if (start) { - thread_add_timer(msdp->master, pim_msdp_peer_cr_timer_cb, mp, - PIM_MSDP_PEER_CONNECT_RETRY_TIME, &mp->cr_timer); - } + THREAD_OFF(mp->cr_timer); + if (start) { + thread_add_timer(msdp->master, pim_msdp_peer_cr_timer_cb, mp, + PIM_MSDP_PEER_CONNECT_RETRY_TIME, + &mp->cr_timer); + } } /* if a valid packet is rxed from the peer we can restart hold timer */ -void -pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp) +void pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp) { - if (mp->state == PIM_MSDP_ESTABLISHED) { - pim_msdp_peer_hold_timer_setup(mp, true /* start */); - } + if (mp->state == PIM_MSDP_ESTABLISHED) { + pim_msdp_peer_hold_timer_setup(mp, true /* start */); + } } /* if a valid packet is txed to the peer we can restart ka timer and avoid * unnecessary ka noise in the network */ -void -pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp) +void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp) { - if (mp->state == PIM_MSDP_ESTABLISHED) { - pim_msdp_peer_ka_timer_setup(mp, true /* start */); - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP ka timer restart on pkt tx to %s", mp->key_str); - } - } + if (mp->state == PIM_MSDP_ESTABLISHED) { + pim_msdp_peer_ka_timer_setup(mp, true /* start */); + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP ka timer restart on pkt tx to %s", + mp->key_str); + } + } } static void pim_msdp_addr2su(union sockunion *su, struct in_addr addr) { - sockunion_init(su); - su->sin.sin_addr = addr; - su->sin.sin_family = AF_INET; + sockunion_init(su); + su->sin.sin_addr = addr; + su->sin.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - su->sin.sin_len = sizeof(struct sockaddr_in); + su->sin.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ } /* 11.2.A1: create a new peer and transition state to listen or connecting */ -static enum pim_msdp_err -pim_msdp_peer_new(struct in_addr peer_addr, struct in_addr local_addr, - const char *mesh_group_name, struct pim_msdp_peer **mp_p) -{ - struct pim_msdp_peer *mp; - - pim_msdp_enable(); - - mp = XCALLOC(MTYPE_PIM_MSDP_PEER, sizeof(*mp)); - if (!mp) { - zlog_err("%s: PIM XCALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*mp)); - return PIM_MSDP_ERR_OOM; - } - - mp->peer = peer_addr; - pim_inet4_dump("<peer?>", mp->peer, mp->key_str, sizeof(mp->key_str)); - pim_msdp_addr2su(&mp->su_peer, mp->peer); - mp->local = local_addr; - /* XXX: originator_id setting needs to move to the mesh group */ - msdp->originator_id = local_addr; - pim_msdp_addr2su(&mp->su_local, mp->local); - mp->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); - mp->state = PIM_MSDP_INACTIVE; - mp->fd = -1; - strcpy(mp->last_reset, "-"); - /* higher IP address is listener */ - if (ntohl(mp->local.s_addr) > ntohl(mp->peer.s_addr)) { - mp->flags |= PIM_MSDP_PEERF_LISTENER; - } - - /* setup packet buffers */ - mp->ibuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); - mp->obuf = stream_fifo_new(); - - /* insert into misc tables for easy access */ - mp = hash_get(msdp->peer_hash, mp, hash_alloc_intern); - listnode_add_sort(msdp->peer_list, mp); - - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP peer %s created", mp->key_str); - - pim_msdp_peer_state_chg_log(mp); - } - - /* fireup the connect state machine */ - if (PIM_MSDP_PEER_IS_LISTENER(mp)) { - pim_msdp_peer_listen(mp); - } else { - pim_msdp_peer_connect(mp); - } - if (mp_p) { - *mp_p = mp; - } - return PIM_MSDP_ERR_NONE; -} - -struct pim_msdp_peer * -pim_msdp_peer_find(struct in_addr peer_addr) -{ - struct pim_msdp_peer lookup; - - lookup.peer = peer_addr; - return hash_lookup(msdp->peer_hash, &lookup); +static enum pim_msdp_err pim_msdp_peer_new(struct in_addr peer_addr, + struct in_addr local_addr, + const char *mesh_group_name, + struct pim_msdp_peer **mp_p) +{ + struct pim_msdp_peer *mp; + + pim_msdp_enable(); + + mp = XCALLOC(MTYPE_PIM_MSDP_PEER, sizeof(*mp)); + if (!mp) { + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, + sizeof(*mp)); + return PIM_MSDP_ERR_OOM; + } + + mp->peer = peer_addr; + pim_inet4_dump("<peer?>", mp->peer, mp->key_str, sizeof(mp->key_str)); + pim_msdp_addr2su(&mp->su_peer, mp->peer); + mp->local = local_addr; + /* XXX: originator_id setting needs to move to the mesh group */ + msdp->originator_id = local_addr; + pim_msdp_addr2su(&mp->su_local, mp->local); + mp->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); + mp->state = PIM_MSDP_INACTIVE; + mp->fd = -1; + strcpy(mp->last_reset, "-"); + /* higher IP address is listener */ + if (ntohl(mp->local.s_addr) > ntohl(mp->peer.s_addr)) { + mp->flags |= PIM_MSDP_PEERF_LISTENER; + } + + /* setup packet buffers */ + mp->ibuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); + mp->obuf = stream_fifo_new(); + + /* insert into misc tables for easy access */ + mp = hash_get(msdp->peer_hash, mp, hash_alloc_intern); + listnode_add_sort(msdp->peer_list, mp); + + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP peer %s created", mp->key_str); + + pim_msdp_peer_state_chg_log(mp); + } + + /* fireup the connect state machine */ + if (PIM_MSDP_PEER_IS_LISTENER(mp)) { + pim_msdp_peer_listen(mp); + } else { + pim_msdp_peer_connect(mp); + } + if (mp_p) { + *mp_p = mp; + } + return PIM_MSDP_ERR_NONE; +} + +struct pim_msdp_peer *pim_msdp_peer_find(struct in_addr peer_addr) +{ + struct pim_msdp_peer lookup; + + lookup.peer = peer_addr; + return hash_lookup(msdp->peer_hash, &lookup); } /* add peer configuration if it doesn't already exist */ -enum pim_msdp_err -pim_msdp_peer_add(struct in_addr peer_addr, struct in_addr local_addr, - const char *mesh_group_name, struct pim_msdp_peer **mp_p) +enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer_addr, + struct in_addr local_addr, + const char *mesh_group_name, + struct pim_msdp_peer **mp_p) { - struct pim_msdp_peer *mp; + struct pim_msdp_peer *mp; - if (mp_p) { - *mp_p = NULL; - } + if (mp_p) { + *mp_p = NULL; + } - if (peer_addr.s_addr == local_addr.s_addr) { - /* skip session setup if config is invalid */ - if (PIM_DEBUG_MSDP_EVENTS) { - char peer_str[INET_ADDRSTRLEN]; + if (peer_addr.s_addr == local_addr.s_addr) { + /* skip session setup if config is invalid */ + if (PIM_DEBUG_MSDP_EVENTS) { + char peer_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<peer?>", peer_addr, peer_str, sizeof(peer_str)); - zlog_debug("%s add skipped as DIP=SIP", peer_str); - } - return PIM_MSDP_ERR_SIP_EQ_DIP; - } + pim_inet4_dump("<peer?>", peer_addr, peer_str, + sizeof(peer_str)); + zlog_debug("%s add skipped as DIP=SIP", peer_str); + } + return PIM_MSDP_ERR_SIP_EQ_DIP; + } - mp = pim_msdp_peer_find(peer_addr); - if (mp) { - if (mp_p) { - *mp_p = mp; - } - return PIM_MSDP_ERR_PEER_EXISTS; - } + mp = pim_msdp_peer_find(peer_addr); + if (mp) { + if (mp_p) { + *mp_p = mp; + } + return PIM_MSDP_ERR_PEER_EXISTS; + } - return pim_msdp_peer_new(peer_addr, local_addr, mesh_group_name, mp_p); + return pim_msdp_peer_new(peer_addr, local_addr, mesh_group_name, mp_p); } /* release all mem associated with a peer */ -static void -pim_msdp_peer_free(struct pim_msdp_peer *mp) +static void pim_msdp_peer_free(struct pim_msdp_peer *mp) { - if (mp->ibuf) { - stream_free(mp->ibuf); - } + if (mp->ibuf) { + stream_free(mp->ibuf); + } - if (mp->obuf) { - stream_fifo_free(mp->obuf); - } + if (mp->obuf) { + stream_fifo_free(mp->obuf); + } - if (mp->mesh_group_name) { - XFREE(MTYPE_PIM_MSDP_MG_NAME, mp->mesh_group_name); - } - XFREE(MTYPE_PIM_MSDP_PEER, mp); + if (mp->mesh_group_name) { + XFREE(MTYPE_PIM_MSDP_MG_NAME, mp->mesh_group_name); + } + XFREE(MTYPE_PIM_MSDP_PEER, mp); } /* delete the peer config */ -static enum pim_msdp_err -pim_msdp_peer_do_del(struct pim_msdp_peer *mp) +static enum pim_msdp_err pim_msdp_peer_do_del(struct pim_msdp_peer *mp) { - /* stop the tcp connection and shutdown all timers */ - pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); + /* stop the tcp connection and shutdown all timers */ + pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); - /* remove the session from various tables */ - listnode_delete(msdp->peer_list, mp); - hash_release(msdp->peer_hash, mp); + /* remove the session from various tables */ + listnode_delete(msdp->peer_list, mp); + hash_release(msdp->peer_hash, mp); - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP peer %s deleted", mp->key_str); - } + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP peer %s deleted", mp->key_str); + } - /* free up any associated memory */ - pim_msdp_peer_free(mp); + /* free up any associated memory */ + pim_msdp_peer_free(mp); - return PIM_MSDP_ERR_NONE; + return PIM_MSDP_ERR_NONE; } -enum pim_msdp_err -pim_msdp_peer_del(struct in_addr peer_addr) +enum pim_msdp_err pim_msdp_peer_del(struct in_addr peer_addr) { - struct pim_msdp_peer *mp; + struct pim_msdp_peer *mp; - mp = pim_msdp_peer_find(peer_addr); - if (!mp) { - return PIM_MSDP_ERR_NO_PEER; - } + mp = pim_msdp_peer_find(peer_addr); + if (!mp) { + return PIM_MSDP_ERR_NO_PEER; + } - return pim_msdp_peer_do_del(mp); + return pim_msdp_peer_do_del(mp); } /* peer hash and peer list helpers */ -static unsigned int -pim_msdp_peer_hash_key_make(void *p) +static unsigned int pim_msdp_peer_hash_key_make(void *p) { - struct pim_msdp_peer *mp = p; - return (jhash_1word(mp->peer.s_addr, 0)); + struct pim_msdp_peer *mp = p; + return (jhash_1word(mp->peer.s_addr, 0)); } -static int -pim_msdp_peer_hash_eq(const void *p1, const void *p2) +static int pim_msdp_peer_hash_eq(const void *p1, const void *p2) { - const struct pim_msdp_peer *mp1 = p1; - const struct pim_msdp_peer *mp2 = p2; + const struct pim_msdp_peer *mp1 = p1; + const struct pim_msdp_peer *mp2 = p2; - return (mp1->peer.s_addr == mp2->peer.s_addr); + return (mp1->peer.s_addr == mp2->peer.s_addr); } -static int -pim_msdp_peer_comp(const void *p1, const void *p2) +static int pim_msdp_peer_comp(const void *p1, const void *p2) { - const struct pim_msdp_peer *mp1 = p1; - const struct pim_msdp_peer *mp2 = p2; + const struct pim_msdp_peer *mp1 = p1; + const struct pim_msdp_peer *mp2 = p2; - if (ntohl(mp1->peer.s_addr) < ntohl(mp2->peer.s_addr)) - return -1; + if (ntohl(mp1->peer.s_addr) < ntohl(mp2->peer.s_addr)) + return -1; - if (ntohl(mp1->peer.s_addr) > ntohl(mp2->peer.s_addr)) - return 1; + if (ntohl(mp1->peer.s_addr) > ntohl(mp2->peer.s_addr)) + return 1; - return 0; + return 0; } /************************** Mesh group management **************************/ -static void -pim_msdp_mg_free(struct pim_msdp_mg *mg) +static void pim_msdp_mg_free(struct pim_msdp_mg *mg) { - /* If the mesh-group has valid member or src_ip don't delete it */ - if (!mg || mg->mbr_cnt || (mg->src_ip.s_addr != INADDR_ANY)) { - return; - } + /* If the mesh-group has valid member or src_ip don't delete it */ + if (!mg || mg->mbr_cnt || (mg->src_ip.s_addr != INADDR_ANY)) { + return; + } - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP mesh-group %s deleted", mg->mesh_group_name); - } - if (mg->mesh_group_name) - XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name); + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP mesh-group %s deleted", mg->mesh_group_name); + } + if (mg->mesh_group_name) + XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name); - if (mg->mbr_list) - list_free(mg->mbr_list); + if (mg->mbr_list) + list_free(mg->mbr_list); - XFREE(MTYPE_PIM_MSDP_MG, mg); - msdp->mg = NULL; + XFREE(MTYPE_PIM_MSDP_MG, mg); + msdp->mg = NULL; } -static struct pim_msdp_mg * -pim_msdp_mg_new(const char *mesh_group_name) +static struct pim_msdp_mg *pim_msdp_mg_new(const char *mesh_group_name) { - struct pim_msdp_mg *mg; + struct pim_msdp_mg *mg; - mg = XCALLOC(MTYPE_PIM_MSDP_MG, sizeof(*mg)); - if (!mg) { - zlog_err("%s: PIM XCALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*mg)); - return NULL; - } + mg = XCALLOC(MTYPE_PIM_MSDP_MG, sizeof(*mg)); + if (!mg) { + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, + sizeof(*mg)); + return NULL; + } - mg->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); - mg->mbr_list = list_new(); - mg->mbr_list->del = (void (*)(void *))pim_msdp_mg_mbr_free; - mg->mbr_list->cmp = (int (*)(void *, void *))pim_msdp_mg_mbr_comp; + mg->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); + mg->mbr_list = list_new(); + mg->mbr_list->del = (void (*)(void *))pim_msdp_mg_mbr_free; + mg->mbr_list->cmp = (int (*)(void *, void *))pim_msdp_mg_mbr_comp; - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP mesh-group %s created", mg->mesh_group_name); - } - return mg; + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP mesh-group %s created", mg->mesh_group_name); + } + return mg; } -enum pim_msdp_err -pim_msdp_mg_del(const char *mesh_group_name) +enum pim_msdp_err pim_msdp_mg_del(const char *mesh_group_name) { - struct pim_msdp_mg *mg = msdp->mg; - struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg = msdp->mg; + struct pim_msdp_mg_mbr *mbr; - if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { - return PIM_MSDP_ERR_NO_MG; - } + if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { + return PIM_MSDP_ERR_NO_MG; + } - /* delete all the mesh-group members */ - while (!list_isempty(mg->mbr_list)) { - mbr = listnode_head(mg->mbr_list); - pim_msdp_mg_mbr_do_del(mg, mbr); - } + /* delete all the mesh-group members */ + while (!list_isempty(mg->mbr_list)) { + mbr = listnode_head(mg->mbr_list); + pim_msdp_mg_mbr_do_del(mg, mbr); + } - /* clear src ip */ - mg->src_ip.s_addr = INADDR_ANY; + /* clear src ip */ + mg->src_ip.s_addr = INADDR_ANY; - /* free up the mesh-group */ - pim_msdp_mg_free(mg); - return PIM_MSDP_ERR_NONE; + /* free up the mesh-group */ + pim_msdp_mg_free(mg); + return PIM_MSDP_ERR_NONE; } -static enum pim_msdp_err -pim_msdp_mg_add(const char *mesh_group_name) +static enum pim_msdp_err pim_msdp_mg_add(const char *mesh_group_name) { - if (msdp->mg) { - if (!strcmp(msdp->mg->mesh_group_name, mesh_group_name)) { - return PIM_MSDP_ERR_NONE; - } - /* currently only one mesh-group can exist at a time */ - return PIM_MSDP_ERR_MAX_MESH_GROUPS; - } + if (msdp->mg) { + if (!strcmp(msdp->mg->mesh_group_name, mesh_group_name)) { + return PIM_MSDP_ERR_NONE; + } + /* currently only one mesh-group can exist at a time */ + return PIM_MSDP_ERR_MAX_MESH_GROUPS; + } - msdp->mg = pim_msdp_mg_new(mesh_group_name); - if (!msdp->mg) { - return PIM_MSDP_ERR_OOM; - } + msdp->mg = pim_msdp_mg_new(mesh_group_name); + if (!msdp->mg) { + return PIM_MSDP_ERR_OOM; + } - return PIM_MSDP_ERR_NONE; + return PIM_MSDP_ERR_NONE; } -static int -pim_msdp_mg_mbr_comp(const void *p1, const void *p2) +static int pim_msdp_mg_mbr_comp(const void *p1, const void *p2) { - const struct pim_msdp_mg_mbr *mbr1 = p1; - const struct pim_msdp_mg_mbr *mbr2 = p2; + const struct pim_msdp_mg_mbr *mbr1 = p1; + const struct pim_msdp_mg_mbr *mbr2 = p2; - if (ntohl(mbr1->mbr_ip.s_addr) < ntohl(mbr2->mbr_ip.s_addr)) - return -1; + if (ntohl(mbr1->mbr_ip.s_addr) < ntohl(mbr2->mbr_ip.s_addr)) + return -1; - if (ntohl(mbr1->mbr_ip.s_addr) > ntohl(mbr2->mbr_ip.s_addr)) - return 1; + if (ntohl(mbr1->mbr_ip.s_addr) > ntohl(mbr2->mbr_ip.s_addr)) + return 1; - return 0; + return 0; } -static void -pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr) +static void pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr) { - XFREE(MTYPE_PIM_MSDP_MG_MBR, mbr); + XFREE(MTYPE_PIM_MSDP_MG_MBR, mbr); } -static struct pim_msdp_mg_mbr * -pim_msdp_mg_mbr_find(struct in_addr mbr_ip) +static struct pim_msdp_mg_mbr *pim_msdp_mg_mbr_find(struct in_addr mbr_ip) { - struct pim_msdp_mg_mbr *mbr; - struct listnode *mbr_node; + struct pim_msdp_mg_mbr *mbr; + struct listnode *mbr_node; - if (!msdp->mg) { - return NULL; - } - /* we can move this to a hash but considering that number of peers in - * a mesh-group that seems like bit of an overkill */ - for (ALL_LIST_ELEMENTS_RO(msdp->mg->mbr_list, mbr_node, mbr)) { - if (mbr->mbr_ip.s_addr == mbr_ip.s_addr) { - return mbr; - } - } - return mbr; + if (!msdp->mg) { + return NULL; + } + /* we can move this to a hash but considering that number of peers in + * a mesh-group that seems like bit of an overkill */ + for (ALL_LIST_ELEMENTS_RO(msdp->mg->mbr_list, mbr_node, mbr)) { + if (mbr->mbr_ip.s_addr == mbr_ip.s_addr) { + return mbr; + } + } + return mbr; } -enum pim_msdp_err -pim_msdp_mg_mbr_add(const char *mesh_group_name, struct in_addr mbr_ip) +enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name, + struct in_addr mbr_ip) { - int rc; - struct pim_msdp_mg_mbr *mbr; - struct pim_msdp_mg *mg; + int rc; + struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg; - rc = pim_msdp_mg_add(mesh_group_name); - if (rc != PIM_MSDP_ERR_NONE) { - return rc; - } + rc = pim_msdp_mg_add(mesh_group_name); + if (rc != PIM_MSDP_ERR_NONE) { + return rc; + } - mg = msdp->mg; - mbr = pim_msdp_mg_mbr_find(mbr_ip); - if (mbr) { - return PIM_MSDP_ERR_MG_MBR_EXISTS; - } + mg = msdp->mg; + mbr = pim_msdp_mg_mbr_find(mbr_ip); + if (mbr) { + return PIM_MSDP_ERR_MG_MBR_EXISTS; + } - mbr = XCALLOC(MTYPE_PIM_MSDP_MG_MBR, sizeof(*mbr)); - if (!mbr) { - zlog_err("%s: PIM XCALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*mbr)); - /* if there are no references to the mg free it */ - pim_msdp_mg_free(mg); - return PIM_MSDP_ERR_OOM; - } - mbr->mbr_ip = mbr_ip; - listnode_add_sort(mg->mbr_list, mbr); + mbr = XCALLOC(MTYPE_PIM_MSDP_MG_MBR, sizeof(*mbr)); + if (!mbr) { + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, + sizeof(*mbr)); + /* if there are no references to the mg free it */ + pim_msdp_mg_free(mg); + return PIM_MSDP_ERR_OOM; + } + mbr->mbr_ip = mbr_ip; + listnode_add_sort(mg->mbr_list, mbr); - /* if valid SIP has been configured add peer session */ - if (mg->src_ip.s_addr != INADDR_ANY) { - pim_msdp_peer_add(mbr_ip, mg->src_ip, mesh_group_name, - &mbr->mp); - } + /* if valid SIP has been configured add peer session */ + if (mg->src_ip.s_addr != INADDR_ANY) { + pim_msdp_peer_add(mbr_ip, mg->src_ip, mesh_group_name, + &mbr->mp); + } - if (PIM_DEBUG_MSDP_EVENTS) { - char ip_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<mbr?>", mbr->mbr_ip, ip_str, sizeof(ip_str)); - zlog_debug("MSDP mesh-group %s mbr %s created", mg->mesh_group_name, ip_str); - } - ++mg->mbr_cnt; - return PIM_MSDP_ERR_NONE; + if (PIM_DEBUG_MSDP_EVENTS) { + char ip_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<mbr?>", mbr->mbr_ip, ip_str, sizeof(ip_str)); + zlog_debug("MSDP mesh-group %s mbr %s created", + mg->mesh_group_name, ip_str); + } + ++mg->mbr_cnt; + return PIM_MSDP_ERR_NONE; } -static void -pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, struct pim_msdp_mg_mbr *mbr) +static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, + struct pim_msdp_mg_mbr *mbr) { - /* Delete active peer session if any */ - if (mbr->mp) { - pim_msdp_peer_do_del(mbr->mp); - } + /* Delete active peer session if any */ + if (mbr->mp) { + pim_msdp_peer_do_del(mbr->mp); + } - listnode_delete(mg->mbr_list, mbr); - if (PIM_DEBUG_MSDP_EVENTS) { - char ip_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<mbr?>", mbr->mbr_ip, ip_str, sizeof(ip_str)); - zlog_debug("MSDP mesh-group %s mbr %s deleted", mg->mesh_group_name, ip_str); - } - pim_msdp_mg_mbr_free(mbr); - if (mg->mbr_cnt) { - --mg->mbr_cnt; - } + listnode_delete(mg->mbr_list, mbr); + if (PIM_DEBUG_MSDP_EVENTS) { + char ip_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<mbr?>", mbr->mbr_ip, ip_str, sizeof(ip_str)); + zlog_debug("MSDP mesh-group %s mbr %s deleted", + mg->mesh_group_name, ip_str); + } + pim_msdp_mg_mbr_free(mbr); + if (mg->mbr_cnt) { + --mg->mbr_cnt; + } } -enum pim_msdp_err -pim_msdp_mg_mbr_del(const char *mesh_group_name, struct in_addr mbr_ip) -{ - struct pim_msdp_mg_mbr *mbr; - struct pim_msdp_mg *mg = msdp->mg; - - if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { - return PIM_MSDP_ERR_NO_MG; - } - - mbr = pim_msdp_mg_mbr_find(mbr_ip); - if (!mbr) { - return PIM_MSDP_ERR_NO_MG_MBR; - } - - pim_msdp_mg_mbr_do_del(mg, mbr); - /* if there are no references to the mg free it */ - pim_msdp_mg_free(mg); - - return PIM_MSDP_ERR_NONE; -} - -static void -pim_msdp_mg_src_do_del(void) -{ - struct pim_msdp_mg_mbr *mbr; - struct listnode *mbr_node; - struct pim_msdp_mg *mg = msdp->mg; - - /* SIP is being removed - tear down all active peer sessions */ - for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { - if (mbr->mp) { - pim_msdp_peer_do_del(mbr->mp); - mbr->mp = NULL; - } - } - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP mesh-group %s src cleared", mg->mesh_group_name); - } -} - -enum pim_msdp_err -pim_msdp_mg_src_del(const char *mesh_group_name) -{ - struct pim_msdp_mg *mg = msdp->mg; - - if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { - return PIM_MSDP_ERR_NO_MG; - } - - if (mg->src_ip.s_addr != INADDR_ANY) { - mg->src_ip.s_addr = INADDR_ANY; - pim_msdp_mg_src_do_del(); - /* if there are no references to the mg free it */ - pim_msdp_mg_free(mg); - } - return PIM_MSDP_ERR_NONE; -} - -enum pim_msdp_err -pim_msdp_mg_src_add(const char *mesh_group_name, struct in_addr src_ip) -{ - int rc; - struct pim_msdp_mg_mbr *mbr; - struct listnode *mbr_node; - struct pim_msdp_mg *mg; - - if (src_ip.s_addr == INADDR_ANY) { - pim_msdp_mg_src_del(mesh_group_name); - return PIM_MSDP_ERR_NONE; - } - - rc = pim_msdp_mg_add(mesh_group_name); - if (rc != PIM_MSDP_ERR_NONE) { - return rc; - } - - mg = msdp->mg; - if (mg->src_ip.s_addr != INADDR_ANY) { - pim_msdp_mg_src_do_del(); - } - mg->src_ip = src_ip; +enum pim_msdp_err pim_msdp_mg_mbr_del(const char *mesh_group_name, + struct in_addr mbr_ip) +{ + struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg = msdp->mg; + + if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { + return PIM_MSDP_ERR_NO_MG; + } + + mbr = pim_msdp_mg_mbr_find(mbr_ip); + if (!mbr) { + return PIM_MSDP_ERR_NO_MG_MBR; + } + + pim_msdp_mg_mbr_do_del(mg, mbr); + /* if there are no references to the mg free it */ + pim_msdp_mg_free(mg); + + return PIM_MSDP_ERR_NONE; +} + +static void pim_msdp_mg_src_do_del(void) +{ + struct pim_msdp_mg_mbr *mbr; + struct listnode *mbr_node; + struct pim_msdp_mg *mg = msdp->mg; + + /* SIP is being removed - tear down all active peer sessions */ + for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { + if (mbr->mp) { + pim_msdp_peer_do_del(mbr->mp); + mbr->mp = NULL; + } + } + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP mesh-group %s src cleared", + mg->mesh_group_name); + } +} + +enum pim_msdp_err pim_msdp_mg_src_del(const char *mesh_group_name) +{ + struct pim_msdp_mg *mg = msdp->mg; + + if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { + return PIM_MSDP_ERR_NO_MG; + } + + if (mg->src_ip.s_addr != INADDR_ANY) { + mg->src_ip.s_addr = INADDR_ANY; + pim_msdp_mg_src_do_del(); + /* if there are no references to the mg free it */ + pim_msdp_mg_free(mg); + } + return PIM_MSDP_ERR_NONE; +} + +enum pim_msdp_err pim_msdp_mg_src_add(const char *mesh_group_name, + struct in_addr src_ip) +{ + int rc; + struct pim_msdp_mg_mbr *mbr; + struct listnode *mbr_node; + struct pim_msdp_mg *mg; + + if (src_ip.s_addr == INADDR_ANY) { + pim_msdp_mg_src_del(mesh_group_name); + return PIM_MSDP_ERR_NONE; + } + + rc = pim_msdp_mg_add(mesh_group_name); + if (rc != PIM_MSDP_ERR_NONE) { + return rc; + } + + mg = msdp->mg; + if (mg->src_ip.s_addr != INADDR_ANY) { + pim_msdp_mg_src_do_del(); + } + mg->src_ip = src_ip; - for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { - pim_msdp_peer_add(mbr->mbr_ip, mg->src_ip, mesh_group_name, - &mbr->mp); - } + for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { + pim_msdp_peer_add(mbr->mbr_ip, mg->src_ip, mesh_group_name, + &mbr->mp); + } - if (PIM_DEBUG_MSDP_EVENTS) { - char ip_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", mg->src_ip, ip_str, sizeof(ip_str)); - zlog_debug("MSDP mesh-group %s src %s set", mg->mesh_group_name, ip_str); - } - return PIM_MSDP_ERR_NONE; + if (PIM_DEBUG_MSDP_EVENTS) { + char ip_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", mg->src_ip, ip_str, sizeof(ip_str)); + zlog_debug("MSDP mesh-group %s src %s set", mg->mesh_group_name, + ip_str); + } + return PIM_MSDP_ERR_NONE; } /*********************** MSDP feature APIs *********************************/ -int -pim_msdp_config_write(struct vty *vty) -{ - struct listnode *mbrnode; - struct pim_msdp_mg_mbr *mbr; - struct pim_msdp_mg *mg = msdp->mg; - char mbr_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; - int count = 0; - - if (!mg) { - return count; - } - - if (mg->src_ip.s_addr != INADDR_ANY) { - pim_inet4_dump("<src?>", mg->src_ip, src_str, sizeof(src_str)); - vty_out (vty, "ip msdp mesh-group %s source %s\n", - mg->mesh_group_name, src_str); - ++count; - } - - for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { - pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); - vty_out (vty, "ip msdp mesh-group %s member %s\n", - mg->mesh_group_name, mbr_str); - ++count; - } - return count; +int pim_msdp_config_write(struct vty *vty) +{ + struct listnode *mbrnode; + struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg = msdp->mg; + char mbr_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + int count = 0; + + if (!mg) { + return count; + } + + if (mg->src_ip.s_addr != INADDR_ANY) { + pim_inet4_dump("<src?>", mg->src_ip, src_str, sizeof(src_str)); + vty_out(vty, "ip msdp mesh-group %s source %s\n", + mg->mesh_group_name, src_str); + ++count; + } + + for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { + pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); + vty_out(vty, "ip msdp mesh-group %s member %s\n", + mg->mesh_group_name, mbr_str); + ++count; + } + return count; } /* Enable feature including active/periodic timers etc. on the first peer * config. Till then MSDP should just stay quiet. */ -static void -pim_msdp_enable(void) +static void pim_msdp_enable(void) { - if (msdp->flags & PIM_MSDPF_ENABLE) { - /* feature is already enabled */ - return; - } - msdp->flags |= PIM_MSDPF_ENABLE; - msdp->work_obuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); - pim_msdp_sa_adv_timer_setup(true /* start */); - /* setup sa cache based on local sources */ - pim_msdp_sa_local_setup(); + if (msdp->flags & PIM_MSDPF_ENABLE) { + /* feature is already enabled */ + return; + } + msdp->flags |= PIM_MSDPF_ENABLE; + msdp->work_obuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); + pim_msdp_sa_adv_timer_setup(true /* start */); + /* setup sa cache based on local sources */ + pim_msdp_sa_local_setup(); } /* MSDP init */ -void -pim_msdp_init(struct thread_master *master) +void pim_msdp_init(struct thread_master *master) { - msdp->master = master; + msdp->master = master; - msdp->peer_hash = hash_create(pim_msdp_peer_hash_key_make, - pim_msdp_peer_hash_eq, NULL); - msdp->peer_list = list_new(); - msdp->peer_list->del = (void (*)(void *))pim_msdp_peer_free; - msdp->peer_list->cmp = (int (*)(void *, void *))pim_msdp_peer_comp; + msdp->peer_hash = hash_create(pim_msdp_peer_hash_key_make, + pim_msdp_peer_hash_eq, NULL); + msdp->peer_list = list_new(); + msdp->peer_list->del = (void (*)(void *))pim_msdp_peer_free; + msdp->peer_list->cmp = (int (*)(void *, void *))pim_msdp_peer_comp; - msdp->sa_hash = hash_create(pim_msdp_sa_hash_key_make, - pim_msdp_sa_hash_eq, NULL); - msdp->sa_list = list_new(); - msdp->sa_list->del = (void (*)(void *))pim_msdp_sa_free; - msdp->sa_list->cmp = (int (*)(void *, void *))pim_msdp_sa_comp; + msdp->sa_hash = hash_create(pim_msdp_sa_hash_key_make, + pim_msdp_sa_hash_eq, NULL); + msdp->sa_list = list_new(); + msdp->sa_list->del = (void (*)(void *))pim_msdp_sa_free; + msdp->sa_list->cmp = (int (*)(void *, void *))pim_msdp_sa_comp; } /* counterpart to MSDP init; XXX: unused currently */ -void -pim_msdp_exit(void) +void pim_msdp_exit(void) { - /* XXX: stop listener and delete all peer sessions */ + /* XXX: stop listener and delete all peer sessions */ - if (msdp->peer_hash) { - hash_free(msdp->peer_hash); - msdp->peer_hash = NULL; - } + if (msdp->peer_hash) { + hash_free(msdp->peer_hash); + msdp->peer_hash = NULL; + } - if (msdp->peer_list) { - list_free(msdp->peer_list); - msdp->peer_list = NULL; - } + if (msdp->peer_list) { + list_free(msdp->peer_list); + msdp->peer_list = NULL; + } } diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index 308b437a6..66e5457df 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -20,35 +20,35 @@ #define PIM_MSDP_H enum pim_msdp_peer_state { - PIM_MSDP_DISABLED, - PIM_MSDP_INACTIVE, - PIM_MSDP_LISTEN, - PIM_MSDP_CONNECTING, - PIM_MSDP_ESTABLISHED + PIM_MSDP_DISABLED, + PIM_MSDP_INACTIVE, + PIM_MSDP_LISTEN, + PIM_MSDP_CONNECTING, + PIM_MSDP_ESTABLISHED }; /* SA and KA TLVs are processed; rest ignored */ enum pim_msdp_tlv { - PIM_MSDP_V4_SOURCE_ACTIVE = 1, - PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST, - PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE, - PIM_MSDP_KEEPALIVE, - PIM_MSDP_RESERVED, - PIM_MSDP_TRACEROUTE_PROGRESS, - PIM_MSDP_TRACEROUTE_REPLY, + PIM_MSDP_V4_SOURCE_ACTIVE = 1, + PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST, + PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE, + PIM_MSDP_KEEPALIVE, + PIM_MSDP_RESERVED, + PIM_MSDP_TRACEROUTE_PROGRESS, + PIM_MSDP_TRACEROUTE_REPLY, }; /* MSDP error codes */ enum pim_msdp_err { - PIM_MSDP_ERR_NONE = 0, - PIM_MSDP_ERR_OOM = -1, - PIM_MSDP_ERR_PEER_EXISTS = -2, - PIM_MSDP_ERR_MAX_MESH_GROUPS = -3, - PIM_MSDP_ERR_NO_PEER = -4, - PIM_MSDP_ERR_MG_MBR_EXISTS = -5, - PIM_MSDP_ERR_NO_MG = -6, - PIM_MSDP_ERR_NO_MG_MBR = -7, - PIM_MSDP_ERR_SIP_EQ_DIP = -8, + PIM_MSDP_ERR_NONE = 0, + PIM_MSDP_ERR_OOM = -1, + PIM_MSDP_ERR_PEER_EXISTS = -2, + PIM_MSDP_ERR_MAX_MESH_GROUPS = -3, + PIM_MSDP_ERR_NO_PEER = -4, + PIM_MSDP_ERR_MG_MBR_EXISTS = -5, + PIM_MSDP_ERR_NO_MG = -6, + PIM_MSDP_ERR_NO_MG_MBR = -7, + PIM_MSDP_ERR_SIP_EQ_DIP = -8, }; #define PIM_MSDP_STATE_STRLEN 16 @@ -58,149 +58,155 @@ enum pim_msdp_err { #define PIM_MSDP_SOCKET_SNDBUF_SIZE 65536 enum pim_msdp_sa_flags { - PIM_MSDP_SAF_NONE = 0, - /* There are two cases where we can pickup an active source locally - - * 1. We are RP and got a source-register from the FHR - * 2. We are RP and FHR and learnt a new directly connected source on a - * DR interface */ - PIM_MSDP_SAF_LOCAL = (1 << 0), - /* We got this in the MSDP SA TLV from a peer (and this passed peer-RPF - * checks) */ - PIM_MSDP_SAF_PEER = (1 << 1), - PIM_MSDP_SAF_REF = (PIM_MSDP_SAF_LOCAL | PIM_MSDP_SAF_PEER), - PIM_MSDP_SAF_STALE = (1 << 2), /* local entries can get kicked out on - * misc pim events such as RP change */ - PIM_MSDP_SAF_UP_DEL_IN_PROG = (1 << 3) + PIM_MSDP_SAF_NONE = 0, + /* There are two cases where we can pickup an active source locally - + * 1. We are RP and got a source-register from the FHR + * 2. We are RP and FHR and learnt a new directly connected source on a + * DR interface */ + PIM_MSDP_SAF_LOCAL = (1 << 0), + /* We got this in the MSDP SA TLV from a peer (and this passed peer-RPF + * checks) */ + PIM_MSDP_SAF_PEER = (1 << 1), + PIM_MSDP_SAF_REF = (PIM_MSDP_SAF_LOCAL | PIM_MSDP_SAF_PEER), + PIM_MSDP_SAF_STALE = (1 << 2), /* local entries can get kicked out on + * misc pim events such as RP change */ + PIM_MSDP_SAF_UP_DEL_IN_PROG = (1 << 3) }; struct pim_msdp_sa { - struct prefix_sg sg; - char sg_str[PIM_SG_LEN]; - struct in_addr rp; /* Last RP address associated with this SA */ - struct in_addr peer; /* last peer from who we heard this SA */ - enum pim_msdp_sa_flags flags; - - /* rfc-3618 is missing default value for SA-hold-down-Period. pulled - * this number from industry-standards */ + struct prefix_sg sg; + char sg_str[PIM_SG_LEN]; + struct in_addr rp; /* Last RP address associated with this SA */ + struct in_addr peer; /* last peer from who we heard this SA */ + enum pim_msdp_sa_flags flags; + +/* rfc-3618 is missing default value for SA-hold-down-Period. pulled + * this number from industry-standards */ #define PIM_MSDP_SA_HOLD_TIME ((3*60)+30) - struct thread *sa_state_timer; // 5.6 - int64_t uptime; + struct thread *sa_state_timer; // 5.6 + int64_t uptime; - struct pim_upstream *up; + struct pim_upstream *up; }; enum pim_msdp_peer_flags { - PIM_MSDP_PEERF_NONE = 0, - PIM_MSDP_PEERF_LISTENER = (1 << 0), + PIM_MSDP_PEERF_NONE = 0, + PIM_MSDP_PEERF_LISTENER = (1 << 0), #define PIM_MSDP_PEER_IS_LISTENER(mp) (mp->flags & PIM_MSDP_PEERF_LISTENER) - PIM_MSDP_PEERF_SA_JUST_SENT = (1 << 1) + PIM_MSDP_PEERF_SA_JUST_SENT = (1 << 1) }; struct pim_msdp_peer { - /* configuration */ - struct in_addr local; - struct in_addr peer; - char *mesh_group_name; - char key_str[INET_ADDRSTRLEN]; - - /* state */ - enum pim_msdp_peer_state state; - enum pim_msdp_peer_flags flags; - - /* TCP socket info */ - union sockunion su_local; - union sockunion su_peer; - int fd; - - /* protocol timers */ + /* configuration */ + struct in_addr local; + struct in_addr peer; + char *mesh_group_name; + char key_str[INET_ADDRSTRLEN]; + + /* state */ + enum pim_msdp_peer_state state; + enum pim_msdp_peer_flags flags; + + /* TCP socket info */ + union sockunion su_local; + union sockunion su_peer; + int fd; + +/* protocol timers */ #define PIM_MSDP_PEER_HOLD_TIME 75 - struct thread *hold_timer; // 5.4 + struct thread *hold_timer; // 5.4 + /* $FRR indent$ */ +/* clang-format off */ #define PIM_MSDP_PEER_KA_TIME 60 - struct thread *ka_timer; // 5.5 + struct thread *ka_timer; // 5.5 + /* $FRR indent$ */ + /* clang-format off */ #define PIM_MSDP_PEER_CONNECT_RETRY_TIME 30 - struct thread *cr_timer; // 5.6 - - /* packet thread and buffers */ - uint32_t packet_size; - struct stream *ibuf; - struct stream_fifo *obuf; - struct thread *t_read; - struct thread *t_write; - - /* stats */ - uint32_t conn_attempts; - uint32_t est_flaps; - uint32_t sa_cnt; /* number of SAs attributed to this peer */ + struct thread *cr_timer; // 5.6 + + /* packet thread and buffers */ + uint32_t packet_size; + struct stream *ibuf; + struct stream_fifo *obuf; + struct thread *t_read; + struct thread *t_write; + + /* stats */ + uint32_t conn_attempts; + uint32_t est_flaps; + uint32_t sa_cnt; /* number of SAs attributed to this peer */ + /* $FRR indent$ */ + /* clang-format off */ #define PIM_MSDP_PEER_LAST_RESET_STR 20 - char last_reset[PIM_MSDP_PEER_LAST_RESET_STR]; + char last_reset[PIM_MSDP_PEER_LAST_RESET_STR]; - /* packet stats */ - uint32_t ka_tx_cnt; - uint32_t sa_tx_cnt; - uint32_t ka_rx_cnt; - uint32_t sa_rx_cnt; - uint32_t unk_rx_cnt; + /* packet stats */ + uint32_t ka_tx_cnt; + uint32_t sa_tx_cnt; + uint32_t ka_rx_cnt; + uint32_t sa_rx_cnt; + uint32_t unk_rx_cnt; - /* timestamps */ - int64_t uptime; + /* timestamps */ + int64_t uptime; }; struct pim_msdp_mg_mbr { - struct in_addr mbr_ip; - struct pim_msdp_peer *mp; + struct in_addr mbr_ip; + struct pim_msdp_peer *mp; }; /* PIM MSDP mesh-group */ struct pim_msdp_mg { - char *mesh_group_name; - struct in_addr src_ip; - uint32_t mbr_cnt; - struct list *mbr_list; + char *mesh_group_name; + struct in_addr src_ip; + uint32_t mbr_cnt; + struct list *mbr_list; }; enum pim_msdp_flags { - PIM_MSDPF_NONE = 0, - PIM_MSDPF_ENABLE = (1 << 0), - PIM_MSDPF_LISTENER = (1 << 1) + PIM_MSDPF_NONE = 0, + PIM_MSDPF_ENABLE = (1 << 0), + PIM_MSDPF_LISTENER = (1 << 1) }; struct pim_msdp_listener { - int fd; - union sockunion su; - struct thread *thread; + int fd; + union sockunion su; + struct thread *thread; }; struct pim_msdp { - enum pim_msdp_flags flags; - struct thread_master *master; - struct pim_msdp_listener listener; - uint32_t rejected_accepts; + enum pim_msdp_flags flags; + struct thread_master *master; + struct pim_msdp_listener listener; + uint32_t rejected_accepts; - /* MSDP peer info */ - struct hash *peer_hash; - struct list *peer_list; + /* MSDP peer info */ + struct hash *peer_hash; + struct list *peer_list; - /* MSDP active-source info */ +/* MSDP active-source info */ #define PIM_MSDP_SA_ADVERTISMENT_TIME 60 - struct thread *sa_adv_timer; // 5.6 - struct hash *sa_hash; - struct list *sa_list; - uint32_t local_cnt; + struct thread *sa_adv_timer; // 5.6 + struct hash *sa_hash; + struct list *sa_list; + uint32_t local_cnt; - /* keep a scratch pad for building SA TLVs */ - struct stream *work_obuf; + /* keep a scratch pad for building SA TLVs */ + struct stream *work_obuf; - struct in_addr originator_id; + struct in_addr originator_id; - /* currently only one mesh-group is supported - so just stash it here */ - struct pim_msdp_mg *mg; + /* currently only one mesh-group is supported - so just stash it here */ + struct pim_msdp_mg *mg; }; -#define PIM_MSDP_PEER_READ_ON(mp) \ - thread_add_read (msdp->master, pim_msdp_read, mp, mp->fd, &mp->t_read) +#define PIM_MSDP_PEER_READ_ON(mp) \ + thread_add_read(msdp->master, pim_msdp_read, mp, mp->fd, &mp->t_read) -#define PIM_MSDP_PEER_WRITE_ON(mp) \ - thread_add_write (msdp->master, pim_msdp_write, mp, mp->fd, &mp->t_write) +#define PIM_MSDP_PEER_WRITE_ON(mp) \ + thread_add_write(msdp->master, pim_msdp_write, mp, mp->fd, &mp->t_write) #define PIM_MSDP_PEER_READ_OFF(mp) THREAD_READ_OFF(mp->t_read) #define PIM_MSDP_PEER_WRITE_OFF(mp) THREAD_WRITE_OFF(mp->t_write) @@ -208,28 +214,36 @@ struct pim_msdp { extern struct pim_msdp *msdp; void pim_msdp_init(struct thread_master *master); void pim_msdp_exit(void); -enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer, struct in_addr local, const char *mesh_group_name, struct pim_msdp_peer **mp_p); +enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer, struct in_addr local, + const char *mesh_group_name, + struct pim_msdp_peer **mp_p); enum pim_msdp_err pim_msdp_peer_del(struct in_addr peer_addr); -char *pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, int buf_size); +char *pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, + int buf_size); struct pim_msdp_peer *pim_msdp_peer_find(struct in_addr peer_addr); void pim_msdp_peer_established(struct pim_msdp_peer *mp); void pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp); void pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state); void pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str); int pim_msdp_write(struct thread *thread); -char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, bool long_format); +char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, + bool long_format); int pim_msdp_config_write(struct vty *vty); void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp); -void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, struct in_addr rp); +void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, + struct in_addr rp); void pim_msdp_sa_local_update(struct pim_upstream *up); void pim_msdp_sa_local_del(struct prefix_sg *sg); void pim_msdp_i_am_rp_changed(void); bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp); void pim_msdp_up_join_state_changed(struct pim_upstream *xg_up); void pim_msdp_up_del(struct prefix_sg *sg); -enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name, struct in_addr mbr_ip); -enum pim_msdp_err pim_msdp_mg_mbr_del(const char *mesh_group_name, struct in_addr mbr_ip); +enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name, + struct in_addr mbr_ip); +enum pim_msdp_err pim_msdp_mg_mbr_del(const char *mesh_group_name, + struct in_addr mbr_ip); enum pim_msdp_err pim_msdp_mg_src_del(const char *mesh_group_name); -enum pim_msdp_err pim_msdp_mg_src_add(const char *mesh_group_name, struct in_addr src_ip); +enum pim_msdp_err pim_msdp_mg_src_add(const char *mesh_group_name, + struct in_addr src_ip); enum pim_msdp_err pim_msdp_mg_del(const char *mesh_group_name); #endif diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c index 0a8679336..01ce293e3 100644 --- a/pimd/pim_msdp_packet.c +++ b/pimd/pim_msdp_packet.c @@ -31,665 +31,661 @@ #include "pim_msdp_packet.h" #include "pim_msdp_socket.h" -static char * -pim_msdp_pkt_type_dump(enum pim_msdp_tlv type, char *buf, int buf_size) +static char *pim_msdp_pkt_type_dump(enum pim_msdp_tlv type, char *buf, + int buf_size) { - switch (type) { - case PIM_MSDP_V4_SOURCE_ACTIVE: - snprintf(buf, buf_size, "%s", "SA"); - break; - case PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST: - snprintf(buf, buf_size, "%s", "SA_REQ"); - break; - case PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE: - snprintf(buf, buf_size, "%s", "SA_RESP"); - break; - case PIM_MSDP_KEEPALIVE: - snprintf(buf, buf_size, "%s", "KA"); - break; - case PIM_MSDP_RESERVED: - snprintf(buf, buf_size, "%s", "RSVD"); - break; - case PIM_MSDP_TRACEROUTE_PROGRESS: - snprintf(buf, buf_size, "%s", "TRACE_PROG"); - break; - case PIM_MSDP_TRACEROUTE_REPLY: - snprintf(buf, buf_size, "%s", "TRACE_REPLY"); - break; - default: - snprintf(buf, buf_size, "UNK-%d", type); - } - return buf; + switch (type) { + case PIM_MSDP_V4_SOURCE_ACTIVE: + snprintf(buf, buf_size, "%s", "SA"); + break; + case PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST: + snprintf(buf, buf_size, "%s", "SA_REQ"); + break; + case PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE: + snprintf(buf, buf_size, "%s", "SA_RESP"); + break; + case PIM_MSDP_KEEPALIVE: + snprintf(buf, buf_size, "%s", "KA"); + break; + case PIM_MSDP_RESERVED: + snprintf(buf, buf_size, "%s", "RSVD"); + break; + case PIM_MSDP_TRACEROUTE_PROGRESS: + snprintf(buf, buf_size, "%s", "TRACE_PROG"); + break; + case PIM_MSDP_TRACEROUTE_REPLY: + snprintf(buf, buf_size, "%s", "TRACE_REPLY"); + break; + default: + snprintf(buf, buf_size, "UNK-%d", type); + } + return buf; } -static void -pim_msdp_pkt_sa_dump_one(struct stream *s) +static void pim_msdp_pkt_sa_dump_one(struct stream *s) { - struct prefix_sg sg; + struct prefix_sg sg; - /* just throw away the three reserved bytes */ - stream_get3(s); - /* throw away the prefix length also */ - stream_getc(s); + /* just throw away the three reserved bytes */ + stream_get3(s); + /* throw away the prefix length also */ + stream_getc(s); - memset(&sg, 0, sizeof (struct prefix_sg)); - sg.grp.s_addr = stream_get_ipv4(s); - sg.src.s_addr = stream_get_ipv4(s); + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.grp.s_addr = stream_get_ipv4(s); + sg.src.s_addr = stream_get_ipv4(s); - zlog_debug(" sg %s", pim_str_sg_dump(&sg)); + zlog_debug(" sg %s", pim_str_sg_dump(&sg)); } -static void -pim_msdp_pkt_sa_dump(struct stream *s) +static void pim_msdp_pkt_sa_dump(struct stream *s) { - int entry_cnt; - int i; - struct in_addr rp; /* Last RP address associated with this SA */ - - entry_cnt = stream_getc(s); - rp.s_addr = stream_get_ipv4(s); - - if (PIM_DEBUG_MSDP_PACKETS) { - char rp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<rp?>", rp, rp_str, sizeof(rp_str)); - zlog_debug(" entry_cnt %d rp %s", entry_cnt, rp_str); - } - - /* dump SAs */ - for (i = 0; i < entry_cnt; ++i) { - pim_msdp_pkt_sa_dump_one(s); - } + int entry_cnt; + int i; + struct in_addr rp; /* Last RP address associated with this SA */ + + entry_cnt = stream_getc(s); + rp.s_addr = stream_get_ipv4(s); + + if (PIM_DEBUG_MSDP_PACKETS) { + char rp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<rp?>", rp, rp_str, sizeof(rp_str)); + zlog_debug(" entry_cnt %d rp %s", entry_cnt, rp_str); + } + + /* dump SAs */ + for (i = 0; i < entry_cnt; ++i) { + pim_msdp_pkt_sa_dump_one(s); + } } -static void -pim_msdp_pkt_dump(struct pim_msdp_peer *mp, int type, int len, bool rx, - struct stream *s) +static void pim_msdp_pkt_dump(struct pim_msdp_peer *mp, int type, int len, + bool rx, struct stream *s) { - char type_str[PIM_MSDP_PKT_TYPE_STRLEN]; + char type_str[PIM_MSDP_PKT_TYPE_STRLEN]; - pim_msdp_pkt_type_dump(type, type_str, sizeof(type_str)); + pim_msdp_pkt_type_dump(type, type_str, sizeof(type_str)); - zlog_debug("MSDP peer %s pkt %s type %s len %d", - mp->key_str, rx?"rx":"tx", type_str, len); + zlog_debug("MSDP peer %s pkt %s type %s len %d", mp->key_str, + rx ? "rx" : "tx", type_str, len); - if (!s) { - return; - } + if (!s) { + return; + } - switch(type) { - case PIM_MSDP_V4_SOURCE_ACTIVE: - pim_msdp_pkt_sa_dump(s); - break; - default:; - } + switch (type) { + case PIM_MSDP_V4_SOURCE_ACTIVE: + pim_msdp_pkt_sa_dump(s); + break; + default:; + } } /* Check file descriptor whether connect is established. */ -static void -pim_msdp_connect_check(struct pim_msdp_peer *mp) +static void pim_msdp_connect_check(struct pim_msdp_peer *mp) { - int status; - socklen_t slen; - int ret; - - if (mp->state != PIM_MSDP_CONNECTING) { - /* if we are here it means we are not in a connecting or established state - * for now treat this as a fatal error */ - pim_msdp_peer_reset_tcp_conn(mp, "invalid-state"); - return; - } - - PIM_MSDP_PEER_READ_OFF(mp); - PIM_MSDP_PEER_WRITE_OFF(mp); - - /* Check file descriptor. */ - slen = sizeof(status); - ret = getsockopt(mp->fd, SOL_SOCKET, SO_ERROR, (void *)&status, &slen); - - /* If getsockopt is fail, this is fatal error. */ - if (ret < 0) { - zlog_err("can't get sockopt for nonblocking connect"); - pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); - return; - } - - /* When status is 0 then TCP connection is established. */ - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_connect_check %s", mp->key_str, status?"fail":"success"); - } - if (status == 0) { - pim_msdp_peer_established(mp); - } else { - pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); - } + int status; + socklen_t slen; + int ret; + + if (mp->state != PIM_MSDP_CONNECTING) { + /* if we are here it means we are not in a connecting or + * established state + * for now treat this as a fatal error */ + pim_msdp_peer_reset_tcp_conn(mp, "invalid-state"); + return; + } + + PIM_MSDP_PEER_READ_OFF(mp); + PIM_MSDP_PEER_WRITE_OFF(mp); + + /* Check file descriptor. */ + slen = sizeof(status); + ret = getsockopt(mp->fd, SOL_SOCKET, SO_ERROR, (void *)&status, &slen); + + /* If getsockopt is fail, this is fatal error. */ + if (ret < 0) { + zlog_err("can't get sockopt for nonblocking connect"); + pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); + return; + } + + /* When status is 0 then TCP connection is established. */ + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_connect_check %s", mp->key_str, + status ? "fail" : "success"); + } + if (status == 0) { + pim_msdp_peer_established(mp); + } else { + pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); + } } -static void -pim_msdp_pkt_delete(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_delete(struct pim_msdp_peer *mp) { - stream_free(stream_fifo_pop(mp->obuf)); + stream_free(stream_fifo_pop(mp->obuf)); } -static void -pim_msdp_pkt_add(struct pim_msdp_peer *mp, struct stream *s) +static void pim_msdp_pkt_add(struct pim_msdp_peer *mp, struct stream *s) { - stream_fifo_push(mp->obuf, s); + stream_fifo_push(mp->obuf, s); } -static void -pim_msdp_write_proceed_actions(struct pim_msdp_peer *mp) +static void pim_msdp_write_proceed_actions(struct pim_msdp_peer *mp) { - if (stream_fifo_head(mp->obuf)) { - PIM_MSDP_PEER_WRITE_ON(mp); - } + if (stream_fifo_head(mp->obuf)) { + PIM_MSDP_PEER_WRITE_ON(mp); + } } -int -pim_msdp_write(struct thread *thread) +int pim_msdp_write(struct thread *thread) { - struct pim_msdp_peer *mp; - struct stream *s; - int num; - enum pim_msdp_tlv type; - int len; - int work_cnt = 0; - int work_max_cnt = 100; - - mp = THREAD_ARG(thread); - mp->t_write = NULL; - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_write", mp->key_str); - } - if (mp->fd < 0) { - return -1; - } - - /* check if TCP connection is established */ - if (mp->state != PIM_MSDP_ESTABLISHED) { - pim_msdp_connect_check(mp); - return 0; - } - - s = stream_fifo_head(mp->obuf); - if (!s) { - pim_msdp_write_proceed_actions(mp); - return 0; - } - - sockopt_cork(mp->fd, 1); - - /* Nonblocking write until TCP output buffer is full */ - do - { - int writenum; - - /* Number of bytes to be sent */ - writenum = stream_get_endp(s) - stream_get_getp(s); - - /* Call write() system call */ - num = write(mp->fd, STREAM_PNT(s), writenum); - if (num < 0) { - /* write failed either retry needed or error */ - if (ERRNO_IO_RETRY(errno)) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_write io retry", mp->key_str); - } - break; - } - - pim_msdp_peer_reset_tcp_conn(mp, "pkt-tx-failed"); - return 0; - } - - if (num != writenum) { - /* Partial write */ - stream_forward_getp(s, num); - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_partial_write", mp->key_str); - } - break; - } - - /* Retrieve msdp packet type. */ - stream_set_getp(s,0); - type = stream_getc(s); - len = stream_getw(s); - switch (type) - { - case PIM_MSDP_KEEPALIVE: - mp->ka_tx_cnt++; - break; - case PIM_MSDP_V4_SOURCE_ACTIVE: - mp->sa_tx_cnt++; - break; - default:; - } - if (PIM_DEBUG_MSDP_PACKETS) { - pim_msdp_pkt_dump(mp, type, len, false /*rx*/, s); - } - - /* packet sent delete it. */ - pim_msdp_pkt_delete(mp); - - ++work_cnt; - /* may need to pause if we have done too much work in this - * loop */ - if (work_cnt >= work_max_cnt) { - break; - } - } while ((s = stream_fifo_head(mp->obuf)) != NULL); - pim_msdp_write_proceed_actions(mp); - - sockopt_cork(mp->fd, 0); - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_write wrote %d packets", mp->key_str, work_cnt); - } - - return 0; + struct pim_msdp_peer *mp; + struct stream *s; + int num; + enum pim_msdp_tlv type; + int len; + int work_cnt = 0; + int work_max_cnt = 100; + + mp = THREAD_ARG(thread); + mp->t_write = NULL; + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_msdp_write", mp->key_str); + } + if (mp->fd < 0) { + return -1; + } + + /* check if TCP connection is established */ + if (mp->state != PIM_MSDP_ESTABLISHED) { + pim_msdp_connect_check(mp); + return 0; + } + + s = stream_fifo_head(mp->obuf); + if (!s) { + pim_msdp_write_proceed_actions(mp); + return 0; + } + + sockopt_cork(mp->fd, 1); + + /* Nonblocking write until TCP output buffer is full */ + do { + int writenum; + + /* Number of bytes to be sent */ + writenum = stream_get_endp(s) - stream_get_getp(s); + + /* Call write() system call */ + num = write(mp->fd, STREAM_PNT(s), writenum); + if (num < 0) { + /* write failed either retry needed or error */ + if (ERRNO_IO_RETRY(errno)) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug( + "MSDP peer %s pim_msdp_write io retry", + mp->key_str); + } + break; + } + + pim_msdp_peer_reset_tcp_conn(mp, "pkt-tx-failed"); + return 0; + } + + if (num != writenum) { + /* Partial write */ + stream_forward_getp(s, num); + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug( + "MSDP peer %s pim_msdp_partial_write", + mp->key_str); + } + break; + } + + /* Retrieve msdp packet type. */ + stream_set_getp(s, 0); + type = stream_getc(s); + len = stream_getw(s); + switch (type) { + case PIM_MSDP_KEEPALIVE: + mp->ka_tx_cnt++; + break; + case PIM_MSDP_V4_SOURCE_ACTIVE: + mp->sa_tx_cnt++; + break; + default:; + } + if (PIM_DEBUG_MSDP_PACKETS) { + pim_msdp_pkt_dump(mp, type, len, false /*rx*/, s); + } + + /* packet sent delete it. */ + pim_msdp_pkt_delete(mp); + + ++work_cnt; + /* may need to pause if we have done too much work in this + * loop */ + if (work_cnt >= work_max_cnt) { + break; + } + } while ((s = stream_fifo_head(mp->obuf)) != NULL); + pim_msdp_write_proceed_actions(mp); + + sockopt_cork(mp->fd, 0); + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_msdp_write wrote %d packets", + mp->key_str, work_cnt); + } + + return 0; } -static void -pim_msdp_pkt_send(struct pim_msdp_peer *mp, struct stream *s) +static void pim_msdp_pkt_send(struct pim_msdp_peer *mp, struct stream *s) { - /* Add packet to the end of list. */ - pim_msdp_pkt_add(mp, s); + /* Add packet to the end of list. */ + pim_msdp_pkt_add(mp, s); - PIM_MSDP_PEER_WRITE_ON(mp); + PIM_MSDP_PEER_WRITE_ON(mp); } -void -pim_msdp_pkt_ka_tx(struct pim_msdp_peer *mp) +void pim_msdp_pkt_ka_tx(struct pim_msdp_peer *mp) { - struct stream *s; + struct stream *s; - if (mp->state != PIM_MSDP_ESTABLISHED) { - /* don't tx anything unless a session is established */ - return; - } - s = stream_new(PIM_MSDP_KA_TLV_MAX_SIZE); - stream_putc(s, PIM_MSDP_KEEPALIVE); - stream_putw(s, PIM_MSDP_KA_TLV_MAX_SIZE); + if (mp->state != PIM_MSDP_ESTABLISHED) { + /* don't tx anything unless a session is established */ + return; + } + s = stream_new(PIM_MSDP_KA_TLV_MAX_SIZE); + stream_putc(s, PIM_MSDP_KEEPALIVE); + stream_putw(s, PIM_MSDP_KA_TLV_MAX_SIZE); - pim_msdp_pkt_send(mp, s); + pim_msdp_pkt_send(mp, s); } -static void -pim_msdp_pkt_sa_push_to_one_peer(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_sa_push_to_one_peer(struct pim_msdp_peer *mp) { - struct stream *s; - - if (mp->state != PIM_MSDP_ESTABLISHED) { - /* don't tx anything unless a session is established */ - return; - } - s = stream_dup(msdp->work_obuf); - if (s) { - pim_msdp_pkt_send(mp, s); - mp->flags |= PIM_MSDP_PEERF_SA_JUST_SENT; - } + struct stream *s; + + if (mp->state != PIM_MSDP_ESTABLISHED) { + /* don't tx anything unless a session is established */ + return; + } + s = stream_dup(msdp->work_obuf); + if (s) { + pim_msdp_pkt_send(mp, s); + mp->flags |= PIM_MSDP_PEERF_SA_JUST_SENT; + } } /* push the stream into the obuf fifo of all the peers */ -static void -pim_msdp_pkt_sa_push(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_sa_push(struct pim_msdp_peer *mp) { - struct listnode *mpnode; - - if (mp) { - pim_msdp_pkt_sa_push_to_one_peer(mp); - } else { - for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_pkt_sa_push", mp->key_str); - } - pim_msdp_pkt_sa_push_to_one_peer(mp); - } - } + struct listnode *mpnode; + + if (mp) { + pim_msdp_pkt_sa_push_to_one_peer(mp); + } else { + for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_msdp_pkt_sa_push", + mp->key_str); + } + pim_msdp_pkt_sa_push_to_one_peer(mp); + } + } } -static int -pim_msdp_pkt_sa_fill_hdr(int local_cnt) +static int pim_msdp_pkt_sa_fill_hdr(int local_cnt) { - int curr_tlv_ecnt; - - stream_reset(msdp->work_obuf); - curr_tlv_ecnt = local_cnt>PIM_MSDP_SA_MAX_ENTRY_CNT?PIM_MSDP_SA_MAX_ENTRY_CNT:local_cnt; - local_cnt -= curr_tlv_ecnt; - stream_putc(msdp->work_obuf, PIM_MSDP_V4_SOURCE_ACTIVE); - stream_putw(msdp->work_obuf, PIM_MSDP_SA_ENTRY_CNT2SIZE(curr_tlv_ecnt)); - stream_putc(msdp->work_obuf, curr_tlv_ecnt); - stream_put_ipv4(msdp->work_obuf, msdp->originator_id.s_addr); - - return local_cnt; + int curr_tlv_ecnt; + + stream_reset(msdp->work_obuf); + curr_tlv_ecnt = local_cnt > PIM_MSDP_SA_MAX_ENTRY_CNT + ? PIM_MSDP_SA_MAX_ENTRY_CNT + : local_cnt; + local_cnt -= curr_tlv_ecnt; + stream_putc(msdp->work_obuf, PIM_MSDP_V4_SOURCE_ACTIVE); + stream_putw(msdp->work_obuf, PIM_MSDP_SA_ENTRY_CNT2SIZE(curr_tlv_ecnt)); + stream_putc(msdp->work_obuf, curr_tlv_ecnt); + stream_put_ipv4(msdp->work_obuf, msdp->originator_id.s_addr); + + return local_cnt; } -static void -pim_msdp_pkt_sa_fill_one(struct pim_msdp_sa *sa) +static void pim_msdp_pkt_sa_fill_one(struct pim_msdp_sa *sa) { - stream_put3(msdp->work_obuf, 0 /* reserved */); - stream_putc(msdp->work_obuf, 32 /* sprefix len */); - stream_put_ipv4(msdp->work_obuf, sa->sg.grp.s_addr); - stream_put_ipv4(msdp->work_obuf, sa->sg.src.s_addr); + stream_put3(msdp->work_obuf, 0 /* reserved */); + stream_putc(msdp->work_obuf, 32 /* sprefix len */); + stream_put_ipv4(msdp->work_obuf, sa->sg.grp.s_addr); + stream_put_ipv4(msdp->work_obuf, sa->sg.src.s_addr); } -static void -pim_msdp_pkt_sa_gen(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_sa_gen(struct pim_msdp_peer *mp) { - struct listnode *sanode; - struct pim_msdp_sa *sa; - int sa_count; - int local_cnt = msdp->local_cnt; - - sa_count = 0; - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug(" sa gen %d", local_cnt); - } - - local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); - - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { - /* current implementation of MSDP is for anycast i.e. full mesh. so - * no re-forwarding of SAs that we learnt from other peers */ - continue; - } - /* add sa into scratch pad */ - pim_msdp_pkt_sa_fill_one(sa); - ++sa_count; - if (sa_count >= PIM_MSDP_SA_MAX_ENTRY_CNT) { - pim_msdp_pkt_sa_push(mp); - /* reset headers */ - sa_count = 0; - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug(" sa gen for remainder %d", local_cnt); - } - local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); - } - } - - if (sa_count) { - pim_msdp_pkt_sa_push(mp); - } - return; + struct listnode *sanode; + struct pim_msdp_sa *sa; + int sa_count; + int local_cnt = msdp->local_cnt; + + sa_count = 0; + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug(" sa gen %d", local_cnt); + } + + local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); + + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { + /* current implementation of MSDP is for anycast i.e. + * full mesh. so + * no re-forwarding of SAs that we learnt from other + * peers */ + continue; + } + /* add sa into scratch pad */ + pim_msdp_pkt_sa_fill_one(sa); + ++sa_count; + if (sa_count >= PIM_MSDP_SA_MAX_ENTRY_CNT) { + pim_msdp_pkt_sa_push(mp); + /* reset headers */ + sa_count = 0; + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug(" sa gen for remainder %d", + local_cnt); + } + local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); + } + } + + if (sa_count) { + pim_msdp_pkt_sa_push(mp); + } + return; } -static void -pim_msdp_pkt_sa_tx_done(void) +static void pim_msdp_pkt_sa_tx_done(void) { - struct listnode *mpnode; - struct pim_msdp_peer *mp; - - /* if SA were sent to the peers we restart ka timer and avoid - * unnecessary ka noise */ - for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { - if (mp->flags & PIM_MSDP_PEERF_SA_JUST_SENT) { - mp->flags &= ~PIM_MSDP_PEERF_SA_JUST_SENT; - pim_msdp_peer_pkt_txed(mp); - } - } + struct listnode *mpnode; + struct pim_msdp_peer *mp; + + /* if SA were sent to the peers we restart ka timer and avoid + * unnecessary ka noise */ + for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { + if (mp->flags & PIM_MSDP_PEERF_SA_JUST_SENT) { + mp->flags &= ~PIM_MSDP_PEERF_SA_JUST_SENT; + pim_msdp_peer_pkt_txed(mp); + } + } } -void -pim_msdp_pkt_sa_tx(void) +void pim_msdp_pkt_sa_tx(void) { - pim_msdp_pkt_sa_gen(NULL /* mp */); - pim_msdp_pkt_sa_tx_done(); + pim_msdp_pkt_sa_gen(NULL /* mp */); + pim_msdp_pkt_sa_tx_done(); } -void -pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa *sa) +void pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa *sa) { - pim_msdp_pkt_sa_fill_hdr(1 /* cnt */); - pim_msdp_pkt_sa_fill_one(sa); - pim_msdp_pkt_sa_push(NULL); - pim_msdp_pkt_sa_tx_done(); + pim_msdp_pkt_sa_fill_hdr(1 /* cnt */); + pim_msdp_pkt_sa_fill_one(sa); + pim_msdp_pkt_sa_push(NULL); + pim_msdp_pkt_sa_tx_done(); } /* when a connection is first established we push all SAs immediately */ -void -pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer *mp) +void pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer *mp) { - pim_msdp_pkt_sa_gen(mp); - pim_msdp_pkt_sa_tx_done(); + pim_msdp_pkt_sa_gen(mp); + pim_msdp_pkt_sa_tx_done(); } -static void -pim_msdp_pkt_rxed_with_fatal_error(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_rxed_with_fatal_error(struct pim_msdp_peer *mp) { - pim_msdp_peer_reset_tcp_conn(mp, "invalid-pkt-rx"); + pim_msdp_peer_reset_tcp_conn(mp, "invalid-pkt-rx"); } -static void -pim_msdp_pkt_ka_rx(struct pim_msdp_peer *mp, int len) +static void pim_msdp_pkt_ka_rx(struct pim_msdp_peer *mp, int len) { - mp->ka_rx_cnt++; - if (len != PIM_MSDP_KA_TLV_MAX_SIZE) { - pim_msdp_pkt_rxed_with_fatal_error(mp); - return; - } - pim_msdp_peer_pkt_rxed(mp); + mp->ka_rx_cnt++; + if (len != PIM_MSDP_KA_TLV_MAX_SIZE) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + return; + } + pim_msdp_peer_pkt_rxed(mp); } -static void -pim_msdp_pkt_sa_rx_one(struct pim_msdp_peer *mp, struct in_addr rp) +static void pim_msdp_pkt_sa_rx_one(struct pim_msdp_peer *mp, struct in_addr rp) { - int prefix_len; - struct prefix_sg sg; - - /* just throw away the three reserved bytes */ - stream_get3(mp->ibuf); - prefix_len = stream_getc(mp->ibuf); - - memset(&sg, 0, sizeof (struct prefix_sg)); - sg.grp.s_addr = stream_get_ipv4(mp->ibuf); - sg.src.s_addr = stream_get_ipv4(mp->ibuf); - - if (prefix_len != 32) { - /* ignore SA update if the prefix length is not 32 */ - zlog_err("rxed sa update with invalid prefix length %d", prefix_len); - return; - } - if (PIM_DEBUG_MSDP_PACKETS) { - zlog_debug(" sg %s", pim_str_sg_dump(&sg)); - } - pim_msdp_sa_ref(mp, &sg, rp); + int prefix_len; + struct prefix_sg sg; + + /* just throw away the three reserved bytes */ + stream_get3(mp->ibuf); + prefix_len = stream_getc(mp->ibuf); + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.grp.s_addr = stream_get_ipv4(mp->ibuf); + sg.src.s_addr = stream_get_ipv4(mp->ibuf); + + if (prefix_len != 32) { + /* ignore SA update if the prefix length is not 32 */ + zlog_err("rxed sa update with invalid prefix length %d", + prefix_len); + return; + } + if (PIM_DEBUG_MSDP_PACKETS) { + zlog_debug(" sg %s", pim_str_sg_dump(&sg)); + } + pim_msdp_sa_ref(mp, &sg, rp); } -static void -pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len) +static void pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len) { - int entry_cnt; - int i; - struct in_addr rp; /* Last RP address associated with this SA */ - - mp->sa_rx_cnt++; - - if (len < PIM_MSDP_SA_TLV_MIN_SIZE) { - pim_msdp_pkt_rxed_with_fatal_error(mp); - return; - } - - entry_cnt = stream_getc(mp->ibuf); - /* some vendors include the actual multicast data in the tlv (at the end). - * we will ignore such data. in the future we may consider pushing it down - * the RPT */ - if (len < PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt)) { - pim_msdp_pkt_rxed_with_fatal_error(mp); - return; - } - rp.s_addr = stream_get_ipv4(mp->ibuf); - - if (PIM_DEBUG_MSDP_PACKETS) { - char rp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<rp?>", rp, rp_str, sizeof(rp_str)); - zlog_debug(" entry_cnt %d rp %s", entry_cnt, rp_str); - } - - if (!pim_msdp_peer_rpf_check(mp, rp)) { - /* if peer-RPF check fails don't process the packet any further */ - if (PIM_DEBUG_MSDP_PACKETS) { - zlog_debug(" peer RPF check failed"); - } - return; - } - - pim_msdp_peer_pkt_rxed(mp); - - /* update SA cache */ - for (i = 0; i < entry_cnt; ++i) { - pim_msdp_pkt_sa_rx_one(mp, rp); - } + int entry_cnt; + int i; + struct in_addr rp; /* Last RP address associated with this SA */ + + mp->sa_rx_cnt++; + + if (len < PIM_MSDP_SA_TLV_MIN_SIZE) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + return; + } + + entry_cnt = stream_getc(mp->ibuf); + /* some vendors include the actual multicast data in the tlv (at the + * end). + * we will ignore such data. in the future we may consider pushing it + * down + * the RPT */ + if (len < PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt)) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + return; + } + rp.s_addr = stream_get_ipv4(mp->ibuf); + + if (PIM_DEBUG_MSDP_PACKETS) { + char rp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<rp?>", rp, rp_str, sizeof(rp_str)); + zlog_debug(" entry_cnt %d rp %s", entry_cnt, rp_str); + } + + if (!pim_msdp_peer_rpf_check(mp, rp)) { + /* if peer-RPF check fails don't process the packet any further + */ + if (PIM_DEBUG_MSDP_PACKETS) { + zlog_debug(" peer RPF check failed"); + } + return; + } + + pim_msdp_peer_pkt_rxed(mp); + + /* update SA cache */ + for (i = 0; i < entry_cnt; ++i) { + pim_msdp_pkt_sa_rx_one(mp, rp); + } } -static void -pim_msdp_pkt_rx(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_rx(struct pim_msdp_peer *mp) { - enum pim_msdp_tlv type; - int len; - - /* re-read type and len */ - type = stream_getc_from(mp->ibuf, 0); - len = stream_getw_from(mp->ibuf, 1); - if (len < PIM_MSDP_HEADER_SIZE) { - pim_msdp_pkt_rxed_with_fatal_error(mp); - return; - } - - if (len > PIM_MSDP_SA_TLV_MAX_SIZE) { - /* if tlv size if greater than max just ignore the tlv */ - return; - } - - if (PIM_DEBUG_MSDP_PACKETS) { - pim_msdp_pkt_dump(mp, type, len, true /*rx*/, NULL /*s*/); - } - - switch(type) { - case PIM_MSDP_KEEPALIVE: - pim_msdp_pkt_ka_rx(mp, len); - break; - case PIM_MSDP_V4_SOURCE_ACTIVE: - mp->sa_rx_cnt++; - pim_msdp_pkt_sa_rx(mp, len); - break; - default: - mp->unk_rx_cnt++; - } + enum pim_msdp_tlv type; + int len; + + /* re-read type and len */ + type = stream_getc_from(mp->ibuf, 0); + len = stream_getw_from(mp->ibuf, 1); + if (len < PIM_MSDP_HEADER_SIZE) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + return; + } + + if (len > PIM_MSDP_SA_TLV_MAX_SIZE) { + /* if tlv size if greater than max just ignore the tlv */ + return; + } + + if (PIM_DEBUG_MSDP_PACKETS) { + pim_msdp_pkt_dump(mp, type, len, true /*rx*/, NULL /*s*/); + } + + switch (type) { + case PIM_MSDP_KEEPALIVE: + pim_msdp_pkt_ka_rx(mp, len); + break; + case PIM_MSDP_V4_SOURCE_ACTIVE: + mp->sa_rx_cnt++; + pim_msdp_pkt_sa_rx(mp, len); + break; + default: + mp->unk_rx_cnt++; + } } /* pim msdp read utility function. */ -static int -pim_msdp_read_packet(struct pim_msdp_peer *mp) +static int pim_msdp_read_packet(struct pim_msdp_peer *mp) { - int nbytes; - int readsize; - int old_endp; - int new_endp; - - old_endp = stream_get_endp(mp->ibuf); - readsize = mp->packet_size - old_endp; - if (!readsize) { - return 0; - } - - /* Read packet from fd */ - nbytes = stream_read_try(mp->ibuf, mp->fd, readsize); - new_endp = stream_get_endp(mp->ibuf); - if (nbytes < 0) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s read failed %d", mp->key_str, nbytes); - } - if (nbytes == -2) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_read io retry old_end: %d new_end: %d", mp->key_str, old_endp, new_endp); - } - /* transient error retry */ - return -1; - } - pim_msdp_pkt_rxed_with_fatal_error(mp); - return -1; - } - - if (!nbytes) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s read failed %d", mp->key_str, nbytes); - } - pim_msdp_peer_reset_tcp_conn(mp, "peer-down"); - return -1; - } - - /* We read partial packet. */ - if (stream_get_endp(mp->ibuf) != mp->packet_size) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s read partial len %d old_endp %d new_endp %d", mp->key_str, mp->packet_size, old_endp, new_endp); - } - return -1; - } - - return 0; + int nbytes; + int readsize; + int old_endp; + int new_endp; + + old_endp = stream_get_endp(mp->ibuf); + readsize = mp->packet_size - old_endp; + if (!readsize) { + return 0; + } + + /* Read packet from fd */ + nbytes = stream_read_try(mp->ibuf, mp->fd, readsize); + new_endp = stream_get_endp(mp->ibuf); + if (nbytes < 0) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s read failed %d", mp->key_str, + nbytes); + } + if (nbytes == -2) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug( + "MSDP peer %s pim_msdp_read io retry old_end: %d new_end: %d", + mp->key_str, old_endp, new_endp); + } + /* transient error retry */ + return -1; + } + pim_msdp_pkt_rxed_with_fatal_error(mp); + return -1; + } + + if (!nbytes) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s read failed %d", mp->key_str, + nbytes); + } + pim_msdp_peer_reset_tcp_conn(mp, "peer-down"); + return -1; + } + + /* We read partial packet. */ + if (stream_get_endp(mp->ibuf) != mp->packet_size) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug( + "MSDP peer %s read partial len %d old_endp %d new_endp %d", + mp->key_str, mp->packet_size, old_endp, + new_endp); + } + return -1; + } + + return 0; } -int -pim_msdp_read(struct thread *thread) +int pim_msdp_read(struct thread *thread) { - struct pim_msdp_peer *mp; - int rc; - uint32_t len; - - mp = THREAD_ARG(thread); - mp->t_read = NULL; - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_read", mp->key_str); - } - - if (mp->fd < 0) { - return -1; - } - - /* check if TCP connection is established */ - if (mp->state != PIM_MSDP_ESTABLISHED) { - pim_msdp_connect_check(mp); - return 0; - } - - PIM_MSDP_PEER_READ_ON(mp); - - if (!mp->packet_size) { - mp->packet_size = PIM_MSDP_HEADER_SIZE; - } - - if (stream_get_endp(mp->ibuf) < PIM_MSDP_HEADER_SIZE) { - /* start by reading the TLV header */ - rc = pim_msdp_read_packet(mp); - if (rc < 0) { - goto pim_msdp_read_end; - } - - /* Find TLV type and len */ - stream_getc(mp->ibuf); - len = stream_getw(mp->ibuf); - if (len < PIM_MSDP_HEADER_SIZE) { - pim_msdp_pkt_rxed_with_fatal_error(mp); - goto pim_msdp_read_end; - } - /* read complete TLV */ - mp->packet_size = len; - } - - rc = pim_msdp_read_packet(mp); - if (rc < 0) { - goto pim_msdp_read_end; - } - - pim_msdp_pkt_rx(mp); - - /* reset input buffers and get ready for the next packet */ - mp->packet_size = 0; - stream_reset(mp->ibuf); + struct pim_msdp_peer *mp; + int rc; + uint32_t len; + + mp = THREAD_ARG(thread); + mp->t_read = NULL; + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_msdp_read", mp->key_str); + } + + if (mp->fd < 0) { + return -1; + } + + /* check if TCP connection is established */ + if (mp->state != PIM_MSDP_ESTABLISHED) { + pim_msdp_connect_check(mp); + return 0; + } + + PIM_MSDP_PEER_READ_ON(mp); + + if (!mp->packet_size) { + mp->packet_size = PIM_MSDP_HEADER_SIZE; + } + + if (stream_get_endp(mp->ibuf) < PIM_MSDP_HEADER_SIZE) { + /* start by reading the TLV header */ + rc = pim_msdp_read_packet(mp); + if (rc < 0) { + goto pim_msdp_read_end; + } + + /* Find TLV type and len */ + stream_getc(mp->ibuf); + len = stream_getw(mp->ibuf); + if (len < PIM_MSDP_HEADER_SIZE) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + goto pim_msdp_read_end; + } + /* read complete TLV */ + mp->packet_size = len; + } + + rc = pim_msdp_read_packet(mp); + if (rc < 0) { + goto pim_msdp_read_end; + } + + pim_msdp_pkt_rx(mp); + + /* reset input buffers and get ready for the next packet */ + mp->packet_size = 0; + stream_reset(mp->ibuf); pim_msdp_read_end: - return 0; + return 0; } diff --git a/pimd/pim_msdp_packet.h b/pimd/pim_msdp_packet.h index aa42bbfe4..986fa3b32 100644 --- a/pimd/pim_msdp_packet.h +++ b/pimd/pim_msdp_packet.h @@ -50,8 +50,8 @@ #define PIM_MSDP_SA_X_SIZE 8 #define PIM_MSDP_SA_ONE_ENTRY_SIZE 12 #define PIM_MSDP_SA_Y_SIZE(entry_cnt) (PIM_MSDP_SA_ONE_ENTRY_SIZE * entry_cnt) -#define PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt) (PIM_MSDP_SA_X_SIZE +\ - PIM_MSDP_SA_Y_SIZE(entry_cnt)) +#define PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt) \ + (PIM_MSDP_SA_X_SIZE + PIM_MSDP_SA_Y_SIZE(entry_cnt)) /* SA TLV has to have atleast only one entry in it so x=8 + y=12 */ #define PIM_MSDP_SA_TLV_MIN_SIZE PIM_MSDP_SA_ENTRY_CNT2SIZE(1) /* XXX: theoretically we can fix a max of 255 but that may result in packet diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c index 9662f054e..0ce097101 100644 --- a/pimd/pim_msdp_socket.c +++ b/pimd/pim_msdp_socket.c @@ -31,199 +31,207 @@ #include "pim_msdp_socket.h" /* increase socket send buffer size */ -static void -pim_msdp_update_sock_send_buffer_size (int fd) +static void pim_msdp_update_sock_send_buffer_size(int fd) { - int size = PIM_MSDP_SOCKET_SNDBUF_SIZE; - int optval; - socklen_t optlen = sizeof(optval); - - if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0) { - zlog_err("getsockopt of SO_SNDBUF failed %s\n", safe_strerror(errno)); - return; - } - - if (optval < size) { - if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0) { - zlog_err("Couldn't increase send buffer: %s\n", safe_strerror(errno)); - } - } + int size = PIM_MSDP_SOCKET_SNDBUF_SIZE; + int optval; + socklen_t optlen = sizeof(optval); + + if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0) { + zlog_err("getsockopt of SO_SNDBUF failed %s\n", + safe_strerror(errno)); + return; + } + + if (optval < size) { + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) + < 0) { + zlog_err("Couldn't increase send buffer: %s\n", + safe_strerror(errno)); + } + } } /* passive peer socket accept */ -static int -pim_msdp_sock_accept(struct thread *thread) +static int pim_msdp_sock_accept(struct thread *thread) { - union sockunion su; - struct pim_msdp_listener *listener = THREAD_ARG(thread); - int accept_sock; - int msdp_sock; - struct pim_msdp_peer *mp; - char buf[SU_ADDRSTRLEN]; - - sockunion_init(&su); - - /* re-register accept thread */ - accept_sock = THREAD_FD(thread); - if (accept_sock < 0) { - zlog_err ("accept_sock is negative value %d", accept_sock); - return -1; - } - listener->thread = NULL; - thread_add_read(master, pim_msdp_sock_accept, listener, accept_sock, - &listener->thread); - - /* accept client connection. */ - msdp_sock = sockunion_accept(accept_sock, &su); - if (msdp_sock < 0) { - zlog_err ("pim_msdp_sock_accept failed (%s)", safe_strerror (errno)); - return -1; - } - - /* see if have peer config for this */ - mp = pim_msdp_peer_find(su.sin.sin_addr); - if (!mp || !PIM_MSDP_PEER_IS_LISTENER(mp)) { - ++msdp->rejected_accepts; - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_err("msdp peer connection refused from %s", - sockunion2str(&su, buf, SU_ADDRSTRLEN)); - } - close(msdp_sock); - return -1; - } - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s accept success%s", mp->key_str, mp->fd>=0?"(dup)":""); - } - - /* if we have an existing connection we need to kill that one - * with this one */ - if (mp->fd >= 0) { - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_err("msdp peer new connection from %s stop old connection", - sockunion2str(&su, buf, SU_ADDRSTRLEN)); - } - pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); - } - mp->fd = msdp_sock; - set_nonblocking(mp->fd); - pim_msdp_update_sock_send_buffer_size(mp->fd); - pim_msdp_peer_established(mp); - return 0; + union sockunion su; + struct pim_msdp_listener *listener = THREAD_ARG(thread); + int accept_sock; + int msdp_sock; + struct pim_msdp_peer *mp; + char buf[SU_ADDRSTRLEN]; + + sockunion_init(&su); + + /* re-register accept thread */ + accept_sock = THREAD_FD(thread); + if (accept_sock < 0) { + zlog_err("accept_sock is negative value %d", accept_sock); + return -1; + } + listener->thread = NULL; + thread_add_read(master, pim_msdp_sock_accept, listener, accept_sock, + &listener->thread); + + /* accept client connection. */ + msdp_sock = sockunion_accept(accept_sock, &su); + if (msdp_sock < 0) { + zlog_err("pim_msdp_sock_accept failed (%s)", + safe_strerror(errno)); + return -1; + } + + /* see if have peer config for this */ + mp = pim_msdp_peer_find(su.sin.sin_addr); + if (!mp || !PIM_MSDP_PEER_IS_LISTENER(mp)) { + ++msdp->rejected_accepts; + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_err("msdp peer connection refused from %s", + sockunion2str(&su, buf, SU_ADDRSTRLEN)); + } + close(msdp_sock); + return -1; + } + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s accept success%s", mp->key_str, + mp->fd >= 0 ? "(dup)" : ""); + } + + /* if we have an existing connection we need to kill that one + * with this one */ + if (mp->fd >= 0) { + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_err( + "msdp peer new connection from %s stop old connection", + sockunion2str(&su, buf, SU_ADDRSTRLEN)); + } + pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); + } + mp->fd = msdp_sock; + set_nonblocking(mp->fd); + pim_msdp_update_sock_send_buffer_size(mp->fd); + pim_msdp_peer_established(mp); + return 0; } /* global listener for the MSDP well know TCP port */ -int -pim_msdp_sock_listen(void) +int pim_msdp_sock_listen(void) { - int sock; - int socklen; - struct sockaddr_in sin; - int rc; - struct pim_msdp_listener *listener = &msdp->listener; - - if (msdp->flags & PIM_MSDPF_LISTENER) { - /* listener already setup */ - return 0; - } - - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock < 0) { - zlog_err ("socket: %s", safe_strerror (errno)); - return sock; - } - - memset(&sin, 0, sizeof(struct sockaddr_in)); - sin.sin_family = AF_INET; - sin.sin_port = htons(PIM_MSDP_TCP_PORT); - socklen = sizeof(struct sockaddr_in); + int sock; + int socklen; + struct sockaddr_in sin; + int rc; + struct pim_msdp_listener *listener = &msdp->listener; + + if (msdp->flags & PIM_MSDPF_LISTENER) { + /* listener already setup */ + return 0; + } + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + zlog_err("socket: %s", safe_strerror(errno)); + return sock; + } + + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; + sin.sin_port = htons(PIM_MSDP_TCP_PORT); + socklen = sizeof(struct sockaddr_in); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin.sin_len = socklen; + sin.sin_len = socklen; #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - sockopt_reuseaddr(sock); - sockopt_reuseport(sock); - - if (pimd_privs.change(ZPRIVS_RAISE)) { - zlog_err ("pim_msdp_socket: could not raise privs, %s", - safe_strerror (errno)); - } - - /* bind to well known TCP port */ - rc = bind(sock, (struct sockaddr *)&sin, socklen); - - if (pimd_privs.change(ZPRIVS_LOWER)) { - zlog_err ("pim_msdp_socket: could not lower privs, %s", - safe_strerror (errno)); - } - - if (rc < 0) { - zlog_err ("pim_msdp_socket bind to port %d: %s", ntohs(sin.sin_port), safe_strerror (errno)); - close(sock); - return rc; - } - - rc = listen(sock, 3 /* backlog */); - if (rc < 0) { - zlog_err ("pim_msdp_socket listen: %s", safe_strerror (errno)); - close(sock); - return rc; - } - - /* add accept thread */ - listener->fd = sock; - memcpy(&listener->su, &sin, socklen); - listener->thread = NULL; - thread_add_read(msdp->master, pim_msdp_sock_accept, listener, sock, - &listener->thread); - - msdp->flags |= PIM_MSDPF_LISTENER; - return 0; + sockopt_reuseaddr(sock); + sockopt_reuseport(sock); + + if (pimd_privs.change(ZPRIVS_RAISE)) { + zlog_err("pim_msdp_socket: could not raise privs, %s", + safe_strerror(errno)); + } + + /* bind to well known TCP port */ + rc = bind(sock, (struct sockaddr *)&sin, socklen); + + if (pimd_privs.change(ZPRIVS_LOWER)) { + zlog_err("pim_msdp_socket: could not lower privs, %s", + safe_strerror(errno)); + } + + if (rc < 0) { + zlog_err("pim_msdp_socket bind to port %d: %s", + ntohs(sin.sin_port), safe_strerror(errno)); + close(sock); + return rc; + } + + rc = listen(sock, 3 /* backlog */); + if (rc < 0) { + zlog_err("pim_msdp_socket listen: %s", safe_strerror(errno)); + close(sock); + return rc; + } + + /* add accept thread */ + listener->fd = sock; + memcpy(&listener->su, &sin, socklen); + listener->thread = NULL; + thread_add_read(msdp->master, pim_msdp_sock_accept, listener, sock, + &listener->thread); + + msdp->flags |= PIM_MSDPF_LISTENER; + return 0; } /* active peer socket setup */ -int -pim_msdp_sock_connect(struct pim_msdp_peer *mp) +int pim_msdp_sock_connect(struct pim_msdp_peer *mp) { - int rc; - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s attempt connect%s", mp->key_str, mp->fd<0?"":"(dup)"); - } - - /* if we have an existing connection we need to kill that one - * with this one */ - if (mp->fd >= 0) { - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_err("msdp duplicate connect to %s nuke old connection", mp->key_str); - } - pim_msdp_peer_stop_tcp_conn(mp, false /* chg_state */); - } - - /* Make socket for the peer. */ - mp->fd = sockunion_socket(&mp->su_peer); - if (mp->fd < 0) { - zlog_err ("pim_msdp_socket socket failure: %s", safe_strerror (errno)); - return -1; - } - - set_nonblocking(mp->fd); - - /* Set socket send buffer size */ - pim_msdp_update_sock_send_buffer_size(mp->fd); - sockopt_reuseaddr(mp->fd); - sockopt_reuseport(mp->fd); - - /* source bind */ - rc = sockunion_bind(mp->fd, &mp->su_local, 0, &mp->su_local); - if (rc < 0) { - zlog_err ("pim_msdp_socket connect bind failure: %s", safe_strerror (errno)); - close(mp->fd); - mp->fd = -1; - return rc; - } - - /* Connect to the remote mp. */ - return (sockunion_connect(mp->fd, &mp->su_peer, htons(PIM_MSDP_TCP_PORT), 0)); + int rc; + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s attempt connect%s", mp->key_str, + mp->fd < 0 ? "" : "(dup)"); + } + + /* if we have an existing connection we need to kill that one + * with this one */ + if (mp->fd >= 0) { + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_err( + "msdp duplicate connect to %s nuke old connection", + mp->key_str); + } + pim_msdp_peer_stop_tcp_conn(mp, false /* chg_state */); + } + + /* Make socket for the peer. */ + mp->fd = sockunion_socket(&mp->su_peer); + if (mp->fd < 0) { + zlog_err("pim_msdp_socket socket failure: %s", + safe_strerror(errno)); + return -1; + } + + set_nonblocking(mp->fd); + + /* Set socket send buffer size */ + pim_msdp_update_sock_send_buffer_size(mp->fd); + sockopt_reuseaddr(mp->fd); + sockopt_reuseport(mp->fd); + + /* source bind */ + rc = sockunion_bind(mp->fd, &mp->su_local, 0, &mp->su_local); + if (rc < 0) { + zlog_err("pim_msdp_socket connect bind failure: %s", + safe_strerror(errno)); + close(mp->fd); + mp->fd = -1; + return rc; + } + + /* Connect to the remote mp. */ + return (sockunion_connect(mp->fd, &mp->su_peer, + htons(PIM_MSDP_TCP_PORT), 0)); } - diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index e077a8516..04f1f4846 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -37,197 +37,202 @@ #include "pim_register.h" #include "pim_jp_agg.h" -void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, uint8_t pim_msg_type) +void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, + uint8_t pim_msg_type) { - struct pim_msg_header *header = (struct pim_msg_header *)pim_msg; - - /* - * Write header - */ - header->ver = PIM_PROTO_VERSION; - header->type = pim_msg_type; - header->reserved = 0; - - - header->checksum = 0; - /* - * The checksum for Registers is done only on the first 8 bytes of the packet, - * including the PIM header and the next 4 bytes, excluding the data packet portion - */ - if (pim_msg_type == PIM_MSG_TYPE_REGISTER) - header->checksum = in_cksum (pim_msg, PIM_MSG_REGISTER_LEN); - else - header->checksum = in_cksum (pim_msg, pim_msg_size); + struct pim_msg_header *header = (struct pim_msg_header *)pim_msg; + + /* + * Write header + */ + header->ver = PIM_PROTO_VERSION; + header->type = pim_msg_type; + header->reserved = 0; + + + header->checksum = 0; + /* + * The checksum for Registers is done only on the first 8 bytes of the + * packet, + * including the PIM header and the next 4 bytes, excluding the data + * packet portion + */ + if (pim_msg_type == PIM_MSG_TYPE_REGISTER) + header->checksum = in_cksum(pim_msg, PIM_MSG_REGISTER_LEN); + else + header->checksum = in_cksum(pim_msg, pim_msg_size); } uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf, struct in_addr addr) { - buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ - buf[1] = '\0'; /* native encoding */ - memcpy(buf+2, &addr, sizeof(struct in_addr)); + buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ + buf[1] = '\0'; /* native encoding */ + memcpy(buf + 2, &addr, sizeof(struct in_addr)); - return buf + PIM_ENCODED_IPV4_UCAST_SIZE; + return buf + PIM_ENCODED_IPV4_UCAST_SIZE; } uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, struct in_addr addr) { - buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ - buf[1] = '\0'; /* native encoding */ - buf[2] = '\0'; /* reserved */ - buf[3] = 32; /* mask len */ - memcpy(buf+4, &addr, sizeof(struct in_addr)); + buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ + buf[1] = '\0'; /* native encoding */ + buf[2] = '\0'; /* reserved */ + buf[3] = 32; /* mask len */ + memcpy(buf + 4, &addr, sizeof(struct in_addr)); - return buf + PIM_ENCODED_IPV4_GROUP_SIZE; + return buf + PIM_ENCODED_IPV4_GROUP_SIZE; } -uint8_t * -pim_msg_addr_encode_ipv4_source(uint8_t *buf, - struct in_addr addr, uint8_t bits) +uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, struct in_addr addr, + uint8_t bits) { - buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ - buf[1] = '\0'; /* native encoding */ - buf[2] = bits; - buf[3] = 32; /* mask len */ - memcpy(buf+4, &addr, sizeof(struct in_addr)); + buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ + buf[1] = '\0'; /* native encoding */ + buf[2] = bits; + buf[3] = 32; /* mask len */ + memcpy(buf + 4, &addr, sizeof(struct in_addr)); - return buf + PIM_ENCODED_IPV4_SOURCE_SIZE; + return buf + PIM_ENCODED_IPV4_SOURCE_SIZE; } /* * For the given 'struct pim_jp_sources' list * determine the size_t it would take up. */ -size_t -pim_msg_get_jp_group_size (struct list *sources) +size_t pim_msg_get_jp_group_size(struct list *sources) { - struct pim_jp_sources *js; - size_t size = 0; - - size += sizeof (struct pim_encoded_group_ipv4); - size += 4; // Joined sources (2) + Pruned Sources (2) - - size += sizeof (struct pim_encoded_source_ipv4) * sources->count; - - js = listgetdata(listhead(sources)); - if (js && js->up->sg.src.s_addr == INADDR_ANY) - { - struct pim_upstream *child, *up; - struct listnode *up_node; - - up = js->up; - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: Considering (%s) children for (S,G,rpt) prune", - __PRETTY_FUNCTION__, up->sg_str); - - for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) - { - if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) - { - if (!pim_rpf_is_same(&up->rpf, &child->rpf)) - { - size += sizeof (struct pim_encoded_source_ipv4); - PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(child->flags); - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", - __PRETTY_FUNCTION__, up->sg_str, child->sg_str); - } - else - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)", - __PRETTY_FUNCTION__, up->sg_str, child->sg_str); - } - else if (pim_upstream_is_sg_rpt (child)) - { - if (pim_upstream_empty_inherited_olist (child)) - { - size += sizeof (struct pim_encoded_source_ipv4); - PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(child->flags); - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message", - __PRETTY_FUNCTION__, child->sg_str); - } - else if (!pim_rpf_is_same (&up->rpf, &child->rpf)) - { - size += sizeof (struct pim_encoded_source_ipv4); - PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(child->flags); - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message", - __PRETTY_FUNCTION__, up->sg_str, child->sg_str); - } - else - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message", - __PRETTY_FUNCTION__, up->sg_str, child->sg_str); - } - else - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: SPT bit is not set for (%s)", - __PRETTY_FUNCTION__, child->sg_str); - } - } - return size; + struct pim_jp_sources *js; + size_t size = 0; + + size += sizeof(struct pim_encoded_group_ipv4); + size += 4; // Joined sources (2) + Pruned Sources (2) + + size += sizeof(struct pim_encoded_source_ipv4) * sources->count; + + js = listgetdata(listhead(sources)); + if (js && js->up->sg.src.s_addr == INADDR_ANY) { + struct pim_upstream *child, *up; + struct listnode *up_node; + + up = js->up; + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: Considering (%s) children for (S,G,rpt) prune", + __PRETTY_FUNCTION__, up->sg_str); + + for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, child)) { + if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) { + if (!pim_rpf_is_same(&up->rpf, &child->rpf)) { + size += sizeof( + struct pim_encoded_source_ipv4); + PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE( + child->flags); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", + __PRETTY_FUNCTION__, + up->sg_str, + child->sg_str); + } else if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)", + __PRETTY_FUNCTION__, up->sg_str, + child->sg_str); + } else if (pim_upstream_is_sg_rpt(child)) { + if (pim_upstream_empty_inherited_olist(child)) { + size += sizeof( + struct pim_encoded_source_ipv4); + PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE( + child->flags); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message", + __PRETTY_FUNCTION__, + child->sg_str); + } else if (!pim_rpf_is_same(&up->rpf, + &child->rpf)) { + size += sizeof( + struct pim_encoded_source_ipv4); + PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE( + child->flags); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message", + __PRETTY_FUNCTION__, + up->sg_str, + child->sg_str); + } else if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message", + __PRETTY_FUNCTION__, up->sg_str, + child->sg_str); + } else if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("%s: SPT bit is not set for (%s)", + __PRETTY_FUNCTION__, child->sg_str); + } + } + return size; } -size_t -pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_jp_agg_group *sgs, size_t size) +size_t pim_msg_build_jp_groups(struct pim_jp_groups *grp, + struct pim_jp_agg_group *sgs, size_t size) { - struct listnode *node, *nnode; - struct pim_jp_sources *source; - struct pim_upstream *up = NULL; - struct in_addr stosend; - uint8_t bits; - uint8_t tgroups = 0; - - memset (grp, 0, size); - pim_msg_addr_encode_ipv4_group ((uint8_t *)&grp->g, sgs->group); - - for (ALL_LIST_ELEMENTS(sgs->sources, node, nnode, source)) - { - /* number of joined/pruned sources */ - if (source->is_join) - grp->joins++; - else - grp->prunes++; - - if (source->up->sg.src.s_addr == INADDR_ANY) - { - struct pim_rpf *rpf = pim_rp_g (source->up->sg.grp); - bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT | PIM_ENCODE_RPT_BIT; - stosend = rpf->rpf_addr.u.prefix4; - /* Only Send SGRpt in case of *,G Join */ - if (source->is_join) - up = source->up; - } - else - { - bits = PIM_ENCODE_SPARSE_BIT; - stosend = source->up->sg.src; - } - - pim_msg_addr_encode_ipv4_source ((uint8_t *)&grp->s[tgroups], stosend, bits); - tgroups++; - } - - if (up) - { - struct pim_upstream *child; - - for (ALL_LIST_ELEMENTS(up->sources, node, nnode, child)) - { - if (PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE(child->flags)) - { - pim_msg_addr_encode_ipv4_source ((uint8_t *)&grp->s[tgroups], - child->sg.src, - PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_RPT_BIT); - tgroups++; - PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE(child->flags); - grp->prunes++; - } - } - } - - grp->joins = htons(grp->joins); - grp->prunes = htons(grp->prunes); - - return size; + struct listnode *node, *nnode; + struct pim_jp_sources *source; + struct pim_upstream *up = NULL; + struct in_addr stosend; + uint8_t bits; + uint8_t tgroups = 0; + + memset(grp, 0, size); + pim_msg_addr_encode_ipv4_group((uint8_t *)&grp->g, sgs->group); + + for (ALL_LIST_ELEMENTS(sgs->sources, node, nnode, source)) { + /* number of joined/pruned sources */ + if (source->is_join) + grp->joins++; + else + grp->prunes++; + + if (source->up->sg.src.s_addr == INADDR_ANY) { + struct pim_rpf *rpf = pim_rp_g(source->up->sg.grp); + bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT + | PIM_ENCODE_RPT_BIT; + stosend = rpf->rpf_addr.u.prefix4; + /* Only Send SGRpt in case of *,G Join */ + if (source->is_join) + up = source->up; + } else { + bits = PIM_ENCODE_SPARSE_BIT; + stosend = source->up->sg.src; + } + + pim_msg_addr_encode_ipv4_source((uint8_t *)&grp->s[tgroups], + stosend, bits); + tgroups++; + } + + if (up) { + struct pim_upstream *child; + + for (ALL_LIST_ELEMENTS(up->sources, node, nnode, child)) { + if (PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE( + child->flags)) { + pim_msg_addr_encode_ipv4_source( + (uint8_t *)&grp->s[tgroups], + child->sg.src, + PIM_ENCODE_SPARSE_BIT + | PIM_ENCODE_RPT_BIT); + tgroups++; + PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE( + child->flags); + grp->prunes++; + } + } + } + + grp->joins = htons(grp->joins); + grp->prunes = htons(grp->prunes); + + return size; } diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h index 38ffaf6a7..ad9b5d9c0 100644 --- a/pimd/pim_msg.h +++ b/pimd/pim_msg.h @@ -24,7 +24,7 @@ #include "pim_jp_agg.h" /* - Number Description + Number Description ---------- ------------------ 0 Reserved 1 IP (IP version 4) @@ -34,70 +34,72 @@ http://www.iana.org/assignments/address-family-numbers */ enum pim_msg_address_family { - PIM_MSG_ADDRESS_FAMILY_RESERVED, - PIM_MSG_ADDRESS_FAMILY_IPV4, - PIM_MSG_ADDRESS_FAMILY_IPV6, + PIM_MSG_ADDRESS_FAMILY_RESERVED, + PIM_MSG_ADDRESS_FAMILY_IPV4, + PIM_MSG_ADDRESS_FAMILY_IPV6, }; /* * Network Order pim_msg_hdr */ struct pim_msg_header { - uint8_t type:4; - uint8_t ver:4; - uint8_t reserved; - uint16_t checksum; -} __attribute__ ((packed)); + uint8_t type : 4; + uint8_t ver : 4; + uint8_t reserved; + uint16_t checksum; +} __attribute__((packed)); struct pim_encoded_ipv4_unicast { - uint8_t family; - uint8_t reserved; - struct in_addr addr; -} __attribute__ ((packed)); + uint8_t family; + uint8_t reserved; + struct in_addr addr; +} __attribute__((packed)); struct pim_encoded_group_ipv4 { - uint8_t ne; - uint8_t family; - uint8_t reserved; - uint8_t mask; - struct in_addr addr; -} __attribute__ ((packed)); + uint8_t ne; + uint8_t family; + uint8_t reserved; + uint8_t mask; + struct in_addr addr; +} __attribute__((packed)); struct pim_encoded_source_ipv4 { - uint8_t ne; - uint8_t family; - uint8_t bits; - uint8_t mask; - struct in_addr addr; -} __attribute__ ((packed)); + uint8_t ne; + uint8_t family; + uint8_t bits; + uint8_t mask; + struct in_addr addr; +} __attribute__((packed)); struct pim_jp_groups { - struct pim_encoded_group_ipv4 g; - uint16_t joins; - uint16_t prunes; - struct pim_encoded_source_ipv4 s[1]; -} __attribute__ ((packed)); + struct pim_encoded_group_ipv4 g; + uint16_t joins; + uint16_t prunes; + struct pim_encoded_source_ipv4 s[1]; +} __attribute__((packed)); struct pim_jp { - struct pim_msg_header header; - struct pim_encoded_ipv4_unicast addr; - uint8_t reserved; - uint8_t num_groups; - uint16_t holdtime; - struct pim_jp_groups groups[1]; -} __attribute__ ((packed)); + struct pim_msg_header header; + struct pim_encoded_ipv4_unicast addr; + uint8_t reserved; + uint8_t num_groups; + uint16_t holdtime; + struct pim_jp_groups groups[1]; +} __attribute__((packed)); -void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, uint8_t pim_msg_type); +void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, + uint8_t pim_msg_type); uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf, struct in_addr addr); uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, struct in_addr addr); #define PIM_ENCODE_SPARSE_BIT 0x04 #define PIM_ENCODE_WC_BIT 0x02 #define PIM_ENCODE_RPT_BIT 0x01 -uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, - struct in_addr addr, uint8_t bits); +uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, struct in_addr addr, + uint8_t bits); -size_t pim_msg_get_jp_group_size (struct list *sources); -size_t pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_jp_agg_group *sgs, size_t size); +size_t pim_msg_get_jp_group_size(struct list *sources); +size_t pim_msg_build_jp_groups(struct pim_jp_groups *grp, + struct pim_jp_agg_group *sgs, size_t size); #endif /* PIM_MSG_H */ diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 8b8946daf..70341a375 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -42,66 +42,61 @@ static void dr_election_by_addr(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct pim_neighbor *neigh; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - pim_ifp->pim_dr_addr = pim_ifp->primary_address; - - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - } - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { - if (ntohl(neigh->source_addr.s_addr) > ntohl(pim_ifp->pim_dr_addr.s_addr)) { - pim_ifp->pim_dr_addr = neigh->source_addr; - } - } + struct pim_interface *pim_ifp; + struct listnode *node; + struct pim_neighbor *neigh; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + pim_ifp->pim_dr_addr = pim_ifp->primary_address; + + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: on interface %s", __PRETTY_FUNCTION__, + ifp->name); + } + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { + if (ntohl(neigh->source_addr.s_addr) + > ntohl(pim_ifp->pim_dr_addr.s_addr)) { + pim_ifp->pim_dr_addr = neigh->source_addr; + } + } } static void dr_election_by_pri(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct pim_neighbor *neigh; - uint32_t dr_pri; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - pim_ifp->pim_dr_addr = pim_ifp->primary_address; - dr_pri = pim_ifp->pim_dr_priority; - - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: dr pri %u on interface %s", - __PRETTY_FUNCTION__, - dr_pri, ifp->name); - } - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { - if (PIM_DEBUG_PIM_TRACE) { - zlog_info("%s: neigh pri %u addr %x if dr addr %x", - __PRETTY_FUNCTION__, - neigh->dr_priority, - ntohl(neigh->source_addr.s_addr), - ntohl(pim_ifp->pim_dr_addr.s_addr)); - } - if ( - (neigh->dr_priority > dr_pri) || - ( - (neigh->dr_priority == dr_pri) && - (ntohl(neigh->source_addr.s_addr) > ntohl(pim_ifp->pim_dr_addr.s_addr)) - ) - ) { - pim_ifp->pim_dr_addr = neigh->source_addr; - dr_pri = neigh->dr_priority; - } - } + struct pim_interface *pim_ifp; + struct listnode *node; + struct pim_neighbor *neigh; + uint32_t dr_pri; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + pim_ifp->pim_dr_addr = pim_ifp->primary_address; + dr_pri = pim_ifp->pim_dr_priority; + + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: dr pri %u on interface %s", __PRETTY_FUNCTION__, + dr_pri, ifp->name); + } + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { + if (PIM_DEBUG_PIM_TRACE) { + zlog_info("%s: neigh pri %u addr %x if dr addr %x", + __PRETTY_FUNCTION__, neigh->dr_priority, + ntohl(neigh->source_addr.s_addr), + ntohl(pim_ifp->pim_dr_addr.s_addr)); + } + if ((neigh->dr_priority > dr_pri) + || ((neigh->dr_priority == dr_pri) + && (ntohl(neigh->source_addr.s_addr) + > ntohl(pim_ifp->pim_dr_addr.s_addr)))) { + pim_ifp->pim_dr_addr = neigh->source_addr; + dr_pri = neigh->dr_priority; + } + } } /* @@ -113,359 +108,359 @@ static void dr_election_by_pri(struct interface *ifp) */ int pim_if_dr_election(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - struct in_addr old_dr_addr; - - ++pim_ifp->pim_dr_election_count; - - old_dr_addr = pim_ifp->pim_dr_addr; - - if (pim_ifp->pim_dr_num_nondrpri_neighbors) { - dr_election_by_addr(ifp); - } - else { - dr_election_by_pri(ifp); - } - - /* DR changed ? */ - if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) { - - if (PIM_DEBUG_PIM_EVENTS) { - char dr_old_str[INET_ADDRSTRLEN]; - char dr_new_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<old_dr?>", old_dr_addr, dr_old_str, sizeof(dr_old_str)); - pim_inet4_dump("<new_dr?>", pim_ifp->pim_dr_addr, dr_new_str, sizeof(dr_new_str)); - zlog_debug("%s: DR was %s now is %s on interface %s", - __PRETTY_FUNCTION__, - dr_old_str, dr_new_str, ifp->name); - } - - pim_ifp->pim_dr_election_last = pim_time_monotonic_sec(); /* timestamp */ - ++pim_ifp->pim_dr_election_changes; - pim_if_update_join_desired(pim_ifp); - pim_if_update_could_assert(ifp); - pim_if_update_assert_tracking_desired(ifp); - return 1; - } - - return 0; + struct pim_interface *pim_ifp = ifp->info; + struct in_addr old_dr_addr; + + ++pim_ifp->pim_dr_election_count; + + old_dr_addr = pim_ifp->pim_dr_addr; + + if (pim_ifp->pim_dr_num_nondrpri_neighbors) { + dr_election_by_addr(ifp); + } else { + dr_election_by_pri(ifp); + } + + /* DR changed ? */ + if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) { + + if (PIM_DEBUG_PIM_EVENTS) { + char dr_old_str[INET_ADDRSTRLEN]; + char dr_new_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<old_dr?>", old_dr_addr, dr_old_str, + sizeof(dr_old_str)); + pim_inet4_dump("<new_dr?>", pim_ifp->pim_dr_addr, + dr_new_str, sizeof(dr_new_str)); + zlog_debug("%s: DR was %s now is %s on interface %s", + __PRETTY_FUNCTION__, dr_old_str, dr_new_str, + ifp->name); + } + + pim_ifp->pim_dr_election_last = + pim_time_monotonic_sec(); /* timestamp */ + ++pim_ifp->pim_dr_election_changes; + pim_if_update_join_desired(pim_ifp); + pim_if_update_could_assert(ifp); + pim_if_update_assert_tracking_desired(ifp); + return 1; + } + + return 0; } static void update_dr_priority(struct pim_neighbor *neigh, pim_hello_options hello_options, uint32_t dr_priority) { - pim_hello_options will_set_pri; /* boolean */ - pim_hello_options bit_flip; /* boolean */ - pim_hello_options pri_change; /* boolean */ - - will_set_pri = PIM_OPTION_IS_SET(hello_options, - PIM_OPTION_MASK_DR_PRIORITY); - - bit_flip = - ( - will_set_pri != - PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY) - ); - - if (bit_flip) { - struct pim_interface *pim_ifp = neigh->interface->info; - - /* update num. of neighbors without dr_pri */ - - if (will_set_pri) { - --pim_ifp->pim_dr_num_nondrpri_neighbors; - } - else { - ++pim_ifp->pim_dr_num_nondrpri_neighbors; - } - } - - pri_change = - ( - bit_flip - || - (neigh->dr_priority != dr_priority) - ); - - if (will_set_pri) { - neigh->dr_priority = dr_priority; - } - else { - neigh->dr_priority = 0; /* cosmetic unset */ - } - - if (pri_change) { - /* - RFC 4601: 4.3.2. DR Election - - A router's idea of the current DR on an interface can change when a - PIM Hello message is received, when a neighbor times out, or when a - router's own DR Priority changes. - */ - pim_if_dr_election(neigh->interface); // router's own DR Priority changes - } + pim_hello_options will_set_pri; /* boolean */ + pim_hello_options bit_flip; /* boolean */ + pim_hello_options pri_change; /* boolean */ + + will_set_pri = + PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_DR_PRIORITY); + + bit_flip = (will_set_pri + != PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_DR_PRIORITY)); + + if (bit_flip) { + struct pim_interface *pim_ifp = neigh->interface->info; + + /* update num. of neighbors without dr_pri */ + + if (will_set_pri) { + --pim_ifp->pim_dr_num_nondrpri_neighbors; + } else { + ++pim_ifp->pim_dr_num_nondrpri_neighbors; + } + } + + pri_change = (bit_flip || (neigh->dr_priority != dr_priority)); + + if (will_set_pri) { + neigh->dr_priority = dr_priority; + } else { + neigh->dr_priority = 0; /* cosmetic unset */ + } + + if (pri_change) { + /* + RFC 4601: 4.3.2. DR Election + + A router's idea of the current DR on an interface can change + when a + PIM Hello message is received, when a neighbor times out, or + when a + router's own DR Priority changes. + */ + pim_if_dr_election( + neigh->interface); // router's own DR Priority changes + } } static int on_neighbor_timer(struct thread *t) { - struct pim_neighbor *neigh; - struct interface *ifp; - char msg[100]; - - neigh = THREAD_ARG(t); - - ifp = neigh->interface; - - if (PIM_DEBUG_PIM_TRACE) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str)); - zlog_debug("Expired %d sec holdtime for neighbor %s on interface %s", - neigh->holdtime, src_str, ifp->name); - } - - snprintf(msg, sizeof(msg), "%d-sec holdtime expired", neigh->holdtime); - pim_neighbor_delete(ifp, neigh, msg); - - /* - RFC 4601: 4.3.2. DR Election - - A router's idea of the current DR on an interface can change when a - PIM Hello message is received, when a neighbor times out, or when a - router's own DR Priority changes. - */ - pim_if_dr_election(ifp); // neighbor times out - - return 0; + struct pim_neighbor *neigh; + struct interface *ifp; + char msg[100]; + + neigh = THREAD_ARG(t); + + ifp = neigh->interface; + + if (PIM_DEBUG_PIM_TRACE) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", neigh->source_addr, src_str, + sizeof(src_str)); + zlog_debug( + "Expired %d sec holdtime for neighbor %s on interface %s", + neigh->holdtime, src_str, ifp->name); + } + + snprintf(msg, sizeof(msg), "%d-sec holdtime expired", neigh->holdtime); + pim_neighbor_delete(ifp, neigh, msg); + + /* + RFC 4601: 4.3.2. DR Election + + A router's idea of the current DR on an interface can change when a + PIM Hello message is received, when a neighbor times out, or when a + router's own DR Priority changes. + */ + pim_if_dr_election(ifp); // neighbor times out + + return 0; } void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime) { - neigh->holdtime = holdtime; - - THREAD_OFF(neigh->t_expire_timer); - - /* - 0xFFFF is request for no holdtime - */ - if (neigh->holdtime == 0xFFFF) { - return; - } - - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str)); - zlog_debug("%s: starting %u sec timer for neighbor %s on %s", - __PRETTY_FUNCTION__, - neigh->holdtime, src_str, neigh->interface->name); - } - - thread_add_timer(master, on_neighbor_timer, neigh, neigh->holdtime, - &neigh->t_expire_timer); + neigh->holdtime = holdtime; + + THREAD_OFF(neigh->t_expire_timer); + + /* + 0xFFFF is request for no holdtime + */ + if (neigh->holdtime == 0xFFFF) { + return; + } + + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", neigh->source_addr, src_str, + sizeof(src_str)); + zlog_debug("%s: starting %u sec timer for neighbor %s on %s", + __PRETTY_FUNCTION__, neigh->holdtime, src_str, + neigh->interface->name); + } + + thread_add_timer(master, on_neighbor_timer, neigh, neigh->holdtime, + &neigh->t_expire_timer); } -static int -on_neighbor_jp_timer (struct thread *t) +static int on_neighbor_jp_timer(struct thread *t) { - struct pim_neighbor *neigh = THREAD_ARG(t); - struct pim_rpf rpf; - - if (PIM_DEBUG_PIM_TRACE) - { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str)); - zlog_debug("%s:Sending JP Agg to %s on %s with %d groups", __PRETTY_FUNCTION__, - src_str, neigh->interface->name, neigh->upstream_jp_agg->count); - } + struct pim_neighbor *neigh = THREAD_ARG(t); + struct pim_rpf rpf; + + if (PIM_DEBUG_PIM_TRACE) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", neigh->source_addr, src_str, + sizeof(src_str)); + zlog_debug("%s:Sending JP Agg to %s on %s with %d groups", + __PRETTY_FUNCTION__, src_str, neigh->interface->name, + neigh->upstream_jp_agg->count); + } - rpf.source_nexthop.interface = neigh->interface; - rpf.rpf_addr.u.prefix4 = neigh->source_addr; - pim_joinprune_send(&rpf, neigh->upstream_jp_agg); + rpf.source_nexthop.interface = neigh->interface; + rpf.rpf_addr.u.prefix4 = neigh->source_addr; + pim_joinprune_send(&rpf, neigh->upstream_jp_agg); - thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic, - &neigh->jp_timer); + thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic, + &neigh->jp_timer); - return 0; + return 0; } -static void -pim_neighbor_start_jp_timer (struct pim_neighbor *neigh) +static void pim_neighbor_start_jp_timer(struct pim_neighbor *neigh) { - THREAD_TIMER_OFF(neigh->jp_timer); - thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic, - &neigh->jp_timer); + THREAD_TIMER_OFF(neigh->jp_timer); + thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic, + &neigh->jp_timer); } -static struct pim_neighbor *pim_neighbor_new(struct interface *ifp, - struct in_addr source_addr, - pim_hello_options hello_options, - uint16_t holdtime, - uint16_t propagation_delay, - uint16_t override_interval, - uint32_t dr_priority, - uint32_t generation_id, - struct list *addr_list) +static struct pim_neighbor * +pim_neighbor_new(struct interface *ifp, struct in_addr source_addr, + pim_hello_options hello_options, uint16_t holdtime, + uint16_t propagation_delay, uint16_t override_interval, + uint32_t dr_priority, uint32_t generation_id, + struct list *addr_list) { - struct pim_interface *pim_ifp; - struct pim_neighbor *neigh; - char src_str[INET_ADDRSTRLEN]; - - zassert(ifp); - pim_ifp = ifp->info; - zassert(pim_ifp); - - neigh = XCALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh)); - if (!neigh) { - zlog_err("%s: PIM XCALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*neigh)); - return 0; - } - - neigh->creation = pim_time_monotonic_sec(); - neigh->source_addr = source_addr; - neigh->hello_options = hello_options; - neigh->propagation_delay_msec = propagation_delay; - neigh->override_interval_msec = override_interval; - neigh->dr_priority = dr_priority; - neigh->generation_id = generation_id; - neigh->prefix_list = addr_list; - neigh->t_expire_timer = NULL; - neigh->interface = ifp; - - neigh->upstream_jp_agg = list_new(); - neigh->upstream_jp_agg->cmp = pim_jp_agg_group_list_cmp; - neigh->upstream_jp_agg->del = (void (*)(void *))pim_jp_agg_group_list_free; - pim_neighbor_start_jp_timer(neigh); - - pim_neighbor_timer_reset(neigh, holdtime); - /* - * The pim_ifstat_hello_sent variable is used to decide if - * we should expedite a hello out the interface. If we - * establish a new neighbor, we unfortunately need to - * reset the value so that we can know to hurry up and - * hello - */ - pim_ifp->pim_ifstat_hello_sent = 0; - - pim_inet4_dump("<src?>", source_addr, src_str, sizeof(src_str)); - - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("%s: creating PIM neighbor %s on interface %s", - __PRETTY_FUNCTION__, - src_str, ifp->name); - } - - zlog_info("PIM NEIGHBOR UP: neighbor %s on interface %s", - src_str, ifp->name); - - if (neigh->propagation_delay_msec > pim_ifp->pim_neighbors_highest_propagation_delay_msec) { - pim_ifp->pim_neighbors_highest_propagation_delay_msec = neigh->propagation_delay_msec; - } - if (neigh->override_interval_msec > pim_ifp->pim_neighbors_highest_override_interval_msec) { - pim_ifp->pim_neighbors_highest_override_interval_msec = neigh->override_interval_msec; - } - - if (!PIM_OPTION_IS_SET(neigh->hello_options, - PIM_OPTION_MASK_LAN_PRUNE_DELAY)) { - /* update num. of neighbors without hello option lan_delay */ - ++pim_ifp->pim_number_of_nonlandelay_neighbors; - } - - if (!PIM_OPTION_IS_SET(neigh->hello_options, - PIM_OPTION_MASK_DR_PRIORITY)) { - /* update num. of neighbors without hello option dr_pri */ - ++pim_ifp->pim_dr_num_nondrpri_neighbors; - } - - //Register PIM Neighbor with BFD - pim_bfd_trigger_event (pim_ifp, neigh, 1); - - return neigh; + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; + char src_str[INET_ADDRSTRLEN]; + + zassert(ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); + + neigh = XCALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh)); + if (!neigh) { + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, + sizeof(*neigh)); + return 0; + } + + neigh->creation = pim_time_monotonic_sec(); + neigh->source_addr = source_addr; + neigh->hello_options = hello_options; + neigh->propagation_delay_msec = propagation_delay; + neigh->override_interval_msec = override_interval; + neigh->dr_priority = dr_priority; + neigh->generation_id = generation_id; + neigh->prefix_list = addr_list; + neigh->t_expire_timer = NULL; + neigh->interface = ifp; + + neigh->upstream_jp_agg = list_new(); + neigh->upstream_jp_agg->cmp = pim_jp_agg_group_list_cmp; + neigh->upstream_jp_agg->del = + (void (*)(void *))pim_jp_agg_group_list_free; + pim_neighbor_start_jp_timer(neigh); + + pim_neighbor_timer_reset(neigh, holdtime); + /* + * The pim_ifstat_hello_sent variable is used to decide if + * we should expedite a hello out the interface. If we + * establish a new neighbor, we unfortunately need to + * reset the value so that we can know to hurry up and + * hello + */ + pim_ifp->pim_ifstat_hello_sent = 0; + + pim_inet4_dump("<src?>", source_addr, src_str, sizeof(src_str)); + + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug("%s: creating PIM neighbor %s on interface %s", + __PRETTY_FUNCTION__, src_str, ifp->name); + } + + zlog_info("PIM NEIGHBOR UP: neighbor %s on interface %s", src_str, + ifp->name); + + if (neigh->propagation_delay_msec + > pim_ifp->pim_neighbors_highest_propagation_delay_msec) { + pim_ifp->pim_neighbors_highest_propagation_delay_msec = + neigh->propagation_delay_msec; + } + if (neigh->override_interval_msec + > pim_ifp->pim_neighbors_highest_override_interval_msec) { + pim_ifp->pim_neighbors_highest_override_interval_msec = + neigh->override_interval_msec; + } + + if (!PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY)) { + /* update num. of neighbors without hello option lan_delay */ + ++pim_ifp->pim_number_of_nonlandelay_neighbors; + } + + if (!PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_DR_PRIORITY)) { + /* update num. of neighbors without hello option dr_pri */ + ++pim_ifp->pim_dr_num_nondrpri_neighbors; + } + + // Register PIM Neighbor with BFD + pim_bfd_trigger_event(pim_ifp, neigh, 1); + + return neigh; } static void delete_prefix_list(struct pim_neighbor *neigh) { - if (neigh->prefix_list) { + if (neigh->prefix_list) { #ifdef DUMP_PREFIX_LIST - struct listnode *p_node; - struct prefix *p; - char addr_str[10]; - int list_size = neigh->prefix_list ? (int) listcount(neigh->prefix_list) : -1; - int i = 0; - for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, p_node, p)) { - pim_inet4_dump("<addr?>", p->u.prefix4, addr_str, sizeof(addr_str)); - zlog_debug("%s: DUMP_PREFIX_LIST neigh=%x prefix_list=%x prefix=%x addr=%s [%d/%d]", - __PRETTY_FUNCTION__, - (unsigned) neigh, (unsigned) neigh->prefix_list, (unsigned) p, - addr_str, i, list_size); - ++i; - } + struct listnode *p_node; + struct prefix *p; + char addr_str[10]; + int list_size = neigh->prefix_list + ? (int)listcount(neigh->prefix_list) + : -1; + int i = 0; + for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, p_node, p)) { + pim_inet4_dump("<addr?>", p->u.prefix4, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s: DUMP_PREFIX_LIST neigh=%x prefix_list=%x prefix=%x addr=%s [%d/%d]", + __PRETTY_FUNCTION__, (unsigned)neigh, + (unsigned)neigh->prefix_list, (unsigned)p, + addr_str, i, list_size); + ++i; + } #endif - list_delete(neigh->prefix_list); - neigh->prefix_list = 0; - } + list_delete(neigh->prefix_list); + neigh->prefix_list = 0; + } } void pim_neighbor_free(struct pim_neighbor *neigh) { - zassert(!neigh->t_expire_timer); + zassert(!neigh->t_expire_timer); - delete_prefix_list(neigh); + delete_prefix_list(neigh); - list_delete(neigh->upstream_jp_agg); - THREAD_OFF(neigh->jp_timer); + list_delete(neigh->upstream_jp_agg); + THREAD_OFF(neigh->jp_timer); - XFREE(MTYPE_PIM_NEIGHBOR, neigh); + XFREE(MTYPE_PIM_NEIGHBOR, neigh); } -struct pim_neighbor * -pim_neighbor_find_by_secondary (struct interface *ifp, - struct prefix *src) +struct pim_neighbor *pim_neighbor_find_by_secondary(struct interface *ifp, + struct prefix *src) { - struct pim_interface *pim_ifp; - struct listnode *node, *pnode; - struct pim_neighbor *neigh; - struct prefix *p; - - pim_ifp = ifp->info; - if (!pim_ifp) - return NULL; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) - { - for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, pnode, p)) - { - if (prefix_same (p, src)) - return neigh; - } - } - - return NULL; + struct pim_interface *pim_ifp; + struct listnode *node, *pnode; + struct pim_neighbor *neigh; + struct prefix *p; + + pim_ifp = ifp->info; + if (!pim_ifp) + return NULL; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { + for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, pnode, p)) { + if (prefix_same(p, src)) + return neigh; + } + } + + return NULL; } struct pim_neighbor *pim_neighbor_find(struct interface *ifp, struct in_addr source_addr) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct pim_neighbor *neigh; + struct pim_interface *pim_ifp; + struct listnode *node; + struct pim_neighbor *neigh; - if (!ifp) - return NULL; + if (!ifp) + return NULL; - pim_ifp = ifp->info; - if (!pim_ifp) - return NULL; + pim_ifp = ifp->info; + if (!pim_ifp) + return NULL; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { - if (source_addr.s_addr == neigh->source_addr.s_addr) { - return neigh; - } - } + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { + if (source_addr.s_addr == neigh->source_addr.s_addr) { + return neigh; + } + } - return NULL; + return NULL; } /* @@ -473,263 +468,256 @@ struct pim_neighbor *pim_neighbor_find(struct interface *ifp, * this interface. If more than * one return NULL */ -struct pim_neighbor * -pim_neighbor_find_if (struct interface *ifp) +struct pim_neighbor *pim_neighbor_find_if(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp || pim_ifp->pim_neighbor_list->count != 1) - return NULL; + if (!pim_ifp || pim_ifp->pim_neighbor_list->count != 1) + return NULL; - return listnode_head (pim_ifp->pim_neighbor_list); + return listnode_head(pim_ifp->pim_neighbor_list); } /* rpf info associated with an upstream entry needs to be re-evaluated * when an RPF neighbor comes or goes */ -static void -pim_neighbor_rpf_update(void) -{ - /* XXX: for the time being piggyback on the timer used on rib changes - * to scan and update the rpf nexthop. This is expensive processing - * and we should be able to optimize neighbor changes differently than - * nexthop changes. */ - sched_rpf_cache_refresh(); -} - -struct pim_neighbor *pim_neighbor_add(struct interface *ifp, - struct in_addr source_addr, - pim_hello_options hello_options, - uint16_t holdtime, - uint16_t propagation_delay, - uint16_t override_interval, - uint32_t dr_priority, - uint32_t generation_id, - struct list *addr_list, - int send_hello_now) +static void pim_neighbor_rpf_update(void) { - struct pim_interface *pim_ifp; - struct pim_neighbor *neigh; - - neigh = pim_neighbor_new(ifp, source_addr, - hello_options, - holdtime, - propagation_delay, - override_interval, - dr_priority, - generation_id, - addr_list); - if (!neigh) { - return 0; - } - - pim_ifp = ifp->info; - zassert(pim_ifp); - - listnode_add(pim_ifp->pim_neighbor_list, neigh); - - if (PIM_DEBUG_PIM_TRACE_DETAIL) - { - char str[INET_ADDRSTRLEN]; - pim_inet4_dump("<nht_nbr?>", source_addr, str, sizeof (str)); - zlog_debug ("%s: neighbor %s added ", __PRETTY_FUNCTION__, str); - } - /* - RFC 4601: 4.3.2. DR Election - - A router's idea of the current DR on an interface can change when a - PIM Hello message is received, when a neighbor times out, or when a - router's own DR Priority changes. - */ - pim_if_dr_election(neigh->interface); // new neighbor -- should not trigger dr election... - - /* - RFC 4601: 4.3.1. Sending Hello Messages - - To allow new or rebooting routers to learn of PIM neighbors quickly, - when a Hello message is received from a new neighbor, or a Hello - message with a new GenID is received from an existing neighbor, a - new Hello message should be sent on this interface after a - randomized delay between 0 and Triggered_Hello_Delay. - - This is a bit silly to do it that way. If I get a new - genid we need to send the hello *now* because we've - lined up a bunch of join/prune messages to go out the - interface. - */ - if (send_hello_now) - pim_hello_restart_now (ifp); - else - pim_hello_restart_triggered(neigh->interface); - - pim_upstream_find_new_rpf(); - - /* RNH can send nexthop update prior to PIM neibhor UP - in that case nexthop cache would not consider this neighbor - as RPF. - Upon PIM neighbor UP, iterate all RPs and update - nexthop cache with this neighbor. - */ - pim_resolve_rp_nh (); - - pim_rp_setup (); - - pim_neighbor_rpf_update(); - return neigh; + /* XXX: for the time being piggyback on the timer used on rib changes + * to scan and update the rpf nexthop. This is expensive processing + * and we should be able to optimize neighbor changes differently than + * nexthop changes. */ + sched_rpf_cache_refresh(); } -static uint16_t -find_neighbors_next_highest_propagation_delay_msec(struct interface *ifp, - struct pim_neighbor *highest_neigh) +struct pim_neighbor * +pim_neighbor_add(struct interface *ifp, struct in_addr source_addr, + pim_hello_options hello_options, uint16_t holdtime, + uint16_t propagation_delay, uint16_t override_interval, + uint32_t dr_priority, uint32_t generation_id, + struct list *addr_list, int send_hello_now) { - struct pim_interface *pim_ifp; - struct listnode *neigh_node; - struct pim_neighbor *neigh; - uint16_t next_highest_delay_msec; - - pim_ifp = ifp->info; - zassert(pim_ifp); + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; + + neigh = pim_neighbor_new(ifp, source_addr, hello_options, holdtime, + propagation_delay, override_interval, + dr_priority, generation_id, addr_list); + if (!neigh) { + return 0; + } - next_highest_delay_msec = pim_ifp->pim_propagation_delay_msec; + pim_ifp = ifp->info; + zassert(pim_ifp); - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) { - if (neigh == highest_neigh) - continue; - if (neigh->propagation_delay_msec > next_highest_delay_msec) - next_highest_delay_msec = neigh->propagation_delay_msec; - } + listnode_add(pim_ifp->pim_neighbor_list, neigh); - return next_highest_delay_msec; + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + char str[INET_ADDRSTRLEN]; + pim_inet4_dump("<nht_nbr?>", source_addr, str, sizeof(str)); + zlog_debug("%s: neighbor %s added ", __PRETTY_FUNCTION__, str); + } + /* + RFC 4601: 4.3.2. DR Election + + A router's idea of the current DR on an interface can change when a + PIM Hello message is received, when a neighbor times out, or when a + router's own DR Priority changes. + */ + pim_if_dr_election(neigh->interface); // new neighbor -- should not + // trigger dr election... + + /* + RFC 4601: 4.3.1. Sending Hello Messages + + To allow new or rebooting routers to learn of PIM neighbors quickly, + when a Hello message is received from a new neighbor, or a Hello + message with a new GenID is received from an existing neighbor, a + new Hello message should be sent on this interface after a + randomized delay between 0 and Triggered_Hello_Delay. + + This is a bit silly to do it that way. If I get a new + genid we need to send the hello *now* because we've + lined up a bunch of join/prune messages to go out the + interface. + */ + if (send_hello_now) + pim_hello_restart_now(ifp); + else + pim_hello_restart_triggered(neigh->interface); + + pim_upstream_find_new_rpf(); + + /* RNH can send nexthop update prior to PIM neibhor UP + in that case nexthop cache would not consider this neighbor + as RPF. + Upon PIM neighbor UP, iterate all RPs and update + nexthop cache with this neighbor. + */ + pim_resolve_rp_nh(); + + pim_rp_setup(); + + pim_neighbor_rpf_update(); + return neigh; } -static uint16_t -find_neighbors_next_highest_override_interval_msec(struct interface *ifp, - struct pim_neighbor *highest_neigh) +static uint16_t find_neighbors_next_highest_propagation_delay_msec( + struct interface *ifp, struct pim_neighbor *highest_neigh) { - struct pim_interface *pim_ifp; - struct listnode *neigh_node; - struct pim_neighbor *neigh; - uint16_t next_highest_interval_msec; - - pim_ifp = ifp->info; - zassert(pim_ifp); + struct pim_interface *pim_ifp; + struct listnode *neigh_node; + struct pim_neighbor *neigh; + uint16_t next_highest_delay_msec; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + next_highest_delay_msec = pim_ifp->pim_propagation_delay_msec; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, + neigh)) { + if (neigh == highest_neigh) + continue; + if (neigh->propagation_delay_msec > next_highest_delay_msec) + next_highest_delay_msec = neigh->propagation_delay_msec; + } - next_highest_interval_msec = pim_ifp->pim_override_interval_msec; + return next_highest_delay_msec; +} - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) { - if (neigh == highest_neigh) - continue; - if (neigh->override_interval_msec > next_highest_interval_msec) - next_highest_interval_msec = neigh->override_interval_msec; - } +static uint16_t find_neighbors_next_highest_override_interval_msec( + struct interface *ifp, struct pim_neighbor *highest_neigh) +{ + struct pim_interface *pim_ifp; + struct listnode *neigh_node; + struct pim_neighbor *neigh; + uint16_t next_highest_interval_msec; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + next_highest_interval_msec = pim_ifp->pim_override_interval_msec; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, + neigh)) { + if (neigh == highest_neigh) + continue; + if (neigh->override_interval_msec > next_highest_interval_msec) + next_highest_interval_msec = + neigh->override_interval_msec; + } - return next_highest_interval_msec; + return next_highest_interval_msec; } -void pim_neighbor_delete(struct interface *ifp, - struct pim_neighbor *neigh, +void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh, const char *delete_message) { - struct pim_interface *pim_ifp; - char src_str[INET_ADDRSTRLEN]; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str)); - zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s", - src_str, ifp->name, delete_message); + struct pim_interface *pim_ifp; + char src_str[INET_ADDRSTRLEN]; - THREAD_OFF(neigh->t_expire_timer); + pim_ifp = ifp->info; + zassert(pim_ifp); - pim_if_assert_on_neighbor_down(ifp, neigh->source_addr); + pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str)); + zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s", src_str, + ifp->name, delete_message); - if (!PIM_OPTION_IS_SET(neigh->hello_options, - PIM_OPTION_MASK_LAN_PRUNE_DELAY)) { - /* update num. of neighbors without hello option lan_delay */ + THREAD_OFF(neigh->t_expire_timer); - --pim_ifp->pim_number_of_nonlandelay_neighbors; - } + pim_if_assert_on_neighbor_down(ifp, neigh->source_addr); - if (!PIM_OPTION_IS_SET(neigh->hello_options, - PIM_OPTION_MASK_DR_PRIORITY)) { - /* update num. of neighbors without dr_pri */ + if (!PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY)) { + /* update num. of neighbors without hello option lan_delay */ - --pim_ifp->pim_dr_num_nondrpri_neighbors; - } - - zassert(neigh->propagation_delay_msec <= pim_ifp->pim_neighbors_highest_propagation_delay_msec); - zassert(neigh->override_interval_msec <= pim_ifp->pim_neighbors_highest_override_interval_msec); + --pim_ifp->pim_number_of_nonlandelay_neighbors; + } - if (pim_if_lan_delay_enabled(ifp)) { + if (!PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_DR_PRIORITY)) { + /* update num. of neighbors without dr_pri */ - /* will delete a neighbor with highest propagation delay? */ - if (neigh->propagation_delay_msec == pim_ifp->pim_neighbors_highest_propagation_delay_msec) { - /* then find the next highest propagation delay */ - pim_ifp->pim_neighbors_highest_propagation_delay_msec = - find_neighbors_next_highest_propagation_delay_msec(ifp, neigh); - } + --pim_ifp->pim_dr_num_nondrpri_neighbors; + } - /* will delete a neighbor with highest override interval? */ - if (neigh->override_interval_msec == pim_ifp->pim_neighbors_highest_override_interval_msec) { - /* then find the next highest propagation delay */ - pim_ifp->pim_neighbors_highest_override_interval_msec = - find_neighbors_next_highest_override_interval_msec(ifp, neigh); - } - } + zassert(neigh->propagation_delay_msec + <= pim_ifp->pim_neighbors_highest_propagation_delay_msec); + zassert(neigh->override_interval_msec + <= pim_ifp->pim_neighbors_highest_override_interval_msec); + + if (pim_if_lan_delay_enabled(ifp)) { + + /* will delete a neighbor with highest propagation delay? */ + if (neigh->propagation_delay_msec + == pim_ifp->pim_neighbors_highest_propagation_delay_msec) { + /* then find the next highest propagation delay */ + pim_ifp->pim_neighbors_highest_propagation_delay_msec = + find_neighbors_next_highest_propagation_delay_msec( + ifp, neigh); + } + + /* will delete a neighbor with highest override interval? */ + if (neigh->override_interval_msec + == pim_ifp->pim_neighbors_highest_override_interval_msec) { + /* then find the next highest propagation delay */ + pim_ifp->pim_neighbors_highest_override_interval_msec = + find_neighbors_next_highest_override_interval_msec( + ifp, neigh); + } + } - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: deleting PIM neighbor %s on interface %s", - __PRETTY_FUNCTION__, - src_str, ifp->name); - } + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: deleting PIM neighbor %s on interface %s", + __PRETTY_FUNCTION__, src_str, ifp->name); + } - //De-Register PIM Neighbor with BFD - pim_bfd_trigger_event (pim_ifp, neigh, 0); + // De-Register PIM Neighbor with BFD + pim_bfd_trigger_event(pim_ifp, neigh, 0); - listnode_delete(pim_ifp->pim_neighbor_list, neigh); + listnode_delete(pim_ifp->pim_neighbor_list, neigh); - pim_neighbor_free(neigh); + pim_neighbor_free(neigh); - pim_neighbor_rpf_update(); + pim_neighbor_rpf_update(); } -void pim_neighbor_delete_all(struct interface *ifp, - const char *delete_message) +void pim_neighbor_delete_all(struct interface *ifp, const char *delete_message) { - struct pim_interface *pim_ifp; - struct listnode *neigh_node; - struct listnode *neigh_nextnode; - struct pim_neighbor *neigh; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node, - neigh_nextnode, neigh)) { - pim_neighbor_delete(ifp, neigh, delete_message); - } + struct pim_interface *pim_ifp; + struct listnode *neigh_node; + struct listnode *neigh_nextnode; + struct pim_neighbor *neigh; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node, + neigh_nextnode, neigh)) { + pim_neighbor_delete(ifp, neigh, delete_message); + } } struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh, struct prefix *addr) { - struct listnode *node; - struct prefix *p; + struct listnode *node; + struct prefix *p; - if (!neigh->prefix_list) - return 0; + if (!neigh->prefix_list) + return 0; - for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, node, p)) { - if (prefix_same (p, addr)) - return p; - } + for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, node, p)) { + if (prefix_same(p, addr)) + return p; + } - return NULL; + return NULL; } /* RFC 4601: 4.3.4. Maintaining Secondary Address Lists - + All the advertised secondary addresses in received Hello messages must be checked against those previously advertised by all other PIM neighbors on that interface. If there is a conflict and the @@ -742,104 +730,109 @@ static void delete_from_neigh_addr(struct interface *ifp, struct list *addr_list, struct in_addr neigh_addr) { - struct listnode *addr_node; - struct prefix *addr; - struct pim_interface *pim_ifp; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - zassert(addr_list); - - /* - Scan secondary address list - */ - for (ALL_LIST_ELEMENTS_RO(addr_list, addr_node, - addr)) { - struct listnode *neigh_node; - struct pim_neighbor *neigh; - - if (addr->family != AF_INET) - continue; - - /* - Scan neighbors - */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, - neigh)) { - { - struct prefix *p = pim_neighbor_find_secondary(neigh, addr); - if (p) { - char addr_str[INET_ADDRSTRLEN]; - char this_neigh_str[INET_ADDRSTRLEN]; - char other_neigh_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("<addr?>", addr->u.prefix4, addr_str, sizeof(addr_str)); - pim_inet4_dump("<neigh1?>", neigh_addr, this_neigh_str, sizeof(this_neigh_str)); - pim_inet4_dump("<neigh2?>", neigh->source_addr, other_neigh_str, sizeof(other_neigh_str)); - - zlog_info("secondary addr %s recvd from neigh %s deleted from neigh %s on %s", - addr_str, this_neigh_str, other_neigh_str, ifp->name); - - listnode_delete(neigh->prefix_list, p); - prefix_free(p); - } - } - - } /* scan neighbors */ - - } /* scan addr list */ - + struct listnode *addr_node; + struct prefix *addr; + struct pim_interface *pim_ifp; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + zassert(addr_list); + + /* + Scan secondary address list + */ + for (ALL_LIST_ELEMENTS_RO(addr_list, addr_node, addr)) { + struct listnode *neigh_node; + struct pim_neighbor *neigh; + + if (addr->family != AF_INET) + continue; + + /* + Scan neighbors + */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, + neigh_node, neigh)) { + { + struct prefix *p = pim_neighbor_find_secondary( + neigh, addr); + if (p) { + char addr_str[INET_ADDRSTRLEN]; + char this_neigh_str[INET_ADDRSTRLEN]; + char other_neigh_str[INET_ADDRSTRLEN]; + + pim_inet4_dump( + "<addr?>", addr->u.prefix4, + addr_str, sizeof(addr_str)); + pim_inet4_dump("<neigh1?>", neigh_addr, + this_neigh_str, + sizeof(this_neigh_str)); + pim_inet4_dump("<neigh2?>", + neigh->source_addr, + other_neigh_str, + sizeof(other_neigh_str)); + + zlog_info( + "secondary addr %s recvd from neigh %s deleted from neigh %s on %s", + addr_str, this_neigh_str, + other_neigh_str, ifp->name); + + listnode_delete(neigh->prefix_list, p); + prefix_free(p); + } + } + + } /* scan neighbors */ + + } /* scan addr list */ } void pim_neighbor_update(struct pim_neighbor *neigh, - pim_hello_options hello_options, - uint16_t holdtime, - uint32_t dr_priority, - struct list *addr_list) + pim_hello_options hello_options, uint16_t holdtime, + uint32_t dr_priority, struct list *addr_list) { - struct pim_interface *pim_ifp = neigh->interface->info; - - /* Received holdtime ? */ - if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { - pim_neighbor_timer_reset(neigh, holdtime); - } - else { - pim_neighbor_timer_reset(neigh, PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); - } + struct pim_interface *pim_ifp = neigh->interface->info; + + /* Received holdtime ? */ + if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { + pim_neighbor_timer_reset(neigh, holdtime); + } else { + pim_neighbor_timer_reset(neigh, + PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); + } #ifdef DUMP_PREFIX_LIST - zlog_debug("%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d", - __PRETTY_FUNCTION__, - (unsigned) neigh->prefix_list, - neigh->prefix_list ? (int) listcount(neigh->prefix_list) : -1, - (unsigned) addr_list, - addr_list ? (int) listcount(addr_list) : -1); + zlog_debug( + "%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d", + __PRETTY_FUNCTION__, (unsigned)neigh->prefix_list, + neigh->prefix_list ? (int)listcount(neigh->prefix_list) : -1, + (unsigned)addr_list, + addr_list ? (int)listcount(addr_list) : -1); #endif - if (neigh->prefix_list == addr_list) { - if (addr_list) { - zlog_err("%s: internal error: trying to replace same prefix list=%p", - __PRETTY_FUNCTION__, (void *) addr_list); - } - } - else { - /* Delete existing secondary address list */ - delete_prefix_list(neigh); - } - - if (addr_list) { - delete_from_neigh_addr(neigh->interface, addr_list, neigh->source_addr); - } - - /* Replace secondary address list */ - neigh->prefix_list = addr_list; - - update_dr_priority(neigh, - hello_options, - dr_priority); - /* - Copy flags - */ - neigh->hello_options = hello_options; + if (neigh->prefix_list == addr_list) { + if (addr_list) { + zlog_err( + "%s: internal error: trying to replace same prefix list=%p", + __PRETTY_FUNCTION__, (void *)addr_list); + } + } else { + /* Delete existing secondary address list */ + delete_prefix_list(neigh); + } + + if (addr_list) { + delete_from_neigh_addr(neigh->interface, addr_list, + neigh->source_addr); + } + + /* Replace secondary address list */ + neigh->prefix_list = addr_list; + + update_dr_priority(neigh, hello_options, dr_priority); + /* + Copy flags + */ + neigh->hello_options = hello_options; } diff --git a/pimd/pim_neighbor.h b/pimd/pim_neighbor.h index eaaefd8fe..a4f2e10c8 100644 --- a/pimd/pim_neighbor.h +++ b/pimd/pim_neighbor.h @@ -29,54 +29,46 @@ #include "pim_tlv.h" struct pim_neighbor { - int64_t creation; /* timestamp of creation */ - struct in_addr source_addr; - pim_hello_options hello_options; - uint16_t holdtime; - uint16_t propagation_delay_msec; - uint16_t override_interval_msec; - uint32_t dr_priority; - uint32_t generation_id; - struct list *prefix_list; /* list of struct prefix */ - struct thread *t_expire_timer; - struct interface *interface; + int64_t creation; /* timestamp of creation */ + struct in_addr source_addr; + pim_hello_options hello_options; + uint16_t holdtime; + uint16_t propagation_delay_msec; + uint16_t override_interval_msec; + uint32_t dr_priority; + uint32_t generation_id; + struct list *prefix_list; /* list of struct prefix */ + struct thread *t_expire_timer; + struct interface *interface; - struct thread *jp_timer; - struct list *upstream_jp_agg; - struct bfd_info *bfd_info; + struct thread *jp_timer; + struct list *upstream_jp_agg; + struct bfd_info *bfd_info; }; void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime); void pim_neighbor_free(struct pim_neighbor *neigh); struct pim_neighbor *pim_neighbor_find(struct interface *ifp, struct in_addr source_addr); -struct pim_neighbor *pim_neighbor_find_by_secondary (struct interface *ifp, - struct prefix *src); -struct pim_neighbor *pim_neighbor_find_if (struct interface *ifp); +struct pim_neighbor *pim_neighbor_find_by_secondary(struct interface *ifp, + struct prefix *src); +struct pim_neighbor *pim_neighbor_find_if(struct interface *ifp); #define PIM_NEIGHBOR_SEND_DELAY 0 #define PIM_NEIGHBOR_SEND_NOW 1 -struct pim_neighbor *pim_neighbor_add(struct interface *ifp, - struct in_addr source_addr, - pim_hello_options hello_options, - uint16_t holdtime, - uint16_t propagation_delay, - uint16_t override_interval, - uint32_t dr_priority, - uint32_t generation_id, - struct list *addr_list, - int send_hello_now); -void pim_neighbor_delete(struct interface *ifp, - struct pim_neighbor *neigh, +struct pim_neighbor * +pim_neighbor_add(struct interface *ifp, struct in_addr source_addr, + pim_hello_options hello_options, uint16_t holdtime, + uint16_t propagation_delay, uint16_t override_interval, + uint32_t dr_priority, uint32_t generation_id, + struct list *addr_list, int send_hello_now); +void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh, const char *delete_message); -void pim_neighbor_delete_all(struct interface *ifp, - const char *delete_message); +void pim_neighbor_delete_all(struct interface *ifp, const char *delete_message); void pim_neighbor_update(struct pim_neighbor *neigh, - pim_hello_options hello_options, - uint16_t holdtime, - uint32_t dr_priority, - struct list *addr_list); + pim_hello_options hello_options, uint16_t holdtime, + uint32_t dr_priority, struct list *addr_list); struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh, struct prefix *addr); int pim_if_dr_election(struct interface *ifp); diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index 4aa6ecd5f..f8bf2ac77 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -44,258 +44,247 @@ * pim_sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister * command to Zebra. */ -void -pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc, - int command) +void pim_sendmsg_zebra_rnh(struct zclient *zclient, + struct pim_nexthop_cache *pnc, int command) { - struct stream *s; - struct prefix *p; - int ret; - - /* Check socket. */ - if (!zclient || zclient->sock < 0) - return; - - p = &(pnc->rpf.rpf_addr); - s = zclient->obuf; - stream_reset (s); - zclient_create_header (s, command, VRF_DEFAULT); - /* get update for all routes for a prefix */ - stream_putc (s, 0); - - stream_putw (s, PREFIX_FAMILY (p)); - stream_putc (s, p->prefixlen); - switch (PREFIX_FAMILY (p)) - { - case AF_INET: - stream_put_in_addr (s, &p->u.prefix4); - break; - case AF_INET6: - stream_put (s, &(p->u.prefix6), 16); - break; - default: - break; - } - stream_putw_at (s, 0, stream_get_endp (s)); - - ret = zclient_send_message (zclient); - if (ret < 0) - zlog_warn ("sendmsg_nexthop: zclient_send_message() failed"); - - - if (PIM_DEBUG_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (p, buf, sizeof (buf)); - zlog_debug ("%s: NHT %sregistered addr %s with Zebra ret:%d ", - __PRETTY_FUNCTION__, - (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de", buf, ret); - } - - return; + struct stream *s; + struct prefix *p; + int ret; + + /* Check socket. */ + if (!zclient || zclient->sock < 0) + return; + + p = &(pnc->rpf.rpf_addr); + s = zclient->obuf; + stream_reset(s); + zclient_create_header(s, command, VRF_DEFAULT); + /* get update for all routes for a prefix */ + stream_putc(s, 0); + + stream_putw(s, PREFIX_FAMILY(p)); + stream_putc(s, p->prefixlen); + switch (PREFIX_FAMILY(p)) { + case AF_INET: + stream_put_in_addr(s, &p->u.prefix4); + break; + case AF_INET6: + stream_put(s, &(p->u.prefix6), 16); + break; + default: + break; + } + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = zclient_send_message(zclient); + if (ret < 0) + zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); + + + if (PIM_DEBUG_TRACE) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(p, buf, sizeof(buf)); + zlog_debug("%s: NHT %sregistered addr %s with Zebra ret:%d ", + __PRETTY_FUNCTION__, + (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de", + buf, ret); + } + + return; } -struct pim_nexthop_cache * -pim_nexthop_cache_find (struct pim_rpf *rpf) +struct pim_nexthop_cache *pim_nexthop_cache_find(struct pim_rpf *rpf) { - struct pim_nexthop_cache *pnc = NULL; - struct pim_nexthop_cache lookup; + struct pim_nexthop_cache *pnc = NULL; + struct pim_nexthop_cache lookup; - lookup.rpf.rpf_addr.family = rpf->rpf_addr.family; - lookup.rpf.rpf_addr.prefixlen = rpf->rpf_addr.prefixlen; - lookup.rpf.rpf_addr.u.prefix4.s_addr = rpf->rpf_addr.u.prefix4.s_addr; + lookup.rpf.rpf_addr.family = rpf->rpf_addr.family; + lookup.rpf.rpf_addr.prefixlen = rpf->rpf_addr.prefixlen; + lookup.rpf.rpf_addr.u.prefix4.s_addr = rpf->rpf_addr.u.prefix4.s_addr; - pnc = hash_lookup (pimg->rpf_hash, &lookup); - - return pnc; + pnc = hash_lookup(pimg->rpf_hash, &lookup); + return pnc; } -struct pim_nexthop_cache * -pim_nexthop_cache_add (struct pim_rpf *rpf_addr) +struct pim_nexthop_cache *pim_nexthop_cache_add(struct pim_rpf *rpf_addr) { - struct pim_nexthop_cache *pnc; - - pnc = XCALLOC (MTYPE_PIM_NEXTHOP_CACHE, sizeof (struct pim_nexthop_cache)); - if (!pnc) - { - zlog_err ("%s: NHT PIM XCALLOC failure ", __PRETTY_FUNCTION__); - return NULL; - } - pnc->rpf.rpf_addr.family = rpf_addr->rpf_addr.family; - pnc->rpf.rpf_addr.prefixlen = rpf_addr->rpf_addr.prefixlen; - pnc->rpf.rpf_addr.u.prefix4.s_addr = rpf_addr->rpf_addr.u.prefix4.s_addr; - - pnc = hash_get (pimg->rpf_hash, pnc, hash_alloc_intern); - - pnc->rp_list = list_new (); - pnc->rp_list->cmp = pim_rp_list_cmp; - - pnc->upstream_list = list_new (); - pnc->upstream_list->cmp = pim_upstream_compare; - - if (PIM_DEBUG_ZEBRA) - { - char rpf_str[PREFIX_STRLEN]; - pim_addr_dump ("<nht?>", &rpf_addr->rpf_addr, rpf_str, - sizeof (rpf_str)); - zlog_debug ("%s: NHT hash node, RP and UP lists allocated for %s ", - __PRETTY_FUNCTION__, rpf_str); - } - - return pnc; + struct pim_nexthop_cache *pnc; + + pnc = XCALLOC(MTYPE_PIM_NEXTHOP_CACHE, + sizeof(struct pim_nexthop_cache)); + if (!pnc) { + zlog_err("%s: NHT PIM XCALLOC failure ", __PRETTY_FUNCTION__); + return NULL; + } + pnc->rpf.rpf_addr.family = rpf_addr->rpf_addr.family; + pnc->rpf.rpf_addr.prefixlen = rpf_addr->rpf_addr.prefixlen; + pnc->rpf.rpf_addr.u.prefix4.s_addr = + rpf_addr->rpf_addr.u.prefix4.s_addr; + + pnc = hash_get(pimg->rpf_hash, pnc, hash_alloc_intern); + + pnc->rp_list = list_new(); + pnc->rp_list->cmp = pim_rp_list_cmp; + + pnc->upstream_list = list_new(); + pnc->upstream_list->cmp = pim_upstream_compare; + + if (PIM_DEBUG_ZEBRA) { + char rpf_str[PREFIX_STRLEN]; + pim_addr_dump("<nht?>", &rpf_addr->rpf_addr, rpf_str, + sizeof(rpf_str)); + zlog_debug( + "%s: NHT hash node, RP and UP lists allocated for %s ", + __PRETTY_FUNCTION__, rpf_str); + } + + return pnc; } /* This API is used to Register an address with Zebra ret 1 means nexthop cache is found. */ -int -pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, - struct rp_info *rp, - struct pim_nexthop_cache *out_pnc) +int pim_find_or_track_nexthop(struct prefix *addr, struct pim_upstream *up, + struct rp_info *rp, + struct pim_nexthop_cache *out_pnc) { - struct pim_nexthop_cache *pnc = NULL; - struct pim_rpf rpf; - struct listnode *ch_node = NULL; - struct zclient *zclient = NULL; - - zclient = pim_zebra_zclient_get (); - memset (&rpf, 0, sizeof (struct pim_rpf)); - rpf.rpf_addr.family = addr->family; - rpf.rpf_addr.prefixlen = addr->prefixlen; - rpf.rpf_addr.u.prefix4 = addr->u.prefix4; - - pnc = pim_nexthop_cache_find (&rpf); - if (!pnc) - { - pnc = pim_nexthop_cache_add (&rpf); - if (pnc) - pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_REGISTER); - else - { - char rpf_str[PREFIX_STRLEN]; - pim_addr_dump ("<nht-pnc?>", addr, rpf_str, sizeof (rpf_str)); - zlog_warn ("%s: pnc node allocation failed. addr %s ", - __PRETTY_FUNCTION__, rpf_str); - return -1; - } - } - - if (rp != NULL) - { - ch_node = listnode_lookup (pnc->rp_list, rp); - if (ch_node == NULL) - { - if (PIM_DEBUG_ZEBRA) - { - char rp_str[PREFIX_STRLEN]; - pim_addr_dump ("<rp?>", &rp->rp.rpf_addr, rp_str, - sizeof (rp_str)); - zlog_debug ("%s: Add RP %s node to pnc cached list", - __PRETTY_FUNCTION__, rp_str); - } - listnode_add_sort (pnc->rp_list, rp); - } - } - - if (up != NULL) - { - ch_node = listnode_lookup (pnc->upstream_list, up); - if (ch_node == NULL) - { - if (PIM_DEBUG_ZEBRA) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (addr, buf, sizeof (buf)); - zlog_debug ("%s: Add upstream %s node to pnc cached list, rpf %s", - __PRETTY_FUNCTION__, up->sg_str, buf); - } - listnode_add_sort (pnc->upstream_list, up); - } - } - - if (pnc && CHECK_FLAG (pnc->flags, PIM_NEXTHOP_VALID)) - { - memcpy (out_pnc, pnc, sizeof (struct pim_nexthop_cache)); - return 1; - } - - return 0; + struct pim_nexthop_cache *pnc = NULL; + struct pim_rpf rpf; + struct listnode *ch_node = NULL; + struct zclient *zclient = NULL; + + zclient = pim_zebra_zclient_get(); + memset(&rpf, 0, sizeof(struct pim_rpf)); + rpf.rpf_addr.family = addr->family; + rpf.rpf_addr.prefixlen = addr->prefixlen; + rpf.rpf_addr.u.prefix4 = addr->u.prefix4; + + pnc = pim_nexthop_cache_find(&rpf); + if (!pnc) { + pnc = pim_nexthop_cache_add(&rpf); + if (pnc) + pim_sendmsg_zebra_rnh(zclient, pnc, + ZEBRA_NEXTHOP_REGISTER); + else { + char rpf_str[PREFIX_STRLEN]; + pim_addr_dump("<nht-pnc?>", addr, rpf_str, + sizeof(rpf_str)); + zlog_warn("%s: pnc node allocation failed. addr %s ", + __PRETTY_FUNCTION__, rpf_str); + return -1; + } + } + + if (rp != NULL) { + ch_node = listnode_lookup(pnc->rp_list, rp); + if (ch_node == NULL) { + if (PIM_DEBUG_ZEBRA) { + char rp_str[PREFIX_STRLEN]; + pim_addr_dump("<rp?>", &rp->rp.rpf_addr, rp_str, + sizeof(rp_str)); + zlog_debug( + "%s: Add RP %s node to pnc cached list", + __PRETTY_FUNCTION__, rp_str); + } + listnode_add_sort(pnc->rp_list, rp); + } + } + + if (up != NULL) { + ch_node = listnode_lookup(pnc->upstream_list, up); + if (ch_node == NULL) { + if (PIM_DEBUG_ZEBRA) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(addr, buf, sizeof(buf)); + zlog_debug( + "%s: Add upstream %s node to pnc cached list, rpf %s", + __PRETTY_FUNCTION__, up->sg_str, buf); + } + listnode_add_sort(pnc->upstream_list, up); + } + } + + if (pnc && CHECK_FLAG(pnc->flags, PIM_NEXTHOP_VALID)) { + memcpy(out_pnc, pnc, sizeof(struct pim_nexthop_cache)); + return 1; + } + + return 0; } -void -pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up, - struct rp_info *rp) +void pim_delete_tracked_nexthop(struct prefix *addr, struct pim_upstream *up, + struct rp_info *rp) { - struct pim_nexthop_cache *pnc = NULL; - struct pim_nexthop_cache lookup; - struct zclient *zclient = NULL; - - zclient = pim_zebra_zclient_get (); - - /* Remove from RPF hash if it is the last entry */ - lookup.rpf.rpf_addr = *addr; - pnc = hash_lookup (pimg->rpf_hash, &lookup); - if (pnc) - { - if (rp) - listnode_delete (pnc->rp_list, rp); - if (up) - listnode_delete (pnc->upstream_list, up); - - if (PIM_DEBUG_ZEBRA) - zlog_debug ("%s: NHT rp_list count:%d upstream_list count:%d ", - __PRETTY_FUNCTION__, pnc->rp_list->count, - pnc->upstream_list->count); - - if (pnc->rp_list->count == 0 && pnc->upstream_list->count == 0) - { - pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_UNREGISTER); - - list_delete (pnc->rp_list); - list_delete (pnc->upstream_list); - - hash_release (pimg->rpf_hash, pnc); - if (pnc->nexthop) - nexthops_free (pnc->nexthop); - XFREE (MTYPE_PIM_NEXTHOP_CACHE, pnc); - } - } + struct pim_nexthop_cache *pnc = NULL; + struct pim_nexthop_cache lookup; + struct zclient *zclient = NULL; + + zclient = pim_zebra_zclient_get(); + + /* Remove from RPF hash if it is the last entry */ + lookup.rpf.rpf_addr = *addr; + pnc = hash_lookup(pimg->rpf_hash, &lookup); + if (pnc) { + if (rp) + listnode_delete(pnc->rp_list, rp); + if (up) + listnode_delete(pnc->upstream_list, up); + + if (PIM_DEBUG_ZEBRA) + zlog_debug( + "%s: NHT rp_list count:%d upstream_list count:%d ", + __PRETTY_FUNCTION__, pnc->rp_list->count, + pnc->upstream_list->count); + + if (pnc->rp_list->count == 0 + && pnc->upstream_list->count == 0) { + pim_sendmsg_zebra_rnh(zclient, pnc, + ZEBRA_NEXTHOP_UNREGISTER); + + list_delete(pnc->rp_list); + list_delete(pnc->upstream_list); + + hash_release(pimg->rpf_hash, pnc); + if (pnc->nexthop) + nexthops_free(pnc->nexthop); + XFREE(MTYPE_PIM_NEXTHOP_CACHE, pnc); + } + } } /* Update RP nexthop info based on Nexthop update received from Zebra.*/ -int -pim_update_rp_nh (struct pim_nexthop_cache *pnc) +int pim_update_rp_nh(struct pim_nexthop_cache *pnc) { - struct listnode *node = NULL; - struct rp_info *rp_info = NULL; - int ret = 0; - - /*Traverse RP list and update each RP Nexthop info */ - for (ALL_LIST_ELEMENTS_RO (pnc->rp_list, node, rp_info)) - { - if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) - continue; - - //Compute PIM RPF using cached nexthop - ret = pim_ecmp_nexthop_search (pnc, &rp_info->rp.source_nexthop, - &rp_info->rp.rpf_addr, &rp_info->group, 1); - - if (PIM_DEBUG_TRACE) - { - char rp_str[PREFIX_STRLEN]; - pim_addr_dump ("<rp?>", &rp_info->rp.rpf_addr, rp_str, - sizeof (rp_str)); - zlog_debug ("%s: NHT update, nexthop for RP %s is interface %s ", - __PRETTY_FUNCTION__, rp_str, - rp_info->rp.source_nexthop.interface->name); - } - } - - if (ret) - return 0; - - return 1; + struct listnode *node = NULL; + struct rp_info *rp_info = NULL; + int ret = 0; + + /*Traverse RP list and update each RP Nexthop info */ + for (ALL_LIST_ELEMENTS_RO(pnc->rp_list, node, rp_info)) { + if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) + continue; + + // Compute PIM RPF using cached nexthop + ret = pim_ecmp_nexthop_search(pnc, &rp_info->rp.source_nexthop, + &rp_info->rp.rpf_addr, + &rp_info->group, 1); + + if (PIM_DEBUG_TRACE) { + char rp_str[PREFIX_STRLEN]; + pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr, rp_str, + sizeof(rp_str)); + zlog_debug( + "%s: NHT update, nexthop for RP %s is interface %s ", + __PRETTY_FUNCTION__, rp_str, + rp_info->rp.source_nexthop.interface->name); + } + } + + if (ret) + return 0; + + return 1; } /* This API is used to traverse nexthop cache of RPF addr @@ -303,771 +292,779 @@ pim_update_rp_nh (struct pim_nexthop_cache *pnc) unresolved state and due to event like pim neighbor UP event if it can be resolved. */ -void -pim_resolve_upstream_nh (struct prefix *nht_p) +void pim_resolve_upstream_nh(struct prefix *nht_p) { - struct nexthop *nh_node = NULL; - struct pim_nexthop_cache pnc; - struct pim_neighbor *nbr = NULL; - - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - if ((pim_find_or_track_nexthop (nht_p, NULL, NULL, &pnc)) == 1) - { - for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) - { - if (nh_node->gate.ipv4.s_addr == 0) - { - struct interface *ifp1 = if_lookup_by_index(nh_node->ifindex, - VRF_DEFAULT); - nbr = pim_neighbor_find_if (ifp1); - if (nbr) - { - nh_node->gate.ipv4 = nbr->source_addr; - if (PIM_DEBUG_TRACE) - { - char str[PREFIX_STRLEN]; - char str1[INET_ADDRSTRLEN]; - pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, str1, - sizeof (str1)); - pim_addr_dump ("<nht_addr?>", nht_p, str, sizeof (str)); - zlog_debug ("%s: addr %s new nexthop addr %s interface %s", - __PRETTY_FUNCTION__, str, str1, ifp1->name); - } - } - } - } - } + struct nexthop *nh_node = NULL; + struct pim_nexthop_cache pnc; + struct pim_neighbor *nbr = NULL; + + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop(nht_p, NULL, NULL, &pnc)) == 1) { + for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) { + if (nh_node->gate.ipv4.s_addr == 0) { + struct interface *ifp1 = if_lookup_by_index( + nh_node->ifindex, VRF_DEFAULT); + nbr = pim_neighbor_find_if(ifp1); + if (nbr) { + nh_node->gate.ipv4 = nbr->source_addr; + if (PIM_DEBUG_TRACE) { + char str[PREFIX_STRLEN]; + char str1[INET_ADDRSTRLEN]; + pim_inet4_dump("<nht_nbr?>", + nbr->source_addr, + str1, + sizeof(str1)); + pim_addr_dump("<nht_addr?>", + nht_p, str, + sizeof(str)); + zlog_debug( + "%s: addr %s new nexthop addr %s interface %s", + __PRETTY_FUNCTION__, + str, str1, ifp1->name); + } + } + } + } + } } /* Update Upstream nexthop info based on Nexthop update received from Zebra.*/ -static int -pim_update_upstream_nh (struct pim_nexthop_cache *pnc) +static int pim_update_upstream_nh(struct pim_nexthop_cache *pnc) { - struct listnode *up_node; - struct listnode *ifnode; - struct listnode *up_nextnode; - struct listnode *node; - struct pim_upstream *up = NULL; - struct interface *ifp = NULL; - int vif_index = 0; - - for (ALL_LIST_ELEMENTS (pnc->upstream_list, up_node, up_nextnode, up)) - { - enum pim_rpf_result rpf_result; - struct pim_rpf old; - - old.source_nexthop.interface = up->rpf.source_nexthop.interface; - rpf_result = pim_rpf_update (up, &old, 0); - if (rpf_result == PIM_RPF_FAILURE) - continue; - - /* update kernel multicast forwarding cache (MFC) */ - if (up->channel_oil) - { - ifindex_t ifindex = up->rpf.source_nexthop.interface->ifindex; - vif_index = pim_if_find_vifindex_by_ifindex (ifindex); - /* Pass Current selected NH vif index to mroute download */ - if (vif_index) - pim_scan_individual_oil (up->channel_oil, vif_index); - else - { - if (PIM_DEBUG_ZEBRA) - zlog_debug ("%s: NHT upstream %s channel_oil IIF %s vif_index is not valid", - __PRETTY_FUNCTION__, up->sg_str, - up->rpf.source_nexthop.interface->name); - } - } - - if (rpf_result == PIM_RPF_CHANGED) - { - struct pim_neighbor *nbr; - - nbr = pim_neighbor_find (old.source_nexthop.interface, - old.rpf_addr.u.prefix4); - if (nbr) - pim_jp_agg_remove_group (nbr->upstream_jp_agg, up); - - /* - * We have detected a case where we might need to rescan - * the inherited o_list so do it. - */ - if (up->channel_oil && up->channel_oil->oil_inherited_rescan) - { - pim_upstream_inherited_olist_decide (up); - up->channel_oil->oil_inherited_rescan = 0; - } - - if (up->join_state == PIM_UPSTREAM_JOINED) - { - /* - * If we come up real fast we can be here - * where the mroute has not been installed - * so install it. - */ - if (up->channel_oil && !up->channel_oil->installed) - pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); - - /* - RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages - - Transitions from Joined State - - RPF'(S,G) changes not due to an Assert - - The upstream (S,G) state machine remains in Joined - state. Send Join(S,G) to the new upstream neighbor, which is - the new value of RPF'(S,G). Send Prune(S,G) to the old - upstream neighbor, which is the old value of RPF'(S,G). Set - the Join Timer (JT) to expire after t_periodic seconds. - */ - pim_jp_agg_switch_interface (&old, &up->rpf, up); - - pim_upstream_join_timer_restart (up, &old); - } /* up->join_state == PIM_UPSTREAM_JOINED */ - - /* FIXME can join_desired actually be changed by pim_rpf_update() - returning PIM_RPF_CHANGED ? */ - pim_upstream_update_join_desired (up); - - } /* PIM_RPF_CHANGED */ - - if (PIM_DEBUG_TRACE) - { - zlog_debug ("%s: NHT upstream %s old ifp %s new ifp %s", - __PRETTY_FUNCTION__, up->sg_str, - old.source_nexthop.interface->name, - up->rpf.source_nexthop.interface->name); - } - } /* for (pnc->upstream_list) */ - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) - if (ifp->info) - { - struct pim_interface *pim_ifp = ifp->info; - struct pim_iface_upstream_switch *us; - - for (ALL_LIST_ELEMENTS_RO (pim_ifp->upstream_switch_list, node, us)) - { - struct pim_rpf rpf; - rpf.source_nexthop.interface = ifp; - rpf.rpf_addr.u.prefix4 = us->address; - pim_joinprune_send (&rpf, us->us); - pim_jp_agg_clear_group (us->us); - } - } - - return 0; + struct listnode *up_node; + struct listnode *ifnode; + struct listnode *up_nextnode; + struct listnode *node; + struct pim_upstream *up = NULL; + struct interface *ifp = NULL; + int vif_index = 0; + + for (ALL_LIST_ELEMENTS(pnc->upstream_list, up_node, up_nextnode, up)) { + enum pim_rpf_result rpf_result; + struct pim_rpf old; + + old.source_nexthop.interface = up->rpf.source_nexthop.interface; + rpf_result = pim_rpf_update(up, &old, 0); + if (rpf_result == PIM_RPF_FAILURE) + continue; + + /* update kernel multicast forwarding cache (MFC) */ + if (up->channel_oil) { + ifindex_t ifindex = + up->rpf.source_nexthop.interface->ifindex; + vif_index = pim_if_find_vifindex_by_ifindex(ifindex); + /* Pass Current selected NH vif index to mroute download + */ + if (vif_index) + pim_scan_individual_oil(up->channel_oil, + vif_index); + else { + if (PIM_DEBUG_ZEBRA) + zlog_debug( + "%s: NHT upstream %s channel_oil IIF %s vif_index is not valid", + __PRETTY_FUNCTION__, up->sg_str, + up->rpf.source_nexthop + .interface->name); + } + } + + if (rpf_result == PIM_RPF_CHANGED) { + struct pim_neighbor *nbr; + + nbr = pim_neighbor_find(old.source_nexthop.interface, + old.rpf_addr.u.prefix4); + if (nbr) + pim_jp_agg_remove_group(nbr->upstream_jp_agg, + up); + + /* + * We have detected a case where we might need to rescan + * the inherited o_list so do it. + */ + if (up->channel_oil + && up->channel_oil->oil_inherited_rescan) { + pim_upstream_inherited_olist_decide(up); + up->channel_oil->oil_inherited_rescan = 0; + } + + if (up->join_state == PIM_UPSTREAM_JOINED) { + /* + * If we come up real fast we can be here + * where the mroute has not been installed + * so install it. + */ + if (up->channel_oil + && !up->channel_oil->installed) + pim_mroute_add(up->channel_oil, + __PRETTY_FUNCTION__); + + /* + RFC 4601: 4.5.7. Sending (S,G) Join/Prune + Messages + + Transitions from Joined State + + RPF'(S,G) changes not due to an Assert + + The upstream (S,G) state machine remains in + Joined + state. Send Join(S,G) to the new upstream + neighbor, which is + the new value of RPF'(S,G). Send Prune(S,G) + to the old + upstream neighbor, which is the old value of + RPF'(S,G). Set + the Join Timer (JT) to expire after + t_periodic seconds. + */ + pim_jp_agg_switch_interface(&old, &up->rpf, up); + + pim_upstream_join_timer_restart(up, &old); + } /* up->join_state == PIM_UPSTREAM_JOINED */ + + /* FIXME can join_desired actually be changed by + pim_rpf_update() + returning PIM_RPF_CHANGED ? */ + pim_upstream_update_join_desired(up); + + } /* PIM_RPF_CHANGED */ + + if (PIM_DEBUG_TRACE) { + zlog_debug("%s: NHT upstream %s old ifp %s new ifp %s", + __PRETTY_FUNCTION__, up->sg_str, + old.source_nexthop.interface->name, + up->rpf.source_nexthop.interface->name); + } + } /* for (pnc->upstream_list) */ + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) + if (ifp->info) { + struct pim_interface *pim_ifp = ifp->info; + struct pim_iface_upstream_switch *us; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, + node, us)) { + struct pim_rpf rpf; + rpf.source_nexthop.interface = ifp; + rpf.rpf_addr.u.prefix4 = us->address; + pim_joinprune_send(&rpf, us->us); + pim_jp_agg_clear_group(us->us); + } + } + + return 0; } -uint32_t -pim_compute_ecmp_hash (struct prefix * src, struct prefix * grp) +uint32_t pim_compute_ecmp_hash(struct prefix *src, struct prefix *grp) { - uint32_t hash_val; - uint32_t s = 0, g = 0; - - if ((!src)) - return 0; - - switch (src->family) - { - case AF_INET: - { - s = src->u.prefix4.s_addr; - s = s == 0 ? 1 : s; - if (grp) - g = grp->u.prefix4.s_addr; - } - break; - default: - break; - } - - hash_val = jhash_2words (g, s, 101); - if (PIM_DEBUG_PIM_TRACE_DETAIL) - { - char buf[PREFIX2STR_BUFFER]; - char bufg[PREFIX2STR_BUFFER]; - prefix2str (src, buf, sizeof (buf)); - if (grp) - prefix2str (grp, bufg, sizeof (bufg)); - zlog_debug ("%s: addr %s %s hash_val %u", __PRETTY_FUNCTION__, buf, - grp ? bufg : "", hash_val); - - } - return hash_val; + uint32_t hash_val; + uint32_t s = 0, g = 0; + + if ((!src)) + return 0; + + switch (src->family) { + case AF_INET: { + s = src->u.prefix4.s_addr; + s = s == 0 ? 1 : s; + if (grp) + g = grp->u.prefix4.s_addr; + } break; + default: + break; + } + + hash_val = jhash_2words(g, s, 101); + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + char buf[PREFIX2STR_BUFFER]; + char bufg[PREFIX2STR_BUFFER]; + prefix2str(src, buf, sizeof(buf)); + if (grp) + prefix2str(grp, bufg, sizeof(bufg)); + zlog_debug("%s: addr %s %s hash_val %u", __PRETTY_FUNCTION__, + buf, grp ? bufg : "", hash_val); + } + return hash_val; } -int -pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc, - struct pim_nexthop *nexthop, struct prefix *src, - struct prefix *grp, int neighbor_needed) +int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc, + struct pim_nexthop *nexthop, struct prefix *src, + struct prefix *grp, int neighbor_needed) { - struct pim_neighbor *nbr = NULL; - struct nexthop *nh_node = NULL; - ifindex_t first_ifindex; - struct interface *ifp = NULL; - uint32_t hash_val = 0, mod_val = 0; - uint8_t nh_iter = 0, found = 0; - - if (!pnc || !pnc->nexthop_num || !nexthop) - return -1; - - //Current Nexthop is VALID, check to stay on the current path. - if (nexthop->interface && nexthop->interface->info && - nexthop->mrib_nexthop_addr.u.prefix4.s_addr != - PIM_NET_INADDR_ANY) - { - /* User configured knob to explicitly switch - to new path is disabled or current path - metric is less than nexthop update. - */ - - if (qpim_ecmp_rebalance_enable == 0) - { - uint8_t curr_route_valid = 0; - //Check if current nexthop is present in new updated Nexthop list. - //If the current nexthop is not valid, candidate to choose new Nexthop. - for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) - curr_route_valid = (nexthop->interface->ifindex == nh_node->ifindex); - - if (curr_route_valid && - !pim_if_connected_to_source (nexthop->interface, - src->u.prefix4)) - { - nbr = pim_neighbor_find (nexthop->interface, - nexthop->mrib_nexthop_addr.u.prefix4); - if (!nbr && !if_is_loopback (nexthop->interface)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: current nexthop does not have nbr ", - __PRETTY_FUNCTION__); - } - else - { - if (PIM_DEBUG_TRACE) - { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("<addr?>", src->u.prefix4, src_str, - sizeof (src_str)); - char grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("<addr?>", grp->u.prefix4, grp_str, - sizeof (grp_str)); - zlog_debug ("%s: (%s, %s) current nexthop %s is valid, skipping new path selection", - __PRETTY_FUNCTION__, src_str, grp_str, - nexthop->interface->name); - } - return 0; - } - } - } - } - if (qpim_ecmp_enable) - { - //PIM ECMP flag is enable then choose ECMP path. - hash_val = pim_compute_ecmp_hash (src, grp); - mod_val = hash_val % pnc->nexthop_num; - if (PIM_DEBUG_PIM_TRACE_DETAIL) - zlog_debug ("%s: hash_val %u mod_val %u ", - __PRETTY_FUNCTION__, hash_val, mod_val); - } - - for (nh_node = pnc->nexthop; nh_node && (found == 0); - nh_node = nh_node->next) - { - first_ifindex = nh_node->ifindex; - ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); - if (!ifp) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("<addr?>", src->u.prefix4, addr_str, - sizeof (addr_str)); - zlog_debug ("%s %s: could not find interface for ifindex %d (address %s)", - __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str); - } - if (nh_iter == mod_val) - mod_val++; //Select nexthpath - nh_iter++; - continue; - } - if (!ifp->info) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("<addr?>", src->u.prefix4, addr_str, - sizeof (addr_str)); - zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", - __PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str); - } - if (nh_iter == mod_val) - mod_val++; //Select nexthpath - nh_iter++; - continue; - } - - if (neighbor_needed - && !pim_if_connected_to_source (ifp, src->u.prefix4)) - { - nbr = pim_neighbor_find (ifp, nh_node->gate.ipv4); - if (PIM_DEBUG_PIM_TRACE_DETAIL) - zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); - if (!nbr && !if_is_loopback (ifp)) - { - if (PIM_DEBUG_ZEBRA) - zlog_debug ("%s: pim nbr not found on input interface %s", - __PRETTY_FUNCTION__, ifp->name); - if (nh_iter == mod_val) - mod_val++; //Select nexthpath - nh_iter++; - continue; - } - } - - if (nh_iter == mod_val) - { - nexthop->interface = ifp; - nexthop->mrib_nexthop_addr.family = AF_INET; - nexthop->mrib_nexthop_addr.prefixlen = IPV4_MAX_BITLEN; - nexthop->mrib_nexthop_addr.u.prefix4 = nh_node->gate.ipv4; - nexthop->mrib_metric_preference = pnc->distance; - nexthop->mrib_route_metric = pnc->metric; - nexthop->last_lookup = src->u.prefix4; - nexthop->last_lookup_time = pim_time_monotonic_usec (); - nexthop->nbr = nbr; - found = 1; - if (PIM_DEBUG_ZEBRA) - { - char buf[INET_ADDRSTRLEN]; - char buf2[INET_ADDRSTRLEN]; - char buf3[INET_ADDRSTRLEN]; - pim_inet4_dump ("<src?>", src->u.prefix4, buf2, sizeof (buf2)); - pim_inet4_dump ("<grp?>", grp->u.prefix4, buf3, sizeof (buf3)); - pim_inet4_dump ("<rpf?>", - nexthop->mrib_nexthop_addr.u.prefix4, buf, - sizeof (buf)); - zlog_debug ("%s: (%s, %s) selected nhop interface %s addr %s mod_val %u iter %d ecmp %d", - __PRETTY_FUNCTION__, buf2, buf3, ifp->name, - buf, mod_val, nh_iter, qpim_ecmp_enable); - } - } - nh_iter++; - } - - if (found) - return 0; - else - return -1; + struct pim_neighbor *nbr = NULL; + struct nexthop *nh_node = NULL; + ifindex_t first_ifindex; + struct interface *ifp = NULL; + uint32_t hash_val = 0, mod_val = 0; + uint8_t nh_iter = 0, found = 0; + + if (!pnc || !pnc->nexthop_num || !nexthop) + return -1; + + // Current Nexthop is VALID, check to stay on the current path. + if (nexthop->interface && nexthop->interface->info + && nexthop->mrib_nexthop_addr.u.prefix4.s_addr + != PIM_NET_INADDR_ANY) { + /* User configured knob to explicitly switch + to new path is disabled or current path + metric is less than nexthop update. + */ + + if (qpim_ecmp_rebalance_enable == 0) { + uint8_t curr_route_valid = 0; + // Check if current nexthop is present in new updated + // Nexthop list. + // If the current nexthop is not valid, candidate to + // choose new Nexthop. + for (nh_node = pnc->nexthop; nh_node; + nh_node = nh_node->next) + curr_route_valid = (nexthop->interface->ifindex + == nh_node->ifindex); + + if (curr_route_valid + && !pim_if_connected_to_source(nexthop->interface, + src->u.prefix4)) { + nbr = pim_neighbor_find( + nexthop->interface, + nexthop->mrib_nexthop_addr.u.prefix4); + if (!nbr + && !if_is_loopback(nexthop->interface)) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: current nexthop does not have nbr ", + __PRETTY_FUNCTION__); + } else { + if (PIM_DEBUG_TRACE) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", + src->u.prefix4, + src_str, + sizeof(src_str)); + char grp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", + grp->u.prefix4, + grp_str, + sizeof(grp_str)); + zlog_debug( + "%s: (%s, %s) current nexthop %s is valid, skipping new path selection", + __PRETTY_FUNCTION__, + src_str, grp_str, + nexthop->interface->name); + } + return 0; + } + } + } + } + if (qpim_ecmp_enable) { + // PIM ECMP flag is enable then choose ECMP path. + hash_val = pim_compute_ecmp_hash(src, grp); + mod_val = hash_val % pnc->nexthop_num; + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug("%s: hash_val %u mod_val %u ", + __PRETTY_FUNCTION__, hash_val, mod_val); + } + + for (nh_node = pnc->nexthop; nh_node && (found == 0); + nh_node = nh_node->next) { + first_ifindex = nh_node->ifindex; + ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); + if (!ifp) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", src->u.prefix4, + addr_str, sizeof(addr_str)); + zlog_debug( + "%s %s: could not find interface for ifindex %d (address %s)", + __FILE__, __PRETTY_FUNCTION__, + first_ifindex, addr_str); + } + if (nh_iter == mod_val) + mod_val++; // Select nexthpath + nh_iter++; + continue; + } + if (!ifp->info) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", src->u.prefix4, + addr_str, sizeof(addr_str)); + zlog_debug( + "%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", + __PRETTY_FUNCTION__, ifp->name, + first_ifindex, addr_str); + } + if (nh_iter == mod_val) + mod_val++; // Select nexthpath + nh_iter++; + continue; + } + + if (neighbor_needed + && !pim_if_connected_to_source(ifp, src->u.prefix4)) { + nbr = pim_neighbor_find(ifp, nh_node->gate.ipv4); + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug("ifp name: %s, pim nbr: %p", + ifp->name, nbr); + if (!nbr && !if_is_loopback(ifp)) { + if (PIM_DEBUG_ZEBRA) + zlog_debug( + "%s: pim nbr not found on input interface %s", + __PRETTY_FUNCTION__, ifp->name); + if (nh_iter == mod_val) + mod_val++; // Select nexthpath + nh_iter++; + continue; + } + } + + if (nh_iter == mod_val) { + nexthop->interface = ifp; + nexthop->mrib_nexthop_addr.family = AF_INET; + nexthop->mrib_nexthop_addr.prefixlen = IPV4_MAX_BITLEN; + nexthop->mrib_nexthop_addr.u.prefix4 = + nh_node->gate.ipv4; + nexthop->mrib_metric_preference = pnc->distance; + nexthop->mrib_route_metric = pnc->metric; + nexthop->last_lookup = src->u.prefix4; + nexthop->last_lookup_time = pim_time_monotonic_usec(); + nexthop->nbr = nbr; + found = 1; + if (PIM_DEBUG_ZEBRA) { + char buf[INET_ADDRSTRLEN]; + char buf2[INET_ADDRSTRLEN]; + char buf3[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src->u.prefix4, buf2, + sizeof(buf2)); + pim_inet4_dump("<grp?>", grp->u.prefix4, buf3, + sizeof(buf3)); + pim_inet4_dump( + "<rpf?>", + nexthop->mrib_nexthop_addr.u.prefix4, + buf, sizeof(buf)); + zlog_debug( + "%s: (%s, %s) selected nhop interface %s addr %s mod_val %u iter %d ecmp %d", + __PRETTY_FUNCTION__, buf2, buf3, + ifp->name, buf, mod_val, nh_iter, + qpim_ecmp_enable); + } + } + nh_iter++; + } + + if (found) + return 0; + else + return -1; } -/* This API is used to parse Registered address nexthop update coming from Zebra */ -int -pim_parse_nexthop_update (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +/* This API is used to parse Registered address nexthop update coming from Zebra + */ +int pim_parse_nexthop_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct prefix p; - struct nexthop *nexthop; - struct nexthop *nhlist_head = NULL; - struct nexthop *nhlist_tail = NULL; - uint32_t metric, distance; - u_char nexthop_num = 0; - int i; - struct pim_rpf rpf; - struct pim_nexthop_cache *pnc = NULL; - struct pim_neighbor *nbr = NULL; - struct interface *ifp = NULL; - struct interface *ifp1 = NULL; - struct pim_interface *pim_ifp = NULL; - char str[INET_ADDRSTRLEN]; - - s = zclient->ibuf; - memset (&p, 0, sizeof (struct prefix)); - p.family = stream_getw (s); - p.prefixlen = stream_getc (s); - switch (p.family) - { - case AF_INET: - p.u.prefix4.s_addr = stream_get_ipv4 (s); - break; - case AF_INET6: - stream_get (&p.u.prefix6, s, 16); - break; - default: - break; - } - - if (command == ZEBRA_NEXTHOP_UPDATE) - { - rpf.rpf_addr.family = p.family; - rpf.rpf_addr.prefixlen = p.prefixlen; - rpf.rpf_addr.u.prefix4.s_addr = p.u.prefix4.s_addr; - pnc = pim_nexthop_cache_find (&rpf); - if (!pnc) - { - if (PIM_DEBUG_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&rpf.rpf_addr, buf, sizeof (buf)); - zlog_debug ("%s: Skipping NHT update, addr %s is not in local cached DB.", - __PRETTY_FUNCTION__, buf); - } - return 0; - } - } - else - { - /* - * We do not currently handle ZEBRA_IMPORT_CHECK_UPDATE - */ - return 0; - } - - pnc->last_update = pim_time_monotonic_usec (); - distance = stream_getc (s); - metric = stream_getl (s); - nexthop_num = stream_getc (s); - - if (nexthop_num) - { - pnc->nexthop_num = 0; //Only increment for pim enabled rpf. - - for (i = 0; i < nexthop_num; i++) - { - nexthop = nexthop_new (); - nexthop->type = stream_getc (s); - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); - nexthop->ifindex = stream_getl (s); - break; - case NEXTHOP_TYPE_IFINDEX: - nexthop->ifindex = stream_getl (s); - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); - nexthop->ifindex = stream_getl (s); - break; - case NEXTHOP_TYPE_IPV6: - stream_get (&nexthop->gate.ipv6, s, 16); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - stream_get (&nexthop->gate.ipv6, s, 16); - nexthop->ifindex = stream_getl (s); - ifp1 = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); - nbr = pim_neighbor_find_if (ifp1); - /* Overwrite with Nbr address as NH addr */ - if (nbr) - { - nexthop->gate.ipv4 = nbr->source_addr; - if (PIM_DEBUG_TRACE) - { - pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, str, - sizeof (str)); - zlog_debug ("%s: NHT using pim nbr addr %s interface %s as rpf", - __PRETTY_FUNCTION__, str, ifp1->name); - } - } - else - { - if (PIM_DEBUG_TRACE) - { - pim_ifp = ifp1->info; - zlog_debug ("%s: NHT pim nbr not found on interface %s nbr count:%d ", - __PRETTY_FUNCTION__, ifp1->name, - pim_ifp->pim_neighbor_list->count); - } - //Mark nexthop address to 0 until PIM Nbr is resolved. - nexthop->gate.ipv4.s_addr = PIM_NET_INADDR_ANY; - } - - break; - default: - /* do nothing */ - break; - } - - if (PIM_DEBUG_TRACE) - { - char p_str[PREFIX2STR_BUFFER]; - prefix2str (&p, p_str, sizeof (p_str)); - zlog_debug ("%s: NHT addr %s %d-nhop via %s type %d distance:%u metric:%u ", - __PRETTY_FUNCTION__, p_str, i + 1, - inet_ntoa (nexthop->gate.ipv4), nexthop->type, distance, - metric); - } - - ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); - if (!ifp) - { - if (PIM_DEBUG_ZEBRA) - { - char buf[NEXTHOP_STRLEN]; - zlog_debug ("%s: could not find interface for ifindex %d (addr %s)", - __PRETTY_FUNCTION__, nexthop->ifindex, - nexthop2str (nexthop, buf, sizeof (buf))); - } - nexthop_free (nexthop); - continue; - } - - if (!ifp->info) - { - if (PIM_DEBUG_ZEBRA) - { - char buf[NEXTHOP_STRLEN]; - zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)", - __PRETTY_FUNCTION__, ifp->name, nexthop->ifindex, - nexthop2str (nexthop, buf, sizeof (buf))); - } - nexthop_free (nexthop); - continue; - } - - if (nhlist_tail) - { - nhlist_tail->next = nexthop; - nhlist_tail = nexthop; - } - else - { - nhlist_tail = nexthop; - nhlist_head = nexthop; - } - //Only keep track of nexthops which are PIM enabled. - pnc->nexthop_num++; - } - /* Reset existing pnc->nexthop before assigning new list */ - nexthops_free (pnc->nexthop); - pnc->nexthop = nhlist_head; - if (pnc->nexthop_num) - { - pnc->flags |= PIM_NEXTHOP_VALID; - pnc->distance = distance; - pnc->metric = metric; - } - } - else - { - pnc->flags &= ~PIM_NEXTHOP_VALID; - pnc->nexthop_num = nexthop_num; - nexthops_free (pnc->nexthop); - pnc->nexthop = NULL; - } - - if (PIM_DEBUG_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&p, buf, sizeof (buf)); - zlog_debug ("%s: NHT Update for %s num_nh %d num_pim_nh %d vrf:%d up %d rp %d", - __PRETTY_FUNCTION__, buf, nexthop_num, pnc->nexthop_num, vrf_id, - listcount (pnc->upstream_list), listcount (pnc->rp_list)); - } - - pim_rpf_set_refresh_time (); - - if (listcount (pnc->rp_list)) - pim_update_rp_nh (pnc); - if (listcount (pnc->upstream_list)) - pim_update_upstream_nh (pnc); - - return 0; + struct stream *s; + struct prefix p; + struct nexthop *nexthop; + struct nexthop *nhlist_head = NULL; + struct nexthop *nhlist_tail = NULL; + uint32_t metric, distance; + u_char nexthop_num = 0; + int i; + struct pim_rpf rpf; + struct pim_nexthop_cache *pnc = NULL; + struct pim_neighbor *nbr = NULL; + struct interface *ifp = NULL; + struct interface *ifp1 = NULL; + struct pim_interface *pim_ifp = NULL; + char str[INET_ADDRSTRLEN]; + + s = zclient->ibuf; + memset(&p, 0, sizeof(struct prefix)); + p.family = stream_getw(s); + p.prefixlen = stream_getc(s); + switch (p.family) { + case AF_INET: + p.u.prefix4.s_addr = stream_get_ipv4(s); + break; + case AF_INET6: + stream_get(&p.u.prefix6, s, 16); + break; + default: + break; + } + + if (command == ZEBRA_NEXTHOP_UPDATE) { + rpf.rpf_addr.family = p.family; + rpf.rpf_addr.prefixlen = p.prefixlen; + rpf.rpf_addr.u.prefix4.s_addr = p.u.prefix4.s_addr; + pnc = pim_nexthop_cache_find(&rpf); + if (!pnc) { + if (PIM_DEBUG_TRACE) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&rpf.rpf_addr, buf, sizeof(buf)); + zlog_debug( + "%s: Skipping NHT update, addr %s is not in local cached DB.", + __PRETTY_FUNCTION__, buf); + } + return 0; + } + } else { + /* + * We do not currently handle ZEBRA_IMPORT_CHECK_UPDATE + */ + return 0; + } + + pnc->last_update = pim_time_monotonic_usec(); + distance = stream_getc(s); + metric = stream_getl(s); + nexthop_num = stream_getc(s); + + if (nexthop_num) { + pnc->nexthop_num = 0; // Only increment for pim enabled rpf. + + for (i = 0; i < nexthop_num; i++) { + nexthop = nexthop_new(); + nexthop->type = stream_getc(s); + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + nexthop->gate.ipv4.s_addr = stream_get_ipv4(s); + nexthop->ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IFINDEX: + nexthop->ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + nexthop->gate.ipv4.s_addr = stream_get_ipv4(s); + nexthop->ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IPV6: + stream_get(&nexthop->gate.ipv6, s, 16); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_get(&nexthop->gate.ipv6, s, 16); + nexthop->ifindex = stream_getl(s); + ifp1 = if_lookup_by_index(nexthop->ifindex, + VRF_DEFAULT); + nbr = pim_neighbor_find_if(ifp1); + /* Overwrite with Nbr address as NH addr */ + if (nbr) { + nexthop->gate.ipv4 = nbr->source_addr; + if (PIM_DEBUG_TRACE) { + pim_inet4_dump("<nht_nbr?>", + nbr->source_addr, + str, + sizeof(str)); + zlog_debug( + "%s: NHT using pim nbr addr %s interface %s as rpf", + __PRETTY_FUNCTION__, + str, ifp1->name); + } + } else { + if (PIM_DEBUG_TRACE) { + pim_ifp = ifp1->info; + zlog_debug( + "%s: NHT pim nbr not found on interface %s nbr count:%d ", + __PRETTY_FUNCTION__, + ifp1->name, + pim_ifp->pim_neighbor_list + ->count); + } + // Mark nexthop address to 0 until PIM + // Nbr is resolved. + nexthop->gate.ipv4.s_addr = + PIM_NET_INADDR_ANY; + } + + break; + default: + /* do nothing */ + break; + } + + if (PIM_DEBUG_TRACE) { + char p_str[PREFIX2STR_BUFFER]; + prefix2str(&p, p_str, sizeof(p_str)); + zlog_debug( + "%s: NHT addr %s %d-nhop via %s type %d distance:%u metric:%u ", + __PRETTY_FUNCTION__, p_str, i + 1, + inet_ntoa(nexthop->gate.ipv4), + nexthop->type, distance, metric); + } + + ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT); + if (!ifp) { + if (PIM_DEBUG_ZEBRA) { + char buf[NEXTHOP_STRLEN]; + zlog_debug( + "%s: could not find interface for ifindex %d (addr %s)", + __PRETTY_FUNCTION__, + nexthop->ifindex, + nexthop2str(nexthop, buf, + sizeof(buf))); + } + nexthop_free(nexthop); + continue; + } + + if (!ifp->info) { + if (PIM_DEBUG_ZEBRA) { + char buf[NEXTHOP_STRLEN]; + zlog_debug( + "%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)", + __PRETTY_FUNCTION__, ifp->name, + nexthop->ifindex, + nexthop2str(nexthop, buf, + sizeof(buf))); + } + nexthop_free(nexthop); + continue; + } + + if (nhlist_tail) { + nhlist_tail->next = nexthop; + nhlist_tail = nexthop; + } else { + nhlist_tail = nexthop; + nhlist_head = nexthop; + } + // Only keep track of nexthops which are PIM enabled. + pnc->nexthop_num++; + } + /* Reset existing pnc->nexthop before assigning new list */ + nexthops_free(pnc->nexthop); + pnc->nexthop = nhlist_head; + if (pnc->nexthop_num) { + pnc->flags |= PIM_NEXTHOP_VALID; + pnc->distance = distance; + pnc->metric = metric; + } + } else { + pnc->flags &= ~PIM_NEXTHOP_VALID; + pnc->nexthop_num = nexthop_num; + nexthops_free(pnc->nexthop); + pnc->nexthop = NULL; + } + + if (PIM_DEBUG_TRACE) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&p, buf, sizeof(buf)); + zlog_debug( + "%s: NHT Update for %s num_nh %d num_pim_nh %d vrf:%d up %d rp %d", + __PRETTY_FUNCTION__, buf, nexthop_num, pnc->nexthop_num, + vrf_id, listcount(pnc->upstream_list), + listcount(pnc->rp_list)); + } + + pim_rpf_set_refresh_time(); + + if (listcount(pnc->rp_list)) + pim_update_rp_nh(pnc); + if (listcount(pnc->upstream_list)) + pim_update_upstream_nh(pnc); + + return 0; } -int -pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr, - struct prefix *src, struct prefix *grp, - int neighbor_needed) +int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, + struct prefix *src, struct prefix *grp, + int neighbor_needed) { - struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; - struct pim_neighbor *nbr = NULL; - int num_ifindex; - struct interface *ifp; - int first_ifindex; - int found = 0; - uint8_t i = 0; - uint32_t hash_val = 0, mod_val = 0; - - if (PIM_DEBUG_TRACE) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); - zlog_debug ("%s: Looking up: %s, last lookup time: %lld", - __PRETTY_FUNCTION__, addr_str, nexthop->last_lookup_time); - } - - memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); - num_ifindex = zclient_lookup_nexthop (nexthop_tab, MULTIPATH_NUM, addr, - PIM_NEXTHOP_LOOKUP_MAX); - if (num_ifindex < 1) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); - zlog_warn ("%s %s: could not find nexthop ifindex for address %s", - __FILE__, __PRETTY_FUNCTION__, addr_str); - return -1; - } - - //If PIM ECMP enable then choose ECMP path. - if (qpim_ecmp_enable) - { - hash_val = pim_compute_ecmp_hash (src, grp); - mod_val = hash_val % num_ifindex; - if (PIM_DEBUG_PIM_TRACE_DETAIL) - zlog_debug ("%s: hash_val %u mod_val %u", - __PRETTY_FUNCTION__, hash_val, mod_val); - } - - while (!found && (i < num_ifindex)) - { - first_ifindex = nexthop_tab[i].ifindex; - - ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT); - if (!ifp) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); - zlog_debug ("%s %s: could not find interface for ifindex %d (address %s)", - __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str); - } - if (i == mod_val) - mod_val++; - i++; - continue; - } - - if (!ifp->info) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); - zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", - __PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str); - } - if (i == mod_val) - mod_val++; - i++; - continue; - } - if (neighbor_needed && !pim_if_connected_to_source (ifp, addr)) - { - nbr = pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4); - if (PIM_DEBUG_PIM_TRACE_DETAIL) - zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); - if (!nbr && !if_is_loopback (ifp)) - { - if (i == mod_val) - mod_val++; - i++; - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("<addr?>", addr, addr_str, - sizeof (addr_str)); - zlog_debug ("%s: NBR not found on input interface %s (RPF for source %s)", - __PRETTY_FUNCTION__, ifp->name, addr_str); - } - continue; - } - } - - if (i == mod_val) - { - if (PIM_DEBUG_ZEBRA) - { - char nexthop_str[PREFIX_STRLEN]; - char addr_str[INET_ADDRSTRLEN]; - pim_addr_dump ("<nexthop?>", &nexthop_tab[i].nexthop_addr, - nexthop_str, sizeof (nexthop_str)); - pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); - zlog_debug ("%s %s: found nhop %s for addr %s interface %s metric %d dist %d", - __FILE__, __PRETTY_FUNCTION__, nexthop_str, addr_str, - ifp->name, nexthop_tab[i].route_metric, - nexthop_tab[i].protocol_distance); - } - /* update nextop data */ - nexthop->interface = ifp; - nexthop->mrib_nexthop_addr = nexthop_tab[i].nexthop_addr; - nexthop->mrib_metric_preference = nexthop_tab[i].protocol_distance; - nexthop->mrib_route_metric = nexthop_tab[i].route_metric; - nexthop->last_lookup = addr; - nexthop->last_lookup_time = pim_time_monotonic_usec(); - nexthop->nbr = nbr; - found = 1; - } - i++; - } - if (found) - return 0; - else - return -1; + struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; + struct pim_neighbor *nbr = NULL; + int num_ifindex; + struct interface *ifp; + int first_ifindex; + int found = 0; + uint8_t i = 0; + uint32_t hash_val = 0, mod_val = 0; + + if (PIM_DEBUG_TRACE) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); + zlog_debug("%s: Looking up: %s, last lookup time: %lld", + __PRETTY_FUNCTION__, addr_str, + nexthop->last_lookup_time); + } + + memset(nexthop_tab, 0, + sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM); + num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, + PIM_NEXTHOP_LOOKUP_MAX); + if (num_ifindex < 1) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); + zlog_warn( + "%s %s: could not find nexthop ifindex for address %s", + __FILE__, __PRETTY_FUNCTION__, addr_str); + return -1; + } + + // If PIM ECMP enable then choose ECMP path. + if (qpim_ecmp_enable) { + hash_val = pim_compute_ecmp_hash(src, grp); + mod_val = hash_val % num_ifindex; + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug("%s: hash_val %u mod_val %u", + __PRETTY_FUNCTION__, hash_val, mod_val); + } + + while (!found && (i < num_ifindex)) { + first_ifindex = nexthop_tab[i].ifindex; + + ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); + if (!ifp) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: could not find interface for ifindex %d (address %s)", + __FILE__, __PRETTY_FUNCTION__, + first_ifindex, addr_str); + } + if (i == mod_val) + mod_val++; + i++; + continue; + } + + if (!ifp->info) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", + __PRETTY_FUNCTION__, ifp->name, + first_ifindex, addr_str); + } + if (i == mod_val) + mod_val++; + i++; + continue; + } + if (neighbor_needed && !pim_if_connected_to_source(ifp, addr)) { + nbr = pim_neighbor_find( + ifp, nexthop_tab[i].nexthop_addr.u.prefix4); + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug("ifp name: %s, pim nbr: %p", + ifp->name, nbr); + if (!nbr && !if_is_loopback(ifp)) { + if (i == mod_val) + mod_val++; + i++; + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, + addr_str, + sizeof(addr_str)); + zlog_debug( + "%s: NBR not found on input interface %s (RPF for source %s)", + __PRETTY_FUNCTION__, ifp->name, + addr_str); + } + continue; + } + } + + if (i == mod_val) { + if (PIM_DEBUG_ZEBRA) { + char nexthop_str[PREFIX_STRLEN]; + char addr_str[INET_ADDRSTRLEN]; + pim_addr_dump("<nexthop?>", + &nexthop_tab[i].nexthop_addr, + nexthop_str, sizeof(nexthop_str)); + pim_inet4_dump("<addr?>", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: found nhop %s for addr %s interface %s metric %d dist %d", + __FILE__, __PRETTY_FUNCTION__, + nexthop_str, addr_str, ifp->name, + nexthop_tab[i].route_metric, + nexthop_tab[i].protocol_distance); + } + /* update nextop data */ + nexthop->interface = ifp; + nexthop->mrib_nexthop_addr = + nexthop_tab[i].nexthop_addr; + nexthop->mrib_metric_preference = + nexthop_tab[i].protocol_distance; + nexthop->mrib_route_metric = + nexthop_tab[i].route_metric; + nexthop->last_lookup = addr; + nexthop->last_lookup_time = pim_time_monotonic_usec(); + nexthop->nbr = nbr; + found = 1; + } + i++; + } + if (found) + return 0; + else + return -1; } -int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, - struct prefix *src, struct prefix *grp) +int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, struct prefix *src, + struct prefix *grp) { - struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; - int num_ifindex; - int vif_index; - ifindex_t first_ifindex; - uint32_t hash_val = 0, mod_val = 0; - - memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); - num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, - PIM_NEXTHOP_LOOKUP_MAX); - if (num_ifindex < 1) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: could not find nexthop ifindex for address %s", - __FILE__, __PRETTY_FUNCTION__, - addr_str); - } - return -1; - } - - //If PIM ECMP enable then choose ECMP path. - if (qpim_ecmp_enable) - { - hash_val = pim_compute_ecmp_hash (src, grp); - mod_val = hash_val % num_ifindex; - if (PIM_DEBUG_PIM_TRACE_DETAIL) - zlog_debug ("%s: hash_val %u mod_val %u", - __PRETTY_FUNCTION__, hash_val, mod_val); - } - - first_ifindex = nexthop_tab[mod_val].ifindex; - - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: found nexthop ifindex=%d (interface %s) for address %s", - __FILE__, __PRETTY_FUNCTION__, - first_ifindex, ifindex2ifname(first_ifindex, VRF_DEFAULT), addr_str); - } - - vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex); - - if (vif_index < 0) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: low vif_index=%d < 1 nexthop for address %s", - __FILE__, __PRETTY_FUNCTION__, - vif_index, addr_str); - } - return -2; - } - - return vif_index; + struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; + int num_ifindex; + int vif_index; + ifindex_t first_ifindex; + uint32_t hash_val = 0, mod_val = 0; + + memset(nexthop_tab, 0, + sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM); + num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, + PIM_NEXTHOP_LOOKUP_MAX); + if (num_ifindex < 1) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: could not find nexthop ifindex for address %s", + __FILE__, __PRETTY_FUNCTION__, addr_str); + } + return -1; + } + + // If PIM ECMP enable then choose ECMP path. + if (qpim_ecmp_enable) { + hash_val = pim_compute_ecmp_hash(src, grp); + mod_val = hash_val % num_ifindex; + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug("%s: hash_val %u mod_val %u", + __PRETTY_FUNCTION__, hash_val, mod_val); + } + + first_ifindex = nexthop_tab[mod_val].ifindex; + + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str)); + zlog_debug( + "%s %s: found nexthop ifindex=%d (interface %s) for address %s", + __FILE__, __PRETTY_FUNCTION__, first_ifindex, + ifindex2ifname(first_ifindex, VRF_DEFAULT), addr_str); + } + + vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex); + + if (vif_index < 0) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: low vif_index=%d < 1 nexthop for address %s", + __FILE__, __PRETTY_FUNCTION__, vif_index, + addr_str); + } + return -2; + } + + return vif_index; } diff --git a/pimd/pim_nht.h b/pimd/pim_nht.h index 6bd224992..fb8d83623 100644 --- a/pimd/pim_nht.h +++ b/pimd/pim_nht.h @@ -30,42 +30,42 @@ #include "pim_rpf.h" /* PIM nexthop cache value structure. */ -struct pim_nexthop_cache -{ - struct pim_rpf rpf; - /* IGP route's metric. */ - u_int32_t metric; - uint32_t distance; - /* Nexthop number and nexthop linked list. */ - u_char nexthop_num; - struct nexthop *nexthop; - int64_t last_update; - u_int16_t flags; +struct pim_nexthop_cache { + struct pim_rpf rpf; + /* IGP route's metric. */ + u_int32_t metric; + uint32_t distance; + /* Nexthop number and nexthop linked list. */ + u_char nexthop_num; + struct nexthop *nexthop; + int64_t last_update; + u_int16_t flags; #define PIM_NEXTHOP_VALID (1 << 0) - struct list *rp_list; - struct list *upstream_list; + struct list *rp_list; + struct list *upstream_list; }; -int pim_parse_nexthop_update (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id); -int pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, - struct rp_info *rp, struct pim_nexthop_cache *out_pnc); -void pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up, - struct rp_info *rp); -struct pim_nexthop_cache *pim_nexthop_cache_add (struct pim_rpf *rpf_addr); -struct pim_nexthop_cache *pim_nexthop_cache_find (struct pim_rpf *rpf); -uint32_t pim_compute_ecmp_hash (struct prefix *src, struct prefix *grp); -int pim_ecmp_nexthop_search (struct pim_nexthop_cache * pnc, - struct pim_nexthop *nexthop, struct prefix *src, - struct prefix *grp, int neighbor_needed); -int pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr, - struct prefix *src, struct prefix *grp, - int neighbor_needed); -void pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc, - int command); -int pim_update_rp_nh (struct pim_nexthop_cache *pnc); -void pim_resolve_upstream_nh (struct prefix *nht_p); -int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, - struct prefix *src, struct prefix *grp); +int pim_parse_nexthop_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id); +int pim_find_or_track_nexthop(struct prefix *addr, struct pim_upstream *up, + struct rp_info *rp, + struct pim_nexthop_cache *out_pnc); +void pim_delete_tracked_nexthop(struct prefix *addr, struct pim_upstream *up, + struct rp_info *rp); +struct pim_nexthop_cache *pim_nexthop_cache_add(struct pim_rpf *rpf_addr); +struct pim_nexthop_cache *pim_nexthop_cache_find(struct pim_rpf *rpf); +uint32_t pim_compute_ecmp_hash(struct prefix *src, struct prefix *grp); +int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc, + struct pim_nexthop *nexthop, struct prefix *src, + struct prefix *grp, int neighbor_needed); +int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, + struct prefix *src, struct prefix *grp, + int neighbor_needed); +void pim_sendmsg_zebra_rnh(struct zclient *zclient, + struct pim_nexthop_cache *pnc, int command); +int pim_update_rp_nh(struct pim_nexthop_cache *pnc); +void pim_resolve_upstream_nh(struct prefix *nht_p); +int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, struct prefix *src, + struct prefix *grp); #endif diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 66be2be6f..aeef0ff4e 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -35,435 +35,477 @@ struct list *pim_channel_oil_list = NULL; struct hash *pim_channel_oil_hash = NULL; -char * -pim_channel_oil_dump (struct channel_oil *c_oil, char *buf, size_t size) +char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size) { - struct prefix_sg sg; - int i; - - memset (buf, 0, size); - sg.src = c_oil->oil.mfcc_origin; - sg.grp = c_oil->oil.mfcc_mcastgrp; - sprintf(buf, "%s IIF: %d, OIFS: ", - pim_str_sg_dump (&sg), c_oil->oil.mfcc_parent); - - for (i = 0 ; i < MAXVIFS ; i++) - { - if (c_oil->oil.mfcc_ttls[i] != 0) - { - char buf1[10]; - sprintf(buf1, "%d ", i); - strcat(buf, buf1); - } - } - - return buf; + struct prefix_sg sg; + int i; + + memset(buf, 0, size); + sg.src = c_oil->oil.mfcc_origin; + sg.grp = c_oil->oil.mfcc_mcastgrp; + sprintf(buf, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg), + c_oil->oil.mfcc_parent); + + for (i = 0; i < MAXVIFS; i++) { + if (c_oil->oil.mfcc_ttls[i] != 0) { + char buf1[10]; + sprintf(buf1, "%d ", i); + strcat(buf, buf1); + } + } + + return buf; } -static int -pim_channel_oil_compare (struct channel_oil *c1, struct channel_oil *c2) +static int pim_channel_oil_compare(struct channel_oil *c1, + struct channel_oil *c2) { - if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) < ntohl(c2->oil.mfcc_mcastgrp.s_addr)) - return -1; + if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) + < ntohl(c2->oil.mfcc_mcastgrp.s_addr)) + return -1; - if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) > ntohl(c2->oil.mfcc_mcastgrp.s_addr)) - return 1; + if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) + > ntohl(c2->oil.mfcc_mcastgrp.s_addr)) + return 1; - if (ntohl(c1->oil.mfcc_origin.s_addr) < ntohl(c2->oil.mfcc_origin.s_addr)) - return -1; + if (ntohl(c1->oil.mfcc_origin.s_addr) + < ntohl(c2->oil.mfcc_origin.s_addr)) + return -1; - if (ntohl(c1->oil.mfcc_origin.s_addr) > ntohl(c2->oil.mfcc_origin.s_addr)) - return 1; + if (ntohl(c1->oil.mfcc_origin.s_addr) + > ntohl(c2->oil.mfcc_origin.s_addr)) + return 1; - return 0; + return 0; } -static int -pim_oil_equal (const void *arg1, const void *arg2) +static int pim_oil_equal(const void *arg1, const void *arg2) { - const struct channel_oil *c1 = (const struct channel_oil *)arg1; - const struct channel_oil *c2 = (const struct channel_oil *)arg2; + const struct channel_oil *c1 = (const struct channel_oil *)arg1; + const struct channel_oil *c2 = (const struct channel_oil *)arg2; - if ((c1->oil.mfcc_mcastgrp.s_addr == c2->oil.mfcc_mcastgrp.s_addr) && - (c1->oil.mfcc_origin.s_addr == c2->oil.mfcc_origin.s_addr)) - return 1; + if ((c1->oil.mfcc_mcastgrp.s_addr == c2->oil.mfcc_mcastgrp.s_addr) + && (c1->oil.mfcc_origin.s_addr == c2->oil.mfcc_origin.s_addr)) + return 1; - return 0; + return 0; } -static unsigned int -pim_oil_hash_key (void *arg) +static unsigned int pim_oil_hash_key(void *arg) { - struct channel_oil *oil = (struct channel_oil *)arg; + struct channel_oil *oil = (struct channel_oil *)arg; - return jhash_2words (oil->oil.mfcc_mcastgrp.s_addr, oil->oil.mfcc_origin.s_addr, 0); + return jhash_2words(oil->oil.mfcc_mcastgrp.s_addr, + oil->oil.mfcc_origin.s_addr, 0); } -void -pim_oil_init (void) +void pim_oil_init(void) { - pim_channel_oil_hash = hash_create_size (8192, pim_oil_hash_key, - pim_oil_equal, NULL); - - pim_channel_oil_list = list_new(); - if (!pim_channel_oil_list) { - zlog_err("%s %s: failure: channel_oil_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return; - } - pim_channel_oil_list->del = (void (*)(void *)) pim_channel_oil_free; - pim_channel_oil_list->cmp = (int (*)(void *, void *)) pim_channel_oil_compare; + pim_channel_oil_hash = + hash_create_size(8192, pim_oil_hash_key, pim_oil_equal, NULL); + + pim_channel_oil_list = list_new(); + if (!pim_channel_oil_list) { + zlog_err("%s %s: failure: channel_oil_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return; + } + pim_channel_oil_list->del = (void (*)(void *))pim_channel_oil_free; + pim_channel_oil_list->cmp = + (int (*)(void *, void *))pim_channel_oil_compare; } -void -pim_oil_terminate (void) +void pim_oil_terminate(void) { - if (pim_channel_oil_list) - list_free(pim_channel_oil_list); - pim_channel_oil_list = NULL; + if (pim_channel_oil_list) + list_free(pim_channel_oil_list); + pim_channel_oil_list = NULL; - if (pim_channel_oil_hash) - hash_free (pim_channel_oil_hash); - pim_channel_oil_hash = NULL; + if (pim_channel_oil_hash) + hash_free(pim_channel_oil_hash); + pim_channel_oil_hash = NULL; } void pim_channel_oil_free(struct channel_oil *c_oil) { - XFREE(MTYPE_PIM_CHANNEL_OIL, c_oil); + XFREE(MTYPE_PIM_CHANNEL_OIL, c_oil); } -static struct channel_oil * -pim_find_channel_oil(struct prefix_sg *sg) +static struct channel_oil *pim_find_channel_oil(struct prefix_sg *sg) { - struct channel_oil *c_oil = NULL; - struct channel_oil lookup; + struct channel_oil *c_oil = NULL; + struct channel_oil lookup; - lookup.oil.mfcc_mcastgrp = sg->grp; - lookup.oil.mfcc_origin = sg->src; + lookup.oil.mfcc_mcastgrp = sg->grp; + lookup.oil.mfcc_origin = sg->src; - c_oil = hash_lookup (pim_channel_oil_hash, &lookup); + c_oil = hash_lookup(pim_channel_oil_hash, &lookup); - return c_oil; + return c_oil; } struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg, int input_vif_index) { - struct channel_oil *c_oil; - struct interface *ifp; - - c_oil = pim_find_channel_oil(sg); - if (c_oil) { - if (c_oil->oil.mfcc_parent != input_vif_index) - { - c_oil->oil_inherited_rescan = 1; - if (PIM_DEBUG_MROUTE) - zlog_debug ("%s: Existing channel oil %s points to %d, modifying to point at %d", - __PRETTY_FUNCTION__, pim_str_sg_dump(sg), c_oil->oil.mfcc_parent, input_vif_index); - } - c_oil->oil.mfcc_parent = input_vif_index; - ++c_oil->oil_ref_count; - c_oil->up = pim_upstream_find(sg); //channel might be present prior to upstream - return c_oil; - } - - ifp = pim_if_find_by_vif_index(input_vif_index); - if (!ifp) { - /* warning only */ - zlog_warn("%s: (S,G)=%s could not find input interface for input_vif_index=%d", - __PRETTY_FUNCTION__, - pim_str_sg_dump (sg), input_vif_index); - } - - c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil)); - if (!c_oil) { - zlog_err("PIM XCALLOC(%zu) failure", sizeof(*c_oil)); - return NULL; - } - - c_oil->oil.mfcc_mcastgrp = sg->grp; - c_oil->oil.mfcc_origin = sg->src; - c_oil = hash_get (pim_channel_oil_hash, c_oil, hash_alloc_intern); - - c_oil->oil.mfcc_parent = input_vif_index; - c_oil->oil_ref_count = 1; - c_oil->installed = 0; - c_oil->up = pim_upstream_find(sg); - - listnode_add_sort(pim_channel_oil_list, c_oil); - - return c_oil; + struct channel_oil *c_oil; + struct interface *ifp; + + c_oil = pim_find_channel_oil(sg); + if (c_oil) { + if (c_oil->oil.mfcc_parent != input_vif_index) { + c_oil->oil_inherited_rescan = 1; + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: Existing channel oil %s points to %d, modifying to point at %d", + __PRETTY_FUNCTION__, + pim_str_sg_dump(sg), + c_oil->oil.mfcc_parent, + input_vif_index); + } + c_oil->oil.mfcc_parent = input_vif_index; + ++c_oil->oil_ref_count; + c_oil->up = pim_upstream_find( + sg); // channel might be present prior to upstream + return c_oil; + } + + ifp = pim_if_find_by_vif_index(input_vif_index); + if (!ifp) { + /* warning only */ + zlog_warn( + "%s: (S,G)=%s could not find input interface for input_vif_index=%d", + __PRETTY_FUNCTION__, pim_str_sg_dump(sg), + input_vif_index); + } + + c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil)); + if (!c_oil) { + zlog_err("PIM XCALLOC(%zu) failure", sizeof(*c_oil)); + return NULL; + } + + c_oil->oil.mfcc_mcastgrp = sg->grp; + c_oil->oil.mfcc_origin = sg->src; + c_oil = hash_get(pim_channel_oil_hash, c_oil, hash_alloc_intern); + + c_oil->oil.mfcc_parent = input_vif_index; + c_oil->oil_ref_count = 1; + c_oil->installed = 0; + c_oil->up = pim_upstream_find(sg); + + listnode_add_sort(pim_channel_oil_list, c_oil); + + return c_oil; } void pim_channel_oil_del(struct channel_oil *c_oil) { - --c_oil->oil_ref_count; - - if (c_oil->oil_ref_count < 1) { - /* - * notice that listnode_delete() can't be moved - * into pim_channel_oil_free() because the later is - * called by list_delete_all_node() - */ - c_oil->up = NULL; - listnode_delete(pim_channel_oil_list, c_oil); - hash_release (pim_channel_oil_hash, c_oil); - - pim_channel_oil_free(c_oil); - } + --c_oil->oil_ref_count; + + if (c_oil->oil_ref_count < 1) { + /* + * notice that listnode_delete() can't be moved + * into pim_channel_oil_free() because the later is + * called by list_delete_all_node() + */ + c_oil->up = NULL; + listnode_delete(pim_channel_oil_list, c_oil); + hash_release(pim_channel_oil_hash, c_oil); + + pim_channel_oil_free(c_oil); + } } -int -pim_channel_del_oif (struct channel_oil *channel_oil, - struct interface *oif, - uint32_t proto_mask) +int pim_channel_del_oif(struct channel_oil *channel_oil, struct interface *oif, + uint32_t proto_mask) { - struct pim_interface *pim_ifp; - - zassert (channel_oil); - zassert (oif); - - pim_ifp = oif->info; - - /* - * Don't do anything if we've been asked to remove a source - * that is not actually on it. - */ - if (!(channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask)) - { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: no existing protocol mask %u(%u) for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - proto_mask, channel_oil->oif_flags[pim_ifp->mroute_vif_index], - oif->name, pim_ifp->mroute_vif_index, - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], - source_str, group_str); + struct pim_interface *pim_ifp; + + zassert(channel_oil); + zassert(oif); + + pim_ifp = oif->info; + + /* + * Don't do anything if we've been asked to remove a source + * that is not actually on it. + */ + if (!(channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask)) { + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("<source?>", + channel_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + zlog_debug( + "%s %s: no existing protocol mask %u(%u) for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, proto_mask, + channel_oil + ->oif_flags[pim_ifp->mroute_vif_index], + oif->name, pim_ifp->mroute_vif_index, + channel_oil->oil + .mfcc_ttls[pim_ifp->mroute_vif_index], + source_str, group_str); + } + return 0; + } + + channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~proto_mask; + + if (channel_oil->oif_flags[pim_ifp->mroute_vif_index]) { + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("<source?>", + channel_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + zlog_debug( + "%s %s: other protocol masks remain for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, oif->name, + pim_ifp->mroute_vif_index, + channel_oil->oil + .mfcc_ttls[pim_ifp->mroute_vif_index], + source_str, group_str); + } + return 0; + } + + channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0; + + if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) { + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("<source?>", + channel_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + zlog_debug( + "%s %s: could not remove output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, oif->name, + pim_ifp->mroute_vif_index, source_str, + group_str); + } + return -1; } - return 0; - } - - channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~proto_mask; - - if (channel_oil->oif_flags[pim_ifp->mroute_vif_index]) - { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: other protocol masks remain for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - oif->name, pim_ifp->mroute_vif_index, - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], - source_str, group_str); + + --channel_oil->oil_size; + + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + zlog_debug( + "%s %s: (S,G)=(%s,%s): proto_mask=%u IIF:%d OIF=%s vif_index=%d", + __FILE__, __PRETTY_FUNCTION__, source_str, group_str, + proto_mask, channel_oil->oil.mfcc_parent, oif->name, + pim_ifp->mroute_vif_index); } - return 0; - } - - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0; - - if (pim_mroute_add (channel_oil, __PRETTY_FUNCTION__)) { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: could not remove output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - oif->name, pim_ifp->mroute_vif_index, - source_str, group_str); - } - return -1; - } - - --channel_oil->oil_size; - - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u IIF:%d OIF=%s vif_index=%d", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - proto_mask, channel_oil->oil.mfcc_parent ,oif->name, pim_ifp->mroute_vif_index); - } - - return 0; + + return 0; } -int pim_channel_add_oif(struct channel_oil *channel_oil, - struct interface *oif, - uint32_t proto_mask) +int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif, + uint32_t proto_mask) { - struct pim_interface *pim_ifp; - int old_ttl; - - /* - * If we've gotten here we've gone bad, but let's - * not take down pim - */ - if (!channel_oil) - { - zlog_warn ("Attempt to Add OIF for non-existent channel oil"); - return -1; - } + struct pim_interface *pim_ifp; + int old_ttl; + + /* + * If we've gotten here we've gone bad, but let's + * not take down pim + */ + if (!channel_oil) { + zlog_warn("Attempt to Add OIF for non-existent channel oil"); + return -1; + } - pim_ifp = oif->info; + pim_ifp = oif->info; #ifdef PIM_ENFORCE_LOOPFREE_MFC - /* - Prevent creating MFC entry with OIF=IIF. - - This is a protection against implementation mistakes. - - PIM protocol implicitely ensures loopfree multicast topology. - - IGMP must be protected against adding looped MFC entries created - by both source and receiver attached to the same interface. See - TODO T22. - */ - if (pim_ifp->mroute_vif_index == channel_oil->oil.mfcc_parent) { - channel_oil->oil_inherited_rescan = 1; - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - proto_mask, oif->name, pim_ifp->mroute_vif_index, - source_str, group_str); - } - return -2; - } + /* + Prevent creating MFC entry with OIF=IIF. + + This is a protection against implementation mistakes. + + PIM protocol implicitely ensures loopfree multicast topology. + + IGMP must be protected against adding looped MFC entries created + by both source and receiver attached to the same interface. See + TODO T22. + */ + if (pim_ifp->mroute_vif_index == channel_oil->oil.mfcc_parent) { + channel_oil->oil_inherited_rescan = 1; + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("<source?>", + channel_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + zlog_debug( + "%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, proto_mask, + oif->name, pim_ifp->mroute_vif_index, + source_str, group_str); + } + return -2; + } #endif - /* Prevent single protocol from subscribing same interface to - channel (S,G) multiple times */ - if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask) { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - proto_mask, oif->name, pim_ifp->mroute_vif_index, - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], - source_str, group_str); - } - return -3; - } - - /* Allow other protocol to request subscription of same interface to - * channel (S,G), we need to note this information - */ - if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & PIM_OIF_FLAG_PROTO_ANY) { - - channel_oil->oif_creation[pim_ifp->mroute_vif_index] = pim_time_monotonic_sec(); - channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask; - /* Check the OIF really exists before returning, and only log - warning otherwise */ - if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) { - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_warn("%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - proto_mask, oif->name, pim_ifp->mroute_vif_index, - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], - source_str, group_str); - } - } - - return 0; - } - - old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]; - - if (old_ttl > 0) { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - oif->name, pim_ifp->mroute_vif_index, - source_str, group_str); - } - return -4; - } - - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = PIM_MROUTE_MIN_TTL; - - if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - oif->name, pim_ifp->mroute_vif_index, - source_str, group_str); - } - - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl; - return -5; - } - - channel_oil->oif_creation[pim_ifp->mroute_vif_index] = pim_time_monotonic_sec(); - ++channel_oil->oil_size; - channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask; - - if (PIM_DEBUG_MROUTE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - proto_mask, oif->name, pim_ifp->mroute_vif_index); - } - - return 0; + /* Prevent single protocol from subscribing same interface to + channel (S,G) multiple times */ + if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask) { + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("<source?>", + channel_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + zlog_debug( + "%s %s: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, proto_mask, + oif->name, pim_ifp->mroute_vif_index, + channel_oil->oil + .mfcc_ttls[pim_ifp->mroute_vif_index], + source_str, group_str); + } + return -3; + } + + /* Allow other protocol to request subscription of same interface to + * channel (S,G), we need to note this information + */ + if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] + & PIM_OIF_FLAG_PROTO_ANY) { + + channel_oil->oif_creation[pim_ifp->mroute_vif_index] = + pim_time_monotonic_sec(); + channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask; + /* Check the OIF really exists before returning, and only log + warning otherwise */ + if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) { + { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("<source?>", + channel_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + zlog_warn( + "%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, + proto_mask, oif->name, + pim_ifp->mroute_vif_index, + channel_oil->oil.mfcc_ttls + [pim_ifp->mroute_vif_index], + source_str, group_str); + } + } + + return 0; + } + + old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]; + + if (old_ttl > 0) { + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("<source?>", + channel_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + zlog_debug( + "%s %s: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, oif->name, + pim_ifp->mroute_vif_index, source_str, + group_str); + } + return -4; + } + + channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = + PIM_MROUTE_MIN_TTL; + + if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) { + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("<source?>", + channel_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + zlog_debug( + "%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, oif->name, + pim_ifp->mroute_vif_index, source_str, + group_str); + } + + channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl; + return -5; + } + + channel_oil->oif_creation[pim_ifp->mroute_vif_index] = + pim_time_monotonic_sec(); + ++channel_oil->oil_size; + channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask; + + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + zlog_debug( + "%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE", + __FILE__, __PRETTY_FUNCTION__, source_str, group_str, + proto_mask, oif->name, pim_ifp->mroute_vif_index); + } + + return 0; } -int -pim_channel_oil_empty (struct channel_oil *c_oil) +int pim_channel_oil_empty(struct channel_oil *c_oil) { - static uint32_t zero[MAXVIFS]; - static int inited = 0; - - if (!c_oil) - return 1; - /* - * Not sure that this is necessary, but I would rather ensure - * that this works. - */ - if (!inited) - { - memset(&zero, 0, sizeof(uint32_t) * MAXVIFS); - inited = 1; - } - - return !memcmp(c_oil->oif_flags, zero, MAXVIFS * sizeof(uint32_t)); + static uint32_t zero[MAXVIFS]; + static int inited = 0; + + if (!c_oil) + return 1; + /* + * Not sure that this is necessary, but I would rather ensure + * that this works. + */ + if (!inited) { + memset(&zero, 0, sizeof(uint32_t) * MAXVIFS); + inited = 1; + } + + return !memcmp(c_oil->oif_flags, zero, MAXVIFS * sizeof(uint32_t)); } diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 02c7e740e..f537062c7 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -34,10 +34,9 @@ #define PIM_OIF_FLAG_PROTO_PIM (1 << 1) #define PIM_OIF_FLAG_PROTO_SOURCE (1 << 2) #define PIM_OIF_FLAG_PROTO_STAR (1 << 3) -#define PIM_OIF_FLAG_PROTO_ANY (PIM_OIF_FLAG_PROTO_IGMP | \ - PIM_OIF_FLAG_PROTO_PIM | \ - PIM_OIF_FLAG_PROTO_SOURCE | \ - PIM_OIF_FLAG_PROTO_STAR) +#define PIM_OIF_FLAG_PROTO_ANY \ + (PIM_OIF_FLAG_PROTO_IGMP | PIM_OIF_FLAG_PROTO_PIM \ + | PIM_OIF_FLAG_PROTO_SOURCE | PIM_OIF_FLAG_PROTO_STAR) /* * We need a pimreg vif id from the kernel. @@ -50,16 +49,14 @@ #define PIM_OIF_PIM_REGISTER_VIF 0 #define PIM_MAX_USABLE_VIFS (MAXVIFS - 1) - -struct channel_counts -{ - unsigned long long lastused; - unsigned long pktcnt; - unsigned long oldpktcnt; - unsigned long bytecnt; - unsigned long oldbytecnt; - unsigned long wrong_if; - unsigned long oldwrong_if; +struct channel_counts { + unsigned long long lastused; + unsigned long pktcnt; + unsigned long oldpktcnt; + unsigned long bytecnt; + unsigned long oldbytecnt; + unsigned long wrong_if; + unsigned long oldwrong_if; }; /* @@ -70,35 +67,33 @@ struct channel_counts */ struct channel_oil { - struct mfcctl oil; - int installed; - int oil_inherited_rescan; - int oil_size; - int oil_ref_count; - time_t oif_creation[MAXVIFS]; - uint32_t oif_flags[MAXVIFS]; - struct channel_counts cc; - struct pim_upstream *up; + struct mfcctl oil; + int installed; + int oil_inherited_rescan; + int oil_size; + int oil_ref_count; + time_t oif_creation[MAXVIFS]; + uint32_t oif_flags[MAXVIFS]; + struct channel_counts cc; + struct pim_upstream *up; }; extern struct list *pim_channel_oil_list; -void pim_oil_init (void); -void pim_oil_terminate (void); +void pim_oil_init(void); +void pim_oil_terminate(void); void pim_channel_oil_free(struct channel_oil *c_oil); struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg, int input_vif_index); void pim_channel_oil_del(struct channel_oil *c_oil); -int pim_channel_add_oif(struct channel_oil *c_oil, - struct interface *oif, +int pim_channel_add_oif(struct channel_oil *c_oil, struct interface *oif, + uint32_t proto_mask); +int pim_channel_del_oif(struct channel_oil *c_oil, struct interface *oif, uint32_t proto_mask); -int pim_channel_del_oif (struct channel_oil *c_oil, - struct interface *oif, - uint32_t proto_mask); -int pim_channel_oil_empty (struct channel_oil *c_oil); +int pim_channel_oil_empty(struct channel_oil *c_oil); -char *pim_channel_oil_dump (struct channel_oil *c_oil, char *buf, size_t size); +char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size); #endif /* PIM_OIL_H */ diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index f6a5bb122..21892f347 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -40,670 +40,673 @@ #include "pim_register.h" static int on_pim_hello_send(struct thread *t); -static int pim_hello_send(struct interface *ifp, - uint16_t holdtime); +static int pim_hello_send(struct interface *ifp, uint16_t holdtime); -static -const char *pim_pim_msgtype2str (enum pim_msg_type type) +static const char *pim_pim_msgtype2str(enum pim_msg_type type) { - switch (type) - { - case PIM_MSG_TYPE_HELLO: return "HELLO"; - case PIM_MSG_TYPE_REGISTER: return "REGISTER"; - case PIM_MSG_TYPE_REG_STOP: return "REGSTOP"; - case PIM_MSG_TYPE_JOIN_PRUNE: return "JOINPRUNE"; - case PIM_MSG_TYPE_BOOTSTRAP: return "BOOT"; - case PIM_MSG_TYPE_ASSERT: return "ASSERT"; - case PIM_MSG_TYPE_GRAFT: return "GRAFT"; - case PIM_MSG_TYPE_GRAFT_ACK: return "GACK"; - case PIM_MSG_TYPE_CANDIDATE: return "CANDIDATE"; - } - - return "UNKNOWN"; + switch (type) { + case PIM_MSG_TYPE_HELLO: + return "HELLO"; + case PIM_MSG_TYPE_REGISTER: + return "REGISTER"; + case PIM_MSG_TYPE_REG_STOP: + return "REGSTOP"; + case PIM_MSG_TYPE_JOIN_PRUNE: + return "JOINPRUNE"; + case PIM_MSG_TYPE_BOOTSTRAP: + return "BOOT"; + case PIM_MSG_TYPE_ASSERT: + return "ASSERT"; + case PIM_MSG_TYPE_GRAFT: + return "GRAFT"; + case PIM_MSG_TYPE_GRAFT_ACK: + return "GACK"; + case PIM_MSG_TYPE_CANDIDATE: + return "CANDIDATE"; + } + + return "UNKNOWN"; } static void sock_close(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - - if (PIM_DEBUG_PIM_TRACE) { - if (pim_ifp->t_pim_sock_read) { - zlog_debug("Cancelling READ event for PIM socket fd=%d on interface %s", - pim_ifp->pim_sock_fd, - ifp->name); - } - } - THREAD_OFF(pim_ifp->t_pim_sock_read); - - if (PIM_DEBUG_PIM_TRACE) { - if (pim_ifp->t_pim_hello_timer) { - zlog_debug("Cancelling PIM hello timer for interface %s", - ifp->name); - } - } - THREAD_OFF(pim_ifp->t_pim_hello_timer); - - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("Deleting PIM socket fd=%d on interface %s", - pim_ifp->pim_sock_fd, ifp->name); - } - - /* - * If the fd is already deleted no need to do anything here - */ - if (pim_ifp->pim_sock_fd > 0 && close(pim_ifp->pim_sock_fd)) { - zlog_warn("Failure closing PIM socket fd=%d on interface %s: errno=%d: %s", - pim_ifp->pim_sock_fd, ifp->name, - errno, safe_strerror(errno)); - } - - pim_ifp->pim_sock_fd = -1; - pim_ifp->pim_sock_creation = 0; + struct pim_interface *pim_ifp = ifp->info; + + if (PIM_DEBUG_PIM_TRACE) { + if (pim_ifp->t_pim_sock_read) { + zlog_debug( + "Cancelling READ event for PIM socket fd=%d on interface %s", + pim_ifp->pim_sock_fd, ifp->name); + } + } + THREAD_OFF(pim_ifp->t_pim_sock_read); + + if (PIM_DEBUG_PIM_TRACE) { + if (pim_ifp->t_pim_hello_timer) { + zlog_debug( + "Cancelling PIM hello timer for interface %s", + ifp->name); + } + } + THREAD_OFF(pim_ifp->t_pim_hello_timer); + + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("Deleting PIM socket fd=%d on interface %s", + pim_ifp->pim_sock_fd, ifp->name); + } + + /* + * If the fd is already deleted no need to do anything here + */ + if (pim_ifp->pim_sock_fd > 0 && close(pim_ifp->pim_sock_fd)) { + zlog_warn( + "Failure closing PIM socket fd=%d on interface %s: errno=%d: %s", + pim_ifp->pim_sock_fd, ifp->name, errno, + safe_strerror(errno)); + } + + pim_ifp->pim_sock_fd = -1; + pim_ifp->pim_sock_creation = 0; } void pim_sock_delete(struct interface *ifp, const char *delete_message) { - zlog_info("PIM INTERFACE DOWN: on interface %s: %s", - ifp->name, delete_message); - - if (!ifp->info) { - zlog_err("%s: %s: but PIM not enabled on interface %s (!)", - __PRETTY_FUNCTION__, delete_message, ifp->name); - return; - } - - /* - RFC 4601: 4.3.1. Sending Hello Messages - - Before an interface goes down or changes primary IP address, a Hello - message with a zero HoldTime should be sent immediately (with the - old IP address if the IP address changed). - */ - pim_hello_send(ifp, 0 /* zero-sec holdtime */); - - pim_neighbor_delete_all(ifp, delete_message); - - sock_close(ifp); + zlog_info("PIM INTERFACE DOWN: on interface %s: %s", ifp->name, + delete_message); + + if (!ifp->info) { + zlog_err("%s: %s: but PIM not enabled on interface %s (!)", + __PRETTY_FUNCTION__, delete_message, ifp->name); + return; + } + + /* + RFC 4601: 4.3.1. Sending Hello Messages + + Before an interface goes down or changes primary IP address, a Hello + message with a zero HoldTime should be sent immediately (with the + old IP address if the IP address changed). + */ + pim_hello_send(ifp, 0 /* zero-sec holdtime */); + + pim_neighbor_delete_all(ifp, delete_message); + + sock_close(ifp); } int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) { - struct ip *ip_hdr; - size_t ip_hlen; /* ip header length in bytes */ - char src_str[INET_ADDRSTRLEN]; - char dst_str[INET_ADDRSTRLEN]; - uint8_t *pim_msg; - int pim_msg_len; - uint16_t pim_checksum; /* received checksum */ - uint16_t checksum; /* computed checksum */ - struct pim_neighbor *neigh; - struct pim_msg_header *header; - - if (len < sizeof(*ip_hdr)) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("PIM packet size=%zu shorter than minimum=%zu", - len, sizeof(*ip_hdr)); - return -1; - } - - ip_hdr = (struct ip *) buf; - ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ - - pim_msg = buf + ip_hlen; - pim_msg_len = len - ip_hlen; - - header = (struct pim_msg_header *)pim_msg; - if (pim_msg_len < PIM_PIM_MIN_LEN) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("PIM message size=%d shorter than minimum=%d", - pim_msg_len, PIM_PIM_MIN_LEN); - return -1; - } - - if (header->ver != PIM_PROTO_VERSION) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("Ignoring PIM pkt from %s with unsupported version: %d", - ifp->name, header->ver); - return -1; - } - - /* save received checksum */ - pim_checksum = header->checksum; - - /* for computing checksum */ - header->checksum = 0; - - if (header->type == PIM_MSG_TYPE_REGISTER) - { - /* First 8 byte header checksum */ - checksum = in_cksum (pim_msg, PIM_MSG_REGISTER_LEN); - if (checksum != pim_checksum) - { - checksum = in_cksum (pim_msg, pim_msg_len); - if (checksum != pim_checksum) - { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug - ("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x", - ifp->name, pim_checksum, checksum); - - return -1; - } - } - } - else - { - checksum = in_cksum (pim_msg, pim_msg_len); - if (checksum != pim_checksum) - { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug - ("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x", - ifp->name, pim_checksum, checksum); - - return -1; - } - } - - if (PIM_DEBUG_PIM_PACKETS) { - pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, sizeof(src_str)); - pim_inet4_dump("<dst?>", ip_hdr->ip_dst, dst_str, sizeof(dst_str)); - zlog_debug("Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x", - pim_pim_msgtype2str (header->type), src_str, dst_str, ifp->name, - ip_hdr->ip_ttl, header->ver, pim_msg_len, checksum); - if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { - pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_len); - } - } - - switch (header->type) - { - case PIM_MSG_TYPE_HELLO: - return pim_hello_recv (ifp, - ip_hdr->ip_src, - pim_msg + PIM_MSG_HEADER_LEN, - pim_msg_len - PIM_MSG_HEADER_LEN); - break; - case PIM_MSG_TYPE_REGISTER: - return pim_register_recv (ifp, - ip_hdr->ip_dst, - ip_hdr->ip_src, - pim_msg + PIM_MSG_HEADER_LEN, - pim_msg_len - PIM_MSG_HEADER_LEN); - break; - case PIM_MSG_TYPE_REG_STOP: - return pim_register_stop_recv (pim_msg + PIM_MSG_HEADER_LEN, - pim_msg_len - PIM_MSG_HEADER_LEN); - break; - case PIM_MSG_TYPE_JOIN_PRUNE: - neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); - if (!neigh) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", - __FILE__, __PRETTY_FUNCTION__, - header->type, src_str, ifp->name); - return -1; - } - pim_neighbor_timer_reset(neigh, neigh->holdtime); - return pim_joinprune_recv(ifp, neigh, - ip_hdr->ip_src, - pim_msg + PIM_MSG_HEADER_LEN, - pim_msg_len - PIM_MSG_HEADER_LEN); - break; - case PIM_MSG_TYPE_ASSERT: - neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); - if (!neigh) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", - __FILE__, __PRETTY_FUNCTION__, - header->type, src_str, ifp->name); + struct ip *ip_hdr; + size_t ip_hlen; /* ip header length in bytes */ + char src_str[INET_ADDRSTRLEN]; + char dst_str[INET_ADDRSTRLEN]; + uint8_t *pim_msg; + int pim_msg_len; + uint16_t pim_checksum; /* received checksum */ + uint16_t checksum; /* computed checksum */ + struct pim_neighbor *neigh; + struct pim_msg_header *header; + + if (len < sizeof(*ip_hdr)) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "PIM packet size=%zu shorter than minimum=%zu", + len, sizeof(*ip_hdr)); + return -1; + } + + ip_hdr = (struct ip *)buf; + ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ + + pim_msg = buf + ip_hlen; + pim_msg_len = len - ip_hlen; + + header = (struct pim_msg_header *)pim_msg; + if (pim_msg_len < PIM_PIM_MIN_LEN) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "PIM message size=%d shorter than minimum=%d", + pim_msg_len, PIM_PIM_MIN_LEN); + return -1; + } + + if (header->ver != PIM_PROTO_VERSION) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "Ignoring PIM pkt from %s with unsupported version: %d", + ifp->name, header->ver); + return -1; + } + + /* save received checksum */ + pim_checksum = header->checksum; + + /* for computing checksum */ + header->checksum = 0; + + if (header->type == PIM_MSG_TYPE_REGISTER) { + /* First 8 byte header checksum */ + checksum = in_cksum(pim_msg, PIM_MSG_REGISTER_LEN); + if (checksum != pim_checksum) { + checksum = in_cksum(pim_msg, pim_msg_len); + if (checksum != pim_checksum) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x", + ifp->name, pim_checksum, + checksum); + + return -1; + } + } + } else { + checksum = in_cksum(pim_msg, pim_msg_len); + if (checksum != pim_checksum) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x", + ifp->name, pim_checksum, checksum); + + return -1; + } + } + + if (PIM_DEBUG_PIM_PACKETS) { + pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, + sizeof(src_str)); + pim_inet4_dump("<dst?>", ip_hdr->ip_dst, dst_str, + sizeof(dst_str)); + zlog_debug( + "Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x", + pim_pim_msgtype2str(header->type), src_str, dst_str, + ifp->name, ip_hdr->ip_ttl, header->ver, pim_msg_len, + checksum); + if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { + pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_len); + } + } + + switch (header->type) { + case PIM_MSG_TYPE_HELLO: + return pim_hello_recv(ifp, ip_hdr->ip_src, + pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); + break; + case PIM_MSG_TYPE_REGISTER: + return pim_register_recv(ifp, ip_hdr->ip_dst, ip_hdr->ip_src, + pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); + break; + case PIM_MSG_TYPE_REG_STOP: + return pim_register_stop_recv(pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); + break; + case PIM_MSG_TYPE_JOIN_PRUNE: + neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); + if (!neigh) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", + __FILE__, __PRETTY_FUNCTION__, + header->type, src_str, ifp->name); + return -1; + } + pim_neighbor_timer_reset(neigh, neigh->holdtime); + return pim_joinprune_recv(ifp, neigh, ip_hdr->ip_src, + pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); + break; + case PIM_MSG_TYPE_ASSERT: + neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); + if (!neigh) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", + __FILE__, __PRETTY_FUNCTION__, + header->type, src_str, ifp->name); + return -1; + } + pim_neighbor_timer_reset(neigh, neigh->holdtime); + return pim_assert_recv(ifp, neigh, ip_hdr->ip_src, + pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); + break; + default: + if (PIM_DEBUG_PIM_PACKETS) { + zlog_debug( + "Recv PIM packet type %d which is not currently understood", + header->type); + } + return -1; + } return -1; - } - pim_neighbor_timer_reset(neigh, neigh->holdtime); - return pim_assert_recv(ifp, neigh, - ip_hdr->ip_src, - pim_msg + PIM_MSG_HEADER_LEN, - pim_msg_len - PIM_MSG_HEADER_LEN); - break; - default: - if (PIM_DEBUG_PIM_PACKETS) { - zlog_debug("Recv PIM packet type %d which is not currently understood", - header->type); - } - return -1; - } - return -1; } static void pim_sock_read_on(struct interface *ifp); static int pim_sock_read(struct thread *t) { - struct interface *ifp; - struct pim_interface *pim_ifp; - int fd; - struct sockaddr_in from; - struct sockaddr_in to; - socklen_t fromlen = sizeof(from); - socklen_t tolen = sizeof(to); - uint8_t buf[PIM_PIM_BUFSIZE_READ]; - int len; - ifindex_t ifindex = -1; - int result = -1; /* defaults to bad */ - static long long count = 0; - int cont = 1; - - ifp = THREAD_ARG(t); - fd = THREAD_FD(t); - - pim_ifp = ifp->info; - - while (cont) - { - len = pim_socket_recvfromto(fd, buf, sizeof(buf), - &from, &fromlen, - &to, &tolen, - &ifindex); - if (len < 0) - { - if (errno == EINTR) - continue; - if (errno == EWOULDBLOCK || errno == EAGAIN) - break; - - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("Received errno: %d %s", errno, safe_strerror (errno)); - goto done; - } + struct interface *ifp; + struct pim_interface *pim_ifp; + int fd; + struct sockaddr_in from; + struct sockaddr_in to; + socklen_t fromlen = sizeof(from); + socklen_t tolen = sizeof(to); + uint8_t buf[PIM_PIM_BUFSIZE_READ]; + int len; + ifindex_t ifindex = -1; + int result = -1; /* defaults to bad */ + static long long count = 0; + int cont = 1; + + ifp = THREAD_ARG(t); + fd = THREAD_FD(t); + + pim_ifp = ifp->info; + + while (cont) { + len = pim_socket_recvfromto(fd, buf, sizeof(buf), &from, + &fromlen, &to, &tolen, &ifindex); + if (len < 0) { + if (errno == EINTR) + continue; + if (errno == EWOULDBLOCK || errno == EAGAIN) + break; + + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("Received errno: %d %s", errno, + safe_strerror(errno)); + goto done; + } #ifdef PIM_CHECK_RECV_IFINDEX_SANITY - /* ifindex sanity check */ - if (ifindex != (int) ifp->ifindex) { - char from_str[INET_ADDRSTRLEN]; - char to_str[INET_ADDRSTRLEN]; - struct interface *recv_ifp; - - if (!inet_ntop(AF_INET, &from.sin_addr, from_str , sizeof(from_str))) - sprintf(from_str, "<from?>"); - if (!inet_ntop(AF_INET, &to.sin_addr, to_str , sizeof(to_str))) - sprintf(to_str, "<to?>"); - - recv_ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); - if (recv_ifp) { - zassert(ifindex == (int) recv_ifp->ifindex); - } + /* ifindex sanity check */ + if (ifindex != (int)ifp->ifindex) { + char from_str[INET_ADDRSTRLEN]; + char to_str[INET_ADDRSTRLEN]; + struct interface *recv_ifp; + + if (!inet_ntop(AF_INET, &from.sin_addr, from_str, + sizeof(from_str))) + sprintf(from_str, "<from?>"); + if (!inet_ntop(AF_INET, &to.sin_addr, to_str, + sizeof(to_str))) + sprintf(to_str, "<to?>"); + + recv_ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + if (recv_ifp) { + zassert(ifindex == (int)recv_ifp->ifindex); + } #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH - zlog_warn("Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)", - from_str, to_str, fd, - ifindex, recv_ifp ? recv_ifp->name : "<if-notfound>", - ifp->ifindex, ifp->name); + zlog_warn( + "Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)", + from_str, to_str, fd, ifindex, + recv_ifp ? recv_ifp->name : "<if-notfound>", + ifp->ifindex, ifp->name); #endif - goto done; - } + goto done; + } #endif - int fail = pim_pim_packet(ifp, buf, len); - if (fail) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("%s: pim_pim_packet() return=%d", - __PRETTY_FUNCTION__, fail); - goto done; - } - - count++; - if (count % qpim_packet_process == 0) - cont = 0; - } + int fail = pim_pim_packet(ifp, buf, len); + if (fail) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("%s: pim_pim_packet() return=%d", + __PRETTY_FUNCTION__, fail); + goto done; + } + + count++; + if (count % qpim_packet_process == 0) + cont = 0; + } - result = 0; /* good */ + result = 0; /* good */ - done: - pim_sock_read_on(ifp); +done: + pim_sock_read_on(ifp); - if (result) { - ++pim_ifp->pim_ifstat_hello_recvfail; - } + if (result) { + ++pim_ifp->pim_ifstat_hello_recvfail; + } - return result; + return result; } static void pim_sock_read_on(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - zassert(ifp); - zassert(ifp->info); + zassert(ifp); + zassert(ifp->info); - pim_ifp = ifp->info; + pim_ifp = ifp->info; - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - zlog_debug("Scheduling READ event on PIM socket fd=%d", - pim_ifp->pim_sock_fd); - } - pim_ifp->t_pim_sock_read = NULL; - thread_add_read(master, pim_sock_read, ifp, pim_ifp->pim_sock_fd, - &pim_ifp->t_pim_sock_read); + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + zlog_debug("Scheduling READ event on PIM socket fd=%d", + pim_ifp->pim_sock_fd); + } + pim_ifp->t_pim_sock_read = NULL; + thread_add_read(master, pim_sock_read, ifp, pim_ifp->pim_sock_fd, + &pim_ifp->t_pim_sock_read); } static int pim_sock_open(struct interface *ifp) { - int fd; - struct pim_interface *pim_ifp = ifp->info; - - fd = pim_socket_mcast(IPPROTO_PIM, pim_ifp->primary_address, ifp, 0 /* loop=false */); - if (fd < 0) - return -1; - - if (pim_socket_join(fd, qpim_all_pim_routers_addr, pim_ifp->primary_address, ifp->ifindex)) { - close(fd); - return -2; - } + int fd; + struct pim_interface *pim_ifp = ifp->info; + + fd = pim_socket_mcast(IPPROTO_PIM, pim_ifp->primary_address, ifp, + 0 /* loop=false */); + if (fd < 0) + return -1; + + if (pim_socket_join(fd, qpim_all_pim_routers_addr, + pim_ifp->primary_address, ifp->ifindex)) { + close(fd); + return -2; + } - return fd; + return fd; } void pim_ifstat_reset(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - zassert(ifp); + zassert(ifp); - pim_ifp = ifp->info; - if (!pim_ifp) { - return; - } + pim_ifp = ifp->info; + if (!pim_ifp) { + return; + } - pim_ifp->pim_ifstat_start = pim_time_monotonic_sec(); - pim_ifp->pim_ifstat_hello_sent = 0; - pim_ifp->pim_ifstat_hello_sendfail = 0; - pim_ifp->pim_ifstat_hello_recv = 0; - pim_ifp->pim_ifstat_hello_recvfail = 0; + pim_ifp->pim_ifstat_start = pim_time_monotonic_sec(); + pim_ifp->pim_ifstat_hello_sent = 0; + pim_ifp->pim_ifstat_hello_sendfail = 0; + pim_ifp->pim_ifstat_hello_recv = 0; + pim_ifp->pim_ifstat_hello_recvfail = 0; } void pim_sock_reset(struct interface *ifp) { - struct pim_interface *pim_ifp; - - zassert(ifp); - zassert(ifp->info); - - pim_ifp = ifp->info; - - pim_ifp->primary_address = pim_find_primary_addr(ifp); - - pim_ifp->pim_sock_fd = -1; - pim_ifp->pim_sock_creation = 0; - pim_ifp->t_pim_sock_read = NULL; - - pim_ifp->t_pim_hello_timer = NULL; - pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD; - pim_ifp->pim_default_holdtime = -1; /* unset: means 3.5 * pim_hello_period */ - pim_ifp->pim_triggered_hello_delay = PIM_DEFAULT_TRIGGERED_HELLO_DELAY; - pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY; - pim_ifp->pim_propagation_delay_msec = PIM_DEFAULT_PROPAGATION_DELAY_MSEC; - pim_ifp->pim_override_interval_msec = PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC; - if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION) { - PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options); - } - else { - PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options); - } - - /* neighbors without lan_delay */ - pim_ifp->pim_number_of_nonlandelay_neighbors = 0; - pim_ifp->pim_neighbors_highest_propagation_delay_msec = 0; - pim_ifp->pim_neighbors_highest_override_interval_msec = 0; - - /* DR Election */ - pim_ifp->pim_dr_election_last = 0; /* timestamp */ - pim_ifp->pim_dr_election_count = 0; - pim_ifp->pim_dr_election_changes = 0; - pim_ifp->pim_dr_num_nondrpri_neighbors = 0; /* neighbors without dr_pri */ - pim_ifp->pim_dr_addr = pim_ifp->primary_address; - - pim_ifstat_reset(ifp); + struct pim_interface *pim_ifp; + + zassert(ifp); + zassert(ifp->info); + + pim_ifp = ifp->info; + + pim_ifp->primary_address = pim_find_primary_addr(ifp); + + pim_ifp->pim_sock_fd = -1; + pim_ifp->pim_sock_creation = 0; + pim_ifp->t_pim_sock_read = NULL; + + pim_ifp->t_pim_hello_timer = NULL; + pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD; + pim_ifp->pim_default_holdtime = + -1; /* unset: means 3.5 * pim_hello_period */ + pim_ifp->pim_triggered_hello_delay = PIM_DEFAULT_TRIGGERED_HELLO_DELAY; + pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY; + pim_ifp->pim_propagation_delay_msec = + PIM_DEFAULT_PROPAGATION_DELAY_MSEC; + pim_ifp->pim_override_interval_msec = + PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC; + if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION) { + PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options); + } else { + PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options); + } + + /* neighbors without lan_delay */ + pim_ifp->pim_number_of_nonlandelay_neighbors = 0; + pim_ifp->pim_neighbors_highest_propagation_delay_msec = 0; + pim_ifp->pim_neighbors_highest_override_interval_msec = 0; + + /* DR Election */ + pim_ifp->pim_dr_election_last = 0; /* timestamp */ + pim_ifp->pim_dr_election_count = 0; + pim_ifp->pim_dr_election_changes = 0; + pim_ifp->pim_dr_num_nondrpri_neighbors = + 0; /* neighbors without dr_pri */ + pim_ifp->pim_dr_addr = pim_ifp->primary_address; + + pim_ifstat_reset(ifp); } static uint16_t ip_id = 0; -static int -pim_msg_send_frame (int fd, char *buf, size_t len, - struct sockaddr *dst, size_t salen) +static int pim_msg_send_frame(int fd, char *buf, size_t len, + struct sockaddr *dst, size_t salen) { - struct ip *ip = (struct ip *)buf; - - while (sendto (fd, buf, len, MSG_DONTWAIT, dst, salen) < 0) - { - char dst_str[INET_ADDRSTRLEN]; - - switch (errno) - { - case EMSGSIZE: - { - size_t hdrsize = sizeof (struct ip); - size_t newlen1 = ((len - hdrsize) / 2 ) & 0xFFF8; - size_t sendlen = newlen1 + hdrsize; - size_t offset = ntohs (ip->ip_off); - - ip->ip_len = htons (sendlen); - ip->ip_off = htons (offset | IP_MF); - if (pim_msg_send_frame (fd, buf, sendlen, dst, salen) == 0) - { - struct ip *ip2 = (struct ip *)(buf + newlen1); - size_t newlen2 = len - sendlen; - sendlen = newlen2 + hdrsize; - - memcpy (ip2, ip, hdrsize); - ip2->ip_len = htons (sendlen); - ip2->ip_off = htons (offset + (newlen1 >> 3)); - return pim_msg_send_frame (fd, (char *)ip2, sendlen, dst, salen); - } - } - - return -1; - break; - default: - if (PIM_DEBUG_PIM_PACKETS) - { - pim_inet4_dump ("<dst?>", ip->ip_dst, dst_str, sizeof (dst_str)); - zlog_warn ("%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s", - __PRETTY_FUNCTION__, - dst_str, fd, len, - errno, safe_strerror(errno)); - } - return -1; - break; + struct ip *ip = (struct ip *)buf; + + while (sendto(fd, buf, len, MSG_DONTWAIT, dst, salen) < 0) { + char dst_str[INET_ADDRSTRLEN]; + + switch (errno) { + case EMSGSIZE: { + size_t hdrsize = sizeof(struct ip); + size_t newlen1 = ((len - hdrsize) / 2) & 0xFFF8; + size_t sendlen = newlen1 + hdrsize; + size_t offset = ntohs(ip->ip_off); + + ip->ip_len = htons(sendlen); + ip->ip_off = htons(offset | IP_MF); + if (pim_msg_send_frame(fd, buf, sendlen, dst, salen) + == 0) { + struct ip *ip2 = (struct ip *)(buf + newlen1); + size_t newlen2 = len - sendlen; + sendlen = newlen2 + hdrsize; + + memcpy(ip2, ip, hdrsize); + ip2->ip_len = htons(sendlen); + ip2->ip_off = htons(offset + (newlen1 >> 3)); + return pim_msg_send_frame(fd, (char *)ip2, + sendlen, dst, salen); + } + } + + return -1; + break; + default: + if (PIM_DEBUG_PIM_PACKETS) { + pim_inet4_dump("<dst?>", ip->ip_dst, dst_str, + sizeof(dst_str)); + zlog_warn( + "%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s", + __PRETTY_FUNCTION__, dst_str, fd, len, + errno, safe_strerror(errno)); + } + return -1; + break; + } } - } - return 0; + return 0; } -int -pim_msg_send(int fd, struct in_addr src, - struct in_addr dst, uint8_t *pim_msg, - int pim_msg_size, const char *ifname) +int pim_msg_send(int fd, struct in_addr src, struct in_addr dst, + uint8_t *pim_msg, int pim_msg_size, const char *ifname) { - struct sockaddr_in to; - socklen_t tolen; - unsigned char buffer[10000]; - unsigned char *msg_start; - uint8_t ttl = MAXTTL; - struct pim_msg_header *header; - struct ip *ip; - - memset (buffer, 0, 10000); - int sendlen = sizeof (struct ip) + pim_msg_size; - - msg_start = buffer + sizeof (struct ip); - memcpy (msg_start, pim_msg, pim_msg_size); - - header = (struct pim_msg_header *)pim_msg; - /* - * Omnios apparently doesn't have a #define for IP default - * ttl that is the same as all other platforms. - */ + struct sockaddr_in to; + socklen_t tolen; + unsigned char buffer[10000]; + unsigned char *msg_start; + uint8_t ttl = MAXTTL; + struct pim_msg_header *header; + struct ip *ip; + + memset(buffer, 0, 10000); + int sendlen = sizeof(struct ip) + pim_msg_size; + + msg_start = buffer + sizeof(struct ip); + memcpy(msg_start, pim_msg, pim_msg_size); + + header = (struct pim_msg_header *)pim_msg; +/* + * Omnios apparently doesn't have a #define for IP default + * ttl that is the same as all other platforms. + */ #ifndef IPDEFTTL #define IPDEFTTL 64 #endif - /* TTL for packets destine to ALL-PIM-ROUTERS is 1 */ - switch (header->type) - { - case PIM_MSG_TYPE_HELLO: - case PIM_MSG_TYPE_JOIN_PRUNE: - case PIM_MSG_TYPE_BOOTSTRAP: - case PIM_MSG_TYPE_ASSERT: - ttl = 1; - break; - case PIM_MSG_TYPE_REGISTER: - case PIM_MSG_TYPE_REG_STOP: - case PIM_MSG_TYPE_GRAFT: - case PIM_MSG_TYPE_GRAFT_ACK: - case PIM_MSG_TYPE_CANDIDATE: - ttl = IPDEFTTL; - break; - default: - ttl = MAXTTL; - break; - } - - ip = (struct ip *) buffer; - ip->ip_id = htons (++ip_id); - ip->ip_hl = 5; - ip->ip_v = 4; - ip->ip_p = PIM_IP_PROTO_PIM; - ip->ip_src = src; - ip->ip_dst = dst; - ip->ip_ttl = ttl; - ip->ip_len = htons (sendlen); - - if (PIM_DEBUG_PIM_PACKETS) { - struct pim_msg_header *header = (struct pim_msg_header *)pim_msg; - char dst_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str)); - zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x", - __PRETTY_FUNCTION__, - dst_str, ifname, pim_msg_size, - header->checksum); - } - - memset(&to, 0, sizeof(to)); - to.sin_family = AF_INET; - to.sin_addr = dst; - tolen = sizeof(to); - - if (PIM_DEBUG_PIM_PACKETDUMP_SEND) { - pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_size); - } - - pim_msg_send_frame (fd, (char *)buffer, sendlen, - (struct sockaddr *)&to, tolen); - return 0; + /* TTL for packets destine to ALL-PIM-ROUTERS is 1 */ + switch (header->type) { + case PIM_MSG_TYPE_HELLO: + case PIM_MSG_TYPE_JOIN_PRUNE: + case PIM_MSG_TYPE_BOOTSTRAP: + case PIM_MSG_TYPE_ASSERT: + ttl = 1; + break; + case PIM_MSG_TYPE_REGISTER: + case PIM_MSG_TYPE_REG_STOP: + case PIM_MSG_TYPE_GRAFT: + case PIM_MSG_TYPE_GRAFT_ACK: + case PIM_MSG_TYPE_CANDIDATE: + ttl = IPDEFTTL; + break; + default: + ttl = MAXTTL; + break; + } + + ip = (struct ip *)buffer; + ip->ip_id = htons(++ip_id); + ip->ip_hl = 5; + ip->ip_v = 4; + ip->ip_p = PIM_IP_PROTO_PIM; + ip->ip_src = src; + ip->ip_dst = dst; + ip->ip_ttl = ttl; + ip->ip_len = htons(sendlen); + + if (PIM_DEBUG_PIM_PACKETS) { + struct pim_msg_header *header = + (struct pim_msg_header *)pim_msg; + char dst_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str)); + zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x", + __PRETTY_FUNCTION__, dst_str, ifname, pim_msg_size, + header->checksum); + } + + memset(&to, 0, sizeof(to)); + to.sin_family = AF_INET; + to.sin_addr = dst; + tolen = sizeof(to); + + if (PIM_DEBUG_PIM_PACKETDUMP_SEND) { + pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_size); + } + + pim_msg_send_frame(fd, (char *)buffer, sendlen, (struct sockaddr *)&to, + tolen); + return 0; } -static int hello_send(struct interface *ifp, - uint16_t holdtime) +static int hello_send(struct interface *ifp, uint16_t holdtime) { - uint8_t pim_msg[PIM_PIM_BUFSIZE_WRITE]; - struct pim_interface *pim_ifp; - int pim_tlv_size; - int pim_msg_size; - - pim_ifp = ifp->info; - - if (PIM_DEBUG_PIM_HELLO) { - char dst_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr, dst_str, sizeof(dst_str)); - zlog_debug("%s: to %s on %s: holdt=%u prop_d=%u overr_i=%u dis_join_supp=%d dr_prio=%u gen_id=%08x addrs=%d", - __PRETTY_FUNCTION__, - dst_str, ifp->name, - holdtime, - pim_ifp->pim_propagation_delay_msec, pim_ifp->pim_override_interval_msec, - PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options), - pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id, - listcount(ifp->connected)); - } - - pim_tlv_size = pim_hello_build_tlv(ifp, - pim_msg + PIM_PIM_MIN_LEN, - sizeof(pim_msg) - PIM_PIM_MIN_LEN, - holdtime, - pim_ifp->pim_dr_priority, - pim_ifp->pim_generation_id, - pim_ifp->pim_propagation_delay_msec, - pim_ifp->pim_override_interval_msec, - PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)); - if (pim_tlv_size < 0) { - return -1; - } - - pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN; - - zassert(pim_msg_size >= PIM_PIM_MIN_LEN); - zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE); - - pim_msg_build_header(pim_msg, pim_msg_size, PIM_MSG_TYPE_HELLO); - - if (pim_msg_send(pim_ifp->pim_sock_fd, - pim_ifp->primary_address, - qpim_all_pim_routers_addr, - pim_msg, - pim_msg_size, - ifp->name)) { - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not send PIM message on interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return -2; - } - - return 0; + uint8_t pim_msg[PIM_PIM_BUFSIZE_WRITE]; + struct pim_interface *pim_ifp; + int pim_tlv_size; + int pim_msg_size; + + pim_ifp = ifp->info; + + if (PIM_DEBUG_PIM_HELLO) { + char dst_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr, dst_str, + sizeof(dst_str)); + zlog_debug( + "%s: to %s on %s: holdt=%u prop_d=%u overr_i=%u dis_join_supp=%d dr_prio=%u gen_id=%08x addrs=%d", + __PRETTY_FUNCTION__, dst_str, ifp->name, holdtime, + pim_ifp->pim_propagation_delay_msec, + pim_ifp->pim_override_interval_msec, + PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION( + pim_ifp->options), + pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id, + listcount(ifp->connected)); + } + + pim_tlv_size = pim_hello_build_tlv( + ifp, pim_msg + PIM_PIM_MIN_LEN, + sizeof(pim_msg) - PIM_PIM_MIN_LEN, holdtime, + pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id, + pim_ifp->pim_propagation_delay_msec, + pim_ifp->pim_override_interval_msec, + PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)); + if (pim_tlv_size < 0) { + return -1; + } + + pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN; + + zassert(pim_msg_size >= PIM_PIM_MIN_LEN); + zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE); + + pim_msg_build_header(pim_msg, pim_msg_size, PIM_MSG_TYPE_HELLO); + + if (pim_msg_send(pim_ifp->pim_sock_fd, pim_ifp->primary_address, + qpim_all_pim_routers_addr, pim_msg, pim_msg_size, + ifp->name)) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug( + "%s: could not send PIM message on interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -2; + } + + return 0; } -static int pim_hello_send(struct interface *ifp, - uint16_t holdtime) +static int pim_hello_send(struct interface *ifp, uint16_t holdtime) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - zassert(ifp); - pim_ifp = ifp->info; - zassert(pim_ifp); + zassert(ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - if (if_is_loopback (ifp)) - return 0; + if (if_is_loopback(ifp)) + return 0; - if (hello_send(ifp, holdtime)) { - ++pim_ifp->pim_ifstat_hello_sendfail; + if (hello_send(ifp, holdtime)) { + ++pim_ifp->pim_ifstat_hello_sendfail; - if (PIM_DEBUG_PIM_HELLO) { - zlog_warn("Could not send PIM hello on interface %s", - ifp->name); - } - return -1; - } + if (PIM_DEBUG_PIM_HELLO) { + zlog_warn("Could not send PIM hello on interface %s", + ifp->name); + } + return -1; + } - ++pim_ifp->pim_ifstat_hello_sent; + ++pim_ifp->pim_ifstat_hello_sent; - return 0; + return 0; } static void hello_resched(struct interface *ifp) { - struct pim_interface *pim_ifp; - - zassert(ifp); - pim_ifp = ifp->info; - zassert(pim_ifp); - - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("Rescheduling %d sec hello on interface %s", - pim_ifp->pim_hello_period, ifp->name); - } - THREAD_OFF(pim_ifp->t_pim_hello_timer); - thread_add_timer(master, on_pim_hello_send, ifp, pim_ifp->pim_hello_period, - &pim_ifp->t_pim_hello_timer); + struct pim_interface *pim_ifp; + + zassert(ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); + + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug("Rescheduling %d sec hello on interface %s", + pim_ifp->pim_hello_period, ifp->name); + } + THREAD_OFF(pim_ifp->t_pim_hello_timer); + thread_add_timer(master, on_pim_hello_send, ifp, + pim_ifp->pim_hello_period, + &pim_ifp->t_pim_hello_timer); } /* @@ -711,22 +714,22 @@ static void hello_resched(struct interface *ifp) */ static int on_pim_hello_send(struct thread *t) { - struct pim_interface *pim_ifp; - struct interface *ifp; + struct pim_interface *pim_ifp; + struct interface *ifp; - ifp = THREAD_ARG(t); + ifp = THREAD_ARG(t); - pim_ifp = ifp->info; + pim_ifp = ifp->info; - /* - * Schedule next hello - */ - hello_resched(ifp); + /* + * Schedule next hello + */ + hello_resched(ifp); - /* - * Send hello - */ - return pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); + /* + * Send hello + */ + return pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); } /* @@ -740,21 +743,21 @@ static int on_pim_hello_send(struct thread *t) */ void pim_hello_restart_now(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - zassert(ifp); - pim_ifp = ifp->info; - zassert(pim_ifp); + zassert(ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - /* - * Reset next hello timer - */ - hello_resched(ifp); + /* + * Reset next hello timer + */ + hello_resched(ifp); - /* - * Immediately send hello - */ - pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); + /* + * Immediately send hello + */ + pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); } /* @@ -768,105 +771,109 @@ void pim_hello_restart_now(struct interface *ifp) */ void pim_hello_restart_triggered(struct interface *ifp) { - struct pim_interface *pim_ifp; - int triggered_hello_delay_msec; - int random_msec; - - zassert(ifp); - pim_ifp = ifp->info; - zassert(pim_ifp); - - /* - * There exists situations where we have the a RPF out this - * interface, but we haven't formed a neighbor yet. This - * happens especially during interface flaps. While - * we would like to handle this more gracefully in other - * parts of the code. In order to get us up and running - * let's just send the hello immediate'ish - * This should be revisited when we get nexthop tracking - * in and when we have a better handle on safely - * handling the rpf information for upstreams that - * we cannot legally reach yet. - */ - triggered_hello_delay_msec = 1; - //triggered_hello_delay_msec = 1000 * pim_ifp->pim_triggered_hello_delay; - - if (pim_ifp->t_pim_hello_timer) { - long remain_msec = pim_time_timer_remain_msec(pim_ifp->t_pim_hello_timer); - if (remain_msec <= triggered_hello_delay_msec) { - /* Rescheduling hello would increase the delay, then it's faster - to just wait for the scheduled periodic hello. */ - return; - } - - THREAD_OFF(pim_ifp->t_pim_hello_timer); - } - - random_msec = triggered_hello_delay_msec; - //random_msec = random() % (triggered_hello_delay_msec + 1); - - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("Scheduling %d msec triggered hello on interface %s", - random_msec, ifp->name); - } - - thread_add_timer_msec(master, on_pim_hello_send, ifp, random_msec, - &pim_ifp->t_pim_hello_timer); + struct pim_interface *pim_ifp; + int triggered_hello_delay_msec; + int random_msec; + + zassert(ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); + + /* + * There exists situations where we have the a RPF out this + * interface, but we haven't formed a neighbor yet. This + * happens especially during interface flaps. While + * we would like to handle this more gracefully in other + * parts of the code. In order to get us up and running + * let's just send the hello immediate'ish + * This should be revisited when we get nexthop tracking + * in and when we have a better handle on safely + * handling the rpf information for upstreams that + * we cannot legally reach yet. + */ + triggered_hello_delay_msec = 1; + // triggered_hello_delay_msec = 1000 * + // pim_ifp->pim_triggered_hello_delay; + + if (pim_ifp->t_pim_hello_timer) { + long remain_msec = + pim_time_timer_remain_msec(pim_ifp->t_pim_hello_timer); + if (remain_msec <= triggered_hello_delay_msec) { + /* Rescheduling hello would increase the delay, then + it's faster + to just wait for the scheduled periodic hello. */ + return; + } + + THREAD_OFF(pim_ifp->t_pim_hello_timer); + } + + random_msec = triggered_hello_delay_msec; + // random_msec = random() % (triggered_hello_delay_msec + 1); + + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug("Scheduling %d msec triggered hello on interface %s", + random_msec, ifp->name); + } + + thread_add_timer_msec(master, on_pim_hello_send, ifp, random_msec, + &pim_ifp->t_pim_hello_timer); } int pim_sock_add(struct interface *ifp) { - struct pim_interface *pim_ifp; - uint32_t old_genid; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - if (pim_ifp->pim_sock_fd >= 0) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("Can't recreate existing PIM socket fd=%d for interface %s", - pim_ifp->pim_sock_fd, ifp->name); - return -1; - } - - pim_ifp->pim_sock_fd = pim_sock_open(ifp); - if (pim_ifp->pim_sock_fd < 0) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("Could not open PIM socket on interface %s", - ifp->name); - return -2; - } - - pim_socket_ip_hdr (pim_ifp->pim_sock_fd); - - pim_ifp->t_pim_sock_read = NULL; - pim_ifp->pim_sock_creation = pim_time_monotonic_sec(); - - /* - * Just ensure that the new generation id - * actually chooses something different. - * Actually ran across a case where this - * happened, pre-switch to random(). - * While this is unlikely to happen now - * let's make sure it doesn't. - */ - old_genid = pim_ifp->pim_generation_id; - - while (old_genid == pim_ifp->pim_generation_id) - pim_ifp->pim_generation_id = random(); - - zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d", - ifp->name, ifp->ifindex); - - /* - * Start receiving PIM messages - */ - pim_sock_read_on(ifp); - - /* - * Start sending PIM hello's - */ - pim_hello_restart_triggered(ifp); - - return 0; + struct pim_interface *pim_ifp; + uint32_t old_genid; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + if (pim_ifp->pim_sock_fd >= 0) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "Can't recreate existing PIM socket fd=%d for interface %s", + pim_ifp->pim_sock_fd, ifp->name); + return -1; + } + + pim_ifp->pim_sock_fd = pim_sock_open(ifp); + if (pim_ifp->pim_sock_fd < 0) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("Could not open PIM socket on interface %s", + ifp->name); + return -2; + } + + pim_socket_ip_hdr(pim_ifp->pim_sock_fd); + + pim_ifp->t_pim_sock_read = NULL; + pim_ifp->pim_sock_creation = pim_time_monotonic_sec(); + + /* + * Just ensure that the new generation id + * actually chooses something different. + * Actually ran across a case where this + * happened, pre-switch to random(). + * While this is unlikely to happen now + * let's make sure it doesn't. + */ + old_genid = pim_ifp->pim_generation_id; + + while (old_genid == pim_ifp->pim_generation_id) + pim_ifp->pim_generation_id = random(); + + zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d", ifp->name, + ifp->ifindex); + + /* + * Start receiving PIM messages + */ + pim_sock_read_on(ifp); + + /* + * Start sending PIM hello's + */ + pim_hello_restart_triggered(ifp); + + return 0; } diff --git a/pimd/pim_pim.h b/pimd/pim_pim.h index 7e2872184..e930ab7c2 100644 --- a/pimd/pim_pim.h +++ b/pimd/pim_pim.h @@ -36,15 +36,15 @@ #define PIM_DEFAULT_T_PERIODIC (60) /* RFC 4601: 4.11. Timer Values */ enum pim_msg_type { - PIM_MSG_TYPE_HELLO = 0, - PIM_MSG_TYPE_REGISTER, - PIM_MSG_TYPE_REG_STOP, - PIM_MSG_TYPE_JOIN_PRUNE, - PIM_MSG_TYPE_BOOTSTRAP, - PIM_MSG_TYPE_ASSERT, - PIM_MSG_TYPE_GRAFT, - PIM_MSG_TYPE_GRAFT_ACK, - PIM_MSG_TYPE_CANDIDATE + PIM_MSG_TYPE_HELLO = 0, + PIM_MSG_TYPE_REGISTER, + PIM_MSG_TYPE_REG_STOP, + PIM_MSG_TYPE_JOIN_PRUNE, + PIM_MSG_TYPE_BOOTSTRAP, + PIM_MSG_TYPE_ASSERT, + PIM_MSG_TYPE_GRAFT, + PIM_MSG_TYPE_GRAFT_ACK, + PIM_MSG_TYPE_CANDIDATE }; void pim_ifstat_reset(struct interface *ifp); @@ -56,11 +56,7 @@ void pim_hello_restart_triggered(struct interface *ifp); int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len); -int pim_msg_send(int fd, - struct in_addr src, - struct in_addr dst, - uint8_t *pim_msg, - int pim_msg_size, - const char *ifname); +int pim_msg_send(int fd, struct in_addr src, struct in_addr dst, + uint8_t *pim_msg, int pim_msg_size, const char *ifname); #endif /* PIM_PIM_H */ diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 682a6401c..1cbe1dcf7 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -46,179 +46,173 @@ struct thread *send_test_packet_timer = NULL; -void -pim_register_join (struct pim_upstream *up) +void pim_register_join(struct pim_upstream *up) { - if (pim_is_grp_ssm (up->sg.grp)) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug ("%s register setup skipped as group is SSM", up->sg_str); - return; - } - - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); - up->reg_state = PIM_REG_JOIN; + if (pim_is_grp_ssm(up->sg.grp)) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug("%s register setup skipped as group is SSM", + up->sg_str); + return; + } + + pim_channel_add_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_PIM); + up->reg_state = PIM_REG_JOIN; } -void -pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, - struct in_addr src, struct in_addr originator) +void pim_register_stop_send(struct interface *ifp, struct prefix_sg *sg, + struct in_addr src, struct in_addr originator) { - struct pim_interface *pinfo; - unsigned char buffer[10000]; - unsigned int b1length = 0; - unsigned int length; - uint8_t *b1; - struct prefix p; - - if (PIM_DEBUG_PIM_REG) - { - zlog_debug ("Sending Register stop for %s to %s on %s", - pim_str_sg_dump (sg), inet_ntoa(originator), ifp->name); - } - - memset (buffer, 0, 10000); - b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN; - - length = pim_encode_addr_group (b1, AFI_IP, 0, 0, sg->grp); - b1length += length; - b1 += length; - - p.family = AF_INET; - p.u.prefix4 = sg->src; - p.prefixlen = 32; - length = pim_encode_addr_ucast (b1, &p); - b1length += length; - - pim_msg_build_header (buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, PIM_MSG_TYPE_REG_STOP); - - pinfo = (struct pim_interface *)ifp->info; - if (!pinfo) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: No pinfo!\n", __PRETTY_FUNCTION__); - return; - } - if (pim_msg_send (pinfo->pim_sock_fd, src, originator, - buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, - ifp->name)) - { - if (PIM_DEBUG_PIM_TRACE) - { - zlog_debug ("%s: could not send PIM register stop message on interface %s", - __PRETTY_FUNCTION__, ifp->name); + struct pim_interface *pinfo; + unsigned char buffer[10000]; + unsigned int b1length = 0; + unsigned int length; + uint8_t *b1; + struct prefix p; + + if (PIM_DEBUG_PIM_REG) { + zlog_debug("Sending Register stop for %s to %s on %s", + pim_str_sg_dump(sg), inet_ntoa(originator), + ifp->name); + } + + memset(buffer, 0, 10000); + b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN; + + length = pim_encode_addr_group(b1, AFI_IP, 0, 0, sg->grp); + b1length += length; + b1 += length; + + p.family = AF_INET; + p.u.prefix4 = sg->src; + p.prefixlen = 32; + length = pim_encode_addr_ucast(b1, &p); + b1length += length; + + pim_msg_build_header(buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, + PIM_MSG_TYPE_REG_STOP); + + pinfo = (struct pim_interface *)ifp->info; + if (!pinfo) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: No pinfo!\n", __PRETTY_FUNCTION__); + return; } - } - ++pinfo->pim_ifstat_reg_stop_send; + if (pim_msg_send(pinfo->pim_sock_fd, src, originator, buffer, + b1length + PIM_MSG_REGISTER_STOP_LEN, ifp->name)) { + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug( + "%s: could not send PIM register stop message on interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + } + ++pinfo->pim_ifstat_reg_stop_send; } -int -pim_register_stop_recv (uint8_t *buf, int buf_size) +int pim_register_stop_recv(uint8_t *buf, int buf_size) { - struct pim_upstream *upstream = NULL; - struct prefix source; - struct prefix_sg sg; - int l; - - memset (&sg, 0, sizeof (struct prefix_sg)); - l = pim_parse_addr_group (&sg, buf, buf_size); - buf += l; - buf_size -= l; - pim_parse_addr_ucast (&source, buf, buf_size); - sg.src = source.u.prefix4; - - upstream = pim_upstream_find (&sg); - if (!upstream) - { - return 0; - } - - if (PIM_DEBUG_PIM_REG) - zlog_debug ("Received Register stop for %s", - upstream->sg_str); - - switch (upstream->reg_state) - { - case PIM_REG_NOINFO: - case PIM_REG_PRUNE: - return 0; - break; - case PIM_REG_JOIN: - upstream->reg_state = PIM_REG_PRUNE; - pim_channel_del_oif (upstream->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); - pim_upstream_start_register_stop_timer (upstream, 0); - break; - case PIM_REG_JOIN_PENDING: - upstream->reg_state = PIM_REG_PRUNE; - pim_upstream_start_register_stop_timer (upstream, 0); - return 0; - break; - } - - return 0; + struct pim_upstream *upstream = NULL; + struct prefix source; + struct prefix_sg sg; + int l; + + memset(&sg, 0, sizeof(struct prefix_sg)); + l = pim_parse_addr_group(&sg, buf, buf_size); + buf += l; + buf_size -= l; + pim_parse_addr_ucast(&source, buf, buf_size); + sg.src = source.u.prefix4; + + upstream = pim_upstream_find(&sg); + if (!upstream) { + return 0; + } + + if (PIM_DEBUG_PIM_REG) + zlog_debug("Received Register stop for %s", upstream->sg_str); + + switch (upstream->reg_state) { + case PIM_REG_NOINFO: + case PIM_REG_PRUNE: + return 0; + break; + case PIM_REG_JOIN: + upstream->reg_state = PIM_REG_PRUNE; + pim_channel_del_oif(upstream->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_PIM); + pim_upstream_start_register_stop_timer(upstream, 0); + break; + case PIM_REG_JOIN_PENDING: + upstream->reg_state = PIM_REG_PRUNE; + pim_upstream_start_register_stop_timer(upstream, 0); + return 0; + break; + } + + return 0; } -void -pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register, struct pim_upstream *up) +void pim_register_send(const uint8_t *buf, int buf_size, struct in_addr src, + struct pim_rpf *rpg, int null_register, + struct pim_upstream *up) { - unsigned char buffer[10000]; - unsigned char *b1; - struct pim_interface *pinfo; - struct interface *ifp; - - if (PIM_DEBUG_PIM_REG) - { - zlog_debug ("Sending %s %sRegister Packet to %s", - up->sg_str, null_register ? "NULL " : "", - inet_ntoa (rpg->rpf_addr.u.prefix4)); - } - - ifp = rpg->source_nexthop.interface; - if (!ifp) - { - if (PIM_DEBUG_PIM_REG) - zlog_debug ("%s: No interface to transmit register on", __PRETTY_FUNCTION__); - return; - } - pinfo = (struct pim_interface *)ifp->info; - if (!pinfo) { - if (PIM_DEBUG_PIM_REG) - zlog_debug("%s: Interface: %s not configured for pim to trasmit on!\n", __PRETTY_FUNCTION__, ifp->name); - return; - } - - if (PIM_DEBUG_PIM_REG) - { - char rp_str[INET_ADDRSTRLEN]; - strncpy (rp_str, inet_ntoa (rpg->rpf_addr.u.prefix4), INET_ADDRSTRLEN-1); - zlog_debug ("%s: Sending %s %sRegister Packet to %s on %s", - __PRETTY_FUNCTION__, up->sg_str, - null_register ? "NULL " : "", rp_str, ifp->name); - } - - memset(buffer, 0, 10000); - b1 = buffer + PIM_MSG_HEADER_LEN; - *b1 |= null_register << 6; - b1 = buffer + PIM_MSG_REGISTER_LEN; - - memcpy(b1, (const unsigned char *)buf, buf_size); - - pim_msg_build_header(buffer, buf_size + PIM_MSG_REGISTER_LEN, PIM_MSG_TYPE_REGISTER); - - ++pinfo->pim_ifstat_reg_send; - - if (pim_msg_send(pinfo->pim_sock_fd, - src, - rpg->rpf_addr.u.prefix4, - buffer, - buf_size + PIM_MSG_REGISTER_LEN, - ifp->name)) { - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: could not send PIM register message on interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return; - } + unsigned char buffer[10000]; + unsigned char *b1; + struct pim_interface *pinfo; + struct interface *ifp; + + if (PIM_DEBUG_PIM_REG) { + zlog_debug("Sending %s %sRegister Packet to %s", up->sg_str, + null_register ? "NULL " : "", + inet_ntoa(rpg->rpf_addr.u.prefix4)); + } + + ifp = rpg->source_nexthop.interface; + if (!ifp) { + if (PIM_DEBUG_PIM_REG) + zlog_debug("%s: No interface to transmit register on", + __PRETTY_FUNCTION__); + return; + } + pinfo = (struct pim_interface *)ifp->info; + if (!pinfo) { + if (PIM_DEBUG_PIM_REG) + zlog_debug( + "%s: Interface: %s not configured for pim to trasmit on!\n", + __PRETTY_FUNCTION__, ifp->name); + return; + } + + if (PIM_DEBUG_PIM_REG) { + char rp_str[INET_ADDRSTRLEN]; + strncpy(rp_str, inet_ntoa(rpg->rpf_addr.u.prefix4), + INET_ADDRSTRLEN - 1); + zlog_debug("%s: Sending %s %sRegister Packet to %s on %s", + __PRETTY_FUNCTION__, up->sg_str, + null_register ? "NULL " : "", rp_str, ifp->name); + } + + memset(buffer, 0, 10000); + b1 = buffer + PIM_MSG_HEADER_LEN; + *b1 |= null_register << 6; + b1 = buffer + PIM_MSG_REGISTER_LEN; + + memcpy(b1, (const unsigned char *)buf, buf_size); + + pim_msg_build_header(buffer, buf_size + PIM_MSG_REGISTER_LEN, + PIM_MSG_TYPE_REGISTER); + + ++pinfo->pim_ifstat_reg_send; + + if (pim_msg_send(pinfo->pim_sock_fd, src, rpg->rpf_addr.u.prefix4, + buffer, buf_size + PIM_MSG_REGISTER_LEN, ifp->name)) { + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug( + "%s: could not send PIM register message on interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return; + } } /* @@ -265,155 +259,160 @@ pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct * } * } */ -int -pim_register_recv (struct interface *ifp, - struct in_addr dest_addr, - struct in_addr src_addr, - uint8_t *tlv_buf, int tlv_buf_size) +int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, + struct in_addr src_addr, uint8_t *tlv_buf, + int tlv_buf_size) { - int sentRegisterStop = 0; - struct ip *ip_hdr; - struct prefix_sg sg; - uint32_t *bits; - int i_am_rp = 0; - struct pim_interface *pim_ifp = NULL; + int sentRegisterStop = 0; + struct ip *ip_hdr; + struct prefix_sg sg; + uint32_t *bits; + int i_am_rp = 0; + struct pim_interface *pim_ifp = NULL; #define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4 - ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN); - - if (!pim_rp_check_is_my_ip_address (ip_hdr->ip_dst, dest_addr)) { - if (PIM_DEBUG_PIM_REG) { - char dest[INET_ADDRSTRLEN]; - - pim_inet4_dump ("<dst?>", dest_addr, dest, sizeof(dest)); - zlog_debug ("%s: Received Register message for %s that I do not own", __func__, - dest); - } - return 0; - } - - pim_ifp = ifp->info; - zassert(pim_ifp); - ++pim_ifp->pim_ifstat_reg_recv; - - /* - * Please note this is not drawn to get the correct bit/data size - * - * The entirety of the REGISTER packet looks like this: - * ------------------------------------------------------------- - * | Ver | Type | Reserved | Checksum | - * |-----------------------------------------------------------| - * |B|N| Reserved 2 | - * |-----------------------------------------------------------| - * | Encap | IP HDR | - * | Mcast | | - * | Packet |--------------------------------------------------| - * | | Mcast Data | - * | | | - * ... - * - * tlv_buf when received from the caller points at the B bit - * We need to know the inner source and dest - */ - bits = (uint32_t *)tlv_buf; - - /* - * tlv_buf points to the start of the |B|N|... Reserved - * Line above. So we need to add 4 bytes to get to the - * start of the actual Encapsulated data. - */ - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = ip_hdr->ip_src; - sg.grp = ip_hdr->ip_dst; - - i_am_rp = I_am_RP (sg.grp); - - if (PIM_DEBUG_PIM_REG) - { - char src_str[INET_ADDRSTRLEN]; - - pim_inet4_dump ("<src?>", src_addr, src_str, sizeof (src_str)); - zlog_debug ("Received Register message(%s) from %s on %s, rp: %d", - pim_str_sg_dump (&sg), src_str, ifp->name, i_am_rp); - } - - if (i_am_rp && (dest_addr.s_addr == ((RP (sg.grp))->rpf_addr.u.prefix4.s_addr))) { - sentRegisterStop = 0; - - if (*bits & PIM_REGISTER_BORDER_BIT) { - struct in_addr pimbr = pim_br_get_pmbr (&sg); - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("%s: Received Register message with Border bit set", __func__); - - if (pimbr.s_addr == pim_br_unknown.s_addr) - pim_br_set_pmbr(&sg, src_addr); - else if (src_addr.s_addr != pimbr.s_addr) { - pim_register_stop_send (ifp, &sg, dest_addr, src_addr); - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet", - __func__, "Sender"); - /* Drop Packet Silently */ + ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN); + + if (!pim_rp_check_is_my_ip_address(ip_hdr->ip_dst, dest_addr)) { + if (PIM_DEBUG_PIM_REG) { + char dest[INET_ADDRSTRLEN]; + + pim_inet4_dump("<dst?>", dest_addr, dest, sizeof(dest)); + zlog_debug( + "%s: Received Register message for %s that I do not own", + __func__, dest); + } + return 0; + } + + pim_ifp = ifp->info; + zassert(pim_ifp); + ++pim_ifp->pim_ifstat_reg_recv; + + /* + * Please note this is not drawn to get the correct bit/data size + * + * The entirety of the REGISTER packet looks like this: + * ------------------------------------------------------------- + * | Ver | Type | Reserved | Checksum | + * |-----------------------------------------------------------| + * |B|N| Reserved 2 | + * |-----------------------------------------------------------| + * | Encap | IP HDR | + * | Mcast | | + * | Packet |--------------------------------------------------| + * | | Mcast Data | + * | | | + * ... + * + * tlv_buf when received from the caller points at the B bit + * We need to know the inner source and dest + */ + bits = (uint32_t *)tlv_buf; + + /* + * tlv_buf points to the start of the |B|N|... Reserved + * Line above. So we need to add 4 bytes to get to the + * start of the actual Encapsulated data. + */ + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = ip_hdr->ip_src; + sg.grp = ip_hdr->ip_dst; + + i_am_rp = I_am_RP(sg.grp); + + if (PIM_DEBUG_PIM_REG) { + char src_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + zlog_debug( + "Received Register message(%s) from %s on %s, rp: %d", + pim_str_sg_dump(&sg), src_str, ifp->name, i_am_rp); + } + + if (i_am_rp && (dest_addr.s_addr + == ((RP(sg.grp))->rpf_addr.u.prefix4.s_addr))) { + sentRegisterStop = 0; + + if (*bits & PIM_REGISTER_BORDER_BIT) { + struct in_addr pimbr = pim_br_get_pmbr(&sg); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: Received Register message with Border bit set", + __func__); + + if (pimbr.s_addr == pim_br_unknown.s_addr) + pim_br_set_pmbr(&sg, src_addr); + else if (src_addr.s_addr != pimbr.s_addr) { + pim_register_stop_send(ifp, &sg, dest_addr, + src_addr); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: Sending register-Stop to %s and dropping mr. packet", + __func__, "Sender"); + /* Drop Packet Silently */ + return 0; + } + } + + struct pim_upstream *upstream = pim_upstream_find(&sg); + /* + * If we don't have a place to send ignore the packet + */ + if (!upstream) { + upstream = pim_upstream_add( + &sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, + __PRETTY_FUNCTION__); + if (!upstream) { + zlog_warn("Failure to create upstream state"); + return 1; + } + + upstream->upstream_register = src_addr; + } + + if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) + || ((SwitchToSptDesired(&sg)) + && pim_upstream_inherited_olist(upstream) == 0)) { + // pim_scan_individual_oil (upstream->channel_oil); + pim_register_stop_send(ifp, &sg, dest_addr, src_addr); + sentRegisterStop = 1; + } else { + if (PIM_DEBUG_PIM_REG) + zlog_debug("(%s) sptbit: %d", upstream->sg_str, + upstream->sptbit); + } + if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) + || (SwitchToSptDesired(&sg))) { + if (sentRegisterStop) { + pim_upstream_keep_alive_timer_start( + upstream, qpim_rp_keep_alive_time); + } else { + pim_upstream_keep_alive_timer_start( + upstream, qpim_keep_alive_time); + } + } + + if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) + && !(*bits & PIM_REGISTER_NR_BIT)) { + // decapsulate and forward the iner packet to + // inherited_olist(S,G,rpt) + // This is taken care of by the kernel for us + } + pim_upstream_msdp_reg_timer_start(upstream); + } else { + if (PIM_DEBUG_PIM_REG) { + if (!i_am_rp) + zlog_debug( + "Received Register packet for %s, Rejecting packet because I am not the RP configured for group", + pim_str_sg_dump(&sg)); + else + zlog_debug( + "Received Register packet for %s, Rejecting packet because the dst ip address is not the actual RP", + pim_str_sg_dump(&sg)); + } + pim_register_stop_send(ifp, &sg, dest_addr, src_addr); + } + return 0; - } - } - - struct pim_upstream *upstream = pim_upstream_find (&sg); - /* - * If we don't have a place to send ignore the packet - */ - if (!upstream) - { - upstream = pim_upstream_add (&sg, ifp, - PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, - __PRETTY_FUNCTION__); - if (!upstream) - { - zlog_warn ("Failure to create upstream state"); - return 1; - } - - upstream->upstream_register = src_addr; - } - - if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || - ((SwitchToSptDesired(&sg)) && - pim_upstream_inherited_olist (upstream) == 0)) { - //pim_scan_individual_oil (upstream->channel_oil); - pim_register_stop_send (ifp, &sg, dest_addr, src_addr); - sentRegisterStop = 1; - } else { - if (PIM_DEBUG_PIM_REG) - zlog_debug ("(%s) sptbit: %d", upstream->sg_str, upstream->sptbit); - } - if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || - (SwitchToSptDesired(&sg))) { - if (sentRegisterStop) { - pim_upstream_keep_alive_timer_start (upstream, qpim_rp_keep_alive_time); - } else { - pim_upstream_keep_alive_timer_start (upstream, qpim_keep_alive_time); - } - } - - if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) && - !(*bits & PIM_REGISTER_NR_BIT)) - { - //decapsulate and forward the iner packet to - //inherited_olist(S,G,rpt) - // This is taken care of by the kernel for us - } - pim_upstream_msdp_reg_timer_start(upstream); - } else { - if (PIM_DEBUG_PIM_REG) - { - if (!i_am_rp) - zlog_debug ("Received Register packet for %s, Rejecting packet because I am not the RP configured for group", - pim_str_sg_dump (&sg)); - else - zlog_debug ("Received Register packet for %s, Rejecting packet because the dst ip address is not the actual RP", - pim_str_sg_dump (&sg)); - } - pim_register_stop_send (ifp, &sg, dest_addr, src_addr); - } - - return 0; } diff --git a/pimd/pim_register.h b/pimd/pim_register.h index adb703c61..ad3deb2b2 100644 --- a/pimd/pim_register.h +++ b/pimd/pim_register.h @@ -30,15 +30,17 @@ #define PIM_MSG_REGISTER_LEN (8) #define PIM_MSG_REGISTER_STOP_LEN (4) -int pim_register_stop_recv (uint8_t *buf, int buf_size); - -int pim_register_recv (struct interface *ifp, - struct in_addr dest_addr, - struct in_addr src_addr, - uint8_t *tlv_buf, int tlv_buf_size); - -void pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register, struct pim_upstream *up); -void pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, struct in_addr src, struct in_addr originator); -void pim_register_join (struct pim_upstream *up); +int pim_register_stop_recv(uint8_t *buf, int buf_size); + +int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, + struct in_addr src_addr, uint8_t *tlv_buf, + int tlv_buf_size); + +void pim_register_send(const uint8_t *buf, int buf_size, struct in_addr src, + struct pim_rpf *rpg, int null_register, + struct pim_upstream *up); +void pim_register_stop_send(struct interface *ifp, struct prefix_sg *sg, + struct in_addr src, struct in_addr originator); +void pim_register_join(struct pim_upstream *up); #endif diff --git a/pimd/pim_routemap.c b/pimd/pim_routemap.c index 20c716c3e..6d06229b9 100644 --- a/pimd/pim_routemap.c +++ b/pimd/pim_routemap.c @@ -27,55 +27,49 @@ #include "pimd.h" -static void -pim_route_map_mark_update (const char *rmap_name) +static void pim_route_map_mark_update(const char *rmap_name) { - // placeholder - return; + // placeholder + return; } -static void -pim_route_map_add (const char *rmap_name) +static void pim_route_map_add(const char *rmap_name) { - if (route_map_mark_updated(rmap_name, 0) == 0) - pim_route_map_mark_update(rmap_name); + if (route_map_mark_updated(rmap_name, 0) == 0) + pim_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); } -static void -pim_route_map_delete (const char *rmap_name) +static void pim_route_map_delete(const char *rmap_name) { - if (route_map_mark_updated(rmap_name, 1) == 0) - pim_route_map_mark_update(rmap_name); + if (route_map_mark_updated(rmap_name, 1) == 0) + pim_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); } -static void -pim_route_map_event (route_map_event_t event, const char *rmap_name) +static void pim_route_map_event(route_map_event_t event, const char *rmap_name) { - if (route_map_mark_updated(rmap_name, 0) == 0) - pim_route_map_mark_update(rmap_name); + if (route_map_mark_updated(rmap_name, 0) == 0) + pim_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); } -void -pim_route_map_init (void) +void pim_route_map_init(void) { - route_map_init (); + route_map_init(); - route_map_add_hook (pim_route_map_add); - route_map_delete_hook (pim_route_map_delete); - route_map_event_hook (pim_route_map_event); + route_map_add_hook(pim_route_map_add); + route_map_delete_hook(pim_route_map_delete); + route_map_event_hook(pim_route_map_event); } -void -pim_route_map_terminate (void) +void pim_route_map_terminate(void) { - route_map_add_hook (NULL); - route_map_delete_hook (NULL); - route_map_event_hook (NULL); - route_map_finish(); + route_map_add_hook(NULL); + route_map_delete_hook(NULL); + route_map_event_hook(NULL); + route_map_finish(); } diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 28300dbdf..2fe0143a8 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -48,158 +48,147 @@ static struct list *qpim_rp_list = NULL; static struct rp_info *tail = NULL; -static void -pim_rp_info_free (struct rp_info *rp_info) +static void pim_rp_info_free(struct rp_info *rp_info) { - XFREE (MTYPE_PIM_RP, rp_info); + XFREE(MTYPE_PIM_RP, rp_info); } -int -pim_rp_list_cmp (void *v1, void *v2) +int pim_rp_list_cmp(void *v1, void *v2) { - struct rp_info *rp1 = (struct rp_info *)v1; - struct rp_info *rp2 = (struct rp_info *)v2; - - /* - * Sort by RP IP address - */ - if (rp1->rp.rpf_addr.u.prefix4.s_addr < rp2->rp.rpf_addr.u.prefix4.s_addr) - return -1; - - if (rp1->rp.rpf_addr.u.prefix4.s_addr > rp2->rp.rpf_addr.u.prefix4.s_addr) - return 1; - - /* - * Sort by group IP address - */ - if (rp1->group.u.prefix4.s_addr < rp2->group.u.prefix4.s_addr) - return -1; - - if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr) - return 1; - - return 0; + struct rp_info *rp1 = (struct rp_info *)v1; + struct rp_info *rp2 = (struct rp_info *)v2; + + /* + * Sort by RP IP address + */ + if (rp1->rp.rpf_addr.u.prefix4.s_addr + < rp2->rp.rpf_addr.u.prefix4.s_addr) + return -1; + + if (rp1->rp.rpf_addr.u.prefix4.s_addr + > rp2->rp.rpf_addr.u.prefix4.s_addr) + return 1; + + /* + * Sort by group IP address + */ + if (rp1->group.u.prefix4.s_addr < rp2->group.u.prefix4.s_addr) + return -1; + + if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr) + return 1; + + return 0; } -void -pim_rp_init (void) +void pim_rp_init(void) { - struct rp_info *rp_info; + struct rp_info *rp_info; - qpim_rp_list = list_new (); - qpim_rp_list->del = (void (*)(void *))pim_rp_info_free; - qpim_rp_list->cmp = pim_rp_list_cmp; + qpim_rp_list = list_new(); + qpim_rp_list->del = (void (*)(void *))pim_rp_info_free; + qpim_rp_list->cmp = pim_rp_list_cmp; - rp_info = XCALLOC (MTYPE_PIM_RP, sizeof (*rp_info)); + rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); - if (!rp_info) - return; + if (!rp_info) + return; - str2prefix ("224.0.0.0/4", &rp_info->group); - rp_info->group.family = AF_INET; - rp_info->rp.rpf_addr.family = AF_INET; - rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; - rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; - tail = rp_info; + str2prefix("224.0.0.0/4", &rp_info->group); + rp_info->group.family = AF_INET; + rp_info->rp.rpf_addr.family = AF_INET; + rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; + rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; + tail = rp_info; - listnode_add (qpim_rp_list, rp_info); + listnode_add(qpim_rp_list, rp_info); } -void -pim_rp_free (void) +void pim_rp_free(void) { - if (qpim_rp_list) - list_delete (qpim_rp_list); - qpim_rp_list = NULL; + if (qpim_rp_list) + list_delete(qpim_rp_list); + qpim_rp_list = NULL; } /* * Given an RP's prefix-list, return the RP's rp_info for that prefix-list */ -static struct rp_info * -pim_rp_find_prefix_list (struct in_addr rp, const char *plist) +static struct rp_info *pim_rp_find_prefix_list(struct in_addr rp, + const char *plist) { - struct listnode *node; - struct rp_info *rp_info; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr && - rp_info->plist && strcmp(rp_info->plist, plist) == 0) - { - return rp_info; - } - } - - return NULL; + struct listnode *node; + struct rp_info *rp_info; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr + && rp_info->plist && strcmp(rp_info->plist, plist) == 0) { + return rp_info; + } + } + + return NULL; } /* * Return true if plist is used by any rp_info */ -static int -pim_rp_prefix_list_used (const char *plist) +static int pim_rp_prefix_list_used(const char *plist) { - struct listnode *node; - struct rp_info *rp_info; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp_info->plist && strcmp(rp_info->plist, plist) == 0) - { - return 1; - } - } - - return 0; + struct listnode *node; + struct rp_info *rp_info; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (rp_info->plist && strcmp(rp_info->plist, plist) == 0) { + return 1; + } + } + + return 0; } /* - * Given an RP's address, return the RP's rp_info that is an exact match for 'group' + * Given an RP's address, return the RP's rp_info that is an exact match for + * 'group' */ -static struct rp_info * -pim_rp_find_exact (struct in_addr rp, struct prefix *group) +static struct rp_info *pim_rp_find_exact(struct in_addr rp, + struct prefix *group) { - struct listnode *node; - struct rp_info *rp_info; + struct listnode *node; + struct rp_info *rp_info; - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr && - prefix_same (&rp_info->group, group)) - return rp_info; - } + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr + && prefix_same(&rp_info->group, group)) + return rp_info; + } - return NULL; + return NULL; } /* * Given a group, return the rp_info for that group */ -static struct rp_info * -pim_rp_find_match_group (struct prefix *group) +static struct rp_info *pim_rp_find_match_group(struct prefix *group) { - struct listnode *node; - struct rp_info *rp_info; - struct prefix_list *plist; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp_info->plist) - { - plist = prefix_list_lookup (AFI_IP, rp_info->plist); - - if (plist && prefix_list_apply (plist, group) == PREFIX_PERMIT) - return rp_info; - } - else - { - if (prefix_match (&rp_info->group, group)) - return rp_info; - } - } - - return NULL; + struct listnode *node; + struct rp_info *rp_info; + struct prefix_list *plist; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (rp_info->plist) { + plist = prefix_list_lookup(AFI_IP, rp_info->plist); + + if (plist + && prefix_list_apply(plist, group) == PREFIX_PERMIT) + return rp_info; + } else { + if (prefix_match(&rp_info->group, group)) + return rp_info; + } + } + + return NULL; } /* @@ -209,480 +198,475 @@ pim_rp_find_match_group (struct prefix *group) * * This is a placeholder function for now. */ -static void -pim_rp_refresh_group_to_rp_mapping() +static void pim_rp_refresh_group_to_rp_mapping() { - pim_msdp_i_am_rp_changed(); + pim_msdp_i_am_rp_changed(); } -void -pim_rp_prefix_list_update (struct prefix_list *plist) +void pim_rp_prefix_list_update(struct prefix_list *plist) { - struct listnode *node; - struct rp_info *rp_info; - int refresh_needed = 0; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp_info->plist && strcmp(rp_info->plist, prefix_list_name (plist)) == 0) - { - refresh_needed = 1; - break; - } - } - - if (refresh_needed) - pim_rp_refresh_group_to_rp_mapping(); + struct listnode *node; + struct rp_info *rp_info; + int refresh_needed = 0; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (rp_info->plist + && strcmp(rp_info->plist, prefix_list_name(plist)) == 0) { + refresh_needed = 1; + break; + } + } + + if (refresh_needed) + pim_rp_refresh_group_to_rp_mapping(); } -static int -pim_rp_check_interface_addrs(struct rp_info *rp_info, - struct pim_interface *pim_ifp) +static int pim_rp_check_interface_addrs(struct rp_info *rp_info, + struct pim_interface *pim_ifp) { - struct listnode *node; - struct pim_secondary_addr *sec_addr; + struct listnode *node; + struct pim_secondary_addr *sec_addr; - if (pim_ifp->primary_address.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) - return 1; + if (pim_ifp->primary_address.s_addr + == rp_info->rp.rpf_addr.u.prefix4.s_addr) + return 1; - if (!pim_ifp->sec_addr_list) { - return 0; - } + if (!pim_ifp->sec_addr_list) { + return 0; + } - for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { - if (prefix_same(&sec_addr->addr, &rp_info->rp.rpf_addr)) { - return 1; - } - } + for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { + if (prefix_same(&sec_addr->addr, &rp_info->rp.rpf_addr)) { + return 1; + } + } - return 0; + return 0; } -static void -pim_rp_check_interfaces (struct rp_info *rp_info) +static void pim_rp_check_interfaces(struct rp_info *rp_info) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - rp_info->i_am_rp = 0; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - struct pim_interface *pim_ifp = ifp->info; + rp_info->i_am_rp = 0; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - continue; + if (!pim_ifp) + continue; - if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) { - rp_info->i_am_rp = 1; - } - } + if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) { + rp_info->i_am_rp = 1; + } + } } -int -pim_rp_new (const char *rp, const char *group_range, const char *plist) +int pim_rp_new(const char *rp, const char *group_range, const char *plist) { - int result = 0; - struct rp_info *rp_info; - struct rp_info *rp_all; - struct prefix group_all; - struct listnode *node, *nnode; - struct rp_info *tmp_rp_info; - char buffer[BUFSIZ]; - struct prefix nht_p; - struct pim_nexthop_cache pnc; - - rp_info = XCALLOC (MTYPE_PIM_RP, sizeof (*rp_info)); - if (!rp_info) - return PIM_MALLOC_FAIL; - - if (group_range == NULL) - result = str2prefix ("224.0.0.0/4", &rp_info->group); - else - result = str2prefix (group_range, &rp_info->group); - - if (!result) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_GROUP_BAD_ADDRESS; - } - - rp_info->rp.rpf_addr.family = AF_INET; - rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; - result = inet_pton (rp_info->rp.rpf_addr.family, rp, &rp_info->rp.rpf_addr.u.prefix4); - - if (result <= 0) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_RP_BAD_ADDRESS; - } - - if (plist) - { - /* - * Return if the prefix-list is already configured for this RP - */ - if (pim_rp_find_prefix_list (rp_info->rp.rpf_addr.u.prefix4, plist)) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_SUCCESS; - } - - /* - * Barf if the prefix-list is already configured for an RP - */ - if (pim_rp_prefix_list_used (plist)) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_RP_PFXLIST_IN_USE; - } - - /* - * Free any existing rp_info entries for this RP - */ - for (ALL_LIST_ELEMENTS (qpim_rp_list, node, nnode, tmp_rp_info)) - { - if (rp_info->rp.rpf_addr.u.prefix4.s_addr == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) - { - if (tmp_rp_info->plist) - pim_rp_del (rp, NULL, tmp_rp_info->plist); - else - pim_rp_del (rp, prefix2str(&tmp_rp_info->group, buffer, BUFSIZ), NULL); - } - } - - rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist); - } - else - { - str2prefix ("224.0.0.0/4", &group_all); - rp_all = pim_rp_find_match_group(&group_all); - - /* - * Barf if group is a non-multicast subnet - */ - if (! prefix_match (&rp_all->group, &rp_info->group)) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_GROUP_BAD_ADDRESS; - } - - /* - * Remove any prefix-list rp_info entries for this RP - */ - for (ALL_LIST_ELEMENTS (qpim_rp_list, node, nnode, tmp_rp_info)) - { - if (tmp_rp_info->plist && - rp_info->rp.rpf_addr.u.prefix4.s_addr == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) - { - pim_rp_del (rp, NULL, tmp_rp_info->plist); - } - } - - /* - * Take over the 224.0.0.0/4 group if the rp is INADDR_NONE - */ - if (prefix_same (&rp_all->group, &rp_info->group) && - pim_rpf_addr_is_inaddr_none (&rp_all->rp)) - { - rp_all->rp.rpf_addr = rp_info->rp.rpf_addr; - XFREE (MTYPE_PIM_RP, rp_info); - - /* Register addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = rp_all->rp.rpf_addr.u.prefix4; //RP address - if (PIM_DEBUG_PIM_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - char buf1[PREFIX2STR_BUFFER]; - prefix2str (&nht_p, buf, sizeof (buf)); - prefix2str (&rp_all->group, buf1, sizeof (buf1)); - zlog_debug ("%s: NHT Register rp_all addr %s grp %s ", - __PRETTY_FUNCTION__, buf, buf1); - } - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_all, &pnc)) == 1) - { - //Compute PIM RPF using Cached nexthop - if ((pim_ecmp_nexthop_search (&pnc, &rp_all->rp.source_nexthop, - &nht_p, &rp_all->group, 1)) != 0) - return PIM_RP_NO_PATH; - } - else - { - if (pim_nexthop_lookup (&rp_all->rp.source_nexthop, rp_all->rp.rpf_addr.u.prefix4, 1) != 0) - return PIM_RP_NO_PATH; - } - pim_rp_check_interfaces (rp_all); - pim_rp_refresh_group_to_rp_mapping (); - return PIM_SUCCESS; - } - - /* - * Return if the group is already configured for this RP - */ - if (pim_rp_find_exact (rp_info->rp.rpf_addr.u.prefix4, &rp_info->group)) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_SUCCESS; - } - - /* - * Barf if this group is already covered by some other RP - */ - tmp_rp_info = pim_rp_find_match_group (&rp_info->group); - - if (tmp_rp_info) - { - if (tmp_rp_info->plist) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_GROUP_PFXLIST_OVERLAP; - } - else - { - /* - * If the only RP that covers this group is an RP configured for - * 224.0.0.0/4 that is fine, ignore that one. For all others - * though we must return PIM_GROUP_OVERLAP - */ - if (! prefix_same (&group_all, &tmp_rp_info->group)) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_GROUP_OVERLAP; - } - } - } - } - - listnode_add_sort (qpim_rp_list, rp_info); - - /* Register addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; - if (PIM_DEBUG_PIM_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - char buf1[PREFIX2STR_BUFFER]; - prefix2str (&nht_p, buf, sizeof (buf)); - prefix2str (&rp_info->group, buf1, sizeof (buf1)); - zlog_debug ("%s: NHT Register RP addr %s grp %s with Zebra ", - __PRETTY_FUNCTION__, buf, buf1); - } - - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) - { - //Compute PIM RPF using Cached nexthop - if (pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop, - &nht_p, &rp_info->group, 1) != 0) - return PIM_RP_NO_PATH; - } - else - { - if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0) - return PIM_RP_NO_PATH; - } - - pim_rp_check_interfaces (rp_info); - pim_rp_refresh_group_to_rp_mapping (); - return PIM_SUCCESS; + int result = 0; + struct rp_info *rp_info; + struct rp_info *rp_all; + struct prefix group_all; + struct listnode *node, *nnode; + struct rp_info *tmp_rp_info; + char buffer[BUFSIZ]; + struct prefix nht_p; + struct pim_nexthop_cache pnc; + + rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); + if (!rp_info) + return PIM_MALLOC_FAIL; + + if (group_range == NULL) + result = str2prefix("224.0.0.0/4", &rp_info->group); + else + result = str2prefix(group_range, &rp_info->group); + + if (!result) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_GROUP_BAD_ADDRESS; + } + + rp_info->rp.rpf_addr.family = AF_INET; + rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; + result = inet_pton(rp_info->rp.rpf_addr.family, rp, + &rp_info->rp.rpf_addr.u.prefix4); + + if (result <= 0) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_RP_BAD_ADDRESS; + } + + if (plist) { + /* + * Return if the prefix-list is already configured for this RP + */ + if (pim_rp_find_prefix_list(rp_info->rp.rpf_addr.u.prefix4, + plist)) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_SUCCESS; + } + + /* + * Barf if the prefix-list is already configured for an RP + */ + if (pim_rp_prefix_list_used(plist)) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_RP_PFXLIST_IN_USE; + } + + /* + * Free any existing rp_info entries for this RP + */ + for (ALL_LIST_ELEMENTS(qpim_rp_list, node, nnode, + tmp_rp_info)) { + if (rp_info->rp.rpf_addr.u.prefix4.s_addr + == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) { + if (tmp_rp_info->plist) + pim_rp_del(rp, NULL, + tmp_rp_info->plist); + else + pim_rp_del( + rp, + prefix2str(&tmp_rp_info->group, + buffer, BUFSIZ), + NULL); + } + } + + rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist); + } else { + str2prefix("224.0.0.0/4", &group_all); + rp_all = pim_rp_find_match_group(&group_all); + + /* + * Barf if group is a non-multicast subnet + */ + if (!prefix_match(&rp_all->group, &rp_info->group)) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_GROUP_BAD_ADDRESS; + } + + /* + * Remove any prefix-list rp_info entries for this RP + */ + for (ALL_LIST_ELEMENTS(qpim_rp_list, node, nnode, + tmp_rp_info)) { + if (tmp_rp_info->plist + && rp_info->rp.rpf_addr.u.prefix4.s_addr + == tmp_rp_info->rp.rpf_addr.u.prefix4 + .s_addr) { + pim_rp_del(rp, NULL, tmp_rp_info->plist); + } + } + + /* + * Take over the 224.0.0.0/4 group if the rp is INADDR_NONE + */ + if (prefix_same(&rp_all->group, &rp_info->group) + && pim_rpf_addr_is_inaddr_none(&rp_all->rp)) { + rp_all->rp.rpf_addr = rp_info->rp.rpf_addr; + XFREE(MTYPE_PIM_RP, rp_info); + + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = + rp_all->rp.rpf_addr.u.prefix4; // RP address + if (PIM_DEBUG_PIM_TRACE) { + char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; + prefix2str(&nht_p, buf, sizeof(buf)); + prefix2str(&rp_all->group, buf1, sizeof(buf1)); + zlog_debug( + "%s: NHT Register rp_all addr %s grp %s ", + __PRETTY_FUNCTION__, buf, buf1); + } + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_all, + &pnc)) + == 1) { + // Compute PIM RPF using Cached nexthop + if ((pim_ecmp_nexthop_search( + &pnc, &rp_all->rp.source_nexthop, + &nht_p, &rp_all->group, 1)) + != 0) + return PIM_RP_NO_PATH; + } else { + if (pim_nexthop_lookup( + &rp_all->rp.source_nexthop, + rp_all->rp.rpf_addr.u.prefix4, 1) + != 0) + return PIM_RP_NO_PATH; + } + pim_rp_check_interfaces(rp_all); + pim_rp_refresh_group_to_rp_mapping(); + return PIM_SUCCESS; + } + + /* + * Return if the group is already configured for this RP + */ + if (pim_rp_find_exact(rp_info->rp.rpf_addr.u.prefix4, + &rp_info->group)) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_SUCCESS; + } + + /* + * Barf if this group is already covered by some other RP + */ + tmp_rp_info = pim_rp_find_match_group(&rp_info->group); + + if (tmp_rp_info) { + if (tmp_rp_info->plist) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_GROUP_PFXLIST_OVERLAP; + } else { + /* + * If the only RP that covers this group is an + * RP configured for + * 224.0.0.0/4 that is fine, ignore that one. + * For all others + * though we must return PIM_GROUP_OVERLAP + */ + if (!prefix_same(&group_all, + &tmp_rp_info->group)) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_GROUP_OVERLAP; + } + } + } + } + + listnode_add_sort(qpim_rp_list, rp_info); + + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + if (PIM_DEBUG_PIM_TRACE) { + char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; + prefix2str(&nht_p, buf, sizeof(buf)); + prefix2str(&rp_info->group, buf1, sizeof(buf1)); + zlog_debug("%s: NHT Register RP addr %s grp %s with Zebra ", + __PRETTY_FUNCTION__, buf, buf1); + } + + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc)) == 1) { + // Compute PIM RPF using Cached nexthop + if (pim_ecmp_nexthop_search(&pnc, &rp_info->rp.source_nexthop, + &nht_p, &rp_info->group, 1) + != 0) + return PIM_RP_NO_PATH; + } else { + if (pim_nexthop_lookup(&rp_info->rp.source_nexthop, + rp_info->rp.rpf_addr.u.prefix4, 1) + != 0) + return PIM_RP_NO_PATH; + } + + pim_rp_check_interfaces(rp_info); + pim_rp_refresh_group_to_rp_mapping(); + return PIM_SUCCESS; } -int -pim_rp_del (const char *rp, const char *group_range, const char *plist) +int pim_rp_del(const char *rp, const char *group_range, const char *plist) { - struct prefix group; - struct in_addr rp_addr; - struct prefix g_all; - struct rp_info *rp_info; - struct rp_info *rp_all; - int result; - struct prefix nht_p; - - if (group_range == NULL) - result = str2prefix ("224.0.0.0/4", &group); - else - result = str2prefix (group_range, &group); - - if (!result) - return PIM_GROUP_BAD_ADDRESS; - - result = inet_pton (AF_INET, rp, &rp_addr); - if (result <= 0) - return PIM_RP_BAD_ADDRESS; - - if (plist) - rp_info = pim_rp_find_prefix_list (rp_addr, plist); - else - rp_info = pim_rp_find_exact (rp_addr, &group); - - if (!rp_info) - return PIM_RP_NOT_FOUND; - - if (rp_info->plist) - { - XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist); - rp_info->plist = NULL; - } - - /* Deregister addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; - if (PIM_DEBUG_PIM_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&nht_p, buf, sizeof (buf)); - zlog_debug ("%s: Deregister RP addr %s with Zebra ", __PRETTY_FUNCTION__, - buf); - } - pim_delete_tracked_nexthop (&nht_p, NULL, rp_info); - - str2prefix ("224.0.0.0/4", &g_all); - rp_all = pim_rp_find_match_group (&g_all); - - if (rp_all == rp_info) - { - rp_all->rp.rpf_addr.family = AF_INET; - rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; - rp_all->i_am_rp = 0; - return PIM_SUCCESS; - } - - listnode_delete (qpim_rp_list, rp_info); - pim_rp_refresh_group_to_rp_mapping (); - return PIM_SUCCESS; + struct prefix group; + struct in_addr rp_addr; + struct prefix g_all; + struct rp_info *rp_info; + struct rp_info *rp_all; + int result; + struct prefix nht_p; + + if (group_range == NULL) + result = str2prefix("224.0.0.0/4", &group); + else + result = str2prefix(group_range, &group); + + if (!result) + return PIM_GROUP_BAD_ADDRESS; + + result = inet_pton(AF_INET, rp, &rp_addr); + if (result <= 0) + return PIM_RP_BAD_ADDRESS; + + if (plist) + rp_info = pim_rp_find_prefix_list(rp_addr, plist); + else + rp_info = pim_rp_find_exact(rp_addr, &group); + + if (!rp_info) + return PIM_RP_NOT_FOUND; + + if (rp_info->plist) { + XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist); + rp_info->plist = NULL; + } + + /* Deregister addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + if (PIM_DEBUG_PIM_TRACE) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&nht_p, buf, sizeof(buf)); + zlog_debug("%s: Deregister RP addr %s with Zebra ", + __PRETTY_FUNCTION__, buf); + } + pim_delete_tracked_nexthop(&nht_p, NULL, rp_info); + + str2prefix("224.0.0.0/4", &g_all); + rp_all = pim_rp_find_match_group(&g_all); + + if (rp_all == rp_info) { + rp_all->rp.rpf_addr.family = AF_INET; + rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; + rp_all->i_am_rp = 0; + return PIM_SUCCESS; + } + + listnode_delete(qpim_rp_list, rp_info); + pim_rp_refresh_group_to_rp_mapping(); + return PIM_SUCCESS; } -int -pim_rp_setup (void) +int pim_rp_setup(void) { - struct listnode *node; - struct rp_info *rp_info; - int ret = 0; - struct prefix nht_p; - struct pim_nexthop_cache pnc; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) - continue; - - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) - { - //Compute PIM RPF using Cached nexthop - if ((pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop, - &nht_p, &rp_info->group, 1)) != 0) - ret++; - } - else - { - if (PIM_DEBUG_ZEBRA) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&nht_p, buf, sizeof (buf)); - zlog_debug ("%s: NHT Local Nexthop not found for RP %s ", - __PRETTY_FUNCTION__, buf); - } - if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("Unable to lookup nexthop for rp specified"); - ret++; - } - } - } - - if (ret) - return 0; - - return 1; + struct listnode *node; + struct rp_info *rp_info; + int ret = 0; + struct prefix nht_p; + struct pim_nexthop_cache pnc; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) + continue; + + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc)) + == 1) { + // Compute PIM RPF using Cached nexthop + if ((pim_ecmp_nexthop_search( + &pnc, &rp_info->rp.source_nexthop, &nht_p, + &rp_info->group, 1)) + != 0) + ret++; + } else { + if (PIM_DEBUG_ZEBRA) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&nht_p, buf, sizeof(buf)); + zlog_debug( + "%s: NHT Local Nexthop not found for RP %s ", + __PRETTY_FUNCTION__, buf); + } + if (pim_nexthop_lookup(&rp_info->rp.source_nexthop, + rp_info->rp.rpf_addr.u.prefix4, + 1) + != 0) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "Unable to lookup nexthop for rp specified"); + ret++; + } + } + } + + if (ret) + return 0; + + return 1; } /* * Checks to see if we should elect ourself the actual RP when new if * addresses are added against an interface. */ -void -pim_rp_check_on_if_add(struct pim_interface *pim_ifp) +void pim_rp_check_on_if_add(struct pim_interface *pim_ifp) { - struct listnode *node; - struct rp_info *rp_info; - bool i_am_rp_changed = false; - - if (qpim_rp_list == NULL) - return; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { - if (pim_rpf_addr_is_inaddr_none (&rp_info->rp)) - continue; - - /* if i_am_rp is already set nothing to be done (adding new addresses - * is not going to make a difference). */ - if (rp_info->i_am_rp) { - continue; - } - - if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) { - i_am_rp_changed = true; - rp_info->i_am_rp = 1; - if (PIM_DEBUG_ZEBRA) { - char rp[PREFIX_STRLEN]; - pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr, rp, sizeof(rp)); - zlog_debug("%s: %s: i am rp", __func__, rp); - } - } - } - - if (i_am_rp_changed) { - pim_msdp_i_am_rp_changed(); - } + struct listnode *node; + struct rp_info *rp_info; + bool i_am_rp_changed = false; + + if (qpim_rp_list == NULL) + return; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (pim_rpf_addr_is_inaddr_none(&rp_info->rp)) + continue; + + /* if i_am_rp is already set nothing to be done (adding new + * addresses + * is not going to make a difference). */ + if (rp_info->i_am_rp) { + continue; + } + + if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) { + i_am_rp_changed = true; + rp_info->i_am_rp = 1; + if (PIM_DEBUG_ZEBRA) { + char rp[PREFIX_STRLEN]; + pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr, + rp, sizeof(rp)); + zlog_debug("%s: %s: i am rp", __func__, rp); + } + } + } + + if (i_am_rp_changed) { + pim_msdp_i_am_rp_changed(); + } } /* up-optimized re-evaluation of "i_am_rp". this is used when ifaddresses * are removed. Removing numbers is an uncommon event in an active network * so I have made no attempt to optimize it. */ -void -pim_i_am_rp_re_evaluate(void) +void pim_i_am_rp_re_evaluate(void) { - struct listnode *node; - struct rp_info *rp_info; - bool i_am_rp_changed = false; - int old_i_am_rp; - - if (qpim_rp_list == NULL) - return; - - for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { - if (pim_rpf_addr_is_inaddr_none(&rp_info->rp)) - continue; - - old_i_am_rp = rp_info->i_am_rp; - pim_rp_check_interfaces(rp_info); - - if (old_i_am_rp != rp_info->i_am_rp) { - i_am_rp_changed = true; - if (PIM_DEBUG_ZEBRA) { - char rp[PREFIX_STRLEN]; - pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr, rp, sizeof(rp)); - if (rp_info->i_am_rp) { - zlog_debug("%s: %s: i am rp", __func__, rp); - } else { - zlog_debug("%s: %s: i am no longer rp", __func__, rp); - } - } - } - } - - if (i_am_rp_changed) { - pim_msdp_i_am_rp_changed(); - } + struct listnode *node; + struct rp_info *rp_info; + bool i_am_rp_changed = false; + int old_i_am_rp; + + if (qpim_rp_list == NULL) + return; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (pim_rpf_addr_is_inaddr_none(&rp_info->rp)) + continue; + + old_i_am_rp = rp_info->i_am_rp; + pim_rp_check_interfaces(rp_info); + + if (old_i_am_rp != rp_info->i_am_rp) { + i_am_rp_changed = true; + if (PIM_DEBUG_ZEBRA) { + char rp[PREFIX_STRLEN]; + pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr, + rp, sizeof(rp)); + if (rp_info->i_am_rp) { + zlog_debug("%s: %s: i am rp", __func__, + rp); + } else { + zlog_debug("%s: %s: i am no longer rp", + __func__, rp); + } + } + } + } + + if (i_am_rp_changed) { + pim_msdp_i_am_rp_changed(); + } } /* @@ -691,23 +675,22 @@ pim_i_am_rp_re_evaluate(void) * * Since we only have static RP, all groups are part of this RP */ -int -pim_rp_i_am_rp (struct in_addr group) +int pim_rp_i_am_rp(struct in_addr group) { - struct prefix g; - struct rp_info *rp_info; + struct prefix g; + struct rp_info *rp_info; - memset (&g, 0, sizeof (g)); - g.family = AF_INET; - g.prefixlen = 32; - g.u.prefix4 = group; + memset(&g, 0, sizeof(g)); + g.family = AF_INET; + g.prefixlen = 32; + g.u.prefix4 = group; - rp_info = pim_rp_find_match_group (&g); + rp_info = pim_rp_find_match_group(&g); - if (rp_info) - return rp_info->i_am_rp; + if (rp_info) + return rp_info->i_am_rp; - return 0; + return 0; } /* @@ -715,62 +698,60 @@ pim_rp_i_am_rp (struct in_addr group) * * Return the RP that the Group belongs too. */ -struct pim_rpf * -pim_rp_g (struct in_addr group) +struct pim_rpf *pim_rp_g(struct in_addr group) { - struct prefix g; - struct rp_info *rp_info; - - memset (&g, 0, sizeof (g)); - g.family = AF_INET; - g.prefixlen = 32; - g.u.prefix4 = group; - - rp_info = pim_rp_find_match_group (&g); - - if (rp_info) - { - struct prefix nht_p; - struct pim_nexthop_cache pnc; - /* Register addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; - if (PIM_DEBUG_PIM_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - char buf1[PREFIX2STR_BUFFER]; - prefix2str (&nht_p, buf, sizeof (buf)); - prefix2str (&rp_info->group, buf1, sizeof (buf1)); - zlog_debug ("%s: NHT Register RP addr %s grp %s with Zebra", - __PRETTY_FUNCTION__, buf, buf1); - } - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) - { - //Compute PIM RPF using Cached nexthop - pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop, - &nht_p, &rp_info->group, 1); - } - else - { - if (PIM_DEBUG_ZEBRA) - { - char buf[PREFIX2STR_BUFFER]; - char buf1[PREFIX2STR_BUFFER]; - prefix2str (&nht_p, buf, sizeof (buf)); - prefix2str (&g, buf1, sizeof (buf1)); - zlog_debug ("%s: Nexthop cache not found for RP %s grp %s register with Zebra", - __PRETTY_FUNCTION__, buf, buf1); - } - pim_rpf_set_refresh_time (); - pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1); - } - return (&rp_info->rp); - } - - // About to Go Down - return NULL; + struct prefix g; + struct rp_info *rp_info; + + memset(&g, 0, sizeof(g)); + g.family = AF_INET; + g.prefixlen = 32; + g.u.prefix4 = group; + + rp_info = pim_rp_find_match_group(&g); + + if (rp_info) { + struct prefix nht_p; + struct pim_nexthop_cache pnc; + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + if (PIM_DEBUG_PIM_TRACE) { + char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; + prefix2str(&nht_p, buf, sizeof(buf)); + prefix2str(&rp_info->group, buf1, sizeof(buf1)); + zlog_debug( + "%s: NHT Register RP addr %s grp %s with Zebra", + __PRETTY_FUNCTION__, buf, buf1); + } + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc)) + == 1) { + // Compute PIM RPF using Cached nexthop + pim_ecmp_nexthop_search(&pnc, + &rp_info->rp.source_nexthop, + &nht_p, &rp_info->group, 1); + } else { + if (PIM_DEBUG_ZEBRA) { + char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; + prefix2str(&nht_p, buf, sizeof(buf)); + prefix2str(&g, buf1, sizeof(buf1)); + zlog_debug( + "%s: Nexthop cache not found for RP %s grp %s register with Zebra", + __PRETTY_FUNCTION__, buf, buf1); + } + pim_rpf_set_refresh_time(); + pim_nexthop_lookup(&rp_info->rp.source_nexthop, + rp_info->rp.rpf_addr.u.prefix4, 1); + } + return (&rp_info->rp); + } + + // About to Go Down + return NULL; } /* @@ -781,222 +762,253 @@ pim_rp_g (struct in_addr group) * then return failure. * */ -int -pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source, struct in_addr group) +int pim_rp_set_upstream_addr(struct in_addr *up, struct in_addr source, + struct in_addr group) { - struct rp_info *rp_info; - struct prefix g; + struct rp_info *rp_info; + struct prefix g; - memset (&g, 0, sizeof (g)); - g.family = AF_INET; - g.prefixlen = 32; - g.u.prefix4 = group; + memset(&g, 0, sizeof(g)); + g.family = AF_INET; + g.prefixlen = 32; + g.u.prefix4 = group; - rp_info = pim_rp_find_match_group (&g); + rp_info = pim_rp_find_match_group(&g); - if ((pim_rpf_addr_is_inaddr_none (&rp_info->rp)) && (source.s_addr == INADDR_ANY)) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); - return 0; - } + if ((pim_rpf_addr_is_inaddr_none(&rp_info->rp)) + && (source.s_addr == INADDR_ANY)) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: Received a (*,G) with no RP configured", + __PRETTY_FUNCTION__); + return 0; + } - *up = (source.s_addr == INADDR_ANY) ? rp_info->rp.rpf_addr.u.prefix4 : source; + *up = (source.s_addr == INADDR_ANY) ? rp_info->rp.rpf_addr.u.prefix4 + : source; - return 1; + return 1; } -int -pim_rp_config_write (struct vty *vty) +int pim_rp_config_write(struct vty *vty) { - struct listnode *node; - struct rp_info *rp_info; - char rp_buffer[32]; - char group_buffer[32]; - int count = 0; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (pim_rpf_addr_is_inaddr_none (&rp_info->rp)) - continue; - - if (rp_info->plist) - vty_out (vty, "ip pim rp %s prefix-list %s\n", - inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp_buffer, 32), - rp_info->plist); - else - vty_out (vty, "ip pim rp %s %s\n", - inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp_buffer, 32), - prefix2str(&rp_info->group, group_buffer, 32)); - count++; - } - - return count; + struct listnode *node; + struct rp_info *rp_info; + char rp_buffer[32]; + char group_buffer[32]; + int count = 0; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (pim_rpf_addr_is_inaddr_none(&rp_info->rp)) + continue; + + if (rp_info->plist) + vty_out(vty, "ip pim rp %s prefix-list %s\n", + inet_ntop(AF_INET, + &rp_info->rp.rpf_addr.u.prefix4, + rp_buffer, 32), + rp_info->plist); + else + vty_out(vty, "ip pim rp %s %s\n", + inet_ntop(AF_INET, + &rp_info->rp.rpf_addr.u.prefix4, + rp_buffer, 32), + prefix2str(&rp_info->group, group_buffer, 32)); + count++; + } + + return count; } -int -pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr) +int pim_rp_check_is_my_ip_address(struct in_addr group, + struct in_addr dest_addr) { - struct rp_info *rp_info; - struct prefix g; - - memset (&g, 0, sizeof (g)); - g.family = AF_INET; - g.prefixlen = 32; - g.u.prefix4 = group; - - rp_info = pim_rp_find_match_group (&g); - /* - * See if we can short-cut some? - * This might not make sense if we ever leave a static RP - * type of configuration. - * Note - Premature optimization might bite our patooeys' here. - */ - if (I_am_RP(group)) - { - if (dest_addr.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) - return 1; - } - - if (if_lookup_exact_address (&dest_addr, AF_INET, VRF_DEFAULT)) - return 1; - - return 0; + struct rp_info *rp_info; + struct prefix g; + + memset(&g, 0, sizeof(g)); + g.family = AF_INET; + g.prefixlen = 32; + g.u.prefix4 = group; + + rp_info = pim_rp_find_match_group(&g); + /* + * See if we can short-cut some? + * This might not make sense if we ever leave a static RP + * type of configuration. + * Note - Premature optimization might bite our patooeys' here. + */ + if (I_am_RP(group)) { + if (dest_addr.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) + return 1; + } + + if (if_lookup_exact_address(&dest_addr, AF_INET, VRF_DEFAULT)) + return 1; + + return 0; } -void -pim_rp_show_information (struct vty *vty, u_char uj) +void pim_rp_show_information(struct vty *vty, u_char uj) { - struct rp_info *rp_info; - struct rp_info *prev_rp_info = NULL; - struct listnode *node; - - json_object *json = NULL; - json_object *json_rp_rows = NULL; - json_object *json_row = NULL; - - if (uj) - json = json_object_new_object(); - else - vty_out (vty, - "RP address group/prefix-list OIF I am RP\n"); - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (!pim_rpf_addr_is_inaddr_none (&rp_info->rp)) - { - char buf[48]; - - if (uj) - { - /* - * If we have moved on to a new RP then add the entry for the previous RP - */ - if (prev_rp_info && - prev_rp_info->rp.rpf_addr.u.prefix4.s_addr != rp_info->rp.rpf_addr.u.prefix4.s_addr) - { - json_object_object_add(json, inet_ntoa (prev_rp_info->rp.rpf_addr.u.prefix4), json_rp_rows); - json_rp_rows = NULL; - } - - if (!json_rp_rows) - json_rp_rows = json_object_new_array(); - - json_row = json_object_new_object(); - if (rp_info->rp.source_nexthop.interface) - json_object_string_add(json_row, "outboundInterface", rp_info->rp.source_nexthop.interface->name); - - if (rp_info->i_am_rp) - json_object_boolean_true_add(json_row, "iAmRP"); - - if (rp_info->plist) - json_object_string_add(json_row, "prefixList", rp_info->plist); - else - json_object_string_add(json_row, "group", prefix2str(&rp_info->group, buf, 48)); - - json_object_array_add(json_rp_rows, json_row); - } - else - { - vty_out (vty, "%-15s ", inet_ntoa (rp_info->rp.rpf_addr.u.prefix4)); - - if (rp_info->plist) - vty_out (vty, "%-18s ", rp_info->plist); - else - vty_out (vty, "%-18s ", prefix2str(&rp_info->group, buf, 48)); - - if (rp_info->rp.source_nexthop.interface) - vty_out (vty, "%-10s ", rp_info->rp.source_nexthop.interface->name); - else - vty_out (vty, "%-10s ", "(Unknown)"); - - if (rp_info->i_am_rp) - vty_out (vty, "yes\n"); - else - vty_out (vty, "no\n"); - } - - prev_rp_info = rp_info; - } - } - - if (uj) { - if (prev_rp_info && json_rp_rows) - json_object_object_add(json, inet_ntoa (prev_rp_info->rp.rpf_addr.u.prefix4), json_rp_rows); - - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + struct rp_info *rp_info; + struct rp_info *prev_rp_info = NULL; + struct listnode *node; + + json_object *json = NULL; + json_object *json_rp_rows = NULL; + json_object *json_row = NULL; + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "RP address group/prefix-list OIF I am RP\n"); + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (!pim_rpf_addr_is_inaddr_none(&rp_info->rp)) { + char buf[48]; + + if (uj) { + /* + * If we have moved on to a new RP then add the + * entry for the previous RP + */ + if (prev_rp_info + && prev_rp_info->rp.rpf_addr.u.prefix4 + .s_addr + != rp_info->rp.rpf_addr.u.prefix4 + .s_addr) { + json_object_object_add( + json, + inet_ntoa(prev_rp_info->rp + .rpf_addr.u + .prefix4), + json_rp_rows); + json_rp_rows = NULL; + } + + if (!json_rp_rows) + json_rp_rows = json_object_new_array(); + + json_row = json_object_new_object(); + if (rp_info->rp.source_nexthop.interface) + json_object_string_add( + json_row, "outboundInterface", + rp_info->rp.source_nexthop + .interface->name); + + if (rp_info->i_am_rp) + json_object_boolean_true_add(json_row, + "iAmRP"); + + if (rp_info->plist) + json_object_string_add(json_row, + "prefixList", + rp_info->plist); + else + json_object_string_add( + json_row, "group", + prefix2str(&rp_info->group, buf, + 48)); + + json_object_array_add(json_rp_rows, json_row); + } else { + vty_out(vty, "%-15s ", + inet_ntoa(rp_info->rp.rpf_addr.u + .prefix4)); + + if (rp_info->plist) + vty_out(vty, "%-18s ", rp_info->plist); + else + vty_out(vty, "%-18s ", + prefix2str(&rp_info->group, buf, + 48)); + + if (rp_info->rp.source_nexthop.interface) + vty_out(vty, "%-10s ", + rp_info->rp.source_nexthop + .interface->name); + else + vty_out(vty, "%-10s ", "(Unknown)"); + + if (rp_info->i_am_rp) + vty_out(vty, "yes\n"); + else + vty_out(vty, "no\n"); + } + + prev_rp_info = rp_info; + } + } + + if (uj) { + if (prev_rp_info && json_rp_rows) + json_object_object_add( + json, + inet_ntoa(prev_rp_info->rp.rpf_addr.u.prefix4), + json_rp_rows); + + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } -void -pim_resolve_rp_nh (void) +void pim_resolve_rp_nh(void) { - struct listnode *node = NULL; - struct rp_info *rp_info = NULL; - struct nexthop *nh_node = NULL; - struct prefix nht_p; - struct pim_nexthop_cache pnc; - struct pim_neighbor *nbr = NULL; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) - continue; - - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) - { - for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) - { - if (nh_node->gate.ipv4.s_addr == 0) - { - nbr = pim_neighbor_find_if (if_lookup_by_index - (nh_node->ifindex, VRF_DEFAULT)); - if (nbr) - { - nh_node->gate.ipv4 = nbr->source_addr; - if (PIM_DEBUG_TRACE) - { - char str[PREFIX_STRLEN]; - char str1[INET_ADDRSTRLEN]; - struct interface *ifp1 = if_lookup_by_index(nh_node->ifindex, - VRF_DEFAULT); - pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, - str1, sizeof (str1)); - pim_addr_dump ("<nht_addr?>", &nht_p, str, - sizeof (str)); - zlog_debug ("%s: addr %s new nexthop addr %s interface %s", - __PRETTY_FUNCTION__, str, str1, - ifp1->name); - } - } - } - } - } - } + struct listnode *node = NULL; + struct rp_info *rp_info = NULL; + struct nexthop *nh_node = NULL; + struct prefix nht_p; + struct pim_nexthop_cache pnc; + struct pim_neighbor *nbr = NULL; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) + continue; + + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc)) + == 1) { + for (nh_node = pnc.nexthop; nh_node; + nh_node = nh_node->next) { + if (nh_node->gate.ipv4.s_addr == 0) { + nbr = pim_neighbor_find_if( + if_lookup_by_index( + nh_node->ifindex, + VRF_DEFAULT)); + if (nbr) { + nh_node->gate.ipv4 = + nbr->source_addr; + if (PIM_DEBUG_TRACE) { + char str[PREFIX_STRLEN]; + char str1 + [INET_ADDRSTRLEN]; + struct interface *ifp1 = + if_lookup_by_index( + nh_node->ifindex, + VRF_DEFAULT); + pim_inet4_dump( + "<nht_nbr?>", + nbr->source_addr, + str1, + sizeof(str1)); + pim_addr_dump( + "<nht_addr?>", + &nht_p, str, + sizeof(str)); + zlog_debug( + "%s: addr %s new nexthop addr %s interface %s", + __PRETTY_FUNCTION__, + str, str1, + ifp1->name); + } + } + } + } + } + } } diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index 319fe573c..7a7c26593 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -27,39 +27,40 @@ #include "pim_iface.h" #include "pim_rpf.h" -struct rp_info -{ - struct prefix group; - struct pim_rpf rp; - int i_am_rp; - char *plist; +struct rp_info { + struct prefix group; + struct pim_rpf rp; + int i_am_rp; + char *plist; }; -void pim_rp_init (void); -void pim_rp_free (void); +void pim_rp_init(void); +void pim_rp_free(void); -int pim_rp_new (const char *rp, const char *group, const char *plist); -int pim_rp_del (const char *rp, const char *group, const char *plist); -void pim_rp_prefix_list_update (struct prefix_list *plist); +int pim_rp_new(const char *rp, const char *group, const char *plist); +int pim_rp_del(const char *rp, const char *group, const char *plist); +void pim_rp_prefix_list_update(struct prefix_list *plist); -int pim_rp_config_write (struct vty *vty); +int pim_rp_config_write(struct vty *vty); -int pim_rp_setup (void); +int pim_rp_setup(void); -int pim_rp_i_am_rp (struct in_addr group); +int pim_rp_i_am_rp(struct in_addr group); void pim_rp_check_on_if_add(struct pim_interface *pim_ifp); void pim_i_am_rp_re_evaluate(void); -int pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr); +int pim_rp_check_is_my_ip_address(struct in_addr group, + struct in_addr dest_addr); -int pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source, struct in_addr group); +int pim_rp_set_upstream_addr(struct in_addr *up, struct in_addr source, + struct in_addr group); -struct pim_rpf *pim_rp_g (struct in_addr group); +struct pim_rpf *pim_rp_g(struct in_addr group); #define I_am_RP(G) pim_rp_i_am_rp ((G)) #define RP(G) pim_rp_g ((G)) -void pim_rp_show_information (struct vty *vty, u_char uj); -void pim_resolve_rp_nh (void); -int pim_rp_list_cmp (void *v1, void *v2); +void pim_rp_show_information(struct vty *vty, u_char uj); +void pim_resolve_rp_nh(void); +int pim_rp_list_cmp(void *v1, void *v2); #endif diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index c5adf423c..4d0652c27 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -38,285 +38,281 @@ static long long last_route_change_time = -1; long long nexthop_lookups_avoided = 0; -static struct in_addr pim_rpf_find_rpf_addr (struct pim_upstream *up); +static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up); -void -pim_rpf_set_refresh_time (void) +void pim_rpf_set_refresh_time(void) { - last_route_change_time = pim_time_monotonic_usec(); - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: New last route change time: %lld", - __PRETTY_FUNCTION__, last_route_change_time); + last_route_change_time = pim_time_monotonic_usec(); + if (PIM_DEBUG_TRACE) + zlog_debug("%s: New last route change time: %lld", + __PRETTY_FUNCTION__, last_route_change_time); } -int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int neighbor_needed) +int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, + int neighbor_needed) { - struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; - struct pim_neighbor *nbr = NULL; - int num_ifindex; - struct interface *ifp = NULL; - ifindex_t first_ifindex = 0; - int found = 0; - int i = 0; - - if ((nexthop->last_lookup.s_addr == addr.s_addr) && - (nexthop->last_lookup_time > last_route_change_time)) - { - if (PIM_DEBUG_TRACE) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - char nexthop_str[PREFIX_STRLEN]; - pim_addr_dump("<nexthop?>", &nexthop->mrib_nexthop_addr, - nexthop_str, sizeof(nexthop_str)); - zlog_debug ("%s: Using last lookup for %s at %lld, %lld addr%s", - __PRETTY_FUNCTION__, - addr_str, - nexthop->last_lookup_time, - last_route_change_time, nexthop_str); + struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; + struct pim_neighbor *nbr = NULL; + int num_ifindex; + struct interface *ifp = NULL; + ifindex_t first_ifindex = 0; + int found = 0; + int i = 0; + + if ((nexthop->last_lookup.s_addr == addr.s_addr) + && (nexthop->last_lookup_time > last_route_change_time)) { + if (PIM_DEBUG_TRACE) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, + sizeof(addr_str)); + char nexthop_str[PREFIX_STRLEN]; + pim_addr_dump("<nexthop?>", &nexthop->mrib_nexthop_addr, + nexthop_str, sizeof(nexthop_str)); + zlog_debug( + "%s: Using last lookup for %s at %lld, %lld addr%s", + __PRETTY_FUNCTION__, addr_str, + nexthop->last_lookup_time, + last_route_change_time, nexthop_str); + } + nexthop_lookups_avoided++; + return 0; + } else { + if (PIM_DEBUG_TRACE) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s: Looking up: %s, last lookup time: %lld, %lld", + __PRETTY_FUNCTION__, addr_str, + nexthop->last_lookup_time, + last_route_change_time); + } } - nexthop_lookups_avoided++; - return 0; - } - else - { - if (PIM_DEBUG_TRACE) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug ("%s: Looking up: %s, last lookup time: %lld, %lld", - __PRETTY_FUNCTION__, - addr_str, - nexthop->last_lookup_time, - last_route_change_time); + + memset(nexthop_tab, 0, + sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM); + num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, + PIM_NEXTHOP_LOOKUP_MAX); + if (num_ifindex < 1) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); + zlog_warn( + "%s %s: could not find nexthop ifindex for address %s", + __FILE__, __PRETTY_FUNCTION__, addr_str); + return -1; + } + + while (!found && (i < num_ifindex)) { + first_ifindex = nexthop_tab[i].ifindex; + + ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); + if (!ifp) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: could not find interface for ifindex %d (address %s)", + __FILE__, __PRETTY_FUNCTION__, + first_ifindex, addr_str); + } + i++; + continue; + } + + if (!ifp->info) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", + __PRETTY_FUNCTION__, ifp->name, + first_ifindex, addr_str); + } + i++; + } else if (neighbor_needed + && !pim_if_connected_to_source(ifp, addr)) { + nbr = pim_neighbor_find( + ifp, nexthop_tab[i].nexthop_addr.u.prefix4); + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug("ifp name: %s, pim nbr: %p", + ifp->name, nbr); + if (!nbr && !if_is_loopback(ifp)) + i++; + else + found = 1; + } else + found = 1; } - } - - memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); - num_ifindex = zclient_lookup_nexthop(nexthop_tab, - MULTIPATH_NUM, - addr, PIM_NEXTHOP_LOOKUP_MAX); - if (num_ifindex < 1) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: could not find nexthop ifindex for address %s", - __FILE__, __PRETTY_FUNCTION__, - addr_str); - return -1; - } - - while (!found && (i < num_ifindex)) - { - first_ifindex = nexthop_tab[i].ifindex; - - ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); - if (!ifp) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: could not find interface for ifindex %d (address %s)", - __FILE__, __PRETTY_FUNCTION__, - first_ifindex, addr_str); - } - i++; - continue; - } - - if (!ifp->info) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", - __PRETTY_FUNCTION__, - ifp->name, first_ifindex, addr_str); - } - i++; - } - else if (neighbor_needed && !pim_if_connected_to_source (ifp, addr)) - { - nbr = pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4); - if (PIM_DEBUG_PIM_TRACE_DETAIL) - zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); - if (!nbr && !if_is_loopback (ifp)) - i++; - else - found = 1; - } - else - found = 1; - } - - if (found) - { - if (PIM_DEBUG_ZEBRA) { - char nexthop_str[PREFIX_STRLEN]; - char addr_str[INET_ADDRSTRLEN]; - pim_addr_dump("<nexthop?>", &nexthop_tab[i].nexthop_addr, nexthop_str, sizeof(nexthop_str)); - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: found nexthop %s for address %s: interface %s ifindex=%d metric=%d pref=%d", - __FILE__, __PRETTY_FUNCTION__, - nexthop_str, addr_str, - ifp->name, first_ifindex, - nexthop_tab[i].route_metric, - nexthop_tab[i].protocol_distance); - } - /* update nextop data */ - nexthop->interface = ifp; - nexthop->mrib_nexthop_addr = nexthop_tab[i].nexthop_addr; - nexthop->mrib_metric_preference = nexthop_tab[i].protocol_distance; - nexthop->mrib_route_metric = nexthop_tab[i].route_metric; - nexthop->last_lookup = addr; - nexthop->last_lookup_time = pim_time_monotonic_usec(); - nexthop->nbr = nbr; - return 0; - } - else - return -1; + + if (found) { + if (PIM_DEBUG_ZEBRA) { + char nexthop_str[PREFIX_STRLEN]; + char addr_str[INET_ADDRSTRLEN]; + pim_addr_dump("<nexthop?>", + &nexthop_tab[i].nexthop_addr, nexthop_str, + sizeof(nexthop_str)); + pim_inet4_dump("<addr?>", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: found nexthop %s for address %s: interface %s ifindex=%d metric=%d pref=%d", + __FILE__, __PRETTY_FUNCTION__, nexthop_str, + addr_str, ifp->name, first_ifindex, + nexthop_tab[i].route_metric, + nexthop_tab[i].protocol_distance); + } + /* update nextop data */ + nexthop->interface = ifp; + nexthop->mrib_nexthop_addr = nexthop_tab[i].nexthop_addr; + nexthop->mrib_metric_preference = + nexthop_tab[i].protocol_distance; + nexthop->mrib_route_metric = nexthop_tab[i].route_metric; + nexthop->last_lookup = addr; + nexthop->last_lookup_time = pim_time_monotonic_usec(); + nexthop->nbr = nbr; + return 0; + } else + return -1; } static int nexthop_mismatch(const struct pim_nexthop *nh1, const struct pim_nexthop *nh2) { - return (nh1->interface != nh2->interface) || - (nh1->mrib_nexthop_addr.u.prefix4.s_addr != nh2->mrib_nexthop_addr.u.prefix4.s_addr) || - (nh1->mrib_metric_preference != nh2->mrib_metric_preference) || - (nh1->mrib_route_metric != nh2->mrib_route_metric); + return (nh1->interface != nh2->interface) + || (nh1->mrib_nexthop_addr.u.prefix4.s_addr + != nh2->mrib_nexthop_addr.u.prefix4.s_addr) + || (nh1->mrib_metric_preference != nh2->mrib_metric_preference) + || (nh1->mrib_route_metric != nh2->mrib_route_metric); } -enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, uint8_t is_new) +enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, + uint8_t is_new) { - struct pim_rpf *rpf = &up->rpf; - struct pim_rpf saved; - struct prefix nht_p; - struct pim_nexthop_cache pnc; - int ret = 0; - struct prefix src, grp; - - saved.source_nexthop = rpf->source_nexthop; - saved.rpf_addr = rpf->rpf_addr; - - if (is_new && PIM_DEBUG_ZEBRA) - { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("<source?>", up->upstream_addr, source_str, - sizeof (source_str)); - zlog_debug ("%s: NHT Register upstream %s addr %s with Zebra.", - __PRETTY_FUNCTION__, up->sg_str, source_str); - } - /* Register addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; - - src.family = AF_INET; - src.prefixlen = IPV4_MAX_BITLEN; - src.u.prefix4 = up->upstream_addr; //RP or Src address - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = up->sg.grp; - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - if ((ret = pim_find_or_track_nexthop (&nht_p, up, NULL, &pnc)) == 1) - { - if (pnc.nexthop_num) - { - //Compute PIM RPF using Cached nexthop - if (pim_ecmp_nexthop_search (&pnc, &up->rpf.source_nexthop, - &src, &grp, - !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) && - !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))) - - { - return PIM_RPF_FAILURE; - } - } - } - else - { - if (pim_ecmp_nexthop_lookup (&rpf->source_nexthop, - up->upstream_addr, &src, &grp, - !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) && - !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))) - { - return PIM_RPF_FAILURE; - } - } - - rpf->rpf_addr.family = AF_INET; - rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up); - if (pim_rpf_addr_is_inaddr_any(rpf) && PIM_DEBUG_ZEBRA) - { - /* RPF'(S,G) not found */ - zlog_debug("%s %s: RPF'%s not found: won't send join upstream", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str); - /* warning only */ - } - - /* detect change in pim_nexthop */ - if (nexthop_mismatch(&rpf->source_nexthop, &saved.source_nexthop)) { - - if (PIM_DEBUG_ZEBRA) { - char nhaddr_str[PREFIX_STRLEN]; - pim_addr_dump("<addr?>", &rpf->source_nexthop.mrib_nexthop_addr, nhaddr_str, sizeof(nhaddr_str)); - zlog_debug("%s %s: (S,G)=%s source nexthop now is: interface=%s address=%s pref=%d metric=%d", + struct pim_rpf *rpf = &up->rpf; + struct pim_rpf saved; + struct prefix nht_p; + struct pim_nexthop_cache pnc; + int ret = 0; + struct prefix src, grp; + + saved.source_nexthop = rpf->source_nexthop; + saved.rpf_addr = rpf->rpf_addr; + + if (is_new && PIM_DEBUG_ZEBRA) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<source?>", up->upstream_addr, source_str, + sizeof(source_str)); + zlog_debug("%s: NHT Register upstream %s addr %s with Zebra.", + __PRETTY_FUNCTION__, up->sg_str, source_str); + } + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; + + src.family = AF_INET; + src.prefixlen = IPV4_MAX_BITLEN; + src.u.prefix4 = up->upstream_addr; // RP or Src address + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = up->sg.grp; + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + if ((ret = pim_find_or_track_nexthop(&nht_p, up, NULL, &pnc)) == 1) { + if (pnc.nexthop_num) { + // Compute PIM RPF using Cached nexthop + if (pim_ecmp_nexthop_search( + &pnc, &up->rpf.source_nexthop, &src, &grp, + !PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) + && !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP( + up->flags))) + + { + return PIM_RPF_FAILURE; + } + } + } else { + if (pim_ecmp_nexthop_lookup( + &rpf->source_nexthop, up->upstream_addr, &src, &grp, + !PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) + && !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP( + up->flags))) { + return PIM_RPF_FAILURE; + } + } + + rpf->rpf_addr.family = AF_INET; + rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up); + if (pim_rpf_addr_is_inaddr_any(rpf) && PIM_DEBUG_ZEBRA) { + /* RPF'(S,G) not found */ + zlog_debug("%s %s: RPF'%s not found: won't send join upstream", + __FILE__, __PRETTY_FUNCTION__, up->sg_str); + /* warning only */ + } + + /* detect change in pim_nexthop */ + if (nexthop_mismatch(&rpf->source_nexthop, &saved.source_nexthop)) { + + if (PIM_DEBUG_ZEBRA) { + char nhaddr_str[PREFIX_STRLEN]; + pim_addr_dump("<addr?>", + &rpf->source_nexthop.mrib_nexthop_addr, + nhaddr_str, sizeof(nhaddr_str)); + zlog_debug("%s %s: (S,G)=%s source nexthop now is: interface=%s address=%s pref=%d metric=%d", __FILE__, __PRETTY_FUNCTION__, up->sg_str, rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>", nhaddr_str, rpf->source_nexthop.mrib_metric_preference, rpf->source_nexthop.mrib_route_metric); - } + } - pim_upstream_update_join_desired(up); - pim_upstream_update_could_assert(up); - pim_upstream_update_my_assert_metric(up); - } + pim_upstream_update_join_desired(up); + pim_upstream_update_could_assert(up); + pim_upstream_update_my_assert_metric(up); + } - /* detect change in RPF_interface(S) */ - if (saved.source_nexthop.interface != rpf->source_nexthop.interface) { + /* detect change in RPF_interface(S) */ + if (saved.source_nexthop.interface != rpf->source_nexthop.interface) { - if (PIM_DEBUG_ZEBRA) { - zlog_debug("%s %s: (S,G)=%s RPF_interface(S) changed from %s to %s", + if (PIM_DEBUG_ZEBRA) { + zlog_debug("%s %s: (S,G)=%s RPF_interface(S) changed from %s to %s", __FILE__, __PRETTY_FUNCTION__, up->sg_str, saved.source_nexthop.interface ? saved.source_nexthop.interface->name : "<oldif?>", rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<newif?>"); - /* warning only */ - } - - pim_upstream_rpf_interface_changed(up, saved.source_nexthop.interface); - } - - /* detect change in RPF'(S,G) */ - if (saved.rpf_addr.u.prefix4.s_addr != rpf->rpf_addr.u.prefix4.s_addr || - saved.source_nexthop.interface != rpf->source_nexthop.interface) - { - - /* return old rpf to caller ? */ - if (old) - { - old->source_nexthop = saved.source_nexthop; - old->rpf_addr = saved.rpf_addr; - } - return PIM_RPF_CHANGED; - } - - return PIM_RPF_OK; + /* warning only */ + } + + pim_upstream_rpf_interface_changed( + up, saved.source_nexthop.interface); + } + + /* detect change in RPF'(S,G) */ + if (saved.rpf_addr.u.prefix4.s_addr != rpf->rpf_addr.u.prefix4.s_addr + || saved.source_nexthop + .interface != rpf->source_nexthop.interface) { + + /* return old rpf to caller ? */ + if (old) { + old->source_nexthop = saved.source_nexthop; + old->rpf_addr = saved.rpf_addr; + } + return PIM_RPF_CHANGED; + } + + return PIM_RPF_OK; } /* RFC 4601: 4.1.6. State Summarization Macros neighbor RPF'(S,G) { - if ( I_Am_Assert_Loser(S, G, RPF_interface(S) )) { - return AssertWinner(S, G, RPF_interface(S) ) - } else { - return NBR( RPF_interface(S), MRIB.next_hop( S ) ) - } + if ( I_Am_Assert_Loser(S, G, RPF_interface(S) )) { + return AssertWinner(S, G, RPF_interface(S) ) + } else { + return NBR( RPF_interface(S), MRIB.next_hop( S ) ) + } } RPF'(*,G) and RPF'(S,G) indicate the neighbor from which data @@ -325,84 +321,78 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, */ static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up) { - struct pim_ifchannel *rpf_ch; - struct pim_neighbor *neigh; - struct in_addr rpf_addr; - - if (!up->rpf.source_nexthop.interface) { - zlog_warn("%s: missing RPF interface for upstream (S,G)=%s", - __PRETTY_FUNCTION__, - up->sg_str); - - rpf_addr.s_addr = PIM_NET_INADDR_ANY; - return rpf_addr; - } - - rpf_ch = pim_ifchannel_find(up->rpf.source_nexthop.interface, - &up->sg); - if (rpf_ch) { - if (rpf_ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { - return rpf_ch->ifassert_winner; - } - } - - /* return NBR( RPF_interface(S), MRIB.next_hop( S ) ) */ - - neigh = pim_if_find_neighbor(up->rpf.source_nexthop.interface, - up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4); - if (neigh) - rpf_addr = neigh->source_addr; - else - rpf_addr.s_addr = PIM_NET_INADDR_ANY; - - return rpf_addr; + struct pim_ifchannel *rpf_ch; + struct pim_neighbor *neigh; + struct in_addr rpf_addr; + + if (!up->rpf.source_nexthop.interface) { + zlog_warn("%s: missing RPF interface for upstream (S,G)=%s", + __PRETTY_FUNCTION__, up->sg_str); + + rpf_addr.s_addr = PIM_NET_INADDR_ANY; + return rpf_addr; + } + + rpf_ch = pim_ifchannel_find(up->rpf.source_nexthop.interface, &up->sg); + if (rpf_ch) { + if (rpf_ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { + return rpf_ch->ifassert_winner; + } + } + + /* return NBR( RPF_interface(S), MRIB.next_hop( S ) ) */ + + neigh = pim_if_find_neighbor( + up->rpf.source_nexthop.interface, + up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4); + if (neigh) + rpf_addr = neigh->source_addr; + else + rpf_addr.s_addr = PIM_NET_INADDR_ANY; + + return rpf_addr; } -int -pim_rpf_addr_is_inaddr_none (struct pim_rpf *rpf) +int pim_rpf_addr_is_inaddr_none(struct pim_rpf *rpf) { - switch (rpf->rpf_addr.family) - { - case AF_INET: - return rpf->rpf_addr.u.prefix4.s_addr == INADDR_NONE; - break; - case AF_INET6: - zlog_warn ("%s: v6 Unimplmeneted", __PRETTY_FUNCTION__); - return 1; - break; - default: - return 0; - break; - } - - return 0; + switch (rpf->rpf_addr.family) { + case AF_INET: + return rpf->rpf_addr.u.prefix4.s_addr == INADDR_NONE; + break; + case AF_INET6: + zlog_warn("%s: v6 Unimplmeneted", __PRETTY_FUNCTION__); + return 1; + break; + default: + return 0; + break; + } + + return 0; } -int -pim_rpf_addr_is_inaddr_any (struct pim_rpf *rpf) +int pim_rpf_addr_is_inaddr_any(struct pim_rpf *rpf) { - switch (rpf->rpf_addr.family) - { - case AF_INET: - return rpf->rpf_addr.u.prefix4.s_addr == INADDR_ANY; - break; - case AF_INET6: - zlog_warn ("%s: v6 Unimplmented", __PRETTY_FUNCTION__); - return 1; - break; - default: - return 0; - break; - } - - return 0; + switch (rpf->rpf_addr.family) { + case AF_INET: + return rpf->rpf_addr.u.prefix4.s_addr == INADDR_ANY; + break; + case AF_INET6: + zlog_warn("%s: v6 Unimplmented", __PRETTY_FUNCTION__); + return 1; + break; + default: + return 0; + break; + } + + return 0; } -int -pim_rpf_is_same (struct pim_rpf *rpf1, struct pim_rpf *rpf2) +int pim_rpf_is_same(struct pim_rpf *rpf1, struct pim_rpf *rpf2) { - if (rpf1->source_nexthop.interface == rpf2->source_nexthop.interface) - return 1; + if (rpf1->source_nexthop.interface == rpf2->source_nexthop.interface) + return 1; - return 0; + return 0; } diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index bb7ee365b..083314356 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -38,36 +38,34 @@ units applicable to the unicast routing protocol used. */ struct pim_nexthop { - struct in_addr last_lookup; - long long last_lookup_time; - struct interface *interface; /* RPF_interface(S) */ - struct prefix mrib_nexthop_addr; /* MRIB.next_hop(S) */ - uint32_t mrib_metric_preference; /* MRIB.pref(S) */ - uint32_t mrib_route_metric; /* MRIB.metric(S) */ - struct pim_neighbor *nbr; + struct in_addr last_lookup; + long long last_lookup_time; + struct interface *interface; /* RPF_interface(S) */ + struct prefix mrib_nexthop_addr; /* MRIB.next_hop(S) */ + uint32_t mrib_metric_preference; /* MRIB.pref(S) */ + uint32_t mrib_route_metric; /* MRIB.metric(S) */ + struct pim_neighbor *nbr; }; struct pim_rpf { - struct pim_nexthop source_nexthop; - struct prefix rpf_addr; /* RPF'(S,G) */ + struct pim_nexthop source_nexthop; + struct prefix rpf_addr; /* RPF'(S,G) */ }; -enum pim_rpf_result { - PIM_RPF_OK = 0, - PIM_RPF_CHANGED, - PIM_RPF_FAILURE -}; +enum pim_rpf_result { PIM_RPF_OK = 0, PIM_RPF_CHANGED, PIM_RPF_FAILURE }; struct pim_upstream; extern long long nexthop_lookups_avoided; -int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int neighbor_needed); -enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, uint8_t is_new); +int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, + int neighbor_needed); +enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, + uint8_t is_new); -int pim_rpf_addr_is_inaddr_none (struct pim_rpf *rpf); -int pim_rpf_addr_is_inaddr_any (struct pim_rpf *rpf); +int pim_rpf_addr_is_inaddr_none(struct pim_rpf *rpf); +int pim_rpf_addr_is_inaddr_any(struct pim_rpf *rpf); -int pim_rpf_is_same (struct pim_rpf *rpf1, struct pim_rpf *rpf2); -void pim_rpf_set_refresh_time (void); +int pim_rpf_is_same(struct pim_rpf *rpf1, struct pim_rpf *rpf2); +void pim_rpf_set_refresh_time(void); #endif /* PIM_RPF_H */ diff --git a/pimd/pim_signals.c b/pimd/pim_signals.c index ef492d0d8..0e9b09bf8 100644 --- a/pimd/pim_signals.c +++ b/pimd/pim_signals.c @@ -35,44 +35,43 @@ static void pim_sighup() { - zlog_info ("SIGHUP received, ignoring"); + zlog_info("SIGHUP received, ignoring"); } static void pim_sigint() { - zlog_notice("Terminating on signal SIGINT"); - pim_terminate(); - exit(1); + zlog_notice("Terminating on signal SIGINT"); + pim_terminate(); + exit(1); } static void pim_sigterm() { - zlog_notice("Terminating on signal SIGTERM"); - pim_terminate(); - exit(1); + zlog_notice("Terminating on signal SIGTERM"); + pim_terminate(); + exit(1); } static void pim_sigusr1() { - zlog_rotate(); + zlog_rotate(); } -struct quagga_signal_t pimd_signals[] = -{ - { - .signal = SIGHUP, - .handler = &pim_sighup, - }, - { - .signal = SIGUSR1, - .handler = &pim_sigusr1, - }, - { - .signal = SIGINT, - .handler = &pim_sigint, - }, - { - .signal = SIGTERM, - .handler = &pim_sigterm, - }, +struct quagga_signal_t pimd_signals[] = { + { + .signal = SIGHUP, + .handler = &pim_sighup, + }, + { + .signal = SIGUSR1, + .handler = &pim_sigusr1, + }, + { + .signal = SIGINT, + .handler = &pim_sigint, + }, + { + .signal = SIGTERM, + .handler = &pim_sigterm, + }, }; diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index ba70cf2e1..a4d3d7e4b 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -42,292 +42,305 @@ /* GLOBAL VARS */ -int -pim_socket_raw (int protocol) +int pim_socket_raw(int protocol) { - int fd; + int fd; - if ( pimd_privs.change (ZPRIVS_RAISE) ) - zlog_err ("pim_sockek_raw: could not raise privs, %s", - safe_strerror (errno) ); + if (pimd_privs.change(ZPRIVS_RAISE)) + zlog_err("pim_sockek_raw: could not raise privs, %s", + safe_strerror(errno)); - fd = socket(AF_INET, SOCK_RAW, protocol); + fd = socket(AF_INET, SOCK_RAW, protocol); - if ( pimd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("pim_socket_raw: could not lower privs, %s", - safe_strerror (errno) ); + if (pimd_privs.change(ZPRIVS_LOWER)) + zlog_err("pim_socket_raw: could not lower privs, %s", + safe_strerror(errno)); - if (fd < 0) { - zlog_warn("Could not create raw socket: errno=%d: %s", - errno, safe_strerror(errno)); - return PIM_SOCK_ERR_SOCKET; - } - - return fd; + if (fd < 0) { + zlog_warn("Could not create raw socket: errno=%d: %s", errno, + safe_strerror(errno)); + return PIM_SOCK_ERR_SOCKET; + } + + return fd; } -int -pim_socket_ip_hdr (int fd) +int pim_socket_ip_hdr(int fd) { - const int on = 1; - int ret; + const int on = 1; + int ret; - if (pimd_privs.change (ZPRIVS_RAISE)) - zlog_err ("%s: could not raise privs, %s", - __PRETTY_FUNCTION__, safe_strerror (errno)); + if (pimd_privs.change(ZPRIVS_RAISE)) + zlog_err("%s: could not raise privs, %s", __PRETTY_FUNCTION__, + safe_strerror(errno)); - ret = setsockopt (fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)); + ret = setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)); - if (pimd_privs.change (ZPRIVS_LOWER)) - zlog_err ("%s: could not lower privs, %s", - __PRETTY_FUNCTION__, safe_strerror (errno)); + if (pimd_privs.change(ZPRIVS_LOWER)) + zlog_err("%s: could not lower privs, %s", __PRETTY_FUNCTION__, + safe_strerror(errno)); - return ret; + return ret; } /* * Given a socket and a interface, * Bind that socket to that interface */ -int -pim_socket_bind (int fd, struct interface *ifp) +int pim_socket_bind(int fd, struct interface *ifp) { - int ret = 0; + int ret = 0; #ifdef SO_BINDTODEVICE - if (pimd_privs.change (ZPRIVS_RAISE)) - zlog_err ("%s: could not raise privs, %s", - __PRETTY_FUNCTION__, safe_strerror (errno)); + if (pimd_privs.change(ZPRIVS_RAISE)) + zlog_err("%s: could not raise privs, %s", __PRETTY_FUNCTION__, + safe_strerror(errno)); - ret = setsockopt (fd, SOL_SOCKET, - SO_BINDTODEVICE, ifp->name, strlen (ifp->name)); + ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifp->name, + strlen(ifp->name)); - if (pimd_privs.change (ZPRIVS_LOWER)) - zlog_err ("%s: could not lower privs, %s", - __PRETTY_FUNCTION__, safe_strerror (errno)); + if (pimd_privs.change(ZPRIVS_LOWER)) + zlog_err("%s: could not lower privs, %s", __PRETTY_FUNCTION__, + safe_strerror(errno)); #endif - return ret; + return ret; } -int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp, u_char loop) +int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp, + u_char loop) { - int rcvbuf = 1024 * 1024 * 8; + int rcvbuf = 1024 * 1024 * 8; #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX - struct ip_mreqn mreq; + struct ip_mreqn mreq; #else - struct ip_mreq mreq; + struct ip_mreq mreq; #endif - int fd; + int fd; - fd = pim_socket_raw(protocol); - if (fd < 0) { - zlog_warn("Could not create multicast socket: errno=%d: %s", - errno, safe_strerror(errno)); - return PIM_SOCK_ERR_SOCKET; - } + fd = pim_socket_raw(protocol); + if (fd < 0) { + zlog_warn("Could not create multicast socket: errno=%d: %s", + errno, safe_strerror(errno)); + return PIM_SOCK_ERR_SOCKET; + } #ifdef SO_BINDTODEVICE - if (protocol == IPPROTO_PIM) - { - int ret; - - ret = pim_socket_bind (fd, ifp); - if (ret) - { - close (fd); - zlog_warn("Could not set fd: %d for interface: %s to device", - fd, ifp->name); - return PIM_SOCK_ERR_BIND; + if (protocol == IPPROTO_PIM) { + int ret; + + ret = pim_socket_bind(fd, ifp); + if (ret) { + close(fd); + zlog_warn( + "Could not set fd: %d for interface: %s to device", + fd, ifp->name); + return PIM_SOCK_ERR_BIND; + } } - } #else - /* XXX: use IP_PKTINFO / IP_RECVIF to emulate behaviour? Or change to - * only use 1 socket for all interfaces? */ +/* XXX: use IP_PKTINFO / IP_RECVIF to emulate behaviour? Or change to + * only use 1 socket for all interfaces? */ #endif - /* Needed to obtain destination address from recvmsg() */ - { + /* Needed to obtain destination address from recvmsg() */ + { #if defined(HAVE_IP_PKTINFO) - /* Linux and Solaris IP_PKTINFO */ - int opt = 1; - if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) { - zlog_warn("Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - } + /* Linux and Solaris IP_PKTINFO */ + int opt = 1; + if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) { + zlog_warn( + "Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + } #elif defined(HAVE_IP_RECVDSTADDR) - /* BSD IP_RECVDSTADDR */ - int opt = 1; - if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt))) { - zlog_warn("Could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - } + /* BSD IP_RECVDSTADDR */ + int opt = 1; + if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, + sizeof(opt))) { + zlog_warn( + "Could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + } #else - zlog_err("%s %s: Missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()", - __FILE__, __PRETTY_FUNCTION__); - close(fd); - return PIM_SOCK_ERR_DSTADDR; + zlog_err( + "%s %s: Missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()", + __FILE__, __PRETTY_FUNCTION__); + close(fd); + return PIM_SOCK_ERR_DSTADDR; #endif - } - - - /* Set router alert (RFC 2113) for all IGMP messages (RFC 3376 4. Message Formats)*/ - if (protocol == IPPROTO_IGMP) { - uint8_t ra[4]; - ra[0] = 148; - ra[1] = 4; - ra[2] = 0; - ra[3] = 0; - if (setsockopt(fd, IPPROTO_IP, IP_OPTIONS, ra, 4)) { - zlog_warn("Could not set Router Alert Option on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_RA; - } - } - - { - int reuse = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (void *) &reuse, sizeof(reuse))) { - zlog_warn("Could not set Reuse Address Option on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_REUSE; - } - } - - { - const int MTTL = 1; - int ttl = MTTL; - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, - (void *) &ttl, sizeof(ttl))) { - zlog_warn("Could not set multicast TTL=%d on socket fd=%d: errno=%d: %s", - MTTL, fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_TTL; - } - } - - if (setsockopt_ipv4_multicast_loop (fd, loop)) { - zlog_warn("Could not %s Multicast Loopback Option on socket fd=%d: errno=%d: %s", - loop ? "enable" : "disable", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_LOOP; - } - - memset (&mreq, 0, sizeof (mreq)); + } + + + /* Set router alert (RFC 2113) for all IGMP messages (RFC 3376 4. + * Message Formats)*/ + if (protocol == IPPROTO_IGMP) { + uint8_t ra[4]; + ra[0] = 148; + ra[1] = 4; + ra[2] = 0; + ra[3] = 0; + if (setsockopt(fd, IPPROTO_IP, IP_OPTIONS, ra, 4)) { + zlog_warn( + "Could not set Router Alert Option on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_RA; + } + } + + { + int reuse = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, + sizeof(reuse))) { + zlog_warn( + "Could not set Reuse Address Option on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_REUSE; + } + } + + { + const int MTTL = 1; + int ttl = MTTL; + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl, + sizeof(ttl))) { + zlog_warn( + "Could not set multicast TTL=%d on socket fd=%d: errno=%d: %s", + MTTL, fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_TTL; + } + } + + if (setsockopt_ipv4_multicast_loop(fd, loop)) { + zlog_warn( + "Could not %s Multicast Loopback Option on socket fd=%d: errno=%d: %s", + loop ? "enable" : "disable", fd, errno, + safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_LOOP; + } + + memset(&mreq, 0, sizeof(mreq)); #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX - mreq.imr_ifindex = ifp->ifindex; + mreq.imr_ifindex = ifp->ifindex; #else - /* - * I am not sure what to do here yet for *BSD - */ - //mreq.imr_interface = ifindex; +/* + * I am not sure what to do here yet for *BSD + */ +// mreq.imr_interface = ifindex; #endif - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (void *) &mreq, sizeof(mreq))) { - zlog_warn("Could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_IFACE; - } - - if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))) - zlog_warn("%s: Failure to set buffer size to %d", - __PRETTY_FUNCTION__, rcvbuf); - - { - long flags; - - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) { - zlog_warn("Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_NONBLOCK_GETFL; - } - - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { - zlog_warn("Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_NONBLOCK_SETFL; - } - } - - return fd; + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (void *)&mreq, + sizeof(mreq))) { + zlog_warn( + "Could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_IFACE; + } + + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))) + zlog_warn("%s: Failure to set buffer size to %d", + __PRETTY_FUNCTION__, rcvbuf); + + { + long flags; + + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) { + zlog_warn( + "Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_NONBLOCK_GETFL; + } + + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { + zlog_warn( + "Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_NONBLOCK_SETFL; + } + } + + return fd; } -int pim_socket_join(int fd, struct in_addr group, - struct in_addr ifaddr, ifindex_t ifindex) +int pim_socket_join(int fd, struct in_addr group, struct in_addr ifaddr, + ifindex_t ifindex) { - int ret; + int ret; #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX - struct ip_mreqn opt; + struct ip_mreqn opt; #else - struct ip_mreq opt; + struct ip_mreq opt; #endif - opt.imr_multiaddr = group; + opt.imr_multiaddr = group; #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX - opt.imr_address = ifaddr; - opt.imr_ifindex = ifindex; + opt.imr_address = ifaddr; + opt.imr_ifindex = ifindex; #else - opt.imr_interface = ifaddr; + opt.imr_interface = ifaddr; #endif - ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt)); - if (ret) { - char group_str[INET_ADDRSTRLEN]; - char ifaddr_str[INET_ADDRSTRLEN]; - if (!inet_ntop(AF_INET, &group, group_str , sizeof(group_str))) - sprintf(group_str, "<group?>"); - if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str , sizeof(ifaddr_str))) - sprintf(ifaddr_str, "<ifaddr?>"); - - zlog_err("Failure socket joining fd=%d group %s on interface address %s: errno=%d: %s", - fd, group_str, ifaddr_str, errno, safe_strerror(errno)); - return ret; - } - - if (PIM_DEBUG_TRACE) { - char group_str[INET_ADDRSTRLEN]; - char ifaddr_str[INET_ADDRSTRLEN]; - if (!inet_ntop(AF_INET, &group, group_str , sizeof(group_str))) - sprintf(group_str, "<group?>"); - if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str , sizeof(ifaddr_str))) - sprintf(ifaddr_str, "<ifaddr?>"); - - zlog_debug("Socket fd=%d joined group %s on interface address %s", - fd, group_str, ifaddr_str); - } - - return ret; + ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt)); + if (ret) { + char group_str[INET_ADDRSTRLEN]; + char ifaddr_str[INET_ADDRSTRLEN]; + if (!inet_ntop(AF_INET, &group, group_str, sizeof(group_str))) + sprintf(group_str, "<group?>"); + if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str, + sizeof(ifaddr_str))) + sprintf(ifaddr_str, "<ifaddr?>"); + + zlog_err( + "Failure socket joining fd=%d group %s on interface address %s: errno=%d: %s", + fd, group_str, ifaddr_str, errno, safe_strerror(errno)); + return ret; + } + + if (PIM_DEBUG_TRACE) { + char group_str[INET_ADDRSTRLEN]; + char ifaddr_str[INET_ADDRSTRLEN]; + if (!inet_ntop(AF_INET, &group, group_str, sizeof(group_str))) + sprintf(group_str, "<group?>"); + if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str, + sizeof(ifaddr_str))) + sprintf(ifaddr_str, "<ifaddr?>"); + + zlog_debug( + "Socket fd=%d joined group %s on interface address %s", + fd, group_str, ifaddr_str); + } + + return ret; } -int pim_socket_join_source(int fd, ifindex_t ifindex, - struct in_addr group_addr, - struct in_addr source_addr, - const char *ifname) +int pim_socket_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr, + struct in_addr source_addr, const char *ifname) { - if (pim_igmp_join_source(fd, ifindex, group_addr, source_addr)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s", - __PRETTY_FUNCTION__, - fd, group_str, source_str, ifindex, ifname, - errno, safe_strerror(errno)); - return -1; - } - - return 0; + if (pim_igmp_join_source(fd, ifindex, group_addr, source_addr)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s", + __PRETTY_FUNCTION__, fd, group_str, source_str, ifindex, + ifname, errno, safe_strerror(errno)); + return -1; + } + + return 0; } int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, @@ -335,117 +348,121 @@ int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, struct sockaddr_in *to, socklen_t *tolen, ifindex_t *ifindex) { - struct msghdr msgh; - struct cmsghdr *cmsg; - struct iovec iov; - char cbuf[1000]; - int err; - - /* - * IP_PKTINFO / IP_RECVDSTADDR don't yield sin_port. - * Use getsockname() to get sin_port. - */ - if (to) { - struct sockaddr_in si; - socklen_t si_len = sizeof(si); - - memset (&si, 0, sizeof (si)); - to->sin_family = AF_INET; - - pim_socket_getsockname(fd, (struct sockaddr *) &si, &si_len); - - to->sin_port = si.sin_port; - to->sin_addr = si.sin_addr; - - if (tolen) - *tolen = sizeof(si); - } - - memset(&msgh, 0, sizeof(struct msghdr)); - iov.iov_base = buf; - iov.iov_len = len; - msgh.msg_control = cbuf; - msgh.msg_controllen = sizeof(cbuf); - msgh.msg_name = from; - msgh.msg_namelen = fromlen ? *fromlen : 0; - msgh.msg_iov = &iov; - msgh.msg_iovlen = 1; - msgh.msg_flags = 0; - - err = recvmsg(fd, &msgh, 0); - if (err < 0) - return err; - - if (fromlen) - *fromlen = msgh.msg_namelen; - - for (cmsg = CMSG_FIRSTHDR(&msgh); - cmsg != NULL; - cmsg = CMSG_NXTHDR(&msgh,cmsg)) { + struct msghdr msgh; + struct cmsghdr *cmsg; + struct iovec iov; + char cbuf[1000]; + int err; + + /* + * IP_PKTINFO / IP_RECVDSTADDR don't yield sin_port. + * Use getsockname() to get sin_port. + */ + if (to) { + struct sockaddr_in si; + socklen_t si_len = sizeof(si); + + memset(&si, 0, sizeof(si)); + to->sin_family = AF_INET; + + pim_socket_getsockname(fd, (struct sockaddr *)&si, &si_len); + + to->sin_port = si.sin_port; + to->sin_addr = si.sin_addr; + + if (tolen) + *tolen = sizeof(si); + } + + memset(&msgh, 0, sizeof(struct msghdr)); + iov.iov_base = buf; + iov.iov_len = len; + msgh.msg_control = cbuf; + msgh.msg_controllen = sizeof(cbuf); + msgh.msg_name = from; + msgh.msg_namelen = fromlen ? *fromlen : 0; + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + msgh.msg_flags = 0; + + err = recvmsg(fd, &msgh, 0); + if (err < 0) + return err; + + if (fromlen) + *fromlen = msgh.msg_namelen; + + for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msgh, cmsg)) { #ifdef HAVE_IP_PKTINFO - if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_PKTINFO)) { - struct in_pktinfo *i = (struct in_pktinfo *) CMSG_DATA(cmsg); - if (to) - ((struct sockaddr_in *) to)->sin_addr = i->ipi_addr; - if (tolen) - *tolen = sizeof(struct sockaddr_in); - if (ifindex) - *ifindex = i->ipi_ifindex; - - break; - } + if ((cmsg->cmsg_level == IPPROTO_IP) + && (cmsg->cmsg_type == IP_PKTINFO)) { + struct in_pktinfo *i = + (struct in_pktinfo *)CMSG_DATA(cmsg); + if (to) + ((struct sockaddr_in *)to)->sin_addr = + i->ipi_addr; + if (tolen) + *tolen = sizeof(struct sockaddr_in); + if (ifindex) + *ifindex = i->ipi_ifindex; + + break; + } #endif #ifdef HAVE_IP_RECVDSTADDR - if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_RECVDSTADDR)) { - struct in_addr *i = (struct in_addr *) CMSG_DATA(cmsg); - if (to) - ((struct sockaddr_in *) to)->sin_addr = *i; - if (tolen) - *tolen = sizeof(struct sockaddr_in); - - break; - } + if ((cmsg->cmsg_level == IPPROTO_IP) + && (cmsg->cmsg_type == IP_RECVDSTADDR)) { + struct in_addr *i = (struct in_addr *)CMSG_DATA(cmsg); + if (to) + ((struct sockaddr_in *)to)->sin_addr = *i; + if (tolen) + *tolen = sizeof(struct sockaddr_in); + + break; + } #endif #if defined(HAVE_IP_RECVIF) && defined(CMSG_IFINDEX) - if (cmsg->cmsg_type == IP_RECVIF) - if (ifindex) - *ifindex = CMSG_IFINDEX(cmsg); + if (cmsg->cmsg_type == IP_RECVIF) + if (ifindex) + *ifindex = CMSG_IFINDEX(cmsg); #endif - } /* for (cmsg) */ + } /* for (cmsg) */ - return err; /* len */ + return err; /* len */ } int pim_socket_mcastloop_get(int fd) { - int loop; - socklen_t loop_len = sizeof(loop); - - if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, - &loop, &loop_len)) { - int e = errno; - zlog_warn("Could not get Multicast Loopback Option on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - errno = e; - return PIM_SOCK_ERR_LOOP; - } - - return loop; + int loop; + socklen_t loop_len = sizeof(loop); + + if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, &loop_len)) { + int e = errno; + zlog_warn( + "Could not get Multicast Loopback Option on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + errno = e; + return PIM_SOCK_ERR_LOOP; + } + + return loop; } int pim_socket_getsockname(int fd, struct sockaddr *name, socklen_t *namelen) { - if (getsockname(fd, name, namelen)) { - int e = errno; - zlog_warn("Could not get Socket Name for socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - errno = e; - return PIM_SOCK_ERR_NAME; - } - - return PIM_SOCK_ERR_NONE; + if (getsockname(fd, name, namelen)) { + int e = errno; + zlog_warn( + "Could not get Socket Name for socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + errno = e; + return PIM_SOCK_ERR_NAME; + } + + return PIM_SOCK_ERR_NONE; } diff --git a/pimd/pim_sock.h b/pimd/pim_sock.h index 9fb64677c..aa46cd620 100644 --- a/pimd/pim_sock.h +++ b/pimd/pim_sock.h @@ -35,16 +35,15 @@ #define PIM_SOCK_ERR_NAME (-10) /* Socket name (getsockname) */ #define PIM_SOCK_ERR_BIND (-11) /* Can't bind to interface */ -int pim_socket_bind (int fd, struct interface *ifp); -int pim_socket_ip_hdr (int fd); +int pim_socket_bind(int fd, struct interface *ifp); +int pim_socket_ip_hdr(int fd); int pim_socket_raw(int protocol); -int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp, u_char loop); -int pim_socket_join(int fd, struct in_addr group, - struct in_addr ifaddr, ifindex_t ifindex); -int pim_socket_join_source(int fd, ifindex_t ifindex, - struct in_addr group_addr, - struct in_addr source_addr, - const char *ifname); +int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp, + u_char loop); +int pim_socket_join(int fd, struct in_addr group, struct in_addr ifaddr, + ifindex_t ifindex); +int pim_socket_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr, + struct in_addr source_addr, const char *ifname); int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, struct sockaddr_in *from, socklen_t *fromlen, struct sockaddr_in *to, socklen_t *tolen, diff --git a/pimd/pim_ssm.c b/pimd/pim_ssm.c index d4f88ec2c..3046e9429 100644 --- a/pimd/pim_ssm.c +++ b/pimd/pim_ssm.c @@ -29,129 +29,119 @@ #include "pim_ssm.h" #include "pim_zebra.h" -static void -pim_ssm_range_reevaluate (void) +static void pim_ssm_range_reevaluate(void) { - /* 1. Setup register state for (S,G) entries if G has changed from SSM to - * ASM. - * 2. check existing (*,G) IGMP registrations to see if they are - * still ASM. if they are now SSM delete them. - * 3. Allow channel setup for IGMP (*,G) members if G is now ASM - * 4. I could tear down all (*,G), (S,G,rpt) states. But that is an - * unnecessary sladge hammer and may not be particularly useful as it is - * likely the SPT switchover has already happened for flows along such RPTs. - * As for the RPT states it seems that the best thing to do is let them age - * out gracefully. As long as the FHR and LHR do the right thing RPTs will - * disappear in time for SSM groups. - */ - pim_upstream_register_reevaluate (); - igmp_source_forward_reevaluate_all (); + /* 1. Setup register state for (S,G) entries if G has changed from SSM + * to + * ASM. + * 2. check existing (*,G) IGMP registrations to see if they are + * still ASM. if they are now SSM delete them. + * 3. Allow channel setup for IGMP (*,G) members if G is now ASM + * 4. I could tear down all (*,G), (S,G,rpt) states. But that is an + * unnecessary sladge hammer and may not be particularly useful as it is + * likely the SPT switchover has already happened for flows along such + * RPTs. + * As for the RPT states it seems that the best thing to do is let them + * age + * out gracefully. As long as the FHR and LHR do the right thing RPTs + * will + * disappear in time for SSM groups. + */ + pim_upstream_register_reevaluate(); + igmp_source_forward_reevaluate_all(); } -void -pim_ssm_prefix_list_update (struct prefix_list *plist) +void pim_ssm_prefix_list_update(struct prefix_list *plist) { - struct pim_ssm *ssm = pimg->ssm_info; + struct pim_ssm *ssm = pimg->ssm_info; - if (!ssm->plist_name || strcmp (ssm->plist_name, prefix_list_name (plist))) - { - /* not ours */ - return; - } + if (!ssm->plist_name + || strcmp(ssm->plist_name, prefix_list_name(plist))) { + /* not ours */ + return; + } - pim_ssm_range_reevaluate (); + pim_ssm_range_reevaluate(); } -static int -pim_is_grp_standard_ssm (struct prefix *group) +static int pim_is_grp_standard_ssm(struct prefix *group) { - static int first = 1; - static struct prefix group_ssm; + static int first = 1; + static struct prefix group_ssm; - if (first) - { - str2prefix (PIM_SSM_STANDARD_RANGE, &group_ssm); - first = 0; - } + if (first) { + str2prefix(PIM_SSM_STANDARD_RANGE, &group_ssm); + first = 0; + } - return prefix_match (&group_ssm, group); + return prefix_match(&group_ssm, group); } -int -pim_is_grp_ssm (struct in_addr group_addr) +int pim_is_grp_ssm(struct in_addr group_addr) { - struct pim_ssm *ssm; - struct prefix group; - struct prefix_list *plist; - - memset (&group, 0, sizeof (group)); - group.family = AF_INET; - group.u.prefix4 = group_addr; - group.prefixlen = 32; - - ssm = pimg->ssm_info; - if (!ssm->plist_name) - { - return pim_is_grp_standard_ssm (&group); - } - - plist = prefix_list_lookup (AFI_IP, ssm->plist_name); - if (!plist) - return 0; - - return (prefix_list_apply (plist, &group) == PREFIX_PERMIT); + struct pim_ssm *ssm; + struct prefix group; + struct prefix_list *plist; + + memset(&group, 0, sizeof(group)); + group.family = AF_INET; + group.u.prefix4 = group_addr; + group.prefixlen = 32; + + ssm = pimg->ssm_info; + if (!ssm->plist_name) { + return pim_is_grp_standard_ssm(&group); + } + + plist = prefix_list_lookup(AFI_IP, ssm->plist_name); + if (!plist) + return 0; + + return (prefix_list_apply(plist, &group) == PREFIX_PERMIT); } -int -pim_ssm_range_set (vrf_id_t vrf_id, const char *plist_name) +int pim_ssm_range_set(vrf_id_t vrf_id, const char *plist_name) { - struct pim_ssm *ssm; - int change = 0; - - if (vrf_id != VRF_DEFAULT) - return PIM_SSM_ERR_NO_VRF; - - ssm = pimg->ssm_info; - if (plist_name) - { - if (ssm->plist_name) - { - if (!strcmp (ssm->plist_name, plist_name)) - return PIM_SSM_ERR_DUP; - XFREE (MTYPE_PIM_FILTER_NAME, ssm->plist_name); - } - ssm->plist_name = XSTRDUP (MTYPE_PIM_FILTER_NAME, plist_name); - change = 1; - } - else - { - if (ssm->plist_name) - { - change = 1; - XFREE (MTYPE_PIM_FILTER_NAME, ssm->plist_name); - } - } - - if (change) - pim_ssm_range_reevaluate (); - - return PIM_SSM_ERR_NONE; + struct pim_ssm *ssm; + int change = 0; + + if (vrf_id != VRF_DEFAULT) + return PIM_SSM_ERR_NO_VRF; + + ssm = pimg->ssm_info; + if (plist_name) { + if (ssm->plist_name) { + if (!strcmp(ssm->plist_name, plist_name)) + return PIM_SSM_ERR_DUP; + XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name); + } + ssm->plist_name = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist_name); + change = 1; + } else { + if (ssm->plist_name) { + change = 1; + XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name); + } + } + + if (change) + pim_ssm_range_reevaluate(); + + return PIM_SSM_ERR_NONE; } -void * -pim_ssm_init (vrf_id_t vrf_id) +void *pim_ssm_init(vrf_id_t vrf_id) { - struct pim_ssm *ssm; + struct pim_ssm *ssm; - ssm = XCALLOC (MTYPE_PIM_SSM_INFO, sizeof (*ssm)); - ssm->vrf_id = vrf_id; + ssm = XCALLOC(MTYPE_PIM_SSM_INFO, sizeof(*ssm)); + ssm->vrf_id = vrf_id; - return ssm; + return ssm; } -void -pim_ssm_terminate (struct pim_ssm *ssm) +void pim_ssm_terminate(struct pim_ssm *ssm) { - if (ssm && ssm->plist_name) - XFREE (MTYPE_PIM_FILTER_NAME, ssm->plist_name); + if (ssm && ssm->plist_name) + XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name); } diff --git a/pimd/pim_ssm.h b/pimd/pim_ssm.h index fe337be8f..9e89d0c80 100644 --- a/pimd/pim_ssm.h +++ b/pimd/pim_ssm.h @@ -22,22 +22,20 @@ #define PIM_SSM_STANDARD_RANGE "232.0.0.0/8" /* SSM error codes */ -enum pim_ssm_err -{ - PIM_SSM_ERR_NONE = 0, - PIM_SSM_ERR_NO_VRF = -1, - PIM_SSM_ERR_DUP = -2, +enum pim_ssm_err { + PIM_SSM_ERR_NONE = 0, + PIM_SSM_ERR_NO_VRF = -1, + PIM_SSM_ERR_DUP = -2, }; -struct pim_ssm -{ - vrf_id_t vrf_id; - char *plist_name; /* prefix list of group ranges */ +struct pim_ssm { + vrf_id_t vrf_id; + char *plist_name; /* prefix list of group ranges */ }; -void pim_ssm_prefix_list_update (struct prefix_list *plist); -int pim_is_grp_ssm (struct in_addr group_addr); -int pim_ssm_range_set (vrf_id_t vrf_id, const char *plist_name); -void *pim_ssm_init (vrf_id_t vrf_id); -void pim_ssm_terminate (struct pim_ssm *ssm); +void pim_ssm_prefix_list_update(struct prefix_list *plist); +int pim_is_grp_ssm(struct in_addr group_addr); +int pim_ssm_range_set(vrf_id_t vrf_id, const char *plist_name); +void *pim_ssm_init(vrf_id_t vrf_id); +void pim_ssm_terminate(struct pim_ssm *ssm); #endif diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index dd92ff1b2..406183db8 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -30,402 +30,423 @@ #include "pim_time.h" #include "pim_sock.h" -static const char * const PIM_SSMPINGD_REPLY_GROUP = "232.43.211.234"; +static const char *const PIM_SSMPINGD_REPLY_GROUP = "232.43.211.234"; -enum { - PIM_SSMPINGD_REQUEST = 'Q', - PIM_SSMPINGD_REPLY = 'A' -}; +enum { PIM_SSMPINGD_REQUEST = 'Q', PIM_SSMPINGD_REPLY = 'A' }; static void ssmpingd_read_on(struct ssmpingd_sock *ss); void pim_ssmpingd_init() { - int result; + int result; - zassert(!qpim_ssmpingd_list); + zassert(!qpim_ssmpingd_list); - result = inet_pton(AF_INET, PIM_SSMPINGD_REPLY_GROUP, &qpim_ssmpingd_group_addr); - - zassert(result > 0); + result = inet_pton(AF_INET, PIM_SSMPINGD_REPLY_GROUP, + &qpim_ssmpingd_group_addr); + + zassert(result > 0); } void pim_ssmpingd_destroy() { - if (qpim_ssmpingd_list) { - list_free(qpim_ssmpingd_list); - qpim_ssmpingd_list = 0; - } + if (qpim_ssmpingd_list) { + list_free(qpim_ssmpingd_list); + qpim_ssmpingd_list = 0; + } } static struct ssmpingd_sock *ssmpingd_find(struct in_addr source_addr) { - struct listnode *node; - struct ssmpingd_sock *ss; + struct listnode *node; + struct ssmpingd_sock *ss; - if (!qpim_ssmpingd_list) - return 0; + if (!qpim_ssmpingd_list) + return 0; - for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) - if (source_addr.s_addr == ss->source_addr.s_addr) - return ss; + for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) + if (source_addr.s_addr == ss->source_addr.s_addr) + return ss; - return 0; + return 0; } static void ssmpingd_free(struct ssmpingd_sock *ss) { - XFREE(MTYPE_PIM_SSMPINGD, ss); + XFREE(MTYPE_PIM_SSMPINGD, ss); } static int ssmpingd_socket(struct in_addr addr, int port, int mttl) { - struct sockaddr_in sockaddr; - int fd; - - fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (fd < 0) { - zlog_err("%s: could not create socket: errno=%d: %s", - __PRETTY_FUNCTION__, errno, safe_strerror(errno)); - return -1; - } - - sockaddr.sin_family = AF_INET; - sockaddr.sin_addr = addr; - sockaddr.sin_port = htons(port); - - if (bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s: bind(fd=%d,addr=%s,port=%d,len=%zu) failure: errno=%d: %s", - __PRETTY_FUNCTION__, - fd, addr_str, port, sizeof(sockaddr), - errno, safe_strerror(errno)); - close(fd); - return -1; - } - - /* Needed to obtain destination address from recvmsg() */ - { + struct sockaddr_in sockaddr; + int fd; + + fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) { + zlog_err("%s: could not create socket: errno=%d: %s", + __PRETTY_FUNCTION__, errno, safe_strerror(errno)); + return -1; + } + + sockaddr.sin_family = AF_INET; + sockaddr.sin_addr = addr; + sockaddr.sin_port = htons(port); + + if (bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); + zlog_warn( + "%s: bind(fd=%d,addr=%s,port=%d,len=%zu) failure: errno=%d: %s", + __PRETTY_FUNCTION__, fd, addr_str, port, + sizeof(sockaddr), errno, safe_strerror(errno)); + close(fd); + return -1; + } + + /* Needed to obtain destination address from recvmsg() */ + { #if defined(HAVE_IP_PKTINFO) - /* Linux and Solaris IP_PKTINFO */ - int opt = 1; - if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) { - zlog_warn("%s: could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - } + /* Linux and Solaris IP_PKTINFO */ + int opt = 1; + if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) { + zlog_warn( + "%s: could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, + safe_strerror(errno)); + } #elif defined(HAVE_IP_RECVDSTADDR) - /* BSD IP_RECVDSTADDR */ - int opt = 1; - if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt))) { - zlog_warn("%s: could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - } + /* BSD IP_RECVDSTADDR */ + int opt = 1; + if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, + sizeof(opt))) { + zlog_warn( + "%s: could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, + safe_strerror(errno)); + } #else - zlog_err("%s %s: missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()", - __FILE__, __PRETTY_FUNCTION__); - close(fd); - return -1; + zlog_err( + "%s %s: missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()", + __FILE__, __PRETTY_FUNCTION__); + close(fd); + return -1; #endif - } - - { - int reuse = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (void *) &reuse, sizeof(reuse))) { - zlog_warn("%s: could not set Reuse Address Option on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } - } - - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, - (void *) &mttl, sizeof(mttl))) { - zlog_warn("%s: could not set multicast TTL=%d on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, mttl, fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } - - if (setsockopt_ipv4_multicast_loop (fd, 0)) { - zlog_warn("%s: could not disable Multicast Loopback Option on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_LOOP; - } - - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (void *) &addr, sizeof(addr))) { - zlog_warn("%s: could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } - - { - long flags; - - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) { - zlog_warn("%s: could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } - - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { - zlog_warn("%s: could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } - } - - return fd; + } + + { + int reuse = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, + sizeof(reuse))) { + zlog_warn( + "%s: could not set Reuse Address Option on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, + safe_strerror(errno)); + close(fd); + return -1; + } + } + + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&mttl, + sizeof(mttl))) { + zlog_warn( + "%s: could not set multicast TTL=%d on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, mttl, fd, errno, + safe_strerror(errno)); + close(fd); + return -1; + } + + if (setsockopt_ipv4_multicast_loop(fd, 0)) { + zlog_warn( + "%s: could not disable Multicast Loopback Option on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_LOOP; + } + + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (void *)&addr, + sizeof(addr))) { + zlog_warn( + "%s: could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); + close(fd); + return -1; + } + + { + long flags; + + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) { + zlog_warn( + "%s: could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, + safe_strerror(errno)); + close(fd); + return -1; + } + + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { + zlog_warn( + "%s: could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, + safe_strerror(errno)); + close(fd); + return -1; + } + } + + return fd; } static void ssmpingd_delete(struct ssmpingd_sock *ss) { - zassert(ss); - zassert(qpim_ssmpingd_list); - - THREAD_OFF(ss->t_sock_read); - - if (close(ss->sock_fd)) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: failure closing ssmpingd sock_fd=%d for source %s: errno=%d: %s", - __PRETTY_FUNCTION__, - ss->sock_fd, source_str, errno, safe_strerror(errno)); - /* warning only */ - } - - listnode_delete(qpim_ssmpingd_list, ss); - ssmpingd_free(ss); + zassert(ss); + zassert(qpim_ssmpingd_list); + + THREAD_OFF(ss->t_sock_read); + + if (close(ss->sock_fd)) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", ss->source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: failure closing ssmpingd sock_fd=%d for source %s: errno=%d: %s", + __PRETTY_FUNCTION__, ss->sock_fd, source_str, errno, + safe_strerror(errno)); + /* warning only */ + } + + listnode_delete(qpim_ssmpingd_list, ss); + ssmpingd_free(ss); } -static void ssmpingd_sendto(struct ssmpingd_sock *ss, - const uint8_t *buf, - int len, - struct sockaddr_in to) +static void ssmpingd_sendto(struct ssmpingd_sock *ss, const uint8_t *buf, + int len, struct sockaddr_in to) { - socklen_t tolen = sizeof(to); - int sent; - - sent = sendto(ss->sock_fd, buf, len, MSG_DONTWAIT, - (struct sockaddr *)&to, tolen); - if (sent != len) { - char to_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<to?>", to.sin_addr, to_str, sizeof(to_str)); - if (sent < 0) { - zlog_warn("%s: sendto() failure to %s,%d: fd=%d len=%d: errno=%d: %s", - __PRETTY_FUNCTION__, - to_str, ntohs(to.sin_port), ss->sock_fd, len, - errno, safe_strerror(errno)); - } - else { - zlog_warn("%s: sendto() partial to %s,%d: fd=%d len=%d: sent=%d", - __PRETTY_FUNCTION__, - to_str, ntohs(to.sin_port), ss->sock_fd, - len, sent); - } - } + socklen_t tolen = sizeof(to); + int sent; + + sent = sendto(ss->sock_fd, buf, len, MSG_DONTWAIT, + (struct sockaddr *)&to, tolen); + if (sent != len) { + char to_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<to?>", to.sin_addr, to_str, sizeof(to_str)); + if (sent < 0) { + zlog_warn( + "%s: sendto() failure to %s,%d: fd=%d len=%d: errno=%d: %s", + __PRETTY_FUNCTION__, to_str, ntohs(to.sin_port), + ss->sock_fd, len, errno, safe_strerror(errno)); + } else { + zlog_warn( + "%s: sendto() partial to %s,%d: fd=%d len=%d: sent=%d", + __PRETTY_FUNCTION__, to_str, ntohs(to.sin_port), + ss->sock_fd, len, sent); + } + } } static int ssmpingd_read_msg(struct ssmpingd_sock *ss) { - struct interface *ifp; - struct sockaddr_in from; - struct sockaddr_in to; - socklen_t fromlen = sizeof(from); - socklen_t tolen = sizeof(to); - ifindex_t ifindex = -1; - uint8_t buf[1000]; - int len; - - ++ss->requests; - - len = pim_socket_recvfromto(ss->sock_fd, buf, sizeof(buf), - &from, &fromlen, - &to, &tolen, - &ifindex); - if (len < 0) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: failure receiving ssmping for source %s on fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, source_str, ss->sock_fd, errno, safe_strerror(errno)); - return -1; - } - - ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); - - if (buf[0] != PIM_SSMPINGD_REQUEST) { - char source_str[INET_ADDRSTRLEN]; - char from_str[INET_ADDRSTRLEN]; - char to_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("<from?>", from.sin_addr, from_str, sizeof(from_str)); - pim_inet4_dump("<to?>", to.sin_addr, to_str, sizeof(to_str)); - zlog_warn("%s: bad ssmping type=%d from %s,%d to %s,%d on interface %s ifindex=%d fd=%d src=%s", - __PRETTY_FUNCTION__, - buf[0], - from_str, ntohs(from.sin_port), - to_str, ntohs(to.sin_port), - ifp ? ifp->name : "<iface?>", - ifindex, ss->sock_fd, - source_str); - return 0; - } - - if (PIM_DEBUG_SSMPINGD) { - char source_str[INET_ADDRSTRLEN]; - char from_str[INET_ADDRSTRLEN]; - char to_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("<from?>", from.sin_addr, from_str, sizeof(from_str)); - pim_inet4_dump("<to?>", to.sin_addr, to_str, sizeof(to_str)); - zlog_debug("%s: recv ssmping from %s,%d to %s,%d on interface %s ifindex=%d fd=%d src=%s", - __PRETTY_FUNCTION__, - from_str, ntohs(from.sin_port), - to_str, ntohs(to.sin_port), - ifp ? ifp->name : "<iface?>", - ifindex, ss->sock_fd, - source_str); - } - - buf[0] = PIM_SSMPINGD_REPLY; - - /* unicast reply */ - ssmpingd_sendto(ss, buf, len, from); - - /* multicast reply */ - from.sin_addr = qpim_ssmpingd_group_addr; - ssmpingd_sendto(ss, buf, len, from); - - return 0; + struct interface *ifp; + struct sockaddr_in from; + struct sockaddr_in to; + socklen_t fromlen = sizeof(from); + socklen_t tolen = sizeof(to); + ifindex_t ifindex = -1; + uint8_t buf[1000]; + int len; + + ++ss->requests; + + len = pim_socket_recvfromto(ss->sock_fd, buf, sizeof(buf), &from, + &fromlen, &to, &tolen, &ifindex); + if (len < 0) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", ss->source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: failure receiving ssmping for source %s on fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, source_str, ss->sock_fd, errno, + safe_strerror(errno)); + return -1; + } + + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + + if (buf[0] != PIM_SSMPINGD_REQUEST) { + char source_str[INET_ADDRSTRLEN]; + char from_str[INET_ADDRSTRLEN]; + char to_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", ss->source_addr, source_str, + sizeof(source_str)); + pim_inet4_dump("<from?>", from.sin_addr, from_str, + sizeof(from_str)); + pim_inet4_dump("<to?>", to.sin_addr, to_str, sizeof(to_str)); + zlog_warn( + "%s: bad ssmping type=%d from %s,%d to %s,%d on interface %s ifindex=%d fd=%d src=%s", + __PRETTY_FUNCTION__, buf[0], from_str, + ntohs(from.sin_port), to_str, ntohs(to.sin_port), + ifp ? ifp->name : "<iface?>", ifindex, ss->sock_fd, + source_str); + return 0; + } + + if (PIM_DEBUG_SSMPINGD) { + char source_str[INET_ADDRSTRLEN]; + char from_str[INET_ADDRSTRLEN]; + char to_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", ss->source_addr, source_str, + sizeof(source_str)); + pim_inet4_dump("<from?>", from.sin_addr, from_str, + sizeof(from_str)); + pim_inet4_dump("<to?>", to.sin_addr, to_str, sizeof(to_str)); + zlog_debug( + "%s: recv ssmping from %s,%d to %s,%d on interface %s ifindex=%d fd=%d src=%s", + __PRETTY_FUNCTION__, from_str, ntohs(from.sin_port), + to_str, ntohs(to.sin_port), + ifp ? ifp->name : "<iface?>", ifindex, ss->sock_fd, + source_str); + } + + buf[0] = PIM_SSMPINGD_REPLY; + + /* unicast reply */ + ssmpingd_sendto(ss, buf, len, from); + + /* multicast reply */ + from.sin_addr = qpim_ssmpingd_group_addr; + ssmpingd_sendto(ss, buf, len, from); + + return 0; } static int ssmpingd_sock_read(struct thread *t) { - struct ssmpingd_sock *ss; - int result; + struct ssmpingd_sock *ss; + int result; - ss = THREAD_ARG(t); + ss = THREAD_ARG(t); - result = ssmpingd_read_msg(ss); + result = ssmpingd_read_msg(ss); - /* Keep reading */ - ssmpingd_read_on(ss); + /* Keep reading */ + ssmpingd_read_on(ss); - return result; + return result; } static void ssmpingd_read_on(struct ssmpingd_sock *ss) { - thread_add_read(master, ssmpingd_sock_read, ss, ss->sock_fd, - &ss->t_sock_read); + thread_add_read(master, ssmpingd_sock_read, ss, ss->sock_fd, + &ss->t_sock_read); } static struct ssmpingd_sock *ssmpingd_new(struct in_addr source_addr) { - struct ssmpingd_sock *ss; - int sock_fd; - - if (!qpim_ssmpingd_list) { - qpim_ssmpingd_list = list_new(); - if (!qpim_ssmpingd_list) { - zlog_err("%s %s: failure: qpim_ssmpingd_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return 0; - } - qpim_ssmpingd_list->del = (void (*)(void *)) ssmpingd_free; - } - - sock_fd = ssmpingd_socket(source_addr, /* port: */ 4321, /* mTTL: */ 64); - if (sock_fd < 0) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: ssmpingd_socket() failure for source %s", - __PRETTY_FUNCTION__, source_str); - return 0; - } - - ss = XCALLOC(MTYPE_PIM_SSMPINGD, sizeof(*ss)); - if (!ss) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_err("%s: XCALLOC(%zu) failure for ssmpingd source %s", - __PRETTY_FUNCTION__, - sizeof(*ss), source_str); - close(sock_fd); - return 0; - } - - ss->sock_fd = sock_fd; - ss->t_sock_read = NULL; - ss->source_addr = source_addr; - ss->creation = pim_time_monotonic_sec(); - ss->requests = 0; - - listnode_add(qpim_ssmpingd_list, ss); - - ssmpingd_read_on(ss); - - return ss; + struct ssmpingd_sock *ss; + int sock_fd; + + if (!qpim_ssmpingd_list) { + qpim_ssmpingd_list = list_new(); + if (!qpim_ssmpingd_list) { + zlog_err( + "%s %s: failure: qpim_ssmpingd_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return 0; + } + qpim_ssmpingd_list->del = (void (*)(void *))ssmpingd_free; + } + + sock_fd = + ssmpingd_socket(source_addr, /* port: */ 4321, /* mTTL: */ 64); + if (sock_fd < 0) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_warn("%s: ssmpingd_socket() failure for source %s", + __PRETTY_FUNCTION__, source_str); + return 0; + } + + ss = XCALLOC(MTYPE_PIM_SSMPINGD, sizeof(*ss)); + if (!ss) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_err("%s: XCALLOC(%zu) failure for ssmpingd source %s", + __PRETTY_FUNCTION__, sizeof(*ss), source_str); + close(sock_fd); + return 0; + } + + ss->sock_fd = sock_fd; + ss->t_sock_read = NULL; + ss->source_addr = source_addr; + ss->creation = pim_time_monotonic_sec(); + ss->requests = 0; + + listnode_add(qpim_ssmpingd_list, ss); + + ssmpingd_read_on(ss); + + return ss; } int pim_ssmpingd_start(struct in_addr source_addr) { - struct ssmpingd_sock *ss; - - ss = ssmpingd_find(source_addr); - if (ss) { - /* silently ignore request to recreate entry */ - return 0; - } - - { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_info("%s: starting ssmpingd for source %s", - __PRETTY_FUNCTION__, source_str); - } - - ss = ssmpingd_new(source_addr); - if (!ss) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: ssmpingd_new() failure for source %s", - __PRETTY_FUNCTION__, source_str); - return -1; - } - - return 0; + struct ssmpingd_sock *ss; + + ss = ssmpingd_find(source_addr); + if (ss) { + /* silently ignore request to recreate entry */ + return 0; + } + + { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_info("%s: starting ssmpingd for source %s", + __PRETTY_FUNCTION__, source_str); + } + + ss = ssmpingd_new(source_addr); + if (!ss) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_warn("%s: ssmpingd_new() failure for source %s", + __PRETTY_FUNCTION__, source_str); + return -1; + } + + return 0; } int pim_ssmpingd_stop(struct in_addr source_addr) { - struct ssmpingd_sock *ss; - - ss = ssmpingd_find(source_addr); - if (!ss) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: could not find ssmpingd for source %s", - __PRETTY_FUNCTION__, source_str); - return -1; - } - - { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_info("%s: stopping ssmpingd for source %s", - __PRETTY_FUNCTION__, source_str); - } - - ssmpingd_delete(ss); - - return 0; + struct ssmpingd_sock *ss; + + ss = ssmpingd_find(source_addr); + if (!ss) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_warn("%s: could not find ssmpingd for source %s", + __PRETTY_FUNCTION__, source_str); + return -1; + } + + { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_info("%s: stopping ssmpingd for source %s", + __PRETTY_FUNCTION__, source_str); + } + + ssmpingd_delete(ss); + + return 0; } diff --git a/pimd/pim_ssmpingd.h b/pimd/pim_ssmpingd.h index 02aa6271c..89fb320a7 100644 --- a/pimd/pim_ssmpingd.h +++ b/pimd/pim_ssmpingd.h @@ -27,11 +27,11 @@ #include "pim_iface.h" struct ssmpingd_sock { - int sock_fd; /* socket */ - struct thread *t_sock_read; /* thread for reading socket */ - struct in_addr source_addr; /* source address */ - int64_t creation; /* timestamp of socket creation */ - int64_t requests; /* counter */ + int sock_fd; /* socket */ + struct thread *t_sock_read; /* thread for reading socket */ + struct in_addr source_addr; /* source address */ + int64_t creation; /* timestamp of socket creation */ + int64_t requests; /* counter */ }; void pim_ssmpingd_init(void); diff --git a/pimd/pim_static.c b/pimd/pim_static.c index d373581fe..7c9aca47a 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -34,317 +34,337 @@ void pim_static_route_free(struct static_route *s_route) { - XFREE(MTYPE_PIM_STATIC_ROUTE, s_route); + XFREE(MTYPE_PIM_STATIC_ROUTE, s_route); } -static struct static_route * static_route_alloc() +static struct static_route *static_route_alloc() { - struct static_route *s_route; - - s_route = XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(*s_route)); - if (!s_route) { - zlog_err("PIM XCALLOC(%zu) failure", sizeof(*s_route)); - return 0; - } - return s_route; + struct static_route *s_route; + + s_route = XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(*s_route)); + if (!s_route) { + zlog_err("PIM XCALLOC(%zu) failure", sizeof(*s_route)); + return 0; + } + return s_route; } -static struct static_route *static_route_new(unsigned int iif, - unsigned int oif, - struct in_addr group, - struct in_addr source) +static struct static_route *static_route_new(unsigned int iif, unsigned int oif, + struct in_addr group, + struct in_addr source) { - struct static_route * s_route; - s_route = static_route_alloc(); - if (!s_route) { - return 0; - } - - s_route->group = group; - s_route->source = source; - s_route->iif = iif; - s_route->oif_ttls[oif] = 1; - s_route->c_oil.oil_ref_count = 1; - s_route->c_oil.oil.mfcc_origin = source; - s_route->c_oil.oil.mfcc_mcastgrp = group; - s_route->c_oil.oil.mfcc_parent = iif; - s_route->c_oil.oil.mfcc_ttls[oif] = 1; - s_route->c_oil.oif_creation[oif] = pim_time_monotonic_sec(); - - return s_route; + struct static_route *s_route; + s_route = static_route_alloc(); + if (!s_route) { + return 0; + } + + s_route->group = group; + s_route->source = source; + s_route->iif = iif; + s_route->oif_ttls[oif] = 1; + s_route->c_oil.oil_ref_count = 1; + s_route->c_oil.oil.mfcc_origin = source; + s_route->c_oil.oil.mfcc_mcastgrp = group; + s_route->c_oil.oil.mfcc_parent = iif; + s_route->c_oil.oil.mfcc_ttls[oif] = 1; + s_route->c_oil.oif_creation[oif] = pim_time_monotonic_sec(); + + return s_route; } -int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source) +int pim_static_add(struct interface *iif, struct interface *oif, + struct in_addr group, struct in_addr source) { - struct listnode *node = NULL; - struct static_route *s_route = NULL; - struct static_route *original_s_route = NULL; - struct pim_interface *pim_iif = iif ? iif->info : NULL; - struct pim_interface *pim_oif = oif ? oif->info : NULL; - ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; - ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; - - if (!iif_index || !oif_index) { - zlog_warn("%s %s: Unable to add static route: Invalid interface index(iif=%d,oif=%d)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index); - return -2; - } + struct listnode *node = NULL; + struct static_route *s_route = NULL; + struct static_route *original_s_route = NULL; + struct pim_interface *pim_iif = iif ? iif->info : NULL; + struct pim_interface *pim_oif = oif ? oif->info : NULL; + ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; + ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; + + if (!iif_index || !oif_index) { + zlog_warn( + "%s %s: Unable to add static route: Invalid interface index(iif=%d,oif=%d)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index); + return -2; + } #ifdef PIM_ENFORCE_LOOPFREE_MFC - if (iif_index == oif_index) { - /* looped MFC entry */ - zlog_warn("%s %s: Unable to add static route: Looped MFC entry(iif=%d,oif=%d)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index); - return -4; - } + if (iif_index == oif_index) { + /* looped MFC entry */ + zlog_warn( + "%s %s: Unable to add static route: Looped MFC entry(iif=%d,oif=%d)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index); + return -4; + } #endif - for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - if (s_route->group.s_addr == group.s_addr && - s_route->source.s_addr == source.s_addr) { - if (s_route->iif == iif_index && - s_route->oif_ttls[oif_index]) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_warn("%s %s: Unable to add static route: Route already exists (iif=%d,oif=%d,group=%s,source=%s)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - return -3; - } - - /* Ok, from here on out we will be making changes to the s_route structure, but if - * for some reason we fail to commit these changes to the kernel, we want to be able - * restore the state of the list. So copy the node data and if need be, we can copy - * back if it fails. - */ - original_s_route = static_route_alloc(); - if (!original_s_route) { - return -5; - } - memcpy(original_s_route, s_route, sizeof(struct static_route)); - - /* Route exists and has the same input interface, but adding a new output interface */ - if (s_route->iif == iif_index) { - s_route->oif_ttls[oif_index] = 1; - s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; - s_route->c_oil.oif_creation[oif_index] = pim_time_monotonic_sec(); - ++s_route->c_oil.oil_ref_count; - } else { - /* input interface changed */ - s_route->iif = iif_index; - s_route->c_oil.oil.mfcc_parent = iif_index; + for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { + if (s_route->group.s_addr == group.s_addr + && s_route->source.s_addr == source.s_addr) { + if (s_route->iif == iif_index + && s_route->oif_ttls[oif_index]) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("<ifaddr?>", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_warn( + "%s %s: Unable to add static route: Route already exists (iif=%d,oif=%d,group=%s,source=%s)", + __FILE__, __PRETTY_FUNCTION__, + iif_index, oif_index, gifaddr_str, + sifaddr_str); + return -3; + } + + /* Ok, from here on out we will be making changes to the + * s_route structure, but if + * for some reason we fail to commit these changes to + * the kernel, we want to be able + * restore the state of the list. So copy the node data + * and if need be, we can copy + * back if it fails. + */ + original_s_route = static_route_alloc(); + if (!original_s_route) { + return -5; + } + memcpy(original_s_route, s_route, + sizeof(struct static_route)); + + /* Route exists and has the same input interface, but + * adding a new output interface */ + if (s_route->iif == iif_index) { + s_route->oif_ttls[oif_index] = 1; + s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; + s_route->c_oil.oif_creation[oif_index] = + pim_time_monotonic_sec(); + ++s_route->c_oil.oil_ref_count; + } else { + /* input interface changed */ + s_route->iif = iif_index; + s_route->c_oil.oil.mfcc_parent = iif_index; #ifdef PIM_ENFORCE_LOOPFREE_MFC - /* check to make sure the new input was not an old output */ - if (s_route->oif_ttls[iif_index]) { - s_route->oif_ttls[iif_index] = 0; - s_route->c_oil.oif_creation[iif_index] = 0; - s_route->c_oil.oil.mfcc_ttls[iif_index] = 0; - --s_route->c_oil.oil_ref_count; - } + /* check to make sure the new input was not an + * old output */ + if (s_route->oif_ttls[iif_index]) { + s_route->oif_ttls[iif_index] = 0; + s_route->c_oil.oif_creation[iif_index] = + 0; + s_route->c_oil.oil + .mfcc_ttls[iif_index] = 0; + --s_route->c_oil.oil_ref_count; + } #endif - /* now add the new output, if it is new */ - if (!s_route->oif_ttls[oif_index]) { - s_route->oif_ttls[oif_index] = 1; - s_route->c_oil.oif_creation[oif_index] = pim_time_monotonic_sec(); - s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; - ++s_route->c_oil.oil_ref_count; - } - } - - break; - } - } - - /* If node is null then we reached the end of the list without finding a match */ - if (!node) { - s_route = static_route_new(iif_index, oif_index, group, source); - listnode_add(qpim_static_route_list, s_route); - } - - if (pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) - { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_warn("%s %s: Unable to add static route(iif=%d,oif=%d,group=%s,source=%s)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - - /* Need to put s_route back to the way it was */ - if (original_s_route) { - memcpy(s_route, original_s_route, sizeof(struct static_route)); - } else { - /* we never stored off a copy, so it must have been a fresh new route */ - listnode_delete(qpim_static_route_list, s_route); - pim_static_route_free(s_route); - } - - if (original_s_route) { - pim_static_route_free(original_s_route); - } - - return -1; - } - - /* Make sure we free the memory for the route copy if used */ - if (original_s_route) { - pim_static_route_free(original_s_route); - } - - if (PIM_DEBUG_STATIC) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_debug("%s: Static route added(iif=%d,oif=%d,group=%s,source=%s)", - __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - } - - return 0; + /* now add the new output, if it is new */ + if (!s_route->oif_ttls[oif_index]) { + s_route->oif_ttls[oif_index] = 1; + s_route->c_oil.oif_creation[oif_index] = + pim_time_monotonic_sec(); + s_route->c_oil.oil + .mfcc_ttls[oif_index] = 1; + ++s_route->c_oil.oil_ref_count; + } + } + + break; + } + } + + /* If node is null then we reached the end of the list without finding a + * match */ + if (!node) { + s_route = static_route_new(iif_index, oif_index, group, source); + listnode_add(qpim_static_route_list, s_route); + } + + if (pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("<ifaddr?>", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_warn( + "%s %s: Unable to add static route(iif=%d,oif=%d,group=%s,source=%s)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index, + gifaddr_str, sifaddr_str); + + /* Need to put s_route back to the way it was */ + if (original_s_route) { + memcpy(s_route, original_s_route, + sizeof(struct static_route)); + } else { + /* we never stored off a copy, so it must have been a + * fresh new route */ + listnode_delete(qpim_static_route_list, s_route); + pim_static_route_free(s_route); + } + + if (original_s_route) { + pim_static_route_free(original_s_route); + } + + return -1; + } + + /* Make sure we free the memory for the route copy if used */ + if (original_s_route) { + pim_static_route_free(original_s_route); + } + + if (PIM_DEBUG_STATIC) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("<ifaddr?>", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_debug( + "%s: Static route added(iif=%d,oif=%d,group=%s,source=%s)", + __PRETTY_FUNCTION__, iif_index, oif_index, gifaddr_str, + sifaddr_str); + } + + return 0; } -int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source) +int pim_static_del(struct interface *iif, struct interface *oif, + struct in_addr group, struct in_addr source) { - struct listnode *node = NULL; - struct listnode *nextnode = NULL; - struct static_route *s_route = NULL; - struct pim_interface *pim_iif = iif ? iif->info : 0; - struct pim_interface *pim_oif = oif ? oif->info : 0; - ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; - ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; - - if (!iif_index || !oif_index) { - zlog_warn("%s %s: Unable to remove static route: Invalid interface index(iif=%d,oif=%d)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index); - return -2; - } - - for (ALL_LIST_ELEMENTS(qpim_static_route_list, node, nextnode, s_route)) { - if (s_route->iif == iif_index && - s_route->group.s_addr == group.s_addr && - s_route->source.s_addr == source.s_addr && - s_route->oif_ttls[oif_index]) { - s_route->oif_ttls[oif_index] = 0; - s_route->c_oil.oil.mfcc_ttls[oif_index] = 0; - --s_route->c_oil.oil_ref_count; - - /* If there are no more outputs then delete the whole route, otherwise set the route with the new outputs */ - if (s_route->c_oil.oil_ref_count <= 0 ? - pim_mroute_del(&s_route->c_oil, __PRETTY_FUNCTION__) : pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_warn("%s %s: Unable to remove static route(iif=%d,oif=%d,group=%s,source=%s)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - - s_route->oif_ttls[oif_index] = 1; - s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; - ++s_route->c_oil.oil_ref_count; - - return -1; - } - - s_route->c_oil.oif_creation[oif_index] = 0; - - if (s_route->c_oil.oil_ref_count <= 0) { - listnode_delete(qpim_static_route_list, s_route); - pim_static_route_free(s_route); - } - - if (PIM_DEBUG_STATIC) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_debug("%s: Static route removed(iif=%d,oif=%d,group=%s,source=%s)", - __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - } - - break; - } - } - - if (!node) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_warn("%s %s: Unable to remove static route: Route does not exist(iif=%d,oif=%d,group=%s,source=%s)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - return -3; - } - - return 0; + struct listnode *node = NULL; + struct listnode *nextnode = NULL; + struct static_route *s_route = NULL; + struct pim_interface *pim_iif = iif ? iif->info : 0; + struct pim_interface *pim_oif = oif ? oif->info : 0; + ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; + ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; + + if (!iif_index || !oif_index) { + zlog_warn( + "%s %s: Unable to remove static route: Invalid interface index(iif=%d,oif=%d)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index); + return -2; + } + + for (ALL_LIST_ELEMENTS(qpim_static_route_list, node, nextnode, + s_route)) { + if (s_route->iif == iif_index + && s_route->group.s_addr == group.s_addr + && s_route->source.s_addr == source.s_addr + && s_route->oif_ttls[oif_index]) { + s_route->oif_ttls[oif_index] = 0; + s_route->c_oil.oil.mfcc_ttls[oif_index] = 0; + --s_route->c_oil.oil_ref_count; + + /* If there are no more outputs then delete the whole + * route, otherwise set the route with the new outputs + */ + if (s_route->c_oil.oil_ref_count <= 0 + ? pim_mroute_del(&s_route->c_oil, + __PRETTY_FUNCTION__) + : pim_mroute_add(&s_route->c_oil, + __PRETTY_FUNCTION__)) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("<ifaddr?>", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_warn( + "%s %s: Unable to remove static route(iif=%d,oif=%d,group=%s,source=%s)", + __FILE__, __PRETTY_FUNCTION__, + iif_index, oif_index, gifaddr_str, + sifaddr_str); + + s_route->oif_ttls[oif_index] = 1; + s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; + ++s_route->c_oil.oil_ref_count; + + return -1; + } + + s_route->c_oil.oif_creation[oif_index] = 0; + + if (s_route->c_oil.oil_ref_count <= 0) { + listnode_delete(qpim_static_route_list, + s_route); + pim_static_route_free(s_route); + } + + if (PIM_DEBUG_STATIC) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("<ifaddr?>", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_debug( + "%s: Static route removed(iif=%d,oif=%d,group=%s,source=%s)", + __PRETTY_FUNCTION__, iif_index, + oif_index, gifaddr_str, sifaddr_str); + } + + break; + } + } + + if (!node) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("<ifaddr?>", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_warn( + "%s %s: Unable to remove static route: Route does not exist(iif=%d,oif=%d,group=%s,source=%s)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index, + gifaddr_str, sifaddr_str); + return -3; + } + + return 0; } -int -pim_static_write_mroute (struct vty *vty, struct interface *ifp) +int pim_static_write_mroute(struct vty *vty, struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *node; - struct static_route *sroute; - int count = 0; - char sbuf[INET_ADDRSTRLEN]; - char gbuf[INET_ADDRSTRLEN]; - - if (!pim_ifp) - return 0; - - for (ALL_LIST_ELEMENTS_RO (qpim_static_route_list, node, sroute)) - { - pim_inet4_dump ("<ifaddr?>", sroute->group, gbuf, sizeof (gbuf)); - pim_inet4_dump ("<ifaddr?>", sroute->source, sbuf, sizeof (sbuf)); - if (sroute->iif == pim_ifp->mroute_vif_index) - { - int i; - for (i = 0; i < MAXVIFS; i++) - if (sroute->oif_ttls[i]) - { - struct interface *oifp = pim_if_find_by_vif_index (i); - if (sroute->source.s_addr == 0) - vty_out (vty, " ip mroute %s %s\n", oifp->name, gbuf); - else - vty_out (vty, " ip mroute %s %s %s\n", oifp->name, gbuf, - sbuf); - count ++; - } - } - } - - return count; + struct pim_interface *pim_ifp = ifp->info; + struct listnode *node; + struct static_route *sroute; + int count = 0; + char sbuf[INET_ADDRSTRLEN]; + char gbuf[INET_ADDRSTRLEN]; + + if (!pim_ifp) + return 0; + + for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, sroute)) { + pim_inet4_dump("<ifaddr?>", sroute->group, gbuf, sizeof(gbuf)); + pim_inet4_dump("<ifaddr?>", sroute->source, sbuf, sizeof(sbuf)); + if (sroute->iif == pim_ifp->mroute_vif_index) { + int i; + for (i = 0; i < MAXVIFS; i++) + if (sroute->oif_ttls[i]) { + struct interface *oifp = + pim_if_find_by_vif_index(i); + if (sroute->source.s_addr == 0) + vty_out(vty, + " ip mroute %s %s\n", + oifp->name, gbuf); + else + vty_out(vty, + " ip mroute %s %s %s\n", + oifp->name, gbuf, sbuf); + count++; + } + } + } + + return count; } diff --git a/pimd/pim_static.h b/pimd/pim_static.h index 4b5ef7921..1114f4b67 100644 --- a/pimd/pim_static.h +++ b/pimd/pim_static.h @@ -25,19 +25,21 @@ #include "if.h" struct static_route { - /* Each static route is unique by these pair of addresses */ - struct in_addr group; - struct in_addr source; + /* Each static route is unique by these pair of addresses */ + struct in_addr group; + struct in_addr source; - struct channel_oil c_oil; - ifindex_t iif; - unsigned char oif_ttls[MAXVIFS]; + struct channel_oil c_oil; + ifindex_t iif; + unsigned char oif_ttls[MAXVIFS]; }; void pim_static_route_free(struct static_route *s_route); -int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source); -int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source); -int pim_static_write_mroute (struct vty *vty, struct interface *ifp); +int pim_static_add(struct interface *iif, struct interface *oif, + struct in_addr group, struct in_addr source); +int pim_static_del(struct interface *iif, struct interface *oif, + struct in_addr group, struct in_addr source); +int pim_static_write_mroute(struct vty *vty, struct interface *ifp); #endif /* PIM_STATIC_H_ */ diff --git a/pimd/pim_str.c b/pimd/pim_str.c index d1219a868..fa1a6e624 100644 --- a/pimd/pim_str.c +++ b/pimd/pim_str.c @@ -27,62 +27,62 @@ #include "pim_str.h" -void pim_addr_dump (const char *onfail, struct prefix *p, char *buf, int buf_size) +void pim_addr_dump(const char *onfail, struct prefix *p, char *buf, + int buf_size) { - int save_errno = errno; + int save_errno = errno; - if (!inet_ntop(p->family, &p->u.prefix, buf, buf_size)) { - zlog_warn("pim_addr_dump: inet_ntop(buf_size=%d): errno=%d: %s", - buf_size, errno, safe_strerror(errno)); - if (onfail) - snprintf(buf, buf_size, "%s", onfail); - } + if (!inet_ntop(p->family, &p->u.prefix, buf, buf_size)) { + zlog_warn("pim_addr_dump: inet_ntop(buf_size=%d): errno=%d: %s", + buf_size, errno, safe_strerror(errno)); + if (onfail) + snprintf(buf, buf_size, "%s", onfail); + } - errno = save_errno; + errno = save_errno; } -void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_size) +void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, + int buf_size) { - int save_errno = errno; - - if (addr.s_addr == INADDR_ANY) - strcpy(buf, "*"); - else - { - if (!inet_ntop(AF_INET, &addr, buf, buf_size)) { - zlog_warn("pim_inet4_dump: inet_ntop(AF_INET,buf_size=%d): errno=%d: %s", - buf_size, errno, safe_strerror(errno)); - if (onfail) - snprintf(buf, buf_size, "%s", onfail); - } - } - - errno = save_errno; + int save_errno = errno; + + if (addr.s_addr == INADDR_ANY) + strcpy(buf, "*"); + else { + if (!inet_ntop(AF_INET, &addr, buf, buf_size)) { + zlog_warn( + "pim_inet4_dump: inet_ntop(AF_INET,buf_size=%d): errno=%d: %s", + buf_size, errno, safe_strerror(errno)); + if (onfail) + snprintf(buf, buf_size, "%s", onfail); + } + } + + errno = save_errno; } -char * -pim_str_sg_dump (const struct prefix_sg *sg) +char *pim_str_sg_dump(const struct prefix_sg *sg) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - static char sg_str[PIM_SG_LEN]; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + static char sg_str[PIM_SG_LEN]; - pim_inet4_dump ("<src?>", sg->src, src_str, sizeof(src_str)); - pim_inet4_dump ("<grp?>", sg->grp, grp_str, sizeof(grp_str)); - snprintf (sg_str, PIM_SG_LEN, "(%s,%s)", src_str, grp_str); + pim_inet4_dump("<src?>", sg->src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", sg->grp, grp_str, sizeof(grp_str)); + snprintf(sg_str, PIM_SG_LEN, "(%s,%s)", src_str, grp_str); - return sg_str; + return sg_str; } -char * -pim_str_sg_set (const struct prefix_sg *sg, char *sg_str) +char *pim_str_sg_set(const struct prefix_sg *sg, char *sg_str) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("<src?>", sg->src, src_str, sizeof(src_str)); - pim_inet4_dump ("<grp?>", sg->grp, grp_str, sizeof(grp_str)); - snprintf (sg_str, PIM_SG_LEN, "(%s,%s)", src_str, grp_str); + pim_inet4_dump("<src?>", sg->src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", sg->grp, grp_str, sizeof(grp_str)); + snprintf(sg_str, PIM_SG_LEN, "(%s,%s)", src_str, grp_str); - return sg_str; + return sg_str; } diff --git a/pimd/pim_str.h b/pimd/pim_str.h index 0ca517102..12a33a810 100644 --- a/pimd/pim_str.h +++ b/pimd/pim_str.h @@ -35,9 +35,11 @@ */ #define PIM_SG_LEN 36 -void pim_addr_dump (const char *onfail, struct prefix *p, char *buf, int buf_size); -void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_size); -char *pim_str_sg_dump (const struct prefix_sg *sg); -char *pim_str_sg_set (const struct prefix_sg *sg, char *sg_str); +void pim_addr_dump(const char *onfail, struct prefix *p, char *buf, + int buf_size); +void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, + int buf_size); +char *pim_str_sg_dump(const struct prefix_sg *sg); +char *pim_str_sg_set(const struct prefix_sg *sg, char *sg_str); #endif diff --git a/pimd/pim_time.c b/pimd/pim_time.c index 406fec58d..6f011da43 100644 --- a/pimd/pim_time.c +++ b/pimd/pim_time.c @@ -30,16 +30,15 @@ static int gettime_monotonic(struct timeval *tv) { - int result; + int result; - result = gettimeofday(tv, 0); - if (result) { - zlog_err("%s: gettimeofday() failure: errno=%d: %s", - __PRETTY_FUNCTION__, - errno, safe_strerror(errno)); - } + result = gettimeofday(tv, 0); + if (result) { + zlog_err("%s: gettimeofday() failure: errno=%d: %s", + __PRETTY_FUNCTION__, errno, safe_strerror(errno)); + } - return result; + return result; } /* @@ -48,16 +47,15 @@ static int gettime_monotonic(struct timeval *tv) */ int64_t pim_time_monotonic_sec() { - struct timeval now_tv; + struct timeval now_tv; - if (gettime_monotonic(&now_tv)) { - zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", - __PRETTY_FUNCTION__, - errno, safe_strerror(errno)); - return -1; - } + if (gettime_monotonic(&now_tv)) { + zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", + __PRETTY_FUNCTION__, errno, safe_strerror(errno)); + return -1; + } - return now_tv.tv_sec; + return now_tv.tv_sec; } /* @@ -66,117 +64,111 @@ int64_t pim_time_monotonic_sec() */ int64_t pim_time_monotonic_dsec() { - struct timeval now_tv; - int64_t now_dsec; + struct timeval now_tv; + int64_t now_dsec; - if (gettime_monotonic(&now_tv)) { - zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", - __PRETTY_FUNCTION__, - errno, safe_strerror(errno)); - return -1; - } + if (gettime_monotonic(&now_tv)) { + zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", + __PRETTY_FUNCTION__, errno, safe_strerror(errno)); + return -1; + } - now_dsec = ((int64_t) now_tv.tv_sec) * 10 + ((int64_t) now_tv.tv_usec) / 100000; + now_dsec = ((int64_t)now_tv.tv_sec) * 10 + + ((int64_t)now_tv.tv_usec) / 100000; - return now_dsec; + return now_dsec; } -int64_t -pim_time_monotonic_usec (void) +int64_t pim_time_monotonic_usec(void) { - struct timeval now_tv; - int64_t now_dsec; + struct timeval now_tv; + int64_t now_dsec; - if (gettime_monotonic(&now_tv)) { - zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", - __PRETTY_FUNCTION__, - errno, safe_strerror(errno)); - return -1; - } + if (gettime_monotonic(&now_tv)) { + zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", + __PRETTY_FUNCTION__, errno, safe_strerror(errno)); + return -1; + } - now_dsec = ((int64_t) now_tv.tv_sec) * 1000000 + ((int64_t) now_tv.tv_usec); - - return now_dsec; + now_dsec = + ((int64_t)now_tv.tv_sec) * 1000000 + ((int64_t)now_tv.tv_usec); + return now_dsec; } int pim_time_mmss(char *buf, int buf_size, long sec) { - long mm; - int wr; + long mm; + int wr; + + zassert(buf_size >= 5); - zassert(buf_size >= 5); + mm = sec / 60; + sec %= 60; - mm = sec / 60; - sec %= 60; - - wr = snprintf(buf, buf_size, "%02ld:%02ld", mm, sec); + wr = snprintf(buf, buf_size, "%02ld:%02ld", mm, sec); - return wr != 8; + return wr != 8; } static int pim_time_hhmmss(char *buf, int buf_size, long sec) { - long hh; - long mm; - int wr; + long hh; + long mm; + int wr; + + zassert(buf_size >= 8); - zassert(buf_size >= 8); + hh = sec / 3600; + sec %= 3600; + mm = sec / 60; + sec %= 60; - hh = sec / 3600; - sec %= 3600; - mm = sec / 60; - sec %= 60; - - wr = snprintf(buf, buf_size, "%02ld:%02ld:%02ld", hh, mm, sec); + wr = snprintf(buf, buf_size, "%02ld:%02ld:%02ld", hh, mm, sec); - return wr != 8; + return wr != 8; } void pim_time_timer_to_mmss(char *buf, int buf_size, struct thread *t_timer) { - if (t_timer) { - pim_time_mmss(buf, buf_size, - thread_timer_remain_second(t_timer)); - } - else { - snprintf(buf, buf_size, "--:--"); - } + if (t_timer) { + pim_time_mmss(buf, buf_size, + thread_timer_remain_second(t_timer)); + } else { + snprintf(buf, buf_size, "--:--"); + } } void pim_time_timer_to_hhmmss(char *buf, int buf_size, struct thread *t_timer) { - if (t_timer) { - pim_time_hhmmss(buf, buf_size, - thread_timer_remain_second(t_timer)); - } - else { - snprintf(buf, buf_size, "--:--:--"); - } + if (t_timer) { + pim_time_hhmmss(buf, buf_size, + thread_timer_remain_second(t_timer)); + } else { + snprintf(buf, buf_size, "--:--:--"); + } } void pim_time_uptime(char *buf, int buf_size, int64_t uptime_sec) { - zassert(buf_size >= 8); + zassert(buf_size >= 8); - pim_time_hhmmss(buf, buf_size, uptime_sec); + pim_time_hhmmss(buf, buf_size, uptime_sec); } void pim_time_uptime_begin(char *buf, int buf_size, int64_t now, int64_t begin) { - if (begin > 0) - pim_time_uptime(buf, buf_size, now - begin); - else - snprintf(buf, buf_size, "--:--:--"); + if (begin > 0) + pim_time_uptime(buf, buf_size, now - begin); + else + snprintf(buf, buf_size, "--:--:--"); } long pim_time_timer_remain_msec(struct thread *t_timer) { - /* FIXME: Actually fetch msec resolution from thread */ + /* FIXME: Actually fetch msec resolution from thread */ - /* no timer thread running means timer has expired: return 0 */ + /* no timer thread running means timer has expired: return 0 */ - return t_timer ? - 1000 * thread_timer_remain_second(t_timer) : - 0; + return t_timer ? 1000 * thread_timer_remain_second(t_timer) : 0; } diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index 550fdde8e..6d7adf242 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -29,67 +29,61 @@ #include "pim_str.h" #include "pim_msg.h" -uint8_t *pim_tlv_append_uint16(uint8_t *buf, - const uint8_t *buf_pastend, - uint16_t option_type, - uint16_t option_value) +uint8_t *pim_tlv_append_uint16(uint8_t *buf, const uint8_t *buf_pastend, + uint16_t option_type, uint16_t option_value) { - uint16_t option_len = 2; + uint16_t option_len = 2; - if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) - return NULL; + if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) + return NULL; - *(uint16_t *) buf = htons(option_type); - buf += 2; - *(uint16_t *) buf = htons(option_len); - buf += 2; - *(uint16_t *) buf = htons(option_value); - buf += option_len; + *(uint16_t *)buf = htons(option_type); + buf += 2; + *(uint16_t *)buf = htons(option_len); + buf += 2; + *(uint16_t *)buf = htons(option_value); + buf += option_len; - return buf; + return buf; } -uint8_t *pim_tlv_append_2uint16(uint8_t *buf, - const uint8_t *buf_pastend, - uint16_t option_type, - uint16_t option_value1, +uint8_t *pim_tlv_append_2uint16(uint8_t *buf, const uint8_t *buf_pastend, + uint16_t option_type, uint16_t option_value1, uint16_t option_value2) { - uint16_t option_len = 4; + uint16_t option_len = 4; - if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) - return NULL; + if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) + return NULL; - *(uint16_t *) buf = htons(option_type); - buf += 2; - *(uint16_t *) buf = htons(option_len); - buf += 2; - *(uint16_t *) buf = htons(option_value1); - buf += 2; - *(uint16_t *) buf = htons(option_value2); - buf += 2; + *(uint16_t *)buf = htons(option_type); + buf += 2; + *(uint16_t *)buf = htons(option_len); + buf += 2; + *(uint16_t *)buf = htons(option_value1); + buf += 2; + *(uint16_t *)buf = htons(option_value2); + buf += 2; - return buf; + return buf; } -uint8_t *pim_tlv_append_uint32(uint8_t *buf, - const uint8_t *buf_pastend, - uint16_t option_type, - uint32_t option_value) +uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend, + uint16_t option_type, uint32_t option_value) { - uint16_t option_len = 4; + uint16_t option_len = 4; - if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) - return NULL; + if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) + return NULL; - *(uint16_t *) buf = htons(option_type); - buf += 2; - *(uint16_t *) buf = htons(option_len); - buf += 2; - pim_write_uint32(buf, option_value); - buf += option_len; + *(uint16_t *)buf = htons(option_type); + buf += 2; + *(uint16_t *)buf = htons(option_len); + buf += 2; + pim_write_uint32(buf, option_value); + buf += option_len; - return buf; + return buf; } #define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr)) @@ -108,7 +102,8 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, * The PIM address family of the 'Unicast Address' field of this * address. * - * Values 0-127 are as assigned by the IANA for Internet Address * Families in [7]. Values 128-250 are reserved to be assigned by + * Values 0-127 are as assigned by the IANA for Internet Address * + * Families in [7]. Values 128-250 are reserved to be assigned by * the IANA for PIM-specific Address Families. Values 251 though * 255 are designated for private use. As there is no assignment * authority for this space, collisions should be expected. @@ -122,31 +117,33 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, * The unicast address as represented by the given Address Family * and Encoding Type. */ -int -pim_encode_addr_ucast (uint8_t *buf, struct prefix *p) +int pim_encode_addr_ucast(uint8_t *buf, struct prefix *p) { - switch (p->family) - { - case AF_INET: - *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ - ++buf; - *(uint8_t *)buf = 0; /* ucast IPv4 native encoding type (RFC 4601: 4.9.1) */ - ++buf; - memcpy (buf, &p->u.prefix4, sizeof (struct in_addr)); - return ucast_ipv4_encoding_len; - break; - case AF_INET6: - *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV6; - ++buf; - *(uint8_t *)buf = 0; - ++buf; - memcpy (buf, &p->u.prefix6, sizeof (struct in6_addr)); - return ucast_ipv6_encoding_len; - break; - default: - return 0; - break; - } + switch (p->family) { + case AF_INET: + *(uint8_t *)buf = + PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != + PIM_MSG_ADDRESS_FAMILY_IPV4 + */ + ++buf; + *(uint8_t *)buf = 0; /* ucast IPv4 native encoding type (RFC + 4601: 4.9.1) */ + ++buf; + memcpy(buf, &p->u.prefix4, sizeof(struct in_addr)); + return ucast_ipv4_encoding_len; + break; + case AF_INET6: + *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV6; + ++buf; + *(uint8_t *)buf = 0; + ++buf; + memcpy(buf, &p->u.prefix6, sizeof(struct in6_addr)); + return ucast_ipv6_encoding_len; + break; + default: + return 0; + break; + } } #define group_ipv4_encoding_len (4 + sizeof (struct in_addr)) @@ -194,614 +191,604 @@ pim_encode_addr_ucast (uint8_t *buf, struct prefix *p) * Group multicast Address * Contains the group address. */ -int -pim_encode_addr_group (uint8_t *buf, afi_t afi, int bidir, int scope, struct in_addr group) +int pim_encode_addr_group(uint8_t *buf, afi_t afi, int bidir, int scope, + struct in_addr group) { - uint8_t flags = 0; - - flags |= bidir << 8; - flags |= scope; - - switch (afi) - { - case AFI_IP: - *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4; - ++buf; - *(uint8_t *)buf = 0; - ++buf; - *(uint8_t *)buf = flags; - ++buf; - *(uint8_t *)buf = 32; - ++buf; - memcpy (buf, &group, sizeof (struct in_addr)); - return group_ipv4_encoding_len; - break; - default: - return 0; - break; - } + uint8_t flags = 0; + + flags |= bidir << 8; + flags |= scope; + + switch (afi) { + case AFI_IP: + *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4; + ++buf; + *(uint8_t *)buf = 0; + ++buf; + *(uint8_t *)buf = flags; + ++buf; + *(uint8_t *)buf = 32; + ++buf; + memcpy(buf, &group, sizeof(struct in_addr)); + return group_ipv4_encoding_len; + break; + default: + return 0; + break; + } } -uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, - const uint8_t *buf_pastend, - struct list *ifconnected, - int family) +uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, + struct list *ifconnected, int family) { - struct listnode *node; - uint16_t option_len = 0; - uint8_t *curr; - size_t uel; - - node = listhead(ifconnected); - - /* Empty address list ? */ - if (!node) { - return buf; - } - - if (family == AF_INET) - uel = ucast_ipv4_encoding_len; - else - uel = ucast_ipv6_encoding_len; - - /* Scan secondary address list */ - curr = buf + 4; /* skip T and L */ - for (; node; node = listnextnode(node)) { - struct connected *ifc = listgetdata(node); - struct prefix *p = ifc->address; - int l_encode; - - if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) - continue; - - if ((curr + uel) > buf_pastend) - return 0; - - if (p->family != family) - continue; - - l_encode = pim_encode_addr_ucast (curr, p); - curr += l_encode; - option_len += l_encode; - } - - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - zlog_debug("%s: number of encoded secondary unicast IPv4 addresses: %zu", - __PRETTY_FUNCTION__, - option_len / uel); - } - - if (option_len < 1) { - /* Empty secondary unicast IPv4 address list */ - return buf; - } - - /* - * Write T and L - */ - *(uint16_t *) buf = htons(PIM_MSG_OPTION_TYPE_ADDRESS_LIST); - *(uint16_t *) (buf + 2) = htons(option_len); - - return curr; + struct listnode *node; + uint16_t option_len = 0; + uint8_t *curr; + size_t uel; + + node = listhead(ifconnected); + + /* Empty address list ? */ + if (!node) { + return buf; + } + + if (family == AF_INET) + uel = ucast_ipv4_encoding_len; + else + uel = ucast_ipv6_encoding_len; + + /* Scan secondary address list */ + curr = buf + 4; /* skip T and L */ + for (; node; node = listnextnode(node)) { + struct connected *ifc = listgetdata(node); + struct prefix *p = ifc->address; + int l_encode; + + if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) + continue; + + if ((curr + uel) > buf_pastend) + return 0; + + if (p->family != family) + continue; + + l_encode = pim_encode_addr_ucast(curr, p); + curr += l_encode; + option_len += l_encode; + } + + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + zlog_debug( + "%s: number of encoded secondary unicast IPv4 addresses: %zu", + __PRETTY_FUNCTION__, option_len / uel); + } + + if (option_len < 1) { + /* Empty secondary unicast IPv4 address list */ + return buf; + } + + /* + * Write T and L + */ + *(uint16_t *)buf = htons(PIM_MSG_OPTION_TYPE_ADDRESS_LIST); + *(uint16_t *)(buf + 2) = htons(option_len); + + return curr; } static int check_tlv_length(const char *label, const char *tlv_name, const char *ifname, struct in_addr src_addr, int correct_len, int option_len) { - if (option_len != correct_len) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %s on interface %s", - label, tlv_name, - option_len, correct_len, - src_str, ifname); - return -1; - } - - return 0; + if (option_len != correct_len) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + zlog_warn( + "%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %s on interface %s", + label, tlv_name, option_len, correct_len, src_str, + ifname); + return -1; + } + + return 0; } -static void check_tlv_redefinition_uint16(const char *label, const char *tlv_name, - const char *ifname, struct in_addr src_addr, - pim_hello_options options, - pim_hello_options opt_mask, - uint16_t new, uint16_t old) +static void check_tlv_redefinition_uint16( + const char *label, const char *tlv_name, const char *ifname, + struct in_addr src_addr, pim_hello_options options, + pim_hello_options opt_mask, uint16_t new, uint16_t old) { - if (PIM_OPTION_IS_SET(options, opt_mask)) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", - label, tlv_name, - new, old, - src_str, ifname); - } + if (PIM_OPTION_IS_SET(options, opt_mask)) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + zlog_warn( + "%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", + label, tlv_name, new, old, src_str, ifname); + } } -static void check_tlv_redefinition_uint32(const char *label, const char *tlv_name, - const char *ifname, struct in_addr src_addr, - pim_hello_options options, - pim_hello_options opt_mask, - uint32_t new, uint32_t old) +static void check_tlv_redefinition_uint32( + const char *label, const char *tlv_name, const char *ifname, + struct in_addr src_addr, pim_hello_options options, + pim_hello_options opt_mask, uint32_t new, uint32_t old) { - if (PIM_OPTION_IS_SET(options, opt_mask)) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", - label, tlv_name, - new, old, - src_str, ifname); - } + if (PIM_OPTION_IS_SET(options, opt_mask)) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + zlog_warn( + "%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", + label, tlv_name, new, old, src_str, ifname); + } } -static void check_tlv_redefinition_uint32_hex(const char *label, const char *tlv_name, - const char *ifname, struct in_addr src_addr, - pim_hello_options options, - pim_hello_options opt_mask, - uint32_t new, uint32_t old) +static void check_tlv_redefinition_uint32_hex( + const char *label, const char *tlv_name, const char *ifname, + struct in_addr src_addr, pim_hello_options options, + pim_hello_options opt_mask, uint32_t new, uint32_t old) { - if (PIM_OPTION_IS_SET(options, opt_mask)) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: PIM hello TLV redefined %s=%08x old=%08x from %s on interface %s", - label, tlv_name, - new, old, - src_str, ifname); - } + if (PIM_OPTION_IS_SET(options, opt_mask)) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + zlog_warn( + "%s: PIM hello TLV redefined %s=%08x old=%08x from %s on interface %s", + label, tlv_name, new, old, src_str, ifname); + } } int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, - uint16_t *hello_option_holdtime, - uint16_t option_len, - const uint8_t *tlv_curr) + uint16_t *hello_option_holdtime, uint16_t option_len, + const uint8_t *tlv_curr) { - const char *label = "holdtime"; - - if (check_tlv_length(__PRETTY_FUNCTION__, label, - ifname, src_addr, - sizeof(uint16_t), option_len)) { - return -1; - } - - check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, label, - ifname, src_addr, - *hello_options, PIM_OPTION_MASK_HOLDTIME, - PIM_TLV_GET_HOLDTIME(tlv_curr), - *hello_option_holdtime); - - PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_HOLDTIME); - - *hello_option_holdtime = PIM_TLV_GET_HOLDTIME(tlv_curr); - - return 0; + const char *label = "holdtime"; + + if (check_tlv_length(__PRETTY_FUNCTION__, label, ifname, src_addr, + sizeof(uint16_t), option_len)) { + return -1; + } + + check_tlv_redefinition_uint16( + __PRETTY_FUNCTION__, label, ifname, src_addr, *hello_options, + PIM_OPTION_MASK_HOLDTIME, PIM_TLV_GET_HOLDTIME(tlv_curr), + *hello_option_holdtime); + + PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_HOLDTIME); + + *hello_option_holdtime = PIM_TLV_GET_HOLDTIME(tlv_curr); + + return 0; } int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, uint16_t *hello_option_propagation_delay, uint16_t *hello_option_override_interval, - uint16_t option_len, - const uint8_t *tlv_curr) + uint16_t option_len, const uint8_t *tlv_curr) { - if (check_tlv_length(__PRETTY_FUNCTION__, "lan_prune_delay", - ifname, src_addr, - sizeof(uint32_t), option_len)) { - return -1; - } - - check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, "propagation_delay", - ifname, src_addr, - *hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY, - PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr), - *hello_option_propagation_delay); - - PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY); - - *hello_option_propagation_delay = PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr); - if (PIM_TLV_GET_CAN_DISABLE_JOIN_SUPPRESSION(tlv_curr)) { - PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION); - } - else { - PIM_OPTION_UNSET(*hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION); - } - ++tlv_curr; - ++tlv_curr; - *hello_option_override_interval = PIM_TLV_GET_OVERRIDE_INTERVAL(tlv_curr); - - return 0; + if (check_tlv_length(__PRETTY_FUNCTION__, "lan_prune_delay", ifname, + src_addr, sizeof(uint32_t), option_len)) { + return -1; + } + + check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, "propagation_delay", + ifname, src_addr, *hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY, + PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr), + *hello_option_propagation_delay); + + PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY); + + *hello_option_propagation_delay = + PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr); + if (PIM_TLV_GET_CAN_DISABLE_JOIN_SUPPRESSION(tlv_curr)) { + PIM_OPTION_SET(*hello_options, + PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION); + } else { + PIM_OPTION_UNSET(*hello_options, + PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION); + } + ++tlv_curr; + ++tlv_curr; + *hello_option_override_interval = + PIM_TLV_GET_OVERRIDE_INTERVAL(tlv_curr); + + return 0; } int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, uint32_t *hello_option_dr_priority, - uint16_t option_len, - const uint8_t *tlv_curr) + uint16_t option_len, const uint8_t *tlv_curr) { - const char *label = "dr_priority"; - - if (check_tlv_length(__PRETTY_FUNCTION__, label, - ifname, src_addr, - sizeof(uint32_t), option_len)) { - return -1; - } - - check_tlv_redefinition_uint32(__PRETTY_FUNCTION__, label, - ifname, src_addr, - *hello_options, PIM_OPTION_MASK_DR_PRIORITY, - PIM_TLV_GET_DR_PRIORITY(tlv_curr), - *hello_option_dr_priority); - - PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_DR_PRIORITY); - - *hello_option_dr_priority = PIM_TLV_GET_DR_PRIORITY(tlv_curr); - - return 0; + const char *label = "dr_priority"; + + if (check_tlv_length(__PRETTY_FUNCTION__, label, ifname, src_addr, + sizeof(uint32_t), option_len)) { + return -1; + } + + check_tlv_redefinition_uint32( + __PRETTY_FUNCTION__, label, ifname, src_addr, *hello_options, + PIM_OPTION_MASK_DR_PRIORITY, PIM_TLV_GET_DR_PRIORITY(tlv_curr), + *hello_option_dr_priority); + + PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_DR_PRIORITY); + + *hello_option_dr_priority = PIM_TLV_GET_DR_PRIORITY(tlv_curr); + + return 0; } int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, uint32_t *hello_option_generation_id, - uint16_t option_len, - const uint8_t *tlv_curr) + uint16_t option_len, const uint8_t *tlv_curr) { - const char *label = "generation_id"; - - if (check_tlv_length(__PRETTY_FUNCTION__, label, - ifname, src_addr, - sizeof(uint32_t), option_len)) { - return -1; - } - - check_tlv_redefinition_uint32_hex(__PRETTY_FUNCTION__, label, - ifname, src_addr, - *hello_options, PIM_OPTION_MASK_GENERATION_ID, - PIM_TLV_GET_GENERATION_ID(tlv_curr), - *hello_option_generation_id); - - PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_GENERATION_ID); - - *hello_option_generation_id = PIM_TLV_GET_GENERATION_ID(tlv_curr); - - return 0; + const char *label = "generation_id"; + + if (check_tlv_length(__PRETTY_FUNCTION__, label, ifname, src_addr, + sizeof(uint32_t), option_len)) { + return -1; + } + + check_tlv_redefinition_uint32_hex(__PRETTY_FUNCTION__, label, ifname, + src_addr, *hello_options, + PIM_OPTION_MASK_GENERATION_ID, + PIM_TLV_GET_GENERATION_ID(tlv_curr), + *hello_option_generation_id); + + PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_GENERATION_ID); + + *hello_option_generation_id = PIM_TLV_GET_GENERATION_ID(tlv_curr); + + return 0; } -int -pim_parse_addr_ucast (struct prefix *p, - const uint8_t *buf, - int buf_size) +int pim_parse_addr_ucast(struct prefix *p, const uint8_t *buf, int buf_size) { - const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */ - const uint8_t *addr; - const uint8_t *pastend; - int family; - int type; - - if (buf_size < ucast_encoding_min_len) { - zlog_warn("%s: unicast address encoding overflow: left=%d needed=%d", - __PRETTY_FUNCTION__, - buf_size, ucast_encoding_min_len); - return -1; - } - - addr = buf; - pastend = buf + buf_size; - - family = *addr++; - type = *addr++; - - if (type) { - zlog_warn("%s: unknown unicast address encoding type=%d", - __PRETTY_FUNCTION__, - type); - return -2; - } - - switch (family) { - case PIM_MSG_ADDRESS_FAMILY_IPV4: - if ((addr + sizeof(struct in_addr)) > pastend) { - zlog_warn("%s: IPv4 unicast address overflow: left=%zd needed=%zu", - __PRETTY_FUNCTION__, - pastend - addr, sizeof(struct in_addr)); - return -3; - } - - p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ - memcpy(&p->u.prefix4, addr, sizeof(struct in_addr)); - p->prefixlen = IPV4_MAX_PREFIXLEN; - addr += sizeof(struct in_addr); - - break; - case PIM_MSG_ADDRESS_FAMILY_IPV6: - if ((addr + sizeof(struct in6_addr)) > pastend) { - zlog_warn ("%s: IPv6 unicast address overflow: left=%zd needed %zu", - __PRETTY_FUNCTION__, - pastend - addr, sizeof(struct in6_addr)); - return -3; - } - - p->family = AF_INET6; - p->prefixlen = IPV6_MAX_PREFIXLEN; - memcpy(&p->u.prefix6, addr, sizeof(struct in6_addr)); - addr += sizeof(struct in6_addr); - - break; - default: - { - zlog_warn("%s: unknown unicast address encoding family=%d from", - __PRETTY_FUNCTION__, - family); - return -4; - } - } - - return addr - buf; + const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */ + const uint8_t *addr; + const uint8_t *pastend; + int family; + int type; + + if (buf_size < ucast_encoding_min_len) { + zlog_warn( + "%s: unicast address encoding overflow: left=%d needed=%d", + __PRETTY_FUNCTION__, buf_size, ucast_encoding_min_len); + return -1; + } + + addr = buf; + pastend = buf + buf_size; + + family = *addr++; + type = *addr++; + + if (type) { + zlog_warn("%s: unknown unicast address encoding type=%d", + __PRETTY_FUNCTION__, type); + return -2; + } + + switch (family) { + case PIM_MSG_ADDRESS_FAMILY_IPV4: + if ((addr + sizeof(struct in_addr)) > pastend) { + zlog_warn( + "%s: IPv4 unicast address overflow: left=%zd needed=%zu", + __PRETTY_FUNCTION__, pastend - addr, + sizeof(struct in_addr)); + return -3; + } + + p->family = AF_INET; /* notice: AF_INET != + PIM_MSG_ADDRESS_FAMILY_IPV4 */ + memcpy(&p->u.prefix4, addr, sizeof(struct in_addr)); + p->prefixlen = IPV4_MAX_PREFIXLEN; + addr += sizeof(struct in_addr); + + break; + case PIM_MSG_ADDRESS_FAMILY_IPV6: + if ((addr + sizeof(struct in6_addr)) > pastend) { + zlog_warn( + "%s: IPv6 unicast address overflow: left=%zd needed %zu", + __PRETTY_FUNCTION__, pastend - addr, + sizeof(struct in6_addr)); + return -3; + } + + p->family = AF_INET6; + p->prefixlen = IPV6_MAX_PREFIXLEN; + memcpy(&p->u.prefix6, addr, sizeof(struct in6_addr)); + addr += sizeof(struct in6_addr); + + break; + default: { + zlog_warn("%s: unknown unicast address encoding family=%d from", + __PRETTY_FUNCTION__, family); + return -4; + } + } + + return addr - buf; } -int -pim_parse_addr_group (struct prefix_sg *sg, - const uint8_t *buf, - int buf_size) +int pim_parse_addr_group(struct prefix_sg *sg, const uint8_t *buf, int buf_size) { - const int grp_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */ - const uint8_t *addr; - const uint8_t *pastend; - int family; - int type; - int mask_len; - - if (buf_size < grp_encoding_min_len) { - zlog_warn("%s: group address encoding overflow: left=%d needed=%d", - __PRETTY_FUNCTION__, - buf_size, grp_encoding_min_len); - return -1; - } - - addr = buf; - pastend = buf + buf_size; - - family = *addr++; - type = *addr++; - //++addr; - ++addr; /* skip b_reserved_z fields */ - mask_len = *addr++; - - switch (family) { - case PIM_MSG_ADDRESS_FAMILY_IPV4: - if (type) { - zlog_warn("%s: unknown group address encoding type=%d from", - __PRETTY_FUNCTION__, type); - return -2; - } - - if ((addr + sizeof(struct in_addr)) > pastend) { - zlog_warn("%s: IPv4 group address overflow: left=%zd needed=%zu from", - __PRETTY_FUNCTION__, - pastend - addr, sizeof(struct in_addr)); - return -3; - } - - memcpy(&sg->grp.s_addr, addr, sizeof(struct in_addr)); - - addr += sizeof(struct in_addr); - - break; - default: - { - zlog_warn("%s: unknown group address encoding family=%d mask_len=%d from", - __PRETTY_FUNCTION__, family, mask_len); - return -4; - } - } - - return addr - buf; + const int grp_encoding_min_len = + 4; /* 1 family + 1 type + 1 reserved + 1 addr */ + const uint8_t *addr; + const uint8_t *pastend; + int family; + int type; + int mask_len; + + if (buf_size < grp_encoding_min_len) { + zlog_warn( + "%s: group address encoding overflow: left=%d needed=%d", + __PRETTY_FUNCTION__, buf_size, grp_encoding_min_len); + return -1; + } + + addr = buf; + pastend = buf + buf_size; + + family = *addr++; + type = *addr++; + //++addr; + ++addr; /* skip b_reserved_z fields */ + mask_len = *addr++; + + switch (family) { + case PIM_MSG_ADDRESS_FAMILY_IPV4: + if (type) { + zlog_warn( + "%s: unknown group address encoding type=%d from", + __PRETTY_FUNCTION__, type); + return -2; + } + + if ((addr + sizeof(struct in_addr)) > pastend) { + zlog_warn( + "%s: IPv4 group address overflow: left=%zd needed=%zu from", + __PRETTY_FUNCTION__, pastend - addr, + sizeof(struct in_addr)); + return -3; + } + + memcpy(&sg->grp.s_addr, addr, sizeof(struct in_addr)); + + addr += sizeof(struct in_addr); + + break; + default: { + zlog_warn( + "%s: unknown group address encoding family=%d mask_len=%d from", + __PRETTY_FUNCTION__, family, mask_len); + return -4; + } + } + + return addr - buf; } -int -pim_parse_addr_source(struct prefix_sg *sg, - uint8_t *flags, - const uint8_t *buf, - int buf_size) +int pim_parse_addr_source(struct prefix_sg *sg, uint8_t *flags, + const uint8_t *buf, int buf_size) { - const int src_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */ - const uint8_t *addr; - const uint8_t *pastend; - int family; - int type; - int mask_len; - - if (buf_size < src_encoding_min_len) { - zlog_warn("%s: source address encoding overflow: left=%d needed=%d", - __PRETTY_FUNCTION__, - buf_size, src_encoding_min_len); - return -1; - } - - addr = buf; - pastend = buf + buf_size; - - family = *addr++; - type = *addr++; - *flags = *addr++; - mask_len = *addr++; - - if (type) { - zlog_warn("%s: unknown source address encoding type=%d: %02x%02x%02x%02x%02x%02x%02x%02x", - __PRETTY_FUNCTION__, - type, - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); - return -2; - } - - switch (family) { - case PIM_MSG_ADDRESS_FAMILY_IPV4: - if ((addr + sizeof(struct in_addr)) > pastend) { - zlog_warn("%s: IPv4 source address overflow: left=%zd needed=%zu", - __PRETTY_FUNCTION__, - pastend - addr, sizeof(struct in_addr)); - return -3; - } - - memcpy(&sg->src, addr, sizeof(struct in_addr)); - - /* - RFC 4601: 4.9.1 Encoded Source and Group Address Formats - - Encoded-Source Address - - The mask length MUST be equal to the mask length in bits for - the given Address Family and Encoding Type (32 for IPv4 native - and 128 for IPv6 native). A router SHOULD ignore any messages - received with any other mask length. - */ - if (mask_len != 32) { - zlog_warn("%s: IPv4 bad source address mask: %d", - __PRETTY_FUNCTION__, mask_len); - return -4; - } - - addr += sizeof(struct in_addr); - - break; - default: - { - zlog_warn("%s: unknown source address encoding family=%d: %02x%02x%02x%02x%02x%02x%02x%02x", - __PRETTY_FUNCTION__, - family, - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); - return -5; - } - } - - return addr - buf; -} + const int src_encoding_min_len = + 4; /* 1 family + 1 type + 1 reserved + 1 addr */ + const uint8_t *addr; + const uint8_t *pastend; + int family; + int type; + int mask_len; + + if (buf_size < src_encoding_min_len) { + zlog_warn( + "%s: source address encoding overflow: left=%d needed=%d", + __PRETTY_FUNCTION__, buf_size, src_encoding_min_len); + return -1; + } + + addr = buf; + pastend = buf + buf_size; + + family = *addr++; + type = *addr++; + *flags = *addr++; + mask_len = *addr++; -#define FREE_ADDR_LIST(hello_option_addr_list) \ -{ \ - if (hello_option_addr_list) { \ - list_delete(hello_option_addr_list); \ - hello_option_addr_list = 0; \ - } \ + if (type) { + zlog_warn( + "%s: unknown source address encoding type=%d: %02x%02x%02x%02x%02x%02x%02x%02x", + __PRETTY_FUNCTION__, type, buf[0], buf[1], buf[2], + buf[3], buf[4], buf[5], buf[6], buf[7]); + return -2; + } + + switch (family) { + case PIM_MSG_ADDRESS_FAMILY_IPV4: + if ((addr + sizeof(struct in_addr)) > pastend) { + zlog_warn( + "%s: IPv4 source address overflow: left=%zd needed=%zu", + __PRETTY_FUNCTION__, pastend - addr, + sizeof(struct in_addr)); + return -3; + } + + memcpy(&sg->src, addr, sizeof(struct in_addr)); + + /* + RFC 4601: 4.9.1 Encoded Source and Group Address Formats + + Encoded-Source Address + + The mask length MUST be equal to the mask length in bits for + the given Address Family and Encoding Type (32 for IPv4 + native + and 128 for IPv6 native). A router SHOULD ignore any + messages + received with any other mask length. + */ + if (mask_len != 32) { + zlog_warn("%s: IPv4 bad source address mask: %d", + __PRETTY_FUNCTION__, mask_len); + return -4; + } + + addr += sizeof(struct in_addr); + + break; + default: { + zlog_warn( + "%s: unknown source address encoding family=%d: %02x%02x%02x%02x%02x%02x%02x%02x", + __PRETTY_FUNCTION__, family, buf[0], buf[1], buf[2], + buf[3], buf[4], buf[5], buf[6], buf[7]); + return -5; + } + } + + return addr - buf; } +#define FREE_ADDR_LIST(hello_option_addr_list) \ + { \ + if (hello_option_addr_list) { \ + list_delete(hello_option_addr_list); \ + hello_option_addr_list = 0; \ + } \ + } + int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, struct list **hello_option_addr_list, - uint16_t option_len, - const uint8_t *tlv_curr) + uint16_t option_len, const uint8_t *tlv_curr) { - const uint8_t *addr; - const uint8_t *pastend; - - zassert(hello_option_addr_list); - - /* - Scan addr list - */ - addr = tlv_curr; - pastend = tlv_curr + option_len; - while (addr < pastend) { - struct prefix tmp; - int addr_offset; - - /* - Parse ucast addr - */ - addr_offset = pim_parse_addr_ucast(&tmp, addr, pastend - addr); - if (addr_offset < 1) { - 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__, - src_str, ifname); - FREE_ADDR_LIST(*hello_option_addr_list); - return -1; - } - addr += addr_offset; - - /* - Debug - */ - if (PIM_DEBUG_PIM_TRACE) { - switch (tmp.family) { - case AF_INET: - { - char addr_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", tmp.u.prefix4, addr_str, sizeof(addr_str)); - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %s on %s", - __PRETTY_FUNCTION__, - *hello_option_addr_list ? - ((int) listcount(*hello_option_addr_list)) : -1, - addr_str, src_str, ifname); - } - break; - case AF_INET6: - break; - default: - { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s", - __PRETTY_FUNCTION__, - *hello_option_addr_list ? - ((int) listcount(*hello_option_addr_list)) : -1, - src_str, ifname); - } - } - } - - /* - Exclude neighbor's primary address if incorrectly included in - the secondary address list - */ - if (tmp.family == AF_INET) { - if (tmp.u.prefix4.s_addr == src_addr.s_addr) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: ignoring primary address in secondary list from %s on %s", - __PRETTY_FUNCTION__, - src_str, ifname); - continue; - } - } - - /* - Allocate list if needed - */ - if (!*hello_option_addr_list) { - *hello_option_addr_list = list_new(); - if (!*hello_option_addr_list) { - zlog_err("%s %s: failure: hello_option_addr_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return -2; - } - (*hello_option_addr_list)->del = (void (*)(void *)) prefix_free; - } - - /* - Attach addr to list - */ - { - struct prefix *p; - p = prefix_new(); - if (!p) { - zlog_err("%s %s: failure: prefix_new()", - __FILE__, __PRETTY_FUNCTION__); - FREE_ADDR_LIST(*hello_option_addr_list); - return -3; - } - prefix_copy(p, &tmp); - listnode_add(*hello_option_addr_list, p); - } - - } /* while (addr < pastend) */ - - /* - Mark hello option - */ - PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_ADDRESS_LIST); - - return 0; + const uint8_t *addr; + const uint8_t *pastend; + + zassert(hello_option_addr_list); + + /* + Scan addr list + */ + addr = tlv_curr; + pastend = tlv_curr + option_len; + while (addr < pastend) { + struct prefix tmp; + int addr_offset; + + /* + Parse ucast addr + */ + addr_offset = pim_parse_addr_ucast(&tmp, addr, pastend - addr); + if (addr_offset < 1) { + 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__, src_str, ifname); + FREE_ADDR_LIST(*hello_option_addr_list); + return -1; + } + addr += addr_offset; + + /* + Debug + */ + if (PIM_DEBUG_PIM_TRACE) { + switch (tmp.family) { + case AF_INET: { + char addr_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", tmp.u.prefix4, + addr_str, sizeof(addr_str)); + pim_inet4_dump("<src?>", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %s on %s", + __PRETTY_FUNCTION__, + *hello_option_addr_list + ? ((int)listcount( + *hello_option_addr_list)) + : -1, + addr_str, src_str, ifname); + } break; + case AF_INET6: + break; + default: { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s", + __PRETTY_FUNCTION__, + *hello_option_addr_list + ? ((int)listcount( + *hello_option_addr_list)) + : -1, + src_str, ifname); + } + } + } + + /* + Exclude neighbor's primary address if incorrectly included in + the secondary address list + */ + if (tmp.family == AF_INET) { + if (tmp.u.prefix4.s_addr == src_addr.s_addr) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", src_addr, src_str, + sizeof(src_str)); + zlog_warn( + "%s: ignoring primary address in secondary list from %s on %s", + __PRETTY_FUNCTION__, src_str, ifname); + continue; + } + } + + /* + Allocate list if needed + */ + if (!*hello_option_addr_list) { + *hello_option_addr_list = list_new(); + if (!*hello_option_addr_list) { + zlog_err( + "%s %s: failure: hello_option_addr_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return -2; + } + (*hello_option_addr_list)->del = + (void (*)(void *))prefix_free; + } + + /* + Attach addr to list + */ + { + struct prefix *p; + p = prefix_new(); + if (!p) { + zlog_err("%s %s: failure: prefix_new()", + __FILE__, __PRETTY_FUNCTION__); + FREE_ADDR_LIST(*hello_option_addr_list); + return -3; + } + prefix_copy(p, &tmp); + listnode_add(*hello_option_addr_list, p); + } + + } /* while (addr < pastend) */ + + /* + Mark hello option + */ + PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_ADDRESS_LIST); + + return 0; } diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h index f80e1fba2..657675b31 100644 --- a/pimd/pim_tlv.h +++ b/pimd/pim_tlv.h @@ -64,63 +64,46 @@ typedef uint32_t pim_hello_options; #define PIM_TLV_MIN_SIZE (PIM_TLV_TYPE_SIZE + PIM_TLV_LENGTH_SIZE) #define PIM_TLV_OPTION_SIZE(option_len) (PIM_TLV_MIN_SIZE + (option_len)) -uint8_t *pim_tlv_append_uint16(uint8_t *buf, - const uint8_t *buf_pastend, - uint16_t option_type, - uint16_t option_value); -uint8_t *pim_tlv_append_2uint16(uint8_t *buf, - const uint8_t *buf_pastend, - uint16_t option_type, - uint16_t option_value1, +uint8_t *pim_tlv_append_uint16(uint8_t *buf, const uint8_t *buf_pastend, + uint16_t option_type, uint16_t option_value); +uint8_t *pim_tlv_append_2uint16(uint8_t *buf, const uint8_t *buf_pastend, + uint16_t option_type, uint16_t option_value1, uint16_t option_value2); -uint8_t *pim_tlv_append_uint32(uint8_t *buf, - const uint8_t *buf_pastend, - uint16_t option_type, - uint32_t option_value); -uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, - const uint8_t *buf_pastend, - struct list *ifconnected, - int family); +uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend, + uint16_t option_type, uint32_t option_value); +uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, + struct list *ifconnected, int family); int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, - uint16_t *hello_option_holdtime, - uint16_t option_len, + uint16_t *hello_option_holdtime, uint16_t option_len, const uint8_t *tlv_curr); int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, uint16_t *hello_option_propagation_delay, uint16_t *hello_option_override_interval, - uint16_t option_len, - const uint8_t *tlv_curr); + uint16_t option_len, const uint8_t *tlv_curr); int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, uint32_t *hello_option_dr_priority, - uint16_t option_len, - const uint8_t *tlv_curr); + uint16_t option_len, const uint8_t *tlv_curr); int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, uint32_t *hello_option_generation_id, - uint16_t option_len, - const uint8_t *tlv_curr); + uint16_t option_len, const uint8_t *tlv_curr); int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, struct list **hello_option_addr_list, - uint16_t option_len, - const uint8_t *tlv_curr); + uint16_t option_len, const uint8_t *tlv_curr); -int pim_encode_addr_ucast (uint8_t *buf, struct prefix *p); -int pim_encode_addr_group (uint8_t *buf, afi_t afi, int bidir, int scope, struct in_addr group); +int pim_encode_addr_ucast(uint8_t *buf, struct prefix *p); +int pim_encode_addr_group(uint8_t *buf, afi_t afi, int bidir, int scope, + struct in_addr group); -int pim_parse_addr_ucast (struct prefix *p, - const uint8_t *buf, - int buf_size); -int pim_parse_addr_group (struct prefix_sg *sg, - const uint8_t *buf, - int buf_size); -int pim_parse_addr_source(struct prefix_sg *sg, - uint8_t *flags, - const uint8_t *buf, - int buf_size); +int pim_parse_addr_ucast(struct prefix *p, const uint8_t *buf, int buf_size); +int pim_parse_addr_group(struct prefix_sg *sg, const uint8_t *buf, + int buf_size); +int pim_parse_addr_source(struct prefix_sg *sg, uint8_t *flags, + const uint8_t *buf, int buf_size); #endif /* PIM_TLV_H */ diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 442cb02a1..0ddd04c38 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -59,35 +59,33 @@ struct list *pim_upstream_list = NULL; struct timer_wheel *pim_upstream_sg_wheel = NULL; static void join_timer_stop(struct pim_upstream *up); -static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up); +static void +pim_upstream_update_assert_tracking_desired(struct pim_upstream *up); /* * A (*,G) or a (*,*) is going away * remove the parent pointer from * those pointing at us */ -static void -pim_upstream_remove_children (struct pim_upstream *up) +static void pim_upstream_remove_children(struct pim_upstream *up) { - struct pim_upstream *child; - - if (!up->sources) - return; - - while (!list_isempty (up->sources)) - { - child = listnode_head (up->sources); - listnode_delete (up->sources, child); - if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(child->flags)) - { - PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(child->flags); - child = pim_upstream_del(child, __PRETTY_FUNCTION__); - } - if (child) - child->parent = NULL; - } - list_delete(up->sources); - up->sources = NULL; + struct pim_upstream *child; + + if (!up->sources) + return; + + while (!list_isempty(up->sources)) { + child = listnode_head(up->sources); + listnode_delete(up->sources, child); + if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(child->flags)) { + PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(child->flags); + child = pim_upstream_del(child, __PRETTY_FUNCTION__); + } + if (child) + child->parent = NULL; + } + list_delete(up->sources); + up->sources = NULL; } /* @@ -95,30 +93,27 @@ pim_upstream_remove_children (struct pim_upstream *up) * Find the children that would point * at us. */ -static void -pim_upstream_find_new_children (struct pim_upstream *up) +static void pim_upstream_find_new_children(struct pim_upstream *up) { - struct pim_upstream *child; - struct listnode *ch_node; - - if ((up->sg.src.s_addr != INADDR_ANY) && - (up->sg.grp.s_addr != INADDR_ANY)) - return; - - if ((up->sg.src.s_addr == INADDR_ANY) && - (up->sg.grp.s_addr == INADDR_ANY)) - return; - - for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, ch_node, child)) - { - if ((up->sg.grp.s_addr != INADDR_ANY) && - (child->sg.grp.s_addr == up->sg.grp.s_addr) && - (child != up)) - { - child->parent = up; - listnode_add_sort (up->sources, child); + struct pim_upstream *child; + struct listnode *ch_node; + + if ((up->sg.src.s_addr != INADDR_ANY) + && (up->sg.grp.s_addr != INADDR_ANY)) + return; + + if ((up->sg.src.s_addr == INADDR_ANY) + && (up->sg.grp.s_addr == INADDR_ANY)) + return; + + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, ch_node, child)) { + if ((up->sg.grp.s_addr != INADDR_ANY) + && (child->sg.grp.s_addr == up->sg.grp.s_addr) + && (child != up)) { + child->parent = up; + listnode_add_sort(up->sources, child); + } } - } } /* @@ -126,218 +121,211 @@ pim_upstream_find_new_children (struct pim_upstream *up) * If we have a (S,G), find the (*,G) * If we have a (*,G), find the (*,*) */ -static struct pim_upstream * -pim_upstream_find_parent (struct pim_upstream *child) +static struct pim_upstream *pim_upstream_find_parent(struct pim_upstream *child) { - struct prefix_sg any = child->sg; - struct pim_upstream *up = NULL; + struct prefix_sg any = child->sg; + struct pim_upstream *up = NULL; - // (S,G) - if ((child->sg.src.s_addr != INADDR_ANY) && - (child->sg.grp.s_addr != INADDR_ANY)) - { - any.src.s_addr = INADDR_ANY; - up = pim_upstream_find (&any); + // (S,G) + if ((child->sg.src.s_addr != INADDR_ANY) + && (child->sg.grp.s_addr != INADDR_ANY)) { + any.src.s_addr = INADDR_ANY; + up = pim_upstream_find(&any); - if (up) - listnode_add (up->sources, child); + if (up) + listnode_add(up->sources, child); - return up; - } + return up; + } - return NULL; + return NULL; } void pim_upstream_free(struct pim_upstream *up) { - XFREE(MTYPE_PIM_UPSTREAM, up); - up = NULL; + XFREE(MTYPE_PIM_UPSTREAM, up); + up = NULL; } static void upstream_channel_oil_detach(struct pim_upstream *up) { - if (up->channel_oil) - { - /* Detaching from channel_oil, channel_oil may exist post del, - but upstream would not keep reference of it - */ - pim_channel_oil_del(up->channel_oil); - up->channel_oil = NULL; - } + if (up->channel_oil) { + /* Detaching from channel_oil, channel_oil may exist post del, + but upstream would not keep reference of it + */ + pim_channel_oil_del(up->channel_oil); + up->channel_oil = NULL; + } } -struct pim_upstream * -pim_upstream_del(struct pim_upstream *up, const char *name) +struct pim_upstream *pim_upstream_del(struct pim_upstream *up, const char *name) { - bool notify_msdp = false; - struct prefix nht_p; - - if (PIM_DEBUG_TRACE) - zlog_debug ("%s(%s): Delete %s ref count: %d , flags: %d c_oil ref count %d (Pre decrement)", - __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count, up->flags, - up->channel_oil->oil_ref_count); - - --up->ref_count; - - if (up->ref_count >= 1) - return up; - - THREAD_OFF(up->t_ka_timer); - THREAD_OFF(up->t_rs_timer); - THREAD_OFF(up->t_msdp_reg_timer); - - if (up->join_state == PIM_UPSTREAM_JOINED) { - pim_jp_agg_single_upstream_send (&up->rpf, up, 0); - - if (up->sg.src.s_addr == INADDR_ANY) { - /* if a (*, G) entry in the joined state is being deleted we - * need to notify MSDP */ - notify_msdp = true; - } - } - - join_timer_stop(up); - pim_jp_agg_upstream_verification (up, false); - up->rpf.source_nexthop.interface = NULL; - - if (up->sg.src.s_addr != INADDR_ANY) { - wheel_remove_item (pim_upstream_sg_wheel, up); - notify_msdp = true; - } - - pim_upstream_remove_children (up); - if (up->sources) - list_delete (up->sources); - up->sources = NULL; - pim_mroute_del (up->channel_oil, __PRETTY_FUNCTION__); - upstream_channel_oil_detach(up); - - list_delete (up->ifchannels); - up->ifchannels = NULL; - - /* - notice that listnode_delete() can't be moved - into pim_upstream_free() because the later is - called by list_delete_all_node() - */ - if (up->parent && up->parent->sources) - listnode_delete (up->parent->sources, up); - up->parent = NULL; - - listnode_delete (pim_upstream_list, up); - hash_release (pim_upstream_hash, up); - - if (notify_msdp) - { - pim_msdp_up_del (&up->sg); - } - - /* Deregister addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = up->upstream_addr; - if (PIM_DEBUG_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&nht_p, buf, sizeof (buf)); - zlog_debug ("%s: Deregister upstream %s addr %s with Zebra NHT", - __PRETTY_FUNCTION__, up->sg_str, buf); - } - pim_delete_tracked_nexthop (&nht_p, up, NULL); - - pim_upstream_free (up); - - return NULL; + bool notify_msdp = false; + struct prefix nht_p; + + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s(%s): Delete %s ref count: %d , flags: %d c_oil ref count %d (Pre decrement)", + __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count, + up->flags, up->channel_oil->oil_ref_count); + + --up->ref_count; + + if (up->ref_count >= 1) + return up; + + THREAD_OFF(up->t_ka_timer); + THREAD_OFF(up->t_rs_timer); + THREAD_OFF(up->t_msdp_reg_timer); + + if (up->join_state == PIM_UPSTREAM_JOINED) { + pim_jp_agg_single_upstream_send(&up->rpf, up, 0); + + if (up->sg.src.s_addr == INADDR_ANY) { + /* if a (*, G) entry in the joined state is being + * deleted we + * need to notify MSDP */ + notify_msdp = true; + } + } + + join_timer_stop(up); + pim_jp_agg_upstream_verification(up, false); + up->rpf.source_nexthop.interface = NULL; + + if (up->sg.src.s_addr != INADDR_ANY) { + wheel_remove_item(pim_upstream_sg_wheel, up); + notify_msdp = true; + } + + pim_upstream_remove_children(up); + if (up->sources) + list_delete(up->sources); + up->sources = NULL; + pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__); + upstream_channel_oil_detach(up); + + list_delete(up->ifchannels); + up->ifchannels = NULL; + + /* + notice that listnode_delete() can't be moved + into pim_upstream_free() because the later is + called by list_delete_all_node() + */ + if (up->parent && up->parent->sources) + listnode_delete(up->parent->sources, up); + up->parent = NULL; + + listnode_delete(pim_upstream_list, up); + hash_release(pim_upstream_hash, up); + + if (notify_msdp) { + pim_msdp_up_del(&up->sg); + } + + /* Deregister addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = up->upstream_addr; + if (PIM_DEBUG_TRACE) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&nht_p, buf, sizeof(buf)); + zlog_debug("%s: Deregister upstream %s addr %s with Zebra NHT", + __PRETTY_FUNCTION__, up->sg_str, buf); + } + pim_delete_tracked_nexthop(&nht_p, up, NULL); + + pim_upstream_free(up); + + return NULL; } -void -pim_upstream_send_join (struct pim_upstream *up) +void pim_upstream_send_join(struct pim_upstream *up) { - if (PIM_DEBUG_TRACE) { - char rpf_str[PREFIX_STRLEN]; - pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); - zlog_debug ("%s: RPF'%s=%s(%s) for Interface %s", __PRETTY_FUNCTION__, - up->sg_str, rpf_str, pim_upstream_state2str (up->join_state), - up->rpf.source_nexthop.interface->name); - if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { - zlog_debug("%s: can't send join upstream: RPF'%s=%s", - __PRETTY_FUNCTION__, - up->sg_str, rpf_str); - /* warning only */ - } - } - - /* send Join(S,G) to the current upstream neighbor */ - pim_jp_agg_single_upstream_send(&up->rpf, up, 1 /* join */); + if (PIM_DEBUG_TRACE) { + char rpf_str[PREFIX_STRLEN]; + pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str, + sizeof(rpf_str)); + zlog_debug("%s: RPF'%s=%s(%s) for Interface %s", + __PRETTY_FUNCTION__, up->sg_str, rpf_str, + pim_upstream_state2str(up->join_state), + up->rpf.source_nexthop.interface->name); + if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { + zlog_debug("%s: can't send join upstream: RPF'%s=%s", + __PRETTY_FUNCTION__, up->sg_str, rpf_str); + /* warning only */ + } + } + + /* send Join(S,G) to the current upstream neighbor */ + pim_jp_agg_single_upstream_send(&up->rpf, up, 1 /* join */); } static int on_join_timer(struct thread *t) { - struct pim_upstream *up; + struct pim_upstream *up; - up = THREAD_ARG(t); + up = THREAD_ARG(t); - /* - * In the case of a HFR we will not ahve anyone to send this to. - */ - if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) - return 0; + /* + * In the case of a HFR we will not ahve anyone to send this to. + */ + if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) + return 0; - /* - * Don't send the join if the outgoing interface is a loopback - * But since this might change leave the join timer running - */ - if (up->rpf.source_nexthop.interface && - !if_is_loopback (up->rpf.source_nexthop.interface)) - pim_upstream_send_join (up); + /* + * Don't send the join if the outgoing interface is a loopback + * But since this might change leave the join timer running + */ + if (up->rpf.source_nexthop + .interface && !if_is_loopback(up->rpf.source_nexthop.interface)) + pim_upstream_send_join(up); - join_timer_start(up); + join_timer_start(up); - return 0; + return 0; } static void join_timer_stop(struct pim_upstream *up) { - struct pim_neighbor *nbr; + struct pim_neighbor *nbr; - THREAD_OFF (up->t_join_timer); + THREAD_OFF(up->t_join_timer); - nbr = pim_neighbor_find (up->rpf.source_nexthop.interface, - up->rpf.rpf_addr.u.prefix4); + nbr = pim_neighbor_find(up->rpf.source_nexthop.interface, + up->rpf.rpf_addr.u.prefix4); - if (nbr) - pim_jp_agg_remove_group (nbr->upstream_jp_agg, up); + if (nbr) + pim_jp_agg_remove_group(nbr->upstream_jp_agg, up); - pim_jp_agg_upstream_verification (up, false); + pim_jp_agg_upstream_verification(up, false); } -void -join_timer_start(struct pim_upstream *up) +void join_timer_start(struct pim_upstream *up) { - struct pim_neighbor *nbr = NULL; - - if (up->rpf.source_nexthop.interface) - { - nbr = pim_neighbor_find (up->rpf.source_nexthop.interface, - up->rpf.rpf_addr.u.prefix4); - - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("%s: starting %d sec timer for upstream (S,G)=%s", - __PRETTY_FUNCTION__, - qpim_t_periodic, - up->sg_str); - } - } - - if (nbr) - pim_jp_agg_add_group (nbr->upstream_jp_agg, up, 1); - else - { - THREAD_OFF (up->t_join_timer); - thread_add_timer(master, on_join_timer, up, qpim_t_periodic, - &up->t_join_timer); - } - pim_jp_agg_upstream_verification (up, true); + struct pim_neighbor *nbr = NULL; + + if (up->rpf.source_nexthop.interface) { + nbr = pim_neighbor_find(up->rpf.source_nexthop.interface, + up->rpf.rpf_addr.u.prefix4); + + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug( + "%s: starting %d sec timer for upstream (S,G)=%s", + __PRETTY_FUNCTION__, qpim_t_periodic, + up->sg_str); + } + } + + if (nbr) + pim_jp_agg_add_group(nbr->upstream_jp_agg, up, 1); + else { + THREAD_OFF(up->t_join_timer); + thread_add_timer(master, on_join_timer, up, qpim_t_periodic, + &up->t_join_timer); + } + pim_jp_agg_upstream_verification(up, true); } /* @@ -347,501 +335,488 @@ join_timer_start(struct pim_upstream *up) * As such we need to remove from the old list and * add to the new list. */ -void pim_upstream_join_timer_restart(struct pim_upstream *up, struct pim_rpf *old) +void pim_upstream_join_timer_restart(struct pim_upstream *up, + struct pim_rpf *old) { - //THREAD_OFF(up->t_join_timer); - join_timer_start(up); + // THREAD_OFF(up->t_join_timer); + join_timer_start(up); } static void pim_upstream_join_timer_restart_msec(struct pim_upstream *up, int interval_msec) { - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("%s: restarting %d msec timer for upstream (S,G)=%s", - __PRETTY_FUNCTION__, - interval_msec, - up->sg_str); - } - - THREAD_OFF(up->t_join_timer); - thread_add_timer_msec(master, on_join_timer, up, interval_msec, - &up->t_join_timer); + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug("%s: restarting %d msec timer for upstream (S,G)=%s", + __PRETTY_FUNCTION__, interval_msec, up->sg_str); + } + + THREAD_OFF(up->t_join_timer); + thread_add_timer_msec(master, on_join_timer, up, interval_msec, + &up->t_join_timer); } void pim_upstream_join_suppress(struct pim_upstream *up, - struct in_addr rpf_addr, - int holdtime) + struct in_addr rpf_addr, int holdtime) { - long t_joinsuppress_msec; - long join_timer_remain_msec; - - t_joinsuppress_msec = MIN(pim_if_t_suppressed_msec(up->rpf.source_nexthop.interface), - 1000 * holdtime); - - join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); - - if (PIM_DEBUG_TRACE) { - char rpf_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<rpf?>", rpf_addr, rpf_str, sizeof(rpf_str)); - zlog_debug("%s %s: detected Join%s to RPF'(S,G)=%s: join_timer=%ld msec t_joinsuppress=%ld msec", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str, - rpf_str, - join_timer_remain_msec, t_joinsuppress_msec); - } - - if (join_timer_remain_msec < t_joinsuppress_msec) { - if (PIM_DEBUG_TRACE) { - zlog_debug("%s %s: suppressing Join(S,G)=%s for %ld msec", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str, t_joinsuppress_msec); - } - - pim_upstream_join_timer_restart_msec(up, t_joinsuppress_msec); - } + long t_joinsuppress_msec; + long join_timer_remain_msec; + + t_joinsuppress_msec = + MIN(pim_if_t_suppressed_msec(up->rpf.source_nexthop.interface), + 1000 * holdtime); + + join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); + + if (PIM_DEBUG_TRACE) { + char rpf_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<rpf?>", rpf_addr, rpf_str, sizeof(rpf_str)); + zlog_debug( + "%s %s: detected Join%s to RPF'(S,G)=%s: join_timer=%ld msec t_joinsuppress=%ld msec", + __FILE__, __PRETTY_FUNCTION__, up->sg_str, rpf_str, + join_timer_remain_msec, t_joinsuppress_msec); + } + + if (join_timer_remain_msec < t_joinsuppress_msec) { + if (PIM_DEBUG_TRACE) { + zlog_debug( + "%s %s: suppressing Join(S,G)=%s for %ld msec", + __FILE__, __PRETTY_FUNCTION__, up->sg_str, + t_joinsuppress_msec); + } + + pim_upstream_join_timer_restart_msec(up, t_joinsuppress_msec); + } } void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label, - struct pim_upstream *up) + struct pim_upstream *up) { - long join_timer_remain_msec; - int t_override_msec; - - join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); - t_override_msec = pim_if_t_override_msec(up->rpf.source_nexthop.interface); - - if (PIM_DEBUG_TRACE) { - char rpf_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<rpf?>", up->rpf.rpf_addr.u.prefix4, rpf_str, sizeof(rpf_str)); - zlog_debug("%s: to RPF'%s=%s: join_timer=%ld msec t_override=%d msec", - debug_label, - up->sg_str, rpf_str, - join_timer_remain_msec, t_override_msec); - } - - if (join_timer_remain_msec > t_override_msec) { - if (PIM_DEBUG_TRACE) { - zlog_debug("%s: decreasing (S,G)=%s join timer to t_override=%d msec", - debug_label, - up->sg_str, - t_override_msec); - } - - pim_upstream_join_timer_restart_msec(up, t_override_msec); - } + long join_timer_remain_msec; + int t_override_msec; + + join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); + t_override_msec = + pim_if_t_override_msec(up->rpf.source_nexthop.interface); + + if (PIM_DEBUG_TRACE) { + char rpf_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<rpf?>", up->rpf.rpf_addr.u.prefix4, rpf_str, + sizeof(rpf_str)); + zlog_debug( + "%s: to RPF'%s=%s: join_timer=%ld msec t_override=%d msec", + debug_label, up->sg_str, rpf_str, + join_timer_remain_msec, t_override_msec); + } + + if (join_timer_remain_msec > t_override_msec) { + if (PIM_DEBUG_TRACE) { + zlog_debug( + "%s: decreasing (S,G)=%s join timer to t_override=%d msec", + debug_label, up->sg_str, t_override_msec); + } + + pim_upstream_join_timer_restart_msec(up, t_override_msec); + } } static void forward_on(struct pim_upstream *up) { - struct listnode *chnode; - struct listnode *chnextnode; - struct pim_ifchannel *ch = NULL; + struct listnode *chnode; + struct listnode *chnextnode; + struct pim_ifchannel *ch = NULL; - /* scan (S,G) state */ - for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { - if (pim_macro_chisin_oiflist(ch)) - pim_forward_start(ch); + /* scan (S,G) state */ + for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { + if (pim_macro_chisin_oiflist(ch)) + pim_forward_start(ch); - } /* scan iface channel list */ + } /* scan iface channel list */ } static void forward_off(struct pim_upstream *up) { - struct listnode *chnode; - struct listnode *chnextnode; - struct pim_ifchannel *ch; + struct listnode *chnode; + struct listnode *chnextnode; + struct pim_ifchannel *ch; - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { - pim_forward_stop(ch); + pim_forward_stop(ch); - } /* scan iface channel list */ + } /* scan iface channel list */ } -static int -pim_upstream_could_register (struct pim_upstream *up) +static int pim_upstream_could_register(struct pim_upstream *up) { - struct pim_interface *pim_ifp = NULL; - - if (up->rpf.source_nexthop.interface) - pim_ifp = up->rpf.source_nexthop.interface->info; - else - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: up %s RPF is not present", __PRETTY_FUNCTION__, up->sg_str); - } + struct pim_interface *pim_ifp = NULL; + + if (up->rpf.source_nexthop.interface) + pim_ifp = up->rpf.source_nexthop.interface->info; + else { + if (PIM_DEBUG_TRACE) + zlog_debug("%s: up %s RPF is not present", + __PRETTY_FUNCTION__, up->sg_str); + } - if (pim_ifp && PIM_I_am_DR (pim_ifp) && - pim_if_connected_to_source (up->rpf.source_nexthop.interface, up->sg.src)) - return 1; + if (pim_ifp && PIM_I_am_DR(pim_ifp) + && pim_if_connected_to_source(up->rpf.source_nexthop.interface, + up->sg.src)) + return 1; - return 0; + return 0; } /* Source registration is supressed for SSM groups. When the SSM range changes * we re-revaluate register setup for existing upstream entries */ -void -pim_upstream_register_reevaluate (void) +void pim_upstream_register_reevaluate(void) { - struct listnode *upnode; - struct pim_upstream *up; - - for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, upnode, up)) - { - /* If FHR is set CouldRegister is True. Also check if the flow - * is actually active; if it is not kat setup will trigger source - * registration whenever the flow becomes active. */ - if (!PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) || !up->t_ka_timer) - continue; - - if (pim_is_grp_ssm (up->sg.grp)) - { - /* clear the register state for SSM groups */ - if (up->reg_state != PIM_REG_NOINFO) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug ("Clear register for %s as G is now SSM", - up->sg_str); - /* remove regiface from the OIL if it is there*/ - pim_channel_del_oif (up->channel_oil, pim_regiface, - PIM_OIF_FLAG_PROTO_PIM); - up->reg_state = PIM_REG_NOINFO; - } - } - else - { - /* register ASM sources with the RP */ - if (up->reg_state == PIM_REG_NOINFO) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug ("Register %s as G is now ASM", up->sg_str); - pim_channel_add_oif (up->channel_oil, pim_regiface, - PIM_OIF_FLAG_PROTO_PIM); - up->reg_state = PIM_REG_JOIN; - } - } - } + struct listnode *upnode; + struct pim_upstream *up; + + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { + /* If FHR is set CouldRegister is True. Also check if the flow + * is actually active; if it is not kat setup will trigger + * source + * registration whenever the flow becomes active. */ + if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) || !up->t_ka_timer) + continue; + + if (pim_is_grp_ssm(up->sg.grp)) { + /* clear the register state for SSM groups */ + if (up->reg_state != PIM_REG_NOINFO) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "Clear register for %s as G is now SSM", + up->sg_str); + /* remove regiface from the OIL if it is there*/ + pim_channel_del_oif(up->channel_oil, + pim_regiface, + PIM_OIF_FLAG_PROTO_PIM); + up->reg_state = PIM_REG_NOINFO; + } + } else { + /* register ASM sources with the RP */ + if (up->reg_state == PIM_REG_NOINFO) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "Register %s as G is now ASM", + up->sg_str); + pim_channel_add_oif(up->channel_oil, + pim_regiface, + PIM_OIF_FLAG_PROTO_PIM); + up->reg_state = PIM_REG_JOIN; + } + } + } } -void -pim_upstream_switch(struct pim_upstream *up, - enum pim_upstream_state new_state) +void pim_upstream_switch(struct pim_upstream *up, + enum pim_upstream_state new_state) { - enum pim_upstream_state old_state = up->join_state; - - if (PIM_DEBUG_PIM_EVENTS) - { - zlog_debug ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s", - __PRETTY_FUNCTION__, - up->sg_str, - pim_upstream_state2str (up->join_state), - pim_upstream_state2str (new_state)); - } - - up->join_state = new_state; - if (old_state != new_state) - up->state_transition = pim_time_monotonic_sec(); - - pim_upstream_update_assert_tracking_desired(up); - - if (new_state == PIM_UPSTREAM_JOINED) { - if (old_state != PIM_UPSTREAM_JOINED) - { - int old_fhr = PIM_UPSTREAM_FLAG_TEST_FHR(up->flags); - forward_on(up); - pim_msdp_up_join_state_changed(up); - if (pim_upstream_could_register (up)) - { - PIM_UPSTREAM_FLAG_SET_FHR(up->flags); - if (!old_fhr && PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) - { - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - pim_register_join (up); - } - } - else - { - pim_upstream_send_join (up); - join_timer_start (up); - } - } - else - { - forward_on (up); - } - } - else { - - forward_off(up); - if (old_state == PIM_UPSTREAM_JOINED) - pim_msdp_up_join_state_changed(up); - - /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards RP. - If I am RP for G then send S,G prune to its IIF. */ - if (pim_upstream_is_sg_rpt(up) && up->parent && !I_am_RP(up->sg.grp)) - { - if (PIM_DEBUG_PIM_TRACE_DETAIL) - zlog_debug ("%s: *,G IIF %s S,G IIF %s ", __PRETTY_FUNCTION__, - up->parent->rpf.source_nexthop.interface->name, - up->rpf.source_nexthop.interface->name); - pim_jp_agg_single_upstream_send(&up->parent->rpf, up->parent, 1 /* (W,G) Join */); - } - else - pim_jp_agg_single_upstream_send(&up->rpf, up, 0 /* prune */); - join_timer_stop(up); - } + enum pim_upstream_state old_state = up->join_state; + + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s", + __PRETTY_FUNCTION__, up->sg_str, + pim_upstream_state2str(up->join_state), + pim_upstream_state2str(new_state)); + } + + up->join_state = new_state; + if (old_state != new_state) + up->state_transition = pim_time_monotonic_sec(); + + pim_upstream_update_assert_tracking_desired(up); + + if (new_state == PIM_UPSTREAM_JOINED) { + if (old_state != PIM_UPSTREAM_JOINED) { + int old_fhr = PIM_UPSTREAM_FLAG_TEST_FHR(up->flags); + forward_on(up); + pim_msdp_up_join_state_changed(up); + if (pim_upstream_could_register(up)) { + PIM_UPSTREAM_FLAG_SET_FHR(up->flags); + if (!old_fhr + && PIM_UPSTREAM_FLAG_TEST_SRC_STREAM( + up->flags)) { + pim_upstream_keep_alive_timer_start( + up, qpim_keep_alive_time); + pim_register_join(up); + } + } else { + pim_upstream_send_join(up); + join_timer_start(up); + } + } else { + forward_on(up); + } + } else { + + forward_off(up); + if (old_state == PIM_UPSTREAM_JOINED) + pim_msdp_up_join_state_changed(up); + + /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards + RP. + If I am RP for G then send S,G prune to its IIF. */ + if (pim_upstream_is_sg_rpt(up) && up->parent + && !I_am_RP(up->sg.grp)) { + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug( + "%s: *,G IIF %s S,G IIF %s ", + __PRETTY_FUNCTION__, + up->parent->rpf.source_nexthop + .interface->name, + up->rpf.source_nexthop.interface->name); + pim_jp_agg_single_upstream_send(&up->parent->rpf, + up->parent, + 1 /* (W,G) Join */); + } else + pim_jp_agg_single_upstream_send(&up->rpf, up, + 0 /* prune */); + join_timer_stop(up); + } } -int -pim_upstream_compare (void *arg1, void *arg2) +int pim_upstream_compare(void *arg1, void *arg2) { - const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; - const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; + const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; + const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; - if (ntohl(up1->sg.grp.s_addr) < ntohl(up2->sg.grp.s_addr)) - return -1; + if (ntohl(up1->sg.grp.s_addr) < ntohl(up2->sg.grp.s_addr)) + return -1; - if (ntohl(up1->sg.grp.s_addr) > ntohl(up2->sg.grp.s_addr)) - return 1; + if (ntohl(up1->sg.grp.s_addr) > ntohl(up2->sg.grp.s_addr)) + return 1; - if (ntohl(up1->sg.src.s_addr) < ntohl(up2->sg.src.s_addr)) - return -1; + if (ntohl(up1->sg.src.s_addr) < ntohl(up2->sg.src.s_addr)) + return -1; - if (ntohl(up1->sg.src.s_addr) > ntohl(up2->sg.src.s_addr)) - return 1; + if (ntohl(up1->sg.src.s_addr) > ntohl(up2->sg.src.s_addr)) + return 1; - return 0; + return 0; } static struct pim_upstream * -pim_upstream_new (struct prefix_sg *sg, - struct interface *incoming, - int flags) +pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags) { - enum pim_rpf_result rpf_result; - struct pim_interface *pim_ifp; - struct pim_upstream *up; - - up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up)); - if (!up) - { - zlog_err("%s: PIM XCALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*up)); - return NULL; - } - - up->sg = *sg; - pim_str_sg_set (sg, up->sg_str); - up = hash_get (pim_upstream_hash, up, hash_alloc_intern); - if (!pim_rp_set_upstream_addr (&up->upstream_addr, sg->src, sg->grp)) - { - if (PIM_DEBUG_TRACE) - zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); - - hash_release (pim_upstream_hash, up); - XFREE (MTYPE_PIM_UPSTREAM, up); - return NULL; - } - - up->parent = pim_upstream_find_parent (up); - if (up->sg.src.s_addr == INADDR_ANY) - { - up->sources = list_new (); - up->sources->cmp = pim_upstream_compare; - } - else - up->sources = NULL; - - pim_upstream_find_new_children (up); - up->flags = flags; - up->ref_count = 1; - up->t_join_timer = NULL; - up->t_ka_timer = NULL; - up->t_rs_timer = NULL; - up->t_msdp_reg_timer = NULL; - up->join_state = PIM_UPSTREAM_NOTJOINED; - up->reg_state = PIM_REG_NOINFO; - up->state_transition = pim_time_monotonic_sec(); - up->channel_oil = NULL; - up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE; - - up->rpf.source_nexthop.interface = NULL; - up->rpf.source_nexthop.mrib_nexthop_addr.family = AF_INET; - up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; - up->rpf.source_nexthop.mrib_metric_preference = qpim_infinite_assert_metric.metric_preference; - up->rpf.source_nexthop.mrib_route_metric = qpim_infinite_assert_metric.route_metric; - up->rpf.rpf_addr.family = AF_INET; - up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; - - up->ifchannels = list_new(); - up->ifchannels->cmp = (int (*)(void *, void *))pim_ifchannel_compare; - - if (up->sg.src.s_addr != INADDR_ANY) - wheel_add_item (pim_upstream_sg_wheel, up); - - rpf_result = pim_rpf_update(up, NULL, 1); - if (rpf_result == PIM_RPF_FAILURE) { - struct prefix nht_p; - - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Attempting to create upstream(%s), Unable to RPF for source", __PRETTY_FUNCTION__, - up->sg_str); - - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = up->upstream_addr; - pim_delete_tracked_nexthop (&nht_p, up, NULL); - - if (up->parent) - { - listnode_delete (up->parent->sources, up); - up->parent = NULL; - } - - if (up->sg.src.s_addr != INADDR_ANY) - wheel_remove_item (pim_upstream_sg_wheel, up); - - pim_upstream_remove_children (up); - if (up->sources) - list_delete (up->sources); - - hash_release (pim_upstream_hash, up); - XFREE(MTYPE_PIM_UPSTREAM, up); - return NULL; - } - - if (up->rpf.source_nexthop.interface) - { - pim_ifp = up->rpf.source_nexthop.interface->info; - if (pim_ifp) - up->channel_oil = pim_channel_oil_add(&up->sg, pim_ifp->mroute_vif_index); - } - listnode_add_sort(pim_upstream_list, up); - - if (PIM_DEBUG_TRACE) - { - zlog_debug ("%s: Created Upstream %s upstream_addr %s ref count %d increment", - __PRETTY_FUNCTION__, up->sg_str, - inet_ntoa (up->upstream_addr), up->ref_count); - } - - return up; + enum pim_rpf_result rpf_result; + struct pim_interface *pim_ifp; + struct pim_upstream *up; + + up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up)); + if (!up) { + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, + sizeof(*up)); + return NULL; + } + + up->sg = *sg; + pim_str_sg_set(sg, up->sg_str); + up = hash_get(pim_upstream_hash, up, hash_alloc_intern); + if (!pim_rp_set_upstream_addr(&up->upstream_addr, sg->src, sg->grp)) { + if (PIM_DEBUG_TRACE) + zlog_debug("%s: Received a (*,G) with no RP configured", + __PRETTY_FUNCTION__); + + hash_release(pim_upstream_hash, up); + XFREE(MTYPE_PIM_UPSTREAM, up); + return NULL; + } + + up->parent = pim_upstream_find_parent(up); + if (up->sg.src.s_addr == INADDR_ANY) { + up->sources = list_new(); + up->sources->cmp = pim_upstream_compare; + } else + up->sources = NULL; + + pim_upstream_find_new_children(up); + up->flags = flags; + up->ref_count = 1; + up->t_join_timer = NULL; + up->t_ka_timer = NULL; + up->t_rs_timer = NULL; + up->t_msdp_reg_timer = NULL; + up->join_state = PIM_UPSTREAM_NOTJOINED; + up->reg_state = PIM_REG_NOINFO; + up->state_transition = pim_time_monotonic_sec(); + up->channel_oil = NULL; + up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE; + + up->rpf.source_nexthop.interface = NULL; + up->rpf.source_nexthop.mrib_nexthop_addr.family = AF_INET; + up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr = + PIM_NET_INADDR_ANY; + up->rpf.source_nexthop.mrib_metric_preference = + qpim_infinite_assert_metric.metric_preference; + up->rpf.source_nexthop.mrib_route_metric = + qpim_infinite_assert_metric.route_metric; + up->rpf.rpf_addr.family = AF_INET; + up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; + + up->ifchannels = list_new(); + up->ifchannels->cmp = (int (*)(void *, void *))pim_ifchannel_compare; + + if (up->sg.src.s_addr != INADDR_ANY) + wheel_add_item(pim_upstream_sg_wheel, up); + + rpf_result = pim_rpf_update(up, NULL, 1); + if (rpf_result == PIM_RPF_FAILURE) { + struct prefix nht_p; + + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Attempting to create upstream(%s), Unable to RPF for source", + __PRETTY_FUNCTION__, up->sg_str); + + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = up->upstream_addr; + pim_delete_tracked_nexthop(&nht_p, up, NULL); + + if (up->parent) { + listnode_delete(up->parent->sources, up); + up->parent = NULL; + } + + if (up->sg.src.s_addr != INADDR_ANY) + wheel_remove_item(pim_upstream_sg_wheel, up); + + pim_upstream_remove_children(up); + if (up->sources) + list_delete(up->sources); + + hash_release(pim_upstream_hash, up); + XFREE(MTYPE_PIM_UPSTREAM, up); + return NULL; + } + + if (up->rpf.source_nexthop.interface) { + pim_ifp = up->rpf.source_nexthop.interface->info; + if (pim_ifp) + up->channel_oil = pim_channel_oil_add( + &up->sg, pim_ifp->mroute_vif_index); + } + listnode_add_sort(pim_upstream_list, up); + + if (PIM_DEBUG_TRACE) { + zlog_debug( + "%s: Created Upstream %s upstream_addr %s ref count %d increment", + __PRETTY_FUNCTION__, up->sg_str, + inet_ntoa(up->upstream_addr), up->ref_count); + } + + return up; } struct pim_upstream *pim_upstream_find(struct prefix_sg *sg) { - struct pim_upstream lookup; - struct pim_upstream *up = NULL; + struct pim_upstream lookup; + struct pim_upstream *up = NULL; - lookup.sg = *sg; - up = hash_lookup (pim_upstream_hash, &lookup); - return up; + lookup.sg = *sg; + up = hash_lookup(pim_upstream_hash, &lookup); + return up; } -struct pim_upstream * -pim_upstream_find_or_add(struct prefix_sg *sg, - struct interface *incoming, - int flags, const char *name) +struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg, + struct interface *incoming, + int flags, const char *name) { - struct pim_upstream *up; - - up = pim_upstream_find(sg); - - if (up) - { - if (!(up->flags & flags)) - { - up->flags |= flags; - up->ref_count++; - if (PIM_DEBUG_TRACE) - zlog_debug ("%s(%s): upstream %s ref count %d increment", - __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count); - } - } - else - up = pim_upstream_add (sg, incoming, flags, name); - - return up; + struct pim_upstream *up; + + up = pim_upstream_find(sg); + + if (up) { + if (!(up->flags & flags)) { + up->flags |= flags; + up->ref_count++; + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s(%s): upstream %s ref count %d increment", + __PRETTY_FUNCTION__, name, up->sg_str, + up->ref_count); + } + } else + up = pim_upstream_add(sg, incoming, flags, name); + + return up; } -void -pim_upstream_ref(struct pim_upstream *up, int flags, const char *name) +void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name) { - up->flags |= flags; - ++up->ref_count; - if (PIM_DEBUG_TRACE) - zlog_debug ("%s(%s): upstream %s ref count %d increment", - __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count); + up->flags |= flags; + ++up->ref_count; + if (PIM_DEBUG_TRACE) + zlog_debug("%s(%s): upstream %s ref count %d increment", + __PRETTY_FUNCTION__, name, up->sg_str, + up->ref_count); } struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, - struct interface *incoming, - int flags, const char *name) + struct interface *incoming, int flags, + const char *name) { - struct pim_upstream *up = NULL; - int found = 0; - up = pim_upstream_find(sg); - if (up) { - pim_upstream_ref(up, flags, name); - found = 1; - } - else { - up = pim_upstream_new(sg, incoming, flags); - } - - if (PIM_DEBUG_TRACE) - { - if (up) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&up->rpf.rpf_addr, buf, sizeof (buf)); - zlog_debug("%s(%s): %s, iif %s (%s) found: %d: ref_count: %d", + struct pim_upstream *up = NULL; + int found = 0; + up = pim_upstream_find(sg); + if (up) { + pim_upstream_ref(up, flags, name); + found = 1; + } else { + up = pim_upstream_new(sg, incoming, flags); + } + + if (PIM_DEBUG_TRACE) { + if (up) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&up->rpf.rpf_addr, buf, sizeof(buf)); + zlog_debug("%s(%s): %s, iif %s (%s) found: %d: ref_count: %d", __PRETTY_FUNCTION__, name, up->sg_str, buf, up->rpf.source_nexthop.interface ? up->rpf.source_nexthop.interface->name : "NIL" , found, up->ref_count); - } - else - zlog_debug("%s(%s): (%s) failure to create", - __PRETTY_FUNCTION__, name, - pim_str_sg_dump (sg)); - } + } else + zlog_debug("%s(%s): (%s) failure to create", + __PRETTY_FUNCTION__, name, + pim_str_sg_dump(sg)); + } - return up; + return up; } /* * Passed in up must be the upstream for ch. starch is NULL if no * information */ -int -pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up, - struct pim_ifchannel *ch, - struct pim_ifchannel *starch) +int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up, + struct pim_ifchannel *ch, + struct pim_ifchannel *starch) { - if (ch) - { - if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) - return 0; - - if (!pim_macro_ch_lost_assert(ch) && pim_macro_chisin_joins_or_include(ch)) - return 1; - } - - /* - * joins (*,G) - */ - if (starch) - { - if (PIM_IF_FLAG_TEST_S_G_RPT (starch->upstream->flags)) - return 0; - - if (!pim_macro_ch_lost_assert (starch) && pim_macro_chisin_joins_or_include (starch)) - return 1; - } - - return 0; + if (ch) { + if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) + return 0; + + if (!pim_macro_ch_lost_assert(ch) + && pim_macro_chisin_joins_or_include(ch)) + return 1; + } + + /* + * joins (*,G) + */ + if (starch) { + if (PIM_IF_FLAG_TEST_S_G_RPT(starch->upstream->flags)) + return 0; + + if (!pim_macro_ch_lost_assert(starch) + && pim_macro_chisin_joins_or_include(starch)) + return 1; + } + + return 0; } /* @@ -859,7 +834,7 @@ pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up, pim_ifp->pim_dr_addr ch->ifassert_winner_metric ch->ifassert_winner - ch->local_ifmembership + ch->local_ifmembership ch->ifjoin_state ch->upstream->rpf.source_nexthop.mrib_metric_preference ch->upstream->rpf.source_nexthop.mrib_route_metric @@ -869,31 +844,31 @@ pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up, */ int pim_upstream_evaluate_join_desired(struct pim_upstream *up) { - struct interface *ifp; - struct listnode *node; - struct pim_ifchannel *ch, *starch; - struct pim_upstream *starup = up->parent; - int ret = 0; + struct interface *ifp; + struct listnode *node; + struct pim_ifchannel *ch, *starch; + struct pim_upstream *starup = up->parent; + int ret = 0; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - if (!ifp->info) - continue; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + if (!ifp->info) + continue; - ch = pim_ifchannel_find (ifp, &up->sg); + ch = pim_ifchannel_find(ifp, &up->sg); - if (starup) - starch = pim_ifchannel_find (ifp, &starup->sg); - else - starch = NULL; + if (starup) + starch = pim_ifchannel_find(ifp, &starup->sg); + else + starch = NULL; - if (!ch && !starch) - continue; + if (!ch && !starch) + continue; - ret += pim_upstream_evaluate_join_desired_interface (up, ch, starch); - } /* scan iface channel list */ + ret += pim_upstream_evaluate_join_desired_interface(up, ch, + starch); + } /* scan iface channel list */ - return ret; /* false */ + return ret; /* false */ } /* @@ -901,28 +876,28 @@ int pim_upstream_evaluate_join_desired(struct pim_upstream *up) */ void pim_upstream_update_join_desired(struct pim_upstream *up) { - int was_join_desired; /* boolean */ - int is_join_desired; /* boolean */ - - was_join_desired = PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags); - - is_join_desired = pim_upstream_evaluate_join_desired(up); - if (is_join_desired) - PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(up->flags); - else - PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(up->flags); - - /* switched from false to true */ - if (is_join_desired && !was_join_desired) { - pim_upstream_switch(up, PIM_UPSTREAM_JOINED); - return; - } - - /* switched from true to false */ - if (!is_join_desired && was_join_desired) { - pim_upstream_switch(up, PIM_UPSTREAM_NOTJOINED); - return; - } + int was_join_desired; /* boolean */ + int is_join_desired; /* boolean */ + + was_join_desired = PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags); + + is_join_desired = pim_upstream_evaluate_join_desired(up); + if (is_join_desired) + PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(up->flags); + else + PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(up->flags); + + /* switched from false to true */ + if (is_join_desired && !was_join_desired) { + pim_upstream_switch(up, PIM_UPSTREAM_JOINED); + return; + } + + /* switched from true to false */ + if (!is_join_desired && was_join_desired) { + pim_upstream_switch(up, PIM_UPSTREAM_NOTJOINED); + return; + } } /* @@ -936,110 +911,110 @@ void pim_upstream_update_join_desired(struct pim_upstream *up) */ void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr) { - struct listnode *up_node; - struct listnode *up_nextnode; - struct pim_upstream *up; - - /* - * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr - */ - for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { - - if (PIM_DEBUG_TRACE) { - char neigh_str[INET_ADDRSTRLEN]; - char rpf_addr_str[PREFIX_STRLEN]; - pim_inet4_dump("<neigh?>", neigh_addr, neigh_str, sizeof(neigh_str)); - pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); - zlog_debug("%s: matching neigh=%s against upstream (S,G)=%s joined=%d rpf_addr=%s", - __PRETTY_FUNCTION__, - neigh_str, up->sg_str, - up->join_state == PIM_UPSTREAM_JOINED, - rpf_addr_str); - } - - /* consider only (S,G) upstream in Joined state */ - if (up->join_state != PIM_UPSTREAM_JOINED) - continue; - - /* match RPF'(S,G)=neigh_addr */ - if (up->rpf.rpf_addr.u.prefix4.s_addr != neigh_addr.s_addr) - continue; - - pim_upstream_join_timer_decrease_to_t_override("RPF'(S,G) GenID change", - up); - } + struct listnode *up_node; + struct listnode *up_nextnode; + struct pim_upstream *up; + + /* + * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr + */ + for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { + + if (PIM_DEBUG_TRACE) { + char neigh_str[INET_ADDRSTRLEN]; + char rpf_addr_str[PREFIX_STRLEN]; + pim_inet4_dump("<neigh?>", neigh_addr, neigh_str, + sizeof(neigh_str)); + pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_addr_str, + sizeof(rpf_addr_str)); + zlog_debug( + "%s: matching neigh=%s against upstream (S,G)=%s joined=%d rpf_addr=%s", + __PRETTY_FUNCTION__, neigh_str, up->sg_str, + up->join_state == PIM_UPSTREAM_JOINED, + rpf_addr_str); + } + + /* consider only (S,G) upstream in Joined state */ + if (up->join_state != PIM_UPSTREAM_JOINED) + continue; + + /* match RPF'(S,G)=neigh_addr */ + if (up->rpf.rpf_addr.u.prefix4.s_addr != neigh_addr.s_addr) + continue; + + pim_upstream_join_timer_decrease_to_t_override( + "RPF'(S,G) GenID change", up); + } } void pim_upstream_rpf_interface_changed(struct pim_upstream *up, struct interface *old_rpf_ifp) { - struct listnode *chnode; - struct listnode *chnextnode; - struct pim_ifchannel *ch; - - /* search all ifchannels */ - for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { - if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { - if ( - /* RPF_interface(S) was NOT I */ - (old_rpf_ifp == ch->interface) - && - /* RPF_interface(S) stopped being I */ - (ch->upstream->rpf.source_nexthop.interface != ch->interface) - ) { - assert_action_a5(ch); - } - } /* PIM_IFASSERT_I_AM_LOSER */ - - pim_ifchannel_update_assert_tracking_desired(ch); - } + struct listnode *chnode; + struct listnode *chnextnode; + struct pim_ifchannel *ch; + + /* search all ifchannels */ + for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { + if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { + if ( + /* RPF_interface(S) was NOT I */ + (old_rpf_ifp == ch->interface) && + /* RPF_interface(S) stopped being I */ + (ch->upstream->rpf.source_nexthop + .interface != ch->interface)) { + assert_action_a5(ch); + } + } /* PIM_IFASSERT_I_AM_LOSER */ + + pim_ifchannel_update_assert_tracking_desired(ch); + } } void pim_upstream_update_could_assert(struct pim_upstream *up) { - struct listnode *chnode; - struct listnode *chnextnode; - struct pim_ifchannel *ch; - - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { - pim_ifchannel_update_could_assert(ch); - } /* scan iface channel list */ + struct listnode *chnode; + struct listnode *chnextnode; + struct pim_ifchannel *ch; + + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { + pim_ifchannel_update_could_assert(ch); + } /* scan iface channel list */ } void pim_upstream_update_my_assert_metric(struct pim_upstream *up) { - struct listnode *chnode; - struct listnode *chnextnode; - struct pim_ifchannel *ch; + struct listnode *chnode; + struct listnode *chnextnode; + struct pim_ifchannel *ch; - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { - pim_ifchannel_update_my_assert_metric(ch); + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { + pim_ifchannel_update_my_assert_metric(ch); - } /* scan iface channel list */ + } /* scan iface channel list */ } static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up) { - struct listnode *chnode; - struct listnode *chnextnode; - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) - { - if (!ch->interface) - continue; - pim_ifp = ch->interface->info; - if (!pim_ifp) - continue; - - pim_ifchannel_update_assert_tracking_desired(ch); - - } /* scan iface channel list */ + struct listnode *chnode; + struct listnode *chnextnode; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { + if (!ch->interface) + continue; + pim_ifp = ch->interface->info; + if (!pim_ifp) + continue; + + pim_ifchannel_update_assert_tracking_desired(ch); + + } /* scan iface channel list */ } /* When kat is stopped CouldRegister goes to false so we need to @@ -1047,19 +1022,21 @@ static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up) * from the OIL */ static void pim_upstream_fhr_kat_expiry(struct pim_upstream *up) { - if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) - return; - - if (PIM_DEBUG_TRACE) - zlog_debug ("kat expired on %s; clear fhr reg state", up->sg_str); - - /* stop reg-stop timer */ - THREAD_OFF(up->t_rs_timer); - /* remove regiface from the OIL if it is there*/ - pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); - /* clear the register state */ - up->reg_state = PIM_REG_NOINFO; - PIM_UPSTREAM_FLAG_UNSET_FHR(up->flags); + if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) + return; + + if (PIM_DEBUG_TRACE) + zlog_debug("kat expired on %s; clear fhr reg state", + up->sg_str); + + /* stop reg-stop timer */ + THREAD_OFF(up->t_rs_timer); + /* remove regiface from the OIL if it is there*/ + pim_channel_del_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_PIM); + /* clear the register state */ + up->reg_state = PIM_REG_NOINFO; + PIM_UPSTREAM_FLAG_UNSET_FHR(up->flags); } /* When kat is started CouldRegister can go to true. And if it does we @@ -1067,14 +1044,16 @@ static void pim_upstream_fhr_kat_expiry(struct pim_upstream *up) * to the OIL */ static void pim_upstream_fhr_kat_start(struct pim_upstream *up) { - if (pim_upstream_could_register(up)) { - if (PIM_DEBUG_TRACE) - zlog_debug ("kat started on %s; set fhr reg state to joined", up->sg_str); - - PIM_UPSTREAM_FLAG_SET_FHR(up->flags); - if (up->reg_state == PIM_REG_NOINFO) - pim_register_join (up); - } + if (pim_upstream_could_register(up)) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "kat started on %s; set fhr reg state to joined", + up->sg_str); + + PIM_UPSTREAM_FLAG_SET_FHR(up->flags); + if (up->reg_state == PIM_REG_NOINFO) + pim_register_join(up); + } } /* @@ -1083,80 +1062,73 @@ static void pim_upstream_fhr_kat_start(struct pim_upstream *up) * KAT expiry indicates that flow is inactive. If the flow was created or * maintained by activity now is the time to deref it. */ -static int -pim_upstream_keep_alive_timer (struct thread *t) +static int pim_upstream_keep_alive_timer(struct thread *t) { - struct pim_upstream *up; - - up = THREAD_ARG(t); - - if (I_am_RP (up->sg.grp)) - { - pim_br_clear_pmbr (&up->sg); - /* - * We need to do more here :) - * But this is the start. - */ - } - - /* source is no longer active - pull the SA from MSDP's cache */ - pim_msdp_sa_local_del(&up->sg); - - /* if entry was created because of activity we need to deref it */ - if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) - { - pim_upstream_fhr_kat_expiry(up); - if (PIM_DEBUG_TRACE) - zlog_debug ("kat expired on %s; remove stream reference", up->sg_str); - PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags); - pim_upstream_del(up, __PRETTY_FUNCTION__); - } - else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) - { - PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags); - pim_upstream_del(up, __PRETTY_FUNCTION__); - } - - return 0; + struct pim_upstream *up; + + up = THREAD_ARG(t); + + if (I_am_RP(up->sg.grp)) { + pim_br_clear_pmbr(&up->sg); + /* + * We need to do more here :) + * But this is the start. + */ + } + + /* source is no longer active - pull the SA from MSDP's cache */ + pim_msdp_sa_local_del(&up->sg); + + /* if entry was created because of activity we need to deref it */ + if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { + pim_upstream_fhr_kat_expiry(up); + if (PIM_DEBUG_TRACE) + zlog_debug("kat expired on %s; remove stream reference", + up->sg_str); + PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags); + pim_upstream_del(up, __PRETTY_FUNCTION__); + } else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) { + PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags); + pim_upstream_del(up, __PRETTY_FUNCTION__); + } + + return 0; } -void -pim_upstream_keep_alive_timer_start (struct pim_upstream *up, - uint32_t time) +void pim_upstream_keep_alive_timer_start(struct pim_upstream *up, uint32_t time) { - if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { - if (PIM_DEBUG_TRACE) - zlog_debug ("kat start on %s with no stream reference", up->sg_str); - } - THREAD_OFF (up->t_ka_timer); - thread_add_timer(master, pim_upstream_keep_alive_timer, up, time, - &up->t_ka_timer); - - /* any time keepalive is started against a SG we will have to - * re-evaluate our active source database */ - pim_msdp_sa_local_update(up); + if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { + if (PIM_DEBUG_TRACE) + zlog_debug("kat start on %s with no stream reference", + up->sg_str); + } + THREAD_OFF(up->t_ka_timer); + thread_add_timer(master, pim_upstream_keep_alive_timer, up, time, + &up->t_ka_timer); + + /* any time keepalive is started against a SG we will have to + * re-evaluate our active source database */ + pim_msdp_sa_local_update(up); } /* MSDP on RP needs to know if a source is registerable to this RP */ -static int -pim_upstream_msdp_reg_timer(struct thread *t) +static int pim_upstream_msdp_reg_timer(struct thread *t) { - struct pim_upstream *up; + struct pim_upstream *up; - up = THREAD_ARG(t); + up = THREAD_ARG(t); - /* source is no longer active - pull the SA from MSDP's cache */ - pim_msdp_sa_local_del(&up->sg); - return 1; + /* source is no longer active - pull the SA from MSDP's cache */ + pim_msdp_sa_local_del(&up->sg); + return 1; } -void -pim_upstream_msdp_reg_timer_start(struct pim_upstream *up) +void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up) { - THREAD_OFF(up->t_msdp_reg_timer); - thread_add_timer(master, pim_upstream_msdp_reg_timer, up, - PIM_MSDP_REG_RXED_PERIOD, &up->t_msdp_reg_timer); + THREAD_OFF(up->t_msdp_reg_timer); + thread_add_timer(master, pim_upstream_msdp_reg_timer, up, + PIM_MSDP_REG_RXED_PERIOD, &up->t_msdp_reg_timer); - pim_msdp_sa_local_update(up); + pim_msdp_sa_local_update(up); } /* @@ -1187,28 +1159,25 @@ pim_upstream_msdp_reg_timer_start(struct pim_upstream *up) * SwitchToSptDesired(S,G) return true once a single packet has been * received for the source and group. */ -int -pim_upstream_switch_to_spt_desired (struct prefix_sg *sg) +int pim_upstream_switch_to_spt_desired(struct prefix_sg *sg) { - if (I_am_RP (sg->grp)) - return 1; + if (I_am_RP(sg->grp)) + return 1; - return 0; + return 0; } -int -pim_upstream_is_sg_rpt (struct pim_upstream *up) +int pim_upstream_is_sg_rpt(struct pim_upstream *up) { - struct listnode *chnode; - struct pim_ifchannel *ch; + struct listnode *chnode; + struct pim_ifchannel *ch; - for (ALL_LIST_ELEMENTS_RO(up->ifchannels, chnode, ch)) - { - if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) - return 1; - } + for (ALL_LIST_ELEMENTS_RO(up->ifchannels, chnode, ch)) { + if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) + return 1; + } - return 0; + return 0; } /* * After receiving a packet set SPTbit: @@ -1226,241 +1195,238 @@ pim_upstream_is_sg_rpt (struct pim_upstream *up) * } * } */ -void -pim_upstream_set_sptbit (struct pim_upstream *up, struct interface *incoming) +void pim_upstream_set_sptbit(struct pim_upstream *up, + struct interface *incoming) { - struct pim_upstream *starup = up->parent; - - // iif == RPF_interfvace(S) - if (up->rpf.source_nexthop.interface != incoming) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Incoming Interface: %s is different than RPF_interface(S) %s", - __PRETTY_FUNCTION__, incoming->name, up->rpf.source_nexthop.interface->name); - return; - } - - // AND JoinDesired(S,G) == TRUE - // FIXME - - // DirectlyConnected(S) == TRUE - if (pim_if_connected_to_source (up->rpf.source_nexthop.interface, up->sg.src)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s is directly connected to the source", __PRETTY_FUNCTION__, - up->sg_str); - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - return; - } - - // OR RPF_interface(S) != RPF_interface(RP(G)) - if (!starup || up->rpf.source_nexthop.interface != starup->rpf.source_nexthop.interface) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s RPF_interface(S) != RPF_interface(RP(G))", - __PRETTY_FUNCTION__, up->sg_str); - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - return; - } - - // OR inherited_olist(S,G,rpt) == NULL - if (pim_upstream_is_sg_rpt(up) && pim_upstream_empty_inherited_olist(up)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s OR inherited_olist(S,G,rpt) == NULL", __PRETTY_FUNCTION__, - up->sg_str); - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - return; - } - - // OR ( ( RPF'(S,G) == RPF'(*,G) ) AND - // ( RPF'(S,G) != NULL ) ) - if (up->parent && pim_rpf_is_same (&up->rpf, &up->parent->rpf)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s RPF'(S,G) is the same as RPF'(*,G)", __PRETTY_FUNCTION__, - up->sg_str); - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - return; - } - - return; + struct pim_upstream *starup = up->parent; + + // iif == RPF_interfvace(S) + if (up->rpf.source_nexthop.interface != incoming) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Incoming Interface: %s is different than RPF_interface(S) %s", + __PRETTY_FUNCTION__, incoming->name, + up->rpf.source_nexthop.interface->name); + return; + } + + // AND JoinDesired(S,G) == TRUE + // FIXME + + // DirectlyConnected(S) == TRUE + if (pim_if_connected_to_source(up->rpf.source_nexthop.interface, + up->sg.src)) { + if (PIM_DEBUG_TRACE) + zlog_debug("%s: %s is directly connected to the source", + __PRETTY_FUNCTION__, up->sg_str); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + // OR RPF_interface(S) != RPF_interface(RP(G)) + if (!starup + || up->rpf.source_nexthop + .interface != starup->rpf.source_nexthop.interface) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: %s RPF_interface(S) != RPF_interface(RP(G))", + __PRETTY_FUNCTION__, up->sg_str); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + // OR inherited_olist(S,G,rpt) == NULL + if (pim_upstream_is_sg_rpt(up) + && pim_upstream_empty_inherited_olist(up)) { + if (PIM_DEBUG_TRACE) + zlog_debug("%s: %s OR inherited_olist(S,G,rpt) == NULL", + __PRETTY_FUNCTION__, up->sg_str); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + // OR ( ( RPF'(S,G) == RPF'(*,G) ) AND + // ( RPF'(S,G) != NULL ) ) + if (up->parent && pim_rpf_is_same(&up->rpf, &up->parent->rpf)) { + if (PIM_DEBUG_TRACE) + zlog_debug("%s: %s RPF'(S,G) is the same as RPF'(*,G)", + __PRETTY_FUNCTION__, up->sg_str); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + return; } -const char * -pim_upstream_state2str (enum pim_upstream_state join_state) +const char *pim_upstream_state2str(enum pim_upstream_state join_state) { - switch (join_state) - { - case PIM_UPSTREAM_NOTJOINED: - return "NotJoined"; - break; - case PIM_UPSTREAM_JOINED: - return "Joined"; - break; - } - return "Unknown"; + switch (join_state) { + case PIM_UPSTREAM_NOTJOINED: + return "NotJoined"; + break; + case PIM_UPSTREAM_JOINED: + return "Joined"; + break; + } + return "Unknown"; } -const char * -pim_reg_state2str (enum pim_reg_state reg_state, char *state_str) +const char *pim_reg_state2str(enum pim_reg_state reg_state, char *state_str) { - switch (reg_state) - { - case PIM_REG_NOINFO: - strcpy (state_str, "RegNoInfo"); - break; - case PIM_REG_JOIN: - strcpy (state_str, "RegJoined"); - break; - case PIM_REG_JOIN_PENDING: - strcpy (state_str, "RegJoinPend"); - break; - case PIM_REG_PRUNE: - strcpy (state_str, "RegPrune"); - break; - default: - strcpy (state_str, "RegUnknown"); - } - return state_str; + switch (reg_state) { + case PIM_REG_NOINFO: + strcpy(state_str, "RegNoInfo"); + break; + case PIM_REG_JOIN: + strcpy(state_str, "RegJoined"); + break; + case PIM_REG_JOIN_PENDING: + strcpy(state_str, "RegJoinPend"); + break; + case PIM_REG_PRUNE: + strcpy(state_str, "RegPrune"); + break; + default: + strcpy(state_str, "RegUnknown"); + } + return state_str; } -static int -pim_upstream_register_stop_timer (struct thread *t) +static int pim_upstream_register_stop_timer(struct thread *t) { - struct pim_interface *pim_ifp; - struct pim_upstream *up; - struct pim_rpf *rpg; - struct ip ip_hdr; - up = THREAD_ARG (t); - - if (PIM_DEBUG_TRACE) - { - char state_str[PIM_REG_STATE_STR_LEN]; - zlog_debug ("%s: (S,G)=%s upstream register stop timer %s", - __PRETTY_FUNCTION__, up->sg_str, - pim_reg_state2str(up->reg_state, state_str)); - } - - switch (up->reg_state) - { - case PIM_REG_JOIN_PENDING: - up->reg_state = PIM_REG_JOIN; - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); - break; - case PIM_REG_JOIN: - break; - case PIM_REG_PRUNE: - pim_ifp = up->rpf.source_nexthop.interface->info; - if (!pim_ifp) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Interface: %s is not configured for pim", - __PRETTY_FUNCTION__, up->rpf.source_nexthop.interface->name); - return 0; - } - up->reg_state = PIM_REG_JOIN_PENDING; - pim_upstream_start_register_stop_timer (up, 1); - - if (((up->channel_oil->cc.lastused/100) > PIM_KEEPALIVE_PERIOD) && - (I_am_RP (up->sg.grp))) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while", __PRETTY_FUNCTION__); - return 0; + struct pim_interface *pim_ifp; + struct pim_upstream *up; + struct pim_rpf *rpg; + struct ip ip_hdr; + up = THREAD_ARG(t); + + if (PIM_DEBUG_TRACE) { + char state_str[PIM_REG_STATE_STR_LEN]; + zlog_debug("%s: (S,G)=%s upstream register stop timer %s", + __PRETTY_FUNCTION__, up->sg_str, + pim_reg_state2str(up->reg_state, state_str)); + } + + switch (up->reg_state) { + case PIM_REG_JOIN_PENDING: + up->reg_state = PIM_REG_JOIN; + pim_channel_add_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_PIM); + break; + case PIM_REG_JOIN: + break; + case PIM_REG_PRUNE: + pim_ifp = up->rpf.source_nexthop.interface->info; + if (!pim_ifp) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Interface: %s is not configured for pim", + __PRETTY_FUNCTION__, + up->rpf.source_nexthop.interface->name); + return 0; + } + up->reg_state = PIM_REG_JOIN_PENDING; + pim_upstream_start_register_stop_timer(up, 1); + + if (((up->channel_oil->cc.lastused / 100) + > PIM_KEEPALIVE_PERIOD) + && (I_am_RP(up->sg.grp))) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while", + __PRETTY_FUNCTION__); + return 0; + } + rpg = RP(up->sg.grp); + memset(&ip_hdr, 0, sizeof(struct ip)); + ip_hdr.ip_p = PIM_IP_PROTO_PIM; + ip_hdr.ip_hl = 5; + ip_hdr.ip_v = 4; + ip_hdr.ip_src = up->sg.src; + ip_hdr.ip_dst = up->sg.grp; + ip_hdr.ip_len = htons(20); + // checksum is broken + pim_register_send((uint8_t *)&ip_hdr, sizeof(struct ip), + pim_ifp->primary_address, rpg, 1, up); + break; + default: + break; } - rpg = RP (up->sg.grp); - memset (&ip_hdr, 0, sizeof (struct ip)); - ip_hdr.ip_p = PIM_IP_PROTO_PIM; - ip_hdr.ip_hl = 5; - ip_hdr.ip_v = 4; - ip_hdr.ip_src = up->sg.src; - ip_hdr.ip_dst = up->sg.grp; - ip_hdr.ip_len = htons (20); - // checksum is broken - pim_register_send ((uint8_t *)&ip_hdr, sizeof (struct ip), - pim_ifp->primary_address, rpg, 1, up); - break; - default: - break; - } - - return 0; + + return 0; } -void -pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_register) +void pim_upstream_start_register_stop_timer(struct pim_upstream *up, + int null_register) { - uint32_t time; - - THREAD_TIMER_OFF (up->t_rs_timer); - - if (!null_register) - { - uint32_t lower = (0.5 * PIM_REGISTER_SUPPRESSION_PERIOD); - uint32_t upper = (1.5 * PIM_REGISTER_SUPPRESSION_PERIOD); - time = lower + (random () % (upper - lower + 1)) - PIM_REGISTER_PROBE_PERIOD; - } - else - time = PIM_REGISTER_PROBE_PERIOD; - - if (PIM_DEBUG_TRACE) - { - zlog_debug ("%s: (S,G)=%s Starting upstream register stop timer %d", - __PRETTY_FUNCTION__, up->sg_str, time); - } - thread_add_timer(master, pim_upstream_register_stop_timer, up, time, - &up->t_rs_timer); + uint32_t time; + + THREAD_TIMER_OFF(up->t_rs_timer); + + if (!null_register) { + uint32_t lower = (0.5 * PIM_REGISTER_SUPPRESSION_PERIOD); + uint32_t upper = (1.5 * PIM_REGISTER_SUPPRESSION_PERIOD); + time = lower + (random() % (upper - lower + 1)) + - PIM_REGISTER_PROBE_PERIOD; + } else + time = PIM_REGISTER_PROBE_PERIOD; + + if (PIM_DEBUG_TRACE) { + zlog_debug( + "%s: (S,G)=%s Starting upstream register stop timer %d", + __PRETTY_FUNCTION__, up->sg_str, time); + } + thread_add_timer(master, pim_upstream_register_stop_timer, up, time, + &up->t_rs_timer); } -int -pim_upstream_inherited_olist_decide (struct pim_upstream *up) +int pim_upstream_inherited_olist_decide(struct pim_upstream *up) { - struct interface *ifp; - struct pim_interface *pim_ifp = NULL; - struct pim_ifchannel *ch, *starch; - struct listnode *node; - struct pim_upstream *starup = up->parent; - int output_intf = 0; - - if (up->rpf.source_nexthop.interface) - pim_ifp = up->rpf.source_nexthop.interface->info; - else - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: up %s RPF is not present", __PRETTY_FUNCTION__, up->sg_str); - } - if (pim_ifp && !up->channel_oil) - up->channel_oil = pim_channel_oil_add (&up->sg, pim_ifp->mroute_vif_index); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - if (!ifp->info) - continue; - - ch = pim_ifchannel_find (ifp, &up->sg); - - if (starup) - starch = pim_ifchannel_find (ifp, &starup->sg); - else - starch = NULL; - - if (!ch && !starch) - continue; - - if (pim_upstream_evaluate_join_desired_interface (up, ch, starch)) - { - int flag = PIM_OIF_FLAG_PROTO_PIM; - - if (!ch) - flag = PIM_OIF_FLAG_PROTO_STAR; - - pim_channel_add_oif (up->channel_oil, ifp, flag); - output_intf++; - } - } - - return output_intf; + struct interface *ifp; + struct pim_interface *pim_ifp = NULL; + struct pim_ifchannel *ch, *starch; + struct listnode *node; + struct pim_upstream *starup = up->parent; + int output_intf = 0; + + if (up->rpf.source_nexthop.interface) + pim_ifp = up->rpf.source_nexthop.interface->info; + else { + if (PIM_DEBUG_TRACE) + zlog_debug("%s: up %s RPF is not present", + __PRETTY_FUNCTION__, up->sg_str); + } + if (pim_ifp && !up->channel_oil) + up->channel_oil = + pim_channel_oil_add(&up->sg, pim_ifp->mroute_vif_index); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + if (!ifp->info) + continue; + + ch = pim_ifchannel_find(ifp, &up->sg); + + if (starup) + starch = pim_ifchannel_find(ifp, &starup->sg); + else + starch = NULL; + + if (!ch && !starch) + continue; + + if (pim_upstream_evaluate_join_desired_interface(up, ch, + starch)) { + int flag = PIM_OIF_FLAG_PROTO_PIM; + + if (!ch) + flag = PIM_OIF_FLAG_PROTO_STAR; + + pim_channel_add_oif(up->channel_oil, ifp, flag); + output_intf++; + } + } + + return output_intf; } /* @@ -1479,29 +1445,27 @@ pim_upstream_inherited_olist_decide (struct pim_upstream *up) * return 1 if there are any output interfaces * return 0 if there are not any output interfaces */ -int -pim_upstream_inherited_olist (struct pim_upstream *up) +int pim_upstream_inherited_olist(struct pim_upstream *up) { - int output_intf = pim_upstream_inherited_olist_decide (up); - - /* - * If we have output_intf switch state to Join and work like normal - * If we don't have an output_intf that means we are probably a - * switch on a stick so turn on forwarding to just accept the - * incoming packets so we don't bother the other stuff! - */ - if (output_intf) - pim_upstream_switch (up, PIM_UPSTREAM_JOINED); - else - forward_on (up); - - return output_intf; + int output_intf = pim_upstream_inherited_olist_decide(up); + + /* + * If we have output_intf switch state to Join and work like normal + * If we don't have an output_intf that means we are probably a + * switch on a stick so turn on forwarding to just accept the + * incoming packets so we don't bother the other stuff! + */ + if (output_intf) + pim_upstream_switch(up, PIM_UPSTREAM_JOINED); + else + forward_on(up); + + return output_intf; } -int -pim_upstream_empty_inherited_olist (struct pim_upstream *up) +int pim_upstream_empty_inherited_olist(struct pim_upstream *up) { - return pim_channel_oil_empty (up->channel_oil); + return pim_channel_oil_empty(up->channel_oil); } /* @@ -1510,58 +1474,54 @@ pim_upstream_empty_inherited_olist (struct pim_upstream *up) * set and see if the new neighbor allows * the join to be sent */ -void -pim_upstream_find_new_rpf (void) +void pim_upstream_find_new_rpf(void) { - struct listnode *up_node; - struct listnode *up_nextnode; - struct pim_upstream *up; - - /* - * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr - */ - for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) - { - if (pim_rpf_addr_is_inaddr_any(&up->rpf)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("Upstream %s without a path to send join, checking", - up->sg_str); - pim_rpf_update (up, NULL, 1); + struct listnode *up_node; + struct listnode *up_nextnode; + struct pim_upstream *up; + + /* + * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr + */ + for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { + if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "Upstream %s without a path to send join, checking", + up->sg_str); + pim_rpf_update(up, NULL, 1); + } } - } } -static unsigned int -pim_upstream_hash_key (void *arg) +static unsigned int pim_upstream_hash_key(void *arg) { - struct pim_upstream *up = (struct pim_upstream *)arg; + struct pim_upstream *up = (struct pim_upstream *)arg; - return jhash_2words (up->sg.src.s_addr, up->sg.grp.s_addr, 0); + return jhash_2words(up->sg.src.s_addr, up->sg.grp.s_addr, 0); } -void pim_upstream_terminate (void) +void pim_upstream_terminate(void) { - if (pim_upstream_list) - list_delete (pim_upstream_list); - pim_upstream_list = NULL; + if (pim_upstream_list) + list_delete(pim_upstream_list); + pim_upstream_list = NULL; - if (pim_upstream_hash) - hash_free (pim_upstream_hash); - pim_upstream_hash = NULL; + if (pim_upstream_hash) + hash_free(pim_upstream_hash); + pim_upstream_hash = NULL; } -static int -pim_upstream_equal (const void *arg1, const void *arg2) +static int pim_upstream_equal(const void *arg1, const void *arg2) { - const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; - const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; + const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; + const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; - if ((up1->sg.grp.s_addr == up2->sg.grp.s_addr) && - (up1->sg.src.s_addr == up2->sg.src.s_addr)) - return 1; + if ((up1->sg.grp.s_addr == up2->sg.grp.s_addr) + && (up1->sg.src.s_addr == up2->sg.src.s_addr)) + return 1; - return 0; + return 0; } /* rfc4601:section-4.2:"Data Packet Forwarding Rules" defines @@ -1580,129 +1540,128 @@ pim_upstream_equal (const void *arg1, const void *arg2) */ static bool pim_upstream_kat_start_ok(struct pim_upstream *up) { - /* "iif == RPF_interface(S)" check has to be done by the kernel or hw - * so we will skip that here */ - if (pim_if_connected_to_source(up->rpf.source_nexthop.interface, - up->sg.src)) { - return true; - } - - if ((up->join_state == PIM_UPSTREAM_JOINED) && - !pim_upstream_empty_inherited_olist(up)) { - /* XXX: I have added this RP check just for 3.2 and it's a digression from - * what rfc-4601 says. Till now we were only running KAT on FHR and RP and - * there is some angst around making the change to run it all routers that - * maintain the (S, G) state. This is tracked via CM-13601 and MUST be - * removed to handle spt turn-arounds correctly in a 3-tier clos */ - if (I_am_RP (up->sg.grp)) - return true; - } - - return false; + /* "iif == RPF_interface(S)" check has to be done by the kernel or hw + * so we will skip that here */ + if (pim_if_connected_to_source(up->rpf.source_nexthop.interface, + up->sg.src)) { + return true; + } + + if ((up->join_state == PIM_UPSTREAM_JOINED) + && !pim_upstream_empty_inherited_olist(up)) { + /* XXX: I have added this RP check just for 3.2 and it's a + * digression from + * what rfc-4601 says. Till now we were only running KAT on FHR + * and RP and + * there is some angst around making the change to run it all + * routers that + * maintain the (S, G) state. This is tracked via CM-13601 and + * MUST be + * removed to handle spt turn-arounds correctly in a 3-tier clos + */ + if (I_am_RP(up->sg.grp)) + return true; + } + + return false; } /* * Code to check and see if we've received packets on a S,G mroute * and if so to set the SPT bit appropriately */ -static void -pim_upstream_sg_running (void *arg) +static void pim_upstream_sg_running(void *arg) { - struct pim_upstream *up = (struct pim_upstream *)arg; - - // No packet can have arrived here if this is the case - if (!up->channel_oil || !up->channel_oil->installed) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s is not installed in mroute", - __PRETTY_FUNCTION__, up->sg_str); - return; - } - - /* - * This is a bit of a hack - * We've noted that we should rescan but - * we've missed the window for doing so in - * pim_zebra.c for some reason. I am - * only doing this at this point in time - * to get us up and working for the moment - */ - if (up->channel_oil->oil_inherited_rescan) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Handling unscanned inherited_olist for %s", __PRETTY_FUNCTION__, up->sg_str); - pim_upstream_inherited_olist_decide (up); - up->channel_oil->oil_inherited_rescan = 0; - } - pim_mroute_update_counters (up->channel_oil); - - // Have we seen packets? - if ((up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) && - (up->channel_oil->cc.lastused/100 > 30)) - { - if (PIM_DEBUG_TRACE) - { - zlog_debug ("%s: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)", - __PRETTY_FUNCTION__, up->sg_str, - up->channel_oil->cc.oldpktcnt, - up->channel_oil->cc.pktcnt, - up->channel_oil->cc.lastused/100); + struct pim_upstream *up = (struct pim_upstream *)arg; + + // No packet can have arrived here if this is the case + if (!up->channel_oil || !up->channel_oil->installed) { + if (PIM_DEBUG_TRACE) + zlog_debug("%s: %s is not installed in mroute", + __PRETTY_FUNCTION__, up->sg_str); + return; + } + + /* + * This is a bit of a hack + * We've noted that we should rescan but + * we've missed the window for doing so in + * pim_zebra.c for some reason. I am + * only doing this at this point in time + * to get us up and working for the moment + */ + if (up->channel_oil->oil_inherited_rescan) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Handling unscanned inherited_olist for %s", + __PRETTY_FUNCTION__, up->sg_str); + pim_upstream_inherited_olist_decide(up); + up->channel_oil->oil_inherited_rescan = 0; + } + pim_mroute_update_counters(up->channel_oil); + + // Have we seen packets? + if ((up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) + && (up->channel_oil->cc.lastused / 100 > 30)) { + if (PIM_DEBUG_TRACE) { + zlog_debug( + "%s: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)", + __PRETTY_FUNCTION__, up->sg_str, + up->channel_oil->cc.oldpktcnt, + up->channel_oil->cc.pktcnt, + up->channel_oil->cc.lastused / 100); + } + return; } - return; - } - - if (pim_upstream_kat_start_ok(up)) - { - /* Add a source reference to the stream if - * one doesn't already exist */ - if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("source reference created on kat restart %s", up->sg_str); - - pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, __PRETTY_FUNCTION__); - PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); - pim_upstream_fhr_kat_start(up); + + if (pim_upstream_kat_start_ok(up)) { + /* Add a source reference to the stream if + * one doesn't already exist */ + if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "source reference created on kat restart %s", + up->sg_str); + + pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, + __PRETTY_FUNCTION__); + PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); + pim_upstream_fhr_kat_start(up); + } + pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); + } else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) + pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); + + if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) { + pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface); } - pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); - } - else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) - pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); - - if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) - { - pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface); - } - return; + return; } -void -pim_upstream_add_lhr_star_pimreg (void) +void pim_upstream_add_lhr_star_pimreg(void) { - struct pim_upstream *up; - struct listnode *node; + struct pim_upstream *up; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up)) - { - if (up->sg.src.s_addr != INADDR_ANY) - continue; + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, node, up)) { + if (up->sg.src.s_addr != INADDR_ANY) + continue; - if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags)) - continue; + if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) + continue; - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); - } + pim_channel_add_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_IGMP); + } } -void -pim_upstream_spt_prefix_list_update (struct prefix_list *pl) +void pim_upstream_spt_prefix_list_update(struct prefix_list *pl) { - const char *pname = prefix_list_name (pl); + const char *pname = prefix_list_name(pl); - if (pimg->spt.plist && strcmp (pimg->spt.plist, pname) == 0) - { - pim_upstream_remove_lhr_star_pimreg (pname); - } + if (pimg->spt.plist && strcmp(pimg->spt.plist, pname) == 0) { + pim_upstream_remove_lhr_star_pimreg(pname); + } } /* @@ -1717,53 +1676,51 @@ pim_upstream_spt_prefix_list_update (struct prefix_list *pl) * the interface * */ -void -pim_upstream_remove_lhr_star_pimreg (const char *nlist) +void pim_upstream_remove_lhr_star_pimreg(const char *nlist) { - struct pim_upstream *up; - struct listnode *node; - struct prefix_list *np; - struct prefix g; - enum prefix_list_type apply_new; - - np = prefix_list_lookup (AFI_IP, nlist); - - g.family = AF_INET; - g.prefixlen = IPV4_MAX_PREFIXLEN; - - for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up)) - { - if (up->sg.src.s_addr != INADDR_ANY) - continue; - - if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags)) - continue; - - if (!nlist) - { - pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); - continue; - } - g.u.prefix4 = up->sg.grp; - apply_new = prefix_list_apply (np, &g); - if (apply_new == PREFIX_DENY) - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); - else - pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); - } + struct pim_upstream *up; + struct listnode *node; + struct prefix_list *np; + struct prefix g; + enum prefix_list_type apply_new; + + np = prefix_list_lookup(AFI_IP, nlist); + + g.family = AF_INET; + g.prefixlen = IPV4_MAX_PREFIXLEN; + + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, node, up)) { + if (up->sg.src.s_addr != INADDR_ANY) + continue; + + if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) + continue; + + if (!nlist) { + pim_channel_del_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_IGMP); + continue; + } + g.u.prefix4 = up->sg.grp; + apply_new = prefix_list_apply(np, &g); + if (apply_new == PREFIX_DENY) + pim_channel_add_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_IGMP); + else + pim_channel_del_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_IGMP); + } } -void -pim_upstream_init (void) +void pim_upstream_init(void) { - pim_upstream_sg_wheel = wheel_init (master, 31000, 100, - pim_upstream_hash_key, - pim_upstream_sg_running); - pim_upstream_hash = hash_create_size (8192, pim_upstream_hash_key, - pim_upstream_equal, NULL); - - pim_upstream_list = list_new (); - pim_upstream_list->del = (void (*)(void *)) pim_upstream_free; - pim_upstream_list->cmp = pim_upstream_compare; - + pim_upstream_sg_wheel = + wheel_init(master, 31000, 100, pim_upstream_hash_key, + pim_upstream_sg_running); + pim_upstream_hash = hash_create_size(8192, pim_upstream_hash_key, + pim_upstream_equal, NULL); + + pim_upstream_list = list_new(); + pim_upstream_list->del = (void (*)(void *))pim_upstream_free; + pim_upstream_list->cmp = pim_upstream_compare; } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index acb4b17c7..b6a9729f0 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -70,100 +70,102 @@ #define PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_LHR) enum pim_upstream_state { - PIM_UPSTREAM_NOTJOINED, - PIM_UPSTREAM_JOINED, + PIM_UPSTREAM_NOTJOINED, + PIM_UPSTREAM_JOINED, }; enum pim_reg_state { - PIM_REG_NOINFO, - PIM_REG_JOIN, - PIM_REG_JOIN_PENDING, - PIM_REG_PRUNE, + PIM_REG_NOINFO, + PIM_REG_JOIN, + PIM_REG_JOIN_PENDING, + PIM_REG_PRUNE, }; enum pim_upstream_sptbit { - PIM_UPSTREAM_SPTBIT_FALSE, - PIM_UPSTREAM_SPTBIT_TRUE + PIM_UPSTREAM_SPTBIT_FALSE, + PIM_UPSTREAM_SPTBIT_TRUE }; /* Upstream (S,G) channel in Joined state - + (S,G) in the "Not Joined" state is not represented - + See RFC 4601: 4.5.7. Sending (S,G) Join/Prune Message */ struct pim_upstream { - struct pim_upstream *parent; - struct in_addr upstream_addr;/* Who we are talking to */ - struct in_addr upstream_register; /*Who we received a register from*/ - struct prefix_sg sg; /* (S,G) group key */ - char sg_str[PIM_SG_LEN]; - uint32_t flags; - struct channel_oil *channel_oil; - struct list *sources; - struct list *ifchannels; - - enum pim_upstream_state join_state; - enum pim_reg_state reg_state; - enum pim_upstream_sptbit sptbit; - - int ref_count; - - struct pim_rpf rpf; - - struct thread *t_join_timer; - - /* - * RST(S,G) - */ - struct thread *t_rs_timer; + struct pim_upstream *parent; + struct in_addr upstream_addr; /* Who we are talking to */ + struct in_addr upstream_register; /*Who we received a register from*/ + struct prefix_sg sg; /* (S,G) group key */ + char sg_str[PIM_SG_LEN]; + uint32_t flags; + struct channel_oil *channel_oil; + struct list *sources; + struct list *ifchannels; + + enum pim_upstream_state join_state; + enum pim_reg_state reg_state; + enum pim_upstream_sptbit sptbit; + + int ref_count; + + struct pim_rpf rpf; + + struct thread *t_join_timer; + + /* + * RST(S,G) + */ + struct thread *t_rs_timer; #define PIM_REGISTER_SUPPRESSION_PERIOD (60) #define PIM_REGISTER_PROBE_PERIOD (15) - /* - * KAT(S,G) - */ - struct thread *t_ka_timer; + /* + * KAT(S,G) + */ + struct thread *t_ka_timer; #define PIM_KEEPALIVE_PERIOD (210) #define PIM_RP_KEEPALIVE_PERIOD ( 3 * qpim_register_suppress_time + qpim_register_probe_time ) - /* on the RP we restart a timer to indicate if registers are being rxed for - * SG. This is needed by MSDP to determine its local SA cache */ - struct thread *t_msdp_reg_timer; + /* on the RP we restart a timer to indicate if registers are being rxed + * for + * SG. This is needed by MSDP to determine its local SA cache */ + struct thread *t_msdp_reg_timer; #define PIM_MSDP_REG_RXED_PERIOD (3 * (1.5 * qpim_register_suppress_time)) - int64_t state_transition; /* Record current state uptime */ + int64_t state_transition; /* Record current state uptime */ }; struct list *pim_upstream_list; struct hash *pim_upstream_hash; void pim_upstream_free(struct pim_upstream *up); -struct pim_upstream *pim_upstream_find (struct prefix_sg *sg); -struct pim_upstream *pim_upstream_find_or_add (struct prefix_sg *sg, - struct interface *ifp, int flags, - const char *name); -struct pim_upstream *pim_upstream_add (struct prefix_sg *sg, - struct interface *ifp, int flags, - const char *name); -void pim_upstream_ref (struct pim_upstream *up, int flags, const char *name); -struct pim_upstream *pim_upstream_del(struct pim_upstream *up, const char *name); +struct pim_upstream *pim_upstream_find(struct prefix_sg *sg); +struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg, + struct interface *ifp, int flags, + const char *name); +struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, + struct interface *ifp, int flags, + const char *name); +void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name); +struct pim_upstream *pim_upstream_del(struct pim_upstream *up, + const char *name); int pim_upstream_evaluate_join_desired(struct pim_upstream *up); int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up, - struct pim_ifchannel *ch, - struct pim_ifchannel *starch); + struct pim_ifchannel *ch, + struct pim_ifchannel *starch); void pim_upstream_update_join_desired(struct pim_upstream *up); void pim_upstream_join_suppress(struct pim_upstream *up, - struct in_addr rpf_addr, - int holdtime); + struct in_addr rpf_addr, int holdtime); void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label, - struct pim_upstream *up); + struct pim_upstream *up); -void pim_upstream_join_timer_restart(struct pim_upstream *up, struct pim_rpf *old); +void pim_upstream_join_timer_restart(struct pim_upstream *up, + struct pim_rpf *old); void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr); void pim_upstream_rpf_interface_changed(struct pim_upstream *up, struct interface *old_rpf_ifp); @@ -171,40 +173,44 @@ void pim_upstream_rpf_interface_changed(struct pim_upstream *up, void pim_upstream_update_could_assert(struct pim_upstream *up); void pim_upstream_update_my_assert_metric(struct pim_upstream *up); -void pim_upstream_keep_alive_timer_start (struct pim_upstream *up, uint32_t time); +void pim_upstream_keep_alive_timer_start(struct pim_upstream *up, + uint32_t time); -int pim_upstream_switch_to_spt_desired (struct prefix_sg *sg); +int pim_upstream_switch_to_spt_desired(struct prefix_sg *sg); #define SwitchToSptDesired(sg) pim_upstream_switch_to_spt_desired (sg) -int pim_upstream_is_sg_rpt (struct pim_upstream *up); +int pim_upstream_is_sg_rpt(struct pim_upstream *up); -void pim_upstream_set_sptbit (struct pim_upstream *up, struct interface *incoming); +void pim_upstream_set_sptbit(struct pim_upstream *up, + struct interface *incoming); -void pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_register); +void pim_upstream_start_register_stop_timer(struct pim_upstream *up, + int null_register); -void pim_upstream_send_join (struct pim_upstream *up); +void pim_upstream_send_join(struct pim_upstream *up); -void pim_upstream_switch (struct pim_upstream *up, enum pim_upstream_state new_state); +void pim_upstream_switch(struct pim_upstream *up, + enum pim_upstream_state new_state); -const char *pim_upstream_state2str (enum pim_upstream_state join_state); +const char *pim_upstream_state2str(enum pim_upstream_state join_state); #define PIM_REG_STATE_STR_LEN 12 -const char *pim_reg_state2str (enum pim_reg_state state, char *state_str); +const char *pim_reg_state2str(enum pim_reg_state state, char *state_str); -int pim_upstream_inherited_olist_decide (struct pim_upstream *up); -int pim_upstream_inherited_olist (struct pim_upstream *up); -int pim_upstream_empty_inherited_olist (struct pim_upstream *up); +int pim_upstream_inherited_olist_decide(struct pim_upstream *up); +int pim_upstream_inherited_olist(struct pim_upstream *up); +int pim_upstream_empty_inherited_olist(struct pim_upstream *up); -void pim_upstream_find_new_rpf (void); +void pim_upstream_find_new_rpf(void); void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up); -void pim_upstream_init (void); -void pim_upstream_terminate (void); +void pim_upstream_init(void); +void pim_upstream_terminate(void); -void join_timer_start (struct pim_upstream *up); -int pim_upstream_compare (void *arg1, void *arg2); -void pim_upstream_register_reevaluate (void); +void join_timer_start(struct pim_upstream *up); +int pim_upstream_compare(void *arg1, void *arg2); +void pim_upstream_register_reevaluate(void); -void pim_upstream_add_lhr_star_pimreg (void); -void pim_upstream_remove_lhr_star_pimreg (const char *nlist); +void pim_upstream_add_lhr_star_pimreg(void); +void pim_upstream_remove_lhr_star_pimreg(const char *nlist); -void pim_upstream_spt_prefix_list_update (struct prefix_list *pl); +void pim_upstream_spt_prefix_list_update(struct prefix_list *pl); #endif /* PIM_UPSTREAM_H */ diff --git a/pimd/pim_util.c b/pimd/pim_util.c index 139c0e3fb..c2e4b2a46 100644 --- a/pimd/pim_util.c +++ b/pimd/pim_util.c @@ -26,18 +26,18 @@ /* RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) - + If QQIC < 128, QQI = QQIC If QQIC >= 128, QQI = (mant | 0x10) << (exp + 3) - + 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+ |1| exp | mant | +-+-+-+-+-+-+-+-+ - + Since exp=0..7 then (exp+3)=3..10, then QQI has one of the following bit patterns: - + exp=0: QQI = 0000.0000.1MMM.M000 exp=1: QQI = 0000.0001.MMMM.0000 ... @@ -48,33 +48,32 @@ */ uint8_t igmp_msg_encode16to8(uint16_t value) { - uint8_t code; - - if (value < 128) { - code = value; - } - else { - uint16_t mask = 0x4000; - uint8_t exp; - uint16_t mant; - for (exp = 7; exp > 0; --exp) { - if (mask & value) - break; - mask >>= 1; - } - mant = 0x000F & (value >> (exp + 3)); - code = ((uint8_t) 1 << 7) | ((uint8_t) exp << 4) | (uint8_t) mant; - } - - return code; + uint8_t code; + + if (value < 128) { + code = value; + } else { + uint16_t mask = 0x4000; + uint8_t exp; + uint16_t mant; + for (exp = 7; exp > 0; --exp) { + if (mask & value) + break; + mask >>= 1; + } + mant = 0x000F & (value >> (exp + 3)); + code = ((uint8_t)1 << 7) | ((uint8_t)exp << 4) | (uint8_t)mant; + } + + return code; } /* RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) - + If QQIC < 128, QQI = QQIC If QQIC >= 128, QQI = (mant | 0x10) << (exp + 3) - + 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+ |1| exp | mant | @@ -82,64 +81,57 @@ uint8_t igmp_msg_encode16to8(uint16_t value) */ uint16_t igmp_msg_decode8to16(uint8_t code) { - uint16_t value; - - if (code < 128) { - value = code; - } - else { - uint16_t mant = (code & 0x0F); - uint8_t exp = (code & 0x70) >> 4; - value = (mant | 0x10) << (exp + 3); - } - - return value; + uint16_t value; + + if (code < 128) { + value = code; + } else { + uint16_t mant = (code & 0x0F); + uint8_t exp = (code & 0x70) >> 4; + value = (mant | 0x10) << (exp + 3); + } + + return value; } void pim_pkt_dump(const char *label, const uint8_t *buf, int size) { - zlog_debug("%s: pkt dump size=%d", - label, - size); - zlog_hexdump(buf, size); + zlog_debug("%s: pkt dump size=%d", label, size); + zlog_hexdump(buf, size); } -int -pim_is_group_224_0_0_0_24 (struct in_addr group_addr) +int pim_is_group_224_0_0_0_24(struct in_addr group_addr) { - static int first = 1; - static struct prefix group_224; - struct prefix group; + static int first = 1; + static struct prefix group_224; + struct prefix group; - if (first) - { - str2prefix ("224.0.0.0/24", &group_224); - first = 0; - } + if (first) { + str2prefix("224.0.0.0/24", &group_224); + first = 0; + } - group.family = AF_INET; - group.u.prefix4 = group_addr; - group.prefixlen = 32; + group.family = AF_INET; + group.u.prefix4 = group_addr; + group.prefixlen = 32; - return prefix_match (&group_224, &group); + return prefix_match(&group_224, &group); } -int -pim_is_group_224_4 (struct in_addr group_addr) +int pim_is_group_224_4(struct in_addr group_addr) { - static int first = 1; - static struct prefix group_all; - struct prefix group; + static int first = 1; + static struct prefix group_all; + struct prefix group; - if (first) - { - str2prefix ("224.0.0.0/4", &group_all); - first = 0; - } + if (first) { + str2prefix("224.0.0.0/4", &group_all); + first = 0; + } - group.family = AF_INET; - group.u.prefix4 = group_addr; - group.prefixlen = 32; + group.family = AF_INET; + group.u.prefix4 = group_addr; + group.prefixlen = 32; - return prefix_match (&group_all, &group); + return prefix_match(&group_all, &group); } diff --git a/pimd/pim_util.h b/pimd/pim_util.h index 478800520..1b319cfe4 100644 --- a/pimd/pim_util.h +++ b/pimd/pim_util.h @@ -31,6 +31,6 @@ uint16_t igmp_msg_decode8to16(uint8_t code); void pim_pkt_dump(const char *label, const uint8_t *buf, int size); -int pim_is_group_224_0_0_0_24 (struct in_addr group_addr); -int pim_is_group_224_4 (struct in_addr group_addr); +int pim_is_group_224_0_0_0_24(struct in_addr group_addr); +int pim_is_group_224_4(struct in_addr group_addr); #endif /* PIM_UTIL_H */ diff --git a/pimd/pim_version.c b/pimd/pim_version.c index 1da4b9663..439f745ac 100644 --- a/pimd/pim_version.c +++ b/pimd/pim_version.c @@ -21,4 +21,4 @@ #include "pim_version.h" -const char * const PIMD_VERSION = PIMD_VERSION_STR; +const char *const PIMD_VERSION = PIMD_VERSION_STR; diff --git a/pimd/pim_version.h b/pimd/pim_version.h index 589c6f68a..c45d01a13 100644 --- a/pimd/pim_version.h +++ b/pimd/pim_version.h @@ -22,6 +22,6 @@ #define PIMD_VERSION_STR "0.166" -const char * const PIMD_VERSION; +const char *const PIMD_VERSION; #endif /* PIM_VERSION_H */ diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 81b49c630..a78776791 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -40,284 +40,287 @@ #include "pim_ssm.h" #include "pim_bfd.h" -int -pim_debug_config_write (struct vty *vty) +int pim_debug_config_write(struct vty *vty) { - int writes = 0; - - if (PIM_DEBUG_MSDP_EVENTS) { - vty_out (vty, "debug msdp events\n"); - ++writes; - } - if (PIM_DEBUG_MSDP_PACKETS) { - vty_out (vty, "debug msdp packets\n"); - ++writes; - } - if (PIM_DEBUG_MSDP_INTERNAL) { - vty_out (vty, "debug msdp internal\n"); - ++writes; - } - if (PIM_DEBUG_IGMP_EVENTS) { - vty_out (vty, "debug igmp events\n"); - ++writes; - } - if (PIM_DEBUG_IGMP_PACKETS) { - vty_out (vty, "debug igmp packets\n"); - ++writes; - } - if (PIM_DEBUG_IGMP_TRACE) { - vty_out (vty, "debug igmp trace\n"); - ++writes; - } - if (PIM_DEBUG_IGMP_TRACE_DETAIL) { - vty_out (vty, "debug igmp trace detail\n"); - ++writes; - } - - if (PIM_DEBUG_MROUTE) { - vty_out (vty, "debug mroute\n"); - ++writes; - } - - if (PIM_DEBUG_MROUTE_DETAIL) { - vty_out (vty, "debug mroute detail\n"); - ++writes; - } - - if (PIM_DEBUG_PIM_EVENTS) { - vty_out (vty, "debug pim events\n"); - ++writes; - } - if (PIM_DEBUG_PIM_PACKETS) { - vty_out (vty, "debug pim packets\n"); - ++writes; - } - if (PIM_DEBUG_PIM_PACKETDUMP_SEND) { - vty_out (vty, "debug pim packet-dump send\n"); - ++writes; - } - if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { - vty_out (vty, "debug pim packet-dump receive\n"); - ++writes; - } - - if (PIM_DEBUG_PIM_TRACE) { - vty_out (vty, "debug pim trace\n"); - ++writes; - } - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - vty_out (vty, "debug pim trace detail\n"); - ++writes; - } - - if (PIM_DEBUG_ZEBRA) { - vty_out (vty, "debug pim zebra\n"); - ++writes; - } - - if (PIM_DEBUG_SSMPINGD) { - vty_out (vty, "debug ssmpingd\n"); - ++writes; - } - - if (PIM_DEBUG_PIM_HELLO) { - vty_out (vty, "debug pim packets hello\n"); - ++writes; - } - - if (PIM_DEBUG_PIM_J_P) { - vty_out (vty, "debug pim packets joins\n"); - ++writes; - } - - if (PIM_DEBUG_PIM_REG) { - vty_out (vty, "debug pim packets register\n"); - ++writes; - } - - if (PIM_DEBUG_STATIC) { - vty_out (vty, "debug pim static\n"); - ++writes; - } - - return writes; + int writes = 0; + + if (PIM_DEBUG_MSDP_EVENTS) { + vty_out(vty, "debug msdp events\n"); + ++writes; + } + if (PIM_DEBUG_MSDP_PACKETS) { + vty_out(vty, "debug msdp packets\n"); + ++writes; + } + if (PIM_DEBUG_MSDP_INTERNAL) { + vty_out(vty, "debug msdp internal\n"); + ++writes; + } + if (PIM_DEBUG_IGMP_EVENTS) { + vty_out(vty, "debug igmp events\n"); + ++writes; + } + if (PIM_DEBUG_IGMP_PACKETS) { + vty_out(vty, "debug igmp packets\n"); + ++writes; + } + if (PIM_DEBUG_IGMP_TRACE) { + vty_out(vty, "debug igmp trace\n"); + ++writes; + } + if (PIM_DEBUG_IGMP_TRACE_DETAIL) { + vty_out(vty, "debug igmp trace detail\n"); + ++writes; + } + + if (PIM_DEBUG_MROUTE) { + vty_out(vty, "debug mroute\n"); + ++writes; + } + + if (PIM_DEBUG_MROUTE_DETAIL) { + vty_out(vty, "debug mroute detail\n"); + ++writes; + } + + if (PIM_DEBUG_PIM_EVENTS) { + vty_out(vty, "debug pim events\n"); + ++writes; + } + if (PIM_DEBUG_PIM_PACKETS) { + vty_out(vty, "debug pim packets\n"); + ++writes; + } + if (PIM_DEBUG_PIM_PACKETDUMP_SEND) { + vty_out(vty, "debug pim packet-dump send\n"); + ++writes; + } + if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { + vty_out(vty, "debug pim packet-dump receive\n"); + ++writes; + } + + if (PIM_DEBUG_PIM_TRACE) { + vty_out(vty, "debug pim trace\n"); + ++writes; + } + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + vty_out(vty, "debug pim trace detail\n"); + ++writes; + } + + if (PIM_DEBUG_ZEBRA) { + vty_out(vty, "debug pim zebra\n"); + ++writes; + } + + if (PIM_DEBUG_SSMPINGD) { + vty_out(vty, "debug ssmpingd\n"); + ++writes; + } + + if (PIM_DEBUG_PIM_HELLO) { + vty_out(vty, "debug pim packets hello\n"); + ++writes; + } + + if (PIM_DEBUG_PIM_J_P) { + vty_out(vty, "debug pim packets joins\n"); + ++writes; + } + + if (PIM_DEBUG_PIM_REG) { + vty_out(vty, "debug pim packets register\n"); + ++writes; + } + + if (PIM_DEBUG_STATIC) { + vty_out(vty, "debug pim static\n"); + ++writes; + } + + return writes; } int pim_global_config_write(struct vty *vty) { - int writes = 0; - struct pim_ssm *ssm = pimg->ssm_info; - - writes += pim_msdp_config_write (vty); - - if (!pimg->send_v6_secondary) - { - vty_out (vty, "no ip pim send-v6-secondary\n"); - ++writes; - } - - writes += pim_rp_config_write (vty); - - if (qpim_register_suppress_time != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) - { - vty_out (vty, "ip pim register-suppress-time %d\n", - qpim_register_suppress_time); - ++writes; - } - if (qpim_t_periodic != PIM_DEFAULT_T_PERIODIC) - { - vty_out (vty, "ip pim join-prune-interval %d\n", - qpim_t_periodic); - ++writes; - } - if (qpim_keep_alive_time != PIM_KEEPALIVE_PERIOD) - { - vty_out (vty, "ip pim keep-alive-timer %d\n", - qpim_keep_alive_time); - ++writes; - } - if (qpim_packet_process != PIM_DEFAULT_PACKET_PROCESS) - { - vty_out (vty, "ip pim packets %d\n", - qpim_packet_process); - ++writes; - } - if (ssm->plist_name) - { - vty_out (vty, "ip pim ssm prefix-list %s\n", - ssm->plist_name); - ++writes; - } - if (pimg->spt.switchover == PIM_SPT_INFINITY) - { - if (pimg->spt.plist) - vty_out (vty, "ip pim spt-switchover infinity-and-beyond prefix-list %s\n", - pimg->spt.plist); - else - vty_out (vty,"ip pim spt-switchover infinity-and-beyond\n"); - ++writes; - } - if (qpim_ecmp_rebalance_enable) - { - vty_out (vty, "ip pim ecmp rebalance\n"); - ++writes; - } - else if (qpim_ecmp_enable) - { - vty_out (vty, "ip pim ecmp\n"); - ++writes; - } - if (qpim_ssmpingd_list) { - struct listnode *node; - struct ssmpingd_sock *ss; - vty_out (vty, "!\n"); - ++writes; - for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str)); - vty_out (vty, "ip ssmpingd %s\n", source_str); - ++writes; - } - } - - return writes; -} + int writes = 0; + struct pim_ssm *ssm = pimg->ssm_info; -int pim_interface_config_write(struct vty *vty) -{ - int writes = 0; - struct listnode *node; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - - /* IF name */ - vty_out (vty, "interface %s\n", ifp->name); - ++writes; - - if (ifp->info) { - struct pim_interface *pim_ifp = ifp->info; - - if (PIM_IF_TEST_PIM(pim_ifp->options)) { - vty_out (vty, " ip pim sm\n"); - ++writes; - } - - /* IF ip pim drpriority */ - if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) { - vty_out (vty, " ip pim drpriority %u\n",pim_ifp->pim_dr_priority); - ++writes; - } - - /* IF ip pim hello */ - if (pim_ifp->pim_hello_period != PIM_DEFAULT_HELLO_PERIOD) { - vty_out(vty, " ip pim hello %d", pim_ifp->pim_hello_period); - if (pim_ifp->pim_default_holdtime != -1) - vty_out(vty, " %d", pim_ifp->pim_default_holdtime); - vty_out (vty, "\n"); - } - - /* update source */ - if (PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", pim_ifp->update_source, src_str, - sizeof(src_str)); - vty_out (vty, " ip pim use-source %s\n", src_str); - ++writes; - } - - /* IF ip igmp */ - if (PIM_IF_TEST_IGMP(pim_ifp->options)) { - vty_out (vty, " ip igmp\n"); - ++writes; - } - - /* ip igmp version */ - if (pim_ifp->igmp_version != IGMP_DEFAULT_VERSION) - { - vty_out (vty, " ip igmp version %d\n", - pim_ifp->igmp_version); - ++writes; - } - - /* IF ip igmp query-interval */ - if (pim_ifp->igmp_default_query_interval != IGMP_GENERAL_QUERY_INTERVAL) - { - vty_out (vty, " ip igmp query-interval %d\n", - pim_ifp->igmp_default_query_interval); - ++writes; + writes += pim_msdp_config_write(vty); + + if (!pimg->send_v6_secondary) { + vty_out(vty, "no ip pim send-v6-secondary\n"); + ++writes; } - /* IF ip igmp query-max-response-time */ - if (pim_ifp->igmp_query_max_response_time_dsec != IGMP_QUERY_MAX_RESPONSE_TIME_DSEC) - { - vty_out (vty, " ip igmp query-max-response-time %d\n", - pim_ifp->igmp_query_max_response_time_dsec); - ++writes; + writes += pim_rp_config_write(vty); + + if (qpim_register_suppress_time + != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) { + vty_out(vty, "ip pim register-suppress-time %d\n", + qpim_register_suppress_time); + ++writes; } + if (qpim_t_periodic != PIM_DEFAULT_T_PERIODIC) { + vty_out(vty, "ip pim join-prune-interval %d\n", + qpim_t_periodic); + ++writes; + } + if (qpim_keep_alive_time != PIM_KEEPALIVE_PERIOD) { + vty_out(vty, "ip pim keep-alive-timer %d\n", + qpim_keep_alive_time); + ++writes; + } + if (qpim_packet_process != PIM_DEFAULT_PACKET_PROCESS) { + vty_out(vty, "ip pim packets %d\n", qpim_packet_process); + ++writes; + } + if (ssm->plist_name) { + vty_out(vty, "ip pim ssm prefix-list %s\n", ssm->plist_name); + ++writes; + } + if (pimg->spt.switchover == PIM_SPT_INFINITY) { + if (pimg->spt.plist) + vty_out(vty, + "ip pim spt-switchover infinity-and-beyond prefix-list %s\n", + pimg->spt.plist); + else + vty_out(vty, + "ip pim spt-switchover infinity-and-beyond\n"); + ++writes; + } + if (qpim_ecmp_rebalance_enable) { + vty_out(vty, "ip pim ecmp rebalance\n"); + ++writes; + } else if (qpim_ecmp_enable) { + vty_out(vty, "ip pim ecmp\n"); + ++writes; + } + if (qpim_ssmpingd_list) { + struct listnode *node; + struct ssmpingd_sock *ss; + vty_out(vty, "!\n"); + ++writes; + for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", ss->source_addr, source_str, + sizeof(source_str)); + vty_out(vty, "ip ssmpingd %s\n", source_str); + ++writes; + } + } + + return writes; +} - /* IF ip igmp join */ - if (pim_ifp->igmp_join_list) { +int pim_interface_config_write(struct vty *vty) +{ + int writes = 0; struct listnode *node; - struct igmp_join *ij; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, node, ij)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", ij->group_addr, group_str, sizeof(group_str)); - inet_ntop(AF_INET, &ij->source_addr, source_str, sizeof(source_str)); - vty_out (vty, " ip igmp join %s %s\n", - group_str,source_str); - ++writes; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + + /* IF name */ + vty_out(vty, "interface %s\n", ifp->name); + ++writes; + + if (ifp->info) { + struct pim_interface *pim_ifp = ifp->info; + + if (PIM_IF_TEST_PIM(pim_ifp->options)) { + vty_out(vty, " ip pim sm\n"); + ++writes; + } + + /* IF ip pim drpriority */ + if (pim_ifp->pim_dr_priority + != PIM_DEFAULT_DR_PRIORITY) { + vty_out(vty, " ip pim drpriority %u\n", + pim_ifp->pim_dr_priority); + ++writes; + } + + /* IF ip pim hello */ + if (pim_ifp->pim_hello_period + != PIM_DEFAULT_HELLO_PERIOD) { + vty_out(vty, " ip pim hello %d", + pim_ifp->pim_hello_period); + if (pim_ifp->pim_default_holdtime != -1) + vty_out(vty, " %d", + pim_ifp->pim_default_holdtime); + vty_out(vty, "\n"); + } + + /* update source */ + if (PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", pim_ifp->update_source, + src_str, sizeof(src_str)); + vty_out(vty, " ip pim use-source %s\n", + src_str); + ++writes; + } + + /* IF ip igmp */ + if (PIM_IF_TEST_IGMP(pim_ifp->options)) { + vty_out(vty, " ip igmp\n"); + ++writes; + } + + /* ip igmp version */ + if (pim_ifp->igmp_version != IGMP_DEFAULT_VERSION) { + vty_out(vty, " ip igmp version %d\n", + pim_ifp->igmp_version); + ++writes; + } + + /* IF ip igmp query-interval */ + if (pim_ifp->igmp_default_query_interval + != IGMP_GENERAL_QUERY_INTERVAL) { + vty_out(vty, " ip igmp query-interval %d\n", + pim_ifp->igmp_default_query_interval); + ++writes; + } + + /* IF ip igmp query-max-response-time */ + if (pim_ifp->igmp_query_max_response_time_dsec + != IGMP_QUERY_MAX_RESPONSE_TIME_DSEC) { + vty_out(vty, + " ip igmp query-max-response-time %d\n", + pim_ifp->igmp_query_max_response_time_dsec); + ++writes; + } + + /* IF ip igmp join */ + if (pim_ifp->igmp_join_list) { + struct listnode *node; + struct igmp_join *ij; + for (ALL_LIST_ELEMENTS_RO( + pim_ifp->igmp_join_list, node, + ij)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", ij->group_addr, + group_str, + sizeof(group_str)); + inet_ntop(AF_INET, &ij->source_addr, + source_str, + sizeof(source_str)); + vty_out(vty, " ip igmp join %s %s\n", + group_str, source_str); + ++writes; + } + } + + writes += pim_static_write_mroute(vty, ifp); + } + vty_out(vty, "!\n"); + ++writes; + /* PIM BFD write */ + pim_bfd_write_config(vty, ifp); } - } - - writes += pim_static_write_mroute (vty, ifp); - } - vty_out (vty, "!\n"); - ++writes; - /* PIM BFD write */ - pim_bfd_write_config (vty, ifp); - } - return writes; + return writes; } diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index b4fff9712..c5cca7d1b 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -58,906 +58,950 @@ static struct zclient *zclient = NULL; static int pim_router_id_update_zebra(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct prefix router_id; + struct prefix router_id; - zebra_router_id_update_read(zclient->ibuf, &router_id); + zebra_router_id_update_read(zclient->ibuf, &router_id); - return 0; + return 0; } static int pim_zebra_if_add(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - - /* - zebra api adds/dels interfaces using the same call - interface_add_read below, see comments in lib/zclient.c - */ - ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); - if (!ifp) - return 0; - - if (PIM_DEBUG_ZEBRA) { - zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, - ifp->mtu, if_is_operative(ifp)); - } - - if (if_is_operative(ifp)) - pim_if_addr_add_all(ifp); - - return 0; + struct interface *ifp; + + /* + zebra api adds/dels interfaces using the same call + interface_add_read below, see comments in lib/zclient.c + */ + ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); + if (!ifp) + return 0; + + if (PIM_DEBUG_ZEBRA) { + zlog_debug( + "%s: %s index %d flags %ld metric %d mtu %d operative %d", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, + (long)ifp->flags, ifp->metric, ifp->mtu, + if_is_operative(ifp)); + } + + if (if_is_operative(ifp)) + pim_if_addr_add_all(ifp); + + return 0; } static int pim_zebra_if_del(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - - /* - zebra api adds/dels interfaces using the same call - interface_add_read below, see comments in lib/zclient.c - - comments in lib/zclient.c seem to indicate that calling - zebra_interface_add_read is the correct call, but that - results in an attemted out of bounds read which causes - pimd to assert. Other clients use zebra_interface_state_read - and it appears to work just fine. - */ - ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); - if (!ifp) - return 0; - - if (PIM_DEBUG_ZEBRA) { - zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, - ifp->mtu, if_is_operative(ifp)); - } - - if (!if_is_operative(ifp)) - pim_if_addr_del_all(ifp); - - return 0; + struct interface *ifp; + + /* + zebra api adds/dels interfaces using the same call + interface_add_read below, see comments in lib/zclient.c + + comments in lib/zclient.c seem to indicate that calling + zebra_interface_add_read is the correct call, but that + results in an attemted out of bounds read which causes + pimd to assert. Other clients use zebra_interface_state_read + and it appears to work just fine. + */ + ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); + if (!ifp) + return 0; + + if (PIM_DEBUG_ZEBRA) { + zlog_debug( + "%s: %s index %d flags %ld metric %d mtu %d operative %d", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, + (long)ifp->flags, ifp->metric, ifp->mtu, + if_is_operative(ifp)); + } + + if (!if_is_operative(ifp)) + pim_if_addr_del_all(ifp); + + return 0; } static int pim_zebra_if_state_up(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - - /* - zebra api notifies interface up/down events by using the same call - zebra_interface_state_read below, see comments in lib/zclient.c - */ - ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); - if (!ifp) - return 0; - - if (PIM_DEBUG_ZEBRA) { - zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, - ifp->mtu, if_is_operative(ifp)); - } - - if (if_is_operative(ifp)) { - /* - pim_if_addr_add_all() suffices for bringing up both IGMP and PIM - */ - pim_if_addr_add_all(ifp); - } - - return 0; + struct interface *ifp; + + /* + zebra api notifies interface up/down events by using the same call + zebra_interface_state_read below, see comments in lib/zclient.c + */ + ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); + if (!ifp) + return 0; + + if (PIM_DEBUG_ZEBRA) { + zlog_debug( + "%s: %s index %d flags %ld metric %d mtu %d operative %d", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, + (long)ifp->flags, ifp->metric, ifp->mtu, + if_is_operative(ifp)); + } + + if (if_is_operative(ifp)) { + /* + pim_if_addr_add_all() suffices for bringing up both IGMP and + PIM + */ + pim_if_addr_add_all(ifp); + } + + return 0; } static int pim_zebra_if_state_down(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - - /* - zebra api notifies interface up/down events by using the same call - zebra_interface_state_read below, see comments in lib/zclient.c - */ - ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); - if (!ifp) - return 0; - - if (PIM_DEBUG_ZEBRA) { - zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, - ifp->mtu, if_is_operative(ifp)); - } - - if (!if_is_operative(ifp)) { - pim_ifchannel_delete_all(ifp); - /* - pim_if_addr_del_all() suffices for shutting down IGMP, - but not for shutting down PIM - */ - pim_if_addr_del_all(ifp); - - /* - pim_sock_delete() closes the socket, stops read and timer threads, - and kills all neighbors. - */ - if (ifp->info) { - pim_sock_delete(ifp, "link down"); - } - } - - if (ifp->info) - pim_if_del_vif(ifp); - - return 0; + struct interface *ifp; + + /* + zebra api notifies interface up/down events by using the same call + zebra_interface_state_read below, see comments in lib/zclient.c + */ + ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); + if (!ifp) + return 0; + + if (PIM_DEBUG_ZEBRA) { + zlog_debug( + "%s: %s index %d flags %ld metric %d mtu %d operative %d", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, + (long)ifp->flags, ifp->metric, ifp->mtu, + if_is_operative(ifp)); + } + + if (!if_is_operative(ifp)) { + pim_ifchannel_delete_all(ifp); + /* + pim_if_addr_del_all() suffices for shutting down IGMP, + but not for shutting down PIM + */ + pim_if_addr_del_all(ifp); + + /* + pim_sock_delete() closes the socket, stops read and timer + threads, + and kills all neighbors. + */ + if (ifp->info) { + pim_sock_delete(ifp, "link down"); + } + } + + if (ifp->info) + pim_if_del_vif(ifp); + + return 0; } #ifdef PIM_DEBUG_IFADDR_DUMP static void dump_if_address(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - - zlog_debug("%s %s: interface %s addresses:", - __FILE__, __PRETTY_FUNCTION__, - ifp->name); - - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - continue; - - zlog_debug("%s %s: interface %s address %s %s", - __FILE__, __PRETTY_FUNCTION__, - ifp->name, - inet_ntoa(p->u.prefix4), - CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? - "secondary" : "primary"); - } + struct connected *ifc; + struct listnode *node; + + zlog_debug("%s %s: interface %s addresses:", __FILE__, + __PRETTY_FUNCTION__, ifp->name); + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) + continue; + + zlog_debug("%s %s: interface %s address %s %s", __FILE__, + __PRETTY_FUNCTION__, ifp->name, + inet_ntoa(p->u.prefix4), + CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) + ? "secondary" + : "primary"); + } } #endif static int pim_zebra_if_address_add(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct connected *c; - struct prefix *p; - struct pim_interface *pim_ifp; - - /* - zebra api notifies address adds/dels events by using the same call - interface_add_read below, see comments in lib/zclient.c - - zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...) - will add address to interface list by calling - connected_add_by_prefix() - */ - c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); - if (!c) - return 0; - - pim_ifp = c->ifp->info; - p = c->address; - - if (PIM_DEBUG_ZEBRA) { - char buf[BUFSIZ]; - prefix2str(p, buf, BUFSIZ); - zlog_debug("%s: %s connected IP address %s flags %u %s", - __PRETTY_FUNCTION__, - c->ifp->name, buf, c->flags, - CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary"); - + struct connected *c; + struct prefix *p; + struct pim_interface *pim_ifp; + + /* + zebra api notifies address adds/dels events by using the same call + interface_add_read below, see comments in lib/zclient.c + + zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...) + will add address to interface list by calling + connected_add_by_prefix() + */ + c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); + if (!c) + return 0; + + pim_ifp = c->ifp->info; + p = c->address; + + if (PIM_DEBUG_ZEBRA) { + char buf[BUFSIZ]; + prefix2str(p, buf, BUFSIZ); + zlog_debug("%s: %s connected IP address %s flags %u %s", + __PRETTY_FUNCTION__, c->ifp->name, buf, c->flags, + CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) + ? "secondary" + : "primary"); + #ifdef PIM_DEBUG_IFADDR_DUMP - dump_if_address(c->ifp); + dump_if_address(c->ifp); #endif - } + } - if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) { - /* trying to add primary address */ + if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) { + /* trying to add primary address */ - struct in_addr primary_addr = pim_find_primary_addr(c->ifp); - if (p->family != AF_INET || primary_addr.s_addr != p->u.prefix4.s_addr) { - if (PIM_DEBUG_ZEBRA) { - /* but we had a primary address already */ + struct in_addr primary_addr = pim_find_primary_addr(c->ifp); + if (p->family != AF_INET + || primary_addr.s_addr != p->u.prefix4.s_addr) { + if (PIM_DEBUG_ZEBRA) { + /* but we had a primary address already */ - char buf[BUFSIZ]; + char buf[BUFSIZ]; - prefix2str(p, buf, BUFSIZ); + prefix2str(p, buf, BUFSIZ); - zlog_warn("%s: %s : forcing secondary flag on %s", - __PRETTY_FUNCTION__, - c->ifp->name, buf); - } - SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY); - } - } + zlog_warn( + "%s: %s : forcing secondary flag on %s", + __PRETTY_FUNCTION__, c->ifp->name, buf); + } + SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY); + } + } - pim_if_addr_add(c); - if (pim_ifp) - pim_rp_check_on_if_add(pim_ifp); + pim_if_addr_add(c); + if (pim_ifp) + pim_rp_check_on_if_add(pim_ifp); - if (if_is_loopback (c->ifp)) - { - struct listnode *ifnode; - struct interface *ifp; + if (if_is_loopback(c->ifp)) { + struct listnode *ifnode; + struct interface *ifp; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) - { - if (!if_is_loopback (ifp) && if_is_operative (ifp)) - pim_if_addr_add_all (ifp); - } - } + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, + ifp)) { + if (!if_is_loopback(ifp) && if_is_operative(ifp)) + pim_if_addr_add_all(ifp); + } + } - return 0; + return 0; } static int pim_zebra_if_address_del(int command, struct zclient *client, zebra_size_t length, vrf_id_t vrf_id) { - struct connected *c; - struct prefix *p; - - /* - zebra api notifies address adds/dels events by using the same call - interface_add_read below, see comments in lib/zclient.c - - zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...) - will remove address from interface list by calling - connected_delete_by_prefix() - */ - c = zebra_interface_address_read(command, client->ibuf, vrf_id); - if (!c) - return 0; - - p = c->address; - if (p->family == AF_INET) - { - if (PIM_DEBUG_ZEBRA) { - char buf[BUFSIZ]; - prefix2str(p, buf, BUFSIZ); - zlog_debug("%s: %s disconnected IP address %s flags %u %s", - __PRETTY_FUNCTION__, - c->ifp->name, buf, c->flags, - CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary"); + struct connected *c; + struct prefix *p; + + /* + zebra api notifies address adds/dels events by using the same call + interface_add_read below, see comments in lib/zclient.c + + zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...) + will remove address from interface list by calling + connected_delete_by_prefix() + */ + c = zebra_interface_address_read(command, client->ibuf, vrf_id); + if (!c) + return 0; + + p = c->address; + if (p->family == AF_INET) { + if (PIM_DEBUG_ZEBRA) { + char buf[BUFSIZ]; + prefix2str(p, buf, BUFSIZ); + zlog_debug( + "%s: %s disconnected IP address %s flags %u %s", + __PRETTY_FUNCTION__, c->ifp->name, buf, + c->flags, + CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) + ? "secondary" + : "primary"); #ifdef PIM_DEBUG_IFADDR_DUMP - dump_if_address(c->ifp); + dump_if_address(c->ifp); #endif - } + } - pim_if_addr_del(c, 0); - pim_rp_setup(); - pim_i_am_rp_re_evaluate(); - } + pim_if_addr_del(c, 0); + pim_rp_setup(); + pim_i_am_rp_re_evaluate(); + } - connected_free (c); - return 0; + connected_free(c); + return 0; } static void scan_upstream_rpf_cache() { - struct listnode *up_node; - struct listnode *ifnode; - struct listnode *up_nextnode; - struct listnode *node; - struct pim_upstream *up; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { - enum pim_rpf_result rpf_result; - struct pim_rpf old; - struct prefix nht_p; - - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; - pim_resolve_upstream_nh (&nht_p); - - old.source_nexthop.interface = up->rpf.source_nexthop.interface; - old.source_nexthop.nbr = up->rpf.source_nexthop.nbr; - rpf_result = pim_rpf_update(up, &old, 0); - - if (rpf_result == PIM_RPF_FAILURE) - continue; - - if (rpf_result == PIM_RPF_CHANGED) { - struct pim_neighbor *nbr; - - nbr = pim_neighbor_find (old.source_nexthop.interface, - old.rpf_addr.u.prefix4); - if (nbr) - pim_jp_agg_remove_group (nbr->upstream_jp_agg, up); - - /* - * We have detected a case where we might need to rescan - * the inherited o_list so do it. - */ - if (up->channel_oil->oil_inherited_rescan) - { - pim_upstream_inherited_olist_decide (up); - up->channel_oil->oil_inherited_rescan = 0; - } - - if (up->join_state == PIM_UPSTREAM_JOINED) { - /* - * If we come up real fast we can be here - * where the mroute has not been installed - * so install it. - */ - if (!up->channel_oil->installed) - pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); - - /* - * RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages - * - * Transitions from Joined State - * - * RPF'(S,G) changes not due to an Assert - * - * The upstream (S,G) state machine remains in Joined - * state. Send Join(S,G) to the new upstream neighbor, which is - * the new value of RPF'(S,G). Send Prune(S,G) to the old - * upstream neighbor, which is the old value of RPF'(S,G). Set - * the Join Timer (JT) to expire after t_periodic seconds. - */ - pim_jp_agg_switch_interface (&old, &up->rpf, up); - - pim_upstream_join_timer_restart(up, &old); - } /* up->join_state == PIM_UPSTREAM_JOINED */ - - /* FIXME can join_desired actually be changed by pim_rpf_update() - returning PIM_RPF_CHANGED ? */ - pim_upstream_update_join_desired(up); - - } /* PIM_RPF_CHANGED */ - - } /* for (qpim_upstream_list) */ - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) - if (ifp->info) - { - struct pim_interface *pim_ifp = ifp->info; - struct pim_iface_upstream_switch *us; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, node, us)) - { - struct pim_rpf rpf; - rpf.source_nexthop.interface = ifp; - rpf.rpf_addr.u.prefix4 = us->address; - pim_joinprune_send(&rpf, us->us); - pim_jp_agg_clear_group(us->us); - } - } + struct listnode *up_node; + struct listnode *ifnode; + struct listnode *up_nextnode; + struct listnode *node; + struct pim_upstream *up; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { + enum pim_rpf_result rpf_result; + struct pim_rpf old; + struct prefix nht_p; + + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; + pim_resolve_upstream_nh(&nht_p); + + old.source_nexthop.interface = up->rpf.source_nexthop.interface; + old.source_nexthop.nbr = up->rpf.source_nexthop.nbr; + rpf_result = pim_rpf_update(up, &old, 0); + + if (rpf_result == PIM_RPF_FAILURE) + continue; + + if (rpf_result == PIM_RPF_CHANGED) { + struct pim_neighbor *nbr; + + nbr = pim_neighbor_find(old.source_nexthop.interface, + old.rpf_addr.u.prefix4); + if (nbr) + pim_jp_agg_remove_group(nbr->upstream_jp_agg, + up); + + /* + * We have detected a case where we might need to rescan + * the inherited o_list so do it. + */ + if (up->channel_oil->oil_inherited_rescan) { + pim_upstream_inherited_olist_decide(up); + up->channel_oil->oil_inherited_rescan = 0; + } + + if (up->join_state == PIM_UPSTREAM_JOINED) { + /* + * If we come up real fast we can be here + * where the mroute has not been installed + * so install it. + */ + if (!up->channel_oil->installed) + pim_mroute_add(up->channel_oil, + __PRETTY_FUNCTION__); + + /* + * RFC 4601: 4.5.7. Sending (S,G) Join/Prune + * Messages + * + * Transitions from Joined State + * + * RPF'(S,G) changes not due to an Assert + * + * The upstream (S,G) state machine remains in + * Joined + * state. Send Join(S,G) to the new upstream + * neighbor, which is + * the new value of RPF'(S,G). Send Prune(S,G) + * to the old + * upstream neighbor, which is the old value of + * RPF'(S,G). Set + * the Join Timer (JT) to expire after + * t_periodic seconds. + */ + pim_jp_agg_switch_interface(&old, &up->rpf, up); + + pim_upstream_join_timer_restart(up, &old); + } /* up->join_state == PIM_UPSTREAM_JOINED */ + + /* FIXME can join_desired actually be changed by + pim_rpf_update() + returning PIM_RPF_CHANGED ? */ + pim_upstream_update_join_desired(up); + + } /* PIM_RPF_CHANGED */ + + } /* for (qpim_upstream_list) */ + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) + if (ifp->info) { + struct pim_interface *pim_ifp = ifp->info; + struct pim_iface_upstream_switch *us; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, + node, us)) { + struct pim_rpf rpf; + rpf.source_nexthop.interface = ifp; + rpf.rpf_addr.u.prefix4 = us->address; + pim_joinprune_send(&rpf, us->us); + pim_jp_agg_clear_group(us->us); + } + } } -void -pim_scan_individual_oil (struct channel_oil *c_oil, int in_vif_index) +void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index) { - struct in_addr vif_source; - int input_iface_vif_index; - int old_vif_index; - - if (!pim_rp_set_upstream_addr (&vif_source, c_oil->oil.mfcc_origin, c_oil->oil.mfcc_mcastgrp)) - return; - - if (in_vif_index) - input_iface_vif_index = in_vif_index; - else - { - struct prefix src, grp; - - src.family = AF_INET; - src.prefixlen = IPV4_MAX_BITLEN; - src.u.prefix4 = vif_source; - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp; - - if (PIM_DEBUG_ZEBRA) - { - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_debug ("%s: channel_oil (%s, %s) upstream info is not present.", - __PRETTY_FUNCTION__, source_str, group_str); - } - input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(vif_source, &src, &grp); - } - - if (input_iface_vif_index < 1) - { - if (PIM_DEBUG_ZEBRA) - { - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_debug("%s %s: could not find input interface(%d) for (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, c_oil->oil.mfcc_parent, - source_str, group_str); - } - pim_mroute_del (c_oil, __PRETTY_FUNCTION__); - return; - } - - if (input_iface_vif_index == c_oil->oil.mfcc_parent) - { - if (!c_oil->installed) - pim_mroute_add (c_oil, __PRETTY_FUNCTION__); - - /* RPF unchanged */ - return; - } - - if (PIM_DEBUG_ZEBRA) - { - struct interface *old_iif = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); - struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_debug("%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - old_iif->name, c_oil->oil.mfcc_parent, - new_iif->name, input_iface_vif_index); - } - - /* new iif loops to existing oif ? */ - if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) - { - struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); - - if (PIM_DEBUG_ZEBRA) { - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_debug("%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - new_iif->name, input_iface_vif_index); - } - } - - /* update iif vif_index */ - old_vif_index = c_oil->oil.mfcc_parent; - c_oil->oil.mfcc_parent = input_iface_vif_index; - - /* update kernel multicast forwarding cache (MFC) */ - if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) - { - if (PIM_DEBUG_MROUTE) - { - /* just log warning */ - struct interface *old_iif = pim_if_find_by_vif_index(old_vif_index); - struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_debug("%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - old_iif ? old_iif->name : "<old_iif?>", c_oil->oil.mfcc_parent, - new_iif ? new_iif->name : "<new_iif?>", input_iface_vif_index); - } - } + struct in_addr vif_source; + int input_iface_vif_index; + int old_vif_index; + + if (!pim_rp_set_upstream_addr(&vif_source, c_oil->oil.mfcc_origin, + c_oil->oil.mfcc_mcastgrp)) + return; + + if (in_vif_index) + input_iface_vif_index = in_vif_index; + else { + struct prefix src, grp; + + src.family = AF_INET; + src.prefixlen = IPV4_MAX_BITLEN; + src.u.prefix4 = vif_source; + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp; + + if (PIM_DEBUG_ZEBRA) { + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + zlog_debug( + "%s: channel_oil (%s, %s) upstream info is not present.", + __PRETTY_FUNCTION__, source_str, group_str); + } + input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index( + vif_source, &src, &grp); + } + + if (input_iface_vif_index < 1) { + if (PIM_DEBUG_ZEBRA) { + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + zlog_debug( + "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, + c_oil->oil.mfcc_parent, source_str, group_str); + } + pim_mroute_del(c_oil, __PRETTY_FUNCTION__); + return; + } + + if (input_iface_vif_index == c_oil->oil.mfcc_parent) { + if (!c_oil->installed) + pim_mroute_add(c_oil, __PRETTY_FUNCTION__); + + /* RPF unchanged */ + return; + } + + if (PIM_DEBUG_ZEBRA) { + struct interface *old_iif = + pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); + struct interface *new_iif = + pim_if_find_by_vif_index(input_iface_vif_index); + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, + sizeof(group_str)); + zlog_debug( + "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d", + __FILE__, __PRETTY_FUNCTION__, source_str, group_str, + old_iif->name, c_oil->oil.mfcc_parent, new_iif->name, + input_iface_vif_index); + } + + /* new iif loops to existing oif ? */ + if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) { + struct interface *new_iif = + pim_if_find_by_vif_index(input_iface_vif_index); + + if (PIM_DEBUG_ZEBRA) { + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + zlog_debug( + "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d", + __FILE__, __PRETTY_FUNCTION__, source_str, + group_str, new_iif->name, + input_iface_vif_index); + } + } + + /* update iif vif_index */ + old_vif_index = c_oil->oil.mfcc_parent; + c_oil->oil.mfcc_parent = input_iface_vif_index; + + /* update kernel multicast forwarding cache (MFC) */ + if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) { + if (PIM_DEBUG_MROUTE) { + /* just log warning */ + struct interface *old_iif = + pim_if_find_by_vif_index(old_vif_index); + struct interface *new_iif = + pim_if_find_by_vif_index(input_iface_vif_index); + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + zlog_debug( + "%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d", + __FILE__, __PRETTY_FUNCTION__, source_str, + group_str, + old_iif ? old_iif->name : "<old_iif?>", + c_oil->oil.mfcc_parent, + new_iif ? new_iif->name : "<new_iif?>", + input_iface_vif_index); + } + } } void pim_scan_oil() { - struct listnode *node; - struct listnode *nextnode; - struct channel_oil *c_oil; - ifindex_t ifindex; - int vif_index = 0; - - qpim_scan_oil_last = pim_time_monotonic_sec(); - ++qpim_scan_oil_events; - - for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil)) - { - if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) - { - ifindex = c_oil->up->rpf.source_nexthop.interface->ifindex; - vif_index = pim_if_find_vifindex_by_ifindex (ifindex); - /* Pass Current selected NH vif index to mroute download */ - if (vif_index) - pim_scan_individual_oil (c_oil, vif_index); - } - else - pim_scan_individual_oil (c_oil, 0); - } + struct listnode *node; + struct listnode *nextnode; + struct channel_oil *c_oil; + ifindex_t ifindex; + int vif_index = 0; + + qpim_scan_oil_last = pim_time_monotonic_sec(); + ++qpim_scan_oil_events; + + for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil)) { + if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) { + ifindex = c_oil->up->rpf.source_nexthop + .interface->ifindex; + vif_index = pim_if_find_vifindex_by_ifindex(ifindex); + /* Pass Current selected NH vif index to mroute download + */ + if (vif_index) + pim_scan_individual_oil(c_oil, vif_index); + } else + pim_scan_individual_oil(c_oil, 0); + } } static int on_rpf_cache_refresh(struct thread *t) { - /* update PIM protocol state */ - scan_upstream_rpf_cache(); + /* update PIM protocol state */ + scan_upstream_rpf_cache(); - /* update kernel multicast forwarding cache (MFC) */ - pim_scan_oil(); + /* update kernel multicast forwarding cache (MFC) */ + pim_scan_oil(); - qpim_rpf_cache_refresh_last = pim_time_monotonic_sec(); - ++qpim_rpf_cache_refresh_events; + qpim_rpf_cache_refresh_last = pim_time_monotonic_sec(); + ++qpim_rpf_cache_refresh_events; - //It is called as part of pim_neighbor_add - //pim_rp_setup (); - return 0; + // It is called as part of pim_neighbor_add + // pim_rp_setup (); + return 0; } void sched_rpf_cache_refresh(void) { - ++qpim_rpf_cache_refresh_requests; + ++qpim_rpf_cache_refresh_requests; - pim_rpf_set_refresh_time (); + pim_rpf_set_refresh_time(); - if (qpim_rpf_cache_refresher) { - /* Refresh timer is already running */ - return; - } + if (qpim_rpf_cache_refresher) { + /* Refresh timer is already running */ + return; + } - /* Start refresh timer */ + /* Start refresh timer */ - if (PIM_DEBUG_ZEBRA) { - zlog_debug("%s: triggering %ld msec timer", - __PRETTY_FUNCTION__, - qpim_rpf_cache_refresh_delay_msec); - } + if (PIM_DEBUG_ZEBRA) { + zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__, + qpim_rpf_cache_refresh_delay_msec); + } - thread_add_timer_msec(master, on_rpf_cache_refresh, 0, - qpim_rpf_cache_refresh_delay_msec, - &qpim_rpf_cache_refresher); + thread_add_timer_msec(master, on_rpf_cache_refresh, 0, + qpim_rpf_cache_refresh_delay_msec, + &qpim_rpf_cache_refresher); } -static void -pim_zebra_connected (struct zclient *zclient) +static void pim_zebra_connected(struct zclient *zclient) { - /* Send the client registration */ - bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); - zclient_send_reg_requests (zclient, VRF_DEFAULT); + zclient_send_reg_requests(zclient, VRF_DEFAULT); } void pim_zebra_init(void) { - int i; + int i; #ifdef HAVE_TCP_ZEBRA - zlog_notice("zclient update contacting ZEBRA daemon at socket TCP %s,%d", "127.0.0.1", ZEBRA_PORT); + zlog_notice( + "zclient update contacting ZEBRA daemon at socket TCP %s,%d", + "127.0.0.1", ZEBRA_PORT); #else - zlog_notice("zclient update contacting ZEBRA daemon at socket UNIX %s", zclient_serv_path_get()); + zlog_notice("zclient update contacting ZEBRA daemon at socket UNIX %s", + zclient_serv_path_get()); #endif - /* Socket for receiving updates from Zebra daemon */ - zclient = zclient_new (master); - - zclient->zebra_connected = pim_zebra_connected; - zclient->router_id_update = pim_router_id_update_zebra; - zclient->interface_add = pim_zebra_if_add; - zclient->interface_delete = pim_zebra_if_del; - zclient->interface_up = pim_zebra_if_state_up; - zclient->interface_down = pim_zebra_if_state_down; - zclient->interface_address_add = pim_zebra_if_address_add; - zclient->interface_address_delete = pim_zebra_if_address_del; - zclient->nexthop_update = pim_parse_nexthop_update; - - zclient_init(zclient, ZEBRA_ROUTE_PIM, 0); - if (PIM_DEBUG_PIM_TRACE) { - zlog_info("zclient_init cleared redistribution request"); - } - - zassert(zclient->redist_default == ZEBRA_ROUTE_PIM); - - /* Request all redistribution */ - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (i == zclient->redist_default) - continue; - vrf_bitmap_set (zclient->redist[AFI_IP][i], VRF_DEFAULT);; - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: requesting redistribution for %s (%i)", - __PRETTY_FUNCTION__, zebra_route_string(i), i); - } - } - - /* Request default information */ - zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, - zclient, VRF_DEFAULT); - - if (PIM_DEBUG_PIM_TRACE) { - zlog_info("%s: requesting default information redistribution", - __PRETTY_FUNCTION__); - - zlog_notice("%s: zclient update socket initialized", - __PRETTY_FUNCTION__); - } - - zclient_lookup_new(); + /* Socket for receiving updates from Zebra daemon */ + zclient = zclient_new(master); + + zclient->zebra_connected = pim_zebra_connected; + zclient->router_id_update = pim_router_id_update_zebra; + zclient->interface_add = pim_zebra_if_add; + zclient->interface_delete = pim_zebra_if_del; + zclient->interface_up = pim_zebra_if_state_up; + zclient->interface_down = pim_zebra_if_state_down; + zclient->interface_address_add = pim_zebra_if_address_add; + zclient->interface_address_delete = pim_zebra_if_address_del; + zclient->nexthop_update = pim_parse_nexthop_update; + + zclient_init(zclient, ZEBRA_ROUTE_PIM, 0); + if (PIM_DEBUG_PIM_TRACE) { + zlog_info("zclient_init cleared redistribution request"); + } + + zassert(zclient->redist_default == ZEBRA_ROUTE_PIM); + + /* Request all redistribution */ + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (i == zclient->redist_default) + continue; + vrf_bitmap_set(zclient->redist[AFI_IP][i], VRF_DEFAULT); + ; + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: requesting redistribution for %s (%i)", + __PRETTY_FUNCTION__, zebra_route_string(i), + i); + } + } + + /* Request default information */ + zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, + VRF_DEFAULT); + + if (PIM_DEBUG_PIM_TRACE) { + zlog_info("%s: requesting default information redistribution", + __PRETTY_FUNCTION__); + + zlog_notice("%s: zclient update socket initialized", + __PRETTY_FUNCTION__); + } + + zclient_lookup_new(); } void igmp_anysource_forward_start(struct igmp_group *group) { - struct igmp_source *source; - struct in_addr src_addr = { .s_addr = 0 }; - /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ - zassert(group->group_filtermode_isexcl); - zassert(listcount(group->group_source_list) < 1); - - source = source_new (group, src_addr); - if (!source) - { - zlog_warn ("%s: Failure to create * source", __PRETTY_FUNCTION__); - return; - } - - igmp_source_forward_start (source); + struct igmp_source *source; + struct in_addr src_addr = {.s_addr = 0}; + /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ + zassert(group->group_filtermode_isexcl); + zassert(listcount(group->group_source_list) < 1); + + source = source_new(group, src_addr); + if (!source) { + zlog_warn("%s: Failure to create * source", + __PRETTY_FUNCTION__); + return; + } + + igmp_source_forward_start(source); } void igmp_anysource_forward_stop(struct igmp_group *group) { - struct igmp_source *source; - struct in_addr star = { .s_addr = 0 }; + struct igmp_source *source; + struct in_addr star = {.s_addr = 0}; - source = igmp_find_source_by_addr (group, star); - if (source) - igmp_source_forward_stop (source); + source = igmp_find_source_by_addr(group, star); + if (source) + igmp_source_forward_stop(source); } -static void -igmp_source_forward_reevaluate_one(struct igmp_source *source) +static void igmp_source_forward_reevaluate_one(struct igmp_source *source) { - struct prefix_sg sg; - struct igmp_group *group = source->source_group; - struct pim_ifchannel *ch; - - if ((source->source_addr.s_addr != INADDR_ANY) || - !IGMP_SOURCE_TEST_FORWARDING (source->source_flags)) - return; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = source->source_addr; - sg.grp = group->group_addr; - - ch = pim_ifchannel_find (group->group_igmp_sock->interface, &sg); - if (pim_is_grp_ssm (group->group_addr)) - { - /* If SSM group withdraw local membership */ - if (ch && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug ("local membership del for %s as G is now SSM", - pim_str_sg_dump (&sg)); - pim_ifchannel_local_membership_del (group->group_igmp_sock->interface, &sg); - } - } - else - { - /* If ASM group add local membership */ - if (!ch || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug ("local membership add for %s as G is now ASM", - pim_str_sg_dump (&sg)); - pim_ifchannel_local_membership_add (group->group_igmp_sock->interface, &sg); - } - } + struct prefix_sg sg; + struct igmp_group *group = source->source_group; + struct pim_ifchannel *ch; + + if ((source->source_addr.s_addr != INADDR_ANY) + || !IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) + return; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = source->source_addr; + sg.grp = group->group_addr; + + ch = pim_ifchannel_find(group->group_igmp_sock->interface, &sg); + if (pim_is_grp_ssm(group->group_addr)) { + /* If SSM group withdraw local membership */ + if (ch + && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "local membership del for %s as G is now SSM", + pim_str_sg_dump(&sg)); + pim_ifchannel_local_membership_del( + group->group_igmp_sock->interface, &sg); + } + } else { + /* If ASM group add local membership */ + if (!ch + || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "local membership add for %s as G is now ASM", + pim_str_sg_dump(&sg)); + pim_ifchannel_local_membership_add( + group->group_igmp_sock->interface, &sg); + } + } } -void -igmp_source_forward_reevaluate_all(void) +void igmp_source_forward_reevaluate_all(void) { - struct listnode *ifnode; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) - { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *sock_node; - struct igmp_sock *igmp; - - if (!pim_ifp) - continue; - - /* scan igmp sockets */ - for (ALL_LIST_ELEMENTS_RO (pim_ifp->igmp_socket_list, sock_node, igmp)) - { - struct listnode *grpnode; - struct igmp_group *grp; - - /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO (igmp->igmp_group_list, grpnode, grp)) - { - struct listnode *srcnode; - struct igmp_source *src; - - /* scan group sources */ - for (ALL_LIST_ELEMENTS_RO (grp->group_source_list, - srcnode, src)) - { - igmp_source_forward_reevaluate_one (src); - } /* scan group sources */ - } /* scan igmp groups */ - } /* scan igmp sockets */ - } /* scan interfaces */ + struct listnode *ifnode; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + struct pim_interface *pim_ifp = ifp->info; + struct listnode *sock_node; + struct igmp_sock *igmp; + + if (!pim_ifp) + continue; + + /* scan igmp sockets */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, + igmp)) { + struct listnode *grpnode; + struct igmp_group *grp; + + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, + grpnode, grp)) { + struct listnode *srcnode; + struct igmp_source *src; + + /* scan group sources */ + for (ALL_LIST_ELEMENTS_RO( + grp->group_source_list, srcnode, + src)) { + igmp_source_forward_reevaluate_one(src); + } /* scan group sources */ + } /* scan igmp groups */ + } /* scan igmp sockets */ + } /* scan interfaces */ } void igmp_source_forward_start(struct igmp_source *source) { - struct igmp_group *group; - struct prefix_sg sg; - int result; - int input_iface_vif_index = 0; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = source->source_addr; - sg.grp = source->source_group->group_addr; - - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), - source->source_group->group_igmp_sock->fd, - source->source_group->group_igmp_sock->interface->name, - IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); - } - - /* Prevent IGMP interface from installing multicast route multiple - times */ - if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { - return; - } - - group = source->source_group; - - if (!source->source_channel_oil) { - struct in_addr vif_source; - struct pim_interface *pim_oif; - struct prefix nht_p, src, grp; - int ret = 0; - struct pim_nexthop_cache out_pnc; - struct pim_nexthop nexthop; - struct pim_upstream *up = NULL; - - if (!pim_rp_set_upstream_addr (&vif_source, source->source_addr, sg.grp)) - return; - - /* Register addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = vif_source; - memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache)); - - src.family = AF_INET; - src.prefixlen = IPV4_MAX_BITLEN; - src.u.prefix4 = vif_source; //RP or Src address - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = sg.grp; - - if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1) - { - if (out_pnc.nexthop_num) - { - up = pim_upstream_find (&sg); - memset (&nexthop, 0, sizeof (struct pim_nexthop)); - if (up) - memcpy (&nexthop, &up->rpf.source_nexthop, sizeof (struct pim_nexthop)); - //Compute PIM RPF using Cached nexthop - pim_ecmp_nexthop_search (&out_pnc, &nexthop, &src, &grp, 0); - if (nexthop.interface) - input_iface_vif_index = pim_if_find_vifindex_by_ifindex (nexthop.interface->ifindex); - } - else - { - if (PIM_DEBUG_ZEBRA) - { - char buf1[INET_ADDRSTRLEN]; - char buf2[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", nht_p.u.prefix4, buf1, sizeof(buf1)); - pim_inet4_dump("<source?>", grp.u.prefix4, buf2, sizeof(buf2)); - zlog_debug ("%s: NHT Nexthop not found for addr %s grp %s" , - __PRETTY_FUNCTION__, buf1, buf2); - } - } - } - else - input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(vif_source, &src, &grp); - - if (PIM_DEBUG_ZEBRA) - { - char buf2[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", vif_source, buf2, sizeof(buf2)); - zlog_debug ("%s: NHT %s vif_source %s vif_index:%d ", __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), buf2, input_iface_vif_index); - } - - if (input_iface_vif_index < 1) { - if (PIM_DEBUG_IGMP_TRACE) - { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); - zlog_debug("%s %s: could not find input interface for source %s", - __FILE__, __PRETTY_FUNCTION__, - source_str); + struct igmp_group *group; + struct prefix_sg sg; + int result; + int input_iface_vif_index = 0; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = source->source_addr; + sg.grp = source->source_group->group_addr; + + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + source->source_group->group_igmp_sock->fd, + source->source_group->group_igmp_sock->interface->name, + IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); + } + + /* Prevent IGMP interface from installing multicast route multiple + times */ + if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { + return; } - return; - } - - /* - Protect IGMP against adding looped MFC entries created by both - source and receiver attached to the same interface. See TODO - T22. - */ - pim_oif = source->source_group->group_igmp_sock->interface->info; - if (!pim_oif) { - if (PIM_DEBUG_IGMP_TRACE) - { - zlog_debug("%s: multicast not enabled on oif=%s ?", - __PRETTY_FUNCTION__, - source->source_group->group_igmp_sock->interface->name); + + group = source->source_group; + + if (!source->source_channel_oil) { + struct in_addr vif_source; + struct pim_interface *pim_oif; + struct prefix nht_p, src, grp; + int ret = 0; + struct pim_nexthop_cache out_pnc; + struct pim_nexthop nexthop; + struct pim_upstream *up = NULL; + + if (!pim_rp_set_upstream_addr(&vif_source, source->source_addr, + sg.grp)) + return; + + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = vif_source; + memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache)); + + src.family = AF_INET; + src.prefixlen = IPV4_MAX_BITLEN; + src.u.prefix4 = vif_source; // RP or Src address + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = sg.grp; + + if ((ret = pim_find_or_track_nexthop(&nht_p, NULL, NULL, + &out_pnc)) + == 1) { + if (out_pnc.nexthop_num) { + up = pim_upstream_find(&sg); + memset(&nexthop, 0, sizeof(struct pim_nexthop)); + if (up) + memcpy(&nexthop, + &up->rpf.source_nexthop, + sizeof(struct pim_nexthop)); + // Compute PIM RPF using Cached nexthop + pim_ecmp_nexthop_search(&out_pnc, &nexthop, + &src, &grp, 0); + if (nexthop.interface) + input_iface_vif_index = + pim_if_find_vifindex_by_ifindex( + nexthop.interface->ifindex); + } else { + if (PIM_DEBUG_ZEBRA) { + char buf1[INET_ADDRSTRLEN]; + char buf2[INET_ADDRSTRLEN]; + pim_inet4_dump("<source?>", + nht_p.u.prefix4, buf1, + sizeof(buf1)); + pim_inet4_dump("<source?>", + grp.u.prefix4, buf2, + sizeof(buf2)); + zlog_debug( + "%s: NHT Nexthop not found for addr %s grp %s", + __PRETTY_FUNCTION__, buf1, + buf2); + } + } + } else + input_iface_vif_index = + pim_ecmp_fib_lookup_if_vif_index(vif_source, + &src, &grp); + + if (PIM_DEBUG_ZEBRA) { + char buf2[INET_ADDRSTRLEN]; + pim_inet4_dump("<source?>", vif_source, buf2, + sizeof(buf2)); + zlog_debug("%s: NHT %s vif_source %s vif_index:%d ", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + buf2, input_iface_vif_index); + } + + if (input_iface_vif_index < 1) { + if (PIM_DEBUG_IGMP_TRACE) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<source?>", source->source_addr, + source_str, sizeof(source_str)); + zlog_debug( + "%s %s: could not find input interface for source %s", + __FILE__, __PRETTY_FUNCTION__, + source_str); + } + return; + } + + /* + Protect IGMP against adding looped MFC entries created by both + source and receiver attached to the same interface. See TODO + T22. + */ + pim_oif = + source->source_group->group_igmp_sock->interface->info; + if (!pim_oif) { + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s: multicast not enabled on oif=%s ?", + __PRETTY_FUNCTION__, + source->source_group->group_igmp_sock + ->interface->name); + } + return; + } + + if (input_iface_vif_index == pim_oif->mroute_vif_index) { + /* ignore request for looped MFC entry */ + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d", + __PRETTY_FUNCTION__, + pim_str_sg_dump(&sg), + source->source_group->group_igmp_sock + ->fd, + source->source_group->group_igmp_sock + ->interface->name, + input_iface_vif_index); + } + return; + } + + source->source_channel_oil = + pim_channel_oil_add(&sg, input_iface_vif_index); + if (!source->source_channel_oil) { + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s %s: could not create OIL for channel (S,G)=%s", + __FILE__, __PRETTY_FUNCTION__, + pim_str_sg_dump(&sg)); + } + return; + } } - return; - } - - if (input_iface_vif_index == pim_oif->mroute_vif_index) { - /* ignore request for looped MFC entry */ - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), - source->source_group->group_igmp_sock->fd, - source->source_group->group_igmp_sock->interface->name, - input_iface_vif_index); - } - return; - } - - source->source_channel_oil = pim_channel_oil_add(&sg, - input_iface_vif_index); - if (!source->source_channel_oil) { - if (PIM_DEBUG_IGMP_TRACE) - { - zlog_debug("%s %s: could not create OIL for channel (S,G)=%s", - __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg)); + + result = pim_channel_add_oif(source->source_channel_oil, + group->group_igmp_sock->interface, + PIM_OIF_FLAG_PROTO_IGMP); + if (result) { + if (PIM_DEBUG_MROUTE) { + zlog_warn("%s: add_oif() failed with return=%d", + __func__, result); + } + return; } - return; - } - } - - result = pim_channel_add_oif(source->source_channel_oil, - group->group_igmp_sock->interface, - PIM_OIF_FLAG_PROTO_IGMP); - if (result) { - if (PIM_DEBUG_MROUTE) - { - zlog_warn("%s: add_oif() failed with return=%d", - __func__, result); - } - return; - } - - /* - Feed IGMPv3-gathered local membership information into PIM - per-interface (S,G) state. - */ - if (!pim_ifchannel_local_membership_add(group->group_igmp_sock->interface, &sg)) - { - if (PIM_DEBUG_MROUTE) - zlog_warn ("%s: Failure to add local membership for %s", - __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); - return; - } - - IGMP_SOURCE_DO_FORWARDING(source->source_flags); + + /* + Feed IGMPv3-gathered local membership information into PIM + per-interface (S,G) state. + */ + if (!pim_ifchannel_local_membership_add( + group->group_igmp_sock->interface, &sg)) { + if (PIM_DEBUG_MROUTE) + zlog_warn("%s: Failure to add local membership for %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); + return; + } + + IGMP_SOURCE_DO_FORWARDING(source->source_flags); } /* @@ -966,203 +1010,219 @@ void igmp_source_forward_start(struct igmp_source *source) */ void igmp_source_forward_stop(struct igmp_source *source) { - struct igmp_group *group; - struct prefix_sg sg; - int result; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = source->source_addr; - sg.grp = source->source_group->group_addr; - - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), - source->source_group->group_igmp_sock->fd, - source->source_group->group_igmp_sock->interface->name, - IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); - } - - /* Prevent IGMP interface from removing multicast route multiple - times */ - if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { - return; - } - - group = source->source_group; - - /* - It appears that in certain circumstances that - igmp_source_forward_stop is called when IGMP forwarding - was not enabled in oif_flags for this outgoing interface. - Possibly because of multiple calls. When that happens, we - enter the below if statement and this function returns early - which in turn triggers the calling function to assert. - Making the call to pim_channel_del_oif and ignoring the return code - fixes the issue without ill effect, similar to - pim_forward_stop below. - */ - result = pim_channel_del_oif(source->source_channel_oil, - group->group_igmp_sock->interface, - PIM_OIF_FLAG_PROTO_IGMP); - if (result) { - if (PIM_DEBUG_IGMP_TRACE) - zlog_debug("%s: pim_channel_del_oif() failed with return=%d", - __func__, result); - return; - } - - /* - Feed IGMPv3-gathered local membership information into PIM - per-interface (S,G) state. - */ - pim_ifchannel_local_membership_del(group->group_igmp_sock->interface, - &sg); - - IGMP_SOURCE_DONT_FORWARDING(source->source_flags); + struct igmp_group *group; + struct prefix_sg sg; + int result; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = source->source_addr; + sg.grp = source->source_group->group_addr; + + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + source->source_group->group_igmp_sock->fd, + source->source_group->group_igmp_sock->interface->name, + IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); + } + + /* Prevent IGMP interface from removing multicast route multiple + times */ + if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { + return; + } + + group = source->source_group; + + /* + It appears that in certain circumstances that + igmp_source_forward_stop is called when IGMP forwarding + was not enabled in oif_flags for this outgoing interface. + Possibly because of multiple calls. When that happens, we + enter the below if statement and this function returns early + which in turn triggers the calling function to assert. + Making the call to pim_channel_del_oif and ignoring the return code + fixes the issue without ill effect, similar to + pim_forward_stop below. + */ + result = pim_channel_del_oif(source->source_channel_oil, + group->group_igmp_sock->interface, + PIM_OIF_FLAG_PROTO_IGMP); + if (result) { + if (PIM_DEBUG_IGMP_TRACE) + zlog_debug( + "%s: pim_channel_del_oif() failed with return=%d", + __func__, result); + return; + } + + /* + Feed IGMPv3-gathered local membership information into PIM + per-interface (S,G) state. + */ + pim_ifchannel_local_membership_del(group->group_igmp_sock->interface, + &sg); + + IGMP_SOURCE_DONT_FORWARDING(source->source_flags); } void pim_forward_start(struct pim_ifchannel *ch) { - struct pim_upstream *up = ch->upstream; - uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; - int input_iface_vif_index = 0; - - if (PIM_DEBUG_PIM_TRACE) { - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - char upstream_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("<source?>", ch->sg.src, source_str, sizeof(source_str)); - pim_inet4_dump("<group?>", ch->sg.grp, group_str, sizeof(group_str)); - pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str, sizeof(upstream_str)); - zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", - __PRETTY_FUNCTION__, - source_str, group_str, ch->interface->name, upstream_str); - } - - /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS, - as part of mroute_del called by pim_forward_stop. - */ - if (!up->channel_oil || - (up->channel_oil && up->channel_oil->oil.mfcc_parent >= MAXVIFS)) - { - struct prefix nht_p, src, grp; - int ret = 0; - struct pim_nexthop_cache out_pnc; - - /* Register addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = up->sg.grp; - memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache)); - - if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1) - { - if (out_pnc.nexthop_num) - { - src.family = AF_INET; - src.prefixlen = IPV4_MAX_BITLEN; - src.u.prefix4 = up->upstream_addr; //RP or Src address - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = up->sg.grp; - //Compute PIM RPF using Cached nexthop - if (pim_ecmp_nexthop_search (&out_pnc, &up->rpf.source_nexthop, &src, &grp, 0) == 0) - input_iface_vif_index = pim_if_find_vifindex_by_ifindex (up->rpf.source_nexthop.interface->ifindex); - else - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Nexthop selection failed for %s ", __PRETTY_FUNCTION__, up->sg_str); - } - } - else - { - if (PIM_DEBUG_ZEBRA) - { - char buf1[INET_ADDRSTRLEN]; - char buf2[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", nht_p.u.prefix4, buf1, sizeof(buf1)); - pim_inet4_dump("<source?>", grp.u.prefix4, buf2, sizeof(buf2)); - zlog_debug ("%s: NHT pnc is NULL for addr %s grp %s" , - __PRETTY_FUNCTION__, buf1, buf2); - } - } - } - else - input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(up->upstream_addr, &src, &grp); - - if (input_iface_vif_index < 1) - { - if (PIM_DEBUG_PIM_TRACE) - { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", up->sg.src, source_str, sizeof(source_str)); - zlog_debug("%s %s: could not find input interface for source %s", - __FILE__, __PRETTY_FUNCTION__, - source_str); - } - return; - } - if (PIM_DEBUG_TRACE) - { - struct interface *in_intf = pim_if_find_by_vif_index (input_iface_vif_index); - zlog_debug ("%s: Update channel_oil IIF %s VIFI %d entry %s ", - __PRETTY_FUNCTION__, in_intf ? in_intf->name : "NIL", - input_iface_vif_index, up->sg_str); - } - up->channel_oil = pim_channel_oil_add (&up->sg, input_iface_vif_index); - if (!up->channel_oil) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s %s: could not create OIL for channel (S,G)=%s", - __FILE__, __PRETTY_FUNCTION__, up->sg_str); - return; - } - } - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) - mask = PIM_OIF_FLAG_PROTO_IGMP; - - pim_channel_add_oif (up->channel_oil, ch->interface, mask); + struct pim_upstream *up = ch->upstream; + uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; + int input_iface_vif_index = 0; + + if (PIM_DEBUG_PIM_TRACE) { + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + char upstream_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("<source?>", ch->sg.src, source_str, + sizeof(source_str)); + pim_inet4_dump("<group?>", ch->sg.grp, group_str, + sizeof(group_str)); + pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str, + sizeof(upstream_str)); + zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__, + source_str, group_str, ch->interface->name, + upstream_str); + } + + /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS, + as part of mroute_del called by pim_forward_stop. + */ + if (!up->channel_oil + || (up->channel_oil + && up->channel_oil->oil.mfcc_parent >= MAXVIFS)) { + struct prefix nht_p, src, grp; + int ret = 0; + struct pim_nexthop_cache out_pnc; + + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = up->sg.grp; + memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache)); + + if ((ret = pim_find_or_track_nexthop(&nht_p, NULL, NULL, + &out_pnc)) + == 1) { + if (out_pnc.nexthop_num) { + src.family = AF_INET; + src.prefixlen = IPV4_MAX_BITLEN; + src.u.prefix4 = + up->upstream_addr; // RP or Src address + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = up->sg.grp; + // Compute PIM RPF using Cached nexthop + if (pim_ecmp_nexthop_search( + &out_pnc, &up->rpf.source_nexthop, + &src, &grp, 0) + == 0) + input_iface_vif_index = + pim_if_find_vifindex_by_ifindex( + up->rpf.source_nexthop + .interface->ifindex); + else { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Nexthop selection failed for %s ", + __PRETTY_FUNCTION__, + up->sg_str); + } + } else { + if (PIM_DEBUG_ZEBRA) { + char buf1[INET_ADDRSTRLEN]; + char buf2[INET_ADDRSTRLEN]; + pim_inet4_dump("<source?>", + nht_p.u.prefix4, buf1, + sizeof(buf1)); + pim_inet4_dump("<source?>", + grp.u.prefix4, buf2, + sizeof(buf2)); + zlog_debug( + "%s: NHT pnc is NULL for addr %s grp %s", + __PRETTY_FUNCTION__, buf1, + buf2); + } + } + } else + input_iface_vif_index = + pim_ecmp_fib_lookup_if_vif_index( + up->upstream_addr, &src, &grp); + + if (input_iface_vif_index < 1) { + if (PIM_DEBUG_PIM_TRACE) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<source?>", up->sg.src, + source_str, sizeof(source_str)); + zlog_debug( + "%s %s: could not find input interface for source %s", + __FILE__, __PRETTY_FUNCTION__, + source_str); + } + return; + } + if (PIM_DEBUG_TRACE) { + struct interface *in_intf = + pim_if_find_by_vif_index(input_iface_vif_index); + zlog_debug( + "%s: Update channel_oil IIF %s VIFI %d entry %s ", + __PRETTY_FUNCTION__, + in_intf ? in_intf->name : "NIL", + input_iface_vif_index, up->sg_str); + } + up->channel_oil = + pim_channel_oil_add(&up->sg, input_iface_vif_index); + if (!up->channel_oil) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s %s: could not create OIL for channel (S,G)=%s", + __FILE__, __PRETTY_FUNCTION__, + up->sg_str); + return; + } + } + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + mask = PIM_OIF_FLAG_PROTO_IGMP; + + pim_channel_add_oif(up->channel_oil, ch->interface, mask); } void pim_forward_stop(struct pim_ifchannel *ch) { - struct pim_upstream *up = ch->upstream; + struct pim_upstream *up = ch->upstream; - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: (S,G)=%s oif=%s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->interface->name); - } + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: (S,G)=%s oif=%s", __PRETTY_FUNCTION__, + ch->sg_str, ch->interface->name); + } - pim_channel_del_oif(up->channel_oil, - ch->interface, - PIM_OIF_FLAG_PROTO_PIM); + pim_channel_del_oif(up->channel_oil, ch->interface, + PIM_OIF_FLAG_PROTO_PIM); } -void -pim_zebra_zclient_update (struct vty *vty) +void pim_zebra_zclient_update(struct vty *vty) { - vty_out(vty, "Zclient update socket: "); - - if (zclient) { - vty_out (vty, "%d failures=%d\n", zclient->sock, - zclient->fail); - } - else { - vty_out (vty, "<null zclient>\n"); - } + vty_out(vty, "Zclient update socket: "); + + if (zclient) { + vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail); + } else { + vty_out(vty, "<null zclient>\n"); + } } -struct zclient *pim_zebra_zclient_get (void) +struct zclient *pim_zebra_zclient_get(void) { - if (zclient) - return zclient; - else - return NULL; + if (zclient) + return zclient; + else + return NULL; } diff --git a/pimd/pim_zebra.h b/pimd/pim_zebra.h index 37024073e..9b5450d66 100644 --- a/pimd/pim_zebra.h +++ b/pimd/pim_zebra.h @@ -27,9 +27,9 @@ #include "pim_ifchannel.h" void pim_zebra_init(void); -void pim_zebra_zclient_update (struct vty *vty); +void pim_zebra_zclient_update(struct vty *vty); -void pim_scan_individual_oil (struct channel_oil *c_oil, int in_vif_index); +void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index); void pim_scan_oil(void); void igmp_anysource_forward_start(struct igmp_group *group); @@ -43,5 +43,5 @@ void pim_forward_start(struct pim_ifchannel *ch); void pim_forward_stop(struct pim_ifchannel *ch); void sched_rpf_cache_refresh(void); -struct zclient *pim_zebra_zclient_get (void); +struct zclient *pim_zebra_zclient_get(void); #endif /* PIM_ZEBRA_H */ diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index f405a39c9..027b18e12 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -43,491 +43,504 @@ static void zclient_lookup_sched(struct zclient *zlookup, int delay); /* Connect to zebra for nexthop lookup. */ static int zclient_lookup_connect(struct thread *t) { - struct zclient *zlookup; - - zlookup = THREAD_ARG(t); - - if (zlookup->sock >= 0) { - return 0; - } - - if (zclient_socket_connect(zlookup) < 0) { - ++zlookup->fail; - zlog_warn("%s: failure connecting zclient socket: failures=%d", - __PRETTY_FUNCTION__, zlookup->fail); - } - else { - zlookup->fail = 0; /* reset counter on connection */ - } - - if (zlookup->sock < 0) { - /* Since last connect failed, retry within 10 secs */ - zclient_lookup_sched(zlookup, 10); - return -1; - } - - return 0; + struct zclient *zlookup; + + zlookup = THREAD_ARG(t); + + if (zlookup->sock >= 0) { + return 0; + } + + if (zclient_socket_connect(zlookup) < 0) { + ++zlookup->fail; + zlog_warn("%s: failure connecting zclient socket: failures=%d", + __PRETTY_FUNCTION__, zlookup->fail); + } else { + zlookup->fail = 0; /* reset counter on connection */ + } + + if (zlookup->sock < 0) { + /* Since last connect failed, retry within 10 secs */ + zclient_lookup_sched(zlookup, 10); + return -1; + } + + return 0; } /* Schedule connection with delay. */ static void zclient_lookup_sched(struct zclient *zlookup, int delay) { - thread_add_timer(master, zclient_lookup_connect, zlookup, delay, - &zlookup->t_connect); + thread_add_timer(master, zclient_lookup_connect, zlookup, delay, + &zlookup->t_connect); - zlog_notice("%s: zclient lookup connection scheduled for %d seconds", - __PRETTY_FUNCTION__, delay); + zlog_notice("%s: zclient lookup connection scheduled for %d seconds", + __PRETTY_FUNCTION__, delay); } /* Schedule connection for now. */ static void zclient_lookup_sched_now(struct zclient *zlookup) { - thread_add_event(master, zclient_lookup_connect, zlookup, 0, - &zlookup->t_connect); + thread_add_event(master, zclient_lookup_connect, zlookup, 0, + &zlookup->t_connect); - zlog_notice("%s: zclient lookup immediate connection scheduled", - __PRETTY_FUNCTION__); + zlog_notice("%s: zclient lookup immediate connection scheduled", + __PRETTY_FUNCTION__); } /* Schedule reconnection, if needed. */ static void zclient_lookup_reconnect(struct zclient *zlookup) { - if (zlookup->t_connect) { - return; - } + if (zlookup->t_connect) { + return; + } - zclient_lookup_sched_now(zlookup); + zclient_lookup_sched_now(zlookup); } static void zclient_lookup_failed(struct zclient *zlookup) { - if (zlookup->sock >= 0) { - if (close(zlookup->sock)) { - zlog_warn("%s: closing fd=%d: errno=%d %s", __func__, zlookup->sock, - errno, safe_strerror(errno)); - } - zlookup->sock = -1; - } - - zclient_lookup_reconnect(zlookup); + if (zlookup->sock >= 0) { + if (close(zlookup->sock)) { + zlog_warn("%s: closing fd=%d: errno=%d %s", __func__, + zlookup->sock, errno, safe_strerror(errno)); + } + zlookup->sock = -1; + } + + zclient_lookup_reconnect(zlookup); } -void -zclient_lookup_free (void) +void zclient_lookup_free(void) { - zclient_stop (zlookup); - zclient_free (zlookup); - zlookup = NULL; + zclient_stop(zlookup); + zclient_free(zlookup); + zlookup = NULL; } -void -zclient_lookup_new (void) +void zclient_lookup_new(void) { - zlookup = zclient_new (master); - if (!zlookup) { - zlog_err("%s: zclient_new() failure", - __PRETTY_FUNCTION__); - return; - } - - zlookup->sock = -1; - zlookup->t_connect = NULL; + zlookup = zclient_new(master); + if (!zlookup) { + zlog_err("%s: zclient_new() failure", __PRETTY_FUNCTION__); + return; + } - zclient_lookup_sched_now(zlookup); + zlookup->sock = -1; + zlookup->t_connect = NULL; - zlog_notice("%s: zclient lookup socket initialized", - __PRETTY_FUNCTION__); + zclient_lookup_sched_now(zlookup); + zlog_notice("%s: zclient lookup socket initialized", + __PRETTY_FUNCTION__); } static int zclient_read_nexthop(struct zclient *zlookup, struct pim_zlookup_nexthop nexthop_tab[], - const int tab_size, - struct in_addr addr) + const int tab_size, struct in_addr addr) { - int num_ifindex = 0; - struct stream *s; - const uint16_t MIN_LEN = 10; /* getipv4=4 getc=1 getl=4 getc=1 */ - uint16_t length; - u_char marker; - u_char version; - vrf_id_t vrf_id; - uint16_t command = 0; - struct in_addr raddr; - uint8_t distance; - uint32_t metric; - int nexthop_num; - int i, err; - - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s: addr=%s", - __PRETTY_FUNCTION__, - addr_str); - } - - s = zlookup->ibuf; - - while (command != ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB) - { - stream_reset(s); - err = zclient_read_header (s, zlookup->sock, &length, &marker, &version, - &vrf_id, &command); - if (err < 0) { - zlog_err("%s %s: zclient_read_header() failed", - __FILE__, __PRETTY_FUNCTION__); - zclient_lookup_failed(zlookup); - return -1; - } - - if (length < MIN_LEN) { - zlog_err("%s %s: failure reading zclient lookup socket: len=%d < MIN_LEN=%d", - __FILE__, __PRETTY_FUNCTION__, length, MIN_LEN); - zclient_lookup_failed(zlookup); - return -2; - } - } - - raddr.s_addr = stream_get_ipv4(s); - - if (raddr.s_addr != addr.s_addr) { - char addr_str[INET_ADDRSTRLEN]; - char raddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - pim_inet4_dump("<raddr?>", raddr, raddr_str, sizeof(raddr_str)); - zlog_warn("%s: address mismatch: addr=%s raddr=%s", - __PRETTY_FUNCTION__, - addr_str, raddr_str); - /* warning only */ - } - - distance = stream_getc(s); - metric = stream_getl(s); - nexthop_num = stream_getc(s); - - if (nexthop_num < 1) { - zlog_err("%s: socket %d bad nexthop_num=%d", - __func__, zlookup->sock, nexthop_num); - return -6; - } - - for (i = 0; i < nexthop_num; ++i) { - enum nexthop_types_t nexthop_type; - struct pim_neighbor *nbr; - struct prefix p; - - nexthop_type = stream_getc(s); - if (num_ifindex >= tab_size) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: found too many nexthop ifindexes (%d > %d) for address %s", - __FILE__, __PRETTY_FUNCTION__, - (num_ifindex + 1), tab_size, addr_str); - return num_ifindex; - } - switch (nexthop_type) { - case NEXTHOP_TYPE_IFINDEX: - case NEXTHOP_TYPE_IPV4_IFINDEX: - case NEXTHOP_TYPE_IPV4: - nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; - if (nexthop_type == NEXTHOP_TYPE_IPV4_IFINDEX || - nexthop_type == NEXTHOP_TYPE_IPV4) { - nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = stream_get_ipv4(s); - } - else { - nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; - } - nexthop_tab[num_ifindex].ifindex = stream_getl(s); - nexthop_tab[num_ifindex].protocol_distance = distance; - nexthop_tab[num_ifindex].route_metric = metric; - ++num_ifindex; - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET6; - stream_get (&nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, - s, - sizeof(struct in6_addr)); - nexthop_tab[num_ifindex].ifindex = stream_getl (s); - - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_PREFIXLEN; - memcpy (&p.u.prefix6, - &nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, - sizeof(struct in6_addr)); - - /* - * If we are sending v6 secondary assume we receive v6 secondary - */ - if (pimg->send_v6_secondary) - nbr = pim_neighbor_find_by_secondary(if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT), &p); - else - nbr = pim_neighbor_find_if (if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT)); - if (nbr) - { - nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; - nexthop_tab[num_ifindex].nexthop_addr.u.prefix4 = nbr->source_addr; - } - ++num_ifindex; - break; - default: - /* do nothing */ - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: found non-ifindex nexthop type=%d for address %s", - __FILE__, __PRETTY_FUNCTION__, - nexthop_type, addr_str); - } - break; - } - } - - return num_ifindex; + int num_ifindex = 0; + struct stream *s; + const uint16_t MIN_LEN = 10; /* getipv4=4 getc=1 getl=4 getc=1 */ + uint16_t length; + u_char marker; + u_char version; + vrf_id_t vrf_id; + uint16_t command = 0; + struct in_addr raddr; + uint8_t distance; + uint32_t metric; + int nexthop_num; + int i, err; + + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); + zlog_debug("%s: addr=%s", __PRETTY_FUNCTION__, addr_str); + } + + s = zlookup->ibuf; + + while (command != ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB) { + stream_reset(s); + err = zclient_read_header(s, zlookup->sock, &length, &marker, + &version, &vrf_id, &command); + if (err < 0) { + zlog_err("%s %s: zclient_read_header() failed", + __FILE__, __PRETTY_FUNCTION__); + zclient_lookup_failed(zlookup); + return -1; + } + + if (length < MIN_LEN) { + zlog_err( + "%s %s: failure reading zclient lookup socket: len=%d < MIN_LEN=%d", + __FILE__, __PRETTY_FUNCTION__, length, MIN_LEN); + zclient_lookup_failed(zlookup); + return -2; + } + } + + raddr.s_addr = stream_get_ipv4(s); + + if (raddr.s_addr != addr.s_addr) { + char addr_str[INET_ADDRSTRLEN]; + char raddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); + pim_inet4_dump("<raddr?>", raddr, raddr_str, sizeof(raddr_str)); + zlog_warn("%s: address mismatch: addr=%s raddr=%s", + __PRETTY_FUNCTION__, addr_str, raddr_str); + /* warning only */ + } + + distance = stream_getc(s); + metric = stream_getl(s); + nexthop_num = stream_getc(s); + + if (nexthop_num < 1) { + zlog_err("%s: socket %d bad nexthop_num=%d", __func__, + zlookup->sock, nexthop_num); + return -6; + } + + for (i = 0; i < nexthop_num; ++i) { + enum nexthop_types_t nexthop_type; + struct pim_neighbor *nbr; + struct prefix p; + + nexthop_type = stream_getc(s); + if (num_ifindex >= tab_size) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, + sizeof(addr_str)); + zlog_warn( + "%s %s: found too many nexthop ifindexes (%d > %d) for address %s", + __FILE__, __PRETTY_FUNCTION__, + (num_ifindex + 1), tab_size, addr_str); + return num_ifindex; + } + switch (nexthop_type) { + case NEXTHOP_TYPE_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: + nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; + if (nexthop_type == NEXTHOP_TYPE_IPV4_IFINDEX + || nexthop_type == NEXTHOP_TYPE_IPV4) { + nexthop_tab[num_ifindex] + .nexthop_addr.u.prefix4.s_addr = + stream_get_ipv4(s); + } else { + nexthop_tab[num_ifindex] + .nexthop_addr.u.prefix4.s_addr = + PIM_NET_INADDR_ANY; + } + nexthop_tab[num_ifindex].ifindex = stream_getl(s); + nexthop_tab[num_ifindex].protocol_distance = distance; + nexthop_tab[num_ifindex].route_metric = metric; + ++num_ifindex; + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET6; + stream_get(&nexthop_tab[num_ifindex] + .nexthop_addr.u.prefix6, + s, sizeof(struct in6_addr)); + nexthop_tab[num_ifindex].ifindex = stream_getl(s); + + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_PREFIXLEN; + memcpy(&p.u.prefix6, + &nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, + sizeof(struct in6_addr)); + + /* + * If we are sending v6 secondary assume we receive v6 + * secondary + */ + if (pimg->send_v6_secondary) + nbr = pim_neighbor_find_by_secondary( + if_lookup_by_index( + nexthop_tab[num_ifindex] + .ifindex, + VRF_DEFAULT), + &p); + else + nbr = pim_neighbor_find_if(if_lookup_by_index( + nexthop_tab[num_ifindex].ifindex, + VRF_DEFAULT)); + if (nbr) { + nexthop_tab[num_ifindex].nexthop_addr.family = + AF_INET; + nexthop_tab[num_ifindex] + .nexthop_addr.u.prefix4 = + nbr->source_addr; + } + ++num_ifindex; + break; + default: + /* do nothing */ + { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, + sizeof(addr_str)); + zlog_warn( + "%s %s: found non-ifindex nexthop type=%d for address %s", + __FILE__, __PRETTY_FUNCTION__, + nexthop_type, addr_str); + } + break; + } + } + + return num_ifindex; } -static int -zclient_lookup_nexthop_once (struct pim_zlookup_nexthop nexthop_tab[], - const int tab_size, - struct in_addr addr) +static int zclient_lookup_nexthop_once(struct pim_zlookup_nexthop nexthop_tab[], + const int tab_size, struct in_addr addr) { - struct stream *s; - int ret; - - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s: addr=%s", - __PRETTY_FUNCTION__, - addr_str); - } - - /* Check socket. */ - if (zlookup->sock < 0) { - zlog_err("%s %s: zclient lookup socket is not connected", - __FILE__, __PRETTY_FUNCTION__); - zclient_lookup_failed(zlookup); - return -1; - } - - s = zlookup->obuf; - stream_reset(s); - zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, VRF_DEFAULT); - stream_put_in_addr(s, &addr); - stream_putw_at(s, 0, stream_get_endp(s)); - - ret = writen(zlookup->sock, s->data, stream_get_endp(s)); - if (ret < 0) { - zlog_err("%s %s: writen() failure: %d writing to zclient lookup socket", - __FILE__, __PRETTY_FUNCTION__, errno); - zclient_lookup_failed(zlookup); - return -2; - } - if (ret == 0) { - zlog_err("%s %s: connection closed on zclient lookup socket", - __FILE__, __PRETTY_FUNCTION__); - zclient_lookup_failed(zlookup); - return -3; - } - - return zclient_read_nexthop(zlookup, nexthop_tab, - tab_size, addr); + struct stream *s; + int ret; + + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); + zlog_debug("%s: addr=%s", __PRETTY_FUNCTION__, addr_str); + } + + /* Check socket. */ + if (zlookup->sock < 0) { + zlog_err("%s %s: zclient lookup socket is not connected", + __FILE__, __PRETTY_FUNCTION__); + zclient_lookup_failed(zlookup); + return -1; + } + + s = zlookup->obuf; + stream_reset(s); + zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, VRF_DEFAULT); + stream_put_in_addr(s, &addr); + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = writen(zlookup->sock, s->data, stream_get_endp(s)); + if (ret < 0) { + zlog_err( + "%s %s: writen() failure: %d writing to zclient lookup socket", + __FILE__, __PRETTY_FUNCTION__, errno); + zclient_lookup_failed(zlookup); + return -2; + } + if (ret == 0) { + zlog_err("%s %s: connection closed on zclient lookup socket", + __FILE__, __PRETTY_FUNCTION__); + zclient_lookup_failed(zlookup); + return -3; + } + + return zclient_read_nexthop(zlookup, nexthop_tab, tab_size, addr); } -int -zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], - const int tab_size, - struct in_addr addr, - int max_lookup) +int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[], + const int tab_size, struct in_addr addr, + int max_lookup) { - int lookup; - uint32_t route_metric = 0xFFFFFFFF; - uint8_t protocol_distance = 0xFF; - - qpim_nexthop_lookups++; - - for (lookup = 0; lookup < max_lookup; ++lookup) { - int num_ifindex; - int first_ifindex; - struct prefix nexthop_addr; - - num_ifindex = zclient_lookup_nexthop_once(nexthop_tab, - tab_size, addr); - if (num_ifindex < 1) { - if (PIM_DEBUG_ZEBRA) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: lookup=%d/%d: could not find nexthop ifindex for address %s", - __FILE__, __PRETTY_FUNCTION__, - lookup, max_lookup, addr_str); - } - return -1; - } - - if (lookup < 1) { - /* this is the non-recursive lookup - save original metric/distance */ - route_metric = nexthop_tab[0].route_metric; - protocol_distance = nexthop_tab[0].protocol_distance; - } - - /* - * FIXME: Non-recursive nexthop ensured only for first ifindex. - * However, recursive route lookup should really be fixed in zebra daemon. - * See also TODO T24. - * - * So Zebra for NEXTHOP_TYPE_IPV4 returns the ifindex now since - * it was being stored. This Doesn't solve all cases of - * recursive lookup but for the most common types it does. - */ - first_ifindex = nexthop_tab[0].ifindex; - nexthop_addr = nexthop_tab[0].nexthop_addr; - if (first_ifindex > 0) { - /* found: first ifindex is non-recursive nexthop */ - - if (lookup > 0) { - /* Report non-recursive success after first lookup */ + int lookup; + uint32_t route_metric = 0xFFFFFFFF; + uint8_t protocol_distance = 0xFF; + + qpim_nexthop_lookups++; + + for (lookup = 0; lookup < max_lookup; ++lookup) { + int num_ifindex; + int first_ifindex; + struct prefix nexthop_addr; + + num_ifindex = zclient_lookup_nexthop_once(nexthop_tab, tab_size, + addr); + if (num_ifindex < 1) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: lookup=%d/%d: could not find nexthop ifindex for address %s", + __FILE__, __PRETTY_FUNCTION__, lookup, + max_lookup, addr_str); + } + return -1; + } + + if (lookup < 1) { + /* this is the non-recursive lookup - save original + * metric/distance */ + route_metric = nexthop_tab[0].route_metric; + protocol_distance = nexthop_tab[0].protocol_distance; + } + + /* + * FIXME: Non-recursive nexthop ensured only for first ifindex. + * However, recursive route lookup should really be fixed in + * zebra daemon. + * See also TODO T24. + * + * So Zebra for NEXTHOP_TYPE_IPV4 returns the ifindex now since + * it was being stored. This Doesn't solve all cases of + * recursive lookup but for the most common types it does. + */ + first_ifindex = nexthop_tab[0].ifindex; + nexthop_addr = nexthop_tab[0].nexthop_addr; + if (first_ifindex > 0) { + /* found: first ifindex is non-recursive nexthop */ + + if (lookup > 0) { + /* Report non-recursive success after first + * lookup */ + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, + addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: lookup=%d/%d: found non-recursive ifindex=%d for address %s dist=%d met=%d", + __FILE__, __PRETTY_FUNCTION__, + lookup, max_lookup, + first_ifindex, addr_str, + nexthop_tab[0] + .protocol_distance, + nexthop_tab[0].route_metric); + } + + /* use last address as nexthop address */ + nexthop_tab[0].nexthop_addr.u.prefix4 = addr; + + /* report original route metric/distance */ + nexthop_tab[0].route_metric = route_metric; + nexthop_tab[0].protocol_distance = + protocol_distance; + } + + return num_ifindex; + } + + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + char nexthop_str[PREFIX_STRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, + sizeof(addr_str)); + pim_addr_dump("<nexthop?>", &nexthop_addr, nexthop_str, + sizeof(nexthop_str)); + zlog_debug( + "%s %s: lookup=%d/%d: zebra returned recursive nexthop %s for address %s dist=%d met=%d", + __FILE__, __PRETTY_FUNCTION__, lookup, + max_lookup, nexthop_str, addr_str, + nexthop_tab[0].protocol_distance, + nexthop_tab[0].route_metric); + } + + addr = + nexthop_addr.u.prefix4; /* use nexthop addr for + recursive lookup */ + + } /* for (max_lookup) */ + if (PIM_DEBUG_ZEBRA) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: lookup=%d/%d: found non-recursive ifindex=%d for address %s dist=%d met=%d", - __FILE__, __PRETTY_FUNCTION__, - lookup, max_lookup, first_ifindex, addr_str, - nexthop_tab[0].protocol_distance, - nexthop_tab[0].route_metric); + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); + zlog_warn( + "%s %s: lookup=%d/%d: failure searching recursive nexthop ifindex for address %s", + __FILE__, __PRETTY_FUNCTION__, lookup, max_lookup, + addr_str); } - /* use last address as nexthop address */ - nexthop_tab[0].nexthop_addr.u.prefix4 = addr; - - /* report original route metric/distance */ - nexthop_tab[0].route_metric = route_metric; - nexthop_tab[0].protocol_distance = protocol_distance; - } - - return num_ifindex; - } - - if (PIM_DEBUG_ZEBRA) { - char addr_str[INET_ADDRSTRLEN]; - char nexthop_str[PREFIX_STRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - pim_addr_dump("<nexthop?>", &nexthop_addr, nexthop_str, sizeof(nexthop_str)); - zlog_debug("%s %s: lookup=%d/%d: zebra returned recursive nexthop %s for address %s dist=%d met=%d", - __FILE__, __PRETTY_FUNCTION__, - lookup, max_lookup, nexthop_str, addr_str, - nexthop_tab[0].protocol_distance, - nexthop_tab[0].route_metric); - } - - addr = nexthop_addr.u.prefix4; /* use nexthop addr for recursive lookup */ - - } /* for (max_lookup) */ - - if (PIM_DEBUG_ZEBRA) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: lookup=%d/%d: failure searching recursive nexthop ifindex for address %s", - __FILE__, __PRETTY_FUNCTION__, - lookup, max_lookup, addr_str); - } - - return -2; + return -2; } -void -pim_zlookup_show_ip_multicast (struct vty *vty) +void pim_zlookup_show_ip_multicast(struct vty *vty) { - vty_out(vty, "Zclient lookup socket: "); - if (zlookup) { - vty_out (vty, "%d failures=%d\n", zlookup->sock, - zlookup->fail); - } - else { - vty_out (vty, "<null zclient>\n"); - } + vty_out(vty, "Zclient lookup socket: "); + if (zlookup) { + vty_out(vty, "%d failures=%d\n", zlookup->sock, zlookup->fail); + } else { + vty_out(vty, "<null zclient>\n"); + } } -int -pim_zlookup_sg_statistics (struct channel_oil *c_oil) +int pim_zlookup_sg_statistics(struct channel_oil *c_oil) { - struct stream *s = zlookup->obuf; - uint16_t command = 0; - unsigned long long lastused; - struct prefix_sg sg; - int count = 0; - int ret; - struct interface *ifp = pim_if_find_by_vif_index (c_oil->oil.mfcc_parent); - - if (PIM_DEBUG_ZEBRA) - { - struct prefix_sg more; - - more.src = c_oil->oil.mfcc_origin; - more.grp = c_oil->oil.mfcc_mcastgrp; - zlog_debug ("Sending Request for New Channel Oil Information(%s) VIIF %d", - pim_str_sg_dump (&more), c_oil->oil.mfcc_parent); - } - - if (!ifp) - return -1; - - stream_reset (s); - zclient_create_header (s, ZEBRA_IPMR_ROUTE_STATS, VRF_DEFAULT); - stream_put_in_addr (s, &c_oil->oil.mfcc_origin); - stream_put_in_addr (s, &c_oil->oil.mfcc_mcastgrp); - stream_putl (s, ifp->ifindex); - stream_putw_at(s, 0, stream_get_endp(s)); - - count = stream_get_endp (s); - ret = writen (zlookup->sock, s->data, count); - if (ret <= 0) - { - zlog_err("%s %s: writen() failure: %d writing to zclient lookup socket", - __FILE__, __PRETTY_FUNCTION__, errno); - return -1; - } - - s = zlookup->ibuf; - - while (command != ZEBRA_IPMR_ROUTE_STATS) - { - int err; - uint16_t length = 0; - vrf_id_t vrf_id; - u_char marker; - u_char version; - - stream_reset (s); - err = zclient_read_header (s, zlookup->sock, &length, &marker, &version, - &vrf_id, &command); - if (err < 0) - { - zlog_err ("%s %s: zclient_read_header() failed", - __FILE__, __PRETTY_FUNCTION__); - zclient_lookup_failed(zlookup); - return -1; - } - } - - sg.src.s_addr = stream_get_ipv4 (s); - sg.grp.s_addr = stream_get_ipv4 (s); - if (sg.src.s_addr != c_oil->oil.mfcc_origin.s_addr || - sg.grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr) - { - zlog_err ("%s: Received wrong %s information", - __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); - zclient_lookup_failed (zlookup); - return -3; - } - - stream_get (&lastused, s, sizeof (lastused)); - ret = stream_getl (s); - - if (PIM_DEBUG_ZEBRA) - zlog_debug ("Received %lld for %s success: %d", lastused, pim_str_sg_dump (&sg), ret); - - c_oil->cc.lastused = lastused; - - return 0; + struct stream *s = zlookup->obuf; + uint16_t command = 0; + unsigned long long lastused; + struct prefix_sg sg; + int count = 0; + int ret; + struct interface *ifp = + pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); + + if (PIM_DEBUG_ZEBRA) { + struct prefix_sg more; + + more.src = c_oil->oil.mfcc_origin; + more.grp = c_oil->oil.mfcc_mcastgrp; + zlog_debug( + "Sending Request for New Channel Oil Information(%s) VIIF %d", + pim_str_sg_dump(&more), c_oil->oil.mfcc_parent); + } + + if (!ifp) + return -1; + + stream_reset(s); + zclient_create_header(s, ZEBRA_IPMR_ROUTE_STATS, VRF_DEFAULT); + stream_put_in_addr(s, &c_oil->oil.mfcc_origin); + stream_put_in_addr(s, &c_oil->oil.mfcc_mcastgrp); + stream_putl(s, ifp->ifindex); + stream_putw_at(s, 0, stream_get_endp(s)); + + count = stream_get_endp(s); + ret = writen(zlookup->sock, s->data, count); + if (ret <= 0) { + zlog_err( + "%s %s: writen() failure: %d writing to zclient lookup socket", + __FILE__, __PRETTY_FUNCTION__, errno); + return -1; + } + + s = zlookup->ibuf; + + while (command != ZEBRA_IPMR_ROUTE_STATS) { + int err; + uint16_t length = 0; + vrf_id_t vrf_id; + u_char marker; + u_char version; + + stream_reset(s); + err = zclient_read_header(s, zlookup->sock, &length, &marker, + &version, &vrf_id, &command); + if (err < 0) { + zlog_err("%s %s: zclient_read_header() failed", + __FILE__, __PRETTY_FUNCTION__); + zclient_lookup_failed(zlookup); + return -1; + } + } + + sg.src.s_addr = stream_get_ipv4(s); + sg.grp.s_addr = stream_get_ipv4(s); + if (sg.src.s_addr != c_oil->oil.mfcc_origin.s_addr + || sg.grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr) { + zlog_err("%s: Received wrong %s information", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); + zclient_lookup_failed(zlookup); + return -3; + } + + stream_get(&lastused, s, sizeof(lastused)); + ret = stream_getl(s); + + if (PIM_DEBUG_ZEBRA) + zlog_debug("Received %lld for %s success: %d", lastused, + pim_str_sg_dump(&sg), ret); + + c_oil->cc.lastused = lastused; + return 0; } diff --git a/pimd/pim_zlookup.h b/pimd/pim_zlookup.h index 08c8768d1..d168464ce 100644 --- a/pimd/pim_zlookup.h +++ b/pimd/pim_zlookup.h @@ -27,21 +27,20 @@ #define PIM_NEXTHOP_LOOKUP_MAX (3) /* max. recursive route lookup */ struct pim_zlookup_nexthop { - struct prefix nexthop_addr; - ifindex_t ifindex; - uint32_t route_metric; - uint8_t protocol_distance; + struct prefix nexthop_addr; + ifindex_t ifindex; + uint32_t route_metric; + uint8_t protocol_distance; }; -void zclient_lookup_new (void); -void zclient_lookup_free (void); +void zclient_lookup_new(void); +void zclient_lookup_free(void); int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[], - const int tab_size, - struct in_addr addr, + const int tab_size, struct in_addr addr, int max_lookup); -void pim_zlookup_show_ip_multicast (struct vty *vty); +void pim_zlookup_show_ip_multicast(struct vty *vty); -int pim_zlookup_sg_statistics (struct channel_oil *c_oil); +int pim_zlookup_sg_statistics(struct channel_oil *c_oil); #endif /* PIM_ZLOOKUP_H */ diff --git a/pimd/pimd.c b/pimd/pimd.c index b1d566f51..89b235bed 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -45,289 +45,272 @@ #include "pim_zlookup.h" #include "pim_nht.h" -const char *const PIM_ALL_SYSTEMS = MCAST_ALL_SYSTEMS; -const char *const PIM_ALL_ROUTERS = MCAST_ALL_ROUTERS; -const char *const PIM_ALL_PIM_ROUTERS = MCAST_ALL_PIM_ROUTERS; +const char *const PIM_ALL_SYSTEMS = MCAST_ALL_SYSTEMS; +const char *const PIM_ALL_ROUTERS = MCAST_ALL_ROUTERS; +const char *const PIM_ALL_PIM_ROUTERS = MCAST_ALL_PIM_ROUTERS; const char *const PIM_ALL_IGMP_ROUTERS = MCAST_ALL_IGMP_ROUTERS; -struct thread_master *master = NULL; -uint32_t qpim_debugs = 0; -int qpim_mroute_socket_fd = -1; -int64_t qpim_mroute_socket_creation = 0; /* timestamp of creation */ -int qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */ -struct pim_assert_metric qpim_infinite_assert_metric; -long qpim_rpf_cache_refresh_delay_msec = 50; -struct thread *qpim_rpf_cache_refresher = NULL; -int64_t qpim_rpf_cache_refresh_requests = 0; -int64_t qpim_rpf_cache_refresh_events = 0; -int64_t qpim_rpf_cache_refresh_last = 0; -struct list *qpim_ssmpingd_list = NULL; -struct in_addr qpim_ssmpingd_group_addr; -int64_t qpim_scan_oil_events = 0; -int64_t qpim_scan_oil_last = 0; -int64_t qpim_mroute_add_events = 0; -int64_t qpim_mroute_add_last = 0; -int64_t qpim_mroute_del_events = 0; -int64_t qpim_mroute_del_last = 0; -struct list *qpim_static_route_list = NULL; -unsigned int qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; -signed int qpim_rp_keep_alive_time = 0; -int64_t qpim_nexthop_lookups = 0; -int qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; -uint8_t qpim_ecmp_enable = 0; -uint8_t qpim_ecmp_rebalance_enable = 0; -struct pim_instance *pimg = NULL; +struct thread_master *master = NULL; +uint32_t qpim_debugs = 0; +int qpim_mroute_socket_fd = -1; +int64_t qpim_mroute_socket_creation = 0; /* timestamp of creation */ +int qpim_t_periodic = + PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */ +struct pim_assert_metric qpim_infinite_assert_metric; +long qpim_rpf_cache_refresh_delay_msec = 50; +struct thread *qpim_rpf_cache_refresher = NULL; +int64_t qpim_rpf_cache_refresh_requests = 0; +int64_t qpim_rpf_cache_refresh_events = 0; +int64_t qpim_rpf_cache_refresh_last = 0; +struct list *qpim_ssmpingd_list = NULL; +struct in_addr qpim_ssmpingd_group_addr; +int64_t qpim_scan_oil_events = 0; +int64_t qpim_scan_oil_last = 0; +int64_t qpim_mroute_add_events = 0; +int64_t qpim_mroute_add_last = 0; +int64_t qpim_mroute_del_events = 0; +int64_t qpim_mroute_del_last = 0; +struct list *qpim_static_route_list = NULL; +unsigned int qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; +signed int qpim_rp_keep_alive_time = 0; +int64_t qpim_nexthop_lookups = 0; +int qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; +uint8_t qpim_ecmp_enable = 0; +uint8_t qpim_ecmp_rebalance_enable = 0; +struct pim_instance *pimg = NULL; int32_t qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; int32_t qpim_register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT; -static struct pim_instance *pim_instance_init (vrf_id_t vrf_id, afi_t afi); -static void pim_instance_terminate (void); +static struct pim_instance *pim_instance_init(vrf_id_t vrf_id, afi_t afi); +static void pim_instance_terminate(void); -static int -pim_vrf_new (struct vrf *vrf) +static int pim_vrf_new(struct vrf *vrf) { - zlog_debug ("VRF Created: %s(%d)", vrf->name, vrf->vrf_id); - return 0; + zlog_debug("VRF Created: %s(%d)", vrf->name, vrf->vrf_id); + return 0; } -static int -pim_vrf_delete (struct vrf *vrf) +static int pim_vrf_delete(struct vrf *vrf) { - zlog_debug ("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id); - return 0; + zlog_debug("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id); + return 0; } -static int -pim_vrf_enable (struct vrf *vrf) +static int pim_vrf_enable(struct vrf *vrf) { - if (!vrf) // unexpected - return -1; - - if (vrf->vrf_id == VRF_DEFAULT) - { - pimg = pim_instance_init (VRF_DEFAULT, AFI_IP); - if (pimg == NULL) - { - zlog_err ("%s %s: pim class init failure ", __FILE__, - __PRETTY_FUNCTION__); - /* - * We will crash and burn otherwise - */ - exit(1); - } - - pimg->send_v6_secondary = 1; - - } - return 0; + if (!vrf) // unexpected + return -1; + + if (vrf->vrf_id == VRF_DEFAULT) { + pimg = pim_instance_init(VRF_DEFAULT, AFI_IP); + if (pimg == NULL) { + zlog_err("%s %s: pim class init failure ", __FILE__, + __PRETTY_FUNCTION__); + /* + * We will crash and burn otherwise + */ + exit(1); + } + + pimg->send_v6_secondary = 1; + } + return 0; } -static int -pim_vrf_disable (struct vrf *vrf) +static int pim_vrf_disable(struct vrf *vrf) { - if (vrf->vrf_id == VRF_DEFAULT) - return 0; + if (vrf->vrf_id == VRF_DEFAULT) + return 0; - if (vrf->vrf_id == VRF_DEFAULT) - pim_instance_terminate (); + if (vrf->vrf_id == VRF_DEFAULT) + pim_instance_terminate(); - /* Note: This is a callback, the VRF will be deleted by the caller. */ - return 0; + /* Note: This is a callback, the VRF will be deleted by the caller. */ + return 0; } -void -pim_vrf_init (void) +void pim_vrf_init(void) { - vrf_init (pim_vrf_new, - pim_vrf_enable, - pim_vrf_disable, - pim_vrf_delete); + vrf_init(pim_vrf_new, pim_vrf_enable, pim_vrf_disable, pim_vrf_delete); } -static void -pim_vrf_terminate (void) +static void pim_vrf_terminate(void) { - vrf_terminate (); + vrf_terminate(); } /* Key generate for pim->rpf_hash */ -static unsigned int -pim_rpf_hash_key (void *arg) +static unsigned int pim_rpf_hash_key(void *arg) { - struct pim_nexthop_cache *r = (struct pim_nexthop_cache *) arg; + struct pim_nexthop_cache *r = (struct pim_nexthop_cache *)arg; - return jhash_1word (r->rpf.rpf_addr.u.prefix4.s_addr, 0); + return jhash_1word(r->rpf.rpf_addr.u.prefix4.s_addr, 0); } /* Compare pim->rpf_hash node data */ -static int -pim_rpf_equal (const void *arg1, const void *arg2) +static int pim_rpf_equal(const void *arg1, const void *arg2) { - const struct pim_nexthop_cache *r1 = - (const struct pim_nexthop_cache *) arg1; - const struct pim_nexthop_cache *r2 = - (const struct pim_nexthop_cache *) arg2; + const struct pim_nexthop_cache *r1 = + (const struct pim_nexthop_cache *)arg1; + const struct pim_nexthop_cache *r2 = + (const struct pim_nexthop_cache *)arg2; - return prefix_same (&r1->rpf.rpf_addr, &r2->rpf.rpf_addr); + return prefix_same(&r1->rpf.rpf_addr, &r2->rpf.rpf_addr); } /* Cleanup pim->rpf_hash each node data */ -static void -pim_rp_list_hash_clean (void *data) +static void pim_rp_list_hash_clean(void *data) { - struct pim_nexthop_cache *pnc; + struct pim_nexthop_cache *pnc; - pnc = (struct pim_nexthop_cache *) data; - if (pnc->rp_list->count) - list_delete_all_node (pnc->rp_list); - if (pnc->upstream_list->count) - list_delete_all_node (pnc->upstream_list); + pnc = (struct pim_nexthop_cache *)data; + if (pnc->rp_list->count) + list_delete_all_node(pnc->rp_list); + if (pnc->upstream_list->count) + list_delete_all_node(pnc->upstream_list); } -void -pim_prefix_list_update (struct prefix_list *plist) +void pim_prefix_list_update(struct prefix_list *plist) { - pim_rp_prefix_list_update (plist); - pim_ssm_prefix_list_update (plist); - pim_upstream_spt_prefix_list_update (plist); + pim_rp_prefix_list_update(plist); + pim_ssm_prefix_list_update(plist); + pim_upstream_spt_prefix_list_update(plist); } -static void -pim_instance_terminate (void) +static void pim_instance_terminate(void) { - /* Traverse and cleanup rpf_hash */ - if (pimg->rpf_hash) - { - hash_clean (pimg->rpf_hash, (void *) pim_rp_list_hash_clean); - hash_free (pimg->rpf_hash); - pimg->rpf_hash = NULL; - } - - if (pimg->ssm_info) - { - pim_ssm_terminate (pimg->ssm_info); - pimg->ssm_info = NULL; - } - - XFREE (MTYPE_PIM_PIM_INSTANCE, pimg); + /* Traverse and cleanup rpf_hash */ + if (pimg->rpf_hash) { + hash_clean(pimg->rpf_hash, (void *)pim_rp_list_hash_clean); + hash_free(pimg->rpf_hash); + pimg->rpf_hash = NULL; + } + + if (pimg->ssm_info) { + pim_ssm_terminate(pimg->ssm_info); + pimg->ssm_info = NULL; + } + + XFREE(MTYPE_PIM_PIM_INSTANCE, pimg); } static void pim_free() { - pim_ssmpingd_destroy(); + pim_ssmpingd_destroy(); - pim_oil_terminate (); + pim_oil_terminate(); - pim_upstream_terminate (); + pim_upstream_terminate(); - if (qpim_static_route_list) - list_free(qpim_static_route_list); + if (qpim_static_route_list) + list_free(qpim_static_route_list); - pim_if_terminate (); - pim_rp_free (); + pim_if_terminate(); + pim_rp_free(); - pim_route_map_terminate(); + pim_route_map_terminate(); - zclient_lookup_free (); + zclient_lookup_free(); - zprivs_terminate(&pimd_privs); + zprivs_terminate(&pimd_privs); } -static struct pim_instance * -pim_instance_init (vrf_id_t vrf_id, afi_t afi) +static struct pim_instance *pim_instance_init(vrf_id_t vrf_id, afi_t afi) { - struct pim_instance *pim; + struct pim_instance *pim; - pim = XCALLOC (MTYPE_PIM_PIM_INSTANCE, sizeof (struct pim_instance)); - if (!pim) - return NULL; + pim = XCALLOC(MTYPE_PIM_PIM_INSTANCE, sizeof(struct pim_instance)); + if (!pim) + return NULL; - pim->vrf_id = vrf_id; - pim->afi = afi; + pim->vrf_id = vrf_id; + pim->afi = afi; - pim->spt.switchover = PIM_SPT_IMMEDIATE; - pim->spt.plist = NULL; + pim->spt.switchover = PIM_SPT_IMMEDIATE; + pim->spt.plist = NULL; - pim->rpf_hash = hash_create_size (256, pim_rpf_hash_key, pim_rpf_equal, NULL); + pim->rpf_hash = + hash_create_size(256, pim_rpf_hash_key, pim_rpf_equal, NULL); - if (PIM_DEBUG_ZEBRA) - zlog_debug ("%s: NHT rpf hash init ", __PRETTY_FUNCTION__); + if (PIM_DEBUG_ZEBRA) + zlog_debug("%s: NHT rpf hash init ", __PRETTY_FUNCTION__); - pim->ssm_info = pim_ssm_init (vrf_id); - if (!pim->ssm_info) { - pim_instance_terminate (); - return NULL; - } + pim->ssm_info = pim_ssm_init(vrf_id); + if (!pim->ssm_info) { + pim_instance_terminate(); + return NULL; + } - return pim; + return pim; } void pim_init() { - qpim_rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD; - - pim_rp_init (); - - if (!inet_aton(PIM_ALL_PIM_ROUTERS, &qpim_all_pim_routers_addr)) { - zlog_err("%s %s: could not solve %s to group address: errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - PIM_ALL_PIM_ROUTERS, errno, safe_strerror(errno)); - zassert(0); - return; - } - - pim_oil_init (); - - pim_upstream_init (); - - qpim_static_route_list = list_new(); - if (!qpim_static_route_list) { - zlog_err("%s %s: failure: static_route_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return; - } - qpim_static_route_list->del = (void (*)(void *)) pim_static_route_free; - - pim_mroute_socket_enable(); - - - /* - RFC 4601: 4.6.3. Assert Metrics - - assert_metric - infinite_assert_metric() { - return {1,infinity,infinity,0} - } - */ - qpim_infinite_assert_metric.rpt_bit_flag = 1; - qpim_infinite_assert_metric.metric_preference = PIM_ASSERT_METRIC_PREFERENCE_MAX; - qpim_infinite_assert_metric.route_metric = PIM_ASSERT_ROUTE_METRIC_MAX; - qpim_infinite_assert_metric.ip_address.s_addr = INADDR_ANY; - - pim_if_init(); - pim_cmd_init(); - pim_ssmpingd_init(); + qpim_rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD; + + pim_rp_init(); + + if (!inet_aton(PIM_ALL_PIM_ROUTERS, &qpim_all_pim_routers_addr)) { + zlog_err( + "%s %s: could not solve %s to group address: errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, PIM_ALL_PIM_ROUTERS, + errno, safe_strerror(errno)); + zassert(0); + return; + } + + pim_oil_init(); + + pim_upstream_init(); + + qpim_static_route_list = list_new(); + if (!qpim_static_route_list) { + zlog_err("%s %s: failure: static_route_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return; + } + qpim_static_route_list->del = (void (*)(void *))pim_static_route_free; + + pim_mroute_socket_enable(); + + + /* + RFC 4601: 4.6.3. Assert Metrics + + assert_metric + infinite_assert_metric() { + return {1,infinity,infinity,0} + } + */ + qpim_infinite_assert_metric.rpt_bit_flag = 1; + qpim_infinite_assert_metric.metric_preference = + PIM_ASSERT_METRIC_PREFERENCE_MAX; + qpim_infinite_assert_metric.route_metric = PIM_ASSERT_ROUTE_METRIC_MAX; + qpim_infinite_assert_metric.ip_address.s_addr = INADDR_ANY; + + pim_if_init(); + pim_cmd_init(); + pim_ssmpingd_init(); } void pim_terminate() { - struct zclient *zclient; + struct zclient *zclient; - pim_free(); + pim_free(); - /* reverse prefix_list_init */ - prefix_list_add_hook (NULL); - prefix_list_delete_hook (NULL); - prefix_list_reset (); + /* reverse prefix_list_init */ + prefix_list_add_hook(NULL); + prefix_list_delete_hook(NULL); + prefix_list_reset(); - pim_vrf_terminate (); + pim_vrf_terminate(); - zclient = pim_zebra_zclient_get (); - if (zclient) - { - zclient_stop (zclient); - zclient_free (zclient); - } + zclient = pim_zebra_zclient_get(); + if (zclient) { + zclient_stop(zclient); + zclient_free(zclient); + } } diff --git a/pimd/pimd.h b/pimd/pimd.h index 18520f57e..7934bce2d 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -65,10 +65,9 @@ * | Number of Joined Sources | Number of Pruned Sources | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -#define PIM_JP_GROUP_HEADER_SIZE (PIM_ENCODED_IPV4_UCAST_SIZE + \ - 1 + 1 + 2 + \ - PIM_ENCODED_IPV4_GROUP_SIZE + \ - 2 + 2) +#define PIM_JP_GROUP_HEADER_SIZE \ + (PIM_ENCODED_IPV4_UCAST_SIZE + 1 + 1 + 2 + PIM_ENCODED_IPV4_GROUP_SIZE \ + + 2 + 2) #define PIM_PROTO_VERSION (2) @@ -108,7 +107,6 @@ #define PIM_MASK_MSDP_PACKETS (1 << 20) #define PIM_MASK_MSDP_INTERNAL (1 << 21) - /* PIM error codes */ #define PIM_SUCCESS 0 #define PIM_MALLOC_FAIL -1 @@ -127,34 +125,34 @@ const char *const PIM_ALL_ROUTERS; const char *const PIM_ALL_PIM_ROUTERS; const char *const PIM_ALL_IGMP_ROUTERS; -extern struct thread_master *master; +extern struct thread_master *master; extern struct zebra_privs_t pimd_privs; -uint32_t qpim_debugs; -int qpim_mroute_socket_fd; -int64_t qpim_mroute_socket_creation; /* timestamp of creation */ -struct in_addr qpim_all_pim_routers_addr; -int qpim_t_periodic; /* Period between Join/Prune Messages */ -struct pim_assert_metric qpim_infinite_assert_metric; -long qpim_rpf_cache_refresh_delay_msec; -struct thread *qpim_rpf_cache_refresher; -int64_t qpim_rpf_cache_refresh_requests; -int64_t qpim_rpf_cache_refresh_events; -int64_t qpim_rpf_cache_refresh_last; -struct list *qpim_ssmpingd_list; /* list of struct ssmpingd_sock */ -struct in_addr qpim_ssmpingd_group_addr; -int64_t qpim_scan_oil_events; -int64_t qpim_scan_oil_last; -int64_t qpim_mroute_add_events; -int64_t qpim_mroute_add_last; -int64_t qpim_mroute_del_events; -int64_t qpim_mroute_del_last; -int64_t qpim_nexthop_lookups; -struct list *qpim_static_route_list; /* list of routes added statically */ -extern unsigned int qpim_keep_alive_time; -extern signed int qpim_rp_keep_alive_time; -extern int qpim_packet_process; -extern uint8_t qpim_ecmp_enable; -extern uint8_t qpim_ecmp_rebalance_enable; +uint32_t qpim_debugs; +int qpim_mroute_socket_fd; +int64_t qpim_mroute_socket_creation; /* timestamp of creation */ +struct in_addr qpim_all_pim_routers_addr; +int qpim_t_periodic; /* Period between Join/Prune Messages */ +struct pim_assert_metric qpim_infinite_assert_metric; +long qpim_rpf_cache_refresh_delay_msec; +struct thread *qpim_rpf_cache_refresher; +int64_t qpim_rpf_cache_refresh_requests; +int64_t qpim_rpf_cache_refresh_events; +int64_t qpim_rpf_cache_refresh_last; +struct list *qpim_ssmpingd_list; /* list of struct ssmpingd_sock */ +struct in_addr qpim_ssmpingd_group_addr; +int64_t qpim_scan_oil_events; +int64_t qpim_scan_oil_last; +int64_t qpim_mroute_add_events; +int64_t qpim_mroute_add_last; +int64_t qpim_mroute_del_events; +int64_t qpim_mroute_del_last; +int64_t qpim_nexthop_lookups; +struct list *qpim_static_route_list; /* list of routes added statically */ +extern unsigned int qpim_keep_alive_time; +extern signed int qpim_rp_keep_alive_time; +extern int qpim_packet_process; +extern uint8_t qpim_ecmp_enable; +extern uint8_t qpim_ecmp_rebalance_enable; #define PIM_DEFAULT_PACKET_PROCESS 3 @@ -239,36 +237,35 @@ extern int32_t qpim_register_probe_time; #define PIM_DONT_DEBUG_MSDP_INTERNAL (qpim_debugs &= ~PIM_MASK_MSDP_INTERNAL) enum pim_spt_switchover { - PIM_SPT_IMMEDIATE, - PIM_SPT_INFINITY, + PIM_SPT_IMMEDIATE, + PIM_SPT_INFINITY, }; /* Per VRF PIM DB */ -struct pim_instance -{ - afi_t afi; - vrf_id_t vrf_id; +struct pim_instance { + afi_t afi; + vrf_id_t vrf_id; + + struct { + enum pim_spt_switchover switchover; + char *plist; + } spt; - struct { - enum pim_spt_switchover switchover; - char *plist; - } spt; + struct hash *rpf_hash; - struct hash *rpf_hash; + void *ssm_info; /* per-vrf SSM configuration */ - void *ssm_info; /* per-vrf SSM configuration */ - - int send_v6_secondary; + int send_v6_secondary; }; -extern struct pim_instance *pimg; //Pim Global Instance +extern struct pim_instance *pimg; // Pim Global Instance void pim_init(void); void pim_terminate(void); -extern void pim_route_map_init (void); +extern void pim_route_map_init(void); extern void pim_route_map_terminate(void); -void pim_vrf_init (void); -void pim_prefix_list_update (struct prefix_list *plist); +void pim_vrf_init(void); +void pim_prefix_list_update(struct prefix_list *plist); #endif /* PIMD_H */ diff --git a/pimd/test_igmpv3_join.c b/pimd/test_igmpv3_join.c index f363152ad..14ec9fb02 100644 --- a/pimd/test_igmpv3_join.c +++ b/pimd/test_igmpv3_join.c @@ -36,114 +36,114 @@ const char *prog_name = 0; static int iface_solve_index(const char *ifname) { - struct if_nameindex *ini; - ifindex_t ifindex = -1; - int i; - - if (!ifname) - return -1; - - ini = if_nameindex(); - if (!ini) { - int err = errno; - fprintf(stderr, - "%s: interface=%s: failure solving index: errno=%d: %s\n", - prog_name, ifname, err, strerror(err)); - errno = err; - return -1; - } - - for (i = 0; ini[i].if_index; ++i) { + struct if_nameindex *ini; + ifindex_t ifindex = -1; + int i; + + if (!ifname) + return -1; + + ini = if_nameindex(); + if (!ini) { + int err = errno; + fprintf(stderr, + "%s: interface=%s: failure solving index: errno=%d: %s\n", + prog_name, ifname, err, strerror(err)); + errno = err; + return -1; + } + + for (i = 0; ini[i].if_index; ++i) { #if 0 fprintf(stderr, "%s: interface=%s matching against local ifname=%s ifindex=%d\n", prog_name, ifname, ini[i].if_name, ini[i].if_index); #endif - if (!strcmp(ini[i].if_name, ifname)) { - ifindex = ini[i].if_index; - break; - } - } + if (!strcmp(ini[i].if_name, ifname)) { + ifindex = ini[i].if_index; + break; + } + } - if_freenameindex(ini); + if_freenameindex(ini); - return ifindex; + return ifindex; } int main(int argc, const char *argv[]) { - struct in_addr group_addr; - struct in_addr source_addr; - const char *ifname; - const char *group; - const char *source; - ifindex_t ifindex; - int result; - int fd; - - prog_name = argv[0]; - - fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (fd < 0) { - fprintf(stderr, - "%s: could not create socket: socket(): errno=%d: %s\n", - prog_name, errno, strerror(errno)); - exit(1); - } - - if (argc != 4) { - fprintf(stderr, - "usage: %s interface group source\n" - "example: %s eth0 232.1.1.1 1.1.1.1\n", - prog_name, prog_name); - exit(1); - } - - ifname = argv[1]; - group = argv[2]; - source = argv[3]; - - ifindex = iface_solve_index(ifname); - if (ifindex < 0) { - fprintf(stderr, "%s: could not find interface: %s\n", - prog_name, ifname); - exit(1); - } - - result = inet_pton(AF_INET, group, &group_addr); - if (result <= 0) { - fprintf(stderr, "%s: bad group address: %s\n", - prog_name, group); - exit(1); - } - - result = inet_pton(AF_INET, source, &source_addr); - if (result <= 0) { - fprintf(stderr, "%s: bad source address: %s\n", - prog_name, source); - exit(1); - } - - result = pim_igmp_join_source(fd, ifindex, group_addr, source_addr); - if (result) { - fprintf(stderr, - "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s\n", - prog_name, fd, group, source, ifindex, ifname, - errno, strerror(errno)); - exit(1); - } - - printf("%s: joined channel (S,G)=(%s,%s) on interface %s\n", - prog_name, source, group, ifname); - - printf("%s: waiting...\n", prog_name); - - getchar(); - - close(fd); - - printf("%s: left channel (S,G)=(%s,%s) on interface %s\n", - prog_name, source, group, ifname); - - exit(0); + struct in_addr group_addr; + struct in_addr source_addr; + const char *ifname; + const char *group; + const char *source; + ifindex_t ifindex; + int result; + int fd; + + prog_name = argv[0]; + + fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) { + fprintf(stderr, + "%s: could not create socket: socket(): errno=%d: %s\n", + prog_name, errno, strerror(errno)); + exit(1); + } + + if (argc != 4) { + fprintf(stderr, + "usage: %s interface group source\n" + "example: %s eth0 232.1.1.1 1.1.1.1\n", + prog_name, prog_name); + exit(1); + } + + ifname = argv[1]; + group = argv[2]; + source = argv[3]; + + ifindex = iface_solve_index(ifname); + if (ifindex < 0) { + fprintf(stderr, "%s: could not find interface: %s\n", prog_name, + ifname); + exit(1); + } + + result = inet_pton(AF_INET, group, &group_addr); + if (result <= 0) { + fprintf(stderr, "%s: bad group address: %s\n", prog_name, + group); + exit(1); + } + + result = inet_pton(AF_INET, source, &source_addr); + if (result <= 0) { + fprintf(stderr, "%s: bad source address: %s\n", prog_name, + source); + exit(1); + } + + result = pim_igmp_join_source(fd, ifindex, group_addr, source_addr); + if (result) { + fprintf(stderr, + "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s\n", + prog_name, fd, group, source, ifindex, ifname, errno, + strerror(errno)); + exit(1); + } + + printf("%s: joined channel (S,G)=(%s,%s) on interface %s\n", prog_name, + source, group, ifname); + + printf("%s: waiting...\n", prog_name); + + getchar(); + + close(fd); + + printf("%s: left channel (S,G)=(%s,%s) on interface %s\n", prog_name, + source, group, ifname); + + exit(0); } |