summaryrefslogtreecommitdiff
path: root/net/core/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 429a55fff667..e50ed677de72 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -748,6 +748,27 @@ static struct net_device_path *dev_fwd_path(struct net_device_path_stack *stack)
return &stack->path[stack->num_paths];
}
+void dev_fill_forward_path_release(struct net_device_path_stack *stack)
+{
+ struct net_device_path *path;
+ int k;
+
+ if (stack->num_paths == 0)
+ return;
+
+ for (k = stack->num_paths - 1; k >= 0; k--) {
+ path = &stack->path[k];
+ switch (path->type) {
+ case DEV_PATH_TUN:
+ dst_release(path->tun.dst);
+ break;
+ default:
+ break;
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(dev_fill_forward_path_release);
+
int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
struct net_device_path_stack *stack)
{
@@ -764,16 +785,16 @@ int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
last_dev = ctx.dev;
path = dev_fwd_path(stack);
if (!path)
- return -1;
+ goto err_out;
memset(path, 0, sizeof(struct net_device_path));
ret = ctx.dev->netdev_ops->ndo_fill_forward_path(&ctx, path);
if (ret < 0)
- return -1;
+ goto err_out;
stack->num_paths++;
if (WARN_ON_ONCE(last_dev == ctx.dev))
- return -1;
+ goto err_out;
}
if (!ctx.dev)
@@ -781,12 +802,17 @@ int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
path = dev_fwd_path(stack);
if (!path)
- return -1;
+ goto err_out;
+
path->type = DEV_PATH_ETHERNET;
path->dev = ctx.dev;
stack->num_paths++;
- return ret;
+ return 0;
+err_out:
+ dev_fill_forward_path_release(stack);
+
+ return -1;
}
EXPORT_SYMBOL_GPL(dev_fill_forward_path);