On Thu, Apr 02, 2020 at 09:26:23AM +0200, Martin Pieuchot wrote: > Hello Vitaliy, > > On 01/04/20(Wed) 12:59, Vitaliy Makkoveev wrote: > > Updated diff. The idea is to use already existing pipex API for > > pipex_session creation and destruction. pppx_if now holds a reference > > to pipex_session. > > This is great! > > There are many things in this diff which makes it complicated to review, > at least to me. Note that I'm not really familiar with this code. > > For example the panic() after the RBT_REMOVE() is now questionable since > the lock is released then retaken. Which brings a question for later: > what is the lock really protecting? That can be documented in the header > like it is done for other data structures. > > So the changes includes: > > - pool_get() with PR_WAITOK should never fail. This could be the first > step and also move the allocation at the beginning to make a pattern > appear. > > - Allocation of `pxi_session' separately from `pxi', this creates quite > some noise because of the line changing indirection. > > - Change in the error paths, which aren't correct and IMHO should be > left out for the moment. > > - Use of pipex_add_session(), isn't that independent from the allocation > of `session'? > > Could you help me review this by submitting smaller diffs? Thanks a > lot! Let's take a break, another pipex(4) issue found. I'll send diff for it it today later with new thread.
> > > > > Index: sys/net/if_pppx.c > > =================================================================== > > RCS file: /cvs/src/sys/net/if_pppx.c,v > > retrieving revision 1.78 > > diff -u -p -r1.78 if_pppx.c > > --- sys/net/if_pppx.c 1 Apr 2020 07:15:59 -0000 1.78 > > +++ sys/net/if_pppx.c 1 Apr 2020 09:50:19 -0000 > > @@ -155,7 +155,7 @@ struct pppx_if { > > int pxi_unit; > > struct ifnet pxi_if; > > struct pppx_dev *pxi_dev; > > - struct pipex_session pxi_session; > > + struct pipex_session *pxi_session; > > struct pipex_iface_context pxi_ifcontext; > > }; > > > > @@ -655,15 +655,10 @@ int > > pppx_add_session(struct pppx_dev *pxd, struct pipex_session_req *req) > > { > > struct pppx_if *pxi; > > - struct pipex_session *session; > > - struct pipex_hash_head *chain; > > struct ifnet *ifp; > > int unit, error = 0; > > struct in_ifaddr *ia; > > struct sockaddr_in ifaddr; > > -#ifdef PIPEX_PPPOE > > - struct ifnet *over_ifp = NULL; > > -#endif > > > > /* > > * XXX: As long as `session' is allocated as part of a `pxi' > > @@ -673,157 +668,16 @@ pppx_add_session(struct pppx_dev *pxd, s > > if (req->pr_timeout_sec != 0) > > return (EINVAL); > > > > - switch (req->pr_protocol) { > > -#ifdef PIPEX_PPPOE > > - case PIPEX_PROTO_PPPOE: > > - over_ifp = ifunit(req->pr_proto.pppoe.over_ifname); > > - if (over_ifp == NULL) > > - return (EINVAL); > > - if (req->pr_peer_address.ss_family != AF_UNSPEC) > > - return (EINVAL); > > - break; > > -#endif > > -#if defined(PIPEX_PPTP) || defined(PIPEX_L2TP) > > - case PIPEX_PROTO_PPTP: > > - case PIPEX_PROTO_L2TP: > > - switch (req->pr_peer_address.ss_family) { > > - case AF_INET: > > - if (req->pr_peer_address.ss_len != sizeof(struct > > sockaddr_in)) > > - return (EINVAL); > > - break; > > -#ifdef INET6 > > - case AF_INET6: > > - if (req->pr_peer_address.ss_len != sizeof(struct > > sockaddr_in6)) > > - return (EINVAL); > > - break; > > -#endif > > - default: > > - return (EPROTONOSUPPORT); > > - } > > - if (req->pr_peer_address.ss_family != > > - req->pr_local_address.ss_family || > > - req->pr_peer_address.ss_len != > > - req->pr_local_address.ss_len) > > - return (EINVAL); > > - break; > > -#endif /* defined(PIPEX_PPTP) || defined(PIPEX_L2TP) */ > > - default: > > - return (EPROTONOSUPPORT); > > - } > > - > > pxi = pool_get(pppx_if_pl, PR_WAITOK | PR_ZERO); > > - if (pxi == NULL) > > - return (ENOMEM); > > - > > - session = &pxi->pxi_session; > > ifp = &pxi->pxi_if; > > > > - /* fake a pipex interface context */ > > - session->pipex_iface = &pxi->pxi_ifcontext; > > - session->pipex_iface->ifnet_this = ifp; > > - session->pipex_iface->pipexmode = PIPEX_ENABLED; > > - > > - /* setup session */ > > - session->state = PIPEX_STATE_OPENED; > > - session->protocol = req->pr_protocol; > > - session->session_id = req->pr_session_id; > > - session->peer_session_id = req->pr_peer_session_id; > > - session->peer_mru = req->pr_peer_mru; > > - session->timeout_sec = req->pr_timeout_sec; > > - session->ppp_flags = req->pr_ppp_flags; > > - session->ppp_id = req->pr_ppp_id; > > - > > - session->ip_forward = 1; > > - > > - session->ip_address.sin_family = AF_INET; > > - session->ip_address.sin_len = sizeof(struct sockaddr_in); > > - session->ip_address.sin_addr = req->pr_ip_address; > > - > > - session->ip_netmask.sin_family = AF_INET; > > - session->ip_netmask.sin_len = sizeof(struct sockaddr_in); > > - session->ip_netmask.sin_addr = req->pr_ip_netmask; > > - > > - if (session->ip_netmask.sin_addr.s_addr == 0L) > > - session->ip_netmask.sin_addr.s_addr = 0xffffffffL; > > - session->ip_address.sin_addr.s_addr &= > > - session->ip_netmask.sin_addr.s_addr; > > - > > - if (req->pr_peer_address.ss_len > 0) > > - memcpy(&session->peer, &req->pr_peer_address, > > - MIN(req->pr_peer_address.ss_len, sizeof(session->peer))); > > - if (req->pr_local_address.ss_len > 0) > > - memcpy(&session->local, &req->pr_local_address, > > - MIN(req->pr_local_address.ss_len, sizeof(session->local))); > > -#ifdef PIPEX_PPPOE > > - if (req->pr_protocol == PIPEX_PROTO_PPPOE) > > - session->proto.pppoe.over_ifidx = over_ifp->if_index; > > -#endif > > -#ifdef PIPEX_PPTP > > - if (req->pr_protocol == PIPEX_PROTO_PPTP) { > > - struct pipex_pptp_session *sess_pptp = &session->proto.pptp; > > - > > - sess_pptp->snd_gap = 0; > > - sess_pptp->rcv_gap = 0; > > - sess_pptp->snd_una = req->pr_proto.pptp.snd_una; > > - sess_pptp->snd_nxt = req->pr_proto.pptp.snd_nxt; > > - sess_pptp->rcv_nxt = req->pr_proto.pptp.rcv_nxt; > > - sess_pptp->rcv_acked = req->pr_proto.pptp.rcv_acked; > > - > > - sess_pptp->winsz = req->pr_proto.pptp.winsz; > > - sess_pptp->maxwinsz = req->pr_proto.pptp.maxwinsz; > > - sess_pptp->peer_maxwinsz = req->pr_proto.pptp.peer_maxwinsz; > > - /* last ack number */ > > - sess_pptp->ul_snd_una = sess_pptp->snd_una - 1; > > - } > > -#endif > > -#ifdef PIPEX_L2TP > > - if (req->pr_protocol == PIPEX_PROTO_L2TP) { > > - struct pipex_l2tp_session *sess_l2tp = &session->proto.l2tp; > > - > > - /* session keys */ > > - sess_l2tp->tunnel_id = req->pr_proto.l2tp.tunnel_id; > > - sess_l2tp->peer_tunnel_id = req->pr_proto.l2tp.peer_tunnel_id; > > - > > - /* protocol options */ > > - sess_l2tp->option_flags = req->pr_proto.l2tp.option_flags; > > - > > - /* initial state of dynamic context */ > > - sess_l2tp->ns_gap = sess_l2tp->nr_gap = 0; > > - sess_l2tp->ns_nxt = req->pr_proto.l2tp.ns_nxt; > > - sess_l2tp->nr_nxt = req->pr_proto.l2tp.nr_nxt; > > - sess_l2tp->ns_una = req->pr_proto.l2tp.ns_una; > > - sess_l2tp->nr_acked = req->pr_proto.l2tp.nr_acked; > > - /* last ack number */ > > - sess_l2tp->ul_ns_una = sess_l2tp->ns_una - 1; > > - } > > -#endif > > -#ifdef PIPEX_MPPE > > - if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) > > - pipex_session_init_mppe_recv(session, > > - req->pr_mppe_recv.stateless, req->pr_mppe_recv.keylenbits, > > - req->pr_mppe_recv.master_key); > > - if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) > > - pipex_session_init_mppe_send(session, > > - req->pr_mppe_send.stateless, req->pr_mppe_send.keylenbits, > > - req->pr_mppe_send.master_key); > > - > > - if (pipex_session_is_mppe_required(session)) { > > - if (!pipex_session_is_mppe_enabled(session) || > > - !pipex_session_is_mppe_accepted(session)) { > > - pool_put(pppx_if_pl, pxi); > > - return (EINVAL); > > - } > > - } > > -#endif > > - > > /* try to set the interface up */ > > rw_enter_write(&pppx_ifs_lk); > > unit = pppx_if_next_unit(); > > if (unit < 0) { > > - pool_put(pppx_if_pl, pxi); > > - error = ENOMEM; > > rw_exit_write(&pppx_ifs_lk); > > - goto out; > > + error = ENOMEM; > > + goto err_free_iface; > > } > > > > pxi->pxi_unit = unit; > > @@ -833,10 +687,9 @@ pppx_add_session(struct pppx_dev *pxd, s > > > > /* this is safe without splnet since we're not modifying it */ > > if (RBT_FIND(pppx_ifs, &pppx_ifs, pxi) != NULL) { > > - pool_put(pppx_if_pl, pxi); > > - error = EADDRINUSE; > > rw_exit_write(&pppx_ifs_lk); > > - goto out; > > + error = EADDRINUSE; > > + goto err_free_iface; > > } > > > > if (RBT_INSERT(pppx_ifs, &pppx_ifs, pxi) != NULL) > > @@ -856,24 +709,21 @@ pppx_add_session(struct pppx_dev *pxd, s > > ifp->if_softc = pxi; > > /* ifp->if_rdomain = req->pr_rdomain; */ > > > > - /* hook up pipex context */ > > - chain = PIPEX_ID_HASHTABLE(session->session_id); > > - LIST_INSERT_HEAD(chain, session, id_chain); > > - LIST_INSERT_HEAD(&pipex_session_list, session, session_list); > > -#if defined(PIPEX_PPTP) || defined(PIPEX_L2TP) > > - switch (req->pr_protocol) { > > - case PIPEX_PROTO_PPTP: > > - case PIPEX_PROTO_L2TP: > > - chain = PIPEX_PEER_ADDR_HASHTABLE( > > - pipex_sockaddr_hash_key(&session->peer.sa)); > > - LIST_INSERT_HEAD(chain, session, peer_addr_chain); > > - break; > > + /* pipex interface context */ > > + pipex_iface_init(&pxi->pxi_ifcontext, ifp); > > + pipex_iface_start(&pxi->pxi_ifcontext); > > + > > + error = pipex_add_session(req, &pxi->pxi_ifcontext); > > + if (error) { > > + goto err_free_pipex; > > } > > -#endif > > > > - /* if first session is added, start timer */ > > - if (LIST_NEXT(session, session_list) == NULL) > > - pipex_timer_start(); > > + pxi->pxi_session = pipex_lookup_by_session_id( > > + pxi->pxi_key.pxik_protocol, pxi->pxi_key.pxik_session_id); > > + if (pxi->pxi_session == NULL) { > > + error = EINVAL; > > + goto err_free_pipex; > > + } > > > > /* XXXSMP breaks atomicity */ > > NET_UNLOCK(); > > @@ -928,7 +778,20 @@ pppx_add_session(struct pppx_dev *pxd, s > > pxi->pxi_ready = 1; > > rw_exit_write(&pppx_ifs_lk); > > > > -out: > > + return (error); > > + > > +err_free_pipex: > > + NET_UNLOCK(); > > + pipex_iface_fini(&pxi->pxi_ifcontext); > > + NET_LOCK(); > > +err_free_iface: > > + rw_enter_write(&pppx_ifs_lk); > > + if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL) > > + panic("%s: pppx_ifs modified while lock was held", __func__); > > + LIST_REMOVE(pxi, pxi_list); > > + rw_exit_write(&pppx_ifs_lk); > > + pool_put(pppx_if_pl, pxi); > > + > > return (error); > > } > > > > @@ -941,7 +804,7 @@ pppx_del_session(struct pppx_dev *pxd, s > > if (pxi == NULL) > > return (EINVAL); > > > > - req->pcr_stat = pxi->pxi_session.stat; > > + req->pcr_stat = pxi->pxi_session->stat; > > > > pppx_if_destroy(pxd, pxi); > > return (0); > > @@ -970,29 +833,19 @@ pppx_if_destroy(struct pppx_dev *pxd, st > > struct pipex_session *session; > > > > NET_ASSERT_LOCKED(); > > - session = &pxi->pxi_session; > > + session = pxi->pxi_session; > > ifp = &pxi->pxi_if; > > > > - LIST_REMOVE(session, id_chain); > > - LIST_REMOVE(session, session_list); > > -#if defined(PIPEX_PPTP) || defined(PIPEX_L2TP) > > - switch (session->protocol) { > > - case PIPEX_PROTO_PPTP: > > - case PIPEX_PROTO_L2TP: > > - LIST_REMOVE(session, peer_addr_chain); > > - break; > > - } > > -#endif > > - > > - /* if final session is destroyed, stop timer */ > > - if (LIST_EMPTY(&pipex_session_list)) > > - pipex_timer_stop(); > > - > > /* XXXSMP breaks atomicity */ > > NET_UNLOCK(); > > if_detach(ifp); > > NET_LOCK(); > > > > + pipex_destroy_session(session); > > + NET_UNLOCK(); > > + pipex_iface_fini(&pxi->pxi_ifcontext); > > + NET_LOCK(); > > + > > rw_enter_write(&pppx_ifs_lk); > > if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL) > > panic("%s: pppx_ifs modified while lock was held", __func__); > > @@ -1024,7 +877,7 @@ pppx_if_start(struct ifnet *ifp) > > ifp->if_obytes += m->m_pkthdr.len; > > ifp->if_opackets++; > > > > - pipex_ppp_output(m, &pxi->pxi_session, proto); > > + pipex_ppp_output(m, pxi->pxi_session, proto); > > } > > } > > > > @@ -1084,7 +937,7 @@ pppx_if_output(struct ifnet *ifp, struct > > } > > th = mtod(m, struct pppx_hdr *); > > th->pppx_proto = 0; /* not used */ > > - th->pppx_id = pxi->pxi_session.ppp_id; > > + th->pppx_id = pxi->pxi_session->ppp_id; > > rw_enter_read(&pppx_devs_lk); > > error = mq_enqueue(&pxi->pxi_dev->pxd_svcq, m); > > if (error == 0) { > > @@ -1123,7 +976,7 @@ pppx_if_ioctl(struct ifnet *ifp, u_long > > > > case SIOCSIFMTU: > > if (ifr->ifr_mtu < 512 || > > - ifr->ifr_mtu > pxi->pxi_session.peer_mru) > > + ifr->ifr_mtu > pxi->pxi_session->peer_mru) > > error = EINVAL; > > else > > ifp->if_mtu = ifr->ifr_mtu; > > >