On Thu, Aug 20, 2020 at 02:32:57PM +0900, YASUOKA Masahiko wrote:

Hello.

I pointed some comments inline.

> Hi,
> 
> Thank you for your comments.
> 
> On Mon, 17 Aug 2020 00:15:08 +0300
> Vitaliy Makkoveev <m...@openbsd.org> wrote:
> > 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?
> 
> I'm sorry the diff was for the old version.
> 
> >> @@ -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().
> 
> The diff was to use `ifindex' to select all sessions associated the
> same pppac(4).  But the latest diff uses `ownersc' instead for the
> same purpose.  Also the allocation was moved to earlier part of the
> function.
> 
> >> @@ -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'.
> 
> The lines were moved after if_detach().
> 
> I'll test this more on this weekend, then I'll ask ok for this.
> 
> Index: sys/net/if_pppx.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_pppx.c,v
> retrieving revision 1.101
> diff -u -p -r1.101 if_pppx.c
> --- sys/net/if_pppx.c 14 Aug 2020 11:05:38 -0000      1.101
> +++ sys/net/if_pppx.c 20 Aug 2020 05:19:55 -0000
> @@ -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
>  
>       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
>                   (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
>               break;
>  
>       default:
> -             error = ENOTTY;
> +             error = pipex_ioctl(pxd, cmd, addr);
>               break;
>       }
>       NET_UNLOCK();
> @@ -741,11 +708,7 @@ pppx_add_session(struct pppx_dev *pxd, s
>               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, s
>  }
>  
>  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)
>  {
> @@ -1014,8 +943,8 @@ struct pppac_softc {
>       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;
> @@ -1075,6 +1004,7 @@ pppacopen(dev_t dev, int flags, int mode
>  {
>       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) {
> @@ -1082,6 +1012,12 @@ pppacopen(dev_t dev, int flags, int mode
>               return (EBUSY);
>       }
>  
> +     /* virtual pipex_session entry for multicast */
> +     session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO);
> +     session->is_multicast = 1;
> +     session->ownersc = sc;
> +     sc->sc_multicast_session = session;
> +
>       sc->sc_dev = dev;
>  
>       mtx_init(&sc->sc_rsel_mtx, IPL_SOFTNET);
> @@ -1112,8 +1048,6 @@ pppacopen(dev_t dev, int flags, int mode
>       bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t));
>  #endif
>  
> -     pipex_iface_init(&sc->sc_pipex_iface, ifp->if_index);
> -
>       return (0);
>  }
>  
> @@ -1244,7 +1178,9 @@ pppacioctl(dev_t dev, u_long cmd, caddr_
>  {
>       struct pppac_softc *sc = pppac_lookup(dev);
>       int error = 0;
> +     struct pipex_session *session;
>  
> +     NET_LOCK();
>       switch (cmd) {
>       case TUNSIFMODE: /* make npppd happy */
>               break;
> @@ -1255,10 +1191,34 @@ pppacioctl(dev_t dev, u_long cmd, caddr_
>               *(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;
> +         }

If pipex_link_session() fails `session' will be leaked.

> +     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) {

Can you compare with `session->ownersc' instead of `ifindex' like other
code does? For consistency with other code.

What about to introduce pppac_{add,del}_session() and move related code
into them?

Also I see no such reason to kill pipex_{add,destroy}_session() because
they play with `pipex_rd_head{4,6}' and you don't need newly introduced
`session->is_pppx' which you use only once for that reason. 

> +                     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);
>  }
> @@ -1373,7 +1333,10 @@ pppacclose(dev_t dev, int flags, int mod
>  
>       if_detach(ifp);
>  
> -     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();
>  
>       LIST_REMOVE(sc, sc_entry);
>       free(sc, M_DEVBUF, sizeof(*sc));
> @@ -1452,7 +1415,10 @@ pppac_qstart(struct ifqueue *ifq)
>  {
>       struct ifnet *ifp = ifq->ifq_if;
>       struct pppac_softc *sc = ifp->if_softc;
> -     struct mbuf *m;
> +     struct mbuf *m, *m0;
> +     struct pipex_session *session;
> +     struct ip ip;
> +     int rv;
>  
>       NET_LOCK();
>       while ((m = ifq_dequeue(ifq)) != NULL) {
> @@ -1463,19 +1429,45 @@ pppac_qstart(struct ifqueue *ifq)
>               }
>  #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++;

Could you use "counters_inc(ifp->if_counters, ifc_collisions);" here?
For consistency with pppacwrite() which uses percpu counters.

> +             continue;
> +bad:
> +             ifp->if_oerrors++;

Could you use "counters_inc(ifp->if_counters, ifc_oerrors);" here? 
For consistency with pppacwrite() which uses percpu counters.

> +             if (m != NULL)
> +                     m_freem(m);
> +             continue;
>       }
>       NET_UNLOCK();
>  
> Index: sys/net/pipex.c
> ===================================================================
> RCS file: /cvs/src/sys/net/pipex.c,v
> retrieving revision 1.124
> diff -u -p -r1.124 pipex.c
> --- sys/net/pipex.c   12 Aug 2020 08:41:39 -0000      1.124
> +++ sys/net/pipex.c   20 Aug 2020 05:19:56 -0000
> @@ -141,115 +141,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 +366,43 @@ pipex_rele_session(struct pipex_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()");
> +     }

Since you will initialize `pipex_rd_head{4,6}' for pppx(4) sessions too,
may be it's better to move this initialization to pipex_init().

>       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 +428,21 @@ pipex_link_session(struct pipex_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 +462,6 @@ pipex_unlink_session(struct pipex_sessio
>               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)
>  {
> @@ -547,46 +473,8 @@ pipex_notify_close_session(struct pipex_
>       return (0);
>  }
>  
> -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,7 +483,7 @@ pipex_config_session(struct pipex_sessio
>           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;
>  
> @@ -603,8 +491,7 @@ pipex_config_session(struct pipex_sessio
>  }
>  
>  Static int
> -pipex_get_stat(struct pipex_session_stat_req *req,
> -    struct pipex_iface_context *iface)
> +pipex_get_stat(struct pipex_session_stat_req *req, void *ownersc)
>  {
>       struct pipex_session *session;
>  
> @@ -613,7 +500,7 @@ pipex_get_stat(struct pipex_session_stat
>           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;
>  
> @@ -621,8 +508,7 @@ pipex_get_stat(struct pipex_session_stat
>  }
>  
>  Static int
> -pipex_get_closed(struct pipex_session_list_req *req,
> -    struct pipex_iface_context *iface)
> +pipex_get_closed(struct pipex_session_list_req *req, void *ownersc)
>  {
>       struct pipex_session *session, *session_tmp;
>  
> @@ -630,7 +516,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 (session->ownersc != ownersc)
>                       continue;
>               req->plr_ppp_id[req->plr_ppp_id_count++] = session->ppp_id;
>               LIST_REMOVE(session, state_list);
> @@ -645,32 +531,14 @@ pipex_get_closed(struct pipex_session_li
>       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 +629,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 +651,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)
>  {
> @@ -872,7 +688,7 @@ pipex_ip_output(struct mbuf *m0, struct 
>               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->ownersc != session->ownersc)
>                               continue;
>                       if (session_tmp->ip_forward == 0 &&
>                           session_tmp->ip6_forward == 0)
> Index: sys/net/pipex.h
> ===================================================================
> RCS file: /cvs/src/sys/net/pipex.h,v
> retrieving revision 1.27
> diff -u -p -r1.27 pipex.h
> --- sys/net/pipex.h   4 Aug 2020 09:32:05 -0000       1.27
> +++ sys/net/pipex.h   20 Aug 2020 05:19:56 -0000
> @@ -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 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,
> 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     20 Aug 2020 05:19:56 -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_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_sess
>  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_h
>  #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 
> *);
> 

Reply via email to