summaryrefslogtreecommitdiffstats
path: root/pimd/pim_vxlan.c
diff options
context:
space:
mode:
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2019-03-25 00:53:32 +0100
committerAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2019-04-20 17:33:23 +0200
commit48b33862456347f8028a30c4b332919d495982ed (patch)
tree07c61aa8c7ae1102dc7145f90e832003b2ca3afc /pimd/pim_vxlan.c
parentpimd: handling termination device in the MFC (diff)
downloadfrr-48b33862456347f8028a30c4b332919d495982ed.tar.xz
frr-48b33862456347f8028a30c4b332919d495982ed.zip
pimd: VxLAN-AA base APIs
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>
Diffstat (limited to 'pimd/pim_vxlan.c')
-rw-r--r--pimd/pim_vxlan.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c
index e3cd0b915..43269b74a 100644
--- a/pimd/pim_vxlan.c
+++ b/pimd/pim_vxlan.c
@@ -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)