]> git.proxmox.com Git - mirror_frr.git/commitdiff
pimd: VxLAN-AA base APIs
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>
Sun, 24 Mar 2019 23:53:32 +0000 (16:53 -0700)
committerAnuradha Karuppiah <anuradhak@cumulusnetworks.com>
Sat, 20 Apr 2019 15:33:23 +0000 (08:33 -0700)
1. peerlink-rif as OIF in origination mroutes -
Hosts are multi-homed to the anycast-VTEP pair and can send BUM traffic to
either switch. But the RP would have only joined one MLAG switch for
pulling down the MDT. To make that work we add the peerlink/ISL as
an OIF to origination mroutes (TORC11<=>TORC12 is an anycast VTEP pair) -
root@TORC11:~# ip mr |grep "(36.0.0.9, 239.1.1.100)"
(36.0.0.9, 239.1.1.100)  Iif: peerlink-3.4094 Oifs: peerlink-3.4094 uplink-1
root@TORC11:~#
root@TORC12:~# ip mr |grep "(36.0.0.9, 239.1.1.100)"
(36.0.0.9, 239.1.1.100)  Iif: peerlink-3.4094 Oifs: peerlink-3.4094
root@TORC12:~#

2. VTEP-PIP as register source -
TORC11 and TORC12 share the same anycast VTEP IP (36.0.0.9 in the above
example). And that is the source registered by both VTEPs for all the BUM
mcast-groups. However to allow the pim register start machine to close
the SIP in the register-pkt's IP header must be set to an unique IP address.
This is the VTEP PIP.

Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
pimd/pim_vxlan.c
pimd/pim_vxlan.h

index e3cd0b9153ef3eb3c20dbf4b9b5c80819d8ce1d7..43269b74a1a15fd708e0dcede1f0c117fcf85c11 100644 (file)
@@ -43,6 +43,8 @@
 struct pim_vxlan vxlan_info, *pim_vxlan_p = &vxlan_info;
 
 static void pim_vxlan_work_timer_setup(bool start);
+static void pim_vxlan_set_peerlink_rif(struct pim_instance *pim,
+                       struct interface *ifp);
 
 /*************************** vxlan work list **********************************
  * A work list is maintained for staggered generation of pim null register
@@ -710,6 +712,101 @@ void pim_vxlan_sg_del(struct pim_instance *pim, struct prefix_sg *sg)
        XFREE(MTYPE_PIM_VXLAN_SG, vxlan_sg);
 }
 
+/******************************* MLAG handling *******************************/
+/* The peerlink sub-interface is added as an OIF to the origination-mroute.
+ * This is done to send a copy of the multicast-vxlan encapsulated traffic
+ * to the MLAG peer which may mroute it over the underlay if there are any
+ * interested receivers.
+ */
+static void pim_vxlan_sg_peerlink_update(struct hash_backet *backet, void *arg)
+{
+       struct interface *new_oif = (struct interface *)arg;
+       struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)backet->data;
+
+       if (!pim_vxlan_is_orig_mroute(vxlan_sg))
+               return;
+
+       if (vxlan_sg->orig_oif == new_oif)
+               return;
+
+       pim_vxlan_orig_mr_oif_del(vxlan_sg);
+
+       vxlan_sg->orig_oif = new_oif;
+       pim_vxlan_orig_mr_oif_add(vxlan_sg);
+}
+
+/* In the case of anycast VTEPs the VTEP-PIP must be used as the
+ * register source.
+ */
+bool pim_vxlan_get_register_src(struct pim_instance *pim,
+               struct pim_upstream *up, struct in_addr *src_p)
+{
+       if (!(vxlan_mlag.flags & PIM_VXLAN_MLAGF_ENABLED))
+               return true;
+
+       /* if address is not available suppress the pim-register */
+       if (vxlan_mlag.reg_addr.s_addr == INADDR_ANY)
+               return false;
+
+       *src_p = vxlan_mlag.reg_addr;
+       return true;
+}
+
+void pim_vxlan_mlag_update(bool enable, bool peer_state, uint32_t role,
+                               struct interface *peerlink_rif,
+                               struct in_addr *reg_addr)
+{
+       struct pim_instance *pim;
+       struct interface *old_oif;
+       struct interface *new_oif;
+       char addr_buf[INET_ADDRSTRLEN];
+       struct pim_interface *pim_ifp = NULL;
+
+       if (PIM_DEBUG_VXLAN) {
+               inet_ntop(AF_INET, reg_addr,
+                               addr_buf, INET_ADDRSTRLEN);
+               zlog_debug("vxlan MLAG update %s state %s role %d rif %s addr %s",
+                               enable ? "enable" : "disable",
+                               peer_state ? "up" : "down",
+                               role,
+                               peerlink_rif ? peerlink_rif->name : "-",
+                               addr_buf);
+       }
+
+       /* XXX: for now vxlan termination is only possible in the default VRF
+        * when that changes this will need to change to iterate all VRFs
+        */
+       pim = pim_get_pim_instance(VRF_DEFAULT);
+
+       old_oif = pim_vxlan_orig_mr_oif_get(pim);
+
+       if (enable)
+               vxlan_mlag.flags |= PIM_VXLAN_MLAGF_ENABLED;
+       else
+               vxlan_mlag.flags &= ~PIM_VXLAN_MLAGF_ENABLED;
+
+       if (vxlan_mlag.peerlink_rif != peerlink_rif)
+               vxlan_mlag.peerlink_rif = peerlink_rif;
+
+       vxlan_mlag.reg_addr = *reg_addr;
+       vxlan_mlag.peer_state = peer_state;
+       vxlan_mlag.role = role;
+
+       /* process changes */
+       if (vxlan_mlag.peerlink_rif)
+               pim_ifp = (struct pim_interface *)vxlan_mlag.peerlink_rif->info;
+       if ((vxlan_mlag.flags & PIM_VXLAN_MLAGF_ENABLED) &&
+                       pim_ifp && (pim_ifp->mroute_vif_index > 0))
+               pim_vxlan_set_peerlink_rif(pim, peerlink_rif);
+       else
+               pim_vxlan_set_peerlink_rif(pim, NULL);
+
+       new_oif = pim_vxlan_orig_mr_oif_get(pim);
+       if (old_oif != new_oif)
+               hash_iterate(pim->vxlan.sg_hash, pim_vxlan_sg_peerlink_update,
+                       new_oif);
+}
+
 /****************************** misc callbacks *******************************/
 static void pim_vxlan_set_default_iif(struct pim_instance *pim,
                                struct interface *ifp)
index 66234d26e8011db60155abb741a4c7e96207fec2..cdd250f1cd19f8412ca71094cfc3d8c66a3645b6 100644 (file)
@@ -128,5 +128,10 @@ extern void pim_vxlan_del_vif(struct interface *ifp);
 extern void pim_vxlan_add_term_dev(struct pim_instance *pim,
                struct interface *ifp);
 extern void pim_vxlan_del_term_dev(struct pim_instance *pim);
+extern bool pim_vxlan_get_register_src(struct pim_instance *pim,
+               struct pim_upstream *up, struct in_addr *src_p);
+extern void pim_vxlan_mlag_update(bool enable, bool peer_state, uint32_t role,
+                               struct interface *peerlink_rif,
+                               struct in_addr *reg_addr);
 
 #endif /* PIM_VXLAN_H */