summaryrefslogtreecommitdiffstats
path: root/pimd/pim_msdp_packet.c
diff options
context:
space:
mode:
authorAdriano Marto Reis <adrianomarto@gmail.com>2020-07-10 00:56:24 +0200
committerDonald Sharp <sharpd@nvidia.com>2020-10-06 14:11:24 +0200
commit9fbd9fc48f7c620dc505ba27319b86035d7dc142 (patch)
tree84b11ff4784c2ae8800f55a019d24c13a027f7d0 /pimd/pim_msdp_packet.c
parentMerge pull request #6904 from chiragshah6/yang_nb6 (diff)
downloadfrr-9fbd9fc48f7c620dc505ba27319b86035d7dc142.tar.xz
frr-9fbd9fc48f7c620dc505ba27319b86035d7dc142.zip
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 <adrianomarto@gmail.com> Signed-off-by: Adriano Reis <areis@barrukka.local>
Diffstat (limited to 'pimd/pim_msdp_packet.c')
-rw-r--r--pimd/pim_msdp_packet.c56
1 files changed, 45 insertions, 11 deletions
diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c
index 39e39b955..4aaf0f53d 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);