I don’t have MPLS.
No regression.
> On 4 dec. 2015, at 14:51, Martin Pieuchot <[email protected]> wrote:
>
> To reduce contention in the fast path we can use a mutex(9) to serialize
> read/write operations on the radix tree instead of the KERNEL_LOCK.
>
> Note that the KERNEL_LOCK is still needed to serialize walk/delete/insert
> because a call to rtable_delete() can be made inside rtable_walk(), and
> we cannot use a mutex for such recursive problem.
>
> I'd be interested to know if this helps MPLS fowarding.
>
> Index: net/rtable.c
> ===================================================================
> RCS file: /cvs/src/sys/net/rtable.c,v
> retrieving revision 1.33
> diff -u -p -r1.33 rtable.c
> --- net/rtable.c 4 Dec 2015 13:42:48 -0000 1.33
> +++ net/rtable.c 4 Dec 2015 13:45:53 -0000
> @@ -292,6 +292,10 @@ rtable_l2set(unsigned int rtableid, unsi
> }
>
> #ifndef ART
> +#include <sys/mutex.h>
> +
> +struct mutex rn_mtx = MUTEX_INITIALIZER(IPL_NONE);
> +
> void
> rtable_init_backend(unsigned int keylen)
> {
> @@ -319,15 +323,16 @@ rtable_lookup(unsigned int rtableid, str
> {
> struct radix_node_head *rnh;
> struct radix_node *rn;
> - struct rtentry *rt;
> + struct rtentry *rt = NULL;
>
> rnh = rtable_get(rtableid, dst->sa_family);
> if (rnh == NULL)
> return (NULL);
>
> + mtx_enter(&rn_mtx);
> rn = rn_lookup(dst, mask, rnh);
> if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0)
> - return (NULL);
> + goto out;
>
> rt = ((struct rtentry *)rn);
>
> @@ -335,11 +340,13 @@ rtable_lookup(unsigned int rtableid, str
> if (rnh->rnh_multipath) {
> rt = rt_mpath_matchgate(rt, gateway, prio);
> if (rt == NULL)
> - return (NULL);
> + goto out;
> }
> #endif /* !SMALL_KERNEL */
>
> rtref(rt);
> +out:
> + mtx_leave(&rn_mtx);
> return (rt);
> }
>
> @@ -354,7 +361,7 @@ rtable_match(unsigned int rtableid, stru
> if (rnh == NULL)
> return (NULL);
>
> - KERNEL_LOCK();
> + mtx_enter(&rn_mtx);
> rn = rn_match(dst, rnh);
> if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0)
> goto out;
> @@ -366,7 +373,7 @@ rtable_match(unsigned int rtableid, stru
> rt = rtable_mpath_select(rt, src);
> #endif /* SMALL_KERNEL */
> out:
> - KERNEL_UNLOCK();
> + mtx_leave(&rn_mtx);
> return (rt);
> }
>
> @@ -377,29 +384,37 @@ rtable_insert(unsigned int rtableid, str
> {
> struct radix_node_head *rnh;
> struct radix_node *rn = (struct radix_node *)rt;
> + int error = 0;
> +
> + KERNEL_ASSERT_LOCKED();
>
> rnh = rtable_get(rtableid, dst->sa_family);
> if (rnh == NULL)
> return (EAFNOSUPPORT);
>
> + mtx_enter(&rn_mtx);
> #ifndef SMALL_KERNEL
> if (rnh->rnh_multipath) {
> /* Do not permit exactly the same dst/mask/gw pair. */
> if (rt_mpath_conflict(rnh, dst, mask, gateway, prio,
> ISSET(rt->rt_flags, RTF_MPATH))) {
> - return (EEXIST);
> + error = EEXIST;
> + goto out;
> }
> }
> #endif /* SMALL_KERNEL */
>
> rn = rn_addroute(dst, mask, rnh, rn, prio);
> - if (rn == NULL)
> - return (ESRCH);
> + if (rn == NULL) {
> + error = ESRCH;
> + goto out;
> + }
>
> rt = ((struct rtentry *)rn);
> rtref(rt);
> -
> - return (0);
> +out:
> + mtx_leave(&rn_mtx);
> + return (error);
> }
>
> int
> @@ -408,22 +423,31 @@ rtable_delete(unsigned int rtableid, str
> {
> struct radix_node_head *rnh;
> struct radix_node *rn = (struct radix_node *)rt;
> + int error = 0;
> +
> + KERNEL_ASSERT_LOCKED();
>
> rnh = rtable_get(rtableid, dst->sa_family);
> if (rnh == NULL)
> return (EAFNOSUPPORT);
>
> + mtx_enter(&rn_mtx);
> rn = rn_delete(dst, mask, rnh, rn);
> - if (rn == NULL)
> - return (ESRCH);
> + if (rn == NULL) {
> + error = ESRCH;
> + goto out;
> + }
>
> +#ifdef DIAGNOSTIC
> if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
> panic("active node flags=%x", rn->rn_flags);
> +#endif /* DIAGNOSTIC */
>
> rt = ((struct rtentry *)rn);
> rtfree(rt);
> -
> - return (0);
> +out:
> + mtx_leave(&rn_mtx);
> + return (error);
> }
>
> int
> @@ -432,6 +456,8 @@ rtable_walk(unsigned int rtableid, sa_fa
> {
> struct radix_node_head *rnh;
> int (*f)(struct radix_node *, void *, unsigned int) = (void *)func;
> +
> + KERNEL_ASSERT_LOCKED();
>
> rnh = rtable_get(rtableid, af);
> if (rnh == NULL)
>