From: Adriano Marto Reis Date: Thu, 9 Jul 2020 22:56:24 +0000 (+1000) Subject: pimd: MSDP SA forwarding X-Git-Tag: base_7.6~456^2~1 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=9fbd9fc48f7c620dc505ba27319b86035d7dc142;p=mirror%2Ffrr.git pimd: MSDP SA forwarding * If the MSDP peer receives the SA from a non-RPF peer towards the originating RP, it will drop the message. * SA messages are forwarded away from the RP address only. * SA messages are not forwarded within the mesh group. * Preventing the MSDP connection from being dropped due to RPF check failure (RFC3618, section 13 "MSDP Error Handling") Signed-off-by: Adriano Marto Reis Signed-off-by: Adriano Reis --- diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index db3f0b8b23..6256774464 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -9694,7 +9694,7 @@ static int ip_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty, return ret; } -DEFUN_HIDDEN (ip_msdp_peer, +DEFUN (ip_msdp_peer, ip_msdp_peer_cmd, "ip msdp peer A.B.C.D source A.B.C.D", IP_STR @@ -9735,7 +9735,7 @@ static int ip_no_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty, return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } -DEFUN_HIDDEN (no_ip_msdp_peer, +DEFUN (no_ip_msdp_peer, no_ip_msdp_peer_cmd, "no ip msdp peer A.B.C.D", NO_STR diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index b42092a464..7336cdfef8 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -423,6 +423,7 @@ void pim_msdp_sa_ref(struct pim_instance *pim, struct pim_msdp_peer *mp, sa->sg_str); } /* send an immediate SA update to peers */ + sa->rp = pim->msdp.originator_id; pim_msdp_pkt_sa_tx_one(sa); } sa->flags &= ~PIM_MSDP_SAF_STALE; @@ -721,10 +722,18 @@ static int pim_msdp_sa_comp(const void *p1, const void *p2) /* 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) { + struct pim_nexthop nexthop; + if (mp->peer.s_addr == rp.s_addr) { return true; } + /* check if the MSDP peer is the nexthop for the RP */ + if (pim_nexthop_lookup(mp->pim, &nexthop, rp, 0) + && nexthop.mrib_nexthop_addr.u.prefix4.s_addr == mp->peer.s_addr) { + return true; + } + return false; } diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c index 39e39b9557..4aaf0f53d1 100644 --- a/pimd/pim_msdp_packet.c +++ b/pimd/pim_msdp_packet.c @@ -348,7 +348,8 @@ static void pim_msdp_pkt_sa_push(struct pim_instance *pim, } } -static int pim_msdp_pkt_sa_fill_hdr(struct pim_instance *pim, int local_cnt) +static int pim_msdp_pkt_sa_fill_hdr(struct pim_instance *pim, int local_cnt, + struct in_addr rp) { int curr_tlv_ecnt; @@ -361,7 +362,7 @@ static int pim_msdp_pkt_sa_fill_hdr(struct pim_instance *pim, int local_cnt) stream_putw(pim->msdp.work_obuf, PIM_MSDP_SA_ENTRY_CNT2SIZE(curr_tlv_ecnt)); stream_putc(pim->msdp.work_obuf, curr_tlv_ecnt); - stream_put_ipv4(pim->msdp.work_obuf, pim->msdp.originator_id.s_addr); + stream_put_ipv4(pim->msdp.work_obuf, rp.s_addr); return local_cnt; } @@ -387,7 +388,8 @@ static void pim_msdp_pkt_sa_gen(struct pim_instance *pim, zlog_debug(" sa gen %d", local_cnt); } - local_cnt = pim_msdp_pkt_sa_fill_hdr(pim, local_cnt); + local_cnt = pim_msdp_pkt_sa_fill_hdr(pim, local_cnt, + pim->msdp.originator_id); for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) { if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { @@ -408,7 +410,8 @@ static void pim_msdp_pkt_sa_gen(struct pim_instance *pim, zlog_debug(" sa gen for remainder %d", local_cnt); } - local_cnt = pim_msdp_pkt_sa_fill_hdr(pim, local_cnt); + local_cnt = pim_msdp_pkt_sa_fill_hdr( + pim, local_cnt, pim->msdp.originator_id); } } @@ -441,7 +444,7 @@ void pim_msdp_pkt_sa_tx(struct pim_instance *pim) void pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa *sa) { - pim_msdp_pkt_sa_fill_hdr(sa->pim, 1 /* cnt */); + pim_msdp_pkt_sa_fill_hdr(sa->pim, 1 /* cnt */, sa->rp); pim_msdp_pkt_sa_fill_one(sa); pim_msdp_pkt_sa_push(sa->pim, NULL); pim_msdp_pkt_sa_tx_done(sa->pim); @@ -454,6 +457,24 @@ void pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer *mp) pim_msdp_pkt_sa_tx_done(mp->pim); } +void pim_msdp_pkt_sa_tx_one_to_one_peer(struct pim_msdp_peer *mp, + struct in_addr rp, struct prefix_sg sg) +{ + struct pim_msdp_sa sa; + + /* Fills the SA header. */ + pim_msdp_pkt_sa_fill_hdr(mp->pim, 1, rp); + + /* Fills the message contents. */ + sa.pim = mp->pim; + sa.sg = sg; + pim_msdp_pkt_sa_fill_one(&sa); + + /* Pushes the message. */ + pim_msdp_pkt_sa_push(sa.pim, mp); + pim_msdp_pkt_sa_tx_done(sa.pim); +} + static void pim_msdp_pkt_rxed_with_fatal_error(struct pim_msdp_peer *mp) { pim_msdp_peer_reset_tcp_conn(mp, "invalid-pkt-rx"); @@ -473,6 +494,8 @@ static void pim_msdp_pkt_sa_rx_one(struct pim_msdp_peer *mp, struct in_addr rp) { int prefix_len; struct prefix_sg sg; + struct listnode *peer_node; + struct pim_msdp_peer *peer; /* just throw away the three reserved bytes */ stream_get3(mp->ibuf); @@ -493,6 +516,18 @@ static void pim_msdp_pkt_sa_rx_one(struct pim_msdp_peer *mp, struct in_addr rp) zlog_debug(" sg %s", pim_str_sg_dump(&sg)); } pim_msdp_sa_ref(mp->pim, mp, &sg, rp); + + /* Forwards the SA to the peers that are not in the RPF to the RP nor in + * the same mesh group as the peer from which we received the message. + * If the message group is not set, i.e. "default", then we assume that + * the message must be forwarded.*/ + for (ALL_LIST_ELEMENTS_RO(mp->pim->msdp.peer_list, peer_node, peer)) { + if (!pim_msdp_peer_rpf_check(peer, rp) + && (strcmp(mp->mesh_group_name, peer->mesh_group_name) + || !strcmp(mp->mesh_group_name, "default"))) { + pim_msdp_pkt_sa_tx_one_to_one_peer(peer, rp, sg); + } + } } static void pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len) @@ -510,10 +545,9 @@ static void pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len) 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 */ + * 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; @@ -526,6 +560,8 @@ static void pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len) zlog_debug(" entry_cnt %d rp %s", entry_cnt, rp_str); } + pim_msdp_peer_pkt_rxed(mp); + if (!pim_msdp_peer_rpf_check(mp, rp)) { /* if peer-RPF check fails don't process the packet any further */ @@ -535,8 +571,6 @@ static void pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len) 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); diff --git a/pimd/pim_msdp_packet.h b/pimd/pim_msdp_packet.h index d922fa50df..f5af8d1140 100644 --- a/pimd/pim_msdp_packet.h +++ b/pimd/pim_msdp_packet.h @@ -67,5 +67,7 @@ int pim_msdp_read(struct thread *thread); void pim_msdp_pkt_sa_tx(struct pim_instance *pim); void pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa *sa); void pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer *mp); +void pim_msdp_pkt_sa_tx_one_to_one_peer(struct pim_msdp_peer *mp, + struct in_addr rp, struct prefix_sg sg); #endif