From cae84fa96856406c93c37e0a38f67d4c6ee7f48a Mon Sep 17 00:00:00 2001 From: Mohsin Kazmi Date: Fri, 8 Oct 2021 15:10:49 +0000 Subject: devices: add support for l3 af_packet interface Type: improvement Signed-off-by: Mohsin Kazmi Change-Id: Ia6b9d4ac55be2216887bfdb99be4021f6a96f166 --- src/vnet/devices/af_packet/af_packet.c | 69 +++++++++++++++++++++------------- src/vnet/devices/af_packet/af_packet.h | 9 ++++- src/vnet/devices/af_packet/cli.c | 8 +++- src/vnet/devices/af_packet/device.c | 8 ++++ src/vnet/devices/af_packet/node.c | 49 +++++++++++++++++++----- 5 files changed, 106 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/vnet/devices/af_packet/af_packet.c b/src/vnet/devices/af_packet/af_packet.c index 2dc263046cb..69e3c871412 100644 --- a/src/vnet/devices/af_packet/af_packet.c +++ b/src/vnet/devices/af_packet/af_packet.c @@ -38,6 +38,11 @@ af_packet_main_t af_packet_main; +VNET_HW_INTERFACE_CLASS (af_packet_ip_device_hw_interface_class, static) = { + .name = "af-packet-ip-device", + .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P, +}; + #define AF_PACKET_DEFAULT_TX_FRAMES_PER_BLOCK 1024 #define AF_PACKET_DEFAULT_TX_FRAME_SIZE (2048 * 5) #define AF_PACKET_TX_BLOCK_NR 1 @@ -367,6 +372,7 @@ af_packet_create_if (af_packet_create_if_arg_t *arg) apif->per_interface_next_index = ~0; apif->next_tx_frame = 0; apif->next_rx_frame = 0; + apif->mode = arg->mode; ret = af_packet_read_mtu (apif); if (ret != 0) @@ -375,36 +381,44 @@ af_packet_create_if (af_packet_create_if_arg_t *arg) if (tm->n_vlib_mains > 1) clib_spinlock_init (&apif->lockp); - /*use configured or generate random MAC address */ - if (arg->hw_addr) - clib_memcpy (hw_addr, arg->hw_addr, 6); - else + if (apif->mode == AF_PACKET_IF_MODE_ETHERNET) { - f64 now = vlib_time_now (vm); - u32 rnd; - rnd = (u32) (now * 1e6); - rnd = random_u32 (&rnd); - - clib_memcpy (hw_addr + 2, &rnd, sizeof (rnd)); - hw_addr[0] = 2; - hw_addr[1] = 0xfe; - } + /*use configured or generate random MAC address */ + if (arg->hw_addr) + clib_memcpy (hw_addr, arg->hw_addr, 6); + else + { + f64 now = vlib_time_now (vm); + u32 rnd; + rnd = (u32) (now * 1e6); + rnd = random_u32 (&rnd); + + clib_memcpy (hw_addr + 2, &rnd, sizeof (rnd)); + hw_addr[0] = 2; + hw_addr[1] = 0xfe; + } - error = ethernet_register_interface (vnm, af_packet_device_class.index, - if_index, hw_addr, &apif->hw_if_index, - af_packet_eth_flag_change); + error = ethernet_register_interface ( + vnm, af_packet_device_class.index, if_index, hw_addr, + &apif->hw_if_index, af_packet_eth_flag_change); - if (error) + if (error) + { + clib_memset (apif, 0, sizeof (*apif)); + pool_put (apm->interfaces, apif); + vlib_log_err (apm->log_class, "Unable to register interface: %U", + format_clib_error, error); + clib_error_free (error); + ret = VNET_API_ERROR_SYSCALL_ERROR_1; + goto error; + } + } + else { - clib_memset (apif, 0, sizeof (*apif)); - pool_put (apm->interfaces, apif); - vlib_log_err (apm->log_class, "Unable to register interface: %U", - format_clib_error, error); - clib_error_free (error); - ret = VNET_API_ERROR_SYSCALL_ERROR_1; - goto error; + apif->hw_if_index = vnet_register_interface ( + vnm, af_packet_device_class.index, if_index, + af_packet_ip_device_hw_interface_class.index, if_index); } - sw = vnet_get_hw_sw_interface (vnm, apif->hw_if_index); hw = vnet_get_hw_interface (vnm, apif->hw_if_index); apif->sw_if_index = sw->sw_if_index; @@ -504,7 +518,10 @@ af_packet_delete_if (u8 *host_if_name) mhash_unset (&apm->if_index_by_host_if_name, host_if_name, &if_index); - ethernet_delete_interface (vnm, apif->hw_if_index); + if (apif->mode == AF_PACKET_IF_MODE_ETHERNET) + ethernet_delete_interface (vnm, apif->hw_if_index); + else + vnet_delete_hw_interface (vnm, apif->hw_if_index); pool_put (apm->interfaces, apif); diff --git a/src/vnet/devices/af_packet/af_packet.h b/src/vnet/devices/af_packet/af_packet.h index 3163aa0323e..652e173fd2a 100644 --- a/src/vnet/devices/af_packet/af_packet.h +++ b/src/vnet/devices/af_packet/af_packet.h @@ -18,9 +18,14 @@ */ #include - #include +typedef enum +{ + AF_PACKET_IF_MODE_ETHERNET = 1, + AF_PACKET_IF_MODE_IP = 2 +} af_packet_if_mode_t; + typedef struct { u32 sw_if_index; @@ -49,6 +54,7 @@ typedef struct u8 is_admin_up; u32 queue_index; u32 host_mtu; + af_packet_if_mode_t mode; } af_packet_if_t; typedef struct @@ -77,6 +83,7 @@ typedef struct u32 tx_frame_size; u32 rx_frames_per_block; u32 tx_frames_per_block; + af_packet_if_mode_t mode; /* return */ u32 sw_if_index; diff --git a/src/vnet/devices/af_packet/cli.c b/src/vnet/devices/af_packet/cli.c index bae4f6181b0..3dd3c8ee848 100644 --- a/src/vnet/devices/af_packet/cli.c +++ b/src/vnet/devices/af_packet/cli.c @@ -51,6 +51,9 @@ af_packet_create_command_fn (vlib_main_t * vm, unformat_input_t * input, clib_memset (arg, 0, sizeof (*arg)); + // Default mode + arg->mode = AF_PACKET_IF_MODE_ETHERNET; + /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -69,6 +72,8 @@ af_packet_create_command_fn (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "tx-per-block %u", &arg->tx_frames_per_block)) ; + else if (unformat (line_input, "mode ip")) + arg->mode = AF_PACKET_IF_MODE_IP; else if (unformat (line_input, "hw-addr %U", unformat_ethernet_address, hwaddr)) arg->hw_addr = hwaddr; @@ -140,7 +145,8 @@ done: ?*/ VLIB_CLI_COMMAND (af_packet_create_command, static) = { .path = "create host-interface", - .short_help = "create host-interface name [hw-addr ]", + .short_help = + "create host-interface name [hw-addr ] [mode ip]", .function = af_packet_create_command_fn, }; diff --git a/src/vnet/devices/af_packet/device.c b/src/vnet/devices/af_packet/device.c index 0542b165a3a..8e4bc2b6b7f 100644 --- a/src/vnet/devices/af_packet/device.c +++ b/src/vnet/devices/af_packet/device.c @@ -339,6 +339,14 @@ static clib_error_t *af_packet_set_mac_address_function int rv, fd = socket (AF_UNIX, SOCK_DGRAM, 0); struct ifreq ifr; + if (apif->mode == AF_PACKET_IF_MODE_IP) + { + vlib_log_warn (apm->log_class, "af_packet_%s interface is in IP mode", + apif->host_if_name); + return clib_error_return (0, + " MAC update failed, interface is in IP mode"); + } + if (0 > fd) { vlib_log_warn (apm->log_class, "af_packet_%s could not open socket", diff --git a/src/vnet/devices/af_packet/node.c b/src/vnet/devices/af_packet/node.c index e2f87b10b35..0fdae5c3039 100644 --- a/src/vnet/devices/af_packet/node.c +++ b/src/vnet/devices/af_packet/node.c @@ -194,7 +194,7 @@ af_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, { af_packet_main_t *apm = &af_packet_main; struct tpacket2_hdr *tph; - u32 next_index = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT; + u32 next_index; u32 block = 0; u32 rx_frame; u32 n_free_bufs; @@ -209,6 +209,21 @@ af_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, u32 thread_index = vm->thread_index; u32 n_buffer_bytes = vlib_buffer_get_default_data_size (vm); u32 min_bufs = apif->rx_req->tp_frame_size / n_buffer_bytes; + vlib_buffer_t bt; + + if (apif->mode == AF_PACKET_IF_MODE_IP) + { + next_index = VNET_DEVICE_INPUT_NEXT_IP4_INPUT; + } + else + { + next_index = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT; + if (PREDICT_FALSE (apif->per_interface_next_index != ~0)) + next_index = apif->per_interface_next_index; + + /* redirect if feature path enabled */ + vnet_feature_start_device_input_x1 (apif->sw_if_index, &next_index, &bt); + } n_free_bufs = vec_len (apm->rx_buffers[thread_index]); if (PREDICT_FALSE (n_free_bufs < VLIB_FRAME_SIZE)) @@ -317,14 +332,30 @@ af_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, } else { - next0 = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT; - - if (PREDICT_FALSE (apif->per_interface_next_index != ~0)) - next0 = apif->per_interface_next_index; - - /* redirect if feature path enabled */ - vnet_feature_start_device_input_x1 (apif->sw_if_index, &next0, - first_b0); + if (PREDICT_FALSE (apif->mode == AF_PACKET_IF_MODE_IP)) + { + switch (first_b0->data[0] & 0xf0) + { + case 0x40: + next0 = VNET_DEVICE_INPUT_NEXT_IP4_INPUT; + break; + case 0x60: + next0 = VNET_DEVICE_INPUT_NEXT_IP6_INPUT; + break; + default: + next0 = VNET_DEVICE_INPUT_NEXT_DROP; + break; + } + if (PREDICT_FALSE (apif->per_interface_next_index != ~0)) + next0 = apif->per_interface_next_index; + } + else + { + /* copy feature arc data from template */ + first_b0->current_config_index = bt.current_config_index; + vnet_buffer (first_b0)->feature_arc_index = + vnet_buffer (&bt)->feature_arc_index; + } } /* trace */ -- cgit 1.2.3-korg