]> git.proxmox.com Git - mirror_frr.git/blobdiff - ospf6d/ospf6_route.c
Merge pull request #1973 from donaldsharp/static_nh_vrf
[mirror_frr.git] / ospf6d / ospf6_route.c
index 88dd7b2187ef55e8d22f6ff6258f711b6abb2f48..8be00d9b41610fa2769fe98993580cb32b32d463 100644 (file)
  * 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.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <zebra.h>
@@ -43,7 +42,7 @@ unsigned char conf_debug_ospf6_route = 0;
 
 static char *ospf6_route_table_name(struct ospf6_route_table *table)
 {
-       static char name[32];
+       static char name[64];
        switch (table->scope_type) {
        case OSPF6_SCOPE_TYPE_GLOBAL: {
                switch (table->table_type) {
@@ -123,7 +122,7 @@ static char *ospf6_route_table_name(struct ospf6_route_table *table)
        return name;
 }
 
-void ospf6_linkstate_prefix(u_int32_t adv_router, u_int32_t id,
+void ospf6_linkstate_prefix(uint32_t adv_router, uint32_t id,
                            struct prefix *prefix)
 {
        memset(prefix, 0, sizeof(struct prefix));
@@ -135,7 +134,7 @@ void ospf6_linkstate_prefix(u_int32_t adv_router, u_int32_t id,
 
 void ospf6_linkstate_prefix2str(struct prefix *prefix, char *buf, int size)
 {
-       u_int32_t adv_router, id;
+       uint32_t adv_router, id;
        char adv_router_str[16], id_str[16];
        memcpy(&adv_router, &prefix->u.prefix6.s6_addr[0], 4);
        memcpy(&id, &prefix->u.prefix6.s6_addr[4], 4);
@@ -179,17 +178,6 @@ void ospf6_nexthop_delete(struct ospf6_nexthop *nh)
                XFREE(MTYPE_OSPF6_NEXTHOP, nh);
 }
 
-void ospf6_free_nexthops(struct list *nh_list)
-{
-       struct ospf6_nexthop *nh;
-       struct listnode *node, *nnode;
-
-       if (nh_list) {
-               for (ALL_LIST_ELEMENTS(nh_list, node, nnode, nh))
-                       ospf6_nexthop_delete(nh);
-       }
-}
-
 void ospf6_clear_nexthops(struct list *nh_list)
 {
        struct listnode *node;
@@ -227,7 +215,7 @@ void ospf6_copy_nexthops(struct list *dst, struct list *src)
                        if (ospf6_nexthop_is_set(nh)) {
                                nh_new = ospf6_nexthop_create();
                                ospf6_nexthop_copy(nh_new, nh);
-                               listnode_add(dst, nh_new);
+                               listnode_add_sort(dst, nh_new);
                        }
                }
        }
@@ -243,7 +231,7 @@ void ospf6_merge_nexthops(struct list *dst, struct list *src)
                        if (!ospf6_route_find_nexthop(dst, nh)) {
                                nh_new = ospf6_nexthop_create();
                                ospf6_nexthop_copy(nh_new, nh);
-                               listnode_add(dst, nh_new);
+                               listnode_add_sort(dst, nh_new);
                        }
                }
        }
@@ -253,18 +241,25 @@ int ospf6_route_cmp_nexthops(struct ospf6_route *a, struct ospf6_route *b)
 {
        struct listnode *anode, *bnode;
        struct ospf6_nexthop *anh, *bnh;
+       bool identical = false;
 
        if (a && b) {
                if (listcount(a->nh_list) == listcount(b->nh_list)) {
                        for (ALL_LIST_ELEMENTS_RO(a->nh_list, anode, anh)) {
+                               identical = false;
                                for (ALL_LIST_ELEMENTS_RO(b->nh_list, bnode,
-                                                         bnh))
-                                       if (!ospf6_nexthop_is_same(anh, bnh))
-                                               return (1);
+                                                         bnh)) {
+                                       if (ospf6_nexthop_is_same(anh, bnh))
+                                               identical = true;
+                               }
+                               /* Currnet List A element not found List B
+                                * Non-Identical lists return */
+                               if (identical == false)
+                                       return 1;
                        }
-                       return (0);
+                       return 0;
                } else
-                       return (1);
+                       return 1;
        }
        /* One of the routes doesn't exist ? */
        return (1);
@@ -297,8 +292,7 @@ void ospf6_add_nexthop(struct list *nh_list, int ifindex, struct in6_addr *addr)
 }
 
 void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route,
-                                    ifindex_t *ifindexes,
-                                    struct in6_addr **nexthop_addr,
+                                    struct zapi_nexthop nexthops[],
                                     int entries)
 {
        struct ospf6_nexthop *nh;
@@ -318,13 +312,17 @@ void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route,
                                zlog_debug("  nexthop: %s%%%.*s(%d)", buf,
                                           IFNAMSIZ, ifname, nh->ifindex);
                        }
-                       if (i < entries) {
-                               nexthop_addr[i] = &nh->address;
-                               ifindexes[i] = nh->ifindex;
-                               i++;
-                       } else {
+                       if (i >= entries)
                                return;
-                       }
+
+                       nexthops[i].vrf_id = VRF_DEFAULT;
+                       nexthops[i].ifindex = nh->ifindex;
+                       if (!IN6_IS_ADDR_UNSPECIFIED(&nh->address)) {
+                               nexthops[i].gate.ipv6 = nh->address;
+                               nexthops[i].type = NEXTHOP_TYPE_IPV6_IFINDEX;
+                       } else
+                               nexthops[i].type = NEXTHOP_TYPE_IFINDEX;
+                       i++;
                }
        }
 }
@@ -341,19 +339,83 @@ int ospf6_route_get_first_nh_index(struct ospf6_route *route)
        return (-1);
 }
 
+int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b)
+{
+       if (a->ifindex < b->ifindex)
+               return -1;
+       else if (a->ifindex > b->ifindex)
+               return 1;
+       else
+               return memcmp(&a->address, &b->address,
+                             sizeof(struct in6_addr));
+
+       return 0;
+}
+
+static int ospf6_path_cmp(struct ospf6_path *a, struct ospf6_path *b)
+{
+       if (a->origin.adv_router < b->origin.adv_router)
+               return -1;
+       else if (a->origin.adv_router > b->origin.adv_router)
+               return 1;
+       else
+               return 0;
+}
+
+void ospf6_path_free(struct ospf6_path *op)
+{
+       if (op->nh_list)
+               list_delete_and_null(&op->nh_list);
+       XFREE(MTYPE_OSPF6_PATH, op);
+}
+
+struct ospf6_path *ospf6_path_dup(struct ospf6_path *path)
+{
+       struct ospf6_path *new;
+
+       new = XCALLOC(MTYPE_OSPF6_PATH, sizeof(struct ospf6_path));
+       memcpy(new, path, sizeof(struct ospf6_path));
+       new->nh_list = list_new();
+       new->nh_list->cmp = (int (*)(void *, void *))ospf6_nexthop_cmp;
+       new->nh_list->del = (void (*)(void *))ospf6_nexthop_delete;
+
+       return new;
+}
+
+void ospf6_copy_paths(struct list *dst, struct list *src)
+{
+       struct ospf6_path *path_new, *path;
+       struct listnode *node;
+
+       if (dst && src) {
+               for (ALL_LIST_ELEMENTS_RO(src, node, path)) {
+                       path_new = ospf6_path_dup(path);
+                       ospf6_copy_nexthops(path_new->nh_list, path->nh_list);
+                       listnode_add_sort(dst, path_new);
+               }
+       }
+}
+
 struct ospf6_route *ospf6_route_create(void)
 {
        struct ospf6_route *route;
        route = XCALLOC(MTYPE_OSPF6_ROUTE, sizeof(struct ospf6_route));
        route->nh_list = list_new();
+       route->nh_list->cmp = (int (*)(void *, void *))ospf6_nexthop_cmp;
+       route->nh_list->del = (void (*)(void *))ospf6_nexthop_delete;
+       route->paths = list_new();
+       route->paths->cmp = (int (*)(void *, void *))ospf6_path_cmp;
+       route->paths->del = (void (*)(void *))ospf6_path_free;
        return route;
 }
 
 void ospf6_route_delete(struct ospf6_route *route)
 {
        if (route) {
-               ospf6_free_nexthops(route->nh_list);
-               list_free(route->nh_list);
+               if (route->nh_list)
+                       list_delete_and_null(&route->nh_list);
+               if (route->paths)
+                       list_delete_and_null(&route->paths);
                XFREE(MTYPE_OSPF6_ROUTE, route);
        }
 }
@@ -372,6 +434,7 @@ struct ospf6_route *ospf6_route_copy(struct ospf6_route *route)
        new->linkstate_id = route->linkstate_id;
        new->path = route->path;
        ospf6_copy_nexthops(new->nh_list, route->nh_list);
+       ospf6_copy_paths(new->paths, route->paths);
        new->rnode = NULL;
        new->prev = NULL;
        new->next = NULL;
@@ -412,20 +475,22 @@ int ospf6_route_cmp(struct ospf6_route *ra, struct ospf6_route *rb)
        if (ra->type != rb->type)
                return (ra->type - rb->type);
 
-       if (ra->path.area_id != rb->path.area_id)
-               return (ntohl(ra->path.area_id) - ntohl(rb->path.area_id));
-
        if (ra->path.type != rb->path.type)
                return (ra->path.type - rb->path.type);
 
        if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2) {
                if (ra->path.u.cost_e2 != rb->path.u.cost_e2)
                        return (ra->path.u.cost_e2 - rb->path.u.cost_e2);
+               else
+                       return (ra->path.cost - rb->path.cost);
        } else {
                if (ra->path.cost != rb->path.cost)
                        return (ra->path.cost - rb->path.cost);
        }
 
+       if (ra->path.area_id != rb->path.area_id)
+               return (ntohl(ra->path.area_id) - ntohl(rb->path.area_id));
+
        return 0;
 }
 
@@ -440,6 +505,7 @@ struct ospf6_route *ospf6_route_lookup(struct prefix *prefix,
                return NULL;
 
        route = (struct ospf6_route *)node->info;
+       route_unlock_node(node); /* to free the lookup lock */
        return route;
 }
 
@@ -451,7 +517,14 @@ ospf6_route_lookup_identical(struct ospf6_route *route,
 
        for (target = ospf6_route_lookup(&route->prefix, table); target;
             target = target->next) {
-               if (ospf6_route_is_identical(target, route))
+               if (target->type == route->type
+                   && (memcmp(&target->prefix, &route->prefix,
+                              sizeof(struct prefix))
+                       == 0)
+                   && target->path.type == route->path.type
+                   && target->path.cost == route->path.cost
+                   && target->path.u.cost_e2 == route->path.u.cost_e2
+                   && ospf6_route_cmp_nexthops(target, route) == 0)
                        return target;
        }
        return NULL;
@@ -572,10 +645,10 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
                if (ospf6_route_is_identical(old, route)) {
                        if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
                                zlog_debug(
-                                       "%s %p: route add %p: needless update of %p",
+                                       "%s %p: route add %p: needless update of %p old cost %u",
                                        ospf6_route_table_name(table),
                                        (void *)table, (void *)route,
-                                       (void *)old);
+                                       (void *)old, old->path.cost);
                        else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
                                zlog_debug("%s: route add: needless update",
                                           ospf6_route_table_name(table));
@@ -584,13 +657,18 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
                        SET_FLAG(old->flag, OSPF6_ROUTE_ADD);
                        ospf6_route_table_assert(table);
 
+                       /* to free the lookup lock */
+                       route_unlock_node(node);
                        return old;
                }
 
                if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
-                       zlog_debug("%s %p: route add %p: update of %p",
-                                  ospf6_route_table_name(table), (void *)table,
-                                  (void *)route, (void *)old);
+                       zlog_debug(
+                               "%s %p: route add %p cost %u nh %u: update of %p old cost %u nh %u",
+                               ospf6_route_table_name(table), (void *)table,
+                               (void *)route, route->path.cost,
+                               listcount(route->nh_list), (void *)old,
+                               old->path.cost, listcount(old->nh_list));
                else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
                        zlog_debug("%s: route add: update",
                                   ospf6_route_table_name(table));
@@ -629,12 +707,14 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
        if (prev || next) {
                if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
                        zlog_debug(
-                               "%s %p: route add %p: another path: prev %p, next %p",
+                               "%s %p: route add %p cost %u: another path: prev %p, next %p node ref %u",
                                ospf6_route_table_name(table), (void *)table,
-                               (void *)route, (void *)prev, (void *)next);
+                               (void *)route, route->path.cost, (void *)prev,
+                               (void *)next, node->lock);
                else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
-                       zlog_debug("%s: route add: another path found",
-                                  ospf6_route_table_name(table));
+                       zlog_debug("%s: route add cost %u: another path found",
+                                  ospf6_route_table_name(table),
+                                  route->path.cost);
 
                if (prev == NULL)
                        prev = next->prev;
@@ -655,10 +735,11 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
                        SET_FLAG(route->flag, OSPF6_ROUTE_BEST);
                        if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
                                zlog_info(
-                                       "%s %p: route add %p: replacing previous best: %p",
+                                       "%s %p: route add %p cost %u: replacing previous best: %p cost %u",
                                        ospf6_route_table_name(table),
                                        (void *)table, (void *)route,
-                                       (void *)next);
+                                       route->path.cost,
+                                       (void *)next, next->path.cost);
                }
 
                route->installed = now;
@@ -679,9 +760,9 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
 
        /* Else, this is the brand new route regarding to the prefix */
        if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
-               zlog_debug("%s %p: route add %p: brand new route",
+               zlog_debug("%s %p: route add %p %s cost %u: brand new route",
                           ospf6_route_table_name(table), (void *)table,
-                          (void *)route);
+                          (void *)route, buf, route->path.cost);
        else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
                zlog_debug("%s: route add: brand new route",
                           ospf6_route_table_name(table));
@@ -756,9 +837,9 @@ void ospf6_route_remove(struct ospf6_route *route,
                prefix2str(&route->prefix, buf, sizeof(buf));
 
        if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
-               zlog_debug("%s %p: route remove %p: %s",
+               zlog_debug("%s %p: route remove %p: %s cost %u refcount %u",
                           ospf6_route_table_name(table), (void *)table,
-                          (void *)route, buf);
+                          (void *)route, buf, route->path.cost, route->lock);
        else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
                zlog_debug("%s: route remove: %s",
                           ospf6_route_table_name(table), buf);
@@ -769,11 +850,9 @@ void ospf6_route_remove(struct ospf6_route *route,
        /* find the route to remove, making sure that the route pointer
           is from the route table. */
        current = node->info;
-       while (current && ospf6_route_is_same(current, route)) {
-               if (current == route)
-                       break;
+       while (current && current != route)
                current = current->next;
-       }
+
        assert(current == route);
 
        /* adjust doubly linked list */
@@ -786,15 +865,20 @@ void ospf6_route_remove(struct ospf6_route *route,
                if (route->next && route->next->rnode == node) {
                        node->info = route->next;
                        SET_FLAG(route->next->flag, OSPF6_ROUTE_BEST);
-               } else
-                       node->info = NULL; /* should unlock route_node here ? */
+               } else {
+                       node->info = NULL;
+                       route->rnode = NULL;
+                       route_unlock_node(node); /* to free the original lock */
+               }
        }
 
+       route_unlock_node(node); /* to free the lookup lock */
        table->count--;
        ospf6_route_table_assert(table);
 
        SET_FLAG(route->flag, OSPF6_ROUTE_WAS_REMOVED);
 
+       /* Note hook_remove may call ospf6_route_remove */
        if (table->hook_remove)
                (*table->hook_remove)(route);
 
@@ -936,6 +1020,7 @@ struct ospf6_route_table *ospf6_route_table_create(int s, int t)
 void ospf6_route_table_delete(struct ospf6_route_table *table)
 {
        ospf6_route_remove_all(table);
+       bf_free(table->idspace);
        route_table_finish(table->table);
        XFREE(MTYPE_OSPF6_ROUTE, table);
 }
@@ -946,7 +1031,7 @@ void ospf6_route_show(struct vty *vty, struct ospf6_route *route)
 {
        int i;
        char destination[PREFIX2STR_BUFFER], nexthop[64];
-       char duration[16];
+       char duration[64];
        const char *ifname;
        struct timeval now, res;
        struct listnode *node;
@@ -973,16 +1058,16 @@ void ospf6_route_show(struct vty *vty, struct ospf6_route *route)
                ifname = ifindex2ifname(nh->ifindex, VRF_DEFAULT);
 
                if (!i) {
-                       vty_out(vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
+                       vty_out(vty, "%c%1s %2s %-30s %-25s %6.*s %s\n",
                                (ospf6_route_is_best(route) ? '*' : ' '),
                                OSPF6_DEST_TYPE_SUBSTR(route->type),
                                OSPF6_PATH_TYPE_SUBSTR(route->path.type),
                                destination, nexthop, IFNAMSIZ, ifname,
-                               duration, VNL);
+                               duration);
                        i++;
                } else
-                       vty_out(vty, "%c%1s %2s %-30s %-25s %6.*s %s%s", ' ',
-                               "", "", "", nexthop, IFNAMSIZ, ifname, "", VNL);
+                       vty_out(vty, "%c%1s %2s %-30s %-25s %6.*s %s\n", ' ',
+                               "", "", "", nexthop, IFNAMSIZ, ifname, "");
        }
 }
 
@@ -992,7 +1077,7 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route)
        char destination[PREFIX2STR_BUFFER], nexthop[64];
        char area_id[16], id[16], adv_router[16], capa[16], options[16];
        struct timeval now, res;
-       char duration[16];
+       char duration[64];
        struct listnode *node;
        struct ospf6_nexthop *nh;
 
@@ -1007,73 +1092,73 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route)
                          destination, sizeof(destination));
        else
                prefix2str(&route->prefix, destination, sizeof(destination));
-       vty_out(vty, "Destination: %s%s", destination, VNL);
+       vty_out(vty, "Destination: %s\n", destination);
 
        /* destination type */
-       vty_out(vty, "Destination type: %s%s",
-               OSPF6_DEST_TYPE_NAME(route->type), VNL);
+       vty_out(vty, "Destination type: %s\n",
+               OSPF6_DEST_TYPE_NAME(route->type));
 
        /* Time */
        timersub(&now, &route->installed, &res);
        timerstring(&res, duration, sizeof(duration));
-       vty_out(vty, "Installed Time: %s ago%s", duration, VNL);
+       vty_out(vty, "Installed Time: %s ago\n", duration);
 
        timersub(&now, &route->changed, &res);
        timerstring(&res, duration, sizeof(duration));
-       vty_out(vty, "  Changed Time: %s ago%s", duration, VNL);
+       vty_out(vty, "  Changed Time: %s ago\n", duration);
 
        /* Debugging info */
-       vty_out(vty, "Lock: %d Flags: %s%s%s%s%s", route->lock,
+       vty_out(vty, "Lock: %d Flags: %s%s%s%s\n", route->lock,
                (CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
                (CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
                (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
-               (CHECK_FLAG(route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"), VNL);
-       vty_out(vty, "Memory: prev: %p this: %p next: %p%s",
-               (void *)route->prev, (void *)route, (void *)route->next, VNL);
+               (CHECK_FLAG(route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"));
+       vty_out(vty, "Memory: prev: %p this: %p next: %p\n",
+               (void *)route->prev, (void *)route, (void *)route->next);
 
        /* Path section */
 
        /* Area-ID */
        inet_ntop(AF_INET, &route->path.area_id, area_id, sizeof(area_id));
-       vty_out(vty, "Associated Area: %s%s", area_id, VNL);
+       vty_out(vty, "Associated Area: %s\n", area_id);
 
        /* Path type */
-       vty_out(vty, "Path Type: %s%s", OSPF6_PATH_TYPE_NAME(route->path.type),
-               VNL);
+       vty_out(vty, "Path Type: %s\n", OSPF6_PATH_TYPE_NAME(route->path.type));
 
        /* LS Origin */
        inet_ntop(AF_INET, &route->path.origin.id, id, sizeof(id));
        inet_ntop(AF_INET, &route->path.origin.adv_router, adv_router,
                  sizeof(adv_router));
-       vty_out(vty, "LS Origin: %s Id: %s Adv: %s%s",
-               ospf6_lstype_name(route->path.origin.type), id, adv_router,
-               VNL);
+       vty_out(vty, "LS Origin: %s Id: %s Adv: %s\n",
+               ospf6_lstype_name(route->path.origin.type), id, adv_router);
 
        /* Options */
        ospf6_options_printbuf(route->path.options, options, sizeof(options));
-       vty_out(vty, "Options: %s%s", options, VNL);
+       vty_out(vty, "Options: %s\n", options);
 
        /* Router Bits */
        ospf6_capability_printbuf(route->path.router_bits, capa, sizeof(capa));
-       vty_out(vty, "Router Bits: %s%s", capa, VNL);
+       vty_out(vty, "Router Bits: %s\n", capa);
 
        /* Prefix Options */
-       vty_out(vty, "Prefix Options: xxx%s", VNL);
+       vty_out(vty, "Prefix Options: xxx\n");
 
        /* Metrics */
-       vty_out(vty, "Metric Type: %d%s", route->path.metric_type, VNL);
-       vty_out(vty, "Metric: %d (%d)%s", route->path.cost,
-               route->path.u.cost_e2, VNL);
+       vty_out(vty, "Metric Type: %d\n", route->path.metric_type);
+       vty_out(vty, "Metric: %d (%d)\n", route->path.cost,
+               route->path.u.cost_e2);
 
+       vty_out(vty, "Paths count: %u\n", route->paths->count);
+       vty_out(vty, "Nexthop count: %u\n", route->nh_list->count);
        /* Nexthops */
-       vty_out(vty, "Nexthop:%s", VNL);
+       vty_out(vty, "Nexthop:\n");
        for (ALL_LIST_ELEMENTS_RO(route->nh_list, node, nh)) {
                /* nexthop */
                inet_ntop(AF_INET6, &nh->address, nexthop, sizeof(nexthop));
                ifname = ifindex2ifname(nh->ifindex, VRF_DEFAULT);
-               vty_out(vty, "  %s %.*s%s", nexthop, IFNAMSIZ, ifname, VNL);
+               vty_out(vty, "  %s %.*s\n", nexthop, IFNAMSIZ, ifname);
        }
-       vty_out(vty, "%s", VNL);
+       vty_out(vty, "\n");
 }
 
 static void ospf6_route_show_table_summary(struct vty *vty,
@@ -1107,13 +1192,13 @@ static void ospf6_route_show_table_summary(struct vty *vty,
 
        assert(number == table->count);
 
-       vty_out(vty, "Number of OSPFv3 routes: %d%s", number, VNL);
-       vty_out(vty, "Number of Destination: %d%s", destination, VNL);
-       vty_out(vty, "Number of Alternative routes: %d%s", alternative, VNL);
-       vty_out(vty, "Number of Equal Cost Multi Path: %d%s", ecmp, VNL);
+       vty_out(vty, "Number of OSPFv3 routes: %d\n", number);
+       vty_out(vty, "Number of Destination: %d\n", destination);
+       vty_out(vty, "Number of Alternative routes: %d\n", alternative);
+       vty_out(vty, "Number of Equal Cost Multi Path: %d\n", ecmp);
        for (i = OSPF6_PATH_TYPE_INTRA; i <= OSPF6_PATH_TYPE_EXTERNAL2; i++) {
-               vty_out(vty, "Number of %s routes: %d%s",
-                       OSPF6_PATH_TYPE_NAME(i), pathtype[i], VNL);
+               vty_out(vty, "Number of %s routes: %d\n",
+                       OSPF6_PATH_TYPE_NAME(i), pathtype[i]);
        }
 }
 
@@ -1176,7 +1261,7 @@ static void ospf6_route_show_table_match(struct vty *vty, int detail,
 }
 
 static void ospf6_route_show_table_type(struct vty *vty, int detail,
-                                       u_char type,
+                                       uint8_t type,
                                        struct ospf6_route_table *table)
 {
        struct ospf6_route *route;
@@ -1219,42 +1304,42 @@ int ospf6_route_table_show(struct vty *vty, int argc_start, int argc,
        int isprefix = 0;
        int i, ret;
        struct prefix prefix;
-       u_char type = 0;
+       uint8_t type = 0;
 
        memset(&prefix, 0, sizeof(struct prefix));
 
        for (i = argc_start; i < argc; i++) {
-               if (!strcmp(argv[i]->arg, "summary")) {
+               if (strmatch(argv[i]->text, "summary")) {
                        summary++;
                        continue;
                }
 
-               if (!strcmp(argv[i]->arg, "intra-area")) {
+               if (strmatch(argv[i]->text, "intra-area")) {
                        type = OSPF6_PATH_TYPE_INTRA;
                        continue;
                }
 
-               if (!strcmp(argv[i]->arg, "inter-area")) {
+               if (strmatch(argv[i]->text, "inter-area")) {
                        type = OSPF6_PATH_TYPE_INTER;
                        continue;
                }
 
-               if (!strcmp(argv[i]->arg, "external-1")) {
+               if (strmatch(argv[i]->text, "external-1")) {
                        type = OSPF6_PATH_TYPE_EXTERNAL1;
                        continue;
                }
 
-               if (!strcmp(argv[i]->arg, "external-2")) {
+               if (strmatch(argv[i]->text, "external-2")) {
                        type = OSPF6_PATH_TYPE_EXTERNAL2;
                        continue;
                }
 
-               if (!strcmp(argv[i]->arg, "detail")) {
+               if (strmatch(argv[i]->text, "detail")) {
                        detail++;
                        continue;
                }
 
-               if (!strcmp(argv[i]->arg, "match")) {
+               if (strmatch(argv[i]->text, "match")) {
                        match++;
                        continue;
                }
@@ -1267,7 +1352,7 @@ int ospf6_route_table_show(struct vty *vty, int argc_start, int argc,
                        continue;
                }
 
-               vty_out(vty, "Malformed argument: %s%s", argv[i]->arg, VNL);
+               vty_out(vty, "Malformed argument: %s\n", argv[i]->arg);
                return CMD_SUCCESS;
        }
 
@@ -1300,13 +1385,13 @@ int ospf6_route_table_show(struct vty *vty, int argc_start, int argc,
 
 static void ospf6_linkstate_show_header(struct vty *vty)
 {
-       vty_out(vty, "%-7s %-15s %-15s %-8s %-14s %s%s", "Type", "Router-ID",
-               "Net-ID", "Rtr-Bits", "Options", "Cost", VNL);
+       vty_out(vty, "%-7s %-15s %-15s %-8s %-14s %s\n", "Type", "Router-ID",
+               "Net-ID", "Rtr-Bits", "Options", "Cost");
 }
 
 static void ospf6_linkstate_show(struct vty *vty, struct ospf6_route *route)
 {
-       u_int32_t router, id;
+       uint32_t router, id;
        char routername[16], idname[16], rbits[16], options[16];
 
        router = ospf6_linkstate_prefix_adv_router(&route->prefix);
@@ -1319,13 +1404,13 @@ static void ospf6_linkstate_show(struct vty *vty, struct ospf6_route *route)
        ospf6_options_printbuf(route->path.options, options, sizeof(options));
 
        if (ntohl(id))
-               vty_out(vty, "%-7s %-15s %-15s %-8s %-14s %lu%s", "Network",
+               vty_out(vty, "%-7s %-15s %-15s %-8s %-14s %lu\n", "Network",
                        routername, idname, rbits, options,
-                       (unsigned long)route->path.cost, VNL);
+                       (unsigned long)route->path.cost);
        else
-               vty_out(vty, "%-7s %-15s %-15s %-8s %-14s %lu%s", "Router",
+               vty_out(vty, "%-7s %-15s %-15s %-8s %-14s %lu\n", "Router",
                        routername, idname, rbits, options,
-                       (unsigned long)route->path.cost, VNL);
+                       (unsigned long)route->path.cost);
 }
 
 
@@ -1382,7 +1467,7 @@ int ospf6_linkstate_table_show(struct vty *vty, int idx_ipv4, int argc,
        memset(&prefix, 0, sizeof(struct prefix));
 
        for (i = idx_ipv4; i < argc; i++) {
-               if (!strcmp(argv[i]->arg, "detail")) {
+               if (strmatch(argv[i]->text, "detail")) {
                        detail++;
                        continue;
                }
@@ -1393,8 +1478,7 @@ int ospf6_linkstate_table_show(struct vty *vty, int idx_ipv4, int argc,
                                is_router++;
                                continue;
                        }
-                       vty_out(vty, "Malformed argument: %s%s", argv[i]->arg,
-                               VNL);
+                       vty_out(vty, "Malformed argument: %s\n", argv[i]->arg);
                        return CMD_SUCCESS;
                }
 
@@ -1404,12 +1488,11 @@ int ospf6_linkstate_table_show(struct vty *vty, int idx_ipv4, int argc,
                                is_id++;
                                continue;
                        }
-                       vty_out(vty, "Malformed argument: %s%s", argv[i]->arg,
-                               VNL);
+                       vty_out(vty, "Malformed argument: %s\n", argv[i]->arg);
                        return CMD_SUCCESS;
                }
 
-               vty_out(vty, "Malformed argument: %s%s", argv[i]->arg, VNL);
+               vty_out(vty, "Malformed argument: %s\n", argv[i]->arg);
                return CMD_SUCCESS;
        }
 
@@ -1428,13 +1511,13 @@ int ospf6_linkstate_table_show(struct vty *vty, int idx_ipv4, int argc,
 
 void ospf6_brouter_show_header(struct vty *vty)
 {
-       vty_out(vty, "%-15s %-8s %-14s %-10s %-15s%s", "Router-ID", "Rtr-Bits",
-               "Options", "Path-Type", "Area", VNL);
+       vty_out(vty, "%-15s %-8s %-14s %-10s %-15s\n", "Router-ID", "Rtr-Bits",
+               "Options", "Path-Type", "Area");
 }
 
 void ospf6_brouter_show(struct vty *vty, struct ospf6_route *route)
 {
-       u_int32_t adv_router;
+       uint32_t adv_router;
        char adv[16], rbits[16], options[16], area[16];
 
        adv_router = ospf6_linkstate_prefix_adv_router(&route->prefix);
@@ -1444,11 +1527,10 @@ void ospf6_brouter_show(struct vty *vty, struct ospf6_route *route)
        ospf6_options_printbuf(route->path.options, options, sizeof(options));
        inet_ntop(AF_INET, &route->path.area_id, area, sizeof(area));
 
-       /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
-                "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
-          */
-       vty_out(vty, "%-15s %-8s %-14s %-10s %-15s%s", adv, rbits, options,
-               OSPF6_PATH_TYPE_NAME(route->path.type), area, VNL);
+       /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s\n",
+                "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area"); */
+       vty_out(vty, "%-15s %-8s %-14s %-10s %-15s\n", adv, rbits, options,
+               OSPF6_PATH_TYPE_NAME(route->path.type), area);
 }
 
 DEFUN (debug_ospf6_route,
@@ -1466,13 +1548,13 @@ DEFUN (debug_ospf6_route,
        int idx_type = 3;
        unsigned char level = 0;
 
-       if (!strncmp(argv[idx_type]->arg, "table", 5))
+       if (!strcmp(argv[idx_type]->text, "table"))
                level = OSPF6_DEBUG_ROUTE_TABLE;
-       else if (!strncmp(argv[idx_type]->arg, "intra", 5))
+       else if (!strcmp(argv[idx_type]->text, "intra-area"))
                level = OSPF6_DEBUG_ROUTE_INTRA;
-       else if (!strncmp(argv[idx_type]->arg, "inter", 5))
+       else if (!strcmp(argv[idx_type]->text, "inter-area"))
                level = OSPF6_DEBUG_ROUTE_INTER;
-       else if (!strncmp(argv[idx_type]->arg, "memor", 5))
+       else if (!strcmp(argv[idx_type]->text, "memory"))
                level = OSPF6_DEBUG_ROUTE_MEMORY;
        OSPF6_DEBUG_ROUTE_ON(level);
        return CMD_SUCCESS;
@@ -1493,13 +1575,13 @@ DEFUN (no_debug_ospf6_route,
        int idx_type = 4;
        unsigned char level = 0;
 
-       if (!strncmp(argv[idx_type]->arg, "table", 5))
+       if (!strcmp(argv[idx_type]->text, "table"))
                level = OSPF6_DEBUG_ROUTE_TABLE;
-       else if (!strncmp(argv[idx_type]->arg, "intra", 5))
+       else if (!strcmp(argv[idx_type]->text, "intra-area"))
                level = OSPF6_DEBUG_ROUTE_INTRA;
-       else if (!strncmp(argv[idx_type]->arg, "inter", 5))
+       else if (!strcmp(argv[idx_type]->text, "inter-area"))
                level = OSPF6_DEBUG_ROUTE_INTER;
-       else if (!strncmp(argv[idx_type]->arg, "memor", 5))
+       else if (!strcmp(argv[idx_type]->text, "memory"))
                level = OSPF6_DEBUG_ROUTE_MEMORY;
        OSPF6_DEBUG_ROUTE_OFF(level);
        return CMD_SUCCESS;
@@ -1508,11 +1590,14 @@ DEFUN (no_debug_ospf6_route,
 int config_write_ospf6_debug_route(struct vty *vty)
 {
        if (IS_OSPF6_DEBUG_ROUTE(TABLE))
-               vty_out(vty, "debug ospf6 route table%s", VNL);
+               vty_out(vty, "debug ospf6 route table\n");
        if (IS_OSPF6_DEBUG_ROUTE(INTRA))
-               vty_out(vty, "debug ospf6 route intra-area%s", VNL);
+               vty_out(vty, "debug ospf6 route intra-area\n");
        if (IS_OSPF6_DEBUG_ROUTE(INTER))
-               vty_out(vty, "debug ospf6 route inter-area%s", VNL);
+               vty_out(vty, "debug ospf6 route inter-area\n");
+       if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
+               vty_out(vty, "debug ospf6 route memory\n");
+
        return 0;
 }