diff options
author | Kristof Provost <kp@FreeBSD.org> | 2025-02-10 09:44:06 +0000 |
---|---|---|
committer | Kristof Provost <kp@FreeBSD.org> | 2025-02-13 12:38:43 +0000 |
commit | 7cef9d196ce999a61ec864961a3849c9159a96a8 (patch) | |
tree | 5756e56a9371db293f93705a70d0bf6c1b3e8003 /sbin | |
parent | c11d317a8bd60d93d3c3ced765071f468adacd69 (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.y | 8 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 31 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.h | 2 |
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); |