On Thu, Apr 21, 2022 at 03:25:03PM +0200, Alexander Bluhm wrote:
> Hi,
>
> As claudio@ wants to refactor router timer before making them MP
> safe, I would like to protect them with kernel lock. It should fix
> this panic.
>
> https://marc.info/?l=openbsd-tech&m=164038527425440&w=2
>
> I hope this is the final step before running IP forwarding in
> parallel.
>
> ok?
I prefer the other diff, I don't like that other diff but this one is worse.
> bluhm
>
> Index: netinet/ip_icmp.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_icmp.c,v
> retrieving revision 1.188
> diff -u -p -r1.188 ip_icmp.c
> --- netinet/ip_icmp.c 20 Apr 2022 09:38:26 -0000 1.188
> +++ netinet/ip_icmp.c 21 Apr 2022 12:45:40 -0000
> @@ -634,8 +634,10 @@ reflect:
> rtredirect(sintosa(&sdst), sintosa(&sgw),
> sintosa(&ssrc), &newrt, m->m_pkthdr.ph_rtableid);
> if (newrt != NULL && icmp_redirtimeout > 0) {
> + KERNEL_LOCK();
> rt_timer_add(newrt, icmp_redirect_timeout,
> icmp_redirect_timeout_q, m->m_pkthdr.ph_rtableid);
> + KERNEL_UNLOCK();
> }
> rtfree(newrt);
> pfctlinput(PRC_REDIRECT_HOST, sintosa(&sdst));
> @@ -884,8 +886,10 @@ icmp_sysctl(int *name, u_int namelen, vo
> NET_LOCK();
> error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
> &icmp_redirtimeout, 0, INT_MAX);
> + KERNEL_LOCK();
> rt_timer_queue_change(icmp_redirect_timeout_q,
> icmp_redirtimeout);
> + KERNEL_UNLOCK();
> NET_UNLOCK();
> break;
>
> @@ -975,8 +979,10 @@ icmp_mtudisc_clone(struct in_addr dst, u
> rt = nrt;
> rtm_send(rt, RTM_ADD, 0, rtableid);
> }
> + KERNEL_LOCK();
> error = rt_timer_add(rt, icmp_mtudisc_timeout, ip_mtudisc_timeout_q,
> rtableid);
> + KERNEL_UNLOCK();
> if (error)
> goto bad;
>
> Index: netinet/ip_input.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v
> retrieving revision 1.367
> diff -u -p -r1.367 ip_input.c
> --- netinet/ip_input.c 20 Apr 2022 09:38:26 -0000 1.367
> +++ netinet/ip_input.c 21 Apr 2022 13:00:33 -0000
> @@ -1616,9 +1616,11 @@ ip_sysctl(int *name, u_int namelen, void
> NET_LOCK();
> error = sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtudisc);
> if (ip_mtudisc == 0) {
> + KERNEL_LOCK();
> rt_timer_queue_destroy(ip_mtudisc_timeout_q);
> ip_mtudisc_timeout_q =
> rt_timer_queue_create(ip_mtudisc_timeout);
> + KERNEL_UNLOCK();
> }
> NET_UNLOCK();
> return error;
> @@ -1626,8 +1628,10 @@ ip_sysctl(int *name, u_int namelen, void
> NET_LOCK();
> error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
> &ip_mtudisc_timeout, 0, INT_MAX);
> + KERNEL_LOCK();
> rt_timer_queue_change(ip_mtudisc_timeout_q,
> ip_mtudisc_timeout);
> + KERNEL_UNLOCK();
> NET_UNLOCK();
> return (error);
> #ifdef IPSEC
> Index: netinet/ip_mroute.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_mroute.c,v
> retrieving revision 1.131
> diff -u -p -r1.131 ip_mroute.c
> --- netinet/ip_mroute.c 15 Dec 2021 17:21:08 -0000 1.131
> +++ netinet/ip_mroute.c 21 Apr 2022 13:02:43 -0000
> @@ -520,7 +520,9 @@ ip_mrouter_init(struct socket *so, struc
> return (EADDRINUSE);
>
> ip_mrouter[rtableid] = so;
> + KERNEL_LOCK();
> mrouterq[rtableid] = rt_timer_queue_create(MCAST_EXPIRE_FREQUENCY);
> + KERNEL_UNLOCK();
>
> return (0);
> }
> @@ -572,7 +574,9 @@ ip_mrouter_done(struct socket *so)
>
> mrt_api_config = 0;
>
> + KERNEL_LOCK();
> rt_timer_queue_destroy(mrouterq[rtableid]);
> + KERNEL_UNLOCK();
> mrouterq[rtableid] = NULL;
> ip_mrouter[rtableid] = NULL;
> mrt_count[rtableid] = 0;
> @@ -799,8 +803,10 @@ mfc_expire_route(struct rtentry *rt, str
> /* Not expired, add it back to the queue. */
> if (mfc->mfc_expire == 0) {
> mfc->mfc_expire = 1;
> + KERNEL_LOCK();
> rt_timer_add(rt, mfc_expire_route, mrouterq[rtableid],
> rtableid);
> + KERNEL_UNLOCK();
> return;
> }
>
> @@ -834,8 +840,10 @@ mfc_add_route(struct ifnet *ifp, struct
>
> rt->rt_llinfo = (caddr_t)mfc;
>
> + KERNEL_LOCK();
> rt_timer_add(rt, mfc_expire_route, mrouterq[rtableid],
> rtableid);
> + KERNEL_UNLOCK();
>
> mfc->mfc_parent = mfccp->mfcc_parent;
> mfc->mfc_pkt_cnt = 0;
> @@ -1342,7 +1350,9 @@ mrt_mcast_del(struct rtentry *rt, unsign
> int error;
>
> /* Remove all timers related to this route. */
> + KERNEL_LOCK();
> rt_timer_remove_all(rt);
> + KERNEL_UNLOCK();
>
> free(rt->rt_llinfo, M_MRTABLE, sizeof(struct mfc));
> rt->rt_llinfo = NULL;
> Index: netinet6/icmp6.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/icmp6.c,v
> retrieving revision 1.239
> diff -u -p -r1.239 icmp6.c
> --- netinet6/icmp6.c 20 Apr 2022 09:38:26 -0000 1.239
> +++ netinet6/icmp6.c 21 Apr 2022 12:48:18 -0000
> @@ -987,7 +987,9 @@ icmp6_mtudisc_update(struct ip6ctlparam
> * allow non-validated cases if memory is plenty, to make traffic
> * from non-connected pcb happy.
> */
> + KERNEL_LOCK();
> rtcount = rt_timer_queue_count(icmp6_mtudisc_timeout_q);
> + KERNEL_UNLOCK();
> if (validated) {
> if (0 <= icmp6_mtudisc_hiwat && rtcount > icmp6_mtudisc_hiwat)
> return;
> @@ -1383,7 +1385,9 @@ icmp6_redirect_input(struct mbuf *m, int
> * work just fine even if we do not install redirect route
> * (there will be additional hops, though).
> */
> + KERNEL_LOCK();
> rtcount = rt_timer_queue_count(icmp6_redirect_timeout_q);
> + KERNEL_UNLOCK();
> if (0 <= ip6_maxdynroutes && rtcount >= ip6_maxdynroutes)
> goto freeit;
> else if (0 <= icmp6_redirect_lowat &&
> @@ -1405,8 +1409,10 @@ icmp6_redirect_input(struct mbuf *m, int
> rtredirect(sin6tosa(&sdst), sin6tosa(&sgw), sin6tosa(&ssrc),
> &newrt, m->m_pkthdr.ph_rtableid);
> if (newrt != NULL && icmp6_redirtimeout > 0) {
> + KERNEL_LOCK();
> rt_timer_add(newrt, icmp6_redirect_timeout,
> icmp6_redirect_timeout_q, m->m_pkthdr.ph_rtableid);
> + KERNEL_UNLOCK();
> }
> rtfree(newrt);
> }
> @@ -1829,8 +1835,10 @@ icmp6_mtudisc_clone(struct sockaddr_in6
> rt = nrt;
> rtm_send(rt, RTM_ADD, 0, rtableid);
> }
> + KERNEL_LOCK();
> error = rt_timer_add(rt, icmp6_mtudisc_timeout, icmp6_mtudisc_timeout_q,
> rtableid);
> + KERNEL_UNLOCK();
> if (error)
> goto bad;
>
> @@ -1921,8 +1929,10 @@ icmp6_sysctl(int *name, u_int namelen, v
> NET_LOCK();
> error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
> &icmp6_redirtimeout, 0, INT_MAX);
> + KERNEL_LOCK();
> rt_timer_queue_change(icmp6_redirect_timeout_q,
> icmp6_redirtimeout);
> + KERNEL_UNLOCK();
> NET_UNLOCK();
> break;
>
> Index: netinet6/ip6_input.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_input.c,v
> retrieving revision 1.241
> diff -u -p -r1.241 ip6_input.c
> --- netinet6/ip6_input.c 20 Apr 2022 09:38:26 -0000 1.241
> +++ netinet6/ip6_input.c 21 Apr 2022 12:48:51 -0000
> @@ -1456,8 +1456,10 @@ ip6_sysctl(int *name, u_int namelen, voi
> NET_LOCK();
> error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
> &ip6_mtudisc_timeout, 0, INT_MAX);
> + KERNEL_LOCK();
> rt_timer_queue_change(icmp6_mtudisc_timeout_q,
> ip6_mtudisc_timeout);
> + KERNEL_UNLOCK();
> NET_UNLOCK();
> return (error);
> case IPV6CTL_IFQUEUE:
> Index: netinet6/ip6_mroute.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_mroute.c,v
> retrieving revision 1.127
> diff -u -p -r1.127 ip6_mroute.c
> --- netinet6/ip6_mroute.c 15 Dec 2021 17:21:08 -0000 1.127
> +++ netinet6/ip6_mroute.c 21 Apr 2022 12:50:04 -0000
> @@ -494,7 +494,9 @@ ip6_mrouter_init(struct socket *so, int
>
> ip6_mrouter[rtableid] = so;
> ip6_mrouter_ver = cmd;
> + KERNEL_LOCK();
> mrouter6q[rtableid] = rt_timer_queue_create(MCAST_EXPIRE_TIMEOUT);
> + KERNEL_UNLOCK();
>
> return (0);
> }
> @@ -544,7 +546,9 @@ ip6_mrouter_done(struct socket *so)
> ip6_mrouter_detach(ifp);
> }
>
> + KERNEL_LOCK();
> rt_timer_queue_destroy(mrouter6q[rtableid]);
> + KERNEL_UNLOCK();
> ip6_mrouter[inp->inp_rtableid] = NULL;
> ip6_mrouter_ver = 0;
> mrouter6q[rtableid] = NULL;
> @@ -682,7 +686,9 @@ mf6c_add_route(struct ifnet *ifp, struct
> }
>
> rt->rt_llinfo = (caddr_t)mf6c;
> + KERNEL_LOCK();
> rt_timer_add(rt, mf6c_expire_route, mrouter6q[rtableid], rtableid);
> + KERNEL_UNLOCK();
> mf6c->mf6c_parent = mf6cc->mf6cc_parent;
> rtfree(rt);
>
> @@ -1010,8 +1016,10 @@ mf6c_expire_route(struct rtentry *rt, st
>
> if (mf6c->mf6c_expire == 0) {
> mf6c->mf6c_expire = 1;
> + KERNEL_LOCK();
> rt_timer_add(rt, mf6c_expire_route, mrouter6q[rtableid],
> rtableid);
> + KERNEL_UNLOCK();
> return;
> }
>
> @@ -1272,7 +1280,9 @@ mrt6_mcast_del(struct rtentry *rt, unsig
> int error;
>
> /* Remove all timers related to this route. */
> + KERNEL_LOCK();
> rt_timer_remove_all(rt);
> + KERNEL_UNLOCK();
>
> free(rt->rt_llinfo, M_MRTABLE, sizeof(struct mf6c));
> rt->rt_llinfo = NULL;
>
--
:wq Claudio