2 *------------------------------------------------------------------
3 * af_packet.c - linux kernel packet interface
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:
10 * http://www.apache.org/licenses/LICENSE-2.0
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 *------------------------------------------------------------------
20 #include <linux/if_ether.h>
21 #include <linux/if_packet.h>
22 #include <linux/ethtool.h>
23 #include <linux/sockios.h>
24 #include <sys/ioctl.h>
28 #include <sys/types.h>
31 #include <vppinfra/linux/sysfs.h>
32 #include <vlib/vlib.h>
33 #include <vlib/unix/unix.h>
34 #include <vnet/ip/ip.h>
35 #include <vnet/devices/netlink.h>
36 #include <vnet/ethernet/ethernet.h>
37 #include <vnet/interface/rx_queue_funcs.h>
38 #include <vnet/interface/tx_queue_funcs.h>
40 #include <af_packet/af_packet.h>
42 af_packet_main_t af_packet_main;
44 VNET_HW_INTERFACE_CLASS (af_packet_ip_device_hw_interface_class, static) = {
45 .name = "af-packet-ip-device",
46 .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
49 #define AF_PACKET_DEFAULT_TX_FRAMES_PER_BLOCK 1024
50 #define AF_PACKET_DEFAULT_TX_FRAME_SIZE (2048 * 33) // GSO packet of 64KB
51 #define AF_PACKET_TX_BLOCK_NR 1
53 #define AF_PACKET_DEFAULT_RX_FRAMES_PER_BLOCK_V2 1024
54 #define AF_PACKET_DEFAULT_RX_FRAME_SIZE_V2 (2048 * 33) // GSO packet of 64KB
55 #define AF_PACKET_RX_BLOCK_NR_V2 1
57 #define AF_PACKET_DEFAULT_RX_FRAMES_PER_BLOCK 32
58 #define AF_PACKET_DEFAULT_RX_FRAME_SIZE 2048
59 #define AF_PACKET_RX_BLOCK_NR 160
61 /*defined in net/if.h but clashes with dpdk headers */
62 unsigned int if_nametoindex (const char *ifname);
64 #define AF_PACKET_OFFLOAD_FLAG_RXCKSUM (1 << 0)
65 #define AF_PACKET_OFFLOAD_FLAG_TXCKSUM (1 << 1)
66 #define AF_PACKET_OFFLOAD_FLAG_SG (1 << 2)
67 #define AF_PACKET_OFFLOAD_FLAG_TSO (1 << 3)
68 #define AF_PACKET_OFFLOAD_FLAG_UFO (1 << 4)
69 #define AF_PACKET_OFFLOAD_FLAG_GSO (1 << 5)
70 #define AF_PACKET_OFFLOAD_FLAG_GRO (1 << 6)
72 #define AF_PACKET_OFFLOAD_FLAG_MASK \
73 (AF_PACKET_OFFLOAD_FLAG_RXCKSUM | AF_PACKET_OFFLOAD_FLAG_TXCKSUM | \
74 AF_PACKET_OFFLOAD_FLAG_SG | AF_PACKET_OFFLOAD_FLAG_TSO | \
75 AF_PACKET_OFFLOAD_FLAG_UFO | AF_PACKET_OFFLOAD_FLAG_GSO | \
76 AF_PACKET_OFFLOAD_FLAG_GRO)
78 #define AF_PACKET_IOCTL(fd, a, ...) \
79 if (ioctl (fd, a, __VA_ARGS__) < 0) \
81 err = clib_error_return_unix (0, "ioctl(" #a ")"); \
82 vlib_log_err (af_packet_main.log_class, "%U", format_clib_error, err); \
87 af_packet_get_if_capabilities (u8 *host_if_name)
90 struct ethtool_value e; // { __u32 cmd; __u32 data; };
91 clib_error_t *err = 0;
95 if ((ctl_fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
97 clib_warning ("Cannot open control socket");
101 clib_memset (&ifr, 0, sizeof (ifr));
102 clib_memcpy (ifr.ifr_name, host_if_name,
103 strlen ((const char *) host_if_name));
104 ifr.ifr_data = (void *) &e;
106 e.cmd = ETHTOOL_GRXCSUM;
107 AF_PACKET_IOCTL (ctl_fd, SIOCETHTOOL, &ifr);
109 oflags |= AF_PACKET_OFFLOAD_FLAG_RXCKSUM;
111 e.cmd = ETHTOOL_GTXCSUM;
112 AF_PACKET_IOCTL (ctl_fd, SIOCETHTOOL, &ifr);
114 oflags |= AF_PACKET_OFFLOAD_FLAG_TXCKSUM;
116 e.cmd = ETHTOOL_GTSO;
117 AF_PACKET_IOCTL (ctl_fd, SIOCETHTOOL, &ifr);
119 oflags |= AF_PACKET_OFFLOAD_FLAG_TSO;
121 e.cmd = ETHTOOL_GGSO;
122 AF_PACKET_IOCTL (ctl_fd, SIOCETHTOOL, &ifr);
124 oflags |= AF_PACKET_OFFLOAD_FLAG_GSO;
126 e.cmd = ETHTOOL_GGRO;
127 AF_PACKET_IOCTL (ctl_fd, SIOCETHTOOL, &ifr);
129 oflags |= AF_PACKET_OFFLOAD_FLAG_GRO;
138 static clib_error_t *
139 af_packet_eth_set_max_frame_size (vnet_main_t *vnm, vnet_hw_interface_t *hi,
142 clib_error_t *error, *rv;
143 af_packet_main_t *apm = &af_packet_main;
144 af_packet_if_t *apif = pool_elt_at_index (apm->interfaces, hi->dev_instance);
146 error = vnet_netlink_set_link_mtu (apif->host_if_index,
147 frame_size + hi->frame_overhead);
151 vlib_log_err (apm->log_class, "netlink failed to change MTU: %U",
152 format_clib_error, error);
153 rv = vnet_error (VNET_ERR_SYSCALL_ERROR_1, "netlink error: %U",
154 format_clib_error, error);
155 clib_error_free (error);
159 apif->host_mtu = frame_size + hi->frame_overhead;
164 af_packet_read_mtu (af_packet_if_t *apif)
166 af_packet_main_t *apm = &af_packet_main;
168 error = vnet_netlink_get_link_mtu (apif->host_if_index, &apif->host_mtu);
171 vlib_log_err (apm->log_class, "netlink failed to get MTU: %U",
172 format_clib_error, error);
173 clib_error_free (error);
174 return VNET_API_ERROR_SYSCALL_ERROR_1;
179 static clib_error_t *
180 af_packet_fd_read_ready (clib_file_t * uf)
182 vnet_main_t *vnm = vnet_get_main ();
184 /* Schedule the rx node */
185 vnet_hw_if_rx_queue_set_int_pending (vnm, uf->private_data);
189 static clib_error_t *
190 af_packet_fd_error (clib_file_t *uf)
192 af_packet_main_t *apm = &af_packet_main;
193 clib_error_t *err = 0;
196 int ret = read (uf->file_descriptor, (char *) &u64, sizeof (u64));
200 err = clib_error_return_unix (0, "");
201 vlib_log_notice (apm->log_class, "fd %u %U", uf->file_descriptor,
202 format_clib_error, err);
203 clib_error_free (err);
210 is_bridge (const u8 * host_if_name)
215 s = format (0, "/sys/class/net/%s/bridge%c", host_if_name, 0);
216 dir = opendir ((char *) s);
229 af_packet_set_rx_queues (vlib_main_t *vm, af_packet_if_t *apif)
231 vnet_main_t *vnm = vnet_get_main ();
232 af_packet_queue_t *rx_queue;
234 vnet_hw_if_set_input_node (vnm, apif->hw_if_index,
235 af_packet_input_node.index);
237 vec_foreach (rx_queue, apif->rx_queues)
239 rx_queue->queue_index = vnet_hw_if_register_rx_queue (
240 vnm, apif->hw_if_index, rx_queue->queue_id, VNET_HW_IF_RXQ_THREAD_ANY);
243 clib_file_t template = { 0 };
244 template.read_function = af_packet_fd_read_ready;
245 template.error_function = af_packet_fd_error;
246 template.file_descriptor = rx_queue->fd;
247 template.private_data = rx_queue->queue_index;
248 template.description =
249 format (0, "%U queue %u", format_af_packet_device_name,
250 apif->dev_instance, rx_queue->queue_id);
251 rx_queue->clib_file_index = clib_file_add (&file_main, &template);
253 vnet_hw_if_set_rx_queue_file_index (vnm, rx_queue->queue_index,
254 rx_queue->clib_file_index);
255 vnet_hw_if_set_rx_queue_mode (vnm, rx_queue->queue_index,
256 VNET_HW_IF_RX_MODE_INTERRUPT);
257 rx_queue->mode = VNET_HW_IF_RX_MODE_INTERRUPT;
259 vnet_hw_if_update_runtime_data (vnm, apif->hw_if_index);
263 af_packet_set_tx_queues (vlib_main_t *vm, af_packet_if_t *apif)
265 vnet_main_t *vnm = vnet_get_main ();
266 af_packet_main_t *apm = &af_packet_main;
267 af_packet_queue_t *tx_queue;
269 vec_foreach (tx_queue, apif->tx_queues)
271 tx_queue->queue_index = vnet_hw_if_register_tx_queue (
272 vnm, apif->hw_if_index, tx_queue->queue_id);
275 if (apif->num_txqs == 0)
277 vlib_log_err (apm->log_class, "Interface %U has 0 txq",
278 format_vnet_hw_if_index_name, vnm, apif->hw_if_index);
282 for (u32 j = 0; j < vlib_get_n_threads (); j++)
284 u32 qi = apif->tx_queues[j % apif->num_txqs].queue_index;
285 vnet_hw_if_tx_queue_assign_thread (vnm, qi, j);
288 vnet_hw_if_update_runtime_data (vnm, apif->hw_if_index);
292 create_packet_sock (int host_if_index, tpacket_req_u_t *rx_req,
293 tpacket_req_u_t *tx_req, int *fd, af_packet_ring_t *ring,
294 u32 fanout_id, af_packet_if_flags_t *flags, int ver)
296 af_packet_main_t *apm = &af_packet_main;
297 struct sockaddr_ll sll;
298 socklen_t req_sz = sizeof (tpacket_req3_t);
302 if ((*fd = socket (AF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0)
304 vlib_log_err (apm->log_class,
305 "Failed to create AF_PACKET socket: %s (errno %d)",
306 strerror (errno), errno);
307 ret = VNET_API_ERROR_SYSCALL_ERROR_1;
311 /* bind before rx ring is cfged so we don't receive packets from other interfaces */
312 clib_memset (&sll, 0, sizeof (sll));
313 sll.sll_family = PF_PACKET;
314 sll.sll_protocol = htons (ETH_P_ALL);
315 sll.sll_ifindex = host_if_index;
316 if (bind (*fd, (struct sockaddr *) &sll, sizeof (sll)) < 0)
318 vlib_log_err (apm->log_class,
319 "Failed to bind rx packet socket: %s (errno %d)",
320 strerror (errno), errno);
321 ret = VNET_API_ERROR_SYSCALL_ERROR_1;
325 if (setsockopt (*fd, SOL_PACKET, PACKET_VERSION, &ver, sizeof (ver)) < 0)
327 vlib_log_err (apm->log_class,
328 "Failed to set rx packet interface version: %s (errno %d)",
329 strerror (errno), errno);
330 ret = VNET_API_ERROR_SYSCALL_ERROR_1;
335 if (setsockopt (*fd, SOL_PACKET, PACKET_LOSS, &opt, sizeof (opt)) < 0)
339 "Failed to set packet tx ring error handling option: %s (errno %d)",
340 strerror (errno), errno);
341 ret = VNET_API_ERROR_SYSCALL_ERROR_1;
345 if (*flags & AF_PACKET_IF_FLAGS_CKSUM_GSO)
349 if (setsockopt (*fd, SOL_PACKET, PACKET_VNET_HDR, &opt2, sizeof (opt2)) <
353 *flags &= ~AF_PACKET_IF_FLAGS_CKSUM_GSO;
354 vlib_log_debug (apm->log_class,
355 "Failed to set packet vnet hdr error handling "
356 "option: %s (errno %d)",
357 strerror (errno), errno);
361 #if defined(PACKET_QDISC_BYPASS)
362 if (*flags & AF_PACKET_IF_FLAGS_QDISC_BYPASS)
363 /* Introduced with Linux 3.14 so the ifdef should eventually be removed */
364 if (setsockopt (*fd, SOL_PACKET, PACKET_QDISC_BYPASS, &opt, sizeof (opt)) <
368 *flags &= ~AF_PACKET_IF_FLAGS_QDISC_BYPASS;
369 vlib_log_debug (apm->log_class,
370 "Failed to set qdisc bypass error "
371 "handling option: %s (errno %d)",
372 strerror (errno), errno);
378 if (*flags & AF_PACKET_IF_FLAGS_FANOUT)
380 int fanout = ((fanout_id & 0xffff) | ((PACKET_FANOUT_HASH) << 16));
381 if (setsockopt (*fd, SOL_PACKET, PACKET_FANOUT, &fanout,
382 sizeof (fanout)) < 0)
385 *flags &= ~AF_PACKET_IF_FLAGS_FANOUT;
386 vlib_log_err (apm->log_class,
387 "Failed to set fanout options: %s (errno %d)",
388 strerror (errno), errno);
389 ret = VNET_API_ERROR_SYSCALL_ERROR_1;
393 if (ver == TPACKET_V2)
395 req_sz = sizeof (tpacket_req_t);
396 ring_sz += rx_req->req.tp_block_size * rx_req->req.tp_block_nr;
399 ring_sz += rx_req->req3.tp_block_size * rx_req->req3.tp_block_nr;
400 if (setsockopt (*fd, SOL_PACKET, PACKET_RX_RING, rx_req, req_sz) < 0)
402 vlib_log_err (apm->log_class,
403 "Failed to set packet rx ring options: %s (errno %d)",
404 strerror (errno), errno);
405 ret = VNET_API_ERROR_SYSCALL_ERROR_1;
412 if (ver == TPACKET_V2)
414 req_sz = sizeof (tpacket_req_t);
415 ring_sz += tx_req->req.tp_block_size * tx_req->req.tp_block_nr;
418 ring_sz += tx_req->req3.tp_block_size * tx_req->req3.tp_block_nr;
419 if (setsockopt (*fd, SOL_PACKET, PACKET_TX_RING, tx_req, req_sz) < 0)
421 vlib_log_err (apm->log_class,
422 "Failed to set packet tx ring options: %s (errno %d)",
423 strerror (errno), errno);
424 ret = VNET_API_ERROR_SYSCALL_ERROR_1;
428 ring->ring_start_addr = mmap (NULL, ring_sz, PROT_READ | PROT_WRITE,
429 MAP_SHARED | MAP_LOCKED, *fd, 0);
430 if (ring->ring_start_addr == MAP_FAILED)
432 vlib_log_err (apm->log_class, "mmap failure: %s (errno %d)",
433 strerror (errno), errno);
434 ret = VNET_API_ERROR_SYSCALL_ERROR_1;
438 ring->ring_size = ring_sz;
451 af_packet_queue_init (vlib_main_t *vm, af_packet_if_t *apif,
452 af_packet_create_if_arg_t *arg,
453 af_packet_queue_t *rx_queue, af_packet_queue_t *tx_queue,
456 af_packet_main_t *apm = &af_packet_main;
457 tpacket_req_u_t *rx_req = 0;
458 tpacket_req_u_t *tx_req = 0;
460 af_packet_ring_t ring = { 0 };
462 u32 rx_frames_per_block, tx_frames_per_block;
463 u32 rx_frame_size, tx_frame_size;
468 rx_frames_per_block = arg->rx_frames_per_block ?
469 arg->rx_frames_per_block :
470 ((apif->version == TPACKET_V3) ?
471 AF_PACKET_DEFAULT_RX_FRAMES_PER_BLOCK :
472 AF_PACKET_DEFAULT_RX_FRAMES_PER_BLOCK_V2);
477 ((apif->version == TPACKET_V3) ? AF_PACKET_DEFAULT_RX_FRAME_SIZE :
478 AF_PACKET_DEFAULT_RX_FRAME_SIZE_V2);
479 vec_validate (rx_queue->rx_req, 0);
480 rx_queue->rx_req->req.tp_block_size =
481 rx_frame_size * rx_frames_per_block;
482 rx_queue->rx_req->req.tp_frame_size = rx_frame_size;
483 rx_queue->rx_req->req.tp_block_nr = (apif->version == TPACKET_V3) ?
484 AF_PACKET_RX_BLOCK_NR :
485 AF_PACKET_RX_BLOCK_NR_V2;
486 rx_queue->rx_req->req.tp_frame_nr =
487 rx_queue->rx_req->req.tp_block_nr * rx_frames_per_block;
488 if (apif->version == TPACKET_V3)
490 rx_queue->rx_req->req3.tp_retire_blk_tov = 1; // 1 ms block timout
491 rx_queue->rx_req->req3.tp_feature_req_word = 0;
492 rx_queue->rx_req->req3.tp_sizeof_priv = 0;
494 rx_req = rx_queue->rx_req;
498 tx_frames_per_block = arg->tx_frames_per_block ?
499 arg->tx_frames_per_block :
500 AF_PACKET_DEFAULT_TX_FRAMES_PER_BLOCK;
501 tx_frame_size = arg->tx_frame_size ? arg->tx_frame_size :
502 AF_PACKET_DEFAULT_TX_FRAME_SIZE;
504 vec_validate (tx_queue->tx_req, 0);
505 tx_queue->tx_req->req.tp_block_size =
506 tx_frame_size * tx_frames_per_block;
507 tx_queue->tx_req->req.tp_frame_size = tx_frame_size;
508 tx_queue->tx_req->req.tp_block_nr = AF_PACKET_TX_BLOCK_NR;
509 tx_queue->tx_req->req.tp_frame_nr =
510 AF_PACKET_TX_BLOCK_NR * tx_frames_per_block;
511 if (apif->version == TPACKET_V3)
513 tx_queue->tx_req->req3.tp_retire_blk_tov = 0;
514 tx_queue->tx_req->req3.tp_sizeof_priv = 0;
515 tx_queue->tx_req->req3.tp_feature_req_word = 0;
517 tx_req = tx_queue->tx_req;
520 if (rx_queue || tx_queue)
523 create_packet_sock (apif->host_if_index, rx_req, tx_req, &fd, &ring,
524 apif->dev_instance, &arg->flags, apif->version);
529 vec_add1 (apif->fds, fd);
530 vec_add1 (apif->rings, ring);
531 ring_addr = ring.ring_start_addr;
537 vec_validate (rx_queue->rx_ring, rx_queue->rx_req->req.tp_block_nr - 1);
538 vec_foreach_index (i, rx_queue->rx_ring)
540 rx_queue->rx_ring[i] =
541 ring_addr + i * rx_queue->rx_req->req.tp_block_size;
544 rx_queue->next_rx_block = 0;
545 rx_queue->queue_id = queue_id;
546 rx_queue->is_rx_pending = 0;
547 ring_addr = ring_addr + rx_queue->rx_req->req.tp_block_size *
548 rx_queue->rx_req->req.tp_block_nr;
554 vec_validate (tx_queue->tx_ring, tx_queue->tx_req->req.tp_block_nr - 1);
555 vec_foreach_index (i, tx_queue->tx_ring)
557 tx_queue->tx_ring[i] =
558 ring_addr + i * tx_queue->tx_req->req.tp_block_size;
561 tx_queue->next_tx_frame = 0;
562 tx_queue->queue_id = queue_id;
563 tx_queue->is_tx_pending = 0;
564 clib_spinlock_init (&tx_queue->lockp);
569 vlib_log_err (apm->log_class, "Failed to set queue %u error", queue_id);
571 vec_free (rx_queue->rx_req);
573 vec_free (tx_queue->tx_req);
578 af_packet_device_init (vlib_main_t *vm, af_packet_if_t *apif,
579 af_packet_create_if_arg_t *args)
581 af_packet_main_t *apm = &af_packet_main;
582 af_packet_queue_t *rx_queue = 0;
583 af_packet_queue_t *tx_queue = 0;
584 u16 nq = clib_min (args->num_rxqs, args->num_txqs);
588 // enable fanout feature for multi-rxqs
589 if (args->num_rxqs > 1)
590 args->flags |= AF_PACKET_IF_FLAGS_FANOUT;
592 vec_validate (apif->rx_queues, args->num_rxqs - 1);
593 vec_validate (apif->tx_queues, args->num_txqs - 1);
597 rx_queue = vec_elt_at_index (apif->rx_queues, i);
598 tx_queue = vec_elt_at_index (apif->tx_queues, i);
599 ret = af_packet_queue_init (vm, apif, args, rx_queue, tx_queue, i);
604 if (args->num_rxqs > args->num_txqs)
606 for (; i < args->num_rxqs; i++)
608 rx_queue = vec_elt_at_index (apif->rx_queues, i);
609 ret = af_packet_queue_init (vm, apif, args, rx_queue, 0, i);
614 else if (args->num_txqs > args->num_rxqs)
616 for (; i < args->num_txqs; i++)
618 tx_queue = vec_elt_at_index (apif->tx_queues, i);
619 ret = af_packet_queue_init (vm, apif, args, 0, tx_queue, i);
625 apif->num_rxqs = args->num_rxqs;
626 apif->num_txqs = args->num_txqs;
630 vlib_log_err (apm->log_class, "Failed to init device error");
635 af_packet_create_if (af_packet_create_if_arg_t *arg)
637 af_packet_main_t *apm = &af_packet_main;
638 vlib_main_t *vm = vlib_get_main ();
641 af_packet_if_t *apif = 0;
643 vnet_sw_interface_t *sw;
644 vnet_main_t *vnm = vnet_get_main ();
645 vnet_hw_if_caps_t caps = VNET_HW_IF_CAP_INT_MODE;
648 u8 *host_if_name_dup = 0;
649 int host_if_index = -1;
651 u32 oflags = 0, i = 0;
653 p = mhash_get (&apm->if_index_by_host_if_name, arg->host_if_name);
656 apif = vec_elt_at_index (apm->interfaces, p[0]);
657 arg->sw_if_index = apif->sw_if_index;
658 return VNET_API_ERROR_IF_ALREADY_EXISTS;
661 host_if_name_dup = vec_dup (arg->host_if_name);
664 * make sure host side of interface is 'UP' before binding AF_PACKET
667 if ((fd2 = socket (AF_UNIX, SOCK_DGRAM, 0)) < 0)
669 vlib_log_debug (apm->log_class,
670 "Failed to create AF_UNIX socket: %s (errno %d)",
671 strerror (errno), errno);
672 ret = VNET_API_ERROR_SYSCALL_ERROR_1;
676 clib_memcpy (ifr.ifr_name, (const char *) arg->host_if_name,
677 vec_len (arg->host_if_name));
678 if (ioctl (fd2, SIOCGIFINDEX, &ifr) < 0)
682 "Failed to retrieve the interface (%s) index: %s (errno %d)",
683 arg->host_if_name, strerror (errno), errno);
684 ret = VNET_API_ERROR_INVALID_INTERFACE;
688 host_if_index = ifr.ifr_ifindex;
689 if (ioctl (fd2, SIOCGIFFLAGS, &ifr) < 0)
691 vlib_log_debug (apm->log_class,
692 "Failed to get the active flag: %s (errno %d)",
693 strerror (errno), errno);
694 ret = VNET_API_ERROR_SYSCALL_ERROR_1;
698 if (!(ifr.ifr_flags & IFF_UP))
700 ifr.ifr_flags |= IFF_UP;
701 if (ioctl (fd2, SIOCSIFFLAGS, &ifr) < 0)
703 vlib_log_debug (apm->log_class,
704 "Failed to set the active flag: %s (errno %d)",
705 strerror (errno), errno);
706 ret = VNET_API_ERROR_SYSCALL_ERROR_1;
717 // check the host interface capabilities
718 oflags = af_packet_get_if_capabilities (arg->host_if_name);
720 ret = is_bridge (arg->host_if_name);
721 if (ret == 0) /* is a bridge, ignore state */
724 /* So far everything looks good, let's create interface */
725 pool_get (apm->interfaces, apif);
726 if_index = apif - apm->interfaces;
728 apif->dev_instance = if_index;
729 apif->host_if_index = host_if_index;
730 apif->host_if_name = host_if_name_dup;
731 apif->per_interface_next_index = ~0;
732 apif->mode = arg->mode;
733 apif->host_interface_oflags = oflags;
736 apif->version = TPACKET_V2;
738 apif->version = TPACKET_V3;
740 ret = af_packet_device_init (vm, apif, arg);
744 ret = af_packet_read_mtu (apif);
749 if (apif->mode != AF_PACKET_IF_MODE_IP)
751 vnet_eth_interface_registration_t eir = {};
752 /*use configured or generate random MAC address */
754 clib_memcpy (hw_addr, arg->hw_addr, 6);
757 f64 now = vlib_time_now (vm);
759 rnd = (u32) (now * 1e6);
760 rnd = random_u32 (&rnd);
762 clib_memcpy (hw_addr + 2, &rnd, sizeof (rnd));
767 eir.dev_class_index = af_packet_device_class.index;
768 eir.dev_instance = apif->dev_instance;
769 eir.address = hw_addr;
770 eir.cb.set_max_frame_size = af_packet_eth_set_max_frame_size;
771 apif->hw_if_index = vnet_eth_register_interface (vnm, &eir);
775 apif->hw_if_index = vnet_register_interface (
776 vnm, af_packet_device_class.index, apif->dev_instance,
777 af_packet_ip_device_hw_interface_class.index, apif->dev_instance);
780 sw = vnet_get_hw_sw_interface (vnm, apif->hw_if_index);
781 apif->sw_if_index = sw->sw_if_index;
783 af_packet_set_rx_queues (vm, apif);
784 af_packet_set_tx_queues (vm, apif);
786 if (arg->flags & AF_PACKET_IF_FLAGS_FANOUT)
787 apif->is_fanout_enabled = 1;
789 apif->is_qdisc_bypass_enabled =
790 (arg->flags & AF_PACKET_IF_FLAGS_QDISC_BYPASS);
792 if (arg->flags & AF_PACKET_IF_FLAGS_CKSUM_GSO)
794 if (apif->host_interface_oflags & AF_PACKET_OFFLOAD_FLAG_TXCKSUM)
796 apif->is_cksum_gso_enabled = 1;
797 caps |= VNET_HW_IF_CAP_TX_IP4_CKSUM | VNET_HW_IF_CAP_TX_TCP_CKSUM |
798 VNET_HW_IF_CAP_TX_UDP_CKSUM;
801 if (apif->host_interface_oflags & AF_PACKET_OFFLOAD_FLAG_GSO)
803 apif->is_cksum_gso_enabled = 1;
804 caps |= VNET_HW_IF_CAP_TCP_GSO | VNET_HW_IF_CAP_TX_IP4_CKSUM |
805 VNET_HW_IF_CAP_TX_TCP_CKSUM | VNET_HW_IF_CAP_TX_UDP_CKSUM;
808 vnet_hw_if_set_caps (vnm, apif->hw_if_index, caps);
809 vnet_hw_interface_set_flags (vnm, apif->hw_if_index,
810 VNET_HW_INTERFACE_FLAG_LINK_UP);
812 mhash_set_mem (&apm->if_index_by_host_if_name, host_if_name_dup, &if_index,
814 arg->sw_if_index = apif->sw_if_index;
824 vec_foreach_index (i, apif->fds)
825 if (apif->fds[i] != -1)
826 close (apif->fds[i]);
827 vec_free (apif->fds);
828 vec_free (host_if_name_dup);
831 memset (apif, 0, sizeof (*apif));
832 pool_put (apm->interfaces, apif);
838 af_packet_rx_queue_free (af_packet_if_t *apif, af_packet_queue_t *rx_queue)
840 clib_file_del_by_index (&file_main, rx_queue->clib_file_index);
842 rx_queue->rx_ring = NULL;
843 vec_free (rx_queue->rx_req);
844 rx_queue->rx_req = NULL;
849 af_packet_tx_queue_free (af_packet_if_t *apif, af_packet_queue_t *tx_queue)
852 clib_spinlock_free (&tx_queue->lockp);
853 tx_queue->tx_ring = NULL;
854 vec_free (tx_queue->tx_req);
855 tx_queue->tx_req = NULL;
860 af_packet_ring_free (af_packet_if_t *apif, af_packet_ring_t *ring)
862 af_packet_main_t *apm = &af_packet_main;
866 // FIXME: unmap the memory
867 if (munmap (ring->ring_start_addr, ring->ring_size))
868 vlib_log_warn (apm->log_class,
869 "Host interface %s could not free ring %p of size %u",
870 apif->host_if_name, ring->ring_start_addr,
873 ring->ring_start_addr = 0;
880 af_packet_delete_if (u8 *host_if_name)
882 vnet_main_t *vnm = vnet_get_main ();
883 af_packet_main_t *apm = &af_packet_main;
884 af_packet_if_t *apif;
885 af_packet_queue_t *rx_queue;
886 af_packet_queue_t *tx_queue;
887 af_packet_ring_t *ring;
891 p = mhash_get (&apm->if_index_by_host_if_name, host_if_name);
894 vlib_log_warn (apm->log_class, "Host interface %s does not exist",
896 return VNET_API_ERROR_SYSCALL_ERROR_1;
898 apif = pool_elt_at_index (apm->interfaces, p[0]);
900 /* bring down the interface */
901 vnet_hw_interface_set_flags (vnm, apif->hw_if_index, 0);
902 if (apif->mode != AF_PACKET_IF_MODE_IP)
903 ethernet_delete_interface (vnm, apif->hw_if_index);
905 vnet_delete_hw_interface (vnm, apif->hw_if_index);
908 vec_foreach_index (i, apif->fds)
909 if (apif->fds[i] != -1)
910 close (apif->fds[i]);
911 vec_foreach (rx_queue, apif->rx_queues)
912 af_packet_rx_queue_free (apif, rx_queue);
913 vec_foreach (tx_queue, apif->tx_queues)
914 af_packet_tx_queue_free (apif, tx_queue);
915 vec_foreach (ring, apif->rings)
916 af_packet_ring_free (apif, ring);
918 vec_free (apif->fds);
920 vec_free (apif->rx_queues);
921 apif->rx_queues = NULL;
922 vec_free (apif->tx_queues);
923 apif->tx_queues = NULL;
924 vec_free (apif->rings);
927 vec_free (apif->host_if_name);
928 apif->host_if_name = NULL;
929 apif->host_if_index = -1;
931 mhash_unset (&apm->if_index_by_host_if_name, host_if_name, p);
933 memset (apif, 0, sizeof (*apif));
934 pool_put (apm->interfaces, apif);
940 af_packet_enable_disable_qdisc_bypass (u32 sw_if_index, u8 enable_disable)
942 af_packet_main_t *apm = &af_packet_main;
943 af_packet_if_t *apif;
944 vnet_main_t *vnm = vnet_get_main ();
945 vnet_hw_interface_t *hw;
948 hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
950 if (hw->dev_class_index != af_packet_device_class.index)
951 return VNET_API_ERROR_INVALID_INTERFACE;
953 apif = pool_elt_at_index (apm->interfaces, hw->dev_instance);
955 #if defined(PACKET_QDISC_BYPASS)
956 vec_foreach_index (i, apif->fds)
962 /* Introduced with Linux 3.14 so the ifdef should eventually be
964 if (setsockopt (apif->fds[i], SOL_PACKET, PACKET_QDISC_BYPASS, &opt,
967 vlib_log_err (apm->log_class,
968 "Failed to enable qdisc bypass error "
969 "handling option: %s (errno %d)",
970 strerror (errno), errno);
972 apif->is_qdisc_bypass_enabled = 1;
977 if (setsockopt (apif->fds[i], SOL_PACKET, PACKET_QDISC_BYPASS, &opt,
980 vlib_log_err (apm->log_class,
981 "Failed to disable qdisc bypass error "
982 "handling option: %s (errno %d)",
983 strerror (errno), errno);
985 apif->is_qdisc_bypass_enabled = 0;
994 af_packet_set_l4_cksum_offload (u32 sw_if_index, u8 set)
1001 af_packet_dump_ifs (af_packet_if_detail_t ** out_af_packet_ifs)
1003 af_packet_main_t *apm = &af_packet_main;
1004 af_packet_if_t *apif;
1005 af_packet_if_detail_t *r_af_packet_ifs = NULL;
1006 af_packet_if_detail_t *af_packet_if = NULL;
1008 pool_foreach (apif, apm->interfaces)
1010 vec_add2 (r_af_packet_ifs, af_packet_if, 1);
1011 af_packet_if->sw_if_index = apif->sw_if_index;
1012 if (apif->host_if_name)
1014 clib_memcpy (af_packet_if->host_if_name, apif->host_if_name,
1015 MIN (ARRAY_LEN (af_packet_if->host_if_name) - 1,
1016 strlen ((const char *) apif->host_if_name)));
1020 *out_af_packet_ifs = r_af_packet_ifs;
1025 static clib_error_t *
1026 af_packet_init (vlib_main_t * vm)
1028 af_packet_main_t *apm = &af_packet_main;
1029 vlib_thread_main_t *tm = vlib_get_thread_main ();
1031 clib_memset (apm, 0, sizeof (af_packet_main_t));
1033 mhash_init_vec_string (&apm->if_index_by_host_if_name, sizeof (uword));
1035 vec_validate_aligned (apm->rx_buffers, tm->n_vlib_mains - 1,
1036 CLIB_CACHE_LINE_BYTES);
1038 apm->log_class = vlib_log_register_class ("af_packet", 0);
1039 vlib_log_debug (apm->log_class, "initialized");
1044 VLIB_INIT_FUNCTION (af_packet_init);
1047 * fd.io coding-style-patch-verification: ON
1050 * eval: (c-set-style "gnu")