X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_pipeline%2Frte_pipeline.c;h=d625fd25ed76bf2e201604432c107142c1d035e5;hb=8827234d70dfc0b92f893f73d43af2275d354df9;hp=f0349e32b9655dfbf9892f37c53e194111711b75;hpb=6f41fe75e2dd8dd38f7bea7b9501edd4f9b72fa5;p=dpdk.git diff --git a/lib/librte_pipeline/rte_pipeline.c b/lib/librte_pipeline/rte_pipeline.c index f0349e32b9..d625fd25ed 100644 --- a/lib/librte_pipeline/rte_pipeline.c +++ b/lib/librte_pipeline/rte_pipeline.c @@ -48,6 +48,17 @@ #define RTE_TABLE_INVALID UINT32_MAX +#ifdef RTE_PIPELINE_STATS_COLLECT +#define RTE_PIPELINE_STATS_ADD(counter, val) \ + ({ (counter) += (val); }) + +#define RTE_PIPELINE_STATS_ADD_M(counter, mask) \ + ({ (counter) += __builtin_popcountll(mask); }) +#else +#define RTE_PIPELINE_STATS_ADD(counter, val) +#define RTE_PIPELINE_STATS_ADD_M(counter, mask) +#endif + struct rte_port_in { /* Input parameters */ struct rte_port_in_ops ops; @@ -63,6 +74,8 @@ struct rte_port_in { /* List of enabled ports */ struct rte_port_in *next; + + uint64_t n_pkts_dropped_by_ah; }; struct rte_port_out { @@ -74,6 +87,8 @@ struct rte_port_out { /* Handle to low-level port */ void *h_port; + + uint64_t n_pkts_dropped_by_ah; }; struct rte_table { @@ -90,6 +105,12 @@ struct rte_table { /* Handle to the low-level table object */ void *h_table; + + /* Stats for this table. */ + uint64_t n_pkts_dropped_by_lkp_hit_ah; + uint64_t n_pkts_dropped_by_lkp_miss_ah; + uint64_t n_pkts_dropped_lkp_hit; + uint64_t n_pkts_dropped_lkp_miss; }; #define RTE_PIPELINE_MAX_NAME_SZ 124 @@ -175,14 +196,6 @@ rte_pipeline_check_params(struct rte_pipeline_params *params) return -EINVAL; } - /* offset_port_id */ - if (params->offset_port_id & 0x3) { - RTE_LOG(ERR, PIPELINE, - "%s: Incorrect value for parameter offset_port_id\n", - __func__); - return -EINVAL; - } - return 0; } @@ -203,7 +216,7 @@ rte_pipeline_create(struct rte_pipeline_params *params) /* Allocate memory for the pipeline on requested socket */ p = rte_zmalloc_socket("PIPELINE", sizeof(struct rte_pipeline), - CACHE_LINE_SIZE, params->socket_id); + RTE_CACHE_LINE_SIZE, params->socket_id); if (p == NULL) { RTE_LOG(ERR, PIPELINE, @@ -343,7 +356,7 @@ rte_pipeline_table_create(struct rte_pipeline *p, entry_size = sizeof(struct rte_pipeline_table_entry) + params->action_data_size; default_entry = (struct rte_pipeline_table_entry *) rte_zmalloc_socket( - "PIPELINE", entry_size, CACHE_LINE_SIZE, p->socket_id); + "PIPELINE", entry_size, RTE_CACHE_LINE_SIZE, p->socket_id); if (default_entry == NULL) { RTE_LOG(ERR, PIPELINE, "%s: Failed to allocate default entry\n", __func__); @@ -574,6 +587,112 @@ rte_pipeline_table_entry_delete(struct rte_pipeline *p, return (table->ops.f_delete)(table->h_table, key, key_found, entry); } +int rte_pipeline_table_entry_add_bulk(struct rte_pipeline *p, + uint32_t table_id, + void **keys, + struct rte_pipeline_table_entry **entries, + uint32_t n_keys, + int *key_found, + struct rte_pipeline_table_entry **entries_ptr) +{ + struct rte_table *table; + uint32_t i; + + /* Check input arguments */ + if (p == NULL) { + RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter is NULL\n", + __func__); + return -EINVAL; + } + + if (keys == NULL) { + RTE_LOG(ERR, PIPELINE, "%s: keys parameter is NULL\n", __func__); + return -EINVAL; + } + + if (entries == NULL) { + RTE_LOG(ERR, PIPELINE, "%s: entries parameter is NULL\n", + __func__); + return -EINVAL; + } + + if (table_id >= p->num_tables) { + RTE_LOG(ERR, PIPELINE, + "%s: table_id %d out of range\n", __func__, table_id); + return -EINVAL; + } + + table = &p->tables[table_id]; + + if (table->ops.f_add_bulk == NULL) { + RTE_LOG(ERR, PIPELINE, "%s: f_add_bulk function pointer NULL\n", + __func__); + return -EINVAL; + } + + for (i = 0; i < n_keys; i++) { + if ((entries[i]->action == RTE_PIPELINE_ACTION_TABLE) && + table->table_next_id_valid && + (entries[i]->table_id != table->table_next_id)) { + RTE_LOG(ERR, PIPELINE, + "%s: Tree-like topologies not allowed\n", __func__); + return -EINVAL; + } + } + + /* Add entry */ + for (i = 0; i < n_keys; i++) { + if ((entries[i]->action == RTE_PIPELINE_ACTION_TABLE) && + (table->table_next_id_valid == 0)) { + table->table_next_id = entries[i]->table_id; + table->table_next_id_valid = 1; + } + } + + return (table->ops.f_add_bulk)(table->h_table, keys, (void **) entries, + n_keys, key_found, (void **) entries_ptr); +} + +int rte_pipeline_table_entry_delete_bulk(struct rte_pipeline *p, + uint32_t table_id, + void **keys, + uint32_t n_keys, + int *key_found, + struct rte_pipeline_table_entry **entries) +{ + struct rte_table *table; + + /* Check input arguments */ + if (p == NULL) { + RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", + __func__); + return -EINVAL; + } + + if (keys == NULL) { + RTE_LOG(ERR, PIPELINE, "%s: key parameter is NULL\n", + __func__); + return -EINVAL; + } + + if (table_id >= p->num_tables) { + RTE_LOG(ERR, PIPELINE, + "%s: table_id %d out of range\n", __func__, table_id); + return -EINVAL; + } + + table = &p->tables[table_id]; + + if (table->ops.f_delete_bulk == NULL) { + RTE_LOG(ERR, PIPELINE, + "%s: f_delete function pointer NULL\n", __func__); + return -EINVAL; + } + + return (table->ops.f_delete_bulk)(table->h_table, keys, n_keys, key_found, + (void **) entries); +} + /* * Port * @@ -999,6 +1118,7 @@ rte_pipeline_compute_masks(struct rte_pipeline *p, uint64_t pkts_mask) { p->action_mask1[RTE_PIPELINE_ACTION_DROP] = 0; p->action_mask1[RTE_PIPELINE_ACTION_PORT] = 0; + p->action_mask1[RTE_PIPELINE_ACTION_PORT_META] = 0; p->action_mask1[RTE_PIPELINE_ACTION_TABLE] = 0; if ((pkts_mask & (pkts_mask + 1)) == 0) { @@ -1039,6 +1159,8 @@ rte_pipeline_action_handler_port_bulk(struct rte_pipeline *p, port_out->f_action_bulk(p->pkts, &pkts_mask, port_out->arg_ah); p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= pkts_mask ^ mask; + RTE_PIPELINE_STATS_ADD_M(port_out->n_pkts_dropped_by_ah, + pkts_mask ^ mask); } /* Output port TX */ @@ -1070,6 +1192,9 @@ rte_pipeline_action_handler_port(struct rte_pipeline *p, uint64_t pkts_mask) p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= (pkt_mask ^ 1LLU) << i; + RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, + pkt_mask ^ 1LLU); + /* Output port TX */ if (pkt_mask != 0) port_out->ops.f_tx(port_out->h_port, @@ -1103,6 +1228,9 @@ rte_pipeline_action_handler_port(struct rte_pipeline *p, uint64_t pkts_mask) p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= (pkt_mask ^ 1LLU) << i; + RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, + pkt_mask ^ 1LLU); + /* Output port TX */ if (pkt_mask != 0) port_out->ops.f_tx(port_out->h_port, @@ -1139,6 +1267,9 @@ rte_pipeline_action_handler_port_meta(struct rte_pipeline *p, p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= (pkt_mask ^ 1LLU) << i; + RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, + pkt_mask ^ 1ULL); + /* Output port TX */ if (pkt_mask != 0) port_out->ops.f_tx(port_out->h_port, @@ -1173,6 +1304,9 @@ rte_pipeline_action_handler_port_meta(struct rte_pipeline *p, p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= (pkt_mask ^ 1LLU) << i; + RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, + pkt_mask ^ 1ULL); + /* Output port TX */ if (pkt_mask != 0) port_out->ops.f_tx(port_out->h_port, @@ -1224,16 +1358,17 @@ rte_pipeline_run(struct rte_pipeline *p) pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t); p->action_mask0[RTE_PIPELINE_ACTION_DROP] = 0; p->action_mask0[RTE_PIPELINE_ACTION_PORT] = 0; + p->action_mask0[RTE_PIPELINE_ACTION_PORT_META] = 0; p->action_mask0[RTE_PIPELINE_ACTION_TABLE] = 0; /* Input port user actions */ if (port_in->f_action != NULL) { uint64_t mask = pkts_mask; - port_in->f_action(p->pkts, n_pkts, &pkts_mask, - port_in->arg_ah); - p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= - pkts_mask ^ mask; + port_in->f_action(p->pkts, n_pkts, &pkts_mask, port_in->arg_ah); + mask ^= pkts_mask; + p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= mask; + RTE_PIPELINE_STATS_ADD_M(port_in->n_pkts_dropped_by_ah, mask); } /* Table */ @@ -1259,9 +1394,10 @@ rte_pipeline_run(struct rte_pipeline *p) table->f_action_miss(p->pkts, &lookup_miss_mask, default_entry, table->arg_ah); - p->action_mask0[ - RTE_PIPELINE_ACTION_DROP] |= - lookup_miss_mask ^ mask; + mask ^= lookup_miss_mask; + p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= mask; + RTE_PIPELINE_STATS_ADD_M( + table->n_pkts_dropped_by_lkp_miss_ah, mask); } /* Table reserved actions */ @@ -1275,6 +1411,10 @@ rte_pipeline_run(struct rte_pipeline *p) uint32_t pos = default_entry->action; p->action_mask0[pos] = lookup_miss_mask; + if (pos == RTE_PIPELINE_ACTION_DROP) { + RTE_PIPELINE_STATS_ADD_M(table->n_pkts_dropped_lkp_miss, + lookup_miss_mask); + } } } @@ -1287,9 +1427,10 @@ rte_pipeline_run(struct rte_pipeline *p) table->f_action_hit(p->pkts, &lookup_hit_mask, p->entries, table->arg_ah); - p->action_mask0[ - RTE_PIPELINE_ACTION_DROP] |= - lookup_hit_mask ^ mask; + mask ^= lookup_hit_mask; + p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= mask; + RTE_PIPELINE_STATS_ADD_M( + table->n_pkts_dropped_by_lkp_hit_ah, mask); } /* Table reserved actions */ @@ -1300,9 +1441,15 @@ rte_pipeline_run(struct rte_pipeline *p) p->action_mask0[RTE_PIPELINE_ACTION_PORT] |= p->action_mask1[ RTE_PIPELINE_ACTION_PORT]; + p->action_mask0[RTE_PIPELINE_ACTION_PORT_META] |= + p->action_mask1[ + RTE_PIPELINE_ACTION_PORT_META]; p->action_mask0[RTE_PIPELINE_ACTION_TABLE] |= p->action_mask1[ RTE_PIPELINE_ACTION_TABLE]; + + RTE_PIPELINE_STATS_ADD_M(table->n_pkts_dropped_lkp_hit, + p->action_mask1[RTE_PIPELINE_ACTION_DROP]); } /* Prepare for next iteration */ @@ -1365,8 +1512,126 @@ rte_pipeline_port_out_packet_insert(struct rte_pipeline *p, if (pkt_mask != 0) /* Output port TX */ port_out->ops.f_tx(port_out->h_port, pkt); - else + else { rte_pktmbuf_free(pkt); + RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, 1); + } + } + + return 0; +} + +int rte_pipeline_port_in_stats_read(struct rte_pipeline *p, uint32_t port_id, + struct rte_pipeline_port_in_stats *stats, int clear) +{ + struct rte_port_in *port; + int retval; + + if (p == NULL) { + RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", + __func__); + return -EINVAL; + } + + if (port_id >= p->num_ports_in) { + RTE_LOG(ERR, PIPELINE, + "%s: port IN ID %u is out of range\n", + __func__, port_id); + return -EINVAL; + } + + port = &p->ports_in[port_id]; + + if (port->ops.f_stats != NULL) { + retval = port->ops.f_stats(port->h_port, &stats->stats, clear); + if (retval) + return retval; + } else if (stats != NULL) + memset(&stats->stats, 0, sizeof(stats->stats)); + + if (stats != NULL) + stats->n_pkts_dropped_by_ah = port->n_pkts_dropped_by_ah; + + if (clear != 0) + port->n_pkts_dropped_by_ah = 0; + + return 0; +} + +int rte_pipeline_port_out_stats_read(struct rte_pipeline *p, uint32_t port_id, + struct rte_pipeline_port_out_stats *stats, int clear) +{ + struct rte_port_out *port; + int retval; + + if (p == NULL) { + RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", __func__); + return -EINVAL; + } + + if (port_id >= p->num_ports_out) { + RTE_LOG(ERR, PIPELINE, + "%s: port OUT ID %u is out of range\n", __func__, port_id); + return -EINVAL; + } + + port = &p->ports_out[port_id]; + if (port->ops.f_stats != NULL) { + retval = port->ops.f_stats(port->h_port, &stats->stats, clear); + if (retval != 0) + return retval; + } else if (stats != NULL) + memset(&stats->stats, 0, sizeof(stats->stats)); + + if (stats != NULL) + stats->n_pkts_dropped_by_ah = port->n_pkts_dropped_by_ah; + + if (clear != 0) + port->n_pkts_dropped_by_ah = 0; + + return 0; +} + +int rte_pipeline_table_stats_read(struct rte_pipeline *p, uint32_t table_id, + struct rte_pipeline_table_stats *stats, int clear) +{ + struct rte_table *table; + int retval; + + if (p == NULL) { + RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", + __func__); + return -EINVAL; + } + + if (table_id >= p->num_tables) { + RTE_LOG(ERR, PIPELINE, + "%s: table %u is out of range\n", __func__, table_id); + return -EINVAL; + } + + table = &p->tables[table_id]; + if (table->ops.f_stats != NULL) { + retval = table->ops.f_stats(table->h_table, &stats->stats, clear); + if (retval != 0) + return retval; + } else if (stats != NULL) + memset(&stats->stats, 0, sizeof(stats->stats)); + + if (stats != NULL) { + stats->n_pkts_dropped_by_lkp_hit_ah = + table->n_pkts_dropped_by_lkp_hit_ah; + stats->n_pkts_dropped_by_lkp_miss_ah = + table->n_pkts_dropped_by_lkp_miss_ah; + stats->n_pkts_dropped_lkp_hit = table->n_pkts_dropped_lkp_hit; + stats->n_pkts_dropped_lkp_miss = table->n_pkts_dropped_lkp_miss; + } + + if (clear != 0) { + table->n_pkts_dropped_by_lkp_hit_ah = 0; + table->n_pkts_dropped_by_lkp_miss_ah = 0; + table->n_pkts_dropped_lkp_hit = 0; + table->n_pkts_dropped_lkp_miss = 0; } return 0;