Hi,
I'm not sure when it is broken, in old versions, it was assumed the
pipex queues are empty when pipex_iface_stop() is called. The problem
mvs@ found is the assumption is not true any more.
pipex has a mechanism that delete a session when the queues are empty.
819 Static void
820 pipex_timer(void *ignored_arg)
821 {
(snip)
854 case PIPEX_STATE_CLOSED:
855 /*
856 * mbuf queued in pipexinq or pipexoutq may
have a
857 * refererce to this session.
858 */
859 if (!mq_empty(&pipexinq) ||
!mq_empty(&pipexoutq))
860 continue;
861
862 pipex_destroy_session(session);
863 break;
I think using this is better.
How about this?
diff --git a/sys/net/pipex.c b/sys/net/pipex.c
index 2ad7757fee9..6fe14c400bf 100644
--- a/sys/net/pipex.c
+++ b/sys/net/pipex.c
@@ -190,7 +190,7 @@ pipex_iface_stop(struct pipex_iface_context *pipex_iface)
LIST_FOREACH_SAFE(session, &pipex_session_list, session_list,
session_tmp) {
if (session->pipex_iface == pipex_iface)
- pipex_destroy_session(session);
+ pipex_unlink_session(session);
}
}
@@ -470,9 +470,16 @@ pipex_link_session(struct pipex_session *session,
void
pipex_unlink_session(struct pipex_session *session)
{
+ struct radix_node *rn;
+
session->ifindex = 0;
NET_ASSERT_LOCKED();
+ if (!in_nullhost(session->ip_address.sin_addr)) {
+ rn = rn_delete(&session->ip_address, &session->ip_netmask,
+ pipex_rd_head4, (struct radix_node *)session);
+ KASSERT(rn != NULL);
+ }
LIST_REMOVE(session, id_chain);
#if defined(PIPEX_PPTP) || defined(PIPEX_L2TP)
switch (session->protocol) {
@@ -486,10 +493,6 @@ pipex_unlink_session(struct pipex_session *session)
LIST_REMOVE(session, state_list);
LIST_REMOVE(session, session_list);
session->state = PIPEX_STATE_CLOSED;
-
- /* if final session is destroyed, stop timer */
- if (LIST_EMPTY(&pipex_session_list))
- pipex_timer_stop();
}
Static int
@@ -652,20 +655,16 @@ pipex_get_closed(struct pipex_session_list_req *req,
Static int
pipex_destroy_session(struct pipex_session *session)
{
- struct radix_node *rn;
-
/* remove from radix tree and hash chain */
NET_ASSERT_LOCKED();
- if (!in_nullhost(session->ip_address.sin_addr)) {
- rn = rn_delete(&session->ip_address, &session->ip_netmask,
- pipex_rd_head4, (struct radix_node *)session);
- KASSERT(rn != NULL);
- }
-
pipex_unlink_session(session);
pipex_rele_session(session);
+ /* if final session is destroyed, stop timer */
+ if (LIST_EMPTY(&pipex_session_list))
+ pipex_timer_stop();
+
return (0);
}
@@ -739,7 +738,8 @@ pipexintr(void)
mq_delist(&pipexoutq, &ml);
while ((m = ml_dequeue(&ml)) != NULL) {
pkt_session = m->m_pkthdr.ph_cookie;
- if (pkt_session == NULL) {
+ if (pkt_session == NULL ||
+ pkt_session->state == PIPEX_STATE_CLOSED) {
m_freem(m);
continue;
}
@@ -776,7 +776,8 @@ pipexintr(void)
mq_delist(&pipexinq, &ml);
while ((m = ml_dequeue(&ml)) != NULL) {
pkt_session = m->m_pkthdr.ph_cookie;
- if (pkt_session == NULL) {
+ if (pkt_session == NULL ||
+ pkt_session->state == PIPEX_STATE_CLOSED) {
m_freem(m);
continue;
}