mlxsw: spectrum_router: Create IPv6 multipath routes in one go
authorIdo Schimmel <idosch@mellanox.com>
Tue, 18 Jun 2019 15:12:56 +0000 (18:12 +0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 18 Jun 2019 16:45:37 +0000 (09:45 -0700)
Allow the driver to create an IPv6 multipath route in one go by passing
an array of sibling routes and iterating over them.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c

index 98fd3c582a60e945558b8da786b8409a914c614d..92ec65188e9ab35c4264651e673cf9d771eea333 100644 (file)
@@ -5373,29 +5373,32 @@ mlxsw_sp_fib6_entry_rt_destroy_all(struct mlxsw_sp_fib6_entry *fib6_entry)
 static struct mlxsw_sp_fib6_entry *
 mlxsw_sp_fib6_entry_create(struct mlxsw_sp *mlxsw_sp,
                           struct mlxsw_sp_fib_node *fib_node,
-                          struct fib6_info *rt)
+                          struct fib6_info **rt_arr, unsigned int nrt6)
 {
        struct mlxsw_sp_fib6_entry *fib6_entry;
        struct mlxsw_sp_fib_entry *fib_entry;
        struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
-       int err;
+       int err, i;
 
        fib6_entry = kzalloc(sizeof(*fib6_entry), GFP_KERNEL);
        if (!fib6_entry)
                return ERR_PTR(-ENOMEM);
        fib_entry = &fib6_entry->common;
 
-       mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt);
-       if (IS_ERR(mlxsw_sp_rt6)) {
-               err = PTR_ERR(mlxsw_sp_rt6);
-               goto err_rt6_create;
+       INIT_LIST_HEAD(&fib6_entry->rt6_list);
+
+       for (i = 0; i < nrt6; i++) {
+               mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt_arr[i]);
+               if (IS_ERR(mlxsw_sp_rt6)) {
+                       err = PTR_ERR(mlxsw_sp_rt6);
+                       goto err_rt6_create;
+               }
+               list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
+               fib6_entry->nrt6++;
        }
 
-       mlxsw_sp_fib6_entry_type_set(mlxsw_sp, fib_entry, mlxsw_sp_rt6->rt);
+       mlxsw_sp_fib6_entry_type_set(mlxsw_sp, fib_entry, rt_arr[0]);
 
-       INIT_LIST_HEAD(&fib6_entry->rt6_list);
-       list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
-       fib6_entry->nrt6 = 1;
        err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry);
        if (err)
                goto err_nexthop6_group_get;
@@ -5405,9 +5408,15 @@ mlxsw_sp_fib6_entry_create(struct mlxsw_sp *mlxsw_sp,
        return fib6_entry;
 
 err_nexthop6_group_get:
-       list_del(&mlxsw_sp_rt6->list);
-       mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
+       i = nrt6;
 err_rt6_create:
+       for (i--; i >= 0; i--) {
+               fib6_entry->nrt6--;
+               mlxsw_sp_rt6 = list_last_entry(&fib6_entry->rt6_list,
+                                              struct mlxsw_sp_rt6, list);
+               list_del(&mlxsw_sp_rt6->list);
+               mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
+       }
        kfree(fib6_entry);
        return ERR_PTR(err);
 }
@@ -5608,7 +5617,8 @@ static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
                return 0;
        }
 
-       fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt);
+       fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt_arr,
+                                               nrt6);
        if (IS_ERR(fib6_entry)) {
                err = PTR_ERR(fib6_entry);
                goto err_fib6_entry_create;