/* * Copyright (c) 2016 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef included_ixge_h #define included_ixge_h #include #include #include #include #include #include typedef volatile struct { /* [31:7] 128 byte aligned. */ u32 descriptor_address[2]; u32 n_descriptor_bytes; /* [5] rx/tx descriptor dca enable [6] rx packet head dca enable [7] rx packet tail dca enable [9] rx/tx descriptor relaxed order [11] rx/tx descriptor write back relaxed order [13] rx/tx data write/read relaxed order [15] rx head data write relaxed order [31:24] apic id for cpu's cache. */ u32 dca_control; u32 head_index; /* [4:0] tail buffer size (in 1k byte units) [13:8] head buffer size (in 64 byte units) [24:22] lo free descriptors threshold (units of 64 descriptors) [27:25] descriptor type 0 = legacy, 1 = advanced one buffer (e.g. tail), 2 = advanced header splitting (head + tail), 5 = advanced header splitting (head only). [28] drop if no descriptors available. */ u32 rx_split_control; u32 tail_index; CLIB_PAD_FROM_TO (0x1c, 0x28); /* [7:0] rx/tx prefetch threshold [15:8] rx/tx host threshold [24:16] rx/tx write back threshold [25] rx/tx enable [26] tx descriptor writeback flush [30] rx strip vlan enable */ u32 control; u32 rx_coallesce_control; union { struct { /* packets bytes lo hi */ u32 stats[3]; u32 unused; } rx; struct { u32 unused[2]; /* [0] enables head write back. */ u32 head_index_write_back_address[2]; } tx; }; } ixge_dma_regs_t; /* Only advanced descriptors are supported. */ typedef struct { u64 tail_address; u64 head_address; } ixge_rx_to_hw_descriptor_t; typedef struct { u32 status[3]; u16 n_packet_bytes_this_descriptor; u16 vlan_tag; } ixge_rx_from_hw_descriptor_t; #define IXGE_RX_DESCRIPTOR_STATUS0_IS_LAYER2 (1 << (4 + 11)) /* Valid if not layer2. */ #define IXGE_RX_DESCRIPTOR_STATUS0_IS_IP4 (1 << (4 + 0)) #define IXGE_RX_DESCRIPTOR_STATUS0_IS_IP4_EXT (1 << (4 + 1)) #define IXGE_RX_DESCRIPTOR_STATUS0_IS_IP6 (1 << (4 + 2)) #define IXGE_RX_DESCRIPTOR_STATUS0_IS_IP6_EXT (1 << (4 + 3)) #define IXGE_RX_DESCRIPTOR_STATUS0_IS_TCP (1 << (4 + 4)) #define IXGE_RX_DESCRIPTOR_STATUS0_IS_UDP (1 << (4 + 5)) #define IXGE_RX_DESCRIPTOR_STATUS0_L3_OFFSET(s) (((s) >> 21) & 0x3ff) #define IXGE_RX_DESCRIPTOR_STATUS2_IS_OWNED_BY_SOFTWARE (1 << (0 + 0)) #define IXGE_RX_DESCRIPTOR_STATUS2_IS_END_OF_PACKET (1 << (0 + 1)) #define IXGE_RX_DESCRIPTOR_STATUS2_IS_VLAN (1 << (0 + 3)) #define IXGE_RX_DESCRIPTOR_STATUS2_IS_UDP_CHECKSUMMED (1 << (0 + 4)) #define IXGE_RX_DESCRIPTOR_STATUS2_IS_TCP_CHECKSUMMED (1 << (0 + 5)) #define IXGE_RX_DESCRIPTOR_STATUS2_IS_IP4_CHECKSUMMED (1 << (0 + 6)) #define IXGE_RX_DESCRIPTOR_STATUS2_NOT_UNICAST (1 << (0 + 7)) #define IXGE_RX_DESCRIPTOR_STATUS2_IS_DOUBLE_VLAN (1 << (0 + 9)) #define IXGE_RX_DESCRIPTOR_STATUS2_UDP_CHECKSUM_ERROR (1 << (0 + 10)) #define IXGE_RX_DESCRIPTOR_STATUS2_ETHERNET_ERROR (1 << (20 + 9)) #define IXGE_RX_DESCRIPTOR_STATUS2_TCP_CHECKSUM_ERROR (1 << (20 + 10)) #define IXGE_RX_DESCRIPTOR_STATUS2_IP4_CHECKSUM_ERROR (1 << (20 + 11)) /* For layer2 packets stats0 bottom 3 bits give ether type index from filter. */ #define IXGE_RX_DESCRIPTOR_STATUS0_LAYER2_ETHERNET_TYPE(s) ((s) & 7) typedef struct { u64 buffer_address; u16 n_bytes_this_buffer; u16 status0; u32 status1; #define IXGE_TX_DESCRIPTOR_STATUS0_ADVANCED (3 << 4) #define IXGE_TX_DESCRIPTOR_STATUS0_IS_ADVANCED (1 << (8 + 5)) #define IXGE_TX_DESCRIPTOR_STATUS0_LOG2_REPORT_STATUS (8 + 3) #define IXGE_TX_DESCRIPTOR_STATUS0_REPORT_STATUS (1 << IXGE_TX_DESCRIPTOR_STATUS0_LOG2_REPORT_STATUS) #define IXGE_TX_DESCRIPTOR_STATUS0_INSERT_FCS (1 << (8 + 1)) #define IXGE_TX_DESCRIPTOR_STATUS0_LOG2_IS_END_OF_PACKET (8 + 0) #define IXGE_TX_DESCRIPTOR_STATUS0_IS_END_OF_PACKET (1 << IXGE_TX_DESCRIPTOR_STATUS0_LOG2_IS_END_OF_PACKET) #define IXGE_TX_DESCRIPTOR_STATUS1_DONE (1 << 0) #define IXGE_TX_DESCRIPTOR_STATUS1_CONTEXT(i) (/* valid */ (1 << 7) | ((i) << 4)) #define IXGE_TX_DESCRIPTOR_STATUS1_IPSEC_OFFLOAD (1 << (8 + 2)) #define IXGE_TX_DESCRIPTOR_STATUS1_INSERT_TCP_UDP_CHECKSUM (1 << (8 + 1)) #define IXGE_TX_DESCRIPTOR_STATUS1_INSERT_IP4_CHECKSUM (1 << (8 + 0)) #define IXGE_TX_DESCRIPTOR_STATUS0_N_BYTES_THIS_BUFFER(l) ((l) << 0) #define IXGE_TX_DESCRIPTOR_STATUS1_N_BYTES_IN_PACKET(l) ((l) << 14) } ixge_tx_descriptor_t; typedef struct { struct { u8 checksum_start_offset; u8 checksum_insert_offset; u16 checksum_end_offset; } ip, tcp; u32 status0; u8 status1; /* Byte offset after UDP/TCP header. */ u8 payload_offset; u16 max_tcp_segment_size; } __attribute__ ((packed)) ixge_tx_context_descriptor_t; typedef union { ixge_rx_to_hw_descriptor_t rx_to_hw; ixge_rx_from_hw_descriptor_t rx_from_hw; ixge_tx_descriptor_t tx; u32x4 as_u32x4; } ixge_descriptor_t; typedef volatile struct { /* [2] pcie master disable [3] mac reset [26] global device reset */ u32 control; u32 control_alias; /* [3:2] device id (0 or 1 for dual port chips) [7] link is up [17:10] num vfs [18] io active [19] pcie master enable status */ u32 status_read_only; CLIB_PAD_FROM_TO (0xc, 0x18); /* [14] pf reset done [17] relaxed ordering disable [26] extended vlan enable [28] driver loaded */ u32 extended_control; CLIB_PAD_FROM_TO (0x1c, 0x20); /* software definable pins. sdp_data [7:0] sdp_is_output [15:8] sdp_is_native [23:16] sdp_function [31:24]. */ u32 sdp_control; CLIB_PAD_FROM_TO (0x24, 0x28); /* [0] i2c clock in [1] i2c clock out [2] i2c data in [3] i2c data out */ u32 i2c_control; CLIB_PAD_FROM_TO (0x2c, 0x4c); u32 tcp_timer; CLIB_PAD_FROM_TO (0x50, 0x200); u32 led_control; CLIB_PAD_FROM_TO (0x204, 0x600); u32 core_spare; CLIB_PAD_FROM_TO (0x604, 0x700); struct { u32 vflr_events_clear[4]; u32 mailbox_interrupt_status[4]; u32 mailbox_interrupt_enable[4]; CLIB_PAD_FROM_TO (0x730, 0x800); } pf_foo; struct { u32 status_write_1_to_clear; CLIB_PAD_FROM_TO (0x804, 0x808); u32 status_write_1_to_set; CLIB_PAD_FROM_TO (0x80c, 0x810); u32 status_auto_clear_enable; CLIB_PAD_FROM_TO (0x814, 0x820); /* [11:3] minimum inter-interrupt interval (2e-6 units; 20e-6 units for fast ethernet). [15] low-latency interrupt moderation enable [20:16] low-latency interrupt credit [27:21] interval counter [31] write disable for credit and counter (write only). */ u32 throttle0[24]; u32 enable_write_1_to_set; CLIB_PAD_FROM_TO (0x884, 0x888); u32 enable_write_1_to_clear; CLIB_PAD_FROM_TO (0x88c, 0x890); u32 enable_auto_clear; u32 msi_to_eitr_select; /* [3:0] spd 0-3 interrupt detection enable [4] msi-x enable [5] other clear disable (makes other bits in status not clear on read) etc. */ u32 control; CLIB_PAD_FROM_TO (0x89c, 0x900); /* Defines interrupt mapping for 128 rx + 128 tx queues. 64 x 4 8 bit entries. For register [i]: [5:0] bit in interrupt status for rx queue 2*i + 0 [7] valid bit [13:8] bit for tx queue 2*i + 0 [15] valid bit similar for rx 2*i + 1 and tx 2*i + 1. */ u32 queue_mapping[64]; /* tcp timer [7:0] and other interrupts [15:8] */ u32 misc_mapping; CLIB_PAD_FROM_TO (0xa04, 0xa90); /* 64 interrupts determined by mappings. */ u32 status1_write_1_to_clear[4]; u32 enable1_write_1_to_set[4]; u32 enable1_write_1_to_clear[4]; CLIB_PAD_FROM_TO (0xac0, 0xad0); u32 status1_enable_auto_clear[4]; CLIB_PAD_FROM_TO (0xae0, 0x1000); } interrupt; ixge_dma_regs_t rx_dma0[64]; CLIB_PAD_FROM_TO (0x2000, 0x2140); u32 dcb_rx_packet_plane_t4_config[8]; u32 dcb_rx_packet_plane_t4_status[8]; CLIB_PAD_FROM_TO (0x2180, 0x2300); /* reg i defines mapping for 4 rx queues starting at 4*i + 0. */ u32 rx_queue_stats_mapping[32]; u32 rx_queue_stats_control; CLIB_PAD_FROM_TO (0x2384, 0x2410); u32 fc_user_descriptor_ptr[2]; u32 fc_buffer_control; CLIB_PAD_FROM_TO (0x241c, 0x2420); u32 fc_rx_dma; CLIB_PAD_FROM_TO (0x2424, 0x2430); u32 dcb_packet_plane_control; CLIB_PAD_FROM_TO (0x2434, 0x2f00); u32 rx_dma_control; u32 pf_queue_drop_enable; CLIB_PAD_FROM_TO (0x2f08, 0x2f20); u32 rx_dma_descriptor_cache_config; CLIB_PAD_FROM_TO (0x2f24, 0x3000); /* 1 bit. */ u32 rx_enable; CLIB_PAD_FROM_TO (0x3004, 0x3008); /* [15:0] ether type (little endian) [31:16] opcode (big endian) */ u32 flow_control_control; CLIB_PAD_FROM_TO (0x300c, 0x3020); /* 3 bit traffic class for each of 8 priorities. */ u32 rx_priority_to_traffic_class; CLIB_PAD_FROM_TO (0x3024, 0x3028); u32 rx_coallesce_data_buffer_control; CLIB_PAD_FROM_TO (0x302c, 0x3190); u32 rx_packet_buffer_flush_detect; CLIB_PAD_FROM_TO (0x3194, 0x3200); u32 flow_control_tx_timers[4]; /* 2 timer values */ CLIB_PAD_FROM_TO (0x3210, 0x3220); u32 flow_control_rx_threshold_lo[8]; CLIB_PAD_FROM_TO (0x3240, 0x3260); u32 flow_control_rx_threshold_hi[8]; CLIB_PAD_FROM_TO (0x3280, 0x32a0); u32 flow_control_refresh_threshold; CLIB_PAD_FROM_TO (0x32a4, 0x3c00); /* For each of 8 traffic classes (units of bytes). */ u32 rx_packet_buffer_size[8]; CLIB_PAD_FROM_TO (0x3c20, 0x3d00); u32 flow_control_config; CLIB_PAD_FROM_TO (0x3d04, 0x4200); struct { u32 pcs_config; CLIB_PAD_FROM_TO (0x4204, 0x4208); u32 link_control; u32 link_status; u32 pcs_debug[2]; u32 auto_negotiation; u32 link_partner_ability; u32 auto_negotiation_tx_next_page; u32 auto_negotiation_link_partner_next_page; CLIB_PAD_FROM_TO (0x4228, 0x4240); } gige_mac; struct { /* [0] tx crc enable [2] enable frames up to max frame size register [31:16] [10] pad frames < 64 bytes if specified by user [15] loopback enable [16] mdc hi speed [17] turn off mdc between mdio packets */ u32 control; /* [5] rx symbol error (all bits clear on read) [6] rx illegal symbol [7] rx idle error [8] rx local fault [9] rx remote fault */ u32 status; u32 pause_and_pace_control; CLIB_PAD_FROM_TO (0x424c, 0x425c); u32 phy_command; u32 phy_data; CLIB_PAD_FROM_TO (0x4264, 0x4268); /* [31:16] max frame size in bytes. */ u32 rx_max_frame_size; CLIB_PAD_FROM_TO (0x426c, 0x4288); /* [0] [2] pcs receive link up? (latch lo) [7] local fault [1] [0] pcs 10g base r capable [1] pcs 10g base x capable [2] pcs 10g base w capable [10] rx local fault [11] tx local fault [15:14] 2 => device present at this address (else not present) */ u32 xgxs_status[2]; u32 base_x_pcs_status; /* [0] pass unrecognized flow control frames [1] discard pause frames [2] rx priority flow control enable (only in dcb mode) [3] rx flow control enable. */ u32 flow_control; /* [3:0] tx lanes change polarity [7:4] rx lanes change polarity [11:8] swizzle tx lanes [15:12] swizzle rx lanes 4 x 2 bit tx lane swap 4 x 2 bit rx lane swap. */ u32 serdes_control; u32 fifo_control; /* [0] force link up [1] autoneg ack2 bit to transmit [6:2] autoneg selector field to transmit [8:7] 10g pma/pmd type 0 => xaui, 1 kx4, 2 cx4 [9] 1g pma/pmd type 0 => sfi, 1 => kx/bx [10] disable 10g on without main power [11] restart autoneg on transition to dx power state [12] restart autoneg [15:13] link mode: 0 => 1g no autoneg 1 => 10g kx4 parallel link no aut
/*
 * Copyright (c) 2015 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
  Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus

  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files (the
  "Software"), to deal in the Software without restriction, including
  without limitation the rights to use, copy, modify, merge, publish,
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#ifdef CLIB_LINUX_KERNEL
#include <linux/unistd.h>
#endif

#ifdef CLIB_UNIX
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>		/* scanf */
#endif

