back to topotato report
topotato coverage report
Current view: top level - ospfd - ospf_asbr.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 117 569 20.6 %
Date: 2023-02-24 19:38:44 Functions: 11 41 26.8 %

          Line data    Source code
       1             : /*
       2             :  * OSPF AS Boundary Router functions.
       3             :  * Copyright (C) 1999, 2000 Kunihiro Ishiguro, Toshiaki Takada
       4             :  *
       5             :  * This file is part of GNU Zebra.
       6             :  *
       7             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       8             :  * under the terms of the GNU General Public License as published by the
       9             :  * Free Software Foundation; either version 2, or (at your option) any
      10             :  * later version.
      11             :  *
      12             :  * GNU Zebra is distributed in the hope that it will be useful, but
      13             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License along
      18             :  * with this program; see the file COPYING; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include <zebra.h>
      23             : 
      24             : #include "thread.h"
      25             : #include "memory.h"
      26             : #include "linklist.h"
      27             : #include "prefix.h"
      28             : #include "if.h"
      29             : #include "table.h"
      30             : #include "vty.h"
      31             : #include "filter.h"
      32             : #include "log.h"
      33             : 
      34             : #include "ospfd/ospfd.h"
      35             : #include "ospfd/ospf_interface.h"
      36             : #include "ospfd/ospf_asbr.h"
      37             : #include "ospfd/ospf_lsa.h"
      38             : #include "ospfd/ospf_lsdb.h"
      39             : #include "ospfd/ospf_neighbor.h"
      40             : #include "ospfd/ospf_spf.h"
      41             : #include "ospfd/ospf_flood.h"
      42             : #include "ospfd/ospf_route.h"
      43             : #include "ospfd/ospf_zebra.h"
      44             : #include "ospfd/ospf_dump.h"
      45             : #include "ospfd/ospf_errors.h"
      46             : 
      47             : /* Remove external route. */
      48           0 : void ospf_external_route_remove(struct ospf *ospf, struct prefix_ipv4 *p)
      49             : {
      50           0 :         struct route_node *rn;
      51           0 :         struct ospf_route * or ;
      52             : 
      53           0 :         rn = route_node_lookup(ospf->old_external_route, (struct prefix *)p);
      54           0 :         if (rn)
      55           0 :                 if ((or = rn->info)) {
      56           0 :                         zlog_info("Route[%pFX]: external path deleted", p);
      57             : 
      58             :                         /* Remove route from zebra. */
      59           0 :                         if (or->type == OSPF_DESTINATION_NETWORK)
      60           0 :                                 ospf_zebra_delete(
      61           0 :                                         ospf, (struct prefix_ipv4 *)&rn->p, or);
      62             : 
      63           0 :                         ospf_route_free(or);
      64           0 :                         rn->info = NULL;
      65             : 
      66           0 :                         route_unlock_node(rn);
      67           0 :                         route_unlock_node(rn);
      68           0 :                         return;
      69             :                 }
      70             : 
      71           0 :         zlog_info("Route[%pFX]: no such external path", p);
      72             : }
      73             : 
      74             : /* Add an External info for AS-external-LSA. */
      75          22 : struct external_info *ospf_external_info_new(struct ospf *ospf, uint8_t type,
      76             :                                              unsigned short instance)
      77             : {
      78          22 :         struct external_info *new;
      79             : 
      80          22 :         new = XCALLOC(MTYPE_OSPF_EXTERNAL_INFO, sizeof(struct external_info));
      81          22 :         new->ospf = ospf;
      82          22 :         new->type = type;
      83          22 :         new->instance = instance;
      84          22 :         new->to_be_processed = 0;
      85             : 
      86          22 :         ospf_reset_route_map_set_values(&new->route_map_set);
      87          22 :         return new;
      88             : }
      89             : 
      90          22 : static void ospf_external_info_free(struct external_info *ei)
      91             : {
      92          44 :         XFREE(MTYPE_OSPF_EXTERNAL_INFO, ei);
      93             : }
      94             : 
      95          51 : void ospf_reset_route_map_set_values(struct route_map_set_values *values)
      96             : {
      97          51 :         values->metric = -1;
      98          51 :         values->metric_type = -1;
      99          29 : }
     100             : 
     101           0 : int ospf_route_map_set_compare(struct route_map_set_values *values1,
     102             :                                struct route_map_set_values *values2)
     103             : {
     104           0 :         return values1->metric == values2->metric
     105           0 :                && values1->metric_type == values2->metric_type;
     106             : }
     107             : 
     108             : /* Add an External info for AS-external-LSA. */
     109             : struct external_info *
     110          44 : ospf_external_info_add(struct ospf *ospf, uint8_t type, unsigned short instance,
     111             :                        struct prefix_ipv4 p, ifindex_t ifindex,
     112             :                        struct in_addr nexthop, route_tag_t tag)
     113             : {
     114          44 :         struct external_info *new;
     115          44 :         struct route_node *rn;
     116          44 :         struct ospf_external *ext;
     117             : 
     118          44 :         ext = ospf_external_lookup(ospf, type, instance);
     119          44 :         if (!ext)
     120           0 :                 ext = ospf_external_add(ospf, type, instance);
     121             : 
     122          44 :         rn = route_node_get(EXTERNAL_INFO(ext), (struct prefix *)&p);
     123             :         /* If old info exists, -- discard new one or overwrite with new one? */
     124          44 :         if (rn && rn->info) {
     125          22 :                 new = rn->info;
     126          22 :                 if ((new->ifindex == ifindex)
     127          22 :                     && (new->nexthop.s_addr == nexthop.s_addr)
     128          22 :                     && (new->tag == tag)) {
     129          22 :                         route_unlock_node(rn);
     130          22 :                         return NULL; /* NULL => no LSA to refresh */
     131             :                 }
     132             : 
     133           0 :                 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
     134           0 :                         zlog_debug(
     135             :                                 "Redistribute[%s][%d][%u]: %pFX discarding old info with NH %pI4.",
     136             :                                 ospf_redist_string(type), instance,
     137             :                                 ospf->vrf_id, &p, &nexthop.s_addr);
     138           0 :                 XFREE(MTYPE_OSPF_EXTERNAL_INFO, rn->info);
     139             :         }
     140             : 
     141             :         /* Create new External info instance. */
     142          22 :         new = ospf_external_info_new(ospf, type, instance);
     143          22 :         new->p = p;
     144          22 :         new->ifindex = ifindex;
     145          22 :         new->nexthop = nexthop;
     146          22 :         new->tag = tag;
     147          22 :         new->orig_tag = tag;
     148          22 :         new->aggr_route = NULL;
     149             : 
     150             :         /* we don't unlock rn from the get() because we're attaching the info */
     151          22 :         if (rn)
     152          22 :                 rn->info = new;
     153             : 
     154          22 :         if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
     155           0 :                 zlog_debug(
     156             :                         "Redistribute[%s][%u]: %pFX external info created, with NH %pI4",
     157             :                         ospf_redist_string(type), ospf->vrf_id, &p,
     158             :                         &nexthop.s_addr);
     159             :         }
     160             :         return new;
     161             : }
     162             : 
     163        1374 : void ospf_external_info_delete(struct ospf *ospf, uint8_t type,
     164             :                                unsigned short instance, struct prefix_ipv4 p)
     165             : {
     166        1374 :         struct route_node *rn;
     167        1374 :         struct ospf_external *ext;
     168             : 
     169        1374 :         ext = ospf_external_lookup(ospf, type, instance);
     170        1374 :         if (!ext)
     171             :                 return;
     172             : 
     173          10 :         rn = route_node_lookup(EXTERNAL_INFO(ext), (struct prefix *)&p);
     174          10 :         if (rn) {
     175          10 :                 ospf_external_info_free(rn->info);
     176          10 :                 rn->info = NULL;
     177          10 :                 route_unlock_node(rn);
     178          10 :                 route_unlock_node(rn);
     179             :         }
     180             : }
     181             : 
     182          38 : struct external_info *ospf_external_info_lookup(struct ospf *ospf, uint8_t type,
     183             :                                                 unsigned short instance,
     184             :                                                 struct prefix_ipv4 *p)
     185             : {
     186          38 :         struct route_node *rn;
     187          38 :         struct ospf_external *ext;
     188             : 
     189          38 :         ext = ospf_external_lookup(ospf, type, instance);
     190          38 :         if (!ext)
     191             :                 return NULL;
     192             : 
     193          20 :         rn = route_node_lookup(EXTERNAL_INFO(ext), (struct prefix *)p);
     194          20 :         if (rn) {
     195          10 :                 route_unlock_node(rn);
     196          10 :                 if (rn->info)
     197             :                         return rn->info;
     198             :         }
     199             : 
     200             :         return NULL;
     201             : }
     202             : 
     203          91 : struct ospf_lsa *ospf_external_info_find_lsa(struct ospf *ospf,
     204             :                                              struct prefix_ipv4 *p)
     205             : {
     206          91 :         struct ospf_lsa *lsa;
     207          91 :         struct as_external_lsa *al;
     208          91 :         struct in_addr mask, id;
     209             : 
     210             :         /* First search the lsdb with address specific LSID
     211             :          * where all the host bits are set, if there a matched
     212             :          * LSA, return.
     213             :          * Ex: For route 10.0.0.0/16, LSID is 10.0.255.255
     214             :          * If no lsa with above LSID, use received address as
     215             :          * LSID and check if any LSA in LSDB.
     216             :          * If LSA found, check if the mask is same b/w the matched
     217             :          * LSA and received prefix, if same then it is the LSA for
     218             :          * this prefix.
     219             :          * Ex: For route 10.0.0.0/16, LSID is 10.0.0.0
     220             :          */
     221             : 
     222          91 :         masklen2ip(p->prefixlen, &mask);
     223          91 :         id.s_addr = p->prefix.s_addr | (~mask.s_addr);
     224          91 :         lsa = ospf_lsdb_lookup_by_id(ospf->lsdb, OSPF_AS_EXTERNAL_LSA, id,
     225             :                                      ospf->router_id);
     226          91 :         if (lsa) {
     227          33 :                 if (p->prefixlen == IPV4_MAX_BITLEN) {
     228          33 :                         al = (struct as_external_lsa *)lsa->data;
     229             : 
     230          33 :                         if (mask.s_addr != al->mask.s_addr)
     231             :                                 return NULL;
     232             :                 }
     233             :                 return lsa;
     234             :         }
     235             : 
     236          58 :         lsa = ospf_lsdb_lookup_by_id(ospf->lsdb, OSPF_AS_EXTERNAL_LSA,
     237             :                                      p->prefix, ospf->router_id);
     238             : 
     239          58 :         if (lsa) {
     240           0 :                 al = (struct as_external_lsa *)lsa->data;
     241           0 :                 if (mask.s_addr == al->mask.s_addr)
     242             :                         return lsa;
     243             :         }
     244             : 
     245             :         return NULL;
     246             : }
     247             : 
     248             : 
     249             : /* Update ASBR status. */
     250           8 : void ospf_asbr_status_update(struct ospf *ospf, uint8_t status)
     251             : {
     252           8 :         zlog_info("ASBR[%s:Status:%d]: Update",
     253             :                   ospf_get_name(ospf), status);
     254             : 
     255             :         /* ASBR on. */
     256           8 :         if (status) {
     257             :                 /* Already ASBR. */
     258           4 :                 if (IS_OSPF_ASBR(ospf)) {
     259           0 :                         zlog_info("ASBR[%s:Status:%d]: Already ASBR",
     260             :                                   ospf_get_name(ospf), status);
     261           0 :                         return;
     262             :                 }
     263           4 :                 SET_FLAG(ospf->flags, OSPF_FLAG_ASBR);
     264             :         } else {
     265             :                 /* Already non ASBR. */
     266           4 :                 if (!IS_OSPF_ASBR(ospf)) {
     267           0 :                         zlog_info("ASBR[%s:Status:%d]: Already non ASBR",
     268             :                                   ospf_get_name(ospf), status);
     269           0 :                         return;
     270             :                 }
     271           4 :                 UNSET_FLAG(ospf->flags, OSPF_FLAG_ASBR);
     272             :         }
     273             : 
     274             :         /* Transition from/to status ASBR, schedule timer. */
     275           8 :         ospf_spf_calculate_schedule(ospf, SPF_FLAG_ASBR_STATUS_CHANGE);
     276           8 :         ospf_router_lsa_update(ospf);
     277             : }
     278             : 
     279             : /* If there's redistribution configured, we need to refresh external
     280             :  * LSAs in order to install Type-7 and flood to all NSSA Areas
     281             :  */
     282           0 : static void ospf_asbr_nssa_redist_update_timer(struct thread *thread)
     283             : {
     284           0 :         struct ospf *ospf = THREAD_ARG(thread);
     285           0 :         int type;
     286             : 
     287           0 :         ospf->t_asbr_nssa_redist_update = NULL;
     288             : 
     289           0 :         if (IS_DEBUG_OSPF_EVENT)
     290           0 :                 zlog_debug("Running ASBR NSSA redistribution update on timer");
     291             : 
     292           0 :         for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
     293           0 :                 struct list *red_list;
     294           0 :                 struct listnode *node;
     295           0 :                 struct ospf_redist *red;
     296             : 
     297           0 :                 red_list = ospf->redist[type];
     298           0 :                 if (!red_list)
     299           0 :                         continue;
     300             : 
     301           0 :                 for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
     302           0 :                         ospf_external_lsa_refresh_type(ospf, type,
     303           0 :                                                        red->instance,
     304             :                                                        LSA_REFRESH_FORCE);
     305             :         }
     306             : 
     307           0 :         ospf_external_lsa_refresh_default(ospf);
     308           0 : }
     309             : 
     310           0 : void ospf_schedule_asbr_nssa_redist_update(struct ospf *ospf)
     311             : {
     312           0 :         if (IS_DEBUG_OSPF_EVENT)
     313           0 :                 zlog_debug("Scheduling ASBR NSSA redistribution update");
     314             : 
     315           0 :         thread_add_timer(master, ospf_asbr_nssa_redist_update_timer, ospf,
     316             :                          OSPF_ASBR_NSSA_REDIST_UPDATE_DELAY,
     317             :                          &ospf->t_asbr_nssa_redist_update);
     318           0 : }
     319             : 
     320           4 : void ospf_redistribute_withdraw(struct ospf *ospf, uint8_t type,
     321             :                                 unsigned short instance)
     322             : {
     323           4 :         struct route_node *rn;
     324           4 :         struct external_info *ei;
     325           4 :         struct ospf_external *ext;
     326             : 
     327           4 :         ext = ospf_external_lookup(ospf, type, instance);
     328           4 :         if (!ext)
     329             :                 return;
     330             : 
     331             :         /* Delete external info for specified type. */
     332           4 :         if (!EXTERNAL_INFO(ext))
     333             :                 return;
     334             : 
     335          24 :         for (rn = route_top(EXTERNAL_INFO(ext)); rn; rn = route_next(rn)) {
     336          20 :                 ei = rn->info;
     337             : 
     338          20 :                 if (!ei)
     339           8 :                         continue;
     340             : 
     341          12 :                 struct ospf_external_aggr_rt *aggr;
     342             : 
     343          12 :                 if (is_default_prefix4(&ei->p)
     344           0 :                     && ospf->default_originate != DEFAULT_ORIGINATE_NONE)
     345           0 :                         continue;
     346             : 
     347          12 :                 aggr = ei->aggr_route;
     348             : 
     349          12 :                 if (aggr)
     350           0 :                         ospf_unlink_ei_from_aggr(ospf, aggr, ei);
     351          12 :                 else if (ospf_external_info_find_lsa(ospf, &ei->p))
     352           4 :                         ospf_external_lsa_flush(ospf, type, &ei->p,
     353             :                                                 ei->ifindex /*, ei->nexthop */);
     354             : 
     355          12 :                 ospf_external_info_free(ei);
     356          12 :                 route_unlock_node(rn);
     357          12 :                 rn->info = NULL;
     358             :         }
     359             : }
     360             : 
     361             : 
     362             : /* External Route Aggregator Handlers */
     363           0 : bool is_valid_summary_addr(struct prefix_ipv4 *p)
     364             : {
     365             :         /* Default prefix validation*/
     366           0 :         if (p->prefix.s_addr == INADDR_ANY)
     367             :                 return false;
     368             : 
     369             :         /*Host route shouldn't be configured as summary addres*/
     370           0 :         if (p->prefixlen == IPV4_MAX_BITLEN)
     371           0 :                 return false;
     372             : 
     373             :         return true;
     374             : }
     375           4 : void ospf_asbr_external_aggregator_init(struct ospf *instance)
     376             : {
     377           4 :         instance->rt_aggr_tbl = route_table_init();
     378             : 
     379           4 :         instance->t_external_aggr = NULL;
     380             : 
     381           4 :         instance->aggr_action = 0;
     382             : 
     383           4 :         instance->aggr_delay_interval = OSPF_EXTL_AGGR_DEFAULT_DELAY;
     384           4 : }
     385             : 
     386           0 : static unsigned int ospf_external_rt_hash_key(const void *data)
     387             : {
     388           0 :         const struct external_info *ei = data;
     389           0 :         unsigned int key = 0;
     390             : 
     391           0 :         key = prefix_hash_key(&ei->p);
     392           0 :         return key;
     393             : }
     394             : 
     395           0 : static bool ospf_external_rt_hash_cmp(const void *d1, const void *d2)
     396             : {
     397           0 :         const struct external_info *ei1 = d1;
     398           0 :         const struct external_info *ei2 = d2;
     399             : 
     400           0 :         return prefix_same((struct prefix *)&ei1->p, (struct prefix *)&ei2->p);
     401             : }
     402             : 
     403             : static struct ospf_external_aggr_rt *
     404           0 : ospf_external_aggregator_new(struct prefix_ipv4 *p)
     405             : {
     406           0 :         struct ospf_external_aggr_rt *aggr;
     407             : 
     408           0 :         aggr = (struct ospf_external_aggr_rt *)XCALLOC(
     409             :                 MTYPE_OSPF_EXTERNAL_RT_AGGR,
     410             :                 sizeof(struct ospf_external_aggr_rt));
     411             : 
     412           0 :         if (!aggr)
     413             :                 return NULL;
     414             : 
     415           0 :         aggr->p.family = p->family;
     416           0 :         aggr->p.prefix = p->prefix;
     417           0 :         aggr->p.prefixlen = p->prefixlen;
     418           0 :         aggr->match_extnl_hash = hash_create(ospf_external_rt_hash_key,
     419             :                                              ospf_external_rt_hash_cmp,
     420             :                                              "Ospf external route hash");
     421           0 :         return aggr;
     422             : }
     423             : 
     424           0 : static void ospf_aggr_handle_external_info(void *data)
     425             : {
     426           0 :         struct external_info *ei = (struct external_info *)data;
     427           0 :         struct ospf_external_aggr_rt *aggr = NULL;
     428           0 :         struct ospf *ospf = ei->ospf;
     429           0 :         struct ospf_lsa *lsa = NULL;
     430             : 
     431           0 :         ei->aggr_route = NULL;
     432             : 
     433           0 :         ei->to_be_processed = true;
     434             : 
     435           0 :         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     436           0 :                 zlog_debug("%s: Handle extrenal route(%pI4/%d)", __func__,
     437             :                            &ei->p.prefix, ei->p.prefixlen);
     438             : 
     439           0 :         assert(ospf);
     440             : 
     441           0 :         if (!ospf_redistribute_check(ospf, ei, NULL))
     442             :                 return;
     443             : 
     444           0 :         aggr = ospf_external_aggr_match(ospf, &ei->p);
     445           0 :         if (aggr) {
     446           0 :                 (void)ospf_originate_summary_lsa(ospf, aggr, ei);
     447           0 :                 return;
     448             :         }
     449             : 
     450           0 :         lsa = ospf_external_info_find_lsa(ospf, &ei->p);
     451           0 :         if (lsa)
     452           0 :                 ospf_external_lsa_refresh(ospf, lsa, ei, LSA_REFRESH_FORCE, 1);
     453             :         else
     454           0 :                 (void)ospf_external_lsa_originate(ospf, ei);
     455             : }
     456             : 
     457           0 : static void ospf_aggr_unlink_external_info(void *data)
     458             : {
     459           0 :         struct external_info *ei = (struct external_info *)data;
     460             : 
     461           0 :         ei->aggr_route = NULL;
     462             : 
     463           0 :         ei->to_be_processed = true;
     464           0 : }
     465             : 
     466           0 : void ospf_external_aggregator_free(struct ospf_external_aggr_rt *aggr)
     467             : {
     468           0 :         if (OSPF_EXTERNAL_RT_COUNT(aggr))
     469           0 :                 hash_clean(aggr->match_extnl_hash,
     470             :                            (void *)ospf_aggr_unlink_external_info);
     471             : 
     472           0 :         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     473           0 :                 zlog_debug("%s: Release the aggregator Address(%pI4/%d)",
     474             :                            __func__, &aggr->p.prefix, aggr->p.prefixlen);
     475           0 :         hash_free(aggr->match_extnl_hash);
     476           0 :         aggr->match_extnl_hash = NULL;
     477             : 
     478           0 :         XFREE(MTYPE_OSPF_EXTERNAL_RT_AGGR, aggr);
     479           0 : }
     480             : 
     481           0 : static void ospf_external_aggr_add(struct ospf *ospf,
     482             :                                    struct ospf_external_aggr_rt *aggr)
     483             : {
     484           0 :         struct route_node *rn;
     485             : 
     486           0 :         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     487           0 :                 zlog_debug("%s: Adding Aggregate route to Aggr table (%pI4/%d)",
     488             :                            __func__, &aggr->p.prefix, aggr->p.prefixlen);
     489           0 :         rn = route_node_get(ospf->rt_aggr_tbl, (struct prefix *)&aggr->p);
     490           0 :         if (rn->info)
     491           0 :                 route_unlock_node(rn);
     492             :         else
     493           0 :                 rn->info = aggr;
     494           0 : }
     495             : 
     496           0 : static void ospf_external_aggr_delete(struct ospf *ospf, struct route_node *rn)
     497             : {
     498           0 :         struct ospf_external_aggr_rt *aggr = rn->info;
     499             : 
     500           0 :         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     501           0 :                 zlog_debug("%s: Deleting Aggregate route (%pI4/%d)", __func__,
     502             :                            &aggr->p.prefix, aggr->p.prefixlen);
     503             : 
     504             :         /* Sent a Max age LSA if it is already originated. */
     505           0 :         if (CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED)) {
     506           0 :                 if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     507           0 :                         zlog_debug("%s: Flushing Aggregate route (%pI4/%d)",
     508             :                                    __func__, &aggr->p.prefix,
     509             :                                    aggr->p.prefixlen);
     510           0 :                 ospf_external_lsa_flush(ospf, 0, &aggr->p, 0);
     511             :         }
     512             : 
     513           0 :         rn->info = NULL;
     514           0 :         route_unlock_node(rn);
     515           0 : }
     516             : 
     517             : struct ospf_external_aggr_rt *
     518           0 : ospf_extrenal_aggregator_lookup(struct ospf *ospf, struct prefix_ipv4 *p)
     519             : {
     520           0 :         struct route_node *rn;
     521           0 :         struct ospf_external_aggr_rt *summary_rt = NULL;
     522             : 
     523           0 :         rn = route_node_lookup(ospf->rt_aggr_tbl, (struct prefix *)p);
     524           0 :         if (rn) {
     525           0 :                 summary_rt = rn->info;
     526           0 :                 route_unlock_node(rn);
     527           0 :                 return summary_rt;
     528             :         }
     529             :         return NULL;
     530             : }
     531             : 
     532          32 : struct ospf_external_aggr_rt *ospf_external_aggr_match(struct ospf *ospf,
     533             :                                                        struct prefix_ipv4 *p)
     534             : {
     535          32 :         struct route_node *node;
     536          32 :         struct ospf_external_aggr_rt *summary_rt = NULL;
     537             : 
     538          32 :         node = route_node_match(ospf->rt_aggr_tbl, (struct prefix *)p);
     539          32 :         if (node) {
     540             : 
     541           0 :                 if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     542           0 :                         if (node->info) {
     543           0 :                                 struct ospf_external_aggr_rt *ag = node->info;
     544             : 
     545           0 :                                 zlog_debug(
     546             :                                         "%s: Matching aggregator found.prefix:%pI4/%d Aggregator %pI4/%d",
     547             :                                         __func__, &p->prefix, p->prefixlen,
     548             :                                         &ag->p.prefix, ag->p.prefixlen);
     549             :                         }
     550             : 
     551           0 :                 summary_rt = node->info;
     552           0 :                 route_unlock_node(node);
     553           0 :                 return summary_rt;
     554             :         }
     555             :         return NULL;
     556             : }
     557             : 
     558           0 : void ospf_unlink_ei_from_aggr(struct ospf *ospf,
     559             :                               struct ospf_external_aggr_rt *aggr,
     560             :                               struct external_info *ei)
     561             : {
     562           0 :         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     563           0 :                 zlog_debug(
     564             :                         "%s: Unlinking extrenal route(%pI4/%d) from aggregator(%pI4/%d), external route count:%ld",
     565             :                         __func__, &ei->p.prefix, ei->p.prefixlen,
     566             :                         &aggr->p.prefix, aggr->p.prefixlen,
     567             :                         OSPF_EXTERNAL_RT_COUNT(aggr));
     568           0 :         hash_release(aggr->match_extnl_hash, ei);
     569           0 :         ei->aggr_route = NULL;
     570             : 
     571             :         /* Flush the aggreagte route if matching
     572             :          * external route count becomes zero.
     573             :          */
     574           0 :         if (!OSPF_EXTERNAL_RT_COUNT(aggr)
     575           0 :             && CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED)) {
     576             : 
     577           0 :                 if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     578           0 :                         zlog_debug("%s: Flushing the aggreagte route (%pI4/%d)",
     579             :                                    __func__, &aggr->p.prefix,
     580             :                                    aggr->p.prefixlen);
     581             : 
     582             :                 /* Flush the aggregate LSA */
     583           0 :                 ospf_external_lsa_flush(ospf, 0, &aggr->p, 0);
     584             : 
     585             :                 /* Unset the Origination flag */
     586           0 :                 UNSET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED);
     587             :         }
     588           0 : }
     589             : 
     590           0 : static void ospf_link_ei_to_aggr(struct ospf_external_aggr_rt *aggr,
     591             :                                  struct external_info *ei)
     592             : {
     593           0 :         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     594           0 :                 zlog_debug(
     595             :                         "%s: Linking extrenal route(%pI4/%d) to aggregator(%pI4/%d)",
     596             :                         __func__, &ei->p.prefix, ei->p.prefixlen,
     597             :                         &aggr->p.prefix, aggr->p.prefixlen);
     598           0 :         (void)hash_get(aggr->match_extnl_hash, ei, hash_alloc_intern);
     599           0 :         ei->aggr_route = aggr;
     600           0 : }
     601             : 
     602           0 : struct ospf_lsa *ospf_originate_summary_lsa(struct ospf *ospf,
     603             :                                             struct ospf_external_aggr_rt *aggr,
     604             :                                             struct external_info *ei)
     605             : {
     606           0 :         struct ospf_lsa *lsa;
     607           0 :         struct external_info ei_aggr;
     608           0 :         struct as_external_lsa *asel;
     609           0 :         struct ospf_external_aggr_rt *old_aggr;
     610           0 :         route_tag_t tag = 0;
     611             : 
     612           0 :         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     613           0 :                 zlog_debug("%s: Prepare to originate Summary route(%pI4/%d)",
     614             :                            __func__, &aggr->p.prefix, aggr->p.prefixlen);
     615             : 
     616             :         /* This case to handle when the overlapping aggregator address
     617             :          * is availbe.Best match will be considered.So need to delink
     618             :          * from old aggregator and link to the new aggr.
     619             :          */
     620           0 :         if (ei->aggr_route) {
     621           0 :                 if (ei->aggr_route != aggr) {
     622           0 :                         old_aggr = ei->aggr_route;
     623           0 :                         ospf_unlink_ei_from_aggr(ospf, old_aggr, ei);
     624             :                 }
     625             :         }
     626             : 
     627             :         /* Add the external route to hash table */
     628           0 :         ospf_link_ei_to_aggr(aggr, ei);
     629             : 
     630           0 :         lsa = ospf_external_info_find_lsa(ospf, &aggr->p);
     631             :         /* Don't originate external LSA,
     632             :          * If it is configured not to advertise.
     633             :          */
     634           0 :         if (CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_NO_ADVERTISE)) {
     635             :                 /* If it is already originated as external LSA,
     636             :                  * But, it is configured not to advertise then
     637             :                  * flush the originated external lsa.
     638             :                  */
     639           0 :                 if (lsa)
     640           0 :                         ospf_external_lsa_flush(ospf, 0, &aggr->p, 0);
     641           0 :                 UNSET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED);
     642             : 
     643           0 :                 if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     644           0 :                         zlog_debug(
     645             :                                 "%s: Don't originate the summary address,It is configured to not-advertise.",
     646             :                                 __func__);
     647           0 :                 return NULL;
     648             :         }
     649             : 
     650             :         /* Prepare the extrenal_info for aggregator */
     651           0 :         memset(&ei_aggr, 0, sizeof(ei_aggr));
     652           0 :         ei_aggr.p = aggr->p;
     653           0 :         ei_aggr.tag = aggr->tag;
     654           0 :         ei_aggr.type = 0;
     655           0 :         ei_aggr.instance = ospf->instance;
     656           0 :         ei_aggr.route_map_set.metric = -1;
     657           0 :         ei_aggr.route_map_set.metric_type = -1;
     658             : 
     659             :         /* Summary route already originated,
     660             :          * So, Do nothing.
     661             :          */
     662           0 :         if (CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED)) {
     663           0 :                 if (!lsa) {
     664           0 :                         flog_warn(EC_OSPF_LSA_MISSING,
     665             :                                   "%s: Could not refresh/originate %pI4/%d",
     666             :                                   __func__, &aggr->p.prefix, aggr->p.prefixlen);
     667           0 :                         return NULL;
     668             :                 }
     669             : 
     670           0 :                 asel = (struct as_external_lsa *)lsa->data;
     671           0 :                 tag = (unsigned long)ntohl(asel->e[0].route_tag);
     672             : 
     673             :                 /* If tag modified , then re-originate the route
     674             :                  * with modified tag details.
     675             :                  */
     676           0 :                 if (tag != ei_aggr.tag) {
     677           0 :                         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     678           0 :                                 zlog_debug(
     679             :                                         "%s: Route tag changed(old:%d new:%d,So refresh the summary route.(%pI4/%d)",
     680             :                                         __func__, tag, ei_aggr.tag,
     681             :                                         &aggr->p.prefix, aggr->p.prefixlen);
     682             : 
     683           0 :                         ospf_external_lsa_refresh(ospf, lsa, &ei_aggr,
     684             :                                                   LSA_REFRESH_FORCE, 1);
     685             :                 }
     686           0 :                 return lsa;
     687             :         }
     688             : 
     689           0 :         if (lsa && IS_LSA_MAXAGE(lsa)) {
     690             :                 /* This is special case.
     691             :                  * If a summary route need to be originated but where
     692             :                  * summary route already exist in lsdb with maxage, then
     693             :                  * it need to be refreshed.
     694             :                  */
     695           0 :                 if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     696           0 :                         zlog_debug(
     697             :                                 "%s: LSA is in MAX-AGE so refreshing LSA(%pI4/%d)",
     698             :                                 __func__, &aggr->p.prefix, aggr->p.prefixlen);
     699             : 
     700           0 :                 ospf_external_lsa_refresh(ospf, lsa, &ei_aggr,
     701             :                                           LSA_REFRESH_FORCE, 1);
     702           0 :                 SET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED);
     703           0 :                 return lsa;
     704             :         }
     705             : 
     706             :         /* If the external route prefix same as aggregate route
     707             :          * and if external route is already originated as TYPE-5
     708             :          * then it need to be refreshed and originate bit should
     709             :          * be set.
     710             :          */
     711           0 :         if (lsa && prefix_same((struct prefix *)&ei_aggr.p,
     712           0 :                                (struct prefix *)&ei->p)) {
     713           0 :                 if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     714           0 :                         zlog_debug(
     715             :                                 "%s: External route prefix is same as aggr so refreshing LSA(%pI4/%d)",
     716             :                                 __func__, &aggr->p.prefix, aggr->p.prefixlen);
     717           0 :                 ospf_external_lsa_refresh(ospf, lsa, &ei_aggr,
     718             :                                           LSA_REFRESH_FORCE, 1);
     719           0 :                 SET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED);
     720           0 :                 return lsa;
     721             :         }
     722             : 
     723           0 :         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     724           0 :                 zlog_debug("%s: Originate Summary route(%pI4/%d)", __func__,
     725             :                            &aggr->p.prefix, aggr->p.prefixlen);
     726             : 
     727             :         /* Originate summary LSA */
     728           0 :         lsa = ospf_external_lsa_originate(ospf, &ei_aggr);
     729           0 :         if (lsa) {
     730           0 :                 if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     731           0 :                         zlog_debug("%s: Set the origination bit for aggregator",
     732             :                                    __func__);
     733           0 :                 SET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED);
     734             :         }
     735             : 
     736             :         return lsa;
     737             : }
     738           4 : void ospf_unset_all_aggr_flag(struct ospf *ospf)
     739             : {
     740           4 :         struct route_node *rn = NULL;
     741             : 
     742           4 :         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     743           0 :                 zlog_debug("Unset the origination bit for all aggregator");
     744             : 
     745           4 :         for (rn = route_top(ospf->rt_aggr_tbl); rn; rn = route_next(rn)) {
     746           0 :                 if (!rn->info)
     747           0 :                         continue;
     748             : 
     749           0 :                 struct ospf_external_aggr_rt *aggr = rn->info;
     750             : 
     751           0 :                 UNSET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED);
     752             :         }
     753           4 : }
     754             : 
     755           0 : static void ospf_delete_all_marked_aggregators(struct ospf *ospf)
     756             : {
     757           0 :         struct route_node *rn = NULL;
     758             : 
     759             :         /* Loop through all the aggregators, Delete all aggregators
     760             :          * which are marked as DELETE. Set action to NONE for remaining
     761             :          * aggregators
     762             :          */
     763           0 :         for (rn = route_top(ospf->rt_aggr_tbl); rn; rn = route_next(rn)) {
     764           0 :                 if (!rn->info)
     765           0 :                         continue;
     766             : 
     767           0 :                 struct ospf_external_aggr_rt *aggr = rn->info;
     768             : 
     769           0 :                 if (aggr->action != OSPF_ROUTE_AGGR_DEL) {
     770           0 :                         aggr->action = OSPF_ROUTE_AGGR_NONE;
     771           0 :                         continue;
     772             :                 }
     773           0 :                 ospf_external_aggr_delete(ospf, rn);
     774           0 :                 ospf_external_aggregator_free(aggr);
     775             :         }
     776           0 : }
     777             : 
     778           0 : static void ospf_handle_aggregated_exnl_rt(struct ospf *ospf,
     779             :                                            struct ospf_external_aggr_rt *aggr,
     780             :                                            struct external_info *ei)
     781             : {
     782           0 :         struct ospf_lsa *lsa;
     783           0 :         struct as_external_lsa *al;
     784           0 :         struct in_addr mask;
     785             : 
     786             :         /* Handling the case where the external route prefix
     787             :          * and aggregate prefix is same
     788             :          * If same don't flush the originated external LSA.
     789             :          */
     790           0 :         if (prefix_same((struct prefix *)&aggr->p, (struct prefix *)&ei->p)) {
     791           0 :                 if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     792           0 :                         zlog_debug(
     793             :                                 "%s: External Route prefix same as Aggregator(%pI4/%d), so don't flush.",
     794             :                                 __func__, &ei->p.prefix, ei->p.prefixlen);
     795           0 :                 return;
     796             :         }
     797             : 
     798           0 :         lsa = ospf_external_info_find_lsa(ospf, &ei->p);
     799           0 :         if (lsa) {
     800           0 :                 al = (struct as_external_lsa *)lsa->data;
     801           0 :                 masklen2ip(ei->p.prefixlen, &mask);
     802             : 
     803           0 :                 if (mask.s_addr != al->mask.s_addr)
     804             :                         return;
     805             : 
     806           0 :                 ospf_external_lsa_flush(ospf, ei->type, &ei->p, 0);
     807             :         }
     808             : }
     809             : 
     810           0 : static void ospf_handle_exnl_rt_after_aggr_del(struct ospf *ospf,
     811             :                                                struct external_info *ei)
     812             : {
     813           0 :         struct ospf_lsa *lsa;
     814             : 
     815             :         /* Process only marked external routes.
     816             :          * These routes were part of a deleted
     817             :          * aggregator.So, originate now.
     818             :          */
     819           0 :         if (!ei->to_be_processed)
     820             :                 return;
     821             : 
     822           0 :         ei->to_be_processed = false;
     823             : 
     824           0 :         lsa = ospf_external_info_find_lsa(ospf, &ei->p);
     825             : 
     826           0 :         if (lsa)
     827           0 :                 ospf_external_lsa_refresh(ospf, lsa, ei, LSA_REFRESH_FORCE, 0);
     828             :         else {
     829           0 :                 if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     830           0 :                         zlog_debug("%s: Originate external route(%pI4/%d)",
     831             :                                    __func__, &ei->p.prefix, ei->p.prefixlen);
     832             : 
     833           0 :                 ospf_external_lsa_originate(ospf, ei);
     834             :         }
     835             : }
     836             : 
     837           0 : static void ospf_handle_external_aggr_add(struct ospf *ospf)
     838             : {
     839           0 :         struct external_info *ei;
     840           0 :         struct route_node *rn = NULL;
     841           0 :         struct route_table *rt = NULL;
     842           0 :         int type = 0;
     843             : 
     844             :         /* Delete all the aggregators which are marked as
     845             :          * OSPF_ROUTE_AGGR_DEL.
     846             :          */
     847           0 :         ospf_delete_all_marked_aggregators(ospf);
     848             : 
     849           0 :         for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
     850           0 :                 struct list *ext_list;
     851           0 :                 struct listnode *node;
     852           0 :                 struct ospf_external *ext;
     853           0 :                 struct ospf_external_aggr_rt *aggr;
     854             : 
     855           0 :                 ext_list = ospf->external[type];
     856           0 :                 if (!ext_list)
     857           0 :                         continue;
     858             : 
     859           0 :                 for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
     860           0 :                         rt = ext->external_info;
     861           0 :                         if (!rt)
     862           0 :                                 continue;
     863             : 
     864           0 :                         for (rn = route_top(rt); rn; rn = route_next(rn)) {
     865           0 :                                 if (!rn->info)
     866           0 :                                         continue;
     867             : 
     868           0 :                                 ei = rn->info;
     869           0 :                                 if (is_default_prefix4(&ei->p))
     870           0 :                                         continue;
     871             : 
     872             :                                 /* Check the AS-external-LSA
     873             :                                  * should be originated.
     874             :                                  */
     875           0 :                                 if (!ospf_redistribute_check(ospf, ei, NULL))
     876           0 :                                         continue;
     877             : 
     878           0 :                                 aggr = ospf_external_aggr_match(ospf, &ei->p);
     879             : 
     880             :                                 /* If matching aggregator found, Add
     881             :                                  * the external route reference to the
     882             :                                  * aggregator and originate the aggr
     883             :                                  * route if it is advertisable.
     884             :                                  * flush the external LSA if it is
     885             :                                  * already originated for this external
     886             :                                  * prefix.
     887             :                                  */
     888           0 :                                 if (aggr) {
     889           0 :                                         ospf_originate_summary_lsa(ospf, aggr,
     890             :                                                                    ei);
     891             : 
     892             :                                         /* All aggregated external rts
     893             :                                          * are handled here.
     894             :                                          */
     895           0 :                                         ospf_handle_aggregated_exnl_rt(
     896             :                                                 ospf, aggr, ei);
     897           0 :                                         continue;
     898             :                                 }
     899             : 
     900             :                                 /* External routes which are only out
     901             :                                  * of aggregation will be handled here.
     902             :                                  */
     903           0 :                                 ospf_handle_exnl_rt_after_aggr_del(ospf, ei);
     904             :                         }
     905             :                 }
     906             :         }
     907           0 : }
     908             : 
     909             : static void
     910           0 : ospf_aggr_handle_advertise_change(struct ospf *ospf,
     911             :                                   struct ospf_external_aggr_rt *aggr,
     912             :                                   struct external_info *ei_aggr)
     913             : {
     914           0 :         struct ospf_lsa *lsa;
     915             : 
     916             :         /* Check if advertise option modified. */
     917           0 :         if (CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_NO_ADVERTISE)) {
     918             : 
     919           0 :                 if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     920           0 :                         zlog_debug(
     921             :                                 "%s: Don't originate the summary address,It is configured to not-advertise.",
     922             :                                 __func__);
     923             : 
     924           0 :                 if (CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED)) {
     925             : 
     926           0 :                         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     927           0 :                                 zlog_debug(
     928             :                                         "%s: No-advertise,So Flush the Aggregate route(%pI4/%d)",
     929             :                                         __func__, &aggr->p.prefix,
     930             :                                         aggr->p.prefixlen);
     931             : 
     932           0 :                         ospf_external_lsa_flush(ospf, 0, &aggr->p, 0);
     933             : 
     934           0 :                         UNSET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED);
     935             :                 }
     936           0 :                 return;
     937             :         }
     938             : 
     939           0 :         if (!CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED)) {
     940           0 :                 if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     941           0 :                         zlog_debug("%s: Now it is advatisable", __func__);
     942             : 
     943           0 :                 lsa = ospf_external_info_find_lsa(ospf, &ei_aggr->p);
     944           0 :                 if (lsa && IS_LSA_MAXAGE(lsa)) {
     945             :                         /* This is special case.
     946             :                          * If a summary route need to be originated but where
     947             :                          * summary route already exist in lsdb with maxage, then
     948             :                          * it need to be refreshed.
     949             :                          */
     950           0 :                         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     951           0 :                                 zlog_debug(
     952             :                                         "%s: It is already with Maxage, So refresh it (%pI4/%d)",
     953             :                                         __func__, &aggr->p.prefix,
     954             :                                         aggr->p.prefixlen);
     955             : 
     956           0 :                         ospf_external_lsa_refresh(ospf, lsa, ei_aggr,
     957             :                                                   LSA_REFRESH_FORCE, 1);
     958             : 
     959           0 :                         SET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED);
     960             : 
     961             :                 } else {
     962             : 
     963           0 :                         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     964           0 :                                 zlog_debug(
     965             :                                         "%s: Originate Aggregate LSA (%pI4/%d)",
     966             :                                         __func__, &aggr->p.prefix,
     967             :                                         aggr->p.prefixlen);
     968             : 
     969             :                         /* Originate summary LSA */
     970           0 :                         lsa = ospf_external_lsa_originate(ospf, ei_aggr);
     971           0 :                         if (lsa)
     972           0 :                                 SET_FLAG(aggr->flags,
     973             :                                          OSPF_EXTERNAL_AGGRT_ORIGINATED);
     974             :                 }
     975             :         }
     976             : }
     977             : 
     978           0 : static void ospf_handle_external_aggr_update(struct ospf *ospf)
     979             : {
     980           0 :         struct route_node *rn = NULL;
     981             : 
     982           0 :         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
     983           0 :                 zlog_debug("%s: Process modified aggregators.", __func__);
     984             : 
     985           0 :         for (rn = route_top(ospf->rt_aggr_tbl); rn; rn = route_next(rn)) {
     986           0 :                 struct ospf_external_aggr_rt *aggr;
     987           0 :                 struct ospf_lsa *lsa = NULL;
     988           0 :                 struct as_external_lsa *asel = NULL;
     989           0 :                 struct external_info ei_aggr;
     990           0 :                 route_tag_t tag = 0;
     991             : 
     992           0 :                 if (!rn->info)
     993           0 :                         continue;
     994             : 
     995           0 :                 aggr = rn->info;
     996             : 
     997           0 :                 if (aggr->action == OSPF_ROUTE_AGGR_DEL) {
     998           0 :                         aggr->action = OSPF_ROUTE_AGGR_NONE;
     999           0 :                         ospf_external_aggr_delete(ospf, rn);
    1000             : 
    1001           0 :                         if (OSPF_EXTERNAL_RT_COUNT(aggr))
    1002           0 :                                 hash_clean(
    1003             :                                         aggr->match_extnl_hash,
    1004             :                                         (void *)ospf_aggr_handle_external_info);
    1005             : 
    1006           0 :                         hash_free(aggr->match_extnl_hash);
    1007           0 :                         XFREE(MTYPE_OSPF_EXTERNAL_RT_AGGR, aggr);
    1008             : 
    1009           0 :                 } else if (aggr->action == OSPF_ROUTE_AGGR_MODIFY) {
    1010             : 
    1011           0 :                         aggr->action = OSPF_ROUTE_AGGR_NONE;
    1012             : 
    1013             :                         /* Prepare the extrenal_info for aggregator */
    1014           0 :                         memset(&ei_aggr, 0, sizeof(ei_aggr));
    1015           0 :                         ei_aggr.p = aggr->p;
    1016           0 :                         ei_aggr.tag = aggr->tag;
    1017           0 :                         ei_aggr.type = 0;
    1018           0 :                         ei_aggr.instance = ospf->instance;
    1019           0 :                         ei_aggr.route_map_set.metric = -1;
    1020           0 :                         ei_aggr.route_map_set.metric_type = -1;
    1021             : 
    1022             :                         /* Check if tag modified */
    1023           0 :                         if (CHECK_FLAG(aggr->flags,
    1024             :                                        OSPF_EXTERNAL_AGGRT_ORIGINATED)) {
    1025           0 :                                 lsa = ospf_external_info_find_lsa(ospf,
    1026             :                                                                   &ei_aggr.p);
    1027           0 :                                 if (!lsa) {
    1028           0 :                                         flog_warn(EC_OSPF_LSA_MISSING,
    1029             :                                                   "%s: Could not refresh/originate %pI4/%d",
    1030             :                                                   __func__, &aggr->p.prefix,
    1031             :                                                   aggr->p.prefixlen);
    1032           0 :                                         continue;
    1033             :                                 }
    1034             : 
    1035           0 :                                 asel = (struct as_external_lsa *)lsa->data;
    1036           0 :                                 tag = (unsigned long)ntohl(
    1037             :                                         asel->e[0].route_tag);
    1038             : 
    1039             :                                 /* If tag modified , then re-originate the
    1040             :                                  * route with modified tag details.
    1041             :                                  */
    1042           0 :                                 if (tag != ei_aggr.tag) {
    1043           0 :                                         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
    1044           0 :                                                 zlog_debug(
    1045             :                                                         "%s: Route tag changed(old:%d new:%d,So refresh the summary route.(%pI4/%d)",
    1046             :                                                         __func__, tag,
    1047             :                                                         ei_aggr.tag,
    1048             :                                                         &aggr->p.prefix,
    1049             :                                                         aggr->p.prefixlen);
    1050             : 
    1051           0 :                                         ospf_external_lsa_refresh(
    1052             :                                                 ospf, lsa, &ei_aggr,
    1053             :                                                 LSA_REFRESH_FORCE, 1);
    1054             :                                 }
    1055             :                         }
    1056             : 
    1057             :                         /* Advertise option modified ?
    1058             :                          * If so, handled it here.
    1059             :                          */
    1060           0 :                         ospf_aggr_handle_advertise_change(ospf, aggr, &ei_aggr);
    1061             :                 }
    1062             :         }
    1063           0 : }
    1064             : 
    1065           0 : static void ospf_asbr_external_aggr_process(struct thread *thread)
    1066             : {
    1067           0 :         struct ospf *ospf = THREAD_ARG(thread);
    1068           0 :         int operation = 0;
    1069             : 
    1070           0 :         ospf->t_external_aggr = NULL;
    1071           0 :         operation = ospf->aggr_action;
    1072             : 
    1073           0 :         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
    1074           0 :                 zlog_debug("%s: operation:%d", __func__, operation);
    1075             : 
    1076           0 :         switch (operation) {
    1077           0 :         case OSPF_ROUTE_AGGR_ADD:
    1078           0 :                 ospf_handle_external_aggr_add(ospf);
    1079           0 :                 break;
    1080           0 :         case OSPF_ROUTE_AGGR_DEL:
    1081             :         case OSPF_ROUTE_AGGR_MODIFY:
    1082           0 :                 ospf_handle_external_aggr_update(ospf);
    1083           0 :                 break;
    1084             :         default:
    1085             :                 break;
    1086             :         }
    1087           0 : }
    1088           0 : static void ospf_external_aggr_timer(struct ospf *ospf,
    1089             :                                      struct ospf_external_aggr_rt *aggr,
    1090             :                                      enum ospf_aggr_action_t operation)
    1091             : {
    1092           0 :         aggr->action = operation;
    1093             : 
    1094           0 :         if (ospf->t_external_aggr) {
    1095           0 :                 if (ospf->aggr_action == OSPF_ROUTE_AGGR_ADD) {
    1096             : 
    1097           0 :                         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
    1098           0 :                                 zlog_debug(
    1099             :                                         "%s: Not required to retsart timer,set is already added.",
    1100             :                                         __func__);
    1101           0 :                         return;
    1102             :                 }
    1103             : 
    1104           0 :                 if (operation == OSPF_ROUTE_AGGR_ADD) {
    1105           0 :                         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
    1106           0 :                                 zlog_debug(
    1107             :                                         "%s, Restarting Aggregator delay timer.",
    1108             :                                         __func__);
    1109           0 :                         THREAD_OFF(ospf->t_external_aggr);
    1110             :                 }
    1111             :         }
    1112             : 
    1113           0 :         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
    1114           0 :                 zlog_debug("%s: Start Aggregator delay timer %u(in seconds).",
    1115             :                            __func__, ospf->aggr_delay_interval);
    1116             : 
    1117           0 :         ospf->aggr_action = operation;
    1118           0 :         thread_add_timer(master, ospf_asbr_external_aggr_process, ospf,
    1119             :                          ospf->aggr_delay_interval, &ospf->t_external_aggr);
    1120             : }
    1121             : 
    1122           0 : int ospf_asbr_external_aggregator_set(struct ospf *ospf, struct prefix_ipv4 *p,
    1123             :                                       route_tag_t tag)
    1124             : {
    1125           0 :         struct ospf_external_aggr_rt *aggregator;
    1126             : 
    1127           0 :         aggregator = ospf_extrenal_aggregator_lookup(ospf, p);
    1128             : 
    1129           0 :         if (aggregator) {
    1130           0 :                 if (CHECK_FLAG(aggregator->flags,
    1131             :                                OSPF_EXTERNAL_AGGRT_NO_ADVERTISE))
    1132           0 :                         UNSET_FLAG(aggregator->flags,
    1133             :                                    OSPF_EXTERNAL_AGGRT_NO_ADVERTISE);
    1134           0 :                 else if (aggregator->tag == tag)
    1135             :                         return OSPF_SUCCESS;
    1136             : 
    1137           0 :                 aggregator->tag = tag;
    1138             : 
    1139           0 :                 ospf_external_aggr_timer(ospf, aggregator,
    1140             :                                          OSPF_ROUTE_AGGR_MODIFY);
    1141             :         } else {
    1142           0 :                 aggregator = ospf_external_aggregator_new(p);
    1143           0 :                 if (!aggregator)
    1144             :                         return OSPF_FAILURE;
    1145             : 
    1146           0 :                 aggregator->tag = tag;
    1147             : 
    1148           0 :                 ospf_external_aggr_add(ospf, aggregator);
    1149           0 :                 ospf_external_aggr_timer(ospf, aggregator, OSPF_ROUTE_AGGR_ADD);
    1150             :         }
    1151             : 
    1152             :         return OSPF_SUCCESS;
    1153             : }
    1154             : 
    1155           0 : int ospf_asbr_external_aggregator_unset(struct ospf *ospf,
    1156             :                                         struct prefix_ipv4 *p, route_tag_t tag)
    1157             : {
    1158           0 :         struct route_node *rn;
    1159           0 :         struct ospf_external_aggr_rt *aggr;
    1160             : 
    1161           0 :         rn = route_node_lookup(ospf->rt_aggr_tbl, (struct prefix *)p);
    1162           0 :         if (!rn)
    1163             :                 return OSPF_INVALID;
    1164           0 :         route_unlock_node(rn);
    1165             : 
    1166           0 :         aggr = rn->info;
    1167             : 
    1168           0 :         if (tag && (tag != aggr->tag))
    1169             :                 return OSPF_INVALID;
    1170             : 
    1171           0 :         if (!OSPF_EXTERNAL_RT_COUNT(aggr)) {
    1172           0 :                 ospf_external_aggr_delete(ospf, rn);
    1173           0 :                 ospf_external_aggregator_free(aggr);
    1174           0 :                 return OSPF_SUCCESS;
    1175             :         }
    1176             : 
    1177           0 :         ospf_external_aggr_timer(ospf, aggr, OSPF_ROUTE_AGGR_DEL);
    1178             : 
    1179           0 :         return OSPF_SUCCESS;
    1180             : }
    1181             : 
    1182           0 : int ospf_asbr_external_rt_no_advertise(struct ospf *ospf, struct prefix_ipv4 *p)
    1183             : {
    1184           0 :         struct ospf_external_aggr_rt *aggr;
    1185           0 :         route_tag_t tag = 0;
    1186             : 
    1187           0 :         aggr = ospf_extrenal_aggregator_lookup(ospf, p);
    1188           0 :         if (aggr) {
    1189           0 :                 if (CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_NO_ADVERTISE))
    1190             :                         return OSPF_SUCCESS;
    1191             : 
    1192           0 :                 SET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_NO_ADVERTISE);
    1193             : 
    1194           0 :                 aggr->tag = tag;
    1195             : 
    1196           0 :                 if (!OSPF_EXTERNAL_RT_COUNT(aggr))
    1197             :                         return OSPF_SUCCESS;
    1198             : 
    1199           0 :                 ospf_external_aggr_timer(ospf, aggr, OSPF_ROUTE_AGGR_MODIFY);
    1200             :         } else {
    1201           0 :                 aggr = ospf_external_aggregator_new(p);
    1202             : 
    1203           0 :                 if (!aggr)
    1204             :                         return OSPF_FAILURE;
    1205             : 
    1206           0 :                 SET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_NO_ADVERTISE);
    1207           0 :                 ospf_external_aggr_add(ospf, aggr);
    1208           0 :                 ospf_external_aggr_timer(ospf, aggr, OSPF_ROUTE_AGGR_ADD);
    1209             :         }
    1210             : 
    1211             :         return OSPF_SUCCESS;
    1212             : }
    1213             : 
    1214           0 : int ospf_asbr_external_rt_advertise(struct ospf *ospf, struct prefix_ipv4 *p)
    1215             : {
    1216           0 :         struct route_node *rn;
    1217           0 :         struct ospf_external_aggr_rt *aggr;
    1218             : 
    1219           0 :         rn = route_node_lookup(ospf->rt_aggr_tbl, (struct prefix *)p);
    1220           0 :         if (!rn)
    1221             :                 return OSPF_INVALID;
    1222           0 :         route_unlock_node(rn);
    1223             : 
    1224           0 :         aggr = rn->info;
    1225             : 
    1226           0 :         if (!CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_NO_ADVERTISE))
    1227             :                 return OSPF_INVALID;
    1228             : 
    1229           0 :         UNSET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_NO_ADVERTISE);
    1230             : 
    1231           0 :         if (!OSPF_EXTERNAL_RT_COUNT(aggr))
    1232             :                 return OSPF_SUCCESS;
    1233             : 
    1234           0 :         ospf_external_aggr_timer(ospf, aggr, OSPF_ROUTE_AGGR_MODIFY);
    1235           0 :         return OSPF_SUCCESS;
    1236             : }
    1237             : 
    1238           0 : int ospf_external_aggregator_timer_set(struct ospf *ospf, uint16_t interval)
    1239             : {
    1240           0 :         ospf->aggr_delay_interval = interval;
    1241           0 :         return OSPF_SUCCESS;
    1242             : }

Generated by: LCOV version v1.16-topotato