diff options
author | rwatson <rwatson@FreeBSD.org> | 2008-06-26 23:05:28 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2008-06-26 23:05:28 +0000 |
commit | 46dd6e44fc7f70ee8d82d41fb83bedfb2c7829c8 (patch) | |
tree | 1a406ca586e36376a4f6fc527aef4c5964c174b5 /sys/net/if_var.h | |
parent | 74854699d26c7fb406a5e0029641de33e278cbce (diff) | |
download | FreeBSD-src-46dd6e44fc7f70ee8d82d41fb83bedfb2c7829c8.zip FreeBSD-src-46dd6e44fc7f70ee8d82d41fb83bedfb2c7829c8.tar.gz |
Introduce locking around use of ifindex_table, whose use was previously
unsynchronized. While races were extremely rare, we've now had a
couple of reports of panics in environments involving large numbers of
IPSEC tunnels being added very quickly on an active system.
- Add accessor functions ifnet_byindex(), ifaddr_byindex(),
ifdev_byindex() to replace existing accessor macros. These functions
now acquire the ifnet lock before derefencing the table.
- Add IFNET_WLOCK_ASSERT().
- Add static accessor functions ifnet_setbyindex(), ifdev_setbyindex(),
which set values in the table either asserting of acquiring the ifnet
lock.
- Use accessor functions throughout if.c to modify and read
ifindex_table.
- Rework ifnet attach/detach to lock around ifindex_table modification.
Note that these changes simply close races around use of ifindex_table,
and make no attempt to solve the probem of disappearing ifnets. Further
refinement of this work, including with respect to ifindex_table
resizing, is still required.
In a future change, the ifnet lock should be converted from a mutex to an
rwlock in order to reduce contention.
Reviewed and tested by: brooks
Diffstat (limited to 'sys/net/if_var.h')
-rw-r--r-- | sys/net/if_var.h | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/sys/net/if_var.h b/sys/net/if_var.h index d738e32..2e3dc0d 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -636,6 +636,7 @@ extern struct mtx ifnet_lock; mtx_init(&ifnet_lock, "ifnet", NULL, MTX_DEF | MTX_RECURSE) #define IFNET_WLOCK() mtx_lock(&ifnet_lock) #define IFNET_WUNLOCK() mtx_unlock(&ifnet_lock) +#define IFNET_WLOCK_ASSERT() mtx_assert(&ifnet_lock, MA_OWNED) #define IFNET_RLOCK() IFNET_WLOCK() #define IFNET_RUNLOCK() IFNET_WUNLOCK() @@ -644,17 +645,16 @@ struct ifindex_entry { struct cdev *ife_dev; }; -#define ifnet_byindex(idx) ifindex_table[(idx)].ife_ifnet +struct ifnet *ifnet_byindex(u_short idx); /* * Given the index, ifaddr_byindex() returns the one and only * link-level ifaddr for the interface. You are not supposed to use * it to traverse the list of addresses associated to the interface. */ -#define ifaddr_byindex(idx) ifnet_byindex(idx)->if_addr -#define ifdev_byindex(idx) ifindex_table[(idx)].ife_dev +struct ifaddr *ifaddr_byindex(u_short idx); +struct cdev *ifdev_byindex(u_short idx); extern struct ifnethead ifnet; -extern struct ifindex_entry *ifindex_table; extern int ifqmaxlen; extern struct ifnet *loif; /* first loopback interface */ extern int if_index; |