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)
> 

Reply via email to