@@ -35,7 +35,7 @@ extern "C" {
/* Maximum PMR Terms in a PMR Set */
#define ODP_PMRTERM_MAX 8
/* Maximum PMRs attached in PKTIO Level */
-#define ODP_PKTIO_MAX_PMR 8
+#define ODP_PMR_PER_COS_MAX 8
/* L2 Priority Bits */
#define ODP_COS_L2_QOS_BITS 3
/* Max L2 QoS value */
@@ -67,15 +67,16 @@ Class Of Service
struct cos_s {
queue_entry_t *queue; /* Associated Queue */
pool_entry_t *pool; /* Associated Buffer pool */
- union pmr_u *pmr; /* Chained PMR */
- union cos_u *linked_cos; /* CoS linked with the PMR */
+ union pmr_u *pmr[ODP_PMR_PER_COS_MAX]; /* Chained PMR */
+ union cos_u *linked_cos[ODP_PMR_PER_COS_MAX]; /* Chained CoS with PMR*/
uint32_t valid; /* validity Flag */
- odp_cls_drop_t drop_policy; /* Associated Drop Policy */
+ odp_cls_drop_t drop_policy; /* Associated Drop Policy */
odp_queue_group_t queue_group; /* Associated Queue Group */
odp_cos_flow_set_t flow_set; /* Assigned Flow Set */
- char name[ODP_COS_NAME_LEN]; /* name */
size_t headroom; /* Headroom for this CoS */
odp_spinlock_t lock; /* cos lock */
+ odp_atomic_u32_t num_rule; /* num of PMRs attached with this CoS */
+ char name[ODP_COS_NAME_LEN]; /* name */
};
typedef union cos_u {
@@ -93,6 +94,7 @@ struct pmr_s {
odp_atomic_u32_t count; /* num of packets matching this rule */
uint32_t num_pmr; /* num of PMR Term Values*/
odp_spinlock_t lock; /* pmr lock*/
+ cos_t *src_cos; /* source CoS where PMR is attached */
pmr_term_value_t pmr_term_value[1]; /* Associated PMR Term */
};
@@ -148,10 +150,6 @@ This structure is stored in pktio_entry and holds all
the classifier configuration value.
**/
typedef struct classifier {
- odp_spinlock_t lock; /*pktio_cos lock */
- uint32_t num_pmr; /* num of PMRs linked to given PKTIO*/
- pmr_t *pmr[ODP_PKTIO_MAX_PMR]; /* PMRs linked with this PKTIO */
- cos_t *cos[ODP_PKTIO_MAX_PMR]; /* CoS linked with this PKTIO */
cos_t *error_cos; /* Associated Error CoS */
cos_t *default_cos; /* Associated Default CoS */
uint32_t l3_precedence; /* L3 QoS precedence */
@@ -163,7 +163,7 @@ void odp_cls_cos_param_init(odp_cls_cos_param_t *param)
odp_cos_t odp_cls_cos_create(const char *name, odp_cls_cos_param_t *param)
{
- int i;
+ int i, j;
queue_entry_t *queue;
pool_entry_t *pool;
odp_cls_drop_t drop_policy;
@@ -187,14 +187,18 @@ odp_cos_t odp_cls_cos_create(const char *name, odp_cls_cos_param_t *param)
strncpy(cos_tbl->cos_entry[i].s.name, name,
ODP_COS_NAME_LEN - 1);
cos_tbl->cos_entry[i].s.name[ODP_COS_NAME_LEN - 1] = 0;
- cos_tbl->cos_entry[i].s.pmr = NULL;
- cos_tbl->cos_entry[i].s.linked_cos = NULL;
+ for (j = 0; j < ODP_PMR_PER_COS_MAX; j++) {
+ cos_tbl->cos_entry[i].s.pmr[j] = NULL;
+ cos_tbl->cos_entry[i].s.linked_cos[j] = NULL;
+ }
cos_tbl->cos_entry[i].s.queue = queue;
cos_tbl->cos_entry[i].s.pool = pool;
cos_tbl->cos_entry[i].s.flow_set = 0;
cos_tbl->cos_entry[i].s.headroom = 0;
cos_tbl->cos_entry[i].s.valid = 1;
cos_tbl->cos_entry[i].s.drop_policy = drop_policy;
+ odp_atomic_init_u32(&cos_tbl->cos_entry[i]
+ .s.num_rule, 0);
UNLOCK(&cos_tbl->cos_entry[i].s.lock);
return _odp_cast_scalar(odp_cos_t, i);
}
@@ -487,15 +491,28 @@ static void odp_pmr_create_term(pmr_term_value_t *value,
value->val &= value->mask;
}
-odp_pmr_t odp_pmr_create(const odp_pmr_match_t *match)
+odp_pmr_t odp_cls_pmr_create(const odp_pmr_match_t *match, odp_cos_t src_cos,
+ odp_cos_t dst_cos)
{
pmr_t *pmr;
odp_pmr_t id;
+ uint32_t loc;
+ cos_t *cos_src = get_cos_entry(src_cos);
+ cos_t *cos_dst = get_cos_entry(dst_cos);
+
+ if (NULL == cos_src || NULL == cos_dst) {
+ ODP_ERR("Invalid input handle");
+ return ODP_PMR_INVAL;
+ }
+
if (match->val_sz > ODP_PMR_TERM_BYTES_MAX) {
ODP_ERR("val_sz greater than max supported limit");
return ODP_PMR_INVAL;
}
+ if (ODP_PMR_PER_COS_MAX == odp_atomic_load_u32(&cos_src->s.num_rule))
+ return ODP_PMR_INVAL;
+
id = alloc_pmr(&pmr);
/*if alloc_pmr() is successful it returns with lock acquired*/
if (id == ODP_PMR_INVAL)
@@ -504,77 +521,43 @@ odp_pmr_t odp_pmr_create(const odp_pmr_match_t *match)
pmr->s.num_pmr = 1;
odp_pmr_create_term(&pmr->s.pmr_term_value[0], match);
UNLOCK(&pmr->s.lock);
- return id;
-}
-int odp_pmr_destroy(odp_pmr_t pmr_id)
-{
- pmr_t *pmr = get_pmr_entry(pmr_id);
+ loc = odp_atomic_fetch_inc_u32(&cos_src->s.num_rule);
+ cos_src->s.pmr[loc] = pmr;
+ cos_src->s.linked_cos[loc] = cos_dst;
+ pmr->s.src_cos = cos_src;
- if (pmr == NULL)
- return -1;
- pmr->s.valid = 0;
- return 0;
+ return id;
}
-int odp_pktio_pmr_cos(odp_pmr_t pmr_id,
- odp_pktio_t src_pktio,
- odp_cos_t dst_cos)
+int odp_cls_pmr_destroy(odp_pmr_t pmr_id)
{
- uint8_t num_pmr;
- pktio_entry_t *pktio_entry;
+ cos_t *src_cos;
+ uint32_t loc;
pmr_t *pmr;
- cos_t *cos;
-
- pktio_entry = get_pktio_entry(src_pktio);
- if (pktio_entry == NULL) {
- ODP_ERR("Invalid odp_pktio_t handle");
- return -1;
- }
+ uint8_t i;
pmr = get_pmr_entry(pmr_id);
- if (pmr == NULL) {
- ODP_ERR("Invalid odp_pmr_t handle");
- return -1;
- }
- cos = get_cos_entry(dst_cos);
- if (cos == NULL) {
- ODP_ERR("Invalid odp_cos_t handle");
+ if (pmr == NULL || pmr->s.src_cos == NULL)
return -1;
- }
- LOCK(&pktio_entry->s.cls.lock);
- num_pmr = pktio_entry->s.cls.num_pmr;
- if (num_pmr >= ODP_PKTIO_MAX_PMR) {
- ODP_ERR("ODP_PKTIO_MAX_PMR reached");
- UNLOCK(&pktio_entry->s.cls.lock);
- return -1;
- }
-
- pktio_entry->s.cls.pmr[num_pmr] = pmr;
- pktio_entry->s.cls.cos[num_pmr] = cos;
- pktio_entry->s.cls.num_pmr++;
- pktio_cls_enabled_set(pktio_entry, 1);
- UNLOCK(&pktio_entry->s.cls.lock);
-
- return 0;
-}
-
-int odp_cos_pmr_cos(odp_pmr_t pmr_id, odp_cos_t src_cos, odp_cos_t dst_cos)
-{
- cos_t *cos_src = get_cos_entry(src_cos);
- cos_t *cos_dst = get_cos_entry(dst_cos);
- pmr_t *pmr = get_pmr_entry(pmr_id);
- if (NULL == cos_src || NULL == cos_dst || NULL == pmr) {
- ODP_ERR("Invalid input handle");
- return -1;
- }
-
- /*Locking is not required as intermittent stale data is acceptable*/
- cos_src->s.pmr = pmr;
- cos_src->s.linked_cos = cos_dst;
+ src_cos = pmr->s.src_cos;
+ LOCK(&src_cos->s.lock);
+ loc = odp_atomic_load_u32(&src_cos->s.num_rule);
+ if (loc == 0)
+ goto no_rule;
+ loc -= 1;
+ for (i = 0; i <= loc; i++)
+ if (src_cos->s.pmr[i] == pmr) {
+ src_cos->s.pmr[i] = src_cos->s.pmr[loc];
+ src_cos->s.linked_cos[i] = src_cos->s.linked_cos[loc];
+ }
+ odp_atomic_dec_u32(&src_cos->s.num_rule);
+no_rule:
+ pmr->s.valid = 0;
+ UNLOCK(&src_cos->s.lock);
return 0;
}
@@ -604,17 +587,28 @@ unsigned odp_pmr_terms_avail(void)
return count;
}
-int odp_pmr_match_set_create(int num_terms, const odp_pmr_match_t *terms,
- odp_pmr_set_t *pmr_set_id)
+int odp_cls_pmr_match_set_create(int num_terms, const odp_pmr_match_t *terms,
+ odp_pmr_set_t *pmr_set_id, odp_cos_t src_cos,
+ odp_cos_t dst_cos)
{
pmr_t *pmr;
int i;
odp_pmr_set_t id;
int val_sz;
int count = 0;
+ uint32_t loc;
+ cos_t *cos_src = get_cos_entry(src_cos);
+ cos_t *cos_dst = get_cos_entry(dst_cos);
+
+ if (NULL == cos_src || NULL == cos_dst) {
+ ODP_ERR("Invalid input handle");
+ *pmr_set_id = ODP_PMR_SET_INVAL;
+ return -1;
+ }
if (num_terms > ODP_PMRTERM_MAX) {
ODP_ERR("no of terms greater than supported ODP_PMRTERM_MAX");
+ *pmr_set_id = ODP_PMR_SET_INVAL;
return -1;
}
@@ -634,60 +628,42 @@ int odp_pmr_match_set_create(int num_terms, const odp_pmr_match_t *terms,
count++;
}
*pmr_set_id = id;
+
+ loc = odp_atomic_fetch_inc_u32(&cos_src->s.num_rule);
+ cos_src->s.pmr[loc] = pmr;
+ cos_src->s.linked_cos[loc] = cos_dst;
+ pmr->s.src_cos = cos_src;
+
UNLOCK(&pmr->s.lock);
return count;
}
-int odp_pmr_match_set_destroy(odp_pmr_set_t pmr_set_id)
+int odp_cls_pmr_match_set_destroy(odp_pmr_set_t pmr_set_id)
{
+ cos_t *src_cos;
+ uint32_t loc;
+ uint8_t i;
pmr_set_t *pmr_set = get_pmr_set_entry(pmr_set_id);
- if (pmr_set == NULL)
- return -1;
- pmr_set->s.pmr.s.valid = 0;
- return 0;
-}
-
-int odp_pktio_pmr_match_set_cos(odp_pmr_set_t pmr_set_id, odp_pktio_t src_pktio,
- odp_cos_t dst_cos)
-{
- uint8_t num_pmr;
- pktio_entry_t *pktio_entry;
- pmr_t *pmr;
- cos_t *cos;
-
- pktio_entry = get_pktio_entry(src_pktio);
- if (pktio_entry == NULL) {
- ODP_ERR("Invalid odp_pktio_t handle");
+ if (pmr_set == NULL || pmr_set->s.pmr.s.src_cos == NULL)
return -1;
- }
- pmr = (pmr_t *)get_pmr_set_entry(pmr_set_id);
- if (pmr == NULL) {
- ODP_ERR("Invalid odp_pmr_set_t handle");
- return -1;
- }
-
- cos = get_cos_entry(dst_cos);
- if (cos == NULL) {
- ODP_ERR("Invalid odp_cos_t handle");
- return -1;
- }
-
- LOCK(&pktio_entry->s.cls.lock);
- num_pmr = pktio_entry->s.cls.num_pmr;
- if (num_pmr >= ODP_PKTIO_MAX_PMR) {
- ODP_ERR("ODP_PKTIO_MAX_PMR reached");
- UNLOCK(&pktio_entry->s.cls.lock);
- return -1;
- }
-
- pktio_entry->s.cls.pmr[num_pmr] = pmr;
- pktio_entry->s.cls.cos[num_pmr] = cos;
- pktio_entry->s.cls.num_pmr++;
- pktio_cls_enabled_set(pktio_entry, 1);
- UNLOCK(&pktio_entry->s.cls.lock);
+ src_cos = pmr_set->s.pmr.s.src_cos;
+ LOCK(&src_cos->s.lock);
+ loc = odp_atomic_load_u32(&src_cos->s.num_rule);
+ if (loc == 0)
+ goto no_rule;
+ loc -= 1;
+ for (i = 0; i <= loc; i++)
+ if (src_cos->s.pmr[i] == (pmr_t *)pmr_set) {
+ src_cos->s.pmr[i] = src_cos->s.pmr[loc];
+ src_cos->s.linked_cos[i] = src_cos->s.linked_cos[loc];
+ }
+ odp_atomic_dec_u32(&src_cos->s.num_rule);
+no_rule:
+ pmr_set->s.pmr.s.valid = 0;
+ UNLOCK(&src_cos->s.lock);
return 0;
}
@@ -846,7 +822,10 @@ int verify_pmr(pmr_t *pmr, const uint8_t *pkt_addr, odp_packet_hdr_t *pkt_hdr)
cos_t *match_pmr_cos(cos_t *cos, const uint8_t *pkt_addr, pmr_t *pmr,
odp_packet_hdr_t *hdr)
{
- cos_t *retcos = NULL;
+ cos_t *retcos;
+ uint32_t i;
+
+ retcos = NULL;
if (cos == NULL || pmr == NULL)
return NULL;
@@ -857,10 +836,15 @@ cos_t *match_pmr_cos(cos_t *cos, const uint8_t *pkt_addr, pmr_t *pmr,
if (verify_pmr(pmr, pkt_addr, hdr)) {
/** This gets called recursively to check all the PMRs in
* a PMR chain */
- retcos = match_pmr_cos(cos->s.linked_cos, pkt_addr,
- cos->s.pmr, hdr);
- if (!retcos)
+ if (0 == odp_atomic_load_u32(&cos->s.num_rule))
return cos;
+
+ for (i = 0; i < odp_atomic_load_u32(&cos->s.num_rule); i++) {
+ retcos = match_pmr_cos(cos->s.linked_cos[i], pkt_addr,
+ cos->s.pmr[i], hdr);
+ if (!retcos)
+ return cos;
+ }
}
return retcos;
}
@@ -868,23 +852,17 @@ cos_t *match_pmr_cos(cos_t *cos, const uint8_t *pkt_addr, pmr_t *pmr,
int pktio_classifier_init(pktio_entry_t *entry)
{
classifier_t *cls;
- int i;
+
/* classifier lock should be acquired by the calling function */
if (entry == NULL)
return -1;
cls = &entry->s.cls;
- cls->num_pmr = 0;
cls->flow_set = 0;
cls->error_cos = NULL;
cls->default_cos = NULL;
cls->headroom = 0;
cls->skip = 0;
- for (i = 0; i < ODP_PKTIO_MAX_PMR; i++) {
- cls->pmr[i] = NULL;
- cls->cos[i] = NULL;
- }
-
return 0;
}
@@ -946,10 +924,12 @@ cos_t *pktio_select_cos(pktio_entry_t *entry, const uint8_t *pkt_addr,
{
pmr_t *pmr;
cos_t *cos;
+ cos_t *default_cos;
uint32_t i;
classifier_t *cls;
cls = &entry->s.cls;
+ default_cos = cls->default_cos;
/* Check for lazy parse needed */
if (packet_parse_not_complete(pkt_hdr))
@@ -959,9 +939,9 @@ cos_t *pktio_select_cos(pktio_entry_t *entry, const uint8_t *pkt_addr,
if (pkt_hdr->error_flags.all)
return cls->error_cos;
/* Calls all the PMRs attached at the PKTIO level*/
- for (i = 0; i < cls->num_pmr; i++) {
- pmr = entry->s.cls.pmr[i];
- cos = entry->s.cls.cos[i];
+ for (i = 0; i < odp_atomic_load_u32(&default_cos->s.num_rule); i++) {
+ pmr = default_cos->s.pmr[i];
+ cos = default_cos->s.linked_cos[i];
cos = match_pmr_cos(cos, pkt_addr, pmr, pkt_hdr);
if (cos)
return cos;
@@ -56,7 +56,6 @@ int odp_pktio_init_global(void)
pktio_entry = &pktio_tbl->entries[id - 1];
odp_ticketlock_init(&pktio_entry->s.lock);
- odp_spinlock_init(&pktio_entry->s.cls.lock);
odp_spinlock_init(&pktio_entry->s.cls.l2_cos_table.lock);
odp_spinlock_init(&pktio_entry->s.cls.l3_cos_table.lock);
@@ -114,18 +113,6 @@ static void unlock_entry(pktio_entry_t *entry)
odp_ticketlock_unlock(&entry->s.lock);
}
-static void lock_entry_classifier(pktio_entry_t *entry)
-{
- odp_ticketlock_lock(&entry->s.lock);
- odp_spinlock_lock(&entry->s.cls.lock);
-}
-
-static void unlock_entry_classifier(pktio_entry_t *entry)
-{
- odp_spinlock_unlock(&entry->s.cls.lock);
- odp_ticketlock_unlock(&entry->s.lock);
-}
-
static void init_pktio_entry(pktio_entry_t *entry)
{
int i;
@@ -151,13 +138,13 @@ static odp_pktio_t alloc_lock_pktio_entry(void)
for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) {
entry = &pktio_tbl->entries[i];
if (is_free(entry)) {
- lock_entry_classifier(entry);
+ odp_ticketlock_lock(&entry->s.lock);
if (is_free(entry)) {
init_pktio_entry(entry);
id = _odp_cast_scalar(odp_pktio_t, i + 1);
return id; /* return with entry locked! */
}
- unlock_entry_classifier(entry);
+ odp_ticketlock_unlock(&entry->s.lock);
}
}
@@ -217,7 +204,6 @@ static odp_pktio_t setup_pktio_entry(const char *dev, odp_pool_t pool,
}
if (ret != 0) {
- unlock_entry_classifier(pktio_entry);
free_pktio_entry(id);
id = ODP_PKTIO_INVALID;
ODP_ERR("Unable to init any I/O type.\n");
@@ -225,10 +211,10 @@ static odp_pktio_t setup_pktio_entry(const char *dev, odp_pool_t pool,
snprintf(pktio_entry->s.name,
sizeof(pktio_entry->s.name), "%s", dev);
pktio_entry->s.state = STATE_STOP;
- unlock_entry_classifier(pktio_entry);
}
pktio_entry->s.handle = id;
+ odp_ticketlock_unlock(&pktio_entry->s.lock);
return id;
}
Implements packet match rule create functions. If a packet match rule needs to be applied at the pktio level it has to be configured to the default class of service. Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org> --- .../include/odp_classification_datamodel.h | 16 +- platform/linux-generic/odp_classification.c | 226 ++++++++++----------- platform/linux-generic/odp_packet_io.c | 20 +- 3 files changed, 113 insertions(+), 149 deletions(-)