From 48b33862456347f8028a30c4b332919d495982ed Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Sun, 24 Mar 2019 16:53:32 -0700 Subject: [PATCH] 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 --- pimd/pim_vxlan.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ pimd/pim_vxlan.h | 5 +++ 2 files changed, 102 insertions(+) diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c index e3cd0b9153..43269b74a1 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) diff --git a/pimd/pim_vxlan.h b/pimd/pim_vxlan.h index 66234d26e8..cdd250f1cd 100644 --- a/pimd/pim_vxlan.h +++ b/pimd/pim_vxlan.h @@ -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 */ -- 2.39.5