fib_semantics.c (fa2e1ba3e9e39072fa7a6a9d11ac432c505b4ac7) fib_semantics.c (ca73b68aca4a242d71a86818789640ca3b53744a)
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * INET An implementation of the TCP/IP protocol suite for the LINUX
4 * operating system. INET is implemented using the BSD Socket
5 * interface as the means of communication with the user level.
6 *
7 * IPv4 Forwarding Information Base: semantics.
8 *

--- 1243 unchanged lines hidden (view full) ---

1252fib_info_laddrhash_bucket(const struct net *net, __be32 val)
1253{
1254 u32 slot = hash_32(net_hash_mix(net) ^ (__force u32)val,
1255 fib_info_hash_bits);
1256
1257 return &fib_info_laddrhash[slot];
1258}
1259
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * INET An implementation of the TCP/IP protocol suite for the LINUX
4 * operating system. INET is implemented using the BSD Socket
5 * interface as the means of communication with the user level.
6 *
7 * IPv4 Forwarding Information Base: semantics.
8 *

--- 1243 unchanged lines hidden (view full) ---

1252fib_info_laddrhash_bucket(const struct net *net, __be32 val)
1253{
1254 u32 slot = hash_32(net_hash_mix(net) ^ (__force u32)val,
1255 fib_info_hash_bits);
1256
1257 return &fib_info_laddrhash[slot];
1258}
1259
1260static struct hlist_head *fib_info_hash_alloc(int bytes)
1261{
1262 if (bytes <= PAGE_SIZE)
1263 return kzalloc(bytes, GFP_KERNEL);
1264 else
1265 return (struct hlist_head *)
1266 __get_free_pages(GFP_KERNEL | __GFP_ZERO,
1267 get_order(bytes));
1268}
1269
1270static void fib_info_hash_free(struct hlist_head *hash, int bytes)
1271{
1272 if (!hash)
1273 return;
1274
1275 if (bytes <= PAGE_SIZE)
1276 kfree(hash);
1277 else
1278 free_pages((unsigned long) hash, get_order(bytes));
1279}
1280
1281static void fib_info_hash_move(struct hlist_head *new_info_hash,
1282 struct hlist_head *new_laddrhash,
1283 unsigned int new_size)
1284{
1285 struct hlist_head *old_info_hash, *old_laddrhash;
1286 unsigned int old_size = fib_info_hash_size;
1260static void fib_info_hash_move(struct hlist_head *new_info_hash,
1261 struct hlist_head *new_laddrhash,
1262 unsigned int new_size)
1263{
1264 struct hlist_head *old_info_hash, *old_laddrhash;
1265 unsigned int old_size = fib_info_hash_size;
1287 unsigned int i, bytes;
1266 unsigned int i;
1288
1289 spin_lock_bh(&fib_info_lock);
1290 old_info_hash = fib_info_hash;
1291 old_laddrhash = fib_info_laddrhash;
1292 fib_info_hash_size = new_size;
1293 fib_info_hash_bits = ilog2(new_size);
1294
1295 for (i = 0; i < old_size; i++) {

--- 24 unchanged lines hidden (view full) ---

1320 ldest = fib_info_laddrhash_bucket(fi->fib_net,
1321 fi->fib_prefsrc);
1322 hlist_add_head(&fi->fib_lhash, ldest);
1323 }
1324 }
1325
1326 spin_unlock_bh(&fib_info_lock);
1327
1267
1268 spin_lock_bh(&fib_info_lock);
1269 old_info_hash = fib_info_hash;
1270 old_laddrhash = fib_info_laddrhash;
1271 fib_info_hash_size = new_size;
1272 fib_info_hash_bits = ilog2(new_size);
1273
1274 for (i = 0; i < old_size; i++) {

--- 24 unchanged lines hidden (view full) ---

1299 ldest = fib_info_laddrhash_bucket(fi->fib_net,
1300 fi->fib_prefsrc);
1301 hlist_add_head(&fi->fib_lhash, ldest);
1302 }
1303 }
1304
1305 spin_unlock_bh(&fib_info_lock);
1306
1328 bytes = old_size * sizeof(struct hlist_head *);
1329 fib_info_hash_free(old_info_hash, bytes);
1330 fib_info_hash_free(old_laddrhash, bytes);
1307 kvfree(old_info_hash);
1308 kvfree(old_laddrhash);
1331}
1332
1333__be32 fib_info_update_nhc_saddr(struct net *net, struct fib_nh_common *nhc,
1334 unsigned char scope)
1335{
1336 struct fib_nh *nh;
1337
1338 if (nhc->nhc_family != AF_INET)

--- 100 unchanged lines hidden (view full) ---

1439
1440 err = -ENOBUFS;
1441
1442 /* Paired with WRITE_ONCE() in fib_release_info() */
1443 if (READ_ONCE(fib_info_cnt) >= fib_info_hash_size) {
1444 unsigned int new_size = fib_info_hash_size << 1;
1445 struct hlist_head *new_info_hash;
1446 struct hlist_head *new_laddrhash;
1309}
1310
1311__be32 fib_info_update_nhc_saddr(struct net *net, struct fib_nh_common *nhc,
1312 unsigned char scope)
1313{
1314 struct fib_nh *nh;
1315
1316 if (nhc->nhc_family != AF_INET)

--- 100 unchanged lines hidden (view full) ---

1417
1418 err = -ENOBUFS;
1419
1420 /* Paired with WRITE_ONCE() in fib_release_info() */
1421 if (READ_ONCE(fib_info_cnt) >= fib_info_hash_size) {
1422 unsigned int new_size = fib_info_hash_size << 1;
1423 struct hlist_head *new_info_hash;
1424 struct hlist_head *new_laddrhash;
1447 unsigned int bytes;
1425 size_t bytes;
1448
1449 if (!new_size)
1450 new_size = 16;
1426
1427 if (!new_size)
1428 new_size = 16;
1451 bytes = new_size * sizeof(struct hlist_head *);
1452 new_info_hash = fib_info_hash_alloc(bytes);
1453 new_laddrhash = fib_info_hash_alloc(bytes);
1429 bytes = (size_t)new_size * sizeof(struct hlist_head *);
1430 new_info_hash = kvzalloc(bytes, GFP_KERNEL);
1431 new_laddrhash = kvzalloc(bytes, GFP_KERNEL);
1454 if (!new_info_hash || !new_laddrhash) {
1432 if (!new_info_hash || !new_laddrhash) {
1455 fib_info_hash_free(new_info_hash, bytes);
1456 fib_info_hash_free(new_laddrhash, bytes);
1457 } else
1433 kvfree(new_info_hash);
1434 kvfree(new_laddrhash);
1435 } else {
1458 fib_info_hash_move(new_info_hash, new_laddrhash, new_size);
1436 fib_info_hash_move(new_info_hash, new_laddrhash, new_size);
1459
1437 }
1460 if (!fib_info_hash_size)
1461 goto failure;
1462 }
1463
1464 fi = kzalloc(struct_size(fi, fib_nh, nhs), GFP_KERNEL);
1465 if (!fi)
1466 goto failure;
1467 fi->fib_metrics = ip_fib_metrics_init(fi->fib_net, cfg->fc_mx,

--- 809 unchanged lines hidden ---
1438 if (!fib_info_hash_size)
1439 goto failure;
1440 }
1441
1442 fi = kzalloc(struct_size(fi, fib_nh, nhs), GFP_KERNEL);
1443 if (!fi)
1444 goto failure;
1445 fi->fib_metrics = ip_fib_metrics_init(fi->fib_net, cfg->fc_mx,

--- 809 unchanged lines hidden ---