Print this page
8381 Convert ipsec_alg_lock from mutex to rwlock

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/inet/ip/spd.c
          +++ new/usr/src/uts/common/inet/ip/spd.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
       24 + * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
  24   25   * Copyright (c) 2016 by Delphix. All rights reserved.
  25   26   */
  26   27  
  27   28  /*
  28   29   * IPsec Security Policy Database.
  29   30   *
  30   31   * This module maintains the SPD and provides routines used by ip and ip6
  31   32   * to apply IPsec policy to inbound and outbound datagrams.
  32   33   */
  33   34  
↓ open down ↓ 372 lines elided ↑ open up ↑
 406  407                  ipsec_action_free_table(ipss->ipsec_action_hash[i].hash_head);
 407  408                  ipss->ipsec_action_hash[i].hash_head = NULL;
 408  409                  mutex_destroy(&(ipss->ipsec_action_hash[i].hash_lock));
 409  410          }
 410  411  
 411  412          for (i = 0; i < ipss->ipsec_spd_hashsize; i++) {
 412  413                  ASSERT(ipss->ipsec_sel_hash[i].hash_head == NULL);
 413  414                  mutex_destroy(&(ipss->ipsec_sel_hash[i].hash_lock));
 414  415          }
 415  416  
 416      -        mutex_enter(&ipss->ipsec_alg_lock);
      417 +        rw_enter(&ipss->ipsec_alg_lock, RW_WRITER);
 417  418          for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype ++) {
 418  419                  int nalgs = ipss->ipsec_nalgs[algtype];
 419  420  
 420  421                  for (i = 0; i < nalgs; i++) {
 421  422                          if (ipss->ipsec_alglists[algtype][i] != NULL)
 422  423                                  ipsec_alg_unreg(algtype, i, ns);
 423  424                  }
 424  425          }
 425      -        mutex_exit(&ipss->ipsec_alg_lock);
 426      -        mutex_destroy(&ipss->ipsec_alg_lock);
      426 +        rw_exit(&ipss->ipsec_alg_lock);
      427 +        rw_destroy(&ipss->ipsec_alg_lock);
 427  428  
 428  429          ipsid_gc(ns);
 429  430          ipsid_fini(ns);
 430  431  
 431  432          (void) ipsec_free_tables(ipss);
 432  433          kmem_free(ipss, sizeof (*ipss));
 433  434  }
 434  435  
 435  436  void
 436  437  ipsec_policy_g_destroy(void)
↓ open down ↓ 211 lines elided ↑ open up ↑
 648  649          rw_init(&ipss->ipsec_inactive_policy.iph_lock, NULL, RW_DEFAULT, NULL);
 649  650  
 650  651          for (i = 0; i < IPSEC_ACTION_HASH_SIZE; i++)
 651  652                  mutex_init(&(ipss->ipsec_action_hash[i].hash_lock),
 652  653                      NULL, MUTEX_DEFAULT, NULL);
 653  654  
 654  655          for (i = 0; i < ipss->ipsec_spd_hashsize; i++)
 655  656                  mutex_init(&(ipss->ipsec_sel_hash[i].hash_lock),
 656  657                      NULL, MUTEX_DEFAULT, NULL);
 657  658  
 658      -        mutex_init(&ipss->ipsec_alg_lock, NULL, MUTEX_DEFAULT, NULL);
      659 +        rw_init(&ipss->ipsec_alg_lock, NULL, RW_DEFAULT, NULL);
 659  660          for (i = 0; i < IPSEC_NALGTYPES; i++) {
 660  661                  ipss->ipsec_nalgs[i] = 0;
 661  662          }
 662  663  
 663  664          ip_drop_init(ipss);
 664  665          ip_drop_register(&ipss->ipsec_spd_dropper, "IPsec SPD");
 665  666  
 666  667          /* IP's IPsec code calls the packet dropper */
 667  668          ip_drop_register(&ipss->ipsec_dropper, "IP IPsec processing");
 668  669  
