summaryrefslogtreecommitdiff
path: root/ospfd/ospf_orr.c
diff options
context:
space:
mode:
Diffstat (limited to 'ospfd/ospf_orr.c')
-rw-r--r--ospfd/ospf_orr.c594
1 files changed, 0 insertions, 594 deletions
diff --git a/ospfd/ospf_orr.c b/ospfd/ospf_orr.c
deleted file mode 100644
index eed948b190..0000000000
--- a/ospfd/ospf_orr.c
+++ /dev/null
@@ -1,594 +0,0 @@
-/*
- * OSPF BGP-IGP IGP metric update handling routines
- * Copyright (C) 2021 Samsung R&D Institute India - Bangalore.
- * Madhurilatha Kuruganti
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <zebra.h>
-#include <string.h>
-
-#include "monotime.h"
-#include "memory.h"
-#include "thread.h"
-#include "prefix.h"
-#include "table.h"
-#include "vty.h"
-#include "command.h"
-#include "plist.h"
-#include "log.h"
-#include "zclient.h"
-#include <lib/json.h>
-#include "defaults.h"
-#include "orr_msg.h"
-
-#include "ospfd.h"
-#include "ospf_asbr.h"
-#include "ospf_dump.h"
-#include "ospf_lsa.h"
-#include "ospf_orr.h"
-#include "ospf_route.h"
-#include "ospf_spf.h"
-#include "ospf_te.h"
-
-static void ospf_show_orr_root(struct orr_root *root);
-static void ospf_show_orr(struct ospf *ospf, afi_t afi, safi_t safi);
-static struct orr_root *ospf_orr_root_new(struct ospf *ospf, afi_t afi,
- safi_t safi, struct prefix *p,
- char *group_name)
-{
- struct list *orr_root_list = NULL;
- struct orr_root *root = NULL;
-
- if (!ospf->orr_root[afi][safi])
- ospf->orr_root[afi][safi] = list_new();
-
- orr_root_list = ospf->orr_root[afi][safi];
- root = XCALLOC(MTYPE_OSPF_ORR_ROOT, sizeof(struct orr_root));
-
- listnode_add(orr_root_list, root);
-
- root->afi = afi;
- root->safi = safi;
- prefix_copy(&root->prefix, p);
- IPV4_ADDR_COPY(&root->router_id, &p->u.prefix4);
- strlcpy(root->group_name, group_name, sizeof(root->group_name));
- root->new_rtrs = NULL;
- root->new_table = NULL;
-
- ospf_orr_debug(
- "%s: For %s %s, ORR Group %s, created ORR Root entry %pFX.",
- __func__, afi2str(afi), safi2str(safi), root->group_name, p);
-
- return root;
-}
-
-static struct orr_root *ospf_orr_root_lookup(struct ospf *ospf, afi_t afi,
- safi_t safi, struct in_addr *rid)
-{
- struct list *orr_root_list = NULL;
- struct orr_root *root = NULL;
- struct listnode *node;
-
- orr_root_list = ospf->orr_root[afi][safi];
- if (!orr_root_list)
- return NULL;
-
- for (ALL_LIST_ELEMENTS_RO(orr_root_list, node, root))
- if (IPV4_ADDR_SAME(&root->router_id, rid))
- return root;
-
- ospf_orr_debug("%s: For %s %s, ORR Root '%pI4' not found.", __func__,
- afi2str(afi), safi2str(safi), rid);
-
- return NULL;
-}
-
-static struct orr_root *ospf_orr_root_lookup_by_adv_rid(struct ospf *ospf,
- afi_t afi, safi_t safi,
- struct in_addr *rid)
-{
- struct list *orr_root_list = NULL;
- struct orr_root *root = NULL;
- struct listnode *node;
-
- orr_root_list = ospf->orr_root[afi][safi];
- if (!orr_root_list)
- return NULL;
-
- for (ALL_LIST_ELEMENTS_RO(orr_root_list, node, root))
- if (IPV4_ADDR_SAME(&root->adv_router, rid))
- return root;
-
- return NULL;
-}
-
-/*
- * Lookup each area's LSDB if is there is any opaque area LSA received and
- * update the root database with the advertising router.
- */
-static struct ospf_lsa *
-ospf_orr_lookup_opaque_area_lsa_by_id(struct in_addr rid)
-{
- struct ospf_lsa *lsa = NULL;
- struct ospf_area *area = NULL;
- struct ospf *ospf = NULL;
- struct listnode *node = NULL, *nnode = NULL;
-
- /* if ospf is not enabled ignore */
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (!ospf)
- return NULL;
-
- /* Lookup for Opaque area LSA in each area. */
- for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
- lsa = ospf_lsa_lookup_by_mpls_te_rid(area, OSPF_OPAQUE_AREA_LSA,
- rid);
- if (!lsa)
- continue;
- ospf_orr_debug(
- "%s: Opaque Area LSA found in area %pI4 for %pI4",
- __func__, &area->area_id, &rid);
- return lsa;
- }
- return NULL;
-}
-
-/*
- * Lookup each area's LSDB if is there is any opaque area LSA received and
- * update the root database with the advertising router.
- */
-static struct ospf_lsa *ospf_orr_lookup_router_lsa_by_id(struct in_addr rid)
-{
- struct ospf_lsa *lsa = NULL;
- struct ospf_area *area = NULL;
- struct ospf *ospf = NULL;
- struct listnode *node = NULL, *nnode = NULL;
-
- /* if ospf is not enabled ignore */
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (!ospf)
- return NULL;
-
- /* Lookup for Router LSA in each area. */
- for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
- lsa = ospf_lsa_lookup_by_adv_rid(area, OSPF_ROUTER_LSA, rid);
- if (!lsa)
- continue;
- ospf_orr_debug("%s: Router LSA found in area %pI4 for %pI4",
- __func__, &area->area_id, &rid);
- return lsa;
- }
- return NULL;
-}
-
-/*
- * BGP-IGP IGP metric msg between BGP and IGP
- */
-int ospf_orr_igp_metric_register(struct orr_igp_metric_reg msg)
-{
- afi_t afi;
- safi_t safi;
- struct ospf *ospf = NULL;
- struct ospf_lsa *lsa = NULL;
- struct orr_root *root = NULL;
-
- /* if ospf is not enabled ignore */
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (!ospf)
- return -1;
-
- if (msg.proto != ZEBRA_ROUTE_BGP)
- return -1;
-
- afi = family2afi(msg.prefix.family);
- safi = msg.safi;
-
- ospf_orr_debug(
- "%s: Received IGP metric %s message from BGP for ORR Group %s from location %pFX",
- __func__, msg.reg ? "Register" : "Unregister", msg.group_name,
- &msg.prefix);
-
- /* Get ORR Root entry for the given address-family */
- root = ospf_orr_root_lookup(ospf, afi, safi, &msg.prefix.u.prefix4);
-
- /* Should not hit this condition */
- if ((root && msg.reg) || (!root && !msg.reg))
- return -1;
-
- /* Create ORR Root entry and calculate SPF from root */
- if (!root) {
- root = ospf_orr_root_new(ospf, afi, safi, &msg.prefix,
- msg.group_name);
- if (!root) {
- ospf_orr_debug(
- "%s: For %s %s, Failed to create ORR Root entry %pFX.",
- __func__, afi2str(afi), safi2str(safi),
- &msg.prefix);
- return -1;
- }
- ospf->orr_spf_request++;
-
- lsa = ospf_orr_lookup_opaque_area_lsa_by_id(root->router_id);
- if (!lsa || !lsa->data)
- return -1;
-
- IPV4_ADDR_COPY(&root->adv_router, &lsa->data->adv_router);
-
- /* Lookup LSDB for Router LSA */
- if (!root->router_lsa_rcvd) {
- lsa = ospf_orr_lookup_router_lsa_by_id(
- root->adv_router);
- if (!lsa || !lsa->data)
- return -1;
- root->router_lsa_rcvd = lsa;
- }
-
- /* Compute SPF for all root nodes */
- ospf_orr_spf_calculate_schedule(ospf);
- }
- /* Delete ORR Root entry. SPF calculation not required. */
- else {
- listnode_delete(ospf->orr_root[afi][safi], root);
- XFREE(MTYPE_OSPF_ORR_ROOT, root);
-
- /* If last node is deleted in the list */
- if (!ospf->orr_root[afi][safi]->count)
- list_delete(&ospf->orr_root[afi][safi]);
-
- ospf->orr_spf_request--;
- }
-
- if (IS_DEBUG_OSPF_ORR)
- ospf_show_orr(ospf, afi, safi);
-
- return 0;
-}
-
-void ospf_orr_igp_metric_send_update_add(struct orr_root *root,
- unsigned short instance)
-{
- int ret;
- uint8_t count = 0;
- struct route_node *rn;
- struct ospf_route *or;
- struct orr_igp_metric_info msg;
-
- memset(&msg, 0, sizeof(msg));
- msg.proto = ZEBRA_ROUTE_OSPF;
- msg.safi = root->safi;
- msg.instId = instance;
- msg.add = true;
- prefix_copy(&msg.root, &root->prefix);
-
- /* Update prefix table from ORR Route table */
- for (rn = route_top(root->new_table); rn; rn = route_next(rn)) {
- or = rn->info;
- if (!or)
- continue;
-
- if (or->type != OSPF_DESTINATION_NETWORK &&
- or->type != OSPF_DESTINATION_DISCARD)
- continue;
-
- if (ospf_route_match_same(root->old_table,
- (struct prefix_ipv4 *)&rn->p, or))
- continue;
-
- if (count < ORR_MAX_PREFIX) {
- prefix_copy(&msg.nexthop[count].prefix,
- (struct prefix_ipv4 *)&rn->p);
- msg.nexthop[count].metric = or->cost;
- count++;
- } else {
- msg.num_entries = count;
- ret = zclient_send_opaque(zclient,
- ORR_IGP_METRIC_UPDATE,
- (uint8_t *)&msg, sizeof(msg));
- if (ret != ZCLIENT_SEND_SUCCESS)
- ospf_orr_debug(
- "%s: Failed to send message to BGP.",
- __func__);
- count = 0;
- prefix_copy(&msg.nexthop[count].prefix,
- (struct prefix_ipv4 *)&rn->p);
- msg.nexthop[count].metric = or->cost;
- count++;
- }
- }
- if (count > 0 && count <= ORR_MAX_PREFIX) {
- msg.num_entries = count;
- ret = zclient_send_opaque(zclient, ORR_IGP_METRIC_UPDATE,
- (uint8_t *)&msg, sizeof(msg));
- if (ret != ZCLIENT_SEND_SUCCESS)
- ospf_orr_debug("%s: Failed to send message to BGP.",
- __func__);
- }
-}
-
-void ospf_orr_igp_metric_send_update_delete(struct orr_root *root,
- unsigned short instance)
-{
- int ret;
- uint8_t count = 0;
- struct route_node *rn;
- struct ospf_route *or;
- struct orr_igp_metric_info msg;
-
- if (!root->old_table)
- return;
-
- memset(&msg, 0, sizeof(msg));
- msg.proto = ZEBRA_ROUTE_OSPF;
- msg.instId = instance;
- msg.safi = root->safi;
- msg.add = false;
- prefix_copy(&msg.root, &root->prefix);
-
- /* Update prefix table from ORR Route table */
- for (rn = route_top(root->old_table); rn; rn = route_next(rn)) {
- or = rn->info;
- if (!or)
- continue;
-
- if (or->path_type != OSPF_PATH_INTRA_AREA &&
- or->path_type != OSPF_PATH_INTER_AREA)
- continue;
-
- if (or->type != OSPF_DESTINATION_NETWORK &&
- or->type != OSPF_DESTINATION_DISCARD)
- continue;
-
- if (ospf_route_exist_new_table(root->new_table,
- (struct prefix_ipv4 *)&rn->p))
- continue;
-
- if (count < ORR_MAX_PREFIX) {
- prefix_copy(&msg.nexthop[count].prefix,
- (struct prefix_ipv4 *)&rn->p);
- msg.nexthop[count].metric = or->cost;
- count++;
- } else {
- msg.num_entries = count;
- ret = zclient_send_opaque(zclient,
- ORR_IGP_METRIC_UPDATE,
- (uint8_t *)&msg, sizeof(msg));
- if (ret != ZCLIENT_SEND_SUCCESS)
- ospf_orr_debug(
- "%s: Failed to send message to BGP.",
- __func__);
- count = 0;
- prefix_copy(&msg.nexthop[count].prefix,
- (struct prefix_ipv4 *)&rn->p);
- msg.nexthop[count].metric = or->cost;
- count++;
- }
- }
- if (count > 0 && count <= ORR_MAX_PREFIX) {
- msg.num_entries = count;
- ret = zclient_send_opaque(zclient, ORR_IGP_METRIC_UPDATE,
- (uint8_t *)&msg, sizeof(msg));
- if (ret != ZCLIENT_SEND_SUCCESS)
- ospf_orr_debug("%s: Failed to send message to BGP.",
- __func__);
- }
-}
-
-static void ospf_show_orr_root(struct orr_root *root)
-{
- if (!root)
- return;
-
- ospf_orr_debug("%s: Address Family: %s %s", __func__,
- afi2str(root->afi), safi2str(root->safi));
- ospf_orr_debug("%s: ORR Group: %s", __func__, root->group_name);
- ospf_orr_debug("%s: Router-Address: %pI4:", __func__, &root->router_id);
- ospf_orr_debug("%s: Advertising Router: %pI4:", __func__,
- &root->adv_router);
-}
-
-static void ospf_show_orr(struct ospf *ospf, afi_t afi, safi_t safi)
-{
- struct listnode *node = NULL;
- struct orr_root *orr_root = NULL;
- struct list *orr_root_list = NULL;
-
- FOREACH_AFI_SAFI (afi, safi) {
- orr_root_list = ospf->orr_root[afi][safi];
- if (!orr_root_list)
- return;
-
- for (ALL_LIST_ELEMENTS_RO(orr_root_list, node, orr_root))
- ospf_show_orr_root(orr_root);
- }
-}
-
-void ospf_orr_root_table_update(struct ospf_lsa *lsa, bool add)
-{
- afi_t afi;
- safi_t safi;
- struct lsa_header *lsah = lsa->data;
- uint32_t lsid = ntohl(lsah->id.s_addr);
- uint8_t opaque_type = GET_OPAQUE_TYPE(lsid);
- uint32_t opaque_id = GET_OPAQUE_ID(lsid);
- struct tlv_header *tlvh = TLV_HDR_TOP(lsah);
- struct te_tlv_router_addr *router_addr = NULL;
- struct orr_root *root = NULL;
- struct ospf *ospf = NULL;
-
- /* if ospf is not enabled ignore */
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (!ospf)
- return;
-
- if (opaque_type != OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA)
- return;
-
- if (!tlvh || (ntohs(tlvh->type) != TE_TLV_ROUTER_ADDR) ||
- (ntohs(tlvh->length) != TE_LINK_SUBTLV_DEF_SIZE))
- return;
-
- router_addr = (struct te_tlv_router_addr *)tlvh;
- if (IS_DEBUG_OSPF_ORR) {
- zlog_debug("[OSPF-ORR] %s: Opaque-area LSA %s LSDB", __func__,
- add ? "added to" : "deleted from");
- zlog_debug("[OSPF-ORR] %s: Opaque-Type %u (%s)", __func__,
- opaque_type, "Traffic Engineering LSA");
- zlog_debug("[OSPF-ORR] %s: Opaque-ID 0x%x", __func__,
- opaque_id);
- zlog_debug("[OSPF-ORR] %s: Opaque-Info: %u octets of data%s",
- __func__, ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE,
- VALID_OPAQUE_INFO_LEN(lsah) ? ""
- : "(Invalid length?)");
- zlog_debug("[OSPF-ORR] %s: Router-Address: %pI4", __func__,
- &router_addr->value);
- zlog_debug("[OSPF-ORR] %s: Advertising Router: %pI4", __func__,
- &lsa->data->adv_router);
- }
- /*
- * When Opaque LSA is added or removed from LSDB check if there is any
- * change in MPLS-TE Router address and Advertising router address and
- * update the table accordingly if there is no change in the mapping
- * ignore update
- *
- * Get ORR Root entry for the given address-family
- */
- FOREACH_AFI_SAFI (afi, safi) {
- root = ospf_orr_root_lookup(ospf, afi, safi,
- &router_addr->value);
- if (root) {
- IPV4_ADDR_COPY(&root->adv_router,
- &lsa->data->adv_router);
- if (IS_DEBUG_OSPF_ORR)
- ospf_show_orr(ospf, afi, safi);
- break;
- }
- }
-}
-
-void ospf_orr_root_update_rcvd_lsa(struct ospf_lsa *lsa)
-{
- afi_t afi;
- safi_t safi;
- struct orr_root *root = NULL;
-
- if (!lsa || !lsa->area || !lsa->area->ospf)
- return;
-
- FOREACH_AFI_SAFI (afi, safi) {
- root = ospf_orr_root_lookup_by_adv_rid(
- lsa->area->ospf, afi, safi, &lsa->data->adv_router);
- if (root) {
- SET_FLAG(lsa->flags, OSPF_LSA_ORR);
- ospf_refresher_register_lsa(lsa->area->ospf, lsa);
- root->router_lsa_rcvd = lsa;
- }
-
- ospf_orr_debug("%s: Received LSA[Type%d:%pI4]", __func__,
- lsa->data->type, &lsa->data->adv_router);
-
- /* Compute SPF for all root nodes */
- ospf_orr_spf_calculate_schedule(lsa->area->ospf);
- return;
- }
-}
-
-/* Do not Install routes to root table. Just update table ponters */
-void ospf_orr_route_install(struct orr_root *root, struct route_table *rt,
- unsigned short instance)
-{
- /*
- * rt contains new routing table, new_table contains an old one.
- * updating pointers
- */
- if (root->old_table)
- ospf_route_table_free(root->old_table);
-
- root->old_table = root->new_table;
- root->new_table = rt;
-
- /* Send update to BGP to delete old routes. */
- ospf_orr_igp_metric_send_update_delete(root, instance);
-
- /* REVISIT: Skipping external route table for now */
-
- /* Send update to BGP to add new routes. */
- ospf_orr_igp_metric_send_update_add(root, instance);
-}
-
-void ospf_orr_spf_calculate_schedule(struct ospf *ospf)
-{
- /* OSPF instance does not exist. */
- if (ospf == NULL)
- return;
-
- /* No roots nodes rgistered for rSPF */
- if (!ospf->orr_spf_request)
- return;
-
- /* ORR SPF calculation timer is already scheduled. */
- if (ospf->t_orr_calc) {
- ospf_orr_debug(
- "SPF: calculation timer is already scheduled: %p",
- (void *)ospf->t_orr_calc);
- return;
- }
-
- ospf->t_orr_calc = NULL;
-
- ospf_orr_debug("%s: SPF: calculation timer scheduled", __func__);
-
- thread_add_timer(master, ospf_orr_spf_calculate_schedule_worker, ospf,
- OSPF_ORR_CALC_INTERVAL, &ospf->t_orr_calc);
-}
-
-void ospf_orr_spf_calculate_area(struct ospf *ospf, struct ospf_area *area,
- struct route_table *new_table,
- struct route_table *all_rtrs,
- struct route_table *new_rtrs,
- struct ospf_lsa *lsa_rcvd)
-{
- ospf_spf_calculate(area, lsa_rcvd, new_table, all_rtrs, new_rtrs, false,
- true);
-}
-
-void ospf_orr_spf_calculate_areas(struct ospf *ospf,
- struct route_table *new_table,
- struct route_table *all_rtrs,
- struct route_table *new_rtrs,
- struct ospf_lsa *lsa_rcvd)
-{
- struct ospf_area *area;
- struct listnode *node, *nnode;
-
- /* Calculate SPF for each area. */
- for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
- /*
- * Do backbone last, so as to first discover intra-area paths
- * for any back-bone virtual-links
- */
- if (ospf->backbone && ospf->backbone == area)
- continue;
-
- ospf_orr_spf_calculate_area(ospf, area, new_table, all_rtrs,
- new_rtrs, lsa_rcvd);
- }
-
- /* SPF for backbone, if required */
- if (ospf->backbone)
- ospf_orr_spf_calculate_area(ospf, ospf->backbone, new_table,
- all_rtrs, new_rtrs, lsa_rcvd);
-}