The `pipex_list_mtx' mutex(9) protects global pipex(4) lists so it need
to be taken while we perform this foreach loop.
The all sessions loop was reworked to make possible to drop the lock
within. This is required because pipex_ppp_output() takes scheduler lock
when performs ip_send().
Index: sys/net/pipex.c
===================================================================
RCS file: /cvs/src/sys/net/pipex.c,v
retrieving revision 1.143
diff -u -p -r1.143 pipex.c
--- sys/net/pipex.c 2 Jul 2022 08:50:42 -0000 1.143
+++ sys/net/pipex.c 7 Jul 2022 21:52:16 -0000
@@ -842,20 +842,39 @@ pipex_ip_output(struct mbuf *m0, struct
m0->m_flags &= ~(M_BCAST|M_MCAST);
- LIST_FOREACH(session_tmp, &pipex_session_list, session_list) {
+ mtx_enter(&pipex_list_mtx);
+
+ session_tmp = LIST_FIRST(&pipex_session_list);
+ while (session_tmp != NULL) {
+ struct pipex_session *session_save = NULL;
+
if (session_tmp->ownersc != session->ownersc)
- continue;
+ goto next;
if ((session->flags & (PIPEX_SFLAGS_IP_FORWARD |
PIPEX_SFLAGS_IP6_FORWARD)) == 0)
- continue;
+ goto next;
m = m_copym(m0, 0, M_COPYALL, M_NOWAIT);
if (m == NULL) {
counters_inc(session->stat_counters,
pxc_oerrors);
- continue;
+ goto next;
}
+
+ refcnt_take(&session->pxs_refcnt);
+ mtx_leave(&pipex_list_mtx);
+
pipex_ppp_output(m, session_tmp, PPP_IP);
+
+ mtx_enter(&pipex_list_mtx);
+ session_save = session_tmp;
+next:
+ session_tmp = LIST_NEXT(session_tmp, session_list);
+ if (session_save != NULL)
+ pipex_rele_session(session_save);
}
+
+ mtx_leave(&pipex_list_mtx);
+
m_freem(m0);
}