X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fpg%2Fstream.c;h=112cc09ae975a8d7f97eafea59535ebb35e41426;hb=f0fc65a4b949a6e5a44250d405ce219b8e547859;hp=1ed7189ffc9e54a91551494c05501ca13f2effb2;hpb=7cd468a3d7dee7d6c92f69a0bb7061ae208ec727;p=vpp.git diff --git a/src/vnet/pg/stream.c b/src/vnet/pg/stream.c index 1ed7189ffc9..112cc09ae97 100644 --- a/src/vnet/pg/stream.c +++ b/src/vnet/pg/stream.c @@ -94,6 +94,24 @@ pg_stream_enable_disable (pg_main_t * pg, pg_stream_t * s, int want_enabled) s->time_last_generate = 0; } +static u8 * +format_pg_output_trace (u8 * s, va_list * va) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *); + pg_output_trace_t *t = va_arg (*va, pg_output_trace_t *); + u32 indent = format_get_indent (s); + + s = format (s, "%Ubuffer 0x%x: %U", format_white_space, indent, + t->buffer_index, format_vnet_buffer_no_chain, &t->buffer); + + s = format (s, "\n%U%U", format_white_space, indent, + format_ethernet_header_with_length, t->buffer.pre_data, + sizeof (t->buffer.pre_data)); + + return s; +} + static u8 * format_pg_interface_name (u8 * s, va_list * args) { @@ -120,12 +138,47 @@ pg_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags) return 0; } +static int +pg_mac_address_cmp (const mac_address_t * m1, const mac_address_t * m2) +{ + return (!mac_address_cmp (m1, m2)); +} + +static clib_error_t * +pg_add_del_mac_address (vnet_hw_interface_t * hi, + const u8 * address, u8 is_add) +{ + pg_main_t *pg = &pg_main; + + if (ethernet_address_cast (address)) + { + mac_address_t mac; + pg_interface_t *pi; + + pi = pool_elt_at_index (pg->interfaces, hi->dev_instance); + + mac_address_from_bytes (&mac, address); + if (is_add) + vec_add1 (pi->allowed_mcast_macs, mac); + else + { + u32 pos = vec_search_with_function (pi->allowed_mcast_macs, &mac, + pg_mac_address_cmp); + if (~0 != pos) + vec_del1 (pi->allowed_mcast_macs, pos); + } + } + return (NULL); +} + /* *INDENT-OFF* */ VNET_DEVICE_CLASS (pg_dev_class) = { .name = "pg", .tx_function = pg_output, .format_device_name = format_pg_interface_name, + .format_tx_trace = format_pg_output_trace, .admin_up_down_function = pg_interface_admin_up_down, + .mac_addr_add_del_function = pg_add_del_mac_address, }; /* *INDENT-ON* */ @@ -158,8 +211,47 @@ pg_eth_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi, u32 flags) return 0; } +void +pg_interface_enable_disable_coalesce (pg_interface_t * pi, u8 enable, + u32 tx_node_index) +{ + if (enable) + { + gro_flow_table_init (&pi->flow_table, 1 /* is_l2 */ , + tx_node_index); + pi->coalesce_enabled = 1; + } + else + { + pi->coalesce_enabled = 0; + gro_flow_table_free (pi->flow_table); + } +} + +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, + .tx_hash_fn_type = VNET_HASH_FN_TYPE_IP, +}; + u32 -pg_interface_add_or_get (pg_main_t * pg, uword if_id) +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 (); @@ -176,6 +268,7 @@ pg_interface_add_or_get (pg_main_t * pg, uword if_id) } else { + vnet_eth_interface_registration_t eir = {}; u8 hw_addr[6]; f64 now = vlib_time_now (vm); u32 rnd; @@ -185,28 +278,52 @@ pg_interface_add_or_get (pg_main_t * pg, uword if_id) rnd = (u32) (now * 1e6); rnd = random_u32 (&rnd); - clib_memcpy (hw_addr + 2, &rnd, sizeof (rnd)); + clib_memcpy_fast (hw_addr + 2, &rnd, sizeof (rnd)); hw_addr[0] = 2; 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: + eir.dev_class_index = pg_dev_class.index; + eir.dev_instance = i; + eir.address = hw_addr; + eir.cb.flag_change = pg_eth_flag_change; + pi->hw_if_index = vnet_eth_register_interface (vnm, &eir); + 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) + { + vnet_hw_if_set_caps (vnm, pi->hw_if_index, VNET_HW_IF_CAP_TCP_GSO); + pi->gso_enabled = 1; + pi->gso_size = gso_size; + if (coalesce_enabled) + { + pg_interface_enable_disable_coalesce (pi, 1, hi->tx_node_index); + } + } pi->sw_if_index = hi->sw_if_index; hash_set (pg->if_index_by_if_id, if_id, i); + vec_validate (pg->if_id_by_sw_if_index, hi->sw_if_index); + pg->if_id_by_sw_if_index[hi->sw_if_index] = i; + if (vlib_num_workers ()) { pi->lockp = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES, CLIB_CACHE_LINE_BYTES); *pi->lockp = 0; } - - ip4_sw_interface_enable_disable (pi->hw_if_index, 1); - ip6_sw_interface_enable_disable (pi->hw_if_index, 1); - mpls_sw_interface_enable_disable (&mpls_main, pi->hw_if_index, 1); } return i; @@ -317,10 +434,10 @@ pg_edit_group_get_fixed_packet_data (pg_stream_t * s, vec_foreach (e, g->edits) do_edit (s, g, e, /* want_commit */ 0); - clib_memcpy (packet_data, g->fixed_packet_data, - vec_len (g->fixed_packet_data)); - clib_memcpy (packet_data_mask, g->fixed_packet_data_mask, - vec_len (g->fixed_packet_data_mask)); + clib_memcpy_fast (packet_data, g->fixed_packet_data, + vec_len (g->fixed_packet_data)); + clib_memcpy_fast (packet_data_mask, g->fixed_packet_data_mask, + vec_len (g->fixed_packet_data_mask)); } static void @@ -419,46 +536,30 @@ pg_stream_add (pg_main_t * pg, pg_stream_t * s_init) s->last_increment_packet_size = s->min_packet_bytes; { - pg_buffer_index_t *bi; int n; -#if DPDK > 0 - s->buffer_bytes = VLIB_BUFFER_DATA_SIZE; -#endif - - if (!s->buffer_bytes) - s->buffer_bytes = s->max_packet_bytes; - - s->buffer_bytes = vlib_buffer_round_size (s->buffer_bytes); - + s->buffer_bytes = vlib_buffer_get_default_data_size (vm); n = s->max_packet_bytes / s->buffer_bytes; n += (s->max_packet_bytes % s->buffer_bytes) != 0; vec_resize (s->buffer_indices, n); - - vec_foreach (bi, s->buffer_indices) - { - bi->free_list_index = - vlib_buffer_create_free_list (vm, s->buffer_bytes, - "pg stream %d buffer #%d", - s - pg->streams, - 1 + (bi - s->buffer_indices)); - } } /* Find an interface to use. */ - s->pg_if_index = pg_interface_add_or_get (pg, s->if_id); - - { - pg_interface_t *pi = pool_elt_at_index (pg->interfaces, s->pg_if_index); - vlib_rx_or_tx_t rx_or_tx; + 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); - vlib_foreach_rx_tx (rx_or_tx) + if (s->sw_if_index[VLIB_RX] == ~0) { - if (s->sw_if_index[rx_or_tx] == ~0) - s->sw_if_index[rx_or_tx] = pi->sw_if_index; + pg_interface_t *pi = pool_elt_at_index (pg->interfaces, s->pg_if_index); + /* + * Default the RX interface if unset. It's a bad mistake to + * set [VLIB_TX] prior to ip lookup, since the ip lookup code + * interprets [VLIB_TX] as a fib index... + */ + s->sw_if_index[VLIB_RX] = pi->sw_if_index; } - } /* Connect the graph. */ s->next_index = vlib_node_add_next (vm, device_input_node.index, @@ -468,7 +569,6 @@ pg_stream_add (pg_main_t * pg, pg_stream_t * s_init) void pg_stream_del (pg_main_t * pg, uword index) { - vlib_main_t *vm = vlib_get_main (); pg_stream_t *s; pg_buffer_index_t *bi; @@ -479,7 +579,6 @@ pg_stream_del (pg_main_t * pg, uword index) vec_foreach (bi, s->buffer_indices) { - vlib_buffer_delete_free_list (vm, bi->free_list_index); clib_fifo_free (bi->buffer_fifo); } @@ -487,6 +586,31 @@ pg_stream_del (pg_main_t * pg, uword index) pool_put (pg->streams, s); } +void +pg_stream_change (pg_main_t * pg, pg_stream_t * s) +{ + /* Determine packet size. */ + switch (s->packet_size_edit_type) + { + case PG_EDIT_INCREMENT: + case PG_EDIT_RANDOM: + if (s->min_packet_bytes == s->max_packet_bytes) + s->packet_size_edit_type = PG_EDIT_FIXED; + case PG_EDIT_FIXED: + break; + + default: + /* Get packet size from fixed edits. */ + s->packet_size_edit_type = PG_EDIT_FIXED; + if (!s->replay_packet_templates) + s->min_packet_bytes = s->max_packet_bytes = + vec_len (s->fixed_packet_data); + break; + } + + s->last_increment_packet_size = s->min_packet_bytes; +} + /* * fd.io coding-style-patch-verification: ON