-/* $OpenBSD: if_ether.c,v 1.245 2021/04/23 21:55:36 bluhm Exp $ */
+/* $OpenBSD: if_ether.c,v 1.246 2021/04/26 07:55:16 bluhm Exp $ */
/* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */
/*
struct llinfo_arp {
LIST_ENTRY(llinfo_arp) la_list;
struct rtentry *la_rt; /* backpointer to rtentry */
- struct mbuf_list la_ml; /* packet hold queue */
+ struct mbuf_queue la_mq; /* packet hold queue */
time_t la_refreshed; /* when was refresh sent */
int la_asked; /* number of queries sent */
};
break;
}
- ml_init(&la->la_ml);
+ mq_init(&la->la_mq, LA_HOLD_QUEUE, IPL_SOFTNET);
la->la_rt = rt;
rt->rt_flags |= RTF_LLINFO;
if ((rt->rt_flags & RTF_LOCAL) == 0)
LIST_REMOVE(la, la_list);
rt->rt_llinfo = NULL;
rt->rt_flags &= ~RTF_LLINFO;
- la_hold_total -= ml_purge(&la->la_ml);
+ atomic_sub_int(&la_hold_total, mq_purge(&la->la_mq));
pool_put(&arp_pool, la);
break;
* response yet. Insert mbuf in hold queue if below limit
* if above the limit free the queue without queuing the new packet.
*/
- if (la_hold_total < LA_HOLD_TOTAL) {
- struct mbuf *mh;
-
- if (ml_len(&la->la_ml) >= LA_HOLD_QUEUE) {
- mh = ml_dequeue(&la->la_ml);
- la_hold_total--;
- m_freem(mh);
- }
- ml_enqueue(&la->la_ml, m);
- la_hold_total++;
+ if (atomic_inc_int_nv(&la_hold_total) <= LA_HOLD_TOTAL) {
+ if (mq_push(&la->la_mq, m) != 0)
+ atomic_dec_int(&la_hold_total);
} else {
- la_hold_total -= ml_purge(&la->la_ml);
+ atomic_sub_int(&la_hold_total, mq_purge(&la->la_mq) + 1);
m_freem(m);
}
rt->rt_expire += arpt_down;
la->la_asked = 0;
la->la_refreshed = 0;
- la_hold_total -= ml_purge(&la->la_ml);
+ atomic_sub_int(&la_hold_total,
+ mq_purge(&la->la_mq));
}
}
}
struct in_addr *spa = (struct in_addr *)ea->arp_spa;
char addr[INET_ADDRSTRLEN];
struct ifnet *rifp;
- unsigned int len;
+ struct mbuf *m;
int changed = 0;
KERNEL_ASSERT_LOCKED();
la->la_asked = 0;
la->la_refreshed = 0;
- while ((len = ml_len(&la->la_ml)) != 0) {
- struct mbuf *mh;
+ while ((m = mq_dequeue(&la->la_mq)) != NULL) {
+ unsigned int len;
- mh = ml_dequeue(&la->la_ml);
- la_hold_total--;
+ atomic_dec_int(&la_hold_total);
+ len = mq_len(&la->la_mq);
- ifp->if_output(ifp, mh, rt_key(rt), rt);
+ ifp->if_output(ifp, m, rt_key(rt), rt);
- if (ml_len(&la->la_ml) == len) {
+ /* XXXSMP we discard if other CPU enqueues */
+ if (mq_len(&la->la_mq) > len) {
/* mbuf is back in queue. Discard. */
- while ((mh = ml_dequeue(&la->la_ml)) != NULL) {
- la_hold_total--;
- m_freem(mh);
- }
+ atomic_sub_int(&la_hold_total, mq_purge(&la->la_mq));
break;
}
}
struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
struct sockaddr_dl *sdl = satosdl(rt->rt_gateway);
- la_hold_total -= ml_purge(&la->la_ml);
+ atomic_sub_int(&la_hold_total, mq_purge(&la->la_mq));
sdl->sdl_alen = 0;
la->la_asked = 0;
}