summaryrefslogtreecommitdiff
path: root/usr/src/uts/common
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@fingolfin.org>2020-04-04 01:41:19 +0000
committerRobert Mustacchi <rm@fingolfin.org>2020-04-20 02:49:15 +0000
commit85f496fabdffd32673f6be280a3caa103f7d58a5 (patch)
treeddc0071bdc9f223edd65caffc5c7bd51bfed5efe /usr/src/uts/common
parent0418219cf21334a9c6712bbb2cec543b2ee4f989 (diff)
downloadillumos-gate-85f496fabdffd32673f6be280a3caa103f7d58a5.tar.gz
12520 Enable IPv6 tso in igb, ixgbe, and i40e
Reviewed by: Patrick Mooney <pmooney@pfmooney.com> Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r--usr/src/uts/common/io/i40e/i40e_gld.c4
-rw-r--r--usr/src/uts/common/io/i40e/i40e_transceiver.c3
-rw-r--r--usr/src/uts/common/io/igb/igb_gld.c6
-rw-r--r--usr/src/uts/common/io/igb/igb_sw.h7
-rw-r--r--usr/src/uts/common/io/igb/igb_tx.c61
-rw-r--r--usr/src/uts/common/io/ixgbe/ixgbe_gld.c4
-rw-r--r--usr/src/uts/common/io/ixgbe/ixgbe_sw.h1
-rw-r--r--usr/src/uts/common/io/ixgbe/ixgbe_tx.c61
8 files changed, 106 insertions, 41 deletions
diff --git a/usr/src/uts/common/io/i40e/i40e_gld.c b/usr/src/uts/common/io/i40e/i40e_gld.c
index ccf814be0b..1bf40bbce3 100644
--- a/usr/src/uts/common/io/i40e/i40e_gld.c
+++ b/usr/src/uts/common/io/i40e/i40e_gld.c
@@ -733,8 +733,10 @@ i40e_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
mac_capab_lso_t *cap_lso = cap_data;
if (i40e->i40e_tx_lso_enable == B_TRUE) {
- cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
+ cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4 |
+ LSO_TX_BASIC_TCP_IPV6;
cap_lso->lso_basic_tcp_ipv4.lso_max = I40E_LSO_MAXLEN;
+ cap_lso->lso_basic_tcp_ipv6.lso_max = I40E_LSO_MAXLEN;
} else {
return (B_FALSE);
}
diff --git a/usr/src/uts/common/io/i40e/i40e_transceiver.c b/usr/src/uts/common/io/i40e/i40e_transceiver.c
index 9662cb58f5..e324957625 100644
--- a/usr/src/uts/common/io/i40e/i40e_transceiver.c
+++ b/usr/src/uts/common/io/i40e/i40e_transceiver.c
@@ -1782,7 +1782,8 @@ i40e_tx_context(i40e_t *i40e, i40e_trqpair_t *itrq, mblk_t *mp,
* LSO requires that checksum offloads are enabled. If for
* some reason they're not we bail out with an error.
*/
- if ((chkflags & HCK_IPV4_HDRCKSUM) == 0 ||
+ if ((meo->meoi_l3proto == ETHERTYPE_IP &&
+ (chkflags & HCK_IPV4_HDRCKSUM) == 0) ||
(chkflags & HCK_PARTIALCKSUM) == 0) {
txs->itxs_lso_nohck.value.ui64++;
return (-1);
diff --git a/usr/src/uts/common/io/igb/igb_gld.c b/usr/src/uts/common/io/igb/igb_gld.c
index 2bb4f99d6f..f68c4b73e9 100644
--- a/usr/src/uts/common/io/igb/igb_gld.c
+++ b/usr/src/uts/common/io/igb/igb_gld.c
@@ -965,8 +965,10 @@ igb_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
mac_capab_lso_t *cap_lso = cap_data;
if (igb->lso_enable) {
- cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
+ cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4 |
+ LSO_TX_BASIC_TCP_IPV6;
cap_lso->lso_basic_tcp_ipv4.lso_max = IGB_LSO_MAXLEN;
+ cap_lso->lso_basic_tcp_ipv6.lso_max = IGB_LSO_MAXLEN;
break;
} else {
return (B_FALSE);
@@ -1645,7 +1647,7 @@ igb_priv_prop_info(igb_t *igb, const char *pr_name, mac_prop_info_handle_t prh)
value = DEFAULT_RX_COPY_THRESHOLD;
} else if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
value = DEFAULT_RX_LIMIT_PER_INTR;
- } else if (strcmp(pr_name, "_intr_throttling") == 0) {
+ } else if (strcmp(pr_name, "_intr_throttling") == 0) {
value = igb->capab->def_intr_throttle;
} else {
return;
diff --git a/usr/src/uts/common/io/igb/igb_sw.h b/usr/src/uts/common/io/igb/igb_sw.h
index f689c44b14..2e329d6fdc 100644
--- a/usr/src/uts/common/io/igb/igb_sw.h
+++ b/usr/src/uts/common/io/igb/igb_sw.h
@@ -227,7 +227,7 @@ extern "C" {
enum ioc_reply {
IOC_INVAL = -1, /* bad, NAK with EINVAL */
- IOC_DONE, /* OK, reply sent */
+ IOC_DONE, /* OK, reply sent */
IOC_ACK, /* OK, just send ACK */
IOC_REPLY /* OK, just send reply */
};
@@ -355,6 +355,7 @@ typedef struct tx_context {
uint32_t hcksum_flags;
uint32_t ip_hdr_len;
uint32_t mac_hdr_len;
+ uint32_t l3_proto;
uint32_t l4_proto;
uint32_t mss;
uint32_t l4_hdr_len;
@@ -558,7 +559,7 @@ typedef struct igb_rx_group {
} igb_rx_group_t;
typedef struct igb {
- int instance;
+ int instance;
mac_handle_t mac_hdl;
dev_info_t *dip;
struct e1000_hw hw;
@@ -606,7 +607,7 @@ typedef struct igb {
boolean_t tx_ring_init;
boolean_t tx_head_wb_enable; /* Tx head wrtie-back */
boolean_t tx_hcksum_enable; /* Tx h/w cksum offload */
- boolean_t lso_enable; /* Large Segment Offload */
+ boolean_t lso_enable; /* Large Segment Offload */
uint32_t tx_copy_thresh; /* Tx copy threshold */
uint32_t tx_recycle_thresh; /* Tx recycle threshold */
uint32_t tx_overload_thresh; /* Tx overload threshold */
diff --git a/usr/src/uts/common/io/igb/igb_tx.c b/usr/src/uts/common/io/igb/igb_tx.c
index 0496bf59fe..5245312adc 100644
--- a/usr/src/uts/common/io/igb/igb_tx.c
+++ b/usr/src/uts/common/io/igb/igb_tx.c
@@ -598,6 +598,7 @@ igb_get_tx_context(mblk_t *mp, tx_context_t *ctx)
uint32_t start;
uint32_t flags;
uint32_t lso_flag;
+ uint32_t lso_cksum;
uint32_t mss;
uint32_t len;
uint32_t size;
@@ -622,19 +623,6 @@ igb_get_tx_context(mblk_t *mp, tx_context_t *ctx)
ctx->mss = mss;
ctx->lso_flag = (lso_flag == HW_LSO);
- /*
- * LSO relies on tx h/w checksum, so here the packet will be
- * dropped if the h/w checksum flags are not set.
- */
- if (ctx->lso_flag) {
- if (!((ctx->hcksum_flags & HCK_PARTIALCKSUM) &&
- (ctx->hcksum_flags & HCK_IPV4_HDRCKSUM))) {
- igb_log(NULL, IGB_LOG_INFO, "igb_tx: h/w "
- "checksum flags are not set for LSO");
- return (TX_CXT_E_LSO_CSUM);
- }
- }
-
etype = 0;
mac_hdr_len = 0;
l4_proto = 0;
@@ -679,6 +667,8 @@ igb_get_tx_context(mblk_t *mp, tx_context_t *ctx)
* Here we assume the IP(V6) header is fully included in one
* mblk fragment.
*/
+ lso_cksum = HCK_PARTIALCKSUM;
+ ctx->l3_proto = etype;
switch (etype) {
case ETHERTYPE_IP:
offset = mac_hdr_len;
@@ -703,11 +693,27 @@ igb_get_tx_context(mblk_t *mp, tx_context_t *ctx)
* with zero. Currently the tcp/ip stack has done
* these.
*/
+ lso_cksum |= HCK_IPV4_HDRCKSUM;
}
l4_proto = *(uint8_t *)(pos + offsetof(ipha_t, ipha_protocol));
break;
case ETHERTYPE_IPV6:
+ /*
+ * We need to zero out the length in the header.
+ */
+ if (ctx->lso_flag) {
+ offset = offsetof(ip6_t, ip6_plen) + mac_hdr_len;
+ while (size <= offset) {
+ mp = mp->b_cont;
+ ASSERT(mp != NULL);
+ len = MBLKL(mp);
+ size += len;
+ }
+ pos = mp->b_rptr + offset + len - size;
+ *((uint16_t *)(uintptr_t)(pos)) = 0;
+ }
+
offset = offsetof(ip6_t, ip6_nxt) + mac_hdr_len;
while (size <= offset) {
mp = mp->b_cont;
@@ -727,6 +733,18 @@ igb_get_tx_context(mblk_t *mp, tx_context_t *ctx)
}
if (ctx->lso_flag) {
+ /*
+ * LSO relies on tx h/w checksum, so here the packet will be
+ * dropped if the h/w checksum flags are not set.
+ */
+ if ((ctx->hcksum_flags & lso_cksum) != lso_cksum) {
+ igb_log(NULL, IGB_LOG_INFO, "igb_tx: h/w "
+ "checksum flags are not set for LSO, found "
+ "0x%x, needed bits 0x%x", ctx->hcksum_flags,
+ lso_cksum);
+ return (TX_CXT_E_LSO_CSUM);
+ }
+
offset = mac_hdr_len + start;
while (size <= offset) {
mp = mp->b_cont;
@@ -771,6 +789,7 @@ igb_check_tx_context(igb_tx_ring_t *tx_ring, tx_context_t *ctx)
* need to be checked are:
* hcksum_flags
* l4_proto
+ * l3_proto
* mss (only check for LSO)
* l4_hdr_len (only check for LSO)
* ip_hdr_len
@@ -783,6 +802,7 @@ igb_check_tx_context(igb_tx_ring_t *tx_ring, tx_context_t *ctx)
if (ctx->hcksum_flags != 0) {
if ((ctx->hcksum_flags != last->hcksum_flags) ||
(ctx->l4_proto != last->l4_proto) ||
+ (ctx->l3_proto != last->l3_proto) ||
(ctx->lso_flag && ((ctx->mss != last->mss) ||
(ctx->l4_hdr_len != last->l4_hdr_len))) ||
(ctx->ip_hdr_len != last->ip_hdr_len) ||
@@ -814,10 +834,19 @@ igb_fill_tx_context(struct e1000_adv_tx_context_desc *ctx_tbd,
ctx_tbd->type_tucmd_mlhl =
E1000_ADVTXD_DCMD_DEXT | E1000_ADVTXD_DTYP_CTXT;
- if (ctx->hcksum_flags & HCK_IPV4_HDRCKSUM)
- ctx_tbd->type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV4;
+ /*
+ * When we have a TX context set up, we enforce that the ethertype is
+ * either IPv4 or IPv6 in igb_get_tx_context().
+ */
+ if (ctx->lso_flag || ctx->hcksum_flags & HCK_IPV4_HDRCKSUM) {
+ if (ctx->l3_proto == ETHERTYPE_IP) {
+ ctx_tbd->type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV4;
+ } else {
+ ctx_tbd->type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV6;
+ }
+ }
- if (ctx->hcksum_flags & HCK_PARTIALCKSUM) {
+ if (ctx->lso_flag || ctx->hcksum_flags & HCK_PARTIALCKSUM) {
switch (ctx->l4_proto) {
case IPPROTO_TCP:
ctx_tbd->type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_TCP;
diff --git a/usr/src/uts/common/io/ixgbe/ixgbe_gld.c b/usr/src/uts/common/io/ixgbe/ixgbe_gld.c
index ea888220fa..8508e32b82 100644
--- a/usr/src/uts/common/io/ixgbe/ixgbe_gld.c
+++ b/usr/src/uts/common/io/ixgbe/ixgbe_gld.c
@@ -304,8 +304,10 @@ ixgbe_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
mac_capab_lso_t *cap_lso = cap_data;
if (ixgbe->lso_enable) {
- cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
+ cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4 |
+ LSO_TX_BASIC_TCP_IPV6;
cap_lso->lso_basic_tcp_ipv4.lso_max = IXGBE_LSO_MAXLEN;
+ cap_lso->lso_basic_tcp_ipv6.lso_max = IXGBE_LSO_MAXLEN;
break;
} else {
return (B_FALSE);
diff --git a/usr/src/uts/common/io/ixgbe/ixgbe_sw.h b/usr/src/uts/common/io/ixgbe/ixgbe_sw.h
index cfd987787a..8bf93afe9c 100644
--- a/usr/src/uts/common/io/ixgbe/ixgbe_sw.h
+++ b/usr/src/uts/common/io/ixgbe/ixgbe_sw.h
@@ -408,6 +408,7 @@ typedef struct ixgbe_tx_context {
uint32_t hcksum_flags;
uint32_t ip_hdr_len;
uint32_t mac_hdr_len;
+ uint32_t l3_proto;
uint32_t l4_proto;
uint32_t mss;
uint32_t l4_hdr_len;
diff --git a/usr/src/uts/common/io/ixgbe/ixgbe_tx.c b/usr/src/uts/common/io/ixgbe/ixgbe_tx.c
index 9191aad058..b6926fc3b7 100644
--- a/usr/src/uts/common/io/ixgbe/ixgbe_tx.c
+++ b/usr/src/uts/common/io/ixgbe/ixgbe_tx.c
@@ -697,6 +697,7 @@ ixgbe_get_context(mblk_t *mp, ixgbe_tx_context_t *ctx)
uint32_t start;
uint32_t hckflags;
uint32_t lsoflags;
+ uint32_t lsocksum;
uint32_t mss;
uint32_t len;
uint32_t size;
@@ -722,19 +723,6 @@ ixgbe_get_context(mblk_t *mp, ixgbe_tx_context_t *ctx)
ctx->mss = mss;
ctx->lso_flag = (lsoflags == HW_LSO);
- /*
- * LSO relies on tx h/w checksum, so here will drop the package
- * if h/w checksum flag is not declared.
- */
- if (ctx->lso_flag) {
- if (!((ctx->hcksum_flags & HCK_PARTIALCKSUM) &&
- (ctx->hcksum_flags & HCK_IPV4_HDRCKSUM))) {
- IXGBE_DEBUGLOG_0(NULL, "ixgbe_tx: h/w "
- "checksum flags are not specified when doing LSO");
- return (-1);
- }
- }
-
etype = 0;
mac_hdr_len = 0;
l4_proto = 0;
@@ -779,6 +767,8 @@ ixgbe_get_context(mblk_t *mp, ixgbe_tx_context_t *ctx)
* Here we don't assume the IP(V6) header is fully included in
* one mblk fragment.
*/
+ lsocksum = HCK_PARTIALCKSUM;
+ ctx->l3_proto = etype;
switch (etype) {
case ETHERTYPE_IP:
if (ctx->lso_flag) {
@@ -810,6 +800,7 @@ ixgbe_get_context(mblk_t *mp, ixgbe_tx_context_t *ctx)
* (ip_source_addr, ip_destination_addr, l4_proto)
* Currently the tcp/ip stack has done it.
*/
+ lsocksum |= HCK_IPV4_HDRCKSUM;
}
offset = offsetof(ipha_t, ipha_protocol) + mac_hdr_len;
@@ -824,6 +815,21 @@ ixgbe_get_context(mblk_t *mp, ixgbe_tx_context_t *ctx)
l4_proto = *(uint8_t *)pos;
break;
case ETHERTYPE_IPV6:
+ /*
+ * We need to zero out the length in the header.
+ */
+ if (ctx->lso_flag) {
+ offset = offsetof(ip6_t, ip6_plen) + mac_hdr_len;
+ while (size <= offset) {
+ mp = mp->b_cont;
+ ASSERT(mp != NULL);
+ len = MBLKL(mp);
+ size += len;
+ }
+ pos = mp->b_rptr + offset + len - size;
+ *((uint16_t *)(uintptr_t)(pos)) = 0;
+ }
+
offset = offsetof(ip6_t, ip6_nxt) + mac_hdr_len;
while (size <= offset) {
mp = mp->b_cont;
@@ -842,6 +848,18 @@ ixgbe_get_context(mblk_t *mp, ixgbe_tx_context_t *ctx)
}
if (ctx->lso_flag) {
+ /*
+ * LSO relies on tx h/w checksum, so here will drop the packet
+ * if h/w checksum flag is not declared.
+ */
+ if ((ctx->hcksum_flags & lsocksum) != lsocksum) {
+ IXGBE_DEBUGLOG_2(NULL, "ixgbe_tx: h/w checksum flags "
+ "are not set for LSO, found 0x%x, needed bits 0x%x",
+ ctx->hcksum_flags, lsocksum);
+ return (-1);
+ }
+
+
offset = mac_hdr_len + start;
while (size <= offset) {
mp = mp->b_cont;
@@ -898,6 +916,7 @@ ixgbe_check_context(ixgbe_tx_ring_t *tx_ring, ixgbe_tx_context_t *ctx)
if ((ctx->hcksum_flags != last->hcksum_flags) ||
(ctx->l4_proto != last->l4_proto) ||
+ (ctx->l3_proto != last->l3_proto) ||
(ctx->mac_hdr_len != last->mac_hdr_len) ||
(ctx->ip_hdr_len != last->ip_hdr_len) ||
(ctx->lso_flag != last->lso_flag) ||
@@ -928,11 +947,19 @@ ixgbe_fill_context(struct ixgbe_adv_tx_context_desc *ctx_tbd,
ctx_tbd->type_tucmd_mlhl =
IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
+ /*
+ * When we have a TX context set up, we enforce that the ethertype is
+ * either IPv4 or IPv6 in ixgbe_get_tx_context().
+ */
+ if (ctx->lso_flag || ctx->hcksum_flags & HCK_IPV4_HDRCKSUM) {
+ if (ctx->l3_proto == ETHERTYPE_IP) {
+ ctx_tbd->type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
+ } else {
+ ctx_tbd->type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
+ }
+ }
- if (ctx->hcksum_flags & HCK_IPV4_HDRCKSUM)
- ctx_tbd->type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
-
- if (ctx->hcksum_flags & HCK_PARTIALCKSUM) {
+ if (ctx->lso_flag || ctx->hcksum_flags & HCK_PARTIALCKSUM) {
switch (ctx->l4_proto) {
case IPPROTO_TCP:
ctx_tbd->type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;