From 6197cb730e1571ca69859489c0ae7ea90a5c5fd4 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Thu, 3 Jun 2021 14:43:21 +0000 Subject: pg: A Tunnel mode variant of a pg interface Type: feature this allows VPP to simulate linux tun devices. Signed-off-by: Neale Ranns Change-Id: I3adf38b49a254804370f78edd5d275d192fd00a6 --- src/vnet/pg/cli.c | 34 +++++++++++++++++++++++++++++----- src/vnet/pg/pg.api | 22 ++++++++++++++++++++++ src/vnet/pg/pg.h | 14 +++++++++++--- src/vnet/pg/pg_api.c | 35 ++++++++++++++++++++++++++--------- src/vnet/pg/stream.c | 46 +++++++++++++++++++++++++++++++++++++++------- 5 files changed, 127 insertions(+), 24 deletions(-) (limited to 'src/vnet/pg') diff --git a/src/vnet/pg/cli.c b/src/vnet/pg/cli.c index 9da0f8d9981..e57e72573f3 100644 --- a/src/vnet/pg/cli.c +++ b/src/vnet/pg/cli.c @@ -333,6 +333,23 @@ validate_stream (pg_stream_t * s) return 0; } +const char * +pg_interface_get_input_node (pg_interface_t *pi) +{ + switch (pi->mode) + { + case PG_MODE_ETHERNET: + return ("ethernet-input"); + case PG_MODE_IP4: + return ("ip4-input"); + case PG_MODE_IP6: + return ("ip6-input"); + } + + ASSERT (0); + return ("ethernet-input"); +} + static clib_error_t * new_stream (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) @@ -351,7 +368,7 @@ new_stream (vlib_main_t * vm, s.node_index = ~0; s.max_packet_bytes = s.min_packet_bytes = 64; s.buffer_bytes = vlib_buffer_get_default_data_size (vm); - s.if_id = 0; + s.if_id = ~0; s.n_max_frame = VLIB_FRAME_SIZE; pcap_file_name = 0; @@ -427,8 +444,15 @@ new_stream (vlib_main_t * vm, { if (pcap_file_name != 0) { - vlib_node_t *n = - vlib_get_node_by_name (vm, (u8 *) "ethernet-input"); + vlib_node_t *n; + + ASSERT (s.if_id != ~0); + + if (s.if_id != ~0) + n = vlib_get_node_by_name (vm, (u8 *) pg_interface_get_input_node ( + &pg->interfaces[s.if_id])); + else + n = vlib_get_node_by_name (vm, (u8 *) "ethernet-input"); s.node_index = n->index; } else @@ -694,8 +718,8 @@ create_pg_if_cmd_fn (vlib_main_t * vm, } } - pg_interface_add_or_get (pg, if_id, gso_enabled, gso_size, - coalesce_enabled); + pg_interface_add_or_get (pg, if_id, gso_enabled, gso_size, coalesce_enabled, + PG_MODE_ETHERNET); done: unformat_free (line_input); diff --git a/src/vnet/pg/pg.api b/src/vnet/pg/pg.api index 3a44f1d87a7..3630e0c2f0d 100644 --- a/src/vnet/pg/pg.api +++ b/src/vnet/pg/pg.api @@ -22,6 +22,13 @@ option version = "2.0.0"; import "vnet/interface_types.api"; +enum pg_interface_mode : u8 +{ + PG_API_MODE_ETHERNET = 0, + PG_API_MODE_IP4, + PG_API_MODE_IP6, +}; + /** \brief PacketGenerator create interface request @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @@ -37,6 +44,15 @@ define pg_create_interface bool gso_enabled; u32 gso_size; }; +define pg_create_interface_v2 +{ + u32 client_index; + u32 context; + vl_api_interface_index_t interface_id; + bool gso_enabled; + u32 gso_size; + vl_api_pg_interface_mode_t mode; +}; /** \brief PacketGenerator create interface response @param context - sender context, to match reply w/ request @@ -48,6 +64,12 @@ define pg_create_interface_reply i32 retval; vl_api_interface_index_t sw_if_index; }; +define pg_create_interface_v2_reply +{ + u32 context; + i32 retval; + vl_api_interface_index_t sw_if_index; +}; /** \brief PacketGenerator interface enable/disable packet coalesce @param client_index - opaque cookie to identify the sender diff --git a/src/vnet/pg/pg.h b/src/vnet/pg/pg.h index da5af25b22e..ffa2f8a82f4 100644 --- a/src/vnet/pg/pg.h +++ b/src/vnet/pg/pg.h @@ -299,6 +299,13 @@ pg_free_edit_group (pg_stream_t * s) _vec_len (s->edit_groups) = i; } +typedef enum pg_interface_mode_t_ +{ + PG_MODE_ETHERNET, + PG_MODE_IP4, + PG_MODE_IP6, +} pg_interface_mode_t; + typedef struct { /* TX lock */ @@ -316,6 +323,7 @@ typedef struct u32 gso_size; pcap_main_t pcap_main; char *pcap_file_name; + pg_interface_mode_t mode; mac_address_t *allowed_mcast_macs; } pg_interface_t; @@ -373,9 +381,9 @@ void pg_interface_enable_disable_coalesce (pg_interface_t * pi, u8 enable, u32 tx_node_index); /* Find/create free packet-generator interface index. */ -u32 pg_interface_add_or_get (pg_main_t * pg, uword stream_index, - u8 gso_enabled, u32 gso_size, - u8 coalesce_enabled); +u32 pg_interface_add_or_get (pg_main_t *pg, uword stream_index, u8 gso_enabled, + u32 gso_size, u8 coalesce_enabled, + pg_interface_mode_t mode); always_inline pg_node_t * pg_get_node (uword node_index) diff --git a/src/vnet/pg/pg_api.c b/src/vnet/pg/pg_api.c index 554e8ea31c1..b3eb315e807 100644 --- a/src/vnet/pg/pg_api.c +++ b/src/vnet/pg/pg_api.c @@ -40,12 +40,13 @@ #include - -#define foreach_pg_api_msg \ -_(PG_CREATE_INTERFACE, pg_create_interface) \ -_(PG_CAPTURE, pg_capture) \ -_(PG_ENABLE_DISABLE, pg_enable_disable) \ -_(PG_INTERFACE_ENABLE_DISABLE_COALESCE, pg_interface_enable_disable_coalesce) +#define foreach_pg_api_msg \ + _ (PG_CREATE_INTERFACE, pg_create_interface) \ + _ (PG_CREATE_INTERFACE_V2, pg_create_interface_v2) \ + _ (PG_CAPTURE, pg_capture) \ + _ (PG_ENABLE_DISABLE, pg_enable_disable) \ + _ (PG_INTERFACE_ENABLE_DISABLE_COALESCE, \ + pg_interface_enable_disable_coalesce) static void vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp) @@ -54,9 +55,9 @@ vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp) int rv = 0; pg_main_t *pg = &pg_main; - u32 pg_if_id = pg_interface_add_or_get (pg, ntohl (mp->interface_id), - mp->gso_enabled, - ntohl (mp->gso_size), 0); + u32 pg_if_id = + pg_interface_add_or_get (pg, ntohl (mp->interface_id), mp->gso_enabled, + ntohl (mp->gso_size), 0, PG_MODE_ETHERNET); pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id); /* *INDENT-OFF* */ @@ -67,6 +68,22 @@ vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp) /* *INDENT-ON* */ } +static void +vl_api_pg_create_interface_v2_t_handler (vl_api_pg_create_interface_v2_t *mp) +{ + vl_api_pg_create_interface_v2_reply_t *rmp; + int rv = 0; + + pg_main_t *pg = &pg_main; + u32 pg_if_id = + pg_interface_add_or_get (pg, ntohl (mp->interface_id), mp->gso_enabled, + ntohl (mp->gso_size), 0, (u8) mp->mode); + pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id); + + REPLY_MACRO2 (VL_API_PG_CREATE_INTERFACE_V2_REPLY, + ({ rmp->sw_if_index = ntohl (pi->sw_if_index); })); +} + static void vl_api_pg_interface_enable_disable_coalesce_t_handler (vl_api_pg_interface_enable_disable_coalesce_t * mp) diff --git a/src/vnet/pg/stream.c b/src/vnet/pg/stream.c index 0ce640bf13f..686627b8d9a 100644 --- a/src/vnet/pg/stream.c +++ b/src/vnet/pg/stream.c @@ -229,9 +229,29 @@ pg_interface_enable_disable_coalesce (pg_interface_t * pi, u8 enable, } } +u8 * +format_pg_tun_tx_trace (u8 *s, va_list *args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + + s = format (s, "PG: tunnel (no-encap)"); + return s; +} + +VNET_HW_INTERFACE_CLASS (pg_tun_hw_interface_class) = { + .name = "PG-tun", + //.format_header = format_gre_header_with_length, + //.unformat_header = unformat_gre_header, + .build_rewrite = NULL, + //.update_adjacency = gre_update_adj, + .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P, +}; + u32 -pg_interface_add_or_get (pg_main_t * pg, uword if_id, u8 gso_enabled, - u32 gso_size, u8 coalesce_enabled) +pg_interface_add_or_get (pg_main_t *pg, uword if_id, u8 gso_enabled, + u32 gso_size, u8 coalesce_enabled, + pg_interface_mode_t mode) { vnet_main_t *vnm = vnet_get_main (); vlib_main_t *vm = vlib_get_main (); @@ -262,8 +282,20 @@ pg_interface_add_or_get (pg_main_t * pg, uword if_id, u8 gso_enabled, hw_addr[1] = 0xfe; pi->id = if_id; - ethernet_register_interface (vnm, pg_dev_class.index, i, hw_addr, - &pi->hw_if_index, pg_eth_flag_change); + pi->mode = mode; + + switch (pi->mode) + { + case PG_MODE_ETHERNET: + ethernet_register_interface (vnm, pg_dev_class.index, i, hw_addr, + &pi->hw_if_index, pg_eth_flag_change); + break; + case PG_MODE_IP4: + case PG_MODE_IP6: + pi->hw_if_index = vnet_register_interface ( + vnm, pg_dev_class.index, i, pg_tun_hw_interface_class.index, i); + break; + } hi = vnet_get_hw_interface (vnm, pi->hw_if_index); if (gso_enabled) { @@ -510,9 +542,9 @@ pg_stream_add (pg_main_t * pg, pg_stream_t * s_init) } /* Find an interface to use. */ - s->pg_if_index = - pg_interface_add_or_get (pg, s->if_id, 0 /* gso_enabled */ , - 0 /* gso_size */ , 0 /* coalesce_enabled */ ); + s->pg_if_index = pg_interface_add_or_get ( + pg, s->if_id, 0 /* gso_enabled */, 0 /* gso_size */, + 0 /* coalesce_enabled */, PG_MODE_ETHERNET); if (s->sw_if_index[VLIB_RX] == ~0) { -- cgit 1.2.3-korg