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 > *); >