📄 ospf_ia.c
字号:
/* * OSPF inter-area routing. * Copyright (C) 1999, 2000 Alex Zinin, Toshiaki Takada * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */#include <zebra.h>#include "thread.h"#include "memory.h"#include "hash.h"#include "linklist.h"#include "prefix.h"#include "table.h"#include "log.h"#include "ospfd/ospfd.h"#include "ospfd/ospf_interface.h"#include "ospfd/ospf_ism.h"#include "ospfd/ospf_asbr.h"#include "ospfd/ospf_lsa.h"#include "ospfd/ospf_lsdb.h"#include "ospfd/ospf_neighbor.h"#include "ospfd/ospf_nsm.h"#include "ospfd/ospf_spf.h"#include "ospfd/ospf_route.h"#include "ospfd/ospf_ase.h"#include "ospfd/ospf_abr.h"#include "ospfd/ospf_ia.h"#include "ospfd/ospf_dump.h"#define DEBUGstruct ospf_route *ospf_find_abr_route (struct route_table *rtrs, struct prefix_ipv4 *abr, struct ospf_area *area){ struct route_node *rn; struct ospf_route *or; listnode node; if ((rn = route_node_lookup (rtrs, (struct prefix *) abr)) == NULL) return NULL; route_unlock_node (rn); for (node = listhead ((list) rn->info); node; nextnode (node)) if ((or = getdata (node)) != NULL) if (IPV4_ADDR_SAME (&or->u.std.area_id, &area->area_id) && (or->u.std.flags & ROUTER_LSA_BORDER)) return or; return NULL;}voidospf_ia_network_route (struct ospf *ospf, struct route_table *rt, struct prefix_ipv4 *p, struct ospf_route *new_or, struct ospf_route *abr_or){ struct route_node *rn1; struct ospf_route *or; if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_network_route(): processing summary route to %s/%d", inet_ntoa (p->prefix), p->prefixlen); /* Find a route to the same dest */ if ((rn1 = route_node_lookup (rt, (struct prefix *) p))) { int res; route_unlock_node (rn1); if ((or = rn1->info)) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_network_route(): " "Found a route to the same network"); /* Check the existing route. */ if ((res = ospf_route_cmp (ospf, new_or, or)) < 0) { /* New route is better, so replace old one. */ ospf_route_subst (rn1, new_or, abr_or); } else if (res == 0) { /* New and old route are equal, so next hops can be added. */ route_lock_node (rn1); ospf_route_copy_nexthops (or, abr_or->path); route_unlock_node (rn1); /* new route can be deleted, because existing route has been updated. */ ospf_route_free (new_or); } else { /* New route is worse, so free it. */ ospf_route_free (new_or); return; } } /* if (or)*/ } /*if (rn1)*/ else { /* no route */ if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_network_route(): add new route to %s/%d", inet_ntoa (p->prefix), p->prefixlen); ospf_route_add (rt, p, new_or, abr_or); }}voidospf_ia_router_route (struct ospf *ospf, struct route_table *rtrs, struct prefix_ipv4 *p, struct ospf_route *new_or, struct ospf_route *abr_or){ struct ospf_route *or = NULL; struct route_node *rn; int ret; if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_router_route(): considering %s/%d", inet_ntoa (p->prefix), p->prefixlen); /* Find a route to the same dest */ rn = route_node_get (rtrs, (struct prefix *) p); if (rn->info == NULL) /* This is a new route */ rn->info = list_new (); else { struct ospf_area *or_area; or_area = ospf_area_lookup_by_area_id (ospf, new_or->u.std.area_id); assert (or_area); /* This is an additional route */ route_unlock_node (rn); or = ospf_find_asbr_route_through_area (rtrs, p, or_area); } if (or) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_router_route(): " "a route to the same ABR through the same area exists"); /* New route is better */ if ((ret = ospf_route_cmp (ospf, new_or, or)) < 0) { listnode_delete (rn->info, or); ospf_route_free (or); /* proceed down */ } /* Routes are the same */ else if (ret == 0) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_router_route(): merging the new route"); ospf_route_copy_nexthops (or, abr_or->path); ospf_route_free (new_or); return; } /* New route is worse */ else { if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_router_route(): skipping the new route"); ospf_route_free (new_or); return; } } ospf_route_copy_nexthops (new_or, abr_or->path); if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_router_route(): adding the new route"); listnode_add (rn->info, new_or);}intprocess_summary_lsa (struct ospf_area *area, struct route_table *rt, struct route_table *rtrs, struct ospf_lsa *lsa){ struct ospf *ospf = area->ospf; struct ospf_area_range *range; struct ospf_route *abr_or, *new_or; struct summary_lsa *sl; struct prefix_ipv4 p, abr; u_int32_t metric; if (lsa == NULL) return 0; sl = (struct summary_lsa *) lsa->data; if (IS_DEBUG_OSPF_EVENT) zlog_info ("process_summary_lsa(): LS ID: %s", inet_ntoa (sl->header.id)); metric = GET_METRIC (sl->metric); if (metric == OSPF_LS_INFINITY) return 0; if (IS_LSA_MAXAGE (lsa)) return 0; if (ospf_lsa_is_self_originated (area->ospf, lsa)) return 0; p.family = AF_INET; p.prefix = sl->header.id; if (sl->header.type == OSPF_SUMMARY_LSA) p.prefixlen = ip_masklen (sl->mask); else p.prefixlen = IPV4_MAX_BITLEN; apply_mask_ipv4 (&p); if (sl->header.type == OSPF_SUMMARY_LSA && (range = ospf_area_range_match_any (ospf, &p)) && ospf_area_range_active (range)) return 0; if (ospf->abr_type != OSPF_ABR_STAND && area->external_routing != OSPF_AREA_DEFAULT && p.prefix.s_addr == OSPF_DEFAULT_DESTINATION && p.prefixlen == 0) return 0; /* Ignore summary default from a stub area */ abr.family = AF_INET; abr.prefix = sl->header.adv_router; abr.prefixlen = IPV4_MAX_BITLEN; apply_mask_ipv4 (&abr); abr_or = ospf_find_abr_route (rtrs, &abr, area); if (abr_or == NULL) return 0; new_or = ospf_route_new (); new_or->type = OSPF_DESTINATION_NETWORK; new_or->id = sl->header.id; new_or->mask = sl->mask; new_or->u.std.options = sl->header.options; new_or->u.std.origin = (struct lsa_header *) sl; new_or->cost = abr_or->cost + metric; new_or->u.std.area_id = area->area_id;#ifdef HAVE_NSSA new_or->u.std.external_routing = area->external_routing;#endif /* HAVE_NSSA */ new_or->path_type = OSPF_PATH_INTER_AREA; if (sl->header.type == OSPF_SUMMARY_LSA) ospf_ia_network_route (ospf, rt, &p, new_or, abr_or); else { new_or->type = OSPF_DESTINATION_ROUTER; new_or->u.std.flags = ROUTER_LSA_EXTERNAL; ospf_ia_router_route (ospf, rtrs, &p, new_or, abr_or); } return 0;}voidospf_examine_summaries (struct ospf_area *area, struct route_table *lsdb_rt, struct route_table *rt, struct route_table *rtrs){ struct ospf_lsa *lsa; struct route_node *rn; LSDB_LOOP (lsdb_rt, rn, lsa) process_summary_lsa (area, rt, rtrs, lsa);}intospf_area_is_transit (struct ospf_area *area){ return (area->transit == OSPF_TRANSIT_TRUE) || ospf_full_virtual_nbrs(area); /* Cisco forgets to set the V-bit :( */}voidospf_update_network_route (struct ospf *ospf, struct route_table *rt, struct route_table *rtrs, struct summary_lsa *lsa, struct prefix_ipv4 *p, struct ospf_area *area){ struct route_node *rn; struct ospf_route *or, *abr_or, *new_or; struct prefix_ipv4 abr; u_int32_t cost; abr.family = AF_INET; abr.prefix =lsa->header.adv_router; abr.prefixlen = IPV4_MAX_BITLEN; apply_mask_ipv4 (&abr); abr_or = ospf_find_abr_route (rtrs, &abr, area); if (abr_or == NULL) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_update_network_route(): can't find a route to the ABR"); return; } cost = abr_or->cost + GET_METRIC (lsa->metric); rn = route_node_lookup (rt, (struct prefix *) p); if (! rn) { if (ospf->abr_type != OSPF_ABR_SHORTCUT) return; /* Standard ABR can update only already installed backbone paths */ if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_update_network_route(): " "Allowing Shortcut ABR to add new route"); new_or = ospf_route_new (); new_or->type = OSPF_DESTINATION_NETWORK; new_or->id = lsa->header.id; new_or->mask = lsa->mask; new_or->u.std.options = lsa->header.options; new_or->u.std.origin = (struct lsa_header *) lsa; new_or->cost = cost; new_or->u.std.area_id = area->area_id;#ifdef HAVE_NSSA new_or->u.std.external_routing = area->external_routing;#endif /* HAVE_NSSA */ new_or->path_type = OSPF_PATH_INTER_AREA; ospf_route_add (rt, p, new_or, abr_or); return; } else { route_unlock_node (rn); if (rn->info == NULL) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -