]> 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 281757222dd1d1b595ef7083af19a4144ab84062..8be00d9b41610fa2769fe98993580cb32b32d463 100644 (file)
@@ -122,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));
@@ -134,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);
@@ -215,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);
                        }
                }
        }
@@ -231,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);
                        }
                }
        }
@@ -315,6 +315,7 @@ void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route,
                        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;
@@ -338,7 +339,7 @@ int ospf6_route_get_first_nh_index(struct ospf6_route *route)
        return (-1);
 }
 
-static int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b)
+int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b)
 {
        if (a->ifindex < b->ifindex)
                return -1;
@@ -351,13 +352,60 @@ static int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b)
        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->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;
 }
 
@@ -366,6 +414,8 @@ void ospf6_route_delete(struct ospf6_route *route)
        if (route) {
                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);
        }
 }
@@ -384,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;
@@ -424,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;
 }
 
@@ -464,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;
@@ -585,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));
@@ -603,9 +663,12 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
                }
 
                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));
@@ -644,13 +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 node refcount %u",
+                               "%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,
-                               node->lock);
+                               (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;
@@ -671,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;
@@ -695,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 %s : 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, buf);
+                          (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));
@@ -772,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 refcount %u",
+               zlog_debug("%s %p: route remove %p: %s cost %u refcount %u",
                           ospf6_route_table_name(table), (void *)table,
-                          (void *)route, buf, route->lock);
+                          (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);
@@ -1083,6 +1148,7 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route)
        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:\n");
@@ -1195,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;
@@ -1238,7 +1304,7 @@ 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));
 
@@ -1325,7 +1391,7 @@ static void ospf6_linkstate_show_header(struct vty *vty)
 
 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);
@@ -1451,7 +1517,7 @@ void ospf6_brouter_show_header(struct vty *vty)
 
 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);