e7bbdfd86ae7818a9c1cfd66e6cbf9eb70ff35c6
[vpp.git] / src / vnet / devices / af_packet / af_packet.c
1 /*
2  *------------------------------------------------------------------
3  * af_packet.c - linux kernel packet interface
4  *
5  * Copyright (c) 2016 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19
20 #include <linux/if_ether.h>
21 #include <linux/if_packet.h>
22 #include <dirent.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <fcntl.h>
26
27 #include <vppinfra/linux/sysfs.h>
28 #include <vlib/vlib.h>
29 #include <vlib/unix/unix.h>
30 #include <vnet/ip/ip.h>
31 #include <vnet/ethernet/ethernet.h>
32
33 #include <vnet/devices/af_packet/af_packet.h>
34
35 #define AF_PACKET_DEBUG_SOCKET          0
36
37 #define AF_PACKET_TX_FRAMES_PER_BLOCK   1024
38 #define AF_PACKET_TX_FRAME_SIZE         (2048 * 5)
39 #define AF_PACKET_TX_BLOCK_NR           1
40 #define AF_PACKET_TX_FRAME_NR           (AF_PACKET_TX_BLOCK_NR * \
41                                          AF_PACKET_TX_FRAMES_PER_BLOCK)
42 #define AF_PACKET_TX_BLOCK_SIZE         (AF_PACKET_TX_FRAME_SIZE * \
43                                          AF_PACKET_TX_FRAMES_PER_BLOCK)
44
45 #define AF_PACKET_RX_FRAMES_PER_BLOCK   1024
46 #define AF_PACKET_RX_FRAME_SIZE         (2048 * 5)
47 #define AF_PACKET_RX_BLOCK_NR           1
48 #define AF_PACKET_RX_FRAME_NR           (AF_PACKET_RX_BLOCK_NR * \
49                                          AF_PACKET_RX_FRAMES_PER_BLOCK)
50 #define AF_PACKET_RX_BLOCK_SIZE         (AF_PACKET_RX_FRAME_SIZE * \
51                                          AF_PACKET_RX_FRAMES_PER_BLOCK)
52
53 #if AF_PACKET_DEBUG_SOCKET == 1
54 #define DBG_SOCK(args...) clib_warning(args);
55 #else
56 #define DBG_SOCK(args...)
57 #endif
58
59 /*defined in net/if.h but clashes with dpdk headers */
60 unsigned int if_nametoindex (const char *ifname);
61
62 typedef struct tpacket_req tpacket_req_t;
63
64 static u32
65 af_packet_eth_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi,
66                            u32 flags)
67 {
68   clib_error_t *error;
69   u8 *s;
70   af_packet_main_t *apm = &af_packet_main;
71   af_packet_if_t *apif =
72     pool_elt_at_index (apm->interfaces, hi->dev_instance);
73
74   if (ETHERNET_INTERFACE_FLAG_MTU == (flags & ETHERNET_INTERFACE_FLAG_MTU))
75     {
76       s = format (0, "/sys/class/net/%s/mtu%c", apif->host_if_name, 0);
77
78       error = clib_sysfs_write ((char *) s, "%d", hi->max_packet_bytes);
79       vec_free (s);
80
81       if (error)
82         {
83           clib_error_report (error);
84           return VNET_API_ERROR_SYSCALL_ERROR_1;
85         }
86     }
87
88   return 0;
89 }
90
91 static clib_error_t *
92 af_packet_fd_read_ready (clib_file_t * uf)
93 {
94   af_packet_main_t *apm = &af_packet_main;
95   vnet_main_t *vnm = vnet_get_main ();
96   u32 idx = uf->private_data;
97   af_packet_if_t *apif = pool_elt_at_index (apm->interfaces, idx);
98
99   apm->pending_input_bitmap =
100     clib_bitmap_set (apm->pending_input_bitmap, idx, 1);
101
102   /* Schedule the rx node */
103   vnet_device_input_set_interrupt_pending (vnm, apif->hw_if_index, 0);
104
105   return 0;
106 }
107
108 static int
109 is_bridge (const u8 * host_if_name)
110 {
111   u8 *s;
112   DIR *dir = NULL;
113
114   s = format (0, "/sys/class/net/%s/bridge%c", host_if_name, 0);
115   dir = opendir ((char *) s);
116   vec_free (s);
117
118   if (dir)
119     {
120       closedir (dir);
121       return 0;
122     }
123
124   return -1;
125 }
126
127 static int
128 create_packet_v2_sock (int host_if_index, tpacket_req_t * rx_req,
129                        tpacket_req_t * tx_req, int *fd, u8 ** ring)
130 {
131   int ret, err;
132   struct sockaddr_ll sll;
133   int ver = TPACKET_V2;
134   socklen_t req_sz = sizeof (struct tpacket_req);
135   u32 ring_sz = rx_req->tp_block_size * rx_req->tp_block_nr +
136     tx_req->tp_block_size * tx_req->tp_block_nr;
137
138   if ((*fd = socket (AF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0)
139     {
140       DBG_SOCK ("Failed to create socket");
141       ret = VNET_API_ERROR_SYSCALL_ERROR_1;
142       goto error;
143     }
144
145   if ((err =
146        setsockopt (*fd, SOL_PACKET, PACKET_VERSION, &ver, sizeof (ver))) < 0)
147     {
148       DBG_SOCK ("Failed to set rx packet interface version");
149       ret = VNET_API_ERROR_SYSCALL_ERROR_1;
150       goto error;
151     }
152
153   int opt = 1;
154   if ((err =
155        setsockopt (*fd, SOL_PACKET, PACKET_LOSS, &opt, sizeof (opt))) < 0)
156     {
157       DBG_SOCK ("Failed to set packet tx ring error handling option");
158       ret = VNET_API_ERROR_SYSCALL_ERROR_1;
159       goto error;
160     }
161
162   if ((err =
163        setsockopt (*fd, SOL_PACKET, PACKET_RX_RING, rx_req, req_sz)) < 0)
164     {
165       DBG_SOCK ("Failed to set packet rx ring options");
166       ret = VNET_API_ERROR_SYSCALL_ERROR_1;
167       goto error;
168     }
169
170   if ((err =
171        setsockopt (*fd, SOL_PACKET, PACKET_TX_RING, tx_req, req_sz)) < 0)
172     {
173       DBG_SOCK ("Failed to set packet rx ring options");
174       ret = VNET_API_ERROR_SYSCALL_ERROR_1;
175       goto error;
176     }
177
178   *ring =
179     mmap (NULL, ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, *fd,
180           0);
181   if (*ring == MAP_FAILED)
182     {
183       DBG_SOCK ("mmap failure");
184       ret = VNET_API_ERROR_SYSCALL_ERROR_1;
185       goto error;
186     }
187
188   memset (&sll, 0, sizeof (sll));
189   sll.sll_family = PF_PACKET;
190   sll.sll_protocol = htons (ETH_P_ALL);
191   sll.sll_ifindex = host_if_index;
192
193   if ((err = bind (*fd, (struct sockaddr *) &sll, sizeof (sll))) < 0)
194     {
195       DBG_SOCK ("Failed to bind rx packet socket (error %d)", err);
196       ret = VNET_API_ERROR_SYSCALL_ERROR_1;
197       goto error;
198     }
199
200   return 0;
201 error:
202   if (*fd >= 0)
203     close (*fd);
204   *fd = -1;
205   return ret;
206 }
207
208 int
209 af_packet_create_if (vlib_main_t * vm, u8 * host_if_name, u8 * hw_addr_set,
210                      u32 * sw_if_index)
211 {
212   af_packet_main_t *apm = &af_packet_main;
213   int ret, fd = -1;
214   struct tpacket_req *rx_req = 0;
215   struct tpacket_req *tx_req = 0;
216   u8 *ring = 0;
217   af_packet_if_t *apif = 0;
218   u8 hw_addr[6];
219   clib_error_t *error;
220   vnet_sw_interface_t *sw;
221   vnet_hw_interface_t *hw;
222   vlib_thread_main_t *tm = vlib_get_thread_main ();
223   vnet_main_t *vnm = vnet_get_main ();
224   uword *p;
225   uword if_index;
226   u8 *host_if_name_dup = vec_dup (host_if_name);
227   int host_if_index = -1;
228
229   p = mhash_get (&apm->if_index_by_host_if_name, host_if_name);
230   if (p)
231     {
232       return VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
233     }
234
235   vec_validate (rx_req, 0);
236   rx_req->tp_block_size = AF_PACKET_RX_BLOCK_SIZE;
237   rx_req->tp_frame_size = AF_PACKET_RX_FRAME_SIZE;
238   rx_req->tp_block_nr = AF_PACKET_RX_BLOCK_NR;
239   rx_req->tp_frame_nr = AF_PACKET_RX_FRAME_NR;
240
241   vec_validate (tx_req, 0);
242   tx_req->tp_block_size = AF_PACKET_TX_BLOCK_SIZE;
243   tx_req->tp_frame_size = AF_PACKET_TX_FRAME_SIZE;
244   tx_req->tp_block_nr = AF_PACKET_TX_BLOCK_NR;
245   tx_req->tp_frame_nr = AF_PACKET_TX_FRAME_NR;
246
247   host_if_index = if_nametoindex ((const char *) host_if_name);
248
249   if (!host_if_index)
250     {
251       DBG_SOCK ("Wrong host interface name");
252       return VNET_API_ERROR_INVALID_INTERFACE;
253     }
254
255   ret = create_packet_v2_sock (host_if_index, rx_req, tx_req, &fd, &ring);
256
257   if (ret != 0)
258     goto error;
259
260   ret = is_bridge (host_if_name);
261
262   if (ret == 0)                 /* is a bridge, ignore state */
263     host_if_index = -1;
264
265   /* So far everything looks good, let's create interface */
266   pool_get (apm->interfaces, apif);
267   if_index = apif - apm->interfaces;
268
269   apif->host_if_index = host_if_index;
270   apif->fd = fd;
271   apif->rx_ring = ring;
272   apif->tx_ring = ring + rx_req->tp_block_size * rx_req->tp_block_nr;
273   apif->rx_req = rx_req;
274   apif->tx_req = tx_req;
275   apif->host_if_name = host_if_name_dup;
276   apif->per_interface_next_index = ~0;
277   apif->next_tx_frame = 0;
278   apif->next_rx_frame = 0;
279
280   if (tm->n_vlib_mains > 1)
281     clib_spinlock_init (&apif->lockp);
282
283   {
284     clib_file_t template = { 0 };
285     template.read_function = af_packet_fd_read_ready;
286     template.file_descriptor = fd;
287     template.private_data = if_index;
288     template.flags = UNIX_FILE_EVENT_EDGE_TRIGGERED;
289     apif->clib_file_index = clib_file_add (&file_main, &template);
290   }
291
292   /*use configured or generate random MAC address */
293   if (hw_addr_set)
294     clib_memcpy (hw_addr, hw_addr_set, 6);
295   else
296     {
297       f64 now = vlib_time_now (vm);
298       u32 rnd;
299       rnd = (u32) (now * 1e6);
300       rnd = random_u32 (&rnd);
301
302       clib_memcpy (hw_addr + 2, &rnd, sizeof (rnd));
303       hw_addr[0] = 2;
304       hw_addr[1] = 0xfe;
305     }
306
307   error = ethernet_register_interface (vnm, af_packet_device_class.index,
308                                        if_index, hw_addr, &apif->hw_if_index,
309                                        af_packet_eth_flag_change);
310
311   if (error)
312     {
313       memset (apif, 0, sizeof (*apif));
314       pool_put (apm->interfaces, apif);
315       clib_error_report (error);
316       ret = VNET_API_ERROR_SYSCALL_ERROR_1;
317       goto error;
318     }
319
320   sw = vnet_get_hw_sw_interface (vnm, apif->hw_if_index);
321   hw = vnet_get_hw_interface (vnm, apif->hw_if_index);
322   apif->sw_if_index = sw->sw_if_index;
323   vnet_hw_interface_set_input_node (vnm, apif->hw_if_index,
324                                     af_packet_input_node.index);
325
326   vnet_hw_interface_assign_rx_thread (vnm, apif->hw_if_index, 0,        /* queue */
327                                       ~0 /* any cpu */ );
328
329   hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE;
330   vnet_hw_interface_set_flags (vnm, apif->hw_if_index,
331                                VNET_HW_INTERFACE_FLAG_LINK_UP);
332
333   vnet_hw_interface_set_rx_mode (vnm, apif->hw_if_index, 0,
334                                  VNET_HW_INTERFACE_RX_MODE_INTERRUPT);
335
336   mhash_set_mem (&apm->if_index_by_host_if_name, host_if_name_dup, &if_index,
337                  0);
338   if (sw_if_index)
339     *sw_if_index = apif->sw_if_index;
340
341   return 0;
342
343 error:
344   vec_free (host_if_name_dup);
345   vec_free (rx_req);
346   vec_free (tx_req);
347   return ret;
348 }
349
350 int
351 af_packet_delete_if (vlib_main_t * vm, u8 * host_if_name)
352 {
353   vnet_main_t *vnm = vnet_get_main ();
354   af_packet_main_t *apm = &af_packet_main;
355   af_packet_if_t *apif;
356   uword *p;
357   uword if_index;
358   u32 ring_sz;
359
360   p = mhash_get (&apm->if_index_by_host_if_name, host_if_name);
361   if (p == NULL)
362     {
363       clib_warning ("Host interface %s does not exist", host_if_name);
364       return VNET_API_ERROR_SYSCALL_ERROR_1;
365     }
366   apif = pool_elt_at_index (apm->interfaces, p[0]);
367   if_index = apif - apm->interfaces;
368
369   /* bring down the interface */
370   vnet_hw_interface_set_flags (vnm, apif->hw_if_index, 0);
371   vnet_hw_interface_unassign_rx_thread (vnm, apif->hw_if_index, 0);
372
373   /* clean up */
374   if (apif->clib_file_index != ~0)
375     {
376       clib_file_del (&file_main, file_main.file_pool + apif->clib_file_index);
377       apif->clib_file_index = ~0;
378     }
379   else
380     close (apif->fd);
381
382   ring_sz = apif->rx_req->tp_block_size * apif->rx_req->tp_block_nr +
383     apif->tx_req->tp_block_size * apif->tx_req->tp_block_nr;
384   if (munmap (apif->rx_ring, ring_sz))
385     clib_warning ("Host interface %s could not free rx/tx ring",
386                   host_if_name);
387   apif->rx_ring = NULL;
388   apif->tx_ring = NULL;
389   apif->fd = -1;
390
391   vec_free (apif->rx_req);
392   apif->rx_req = NULL;
393   vec_free (apif->tx_req);
394   apif->tx_req = NULL;
395
396   vec_free (apif->host_if_name);
397   apif->host_if_name = NULL;
398   apif->host_if_index = -1;
399
400   mhash_unset (&apm->if_index_by_host_if_name, host_if_name, &if_index);
401
402   ethernet_delete_interface (vnm, apif->hw_if_index);
403
404   pool_put (apm->interfaces, apif);
405
406   return 0;
407 }
408
409 int
410 af_packet_set_l4_cksum_offload (vlib_main_t * vm, u32 sw_if_index, u8 set)
411 {
412   vnet_main_t *vnm = vnet_get_main ();
413   vnet_hw_interface_t *hw;
414
415   hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
416
417   if (set)
418     hw->flags &= ~VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD;
419   else
420     hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD;
421
422   return 0;
423 }
424
425 static clib_error_t *
426 af_packet_init (vlib_main_t * vm)
427 {
428   af_packet_main_t *apm = &af_packet_main;
429   vlib_thread_main_t *tm = vlib_get_thread_main ();
430
431   memset (apm, 0, sizeof (af_packet_main_t));
432
433   mhash_init_vec_string (&apm->if_index_by_host_if_name, sizeof (uword));
434
435   vec_validate_aligned (apm->rx_buffers, tm->n_vlib_mains - 1,
436                         CLIB_CACHE_LINE_BYTES);
437
438   return 0;
439 }
440
441 VLIB_INIT_FUNCTION (af_packet_init);
442
443 /*
444  * fd.io coding-style-patch-verification: ON
445  *
446  * Local Variables:
447  * eval: (c-set-style "gnu")
448  * End:
449  */