Author: glebius
Date: Sat Mar 28 16:06:46 2015
New Revision: 280787
URL: https://svnweb.freebsd.org/changeset/base/280787

Log:
  Initialize random IP ID engine via SYSINIT() instead of doing that on
  first packet.  This allow to use M_WAITOK and cut down some error handling.
  
  Sponsored by: Nginx, Inc.

Modified:
  head/sys/netinet/ip_id.c

Modified: head/sys/netinet/ip_id.c
==============================================================================
--- head/sys/netinet/ip_id.c    Sat Mar 28 15:07:19 2015        (r280786)
+++ head/sys/netinet/ip_id.c    Sat Mar 28 16:06:46 2015        (r280787)
@@ -91,18 +91,17 @@ __FBSDID("$FreeBSD$");
 
 static MALLOC_DEFINE(M_IPID, "ipid", "randomized ip id state");
 
-static u_int16_t       *id_array = NULL;
-static bitstr_t                *id_bits = NULL;
-static int              array_ptr = 0;
-static int              array_size = 8192;
-static int              random_id_collisions = 0;
-static int              random_id_total = 0;
+static uint16_t        *id_array;
+static bitstr_t                *id_bits;
+static int              array_ptr;
+static int              array_size;
+static int              random_id_collisions;
+static int              random_id_total;
 static struct mtx       ip_id_mtx;
 
-static void    ip_initid(void);
+static void    ip_initid(int);
 static int     sysctl_ip_id_change(SYSCTL_HANDLER_ARGS);
-
-MTX_SYSINIT(ip_id_mtx, &ip_id_mtx, "ip_id_mtx", MTX_DEF);
+static void    ip_sysinitid(void);
 
 SYSCTL_DECL(_net_inet_ip);
 SYSCTL_PROC(_net_inet_ip, OID_AUTO, random_id_period, CTLTYPE_INT|CTLFLAG_RW,
@@ -120,73 +119,44 @@ sysctl_ip_id_change(SYSCTL_HANDLER_ARGS)
        new = array_size;
        error = sysctl_handle_int(oidp, &new, 0, req);
        if (error == 0 && req->newptr) {
-               if (new >= 512 && new <= 32768) {
-                       mtx_lock(&ip_id_mtx);
-                       array_size = new;
-                       ip_initid();
-                       mtx_unlock(&ip_id_mtx);
-               } else
+               if (new >= 512 && new <= 32768)
+                       ip_initid(new);
+               else
                        error = EINVAL;
        }
        return (error);
 }
 
-/*
- * ip_initid() runs with a mutex held and may execute in a network context.
- * As a result, it uses M_NOWAIT.  Ideally, we would always do this
- * allocation from the sysctl contact and have it be an invariant that if
- * this random ID allocation mode is selected, the buffers are present.  This
- * would also avoid potential network context failures of IP ID generation.
- */
 static void
-ip_initid(void)
+ip_initid(int new_size)
 {
+       uint16_t *new_array;
+       bitstr_t *new_bits;
 
-       mtx_assert(&ip_id_mtx, MA_OWNED);
+       new_array = malloc(new_size * sizeof(uint16_t), M_IPID,
+           M_WAITOK | M_ZERO);
+       new_bits = malloc(bitstr_size(65536), M_IPID, M_WAITOK | M_ZERO);
 
+       mtx_lock(&ip_id_mtx);
        if (id_array != NULL) {
                free(id_array, M_IPID);
                free(id_bits, M_IPID);
        }
+       id_array = new_array;
+       id_bits = new_bits;
+       array_size = new_size;
+       array_ptr = 0;
        random_id_collisions = 0;
        random_id_total = 0;
-       array_ptr = 0;
-       id_array = (u_int16_t *) malloc(array_size * sizeof(u_int16_t),
-           M_IPID, M_NOWAIT | M_ZERO);
-       id_bits = (bitstr_t *) malloc(bitstr_size(65536), M_IPID,
-           M_NOWAIT | M_ZERO);
-       if (id_array == NULL || id_bits == NULL) {
-               /* Neither or both. */
-               if (id_array != NULL) {
-                       free(id_array, M_IPID);
-                       id_array = NULL;
-               }
-               if (id_bits != NULL) {
-                       free(id_bits, M_IPID);
-                       id_bits = NULL;
-               }
-       }
+       mtx_unlock(&ip_id_mtx);
 }
 
-u_int16_t
+uint16_t
 ip_randomid(void)
 {
-       u_int16_t new_id;
+       uint16_t new_id;
 
        mtx_lock(&ip_id_mtx);
-       if (id_array == NULL)
-               ip_initid();
-
-       /*
-        * Fail gracefully; return a fixed id if memory allocation failed;
-        * ideally we wouldn't do allocation in this context in order to
-        * avoid the possibility of this failure mode.
-        */
-       if (id_array == NULL) {
-               mtx_unlock(&ip_id_mtx);
-               return (1);
-       }
-
        /*
         * To avoid a conflict with the zeros that the array is initially
         * filled with, we never hand out an id of zero.
@@ -207,3 +177,12 @@ ip_randomid(void)
        mtx_unlock(&ip_id_mtx);
        return (new_id);
 }
+
+static void
+ip_sysinitid(void)
+{
+
+       mtx_init(&ip_id_mtx, "ip_id_mtx", NULL, MTX_DEF);
+       ip_initid(8192);
+}
+SYSINIT(ip_id, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, ip_sysinitid, NULL);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to