* Grow the hash larger or smaller if memory permits. */
| 435 | * Grow the hash larger or smaller if memory permits. |
| 436 | */ |
| 437 | static void |
| 438 | vlan_growhash(struct ifvlantrunk *trunk, int howmuch) |
| 439 | { |
| 440 | struct ifvlan *ifv; |
| 441 | struct ifvlanhead *hash2; |
| 442 | int hwidth2, i, j, n, n2; |
| 443 | |
| 444 | VLAN_XLOCK_ASSERT(); |
| 445 | KASSERT(trunk->hwidth > 0, ("%s: hwidth not positive", __func__)); |
| 446 | |
| 447 | if (howmuch == 0) { |
| 448 | /* Harmless yet obvious coding error */ |
| 449 | printf("%s: howmuch is 0\n", __func__); |
| 450 | return; |
| 451 | } |
| 452 | |
| 453 | hwidth2 = trunk->hwidth + howmuch; |
| 454 | n = 1 << trunk->hwidth; |
| 455 | n2 = 1 << hwidth2; |
| 456 | /* Do not shrink the table below the default */ |
| 457 | if (hwidth2 < VLAN_DEF_HWIDTH) |
| 458 | return; |
| 459 | |
| 460 | hash2 = malloc(sizeof(struct ifvlanhead) * n2, M_VLAN, M_WAITOK); |
| 461 | if (hash2 == NULL) { |
| 462 | printf("%s: out of memory -- hash size not changed\n", |
| 463 | __func__); |
| 464 | return; /* We can live with the old hash table */ |
| 465 | } |
| 466 | for (j = 0; j < n2; j++) |
| 467 | CK_SLIST_INIT(&hash2[j]); |
| 468 | for (i = 0; i < n; i++) |
| 469 | while ((ifv = CK_SLIST_FIRST(&trunk->hash[i])) != NULL) { |
| 470 | CK_SLIST_REMOVE(&trunk->hash[i], ifv, ifvlan, ifv_list); |
| 471 | j = HASH(ifv->ifv_vid, n2 - 1); |
| 472 | CK_SLIST_INSERT_HEAD(&hash2[j], ifv, ifv_list); |
| 473 | } |
| 474 | NET_EPOCH_WAIT(); |
| 475 | free(trunk->hash, M_VLAN); |
| 476 | trunk->hash = hash2; |
| 477 | trunk->hwidth = hwidth2; |
| 478 | trunk->hmask = n2 - 1; |
| 479 | |
| 480 | if (bootverbose) |
| 481 | if_printf(trunk->parent, |
| 482 | "VLAN hash table resized from %d to %d buckets\n", n, n2); |
| 483 | } |
| 484 | |
| 485 | static __inline struct ifvlan * |
| 486 | vlan_gethash(struct ifvlantrunk *trunk, uint16_t vid) |
no test coverage detected