Index: net/pf.c =================================================================== RCS file: /cvs/src/sys/net/pf.c,v retrieving revision 1.1153 diff -u -p -r1.1153 pf.c --- net/pf.c 12 Nov 2022 02:48:14 -0000 1.1153 +++ net/pf.c 21 Nov 2022 08:03:03 -0000 @@ -60,6 +60,7 @@ #include #include #include +#include #include #include @@ -232,8 +233,12 @@ int pf_addr_wrap_neq(struct pf_addr_w struct pf_addr_wrap *); int pf_compare_state_keys(struct pf_state_key *, struct pf_state_key *, struct pfi_kif *, u_int); +uint16_t pf_pkt_hash(sa_family_t, uint8_t, + const struct pf_addr *, const struct pf_addr *, + uint16_t, uint16_t); int pf_find_state(struct pf_pdesc *, - struct pf_state_key_cmp *, struct pf_state **); + const struct pf_state_key_cmp *, + struct pf_state **); int pf_src_connlimit(struct pf_state **); int pf_match_rcvif(struct mbuf *, struct pf_rule *); int pf_step_into_anchor(struct pf_test_ctx *, @@ -684,6 +689,8 @@ pf_state_compare_key(struct pf_state_key { int diff; + if ((diff = a->hash - b->hash) != 0) + return (diff); if ((diff = a->proto - b->proto) != 0) return (diff); if ((diff = a->af - b->af) != 0) @@ -912,6 +919,7 @@ pf_state_key_setup(struct pf_pdesc *pd, sk1->proto = pd->proto; sk1->af = pd->af; sk1->rdomain = pd->rdomain; + sk1->hash = pd->hash; PF_REF_INIT(sk1->refcnt); sk1->removed = 0; if (rtableid >= 0) @@ -930,6 +938,7 @@ pf_state_key_setup(struct pf_pdesc *pd, pd->naf, 0); sk2->port[afto ? pd->didx : pd->sidx] = pd->nsport; sk2->port[afto ? pd->sidx : pd->didx] = pd->ndport; + if (afto) { switch (pd->proto) { case IPPROTO_ICMP: @@ -945,6 +954,8 @@ pf_state_key_setup(struct pf_pdesc *pd, sk2->proto = pd->proto; sk2->af = pd->naf; sk2->rdomain = wrdom; + sk2->hash = pf_pkt_hash(sk2->af, sk2->proto, + &sk2->addr[0], &sk2->addr[1], sk2->port[0], sk2->port[1]); PF_REF_INIT(sk2->refcnt); sk2->removed = 0; } else @@ -1066,7 +1077,7 @@ pf_compare_state_keys(struct pf_state_ke } int -pf_find_state(struct pf_pdesc *pd, struct pf_state_key_cmp *key, +pf_find_state(struct pf_pdesc *pd, const struct pf_state_key_cmp *key, struct pf_state **state) { struct pf_state_key *sk, *pkt_sk, *inp_sk; @@ -1387,6 +1398,9 @@ pf_state_import(const struct pfsync_stat skw->proto = sp->proto; if (!(skw->af = sp->key[PF_SK_WIRE].af)) skw->af = sp->af; + skw->hash = pf_pkt_hash(skw->af, skw->proto, + &skw->addr[0], &skw->addr[1], skw->port[0], skw->port[1]); + if (sks != skw) { sks->addr[0] = sp->key[PF_SK_STACK].addr[0]; sks->addr[1] = sp->key[PF_SK_STACK].addr[1]; @@ -1416,6 +1430,9 @@ pf_state_import(const struct pfsync_stat goto cleanup; } + sks->hash = pf_pkt_hash(sks->af, sks->proto, + &sks->addr[0], &sks->addr[1], sks->port[0], sks->port[1]); + } else if ((sks->af != AF_INET) && (sks->af != AF_INET6)) { error = EINVAL; goto cleanup; @@ -5343,6 +5360,9 @@ pf_icmp_state_lookup(struct pf_pdesc *pd pd->dst, pd->af, multi)) return (PF_DROP); + key->hash = pf_pkt_hash(pd->af, pd->proto, + pd->src, pd->dst, 0, 0); + action = pf_find_state(pd, key, state); if (action != PF_MATCH) return (action); @@ -5612,6 +5632,8 @@ pf_test_state_icmp(struct pf_pdesc *pd, pf_addrcpy(&key.addr[pd2.didx], pd2.dst, key.af); key.port[pd2.sidx] = th->th_sport; key.port[pd2.didx] = th->th_dport; + key.hash = pf_pkt_hash(pd2.af, pd2.proto, + pd2.src, pd2.dst, th->th_sport, th->th_dport); action = pf_find_state(&pd2, &key, state); if (action != PF_MATCH) @@ -5790,6 +5812,8 @@ pf_test_state_icmp(struct pf_pdesc *pd, pf_addrcpy(&key.addr[pd2.didx], pd2.dst, key.af); key.port[pd2.sidx] = uh->uh_sport; key.port[pd2.didx] = uh->uh_dport; + key.hash = pf_pkt_hash(pd2.af, pd2.proto, + pd2.src, pd2.dst, uh->uh_sport, uh->uh_dport); action = pf_find_state(&pd2, &key, state); if (action != PF_MATCH) @@ -6124,6 +6148,8 @@ pf_test_state_icmp(struct pf_pdesc *pd, pf_addrcpy(&key.addr[pd2.sidx], pd2.src, key.af); pf_addrcpy(&key.addr[pd2.didx], pd2.dst, key.af); key.port[0] = key.port[1] = 0; + key.hash = pf_pkt_hash(pd2.af, pd2.proto, + pd2.src, pd2.dst, 0, 0); action = pf_find_state(&pd2, &key, state); if (action != PF_MATCH) @@ -7052,6 +7078,32 @@ pf_walk_header6(struct pf_pdesc *pd, str } #endif /* INET6 */ +uint16_t +pf_pkt_hash(sa_family_t af, uint8_t proto, + const struct pf_addr *src, const struct pf_addr *dst, + uint16_t sport, uint16_t dport) +{ + uint32_t hash; + + hash = src->addr32[0] ^ dst->addr32[0]; +#ifdef INET6 + if (af == AF_INET6) { + hash ^= src->addr32[1] ^ dst->addr32[1]; + hash ^= src->addr32[2] ^ dst->addr32[2]; + hash ^= src->addr32[3] ^ dst->addr32[3]; + } +#endif + + switch (proto) { + case IPPROTO_TCP: + case IPPROTO_UDP: + hash ^= sport ^ dport; + break; + } + + return stoeplitz_n32(hash); +} + int pf_setup_pdesc(struct pf_pdesc *pd, sa_family_t af, int dir, struct pfi_kif *kif, struct mbuf *m, u_short *reason) @@ -7239,6 +7291,9 @@ pf_setup_pdesc(struct pf_pdesc *pd, sa_f if (pd->dport) pd->odport = pd->ndport = *pd->dport; + pd->hash = pf_pkt_hash(pd->af, pd->proto, + pd->src, pd->dst, pd->osport, pd->odport); + return (PF_PASS); } @@ -7512,6 +7567,7 @@ pf_test(sa_family_t af, int fwdir, struc break; } + key.hash = pd.hash; key.af = pd.af; key.proto = pd.virtual_proto; key.rdomain = pd.rdomain; @@ -7519,6 +7575,7 @@ pf_test(sa_family_t af, int fwdir, struc pf_addrcpy(&key.addr[pd.didx], pd.dst, key.af); key.port[pd.sidx] = pd.osport; key.port[pd.didx] = pd.odport; + key.hash = pd.hash; PF_STATE_ENTER_READ(); action = pf_find_state(&pd, &key, &s); Index: net/pfvar.h =================================================================== RCS file: /cvs/src/sys/net/pfvar.h,v retrieving revision 1.520 diff -u -p -r1.520 pfvar.h --- net/pfvar.h 11 Nov 2022 16:12:08 -0000 1.520 +++ net/pfvar.h 21 Nov 2022 08:03:03 -0000 @@ -704,6 +704,7 @@ struct pf_state_key_cmp { struct pf_addr addr[2]; u_int16_t port[2]; u_int16_t rdomain; + u_int16_t hash; sa_family_t af; u_int8_t proto; }; @@ -719,6 +720,7 @@ struct pf_state_key { struct pf_addr addr[2]; u_int16_t port[2]; u_int16_t rdomain; + u_int16_t hash; sa_family_t af; u_int8_t proto; Index: net/pfvar_priv.h =================================================================== RCS file: /cvs/src/sys/net/pfvar_priv.h,v retrieving revision 1.21 diff -u -p -r1.21 pfvar_priv.h --- net/pfvar_priv.h 11 Nov 2022 17:12:30 -0000 1.21 +++ net/pfvar_priv.h 21 Nov 2022 08:03:03 -0000 @@ -228,6 +228,7 @@ struct pf_pdesc { u_int16_t *dport; u_int16_t osport; u_int16_t odport; + u_int16_t hash; u_int16_t nsport; /* src port after NAT */ u_int16_t ndport; /* dst port after NAT */ Index: net/toeplitz.h =================================================================== RCS file: /cvs/src/sys/net/toeplitz.h,v retrieving revision 1.8 diff -u -p -r1.8 toeplitz.h --- net/toeplitz.h 24 Feb 2021 23:44:04 -0000 1.8 +++ net/toeplitz.h 21 Nov 2022 08:03:03 -0000 @@ -118,6 +118,8 @@ extern const struct stoeplitz_cache *con #define stoeplitz_n16(_n16) \ stoeplitz_hash_n16(stoeplitz_cache, (_n16)) +#define stoeplitz_n32(_n32) \ + stoeplitz_hash_n32(stoeplitz_cache, (_n32)) #define stoeplitz_h16(_h16) \ stoeplitz_hash_h16(stoeplitz_cache, (_h16)) #define stoeplitz_h32(_h32) \ Index: conf/files =================================================================== RCS file: /cvs/src/sys/conf/files,v retrieving revision 1.719 diff -u -p -r1.719 files --- conf/files 6 Nov 2022 15:36:13 -0000 1.719 +++ conf/files 22 Nov 2022 01:18:02 -0000 @@ -587,7 +587,7 @@ file miscfs/fuse/fuse_vfsops.c fuse file miscfs/fuse/fuse_vnops.c fuse file miscfs/fuse/fusebuf.c fuse -pseudo-device pf: ifnet +pseudo-device pf: ifnet, stoeplitz file net/pf.c pf needs-flag file net/pf_norm.c pf file net/pf_ruleset.c pf