Protect interface queues with read once and mutex.
authorbluhm <bluhm@openbsd.org>
Thu, 5 Oct 2023 11:08:56 +0000 (11:08 +0000)
committerbluhm <bluhm@openbsd.org>
Thu, 5 Oct 2023 11:08:56 +0000 (11:08 +0000)
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@

sys/net/ifq.c
sys/net/ifq.h

index 81aa5b9..7255f44 100644 (file)
@@ -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 <dlg@openbsd.org>
@@ -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)
 {
index c32a635..d15af37 100644 (file)
@@ -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 <dlg@openbsd.org>
@@ -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 */