FD.io VPP  v18.07-rc0-415-g6c78436
Vector Packet Processing
device.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2016 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 <stdint.h>
19 #include <net/if.h>
20 #include <sys/ioctl.h>
21 
22 #include <vlib/vlib.h>
23 #include <vlib/unix/unix.h>
24 #include <vnet/ethernet/ethernet.h>
25 
28 
29 #define foreach_netmap_tx_func_error \
30 _(NO_FREE_SLOTS, "no free tx slots") \
31 _(PENDING_MSGS, "pending msgs in tx ring")
32 
33 typedef enum
34 {
35 #define _(f,s) NETMAP_TX_ERROR_##f,
37 #undef _
40 
41 static char *netmap_tx_func_error_strings[] = {
42 #define _(n,s) s,
44 #undef _
45 };
46 
47 
48 static u8 *
49 format_netmap_device_name (u8 * s, va_list * args)
50 {
51  u32 i = va_arg (*args, u32);
52  netmap_main_t *apm = &netmap_main;
53  netmap_if_t *nif = pool_elt_at_index (apm->interfaces, i);
54 
55  s = format (s, "netmap-%s", nif->host_if_name);
56  return s;
57 }
58 
59 static u8 *
60 format_netmap_device (u8 * s, va_list * args)
61 {
62  u32 dev_instance = va_arg (*args, u32);
63  int verbose = va_arg (*args, int);
65  netmap_if_t *nif = vec_elt_at_index (nm->interfaces, dev_instance);
66  u32 indent = format_get_indent (s);
67 
68  s = format (s, "NETMAP interface");
69  if (verbose)
70  {
71  s = format (s, "\n%U version %d flags 0x%x"
72  "\n%U region %u memsize 0x%x offset 0x%x"
73  "\n%U tx_slots %u rx_slots %u tx_rings %u rx_rings %u",
74  format_white_space, indent + 2,
75  nif->req->nr_version,
76  nif->req->nr_flags,
77  format_white_space, indent + 2,
78  nif->mem_region,
79  nif->req->nr_memsize,
80  nif->req->nr_offset,
81  format_white_space, indent + 2,
82  nif->req->nr_tx_slots,
83  nif->req->nr_rx_slots,
84  nif->req->nr_tx_rings, nif->req->nr_rx_rings);
85  }
86  return s;
87 }
88 
89 static u8 *
90 format_netmap_tx_trace (u8 * s, va_list * args)
91 {
92  s = format (s, "Unimplemented...");
93  return s;
94 }
95 
96 static uword
98  vlib_node_runtime_t * node, vlib_frame_t * frame)
99 {
100  netmap_main_t *nm = &netmap_main;
101  u32 *buffers = vlib_frame_args (frame);
102  u32 n_left = frame->n_vectors;
103  f64 const time_constant = 1e3;
104  vnet_interface_output_runtime_t *rd = (void *) node->runtime_data;
106  int cur_ring;
107 
108  clib_spinlock_lock_if_init (&nif->lockp);
109 
110  cur_ring = nif->first_tx_ring;
111 
112  while (n_left && cur_ring <= nif->last_tx_ring)
113  {
114  struct netmap_ring *ring = NETMAP_TXRING (nif->nifp, cur_ring);
115  int n_free_slots = nm_ring_space (ring);
116  uint cur = ring->cur;
117 
118  if (nm_tx_pending (ring))
119  {
120  if (ioctl (nif->fd, NIOCTXSYNC, NULL) < 0)
121  clib_unix_warning ("NIOCTXSYNC");
122  clib_cpu_time_wait (time_constant);
123 
124  if (nm_tx_pending (ring) && !n_free_slots)
125  {
126  cur_ring++;
127  continue;
128  }
129  }
130 
131  while (n_left && n_free_slots)
132  {
133  vlib_buffer_t *b0 = 0;
134  u32 bi = buffers[0];
135  u32 len;
136  u32 offset = 0;
137  buffers++;
138 
139  struct netmap_slot *slot = &ring->slot[cur];
140 
141  do
142  {
143  b0 = vlib_get_buffer (vm, bi);
144  len = b0->current_length;
145  /* memcpy */
146  clib_memcpy ((u8 *) NETMAP_BUF (ring, slot->buf_idx) + offset,
147  vlib_buffer_get_current (b0), len);
148  offset += len;
149  }
150  while ((bi = b0->next_buffer));
151 
152  slot->len = offset;
153  cur = (cur + 1) % ring->num_slots;
154  n_free_slots--;
155  n_left--;
156  }
158  ring->head = ring->cur = cur;
159  }
160 
161  if (n_left < frame->n_vectors)
162  ioctl (nif->fd, NIOCTXSYNC, NULL);
163 
164  clib_spinlock_unlock_if_init (&nif->lockp);
165 
166  if (n_left)
167  vlib_error_count (vm, node->node_index,
168  (n_left ==
169  frame->n_vectors ? NETMAP_TX_ERROR_PENDING_MSGS :
170  NETMAP_TX_ERROR_NO_FREE_SLOTS), n_left);
171 
172  vlib_buffer_free (vm, vlib_frame_args (frame), frame->n_vectors);
173  return frame->n_vectors;
174 }
175 
176 static void
178  u32 node_index)
179 {
180  netmap_main_t *apm = &netmap_main;
181  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
183 
184  /* Shut off redirection */
185  if (node_index == ~0)
186  {
187  nif->per_interface_next_index = node_index;
188  return;
189  }
190 
193  node_index);
194 }
195 
196 static void
198 {
199  /* Nothing for now */
200 }
201 
202 static clib_error_t *
204 {
205  netmap_main_t *apm = &netmap_main;
206  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
208  u32 hw_flags;
209 
210  nif->is_admin_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
211 
212  if (nif->is_admin_up)
214  else
215  hw_flags = 0;
216 
217  vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
218 
219  return 0;
220 }
221 
222 static clib_error_t *
224  u32 hw_if_index,
225  struct vnet_sw_interface_t *st, int is_add)
226 {
227  /* Nothing for now */
228  return 0;
229 }
230 
231 /* *INDENT-OFF* */
233  .name = "netmap",
234  .tx_function = netmap_interface_tx,
235  .format_device_name = format_netmap_device_name,
236  .format_device = format_netmap_device,
237  .format_tx_trace = format_netmap_tx_trace,
238  .tx_function_n_errors = NETMAP_TX_N_ERROR,
239  .tx_function_error_strings = netmap_tx_func_error_strings,
240  .rx_redirect_to_node = netmap_set_interface_next_node,
241  .clear_counters = netmap_clear_hw_interface_counters,
242  .admin_up_down_function = netmap_interface_admin_up_down,
243  .subif_add_del_function = netmap_subif_add_del_function,
244 };
245 
248 /* *INDENT-ON* */
249 
250 /*
251  * fd.io coding-style-patch-verification: ON
252  *
253  * Local Variables:
254  * eval: (c-set-style "gnu")
255  * End:
256  */
struct netmap_slot slot[0]
Definition: net_netmap.h:287
const uint32_t num_slots
Definition: net_netmap.h:266
uint32_t nr_rx_slots
Definition: net_netmap.h:480
uint16_t nr_rx_rings
Definition: net_netmap.h:482
uint32_t nr_offset
Definition: net_netmap.h:477
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:541
netmap_if_t * interfaces
Definition: netmap.h:80
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:534
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:500
static void clib_cpu_time_wait(u64 dt)
Definition: time.h:209
uint16_t nr_tx_rings
Definition: net_netmap.h:481
static u8 * format_netmap_device_name(u8 *s, va_list *args)
Definition: device.c:49
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:57
#define NULL
Definition: clib.h:55
uint32_t cur
Definition: net_netmap.h:272
uint32_t nr_tx_slots
Definition: net_netmap.h:479
static_always_inline void clib_spinlock_unlock_if_init(clib_spinlock_t *p)
Definition: lock.h:98
uint32_t nr_memsize
Definition: net_netmap.h:478
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
static u8 * format_netmap_tx_trace(u8 *s, va_list *args)
Definition: device.c:90
int i
static u32 format_get_indent(u8 *s)
Definition: format.h:72
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:458
#define NIOCTXSYNC
Definition: net_netmap.h:596
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1110
unsigned char u8
Definition: types.h:56
uint16_t len
Definition: net_netmap.h:147
static void netmap_set_interface_next_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: device.c:177
double f64
Definition: types.h:142
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
static clib_error_t * netmap_subif_add_del_function(vnet_main_t *vnm, u32 hw_if_index, struct vnet_sw_interface_t *st, int is_add)
Definition: device.c:223
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
u32 per_interface_next_index
Definition: netmap.h:55
unsigned int u32
Definition: types.h:88
struct nmreq * req
Definition: netmap.h:59
static uword netmap_interface_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: device.c:97
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:461
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:108
static u8 * format_netmap_device(u8 *s, va_list *args)
Definition: device.c:60
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:202
uint32_t nr_version
Definition: net_netmap.h:476
uint32_t buf_idx
Definition: net_netmap.h:146
u32 node_index
Node index.
Definition: node.h:473
netmap_tx_func_error_t
Definition: device.c:33
#define foreach_netmap_tx_func_error
Definition: device.c:29
u16 n_vectors
Definition: node.h:380
vlib_main_t * vm
Definition: buffer.c:294
uint32_t head
Definition: net_netmap.h:271
#define clib_memcpy(a, b, c)
Definition: string.h:75
static char * netmap_tx_func_error_strings[]
Definition: device.c:41
static clib_error_t * netmap_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: device.c:203
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:660
vlib_node_registration_t netmap_input_node
(constructor) VLIB_REGISTER_NODE (netmap_input_node)
Definition: node.c:280
u16 mem_region
Definition: netmap.h:60
u8 * host_if_name
Definition: netmap.h:49
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:126
static void * vlib_frame_args(vlib_frame_t *f)
Get pointer to frame scalar data.
Definition: node_funcs.h:284
VNET_DEVICE_CLASS(bond_dev_class)
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
template key/value backing page structure
Definition: bihash_doc.h:44
u8 is_admin_up
Definition: netmap.h:56
vnet_device_class_t netmap_device_class
u64 uword
Definition: types.h:112
#define clib_unix_warning(format, args...)
Definition: error.h:68
struct clib_bihash_value offset
template key/value backing page structure
static void netmap_clear_hw_interface_counters(u32 instance)
Definition: device.c:197
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:109
netmap_main_t netmap_main
Definition: netmap.c:30
u32 flags
Definition: vhost-user.h:77
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:57
uint32_t nr_flags
Definition: net_netmap.h:513
#define VLIB_DEVICE_TX_FUNCTION_MULTIARCH(dev, fn)
Definition: interface.h:283