Source-Changes-D archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: CVS commit: src/sys/net



On Tue, Feb 16, 2016 at 6:16 AM, Taylor R Campbell
<campbell+netbsd-source-changes-d%mumble.net@localhost> wrote:
>    Date: Mon, 15 Feb 2016 11:06:52 +0000
>    From: Roy Marples <roy%marples.name@localhost>
>
>    On 15/02/2016 10:32, Ryota Ozaki wrote:
>    > I think we can fix by returning from if_link_state_change_si
>    > if ifp->if_link_state == ifp->if_old_link_state. Is it correct?
>
>    Then we're not doing what we should because the protocol actions may not
>    fire.
>
>    Can we not extend softint_schedule to take some user data? That way,
>    each call (which I'm assuming would be sequential) can carry the link
>    state change in the user data which can then be applied to the interface.
>
> Changing softint is not really a good idea -- it is a significant
> semantic change that most current users don't require, because they
> already have existing queue mechanisms, e.g. pktq.
>
> If it is necessary to report every link state transition, then we need
> to create a queueing mechanism -- and possibly drop some transitions
> in the case of memory shortage, as we already do in route_enqueue.
>
> Maybe something like this, with a queue and a link_state_pending field
> to avoid creating extra queue entries unnecessarily but guaranteeing
> that the most recent link state change will take effect, and be
> preceded by LINK_STATE_DOWN if anything was lost:

Oops. Our (IIJ) local changes have a similar code (softint + queuing)
and it works for long time. So I concur the design.

>
> struct link_state_change {
>         SIMPLEQ_ENTRY(link_state_change)        lsc_entry;
>         int                                     lsc_state;
>         bool                                    lsc_lost;
> };
>
> static pool_cache_t link_state_change_pc __read_mostly;
>
> void
> if_link_state_change(struct ifnet *ifp, int link_state)
> {
>         int s;
>
>         s = splnet();
>         if (ifp->if_link_state_pending == link_state)
>                 goto out;
>
>         if (ifp->if_link_state_pending != ifp->if_link_state) {

What does the conditional intend?

>                 struct link_state_change *lsc;
>
>                 lsc = pool_cache_get(link_state_change_pc, PR_NOWAIT);
>                 if (lsc == NULL) {
>                         ifp->if_link_state_lost = true;
>                         goto change;
>                 }
>
>                 lsc->lsc_state = link_state;
>                 lsc->lsc_lost = ifp->if_link_state_lost;
>                 SIMPLEQ_INSERT_TAIL(&ifp->if_link_state_changes, lsc,
>                     lsc_entry);
>         }
>
>         ifp->if_link_state_lost = false;
> change: ifp->if_link_state_pending = link_state;
>         softint_schedule(ifp->if_link_state_softint);
> out:    splx(s);
> }
>
> static void
> if_link_state_change_softintr(void *cookie)
> {
>         struct ifnet *ifp = cookie;
>         struct link_state_change *lsc;
>         int s;
>
>         s = splnet();
>         while (!SIMPLEQ_EMPTY(&ifp->if_link_state_changes)) {
>                 lsc = SIMPLEQ_HEAD(&ifp->if_link_state_changes);
>                 SIMPLEQ_REMOVE_HEAD(&ifp->if_link_state_changes, lsc_entry);
>                 if_link_state_change_1(ifp, lsc->lsc_state, lsc->lsc_lost);
>         }
>
>         if (ifp->if_link_state_pending != ifp->if_link_state)
>                 if_link_state_change_1(ifp, ifp->if_link_state_pending,
>                     ifp->if_link_state_lost);
>         ifp->if_link_state_lost = false;
>         splx(s);
> }
>
> static void
> if_link_state_change_1(struct ifnet *ifp, int link_state, bool lost)
> {
>
>         if (lost ||
>             (ifp->if_link_state == LINK_STATE_UP &&
>                 link_state == LINK_STATE_UNKNOWN)) {
>                 /* pretend LINK_STATE_DOWN first */
>         }
>
>         ifp->if_link_state = link_state;
>         /* call domain dom_if_link_state_change callbacks */
>         /* call rt_ifmsg */
> }

Anyway I made a patch based on the above code:
  http://www.netbsd.org/~ozaki-r/link_state_change.diff

What I did are to make your code compilable and workable,
and limit the number of pending events.

Thanks,
  ozaki-r


Home | Main Index | Thread Index | Old Index