↓ open down ↓ 42 lines elided ↑ open up ↑
 711  712  alg_insert_sortlist(enum ipsec_algtype at, uint8_t algid, netstack_t *ns)
 712  713  {
 713  714          ipsec_stack_t   *ipss = ns->netstack_ipsec;
 714  715          ipsec_alginfo_t *ai = ipss->ipsec_alglists[at][algid];
 715  716          uint8_t holder, swap;
 716  717          uint_t i;
 717  718          uint_t count = ipss->ipsec_nalgs[at];
 718  719          ASSERT(ai != NULL);
 719  720          ASSERT(algid == ai->alg_id);
 720  721  
 721      -        ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
      722 +        ASSERT(RW_WRITE_HELD(&ipss->ipsec_alg_lock));
 722  723  
 723  724          holder = algid;
 724  725  
 725  726          for (i = 0; i < count - 1; i++) {
 726  727                  ipsec_alginfo_t *alt;
 727  728  
 728  729                  alt = ipss->ipsec_alglists[at][ipss->ipsec_sortlist[at][i]];
 729  730                  /*
 730  731                   * If you want to give precedence to newly added algs,
 731  732                   * add the = in the > comparison.
↓ open down ↓ 16 lines elided ↑ open up ↑
 748  749   * This should be considerably easier, even with complex sorting.
 749  750   */
 750  751  static void
 751  752  alg_remove_sortlist(enum ipsec_algtype at, uint8_t algid, netstack_t *ns)
 752  753  {
 753  754          boolean_t copyback = B_FALSE;
 754  755          int i;
 755  756          ipsec_stack_t   *ipss = ns->netstack_ipsec;
 756  757          int newcount = ipss->ipsec_nalgs[at];
 757  758  
 758      -        ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
      759 +        ASSERT(RW_WRITE_HELD(&ipss->ipsec_alg_lock));
 759  760  
 760  761          for (i = 0; i <= newcount; i++) {
 761  762                  if (copyback) {
 762  763                          ipss->ipsec_sortlist[at][i-1] =
 763  764                              ipss->ipsec_sortlist[at][i];
 764  765                  } else if (ipss->ipsec_sortlist[at][i] == algid) {
 765  766                          copyback = B_TRUE;
 766  767                  }
 767  768          }
 768  769  }
 769  770  
 770  771  /*
 771  772   * Add the specified algorithm to the algorithm tables.
 772  773   * Must be called while holding the algorithm table writer lock.
 773  774   */
 774  775  void
 775  776  ipsec_alg_reg(ipsec_algtype_t algtype, ipsec_alginfo_t *alg, netstack_t *ns)
 776  777  {
 777  778          ipsec_stack_t   *ipss = ns->netstack_ipsec;
 778  779  
 779      -        ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
      780 +        ASSERT(RW_WRITE_HELD(&ipss->ipsec_alg_lock));
 780  781  
 781  782          ASSERT(ipss->ipsec_alglists[algtype][alg->alg_id] == NULL);
 782  783          ipsec_alg_fix_min_max(alg, algtype, ns);
 783  784          ipss->ipsec_alglists[algtype][alg->alg_id] = alg;
 784  785  
 785  786          ipss->ipsec_nalgs[algtype]++;
 786  787          alg_insert_sortlist(algtype, alg->alg_id, ns);
 787  788  }
 788  789  
 789  790  /*
 790  791   * Remove the specified algorithm from the algorithm tables.
 791  792   * Must be called while holding the algorithm table writer lock.
 792  793   */
 793  794  void
 794  795  ipsec_alg_unreg(ipsec_algtype_t algtype, uint8_t algid, netstack_t *ns)
 795  796  {
 796  797          ipsec_stack_t   *ipss = ns->netstack_ipsec;
 797  798  
 798      -        ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
      799 +        ASSERT(RW_WRITE_HELD(&ipss->ipsec_alg_lock));
 799  800  
 800  801          ASSERT(ipss->ipsec_alglists[algtype][algid] != NULL);
 801  802          ipsec_alg_free(ipss->ipsec_alglists[algtype][algid]);
 802  803          ipss->ipsec_alglists[algtype][algid] = NULL;
 803  804  
 804  805          ipss->ipsec_nalgs[algtype]--;
 805  806          alg_remove_sortlist(algtype, algid, ns);
 806  807  }
 807  808  
 808  809  /*
↓ open down ↓ 3887 lines elided ↑ open up ↑
4696 4697  {
4697 4698          size_t crypto_min = (size_t)-1, crypto_max = 0;
4698 4699          size_t cur_crypto_min, cur_crypto_max;
4699 4700          boolean_t is_valid;
4700 4701          crypto_mechanism_info_t *mech_infos;
4701 4702          uint_t nmech_infos;
4702 4703          int crypto_rc, i;
4703 4704          crypto_mech_usage_t mask;
4704 4705          ipsec_stack_t   *ipss = ns->netstack_ipsec;
4705 4706  
4706      -        ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
     4707 +        ASSERT(RW_WRITE_HELD(&ipss->ipsec_alg_lock));
4707 4708  
4708 4709          /*
4709 4710           * Compute the min, max, and default key sizes (in number of
4710 4711           * increments to the default key size in bits) as defined
4711 4712           * by the algorithm mappings. This range of key sizes is used
4712 4713           * for policy related operations. The effective key sizes
4713 4714           * supported by the framework could be more limited than
4714 4715           * those defined for an algorithm.
4715 4716           */
4716 4717          alg->alg_default_bits = alg->alg_key_sizes[0];
↓ open down ↓ 332 lines elided ↑ open up ↑
5049 5050  
5050 5051          mechs = crypto_get_mech_list(&mech_count, KM_SLEEP);
5051 5052          if (mechs == NULL)
5052 5053                  return;
5053 5054  
5054 5055          /*
5055 5056           * Walk the list of currently defined IPsec algorithm. Update
5056 5057           * the algorithm valid flag and trigger an update of the
5057 5058           * SAs that depend on that algorithm.
5058 5059           */
5059      -        mutex_enter(&ipss->ipsec_alg_lock);
     5060 +        rw_enter(&ipss->ipsec_alg_lock, RW_WRITER);
5060 5061          for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype++) {
5061 5062                  for (algidx = 0; algidx < ipss->ipsec_nalgs[algtype];
5062 5063                      algidx++) {
5063 5064  
5064 5065                          algid = ipss->ipsec_sortlist[algtype][algidx];
5065 5066                          alg = ipss->ipsec_alglists[algtype][algid];
5066 5067                          ASSERT(alg != NULL);
5067 5068  
5068 5069                          /*
5069 5070                           * Skip the algorithms which do not map to the
↓ open down ↓ 42 lines elided ↑ open up ↑
5112 5113                           * Update the affected SAs if a software provider is
5113 5114                           * being added or removed.
5114 5115                           */
5115 5116                          if (prov_change->ec_provider_type ==
5116 5117                              CRYPTO_SW_PROVIDER)
5117 5118                                  sadb_alg_update(algtype, alg->alg_id,
5118 5119                                      prov_change->ec_change ==
5119 5120                                      CRYPTO_MECH_ADDED, ns);
5120 5121                  }
5121 5122          }
5122      -        mutex_exit(&ipss->ipsec_alg_lock);
     5123 +        rw_exit(&ipss->ipsec_alg_lock);
5123 5124          crypto_free_mech_list(mechs, mech_count);
5124 5125  
5125 5126          if (alg_changed) {
5126 5127                  /*
5127 5128                   * An algorithm has changed, i.e. it became valid or
5128 5129                   * invalid, or its support key sizes have changed.
5129 5130                   * Notify ipsecah and ipsecesp of this change so
5130 5131                   * that they can send a SADB_REGISTER to their consumers.
5131 5132                   */
5132 5133                  ipsecah_algs_changed(ns);
↓ open down ↓ 1779 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX