svn commit: r232656 - projects/pf/head/sys/contrib/pf/net
Gleb Smirnoff
glebius at FreeBSD.org
Wed Mar 7 11:47:46 UTC 2012
Author: glebius
Date: Wed Mar 7 11:47:46 2012
New Revision: 232656
URL: http://svn.freebsd.org/changeset/base/232656
Log:
I was too optimistic in r232340. The intermediate structure was
used to make it possible one state be referenced by >1 keys. This
is important for NAT states.
Instead of reverting r232340, I decided to keep two a couple of
TAILQ_HEADs in keys, and couple of TAILQ_ENTRYies in states. Let's
see how that would work.
Modified:
projects/pf/head/sys/contrib/pf/net/pf.c
projects/pf/head/sys/contrib/pf/net/pf_ioctl.c
projects/pf/head/sys/contrib/pf/net/pfvar.h
Modified: projects/pf/head/sys/contrib/pf/net/pf.c
==============================================================================
--- projects/pf/head/sys/contrib/pf/net/pf.c Wed Mar 7 11:36:02 2012 (r232655)
+++ projects/pf/head/sys/contrib/pf/net/pf.c Wed Mar 7 11:47:46 2012 (r232656)
@@ -688,7 +688,7 @@ pf_state_key_attach(struct pf_state_key
if ((cur = RB_INSERT(pf_state_tree, &V_pf_statetbl, sk)) != NULL) {
/* key exists. check for same kif, if none, add to key */
- TAILQ_FOREACH(si, &cur->states, key_list)
+ TAILQ_FOREACH(si, &cur->states[idx], key_list[idx])
if (si->kif == s->kif &&
si->direction == s->direction) {
if (sk->proto == IPPROTO_TCP &&
@@ -696,7 +696,7 @@ pf_state_key_attach(struct pf_state_key
si->dst.state >= TCPS_FIN_WAIT_2) {
si->src.state = si->dst.state =
TCPS_CLOSED;
- /* unlink late or sks can go away */
+ /* Unlink later or sk can go away. */
olds = si;
} else {
if (V_pf_status.debug >= PF_DEBUG_MISC) {
@@ -722,16 +722,22 @@ pf_state_key_attach(struct pf_state_key
return (-1); /* collision! */
}
}
- uma_zfree(V_pf_state_key_z, sk);
+ /*
+ * Collided key may be the same we are trying to attach,
+ * this happens for non-NAT states, they are attached
+ * twice: via PF_SK_WIRE and PF_SK_STACK tailqs.
+ */
+ if (cur != sk)
+ uma_zfree(V_pf_state_key_z, sk);
s->key[idx] = cur;
} else
s->key[idx] = sk;
/* list is sorted, if-bound states before floating */
if (s->kif == V_pfi_all)
- TAILQ_INSERT_TAIL(&s->key[idx]->states, s, key_list);
+ TAILQ_INSERT_TAIL(&s->key[idx]->states[idx], s, key_list[idx]);
else
- TAILQ_INSERT_HEAD(&s->key[idx]->states, s, key_list);
+ TAILQ_INSERT_HEAD(&s->key[idx]->states[idx], s, key_list[idx]);
if (olds)
pf_unlink_state(olds, 0);
@@ -745,9 +751,6 @@ pf_detach_state(struct pf_state *s)
PF_KEYS_ASSERT();
- if (s->key[PF_SK_WIRE] == s->key[PF_SK_STACK])
- s->key[PF_SK_WIRE] = NULL;
-
if (s->key[PF_SK_STACK] != NULL)
pf_state_key_detach(s, PF_SK_STACK);
@@ -758,24 +761,20 @@ pf_detach_state(struct pf_state *s)
static void
pf_state_key_detach(struct pf_state *s, int idx)
{
- struct pf_state *si;
+ struct pf_state_key *sk = s->key[idx];
+ int idx2 = (idx == PF_SK_STACK ? PF_SK_WIRE : PF_SK_STACK);
PF_KEYS_ASSERT();
- si = TAILQ_FIRST(&s->key[idx]->states);
- while (si && si != s)
- si = TAILQ_NEXT(si, key_list);
-
- if (si)
- TAILQ_REMOVE(&s->key[idx]->states, si, key_list);
-
- if (TAILQ_EMPTY(&s->key[idx]->states)) {
- RB_REMOVE(pf_state_tree, &V_pf_statetbl, s->key[idx]);
- if (s->key[idx]->reverse)
- s->key[idx]->reverse->reverse = NULL;
- uma_zfree(V_pf_state_key_z, s->key[idx]);
- }
+ TAILQ_REMOVE(&sk->states[idx], s, key_list[idx]);
s->key[idx] = NULL;
+
+ if (TAILQ_EMPTY(&sk->states[idx]) && TAILQ_EMPTY(&sk->states[idx2])) {
+ RB_REMOVE(pf_state_tree, &V_pf_statetbl, sk);
+ if (sk->reverse)
+ sk->reverse->reverse = NULL;
+ uma_zfree(V_pf_state_key_z, sk);
+ }
}
int
@@ -832,23 +831,14 @@ pf_state_insert(struct pfi_kif *kif, str
s->kif = kif;
PF_KEYS_LOCK();
- if (skw == sks) {
- if (pf_state_key_attach(skw, s, PF_SK_WIRE)) {
- PF_KEYS_UNLOCK();
- return (-1);
- }
- s->key[PF_SK_STACK] = s->key[PF_SK_WIRE];
- } else {
- if (pf_state_key_attach(skw, s, PF_SK_WIRE)) {
- PF_KEYS_UNLOCK();
- uma_zfree(V_pf_state_key_z, sks);
- return (-1);
- }
- if (pf_state_key_attach(sks, s, PF_SK_STACK)) {
- pf_state_key_detach(s, PF_SK_WIRE);
- PF_KEYS_UNLOCK();
- return (-1);
- }
+ if (pf_state_key_attach(skw, s, PF_SK_WIRE)) {
+ PF_KEYS_UNLOCK();
+ return (-1);
+ }
+ if (pf_state_key_attach(sks, s, PF_SK_STACK)) {
+ pf_state_key_detach(s, PF_SK_WIRE);
+ PF_KEYS_UNLOCK();
+ return (-1);
}
if (s->id == 0 && s->creatorid == 0) {
@@ -931,6 +921,7 @@ pf_find_state(struct pfi_kif *kif, struc
{
struct pf_state_key *sk;
struct pf_state *si;
+ int idx;
V_pf_status.fcounters[FCNT_STATE_SEARCH]++;
@@ -956,11 +947,11 @@ pf_find_state(struct pfi_kif *kif, struc
if (dir == PF_OUT)
pftag->statekey = NULL;
+ idx = (dir == PF_IN ? PF_SK_WIRE : PF_SK_STACK);
+
/* list is sorted, if-bound states before floating ones */
- TAILQ_FOREACH(si, &sk->states, key_list)
- if ((si->kif == V_pfi_all || si->kif == kif) &&
- sk == (dir == PF_IN ? si->key[PF_SK_WIRE] :
- si->key[PF_SK_STACK])) {
+ TAILQ_FOREACH(si, &sk->states[idx], key_list[idx])
+ if (si->kif == V_pfi_all || si->kif == kif) {
PF_KEYS_UNLOCK();
return (si);
}
@@ -974,26 +965,46 @@ pf_find_state_all(struct pf_state_key_cm
{
struct pf_state_key *sk;
struct pf_state *s, *ret = NULL;
+ int idx, inout = 0;
V_pf_status.fcounters[FCNT_STATE_SEARCH]++;
PF_KEYS_LOCK();
sk = RB_FIND(pf_state_tree, &V_pf_statetbl, (struct pf_state_key *)key);
- if (sk != NULL) {
- TAILQ_FOREACH(s, &sk->states, key_list)
- if (dir == PF_INOUT ||
- (sk == (dir == PF_IN ? s->key[PF_SK_WIRE] :
- s->key[PF_SK_STACK]))) {
- if (more == NULL) {
- PF_KEYS_UNLOCK();
- return (s);
- }
+ if (sk == NULL) {
+ PF_KEYS_UNLOCK();
+ return (NULL);
+ }
+ switch (dir) {
+ case PF_IN:
+ idx = PF_SK_WIRE;
+ break;
+ case PF_OUT:
+ idx = PF_SK_STACK;
+ break;
+ case PF_INOUT:
+ idx = PF_SK_WIRE;
+ inout = 1;
+ break;
+ default:
+ panic("%s: dir %u", __func__, dir);
+ }
+second_run:
+ TAILQ_FOREACH(s, &sk->states[idx], key_list[idx]) {
+ if (more == NULL) {
+ PF_KEYS_UNLOCK();
+ return (s);
+ }
- if (ret)
- (*more)++;
- else
- ret = s;
- }
+ if (ret)
+ (*more)++;
+ else
+ ret = s;
+ }
+ if (inout == 1) {
+ inout = 0;
+ idx = PF_SK_STACK;
+ goto second_run;
}
PF_KEYS_UNLOCK();
Modified: projects/pf/head/sys/contrib/pf/net/pf_ioctl.c
==============================================================================
--- projects/pf/head/sys/contrib/pf/net/pf_ioctl.c Wed Mar 7 11:36:02 2012 (r232655)
+++ projects/pf/head/sys/contrib/pf/net/pf_ioctl.c Wed Mar 7 11:47:46 2012 (r232656)
@@ -276,7 +276,8 @@ pf_state_key_ini(void *mem, int size, in
struct pf_state_key *sk = mem;
bzero(sk, sizeof(*sk));
- TAILQ_INIT(&sk->states);
+ TAILQ_INIT(&sk->states[PF_SK_WIRE]);
+ TAILQ_INIT(&sk->states[PF_SK_STACK]);
return (0);
}
Modified: projects/pf/head/sys/contrib/pf/net/pfvar.h
==============================================================================
--- projects/pf/head/sys/contrib/pf/net/pfvar.h Wed Mar 7 11:36:02 2012 (r232655)
+++ projects/pf/head/sys/contrib/pf/net/pfvar.h Wed Mar 7 11:47:46 2012 (r232656)
@@ -790,7 +790,7 @@ struct pf_state_key {
u_int8_t pad[2];
RB_ENTRY(pf_state_key) entry;
- TAILQ_HEAD(, pf_state) states;
+ TAILQ_HEAD(, pf_state) states[2];
struct pf_state_key *reverse;
struct inpcb *inp;
};
@@ -810,7 +810,7 @@ struct pf_state {
u_int8_t pad[2];
TAILQ_ENTRY(pf_state) sync_list;
TAILQ_ENTRY(pf_state) entry_list;
- TAILQ_ENTRY(pf_state) key_list;
+ TAILQ_ENTRY(pf_state) key_list[2];
RB_ENTRY(pf_state) entry_id;
struct pf_state_peer src;
struct pf_state_peer dst;
More information about the svn-src-projects
mailing list