diff options
Diffstat (limited to 'ospf6d/ospf6_lsdb.c')
-rw-r--r-- | ospf6d/ospf6_lsdb.c | 723 |
1 files changed, 723 insertions, 0 deletions
diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c new file mode 100644 index 00000000..ad53eb4f --- /dev/null +++ b/ospf6d/ospf6_lsdb.c @@ -0,0 +1,723 @@ +/* + * 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 <zebra.h> + +#include "memory.h" +#include "log.h" +#include "command.h" +#include "if.h" + +#include "ospf6_dump.h" +#include "ospf6_lsdb.h" + +#include "ospf6_interface.h" +#include "ospf6_area.h" +#include "ospf6_top.h" + +#define OSPF6_LSDB_MATCH_TYPE 0x01 +#define OSPF6_LSDB_MATCH_ID 0x02 +#define OSPF6_LSDB_MATCH_ADV_ROUTER 0x04 +#define OSPF6_LSDB_SHOW_DUMP 0x08 +#define OSPF6_LSDB_SHOW_DETAIL 0x10 + +struct ospf6_lsdb_hook_t hooks[0x2000]; +struct ospf6_lsdb_hook_t *ospf6_lsdb_hook = hooks; + +struct ospf6_lsdb * +ospf6_lsdb_create () +{ + struct ospf6_lsdb *lsdb; + + lsdb = XCALLOC (MTYPE_OSPF6_LSDB, sizeof (struct ospf6_lsdb)); + if (lsdb == NULL) + { + zlog_warn ("Can't malloc lsdb"); + return NULL; + } + memset (lsdb, 0, sizeof (struct ospf6_lsdb)); + + lsdb->table = route_table_init (); + return lsdb; +} + +void +ospf6_lsdb_delete (struct ospf6_lsdb *lsdb) +{ + ospf6_lsdb_remove_all (lsdb); + route_table_finish (lsdb->table); + XFREE (MTYPE_OSPF6_LSDB, lsdb); +} + +static void +ospf6_lsdb_set_key (struct prefix_ipv6 *key, int flag, + u_int16_t type, u_int32_t id, u_int32_t adv_router) +{ + int len = 0; + memset (key, 0, sizeof (struct prefix_ipv6)); + + if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_TYPE)) + { + len += 2; + if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_ADV_ROUTER)) + { + len += 4; + if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_ID)) + len += 4; + } + } + + if (len > 0) + memcpy ((char *)&key->prefix, &type, 2); + if (len > 2) + memcpy ((char *)&key->prefix + 2, &adv_router, 4); + if (len > 6) + memcpy ((char *)&key->prefix + 6, &id, 4); + + key->family = AF_INET6; + key->prefixlen = len * 8; +} + +void +ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb) +{ + int flag; + struct prefix_ipv6 key; + struct route_node *rn; + struct ospf6_lsa *old = NULL; + + flag = OSPF6_LSDB_MATCH_TYPE | OSPF6_LSDB_MATCH_ID | + OSPF6_LSDB_MATCH_ADV_ROUTER; + ospf6_lsdb_set_key (&key, flag, lsa->header->type, lsa->header->id, + lsa->header->adv_router); + + rn = route_node_get (lsdb->table, (struct prefix *) &key); + if (rn->info) + old = rn->info; + rn->info = lsa; + ospf6_lsa_lock (lsa); + + if (old) + ospf6_lsa_unlock (old); + else + lsdb->count++; +} + +void +ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb) +{ + int flag; + struct prefix_ipv6 key; + struct route_node *rn; + struct ospf6_lsa *old; + + flag = OSPF6_LSDB_MATCH_TYPE | OSPF6_LSDB_MATCH_ID | + OSPF6_LSDB_MATCH_ADV_ROUTER; + ospf6_lsdb_set_key (&key, flag, lsa->header->type, lsa->header->id, + lsa->header->adv_router); + + rn = route_node_lookup (lsdb->table, (struct prefix *) &key); + if (! rn || ! rn->info) + { + zlog_warn ("LSDB: Can't remove: no such LSA: %s", lsa->str); + return; + } + + old = rn->info; + if (old != lsa) + { + zlog_warn ("LSDB: Can't remove: different instance: %s (%p <-> %p) %s", + lsa->str, lsa, old, old->str); + return; + } + + rn->info = NULL; + ospf6_lsa_unlock (old); + lsdb->count--; +} + +static void +ospf6_lsdb_lookup_node (struct ospf6_lsdb_node *node, + u_int16_t type, u_int32_t id, u_int32_t adv_router, + struct ospf6_lsdb *lsdb) +{ + int flag; + struct route_node *rn; + + memset (node, 0, sizeof (struct ospf6_lsdb_node)); + + flag = OSPF6_LSDB_MATCH_TYPE | OSPF6_LSDB_MATCH_ID | + OSPF6_LSDB_MATCH_ADV_ROUTER; + ospf6_lsdb_set_key (&node->key, flag, type, id, adv_router); + + rn = route_node_lookup (lsdb->table, (struct prefix *) &node->key); + if (! rn || ! rn->info) + return; + + node->node = rn; + node->next = route_next (rn); + node->lsa = rn->info; + if (node->next != NULL) + route_unlock_node (node->next); +} + +struct ospf6_lsa * +ospf6_lsdb_lookup_lsdb (u_int16_t type, u_int32_t id, u_int32_t adv_router, + struct ospf6_lsdb *lsdb) +{ + struct ospf6_lsdb_node node; + ospf6_lsdb_lookup_node (&node, type, id, adv_router, lsdb); + return node.lsa; +} + +/* Iteration function */ +void +ospf6_lsdb_head (struct ospf6_lsdb_node *node, struct ospf6_lsdb *lsdb) +{ + struct route_node *rn; + + memset (node, 0, sizeof (struct ospf6_lsdb_node)); + + rn = route_top (lsdb->table); + if (rn == NULL) + return; + + while (rn && rn->info == NULL) + rn = route_next (rn); + + if (rn && rn->info) + { + node->node = rn; + node->next = route_next (rn); + node->lsa = rn->info; + if (node->next != NULL) + route_unlock_node (node->next); + } +} + +void +ospf6_lsdb_type (struct ospf6_lsdb_node *node, u_int16_t type, + struct ospf6_lsdb *lsdb) +{ + int flag; + struct route_node *rn; + + memset (node, 0, sizeof (struct ospf6_lsdb_node)); + + flag = OSPF6_LSDB_MATCH_TYPE; + ospf6_lsdb_set_key (&node->key, flag, type, 0, 0); + + /* get the closest radix node */ + rn = route_node_get (lsdb->table, (struct prefix *) &node->key); + + /* skip to the real existing lsdb entry */ + while (rn && rn->info == NULL && rn->p.prefixlen >= node->key.prefixlen && + prefix_match ((struct prefix *) &node->key, &rn->p)) + rn = route_next (rn); + + if (rn && rn->info) + { + node->node = rn; + node->next = route_next (rn); + node->lsa = rn->info; + if (node->next != NULL) + route_unlock_node (node->next); + } +} + +void +ospf6_lsdb_type_router (struct ospf6_lsdb_node *node, + u_int16_t type, u_int32_t adv_router, + struct ospf6_lsdb *lsdb) +{ + int flag; + struct route_node *rn; + + memset (node, 0, sizeof (struct ospf6_lsdb_node)); + + flag = OSPF6_LSDB_MATCH_TYPE | OSPF6_LSDB_MATCH_ADV_ROUTER; + ospf6_lsdb_set_key (&node->key, flag, type, 0, adv_router); + + /* get the closest radix node */ + rn = route_node_get (lsdb->table, (struct prefix *) &node->key); + + /* skip to the real existing lsdb entry */ + while (rn && rn->info == NULL && rn->p.prefixlen >= node->key.prefixlen && + prefix_match ((struct prefix *) &node->key, &rn->p)) + rn = route_next (rn); + + if (rn && rn->info) + { + node->node = rn; + node->next = route_next (rn); + node->lsa = rn->info; + if (node->next != NULL) + route_unlock_node (node->next); + } +} + +void +ospf6_lsdb_next (struct ospf6_lsdb_node *node) +{ + struct route_node *rn; + + route_lock_node (node->node); + rn = route_next (node->node); + + /* skip to the real existing lsdb entry */ + while (rn && rn->info == NULL && rn->p.prefixlen >= node->key.prefixlen && + prefix_match ((struct prefix *) &node->key, &rn->p)) + rn = route_next (rn); + + if (rn && rn->info && rn->p.prefixlen >= node->key.prefixlen && + prefix_match ((struct prefix *) &node->key, &rn->p)) + { + node->node = rn; + node->next = route_next (rn); + node->lsa = rn->info; + if (node->next != NULL) + route_unlock_node (node->next); + } + else + { + node->node = NULL; + node->next = NULL; + node->lsa = NULL; + } +} + +struct ospf6_lsa * +ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router, + void *scope) +{ + struct ospf6_interface *o6i; + struct ospf6_area *o6a; + listnode i, j; + + if (scope == (void *) ospf6) + return ospf6_lsdb_lookup_lsdb (type, id, adv_router, ospf6->lsdb); + + for (i = listhead (ospf6->area_list); i; nextnode (i)) + { + o6a = getdata (i); + + if (scope == (void *) o6a) + return ospf6_lsdb_lookup_lsdb (type, id, adv_router, o6a->lsdb); + + for (j = listhead (o6a->if_list); j; nextnode (j)) + { + o6i = getdata (j); + + if (scope == (void *) o6i) + return ospf6_lsdb_lookup_lsdb (type, id, adv_router, o6i->lsdb); + } + } + + zlog_warn ("LSDB: Can't lookup: unknown scope, type %#hx", ntohs (type)); + return NULL; +} + +void +ospf6_lsdb_install (struct ospf6_lsa *new) +{ + struct ospf6_lsdb *lsdb; + struct ospf6_lsa *old; + int need_hook = 0; + void (*hook) (struct ospf6_lsa *, struct ospf6_lsa *); + + struct ospf6 *as = NULL; + struct ospf6_area *area = NULL; + struct ospf6_interface *linklocal = NULL; + hook = NULL; + + switch (ntohs (new->header->type) & OSPF6_LSTYPE_SCOPE_MASK) + { + case OSPF6_LSA_SCOPE_LINKLOCAL: + linklocal = (struct ospf6_interface *) new->scope; + lsdb = linklocal->lsdb; + break; + case OSPF6_LSA_SCOPE_AREA: + area = (struct ospf6_area *) new->scope; + lsdb = area->lsdb; + break; + case OSPF6_LSA_SCOPE_AS: + as = (struct ospf6 *) new->scope; + lsdb = as->lsdb; + break; + default: + zlog_warn ("LSDB: Can't install: scope unknown: %s", new->str); + return; + } + + /* whether schedule calculation or not */ + old = ospf6_lsdb_lookup_lsdb (new->header->type, new->header->id, + new->header->adv_router, lsdb); + + if (! old || ospf6_lsa_differ (old, new)) + need_hook++; + + /* log */ + if (IS_OSPF6_DUMP_LSDB) + zlog_info ("LSDB: Install: %s %s", new->str, + ((IS_LSA_MAXAGE (new)) ? "(MaxAge)" : "")); + + if (old) + ospf6_lsa_lock (old); + + ospf6_lsdb_add (new, lsdb); + gettimeofday (&new->installed, NULL); + + hook = ospf6_lsdb_hook[ntohs (new->header->type) & + OSPF6_LSTYPE_CODE_MASK].hook; + if (need_hook && hook) + (*hook) (old, new); + + /* old LSA should be freed here */ + if (old) + ospf6_lsa_unlock (old); +} + +void +ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb) +{ + struct ospf6_lsdb_node node; + for (ospf6_lsdb_head (&node, lsdb); ! ospf6_lsdb_is_end (&node); + ospf6_lsdb_next (&node)) + ospf6_lsdb_remove (node.lsa, lsdb); +} + +void +ospf6_lsdb_remove_maxage (struct ospf6_lsdb *lsdb) +{ + struct ospf6_lsdb_node node; + struct ospf6_lsa *lsa; + + for (ospf6_lsdb_head (&node, lsdb); ! ospf6_lsdb_is_end (&node); + ospf6_lsdb_next (&node)) + { + lsa = node.lsa; + + /* contiue if it's not MaxAge */ + if (! IS_LSA_MAXAGE (lsa)) + continue; + + /* continue if it's referenced by some retrans-lists */ + if (lsa->lock != 1) + continue; + + if (IS_OSPF6_DUMP_LSDB) + zlog_info ("Remove MaxAge LSA: %s", lsa->str); + + ospf6_lsdb_remove (lsa, lsdb); + } +} + + + +/* vty functions */ + +static int +ospf6_lsdb_match (int flag, u_int16_t type, u_int32_t id, + u_int32_t adv_router, struct ospf6_lsa *lsa) +{ + if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_TYPE) && + lsa->header->type != type) + return 0; + + if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_ID) && + lsa->header->id != id) + return 0; + + if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_ADV_ROUTER) && + lsa->header->adv_router != adv_router) + return 0; + + return 1; +} + +int +show_ipv6_ospf6_lsdb (struct vty *vty, int argc, char **argv, + struct ospf6_lsdb *lsdb) +{ + u_int flag; + u_int16_t type = 0; + u_int32_t id, adv_router; + int ret; + struct ospf6_lsdb_node node; + char invalid[32], *invalidp; + int l_argc = argc; + char **l_argv = argv; + + flag = 0; + memset (invalid, 0, sizeof (invalid)); + invalidp = invalid; + + /* chop tail if the words is 'dump' or 'summary' */ + if (l_argc > 0 && ! strcmp (l_argv[l_argc - 1], "dump")) + { + SET_FLAG (flag, OSPF6_LSDB_SHOW_DUMP); + l_argc --; + } + else if (l_argc > 0 && ! strcmp (l_argv[l_argc - 1], "detail")) + { + SET_FLAG (flag, OSPF6_LSDB_SHOW_DETAIL); + l_argc --; + } + + if (l_argc > 0) + { + SET_FLAG (flag, OSPF6_LSDB_MATCH_TYPE); + if (! strncmp (l_argv[0], "r", 1)) + type = htons (OSPF6_LSA_TYPE_ROUTER); + if (! strncmp (l_argv[0], "n", 1)) + type = htons (OSPF6_LSA_TYPE_NETWORK); + if (! strncmp (l_argv[0], "a", 1)) + type = htons (OSPF6_LSA_TYPE_AS_EXTERNAL); + if (! strcmp (l_argv[0], "intra-prefix")) + type = htons (OSPF6_LSA_TYPE_INTRA_PREFIX); + if (! strcmp (l_argv[0], "inter-router")) + type = htons (OSPF6_LSA_TYPE_INTER_ROUTER); + if (! strcmp (l_argv[0], "inter-prefix")) + type = htons (OSPF6_LSA_TYPE_INTER_PREFIX); + if (! strncmp (l_argv[0], "l", 1)) + type = htons (OSPF6_LSA_TYPE_LINK); + if (! strncmp (l_argv[0], "0x", 2) && strlen (l_argv[0]) == 6) + type = htons ((short) strtol (l_argv[0], (char **)NULL, 16)); + if (! strncmp (l_argv[0], "*", 1)) + UNSET_FLAG (flag, OSPF6_LSDB_MATCH_TYPE); + } + + if (l_argc > 1) + { + SET_FLAG (flag, OSPF6_LSDB_MATCH_ID); + if (! strncmp (l_argv[1], "*", 1)) + UNSET_FLAG (flag, OSPF6_LSDB_MATCH_ID); + else + { + ret = inet_pton (AF_INET, l_argv[1], &id); + if (ret != 1) + { + id = htonl (strtoul (l_argv[1], &invalidp, 10)); + if (invalid[0] != '\0') + { + vty_out (vty, "Link State ID is not parsable: %s%s", + l_argv[1], VTY_NEWLINE); + return CMD_SUCCESS; + } + } + } + } + + if (l_argc > 2) + { + SET_FLAG (flag, OSPF6_LSDB_MATCH_ADV_ROUTER); + if (! strncmp (l_argv[2], "*", 1)) + UNSET_FLAG (flag, OSPF6_LSDB_MATCH_ADV_ROUTER); + else + { + ret = inet_pton (AF_INET, l_argv[2], &adv_router); + if (ret != 1) + { + adv_router = htonl (strtoul (l_argv[2], &invalidp, 10)); + if (invalid[0] != '\0') + { + vty_out (vty, "Advertising Router is not parsable: %s%s", + l_argv[2], VTY_NEWLINE); + return CMD_SUCCESS; + } + } + } + } + + if (! CHECK_FLAG (flag, OSPF6_LSDB_SHOW_DETAIL)) + ospf6_lsa_show_summary_header (vty); + + for (ospf6_lsdb_head (&node, lsdb); ! ospf6_lsdb_is_end (&node); + ospf6_lsdb_next (&node)) + { + if (! ospf6_lsdb_match (flag, type, id, adv_router, node.lsa)) + continue; + + if (CHECK_FLAG (flag, OSPF6_LSDB_SHOW_DUMP)) + ospf6_lsa_show_dump (vty, node.lsa); + else if (CHECK_FLAG (flag, OSPF6_LSDB_SHOW_DETAIL)) + ospf6_lsa_show (vty, node.lsa); + else + ospf6_lsa_show_summary (vty, node.lsa); + } + + return CMD_SUCCESS; +} + +DEFUN (show_ipv6_ospf6_database, + show_ipv6_ospf6_database_cmd, + "show ipv6 ospf6 database", + SHOW_STR + IP6_STR + OSPF6_STR + "LSA Database\n" + ) +{ + struct ospf6_area *o6a; + struct ospf6_interface *o6i; + listnode i, j; + + /* call show function for each of LSAs in the LSDBs */ + + for (i = listhead (ospf6->area_list); i; nextnode (i)) + { + o6a = (struct ospf6_area *) getdata (i); + + /* LinkLocal LSDBs */ + for (j = listhead (o6a->if_list); j; nextnode (j)) + { + o6i = (struct ospf6_interface *) getdata (j); + + vty_out (vty, "%s", VTY_NEWLINE); + vty_out (vty, " Interface %s (Area: %s):%s", + o6i->interface->name, o6a->str, VTY_NEWLINE); + vty_out (vty, "%s", VTY_NEWLINE); + show_ipv6_ospf6_lsdb (vty, argc, argv, o6i->lsdb); + } + + /* Area LSDBs */ + vty_out (vty, "%s", VTY_NEWLINE); + vty_out (vty, " Area %s:%s", o6a->str, VTY_NEWLINE); + vty_out (vty, "%s", VTY_NEWLINE); + show_ipv6_ospf6_lsdb (vty, argc, argv, o6a->lsdb); + } + + /* AS LSDBs */ + vty_out (vty, "%s", VTY_NEWLINE); + vty_out (vty, " AS:%s", VTY_NEWLINE); + vty_out (vty, "%s", VTY_NEWLINE); + show_ipv6_ospf6_lsdb (vty, argc, argv, ospf6->lsdb); + + return CMD_SUCCESS; +} + +ALIAS (show_ipv6_ospf6_database, + show_ipv6_ospf6_database_type_cmd, + "show ipv6 ospf6 database (router|network|as-external|intra-prefix|inter-prefix|inter-router|link|*|HEX|dump|detail)", + SHOW_STR + IP6_STR + OSPF6_STR + "LSA Database\n" + "Router-LSA\n" + "Network-LSA\n" + "AS-External-LSA\n" + "Intra-Area-Prefix-LSA\n" + "Inter-Area-Router-LSA\n" + "Inter-Area-Prefix-LSA\n" + "Link-LSA\n" + "All LS Type\n" + "Specify LS Type by Hex\n" + "Dump raw LSA data in Hex\n" + "show detail of LSAs\n" + ) + +ALIAS (show_ipv6_ospf6_database, + show_ipv6_ospf6_database_type_id_cmd, + "show ipv6 ospf6 database (router|network|as-external|intra-prefix|inter-prefix|inter-router|link|*|HEX) (A.B.C.D|*|dump|detail)", + SHOW_STR + IP6_STR + OSPF6_STR + "LSA Database\n" + "Router-LSA\n" + "Network-LSA\n" + "AS-External-LSA\n" + "Intra-Area-Prefix-LSA\n" + "Inter-Area-Router-LSA\n" + "Inter-Area-Prefix-LSA\n" + "Link-LSA\n" + "All LS Type\n" + "Specify LS Type by Hex\n" + "Link State ID\n" + "All Link State ID\n" + "Dump raw LSA data in Hex\n" + "show detail of LSAs\n" + ) + +ALIAS (show_ipv6_ospf6_database, + show_ipv6_ospf6_database_type_id_adv_router_cmd, + "show ipv6 ospf6 database (router|network|as-external|intra-prefix|inter-prefix|inter-router|link|*|HEX) (A.B.C.D|*) (A.B.C.D|*|dump|detail)", + SHOW_STR + IP6_STR + OSPF6_STR + "LSA Database\n" + "Router-LSA\n" + "Network-LSA\n" + "AS-External-LSA\n" + "Intra-Area-Prefix-LSA\n" + "Inter-Area-Router-LSA\n" + "Inter-Area-Prefix-LSA\n" + "Link-LSA\n" + "All LS Type\n" + "Specify LS Type by Hex\n" + "Link State ID\n" + "All Link State ID\n" + "Advertising Router\n" + "All Advertising Router\n" + "Dump raw LSA data in Hex\n" + "show detail of LSAs\n" + ) + +ALIAS (show_ipv6_ospf6_database, + show_ipv6_ospf6_database_type_id_adv_router_dump_cmd, + "show ipv6 ospf6 database (router|network|as-external|intra-prefix|inter-prefix|inter-router|link|*|HEX) (A.B.C.D|*) (A.B.C.D|*) (dump|detail|)", + SHOW_STR + IP6_STR + OSPF6_STR + "LSA Database\n" + "Router-LSA\n" + "Network-LSA\n" + "AS-External-LSA\n" + "Intra-Area-Prefix-LSA\n" + "Inter-Area-Router-LSA\n" + "Inter-Area-Prefix-LSA\n" + "Link-LSA\n" + "All LS Type\n" + "Specify LS Type by Hex\n" + "Link State ID\n" + "All Link State ID\n" + "Advertising Router\n" + "All Advertising Router\n" + "Dump raw LSA data in Hex\n" + "show detail of LSAs\n" + ) + +void +ospf6_lsdb_init () +{ + install_element (VIEW_NODE, &show_ipv6_ospf6_database_cmd); + install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_cmd); + install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_cmd); + install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_adv_router_cmd); + install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_adv_router_dump_cmd); + + install_element (ENABLE_NODE, &show_ipv6_ospf6_database_cmd); + install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_cmd); + install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_cmd); + install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_adv_router_cmd); + install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_adv_router_dump_cmd); +} + + |