FD.io VPP  v21.06
Vector Packet Processing
pp2.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 <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <sys/ioctl.h>
22 
23 #include <vlib/vlib.h>
24 #include <vlib/unix/unix.h>
25 #include <vppinfra/linux/syscall.h>
26 #include <vnet/plugin/plugin.h>
27 #include <marvell/pp2/pp2.h>
29 
30 /* size of DMA memory used by musdk (not used for buffers) */
31 #define MV_SYS_DMA_MEM_SZ (2 << 20)
32 /* number of HIFs reserved (first X) */
33 #define NUM_HIFS_RSVD 4
34 /* number of buffer pools reserved (first X) */
35 #define NUM_BPOOLS_RSVD 7
36 
39 
40 static void
42 {
44  int i;
46  {
48  i);
49  if (ptd->hif)
50  pp2_hif_deinit (ptd->hif);
51  vec_free (ptd->descs);
52  }
54  pp2_deinit ();
55  mv_sys_dma_mem_destroy ();
56 }
57 
58 static clib_error_t *
60 {
63  clib_error_t *err = 0;
64  struct pp2_init_params init_params = { 0 };
65  int i, rv;
66  u8 *s = 0;
67 
68  rv = mv_sys_dma_mem_init (MV_SYS_DMA_MEM_SZ);
69  if (rv)
70  return clib_error_return (0, "mv_sys_dma_mem_init failed, rv = %u", rv);
71 
72  init_params.hif_reserved_map = ((1 << NUM_HIFS_RSVD) - 1);
73  init_params.bm_pool_reserved_map = ((1 << NUM_BPOOLS_RSVD) - 1);
74  rv = pp2_init (&init_params);
75  if (rv)
76  {
77  err = clib_error_return (0, "mrvl_pp2_init failed, rv = %u", rv);
78  goto done;
79  }
80 
83 
85  {
87  i);
88  struct pp2_hif_params hif_params = { 0 };
89  vec_reset_length (s);
90  s = format (s, "hif-%d%c", NUM_HIFS_RSVD + i, 0);
91  hif_params.match = (char *) s;
92  hif_params.out_size = 2048; /* FIXME */
93  if (pp2_hif_init (&hif_params, &ptd->hif))
94  {
95  err = clib_error_return (0, "hif '%s' init failed", s);
96  goto done;
97  }
98  }
99 
100 done:
101  if (err)
103  vec_free (s);
104  return err;
105 }
106 
107 static u32
109  u32 flags)
110 {
111  /* nothing for now */
112  return 0;
113 }
114 
115 void
117 {
119  vnet_main_t *vnm = vnet_get_main ();
121  mrvl_pp2_outq_t *outq;
122  mrvl_pp2_inq_t *inq;
123 
124  if (ppif->hw_if_index != ~0)
126 
127  if (ppif->ppio)
128  {
129  pp2_ppio_disable (ppif->ppio);
130  pp2_ppio_deinit (ppif->ppio);
131  }
132 
133  /* *INDENT-OFF* */
134  /* free buffers hanging in the tx ring */
135  vec_foreach (outq, ppif->outqs)
136  {
137  while (outq->tail < outq->head)
138  {
139  u16 slot = outq->tail & (outq->size - 1);
140  vlib_buffer_free (vm, outq->buffers + slot, 1);
141  outq->tail++;
142  }
143  vec_free (outq->buffers);
144  }
145  vec_free (ppif->outqs);
146 
147  /* free buffers hangin in the rx buffer pool */
148  vec_foreach (inq, ppif->inqs)
149  if (inq->bpool)
150  {
151  u32 n_bufs = 0;
152  pp2_bpool_get_num_buffs (inq->bpool, &n_bufs);
153  while (n_bufs--)
154  {
155  struct pp2_buff_inf binf;
156  if (pp2_bpool_get_buff (ppm->per_thread_data[0].hif, inq->bpool,
157  &binf) == 0)
158  {
159  u32 bi = binf.cookie;
160  vlib_buffer_free (vm, &bi, 1);
161  }
162  }
163  pp2_bpool_deinit (inq->bpool);
164  }
165  vec_free (ppif->inqs);
166  /* *INDENT-ON* */
167 
168 
169  pool_put (ppm->interfaces, ppif);
170 
171  if (pool_elts (ppm->interfaces) == 0)
173 }
174 
175 void
177 {
179  vnet_main_t *vnm = vnet_get_main ();
182  struct pp2_bpool_params bpool_params = { 0 };
183  struct pp2_ppio_params ppio_params = { 0 };
184  struct pp2_ppio_inq_params inq_params = { 0 };
186  mrvl_pp2_if_t *ppif = 0;
187  u8 pp2_id, port_id, *s = 0;
188  eth_addr_t mac_addr;
189  u8 n_outqs, n_inqs = 1;
190  int i;
191 
192  if (tm->n_vlib_mains > PP2_PPIO_MAX_NUM_OUTQS)
193  {
194  args->rv = VNET_API_ERROR_INIT_FAILED;
195  args->error = clib_error_return (0, "number of threads (main + workers)"
196  " is bigger than number of output "
197  "queues (%u)", PP2_PPIO_MAX_NUM_OUTQS);
198  return;
199  }
200  n_outqs = tm->n_vlib_mains;
201 
202  /* defaults */
203  args->tx_q_sz = args->tx_q_sz ? args->tx_q_sz : 2 * VLIB_FRAME_SIZE;
204  args->rx_q_sz = args->rx_q_sz ? args->rx_q_sz : 2 * VLIB_FRAME_SIZE;
205 
206  if (vec_len (ppm->per_thread_data) == 0)
207  {
208  if ((args->error = mrvl_pp2_main_init ()) != 0)
209  {
210  args->rv = VNET_API_ERROR_INIT_FAILED;
211  return;
212  }
213  }
214 
215  pool_get_zero (ppm->interfaces, ppif);
216  ppif->dev_instance = ppif - ppm->interfaces;
217  ppif->hw_if_index = ~0;
218  vec_validate_aligned (ppif->inqs, n_inqs - 1, CLIB_CACHE_LINE_BYTES);
219  vec_validate_aligned (ppif->outqs, n_outqs - 1, CLIB_CACHE_LINE_BYTES);
220 
221  for (i = 0; i < n_inqs; i++)
222  {
223  mrvl_pp2_inq_t *inq = vec_elt_at_index (ppif->inqs, i);
224  inq->size = args->rx_q_sz;
225  }
226  for (i = 0; i < n_outqs; i++)
227  {
228  mrvl_pp2_outq_t *outq = vec_elt_at_index (ppif->outqs, i);
229  outq->size = args->tx_q_sz;
231  }
232 
233  if (pp2_netdev_get_ppio_info ((char *) args->name, &pp2_id, &port_id))
234  {
235  args->rv = VNET_API_ERROR_INVALID_INTERFACE;
236  args->error = clib_error_return (0, "Invalid interface '%s'",
237  args->name);
238  goto error;
239  }
240 
241  /* FIXME bpool bit select per pp */
242  s = format (s, "pool-%d:%d%c", pp2_id, pp2_id + 8, 0);
243  bpool_params.match = (char *) s;
244  bpool_params.buff_len = vlib_buffer_get_default_data_size (vm);
245  /* FIXME +64 ? */
246  if (pp2_bpool_init (&bpool_params, &ppif->inqs[0].bpool))
247  {
248  args->rv = VNET_API_ERROR_INIT_FAILED;
249  args->error = clib_error_return (0, "bpool '%s' init failed", s);
250  goto error;
251  }
252  vec_reset_length (s);
253 
254  s = format (s, "ppio-%d:%d%c", pp2_id, port_id, 0);
255  ppio_params.match = (char *) s;
256  ppio_params.type = PP2_PPIO_T_NIC;
257  inq_params.size = args->rx_q_sz;
258  ppio_params.inqs_params.num_tcs = 1;
259  ppio_params.inqs_params.tcs_params[0].pkt_offset = 0;
260  ppio_params.inqs_params.tcs_params[0].num_in_qs = n_inqs;
261  ppio_params.inqs_params.tcs_params[0].inqs_params = &inq_params;
262  ppio_params.inqs_params.tcs_params[0].pools[0][0] = ppif->inqs[0].bpool;
263  ppio_params.outqs_params.num_outqs = n_outqs;
264  for (i = 0; i < n_outqs; i++)
265  {
266  ppio_params.outqs_params.outqs_params[i].weight = 1;
267  ppio_params.outqs_params.outqs_params[i].size = args->tx_q_sz;
268  }
269  if (pp2_ppio_init (&ppio_params, &ppif->ppio))
270  {
271  args->rv = VNET_API_ERROR_INIT_FAILED;
272  args->error = clib_error_return (0, "ppio '%s' init failed", s);
273  goto error;
274  }
275  vec_reset_length (s);
276 
277  if (pp2_ppio_get_mac_addr (ppif->ppio, mac_addr))
278  {
279  args->rv = VNET_API_ERROR_INIT_FAILED;
280  args->error =
281  clib_error_return (0, "%s: pp2_ppio_get_mac_addr failed", s);
282  goto error;
283  }
284 
286  ppif->dev_instance,
287  mac_addr,
288  &ppif->hw_if_index,
290  if (args->error)
291  {
292  args->rv = VNET_API_ERROR_INVALID_REGISTRATION;
293  goto error;
294  }
295 
296  sw = vnet_get_hw_sw_interface (vnm, ppif->hw_if_index);
297  ppif->sw_if_index = sw->sw_if_index;
298  ppif->per_interface_next_index = ~0;
299  args->sw_if_index = sw->sw_if_index;
301  mrvl_pp2_input_node.index);
302  /* FIXME: only one RX queue ? */
304  vnm, ppif->hw_if_index, 0, VNET_HW_IF_RXQ_THREAD_ANY);
305 
311  goto done;
312 
313 error:
314  mrvl_pp2_delete_if (ppif);
315 done:
316  vec_free (s);
317 }
318 
319 static clib_error_t *
321  u32 flags)
322 {
324  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
326  static clib_error_t *error = 0;
327  int is_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
328  int rv;
329 
330  if (is_up)
331  rv = pp2_ppio_enable (ppif->ppio);
332  else
333  rv = pp2_ppio_disable (ppif->ppio);
334 
335  if (rv)
336  return clib_error_return (0, "failed to %s interface",
337  is_up ? "enable" : "disable");
338 
339  if (is_up)
340  ppif->flags |= MRVL_PP2_IF_F_ADMIN_UP;
341  else
342  ppif->flags &= ~MRVL_PP2_IF_F_ADMIN_UP;
343 
344  return error;
345 }
346 
347 static void
349 {
351  mrvl_pp2_if_t *ppif = pool_elt_at_index (ppm->interfaces, instance);
352  struct pp2_ppio_statistics stats;
353 
354  pp2_ppio_get_statistics (ppif->ppio, &stats, 1);
355 }
356 
357 static void
359  u32 node_index)
360 {
362  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
364 
365  /* Shut off redirection */
366  if (node_index == ~0)
367  {
369  return;
370  }
371 
374  node_index);
375 }
376 
378 #define _(n,s) s,
380 #undef _
381 };
382 
383 /* *INDENT-OFF* */
385 {
386  .name = "Marvell PPv2 interface",
387  .format_device_name = format_mrvl_pp2_interface_name,
388  .format_device = format_mrvl_pp2_interface,
389  .tx_function = mrvl_pp2_interface_tx,
390  .tx_function_n_errors = MRVL_PP2_TX_N_ERROR,
391  .tx_function_error_strings = mrvl_pp2_tx_func_error_strings,
392  .admin_up_down_function = mrvl_pp2_interface_admin_up_down,
393  .clear_counters = mrvl_pp2_clear_interface_counters,
394  .rx_redirect_to_node = mrvl_pp2_set_interface_next_node,
395 };
396 /* *INDENT-ON* */
397 
398 static clib_error_t *
400 {
401  return 0;
402 }
403 
405 
406 /*
407  * fd.io coding-style-patch-verification: ON
408  *
409  * Local Variables:
410  * eval: (c-set-style "gnu")
411  * End:
412  */
struct pp2_ppio * ppio
Definition: pp2.h:56
static u32 mrvl_pp2_eth_flag_change(vnet_main_t *vnm, vnet_hw_interface_t *hi, u32 flags)
Definition: pp2.c:108
mrvl_pp2_outq_t * outqs
Definition: pp2.h:60
#define vec_foreach_index(var, v)
Iterate over vector indices.
#define NUM_BPOOLS_RSVD
Definition: pp2.c:35
u32 dev_instance
Definition: pp2.h:62
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
u16 head
Definition: pp2.h:47
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:982
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:393
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:258
struct pp2_ppio_desc * descs
Definition: pp2.h:73
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 per_interface_next_index
Definition: pp2.h:57
mrvl_pp2_main_t mrvl_pp2_main
Definition: pp2.c:37
vnet_device_class_t mrvl_pp2_device_class
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:535
#define MV_SYS_DMA_MEM_SZ
Definition: pp2.c:31
static clib_error_t * mrvl_pp2_main_init()
Definition: pp2.c:59
struct _vnet_device_class vnet_device_class_t
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags)
Definition: interface.c:513
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1177
unsigned char u8
Definition: types.h:56
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
u32 hw_if_index
Definition: pp2.h:64
static vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)
unsigned int u32
Definition: types.h:88
static clib_error_t * mrvl_pp2_init(vlib_main_t *vm)
Definition: pp2.c:399
struct pp2_bpool * bpool
Definition: pp2.h:39
static char * mrvl_pp2_tx_func_error_strings[]
Definition: pp2.c:377
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
#define foreach_mrvl_pp2_tx_func_error
Definition: pp2.h:108
format_function_t format_mrvl_pp2_interface
Definition: pp2.h:137
description fragment has unexpected format
Definition: map.api:433
u32 sw_if_index
Definition: pp2.h:63
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define clib_error_return(e, args...)
Definition: error.h:99
vnet_main_t * vnet_get_main(void)
u16 size
Definition: pp2.h:45
int __clib_unused rv
Definition: application.c:491
#define VLIB_FRAME_SIZE
Definition: node.h:369
struct pp2_hif * hif
Definition: pp2.h:72
Definition: cJSON.c:88
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
u32 vnet_hw_if_register_rx_queue(vnet_main_t *vnm, u32 hw_if_index, u32 queue_id, u32 thread_index)
Definition: rx_queue.c:64
unsigned short u16
Definition: types.h:57
static clib_error_t * mrvl_pp2_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: pp2.c:320
u32 flags
Definition: pp2.h:54
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
u32 queue_index
Definition: pp2.h:38
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
void vnet_hw_if_update_runtime_data(vnet_main_t *vnm, u32 hw_if_index)
Definition: runtime.c:58
vlib_node_registration_t mrvl_pp2_input_node
(constructor) VLIB_REGISTER_NODE (mrvl_pp2_input_node)
Definition: input.c:374
static_always_inline u32 vlib_buffer_get_default_data_size(vlib_main_t *vm)
Definition: buffer_funcs.h:122
VNET_DEVICE_CLASS(mrvl_pp2_device_class,)
int vnet_hw_if_set_rx_queue_mode(vnet_main_t *vnm, u32 queue_index, vnet_hw_if_rx_mode mode)
Definition: rx_queue.c:167
u8 slot
Definition: pci_types.api:22
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:395
u32 * buffers
Definition: pp2.h:46
void mrvl_pp2_delete_if(mrvl_pp2_if_t *ppif)
Definition: pp2.c:116
#define NUM_HIFS_RSVD
Definition: pp2.c:33
static void mrvl_pp2_clear_interface_counters(u32 instance)
Definition: pp2.c:348
void mrvl_pp2_create_if(mrvl_pp2_create_if_args_t *args)
Definition: pp2.c:176
u16 tail
Definition: pp2.h:48
static void mrvl_pp2_set_interface_next_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: pp2.c:358
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
vl_api_ip4_address_t hi
Definition: arp.api:37
void vnet_hw_if_set_input_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: rx_queue.c:157
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
clib_error_t * ethernet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, const u8 *address, u32 *hw_if_index_return, ethernet_flag_change_function_t flag_change)
Definition: interface.c:348
vl_api_mac_address_t mac_addr
Definition: l2.api:210
u32 instance
Definition: gre.api:51
format_function_t format_mrvl_pp2_interface_name
Definition: pp2.h:138
node node_index
uword mrvl_pp2_interface_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: output.c:31
clib_error_t * error
Definition: pp2.h:99
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:56
#define vec_foreach(var, vec)
Vector iterator.
mrvl_pp2_if_t * interfaces
Definition: pp2.h:80
mrvl_pp2_per_thread_data_t * per_thread_data
Definition: pp2.h:81
static void mrvl_pp2_main_deinit()
Definition: pp2.c:41
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
mrvl_pp2_inq_t * inqs
Definition: pp2.h:59
vnet_device_class_t ppa2_device_class
#define VNET_HW_IF_RXQ_THREAD_ANY
Definition: interface.h:598
#define MRVL_PP2_IF_F_ADMIN_UP
Definition: pp2.h:55
u16 size
Definition: pp2.h:37
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127