FD.io VPP  v16.06
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 <vlib/vlib.h>
19 #include <vlib/unix/unix.h>
20 #include <vnet/ethernet/ethernet.h>
21 
23 
24 #define foreach_netmap_tx_func_error \
25 _(NO_FREE_SLOTS, "no free tx slots") \
26 _(PENDING_MSGS, "pending msgs in tx ring")
27 
28 typedef enum {
29 #define _(f,s) NETMAP_TX_ERROR_##f,
31 #undef _
34 
35 static char * netmap_tx_func_error_strings[] = {
36 #define _(n,s) s,
38 #undef _
39 };
40 
41 
42 static u8 * format_netmap_device_name (u8 * s, va_list * args)
43 {
44  u32 i = va_arg (*args, u32);
45  netmap_main_t * apm = &netmap_main;
46  netmap_if_t * nif = pool_elt_at_index (apm->interfaces, i);
47 
48  s = format (s, "netmap-%s", nif->host_if_name);
49  return s;
50 }
51 
52 static u8 * format_netmap_device (u8 * s, va_list * args)
53 {
54  u32 dev_instance = va_arg (*args, u32);
55  int verbose = va_arg (*args, int);
56  netmap_main_t * nm = &netmap_main;
57  netmap_if_t * nif = vec_elt_at_index (nm->interfaces, dev_instance);
58  uword indent = format_get_indent (s);
59 
60  s = format (s, "NETMAP interface");
61  if (verbose)
62  {
63  s = format (s, "\n%U version %d flags 0x%x"
64  "\n%U region %u memsize 0x%x offset 0x%x"
65  "\n%U tx_slots %u rx_slots %u tx_rings %u rx_rings %u",
66  format_white_space, indent + 2,
67  nif->req->nr_version,
68  nif->req->nr_flags,
69  format_white_space, indent + 2,
70  nif->mem_region,
71  nif->req->nr_memsize,
72  nif->req->nr_offset,
73  format_white_space, indent + 2,
74  nif->req->nr_tx_slots,
75  nif->req->nr_rx_slots,
76  nif->req->nr_tx_rings,
77  nif->req->nr_rx_rings);
78  }
79  return s;
80 }
81 
82 static u8 * format_netmap_tx_trace (u8 * s, va_list * args)
83 {
84  s = format (s, "Unimplemented...");
85  return s;
86 }
87 
88 static uword
90  vlib_node_runtime_t * node,
91  vlib_frame_t * frame)
92 {
93  netmap_main_t * nm = &netmap_main;
94  u32 * buffers = vlib_frame_args (frame);
95  u32 n_left = frame->n_vectors;
96  f64 const time_constant = 1e3;
97  vnet_interface_output_runtime_t * rd = (void *) node->runtime_data;
99  int cur_ring;
100 
101  cur_ring = nif->first_tx_ring;
102 
103  while(n_left && cur_ring <= nif->last_tx_ring)
104  {
105  struct netmap_ring * ring = NETMAP_TXRING(nif->nifp, cur_ring);
106  int n_free_slots = nm_ring_space(ring);
107  uint cur = ring->cur;
108 
109  if (nm_tx_pending(ring))
110  {
111  ioctl(nif->fd, NIOCTXSYNC, NULL);
112  clib_cpu_time_wait(time_constant);
113 
114  if (nm_tx_pending(ring) && !n_free_slots)
115  {
116  cur_ring++;
117  continue;
118  }
119  }
120 
121  while (n_left && n_free_slots)
122  {
123  vlib_buffer_t * b0 = 0;
124  u32 bi = buffers[0];
125  u32 len;
126  u32 offset = 0;
127  buffers++;
128 
129  struct netmap_slot * slot = &ring->slot[cur];
130 
131  do
132  {
133  b0 = vlib_get_buffer (vm, bi);
134  len = b0->current_length;
135  /* memcpy */
136  clib_memcpy ((u8 *) NETMAP_BUF(ring, slot->buf_idx) + offset,
137  vlib_buffer_get_current(b0), len);
138  offset += len;
139  }
140  while ((bi = b0->next_buffer));
141 
142  slot->len = offset;
143  cur = (cur + 1) % ring->num_slots;
144  n_free_slots--;
145  n_left--;
146  }
148  ring->head = ring->cur = cur;
149  }
150 
151  if (n_left < frame->n_vectors)
152  ioctl(nif->fd, NIOCTXSYNC, NULL);
153 
154  if (n_left)
155  vlib_error_count (vm, node->node_index,
156  (n_left == frame->n_vectors ? NETMAP_TX_ERROR_PENDING_MSGS : NETMAP_TX_ERROR_NO_FREE_SLOTS), n_left);
157 
158  vlib_buffer_free (vm, vlib_frame_args (frame), frame->n_vectors);
159  return frame->n_vectors;
160 }
161 
162 static void
164  u32 node_index)
165 {
166  netmap_main_t * apm = &netmap_main;
167  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
169 
170  /* Shut off redirection */
171  if (node_index == ~0)
172  {
173  nif->per_interface_next_index = node_index;
174  return;
175  }
176 
178  vlib_node_add_next (vlib_get_main(), netmap_input_node.index, node_index);
179 }
180 
182 {
183  /* Nothing for now */
184 }
185 
186 static clib_error_t *
188 {
189  netmap_main_t * apm = &netmap_main;
190  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
192  u32 hw_flags;
193 
194  nif->is_admin_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
195 
196  if (nif->is_admin_up)
198  else
199  hw_flags = 0;
200 
201  vnet_hw_interface_set_flags(vnm, hw_if_index, hw_flags);
202 
203  return 0;
204 }
205 
206 static clib_error_t *
208  u32 hw_if_index,
209  struct vnet_sw_interface_t * st,
210  int is_add)
211 {
212  /* Nothing for now */
213  return 0;
214 }
215 
217  .name = "netmap",
218  .tx_function = netmap_interface_tx,
219  .format_device_name = format_netmap_device_name,
220  .format_device = format_netmap_device,
221  .format_tx_trace = format_netmap_tx_trace,
222  .tx_function_n_errors = NETMAP_TX_N_ERROR,
223  .tx_function_error_strings = netmap_tx_func_error_strings,
224  .rx_redirect_to_node = netmap_set_interface_next_node,
225  .clear_counters = netmap_clear_hw_interface_counters,
226  .admin_up_down_function = netmap_interface_admin_up_down,
227  .subif_add_del_function = netmap_subif_add_del_function,
228  .no_flatten_output_chains = 1,
229 };
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
always_inline void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:54
uint16_t nr_rx_rings
Definition: net_netmap.h:482
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
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:454
netmap_if_t * interfaces
Definition: netmap.h:79
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:163
#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:89
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 u8 * format_netmap_device_name(u8 *s, va_list *args)
Definition: device.c:42
static u8 * format_netmap_tx_trace(u8 *s, va_list *args)
Definition: device.c:82
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:241
#define NIOCTXSYNC
Definition: net_netmap.h:596
always_inline void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:184
always_inline vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
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:52
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:107
#define foreach_netmap_tx_func_error
Definition: device.c:24
#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:56
static char * netmap_tx_func_error_strings[]
Definition: device.c:35
struct nmreq * req
Definition: netmap.h:60
#define pool_elt_at_index(p, i)
Definition: pool.h:346
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.c:1060
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:81
uint32_t nr_version
Definition: net_netmap.h:476
uint32_t buf_idx
Definition: net_netmap.h:146
always_inline void * vlib_frame_args(vlib_frame_t *f)
Definition: node_funcs.h:209
u16 n_vectors
Definition: node.h:307
uint32_t head
Definition: net_netmap.h:271
static void netmap_clear_hw_interface_counters(u32 instance)
Definition: device.c:181
#define clib_memcpy(a, b, c)
Definition: string.h:63
always_inline vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:373
netmap_main_t netmap_main
Definition: netmap.h:94
vlib_node_registration_t netmap_input_node
(constructor) VLIB_REGISTER_NODE (netmap_input_node)
Definition: node.c:269
unsigned int u32
Definition: types.h:88
u16 mem_region
Definition: netmap.h:61
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
netmap_tx_func_error_t
Definition: device.c:28
u8 * host_if_name
Definition: netmap.h:50
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:112
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:207
static uint32_t nm_ring_space(struct netmap_ring *ring)
Definition: netmap.h:140
always_inline uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:919
always_inline void clib_cpu_time_wait(u64 dt)
Definition: time.h:190
always_inline uword format_get_indent(u8 *s)
Definition: format.h:72
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:187
u8 is_admin_up
Definition: netmap.h:57
double f64
Definition: types.h:140
unsigned char u8
Definition: types.h:56
vnet_device_class_t netmap_device_class
static int nm_tx_pending(struct netmap_ring *ring)
Definition: netmap.h:134
#define NETMAP_TXRING(nifp, index)
Definition: netmap.h:109
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:101
u32 flags
Definition: vhost-user.h:73
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:432
always_inline vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
#define NETMAP_BUF(ring, index)
Definition: netmap.h:115
uint32_t nr_flags
Definition: net_netmap.h:513