Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144858402
D38904.1776731652.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
2 KB
Referenced Files
None
Subscribers
None
D38904.1776731652.diff
View Options
diff --git a/sys/net/if.c b/sys/net/if.c
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -4535,6 +4535,71 @@
return (error);
}
+/*
+ * Iterates over the list of interfaces, permitting callback function @cb to sleep.
+ * Stops iteration if @cb returns non-zero error code.
+ * Returns the last error code from @cb.
+ * @match_cb: optional match callback limiting the iteration to only matched interfaces
+ * @match_arg: argument to pass to @match_cb
+ * @cb: iteration callback
+ * @cb_arg: argument to pass to @cb
+ */
+int
+if_foreach_sleep(if_foreach_match_t match_cb, void *match_arg, if_foreach_cb_t cb,
+ void *cb_arg)
+{
+ int match_count = 0, array_size = 16; /* 128 bytes for malloc */
+ struct ifnet **match_array = NULL;
+ int error = 0;
+
+ MPASS(cb);
+
+ while (true) {
+ struct ifnet **new_array;
+ int new_size = array_size;
+ struct epoch_tracker et;
+ struct ifnet *ifp;
+
+ while (new_size < match_count)
+ new_size *= 2;
+ new_array = malloc(new_size * sizeof(void *), M_TEMP, M_WAITOK);
+ if (match_array != NULL)
+ memcpy(new_array, match_array, array_size * sizeof(void *));
+ free(match_array, M_TEMP);
+ match_array = new_array;
+ array_size = new_size;
+
+ match_count = 0;
+ NET_EPOCH_ENTER(et);
+ CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
+ if (match_cb != NULL && !match_cb(ifp, match_arg))
+ continue;
+ if (match_count < array_size) {
+ if (if_try_ref(ifp))
+ match_array[match_count++] = ifp;
+ } else
+ match_count++;
+ }
+ NET_EPOCH_EXIT(et);
+
+ if (match_count > array_size) {
+ for (int i = 0; i < array_size; i++)
+ if_rele(match_array[i]);
+ continue;
+ } else {
+ for (int i = 0; i < match_count; i++) {
+ if (error == 0)
+ error = cb(match_array[i], cb_arg);
+ if_rele(match_array[i]);
+ }
+ free(match_array, M_TEMP);
+ break;
+ }
+ }
+
+ return (error);
+}
+
u_int
if_foreach_lladdr(if_t ifp, iflladdr_cb_t cb, void *cb_arg)
{
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -680,7 +680,9 @@
u_int if_foreach_addr_type(if_t ifp, int type, if_addr_cb_t cb, void *cb_arg);
typedef int (*if_foreach_cb_t)(if_t, void *);
+typedef bool (*if_foreach_match_t)(if_t, void *);
int if_foreach(if_foreach_cb_t, void *);
+int if_foreach_sleep(if_foreach_match_t, void *, if_foreach_cb_t, void *);
/* Functions */
void if_setinitfn(if_t ifp, if_init_fn_t);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 21, 12:34 AM (3 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28394292
Default Alt Text
D38904.1776731652.diff (2 KB)
Attached To
Mode
D38904: ifnet: add if_foreach_sleep() to allow ifnet iterations with sleep.
Attached
Detach File
Event Timeline
Log In to Comment