#include <vppinfra/mheap.h>
#include <vppinfra/format.h>
#include <vppinfra/random.h>

static int verbose = 0;
#define if_verbose(format,args...) \
  if (verbose) { clib_warning(format, ## args); }

int
test_mheap_main (unformat_input_t * input)
{
  int i, j, k, n_iterations;
  void *h, *h_mem;
  uword *objects = 0;
  u32 objects_used, really_verbose, n_objects, max_object_size;
  u32 check_mask, seed, trace, use_vm;
  u32 print_every = 0;
  u32 *data;
  mheap_t *mh;

  /* Validation flags. */
  check_mask = 0;
#define CHECK_VALIDITY 1
#define CHECK_DATA     2
#define CHECK_ALIGN    4

  n_iterations = 10;
  seed = 0;
  max_object_size = 100;
  n_objects = 1000;
  trace = 0;
  really_verbose = 0;
  use_vm = 0;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (0 == unformat (input, "iter %d", &n_iterations)
	  && 0 == unformat (input, "count %d", &n_objects)
	  && 0 == unformat (input, "size %d", &max_object_size)
	  && 0 == unformat (input, "seed %d", &seed)
	  && 0 == unformat (input, "print %d", &print_every)
	  && 0 == unformat (input, "validdata %|",
			    &check_mask, CHECK_DATA | CHECK_VALIDITY)
	  && 0 == unformat (input, "valid %|",
			    &check_mask, CHECK_VALIDITY)
	  && 0 == unformat (input, "verbose %=", &really_verbose, 1)
	  && 0 == unformat (input, "trace %=", &trace, 1)
	  && 0 == unformat (input, "vm %=", &use_vm, 1)
	  && 0 == unformat (input, "align %|", &check_mask, CHECK_ALIGN))
	{
	  clib_warning ("unknown input `%U'", format_unformat_error, input);
	  return 1;
	}
    }

  /* Zero seed means use default. */
  if (!seed)
    seed = random_default_seed ();

  if_verbose
    ("testing %d iterations, %d %saligned objects, max. size %d, seed %d",
     n_iterations, n_objects, (check_mask & CHECK_ALIGN) ? "randomly " : "un",
     max_object_size, seed);

  vec_resize (objects, n_objects);
  if (vec_bytes (objects))	/* stupid warning be gone */
    memset (objects, ~0, vec_bytes (objects));
  objects_used = 0;

  /* Allocate initial heap. */
  {
    uword size =
      max_pow2 (2 * n_objects * max_object_size * sizeof (data[0]));

    h_mem = clib_mem_alloc (size);
    if (!h_mem)
      return 0;

    h = mheap_alloc (h_mem, size);
  }

  if (trace