netlink: use newly-added if_foreach_sleep() to iterate over the interface list.

Summary: MFC after:	2 weeks

Subscribers: imp, glebius

Differential Revision: https://reviews.freebsd.org/D38907
This commit is contained in:
Alexander V. Chernikov 2023-03-04 15:15:56 +00:00
parent df2b419a41
commit 055776c84a

View File

@ -360,8 +360,10 @@ static const struct nlattr_parser nla_p_if[] = {
NL_DECLARE_STRICT_PARSER(ifmsg_parser, struct ifinfomsg, check_ifmsg, nlf_p_if, nla_p_if);
static bool
match_iface(struct nl_parsed_link *attrs, struct ifnet *ifp)
match_iface(struct ifnet *ifp, void *_arg)
{
struct nl_parsed_link *attrs = (struct nl_parsed_link *)_arg;
if (attrs->ifi_index != 0 && attrs->ifi_index != ifp->if_index)
return (false);
if (attrs->ifi_type != 0 && attrs->ifi_index != ifp->if_type)
@ -373,6 +375,15 @@ match_iface(struct nl_parsed_link *attrs, struct ifnet *ifp)
return (true);
}
static int
dump_cb(struct ifnet *ifp, void *_arg)
{
struct netlink_walkargs *wa = (struct netlink_walkargs *)_arg;
if (!dump_iface(wa->nw, ifp, &wa->hdr, 0))
return (ENOMEM);
return (0);
}
/*
* {nlmsg_len=52, nlmsg_type=RTM_GETLINK, nlmsg_flags=NLM_F_REQUEST, nlmsg_seq=1662842818, nlmsg_pid=0},
* {ifi_family=AF_PACKET, ifi_type=ARPHRD_NETROM, ifi_index=0, ifi_flags=0, ifi_change=0},
@ -417,7 +428,7 @@ rtnl_handle_getlink(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *n
}
if (ifp != NULL) {
if (match_iface(&attrs, ifp)) {
if (match_iface(ifp, &attrs)) {
if (!dump_iface(wa.nw, ifp, &wa.hdr, 0))
error = ENOMEM;
} else
@ -438,46 +449,7 @@ rtnl_handle_getlink(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *n
*/
NL_LOG(LOG_DEBUG2, "Start dump");
struct ifnet **match_array = NULL;
int offset = 0, base_count = 0;
NLP_LOG(LOG_DEBUG3, nlp, "MATCHING: index=%u type=%d name=%s",
attrs.ifi_index, attrs.ifi_type, attrs.ifla_ifname);
NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
wa.count++;
if (match_iface(&attrs, ifp)) {
if (offset >= base_count) {
/* Too many matches, need to reallocate */
struct ifnet **new_array;
/* Start with 128 bytes, do 2x increase on each realloc */
base_count = (base_count != 0) ? base_count * 2 : 16;
new_array = malloc(base_count * sizeof(void *), M_TEMP, M_NOWAIT);
if (new_array == NULL) {
error = ENOMEM;
break;
}
memcpy(new_array, match_array, offset * sizeof(void *));
free(match_array, M_TEMP);
match_array = new_array;
}
if (if_try_ref(ifp))
match_array[offset++] = ifp;
}
}
NET_EPOCH_EXIT(et);
NL_LOG(LOG_DEBUG2, "Matched %d interface(s), dumping", offset);
for (int i = 0; error == 0 && i < offset; i++) {
if (!dump_iface(wa.nw, match_array[i], &wa.hdr, 0))
error = ENOMEM;
}
for (int i = 0; i < offset; i++)
if_rele(match_array[i]);
free(match_array, M_TEMP);
if_foreach_sleep(match_iface, &attrs, dump_cb, &wa);
NL_LOG(LOG_DEBUG2, "End dump, iterated %d dumped %d", wa.count, wa.dumped);
if (!nlmsg_end_dump(wa.nw, error, &wa.hdr)) {