From: Saeed Mahameed > Sent: 22 April 2016 20:01 > Redesign the statistics in the driver: > 1. Move counters to a separate file (en_stats.h). > 2. Remove unnecessary dependencies between stats and strings. > 3. Use counter descriptors which hold a name and offset for each counter, > and will be used to decide which counters will be exposed. > > For example when adding a new software counter to ethtool, instead of: > 1. Add to stats struct. > 2. Add to strings struct in the same order. > 3. Change macro defining number of software counters. > The only thing needed is to link the new counter to a counter descriptor. ...
This looks like a place for some pre-processor magic to define two (or more) items from the same line of C source. Taking one definition. Instead of: > +static const struct counter_desc vport_stats_desc[] = { > + { "rx_error_packets", VPORT_COUNTER_OFF(received_errors.packets) }, > + { "rx_error_bytes", VPORT_COUNTER_OFF(received_errors.octets) }, > + { "tx_error_packets", VPORT_COUNTER_OFF(transmit_errors.packets) }, > + { "tx_error_bytes", VPORT_COUNTER_OFF(transmit_errors.octets) }, Use the following #define to generate both the array of names and the structure. #define VPORT_STATS_DEFN(RX, TX) \ RX( "rx_error_packets", packets) \ RX( "rx_error_bytes", octets) \ TX( "tx_error_packets", packets) \ TX( "tx_error_bytes", octets) \ ... You can then expand it two (or more) ways: #define STATS_NAMES(name, field) name, static const char *const vport_stats_names[] = { VPORT_STATS_DEFN(STATS_NAMES, STATS_NAMES) }; #define STAT_FIELD(name, field) uint64_t field; #define STAT_NONE(name, field) struct received_errors { VPORT_STATS_DEFN(STAT_FIELD, STAT_NONE) }; struct transmit_errors errors { VPORT_STATS_DEFN(STAT_NONE, STAT_FIELD) }; Adding an extra stat then just requires you add an extra line to VPORT_STATS_DEFN(). David