FD.io VPP  v18.10-34-gcce845e
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 
24 #include <vmxnet3/vmxnet3.h>
25 
28 {
29  vmxnet3_tx_comp_ring *comp_ring = &txq->tx_comp_ring;
30 
31  comp_ring->next++;
32  if (PREDICT_FALSE (comp_ring->next == txq->size))
33  {
34  comp_ring->next = 0;
35  comp_ring->gen ^= VMXNET3_TXCF_GEN;
36  }
37 }
38 
41 {
42  txq->tx_ring.produce++;
43  if (PREDICT_FALSE (txq->tx_ring.produce == txq->size))
44  {
45  txq->tx_ring.produce = 0;
46  txq->tx_ring.gen ^= VMXNET3_TXF_GEN;
47  }
48 }
49 
52 {
53  txq->tx_ring.consume++;
54  txq->tx_ring.consume &= txq->size - 1;
55 }
56 
59  vmxnet3_txq_t * txq)
60 {
61  vmxnet3_tx_comp *tx_comp;
62  vmxnet3_tx_comp_ring *comp_ring;
63 
64  comp_ring = &txq->tx_comp_ring;
65  tx_comp = &txq->tx_comp[comp_ring->next];
66 
67  while ((tx_comp->flags & VMXNET3_TXCF_GEN) == comp_ring->gen)
68  {
69  u16 eop_idx = tx_comp->index & VMXNET3_TXC_INDEX;
70  u32 bi0 = txq->tx_ring.bufs[txq->tx_ring.consume];
71 
72  vlib_buffer_free_one (vm, bi0);
73  while (txq->tx_ring.consume != eop_idx)
74  {
76  }
78 
80  tx_comp = &txq->tx_comp[comp_ring->next];
81  }
82 }
83 
86 {
87  u16 count;
88 
89  count = (txq->tx_ring.consume - txq->tx_ring.produce - 1);
90  /* Wrapped? */
91  if (txq->tx_ring.produce >= txq->tx_ring.consume)
92  count += txq->size;
93  return count;
94 }
95 
97  vlib_node_runtime_t * node,
98  vlib_frame_t * frame)
99 {
100  vmxnet3_main_t *vmxm = &vmxnet3_main;
101  vnet_interface_output_runtime_t *rd = (void *) node->runtime_data;
103  u32 *buffers = vlib_frame_args (frame);
104  u32 bi0;
105  vlib_buffer_t *b0;
106  vmxnet3_tx_desc *txd = 0;
107  u32 desc_idx, generation, first_idx;
108  u16 space_left;
109  u16 n_left = frame->n_vectors;
110  vmxnet3_txq_t *txq;
111  u32 thread_index = vm->thread_index;
112  u16 qid = thread_index;
113 
114  if (PREDICT_FALSE (!(vd->flags & VMXNET3_DEVICE_F_LINK_UP)))
115  {
116  vlib_buffer_free (vm, buffers, n_left);
117  vlib_error_count (vm, node->node_index, VMXNET3_TX_ERROR_LINK_DOWN,
118  n_left);
119  return (0);
120  }
121 
122  txq = vec_elt_at_index (vd->txqs, qid % vd->num_tx_queues);
124 
125  vmxnet3_txq_release (vm, vd, txq);
126 
127  while (n_left)
128  {
129  u16 space_needed = 1, i;
130  vlib_buffer_t *b;
131 
132  bi0 = buffers[0];
133  b0 = vlib_get_buffer (vm, bi0);
134  b = b0;
135 
136  space_left = vmxnet3_tx_ring_space_left (txq);
137  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
138  {
139  u32 next_buffer = b->next_buffer;
140 
141  b = vlib_get_buffer (vm, next_buffer);
142  space_needed++;
143  }
144  if (PREDICT_FALSE (space_left < space_needed))
145  {
146  vmxnet3_txq_release (vm, vd, txq);
147  space_left = vmxnet3_tx_ring_space_left (txq);
148 
149  if (PREDICT_FALSE (space_left < space_needed))
150  {
151  vlib_buffer_free_one (vm, bi0);
152  vlib_error_count (vm, node->node_index,
153  VMXNET3_TX_ERROR_NO_FREE_SLOTS, 1);
154  buffers++;
155  n_left--;
156  /*
157  * Drop this packet. But we may have enough room for the next
158  * packet
159  */
160  continue;
161  }
162  }
163 
164  /*
165  * Toggle the generation bit for SOP fragment to avoid device starts
166  * reading incomplete packet
167  */
168  generation = txq->tx_ring.gen ^ VMXNET3_TXF_GEN;
169  first_idx = txq->tx_ring.produce;
170  for (i = 0; i < space_needed; i++)
171  {
172  b0 = vlib_get_buffer (vm, bi0);
174 
175  desc_idx = txq->tx_ring.produce;
176 
178  txq->tx_ring.bufs[desc_idx] = bi0;
179 
180  txd = &txq->tx_desc[desc_idx];
181  txd->address =
183  bi0) + b0->current_data;
184 
185  txd->flags[0] = generation | b0->current_length;
186 
187  generation = txq->tx_ring.gen;
188 
189  txd->flags[1] = 0;
190  bi0 = b0->next_buffer;
191  }
192 
193  txd->flags[1] = VMXNET3_TXF_CQ | VMXNET3_TXF_EOP;
194  asm volatile ("":::"memory");
195  /*
196  * Now toggle back the generation bit for the first segment.
197  * Device can start reading the packet
198  */
199  txq->tx_desc[first_idx].flags[0] ^= VMXNET3_TXF_GEN;
201  txq->tx_ring.produce);
202 
203  buffers++;
204  n_left--;
205  }
206 
208 
209  return (frame->n_vectors - n_left);
210 }
211 
212 /*
213  * fd.io coding-style-patch-verification: ON
214  *
215  * Local Variables:
216  * eval: (c-set-style "gnu")
217  * End:
218  */
static_always_inline void vmxnet3_tx_ring_advance_consume(vmxnet3_txq_t *txq)
Definition: output.c:51
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:547
#define VMXNET3_REG_TXPROD
Definition: vmxnet3.h:62
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:57
clib_spinlock_t lock
Definition: vmxnet3.h:448
static_always_inline void clib_spinlock_unlock_if_init(clib_spinlock_t *p)
Definition: lock.h:98
u32 thread_index
Definition: main.h:179
vmxnet3_main_t vmxnet3_main
Definition: vmxnet3.c:28
int i
static u64 vlib_get_buffer_data_physical_address(vlib_main_t *vm, u32 buffer_index)
Definition: buffer_funcs.h:319
VNET_DEVICE_CLASS_TX_FN() vmxnet3_device_class(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: output.c:96
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:109
#define static_always_inline
Definition: clib.h:95
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define VNET_DEVICE_CLASS_TX_FN(devclass)
Definition: interface.h:286
unsigned int u32
Definition: types.h:88
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:464
#define VMXNET3_TXC_INDEX
Definition: vmxnet3.h:93
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
static_always_inline u16 vmxnet3_tx_ring_space_left(vmxnet3_txq_t *txq)
Definition: output.c:85
unsigned short u16
Definition: types.h:57
static_always_inline void vmxnet3_tx_ring_advance_produce(vmxnet3_txq_t *txq)
Definition: output.c:40
vmxnet3_tx_comp_ring tx_comp_ring
Definition: vmxnet3.h:453
vmxnet3_tx_comp * tx_comp
Definition: vmxnet3.h:451
#define PREDICT_FALSE(x)
Definition: clib.h:107
#define VMXNET3_TXF_CQ
Definition: vmxnet3.h:91
#define VMXNET3_TXF_GEN
Definition: vmxnet3.h:89
vlib_main_t * vm
Definition: buffer.c:294
static_always_inline void vmxnet3_txq_release(vlib_main_t *vm, vmxnet3_device_t *vd, vmxnet3_txq_t *txq)
Definition: output.c:58
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:129
#define VMXNET3_TXCF_GEN
Definition: vmxnet3.h:92
static void * vlib_frame_args(vlib_frame_t *f)
Get pointer to frame scalar data.
Definition: node_funcs.h:284
size_t count
Definition: vapi.c:46
#define VMXNET3_TXF_EOP
Definition: vmxnet3.h:90
static_always_inline void vmxnet3_tx_comp_ring_advance_next(vmxnet3_txq_t *txq)
Definition: output.c:27
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:547
vmxnet3_tx_desc * tx_desc
Definition: vmxnet3.h:450
vmxnet3_device_t * devices
Definition: vmxnet3.h:495
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:588
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:116
vmxnet3_tx_ring tx_ring
Definition: vmxnet3.h:452
static_always_inline void clib_spinlock_lock_if_init(clib_spinlock_t *p)
Definition: lock.h:82
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:58
static_always_inline void vmxnet3_reg_write_inline(vmxnet3_device_t *vd, u8 bar, u32 addr, u32 val)
Definition: vmxnet3.h:547