On 27/06/20(Sat) 01:02, Vitaliy Makkoveev wrote:
> On Fri, Jun 26, 2020 at 09:15:38PM +0200, Martin Pieuchot wrote:
> > On 26/06/20(Fri) 17:53, Vitaliy Makkoveev wrote:
> > > On Fri, Jun 26, 2020 at 02:29:03PM +0200, Martin Pieuchot wrote:
> > > > On 26/06/20(Fri) 12:35, Vitaliy Makkoveev wrote:
> > > > > On Fri, Jun 26, 2020 at 10:23:42AM +0200, Martin Pieuchot wrote:
> > > > > > On 25/06/20(Thu) 19:56, Vitaliy Makkoveev wrote:
> > > > > > > Updated diff. 
> > > > > > > 
> > > > > > > OpenBSD uses 16 bit counter for allocate interface indexes. So we 
> > > > > > > can't
> > > > > > > store index in session and be sure if_get(9) returned `ifnet' is 
> > > > > > > our
> > > > > > > original `ifnet'.
> > > > > > 
> > > > > > Why not?  The point of if_get(9) is to be sure.  If that doesn't 
> > > > > > work
> > > > > > for whatever reason then the if_get(9) interface has to be fixed.  
> > > > > > Which
> > > > > > case doesn't work for you?  Do you have a reproducer?  
> > > > > > 
> > > > > > How does sessions stay around if their corresponding interface is
> > > > > > destroyed?
> > > > > 
> > > > > We have `pipexinq' and `pipexoutq' which can store pointers to 
> > > > > session.
> > > > > pipexintr() process these queues. pipexintr() and
> > > > > pipex_destroy_session() are *always* different context. This mean we
> > > > > *can't* free pipex(4) session without be sure there is no reference to
> > > > > this session in `pipexinq' or `pipexoutq'. Elsewhere this will cause 
> > > > > use
> > > > > afret free issue. Look please at net/pipex.c:846. The way pppx(4)
> > > > > destroy sessions is wrong. While pppac(4) destroys sessions by
> > > > > pipex_iface_fini() it's also wrong. Because we don't check `pipexinq'
> > > > > and `pipexoutq' state. I'am said it again and again.
> > > > 
> > > > I understand.  Why is it a problem?  Using reference counting the way
> > > > you're suggesting is *one* possible solution to a problem we don't fully
> > > > understand.  What are we trying to achieve?  Which problem are we trying
> > > > to solve?
> > > 
> > > Sorry, may be I misunderstand something.
> > > 
> > > `pipexoutq' case:
> > > 
> > > 1. pppac_start() calls pipex_output()
> > > 2. pipex_output() calls pipex_ip_output()
> > > 3. pipex_ip_output() calls pipex_ppp_enqueue()
> > > 4. pipex_ppp_enqueue() calls schednetisr() which is task_add()
> > > 
> > > `pipexinq' cases:
> > > 
> > > 1.1. ether_input() calls pipex_pppoe_input()
> > > 1.2. gre_input() calls gre_input_1()
> > >          gre_input_1() calls pipex_pptp_input()
> > > 1.3. udp_input() calls pipex_l2tp_input()
> > > 
> > > 2. pipex_{pppoe,pptp,l2tp}_input() calls pipex_common_input()
> > > 3. pipex_common_input() calls schednetisr() which is task_add()
> > > 
> > > task_add(9) just schedules the execution of the work specified by `tq'.
> > > So we can do pipex_destroy_session() * between * schednetisr() and
> > > pipexintr(). And we can do this right * now *, with our current locking.
> > > And this is the problem I'am trying to solve.
> > > 
> > > My apologies if I'am wrong above. Please point me where I'am wrong.
> > > 
> > > Also before pipex_{pppoe,pptp,l2tp}_input() we call corresponding
> > > pipex_{pptp,l2tp}_lookup_session() to obtain pointer to pipex(4)
> > > session. We should be shure `session' is still walid between
> > > pipex_*_lookup() and pipex_*_input(). It's not required now, but will be
> > > required in future.
> > 
> > Why not iterate over the queues and garbage collect the sessions that
> > are about to be removed?  That's what the network stack was doing with
> > mbuf queues prior to if_get(9) when interfaces where destroyed.
> > 
> 
> Do you mean net/if.c:1185 and below? This is the queues associated with
> this `ifp'. But for pipex(4) we should go through all mbufs associated
> with pipex(4). This can be heavy if we have hundreds of sessions. Also
> this would work until session destruction and `pr_input' are serialized.
> 
> Point me please the line in source to see if I'am wrong about `ifnet's
> mbuf queues claninig.

Look at r1.329 of net/if.c.  Prior to this change if_detach_queues() was
used to free all mbufs when an interface was removed.  Now lazy freeing
is used everytime if_get(9) rerturns NULL.

This is possible because we store an index and not a pointer directly in
the mbuf.

The advantage of storing a session pointer in `ph_cookie' is that no
lookup is required in pipexintr(), right?  Maybe we could save a ID
instead and do a lookup.  How big can be the `pipex_session_list'?

Reply via email to