network: copy multipath route element earlier

`route_get()` compares input with existing routes, however previously,
the input may did not have information about gateway. So, the
comparison result might be incorrect, and the foregoing set_put() might
return -EEXIST.
This commit is contained in:
Yu Watanabe 2020-10-20 15:26:51 +09:00
parent 8c212f76c2
commit cc17f75f66

View file

@ -487,20 +487,19 @@ static void route_copy(Route *dest, const Route *src, const MultipathRoute *m) {
} }
} }
static int route_add_internal(Manager *manager, Link *link, Set **routes, const Route *in, const MultipathRoute *m, Route **ret) { static int route_add_internal(Manager *manager, Link *link, Set **routes, const Route *in, Route **ret) {
_cleanup_(route_freep) Route *route = NULL; _cleanup_(route_freep) Route *route = NULL;
int r; int r;
assert(manager || link); assert(manager || link);
assert(routes); assert(routes);
assert(in); assert(in);
assert(!m || (link && (m->ifindex == 0 || m->ifindex == link->ifindex)));
r = route_new(&route); r = route_new(&route);
if (r < 0) if (r < 0)
return r; return r;
route_copy(route, in, m); route_copy(route, in, NULL);
r = set_ensure_put(routes, &route_hash_ops, route); r = set_ensure_put(routes, &route_hash_ops, route);
if (r < 0) if (r < 0)
@ -521,20 +520,32 @@ static int route_add_internal(Manager *manager, Link *link, Set **routes, const
static int route_add_foreign(Manager *manager, Link *link, const Route *in, Route **ret) { static int route_add_foreign(Manager *manager, Link *link, const Route *in, Route **ret) {
assert(manager || link); assert(manager || link);
return route_add_internal(manager, link, link ? &link->routes_foreign : &manager->routes_foreign, in, NULL, ret); return route_add_internal(manager, link, link ? &link->routes_foreign : &manager->routes_foreign, in, ret);
} }
static int route_add(Manager *manager, Link *link, const Route *in, const MultipathRoute *m, Route **ret) { static int route_add(Manager *manager, Link *link, const Route *in, const MultipathRoute *m, Route **ret) {
_cleanup_(route_freep) Route *tmp = NULL;
Route *route; Route *route;
int r; int r;
assert(manager || link); assert(manager || link);
assert(in); assert(in);
if (m) {
assert(link && (m->ifindex == 0 || m->ifindex == link->ifindex));
r = route_new(&tmp);
if (r < 0)
return r;
route_copy(tmp, in, m);
in = tmp;
}
r = route_get(manager, link, in, &route); r = route_get(manager, link, in, &route);
if (r == -ENOENT) { if (r == -ENOENT) {
/* Route does not exist, create a new one */ /* Route does not exist, create a new one */
r = route_add_internal(manager, link, link ? &link->routes : &manager->routes, in, m, &route); r = route_add_internal(manager, link, link ? &link->routes : &manager->routes, in, &route);
if (r < 0) if (r < 0)
return r; return r;
} else if (r == 0) { } else if (r == 0) {