aboutsummaryrefslogtreecommitdiff
path: root/platform/linux-generic/odp_classification.c
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linux-generic/odp_classification.c')
-rw-r--r--platform/linux-generic/odp_classification.c119
1 files changed, 84 insertions, 35 deletions
diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c
index 3b50232d6..2fdecbc51 100644
--- a/platform/linux-generic/odp_classification.c
+++ b/platform/linux-generic/odp_classification.c
@@ -150,7 +150,7 @@ void odp_cls_pmr_param_init(odp_pmr_param_t *param)
int odp_cls_capability(odp_cls_capability_t *capability)
{
- unsigned int count = 0;
+ uint32_t count = 0;
memset(capability, 0, sizeof(odp_cls_capability_t));
@@ -161,6 +161,7 @@ int odp_cls_capability(odp_cls_capability_t *capability)
capability->max_pmr_terms = CLS_PMR_MAX_ENTRY;
capability->available_pmr_terms = count;
capability->max_cos = CLS_COS_MAX_ENTRY;
+ capability->max_cos_stats = capability->max_cos;
capability->pmr_range_supported = false;
capability->supported_terms.all_bits = 0;
capability->supported_terms.bit.len = 1;
@@ -186,6 +187,8 @@ int odp_cls_capability(odp_cls_capability_t *capability)
capability->threshold_bp.all_bits = 0;
capability->max_hash_queues = CLS_COS_QUEUE_MAX;
capability->max_mark = MAX_MARK;
+ capability->stats.cos.counter.discards = 1;
+ capability->stats.cos.counter.packets = 1;
capability->stats.queue.counter.discards = 1;
capability->stats.queue.counter.packets = 1;
@@ -220,21 +223,29 @@ static inline void _cls_queue_unwind(uint32_t tbl_index, uint32_t j)
odp_queue_destroy(queue_grp_tbl->s.queue[tbl_index + --j]);
}
-odp_cos_t odp_cls_cos_create(const char *name, const odp_cls_cos_param_t *param)
+odp_cos_t odp_cls_cos_create(const char *name, const odp_cls_cos_param_t *param_in)
{
uint32_t i, j;
odp_queue_t queue;
odp_cls_drop_t drop_policy;
cos_t *cos;
uint32_t tbl_index;
+ odp_cls_cos_param_t param = *param_in;
+
+ if (param.action == ODP_COS_ACTION_DROP) {
+ param.num_queue = 1;
+ param.queue = ODP_QUEUE_INVALID;
+ param.pool = ODP_POOL_INVALID;
+ param.vector.enable = false;
+ }
/* num_queue should not be zero */
- if (param->num_queue > CLS_COS_QUEUE_MAX || param->num_queue < 1)
+ if (param.num_queue > CLS_COS_QUEUE_MAX || param.num_queue < 1)
return ODP_COS_INVALID;
/* Validate packet vector parameters */
- if (param->vector.enable) {
- odp_pool_t pool = param->vector.pool;
+ if (param.vector.enable) {
+ odp_pool_t pool = param.vector.pool;
odp_pool_info_t pool_info;
if (pool == ODP_POOL_INVALID || odp_pool_info(pool, &pool_info)) {
@@ -245,17 +256,17 @@ odp_cos_t odp_cls_cos_create(const char *name, const odp_cls_cos_param_t *param)
ODP_ERR("wrong pool type\n");
return ODP_COS_INVALID;
}
- if (param->vector.max_size == 0) {
+ if (param.vector.max_size == 0) {
ODP_ERR("vector.max_size is zero\n");
return ODP_COS_INVALID;
}
- if (param->vector.max_size > pool_info.params.vector.max_size) {
+ if (param.vector.max_size > pool_info.params.vector.max_size) {
ODP_ERR("vector.max_size larger than pool max vector size\n");
return ODP_COS_INVALID;
}
}
- drop_policy = param->drop_policy;
+ drop_policy = param.drop_policy;
for (i = 0; i < CLS_COS_MAX_ENTRY; i++) {
cos = &cos_tbl->cos_entry[i];
@@ -274,16 +285,16 @@ odp_cos_t odp_cls_cos_create(const char *name, const odp_cls_cos_param_t *param)
cos->s.linked_cos[j] = NULL;
}
- cos->s.num_queue = param->num_queue;
+ cos->s.num_queue = param.num_queue;
- if (param->num_queue > 1) {
+ if (param.num_queue > 1) {
odp_queue_param_init(&cos->s.queue_param);
cos->s.queue_group = true;
cos->s.queue = ODP_QUEUE_INVALID;
_odp_cls_update_hash_proto(cos,
- param->hash_proto);
+ param.hash_proto);
tbl_index = i * CLS_COS_QUEUE_MAX;
- for (j = 0; j < param->num_queue; j++) {
+ for (j = 0; j < param.num_queue; j++) {
queue = odp_queue_create(NULL, &cos->s.queue_param);
if (queue == ODP_QUEUE_INVALID) {
/* unwind the queues */
@@ -296,21 +307,27 @@ odp_cos_t odp_cls_cos_create(const char *name, const odp_cls_cos_param_t *param)
}
} else {
- cos->s.queue = param->queue;
+ cos->s.queue = param.queue;
}
+
+ odp_atomic_init_u64(&cos->s.stats.discards, 0);
+ odp_atomic_init_u64(&cos->s.stats.packets, 0);
+
/* Initialize statistics counters */
for (j = 0; j < cos->s.num_queue; j++) {
- odp_atomic_init_u64(&cos->s.stats[j].discards, 0);
- odp_atomic_init_u64(&cos->s.stats[j].packets, 0);
+ odp_atomic_init_u64(&cos->s.queue_stats[j].discards, 0);
+ odp_atomic_init_u64(&cos->s.queue_stats[j].packets, 0);
}
- cos->s.pool = param->pool;
+ cos->s.action = param.action;
+ cos->s.pool = param.pool;
cos->s.headroom = 0;
cos->s.valid = 1;
cos->s.drop_policy = drop_policy;
odp_atomic_init_u32(&cos->s.num_rule, 0);
cos->s.index = i;
- cos->s.vector = param->vector;
+ cos->s.vector = param.vector;
+ cos->s.stats_enable = param.stats_enable;
UNLOCK(&cos->s.lock);
return _odp_cos_from_ndx(i);
}
@@ -1461,6 +1478,9 @@ static cos_t *match_pmr_cos(cos_t *cos, const uint8_t *pkt_addr, pmr_t *pmr,
/* PMR matched */
pmr_debug_print(pmr, cos);
+ if (cos->s.stats_enable)
+ odp_atomic_inc_u64(&cos->s.stats.packets);
+
hdr->p.input_flags.cls_mark = 0;
if (pmr->s.mark) {
hdr->p.input_flags.cls_mark = 1;
@@ -1537,8 +1557,11 @@ static inline cos_t *cls_select_cos(pktio_entry_t *entry,
default_cos = cls->default_cos;
/* Return error cos for error packet */
- if (pkt_hdr->p.flags.all.error)
- return cls->error_cos;
+ if (pkt_hdr->p.flags.all.error) {
+ cos = cls->error_cos;
+ goto done;
+ }
+
/* Calls all the PMRs attached at the PKTIO level*/
for (i = 0; i < odp_atomic_load_u32(&default_cos->s.num_rule); i++) {
pmr = default_cos->s.pmr[i];
@@ -1551,11 +1574,17 @@ static inline cos_t *cls_select_cos(pktio_entry_t *entry,
cos = match_qos_cos(entry, pkt_addr, pkt_hdr);
if (cos) {
ODP_DBG_RAW(CLS_DBG, " QoS matched -> cos: %s(%u)\n", cos->s.name, cos->s.index);
- return cos;
+ goto done;
}
ODP_DBG_RAW(CLS_DBG, " No match -> default cos\n");
- return cls->default_cos;
+ cos = cls->default_cos;
+
+done:
+ if (cos && cos->s.stats_enable)
+ odp_atomic_inc_u64(&cos->s.stats.packets);
+
+ return cos;
}
static uint32_t packet_rss_hash(odp_packet_hdr_t *pkt_hdr,
@@ -1575,12 +1604,12 @@ static uint32_t packet_rss_hash(odp_packet_hdr_t *pkt_hdr,
* @retval 0 on success
* @retval -EFAULT Bug
* @retval -EINVAL Config error
+ * @retval -ENOENT Drop action
*
* @note *base is not released
*/
int _odp_cls_classify_packet(pktio_entry_t *entry, const uint8_t *base,
- uint16_t pkt_len, uint32_t seg_len, odp_pool_t *pool,
- odp_packet_hdr_t *pkt_hdr, odp_bool_t parse)
+ odp_pool_t *pool, odp_packet_hdr_t *pkt_hdr)
{
cos_t *cos;
uint32_t tbl_index;
@@ -1588,24 +1617,19 @@ int _odp_cls_classify_packet(pktio_entry_t *entry, const uint8_t *base,
ODP_DBG_LVL(CLS_DBG, "Classify packet from %s\n", entry->s.full_name);
- if (parse) {
- packet_parse_reset(pkt_hdr, 1);
- packet_set_len(pkt_hdr, pkt_len);
-
- _odp_packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len,
- ODP_PROTO_LAYER_ALL,
- entry->s.in_chksums);
- }
cos = cls_select_cos(entry, base, pkt_hdr);
if (cos == NULL)
return -EINVAL;
+ if (cos->s.action == ODP_COS_ACTION_DROP)
+ return -ENOENT;
+
if (cos->s.queue == ODP_QUEUE_INVALID && cos->s.num_queue == 1)
- return -EFAULT;
+ goto error;
if (cos->s.pool == ODP_POOL_INVALID)
- return -EFAULT;
+ goto error;
*pool = cos->s.pool;
pkt_hdr->p.input_flags.dst_queue = 1;
@@ -1623,6 +1647,10 @@ int _odp_cls_classify_packet(pktio_entry_t *entry, const uint8_t *base,
cos->s.num_queue);
pkt_hdr->dst_queue = queue_grp_tbl->s.queue[tbl_index];
return 0;
+
+error:
+ odp_atomic_inc_u64(&cos->s.stats.discards);
+ return -EFAULT;
}
static uint32_t packet_rss_hash(odp_packet_hdr_t *pkt_hdr,
@@ -1780,6 +1808,27 @@ uint64_t odp_pmr_to_u64(odp_pmr_t hdl)
return _odp_pri(hdl);
}
+int odp_cls_cos_stats(odp_cos_t hdl, odp_cls_cos_stats_t *stats)
+{
+ cos_t *cos = get_cos_entry(hdl);
+
+ if (odp_unlikely(cos == NULL)) {
+ ODP_ERR("Invalid odp_cos_t handle\n");
+ return -1;
+ }
+
+ if (odp_unlikely(stats == NULL)) {
+ ODP_ERR("Output structure NULL\n");
+ return -1;
+ }
+
+ memset(stats, 0, sizeof(*stats));
+ stats->discards = odp_atomic_load_u64(&cos->s.stats.discards);
+ stats->packets = odp_atomic_load_u64(&cos->s.stats.packets);
+
+ return 0;
+}
+
int odp_cls_queue_stats(odp_cos_t hdl, odp_queue_t queue,
odp_cls_queue_stats_t *stats)
{
@@ -1803,8 +1852,8 @@ int odp_cls_queue_stats(odp_cos_t hdl, odp_queue_t queue,
}
memset(stats, 0, sizeof(odp_cls_queue_stats_t));
- stats->discards = odp_atomic_load_u64(&cos->s.stats[queue_idx].discards);
- stats->packets = odp_atomic_load_u64(&cos->s.stats[queue_idx].packets);
+ stats->discards = odp_atomic_load_u64(&cos->s.queue_stats[queue_idx].discards);
+ stats->packets = odp_atomic_load_u64(&cos->s.queue_stats[queue_idx].packets);
return 0;
}