Page MenuHomeFreeBSD

D39200.diff
No OneTemporary

D39200.diff

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, &params); 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, &params));
+}
+
+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

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)

Event Timeline