83 #include <inet/ipdrop.h>
84 #include <inet/ip_netinfo.h>
85 #include <sys/squeue_impl.h>
86 #include <sys/squeue.h>
87
88 #include <inet/ipclassifier.h>
89 #include <inet/sctp_ip.h>
90 #include <inet/sctp/sctp_impl.h>
91 #include <inet/udp_impl.h>
92 #include <sys/sunddi.h>
93
94 #include <sys/tsol/label.h>
95 #include <sys/tsol/tnet.h>
96
97 /*
98 * Release a reference on ip_xmit_attr.
99 * The reference is acquired by conn_get_ixa()
100 */
101 #define IXA_REFRELE(ixa) \
102 { \
103 if (atomic_add_32_nv(&(ixa)->ixa_refcnt, -1) == 0) \
104 ixa_inactive(ixa); \
105 }
106
107 #define IXA_REFHOLD(ixa) \
108 { \
109 ASSERT((ixa)->ixa_refcnt != 0); \
110 atomic_add_32(&(ixa)->ixa_refcnt, 1); \
111 }
112
113 /*
114 * When we need to handle a transmit side asynchronous operation, then we need
115 * to save sufficient information so that we can call the fragment and postfrag
116 * functions. That information is captured in an mblk containing this structure.
117 *
118 * Since this is currently only used for IPsec, we include information for
119 * the kernel crypto framework.
120 */
121 typedef struct ixamblk_s {
122 boolean_t ixm_inbound; /* B_FALSE */
123 iaflags_t ixm_flags; /* ixa_flags */
124 netstackid_t ixm_stackid; /* Verify it didn't go away */
125 uint_t ixm_ifindex; /* Used to find the nce */
126 in6_addr_t ixm_nceaddr_v6; /* Used to find nce */
127 #define ixm_nceaddr_v4 V4_PART_OF_V6(ixm_nceaddr_v6)
128 uint32_t ixm_fragsize;
129 uint_t ixm_pktlen;
130 uint16_t ixm_ip_hdr_length; /* Points to ULP header */
737
738 irm = (iramblk_t *)mp->b_rptr;
739 ASSERT(irm->irm_inbound);
740 return (B_TRUE);
741 #else
742 return (DB_TYPE(mp) == M_BREAK);
743 #endif
744 }
745
746 static ip_xmit_attr_t *
747 conn_get_ixa_impl(conn_t *connp, boolean_t replace, int kmflag)
748 {
749 ip_xmit_attr_t *ixa;
750 ip_xmit_attr_t *oldixa;
751
752 mutex_enter(&connp->conn_lock);
753 ixa = connp->conn_ixa;
754
755 /* At least one references for the conn_t */
756 ASSERT(ixa->ixa_refcnt >= 1);
757 if (atomic_add_32_nv(&ixa->ixa_refcnt, 1) == 2) {
758 /* No other thread using conn_ixa */
759 mutex_exit(&connp->conn_lock);
760 return (ixa);
761 }
762 ixa = kmem_alloc(sizeof (*ixa), kmflag);
763 if (ixa == NULL) {
764 mutex_exit(&connp->conn_lock);
765 ixa_refrele(connp->conn_ixa);
766 return (NULL);
767 }
768 ixa_safe_copy(connp->conn_ixa, ixa);
769
770 /* Make sure we drop conn_lock before any refrele */
771 if (replace) {
772 ixa->ixa_refcnt++; /* No atomic needed - not visible */
773 oldixa = connp->conn_ixa;
774 connp->conn_ixa = ixa;
775 mutex_exit(&connp->conn_lock);
776 IXA_REFRELE(oldixa); /* Undo refcnt from conn_t */
777 } else {
839 * Return a ip_xmit_attr_t to use with a conn_t that is based on but
840 * separate from conn_ixa.
841 *
842 * This "safe" copy has the pointers set to NULL
843 * (since the pointers might be changed by another thread using
844 * conn_ixa). The caller needs to check for NULL pointers to see
845 * if ip_set_destination needs to be called to re-establish the pointers.
846 */
847 ip_xmit_attr_t *
848 conn_get_ixa_exclusive(conn_t *connp)
849 {
850 ip_xmit_attr_t *ixa;
851
852 mutex_enter(&connp->conn_lock);
853 ixa = connp->conn_ixa;
854
855 /* At least one references for the conn_t */
856 ASSERT(ixa->ixa_refcnt >= 1);
857
858 /* Make sure conn_ixa doesn't disappear while we copy it */
859 atomic_add_32(&ixa->ixa_refcnt, 1);
860
861 ixa = kmem_alloc(sizeof (*ixa), KM_NOSLEEP);
862 if (ixa == NULL) {
863 mutex_exit(&connp->conn_lock);
864 ixa_refrele(connp->conn_ixa);
865 return (NULL);
866 }
867 ixa_safe_copy(connp->conn_ixa, ixa);
868 mutex_exit(&connp->conn_lock);
869 IXA_REFRELE(connp->conn_ixa);
870 return (ixa);
871 }
872
873 void
874 ixa_safe_copy(ip_xmit_attr_t *src, ip_xmit_attr_t *ixa)
875 {
876 bcopy(src, ixa, sizeof (*ixa));
877 ixa->ixa_refcnt = 1;
878 /*
879 * Clear any pointers that have references and might be changed
|
83 #include <inet/ipdrop.h>
84 #include <inet/ip_netinfo.h>
85 #include <sys/squeue_impl.h>
86 #include <sys/squeue.h>
87
88 #include <inet/ipclassifier.h>
89 #include <inet/sctp_ip.h>
90 #include <inet/sctp/sctp_impl.h>
91 #include <inet/udp_impl.h>
92 #include <sys/sunddi.h>
93
94 #include <sys/tsol/label.h>
95 #include <sys/tsol/tnet.h>
96
97 /*
98 * Release a reference on ip_xmit_attr.
99 * The reference is acquired by conn_get_ixa()
100 */
101 #define IXA_REFRELE(ixa) \
102 { \
103 if (atomic_dec_32_nv(&(ixa)->ixa_refcnt) == 0) \
104 ixa_inactive(ixa); \
105 }
106
107 #define IXA_REFHOLD(ixa) \
108 { \
109 ASSERT((ixa)->ixa_refcnt != 0); \
110 atomic_inc_32(&(ixa)->ixa_refcnt); \
111 }
112
113 /*
114 * When we need to handle a transmit side asynchronous operation, then we need
115 * to save sufficient information so that we can call the fragment and postfrag
116 * functions. That information is captured in an mblk containing this structure.
117 *
118 * Since this is currently only used for IPsec, we include information for
119 * the kernel crypto framework.
120 */
121 typedef struct ixamblk_s {
122 boolean_t ixm_inbound; /* B_FALSE */
123 iaflags_t ixm_flags; /* ixa_flags */
124 netstackid_t ixm_stackid; /* Verify it didn't go away */
125 uint_t ixm_ifindex; /* Used to find the nce */
126 in6_addr_t ixm_nceaddr_v6; /* Used to find nce */
127 #define ixm_nceaddr_v4 V4_PART_OF_V6(ixm_nceaddr_v6)
128 uint32_t ixm_fragsize;
129 uint_t ixm_pktlen;
130 uint16_t ixm_ip_hdr_length; /* Points to ULP header */
737
738 irm = (iramblk_t *)mp->b_rptr;
739 ASSERT(irm->irm_inbound);
740 return (B_TRUE);
741 #else
742 return (DB_TYPE(mp) == M_BREAK);
743 #endif
744 }
745
746 static ip_xmit_attr_t *
747 conn_get_ixa_impl(conn_t *connp, boolean_t replace, int kmflag)
748 {
749 ip_xmit_attr_t *ixa;
750 ip_xmit_attr_t *oldixa;
751
752 mutex_enter(&connp->conn_lock);
753 ixa = connp->conn_ixa;
754
755 /* At least one references for the conn_t */
756 ASSERT(ixa->ixa_refcnt >= 1);
757 if (atomic_inc_32_nv(&ixa->ixa_refcnt) == 2) {
758 /* No other thread using conn_ixa */
759 mutex_exit(&connp->conn_lock);
760 return (ixa);
761 }
762 ixa = kmem_alloc(sizeof (*ixa), kmflag);
763 if (ixa == NULL) {
764 mutex_exit(&connp->conn_lock);
765 ixa_refrele(connp->conn_ixa);
766 return (NULL);
767 }
768 ixa_safe_copy(connp->conn_ixa, ixa);
769
770 /* Make sure we drop conn_lock before any refrele */
771 if (replace) {
772 ixa->ixa_refcnt++; /* No atomic needed - not visible */
773 oldixa = connp->conn_ixa;
774 connp->conn_ixa = ixa;
775 mutex_exit(&connp->conn_lock);
776 IXA_REFRELE(oldixa); /* Undo refcnt from conn_t */
777 } else {
839 * Return a ip_xmit_attr_t to use with a conn_t that is based on but
840 * separate from conn_ixa.
841 *
842 * This "safe" copy has the pointers set to NULL
843 * (since the pointers might be changed by another thread using
844 * conn_ixa). The caller needs to check for NULL pointers to see
845 * if ip_set_destination needs to be called to re-establish the pointers.
846 */
847 ip_xmit_attr_t *
848 conn_get_ixa_exclusive(conn_t *connp)
849 {
850 ip_xmit_attr_t *ixa;
851
852 mutex_enter(&connp->conn_lock);
853 ixa = connp->conn_ixa;
854
855 /* At least one references for the conn_t */
856 ASSERT(ixa->ixa_refcnt >= 1);
857
858 /* Make sure conn_ixa doesn't disappear while we copy it */
859 atomic_inc_32(&ixa->ixa_refcnt);
860
861 ixa = kmem_alloc(sizeof (*ixa), KM_NOSLEEP);
862 if (ixa == NULL) {
863 mutex_exit(&connp->conn_lock);
864 ixa_refrele(connp->conn_ixa);
865 return (NULL);
866 }
867 ixa_safe_copy(connp->conn_ixa, ixa);
868 mutex_exit(&connp->conn_lock);
869 IXA_REFRELE(connp->conn_ixa);
870 return (ixa);
871 }
872
873 void
874 ixa_safe_copy(ip_xmit_attr_t *src, ip_xmit_attr_t *ixa)
875 {
876 bcopy(src, ixa, sizeof (*ixa));
877 ixa->ixa_refcnt = 1;
878 /*
879 * Clear any pointers that have references and might be changed
|