diff options
Diffstat (limited to 'pimd')
| -rw-r--r-- | pimd/pim_bsm.c | 6 | ||||
| -rw-r--r-- | pimd/pim_bsm.h | 3 | ||||
| -rw-r--r-- | pimd/pim_cmd.c | 169 | ||||
| -rw-r--r-- | pimd/pim_ifchannel.c | 28 | ||||
| -rw-r--r-- | pimd/pim_igmp.c | 4 | ||||
| -rw-r--r-- | pimd/pim_igmpv2.c | 31 | ||||
| -rw-r--r-- | pimd/pim_igmpv2.h | 2 | ||||
| -rw-r--r-- | pimd/pim_mroute.c | 2 | ||||
| -rw-r--r-- | pimd/pim_rp.c | 4 | ||||
| -rw-r--r-- | pimd/pim_rp.h | 1 | ||||
| -rw-r--r-- | pimd/pim_static.c | 2 | ||||
| -rw-r--r-- | pimd/pim_upstream.c | 7 | ||||
| -rw-r--r-- | pimd/pim_vty.c | 7 | ||||
| -rw-r--r-- | pimd/pim_vxlan.h | 2 |
14 files changed, 242 insertions, 26 deletions
diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c index 1acfece895..e873af5759 100644 --- a/pimd/pim_bsm.c +++ b/pimd/pim_bsm.c @@ -63,7 +63,7 @@ void pim_bsm_write_config(struct vty *vty, struct interface *ifp) } } -static void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node) +void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node) { if (bsgrp_node->bsrp_list) list_delete(&bsgrp_node->bsrp_list); @@ -72,7 +72,7 @@ static void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node) XFREE(MTYPE_PIM_BSGRP_NODE, bsgrp_node); } -static void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp) +void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp) { struct route_node *rn; @@ -222,7 +222,7 @@ static int pim_on_bs_timer(struct thread *t) return 0; } -static void pim_bs_timer_stop(struct bsm_scope *scope) +void pim_bs_timer_stop(struct bsm_scope *scope) { if (PIM_DEBUG_BSM) zlog_debug("%s : BS timer being stopped of sz: %d", __func__, diff --git a/pimd/pim_bsm.h b/pimd/pim_bsm.h index 0758c94f19..2829c1e05a 100644 --- a/pimd/pim_bsm.h +++ b/pimd/pim_bsm.h @@ -195,4 +195,7 @@ int pim_bsm_process(struct interface *ifp, bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp); struct bsgrp_node *pim_bsm_get_bsgrp_node(struct bsm_scope *scope, struct prefix *grp); +void pim_bs_timer_stop(struct bsm_scope *scope); +void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node); +void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp); #endif diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 6d01cc73d7..ff85151839 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4001,6 +4001,152 @@ DEFUN (clear_ip_pim_oil, return CMD_SUCCESS; } +static void clear_pim_bsr_db(struct pim_instance *pim) +{ + struct route_node *rn; + struct route_node *rpnode; + struct bsgrp_node *bsgrp; + struct prefix nht_p; + struct prefix g_all; + struct rp_info *rp_all; + struct pim_upstream *up; + struct rp_info *rp_info; + bool is_bsr_tracking = true; + + /* Remove next hop tracking for the bsr */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = pim->global_scope.current_bsr; + if (PIM_DEBUG_BSM) { + zlog_debug("%s: Deregister BSR addr %pFX with Zebra NHT", + __func__, &nht_p); + } + pim_delete_tracked_nexthop(pim, &nht_p, NULL, NULL, is_bsr_tracking); + + /* Reset scope zone data */ + pim->global_scope.accept_nofwd_bsm = false; + pim->global_scope.state = ACCEPT_ANY; + pim->global_scope.current_bsr.s_addr = INADDR_ANY; + pim->global_scope.current_bsr_prio = 0; + pim->global_scope.current_bsr_first_ts = 0; + pim->global_scope.current_bsr_last_ts = 0; + pim->global_scope.bsm_frag_tag = 0; + list_delete_all_node(pim->global_scope.bsm_list); + + pim_bs_timer_stop(&pim->global_scope); + + for (rn = route_top(pim->global_scope.bsrp_table); rn; + rn = route_next(rn)) { + bsgrp = rn->info; + if (!bsgrp) + continue; + + rpnode = route_node_lookup(pim->rp_table, &bsgrp->group); + + if (!rpnode) { + pim_free_bsgrp_node(bsgrp->scope->bsrp_table, + &bsgrp->group); + pim_free_bsgrp_data(bsgrp); + continue; + } + + rp_info = (struct rp_info *)rpnode->info; + + if ((!rp_info) || (rp_info->rp_src != RP_SRC_BSR)) { + pim_free_bsgrp_node(bsgrp->scope->bsrp_table, + &bsgrp->group); + pim_free_bsgrp_data(bsgrp); + continue; + } + + /* 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_NHT_RP) { + zlog_debug("%s: Deregister RP addr %pFX with Zebra ", + __func__, &nht_p); + } + + pim_delete_tracked_nexthop(pim, &nht_p, NULL, rp_info, false); + + if (!str2prefix("224.0.0.0/4", &g_all)) + return; + + rp_all = pim_rp_find_match_group(pim, &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; + } else { + /* Delete the rp_info from rp-list */ + listnode_delete(pim->rp_list, rp_info); + + /* Delete the rp node from rp_table */ + rpnode->info = NULL; + route_unlock_node(rpnode); + route_unlock_node(rpnode); + } + + XFREE(MTYPE_PIM_RP, rp_info); + + pim_free_bsgrp_node(bsgrp->scope->bsrp_table, &bsgrp->group); + pim_free_bsgrp_data(bsgrp); + } + pim_rp_refresh_group_to_rp_mapping(pim); + + + frr_each (rb_pim_upstream, &pim->upstream_head, up) { + /* Find the upstream (*, G) whose upstream address is same as + * the RP + */ + if (up->sg.src.s_addr != INADDR_ANY) + continue; + + struct prefix grp; + struct rp_info *trp_info; + + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = up->sg.grp; + + trp_info = pim_rp_find_match_group(pim, &grp); + + /* RP not found for the group grp */ + if (pim_rpf_addr_is_inaddr_none(&trp_info->rp)) { + pim_upstream_rpf_clear(pim, up); + pim_rp_set_upstream_addr(pim, &up->upstream_addr, + up->sg.src, up->sg.grp); + } else { + /* RP found for the group grp */ + pim_upstream_update(pim, up); + } + } +} + + +DEFUN (clear_ip_pim_bsr_db, + clear_ip_pim_bsr_db_cmd, + "clear ip pim [vrf NAME] bsr-data", + CLEAR_STR + IP_STR + CLEAR_IP_PIM_STR + VRF_CMD_HELP_STR + "Reset pim bsr data\n") +{ + int idx = 2; + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + + if (!vrf) + return CMD_WARNING; + + clear_pim_bsr_db(vrf->info); + + return CMD_SUCCESS; +} + DEFUN (show_ip_igmp_interface, show_ip_igmp_interface_cmd, "show ip igmp [vrf NAME] interface [detail|WORD] [json]", @@ -4560,8 +4706,8 @@ DEFPY (show_ip_pim_join, return CMD_WARNING; } - if (s_or_g.s_addr != 0) { - if (g.s_addr != 0) { + if (s_or_g.s_addr != INADDR_ANY) { + if (g.s_addr != INADDR_ANY) { sg.src = s_or_g; sg.grp = g; } else @@ -5180,8 +5326,8 @@ DEFPY (show_ip_pim_upstream, return CMD_WARNING; } - if (s_or_g.s_addr != 0) { - if (g.s_addr != 0) { + if (s_or_g.s_addr != INADDR_ANY) { + if (g.s_addr != INADDR_ANY) { sg.src = s_or_g; sg.grp = g; } else @@ -5858,7 +6004,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, vty_out(vty, "IP Multicast Routing Table\n"); vty_out(vty, "Flags: S - Sparse, C - Connected, P - Pruned\n"); vty_out(vty, - " R - RP-bit set, F - Register flag, T - SPT-bit set\n"); + " R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n"); vty_out(vty, "\nSource Group Flags Proto Input Output TTL Uptime\n"); } @@ -5872,11 +6018,11 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, if (!c_oil->installed) continue; - if (sg->grp.s_addr != 0 && - sg->grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr) + if (sg->grp.s_addr != INADDR_ANY + && sg->grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr) continue; - if (sg->src.s_addr != 0 && - sg->src.s_addr != c_oil->oil.mfcc_origin.s_addr) + if (sg->src.s_addr != INADDR_ANY + && sg->src.s_addr != c_oil->oil.mfcc_origin.s_addr) continue; pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, @@ -6232,8 +6378,8 @@ DEFPY (show_ip_mroute, return CMD_WARNING; } - if (s_or_g.s_addr != 0) { - if (g.s_addr != 0) { + if (s_or_g.s_addr != INADDR_ANY) { + if (g.s_addr != INADDR_ANY) { sg.src = s_or_g; sg.grp = g; } else @@ -11396,6 +11542,7 @@ void pim_cmd_init(void) install_element(ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd); install_element(ENABLE_NODE, &clear_ip_pim_oil_cmd); install_element(ENABLE_NODE, &clear_ip_pim_statistics_cmd); + install_element(ENABLE_NODE, &clear_ip_pim_bsr_db_cmd); install_element(ENABLE_NODE, &show_debugging_pim_cmd); diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index e7ff434f4b..fc0f514a49 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -550,8 +550,21 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, struct pim_upstream *up; ch = pim_ifchannel_find(ifp, sg); - if (ch) + if (ch) { + if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_PIM) + PIM_IF_FLAG_SET_PROTO_PIM(ch->flags); + + if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + PIM_IF_FLAG_SET_PROTO_IGMP(ch->flags); + + if (ch->upstream) + ch->upstream->flags |= up_flags; + else if (PIM_DEBUG_EVENTS) + zlog_debug("%s:%s No Upstream found", __func__, + pim_str_sg_dump(sg)); + return ch; + } pim_ifp = ifp->info; @@ -642,6 +655,12 @@ static void ifjoin_to_noinfo(struct pim_ifchannel *ch, bool ch_del) { pim_forward_stop(ch, !ch_del); pim_ifchannel_ifjoin_switch(__func__, ch, PIM_IFJOIN_NOINFO); + + if (ch->upstream) + PIM_UPSTREAM_FLAG_UNSET_SRC_PIM(ch->upstream->flags); + + PIM_IF_FLAG_UNSET_PROTO_PIM(ch->flags); + if (ch_del) delete_on_noinfo(ch); } @@ -1272,6 +1291,13 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, * parent' delete_no_info */ } } + + /* Resettng the IGMP flags here */ + if (orig->upstream) + PIM_UPSTREAM_FLAG_UNSET_SRC_IGMP(orig->upstream->flags); + + PIM_IF_FLAG_UNSET_PROTO_IGMP(orig->flags); + delete_on_noinfo(orig); } diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 9924e335b0..73e42e9d83 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -558,8 +558,8 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len) 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); + return igmp_v2_recv_leave(igmp, ip_hdr, from_str, igmp_msg, + igmp_msg_len); case PIM_IGMP_MTRACE_RESPONSE: return igmp_mtrace_recv_response(igmp, ip_hdr, ip_hdr->ip_src, diff --git a/pimd/pim_igmpv2.c b/pimd/pim_igmpv2.c index d836c66cbb..7f3c7a0f8c 100644 --- a/pimd/pim_igmpv2.c +++ b/pimd/pim_igmpv2.c @@ -158,12 +158,13 @@ int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from, return 0; } -int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from, +int igmp_v2_recv_leave(struct igmp_sock *igmp, struct ip *ip_hdr, 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]; + struct in_addr from = ip_hdr->ip_src; on_trace(__func__, igmp->interface, from); @@ -184,8 +185,6 @@ int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from, return -1; } - /* Collecting IGMP Rx stats */ - igmp->rx_stats.leave_v2++; memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); @@ -195,6 +194,32 @@ int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from, zlog_debug("Recv IGMPv2 LEAVE from %s on %s for %s", from_str, ifp->name, group_str); } + /* + * As per RFC 2236, section 9: + Message Type Destination Group + ------------ ----------------- + General Query ALL-SYSTEMS (224.0.0.1) + Group-Specific Query The group being queried + Membership Report The group being reported + Leave Message ALL-ROUTERS (224.0.0.2) + + Note: in older (i.e., non-standard and now obsolete) versions of + IGMPv2, hosts send Leave Messages to the group being left. A + router SHOULD accept Leave Messages addressed to the group being + left in the interests of backwards compatibility with such hosts. + In all cases, however, hosts MUST send to the ALL-ROUTERS address + to be compliant with this specification. + */ + if ((ntohl(ip_hdr->ip_dst.s_addr) != INADDR_ALLRTRS_GROUP) + && (ip_hdr->ip_dst.s_addr != group_addr.s_addr)) { + if (PIM_DEBUG_IGMP_EVENTS) + zlog_debug( + "IGMPv2 Leave message is ignored since received on address other than ALL-ROUTERS or Group-address"); + return -1; + } + + /* Collecting IGMP Rx stats */ + igmp->rx_stats.leave_v2++; /* * RFC 3376 diff --git a/pimd/pim_igmpv2.h b/pimd/pim_igmpv2.h index f0a6fdc5fb..29591ff16c 100644 --- a/pimd/pim_igmpv2.h +++ b/pimd/pim_igmpv2.h @@ -29,7 +29,7 @@ void igmp_v2_send_query(struct igmp_group *group, int fd, const char *ifname, 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, +int igmp_v2_recv_leave(struct igmp_sock *igmp, struct ip *ip_hdr, const char *from_str, char *igmp_msg, int igmp_msg_len); #endif /* PIM_IGMPV2_H */ diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 0bccba397b..23259900b7 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -628,7 +628,7 @@ static int pim_mroute_msg(struct pim_instance *pim, const char *buf, ifaddr = connected_src->u.prefix4; igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr); - if (PIM_DEBUG_MROUTE) { + if (PIM_DEBUG_IGMP_PACKETS) { zlog_debug( "%s(%s): igmp kernel upcall on %s(%p) for %pI4 -> %pI4", __func__, pim->vrf->name, ifp->name, igmp, diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 727daa42c1..301a27001f 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -271,7 +271,7 @@ struct rp_info *pim_rp_find_match_group(struct pim_instance *pim, * * This is a placeholder function for now. */ -static void pim_rp_refresh_group_to_rp_mapping(struct pim_instance *pim) +void pim_rp_refresh_group_to_rp_mapping(struct pim_instance *pim) { pim_msdp_i_am_rp_changed(pim); pim_upstream_reeval_use_rpt(pim); @@ -1319,7 +1319,7 @@ void pim_resolve_rp_nh(struct pim_instance *pim, struct pim_neighbor *nbr) continue; for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) { - if (nh_node->gate.ipv4.s_addr != 0) + if (nh_node->gate.ipv4.s_addr != INADDR_ANY) continue; struct interface *ifp1 = if_lookup_by_index( diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index 8a12cb076c..dd7cd5d75e 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -86,4 +86,5 @@ int pim_rp_list_cmp(void *v1, void *v2); struct rp_info *pim_rp_find_match_group(struct pim_instance *pim, const struct prefix *group); void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up); +void pim_rp_refresh_group_to_rp_mapping(struct pim_instance *pim); #endif diff --git a/pimd/pim_static.c b/pimd/pim_static.c index 91c9b5b933..63a9a00659 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -345,7 +345,7 @@ int pim_static_write_mroute(struct pim_instance *pim, struct vty *vty, struct interface *oifp = pim_if_find_by_vif_index(pim, i); - if (sroute->source.s_addr == 0) + if (sroute->source.s_addr == INADDR_ANY) vty_out(vty, " ip mroute %s %s\n", oifp->name, gbuf); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index d95b092d94..9899172e6c 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -749,6 +749,13 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up, bool send_xg_jp = false; forward_off(up); + /* + * RFC 4601 Sec 4.5.7: + * JoinDesired(S,G) -> False, set SPTbit to false. + */ + if (up->sg.src.s_addr != INADDR_ANY) + up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE; + if (old_state == PIM_UPSTREAM_JOINED) pim_msdp_up_join_state_changed(pim, up); diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 1f2ca11db3..57a0c69166 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -275,6 +275,13 @@ int pim_interface_config_write(struct vty *vty) continue; FOR_ALL_INTERFACES (pim->vrf, ifp) { + /* pim is enabled internally/implicitly on the vxlan + * termination device ipmr-lo. skip displaying that + * config to avoid confusion + */ + if (pim_vxlan_is_term_dev_cfg(pim, ifp)) + continue; + /* IF name */ if (vrf->vrf_id == VRF_DEFAULT) vty_frame(vty, "interface %s\n", ifp->name); diff --git a/pimd/pim_vxlan.h b/pimd/pim_vxlan.h index 18f1b74175..ce9054cd26 100644 --- a/pimd/pim_vxlan.h +++ b/pimd/pim_vxlan.h @@ -109,7 +109,7 @@ struct pim_vxlan { */ static inline bool pim_vxlan_is_orig_mroute(struct pim_vxlan_sg *vxlan_sg) { - return (vxlan_sg->sg.src.s_addr != 0); + return (vxlan_sg->sg.src.s_addr != INADDR_ANY); } static inline bool pim_vxlan_is_local_sip(struct pim_upstream *up) |
