| 3124 | #define IS_TX_OFFLOAD6(pi) ((pi)->ipi_csum_flags & (CSUM_IP6_TCP | CSUM_IP6_TSO)) |
| 3125 | |
| 3126 | static int |
| 3127 | iflib_parse_header(iflib_txq_t txq, if_pkt_info_t pi, struct mbuf **mp) |
| 3128 | { |
| 3129 | if_shared_ctx_t sctx = txq->ift_ctx->ifc_sctx; |
| 3130 | struct ether_vlan_header *eh; |
| 3131 | struct mbuf *m; |
| 3132 | |
| 3133 | m = *mp; |
| 3134 | if ((sctx->isc_flags & IFLIB_NEED_SCRATCH) && |
| 3135 | M_WRITABLE(m) == 0) { |
| 3136 | if ((m = m_dup(m, M_NOWAIT)) == NULL) { |
| 3137 | return (ENOMEM); |
| 3138 | } else { |
| 3139 | m_freem(*mp); |
| 3140 | DBG_COUNTER_INC(tx_frees); |
| 3141 | *mp = m; |
| 3142 | } |
| 3143 | } |
| 3144 | |
| 3145 | /* |
| 3146 | * Determine where frame payload starts. |
| 3147 | * Jump over vlan headers if already present, |
| 3148 | * helpful for QinQ too. |
| 3149 | */ |
| 3150 | if (__predict_false(m->m_len < sizeof(*eh))) { |
| 3151 | txq->ift_pullups++; |
| 3152 | if (__predict_false((m = m_pullup(m, sizeof(*eh))) == NULL)) |
| 3153 | return (ENOMEM); |
| 3154 | } |
| 3155 | eh = mtod(m, struct ether_vlan_header *); |
| 3156 | if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { |
| 3157 | pi->ipi_etype = ntohs(eh->evl_proto); |
| 3158 | pi->ipi_ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; |
| 3159 | } else { |
| 3160 | pi->ipi_etype = ntohs(eh->evl_encap_proto); |
| 3161 | pi->ipi_ehdrlen = ETHER_HDR_LEN; |
| 3162 | } |
| 3163 | |
| 3164 | switch (pi->ipi_etype) { |
| 3165 | #ifdef INET |
| 3166 | case ETHERTYPE_IP: |
| 3167 | { |
| 3168 | struct mbuf *n; |
| 3169 | struct ip *ip = NULL; |
| 3170 | struct tcphdr *th = NULL; |
| 3171 | int minthlen; |
| 3172 | |
| 3173 | minthlen = min(m->m_pkthdr.len, pi->ipi_ehdrlen + sizeof(*ip) + sizeof(*th)); |
| 3174 | if (__predict_false(m->m_len < minthlen)) { |
| 3175 | /* |
| 3176 | * if this code bloat is causing too much of a hit |
| 3177 | * move it to a separate function and mark it noinline |
| 3178 | */ |
| 3179 | if (m->m_len == pi->ipi_ehdrlen) { |
| 3180 | n = m->m_next; |
| 3181 | MPASS(n); |
| 3182 | if (n->m_len >= sizeof(*ip)) { |
| 3183 | ip = (struct ip *)n->m_data; |
no test coverage detected