📄 ospf6_abr.c
字号:
/* * Area Border Router function. * Copyright (C) 2004 Yasuhiro Ohara * * 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 "log.h"#include "prefix.h"#include "table.h"#include "vty.h"#include "linklist.h"#include "command.h"#include "thread.h"#include "ospf6_proto.h"#include "ospf6_route.h"#include "ospf6_lsa.h"#include "ospf6_route.h"#include "ospf6_lsdb.h"#include "ospf6_message.h"#include "ospf6_top.h"#include "ospf6_area.h"#include "ospf6_interface.h"#include "ospf6_neighbor.h"#include "ospf6_flood.h"#include "ospf6_intra.h"#include "ospf6_abr.h"#include "ospf6d.h"unsigned char conf_debug_ospf6_abr;intospf6_is_router_abr (struct ospf6 *o){ listnode node; struct ospf6_area *oa; int area_count = 0; for (node = listhead (o->area_list); node; nextnode (node)) { oa = OSPF6_AREA (getdata (node)); if (IS_AREA_ENABLED (oa)) area_count++; } if (area_count > 1) return 1; return 0;}voidospf6_abr_enable_area (struct ospf6_area *area){ struct ospf6_area *oa; struct ospf6_route *ro; listnode node; for (node = listhead (area->ospf6->area_list); node; nextnode (node)) { oa = OSPF6_AREA (getdata (node)); /* update B bit for each area */ OSPF6_ROUTER_LSA_SCHEDULE (oa); /* install other area's configured address range */ if (oa != area) { for (ro = ospf6_route_head (oa->range_table); ro; ro = ospf6_route_next (ro)) { if (CHECK_FLAG (ro->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) ospf6_abr_originate_summary_to_area (ro, area); } } } /* install calculated routes to border routers */ for (ro = ospf6_route_head (area->ospf6->brouter_table); ro; ro = ospf6_route_next (ro)) ospf6_abr_originate_summary_to_area (ro, area); /* install calculated routes to network (may be rejected by ranges) */ for (ro = ospf6_route_head (area->ospf6->route_table); ro; ro = ospf6_route_next (ro)) ospf6_abr_originate_summary_to_area (ro, area);}voidospf6_abr_disable_area (struct ospf6_area *area){ struct ospf6_area *oa; struct ospf6_route *ro; struct ospf6_lsa *old; listnode node; /* Withdraw all summary prefixes previously originated */ for (ro = ospf6_route_head (area->summary_prefix); ro; ro = ospf6_route_next (ro)) { old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id, area->ospf6->router_id, area->lsdb); if (old) ospf6_lsa_purge (old); ospf6_route_remove (ro, area->summary_prefix); } /* Withdraw all summary router-routes previously originated */ for (ro = ospf6_route_head (area->summary_router); ro; ro = ospf6_route_next (ro)) { old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id, area->ospf6->router_id, area->lsdb); if (old) ospf6_lsa_purge (old); ospf6_route_remove (ro, area->summary_router); } /* Schedule Router-LSA for each area (ABR status may change) */ for (node = listhead (area->ospf6->area_list); node; nextnode (node)) { oa = OSPF6_AREA (getdata (node)); /* update B bit for each area */ OSPF6_ROUTER_LSA_SCHEDULE (oa); }}/* RFC 2328 12.4.3. Summary-LSAs */voidospf6_abr_originate_summary_to_area (struct ospf6_route *route, struct ospf6_area *area){ struct ospf6_lsa *lsa, *old = NULL; struct ospf6_interface *oi; struct ospf6_route *summary, *range = NULL; struct ospf6_area *route_area; char buffer[OSPF6_MAX_LSASIZE]; struct ospf6_lsa_header *lsa_header; caddr_t p; struct ospf6_inter_prefix_lsa *prefix_lsa; struct ospf6_inter_router_lsa *router_lsa; struct ospf6_route_table *summary_table = NULL; u_int16_t type; char buf[64]; int is_debug = 0; if (route->type == OSPF6_DEST_TYPE_ROUTER) { if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_ROUTER)) { is_debug++; inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), buf, sizeof (buf)); zlog_info ("Originating summary in area %s for ASBR %s", area->name, buf); } summary_table = area->summary_router; } else { if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_PREFIX)) { is_debug++; prefix2str (&route->prefix, buf, sizeof (buf)); zlog_info ("Originating summary in area %s for %s", area->name, buf); } summary_table = area->summary_prefix; } summary = ospf6_route_lookup (&route->prefix, summary_table); if (summary) old = ospf6_lsdb_lookup (summary->path.origin.type, summary->path.origin.id, area->ospf6->router_id, area->lsdb); /* if this route has just removed, remove corresponding LSA */ if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE)) { if (is_debug) zlog_info ("The route has just removed, purge previous LSA"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* Only destination type network, range or ASBR are considered */ if (route->type != OSPF6_DEST_TYPE_NETWORK && route->type != OSPF6_DEST_TYPE_RANGE && (route->type != OSPF6_DEST_TYPE_ROUTER || ! CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E))) { if (is_debug) zlog_info ("Route type is none of network, range nor ASBR, withdraw"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* AS External routes are never considered */ if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 || route->path.type == OSPF6_PATH_TYPE_EXTERNAL2) { if (is_debug) zlog_info ("Path type is external, withdraw"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* do not generate if the path's area is the same as target area */ if (route->path.area_id == area->area_id) { if (is_debug) zlog_info ("The route is in the area itself, ignore"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* do not generate if the nexthops belongs to the target area */ oi = ospf6_interface_lookup_by_ifindex (route->nexthop[0].ifindex); if (oi && oi->area && oi->area == area) { if (is_debug) zlog_info ("The route's nexthop is in the same area, ignore"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* do not generate if the route cost is greater or equal to LSInfinity */ if (route->path.cost >= LS_INFINITY) { if (is_debug) zlog_info ("The cost exceeds LSInfinity, withdraw"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* if this is a route to ASBR */ if (route->type == OSPF6_DEST_TYPE_ROUTER) { /* Only the prefered best path is considered */ if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST)) { if (is_debug) zlog_info ("This is the secondary path to the ASBR, ignore"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* Do not generate if the area is stub */ /* XXX */ } /* if this is an intra-area route, this may be suppressed by aggregation */ if (route->type == OSPF6_DEST_TYPE_NETWORK && route->path.type == OSPF6_PATH_TYPE_INTRA) { /* search for configured address range for the route's area */ route_area = ospf6_area_lookup (route->path.area_id, area->ospf6); assert (route_area); range = ospf6_route_lookup_bestmatch (&route->prefix, route_area->range_table); /* ranges are ignored when originate backbone routes to transit area. Otherwise, if ranges are configured, the route is suppressed. */ if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) && (route->path.area_id != BACKBONE_AREA_ID || ! IS_AREA_TRANSIT (area))) { if (is_debug) { prefix2str (&range->prefix, buf, sizeof (buf)); zlog_info ("Suppressed by range %s of area %s", buf, route_area->name); } if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } } /* If this is a configured address range */ if (route->type == OSPF6_DEST_TYPE_RANGE) { /* If DoNotAdvertise is set */ if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) { if (is_debug) zlog_info ("This is the range with DoNotAdvertise set. ignore"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* Whether the route have active longer prefix */ if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) { if (is_debug) zlog_info ("The range is not active. withdraw"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } } /* the route is going to be originated. store it in area's summary_table */ if (summary == NULL) { summary = ospf6_route_copy (route); if (route->type == OSPF6_DEST_TYPE_NETWORK || route->type == OSPF6_DEST_TYPE_RANGE) summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX); else summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER); summary->path.origin.adv_router = area->ospf6->router_id; summary->path.origin.id = ospf6_new_ls_id (summary->path.origin.type, summary->path.origin.adv_router, area->lsdb); summary = ospf6_route_add (summary, summary_table); } else { summary->type = route->type; gettimeofday (&summary->changed, NULL); } summary->path.router_bits = route->path.router_bits; summary->path.options[0] = route->path.options[0]; summary->path.options[1] = route->path.options[1]; summary->path.options[2] = route->path.options[2]; summary->path.prefix_options = route->path.prefix_options; summary->path.area_id = area->area_id; summary->path.type = OSPF6_PATH_TYPE_INTER; summary->path.cost = route->path.cost; summary->nexthop[0] = route->nexthop[0]; /* prepare buffer */ memset (buffer, 0, sizeof (buffer)); lsa_header = (struct ospf6_lsa_header *) buffer; if (route->type == OSPF6_DEST_TYPE_ROUTER) { router_lsa = (struct ospf6_inter_router_lsa *) ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa); /* Fill Inter-Area-Router-LSA */ router_lsa->options[0] = route->path.options[0]; router_lsa->options[1] = route->path.options[1]; router_lsa->options[2] = route->path.options[2];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -