On Sat, Aug 15, 2020 at 05:42:06PM +0900, YASUOKA Masahiko wrote:
> Let me update the diff. A bug found by the test.
>
Hello Yasuoka.
I like your idea to kill `pipex_iface_context'. I had trying to keep it
by myself and this was wrong way. Could you rework your diff to be
against the recent sources?
Also I have little comments below.
> diff --git a/sys/net/if_pppx.c b/sys/net/if_pppx.c
> index 62b85bc34af..6d3de6973bd 100644
> --- a/sys/net/if_pppx.c
> +++ b/sys/net/if_pppx.c
> @@ -163,7 +163,6 @@ struct pppx_if {
> struct ifnet pxi_if;
> struct pppx_dev *pxi_dev; /* [I] */
> struct pipex_session *pxi_session; /* [I] */
> - struct pipex_iface_context pxi_ifcontext; /* [N] */
> };
>
> static inline int
> @@ -181,12 +180,6 @@ int pppx_add_session(struct pppx_dev *,
> struct pipex_session_req *);
> int pppx_del_session(struct pppx_dev *,
> struct pipex_session_close_req *);
> -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_get_closed(struct pppx_dev *,
> - struct pipex_session_list_req *);
> int pppx_set_session_descr(struct pppx_dev *,
> struct pipex_session_descr_req *);
>
> @@ -424,17 +417,6 @@ pppxioctl(dev_t dev, u_long cmd, caddr_t addr, int
> flags, struct proc *p)
>
> NET_LOCK();
> switch (cmd) {
> - case PIPEXSMODE:
> - /*
> - * npppd always enables on open, and only disables before
> - * closing. we cheat and let open and close do that, so lie
> - * to npppd.
> - */
> - break;
> - case PIPEXGMODE:
> - *(int *)addr = 1;
> - break;
> -
> case PIPEXASESSION:
> error = pppx_add_session(pxd,
> (struct pipex_session_req *)addr);
> @@ -445,21 +427,6 @@ pppxioctl(dev_t dev, u_long cmd, caddr_t addr, int
> flags, struct proc *p)
> (struct pipex_session_close_req *)addr);
> break;
>
> - case PIPEXCSESSION:
> - error = pppx_config_session(pxd,
> - (struct pipex_session_config_req *)addr);
> - break;
> -
> - case PIPEXGSTAT:
> - error = pppx_get_stat(pxd,
> - (struct pipex_session_stat_req *)addr);
> - break;
> -
> - case PIPEXGCLOSED:
> - error = pppx_get_closed(pxd,
> - (struct pipex_session_list_req *)addr);
> - break;
> -
> case PIPEXSIFDESCR:
> error = pppx_set_session_descr(pxd,
> (struct pipex_session_descr_req *)addr);
> @@ -472,7 +439,7 @@ pppxioctl(dev_t dev, u_long cmd, caddr_t addr, int flags,
> struct proc *p)
> break;
>
> default:
> - error = ENOTTY;
> + error = pipex_ioctl(pxd, cmd, addr);
> break;
> }
> NET_UNLOCK();
> @@ -742,11 +709,7 @@ pppx_add_session(struct pppx_dev *pxd, struct
> pipex_session_req *req)
> if_addrhooks_run(ifp);
> }
>
> - /* fake a pipex interface context */
> - pxi->pxi_ifcontext.ifindex = ifp->if_index;
> - pxi->pxi_ifcontext.pipexmode = PIPEX_ENABLED;
> -
> - error = pipex_link_session(session, &pxi->pxi_ifcontext);
> + error = pipex_link_session(session, ifp, pxd);
> if (error)
> goto detach;
>
> @@ -786,40 +749,6 @@ pppx_del_session(struct pppx_dev *pxd, struct
> pipex_session_close_req *req)
> return (0);
> }
>
> -int
> -pppx_config_session(struct pppx_dev *pxd,
> - struct pipex_session_config_req *req)
> -{
> - struct pppx_if *pxi;
> -
> - pxi = pppx_if_find(pxd, req->pcr_session_id, req->pcr_protocol);
> - if (pxi == NULL)
> - return (EINVAL);
> -
> - return pipex_config_session(req, &pxi->pxi_ifcontext);
> -}
> -
> -int
> -pppx_get_stat(struct pppx_dev *pxd, struct pipex_session_stat_req *req)
> -{
> - struct pppx_if *pxi;
> -
> - pxi = pppx_if_find(pxd, req->psr_session_id, req->psr_protocol);
> - if (pxi == NULL)
> - return (EINVAL);
> -
> - return pipex_get_stat(req, &pxi->pxi_ifcontext);
> -}
> -
> -int
> -pppx_get_closed(struct pppx_dev *pxd, struct pipex_session_list_req *req)
> -{
> - /* XXX: Only opened sessions exist for pppx(4) */
> - memset(req, 0, sizeof(*req));
> -
> - return 0;
> -}
> -
> int
> pppx_set_session_descr(struct pppx_dev *pxd,
> struct pipex_session_descr_req *req)
> @@ -1022,9 +951,8 @@ struct pppac_softc {
> struct selinfo sc_rsel;
> struct mutex sc_wsel_mtx;
> struct selinfo sc_wsel;
> -
> - struct pipex_iface_context
> - sc_pipex_iface;
> + struct pipex_session
> + *sc_multicast_session;
>
> struct mbuf_queue
> sc_mq;
> @@ -1084,6 +1012,7 @@ pppacopen(dev_t dev, int flags, int mode, struct proc
> *p)
> {
> struct pppac_softc *sc;
> struct ifnet *ifp;
> + struct pipex_session *session;
>
> sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
> if (pppac_lookup(dev) != NULL) {
> @@ -1122,8 +1051,11 @@ pppacopen(dev_t dev, int flags, int mode, struct proc
> *p)
> #if NBPFILTER > 0
> bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t));
> #endif
> -
> - pipex_iface_init(&sc->sc_pipex_iface, ifp->if_index);
> + /* virtual pipex_session entry for multicast */
> + session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO);
> + session->is_multicast = 1;
> + session->ifindex = ifp->if_index;
> + sc->sc_multicast_session = session;
>
Interface index is not required for multicast session, because it's
never used. Also I like to alloc `sc_multicast_session' before
if_attach().
> return (0);
> }
> @@ -1255,7 +1187,9 @@ pppacioctl(dev_t dev, u_long cmd, caddr_t data, int
> flags, struct proc *p)
> {
> struct pppac_softc *sc = pppac_lookup(dev);
> int error = 0;
> + struct pipex_session *session;
>
> + NET_LOCK();
> switch (cmd) {
> case TUNSIFMODE: /* make npppd happy */
> break;
> @@ -1266,10 +1200,34 @@ pppacioctl(dev_t dev, u_long cmd, caddr_t data, int
> flags, struct proc *p)
> *(int *)data = mq_hdatalen(&sc->sc_mq);
> break;
>
> + case PIPEXASESSION:
> + {
> + struct pipex_session_req *req =
> + (struct pipex_session_req *)data;
> + if ((error = pipex_init_session(&session, req)) != 0)
> + break;
> + error = pipex_link_session(session, &sc->sc_if, sc);
> + break;
> + }
> + case PIPEXDSESSION:
> + {
> + struct pipex_session_close_req *req =
> + (struct pipex_session_close_req *)data;
> + session = pipex_lookup_by_session_id(req->pcr_protocol,
> + req->pcr_session_id);
> + if (session == NULL || session->ifindex != sc->sc_if.if_index) {
> + error = EINVAL;
> + break;
> + }
> + pipex_unlink_session(session);
> + pipex_rele_session(session);
> + break;
> + }
> default:
> - error = pipex_ioctl(&sc->sc_pipex_iface, cmd, data);
> + error = pipex_ioctl(sc, cmd, data);
> break;
> }
> + NET_UNLOCK();
>
> return (error);
> }
> @@ -1382,7 +1340,10 @@ pppacclose(dev_t dev, int flags, int mode, struct proc
> *p)
> klist_invalidate(&sc->sc_wsel.si_note);
> splx(s);
>
> - pipex_iface_fini(&sc->sc_pipex_iface);
> + pool_put(&pipex_session_pool, sc->sc_multicast_session);
> + NET_LOCK();
> + pipex_destroy_all_sessions(sc);
> + NET_UNLOCK();
>
> if_detach(ifp);
The recent sources has pppac(4) with unlocked start routine. I like you
detach `ifp' before destroy `sc_multicast_session'.
>
> @@ -1462,7 +1423,10 @@ static void
> pppac_start(struct ifnet *ifp)
> {
> struct pppac_softc *sc = ifp->if_softc;
> - struct mbuf *m;
> + struct mbuf *m, *m0;
> + struct pipex_session *session;
> + struct ip ip;
> + int rv;
>
> if (!ISSET(ifp->if_flags, IFF_RUNNING))
> return;
> @@ -1475,19 +1439,44 @@ pppac_start(struct ifnet *ifp)
> }
> #endif
>
> - m = pipex_output(m, m->m_pkthdr.ph_family, 0,
> - &sc->sc_pipex_iface);
> - if (m == NULL)
> + switch (m->m_pkthdr.ph_family) {
> + case AF_INET:
> + if (m->m_pkthdr.len < sizeof(struct ip))
> + goto bad;
> + m_copydata(m, 0, sizeof(struct ip), (caddr_t)&ip);
> + if (IN_MULTICAST(ip.ip_dst.s_addr)) {
> + /* pass a copy to pipex */
> + m0 = m_copym(m, 0, M_COPYALL, M_NOWAIT);
> + if (m0 != NULL)
> + pipex_ip_output(m0,
> + sc->sc_multicast_session);
> + else
> + goto bad;
> + } else {
> + session = pipex_lookup_by_ip_address(ip.ip_dst);
> + if (session != NULL) {
> + pipex_ip_output(m, session);
> + m = NULL;
> + }
> + }
> + break;
> + }
> + if (m == NULL) /* handled by pipex */
> continue;
>
> m = m_prepend(m, sizeof(uint32_t), M_DONTWAIT);
> - if (m == NULL) {
> - /* oh well */
> - continue;
> - }
> + if (m == NULL)
> + goto bad;
> *mtod(m, uint32_t *) = htonl(m->m_pkthdr.ph_family);
> -
> - mq_enqueue(&sc->sc_mq, m); /* qdrop */
> + rv = mq_enqueue(&sc->sc_mq, m);
> + if (rv == 1)
> + ifp->if_collisions++;
> + continue;
> +bad:
> + ifp->if_oerrors++;
> + if (m != NULL)
> + m_freem(m);
> + continue;
pppac(4) uses per-cpu counters for interface stats. I like you use them
here too.
> }
>
> if (!mq_empty(&sc->sc_mq)) {
> diff --git a/sys/net/pipex.c b/sys/net/pipex.c
> index 823c414098b..e1b3646b63c 100644
> --- a/sys/net/pipex.c
> +++ b/sys/net/pipex.c
> @@ -125,7 +125,6 @@ pipex_init(void)
> return;
>
> rn_init(sizeof(struct sockaddr_in6));
> -
> pool_init(&pipex_session_pool, sizeof(struct pipex_session), 0,
> IPL_SOFTNET, PR_WAITOK, "ppxss", NULL);
> pool_init(&mppe_key_pool, PIPEX_MPPE_KEYLEN * PIPEX_MPPE_NOLDKEY, 0,
> @@ -141,115 +140,55 @@ pipex_init(void)
> }
>
> void
> -pipex_iface_init(struct pipex_iface_context *pipex_iface, u_int ifindex)
> -{
> - struct pipex_session *session;
> -
> - pipex_iface->pipexmode = 0;
> - pipex_iface->ifindex = ifindex;
> -
> - if (pipex_rd_head4 == NULL) {
> - if (!rn_inithead((void **)&pipex_rd_head4,
> - offsetof(struct sockaddr_in, sin_addr)))
> - panic("rn_inithead() failed on pipex_init()");
> - }
> - if (pipex_rd_head6 == NULL) {
> - if (!rn_inithead((void **)&pipex_rd_head6,
> - offsetof(struct sockaddr_in6, sin6_addr)))
> - panic("rn_inithead() failed on pipex_init()");
> - }
> -
> - /* virtual pipex_session entry for multicast */
> - session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO);
> - session->is_multicast = 1;
> - session->pipex_iface = pipex_iface;
> - session->ifindex = ifindex;
> - pipex_iface->multicast_session = session;
> -}
> -
> -Static void
> -pipex_iface_start(struct pipex_iface_context *pipex_iface)
> -{
> - pipex_iface->pipexmode = 1;
> -}
> -
> -Static void
> -pipex_iface_stop(struct pipex_iface_context *pipex_iface)
> +pipex_destroy_all_sessions(void *ownersc)
> {
> struct pipex_session *session, *session_tmp;
>
> - pipex_iface->pipexmode = 0;
> - /*
> - * traversal all pipex sessions.
> - * it will become heavy if the number of pppac devices bocomes large.
> - */
> + NET_ASSERT_LOCKED();
> +
> LIST_FOREACH_SAFE(session, &pipex_session_list, session_list,
> session_tmp) {
> - if (session->pipex_iface == pipex_iface)
> - pipex_destroy_session(session);
> + if (session->ownersc == ownersc) {
> + KASSERT(session->is_pppx == 0);
> + pipex_unlink_session(session);
> + pipex_rele_session(session);
> + }
> }
> }
>
> -void
> -pipex_iface_fini(struct pipex_iface_context *pipex_iface)
> -{
> - pool_put(&pipex_session_pool, pipex_iface->multicast_session);
> - NET_LOCK();
> - pipex_iface_stop(pipex_iface);
> - NET_UNLOCK();
> -}
> -
> int
> -pipex_ioctl(struct pipex_iface_context *pipex_iface, u_long cmd, caddr_t
> data)
> +pipex_ioctl(void *ownersc, u_long cmd, caddr_t data)
> {
> - int pipexmode, ret = 0;
> + int ret = 0;
>
> - NET_LOCK();
> + NET_ASSERT_LOCKED();
> switch (cmd) {
> case PIPEXSMODE:
> - pipexmode = *(int *)data;
> - if (pipex_iface->pipexmode != pipexmode) {
> - if (pipexmode)
> - pipex_iface_start(pipex_iface);
> - else
> - pipex_iface_stop(pipex_iface);
> - }
> break;
>
> case PIPEXGMODE:
> - *(int *)data = pipex_iface->pipexmode;
> - break;
> -
> - case PIPEXASESSION:
> - ret = pipex_add_session((struct pipex_session_req *)data,
> - pipex_iface);
> - break;
> -
> - case PIPEXDSESSION:
> - ret = pipex_close_session(
> - (struct pipex_session_close_req *)data, pipex_iface);
> + *(int *)data = 1;
> break;
>
> case PIPEXCSESSION:
> ret = pipex_config_session(
> - (struct pipex_session_config_req *)data, pipex_iface);
> + (struct pipex_session_config_req *)data, ownersc);
> break;
>
> case PIPEXGSTAT:
> ret = pipex_get_stat((struct pipex_session_stat_req *)data,
> - pipex_iface);
> + ownersc);
> break;
>
> case PIPEXGCLOSED:
> ret = pipex_get_closed((struct pipex_session_list_req *)data,
> - pipex_iface);
> + ownersc);
> break;
>
> default:
> ret = ENOTTY;
> break;
> }
> - NET_UNLOCK();
>
> return (ret);
> }
> @@ -426,21 +365,43 @@ pipex_rele_session(struct pipex_session *session)
> }
>
> int
> -pipex_link_session(struct pipex_session *session,
> - struct pipex_iface_context *iface)
> +pipex_link_session(struct pipex_session *session, struct ifnet *ifp,
> + void *ownersc)
> {
> struct pipex_hash_head *chain;
> + struct radix_node *rn;
>
> NET_ASSERT_LOCKED();
>
> - if (!iface->pipexmode)
> - return (ENXIO);
> + if (pipex_rd_head4 == NULL) {
> + if (!rn_inithead((void **)&pipex_rd_head4,
> + offsetof(struct sockaddr_in, sin_addr)))
> + panic("rn_inithead() failed on pipex_link_session()");
> + }
> + if (pipex_rd_head6 == NULL) {
> + if (!rn_inithead((void **)&pipex_rd_head6,
> + offsetof(struct sockaddr_in6, sin6_addr)))
> + panic("rn_inithead() failed on pipex_link_session()");
> + }
> if (pipex_lookup_by_session_id(session->protocol,
> session->session_id))
> return (EEXIST);
>
> - session->pipex_iface = iface;
> - session->ifindex = iface->ifindex;
> + session->ownersc = ownersc;
> + session->ifindex = ifp->if_index;
> + if (ifp->if_flags & IFF_POINTOPOINT)
> + session->is_pppx = 1;
> +
> + if (session->is_pppx == 0 &&
> + !in_nullhost(session->ip_address.sin_addr)) {
> + if (pipex_lookup_by_ip_address(session->ip_address.sin_addr)
> + != NULL)
> + return (EADDRINUSE);
> + rn = rn_addroute(&session->ip_address, &session->ip_netmask,
> + pipex_rd_head4, session->ps4_rn, RTP_STATIC);
> + if (rn == NULL)
> + return (ENOMEM);
> + }
>
> LIST_INSERT_HEAD(&pipex_session_list, session, session_list);
> chain = PIPEX_ID_HASHTABLE(session->session_id);
> @@ -466,9 +427,21 @@ 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 (session->state == PIPEX_STATE_CLOSED)
> + return;
> + if (session->is_pppx == 0 &&
> + !in_nullhost(session->ip_address.sin_addr)) {
> + KASSERT(pipex_rd_head4 != NULL);
> + 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) {
> @@ -488,54 +461,6 @@ pipex_unlink_session(struct pipex_session *session)
> pipex_timer_stop();
> }
>
> -Static int
> -pipex_add_session(struct pipex_session_req *req,
> - struct pipex_iface_context *iface)
> -{
> - struct pipex_session *session;
> - struct radix_node *rn;
> - int error;
> -
> - if ((error = pipex_init_session(&session, req)) != 0)
> - goto out;
> -
> - /* commit the session */
> - if (!in_nullhost(session->ip_address.sin_addr)) {
> - if (pipex_lookup_by_ip_address(session->ip_address.sin_addr)
> - != NULL) {
> - error = EADDRINUSE;
> - goto free;
> - }
> -
> - rn = rn_addroute(&session->ip_address, &session->ip_netmask,
> - pipex_rd_head4, session->ps4_rn, RTP_STATIC);
> - if (rn == NULL) {
> - error = ENOMEM;
> - goto free;
> - }
> - }
> - if (0) { /* NOT YET */
> - rn = rn_addroute(&session->ip6_address, &session->ip6_prefixlen,
> - pipex_rd_head6, session->ps6_rn, RTP_STATIC);
> - if (rn == NULL) {
> - error = ENOMEM;
> - goto free;
> - }
> - }
> -
> - if ((error = pipex_link_session(session, iface)) != 0)
> - goto free;
> -
> - pipex_session_log(session, LOG_INFO, "PIPEX is ready.");
> -
> - return 0;
> -
> -free:
> - pipex_rele_session(session);
> -out:
> - return error;
> -}
> -
> int
> pipex_notify_close_session(struct pipex_session *session)
> {
> @@ -548,45 +473,7 @@ pipex_notify_close_session(struct pipex_session *session)
> }
>
> int
> -pipex_notify_close_session_all(void)
> -{
> - struct pipex_session *session;
> -
> - NET_ASSERT_LOCKED();
> - LIST_FOREACH(session, &pipex_session_list, session_list)
> - if (session->state == PIPEX_STATE_OPENED)
> - pipex_notify_close_session(session);
> - return (0);
> -}
> -
> -Static int
> -pipex_close_session(struct pipex_session_close_req *req,
> - struct pipex_iface_context *iface)
> -{
> - struct pipex_session *session;
> -
> - NET_ASSERT_LOCKED();
> - session = pipex_lookup_by_session_id(req->pcr_protocol,
> - req->pcr_session_id);
> - if (session == NULL)
> - return (EINVAL);
> - if (session->pipex_iface != iface)
> - return (EINVAL);
> -
> - /* remove from close_wait list */
> - if (session->state == PIPEX_STATE_CLOSE_WAIT)
> - LIST_REMOVE(session, state_list);
> -
> - /* get statistics before destroy the session */
> - req->pcr_stat = session->stat;
> - session->state = PIPEX_STATE_CLOSED;
> -
> - return (0);
> -}
> -
> -Static int
> -pipex_config_session(struct pipex_session_config_req *req,
> - struct pipex_iface_context *iface)
> +pipex_config_session(struct pipex_session_config_req *req, void *ownersc)
> {
> struct pipex_session *session;
>
> @@ -595,16 +482,15 @@ pipex_config_session(struct pipex_session_config_req
> *req,
> req->pcr_session_id);
> if (session == NULL)
> return (EINVAL);
> - if (session->pipex_iface != iface)
> + if (session->ownersc != ownersc)
> return (EINVAL);
> session->ip_forward = req->pcr_ip_forward;
>
> return (0);
> }
>
> -Static int
> -pipex_get_stat(struct pipex_session_stat_req *req,
> - struct pipex_iface_context *iface)
> +int
> +pipex_get_stat(struct pipex_session_stat_req *req, void *ownersc)
> {
> struct pipex_session *session;
>
> @@ -613,16 +499,15 @@ pipex_get_stat(struct pipex_session_stat_req *req,
> req->psr_session_id);
> if (session == NULL)
> return (EINVAL);
> - if (session->pipex_iface != iface)
> + if (session->ownersc != ownersc)
> return (EINVAL);
> req->psr_stat = session->stat;
>
> return (0);
> }
>
> -Static int
> -pipex_get_closed(struct pipex_session_list_req *req,
> - struct pipex_iface_context *iface)
> +int
> +pipex_get_closed(struct pipex_session_list_req *req, void *ownersc)
> {
> struct pipex_session *session, *session_tmp;
>
> @@ -630,7 +515,7 @@ pipex_get_closed(struct pipex_session_list_req *req,
> bzero(req, sizeof(*req));
> LIST_FOREACH_SAFE(session, &pipex_close_wait_list, state_list,
> session_tmp) {
> - if (session->pipex_iface != iface)
> + if (session->ownersc != ownersc)
> continue;
> req->plr_ppp_id[req->plr_ppp_id_count++] = session->ppp_id;
> LIST_REMOVE(session, state_list);
> @@ -645,32 +530,14 @@ pipex_get_closed(struct pipex_session_list_req *req,
> return (0);
> }
>
> -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);
> -
> - return (0);
> -}
> -
> Static struct pipex_session *
> pipex_lookup_by_ip_address(struct in_addr addr)
> {
> struct pipex_session *session;
> struct sockaddr_in pipex_in4, pipex_in4mask;
>
> + if (pipex_rd_head4 == NULL)
> + return (NULL);
> bzero(&pipex_in4, sizeof(pipex_in4));
> pipex_in4.sin_addr = addr;
> pipex_in4.sin_family = AF_INET;
> @@ -761,18 +628,15 @@ pipex_timer(void *ignored_arg)
>
> case PIPEX_STATE_CLOSE_WAIT:
> case PIPEX_STATE_CLOSE_WAIT2:
> - /* Wait PIPEXDSESSION from userland */
> + /* Waiting PIPEXDSESSION from userland */
> session->stat.idle_time++;
> 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);
> + /* Release the sessions when timeout */
> + pipex_unlink_session(session);
> + KASSERTMSG(session->is_pppx == 0,
> + "FIXME session must not be released when pppx");
> + pipex_rele_session(session);
> break;
>
> default:
> @@ -786,55 +650,6 @@ pipex_timer(void *ignored_arg)
> /***********************************************************************
> * Common network I/O functions. (tunnel protocol independent)
> ***********************************************************************/
> -struct mbuf *
> -pipex_output(struct mbuf *m0, int af, int off,
> - struct pipex_iface_context *pipex_iface)
> -{
> - struct pipex_session *session;
> - struct ip ip;
> - struct mbuf *mret;
> -
> - NET_ASSERT_LOCKED();
> - session = NULL;
> - mret = NULL;
> - switch (af) {
> - case AF_INET:
> - if (m0->m_pkthdr.len >= sizeof(struct ip) + off) {
> - m_copydata(m0, off, sizeof(struct ip), (caddr_t)&ip);
> - if (IN_MULTICAST(ip.ip_dst.s_addr))
> - session = pipex_iface->multicast_session;
> - else
> - session = pipex_lookup_by_ip_address(ip.ip_dst);
> - }
> - if (session != NULL) {
> - if (session == pipex_iface->multicast_session) {
> - mret = m0;
> - m0 = m_copym(m0, 0, M_COPYALL, M_NOWAIT);
> - if (m0 == NULL) {
> - m0 = mret;
> - mret = NULL;
> - goto drop;
> - }
> - }
> -
> - if (off > 0)
> - m_adj(m0, off);
> -
> - pipex_ip_output(m0, session);
> - return (mret);
> - }
> - break;
> - }
> -
> - return (m0);
> -
> -drop:
> - m_freem(m0);
> - if (session != NULL)
> - session->stat.oerrors++;
> - return(NULL);
> -}
> -
> Static void
> pipex_ip_output(struct mbuf *m0, struct pipex_session *session)
> {
> @@ -846,7 +661,6 @@ pipex_ip_output(struct mbuf *m0, struct pipex_session
> *session)
> ifp->if_opackets++;
> ifp->if_obytes+=m0->m_pkthdr.len;
> }
> - if_put(ifp);
>
> if (session->is_multicast == 0) {
> /*
> @@ -880,7 +694,7 @@ pipex_ip_output(struct mbuf *m0, struct pipex_session
> *session)
> m0->m_flags &= ~(M_BCAST|M_MCAST);
>
> LIST_FOREACH(session_tmp, &pipex_session_list, session_list) {
> - if (session_tmp->pipex_iface != session->pipex_iface)
> + if (session_tmp->ifindex != ifp->if_index)
> continue;
> if (session_tmp->ip_forward == 0 &&
> session_tmp->ip6_forward == 0)
> @@ -894,12 +708,14 @@ pipex_ip_output(struct mbuf *m0, struct pipex_session
> *session)
> }
> m_freem(m0);
> }
> + if_put(ifp);
>
> return;
> drop:
> m_freem(m0);
> dropped:
> session->stat.oerrors++;
> + if_put(ifp);
> }
>
> Static void
> diff --git a/sys/net/pipex.h b/sys/net/pipex.h
> index 9ea4dd9bf7b..c37c33696c1 100644
> --- a/sys/net/pipex.h
> +++ b/sys/net/pipex.h
> @@ -194,13 +194,8 @@ struct pipex_iface_context {
>
> __BEGIN_DECLS
> void pipex_init (void);
> -void pipex_iface_init (struct pipex_iface_context *, u_int);
> void pipex_iface_fini (struct pipex_iface_context *);
>
> -int pipex_notify_close_session(struct pipex_session
> *session);
> -int pipex_notify_close_session_all(void);
> -
> -struct mbuf *pipex_output (struct mbuf *, int, int, struct
> pipex_iface_context *);
> struct pipex_session *pipex_pppoe_lookup_session (struct mbuf *);
> struct mbuf *pipex_pppoe_input (struct mbuf *, struct
> pipex_session *);
> struct pipex_session *pipex_pptp_lookup_session (struct mbuf *);
> @@ -214,7 +209,7 @@ struct mbuf *pipex_l2tp_input (struct mbuf *,
> int off, struct pipex_se
> struct pipex_session *pipex_l2tp_userland_lookup_session_ipv4 (struct mbuf
> *, struct in_addr);
> struct pipex_session *pipex_l2tp_userland_lookup_session_ipv6 (struct mbuf
> *, struct in6_addr);
> struct mbuf *pipex_l2tp_userland_output (struct mbuf *, struct
> pipex_session *);
> -int pipex_ioctl (struct pipex_iface_context *, u_long,
> caddr_t);
> +int pipex_ioctl (void *, u_long, caddr_t);
> void pipex_session_init_mppe_recv(struct pipex_session *,
> int,
> int, u_char *);
> void pipex_session_init_mppe_send(struct pipex_session *,
> int,
> diff --git a/sys/net/pipex_local.h b/sys/net/pipex_local.h
> index ba16d1818ff..30cb7f0e961 100644
> --- a/sys/net/pipex_local.h
> +++ b/sys/net/pipex_local.h
> @@ -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_pppx: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 */
> @@ -182,8 +183,8 @@ struct pipex_session {
> struct sockaddr_in6 ip6_address; /* [I] remote IPv6 address */
> int ip6_prefixlen; /* [I] remote IPv6 prefixlen */
>
> - struct pipex_iface_context* pipex_iface; /* [N] context for interface */
> u_int ifindex; /* [N] interface index */
> + void *ownersc; /* [I] owner context */
>
> uint32_t ppp_flags; /* [I] configure flags */
> #ifdef PIPEX_MPPE
> @@ -285,6 +286,7 @@ extern struct pipex_hash_head pipex_session_list;
> extern struct pipex_hash_head pipex_close_wait_list;
> extern struct pipex_hash_head pipex_peer_addr_hashtable[];
> extern struct pipex_hash_head pipex_id_hashtable[];
> +extern struct pool pipex_session_pool;
>
>
> #define PIPEX_ID_HASHTABLE(key)
> \
> @@ -375,24 +377,21 @@ extern struct pipex_hash_head pipex_id_hashtable[];
> #define PIPEX_TCP_OPTLEN 40
> #define PIPEX_L2TP_MINLEN 8
>
> -void pipex_iface_start (struct pipex_iface_context *);
> -void pipex_iface_stop (struct pipex_iface_context *);
> +void pipex_destroy_all_sessions (void *);
> int pipex_init_session(struct pipex_session **,
> struct pipex_session_req *);
> void pipex_rele_session(struct pipex_session *);
> int pipex_link_session(struct pipex_session *,
> - struct pipex_iface_context *);
> + struct ifnet *, void *);
> void pipex_unlink_session(struct pipex_session *);
> -int pipex_add_session (struct pipex_session_req *, struct
> pipex_iface_context *);
> int pipex_close_session (struct pipex_session_close_req *,
> struct pipex_iface_context *);
> int pipex_config_session (struct pipex_session_config_req
> *,
> - struct pipex_iface_context *);
> + void *);
> int pipex_get_stat (struct pipex_session_stat_req *,
> - struct pipex_iface_context *);
> + void *);
> int pipex_get_closed (struct pipex_session_list_req *,
> - struct pipex_iface_context *);
> -int pipex_destroy_session (struct pipex_session *);
> + void *);
> struct pipex_session *pipex_lookup_by_ip_address (struct in_addr);
> struct pipex_session *pipex_lookup_by_session_id (int, int);
> void pipex_ip_output (struct mbuf *, struct pipex_session
> *);
>