diff options
| -rw-r--r-- | usr/src/uts/common/inet/tcp/tcp.c | 14 | ||||
| -rw-r--r-- | usr/src/uts/common/io/aggr/aggr_grp.c | 40 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/aggr_impl.h | 4 |
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. |
