]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: MSDP SA forwarding
authorAdriano Marto Reis <adrianomarto@gmail.com>
Thu, 9 Jul 2020 22:56:24 +0000 (08:56 +1000)
committerDonald Sharp <sharpd@nvidia.com>
Tue, 6 Oct 2020 12:11:24 +0000 (08:11 -0400)
* 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>
pimd/pim_cmd.c
pimd/pim_msdp.c
pimd/pim_msdp_packet.c
pimd/pim_msdp_packet.h

index db3f0b8b234903d317f6d372509c5aadbb574bd8..6256774464cbe4ade2935343ec072000ca681164 100644 (file)
@@ -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
index b42092a464981ae52d6aaf0d3a4279bdb523e713..7336cdfef8b8c6c2962e81a0fb0217194b084553 100644 (file)
@@ -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;
 }
 
index 39e39b9557fe8596fce50952c643e016c3ad1fe2..4aaf0f53d178905c754c47d7f47f90a677155075 100644 (file)
@@ -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);
index d922fa50dfb8e059ea30480261c5e4d0dfd3c7a4..f5af8d11408596d7b394e63304d683e46fd2a9a3 100644 (file)
@@ -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