summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/uts/common/inet/tcp/tcp.c14
-rw-r--r--usr/src/uts/common/io/aggr/aggr_grp.c40
-rw-r--r--usr/src/uts/common/sys/aggr_impl.h4
3 files changed, 53 insertions, 5 deletions
diff --git a/usr/src/uts/common/inet/tcp/tcp.c b/usr/src/uts/common/inet/tcp/tcp.c
index af748fe140..cf6dcb4fdc 100644
--- a/usr/src/uts/common/inet/tcp/tcp.c
+++ b/usr/src/uts/common/inet/tcp/tcp.c
@@ -21469,13 +21469,17 @@ tcp_send(queue_t *q, tcp_t *tcp, const int mss, const int tcp_hdr_len,
num_burst_seg >= 2 && (*usable - 1) / mss >= 1) {
/*
* Try to find usable IRE/ILL and do basic check to the ILL.
+ * Double check LSO usability before going further, since the
+ * underlying interface could have been changed. In case of any
+ * change of LSO capability, set tcp_ire_ill_check_done to
+ * B_FALSE to force to check the ILL with the next send.
*/
- if (tcp_send_find_ire_ill(tcp, NULL, &ire, &ill)) {
+ if (tcp_send_find_ire_ill(tcp, NULL, &ire, &ill) &&
+ tcp->tcp_lso && ILL_LSO_TCP_USABLE(ill)) {
/*
* Enable LSO with this transmission.
- * Since IRE has been hold in
- * tcp_send_find_ire_ill(), IRE_REFRELE(ire)
- * should be called before return.
+ * Since IRE has been hold in tcp_send_find_ire_ill(),
+ * IRE_REFRELE(ire) should be called before return.
*/
do_lso_send = B_TRUE;
ire_fp_mp = ire->ire_nce->nce_fp_mp;
@@ -21483,6 +21487,8 @@ tcp_send(queue_t *q, tcp_t *tcp, const int mss, const int tcp_hdr_len,
/* Round up to multiple of 4 */
ire_fp_mp_len = ((ire_fp_mp_len + 3) / 4) * 4;
} else {
+ tcp->tcp_lso = B_FALSE;
+ tcp->tcp_ire_ill_check_done = B_FALSE;
do_lso_send = B_FALSE;
ill = NULL;
}
diff --git a/usr/src/uts/common/io/aggr/aggr_grp.c b/usr/src/uts/common/io/aggr/aggr_grp.c
index 59eb75f9d5..70bd89320a 100644
--- a/usr/src/uts/common/io/aggr/aggr_grp.c
+++ b/usr/src/uts/common/io/aggr/aggr_grp.c
@@ -1784,6 +1784,16 @@ aggr_m_capab_get(void *arg, mac_capab_t cap, void *cap_data)
*hcksum_txflags = grp->lg_hcksum_txflags;
break;
}
+ case MAC_CAPAB_LSO: {
+ mac_capab_lso_t *cap_lso = cap_data;
+
+ if (grp->lg_lso) {
+ *cap_lso = grp->lg_cap_lso;
+ break;
+ } else {
+ return (B_FALSE);
+ }
+ }
case MAC_CAPAB_NO_NATIVEVLAN:
return (!grp->lg_vlan);
case MAC_CAPAB_NO_ZCOPY:
@@ -2092,6 +2102,7 @@ aggr_grp_capab_set(aggr_grp_t *grp)
{
uint32_t cksum;
aggr_port_t *port;
+ mac_capab_lso_t cap_lso;
ASSERT(grp->lg_mh == NULL);
ASSERT(grp->lg_ports != NULL);
@@ -2100,6 +2111,10 @@ aggr_grp_capab_set(aggr_grp_t *grp)
grp->lg_zcopy = B_TRUE;
grp->lg_vlan = B_TRUE;
+ grp->lg_lso = B_TRUE;
+ grp->lg_cap_lso.lso_flags = (t_uscalar_t)-1;
+ grp->lg_cap_lso.lso_basic_tcp_ipv4.lso_max = (t_uscalar_t)-1;
+
for (port = grp->lg_ports; port != NULL; port = port->lp_next) {
if (!mac_capab_get(port->lp_mh, MAC_CAPAB_HCKSUM, &cksum))
cksum = 0;
@@ -2110,6 +2125,16 @@ aggr_grp_capab_set(aggr_grp_t *grp)
grp->lg_zcopy &=
!mac_capab_get(port->lp_mh, MAC_CAPAB_NO_ZCOPY, NULL);
+
+ grp->lg_lso &=
+ mac_capab_get(port->lp_mh, MAC_CAPAB_LSO, &cap_lso);
+ if (grp->lg_lso) {
+ grp->lg_cap_lso.lso_flags &= cap_lso.lso_flags;
+ if (grp->lg_cap_lso.lso_basic_tcp_ipv4.lso_max >
+ cap_lso.lso_basic_tcp_ipv4.lso_max)
+ grp->lg_cap_lso.lso_basic_tcp_ipv4.lso_max =
+ cap_lso.lso_basic_tcp_ipv4.lso_max;
+ }
}
}
@@ -2142,6 +2167,21 @@ aggr_grp_capab_check(aggr_grp_t *grp, aggr_port_t *port)
return (B_FALSE);
}
+ if (grp->lg_lso) {
+ mac_capab_lso_t cap_lso;
+
+ if (mac_capab_get(port->lp_mh, MAC_CAPAB_LSO, &cap_lso)) {
+ if ((grp->lg_cap_lso.lso_flags & cap_lso.lso_flags) !=
+ grp->lg_cap_lso.lso_flags)
+ return (B_FALSE);
+ if (grp->lg_cap_lso.lso_basic_tcp_ipv4.lso_max >
+ cap_lso.lso_basic_tcp_ipv4.lso_max)
+ return (B_FALSE);
+ } else {
+ return (B_FALSE);
+ }
+ }
+
return (B_TRUE);
}
diff --git a/usr/src/uts/common/sys/aggr_impl.h b/usr/src/uts/common/sys/aggr_impl.h
index 59babc2876..96182b14f3 100644
--- a/usr/src/uts/common/sys/aggr_impl.h
+++ b/usr/src/uts/common/sys/aggr_impl.h
@@ -147,7 +147,8 @@ typedef struct aggr_grp_s {
lg_zcopy : 1,
lg_vlan : 1,
lg_force : 1,
- lg_pad_bits : 9;
+ lg_lso : 1,
+ lg_pad_bits : 8;
aggr_port_t *lg_ports; /* list of configured ports */
aggr_port_t *lg_mac_addr_port;
mac_handle_t lg_mh;
@@ -168,6 +169,7 @@ typedef struct aggr_grp_s {
uint32_t lg_hcksum_txflags;
uint_t lg_max_sdu;
uint32_t lg_margin;
+ mac_capab_lso_t lg_cap_lso;
/*
* The following fields are used by the LACP packets processing.