We are doing all wrong :) We can just unlink pppx(4) related session from `pipex_session_list' if it's time expired. But since this unlinked session is still exists in pppx(4) layer we can access through pppx_get_closed() without any search. We should only add flag to session which identifies it as pppx(4) related.
I hope you like this idea. ---- cut begin ---- Static void pipex_timer(void *ignored_arg) { struct pipex_session *session, *session_tmp; timeout_add_sec(&pipex_timer_ch, pipex_prune); NET_LOCK(); /* walk through */ LIST_FOREACH_SAFE(session, &pipex_session_list, session_list, session_tmp) { switch (session->state) { case PIPEX_STATE_OPENED: if (session->timeout_sec == 0) continue; session->stat.idle_time++; if (session->stat.idle_time < session->timeout_sec) continue; if (session->pppx_session) pipex_unlink_session(session); else pipex_notify_close_session(session); break; /* ... */ } pppx_get_closed(struct pppx_dev *pxd, struct pipex_session_list_req *req) { struct pppx_if *pxi; pxi = pppx_if_find(pxd, req->pdr_session_id, req->pdr_protocol); if (pxi == NULL) return (EINVAL); memset(req, 0, sizeof(*req)); if (session->state == PIPEX_STATE_CLOSED) { req->plr_ppp_id[req->plr_ppp_id_count++] = session->ppp_id; pppx_if_destroy(pxi); } return 0; } ---- cut end ---- On Mon, Aug 10, 2020 at 04:30:27PM +0300, Vitaliy Makkoveev wrote: > On Mon, Aug 10, 2020 at 03:12:02PM +0900, YASUOKA Masahiko wrote: > > Hi, > > > > Thank you for your review. > > > > On Sun, 9 Aug 2020 20:03:50 +0300 > > Vitaliy Makkoveev <m...@openbsd.org> wrote: > > > On Sun, Aug 09, 2020 at 06:20:13PM +0300, Vitaliy Makkoveev wrote: > > >> You propose to unlink pppx(4) related session which reached timeout. I'm > > >> ok with this direction. But I see no reason to rework _get_closed() > > >> routines. > > >> > > >> in pppac(4) case it's assumed what if session is not yet destroyed by > > >> garbage collector, it will be destroyed while we performing PIPEXGCLOSED > > >> command. We can make pppx(4) behavior the same and I propose to > > >> pppx_get_closed() be like below. > > >> > > >> Also, nothing requires to modify pipex_get_closed(). > > >> > > >> ---- cut begin ---- > > > > > > Sorry, I mean > > > > > > pppx_get_closed(struct pppx_dev *pxd, struct pipex_session_list_req *req) > > > { > > > struct pppx_if *pxi; > > > > > > memset(req, 0, sizeof(*req)); > > > > > > while ((pxi = LIST_FIRST(&pxd->pxd_pxis))) { > > > if (pxi->pxi_session->state == session->state = > > > PIPEX_STATE_CLOSED) { > > > req->plr_ppp_id[req->plr_ppp_id_count++] = > > > pxi->pxi_session->ppp_id; > > > pppx_if_destroy(pxi); > > > } > > > } > > > > > > return 0; > > > } > > > > Yes, the diff doesn't seem to be completed but this way also will work. > > > > Usually there is few CLOSED session even if there is a lot of session. > > Also there is no CLOSED session if idle-timeout is not configured. I > > avoided that way because I think checking all sessions' state to find > > such the few sessions is too expensive. > > > > A way I am suggesting: > > > > @@ -622,7 +625,7 @@ pipex_get_stat(struct pipex_session_stat > > > > Static int > > pipex_get_closed(struct pipex_session_list_req *req, > > - struct pipex_iface_context *iface) > > + int (*isowner)(void *, struct pipex_session *), void *ctx) > > { > > struct pipex_session *session, *session_tmp; > > > > @@ -630,7 +633,7 @@ pipex_get_closed(struct pipex_session_li > > bzero(req, sizeof(*req)); > > LIST_FOREACH_SAFE(session, &pipex_close_wait_list, state_list, > > session_tmp) { > > - if (session->pipex_iface != iface) > > + if (!isowner(ctx, session)) > > continue; > > req->plr_ppp_id[req->plr_ppp_id_count++] = session->ppp_id; > > LIST_REMOVE(session, state_list); > > > > uses pipex_close_wait_list which contains only sessions which is timed > > out. > > You are right. pipex_get_closed() walks through `pipex_close_wait_list' > which contains only CLOSE_WAIT sessions. > > According to npppd(8) code we do PIPEXGCLOSED related walkthrough once > per NPPPD_TIMER_TICK_IVAL seconds, which is defined as 4. Is this such > performance impact? > > Also who should destroy these sessions? It's assumed npppd(8) will > destroy them by l2tp_ctrl_timeout() and pptp_ctrl_timeout()? Excuse me > if I'm wrong, but who will destroy sessions in pppoe case? > > > > > >> Also I have one inlined comment within your diff. > > > > >> > @@ -430,6 +425,7 @@ pipex_link_session(struct pipex_session > > >> > struct pipex_iface_context *iface) > > >> > { > > >> > struct pipex_hash_head *chain; > > >> > + struct ifnet *ifp; > > >> > > > >> > NET_ASSERT_LOCKED(); > > >> > > > >> > @@ -442,6 +438,11 @@ pipex_link_session(struct pipex_session > > >> > session->pipex_iface = iface; > > >> > session->ifindex = iface->ifindex; > > >> > > > >> > + ifp = if_get(iface->ifindex); > > >> > + if (ifp != NULL && ifp->if_flags & IFF_POINTOPOINT) > > >> > + session->is_p2p = 1; > > >> > + if_put(ifp); > > >> > + > > >> > > >> I guess NULL `ifp' here exposes us a bug. I like to have assertion here. > > > > ok, I agree here. > > > > > > The diff is updated. > > > > Index: sys/net/if_pppx.c > > =================================================================== > > RCS file: /cvs/src/sys/net/if_pppx.c,v > > retrieving revision 1.98 > > diff -u -p -r1.98 if_pppx.c > > --- sys/net/if_pppx.c 28 Jul 2020 09:53:36 -0000 1.98 > > +++ sys/net/if_pppx.c 10 Aug 2020 06:09:52 -0000 > > @@ -185,6 +185,7 @@ int pppx_config_session(struct pppx_dev > > struct pipex_session_config_req *); > > int pppx_get_stat(struct pppx_dev *, > > struct pipex_session_stat_req *); > > +int pppx_is_owner(void *, struct pipex_session *); > > int pppx_get_closed(struct pppx_dev *, > > struct pipex_session_list_req *); > > int pppx_set_session_descr(struct pppx_dev *, > > @@ -645,14 +646,6 @@ pppx_add_session(struct pppx_dev *pxd, s > > struct in_ifaddr *ia; > > struct sockaddr_in ifaddr; > > > > - /* > > - * XXX: As long as `session' is allocated as part of a `pxi' > > - * it isn't possible to free it separately. So disallow > > - * the timeout feature until this is fixed. > > - */ > > - if (req->pr_timeout_sec != 0) > > - return (EINVAL); > > - > > error = pipex_init_session(&session, req); > > if (error) > > return (error); > > @@ -812,12 +805,22 @@ pppx_get_stat(struct pppx_dev *pxd, stru > > } > > > > int > > -pppx_get_closed(struct pppx_dev *pxd, struct pipex_session_list_req *req) > > +pppx_is_owner(void *ctx, struct pipex_session *session) > > { > > - /* XXX: Only opened sessions exist for pppx(4) */ > > - memset(req, 0, sizeof(*req)); > > + struct pppx_dev *pxd = ctx; > > + struct pppx_if *pxi; > > > > - return 0; > > + pxi = pppx_if_find(pxd, session->session_id, session->protocol); > > + if (pxi != NULL) > > + return (1); > > + > > + return (0); > > +} > > + > > +int > > +pppx_get_closed(struct pppx_dev *pxd, struct pipex_session_list_req *req) > > +{ > > + return (pipex_get_closed(req, pppx_is_owner, pxd)); > > } > > > > int > > @@ -1059,6 +1062,7 @@ static int pppac_ioctl(struct ifnet *, u > > static int pppac_output(struct ifnet *, struct mbuf *, struct sockaddr *, > > struct rtentry *); > > static void pppac_start(struct ifnet *); > > +static int pppac_is_owner(void *, struct pipex_session *); > > > > static inline struct pppac_softc * > > pppac_lookup(dev_t dev) > > @@ -1251,6 +1255,16 @@ pppacwrite(dev_t dev, struct uio *uio, i > > } > > > > int > > +pppac_is_owner(void *ctx, struct pipex_session *session) > > +{ > > + struct pppac_softc *sc = ctx; > > + > > + if (session->ifindex == sc->sc_if.if_index) > > + return (1); > > + return (0); > > +} > > + > > +int > > pppacioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) > > { > > struct pppac_softc *sc = pppac_lookup(dev); > > @@ -1264,6 +1278,13 @@ pppacioctl(dev_t dev, u_long cmd, caddr_ > > break; > > case FIONREAD: > > *(int *)data = mq_hdatalen(&sc->sc_mq); > > + break; > > + > > + case PIPEXGCLOSED: > > + NET_LOCK(); > > + error = pipex_get_closed((struct pipex_session_list_req *)data, > > + pppac_is_owner, sc); > > + NET_UNLOCK(); > > break; > > > > default: > > Index: sys/net/pipex.c > > =================================================================== > > RCS file: /cvs/src/sys/net/pipex.c,v > > retrieving revision 1.123 > > diff -u -p -r1.123 pipex.c > > --- sys/net/pipex.c 4 Aug 2020 09:32:05 -0000 1.123 > > +++ sys/net/pipex.c 10 Aug 2020 06:09:52 -0000 > > @@ -240,11 +240,6 @@ pipex_ioctl(struct pipex_iface_context * > > pipex_iface); > > break; > > > > - case PIPEXGCLOSED: > > - ret = pipex_get_closed((struct pipex_session_list_req *)data, > > - pipex_iface); > > - break; > > - > > default: > > ret = ENOTTY; > > break; > > @@ -430,6 +425,7 @@ pipex_link_session(struct pipex_session > > struct pipex_iface_context *iface) > > { > > struct pipex_hash_head *chain; > > + struct ifnet *ifp; > > > > NET_ASSERT_LOCKED(); > > > > @@ -442,6 +438,12 @@ pipex_link_session(struct pipex_session > > session->pipex_iface = iface; > > session->ifindex = iface->ifindex; > > > > + ifp = if_get(iface->ifindex); > > + KASSERT(ifp != NULL); > > + if (ifp->if_flags & IFF_POINTOPOINT) > > + session->is_p2p = 1; > > + if_put(ifp); > > + > > LIST_INSERT_HEAD(&pipex_session_list, session, session_list); > > chain = PIPEX_ID_HASHTABLE(session->session_id); > > LIST_INSERT_HEAD(chain, session, id_chain); > > @@ -469,6 +471,8 @@ pipex_unlink_session(struct pipex_sessio > > session->ifindex = 0; > > > > NET_ASSERT_LOCKED(); > > + if (session->state == PIPEX_STATE_CLOSED) > > + return; > > LIST_REMOVE(session, id_chain); > > #if defined(PIPEX_PPTP) || defined(PIPEX_L2TP) > > switch (session->protocol) { > > @@ -622,7 +626,7 @@ pipex_get_stat(struct pipex_session_stat > > > > Static int > > pipex_get_closed(struct pipex_session_list_req *req, > > - struct pipex_iface_context *iface) > > + int (*isowner)(void *, struct pipex_session *), void *ctx) > > { > > struct pipex_session *session, *session_tmp; > > > > @@ -630,7 +634,7 @@ pipex_get_closed(struct pipex_session_li > > bzero(req, sizeof(*req)); > > LIST_FOREACH_SAFE(session, &pipex_close_wait_list, state_list, > > session_tmp) { > > - if (session->pipex_iface != iface) > > + if (!isowner(ctx, session)) > > continue; > > req->plr_ppp_id[req->plr_ppp_id_count++] = session->ppp_id; > > LIST_REMOVE(session, state_list); > > @@ -766,13 +770,13 @@ pipex_timer(void *ignored_arg) > > if (session->stat.idle_time < PIPEX_CLOSE_TIMEOUT) > > continue; > > > > - if (session->state == PIPEX_STATE_CLOSE_WAIT) > > - LIST_REMOVE(session, state_list); > > - session->state = PIPEX_STATE_CLOSED; > > /* FALLTHROUGH */ > > > > case PIPEX_STATE_CLOSED: > > - pipex_destroy_session(session); > > + if (session->is_p2p) > > + pipex_unlink_session(session); > > + else > > + pipex_destroy_session(session); > > break; > > > > default: > > Index: sys/net/pipex_local.h > > =================================================================== > > RCS file: /cvs/src/sys/net/pipex_local.h,v > > retrieving revision 1.39 > > diff -u -p -r1.39 pipex_local.h > > --- sys/net/pipex_local.h 4 Aug 2020 09:32:05 -0000 1.39 > > +++ sys/net/pipex_local.h 10 Aug 2020 06:09:52 -0000 > > @@ -169,7 +169,8 @@ struct pipex_session { > > uint16_t ip_forward:1, /* [N] {en|dis}ableIP forwarding */ > > ip6_forward:1, /* [I] {en|dis}able IPv6 forwarding */ > > is_multicast:1, /* [I] virtual entry for multicast */ > > - reserved:13; > > + is_p2p:1, /* [I] interface is point2point(pppx) */ > > + reserved:12; > > uint16_t protocol; /* [I] tunnel protocol (PK) */ > > uint16_t session_id; /* [I] session-id (PK) */ > > uint16_t peer_session_id; /* [I] peer's session-id */ > > @@ -391,7 +392,7 @@ int pipex_config_sessi > > int pipex_get_stat (struct pipex_session_stat_req *, > > struct pipex_iface_context *); > > int pipex_get_closed (struct pipex_session_list_req *, > > - struct pipex_iface_context *); > > + int (*)(void *, struct pipex_session *), void *); > > int pipex_destroy_session (struct pipex_session *); > > struct pipex_session *pipex_lookup_by_ip_address (struct in_addr); > > struct pipex_session *pipex_lookup_by_session_id (int, int); > > >