2 * drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
3 * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
4 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
5 * Copyright (c) 2016 Ido Schimmel <idosch@mellanox.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the names of the copyright holders nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * Alternatively, this software may be distributed under the terms of the
20 * GNU General Public License ("GPL") version 2 as published by the Free
21 * Software Foundation.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
36 #include <linux/kernel.h>
37 #include <linux/types.h>
38 #include <linux/rhashtable.h>
39 #include <linux/bitops.h>
40 #include <linux/in6.h>
47 mlxsw_sp_prefix_usage_set(struct mlxsw_sp_prefix_usage
*prefix_usage
,
48 unsigned char prefix_len
)
50 set_bit(prefix_len
, prefix_usage
->b
);
54 mlxsw_sp_prefix_usage_clear(struct mlxsw_sp_prefix_usage
*prefix_usage
,
55 unsigned char prefix_len
)
57 clear_bit(prefix_len
, prefix_usage
->b
);
60 struct mlxsw_sp_fib_key
{
61 unsigned char addr
[sizeof(struct in6_addr
)];
62 unsigned char prefix_len
;
65 struct mlxsw_sp_fib_entry
{
66 struct rhash_head ht_node
;
67 struct mlxsw_sp_fib_key key
;
72 unsigned long prefix_ref_count
[MLXSW_SP_PREFIX_COUNT
];
73 struct mlxsw_sp_prefix_usage prefix_usage
;
76 static const struct rhashtable_params mlxsw_sp_fib_ht_params
= {
77 .key_offset
= offsetof(struct mlxsw_sp_fib_entry
, key
),
78 .head_offset
= offsetof(struct mlxsw_sp_fib_entry
, ht_node
),
79 .key_len
= sizeof(struct mlxsw_sp_fib_key
),
80 .automatic_shrinking
= true,
83 static int mlxsw_sp_fib_entry_insert(struct mlxsw_sp_fib
*fib
,
84 struct mlxsw_sp_fib_entry
*fib_entry
)
86 unsigned char prefix_len
= fib_entry
->key
.prefix_len
;
89 err
= rhashtable_insert_fast(&fib
->ht
, &fib_entry
->ht_node
,
90 mlxsw_sp_fib_ht_params
);
93 if (fib
->prefix_ref_count
[prefix_len
]++ == 0)
94 mlxsw_sp_prefix_usage_set(&fib
->prefix_usage
, prefix_len
);
98 static void mlxsw_sp_fib_entry_remove(struct mlxsw_sp_fib
*fib
,
99 struct mlxsw_sp_fib_entry
*fib_entry
)
101 unsigned char prefix_len
= fib_entry
->key
.prefix_len
;
103 if (--fib
->prefix_ref_count
[prefix_len
] == 0)
104 mlxsw_sp_prefix_usage_clear(&fib
->prefix_usage
, prefix_len
);
105 rhashtable_remove_fast(&fib
->ht
, &fib_entry
->ht_node
,
106 mlxsw_sp_fib_ht_params
);
109 static struct mlxsw_sp_fib_entry
*
110 mlxsw_sp_fib_entry_create(struct mlxsw_sp_fib
*fib
, const void *addr
,
111 size_t addr_len
, unsigned char prefix_len
)
113 struct mlxsw_sp_fib_entry
*fib_entry
;
115 fib_entry
= kzalloc(sizeof(*fib_entry
), GFP_KERNEL
);
118 memcpy(fib_entry
->key
.addr
, addr
, addr_len
);
119 fib_entry
->key
.prefix_len
= prefix_len
;
123 static void mlxsw_sp_fib_entry_destroy(struct mlxsw_sp_fib_entry
*fib_entry
)
128 static struct mlxsw_sp_fib_entry
*
129 mlxsw_sp_fib_entry_lookup(struct mlxsw_sp_fib
*fib
, const void *addr
,
130 size_t addr_len
, unsigned char prefix_len
)
132 struct mlxsw_sp_fib_key key
= {{ 0 } };
134 memcpy(key
.addr
, addr
, addr_len
);
135 key
.prefix_len
= prefix_len
;
136 return rhashtable_lookup_fast(&fib
->ht
, &key
, mlxsw_sp_fib_ht_params
);
139 static struct mlxsw_sp_fib
*mlxsw_sp_fib_create(void)
141 struct mlxsw_sp_fib
*fib
;
144 fib
= kzalloc(sizeof(*fib
), GFP_KERNEL
);
146 return ERR_PTR(-ENOMEM
);
147 err
= rhashtable_init(&fib
->ht
, &mlxsw_sp_fib_ht_params
);
149 goto err_rhashtable_init
;
157 static void mlxsw_sp_fib_destroy(struct mlxsw_sp_fib
*fib
)
159 rhashtable_destroy(&fib
->ht
);
163 static int __mlxsw_sp_router_init(struct mlxsw_sp
*mlxsw_sp
)
165 char rgcr_pl
[MLXSW_REG_RGCR_LEN
];
167 mlxsw_reg_rgcr_pack(rgcr_pl
, true);
168 mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl
, MLXSW_SP_RIF_MAX
);
169 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rgcr
), rgcr_pl
);
172 static void __mlxsw_sp_router_fini(struct mlxsw_sp
*mlxsw_sp
)
174 char rgcr_pl
[MLXSW_REG_RGCR_LEN
];
176 mlxsw_reg_rgcr_pack(rgcr_pl
, false);
177 mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rgcr
), rgcr_pl
);
180 int mlxsw_sp_router_init(struct mlxsw_sp
*mlxsw_sp
)
182 return __mlxsw_sp_router_init(mlxsw_sp
);
185 void mlxsw_sp_router_fini(struct mlxsw_sp
*mlxsw_sp
)
187 __mlxsw_sp_router_fini(mlxsw_sp
);