pfctl: cache getprotobynumber results
As for example pfctl -ss keeps calling it, it saves a lot of overhead from elided parsing of /etc/nsswitch.conf and /etc/protocols. Sample result when running a pre-nvlist binary with nfs root and dumping 7 mln states: before: 24.817u 62.993s 1:28.52 99.1% after: 8.064u 1.117s 0:18.87 48.5% Idea by Jim Thompson Reviewed by: kp Sponsored by: Rubicon Communications, LLC ("Netgate")
This commit is contained in:
parent
fa3d57c256
commit
858937bea4
@ -5017,13 +5017,13 @@ expand_label_port(const char *name, char *label, size_t len,
|
||||
void
|
||||
expand_label_proto(const char *name, char *label, size_t len, u_int8_t proto)
|
||||
{
|
||||
struct protoent *pe;
|
||||
const char *protoname;
|
||||
char n[4];
|
||||
|
||||
if (strstr(label, name) != NULL) {
|
||||
pe = getprotobynumber(proto);
|
||||
if (pe != NULL)
|
||||
expand_label_str(label, len, name, pe->p_name);
|
||||
protoname = pfctl_proto2name(proto);
|
||||
if (protoname != NULL)
|
||||
expand_label_str(label, len, name, protoname);
|
||||
else {
|
||||
snprintf(n, sizeof(n), "%u", proto);
|
||||
expand_label_str(label, len, name, n);
|
||||
|
@ -211,7 +211,7 @@ print_state(struct pfctl_state *s, int opts)
|
||||
{
|
||||
struct pfctl_state_peer *src, *dst;
|
||||
struct pfctl_state_key *key, *sk, *nk;
|
||||
struct protoent *p;
|
||||
const char *protoname;
|
||||
int min, sec;
|
||||
sa_family_t af;
|
||||
uint8_t proto;
|
||||
@ -243,8 +243,8 @@ print_state(struct pfctl_state *s, int opts)
|
||||
sk->port[1] = nk->port[1];
|
||||
}
|
||||
printf("%s ", s->ifname);
|
||||
if ((p = getprotobynumber(proto)) != NULL)
|
||||
printf("%s ", p->p_name);
|
||||
if ((protoname = pfctl_proto2name(proto)) != NULL)
|
||||
printf("%s ", protoname);
|
||||
else
|
||||
printf("%u ", proto);
|
||||
|
||||
|
@ -254,6 +254,49 @@ usage(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cache protocol number to name translations.
|
||||
*
|
||||
* Translation is performed a lot e.g., when dumping states and
|
||||
* getprotobynumber is incredibly expensive.
|
||||
*
|
||||
* Note from the getprotobynumber(3) manpage:
|
||||
* <quote>
|
||||
* These functions use a thread-specific data space; if the data is needed
|
||||
* for future use, it should be copied before any subsequent calls overwrite
|
||||
* it. Only the Internet protocols are currently understood.
|
||||
* </quote>
|
||||
*
|
||||
* Consequently we only cache the name and strdup it for safety.
|
||||
*
|
||||
* At the time of writing this comment the last entry in /etc/protocols is:
|
||||
* divert 258 DIVERT # Divert pseudo-protocol [non IANA]
|
||||
*/
|
||||
const char *
|
||||
pfctl_proto2name(int proto)
|
||||
{
|
||||
static const char *pfctl_proto_cache[259];
|
||||
struct protoent *p;
|
||||
|
||||
if (proto >= nitems(pfctl_proto_cache)) {
|
||||
p = getprotobynumber(proto);
|
||||
if (p == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
return (p->p_name);
|
||||
}
|
||||
|
||||
if (pfctl_proto_cache[proto] == NULL) {
|
||||
p = getprotobynumber(proto);
|
||||
if (p == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
pfctl_proto_cache[proto] = strdup(p->p_name);
|
||||
}
|
||||
|
||||
return (pfctl_proto_cache[proto]);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_enable(int dev, int opts)
|
||||
{
|
||||
|
@ -138,4 +138,6 @@ void pf_remove_if_empty_ruleset(struct pfctl_ruleset *);
|
||||
struct pfctl_ruleset *pf_find_ruleset(const char *);
|
||||
struct pfctl_ruleset *pf_find_or_create_ruleset(const char *);
|
||||
|
||||
const char *pfctl_proto2name(int);
|
||||
|
||||
#endif /* _PFCTL_H_ */
|
||||
|
@ -812,10 +812,10 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
|
||||
printf(" inet6");
|
||||
}
|
||||
if (r->proto) {
|
||||
struct protoent *p;
|
||||
const char *protoname;
|
||||
|
||||
if ((p = getprotobynumber(r->proto)) != NULL)
|
||||
printf(" proto %s", p->p_name);
|
||||
if ((protoname = pfctl_proto2name(r->proto)) != NULL)
|
||||
printf(" proto %s", protoname);
|
||||
else
|
||||
printf(" proto %u", r->proto);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user