FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
output.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2018 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17 
18 #include <vlib/vlib.h>
19 #include <vlib/unix/unix.h>
20 #include <vlib/pci/pci.h>
21 #include <vnet/ethernet/ethernet.h>
22 #include <vnet/devices/devices.h>
23 #include <vnet/ip/ip6_packet.h>
24 #include <vnet/ip/ip4_packet.h>
25 
26 #include <vmxnet3/vmxnet3.h>
27 
30 {
31  vmxnet3_tx_comp_ring *comp_ring = &txq->tx_comp_ring;
32 
33  comp_ring->next++;
34  if (PREDICT_FALSE (comp_ring->next == txq->size))
35  {
36  comp_ring->next = 0;
37  comp_ring->gen ^= VMXNET3_TXCF_GEN;
38  }
39 }
40 
43 {
44  txq->tx_ring.produce++;
45  if (PREDICT_FALSE (txq->tx_ring.produce == txq->size))
46  {
47  txq->tx_ring.produce = 0;
48  txq->tx_ring.gen ^= VMXNET3_TXF_GEN;
49  }
50 }
51 
54 {
55  txq->tx_ring.consume++;
56  txq->tx_ring.consume &= txq->size - 1;
57 }
58 
61  vmxnet3_txq_t * txq)
62 {
63  vmxnet3_tx_comp *tx_comp;
64  vmxnet3_tx_comp_ring *comp_ring;
65 
66  comp_ring = &txq->tx_comp_ring;
67  tx_comp = &txq->tx_comp[comp_ring->next];
68 
69  while ((tx_comp->flags & VMXNET3_TXCF_GEN) == comp_ring->gen)
70  {
71  u16 eop_idx = tx_comp->index & VMXNET3_TXC_INDEX;
72  u32 bi0 = txq->tx_ring.bufs[txq->tx_ring.consume];
73 
74  vlib_buffer_free_one (vm, bi0);
75  while (txq->tx_ring.consume != eop_idx)
76  {
78  }
80 
82  tx_comp = &txq->tx_comp[comp_ring->next];
83  }
84 }
85 
88 {
89  u16 count;
90 
91  count = (txq->tx_ring.consume - txq->tx_ring.produce - 1);
92  /* Wrapped? */
93  if (txq->tx_ring.produce >= txq->tx_ring.consume)
94  count += txq->size;
95  return count;
96 }
97 
101 {
102  vmxnet3_main_t *vmxm = &vmxnet3_main;
103  vnet_interface_output_runtime_t *rd = (void *) node->runtime_data;
105  u32 *buffers = vlib_frame_vector_args (frame);
106  u32 bi0;
107  vlib_buffer_t *b0;
108  vmxnet3_tx_desc *txd = 0;
109  u32 desc_idx, generation, first_idx;
110  u16 space_left;
111  u16 n_left = frame->n_vectors;
112  vmxnet3_txq_t *txq;
114  u16 qid = tf->queue_id, produce;
115 
116  if (PREDICT_FALSE (!(vd->flags & VMXNET3_DEVICE_F_LINK_UP)))
117  {
118  vlib_buffer_free (vm, buffers, n_left);
119  vlib_error_count (vm, node->node_index, VMXNET3_TX_ERROR_LINK_DOWN,
120  n_left);
121  return (0);
122  }
123 
124  txq = vec_elt_at_index (vd->txqs, qid);
125  if (tf->shared_queue)
126  clib_spinlock_lock (&txq->lock);
127 
128  vmxnet3_txq_release (vm, vd, txq);
129 
130  produce = txq->tx_ring.produce;
131  while (PREDICT_TRUE (n_left))
132  {
133  u16 space_needed = 1, i;
134  u32 gso_size = 0;
135  u32 l4_hdr_sz;
136  vlib_buffer_t *b;
137  u32 hdr_len = 0;
138 
139  bi0 = buffers[0];
140  b0 = vlib_get_buffer (vm, bi0);
141  b = b0;
142 
143  space_left = vmxnet3_tx_ring_space_left (txq);
144  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
145  {
146  u32 next_buffer = b->next_buffer;
147 
148  b = vlib_get_buffer (vm, next_buffer);
149  space_needed++;
150  }
151  if (PREDICT_FALSE (space_left < space_needed))
152  {
153  vmxnet3_txq_release (vm, vd, txq);
154  space_left = vmxnet3_tx_ring_space_left (txq);
155 
156  if (PREDICT_FALSE (space_left < space_needed))
157  {
158  vlib_buffer_free_one (vm, bi0);
159  vlib_error_count (vm, node->node_index,
160  VMXNET3_TX_ERROR_NO_FREE_SLOTS, 1);
161  buffers++;
162  n_left--;
163  /*
164  * Drop this packet. But we may have enough room for the next
165  * packet
166  */
167  continue;
168  }
169  }
170 
171  /*
172  * Toggle the generation bit for SOP fragment to avoid device starts
173  * reading incomplete packet
174  */
175  generation = txq->tx_ring.gen ^ VMXNET3_TXF_GEN;
176  first_idx = txq->tx_ring.produce;
177  for (i = 0; i < space_needed; i++)
178  {
179  b0 = vlib_get_buffer (vm, bi0);
180 
181  desc_idx = txq->tx_ring.produce;
182 
184  txq->tx_ring.bufs[desc_idx] = bi0;
185 
186  txd = &txq->tx_desc[desc_idx];
187 
188  txd->address = vlib_buffer_get_current_pa (vm, b0);
189 
190  txd->flags[0] = generation | b0->current_length;
191  txd->flags[1] = 0;
192  if (PREDICT_FALSE (b0->flags & VNET_BUFFER_F_GSO))
193  {
194  /*
195  * We should not be getting GSO outbound traffic unless it is
196  * lro is enable
197  */
198  ASSERT (vd->gso_enable == 1);
199  gso_size = vnet_buffer2 (b0)->gso_size;
200  l4_hdr_sz = vnet_buffer2 (b0)->gso_l4_hdr_sz;
201  if (b0->flags & VNET_BUFFER_F_IS_IP6)
202  hdr_len = sizeof (ethernet_header_t) + sizeof (ip6_header_t) +
203  l4_hdr_sz;
204  else
205  hdr_len = sizeof (ethernet_header_t) + sizeof (ip4_header_t) +
206  l4_hdr_sz;
207  }
208 
209  generation = txq->tx_ring.gen;
210  bi0 = b0->next_buffer;
211  }
212  if (PREDICT_FALSE (gso_size != 0))
213  {
214  txq->tx_desc[first_idx].flags[1] = hdr_len;
215  txq->tx_desc[first_idx].flags[1] |= VMXNET3_TXF_OM (VMXNET3_OM_TSO);
216  txq->tx_desc[first_idx].flags[0] |= VMXNET3_TXF_MSSCOF (gso_size);
217  }
218  txd->flags[1] |= VMXNET3_TXF_CQ | VMXNET3_TXF_EOP;
219  asm volatile ("":::"memory");
220  /*
221  * Now toggle back the generation bit for the first segment.
222  * Device can start reading the packet
223  */
224  txq->tx_desc[first_idx].flags[0] ^= VMXNET3_TXF_GEN;
225 
226  buffers++;
227  n_left--;
228  }
229 
230  if (PREDICT_TRUE (produce != txq->tx_ring.produce))
232 
233  if (tf->shared_queue)
234  clib_spinlock_unlock (&txq->lock);
235 
236  return (frame->n_vectors - n_left);
237 }
238 
239 /*
240  * fd.io coding-style-patch-verification: ON
241  *
242  * Local Variables:
243  * eval: (c-set-style "gnu")
244  * End:
245  */
vmxnet3_main
vmxnet3_main_t vmxnet3_main
Definition: vmxnet3.c:29
vlib.h
vlib_buffer_t::next_buffer
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:149
vlib_buffer_free
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:979
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
vlib_buffer_get_current_pa
static uword vlib_buffer_get_current_pa(vlib_main_t *vm, vlib_buffer_t *b)
Definition: buffer_funcs.h:494
vmxnet3_txq_t::lock
clib_spinlock_t lock
Definition: vmxnet3.h:555
vlib_get_buffer
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
vmxnet3_txq_t::tx_comp
vmxnet3_tx_comp * tx_comp
Definition: vmxnet3.h:558
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:549
vmxnet3_tx_comp_ring
Definition: vmxnet3.h:542
vmxnet3_reg_write_inline
static_always_inline void vmxnet3_reg_write_inline(vmxnet3_device_t *vd, u8 bar, u32 addr, u32 val)
Definition: vmxnet3.h:656
vmxnet3_tx_ring_advance_produce
static_always_inline void vmxnet3_tx_ring_advance_produce(vmxnet3_txq_t *txq)
Definition: output.c:42
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
vnet_hw_if_tx_frame_t::shared_queue
u8 shared_queue
Definition: interface.h:624
u16
unsigned short u16
Definition: types.h:57
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
vnet_hw_if_tx_frame_t::queue_id
u32 queue_id
Definition: interface.h:626
vmxnet3_main_t
Definition: vmxnet3.h:599
vnet_buffer2
#define vnet_buffer2(b)
Definition: buffer.h:505
vlib_error_count
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:57
vlib_frame_t
Definition: node.h:372
ip4_header_t
Definition: ip4_packet.h:87
ethernet.h
vmxnet3_device_class
VNET_DEVICE_CLASS_TX_FN() vmxnet3_device_class(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: output.c:98
VNET_DEVICE_CLASS_TX_FN
#define VNET_DEVICE_CLASS_TX_FN(devclass)
Definition: interface.h:317
ip6_packet.h
count
u8 count
Definition: dhcp.api:208
VMXNET3_TXC_INDEX
#define VMXNET3_TXC_INDEX
Definition: vmxnet3.h:156
vmxnet3_tx_ring_space_left
static_always_inline u16 vmxnet3_tx_ring_space_left(vmxnet3_txq_t *txq)
Definition: output.c:87
vnet_interface_output_runtime_t::dev_instance
u32 dev_instance
Definition: interface_funcs.h:479
VMXNET3_TXF_OM
#define VMXNET3_TXF_OM(x)
Definition: vmxnet3.h:149
vec_elt_at_index
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Definition: vec_bootstrap.h:203
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
vlib_frame_vector_args
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
clib_spinlock_lock
static_always_inline void clib_spinlock_lock(clib_spinlock_t *p)
Definition: lock.h:82
vmxnet3_txq_t::tx_comp_ring
vmxnet3_tx_comp_ring tx_comp_ring
Definition: vmxnet3.h:560
static_always_inline
#define static_always_inline
Definition: clib.h:112
ethernet_header_t
Definition: packet.h:52
vmxnet3_tx_ring::produce
u16 produce
Definition: vmxnet3.h:538
vlib_buffer_t::current_length
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:122
vlib_frame_scalar_args
static void * vlib_frame_scalar_args(vlib_frame_t *f)
Get pointer to frame scalar data.
Definition: node_funcs.h:315
tf
vnet_hw_if_tx_frame_t * tf
Definition: interface_output.c:1091
vmxnet3_tx_comp_ring::gen
u32 gen
Definition: vmxnet3.h:545
ip4_packet.h
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
VMXNET3_TXF_GEN
#define VMXNET3_TXF_GEN
Definition: vmxnet3.h:146
VMXNET3_TXF_CQ
#define VMXNET3_TXF_CQ
Definition: vmxnet3.h:152
vmxnet3_txq_t::tx_ring
vmxnet3_tx_ring tx_ring
Definition: vmxnet3.h:559
vmxnet3_tx_comp_ring::next
u16 next
Definition: vmxnet3.h:546
u32
unsigned int u32
Definition: types.h:88
vmxnet3_txq_t
Definition: vmxnet3.h:549
pci.h
n_left
u32 n_left
Definition: interface_output.c:1096
vmxnet3_tx_ring::bufs
u32 * bufs
Definition: vmxnet3.h:536
vmxnet3_tx_comp_ring_advance_next
static_always_inline void vmxnet3_tx_comp_ring_advance_next(vmxnet3_txq_t *txq)
Definition: output.c:29
clib_spinlock_unlock
static_always_inline void clib_spinlock_unlock(clib_spinlock_t *p)
Definition: lock.h:121
ip6_header_t
Definition: ip6_packet.h:294
VMXNET3_TXCF_GEN
#define VMXNET3_TXCF_GEN
Definition: vmxnet3.h:155
vlib_main_t
Definition: main.h:102
VMXNET3_TXF_EOP
#define VMXNET3_TXF_EOP
Definition: vmxnet3.h:151
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
unix.h
i
int i
Definition: flowhash_template.h:376
VMXNET3_TXF_MSSCOF
#define VMXNET3_TXF_MSSCOF(x)
Definition: vmxnet3.h:150
vmxnet3_txq_t::tx_desc
vmxnet3_tx_desc * tx_desc
Definition: vmxnet3.h:557
devices.h
vlib_buffer_free_one
static void vlib_buffer_free_one(vlib_main_t *vm, u32 buffer_index)
Free one buffer Shorthand to free a single buffer chain.
Definition: buffer_funcs.h:1012
vmxnet3_tx_ring_advance_consume
static_always_inline void vmxnet3_tx_ring_advance_consume(vmxnet3_txq_t *txq)
Definition: output.c:53
vlib_node_runtime_t
Definition: node.h:454
vmxnet3_txq_t::reg_txprod
u32 reg_txprod
Definition: vmxnet3.h:554
PREDICT_TRUE
#define PREDICT_TRUE(x)
Definition: clib.h:125
vmxnet3_txq_t::size
u16 size
Definition: vmxnet3.h:552
vmxnet3_device_t
Definition: vmxnet3.h:563
vmxnet3_tx_ring::gen
u32 gen
Definition: vmxnet3.h:537
vmxnet3_main_t::devices
vmxnet3_device_t * devices
Definition: vmxnet3.h:601
vmxnet3_txq_release
static_always_inline void vmxnet3_txq_release(vlib_main_t *vm, vmxnet3_device_t *vd, vmxnet3_txq_t *txq)
Definition: output.c:60
vmxnet3.h
vnet_hw_if_tx_frame_t
Definition: interface.h:622
vlib_buffer_t::flags
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
Definition: buffer.h:133
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
vnet_interface_output_runtime_t
Definition: interface_funcs.h:475
vmxnet3_tx_ring::consume
u16 consume
Definition: vmxnet3.h:539