Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2015 Cisco and/or its affiliates. |
| 3 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | * you may not use this file except in compliance with the License. |
| 5 | * You may obtain a copy of the License at: |
| 6 | * |
| 7 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | * |
| 9 | * Unless required by applicable law or agreed to in writing, software |
| 10 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | * See the License for the specific language governing permissions and |
| 13 | * limitations under the License. |
| 14 | */ |
| 15 | #include <vnet/vnet.h> |
| 16 | #include <vppinfra/vec.h> |
| 17 | #include <vppinfra/error.h> |
| 18 | #include <vppinfra/format.h> |
| 19 | #include <vppinfra/xxhash.h> |
| 20 | |
| 21 | #include <vnet/ethernet/ethernet.h> |
| 22 | #include <vnet/devices/dpdk/dpdk.h> |
| 23 | #include <vnet/classify/vnet_classify.h> |
Neale Ranns | 0bfe5d8 | 2016-08-25 15:29:12 +0100 | [diff] [blame] | 24 | #include <vnet/mpls/packet.h> |
Damjan Marion | 0247b46 | 2016-06-08 01:37:11 +0200 | [diff] [blame] | 25 | #include <vnet/handoff.h> |
Damjan Marion | 8bdc63b | 2016-11-02 14:48:21 +0100 | [diff] [blame] | 26 | #include <vnet/devices/devices.h> |
Damjan Marion | 2231150 | 2016-10-28 20:30:15 +0200 | [diff] [blame] | 27 | #include <vnet/feature/feature.h> |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 28 | |
| 29 | #include "dpdk_priv.h" |
| 30 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 31 | static char *dpdk_error_strings[] = { |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 32 | #define _(n,s) s, |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 33 | foreach_dpdk_error |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 34 | #undef _ |
| 35 | }; |
| 36 | |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 37 | always_inline int |
| 38 | vlib_buffer_is_ip4 (vlib_buffer_t * b) |
| 39 | { |
| 40 | ethernet_header_t *h = (ethernet_header_t *) b->data; |
| 41 | return (h->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP4)); |
| 42 | } |
| 43 | |
| 44 | always_inline int |
| 45 | vlib_buffer_is_ip6 (vlib_buffer_t * b) |
| 46 | { |
| 47 | ethernet_header_t *h = (ethernet_header_t *) b->data; |
| 48 | return (h->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6)); |
| 49 | } |
| 50 | |
| 51 | always_inline int |
| 52 | vlib_buffer_is_mpls (vlib_buffer_t * b) |
| 53 | { |
| 54 | ethernet_header_t *h = (ethernet_header_t *) b->data; |
| 55 | return (h->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS_UNICAST)); |
| 56 | } |
| 57 | |
| 58 | #if RTE_VERSION < RTE_VERSION_NUM(16, 11, 0, 0) |
| 59 | /* New ol_flags bits added in DPDK-16.11 */ |
| 60 | #define PKT_RX_IP_CKSUM_GOOD (1ULL << 7) |
| 61 | #endif |
| 62 | |
| 63 | always_inline u32 |
| 64 | dpdk_rx_next_from_etype (struct rte_mbuf * mb, vlib_buffer_t * b0) |
| 65 | { |
| 66 | if (PREDICT_TRUE (vlib_buffer_is_ip4 (b0))) |
| 67 | if (PREDICT_TRUE ((mb->ol_flags & PKT_RX_IP_CKSUM_GOOD) != 0)) |
| 68 | return VNET_DEVICE_INPUT_NEXT_IP4_NCS_INPUT; |
| 69 | else |
| 70 | return VNET_DEVICE_INPUT_NEXT_IP4_INPUT; |
| 71 | else if (PREDICT_TRUE (vlib_buffer_is_ip6 (b0))) |
| 72 | return VNET_DEVICE_INPUT_NEXT_IP6_INPUT; |
| 73 | else if (PREDICT_TRUE (vlib_buffer_is_mpls (b0))) |
| 74 | return VNET_DEVICE_INPUT_NEXT_MPLS_INPUT; |
| 75 | else |
| 76 | return VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT; |
| 77 | } |
| 78 | |
John Lo | d690049 | 2016-12-15 23:25:04 -0500 | [diff] [blame] | 79 | always_inline int |
| 80 | dpdk_mbuf_is_vlan (struct rte_mbuf *mb) |
| 81 | { |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 82 | #if RTE_VERSION >= RTE_VERSION_NUM(16, 11, 0, 0) |
John Lo | d690049 | 2016-12-15 23:25:04 -0500 | [diff] [blame] | 83 | return (mb->packet_type & RTE_PTYPE_L2_ETHER_VLAN) == |
| 84 | RTE_PTYPE_L2_ETHER_VLAN; |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 85 | #else |
| 86 | return |
| 87 | (mb->ol_flags & |
| 88 | (PKT_RX_VLAN_PKT | PKT_RX_VLAN_STRIPPED | PKT_RX_QINQ_STRIPPED)) == |
| 89 | PKT_RX_VLAN_PKT; |
John Lo | d690049 | 2016-12-15 23:25:04 -0500 | [diff] [blame] | 90 | #endif |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 91 | } |
John Lo | d690049 | 2016-12-15 23:25:04 -0500 | [diff] [blame] | 92 | |
Damjan Marion | 0247b46 | 2016-06-08 01:37:11 +0200 | [diff] [blame] | 93 | always_inline int |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 94 | dpdk_mbuf_is_ip4 (struct rte_mbuf *mb) |
Damjan Marion | 0247b46 | 2016-06-08 01:37:11 +0200 | [diff] [blame] | 95 | { |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 96 | return RTE_ETH_IS_IPV4_HDR (mb->packet_type) != 0; |
Damjan Marion | 0247b46 | 2016-06-08 01:37:11 +0200 | [diff] [blame] | 97 | } |
| 98 | |
| 99 | always_inline int |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 100 | dpdk_mbuf_is_ip6 (struct rte_mbuf *mb) |
Damjan Marion | 0247b46 | 2016-06-08 01:37:11 +0200 | [diff] [blame] | 101 | { |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 102 | return RTE_ETH_IS_IPV6_HDR (mb->packet_type) != 0; |
Damjan Marion | 0247b46 | 2016-06-08 01:37:11 +0200 | [diff] [blame] | 103 | } |
| 104 | |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 105 | always_inline u32 |
| 106 | dpdk_rx_next_from_mb (struct rte_mbuf * mb, vlib_buffer_t * b0) |
Damjan Marion | 0247b46 | 2016-06-08 01:37:11 +0200 | [diff] [blame] | 107 | { |
John Lo | d690049 | 2016-12-15 23:25:04 -0500 | [diff] [blame] | 108 | if (PREDICT_FALSE (dpdk_mbuf_is_vlan (mb))) |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 109 | return VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT; |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 110 | else if (PREDICT_TRUE (dpdk_mbuf_is_ip4 (mb))) |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 111 | return VNET_DEVICE_INPUT_NEXT_IP4_NCS_INPUT; |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 112 | else if (PREDICT_TRUE (dpdk_mbuf_is_ip6 (mb))) |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 113 | return VNET_DEVICE_INPUT_NEXT_IP6_INPUT; |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 114 | else if (PREDICT_TRUE (vlib_buffer_is_mpls (b0))) |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 115 | return VNET_DEVICE_INPUT_NEXT_MPLS_INPUT; |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 116 | else |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 117 | return dpdk_rx_next_from_etype (mb, b0); |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 118 | } |
| 119 | |
| 120 | always_inline void |
| 121 | dpdk_rx_error_from_mb (struct rte_mbuf *mb, u32 * next, u8 * error) |
| 122 | { |
| 123 | if (mb->ol_flags & PKT_RX_IP_CKSUM_BAD) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 124 | { |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 125 | *error = DPDK_ERROR_IP_CHECKSUM_ERROR; |
| 126 | *next = VNET_DEVICE_INPUT_NEXT_DROP; |
| 127 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 128 | else |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 129 | *error = DPDK_ERROR_NONE; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 130 | } |
| 131 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 132 | void |
| 133 | dpdk_rx_trace (dpdk_main_t * dm, |
| 134 | vlib_node_runtime_t * node, |
| 135 | dpdk_device_t * xd, |
| 136 | u16 queue_id, u32 * buffers, uword n_buffers) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 137 | { |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 138 | vlib_main_t *vm = vlib_get_main (); |
| 139 | u32 *b, n_left; |
Damjan Marion | 6e3c65e | 2016-10-31 23:23:34 +0100 | [diff] [blame] | 140 | u32 next0; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 141 | |
| 142 | n_left = n_buffers; |
| 143 | b = buffers; |
| 144 | |
| 145 | while (n_left >= 1) |
| 146 | { |
| 147 | u32 bi0; |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 148 | vlib_buffer_t *b0; |
| 149 | dpdk_rx_dma_trace_t *t0; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 150 | struct rte_mbuf *mb; |
| 151 | u8 error0; |
| 152 | |
| 153 | bi0 = b[0]; |
| 154 | n_left -= 1; |
| 155 | |
| 156 | b0 = vlib_get_buffer (vm, bi0); |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 157 | mb = rte_mbuf_from_vlib_buffer (b0); |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 158 | |
| 159 | if (PREDICT_FALSE (xd->per_interface_next_index != ~0)) |
| 160 | next0 = xd->per_interface_next_index; |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 161 | else if (PREDICT_TRUE |
| 162 | ((xd->flags & DPDK_DEVICE_FLAG_PMD_SUPPORTS_PTYPE) != 0)) |
| 163 | next0 = dpdk_rx_next_from_mb (mb, b0); |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 164 | else |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 165 | next0 = dpdk_rx_next_from_etype (mb, b0); |
| 166 | |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 167 | dpdk_rx_error_from_mb (mb, &next0, &error0); |
| 168 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 169 | vlib_trace_buffer (vm, node, next0, b0, /* follow_chain */ 0); |
| 170 | t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0])); |
| 171 | t0->queue_index = queue_id; |
| 172 | t0->device_index = xd->device_index; |
| 173 | t0->buffer_index = bi0; |
| 174 | |
Damjan Marion | f1213b8 | 2016-03-13 02:22:06 +0100 | [diff] [blame] | 175 | clib_memcpy (&t0->mb, mb, sizeof (t0->mb)); |
| 176 | clib_memcpy (&t0->buffer, b0, sizeof (b0[0]) - sizeof (b0->pre_data)); |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 177 | clib_memcpy (t0->buffer.pre_data, b0->data, |
| 178 | sizeof (t0->buffer.pre_data)); |
Damjan Marion | db7b269 | 2016-06-09 16:16:27 +0200 | [diff] [blame] | 179 | clib_memcpy (&t0->data, mb->buf_addr + mb->data_off, sizeof (t0->data)); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 180 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 181 | b += 1; |
| 182 | } |
| 183 | } |
| 184 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 185 | static inline u32 |
| 186 | dpdk_rx_burst (dpdk_main_t * dm, dpdk_device_t * xd, u16 queue_id) |
| 187 | { |
| 188 | u32 n_buffers; |
| 189 | u32 n_left; |
| 190 | u32 n_this_chunk; |
| 191 | |
| 192 | n_left = VLIB_FRAME_SIZE; |
| 193 | n_buffers = 0; |
| 194 | |
Damjan Marion | 5643170 | 2016-09-19 13:18:09 +0200 | [diff] [blame] | 195 | if (PREDICT_TRUE (xd->flags & DPDK_DEVICE_FLAG_PMD)) |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 196 | { |
| 197 | while (n_left) |
| 198 | { |
| 199 | n_this_chunk = rte_eth_rx_burst (xd->device_index, queue_id, |
| 200 | xd->rx_vectors[queue_id] + |
| 201 | n_buffers, n_left); |
| 202 | n_buffers += n_this_chunk; |
| 203 | n_left -= n_this_chunk; |
| 204 | |
| 205 | /* Empirically, DPDK r1.8 produces vectors w/ 32 or fewer elts */ |
| 206 | if (n_this_chunk < 32) |
| 207 | break; |
| 208 | } |
| 209 | } |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 210 | else |
| 211 | { |
| 212 | ASSERT (0); |
| 213 | } |
| 214 | |
| 215 | return n_buffers; |
| 216 | } |
| 217 | |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 218 | |
| 219 | static_always_inline void |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 220 | dpdk_process_subseq_segs (vlib_main_t * vm, vlib_buffer_t * b, |
| 221 | struct rte_mbuf *mb, vlib_buffer_free_list_t * fl) |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 222 | { |
| 223 | u8 nb_seg = 1; |
| 224 | struct rte_mbuf *mb_seg = 0; |
| 225 | vlib_buffer_t *b_seg, *b_chain = 0; |
| 226 | mb_seg = mb->next; |
| 227 | b_chain = b; |
| 228 | |
| 229 | while ((mb->nb_segs > 1) && (nb_seg < mb->nb_segs)) |
| 230 | { |
| 231 | ASSERT (mb_seg != 0); |
| 232 | |
| 233 | b_seg = vlib_buffer_from_rte_mbuf (mb_seg); |
| 234 | vlib_buffer_init_for_free_list (b_seg, fl); |
| 235 | |
| 236 | ASSERT ((b_seg->flags & VLIB_BUFFER_NEXT_PRESENT) == 0); |
| 237 | ASSERT (b_seg->current_data == 0); |
| 238 | |
| 239 | /* |
| 240 | * The driver (e.g. virtio) may not put the packet data at the start |
| 241 | * of the segment, so don't assume b_seg->current_data == 0 is correct. |
| 242 | */ |
| 243 | b_seg->current_data = |
| 244 | (mb_seg->buf_addr + mb_seg->data_off) - (void *) b_seg->data; |
| 245 | |
| 246 | b_seg->current_length = mb_seg->data_len; |
| 247 | b->total_length_not_including_first_buffer += mb_seg->data_len; |
| 248 | |
| 249 | b_chain->flags |= VLIB_BUFFER_NEXT_PRESENT; |
| 250 | b_chain->next_buffer = vlib_get_buffer_index (vm, b_seg); |
| 251 | |
| 252 | b_chain = b_seg; |
| 253 | mb_seg = mb_seg->next; |
| 254 | nb_seg++; |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | static_always_inline void |
| 259 | dpdk_prefetch_buffer (struct rte_mbuf *mb) |
| 260 | { |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 261 | vlib_buffer_t *b = vlib_buffer_from_rte_mbuf (mb); |
| 262 | CLIB_PREFETCH (mb, CLIB_CACHE_LINE_BYTES, LOAD); |
| 263 | CLIB_PREFETCH (b, CLIB_CACHE_LINE_BYTES, STORE); |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 264 | } |
| 265 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 266 | /* |
| 267 | * This function is used when there are no worker threads. |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 268 | * The main thread performs IO and forwards the packets. |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 269 | */ |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 270 | static_always_inline u32 |
| 271 | dpdk_device_input (dpdk_main_t * dm, dpdk_device_t * xd, |
| 272 | vlib_node_runtime_t * node, u32 cpu_index, u16 queue_id) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 273 | { |
| 274 | u32 n_buffers; |
Damjan Marion | 8bdc63b | 2016-11-02 14:48:21 +0100 | [diff] [blame] | 275 | u32 next_index = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT; |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 276 | u32 n_left_to_next, *to_next; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 277 | u32 mb_index; |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 278 | vlib_main_t *vm = vlib_get_main (); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 279 | uword n_rx_bytes = 0; |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 280 | u32 n_trace, trace_cnt __attribute__ ((unused)); |
| 281 | vlib_buffer_free_list_t *fl; |
Dave Barach | d81566f | 2016-02-15 11:34:13 -0500 | [diff] [blame] | 282 | u32 buffer_flags_template; |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 283 | |
Damjan Marion | b28e498 | 2016-08-22 22:34:38 +0200 | [diff] [blame] | 284 | if ((xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP) == 0) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 285 | return 0; |
| 286 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 287 | n_buffers = dpdk_rx_burst (dm, xd, queue_id); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 288 | |
| 289 | if (n_buffers == 0) |
| 290 | { |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 291 | return 0; |
| 292 | } |
| 293 | |
Dave Barach | d81566f | 2016-02-15 11:34:13 -0500 | [diff] [blame] | 294 | buffer_flags_template = dm->buffer_flags_template; |
| 295 | |
Damjan Marion | 4015b19 | 2016-11-18 11:41:37 +0100 | [diff] [blame] | 296 | vec_reset_length (xd->d_trace_buffers[cpu_index]); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 297 | trace_cnt = n_trace = vlib_get_trace_count (vm, node); |
| 298 | |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 299 | if (n_trace > 0) |
| 300 | { |
| 301 | u32 n = clib_min (n_trace, n_buffers); |
| 302 | mb_index = 0; |
| 303 | |
| 304 | while (n--) |
| 305 | { |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 306 | struct rte_mbuf *mb = xd->rx_vectors[queue_id][mb_index++]; |
| 307 | vlib_buffer_t *b = vlib_buffer_from_rte_mbuf (mb); |
| 308 | vec_add1 (xd->d_trace_buffers[cpu_index], |
| 309 | vlib_get_buffer_index (vm, b)); |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 310 | } |
| 311 | } |
| 312 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 313 | fl = vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX); |
| 314 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 315 | mb_index = 0; |
| 316 | |
| 317 | while (n_buffers > 0) |
| 318 | { |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 319 | vlib_buffer_t *b0, *b1, *b2, *b3; |
| 320 | u32 bi0, next0, l3_offset0; |
| 321 | u32 bi1, next1, l3_offset1; |
| 322 | u32 bi2, next2, l3_offset2; |
| 323 | u32 bi3, next3, l3_offset3; |
| 324 | u8 error0, error1, error2, error3; |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 325 | u64 or_ol_flags; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 326 | |
| 327 | vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); |
| 328 | |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 329 | while (n_buffers > 8 && n_left_to_next > 4) |
| 330 | { |
| 331 | struct rte_mbuf *mb0 = xd->rx_vectors[queue_id][mb_index]; |
| 332 | struct rte_mbuf *mb1 = xd->rx_vectors[queue_id][mb_index + 1]; |
| 333 | struct rte_mbuf *mb2 = xd->rx_vectors[queue_id][mb_index + 2]; |
| 334 | struct rte_mbuf *mb3 = xd->rx_vectors[queue_id][mb_index + 3]; |
| 335 | |
| 336 | dpdk_prefetch_buffer (xd->rx_vectors[queue_id][mb_index + 4]); |
| 337 | dpdk_prefetch_buffer (xd->rx_vectors[queue_id][mb_index + 5]); |
| 338 | dpdk_prefetch_buffer (xd->rx_vectors[queue_id][mb_index + 6]); |
| 339 | dpdk_prefetch_buffer (xd->rx_vectors[queue_id][mb_index + 7]); |
| 340 | |
| 341 | if (xd->flags & DPDK_DEVICE_FLAG_MAYBE_MULTISEG) |
| 342 | { |
| 343 | if (PREDICT_FALSE (mb0->nb_segs > 1)) |
| 344 | dpdk_prefetch_buffer (mb0->next); |
| 345 | if (PREDICT_FALSE (mb1->nb_segs > 1)) |
| 346 | dpdk_prefetch_buffer (mb1->next); |
| 347 | if (PREDICT_FALSE (mb2->nb_segs > 1)) |
| 348 | dpdk_prefetch_buffer (mb2->next); |
| 349 | if (PREDICT_FALSE (mb3->nb_segs > 1)) |
| 350 | dpdk_prefetch_buffer (mb3->next); |
| 351 | } |
| 352 | |
| 353 | ASSERT (mb0); |
| 354 | ASSERT (mb1); |
| 355 | ASSERT (mb2); |
| 356 | ASSERT (mb3); |
| 357 | |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 358 | or_ol_flags = (mb0->ol_flags | mb1->ol_flags | |
| 359 | mb2->ol_flags | mb3->ol_flags); |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 360 | b0 = vlib_buffer_from_rte_mbuf (mb0); |
| 361 | b1 = vlib_buffer_from_rte_mbuf (mb1); |
| 362 | b2 = vlib_buffer_from_rte_mbuf (mb2); |
| 363 | b3 = vlib_buffer_from_rte_mbuf (mb3); |
| 364 | |
| 365 | vlib_buffer_init_for_free_list (b0, fl); |
| 366 | vlib_buffer_init_for_free_list (b1, fl); |
| 367 | vlib_buffer_init_for_free_list (b2, fl); |
| 368 | vlib_buffer_init_for_free_list (b3, fl); |
| 369 | |
| 370 | bi0 = vlib_get_buffer_index (vm, b0); |
| 371 | bi1 = vlib_get_buffer_index (vm, b1); |
| 372 | bi2 = vlib_get_buffer_index (vm, b2); |
| 373 | bi3 = vlib_get_buffer_index (vm, b3); |
| 374 | |
| 375 | to_next[0] = bi0; |
| 376 | to_next[1] = bi1; |
| 377 | to_next[2] = bi2; |
| 378 | to_next[3] = bi3; |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 379 | to_next += 4; |
| 380 | n_left_to_next -= 4; |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 381 | |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 382 | if (PREDICT_FALSE (xd->per_interface_next_index != ~0)) |
| 383 | { |
| 384 | next0 = next1 = next2 = next3 = xd->per_interface_next_index; |
| 385 | } |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 386 | else if (PREDICT_TRUE |
| 387 | ((xd->flags & DPDK_DEVICE_FLAG_PMD_SUPPORTS_PTYPE) != 0)) |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 388 | { |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 389 | next0 = dpdk_rx_next_from_mb (mb0, b0); |
| 390 | next1 = dpdk_rx_next_from_mb (mb1, b1); |
| 391 | next2 = dpdk_rx_next_from_mb (mb2, b2); |
| 392 | next3 = dpdk_rx_next_from_mb (mb3, b3); |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 393 | } |
| 394 | else |
| 395 | { |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 396 | next0 = dpdk_rx_next_from_etype (mb0, b0); |
| 397 | next1 = dpdk_rx_next_from_etype (mb1, b1); |
| 398 | next2 = dpdk_rx_next_from_etype (mb2, b2); |
| 399 | next3 = dpdk_rx_next_from_etype (mb3, b3); |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 400 | } |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 401 | |
Damjan Marion | 2c4dbff | 2016-12-08 09:55:07 +0100 | [diff] [blame] | 402 | if (PREDICT_FALSE (or_ol_flags & PKT_RX_IP_CKSUM_BAD)) |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 403 | { |
| 404 | dpdk_rx_error_from_mb (mb0, &next0, &error0); |
| 405 | dpdk_rx_error_from_mb (mb1, &next1, &error1); |
| 406 | dpdk_rx_error_from_mb (mb2, &next2, &error2); |
| 407 | dpdk_rx_error_from_mb (mb3, &next3, &error3); |
| 408 | b0->error = node->errors[error0]; |
| 409 | b1->error = node->errors[error1]; |
| 410 | b2->error = node->errors[error2]; |
| 411 | b3->error = node->errors[error3]; |
| 412 | } |
| 413 | else |
| 414 | { |
| 415 | b0->error = b1->error = node->errors[DPDK_ERROR_NONE]; |
| 416 | b2->error = b3->error = node->errors[DPDK_ERROR_NONE]; |
| 417 | } |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 418 | |
| 419 | l3_offset0 = device_input_next_node_advance[next0]; |
| 420 | l3_offset1 = device_input_next_node_advance[next1]; |
| 421 | l3_offset2 = device_input_next_node_advance[next2]; |
| 422 | l3_offset3 = device_input_next_node_advance[next3]; |
| 423 | |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 424 | b0->current_data = l3_offset0 + mb0->data_off; |
| 425 | b1->current_data = l3_offset1 + mb1->data_off; |
| 426 | b2->current_data = l3_offset2 + mb2->data_off; |
| 427 | b3->current_data = l3_offset3 + mb3->data_off; |
| 428 | |
| 429 | b0->current_data -= RTE_PKTMBUF_HEADROOM; |
| 430 | b1->current_data -= RTE_PKTMBUF_HEADROOM; |
| 431 | b2->current_data -= RTE_PKTMBUF_HEADROOM; |
| 432 | b3->current_data -= RTE_PKTMBUF_HEADROOM; |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 433 | |
| 434 | b0->current_length = mb0->data_len - l3_offset0; |
| 435 | b1->current_length = mb1->data_len - l3_offset1; |
| 436 | b2->current_length = mb2->data_len - l3_offset2; |
| 437 | b3->current_length = mb3->data_len - l3_offset3; |
| 438 | |
| 439 | b0->flags = buffer_flags_template; |
| 440 | b1->flags = buffer_flags_template; |
| 441 | b2->flags = buffer_flags_template; |
| 442 | b3->flags = buffer_flags_template; |
| 443 | |
| 444 | vnet_buffer (b0)->sw_if_index[VLIB_RX] = xd->vlib_sw_if_index; |
| 445 | vnet_buffer (b1)->sw_if_index[VLIB_RX] = xd->vlib_sw_if_index; |
| 446 | vnet_buffer (b2)->sw_if_index[VLIB_RX] = xd->vlib_sw_if_index; |
| 447 | vnet_buffer (b3)->sw_if_index[VLIB_RX] = xd->vlib_sw_if_index; |
| 448 | |
| 449 | vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0; |
| 450 | vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0; |
| 451 | vnet_buffer (b2)->sw_if_index[VLIB_TX] = (u32) ~ 0; |
| 452 | vnet_buffer (b3)->sw_if_index[VLIB_TX] = (u32) ~ 0; |
| 453 | |
| 454 | n_rx_bytes += mb0->pkt_len; |
| 455 | n_rx_bytes += mb1->pkt_len; |
| 456 | n_rx_bytes += mb2->pkt_len; |
| 457 | n_rx_bytes += mb3->pkt_len; |
| 458 | |
| 459 | /* Process subsequent segments of multi-segment packets */ |
| 460 | if (xd->flags & DPDK_DEVICE_FLAG_MAYBE_MULTISEG) |
| 461 | { |
| 462 | dpdk_process_subseq_segs (vm, b0, mb0, fl); |
| 463 | dpdk_process_subseq_segs (vm, b1, mb1, fl); |
| 464 | dpdk_process_subseq_segs (vm, b2, mb2, fl); |
| 465 | dpdk_process_subseq_segs (vm, b3, mb3, fl); |
| 466 | } |
| 467 | |
| 468 | /* |
| 469 | * Turn this on if you run into |
| 470 | * "bad monkey" contexts, and you want to know exactly |
| 471 | * which nodes they've visited... See main.c... |
| 472 | */ |
| 473 | VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0); |
| 474 | VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b1); |
| 475 | VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b2); |
| 476 | VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b3); |
| 477 | |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 478 | /* Do we have any driver RX features configured on the interface? */ |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 479 | vnet_feature_start_device_input_x4 (xd->vlib_sw_if_index, |
| 480 | &next0, &next1, &next2, &next3, |
| 481 | b0, b1, b2, b3, |
| 482 | l3_offset0, l3_offset1, |
| 483 | l3_offset2, l3_offset3); |
| 484 | |
| 485 | vlib_validate_buffer_enqueue_x4 (vm, node, next_index, |
| 486 | to_next, n_left_to_next, |
| 487 | bi0, bi1, bi2, bi3, |
| 488 | next0, next1, next2, next3); |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 489 | n_buffers -= 4; |
| 490 | mb_index += 4; |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 491 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 492 | while (n_buffers > 0 && n_left_to_next > 0) |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 493 | { |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 494 | struct rte_mbuf *mb0 = xd->rx_vectors[queue_id][mb_index]; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 495 | |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 496 | ASSERT (mb0); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 497 | |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 498 | b0 = vlib_buffer_from_rte_mbuf (mb0); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 499 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 500 | /* Prefetch one next segment if it exists. */ |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 501 | if (PREDICT_FALSE (mb0->nb_segs > 1)) |
| 502 | dpdk_prefetch_buffer (mb0->next); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 503 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 504 | vlib_buffer_init_for_free_list (b0, fl); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 505 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 506 | bi0 = vlib_get_buffer_index (vm, b0); |
| 507 | |
| 508 | to_next[0] = bi0; |
| 509 | to_next++; |
| 510 | n_left_to_next--; |
| 511 | |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 512 | if (PREDICT_FALSE (xd->per_interface_next_index != ~0)) |
| 513 | next0 = xd->per_interface_next_index; |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 514 | else if (PREDICT_TRUE |
| 515 | ((xd->flags & DPDK_DEVICE_FLAG_PMD_SUPPORTS_PTYPE) != 0)) |
| 516 | next0 = dpdk_rx_next_from_mb (mb0, b0); |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 517 | else |
John Lo | a60d4cb | 2016-12-17 03:09:58 -0500 | [diff] [blame] | 518 | next0 = dpdk_rx_next_from_etype (mb0, b0); |
| 519 | |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 520 | dpdk_rx_error_from_mb (mb0, &next0, &error0); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 521 | b0->error = node->errors[error0]; |
| 522 | |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 523 | l3_offset0 = device_input_next_node_advance[next0]; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 524 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 525 | b0->current_data = l3_offset0; |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 526 | b0->current_data += mb0->data_off - RTE_PKTMBUF_HEADROOM; |
| 527 | b0->current_length = mb0->data_len - l3_offset0; |
Dave Barach | 61efa14 | 2016-01-22 08:23:09 -0500 | [diff] [blame] | 528 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 529 | b0->flags = buffer_flags_template; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 530 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 531 | vnet_buffer (b0)->sw_if_index[VLIB_RX] = xd->vlib_sw_if_index; |
| 532 | vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0; |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 533 | n_rx_bytes += mb0->pkt_len; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 534 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 535 | /* Process subsequent segments of multi-segment packets */ |
Damjan Marion | 7dc4146 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 536 | dpdk_process_subseq_segs (vm, b0, mb0, fl); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 537 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 538 | /* |
| 539 | * Turn this on if you run into |
| 540 | * "bad monkey" contexts, and you want to know exactly |
| 541 | * which nodes they've visited... See main.c... |
| 542 | */ |
| 543 | VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 544 | |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 545 | /* Do we have any driver RX features configured on the interface? */ |
| 546 | vnet_feature_start_device_input_x1 (xd->vlib_sw_if_index, &next0, |
| 547 | b0, l3_offset0); |
Damjan Marion | 2231150 | 2016-10-28 20:30:15 +0200 | [diff] [blame] | 548 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 549 | vlib_validate_buffer_enqueue_x1 (vm, node, next_index, |
| 550 | to_next, n_left_to_next, |
| 551 | bi0, next0); |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 552 | n_buffers--; |
| 553 | mb_index++; |
| 554 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 555 | vlib_put_next_frame (vm, node, next_index, n_left_to_next); |
| 556 | } |
| 557 | |
Damjan Marion | 4015b19 | 2016-11-18 11:41:37 +0100 | [diff] [blame] | 558 | if (PREDICT_FALSE (vec_len (xd->d_trace_buffers[cpu_index]) > 0)) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 559 | { |
Damjan Marion | 4015b19 | 2016-11-18 11:41:37 +0100 | [diff] [blame] | 560 | dpdk_rx_trace (dm, node, xd, queue_id, xd->d_trace_buffers[cpu_index], |
| 561 | vec_len (xd->d_trace_buffers[cpu_index])); |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 562 | vlib_set_trace_count (vm, node, n_trace - |
| 563 | vec_len (xd->d_trace_buffers[cpu_index])); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 564 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 565 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 566 | vlib_increment_combined_counter |
| 567 | (vnet_get_main ()->interface_main.combined_sw_if_counters |
| 568 | + VNET_INTERFACE_COUNTER_RX, |
| 569 | cpu_index, xd->vlib_sw_if_index, mb_index, n_rx_bytes); |
| 570 | |
| 571 | dpdk_worker_t *dw = vec_elt_at_index (dm->workers, cpu_index); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 572 | dw->aggregate_rx_packets += mb_index; |
| 573 | |
| 574 | return mb_index; |
| 575 | } |
| 576 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 577 | static inline void |
| 578 | poll_rate_limit (dpdk_main_t * dm) |
Dave Barach | 08602d1 | 2016-06-04 14:10:59 -0400 | [diff] [blame] | 579 | { |
| 580 | /* Limit the poll rate by sleeping for N msec between polls */ |
| 581 | if (PREDICT_FALSE (dm->poll_sleep != 0)) |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 582 | { |
| 583 | struct timespec ts, tsrem; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 584 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 585 | ts.tv_sec = 0; |
| 586 | ts.tv_nsec = 1000 * 1000 * dm->poll_sleep; /* 1ms */ |
Dave Barach | 08602d1 | 2016-06-04 14:10:59 -0400 | [diff] [blame] | 587 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 588 | while (nanosleep (&ts, &tsrem) < 0) |
| 589 | { |
| 590 | ts = tsrem; |
| 591 | } |
| 592 | } |
Dave Barach | 08602d1 | 2016-06-04 14:10:59 -0400 | [diff] [blame] | 593 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 594 | |
Dave Barach | 132d51d | 2016-07-07 10:10:17 -0400 | [diff] [blame] | 595 | /** \brief Main DPDK input node |
| 596 | @node dpdk-input |
| 597 | |
| 598 | This is the main DPDK input node: across each assigned interface, |
| 599 | call rte_eth_rx_burst(...) or similar to obtain a vector of |
| 600 | packets to process. Handle early packet discard. Derive @c |
| 601 | vlib_buffer_t metadata from <code>struct rte_mbuf</code> metadata, |
| 602 | Depending on the resulting metadata: adjust <code>b->current_data, |
| 603 | b->current_length </code> and dispatch directly to |
| 604 | ip4-input-no-checksum, or ip6-input. Trace the packet if required. |
| 605 | |
Chris Luke | d4024f5 | 2016-09-06 09:32:36 -0400 | [diff] [blame] | 606 | @param vm vlib_main_t corresponding to the current thread |
Dave Barach | 132d51d | 2016-07-07 10:10:17 -0400 | [diff] [blame] | 607 | @param node vlib_node_runtime_t |
Chris Luke | d4024f5 | 2016-09-06 09:32:36 -0400 | [diff] [blame] | 608 | @param f vlib_frame_t input-node, not used. |
Dave Barach | 132d51d | 2016-07-07 10:10:17 -0400 | [diff] [blame] | 609 | |
| 610 | @par Graph mechanics: buffer metadata, next index usage |
| 611 | |
| 612 | @em Uses: |
| 613 | - <code>struct rte_mbuf mb->ol_flags</code> |
Damjan Marion | 2c4dbff | 2016-12-08 09:55:07 +0100 | [diff] [blame] | 614 | - PKT_RX_IP_CKSUM_BAD |
Dave Barach | 132d51d | 2016-07-07 10:10:17 -0400 | [diff] [blame] | 615 | - <code> RTE_ETH_IS_xxx_HDR(mb->packet_type) </code> |
| 616 | - packet classification result |
| 617 | |
| 618 | @em Sets: |
| 619 | - <code>b->error</code> if the packet is to be dropped immediately |
| 620 | - <code>b->current_data, b->current_length</code> |
| 621 | - adjusted as needed to skip the L2 header in direct-dispatch cases |
| 622 | - <code>vnet_buffer(b)->sw_if_index[VLIB_RX]</code> |
| 623 | - rx interface sw_if_index |
| 624 | - <code>vnet_buffer(b)->sw_if_index[VLIB_TX] = ~0</code> |
| 625 | - required by ipX-lookup |
| 626 | - <code>b->flags</code> |
| 627 | - to indicate multi-segment pkts (VLIB_BUFFER_NEXT_PRESENT), etc. |
| 628 | |
| 629 | <em>Next Nodes:</em> |
| 630 | - Static arcs to: error-drop, ethernet-input, |
Neale Ranns | 0bfe5d8 | 2016-08-25 15:29:12 +0100 | [diff] [blame] | 631 | ip4-input-no-checksum, ip6-input, mpls-input |
Dave Barach | 132d51d | 2016-07-07 10:10:17 -0400 | [diff] [blame] | 632 | - per-interface redirection, controlled by |
| 633 | <code>xd->per_interface_next_index</code> |
| 634 | */ |
| 635 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 636 | static uword |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 637 | dpdk_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 638 | { |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 639 | dpdk_main_t *dm = &dpdk_main; |
| 640 | dpdk_device_t *xd; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 641 | uword n_rx_packets = 0; |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 642 | dpdk_device_and_queue_t *dq; |
| 643 | u32 cpu_index = os_get_cpu_number (); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 644 | |
| 645 | /* |
| 646 | * Poll all devices on this cpu for input/interrupts. |
| 647 | */ |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 648 | /* *INDENT-OFF* */ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 649 | vec_foreach (dq, dm->devices_by_cpu[cpu_index]) |
| 650 | { |
| 651 | xd = vec_elt_at_index(dm->devices, dq->device); |
Damjan Marion | 4ee3a65 | 2016-11-15 19:47:58 +0100 | [diff] [blame] | 652 | n_rx_packets += dpdk_device_input (dm, xd, node, cpu_index, dq->queue_id); |
Damjan Marion | 1c80e83 | 2016-05-11 23:07:18 +0200 | [diff] [blame] | 653 | } |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 654 | /* *INDENT-ON* */ |
Damjan Marion | 1c80e83 | 2016-05-11 23:07:18 +0200 | [diff] [blame] | 655 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 656 | poll_rate_limit (dm); |
Damjan Marion | 1c80e83 | 2016-05-11 23:07:18 +0200 | [diff] [blame] | 657 | |
| 658 | return n_rx_packets; |
| 659 | } |
| 660 | |
Damjan Marion | 2566567 | 2016-08-16 18:56:08 +0200 | [diff] [blame] | 661 | /* *INDENT-OFF* */ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 662 | VLIB_REGISTER_NODE (dpdk_input_node) = { |
| 663 | .function = dpdk_input, |
| 664 | .type = VLIB_NODE_TYPE_INPUT, |
| 665 | .name = "dpdk-input", |
Damjan Marion | 51327ac | 2016-11-09 11:59:42 +0100 | [diff] [blame] | 666 | .sibling_of = "device-input", |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 667 | |
| 668 | /* Will be enabled if/when hardware is detected. */ |
| 669 | .state = VLIB_NODE_STATE_DISABLED, |
| 670 | |
| 671 | .format_buffer = format_ethernet_header_with_length, |
| 672 | .format_trace = format_dpdk_rx_dma_trace, |
| 673 | |
| 674 | .n_errors = DPDK_N_ERROR, |
| 675 | .error_strings = dpdk_error_strings, |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 676 | }; |
| 677 | |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 678 | VLIB_NODE_FUNCTION_MULTIARCH (dpdk_input_node, dpdk_input); |
| 679 | /* *INDENT-ON* */ |
Damjan Marion | 1c80e83 | 2016-05-11 23:07:18 +0200 | [diff] [blame] | 680 | |
Damjan Marion | 7549621 | 2016-11-22 18:21:51 -0800 | [diff] [blame] | 681 | /* |
| 682 | * fd.io coding-style-patch-verification: ON |
| 683 | * |
| 684 | * Local Variables: |
| 685 | * eval: (c-set-style "gnu") |
| 686 | * End: |
| 687 | */ |