📄 ospf6_intra.c
字号:
/* * Copyright (C) 2002 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 "ospf6d.h"static int intra_index;#define IS_OSPF6_DUMP_INTRA (ospf6_dump_is_on (intra_index))#define ADD 0#define REMOVE 1static voidospf6_intra_route_calculate (int type, struct ospf6_lsa *lsa, struct ospf6_route_req *topo_entry){ struct ospf6_intra_area_prefix_lsa *intra_prefix; char *start, *end; struct ospf6_prefix *ospf6_prefix; struct ospf6_route_req request; struct ospf6_area *area; if (IS_OSPF6_DUMP_INTRA) { char buf[64]; struct prefix_ls *p_ls; p_ls = (struct prefix_ls *) &topo_entry->route.prefix; inet_ntop (AF_INET, &p_ls->adv_router, buf, sizeof (buf)); zlog_info ("INTRA: Calculate [%s] %s and %s", (type == ADD ? "add" : "remove"), lsa->str, buf); } intra_prefix = OSPF6_LSA_HEADER_END (lsa->header); area = lsa->scope; assert (area); start = (char *) (intra_prefix + 1); end = (char *) lsa->header + ntohs (lsa->header->length); for (ospf6_prefix = (struct ospf6_prefix *) start; (char *) ospf6_prefix < end; ospf6_prefix = OSPF6_NEXT_PREFIX (ospf6_prefix)) { memset (&request, 0, sizeof (request)); request.route.type = OSPF6_DEST_TYPE_NETWORK; request.route.prefix.family = AF_INET6; request.route.prefix.prefixlen = ospf6_prefix->prefix_length; ospf6_prefix_in6_addr (ospf6_prefix, &request.route.prefix.u.prefix6); request.path.type = OSPF6_PATH_TYPE_INTRA; request.path.area_id = area->area_id; request.path.origin.type = lsa->header->type; request.path.origin.id = lsa->header->id; request.path.origin.adv_router = lsa->header->adv_router; request.path.cost = topo_entry->path.cost + ntohs (ospf6_prefix->prefix_metric); request.path.capability[0] = topo_entry->path.capability[0]; request.path.capability[1] = topo_entry->path.capability[1]; request.path.capability[2] = topo_entry->path.capability[2]; memcpy (&request.nexthop.address, &topo_entry->nexthop.address, sizeof (request.nexthop.address)); request.nexthop.ifindex = topo_entry->nexthop.ifindex; if (type == ADD) ospf6_route_add (&request, area->route_table); else if (type == REMOVE) ospf6_route_remove (&request, area->route_table); else assert (0); }}intospf6_intra_prefix_database_hook_remove (void *data){ struct ospf6_lsa *lsa = data; struct ospf6_area *area; struct ospf6_intra_area_prefix_lsa *iap; struct prefix_ls prefix_ls; struct ospf6_route_req topo_entry; if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTRA_PREFIX)) return 0; area = (struct ospf6_area *) lsa->scope; assert (area); if (IS_OSPF6_DUMP_INTRA) zlog_info ("INTRA: area %s remove: %s", area->str, lsa->str); iap = OSPF6_LSA_HEADER_END (lsa->header); memset (&prefix_ls, 0, sizeof (prefix_ls)); prefix_ls.prefixlen = 64; prefix_ls.adv_router.s_addr = iap->refer_advrtr; prefix_ls.id.s_addr = iap->refer_lsid; if (iap->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER) && iap->refer_lsid != htonl (0)) { zlog_warn ("SPF: Malformed ID %lu of Router reference in %s", (u_long) ntohl (iap->refer_lsid), lsa->str); prefix_ls.id.s_addr = htonl (0); } ospf6_route_lookup (&topo_entry, (struct prefix *) &prefix_ls, area->table_topology); while (iap->refer_lstype == topo_entry.path.origin.type && iap->refer_lsid == topo_entry.path.origin.id && iap->refer_advrtr == topo_entry.path.origin.adv_router) { ospf6_intra_route_calculate (REMOVE, lsa, &topo_entry); ospf6_route_next (&topo_entry); } return 0;}intospf6_intra_prefix_database_hook_add (void *data){ struct ospf6_lsa *lsa = data; struct ospf6_area *area; struct ospf6_intra_area_prefix_lsa *iap; struct prefix_ls prefix_ls; struct ospf6_route_req topo_entry; if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTRA_PREFIX)) return 0; area = (struct ospf6_area *) lsa->scope; assert (area); if (IS_LSA_MAXAGE (lsa)) { ospf6_intra_prefix_database_hook_remove (lsa); return 0; } if (IS_OSPF6_DUMP_INTRA) zlog_info ("INTRA: area %s add: %s", area->str, lsa->str); iap = OSPF6_LSA_HEADER_END (lsa->header); memset (&prefix_ls, 0, sizeof (struct prefix_ls)); prefix_ls.prefixlen = 64; prefix_ls.adv_router.s_addr = iap->refer_advrtr; prefix_ls.id.s_addr = iap->refer_lsid; if (iap->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER) && iap->refer_lsid != htonl (0)) { zlog_warn ("INTRA: Malformed ID %lu of Router reference in %s", (u_long) ntohl (iap->refer_lsid), lsa->str); prefix_ls.id.s_addr = htonl (0); } ospf6_route_lookup (&topo_entry, (struct prefix *) &prefix_ls, area->table_topology); while (iap->refer_lstype == topo_entry.path.origin.type && iap->refer_lsid == topo_entry.path.origin.id && iap->refer_advrtr == topo_entry.path.origin.adv_router) { ospf6_intra_route_calculate (ADD, lsa, &topo_entry); ospf6_route_next (&topo_entry); } return 0;}voidospf6_intra_topology_add (void *data){ struct ospf6_route_req *topo_entry = data; struct ospf6_area *area; struct ospf6_intra_area_prefix_lsa *iap; struct ospf6_lsdb_node node; area = ospf6_area_lookup (topo_entry->path.area_id, ospf6); if (! area) return; if (topo_entry->route.type == OSPF6_DEST_TYPE_ROUTER && (CHECK_FLAG (topo_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_B) || CHECK_FLAG (topo_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_E))) ospf6_route_add (topo_entry, ospf6->topology_table); for (ospf6_lsdb_type (&node, htons (OSPF6_LSA_TYPE_INTRA_PREFIX), area->lsdb); ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node)) { if (IS_LSA_MAXAGE (node.lsa)) continue; iap = OSPF6_LSA_HEADER_END (node.lsa->header); if (iap->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER) && iap->refer_lsid != htonl (0)) { zlog_warn ("INTRA: Malformed ID %lu of Router reference in %s", (u_long) ntohl (iap->refer_lsid), node.lsa->str); } if (iap->refer_lstype != topo_entry->path.origin.type || iap->refer_lsid != topo_entry->path.origin.id || iap->refer_advrtr != topo_entry->path.origin.adv_router) continue; ospf6_intra_route_calculate (ADD, node.lsa, topo_entry); }}voidospf6_intra_topology_remove (void *data){ struct ospf6_route_req *topo_entry = data; struct ospf6_area *area; struct ospf6_intra_area_prefix_lsa *iap; struct ospf6_lsdb_node node; area = ospf6_area_lookup (topo_entry->path.area_id, ospf6); if (! area) return; if (topo_entry->route.type == OSPF6_DEST_TYPE_ROUTER && (CHECK_FLAG (topo_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_B) || CHECK_FLAG (topo_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_E))) ospf6_route_remove (topo_entry, ospf6->topology_table); for (ospf6_lsdb_type (&node, htons (OSPF6_LSA_TYPE_INTRA_PREFIX), area->lsdb); ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node)) { if (IS_LSA_MAXAGE (node.lsa)) continue; iap = OSPF6_LSA_HEADER_END (node.lsa->header); if (iap->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER) && iap->refer_lsid != htonl (0)) zlog_warn ("SPF: Malformed ID %lu of Router reference in %s", (u_long) ntohl (iap->refer_lsid), node.lsa->str); if (iap->refer_lstype != topo_entry->path.origin.type || iap->refer_lsid != topo_entry->path.origin.id || iap->refer_advrtr != topo_entry->path.origin.adv_router) continue; ospf6_intra_route_calculate (REMOVE, node.lsa, topo_entry); }}/*****************************************//* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA *//*****************************************/#define CONTINUE_IF_ADDRESS_LINKLOCAL(addr)\ if (IN6_IS_ADDR_LINKLOCAL (&(addr)->u.prefix6))\ {\ char buf[64];\ prefix2str (addr, buf, sizeof (buf));\ if (IS_OSPF6_DUMP_PREFIX)\ zlog_info (" Filter out Linklocal: %s", buf);\ continue;\ }#define CONTINUE_IF_ADDRESS_UNSPECIFIED(addr)\ if (IN6_IS_ADDR_UNSPECIFIED (&(addr)->u.prefix6))\ {\ char buf[64];\ prefix2str (addr, buf, sizeof (buf));\ if (IS_OSPF6_DUMP_PREFIX)\ zlog_info (" Filter out Unspecified: %s", buf);\ continue;\ }#define CONTINUE_IF_ADDRESS_LOOPBACK(addr)\ if (IN6_IS_ADDR_LOOPBACK (&(addr)->u.prefix6))\ {\ char buf[64];\ prefix2str (addr, buf, sizeof (buf));\ if (IS_OSPF6_DUMP_PREFIX)\ zlog_info (" Filter out Loopback: %s", buf);\ continue;\ }#define CONTINUE_IF_ADDRESS_V4COMPAT(addr)\ if (IN6_IS_ADDR_V4COMPAT (&(addr)->u.prefix6))\ {\ char buf[64];\ prefix2str (addr, buf, sizeof (buf));\ if (IS_OSPF6_DUMP_PREFIX)\ zlog_info (" Filter out V4Compat: %s", buf);\ continue;\ }#define CONTINUE_IF_ADDRESS_V4MAPPED(addr)\ if (IN6_IS_ADDR_V4MAPPED (&(addr)->u.prefix6))\ {\ char buf[64];\ prefix2str (addr, buf, sizeof (buf));\ if (IS_OSPF6_DUMP_PREFIX)\ zlog_info (" Filter out V4Mapped: %s", buf);\ continue;\ }intospf6_lsa_intra_prefix_show (struct vty *vty, struct ospf6_lsa *lsa){ struct ospf6_intra_area_prefix_lsa *iap_lsa; struct ospf6_prefix *prefix; unsigned short prefixnum; char buf[128], type[32], id[32], adv_router[32]; struct in6_addr in6; char *start, *end, *current; assert (lsa->header); iap_lsa = (struct ospf6_intra_area_prefix_lsa *) (lsa->header + 1); prefixnum = ntohs (iap_lsa->prefix_number); ospf6_lsa_type_string (iap_lsa->refer_lstype, type, sizeof (type)); inet_ntop (AF_INET, &iap_lsa->refer_lsid, id, sizeof (id)); inet_ntop (AF_INET, &iap_lsa->refer_advrtr, adv_router, sizeof (adv_router)); vty_out (vty, " Number of Prefix: %d%s", prefixnum, VTY_NEWLINE); vty_out (vty, " Referenced LS Type: %s%s", type, VTY_NEWLINE); vty_out (vty, " Referenced LS ID: %s%s", id, VTY_NEWLINE); vty_out (vty, " Referenced Advertising Router: %s%s", adv_router, VTY_NEWLINE); start = (char *) lsa->header + sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_intra_area_prefix_lsa); end = (char *) lsa->header + ntohs (lsa->header->length); for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix)) { prefix = (struct ospf6_prefix *) current; if (current + OSPF6_PREFIX_SIZE (prefix) > end) { vty_out (vty, " Trailing %d byte garbage ... Malformed%s", end - current, VTY_NEWLINE); return -1; } ospf6_prefix_options_str (prefix->prefix_options, buf, sizeof (buf)); vty_out (vty, " Prefix Options: %s%s", buf, VTY_NEWLINE); ospf6_prefix_in6_addr (prefix, &in6); inet_ntop (AF_INET6, &in6, buf, sizeof (buf)); vty_out (vty, " Prefix: %s/%d%s", buf, prefix->prefix_length, VTY_NEWLINE); } return 0;}voidospf6_lsa_intra_prefix_update_transit (char *ifname){ char buffer [MAXLSASIZE]; u_int16_t size; struct ospf6_lsa *old; struct interface *ifp; struct ospf6_interface *o6i; struct ospf6_neighbor *o6n; struct ospf6_intra_area_prefix_lsa *iap; struct ospf6_lsdb_node n; listnode node; char *start, *end, *current; struct ospf6_prefix *prefix, *dup, *src, *dst; struct ospf6_link_lsa *link; char buf[128]; int count, prefix_num; list adv_list; ifp = if_lookup_by_name (ifname); if (! ifp) { zlog_warn ("Update Intra-Prefix (Transit): No such Interface: %s", ifname); return; } o6i = (struct ospf6_interface *) ifp->info; if (! o6i || ! o6i->area) { zlog_warn ("Update Intra-Prefix (Transit): Interface not enabled: %s", ifname); return; } /* find previous LSA */ old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_INTRA_PREFIX), htonl (o6i->if_id), ospf6->router_id, o6i->area); /* Don't originate Network-LSA if not DR */ if (o6i->state != IFS_DR) { if (old) { if (IS_OSPF6_DUMP_PREFIX) zlog_info ("Update Intra-Prefix (Transit): %s not DR", o6i->interface->name); ospf6_lsa_premature_aging (old); } return; } /* If none of neighbor is adjacent to us */ count = 0; o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state); if (count == 0) { if (IS_OSPF6_DUMP_PREFIX) zlog_info ("Update Intra-Prefix (Transit): %s is Stub", o6i->interface->name); if (old) ospf6_lsa_premature_aging (old); return; } if (IS_OSPF6_DUMP_PREFIX) zlog_info ("Update Intra-Prefix (Transit): Interface %s",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -