Hello,

On Tue, Apr 27, 2021 at 11:45:19PM +0200, Alexander Bluhm wrote:
> On Sun, Apr 25, 2021 at 06:08:17PM +1000, Jonathan Matthew wrote:
> > On Sun, Apr 25, 2021 at 09:44:16AM +0200, Alexandr Nedvedicky wrote:
> > This already exists, it's called mq_delist()
> 
> Here is the diff with mq_delist().
> 
> > We'd need some other way to do the 'mbuf is back in queue' detection,
> > but I agree this seems like a sensible thing to do.
> 
> This part is ugly as before.  I have put a printf in the discard
> case it and I never hit it.  Any idea why we need this and how to
> fix it?
> 
> ok?
> 
> bluhm
> 
> Index: netinet/if_ether.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/if_ether.c,v
> retrieving revision 1.246
> diff -u -p -r1.246 if_ether.c
> --- netinet/if_ether.c        26 Apr 2021 07:55:16 -0000      1.246
> +++ netinet/if_ether.c        27 Apr 2021 21:02:27 -0000
> @@ -594,7 +594,9 @@ arpcache(struct ifnet *ifp, struct ether
>       struct in_addr *spa = (struct in_addr *)ea->arp_spa;
>       char addr[INET_ADDRSTRLEN];
>       struct ifnet *rifp;
> +     struct mbuf_list ml;
>       struct mbuf *m;
> +     unsigned int len;
>       int changed = 0;
> 
>       KERNEL_ASSERT_LOCKED();
> @@ -666,21 +668,17 @@ arpcache(struct ifnet *ifp, struct ether
> 
>       la->la_asked = 0;
>       la->la_refreshed = 0;
> -     while ((m = mq_dequeue(&la->la_mq)) != NULL) {
> -             unsigned int len;
> -
> -             atomic_dec_int(&la_hold_total);
> -             len = mq_len(&la->la_mq);
> -
> +     mq_delist(&la->la_mq, &ml);
> +     len = ml_len(&ml);
> +     while ((m = ml_dequeue(&ml)) != NULL) {
>               ifp->if_output(ifp, m, rt_key(rt), rt);
> -
> -             /* XXXSMP we discard if other CPU enqueues */
> -             if (mq_len(&la->la_mq) > len) {
> -                     /* mbuf is back in queue. Discard. */
> -                     atomic_sub_int(&la_hold_total, mq_purge(&la->la_mq));
> -                     break;
> -             }
>       }

> +     /* XXXSMP we discard if other CPU enqueues */
> +     if (mq_len(&la->la_mq) > 0) {
> +             /* mbuf is back in queue. Discard. */
> +             atomic_sub_int(&la_hold_total, len + mq_purge(&la->la_mq));
> +     } else
> +             atomic_sub_int(&la_hold_total, len);
> 

    I think /* XXXSMP ... */ code-chunk is no longer needed. I think your
    change, which introduces  ml_dequeue(), turns that into an useless
    artifact.

    If I understand old code right this extra check tries to make sure
    the while() loop completes. I assume ifp->if_output() calls ether_output(),
    which in turn calls ether_encap() -> ether_resolve(). If ether_resolve()
    fails to find ARP entry (for whatever reason, perhaps explicit 'arp -d -a'
    or interface down), the packet is inserted back to la->la_mq. This would
    keep the while loop spinning.

    using ml_dequeue() solves that problem, because the while() loop now
    consumes a private list of packets, which can not grow. It's granted
    the loop will finish.

    So I would just delete those lines.


thanks and
regards
sashan


>       return (0);
>  }

Reply via email to