📄 ospf6_route.c
字号:
/* * Copyright (C) 1999 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"char *dtype_name[OSPF6_DEST_TYPE_MAX] ={ "Unknown", "Router", "Network", "Discard"};#define DTYPE_NAME(x) \ (0 < (x) && (x) < sizeof (dtype_name) ? \ dtype_name[(x)] : dtype_name[0])char *dtype_abname[OSPF6_DEST_TYPE_MAX] ={ "?", "R", "N", "D"};#define DTYPE_ABNAME(x) \ (0 < (x) && (x) < sizeof (dtype_abname) ? \ dtype_abname[(x)] : dtype_abname[0])char *ptype_name[OSPF6_PATH_TYPE_MAX] ={ "Unknown", "Intra", "Inter", "External-1", "External-2", "System", "Kernel", "Connect", "Static", "RIP", "RIPng", "OSPF", "OSPF6", "BGP"};#define PTYPE_NAME(x) \ (0 < (x) && (x) < sizeof (ptype_name) ? \ ptype_name[(x)] : ptype_name[0])char *ptype_abname[OSPF6_PATH_TYPE_MAX] ={ "??", "Ia", "Ie", "E1", "E2", "-X", "-K", "-C", "-S", "-R", "-R", "-O", "-O", "-B"};#define PTYPE_ABNAME(x) \ (0 < (x) && (x) < sizeof (ptype_abname) ? \ ptype_abname[(x)] : ptype_abname[0])intospf6_path_cmp (void *arg1, void *arg2){ struct ospf6_path_node *pn1 = arg1; struct ospf6_path_node *pn2 = arg2; struct ospf6_path *p1 = &pn1->path; struct ospf6_path *p2 = &pn2->path; if (p1->type < p2->type) return -1; else if (p1->type > p2->type) return 1; if (p1->type == OSPF6_PATH_TYPE_EXTERNAL2) { if (p1->cost_e2 < p2->cost_e2) return -1; else if (p1->cost_e2 > p2->cost_e2) return 1; } if (p1->cost < p2->cost) return -1; else if (p1->cost > p2->cost) return 1; /* if from the same source, recognize as identical (and treat this as update) */ if (! memcmp (&p1->origin, &p2->origin, sizeof (struct ls_origin)) && p1->area_id == p2->area_id) return 0; /* else, always prefer left */ return -1;}intospf6_nexthop_cmp (void *arg1, void *arg2){ int i, ret = 0; struct ospf6_nexthop_node *nn1 = arg1; struct ospf6_nexthop_node *nn2 = arg2; struct ospf6_nexthop *n1 = &nn1->nexthop; struct ospf6_nexthop *n2 = &nn2->nexthop; if (memcmp (n1, n2, sizeof (struct ospf6_nexthop)) == 0) return 0; for (i = 0; i < sizeof (struct in6_addr); i++) { if (nn1->nexthop.address.s6_addr[i] != nn2->nexthop.address.s6_addr[i]) { ret = nn1->nexthop.address.s6_addr[i] - nn2->nexthop.address.s6_addr[i]; break; } } if (ret == 0) ret = -1; return ret;}static voidospf6_route_request (struct ospf6_route_req *request, struct ospf6_route_node *rn, struct ospf6_path_node *pn, struct ospf6_nexthop_node *nn){ assert (request); assert (rn && pn && nn); request->route_node = rn->route_node; linklist_head (rn->path_list, &request->path_lnode); while (request->path_lnode.data != pn) { //assert (! linklist_end (&request->path_lnode)); if (linklist_end (&request->path_lnode)) { struct linklist_node node; zlog_info ("rn: %p, pn: %p", rn, pn); zlog_info ("origin: %hx %x %x bits: %x opt: %x%x%x popt: %x area: %x type: %d cost %d %d %d", pn->path.origin.type, pn->path.origin.id, pn->path.origin.adv_router, (int)pn->path.router_bits, (int)pn->path.capability[0], (int)pn->path.capability[1], (int)pn->path.capability[2], (int)pn->path.prefix_options, pn->path.area_id, pn->path.type, pn->path.metric_type, pn->path.cost, pn->path.cost_e2); for (linklist_head (rn->path_list, &node); ! linklist_end (&node); linklist_next (&node)) { struct ospf6_path_node *pn2 = node.data; zlog_info (" %p: path data with pn(%p): %s", pn2, pn, (memcmp (&pn->path, &pn2->path, sizeof (struct ospf6_path)) ? "different" : "same")); zlog_info (" origin: %hx %x %x bits: %x opt: %x%x%x popt: %x area: %x type: %d cost %d %d %d", pn2->path.origin.type, pn2->path.origin.id, pn2->path.origin.adv_router, (int)pn2->path.router_bits, (int)pn2->path.capability[0], (int)pn2->path.capability[1], (int)pn2->path.capability[2], (int)pn2->path.prefix_options, pn2->path.area_id, pn2->path.type, pn2->path.metric_type, pn2->path.cost, pn2->path.cost_e2); if (! memcmp (&pn->path, &pn2->path, sizeof (struct ospf6_path))) { pn = pn2; request->nexthop_lnode.data = pn2; } } break; } linklist_next (&request->path_lnode); } assert (request->path_lnode.data == pn); linklist_head (pn->nexthop_list, &request->nexthop_lnode); while (request->nexthop_lnode.data != nn) { assert (! linklist_end (&request->nexthop_lnode)); linklist_next (&request->nexthop_lnode); } assert (request->nexthop_lnode.data == nn); request->table = rn->table; request->count = rn->count; request->route_id = rn->route_id; memcpy (&request->route, &rn->route, sizeof (struct ospf6_route)); memcpy (&request->path, &pn->path, sizeof (struct ospf6_path)); memcpy (&request->nexthop, &nn->nexthop, sizeof (struct ospf6_nexthop));}intospf6_route_count (struct ospf6_route_req *request){ return request->count;}intospf6_route_lookup (struct ospf6_route_req *request, struct prefix *prefix, struct ospf6_route_table *table){ struct route_node *node; struct ospf6_route_node *rn = NULL; struct ospf6_path_node *pn = NULL; struct ospf6_nexthop_node *nn = NULL; struct linklist_node lnode; if (request) memset ((void *) request, 0, sizeof (struct ospf6_route_req)); node = route_node_lookup (table->table, prefix); if (! node) return 0; rn = (struct ospf6_route_node *) node->info; if (! rn) return 0; if (request) { linklist_head (rn->path_list, &lnode); pn = lnode.data; linklist_head (pn->nexthop_list, &lnode); nn = lnode.data; ospf6_route_request (request, rn, pn, nn); } return 1;}voidospf6_route_head (struct ospf6_route_req *request, struct ospf6_route_table *table){ struct route_node *node; struct ospf6_route_node *rn = NULL; struct ospf6_path_node *pn = NULL; struct ospf6_nexthop_node *nn = NULL; struct linklist_node lnode; if (request) memset (request, 0, sizeof (struct ospf6_route_req)); node = route_top (table->table); if (! node) return; while (node && node->info == NULL) node = route_next (node); if (! node) return; rn = (struct ospf6_route_node *) node->info; linklist_head (rn->path_list, &lnode); pn = lnode.data; linklist_head (pn->nexthop_list, &lnode); nn = lnode.data; ospf6_route_request (request, rn, pn, nn);}intospf6_route_end (struct ospf6_route_req *request){ if (request->route_node == NULL && linklist_end (&request->path_lnode) && linklist_end (&request->nexthop_lnode) && request->nexthop.ifindex == 0 && IN6_IS_ADDR_UNSPECIFIED (&request->nexthop.address)) return 1; return 0;}voidospf6_route_next (struct ospf6_route_req *request){ struct ospf6_route_node *route_node = NULL; struct ospf6_path_node *path_node = NULL; struct ospf6_nexthop_node *nexthop_node = NULL; linklist_next (&request->nexthop_lnode); if (linklist_end (&request->nexthop_lnode)) { linklist_next (&request->path_lnode); if (linklist_end (&request->path_lnode)) { request->route_node = route_next (request->route_node); while (request->route_node && request->route_node->info == NULL) request->route_node = route_next (request->route_node); if (request->route_node) { route_node = request->route_node->info; if (route_node) linklist_head (route_node->path_list, &request->path_lnode); } } path_node = request->path_lnode.data; if (path_node) linklist_head (path_node->nexthop_list, &request->nexthop_lnode); } nexthop_node = request->nexthop_lnode.data; if (nexthop_node == NULL) { assert (path_node == NULL); assert (route_node == NULL); memset (&request->route, 0, sizeof (struct ospf6_route)); memset (&request->path, 0, sizeof (struct ospf6_path)); memset (&request->nexthop, 0, sizeof (struct ospf6_nexthop)); } else { path_node = request->path_lnode.data; route_node = request->route_node->info; assert (path_node != NULL); assert (route_node != NULL); memcpy (&request->route, &route_node->route, sizeof (struct ospf6_route)); memcpy (&request->path, &path_node->path, sizeof (struct ospf6_path)); memcpy (&request->nexthop, &nexthop_node->nexthop, sizeof (struct ospf6_nexthop)); }}#define ADD 0#define CHANGE 1#define REMOVE 2voidospf6_route_hook_call (int type, struct ospf6_route_req *request, struct ospf6_route_table *table){ struct linklist_node node; void (*func) (struct ospf6_route_req *); for (linklist_head (table->hook_list[type], &node); ! linklist_end (&node); linklist_next (&node)) { func = node.data; (*func) (request); }}voidospf6_route_hook_register (void (*add) (struct ospf6_route_req *), void (*change) (struct ospf6_route_req *), void (*remove) (struct ospf6_route_req *), struct ospf6_route_table *table){ linklist_add (add, table->hook_list[ADD]); linklist_add (change, table->hook_list[CHANGE]); linklist_add (remove, table->hook_list[REMOVE]);}voidospf6_route_hook_unregister (void (*add) (struct ospf6_route_req *), void (*change) (struct ospf6_route_req *), void (*remove) (struct ospf6_route_req *), struct ospf6_route_table *table)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -