Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 22 Jul 2022 14:29:52 +0000
From:      bugzilla-noreply@freebsd.org
To:        bugs@FreeBSD.org
Subject:   [Bug 265382] VLAN hash-list table thrashing when adding and removing entries
Message-ID:  <bug-265382-227@https.bugs.freebsd.org/bugzilla/>

next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D265382

            Bug ID: 265382
           Summary: VLAN hash-list table thrashing when adding and
                    removing entries
           Product: Base System
           Version: Unspecified
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: dsips@netapp.com
                CC: dsips@netapp.com

vlan_remhash() uses incorrect value for b.

When using the default value for VLAN_DEF_HWIDTH (4), the VLAN hash-list ta=
ble
expands from 16 chains to 32 chains as the 129th entry is added. trunk->hwi=
dth=20
becomes 5. Say a few more entries are added and there are now 135 entries.=
=20
trunk-hwidth will still be 5. If an entry is removed, vlan_remhash() will=20
calculate a value of 32 for b. refcnt will be decremented to 134. The if=20
comparison at line 473 will return true and vlan_growhash() will be called.=
 The=20
VLAN hash-list table will be compressed from 32 chains wide to 16 chains wi=
de.
hwidth will become 4. This is an error, and it can be seen when a new VLAN =
is=20
added. The table will again be expanded. If an entry is then removed, again=
=20
the table is contracted.=20

If the number of VLANS stays in the range of 128-512, each time an insert
follows a remove, the table will expand. Each time a remove follows an
insert, the table will be contracted.

The fix is simple. The line 473 should test that the number of entries has
decreased such that the table should be contracted using what would be the =
new=20
value of hwidth. line 467 should be:

        b =3D 1 << (trunk->hwidth - 1);

For reference:

458  static int
459  vlan_remhash(struct ifvlantrunk *trunk, struct ifvlan *ifv)
460  {
461     int i, b;
462     struct ifvlan *ifv2;
463=20=20
464     VLAN_XLOCK_ASSERT();
465     KASSERT(trunk->hwidth > 0, ("%s: hwidth not positive", __func__));
466=20=20
467     b =3D 1 << trunk->hwidth;
468     i =3D HASH(ifv->ifv_vid, trunk->hmask);
469     CK_SLIST_FOREACH(ifv2, &trunk->hash[i], ifv_list)
470             if (ifv2 =3D=3D ifv) {
471                     trunk->refcnt--;
472                     CK_SLIST_REMOVE(&trunk->hash[i], ifv2, ifvlan,
ifv_list);
473                     if (trunk->refcnt < (b * b) / 2)
474                             vlan_growhash(trunk, -1);
475                     return (0);
476             }
477=20=20
478     panic("%s: vlan not found\n", __func__);
479     return (ENOENT); /*NOTREACHED*/
480 }

--=20
You are receiving this mail because:
You are the assignee for the bug.=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-265382-227>