FD.io VPP  v16.09
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  uword 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  if (PREDICT_FALSE (nif->lockp != 0))
109  {
110  while (__sync_lock_test_and_set (nif->lockp, 1))
111  ;
112  }
113 
114  cur_ring = nif->first_tx_ring;
115 
116  while (n_left && cur_ring <= nif->last_tx_ring)
117  {
118  struct netmap_ring *ring = NETMAP_TXRING (nif->nifp, cur_ring);
119  int n_free_slots = nm_ring_space (ring);
120  uint cur = ring->cur;
121 
122  if (nm_tx_pending (ring))
123  {
124  if (ioctl (nif->fd, NIOCTXSYNC, NULL) < 0)
125  clib_unix_warning ("NIOCTXSYNC");
126  clib_cpu_time_wait (time_constant);
127 
128  if (nm_tx_pending (ring) && !n_free_slots)
129  {
130  cur_ring++;
131  continue;
132  }
133  }
134 
135  while (n_left && n_free_slots)
136  {
137  vlib_buffer_t *b0 = 0;
138  u32 bi = buffers[0];
139  u32 len;
140  u32 offset = 0;
141  buffers++;
142 
143  struct netmap_slot *slot = &ring->slot[cur];
144 
145  do
146  {
147  b0 = vlib_get_buffer (vm, bi);
148  len = b0->current_length;
149  /* memcpy */
150  clib_memcpy ((u8 *) NETMAP_BUF (ring, slot->buf_idx) + offset,
151  vlib_buffer_get_current (b0), len);
152  offset += len;
153  }
154  while ((bi = b0->next_buffer));
155 
156  slot->len = offset;
157  cur = (cur + 1) % ring->num_slots;
158  n_free_slots--;
159  n_left--;
160  }
162  ring->head = ring->cur = cur;
163  }
164 
165  if (n_left < frame->n_vectors)
166  ioctl (nif->fd, NIOCTXSYNC, NULL);
167 
168  if (PREDICT_FALSE (nif->lockp != 0))
169  *nif->lockp = 0;
170 
171  if (n_left)
172  vlib_error_count (vm, node->node_index,
173  (n_left ==
174  frame->n_vectors ? NETMAP_TX_ERROR_PENDING_MSGS :
175  NETMAP_TX_ERROR_NO_FREE_SLOTS), n_left);
176 
177  vlib_buffer_free (vm, vlib_frame_args (frame), frame->n_vectors);
178  return frame->n_vectors;
179 }
180 
181 static void
183  u32 node_index)
184 {
185  netmap_main_t *apm = &netmap_main;
186  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
188 
189  /* Shut off redirection */
190  if (node_index == ~0)
191  {
192  nif->per_interface_next_index = node_index;
193  return;
194  }
195 
198  node_index);
199 }
200 
201 static void
203 {
204  /* Nothing for now */
205 }
206 
207 static clib_error_t *
209 {
210  netmap_main_t *apm = &netmap_main;
211  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
213  u32 hw_flags;
214 
215  nif->is_admin_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
216 
217  if (nif->is_admin_up)
219  else
220  hw_flags = 0;
221 
222  vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
223 
224  return 0;
225 }
226 
227 static clib_error_t *
229  u32 hw_if_index,
230  struct vnet_sw_interface_t *st, int is_add)
231 {
232  /* Nothing for now */
233  return 0;
234 }
235 
236 /* *INDENT-OFF* */
238  .name = "netmap",
239  .tx_function = netmap_interface_tx,
240  .format_device_name = format_netmap_device_name,
241  .format_device = format_netmap_device,
242  .format_tx_trace = format_netmap_tx_trace,
243  .tx_function_n_errors = NETMAP_TX_N_ERROR,
244  .tx_function_error_strings = netmap_tx_func_error_strings,
245  .rx_redirect_to_node = netmap_set_interface_next_node,
246  .clear_counters = netmap_clear_hw_interface_counters,
247  .admin_up_down_function = netmap_interface_admin_up_down,
248  .subif_add_del_function = netmap_subif_add_del_function,
249  .no_flatten_output_chains = 1,
250 };
251 
254 /* *INDENT-ON* */
255 
256 /*
257  * fd.io coding-style-patch-verification: ON
258  *
259  * Local Variables:
260  * eval: (c-set-style "gnu")
261  * End:
262  */
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
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
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:513
netmap_if_t * interfaces
Definition: netmap.h:78
static void clib_cpu_time_wait(u64 dt)
Definition: time.h:208
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
uint16_t nr_tx_rings
Definition: net_netmap.h:481
static void netmap_set_interface_next_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: device.c:182
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:55
#define NULL
Definition: clib.h:55
static uword netmap_interface_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: device.c:97
uint32_t cur
Definition: net_netmap.h:272
uint32_t nr_tx_slots
Definition: net_netmap.h:479
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_device_name(u8 *s, va_list *args)
Definition: device.c:49
static u8 * format_netmap_tx_trace(u8 *s, va_list *args)
Definition: device.c:90
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:273
#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:1061
uint16_t len
Definition: net_netmap.h:147
VNET_DEVICE_CLASS(af_packet_device_class)
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:187
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
#define foreach_netmap_tx_func_error
Definition: device.c:29
#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:53
static char * netmap_tx_func_error_strings[]
Definition: device.c:41
struct nmreq * req
Definition: netmap.h:57
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
static uword format_get_indent(u8 *s)
Definition: format.h:72
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:82
#define PREDICT_FALSE(x)
Definition: clib.h:97
uint32_t nr_version
Definition: net_netmap.h:476
uint32_t buf_idx
Definition: net_netmap.h:146
u16 n_vectors
Definition: node.h:344
uint32_t head
Definition: net_netmap.h:271
static void netmap_clear_hw_interface_counters(u32 instance)
Definition: device.c:202
#define clib_memcpy(a, b, c)
Definition: string.h:63
#define clib_unix_warning(format, args...)
Definition: error.h:68
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:415
netmap_main_t netmap_main
Definition: netmap.h:99
vlib_node_registration_t netmap_input_node
(constructor) VLIB_REGISTER_NODE (netmap_input_node)
Definition: node.c:293
unsigned int u32
Definition: types.h:88
u16 mem_region
Definition: netmap.h:58
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: dpdk_buffer.c:766
netmap_tx_func_error_t
Definition: device.c:33
u8 * host_if_name
Definition: netmap.h:47
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:114
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:228
static void * vlib_frame_args(vlib_frame_t *f)
Get pointer to frame scalar data.
Definition: node_funcs.h:268
u64 uword
Definition: types.h:112
static clib_error_t * netmap_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: device.c:208
template key/value backing page structure
Definition: bihash_doc.h:44
u8 is_admin_up
Definition: netmap.h:54
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
vnet_device_class_t netmap_device_class
struct clib_bihash_value offset
template key/value backing page structure
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:101
u32 flags
Definition: vhost-user.h:76
uword runtime_data[(128-1 *sizeof(vlib_node_function_t *)-1 *sizeof(vlib_error_t *)-11 *sizeof(u32)-5 *sizeof(u16))/sizeof(uword)]
Definition: node.h:472
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
uint32_t nr_flags
Definition: net_netmap.h:513
#define VLIB_DEVICE_TX_FUNCTION_MULTIARCH(dev, fn)
Definition: interface.h:183