Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F146108479
D39200.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D39200.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,45 @@
return (error);
}
+struct _if_iter_ext {
+ union {
+ if_t ifp;
+ int array_index;
+ };
+ union {
+ if_foreach_match_t match_cb;
+ struct ifnet **array;
+ };
+ union {
+ void *match_arg;
+ int array_len;
+ };
+ uint32_t can_sleep:1;
+};
+_Static_assert(sizeof(struct _if_iter_ext) <= sizeof(struct if_iter),
+ "Public version of if_iter structure is too small");
+
+
+int
+if_foreach_sleep(if_foreach_match_t match_cb, void *match_arg, if_foreach_cb_t cb,
+ void *cb_arg)
+{
+ struct if_iter_ext_params params = {
+ .match_cb = match_cb,
+ .match_arg = match_arg,
+ .can_sleep = true,
+ };
+ struct if_iter it;
+ int error = 0;
+
+ for (if_t ifp = if_iter_ext_start(&it, ¶ms); ifp; ifp = if_iter_ext_next(&it)) {
+ if (error == 0)
+ error = cb(ifp, cb_arg);
+ }
+
+ return (error);
+}
+
/*
* Iterates over the list of interfaces, permitting callback function @cb to sleep.
* Stops iteration if @cb returns non-zero error code.
@@ -4544,15 +4583,11 @@
* @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)
+static void
+prepare_iflist(struct _if_iter_ext *iter)
{
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;
@@ -4572,7 +4607,7 @@
match_count = 0;
NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
- if (match_cb != NULL && !match_cb(ifp, match_arg))
+ if (!iter->match_cb(ifp, iter->match_arg))
continue;
if (match_count < array_size) {
if (if_try_ref(ifp))
@@ -4587,17 +4622,80 @@
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);
+ iter->array = match_array;
+ iter->array_index = 0;
+ iter->array_len = match_count;
break;
}
}
+}
- return (error);
+static bool
+match_each_ifp(struct ifnet *ifp __unused, void *_arg __unused)
+{
+ return (true);
+}
+
+/*
+ * Starts iteration over the list of interfaces.
+ * If @params->can_sleep is true, permits sleeping while iterating
+ *
+ * Returns: first matching interface or NULL
+ */
+if_t
+if_iter_ext_start(struct if_iter *_iter, struct if_iter_ext_params *params)
+{
+ struct _if_iter_ext *iter = (struct _if_iter_ext *)_iter;
+
+ bzero(iter, sizeof(*iter));
+
+ iter->match_cb = params->match_cb ? params->match_cb : match_each_ifp;
+ if (params != NULL) {
+ iter->match_arg = params->match_arg;
+ iter->can_sleep = params->can_sleep;
+ }
+
+ if (iter->can_sleep)
+ prepare_iflist(iter);
+ else
+ iter->ifp = CK_STAILQ_FIRST(&V_ifnet);
+
+ return (if_iter_ext_next(_iter));
+}
+
+if_t
+if_iter_ext_next(struct if_iter *_iter)
+{
+ struct _if_iter_ext *iter = (struct _if_iter_ext *)_iter;
+
+ if (iter->can_sleep) {
+ if (iter->array_index < iter->array_len)
+ return (iter->array[iter->array_index++]);
+ } else {
+ if_t ifp = iter->ifp;
+
+ while (ifp != NULL && !iter->match_cb(ifp, iter->match_arg)) {
+ ifp = CK_STAILQ_NEXT(ifp, if_link);
+ }
+
+ if (ifp != NULL)
+ iter->ifp = CK_STAILQ_NEXT(ifp, if_link);
+ return (ifp);
+ }
+
+ return (NULL);
+}
+
+void
+if_iter_ext_finish(struct if_iter *_iter)
+{
+ struct _if_iter_ext *iter = (struct _if_iter_ext *)_iter;
+
+ if (iter->can_sleep && iter->array != NULL) {
+ for (int i = 0; i < iter->array_len; i++)
+ if_rele(iter->array[i]);
+ free(iter->array, M_TEMP);
+ }
}
@@ -4718,6 +4816,105 @@
return (count);
}
+struct _ifa_iter_ext {
+ struct ifaddr *ifa;
+ sa_family_t type;
+};
+_Static_assert(sizeof(struct _ifa_iter_ext) < sizeof(struct ifa_iter),
+ "Public version of ifa_iter structure is too small");
+
+struct ifaddr *
+ifa_iter_ext_start(if_t ifp, struct ifa_iter *_iter, struct ifa_iter_ext_params *params)
+{
+ struct _ifa_iter_ext *iter = (struct _ifa_iter_ext *)_iter;
+
+ NET_EPOCH_ASSERT();
+
+ bzero(iter, sizeof(*iter));
+ if (params != NULL)
+ iter->type = params->type;
+ iter->ifa = CK_STAILQ_FIRST(&ifp->if_addrhead);
+
+ return (ifa_iter_ext_next(_iter));
+}
+
+struct ifaddr *
+ifa_iter_ext_next(struct ifa_iter *_iter)
+{
+ struct _ifa_iter_ext *iter = (struct _ifa_iter_ext *)_iter;
+ struct ifaddr *ifa = iter->ifa;
+
+ while (ifa != NULL && iter->type != 0 && iter->type != ifa->ifa_addr->sa_family)
+ ifa = CK_STAILQ_NEXT(ifa, ifa_link);
+ if (ifa != NULL)
+ iter->ifa = CK_STAILQ_NEXT(ifa, ifa_link);
+ return (ifa);
+}
+
+void
+ifa_iter_ext_finish(struct ifa_iter *_iter __unused)
+{
+}
+
+struct ifaddr *
+ifa_ll_iter_start(if_t ifp, struct ifa_iter *_iter)
+{
+ struct ifa_iter_ext_params params = { .type = AF_LINK };
+
+ return (ifa_iter_ext_start(ifp, _iter, ¶ms));
+}
+
+struct ifaddr *
+ifa_ll_iter_next(struct ifa_iter *_iter)
+{
+ return (ifa_iter_ext_next(_iter));
+}
+
+void
+ifa_ll_iter_finish(struct ifa_iter *_iter __unused)
+{
+}
+
+struct _ifma_iter {
+ struct ifmultiaddr *ifma;
+};
+_Static_assert(sizeof(struct _ifma_iter) < sizeof(struct ifa_iter),
+ "Public version of ifa_iter structure is too small");
+
+struct ifmultiaddr *
+ifma_ll_iter_start(if_t ifp, struct ifa_iter *_iter)
+{
+ struct _ifma_iter *iter = (struct _ifma_iter *)_iter;
+
+ NET_EPOCH_ASSERT();
+
+ bzero(iter, sizeof(*iter));
+
+ iter->ifma = CK_STAILQ_FIRST(&ifp->if_multiaddrs);
+
+ return (ifma_ll_iter_next(_iter));
+}
+
+struct ifmultiaddr *
+ifma_ll_iter_next(struct ifa_iter *_iter)
+{
+ struct _ifma_iter *iter = (struct _ifma_iter *)_iter;
+ struct ifmultiaddr *ifma = iter->ifma;
+
+ while (ifma != NULL && ifma->ifma_addr->sa_family != AF_LINK)
+ ifma = CK_STAILQ_NEXT(ifma, ifma_link);
+
+ if (ifma != NULL)
+ iter->ifma = CK_STAILQ_NEXT(ifma, ifma_link);
+
+ return (ifma);
+}
+
+void
+ifma_ll_iter_finish(struct ifa_iter *_iter __unused)
+{
+}
+
int
if_setsoftc(if_t ifp, void *softc)
{
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
@@ -689,9 +689,42 @@
void *context[4];
};
+struct if_iter_ext_params {
+ if_foreach_match_t match_cb;
+ void *match_arg;
+ uint32_t can_sleep:1;
+ uint32_t spare;
+};
+
if_t if_iter_start(struct if_iter *);
if_t if_iter_next(struct if_iter *);
void if_iter_finish(struct if_iter *);
+if_t if_iter_ext_start(struct if_iter *, struct if_iter_ext_params *);
+if_t if_iter_ext_next(struct if_iter *);
+void if_iter_ext_finish(struct if_iter *iter);
+
+/* Opaque iterator structure for iterating over interface addresses. */
+struct ifa_iter {
+ void *context[4];
+};
+
+struct ifa_iter_ext_params {
+ sa_family_t type;
+ uint8_t spare0[7];
+ uint64_t spare1[3];
+};
+
+struct ifaddr *ifa_iter_ext_start(if_t ifp, struct ifa_iter *, struct ifa_iter_ext_params *);
+struct ifaddr *ifa_iter_ext_next(struct ifa_iter *);
+void ifa_iter_ext_finish(struct ifa_iter *);
+
+struct ifaddr *ifa_ll_iter_start(if_t, struct ifa_iter *);
+struct ifaddr *ifa_ll_iter_next(struct ifa_iter *);
+void ifa_ll_iter_finish(struct ifa_iter *);
+
+struct ifmultiaddr *ifma_ll_iter_start(if_t, struct ifa_iter *);
+struct ifmultiaddr *ifma_ll_iter_next(struct ifa_iter *);
+void ifma_ll_iter_finish(struct ifa_iter *);
/* Functions */
void if_setinitfn(if_t ifp, if_init_fn_t);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Feb 28, 9:34 PM (47 m, 27 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29083301
Default Alt Text
D39200.diff (7 KB)
Attached To
Mode
D39200: ifnet: add iterator functions for the if/ifa/ifma.
Attached
Detach File
Event Timeline
Log In to Comment