FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
netmap.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 #include <sys/types.h>
22 #include <fcntl.h>
23 #include <vnet/devices/netmap/net_netmap.h>
24 
25 #include <vlib/vlib.h>
26 #include <vlib/unix/unix.h>
27 #include <vnet/ethernet/ethernet.h>
28 #include <vnet/devices/netmap/netmap.h>
29 
31 
32 static u32
34  u32 flags)
35 {
36  /* nothing for now */
37  return 0;
38 }
39 
40 static clib_error_t *
42 {
45  u32 idx = uf->private_data;
46 
47  nm->pending_input_bitmap =
48  clib_bitmap_set (nm->pending_input_bitmap, idx, 1);
49 
50  /* Schedule the rx node */
52 
53  return 0;
54 }
55 
56 static void
58 {
59  if (nif->clib_file_index != ~0)
60  {
62  nif->clib_file_index = ~0;
63  }
64  else if (nif->fd > -1)
65  close (nif->fd);
66 
67  if (nif->mem_region)
68  {
69  netmap_mem_region_t *reg = &nm->mem_regions[nif->mem_region];
70  if (--reg->refcnt == 0)
71  {
72  munmap (reg->mem, reg->region_size);
73  reg->region_size = 0;
74  }
75  }
76 
77 
78  mhash_unset (&nm->if_index_by_host_if_name, nif->host_if_name,
79  &nif->if_index);
80  vec_free (nif->host_if_name);
81  vec_free (nif->req);
82 
83  clib_memset (nif, 0, sizeof (*nif));
84  pool_put (nm->interfaces, nif);
85 }
86 
87 int
89 {
90  /* if worker threads are enabled, switch to polling mode */
92  {
93  vlib_node_set_state (this_vlib_main,
94  netmap_input_node.index,
95  VLIB_NODE_STATE_POLLING);
96  }));
97 
98  return 0;
99 }
100 
101 int
103 {
105  {
106  vlib_node_set_state (this_vlib_main,
107  netmap_input_node.index,
108  VLIB_NODE_STATE_INTERRUPT);
109  }));
110 
111  return 0;
112 }
113 
114 int
115 netmap_create_if (vlib_main_t * vm, u8 * if_name, u8 * hw_addr_set,
116  u8 is_pipe, u8 is_master, u32 * sw_if_index)
117 {
119  int ret = 0;
120  netmap_if_t *nif = 0;
121  u8 hw_addr[6];
122  clib_error_t *error = 0;
124  vnet_main_t *vnm = vnet_get_main ();
125  uword *p;
126  struct nmreq *req = 0;
127  netmap_mem_region_t *reg;
129  int fd;
130 
131  p = mhash_get (&nm->if_index_by_host_if_name, if_name);
132  if (p)
133  return VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
134 
135  fd = open ("/dev/netmap", O_RDWR);
136  if (fd < 0)
137  return VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
138 
139  pool_get (nm->interfaces, nif);
140  nif->if_index = nif - nm->interfaces;
141  nif->fd = fd;
142  nif->clib_file_index = ~0;
143 
144  vec_validate (req, 0);
145  nif->req = req;
146  req->nr_version = NETMAP_API;
147  req->nr_flags = NR_REG_ALL_NIC;
148 
149  if (is_pipe)
150  req->nr_flags = is_master ? NR_REG_PIPE_MASTER : NR_REG_PIPE_SLAVE;
151  else
152  req->nr_flags = NR_REG_ALL_NIC;
153 
155  snprintf (req->nr_name, IFNAMSIZ, "%s", if_name);
156  req->nr_name[IFNAMSIZ - 1] = 0;
157 
158  if (ioctl (nif->fd, NIOCREGIF, req))
159  {
160  ret = VNET_API_ERROR_NOT_CONNECTED;
161  goto error;
162  }
163 
164  nif->mem_region = req->nr_arg2;
165  vec_validate (nm->mem_regions, nif->mem_region);
166  reg = &nm->mem_regions[nif->mem_region];
167  if (reg->region_size == 0)
168  {
169  reg->mem = mmap (NULL, req->nr_memsize, PROT_READ | PROT_WRITE,
170  MAP_SHARED, fd, 0);
171  clib_warning ("mem %p", reg->mem);
172  if (reg->mem == MAP_FAILED)
173  {
174  ret = VNET_API_ERROR_NOT_CONNECTED;
175  goto error;
176  }
177  reg->region_size = req->nr_memsize;
178  }
179  reg->refcnt++;
180 
181  nif->nifp = NETMAP_IF (reg->mem, req->nr_offset);
182  nif->first_rx_ring = 0;
183  nif->last_rx_ring = 0;
184  nif->first_tx_ring = 0;
185  nif->last_tx_ring = 0;
186  nif->host_if_name = if_name;
187  nif->per_interface_next_index = ~0;
188 
189  if (tm->n_vlib_mains > 1)
190  clib_spinlock_init (&nif->lockp);
191 
192  {
193  clib_file_t template = { 0 };
195  template.file_descriptor = nif->fd;
196  template.private_data = nif->if_index;
197  template.description = format (0, "netmap socket");
198  nif->clib_file_index = clib_file_add (&file_main, &template);
199  }
200 
201  /*use configured or generate random MAC address */
202  if (hw_addr_set)
203  memcpy (hw_addr, hw_addr_set, 6);
204  else
205  {
206  f64 now = vlib_time_now (vm);
207  u32 rnd;
208  rnd = (u32) (now * 1e6);
209  rnd = random_u32 (&rnd);
210 
211  memcpy (hw_addr + 2, &rnd, sizeof (rnd));
212  hw_addr[0] = 2;
213  hw_addr[1] = 0xfe;
214  }
215 
217  nif->if_index, hw_addr,
218  &nif->hw_if_index,
220 
221  if (error)
222  {
224  ret = VNET_API_ERROR_SYSCALL_ERROR_1;
225  goto error;
226  }
227 
228  sw = vnet_get_hw_sw_interface (vnm, nif->hw_if_index);
229  nif->sw_if_index = sw->sw_if_index;
230 
231  mhash_set_mem (&nm->if_index_by_host_if_name, if_name, &nif->if_index, 0);
232 
233  if (sw_if_index)
234  *sw_if_index = nif->sw_if_index;
235 
236  if (tm->n_vlib_mains > 1 && pool_elts (nm->interfaces) == 1)
238 
239  return 0;
240 
241 error:
242  close_netmap_if (nm, nif);
243  return ret;
244 }
245 
246 int
247 netmap_delete_if (vlib_main_t * vm, u8 * host_if_name)
248 {
249  vnet_main_t *vnm = vnet_get_main ();
251  netmap_if_t *nif;
252  uword *p;
254 
255  p = mhash_get (&nm->if_index_by_host_if_name, host_if_name);
256  if (p == NULL)
257  {
258  clib_warning ("Host interface %s does not exist", host_if_name);
259  return VNET_API_ERROR_SYSCALL_ERROR_1;
260  }
261  nif = pool_elt_at_index (nm->interfaces, p[0]);
262 
263  /* bring down the interface */
265 
267 
268  close_netmap_if (nm, nif);
269 
270  if (tm->n_vlib_mains > 1 && pool_elts (nm->interfaces) == 0)
272 
273  return 0;
274 }
275 
276 static clib_error_t *
278 {
282  uword *p;
283 
284  clib_memset (nm, 0, sizeof (netmap_main_t));
285 
286  nm->input_cpu_first_index = 0;
287  nm->input_cpu_count = 1;
288 
289  /* find out which cpus will be used for input */
290  p = hash_get_mem (tm->thread_registrations_by_name, "workers");
291  tr = p ? (vlib_thread_registration_t *) p[0] : 0;
292 
293  if (tr && tr->count > 0)
294  {
295  nm->input_cpu_first_index = tr->first_index;
296  nm->input_cpu_count = tr->count;
297  }
298 
299  mhash_init_vec_string (&nm->if_index_by_host_if_name, sizeof (uword));
300 
301  vec_validate_aligned (nm->rx_buffers, tm->n_vlib_mains - 1,
303 
304  return 0;
305 }
306 
308 
309 /*
310  * fd.io coding-style-patch-verification: ON
311  *
312  * Local Variables:
313  * eval: (c-set-style "gnu")
314  * End:
315  */
vlib.h
clib_spinlock_init
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:65
nmreq::nr_arg2
uint16_t nr_arg2
Definition: net_netmap.h:511
netmap_if_t::sw_if_index
u32 sw_if_index
Definition: netmap.h:52
netmap_init
static clib_error_t * netmap_init(vlib_main_t *vm)
Definition: netmap.c:277
netmap_if_t::lockp
clib_spinlock_t lockp
Definition: netmap.h:48
file_main
clib_file_main_t file_main
Definition: main.c:63
NR_REG_PIPE_MASTER
@ NR_REG_PIPE_MASTER
Definition: net_netmap.h:524
netmap_mem_region_t
Definition: netmap.h:70
netmap_main
netmap_main_t netmap_main
Definition: netmap.c:30
vnet_sw_interface_t
Definition: interface.h:869
netmap_worker_thread_disable
int netmap_worker_thread_disable()
Definition: netmap.c:102
netmap_if_t::hw_if_index
u32 hw_if_index
Definition: netmap.h:51
netmap_if_t::req
struct nmreq * req
Definition: netmap.h:59
netmap_mem_region_t::refcnt
int refcnt
Definition: netmap.h:74
vlib_node_set_state
static void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
Set node dispatch state.
Definition: node_funcs.h:175
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:549
NETMAP_API
#define NETMAP_API
Definition: net_netmap.h:42
nat44_ei_main_s::interfaces
nat44_ei_interface_t * interfaces
Definition: nat44_ei.h:340
clib_file::read_function
clib_file_function_t * read_function
Definition: file.h:67
close_netmap_if
static void close_netmap_if(netmap_main_t *nm, netmap_if_t *nif)
Definition: netmap.c:57
clib_file::private_data
u64 private_data
Definition: file.h:64
pool_put
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
mhash_get
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
netmap_if_t::nifp
struct netmap_if * nifp
Definition: netmap.h:62
hi
vl_api_ip4_address_t hi
Definition: arp.api:37
clib_error_report
#define clib_error_report(e)
Definition: error.h:113
netmap_if_t::first_rx_ring
u16 first_rx_ring
Definition: netmap.h:65
netmap_worker_thread_enable
int netmap_worker_thread_enable()
Definition: netmap.c:88
vlib_thread_registration_::count
u32 count
Definition: threads.h:38
ethernet.h
error
Definition: cJSON.c:88
netmap_fd_read_ready
static clib_error_t * netmap_fd_read_ready(clib_file_t *uf)
Definition: netmap.c:41
nmreq::nr_version
uint32_t nr_version
Definition: net_netmap.h:476
random_u32
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
foreach_vlib_main
#define foreach_vlib_main()
Definition: threads.h:216
vnet_sw_interface_t::sw_if_index
u32 sw_if_index
Definition: interface.h:876
vlib_thread_main_t::n_vlib_mains
u32 n_vlib_mains
Definition: threads.h:262
netmap_if_t::last_tx_ring
u16 last_tx_ring
Definition: netmap.h:64
nmreq::nr_flags
uint32_t nr_flags
Definition: net_netmap.h:513
netmap_create_if
int netmap_create_if(vlib_main_t *vm, u8 *if_name, u8 *hw_addr_set, u8 is_pipe, u8 is_master, u32 *sw_if_index)
Definition: netmap.c:115
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
clib_file
Definition: file.h:51
vec_validate_aligned
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:534
mhash_init_vec_string
static void mhash_init_vec_string(mhash_t *h, uword n_value_bytes)
Definition: mhash.h:84
uword
u64 uword
Definition: types.h:112
netmap_eth_flag_change
static u32 netmap_eth_flag_change(vnet_main_t *vnm, vnet_hw_interface_t *hi, u32 flags)
Definition: netmap.c:33
vlib_thread_main_t::thread_registrations_by_name
uword * thread_registrations_by_name
Definition: threads.h:251
vlib_thread_registration_::first_index
u32 first_index
Definition: threads.h:44
nmreq::nr_name
char nr_name[IFNAMSIZ]
Definition: net_netmap.h:475
NR_ACCEPT_VNET_HDR
#define NR_ACCEPT_VNET_HDR
Definition: net_netmap.h:543
f64
double f64
Definition: types.h:142
netmap_if_t::mem_region
u16 mem_region
Definition: netmap.h:60
netmap_if_t::fd
int fd
Definition: netmap.h:61
pool_get
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:255
nmreq::nr_offset
uint32_t nr_offset
Definition: net_netmap.h:477
vec_validate
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment)
Definition: vec.h:523
netmap_if_t::first_tx_ring
u16 first_tx_ring
Definition: netmap.h:63
clib_file_main_t::file_pool
clib_file_t * file_pool
Definition: file.h:88
NR_REG_ALL_NIC
@ NR_REG_ALL_NIC
Definition: net_netmap.h:520
clib_bitmap_set
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap.
Definition: bitmap.h:167
netmap_main_t
Definition: netmap.h:77
CLIB_CACHE_LINE_BYTES
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:58
netmap_mem_region_t::region_size
u32 region_size
Definition: netmap.h:73
hash_get_mem
#define hash_get_mem(h, key)
Definition: hash.h:269
netmap_delete_if
int netmap_delete_if(vlib_main_t *vm, u8 *host_if_name)
Definition: netmap.c:247
netmap_mem_region_t::mem
char * mem
Definition: netmap.h:72
vnet_hw_interface_t
Definition: interface.h:638
vnet_main_t
Definition: vnet.h:76
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
nmreq::nr_memsize
uint32_t nr_memsize
Definition: net_netmap.h:478
netmap_if_t::host_if_name
u8 * host_if_name
Definition: netmap.h:49
format
description fragment has unexpected format
Definition: map.api:433
clib_file_del
static void clib_file_del(clib_file_main_t *um, clib_file_t *f)
Definition: file.h:109
netmap_if_t::per_interface_next_index
u32 per_interface_next_index
Definition: netmap.h:55
vnet_get_hw_sw_interface
static vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface_funcs.h:72
u32
unsigned int u32
Definition: types.h:88
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
ethernet_delete_interface
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:393
vlib_thread_main_t
Definition: threads.h:243
vlib_node_set_interrupt_pending
static void vlib_node_set_interrupt_pending(vlib_main_t *vm, u32 node_index)
Definition: node_funcs.h:249
NIOCREGIF
#define NIOCREGIF
Definition: net_netmap.h:595
pool_elts
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127
clib_file_add
static uword clib_file_add(clib_file_main_t *um, clib_file_t *template)
Definition: file.h:96
nm
nat44_ei_main_t * nm
Definition: nat44_ei_hairpinning.c:413
NR_REG_PIPE_SLAVE
@ NR_REG_PIPE_SLAVE
Definition: net_netmap.h:525
netmap_if_t
Definition: netmap.h:45
now
f64 now
Definition: nat44_ei_out2in.c:710
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_main_t
Definition: main.h:102
netmap_device_class
vnet_device_class_t netmap_device_class
vlib_get_main
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
vnet_hw_interface_set_flags
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
unix.h
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
netmap_if_t::last_rx_ring
u16 last_rx_ring
Definition: netmap.h:66
clib_warning
#define clib_warning(format, args...)
Definition: error.h:59
vlib_time_now
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:327
vlib_thread_registration_
Definition: threads.h:27
nmreq
Definition: net_netmap.h:474
vlib_get_thread_main
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:56
sw_if_index
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
netmap_input_node
vlib_node_registration_t netmap_input_node
(constructor) VLIB_REGISTER_NODE (netmap_input_node)
Definition: node.c:277
mhash_set_mem
__clib_export uword mhash_set_mem(mhash_t *h, void *key, uword *new_value, uword *old_value)
Definition: mhash.c:264
mhash_unset
__clib_export uword mhash_unset(mhash_t *h, void *key, uword *old_value)
Definition: mhash.c:346
ethernet_register_interface
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
netmap_if_t::clib_file_index
u32 clib_file_index
Definition: netmap.h:53
flags
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
netmap_if_t::if_index
uword if_index
Definition: netmap.h:50