diff options
author | Anuradha Karuppiah <anuradhak@cumulusnetworks.com> | 2019-11-15 18:29:04 +0100 |
---|---|---|
committer | Anuradha Karuppiah <anuradhak@cumulusnetworks.com> | 2019-11-15 18:29:04 +0100 |
commit | 5a5f404e1b69c35034a8f57b81a37e4972681003 (patch) | |
tree | 2f4d8d9c7063fac321bea21cad7b108ee22f8adc /pimd/pim_mroute.c | |
parent | pimd: MUTE flag to suppress traffic forwarding on non-DF (diff) | |
download | frr-5a5f404e1b69c35034a8f57b81a37e4972681003.tar.xz frr-5a5f404e1b69c35034a8f57b81a37e4972681003.zip |
pimd: build a temp copy of the OIL for kernel mroute add
1. This avoids the needs to re-run "muting" decisions.
2. Avoids the need to restore's pim OIL after fixup and send to kernel
(this is getting harder to manage).
In the future we need to also move the PIM maintained channel OIL from
an array of MAXVIFs to a simple DLL. This will be a significant
optimization in memory usage and preformance (OIL reads, copies etc).
Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
Diffstat (limited to 'pimd/pim_mroute.c')
-rw-r--r-- | pimd/pim_mroute.c | 89 |
1 files changed, 29 insertions, 60 deletions
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index ec06cd734..f28d801f0 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -882,18 +882,28 @@ int pim_mroute_del_vif(struct interface *ifp) return 0; } +static inline void pim_mroute_copy(struct mfcctl *oil, + struct channel_oil *c_oil) +{ + int i; + + oil->mfcc_origin = c_oil->oil.mfcc_origin; + oil->mfcc_mcastgrp = c_oil->oil.mfcc_mcastgrp; + oil->mfcc_parent = c_oil->oil.mfcc_parent; + + for (i = 0; i < MAXVIFS; ++i) { + if (c_oil->oif_flags[i] & PIM_OIF_FLAG_MUTE) + oil->mfcc_ttls[i] = 0; + else + oil->mfcc_ttls[i] = c_oil->oil.mfcc_ttls[i]; + } +} + int pim_mroute_add(struct channel_oil *c_oil, const char *name) { struct pim_instance *pim = c_oil->pim; + struct mfcctl tmp_oil; int err; - int orig = 0; - int orig_iif_vif = 0; - struct pim_interface *pim_reg_ifp = NULL; - int orig_pimreg_ttl = 0; - bool pimreg_ttl_reset = false; - struct pim_interface *vxlan_ifp = NULL; - int orig_term_ttl = 0; - bool orig_term_ttl_reset = false; pim->mroute_add_last = pim_time_monotonic_sec(); ++pim->mroute_add_events; @@ -910,44 +920,17 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name) return -2; } + /* Copy the oil to a temporary structure to fixup (without need to + * later restore) before sending the mroute add to the dataplane + */ + pim_mroute_copy(&tmp_oil, c_oil); + /* The linux kernel *expects* the incoming * vif to be part of the outgoing list * in the case of a (*,G). */ if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) { - orig = c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent]; - c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1; - } - - if (c_oil->up) { - /* suppress pimreg in the OIL if the mroute is not supposed to - * trigger register encapsulated data - */ - if (PIM_UPSTREAM_FLAG_TEST_NO_PIMREG_DATA(c_oil->up->flags)) { - pim_reg_ifp = pim->regiface->info; - orig_pimreg_ttl = - c_oil->oil.mfcc_ttls[pim_reg_ifp->mroute_vif_index]; - c_oil->oil.mfcc_ttls[pim_reg_ifp->mroute_vif_index] = 0; - /* remember to flip it back after MFC programming */ - pimreg_ttl_reset = true; - } - - vxlan_ifp = pim_vxlan_get_term_ifp(pim); - /* 1. vxlan termination device must never be added to the - * origination mroute (and that can actually happen because - * of XG inheritance from the termination mroute) otherwise - * traffic will end up looping. - * 2. vxlan termination device should be removed from the non-DF - * to prevent duplicates to the overlay rxer - */ - if (vxlan_ifp && - (PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_ORIG(c_oil->up->flags) || - PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(c_oil->up->flags))) { - orig_term_ttl_reset = true; - orig_term_ttl = - c_oil->oil.mfcc_ttls[vxlan_ifp->mroute_vif_index]; - c_oil->oil.mfcc_ttls[vxlan_ifp->mroute_vif_index] = 0; - } + tmp_oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1; } /* @@ -959,33 +942,19 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name) */ if (!c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY && c_oil->oil.mfcc_parent != 0) { - orig_iif_vif = c_oil->oil.mfcc_parent; - c_oil->oil.mfcc_parent = 0; + tmp_oil.mfcc_parent = 0; } err = setsockopt(pim->mroute_socket, IPPROTO_IP, MRT_ADD_MFC, - &c_oil->oil, sizeof(c_oil->oil)); + &tmp_oil, sizeof(tmp_oil)); if (!err && !c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY - && orig_iif_vif != 0) { - c_oil->oil.mfcc_parent = orig_iif_vif; + && c_oil->oil.mfcc_parent != 0) { + tmp_oil.mfcc_parent = c_oil->oil.mfcc_parent; err = setsockopt(pim->mroute_socket, IPPROTO_IP, MRT_ADD_MFC, - &c_oil->oil, sizeof(c_oil->oil)); + &tmp_oil, sizeof(tmp_oil)); } - if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) - c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig; - - if (pimreg_ttl_reset) { - assert(pim_reg_ifp); - c_oil->oil.mfcc_ttls[pim_reg_ifp->mroute_vif_index] = - orig_pimreg_ttl; - } - - if (orig_term_ttl_reset) - c_oil->oil.mfcc_ttls[vxlan_ifp->mroute_vif_index] = - orig_term_ttl; - if (err) { zlog_warn( "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s", |