2 * Copyright (C) 1999 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
25 dtype_name
[OSPF6_DEST_TYPE_MAX
] =
27 "Unknown", "Router", "Network", "Discard"
29 #define DTYPE_NAME(x) \
30 (0 < (x) && (x) < sizeof (dtype_name) ? \
31 dtype_name[(x)] : dtype_name[0])
34 dtype_abname
[OSPF6_DEST_TYPE_MAX
] =
38 #define DTYPE_ABNAME(x) \
39 (0 < (x) && (x) < sizeof (dtype_abname) ? \
40 dtype_abname[(x)] : dtype_abname[0])
43 ptype_name
[OSPF6_PATH_TYPE_MAX
] =
45 "Unknown", "Intra", "Inter", "External-1", "External-2",
46 "System", "Kernel", "Connect", "Static", "RIP", "RIPng",
47 "OSPF", "OSPF6", "BGP"
49 #define PTYPE_NAME(x) \
50 (0 < (x) && (x) < sizeof (ptype_name) ? \
51 ptype_name[(x)] : ptype_name[0])
54 ptype_abname
[OSPF6_PATH_TYPE_MAX
] =
56 "??", "Ia", "Ie", "E1", "E2",
57 "-X", "-K", "-C", "-S", "-R", "-R",
60 #define PTYPE_ABNAME(x) \
61 (0 < (x) && (x) < sizeof (ptype_abname) ? \
62 ptype_abname[(x)] : ptype_abname[0])
67 ospf6_path_cmp (void *arg1
, void *arg2
)
69 struct ospf6_path_node
*pn1
= arg1
;
70 struct ospf6_path_node
*pn2
= arg2
;
71 struct ospf6_path
*p1
= &pn1
->path
;
72 struct ospf6_path
*p2
= &pn2
->path
;
74 if (p1
->type
< p2
->type
)
76 else if (p1
->type
> p2
->type
)
79 if (p1
->type
== OSPF6_PATH_TYPE_EXTERNAL2
)
81 if (p1
->cost_e2
< p2
->cost_e2
)
83 else if (p1
->cost_e2
> p2
->cost_e2
)
87 if (p1
->cost
< p2
->cost
)
89 else if (p1
->cost
> p2
->cost
)
92 /* if from the same source, recognize as identical
93 (and treat this as update) */
94 if (! memcmp (&p1
->origin
, &p2
->origin
, sizeof (struct ls_origin
)) &&
95 p1
->area_id
== p2
->area_id
)
98 /* else, always prefer left */
103 ospf6_nexthop_cmp (void *arg1
, void *arg2
)
106 struct ospf6_nexthop_node
*nn1
= arg1
;
107 struct ospf6_nexthop_node
*nn2
= arg2
;
108 struct ospf6_nexthop
*n1
= &nn1
->nexthop
;
109 struct ospf6_nexthop
*n2
= &nn2
->nexthop
;
111 if (memcmp (n1
, n2
, sizeof (struct ospf6_nexthop
)) == 0)
114 for (i
= 0; i
< sizeof (struct in6_addr
); i
++)
116 if (nn1
->nexthop
.address
.s6_addr
[i
] != nn2
->nexthop
.address
.s6_addr
[i
])
118 ret
= nn1
->nexthop
.address
.s6_addr
[i
] -
119 nn2
->nexthop
.address
.s6_addr
[i
];
131 ospf6_route_request (struct ospf6_route_req
*request
,
132 struct ospf6_route_node
*rn
,
133 struct ospf6_path_node
*pn
,
134 struct ospf6_nexthop_node
*nn
)
137 assert (rn
&& pn
&& nn
);
139 request
->route_node
= rn
->route_node
;
141 linklist_head (rn
->path_list
, &request
->path_lnode
);
142 while (request
->path_lnode
.data
!= pn
)
144 //assert (! linklist_end (&request->path_lnode));
145 if (linklist_end (&request
->path_lnode
))
147 struct linklist_node node
;
149 zlog_info ("rn: %p, pn: %p", rn
, pn
);
150 zlog_info ("origin: %hx %x %x bits: %x opt: %x%x%x popt: %x area: %x type: %d cost %d %d %d",
151 pn
->path
.origin
.type
, pn
->path
.origin
.id
, pn
->path
.origin
.adv_router
, (int)pn
->path
.router_bits
, (int)pn
->path
.capability
[0],
152 (int)pn
->path
.capability
[1], (int)pn
->path
.capability
[2],
153 (int)pn
->path
.prefix_options
, pn
->path
.area_id
,
154 pn
->path
.type
, pn
->path
.metric_type
, pn
->path
.cost
, pn
->path
.cost_e2
);
156 for (linklist_head (rn
->path_list
, &node
); ! linklist_end (&node
);
157 linklist_next (&node
))
159 struct ospf6_path_node
*pn2
= node
.data
;
161 zlog_info (" %p: path data with pn(%p): %s", pn2
, pn
,
162 (memcmp (&pn
->path
, &pn2
->path
,
163 sizeof (struct ospf6_path
)) ?
164 "different" : "same"));
166 zlog_info (" origin: %hx %x %x bits: %x opt: %x%x%x popt: %x area: %x type: %d cost %d %d %d",
167 pn2
->path
.origin
.type
, pn2
->path
.origin
.id
, pn2
->path
.origin
.adv_router
, (int)pn2
->path
.router_bits
, (int)pn2
->path
.capability
[0],
168 (int)pn2
->path
.capability
[1], (int)pn2
->path
.capability
[2],
169 (int)pn2
->path
.prefix_options
, pn2
->path
.area_id
,
170 pn2
->path
.type
, pn2
->path
.metric_type
, pn2
->path
.cost
, pn2
->path
.cost_e2
);
172 if (! memcmp (&pn
->path
, &pn2
->path
, sizeof (struct ospf6_path
)))
175 request
->nexthop_lnode
.data
= pn2
;
180 linklist_next (&request
->path_lnode
);
182 assert (request
->path_lnode
.data
== pn
);
184 linklist_head (pn
->nexthop_list
, &request
->nexthop_lnode
);
185 while (request
->nexthop_lnode
.data
!= nn
)
187 assert (! linklist_end (&request
->nexthop_lnode
));
188 linklist_next (&request
->nexthop_lnode
);
190 assert (request
->nexthop_lnode
.data
== nn
);
192 request
->table
= rn
->table
;
193 request
->count
= rn
->count
;
194 request
->route_id
= rn
->route_id
;
195 memcpy (&request
->route
, &rn
->route
, sizeof (struct ospf6_route
));
196 memcpy (&request
->path
, &pn
->path
, sizeof (struct ospf6_path
));
197 memcpy (&request
->nexthop
, &nn
->nexthop
, sizeof (struct ospf6_nexthop
));
201 ospf6_route_count (struct ospf6_route_req
*request
)
203 return request
->count
;
207 ospf6_route_lookup (struct ospf6_route_req
*request
,
208 struct prefix
*prefix
,
209 struct ospf6_route_table
*table
)
211 struct route_node
*node
;
212 struct ospf6_route_node
*rn
= NULL
;
213 struct ospf6_path_node
*pn
= NULL
;
214 struct ospf6_nexthop_node
*nn
= NULL
;
215 struct linklist_node lnode
;
218 memset ((void *) request
, 0, sizeof (struct ospf6_route_req
));
220 node
= route_node_lookup (table
->table
, prefix
);
224 rn
= (struct ospf6_route_node
*) node
->info
;
230 linklist_head (rn
->path_list
, &lnode
);
232 linklist_head (pn
->nexthop_list
, &lnode
);
235 ospf6_route_request (request
, rn
, pn
, nn
);
242 ospf6_route_head (struct ospf6_route_req
*request
,
243 struct ospf6_route_table
*table
)
245 struct route_node
*node
;
246 struct ospf6_route_node
*rn
= NULL
;
247 struct ospf6_path_node
*pn
= NULL
;
248 struct ospf6_nexthop_node
*nn
= NULL
;
249 struct linklist_node lnode
;
252 memset (request
, 0, sizeof (struct ospf6_route_req
));
254 node
= route_top (table
->table
);
258 while (node
&& node
->info
== NULL
)
259 node
= route_next (node
);
263 rn
= (struct ospf6_route_node
*) node
->info
;
264 linklist_head (rn
->path_list
, &lnode
);
266 linklist_head (pn
->nexthop_list
, &lnode
);
269 ospf6_route_request (request
, rn
, pn
, nn
);
273 ospf6_route_end (struct ospf6_route_req
*request
)
275 if (request
->route_node
== NULL
&&
276 linklist_end (&request
->path_lnode
) &&
277 linklist_end (&request
->nexthop_lnode
) &&
278 request
->nexthop
.ifindex
== 0 &&
279 IN6_IS_ADDR_UNSPECIFIED (&request
->nexthop
.address
))
285 ospf6_route_next (struct ospf6_route_req
*request
)
287 struct ospf6_route_node
*route_node
= NULL
;
288 struct ospf6_path_node
*path_node
= NULL
;
289 struct ospf6_nexthop_node
*nexthop_node
= NULL
;
291 linklist_next (&request
->nexthop_lnode
);
292 if (linklist_end (&request
->nexthop_lnode
))
294 linklist_next (&request
->path_lnode
);
295 if (linklist_end (&request
->path_lnode
))
297 request
->route_node
= route_next (request
->route_node
);
298 while (request
->route_node
&& request
->route_node
->info
== NULL
)
299 request
->route_node
= route_next (request
->route_node
);
300 if (request
->route_node
)
302 route_node
= request
->route_node
->info
;
304 linklist_head (route_node
->path_list
, &request
->path_lnode
);
308 path_node
= request
->path_lnode
.data
;
310 linklist_head (path_node
->nexthop_list
, &request
->nexthop_lnode
);
313 nexthop_node
= request
->nexthop_lnode
.data
;
315 if (nexthop_node
== NULL
)
317 assert (path_node
== NULL
);
318 assert (route_node
== NULL
);
320 memset (&request
->route
, 0, sizeof (struct ospf6_route
));
321 memset (&request
->path
, 0, sizeof (struct ospf6_path
));
322 memset (&request
->nexthop
, 0, sizeof (struct ospf6_nexthop
));
326 path_node
= request
->path_lnode
.data
;
327 route_node
= request
->route_node
->info
;
329 assert (path_node
!= NULL
);
330 assert (route_node
!= NULL
);
332 memcpy (&request
->route
, &route_node
->route
,
333 sizeof (struct ospf6_route
));
334 memcpy (&request
->path
, &path_node
->path
,
335 sizeof (struct ospf6_path
));
336 memcpy (&request
->nexthop
, &nexthop_node
->nexthop
,
337 sizeof (struct ospf6_nexthop
));
346 ospf6_route_hook_call (int type
,
347 struct ospf6_route_req
*request
,
348 struct ospf6_route_table
*table
)
350 struct linklist_node node
;
351 void (*func
) (struct ospf6_route_req
*);
353 for (linklist_head (table
->hook_list
[type
], &node
);
354 ! linklist_end (&node
);
355 linklist_next (&node
))
363 ospf6_route_hook_register (void (*add
) (struct ospf6_route_req
*),
364 void (*change
) (struct ospf6_route_req
*),
365 void (*remove
) (struct ospf6_route_req
*),
366 struct ospf6_route_table
*table
)
368 linklist_add (add
, table
->hook_list
[ADD
]);
369 linklist_add (change
, table
->hook_list
[CHANGE
]);
370 linklist_add (remove
, table
->hook_list
[REMOVE
]);
374 ospf6_route_hook_unregister (void (*add
) (struct ospf6_route_req
*),
375 void (*change
) (struct ospf6_route_req
*),
376 void (*remove
) (struct ospf6_route_req
*),
377 struct ospf6_route_table
*table
)
379 linklist_remove (add
, table
->hook_list
[ADD
]);
380 linklist_remove (change
, table
->hook_list
[CHANGE
]);
381 linklist_remove (remove
, table
->hook_list
[REMOVE
]);
386 prefix_ls2str (struct prefix
*p
, char *str
, int size
)
388 char id
[BUFSIZ
], adv_router
[BUFSIZ
];
389 struct prefix_ls
*pl
= (struct prefix_ls
*) p
;
391 inet_ntop (AF_INET
, &pl
->id
, id
, BUFSIZ
);
392 inet_ntop (AF_INET
, &pl
->adv_router
, adv_router
, BUFSIZ
);
393 snprintf (str
, size
, "%s-%s", adv_router
, id
);
398 ospf6_route_log_request (char *what
, char *where
,
399 struct ospf6_route_req
*request
)
403 char type
[16], id
[16], adv
[16];
404 char address
[64], ifname
[IFNAMSIZ
];
406 if (request
->route
.prefix
.family
!= AF_INET
&&
407 request
->route
.prefix
.family
!= AF_INET6
)
408 prefix_ls2str (&request
->route
.prefix
, prefix
, sizeof (prefix
));
410 prefix2str (&request
->route
.prefix
, prefix
, sizeof (prefix
));
412 inet_ntop (AF_INET
, &request
->path
.area_id
, area_id
, sizeof (area_id
));
414 ospf6_lsa_type_string (request
->path
.origin
.type
, type
, sizeof (type
));
415 inet_ntop (AF_INET
, &request
->path
.origin
.id
, id
, sizeof (id
));
416 inet_ntop (AF_INET
, &request
->path
.origin
.adv_router
, adv
, sizeof (adv
));
418 inet_ntop (AF_INET6
, &request
->nexthop
.address
, address
, sizeof (address
));
420 zlog_info ("ROUTE: %s %s %s %s %s",
421 what
, DTYPE_ABNAME (request
->route
.type
), prefix
,
422 ((strcmp ("Add", what
) == 0) ? "to" : "from"), where
);
423 zlog_info ("ROUTE: Area: %s type: %s cost: %lu (E2: %lu)",
424 area_id
, PTYPE_NAME (request
->path
.type
),
425 (u_long
) request
->path
.cost
, (u_long
) request
->path
.cost_e2
);
426 zlog_info ("ROUTE: Origin: Type: %s", type
);
427 zlog_info ("ROUTE: Origin: Id: %s Adv: %s", id
, adv
);
428 zlog_info ("ROUTE: Nexthop: %s", address
);
429 zlog_info ("ROUTE: Nexthop: Ifindex: %u (%s)",
430 request
->nexthop
.ifindex
,
431 if_indextoname (request
->nexthop
.ifindex
, ifname
));
434 struct ospf6_path_node
*
435 ospf6_route_find_path_node (struct ospf6_route_req
*request
,
436 struct ospf6_route_node
*rn
)
438 struct linklist_node node
;
440 for (linklist_head (rn
->path_list
, &node
); ! linklist_end (&node
);
441 linklist_next (&node
))
443 struct ospf6_path_node
*path_node
= node
.data
;
445 if (path_node
->path
.area_id
== request
->path
.area_id
&&
446 path_node
->path
.origin
.type
== request
->path
.origin
.type
&&
447 path_node
->path
.origin
.id
== request
->path
.origin
.id
&&
448 path_node
->path
.origin
.adv_router
== request
->path
.origin
.adv_router
)
453 zlog_info ("req path : area: %#x origin: type: %d, id: %d, adv_router: %#x",
454 request
->path
.area_id
, request
->path
.origin
.type
,
455 request
->path
.origin
.id
, request
->path
.origin
.adv_router
);
456 for (linklist_head (rn
->path_list
, &node
); ! linklist_end (&node
);
457 linklist_next (&node
))
459 struct ospf6_path_node
*path_node
= node
.data
;
460 zlog_info (" path : area: %#x origin: type: %d, id: %d, adv_router: %#x",
461 path_node
->path
.area_id
, path_node
->path
.origin
.type
,
462 path_node
->path
.origin
.id
, path_node
->path
.origin
.adv_router
);
469 struct ospf6_nexthop_node
*
470 ospf6_route_find_nexthop_node (struct ospf6_route_req
*request
,
471 struct ospf6_path_node
*pn
)
473 struct linklist_node node
;
474 for (linklist_head (pn
->nexthop_list
, &node
); ! linklist_end (&node
);
475 linklist_next (&node
))
477 struct ospf6_nexthop_node
*nexthop_node
= node
.data
;
479 if (! memcmp (&nexthop_node
->nexthop
, &request
->nexthop
,
480 sizeof (struct ospf6_nexthop
)))
487 ospf6_route_add (struct ospf6_route_req
*request
,
488 struct ospf6_route_table
*table
)
490 struct ospf6_route_node
*rn
;
491 struct ospf6_path_node
*pn
;
492 struct ospf6_nexthop_node
*nn
;
493 struct route_node
*route_node
;
495 struct ospf6_route_req route
;
497 int route_change
= 0;
499 int nexthop_change
= 0;
501 /* find the requested route */
502 route_node
= route_node_get (table
->table
, &request
->route
.prefix
);
503 rn
= (struct ospf6_route_node
*) route_node
->info
;
507 if (memcmp (&rn
->route
, &request
->route
, sizeof (struct ospf6_route
)))
509 memcpy (&rn
->route
, &request
->route
, sizeof (struct ospf6_route
));
515 rn
= XCALLOC (MTYPE_OSPF6_ROUTE
, sizeof (struct ospf6_route_node
));
517 rn
->route_node
= route_node
;
518 rn
->route_id
= table
->route_id
++;
519 rn
->path_list
= linklist_create ();
520 rn
->path_list
->cmp
= ospf6_path_cmp
;
521 memcpy (&rn
->route
, &request
->route
, sizeof (struct ospf6_route
));
522 route_node
->info
= rn
;
525 /* find the same path */
526 pn
= ospf6_route_find_path_node (request
, rn
);
530 if (memcmp (&pn
->path
, &request
->path
, sizeof (struct ospf6_path
)))
532 memcpy (&pn
->path
, &request
->path
, sizeof (struct ospf6_path
));
538 pn
= XCALLOC (MTYPE_OSPF6_ROUTE
, sizeof (struct ospf6_path_node
));
540 pn
->nexthop_list
= linklist_create ();
541 pn
->nexthop_list
->cmp
= ospf6_nexthop_cmp
;
542 memcpy (&pn
->path
, &request
->path
, sizeof (struct ospf6_path
));
543 linklist_add (pn
, rn
->path_list
);
546 /* find the same nexthop */
547 nn
= ospf6_route_find_nexthop_node (request
, pn
);
551 if (memcmp (&nn
->nexthop
, &request
->nexthop
,
552 sizeof (struct ospf6_nexthop
)))
554 memcpy (&nn
->nexthop
, &request
->nexthop
,
555 sizeof (struct ospf6_nexthop
));
557 gettimeofday (&nn
->installed
, (struct timezone
*) NULL
);
562 nn
= XCALLOC (MTYPE_OSPF6_ROUTE
, sizeof (struct ospf6_nexthop_node
));
564 memcpy (&nn
->nexthop
, &request
->nexthop
, sizeof (struct ospf6_nexthop
));
565 linklist_add (nn
, pn
->nexthop_list
);
567 gettimeofday (&nn
->installed
, (struct timezone
*) NULL
);
570 SET_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_ADD
);
572 SET_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_ROUTE_CHANGE
);
574 SET_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_PATH_CHANGE
);
576 SET_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_CHANGE
);
581 if (IS_OSPF6_DUMP_ROUTE
)
583 ospf6_route_log_request ("Add", table
->name
, request
);
585 if (CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_ROUTE_CHANGE
))
586 zlog_info ("ROUTE: route attribute change");
587 if (CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_PATH_CHANGE
))
588 zlog_info ("ROUTE: path attribute change");
589 if (CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_CHANGE
))
590 zlog_info ("ROUTE: nexthop attribute change");
593 if (CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_ROUTE_CHANGE
) ||
594 CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_PATH_CHANGE
))
595 SET_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_CHANGE
);
598 ospf6_route_request (&route
, rn
, pn
, nn
);
599 if (CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_ADD
))
600 ospf6_route_hook_call (ADD
, &route
, table
);
601 else if (CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_CHANGE
))
602 ospf6_route_hook_call (CHANGE
, &route
, table
);
604 if (table
->hook_add
&&
605 CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_ADD
))
606 (*table
->hook_add
) (&route
);
607 else if (table
->hook_change
&&
608 CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_CHANGE
))
609 (*table
->hook_change
) (&route
);
616 ospf6_route_remove (struct ospf6_route_req
*request
,
617 struct ospf6_route_table
*table
)
619 struct ospf6_route_node
*rn
;
620 struct ospf6_path_node
*pn
;
621 struct ospf6_nexthop_node
*nn
;
622 struct route_node
*route_node
;
623 struct ospf6_route_req route
;
625 /* find the requested route */
626 route_node
= route_node_get (table
->table
, &request
->route
.prefix
);
627 rn
= (struct ospf6_route_node
*) route_node
->info
;
631 if (IS_OSPF6_DUMP_ROUTE
)
633 ospf6_route_log_request ("Remove", table
->name
, request
);
634 zlog_info ("ROUTE: Can't remove: No such route");
639 pn
= ospf6_route_find_path_node (request
, rn
);
642 if (IS_OSPF6_DUMP_ROUTE
)
644 ospf6_route_log_request ("Remove", table
->name
, request
);
645 zlog_info ("ROUTE: Can't remove: No such path");
650 if (pn
->path
.area_id
!= request
->path
.area_id
||
651 pn
->path
.origin
.type
!= request
->path
.origin
.type
||
652 pn
->path
.origin
.id
!= request
->path
.origin
.id
||
653 pn
->path
.origin
.adv_router
!= request
->path
.origin
.adv_router
)
655 if (IS_OSPF6_DUMP_ROUTE
)
657 ospf6_route_log_request ("Remove", table
->name
, request
);
658 zlog_info ("ROUTE: Can't remove: Path differ");
664 s
= (char *) &pn
->path
;
665 e
= s
+ sizeof (struct ospf6_path
);
666 for (c
= s
; c
< e
; c
++)
668 if ((c
- s
) % 4 == 0)
670 snprintf (p
, line
+ sizeof (line
) - p
, " ");
673 snprintf (p
, line
+ sizeof (line
) - p
, "%02x", *c
);
676 zlog_info ("ROUTE: path: %s", line
);
679 s
= (char *) &request
->path
;
680 e
= s
+ sizeof (struct ospf6_path
);
681 for (c
= s
; c
< e
; c
++)
683 if ((c
- s
) % 4 == 0)
685 snprintf (p
, line
+ sizeof (line
) - p
, " ");
688 snprintf (p
, line
+ sizeof (line
) - p
, "%02x", *c
);
691 zlog_info ("ROUTE: req : %s", line
);
698 nn
= ospf6_route_find_nexthop_node (request
, pn
);
701 if (IS_OSPF6_DUMP_ROUTE
)
703 ospf6_route_log_request ("Remove", table
->name
, request
);
704 zlog_info ("ROUTE: Can't remove: No such nexthop");
709 if (memcmp (&nn
->nexthop
, &request
->nexthop
, sizeof (struct ospf6_nexthop
)))
711 if (IS_OSPF6_DUMP_ROUTE
)
713 ospf6_route_log_request ("Remove", table
->name
, request
);
714 zlog_info ("ROUTE: Can't remove: Nexthop differ");
719 SET_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_REMOVE
);
724 if (IS_OSPF6_DUMP_ROUTE
)
725 ospf6_route_log_request ("Remove", table
->name
, request
);
727 ospf6_route_request (&route
, rn
, pn
, nn
);
728 ospf6_route_hook_call (REMOVE
, &route
, table
);
729 if (table
->hook_remove
)
730 (*table
->hook_remove
) (&route
);
736 linklist_remove (nn
, pn
->nexthop_list
);
738 XFREE (MTYPE_OSPF6_ROUTE
, nn
);
740 /* remove path if there's no nexthop for the path */
741 if (pn
->nexthop_list
->count
!= 0)
743 linklist_remove (pn
, rn
->path_list
);
744 linklist_delete (pn
->nexthop_list
);
745 XFREE (MTYPE_OSPF6_ROUTE
, pn
);
747 /* remove route if there's no path for the route */
748 if (rn
->path_list
->count
!= 0)
750 route_node
->info
= NULL
;
751 linklist_delete (rn
->path_list
);
752 XFREE (MTYPE_OSPF6_ROUTE
, rn
);
756 ospf6_route_remove_all (struct ospf6_route_table
*table
)
758 struct ospf6_route_req request
;
760 for (ospf6_route_head (&request
, table
); ! ospf6_route_end (&request
);
761 ospf6_route_next (&request
))
762 ospf6_route_remove (&request
, table
);
766 struct ospf6_route_table
*
767 ospf6_route_table_create (char *name
)
770 struct ospf6_route_table
*new;
772 new = XCALLOC (MTYPE_OSPF6_ROUTE
, sizeof (struct ospf6_route_table
));
773 snprintf (new->name
, sizeof (new->name
), "%s", name
);
775 new->table
= route_table_init ();
776 for (i
= 0; i
< 3; i
++)
777 new->hook_list
[i
] = linklist_create ();
783 ospf6_route_table_delete (struct ospf6_route_table
*table
)
787 ospf6_route_remove_all (table
);
788 route_table_finish (table
->table
);
789 for (i
= 0; i
< 3; i
++)
790 linklist_delete (table
->hook_list
[i
]);
791 XFREE (MTYPE_OSPF6_ROUTE
, table
);
795 ospf6_route_table_freeze (struct ospf6_route_table
*route_table
)
797 if (IS_OSPF6_DUMP_ROUTE
)
798 zlog_info ("ROUTE: Table freeze: %s", route_table
->name
);
799 assert (route_table
->freeze
== 0);
800 route_table
->freeze
= 1;
804 ospf6_route_table_thaw (struct ospf6_route_table
*route_table
)
806 struct route_node
*node
;
807 struct linklist_node pnode
;
808 struct linklist_node nnode
;
810 struct ospf6_route_node
*rn
;
811 struct ospf6_path_node
*pn
;
812 struct ospf6_nexthop_node
*nn
;
814 struct ospf6_route_req request
;
816 if (IS_OSPF6_DUMP_ROUTE
)
817 zlog_info ("ROUTE: Table thaw: %s", route_table
->name
);
819 assert (route_table
->freeze
== 1);
820 route_table
->freeze
= 0;
822 for (node
= route_top (route_table
->table
); node
;
823 node
= route_next (node
))
829 for (linklist_head (rn
->path_list
, &pnode
);
830 ! linklist_end (&pnode
);
831 linklist_next (&pnode
))
835 for (linklist_head (pn
->nexthop_list
, &nnode
);
836 ! linklist_end (&nnode
);
837 linklist_next (&nnode
))
841 /* if the add and remove flag set without change flag,
842 do nothing with this route */
843 if (! CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_CHANGE
) &&
844 CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_ADD
) &&
845 CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_REMOVE
))
851 memset (&request
, 0, sizeof (request
));
852 memcpy (&request
.route
, &rn
->route
, sizeof (rn
->route
));
853 memcpy (&request
.path
, &pn
->path
, sizeof (pn
->path
));
854 memcpy (&request
.nexthop
, &nn
->nexthop
, sizeof (nn
->nexthop
));
856 if (CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_ADD
) ||
857 CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_CHANGE
))
858 ospf6_route_add (&request
, route_table
);
859 else if (CHECK_FLAG (nn
->flag
, OSPF6_ROUTE_FLAG_REMOVE
))
860 ospf6_route_remove (&request
, route_table
);
870 ospf6_route_show (struct vty
*vty
, struct ospf6_route_node
*rn
)
872 struct linklist_node pnode
;
873 struct linklist_node nnode
;
874 struct ospf6_path_node
*pn
;
875 struct ospf6_nexthop_node
*nn
;
877 struct timeval now
, res
;
882 #define HEAD (pc == 0 && nc == 0)
884 char prefix
[64], nexthop
[64], ifname
[IFNAMSIZ
];
886 gettimeofday (&now
, (struct timezone
*) NULL
);
889 if (rn
->route
.prefix
.family
== AF_INET
||
890 rn
->route
.prefix
.family
== AF_INET6
)
891 prefix2str (&rn
->route
.prefix
, prefix
, sizeof (prefix
));
893 prefix_ls2str (&rn
->route
.prefix
, prefix
, sizeof (prefix
));
895 for (linklist_head (rn
->path_list
, &pnode
); ! linklist_end (&pnode
);
896 linklist_next (&pnode
))
900 for (linklist_head (pn
->nexthop_list
, &nnode
); ! linklist_end (&nnode
);
901 linklist_next (&nnode
))
905 inet_ntop (AF_INET6
, &nn
->nexthop
.address
, nexthop
,
907 if (! if_indextoname (nn
->nexthop
.ifindex
, ifname
))
908 snprintf (ifname
, sizeof (ifname
), "%d", nn
->nexthop
.ifindex
);
910 ospf6_timeval_sub (&now
, &nn
->installed
, &res
);
911 ospf6_timeval_string_summary (&res
, duration
, sizeof (duration
));
913 vty_out (vty
, "%c%1s %2s %-30s %-25s %6s %s%s",
915 DTYPE_ABNAME (rn
->route
.type
),
916 PTYPE_ABNAME (pn
->path
.type
),
917 prefix
, nexthop
, ifname
, duration
, VTY_NEWLINE
);
926 ospf6_route_show_detail (struct vty
*vty
, struct ospf6_route_node
*rn
)
928 struct linklist_node pnode
;
929 struct linklist_node nnode
;
930 struct ospf6_path_node
*pn
;
931 struct ospf6_nexthop_node
*nn
;
936 char prefix
[64], nexthop
[64], ifname
[IFNAMSIZ
];
937 char area_id
[16], type
[16], id
[16], adv
[16];
941 if (rn
->route
.prefix
.family
== AF_INET
||
942 rn
->route
.prefix
.family
== AF_INET6
)
943 prefix2str (&rn
->route
.prefix
, prefix
, sizeof (prefix
));
945 prefix_ls2str (&rn
->route
.prefix
, prefix
, sizeof (prefix
));
947 vty_out (vty
, "%s%s%s", VTY_NEWLINE
, prefix
, VTY_NEWLINE
);
948 vty_out (vty
, " Destination Type: %s%s",
949 DTYPE_NAME (rn
->route
.type
), VTY_NEWLINE
);
951 for (linklist_head (rn
->path_list
, &pnode
); ! linklist_end (&pnode
);
952 linklist_next (&pnode
))
956 inet_ntop (AF_INET
, &pn
->path
.area_id
, area_id
, sizeof (area_id
));
957 ospf6_lsa_type_string (pn
->path
.origin
.type
, type
, sizeof (type
));
958 inet_ntop (AF_INET
, &pn
->path
.origin
.id
, id
, sizeof (id
));
959 inet_ntop (AF_INET
, &pn
->path
.origin
.adv_router
, adv
, sizeof (adv
));
960 ospf6_options_string (pn
->path
.capability
, capa
, sizeof (capa
));
962 vty_out (vty
, " Path:%s", VTY_NEWLINE
);
963 vty_out (vty
, " Associated Area: %s%s", area_id
, VTY_NEWLINE
);
964 vty_out (vty
, " LS Origin: %s ID: %s Adv: %s%s",
965 type
, id
, adv
, VTY_NEWLINE
);
966 vty_out (vty
, " Path Type: %s%s",
967 PTYPE_NAME (pn
->path
.type
), VTY_NEWLINE
);
968 vty_out (vty
, " Metric Type: %d%s",
969 pn
->path
.metric_type
, VTY_NEWLINE
);
970 vty_out (vty
, " Cost: Type-1: %lu Type-2: %lu%s",
971 (u_long
) pn
->path
.cost
, (u_long
) pn
->path
.cost_e2
,
973 vty_out (vty
, " Router Bits: %s|%s|%s|%s%s",
974 (CHECK_FLAG (pn
->path
.router_bits
, OSPF6_ROUTER_LSA_BIT_W
) ?
976 (CHECK_FLAG (pn
->path
.router_bits
, OSPF6_ROUTER_LSA_BIT_V
) ?
978 (CHECK_FLAG (pn
->path
.router_bits
, OSPF6_ROUTER_LSA_BIT_E
) ?
980 (CHECK_FLAG (pn
->path
.router_bits
, OSPF6_ROUTER_LSA_BIT_B
) ?
981 "B" : "-"), VTY_NEWLINE
);
982 vty_out (vty
, " Optional Capabilities: %s%s", capa
, VTY_NEWLINE
);
983 vty_out (vty
, " Prefix Options: %s%s", "xxx", VTY_NEWLINE
);
984 vty_out (vty
, " Next Hops:%s", VTY_NEWLINE
);
986 for (linklist_head (pn
->nexthop_list
, &nnode
); ! linklist_end (&nnode
);
987 linklist_next (&nnode
))
991 inet_ntop (AF_INET6
, &nn
->nexthop
.address
, nexthop
,
993 if (! if_indextoname (nn
->nexthop
.ifindex
, ifname
))
994 snprintf (ifname
, sizeof (ifname
), "%d", nn
->nexthop
.ifindex
);
996 vty_out (vty
, " %c%s%%%s%s",
997 (HEAD
? '*' : ' '), nexthop
, ifname
, VTY_NEWLINE
);
1003 vty_out (vty
, "%s", VTY_NEWLINE
);
1007 ospf6_route_table_show (struct vty
*vty
, int argc
, char **argv
,
1008 struct ospf6_route_table
*table
)
1011 unsigned long ret_ul
;
1013 struct prefix prefix
;
1018 struct prefix_ipv6
*p6
= (struct prefix_ipv6
*) &prefix
;
1019 struct prefix_ls
*pl
= (struct prefix_ls
*) &prefix
;
1020 struct route_node
*node
;
1022 u_int route_count
= 0;
1023 u_int path_count
= 0;
1024 u_int route_redundant
= 0;
1026 memset (&prefix
, 0, sizeof (struct prefix
));
1028 for (i
= 0; i
< argc
; i
++)
1030 if (! strcmp (argv
[i
], "detail"))
1036 if (! arg_ipv6
&& ! arg_ipv4
&& ! arg_digit
)
1039 if ((ret
= inet_pton (AF_INET6
, argv
[i
], &p6
->prefix
)) == 1)
1041 p6
->family
= AF_INET6
;
1042 p6
->prefixlen
= 128;
1046 else if ((ret
= inet_pton (AF_INET
, argv
[i
], &pl
->adv_router
)) == 1)
1048 pl
->family
= AF_UNSPEC
;
1049 pl
->prefixlen
= 64; /* xxx */
1055 ret_ul
= strtoul (argv
[i
], &endptr
, 10);
1056 if (*endptr
== '\0')
1058 pl
->adv_router
.s_addr
= htonl (ret_ul
);
1059 pl
->family
= AF_UNSPEC
;
1060 pl
->prefixlen
= 64; /* xxx */
1066 vty_out (vty
, "Malformed argument: %s%s",
1067 argv
[i
], VTY_NEWLINE
);
1073 if (arg_ipv4
|| arg_digit
)
1075 if ((ret
= inet_pton (AF_INET
, argv
[i
], &pl
->id
)) == 1)
1081 ret_ul
= strtoul (argv
[i
], &endptr
, 10);
1082 if (*endptr
== '\0')
1084 pl
->id
.s_addr
= htonl (ret_ul
);
1089 vty_out (vty
, "Malformed argument: %s%s",
1090 argv
[i
], VTY_NEWLINE
);
1097 if (arg_ipv4
|| arg_ipv6
|| arg_digit
)
1099 node
= route_node_match (table
->table
, &prefix
);
1100 if (node
&& node
->info
)
1101 ospf6_route_show_detail (vty
, node
->info
);
1107 vty_out (vty
, "%s%c%1s %2s %-30s %-25s %6s%s", VTY_NEWLINE
,
1108 ' ', " ", " ", "Destination", "Gateway", "I/F", VTY_NEWLINE
);
1109 vty_out (vty
, "---------------------------%s", VTY_NEWLINE
);
1112 for (node
= route_top (table
->table
); node
; node
= route_next (node
))
1114 struct ospf6_route_node
*route
= node
->info
;
1120 ospf6_route_show_detail (vty
, route
);
1122 ospf6_route_show (vty
, route
);
1125 path_count
+= route
->path_list
->count
;
1126 if (route
->path_list
->count
> 1)
1130 vty_out (vty
, "===========%s", VTY_NEWLINE
);
1131 vty_out (vty
, "Route: %d Path: %d Redundant: %d%s",
1132 route_count
, path_count
, route_redundant
, VTY_NEWLINE
);