X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;ds=inline;f=lib%2Flibrte_pipeline%2Frte_pipeline.c;h=bd700d230652d84f6c81f90c473b7abb0c90dc86;hb=5915699153d788c5cb3c449635eca46f1da6f2fe;hp=ac7e887381559a786461b822a2fec61175038980;hpb=fdf20fa7bee9df9037116318a87080e1eb7e757e;p=dpdk.git diff --git a/lib/librte_pipeline/rte_pipeline.c b/lib/librte_pipeline/rte_pipeline.c index ac7e887381..bd700d2306 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; } @@ -999,6 +1012,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 +1053,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 +1086,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 +1122,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 +1161,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 +1198,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 +1252,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 +1288,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 +1305,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 +1321,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 +1335,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,9 +1406,128 @@ 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; +} +