svn commit: r349198 - releng/12.0/sys/net
Gleb Smirnoff
glebius at freebsd.org
Mon Jun 24 21:25:50 UTC 2019
Hi,
On Wed, Jun 19, 2019 at 04:41:18PM +0000, Gordon Tetlow wrote:
G> Author: gordon
G> Date: Wed Jun 19 16:41:18 2019
G> New Revision: 349198
G> URL: https://svnweb.freebsd.org/changeset/base/349198
G>
G> Log:
G> Fix incorrect locking in networking stack.
G>
G> Approved by: so
G> Security: FreeBSD-EN-19:11.net
do I understand correct that problem isn't applicable to head, since
it was accidentially covered in r340413? Either fix for stable or
r340413 aren't a good looking code.
My general comment about if_addr_rlock/if_maddr_lock is that they
are my most hated functions, since they are one of biggest obstacles
on making NIC drivers less aware of what's inside struct ifnet.
In my non-finished projects/ifnet branch, there is a different
KPI to achieve traversal of address lists:
/*
* Traversing through interface address lists.
*/
typedef void ifaddr_cb_t(void *, struct sockaddr *, struct sockaddr *,
struct sockaddr *);
typedef void ifmaddr_cb_t(void *, struct sockaddr *);
void if_foreach_addr(if_t, ifaddr_cb_t, void *);
void if_foreach_maddr(if_t, ifmaddr_cb_t, void *);
The functions are internal to if.c and do whatever locking
is approprite in our kernel. Mutexes before, and epoch now.
And in the driver side this would look like this:
static void
bge_hash_maddr(void *arg, struct sockaddr *maddr)
{
struct sockaddr_dl *sdl = (struct sockaddr_dl *)maddr;
uint32_t *hashes = arg;
int h;
if (sdl->sdl_family != AF_LINK)
return;
h = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN) & 0x7F;
hashes[(h & 0x60) >> 5] |= 1 << (h & 0x1F);
}
static void
bge_setmulti(struct bge_softc *sc)
{
uint32_t hashes[4] = { 0, 0, 0, 0 };
int i;
BGE_LOCK_ASSERT(sc);
if (sc->bge_if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
for (i = 0; i < 4; i++)
CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0xFFFFFFFF);
return;
}
/* First, zot all the existing filters. */
for (i = 0; i < 4; i++)
CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0);
if_foreach_maddr(sc->bge_ifp, bge_hash_maddr, hashes);
for (i = 0; i < 4; i++)
CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), hashes[i]);
}
IMHO, much cleaner and independent of struct ifnet than
if_maddr_lock() + traversal, and better than if_multiaddr_count +
if_multiaddr_array since doesn't require allocating memory.
I'd say that there have been enough pain around interface address
traversal, so I would like to go forward with the following plan:
1) Introduce if_foreach_addr/if_foreach_maddr
2) Convert all drivers to this KPI.
3) Declare if_addr_lock/if_maddr_lock and if_multiaddr_count+if_multiaddr_array
gone in 14.0
4) Indeed make them gone in head once stable/13 is forked.
Any objections?
--
Gleb Smirnoff
More information about the svn-src-all
mailing list