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 21 : struct external_info *ospf_external_info_new(struct ospf *ospf, uint8_t type,
76 : unsigned short instance)
77 : {
78 21 : struct external_info *new;
79 :
80 21 : new = XCALLOC(MTYPE_OSPF_EXTERNAL_INFO, sizeof(struct external_info));
81 21 : new->ospf = ospf;
82 21 : new->type = type;
83 21 : new->instance = instance;
84 21 : new->to_be_processed = 0;
85 :
86 21 : ospf_reset_route_map_set_values(&new->route_map_set);
87 21 : return new;
88 : }
89 :
90 21 : static void ospf_external_info_free(struct external_info *ei)
91 : {
92 42 : XFREE(MTYPE_OSPF_EXTERNAL_INFO, ei);
93 : }
94 :
95 49 : void ospf_reset_route_map_set_values(struct route_map_set_values *values)
96 : {
97 49 : values->metric = -1;
98 49 : values->metric_type = -1;
99 28 : }
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 37 : 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 37 : struct external_info *new;
115 37 : struct route_node *rn;
116 37 : struct ospf_external *ext;
117 :
118 37 : ext = ospf_external_lookup(ospf, type, instance);
119 37 : if (!ext)
120 0 : ext = ospf_external_add(ospf, type, instance);
121 :
122 37 : rn = route_node_get(EXTERNAL_INFO(ext), (struct prefix *)&p);
123 : /* If old info exists, -- discard new one or overwrite with new one? */
124 37 : if (rn && rn->info) {
125 16 : new = rn->info;
126 16 : if ((new->ifindex == ifindex)
127 16 : && (new->nexthop.s_addr == nexthop.s_addr)
128 16 : && (new->tag == tag)) {
129 16 : route_unlock_node(rn);
130 16 : 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 21 : new = ospf_external_info_new(ospf, type, instance);
143 21 : new->p = p;
144 21 : new->ifindex = ifindex;
145 21 : new->nexthop = nexthop;
146 21 : new->tag = tag;
147 21 : new->orig_tag = tag;
148 21 : new->aggr_route = NULL;
149 :
150 : /* we don't unlock rn from the get() because we're attaching the info */
151 21 : if (rn)
152 21 : rn->info = new;
153 :
154 21 : 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 1156 : void ospf_external_info_delete(struct ospf *ospf, uint8_t type,
164 : unsigned short instance, struct prefix_ipv4 p)
165 : {
166 1156 : struct route_node *rn;
167 1156 : struct ospf_external *ext;
168 :
169 1156 : ext = ospf_external_lookup(ospf, type, instance);
170 1156 : if (!ext)
171 : return;
172 :
173 9 : rn = route_node_lookup(EXTERNAL_INFO(ext), (struct prefix *)&p);
174 9 : if (rn) {
175 9 : ospf_external_info_free(rn->info);
176 9 : rn->info = NULL;
177 9 : route_unlock_node(rn);
178 9 : route_unlock_node(rn);
179 : }
180 : }
181 :
182 35 : struct external_info *ospf_external_info_lookup(struct ospf *ospf, uint8_t type,
183 : unsigned short instance,
184 : struct prefix_ipv4 *p)
185 : {
186 35 : struct route_node *rn;
187 35 : struct ospf_external *ext;
188 :
189 35 : ext = ospf_external_lookup(ospf, type, instance);
190 35 : if (!ext)
191 : return NULL;
192 :
193 18 : rn = route_node_lookup(EXTERNAL_INFO(ext), (struct prefix *)p);
194 18 : if (rn) {
195 9 : route_unlock_node(rn);
196 9 : 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 32 : if (p->prefixlen == IPV4_MAX_BITLEN) {
228 32 : al = (struct as_external_lsa *)lsa->data;
229 :
230 32 : if (mask.s_addr != al->mask.s_addr)
231 : return NULL;
232 : }
233 : return lsa;
234 : }
235 :
236 59 : lsa = ospf_lsdb_lookup_by_id(ospf->lsdb, OSPF_AS_EXTERNAL_LSA,
237 : p->prefix, ospf->router_id);
238 :
239 59 : 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 30 : struct ospf_external_aggr_rt *ospf_external_aggr_match(struct ospf *ospf,
533 : struct prefix_ipv4 *p)
534 : {
535 30 : struct route_node *node;
536 30 : struct ospf_external_aggr_rt *summary_rt = NULL;
537 :
538 30 : node = route_node_match(ospf->rt_aggr_tbl, (struct prefix *)p);
539 30 : 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 : }
|