From: bluhm Date: Thu, 5 Oct 2023 11:08:56 +0000 (+0000) Subject: Protect interface queues with read once and mutex. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=37a618ff0e3b8e2e9e04053f139425739064f885;p=openbsd Protect interface queues with read once and mutex. Reading atomic values need at least read once and writing values should have a mutex. This is what mbuf queues already do. Add READ_ONCE() to ifq and ifiq macros for len and empty. Convert ifq_set_maxlen() to a function that grabs ifq_mtx. OK mvs@ --- diff --git a/sys/net/ifq.c b/sys/net/ifq.c index 81aa5b9a61f..7255f449ba3 100644 --- a/sys/net/ifq.c +++ b/sys/net/ifq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ifq.c,v 1.50 2023/07/30 05:39:52 dlg Exp $ */ +/* $OpenBSD: ifq.c,v 1.51 2023/10/05 11:08:56 bluhm Exp $ */ /* * Copyright (c) 2015 David Gwynne @@ -529,6 +529,14 @@ ifq_hdatalen(struct ifqueue *ifq) return (len); } +void +ifq_set_maxlen(struct ifqueue *ifq, unsigned int maxlen) +{ + mtx_enter(&ifq->ifq_mtx); + ifq->ifq_maxlen = maxlen; + mtx_leave(&ifq->ifq_mtx); +} + unsigned int ifq_purge(struct ifqueue *ifq) { diff --git a/sys/net/ifq.h b/sys/net/ifq.h index c32a635a835..d15af37b45f 100644 --- a/sys/net/ifq.h +++ b/sys/net/ifq.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ifq.h,v 1.38 2023/07/30 05:39:52 dlg Exp $ */ +/* $OpenBSD: ifq.h,v 1.39 2023/10/05 11:08:56 bluhm Exp $ */ /* * Copyright (c) 2015 David Gwynne @@ -435,6 +435,7 @@ void ifq_deq_commit(struct ifqueue *, struct mbuf *); void ifq_deq_rollback(struct ifqueue *, struct mbuf *); struct mbuf *ifq_dequeue(struct ifqueue *); int ifq_hdatalen(struct ifqueue *); +void ifq_set_maxlen(struct ifqueue *, unsigned int); void ifq_mfreem(struct ifqueue *, struct mbuf *); void ifq_mfreeml(struct ifqueue *, struct mbuf_list *); unsigned int ifq_purge(struct ifqueue *); @@ -448,9 +449,8 @@ int ifq_deq_sleep(struct ifqueue *, struct mbuf **, int, int, const char *, volatile unsigned int *, volatile unsigned int *); -#define ifq_len(_ifq) ((_ifq)->ifq_len) -#define ifq_empty(_ifq) (ifq_len(_ifq) == 0) -#define ifq_set_maxlen(_ifq, _l) ((_ifq)->ifq_maxlen = (_l)) +#define ifq_len(_ifq) READ_ONCE((_ifq)->ifq_len) +#define ifq_empty(_ifq) (ifq_len(_ifq) == 0) static inline int ifq_is_priq(struct ifqueue *ifq) @@ -490,8 +490,8 @@ int ifiq_input(struct ifiqueue *, struct mbuf_list *); int ifiq_enqueue(struct ifiqueue *, struct mbuf *); void ifiq_add_data(struct ifiqueue *, struct if_data *); -#define ifiq_len(_ifiq) ml_len(&(_ifiq)->ifiq_ml) -#define ifiq_empty(_ifiq) ml_empty(&(_ifiq)->ifiq_ml) +#define ifiq_len(_ifiq) READ_ONCE(ml_len(&(_ifiq)->ifiq_ml)) +#define ifiq_empty(_ifiq) (ifiq_len(_ifiq) == 0) #endif /* _KERNEL */