aboutsummaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2025-02-10 09:44:06 +0000
committerKristof Provost <kp@FreeBSD.org>2025-02-13 12:38:43 +0000
commit7cef9d196ce999a61ec864961a3849c9159a96a8 (patch)
tree5756e56a9371db293f93705a70d0bf6c1b3e8003 /sbin
parentc11d317a8bd60d93d3c3ced765071f468adacd69 (diff)
pfctl: cache name/index mappings
Provide local implementations of if_nametoindex(3) and if_indextoname(3) that make use of the cache of addresses populated by the ifa_load on startup to save the trouble of calling expensive getaddrinfo(3) up to four times per rule. Performance wise this change provides a speed up factor of 20 with a 11k line ruleset on a machine with 150 VLANs and 250 IP addresses (20 seconds down to 1 in this case). "wow!" henning, ok benno, florian Obtained from: OpenBSD, mikeb <mikeb@openbsd.org>, 918dda8655 Sponsored by: Rubicon Communications, LLC ("Netgate")
Diffstat (limited to 'sbin')
-rw-r--r--sbin/pfctl/parse.y8
-rw-r--r--sbin/pfctl/pfctl_parser.c31
-rw-r--r--sbin/pfctl/pfctl_parser.h2
3 files changed, 37 insertions, 4 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index efbd7cac18e8..40d116fe1a50 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -6216,9 +6216,9 @@ expand_rule(struct pfctl_rule *r,
(src_host->ifindex && dst_host->ifindex &&
src_host->ifindex != dst_host->ifindex) ||
(src_host->ifindex && *interface->ifname &&
- src_host->ifindex != if_nametoindex(interface->ifname)) ||
+ src_host->ifindex != ifa_nametoindex(interface->ifname)) ||
(dst_host->ifindex && *interface->ifname &&
- dst_host->ifindex != if_nametoindex(interface->ifname)))
+ dst_host->ifindex != ifa_nametoindex(interface->ifname)))
continue;
if (!r->af && src_host->af)
r->af = src_host->af;
@@ -6228,9 +6228,9 @@ expand_rule(struct pfctl_rule *r,
if (*interface->ifname)
strlcpy(r->ifname, interface->ifname,
sizeof(r->ifname));
- else if (if_indextoname(src_host->ifindex, ifname))
+ else if (ifa_indextoname(src_host->ifindex, ifname))
strlcpy(r->ifname, ifname, sizeof(r->ifname));
- else if (if_indextoname(dst_host->ifindex, ifname))
+ else if (ifa_indextoname(dst_host->ifindex, ifname))
strlcpy(r->ifname, ifname, sizeof(r->ifname));
else
memset(r->ifname, '\0', sizeof(r->ifname));
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index f567cc78dd23..d1e0b4e99940 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -38,6 +38,7 @@
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/proc.h>
+#include <net/if_dl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
@@ -1518,6 +1519,8 @@ ifa_load(void)
ifa->ifa_addr)->sin6_scope_id;
} else if (n->af == AF_LINK) {
ifa_add_groups_to_map(ifa->ifa_name);
+ n->ifindex = ((struct sockaddr_dl *)
+ ifa->ifa_addr)->sdl_index;
}
if ((n->ifname = strdup(ifa->ifa_name)) == NULL)
err(1, "ifa_load: strdup");
@@ -1584,6 +1587,34 @@ is_a_group(char *name)
return (*(int *)ret_item->data);
}
+unsigned int
+ifa_nametoindex(const char *ifa_name)
+{
+ struct node_host *p;
+
+ for (p = iftab; p; p = p->next) {
+ if (p->af == AF_LINK && strcmp(p->ifname, ifa_name) == 0)
+ return (p->ifindex);
+ }
+ errno = ENXIO;
+ return (0);
+}
+
+char *
+ifa_indextoname(unsigned int ifindex, char *ifa_name)
+{
+ struct node_host *p;
+
+ for (p = iftab; p; p = p->next) {
+ if (p->af == AF_LINK && ifindex == p->ifindex) {
+ strlcpy(ifa_name, p->ifname, IFNAMSIZ);
+ return (ifa_name);
+ }
+ }
+ errno = ENXIO;
+ return (NULL);
+}
+
struct node_host *
ifa_exists(char *ifa_name)
{
diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
index 2b0766dfd99f..e916f5e7c100 100644
--- a/sbin/pfctl/pfctl_parser.h
+++ b/sbin/pfctl/pfctl_parser.h
@@ -363,6 +363,8 @@ int check_netmask(struct node_host *, sa_family_t);
int unmask(struct pf_addr *, sa_family_t);
struct node_host *gen_dynnode(struct node_host *, sa_family_t);
void ifa_load(void);
+unsigned int ifa_nametoindex(const char *);
+char *ifa_indextoname(unsigned int, char *);
int get_query_socket(void);
struct node_host *ifa_exists(char *);
struct node_host *ifa_grouplookup(char *ifa_name, int flags);