diff mbox

[API-NEXT,PATCHv1,2/4] linux-generic: classification: implement pmr create api

Message ID 1453463648-11158-2-git-send-email-bala.manoharan@linaro.org
State New
Headers show

Commit Message

Balasubramanian Manoharan Jan. 22, 2016, 11:54 a.m. UTC
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(-)
diff mbox

Patch

diff --git a/platform/linux-generic/include/odp_classification_datamodel.h b/platform/linux-generic/include/odp_classification_datamodel.h
index 27d8a52..05f5e77 100644
--- a/platform/linux-generic/include/odp_classification_datamodel.h
+++ b/platform/linux-generic/include/odp_classification_datamodel.h
@@ -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 */
diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c
index da195ad..6308c7b 100644
--- a/platform/linux-generic/odp_classification.c
+++ b/platform/linux-generic/odp_classification.c
@@ -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;
diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c
index 95b8904..34a7c1c 100644
--- a/platform/linux-generic/odp_packet_io.c
+++ b/platform/linux-generic/odp_packet_io.c
@@ -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;
 }