Author: glebius
Date: Fri Nov 22 19:16:34 2013
New Revision: 258479
URL: http://svnweb.freebsd.org/changeset/base/258479

Log:
  To support upcoming changes change internal API for source node handling:
  - Removed pf_remove_src_node().
  - Introduce pf_unlink_src_node() and pf_unlink_src_node_locked().
    These function do not proceed with freeing of a node, just disconnect
    it from storage.
  - New function pf_free_src_nodes() works on a list of previously
    disconnected nodes and frees them.
  - Utilize new API in pf_purge_expired_src_nodes().
  
  In collaboration with:        Kajetan Staszkiewicz <kajetan.staszkiewicz 
innogames.de>
  
  Sponsored by: InnoGames GmbH
  Sponsored by: Nginx, Inc.

Modified:
  head/sys/net/pfvar.h
  head/sys/netpfil/pf/pf.c

Modified: head/sys/net/pfvar.h
==============================================================================
--- head/sys/net/pfvar.h        Fri Nov 22 19:02:22 2013        (r258478)
+++ head/sys/net/pfvar.h        Fri Nov 22 19:16:34 2013        (r258479)
@@ -1467,8 +1467,9 @@ struct pf_ifspeed {
 #define        DIOCGIFSPEED    _IOWR('D', 92, struct pf_ifspeed)
 
 #ifdef _KERNEL
+LIST_HEAD(pf_src_node_list, pf_src_node);
 struct pf_srchash {
-       LIST_HEAD(, pf_src_node)        nodes;
+       struct pf_src_node_list         nodes;
        struct mtx                      lock;
 };
 
@@ -1576,6 +1577,9 @@ extern struct pf_state            *pf_find_state_a
                                    u_int, int *);
 extern struct pf_src_node      *pf_find_src_node(struct pf_addr *,
                                    struct pf_rule *, sa_family_t, int);
+extern void                     pf_unlink_src_node(struct pf_src_node *);
+extern void                     pf_unlink_src_node_locked(struct pf_src_node 
*);
+extern u_int                    pf_free_src_nodes(struct pf_src_node_list *);
 extern void                     pf_print_state(struct pf_state *);
 extern void                     pf_print_flags(u_int8_t);
 extern u_int16_t                pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t,

Modified: head/sys/netpfil/pf/pf.c
==============================================================================
--- head/sys/netpfil/pf/pf.c    Fri Nov 22 19:02:22 2013        (r258478)
+++ head/sys/netpfil/pf/pf.c    Fri Nov 22 19:16:34 2013        (r258479)
@@ -681,20 +681,54 @@ pf_insert_src_node(struct pf_src_node **
        return (0);
 }
 
-static void
-pf_remove_src_node(struct pf_src_node *src)
+void
+pf_unlink_src_node_locked(struct pf_src_node *src)
 {
+#ifdef INVARIANTS
        struct pf_srchash *sh;
 
        sh = &V_pf_srchash[pf_hashsrc(&src->addr, src->af)];
-       PF_HASHROW_LOCK(sh);
+       PF_HASHROW_ASSERT(sh);
+#endif
        LIST_REMOVE(src, entry);
-       PF_HASHROW_UNLOCK(sh);
-
+       if (src->rule.ptr)
+               src->rule.ptr->src_nodes--;
        V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
        V_pf_status.src_nodes--;
+}
 
-       uma_zfree(V_pf_sources_z, src);
+void
+pf_unlink_src_node(struct pf_src_node *src)
+{
+       struct pf_srchash *sh;
+
+       sh = &V_pf_srchash[pf_hashsrc(&src->addr, src->af)];
+       PF_HASHROW_LOCK(sh);
+       pf_unlink_src_node_locked(src);
+       PF_HASHROW_UNLOCK(sh);
+}
+
+static void
+pf_free_src_node(struct pf_src_node *sn)
+{
+
+       KASSERT(sn->states == 0, ("%s: %p has refs", __func__, sn));
+       LIST_REMOVE(sn, entry);
+       uma_zfree(V_pf_sources_z, sn);
+}
+
+u_int
+pf_free_src_nodes(struct pf_src_node_list *head)
+{
+       struct pf_src_node *sn, *tmp;
+       u_int count = 0;
+
+       LIST_FOREACH_SAFE(sn, head, entry, tmp) {
+               pf_free_src_node(sn);
+               count++;
+       }
+
+       return (count);
 }
 
 /* Data storage structures initialization. */
@@ -1464,24 +1498,24 @@ pf_state_expires(const struct pf_state *
 void
 pf_purge_expired_src_nodes()
 {
+       struct pf_src_node_list  freelist;
        struct pf_srchash       *sh;
        struct pf_src_node      *cur, *next;
        int i;
 
+       LIST_INIT(&freelist);
        for (i = 0, sh = V_pf_srchash; i <= V_pf_srchashmask; i++, sh++) {
            PF_HASHROW_LOCK(sh);
            LIST_FOREACH_SAFE(cur, &sh->nodes, entry, next)
                if (cur->states == 0 && cur->expire <= time_uptime) {
-                       if (cur->rule.ptr != NULL)
-                               cur->rule.ptr->src_nodes--;
-                       LIST_REMOVE(cur, entry);
-                       V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
-                       V_pf_status.src_nodes--;
-                       uma_zfree(V_pf_sources_z, cur);
+                       pf_unlink_src_node_locked(cur);
+                       LIST_INSERT_HEAD(&freelist, cur, entry);
                } else if (cur->rule.ptr != NULL)
                        cur->rule.ptr->rule_flag |= PFRULE_REFS;
            PF_HASHROW_UNLOCK(sh);
        }
+
+       pf_free_src_nodes(&freelist);
 }
 
 static void
@@ -3771,11 +3805,15 @@ csfailed:
        if (nk != NULL)
                uma_zfree(V_pf_state_key_z, nk);
 
-       if (sn != NULL && sn->states == 0 && sn->expire == 0)
-               pf_remove_src_node(sn);
+       if (sn != NULL && sn->states == 0 && sn->expire == 0) {
+               pf_unlink_src_node(sn);
+               pf_free_src_node(sn);
+       }
 
-       if (nsn != sn && nsn != NULL && nsn->states == 0 && nsn->expire == 0)
-               pf_remove_src_node(nsn);
+       if (nsn != sn && nsn != NULL && nsn->states == 0 && nsn->expire == 0) {
+               pf_unlink_src_node(nsn);
+               pf_free_src_node(nsn);
+       }
 
        return (PF_DROP);
 }
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to