1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2008-2018 Cisco Systems, Inc. All rights reserved. 3 * Copyright 2007 Nuova Systems, Inc. All rights reserved. 4 */ 5 6 #ifndef _ENIC_RXTX_COMMON_H_ 7 #define _ENIC_RXTX_COMMON_H_ 8 9 #include <rte_byteorder.h> 10 11 static inline uint16_t 12 enic_cq_rx_desc_ciflags(struct cq_enet_rq_desc *crd) 13 { 14 return rte_le_to_cpu_16(crd->completed_index_flags) & 15 ~CQ_DESC_COMP_NDX_MASK; 16 } 17 18 static inline uint16_t 19 enic_cq_rx_desc_bwflags(struct cq_enet_rq_desc *crd) 20 { 21 return rte_le_to_cpu_16(crd->bytes_written_flags) & 22 ~CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK; 23 } 24 25 static inline uint8_t 26 enic_cq_rx_desc_packet_error(uint16_t bwflags) 27 { 28 return (bwflags & CQ_ENET_RQ_DESC_FLAGS_TRUNCATED) == 29 CQ_ENET_RQ_DESC_FLAGS_TRUNCATED; 30 } 31 32 static inline uint8_t 33 enic_cq_rx_desc_eop(uint16_t ciflags) 34 { 35 return (ciflags & CQ_ENET_RQ_DESC_FLAGS_EOP) 36 == CQ_ENET_RQ_DESC_FLAGS_EOP; 37 } 38 39 static inline uint8_t 40 enic_cq_rx_desc_csum_not_calc(struct cq_enet_rq_desc *cqrd) 41 { 42 return (rte_le_to_cpu_16(cqrd->q_number_rss_type_flags) & 43 CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC) == 44 CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC; 45 } 46 47 static inline uint8_t 48 enic_cq_rx_desc_ipv4_csum_ok(struct cq_enet_rq_desc *cqrd) 49 { 50 return (cqrd->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK) == 51 CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK; 52 } 53 54 static inline uint8_t 55 enic_cq_rx_desc_tcp_udp_csum_ok(struct cq_enet_rq_desc *cqrd) 56 { 57 return (cqrd->flags & CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK) == 58 CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK; 59 } 60 61 static inline uint8_t 62 enic_cq_rx_desc_rss_type(struct cq_enet_rq_desc *cqrd) 63 { 64 return (uint8_t)((rte_le_to_cpu_16(cqrd->q_number_rss_type_flags) >> 65 CQ_DESC_Q_NUM_BITS) & CQ_ENET_RQ_DESC_RSS_TYPE_MASK); 66 } 67 68 static inline uint32_t 69 enic_cq_rx_desc_rss_hash(struct cq_enet_rq_desc *cqrd) 70 { 71 return rte_le_to_cpu_32(cqrd->rss_hash); 72 } 73 74 static inline uint16_t 75 enic_cq_rx_desc_vlan(struct cq_enet_rq_desc *cqrd) 76 { 77 return rte_le_to_cpu_16(cqrd->vlan); 78 } 79 80 static inline uint16_t 81 enic_cq_rx_desc_n_bytes(struct cq_desc *cqd) 82 { 83 struct cq_enet_rq_desc *cqrd = (struct cq_enet_rq_desc *)cqd; 84 return rte_le_to_cpu_16(cqrd->bytes_written_flags) & 85 CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK; 86 } 87 88 89 static inline uint8_t 90 enic_cq_rx_check_err(struct cq_desc *cqd) 91 { 92 struct cq_enet_rq_desc *cqrd = (struct cq_enet_rq_desc *)cqd; 93 uint16_t bwflags; 94 95 bwflags = enic_cq_rx_desc_bwflags(cqrd); 96 if (unlikely(enic_cq_rx_desc_packet_error(bwflags))) 97 return 1; 98 return 0; 99 } 100 101 /* Lookup table to translate RX CQ flags to mbuf flags. */ 102 static uint32_t 103 enic_cq_rx_flags_to_pkt_type(struct cq_desc *cqd, uint8_t tnl) 104 { 105 struct cq_enet_rq_desc *cqrd = (struct cq_enet_rq_desc *)cqd; 106 uint8_t cqrd_flags = cqrd->flags; 107 /* 108 * Odd-numbered entries are for tunnel packets. All packet type info 109 * applies to the inner packet, and there is no info on the outer 110 * packet. The outer flags in these entries exist only to avoid 111 * changing enic_cq_rx_to_pkt_flags(). They are cleared from mbuf 112 * afterwards. 113 * 114 * Also, as there is no tunnel type info (VXLAN, NVGRE, or GENEVE), set 115 * RTE_PTYPE_TUNNEL_GRENAT.. 116 */ 117 static const uint32_t cq_type_table[128] __rte_cache_aligned = { 118 [0x00] = RTE_PTYPE_UNKNOWN, 119 [0x01] = RTE_PTYPE_UNKNOWN | 120 RTE_PTYPE_TUNNEL_GRENAT | 121 RTE_PTYPE_INNER_L2_ETHER, 122 [0x20] = RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_NONFRAG, 123 [0x21] = RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_NONFRAG | 124 RTE_PTYPE_TUNNEL_GRENAT | 125 RTE_PTYPE_INNER_L2_ETHER | 126 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 127 RTE_PTYPE_INNER_L4_NONFRAG, 128 [0x22] = RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP, 129 [0x23] = RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | 130 RTE_PTYPE_TUNNEL_GRENAT | 131 RTE_PTYPE_INNER_L2_ETHER | 132 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 133 RTE_PTYPE_INNER_L4_UDP, 134 [0x24] = RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_TCP, 135 [0x25] = RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_TCP | 136 RTE_PTYPE_TUNNEL_GRENAT | 137 RTE_PTYPE_INNER_L2_ETHER | 138 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 139 RTE_PTYPE_INNER_L4_TCP, 140 [0x60] = RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_FRAG, 141 [0x61] = RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_FRAG | 142 RTE_PTYPE_TUNNEL_GRENAT | 143 RTE_PTYPE_INNER_L2_ETHER | 144 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 145 RTE_PTYPE_INNER_L4_FRAG, 146 [0x62] = RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_FRAG, 147 [0x63] = RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_FRAG | 148 RTE_PTYPE_TUNNEL_GRENAT | 149 RTE_PTYPE_INNER_L2_ETHER | 150 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 151 RTE_PTYPE_INNER_L4_FRAG, 152 [0x64] = RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_FRAG, 153 [0x65] = RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_FRAG | 154 RTE_PTYPE_TUNNEL_GRENAT | 155 RTE_PTYPE_INNER_L2_ETHER | 156 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 157 RTE_PTYPE_INNER_L4_FRAG, 158 [0x10] = RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_NONFRAG, 159 [0x11] = RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_NONFRAG | 160 RTE_PTYPE_TUNNEL_GRENAT | 161 RTE_PTYPE_INNER_L2_ETHER | 162 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 163 RTE_PTYPE_INNER_L4_NONFRAG, 164 [0x12] = RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_UDP, 165 [0x13] = RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_UDP | 166 RTE_PTYPE_TUNNEL_GRENAT | 167 RTE_PTYPE_INNER_L2_ETHER | 168 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 169 RTE_PTYPE_INNER_L4_UDP, 170 [0x14] = RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_TCP, 171 [0x15] = RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_TCP | 172 RTE_PTYPE_TUNNEL_GRENAT | 173 RTE_PTYPE_INNER_L2_ETHER | 174 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 175 RTE_PTYPE_INNER_L4_TCP, 176 [0x50] = RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_FRAG, 177 [0x51] = RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_FRAG | 178 RTE_PTYPE_TUNNEL_GRENAT | 179 RTE_PTYPE_INNER_L2_ETHER | 180 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 181 RTE_PTYPE_INNER_L4_FRAG, 182 [0x52] = RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_FRAG, 183 [0x53] = RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_FRAG | 184 RTE_PTYPE_TUNNEL_GRENAT | 185 RTE_PTYPE_INNER_L2_ETHER | 186 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 187 RTE_PTYPE_INNER_L4_FRAG, 188 [0x54] = RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_FRAG, 189 [0x55] = RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_FRAG | 190 RTE_PTYPE_TUNNEL_GRENAT | 191 RTE_PTYPE_INNER_L2_ETHER | 192 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 193 RTE_PTYPE_INNER_L4_FRAG, 194 /* All others reserved */ 195 }; 196 cqrd_flags &= CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT 197 | CQ_ENET_RQ_DESC_FLAGS_IPV4 | CQ_ENET_RQ_DESC_FLAGS_IPV6 198 | CQ_ENET_RQ_DESC_FLAGS_TCP | CQ_ENET_RQ_DESC_FLAGS_UDP; 199 return cq_type_table[cqrd_flags + tnl]; 200 } 201 202 static void 203 enic_cq_rx_to_pkt_flags(struct cq_desc *cqd, struct rte_mbuf *mbuf) 204 { 205 struct cq_enet_rq_desc *cqrd = (struct cq_enet_rq_desc *)cqd; 206 uint16_t bwflags, pkt_flags = 0, vlan_tci; 207 bwflags = enic_cq_rx_desc_bwflags(cqrd); 208 vlan_tci = enic_cq_rx_desc_vlan(cqrd); 209 210 /* VLAN STRIPPED flag. The L2 packet type updated here also */ 211 if (bwflags & CQ_ENET_RQ_DESC_FLAGS_VLAN_STRIPPED) { 212 pkt_flags |= PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED; 213 mbuf->packet_type |= RTE_PTYPE_L2_ETHER; 214 } else { 215 if (vlan_tci != 0) { 216 pkt_flags |= PKT_RX_VLAN; 217 mbuf->packet_type |= RTE_PTYPE_L2_ETHER_VLAN; 218 } else { 219 mbuf->packet_type |= RTE_PTYPE_L2_ETHER; 220 } 221 } 222 mbuf->vlan_tci = vlan_tci; 223 224 if ((cqd->type_color & CQ_DESC_TYPE_MASK) == CQ_DESC_TYPE_CLASSIFIER) { 225 struct cq_enet_rq_clsf_desc *clsf_cqd; 226 uint16_t filter_id; 227 clsf_cqd = (struct cq_enet_rq_clsf_desc *)cqd; 228 filter_id = clsf_cqd->filter_id; 229 if (filter_id) { 230 pkt_flags |= PKT_RX_FDIR; 231 if (filter_id != ENIC_MAGIC_FILTER_ID) { 232 /* filter_id = mark id + 1, so subtract 1 */ 233 mbuf->hash.fdir.hi = filter_id - 1; 234 pkt_flags |= PKT_RX_FDIR_ID; 235 } 236 } 237 } else if (enic_cq_rx_desc_rss_type(cqrd)) { 238 /* RSS flag */ 239 pkt_flags |= PKT_RX_RSS_HASH; 240 mbuf->hash.rss = enic_cq_rx_desc_rss_hash(cqrd); 241 } 242 243 /* checksum flags */ 244 if (mbuf->packet_type & (RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L3_IPV6)) { 245 if (!enic_cq_rx_desc_csum_not_calc(cqrd)) { 246 uint32_t l4_flags; 247 l4_flags = mbuf->packet_type & RTE_PTYPE_L4_MASK; 248 249 /* 250 * When overlay offload is enabled, the NIC may 251 * set ipv4_csum_ok=1 if the inner packet is IPv6.. 252 * So, explicitly check for IPv4 before checking 253 * ipv4_csum_ok. 254 */ 255 if (mbuf->packet_type & RTE_PTYPE_L3_IPV4) { 256 if (enic_cq_rx_desc_ipv4_csum_ok(cqrd)) 257 pkt_flags |= PKT_RX_IP_CKSUM_GOOD; 258 else 259 pkt_flags |= PKT_RX_IP_CKSUM_BAD; 260 } 261 262 if (l4_flags == RTE_PTYPE_L4_UDP || 263 l4_flags == RTE_PTYPE_L4_TCP) { 264 if (enic_cq_rx_desc_tcp_udp_csum_ok(cqrd)) 265 pkt_flags |= PKT_RX_L4_CKSUM_GOOD; 266 else 267 pkt_flags |= PKT_RX_L4_CKSUM_BAD; 268 } 269 } 270 } 271 272 mbuf->ol_flags = pkt_flags; 273 } 274 275 #endif /* _ENIC_RXTX_COMMON_H_ */ 276