summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMohsin Kazmi <sykazmi@cisco.com>2021-10-08 15:10:49 +0000
committerBeno�t Ganne <bganne@cisco.com>2021-10-22 12:37:36 +0000
commitcae84fa96856406c93c37e0a38f67d4c6ee7f48a (patch)
tree617e05be28146aff824d47ed71a28ab72bcf8cde
parent0ad060851b4989a1cd300ad711e8498435f65f9a (diff)
devices: add support for l3 af_packet interface
Type: improvement Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com> Change-Id: Ia6b9d4ac55be2216887bfdb99be4021f6a96f166
-rw-r--r--src/vnet/devices/af_packet/af_packet.c69
-rw-r--r--src/vnet/devices/af_packet/af_packet.h9
-rw-r--r--src/vnet/devices/af_packet/cli.c8
-rw-r--r--src/vnet/devices/af_packet/device.c8
-rw-r--r--src/vnet/devices/af_packet/node.c49
5 files changed, 106 insertions, 37 deletions
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 <vppinfra/lock.h>
-
#include <vlib/log.h>
+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 <ifname> [hw-addr <mac-addr>]",
+ .short_help =
+ "create host-interface name <ifname> [hw-addr <mac-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 */