This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "".
The branch, api-next has been updated via 8390f890d4bd2babb63a24f7b15d2f4763e44050 (commit) via e02f89b3a981d5f87332cd9a3dfd6b532f92c3bc (commit) via 8eeb3366d62c34665bcef2392b22b73489d70f88 (commit) via 705062dc19a4ce5e6ae2224c21bc9e32dae64ebc (commit) from b4cd6c50f9f0c2e1fa975b768253d4f4b35fad07 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit 8390f890d4bd2babb63a24f7b15d2f4763e44050 Author: Balasubramanian Manoharan bala.manoharan@linaro.org Date: Thu Aug 3 08:44:29 2017 -0700
linux-generic: classification: rename internal defines
remove ODP_ from internal #define variable names
Signed-off-by: Balasubramanian Manoharan bala.manoharan@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/include/odp_classification_datamodel.h b/platform/linux-generic/include/odp_classification_datamodel.h index 3cfe8c5a..29b39f9c 100644 --- a/platform/linux-generic/include/odp_classification_datamodel.h +++ b/platform/linux-generic/include/odp_classification_datamodel.h @@ -28,27 +28,27 @@ extern "C" { #include <protocols/ip.h>
/* Maximum Class Of Service Entry */ -#define ODP_COS_MAX_ENTRY 64 +#define CLS_COS_MAX_ENTRY 64 /* Maximum PMR Entry */ -#define ODP_PMR_MAX_ENTRY 256 +#define CLS_PMR_MAX_ENTRY 256 /* Maximum PMR Terms in a PMR Set */ -#define ODP_PMRTERM_MAX 8 +#define CLS_PMRTERM_MAX 8 /* Maximum PMRs attached in PKTIO Level */ -#define ODP_PMR_PER_COS_MAX 8 +#define CLS_PMR_PER_COS_MAX 8 /* L2 Priority Bits */ -#define ODP_COS_L2_QOS_BITS 3 +#define CLS_COS_L2_QOS_BITS 3 /* Max L2 QoS value */ -#define ODP_COS_MAX_L2_QOS (1 << ODP_COS_L2_QOS_BITS) +#define CLS_COS_MAX_L2_QOS (1 << CLS_COS_L2_QOS_BITS) /* L2 DSCP Bits */ -#define ODP_COS_L3_QOS_BITS 6 +#define CLS_COS_L3_QOS_BITS 6 /* Max L3 QoS Value */ -#define ODP_COS_MAX_L3_QOS (1 << ODP_COS_L3_QOS_BITS) +#define CLS_COS_MAX_L3_QOS (1 << CLS_COS_L3_QOS_BITS) /* Max PMR Term bits */ -#define ODP_PMR_TERM_BYTES_MAX 16 - -#define ODP_COS_QUEUE_MAX 32 - -#define ODP_CLS_QUEUE_GROUP_MAX (ODP_COS_MAX_ENTRY * ODP_COS_QUEUE_MAX) +#define CLS_PMR_TERM_BYTES_MAX 16 +/* Max queue per Class of service */ +#define CLS_COS_QUEUE_MAX 32 +/* Max number of implementation created queues */ +#define CLS_QUEUE_GROUP_MAX (CLS_COS_MAX_ENTRY * CLS_COS_QUEUE_MAX)
typedef union { /* All proto fileds */ @@ -103,8 +103,8 @@ Class Of Service struct cos_s { odp_queue_t queue; /* Associated Queue */ odp_pool_t pool; /* Associated Buffer pool */ - 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*/ + union pmr_u *pmr[CLS_PMR_PER_COS_MAX]; /* Chained PMR */ + union cos_u *linked_cos[CLS_PMR_PER_COS_MAX]; /* Chained CoS with PMR*/ uint32_t valid; /* validity Flag */ odp_cls_drop_t drop_policy; /* Associated Drop Policy */ size_t headroom; /* Headroom for this CoS */ @@ -134,7 +134,7 @@ struct pmr_s { 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[ODP_PMRTERM_MAX]; + pmr_term_value_t pmr_term_value[CLS_PMRTERM_MAX]; /* List of associated PMR Terms */ };
@@ -144,7 +144,7 @@ typedef union pmr_u { } pmr_t;
typedef struct _cls_queue_grp_tbl_s { - odp_queue_t queue[ODP_CLS_QUEUE_GROUP_MAX]; + odp_queue_t queue[CLS_QUEUE_GROUP_MAX]; } _cls_queue_grp_tbl_s;
typedef union _cls_queue_grp_tbl_t { @@ -160,7 +160,7 @@ corresponding cos_t object **/ typedef struct pmr_l2_cos { odp_spinlock_t lock; /* pmr_l2_cos lock */ - cos_t *cos[ODP_COS_MAX_L2_QOS]; /* Array of CoS objects */ + cos_t *cos[CLS_COS_MAX_L2_QOS]; /* Array of CoS objects */ } pmr_l2_cos_t;
/** @@ -171,7 +171,7 @@ corresponding cos_t object **/ typedef struct pmr_l3_cos { odp_spinlock_t lock; /* pmr_l3_cos lock */ - cos_t *cos[ODP_COS_MAX_L3_QOS]; /* Array of CoS objects */ + cos_t *cos[CLS_COS_MAX_L3_QOS]; /* Array of CoS objects */ } pmr_l3_cos_t;
/** @@ -194,14 +194,14 @@ typedef struct classifier { Class of Service Table **/ typedef struct odp_cos_table { - cos_t cos_entry[ODP_COS_MAX_ENTRY]; + cos_t cos_entry[CLS_COS_MAX_ENTRY]; } cos_tbl_t;
/** PMR table **/ typedef struct pmr_tbl { - pmr_t pmr[ODP_PMR_MAX_ENTRY]; + pmr_t pmr[CLS_PMR_MAX_ENTRY]; } pmr_tbl_t;
#ifdef __cplusplus diff --git a/platform/linux-generic/include/odp_classification_inlines.h b/platform/linux-generic/include/odp_classification_inlines.h index 2747db8c..c2e94c63 100644 --- a/platform/linux-generic/include/odp_classification_inlines.h +++ b/platform/linux-generic/include/odp_classification_inlines.h @@ -320,7 +320,7 @@ static inline int verify_pmr_custom_frame(const uint8_t *pkt_addr, uint32_t offset = term_value->offset; uint32_t val_sz = term_value->val_sz;
- ODP_ASSERT(val_sz <= ODP_PMR_TERM_BYTES_MAX); + ODP_ASSERT(val_sz <= CLS_PMR_TERM_BYTES_MAX);
if (packet_len(pkt_hdr) <= offset + val_sz) return 0; diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c index 5672b234..892d2fad 100644 --- a/platform/linux-generic/odp_classification.c +++ b/platform/linux-generic/odp_classification.c @@ -74,7 +74,7 @@ int odp_classification_init_global(void) goto error_cos;
memset(cos_tbl, 0, sizeof(cos_tbl_t)); - for (i = 0; i < ODP_COS_MAX_ENTRY; i++) { + for (i = 0; i < CLS_COS_MAX_ENTRY; i++) { /* init locks */ cos_t *cos = get_cos_entry_internal(_odp_cast_scalar(odp_cos_t, i)); @@ -95,7 +95,7 @@ int odp_classification_init_global(void) goto error_pmr;
memset(pmr_tbl, 0, sizeof(pmr_tbl_t)); - for (i = 0; i < ODP_PMR_MAX_ENTRY; i++) { + for (i = 0; i < CLS_PMR_MAX_ENTRY; i++) { /* init locks */ pmr_t *pmr = get_pmr_entry_internal(_odp_cast_scalar(odp_pmr_t, i)); @@ -170,13 +170,13 @@ int odp_cls_capability(odp_cls_capability_t *capability) { unsigned count = 0;
- for (int i = 0; i < ODP_PMR_MAX_ENTRY; i++) + for (int i = 0; i < CLS_PMR_MAX_ENTRY; i++) if (!pmr_tbl->pmr[i].s.valid) count++;
- capability->max_pmr_terms = ODP_PMR_MAX_ENTRY; + capability->max_pmr_terms = CLS_PMR_MAX_ENTRY; capability->available_pmr_terms = count; - capability->max_cos = ODP_COS_MAX_ENTRY; + capability->max_cos = CLS_COS_MAX_ENTRY; capability->pmr_range_supported = false; capability->supported_terms.all_bits = 0; capability->supported_terms.bit.ip_proto = 1; @@ -212,12 +212,12 @@ odp_cos_t odp_cls_cos_create(const char *name, odp_cls_cos_param_t *param) uint32_t tbl_index;
/* Packets are dropped if Queue or Pool is invalid*/ - if (param->num_queue > ODP_COS_QUEUE_MAX) + if (param->num_queue > CLS_COS_QUEUE_MAX) return ODP_COS_INVALID;
drop_policy = param->drop_policy;
- for (i = 0; i < ODP_COS_MAX_ENTRY; i++) { + for (i = 0; i < CLS_COS_MAX_ENTRY; i++) { cos = &cos_tbl->cos_entry[i]; LOCK(&cos->s.lock); if (0 == cos->s.valid) { @@ -229,7 +229,7 @@ odp_cos_t odp_cls_cos_create(const char *name, odp_cls_cos_param_t *param) strncpy(cos_name, name, ODP_COS_NAME_LEN - 1); cos_name[ODP_COS_NAME_LEN - 1] = 0; } - for (j = 0; j < ODP_PMR_PER_COS_MAX; j++) { + for (j = 0; j < CLS_PMR_PER_COS_MAX; j++) { cos->s.pmr[j] = NULL; cos->s.linked_cos[j] = NULL; } @@ -241,8 +241,8 @@ odp_cos_t odp_cls_cos_create(const char *name, odp_cls_cos_param_t *param) cos->s.num_queue = param->num_queue; _odp_cls_update_hash_proto(cos, param->hash_proto); - tbl_index = cos->s.index * ODP_COS_QUEUE_MAX; - for (j = 0; j < ODP_COS_QUEUE_MAX; j++) { + tbl_index = cos->s.index * CLS_COS_QUEUE_MAX; + for (j = 0; j < CLS_COS_QUEUE_MAX; j++) { queue = odp_queue_create(NULL, &cos->s. queue_param); if (queue == ODP_QUEUE_INVALID) { @@ -269,7 +269,7 @@ odp_cos_t odp_cls_cos_create(const char *name, odp_cls_cos_param_t *param) UNLOCK(&cos->s.lock); }
- ODP_ERR("ODP_COS_MAX_ENTRY reached"); + ODP_ERR("CLS_COS_MAX_ENTRY reached"); return ODP_COS_INVALID; }
@@ -277,7 +277,7 @@ odp_pmr_t alloc_pmr(pmr_t **pmr) { int i;
- for (i = 0; i < ODP_PMR_MAX_ENTRY; i++) { + for (i = 0; i < CLS_PMR_MAX_ENTRY; i++) { LOCK(&pmr_tbl->pmr[i].s.lock); if (0 == pmr_tbl->pmr[i].s.valid) { pmr_tbl->pmr[i].s.valid = 1; @@ -289,13 +289,13 @@ odp_pmr_t alloc_pmr(pmr_t **pmr) } UNLOCK(&pmr_tbl->pmr[i].s.lock); } - ODP_ERR("ODP_PMR_MAX_ENTRY reached"); + ODP_ERR("CLS_PMR_MAX_ENTRY reached"); return ODP_PMR_INVAL; }
cos_t *get_cos_entry(odp_cos_t cos_id) { - if (_odp_typeval(cos_id) >= ODP_COS_MAX_ENTRY || + if (_odp_typeval(cos_id) >= CLS_COS_MAX_ENTRY || cos_id == ODP_COS_INVALID) return NULL; if (cos_tbl->cos_entry[_odp_typeval(cos_id)].s.valid == 0) @@ -305,7 +305,7 @@ cos_t *get_cos_entry(odp_cos_t cos_id)
pmr_t *get_pmr_entry(odp_pmr_t pmr_id) { - if (_odp_typeval(pmr_id) >= ODP_PMR_MAX_ENTRY || + if (_odp_typeval(pmr_id) >= CLS_PMR_MAX_ENTRY || pmr_id == ODP_PMR_INVAL) return NULL; if (pmr_tbl->pmr[_odp_typeval(pmr_id)].s.valid == 0) @@ -383,7 +383,7 @@ uint32_t odp_cls_cos_queues(odp_cos_t cos_id, odp_queue_t queue[], else num_queues = cos->s.num_queue;
- tbl_index = cos->s.index * ODP_COS_QUEUE_MAX; + tbl_index = cos->s.index * CLS_COS_QUEUE_MAX; for (i = 0; i < num_queues; i++) queue[i] = queue_grp_tbl->s.queue[tbl_index + i];
@@ -504,7 +504,7 @@ int odp_cos_with_l2_priority(odp_pktio_t pktio_in, for (i = 0; i < num_qos; i++) { cos = get_cos_entry(cos_table[i]); if (cos != NULL) { - if (ODP_COS_MAX_L2_QOS > qos_table[i]) + if (CLS_COS_MAX_L2_QOS > qos_table[i]) l2_cos->cos[qos_table[i]] = cos; } } @@ -537,7 +537,7 @@ int odp_cos_with_l3_qos(odp_pktio_t pktio_in, for (i = 0; i < num_qos; i++) { cos = get_cos_entry(cos_table[i]); if (cos != NULL) { - if (ODP_COS_MAX_L3_QOS > qos_table[i]) + if (CLS_COS_MAX_L3_QOS > qos_table[i]) l3_cos->cos[qos_table[i]] = cos; } } @@ -643,12 +643,12 @@ odp_pmr_t odp_cls_pmr_create(const odp_pmr_param_t *terms, int num_terms, return ODP_PMR_INVAL; }
- if (num_terms > ODP_PMRTERM_MAX) { - ODP_ERR("no of terms greater than supported ODP_PMRTERM_MAX"); + if (num_terms > CLS_PMRTERM_MAX) { + ODP_ERR("no of terms greater than supported CLS_PMRTERM_MAX"); return ODP_PMR_INVAL; }
- if (ODP_PMR_PER_COS_MAX == odp_atomic_load_u32(&cos_src->s.num_rule)) + if (CLS_PMR_PER_COS_MAX == odp_atomic_load_u32(&cos_src->s.num_rule)) return ODP_PMR_INVAL;
id = alloc_pmr(&pmr); @@ -659,7 +659,7 @@ odp_pmr_t odp_cls_pmr_create(const odp_pmr_param_t *terms, int num_terms, pmr->s.num_pmr = num_terms; for (i = 0; i < num_terms; i++) { val_sz = terms[i].val_sz; - if (val_sz > ODP_PMR_TERM_BYTES_MAX) { + if (val_sz > CLS_PMR_TERM_BYTES_MAX) { pmr->s.valid = 0; return ODP_PMR_INVAL; } @@ -961,9 +961,9 @@ int cls_classify_packet(pktio_entry_t *entry, const uint8_t *base, }
hash = packet_rss_hash(pkt_hdr, cos->s.hash_proto, base); - /* ODP_COS_QUEUE_MAX is a power of 2 */ - hash = hash & (ODP_COS_QUEUE_MAX - 1); - tbl_index = (cos->s.index * ODP_COS_QUEUE_MAX) + hash; + /* CLS_COS_QUEUE_MAX is a power of 2 */ + hash = hash & (CLS_COS_QUEUE_MAX - 1); + tbl_index = (cos->s.index * CLS_COS_QUEUE_MAX) + hash; pkt_hdr->dst_queue = queue_fn->from_ext(queue_grp_tbl-> s.queue[tbl_index]); return 0;
commit e02f89b3a981d5f87332cd9a3dfd6b532f92c3bc Author: Balasubramanian Manoharan bala.manoharan@linaro.org Date: Tue Jul 25 16:42:16 2017 +0530
linux-generic: classification implement packet hashing
implementation for packet hashing on classification
Signed-off-by: Balasubramanian Manoharan bala.manoharan@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/include/odp_classification_datamodel.h b/platform/linux-generic/include/odp_classification_datamodel.h index fbe10cb4..3cfe8c5a 100644 --- a/platform/linux-generic/include/odp_classification_datamodel.h +++ b/platform/linux-generic/include/odp_classification_datamodel.h @@ -46,6 +46,22 @@ extern "C" { /* Max PMR Term bits */ #define ODP_PMR_TERM_BYTES_MAX 16
+#define ODP_COS_QUEUE_MAX 32 + +#define ODP_CLS_QUEUE_GROUP_MAX (ODP_COS_MAX_ENTRY * ODP_COS_QUEUE_MAX) + +typedef union { + /* All proto fileds */ + uint32_t all; + + struct { + uint32_t ipv4:1; + uint32_t ipv6:1; + uint32_t udp:1; + uint32_t tcp:1; + }; +} odp_cls_hash_proto_t; + /** Packet Matching Rule Term Value
@@ -85,7 +101,7 @@ typedef struct pmr_term_value { Class Of Service */ struct cos_s { - queue_t queue; /* Associated Queue */ + odp_queue_t queue; /* Associated Queue */ odp_pool_t pool; /* Associated Buffer pool */ 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*/ @@ -94,7 +110,12 @@ struct cos_s { 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 */ + bool queue_group; + odp_cls_hash_proto_t hash_proto; + uint32_t num_queue; + odp_queue_param_t queue_param; char name[ODP_COS_NAME_LEN]; /* name */ + uint8_t index; };
typedef union cos_u { @@ -122,6 +143,15 @@ typedef union pmr_u { uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(struct pmr_s))]; } pmr_t;
+typedef struct _cls_queue_grp_tbl_s { + odp_queue_t queue[ODP_CLS_QUEUE_GROUP_MAX]; +} _cls_queue_grp_tbl_s; + +typedef union _cls_queue_grp_tbl_t { + _cls_queue_grp_tbl_s s; + uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(_cls_queue_grp_tbl_s))]; +} _cls_queue_grp_tbl_t; + /** L2 QoS and CoS Map
diff --git a/platform/linux-generic/include/odp_classification_internal.h b/platform/linux-generic/include/odp_classification_internal.h index 78eaac90..aca8e8c6 100644 --- a/platform/linux-generic/include/odp_classification_internal.h +++ b/platform/linux-generic/include/odp_classification_internal.h @@ -79,6 +79,9 @@ This function returns the CoS associated with L3 QoS value cos_t *match_qos_l3_cos(pmr_l3_cos_t *l3_cos, const uint8_t *pkt_addr, odp_packet_hdr_t *hdr);
+void _odp_cls_update_hash_proto(cos_t *cos, + odp_pktin_hash_proto_t hash_proto); + /** @internal CoS associated with L2 QoS value @@ -138,6 +141,10 @@ Otherwise. **/ int verify_pmr(pmr_t *pmr, const uint8_t *pkt_addr, odp_packet_hdr_t *pkt_hdr);
+uint32_t packet_rss_hash(odp_packet_hdr_t *pkt_hdr, + odp_cls_hash_proto_t hash_proto, + const uint8_t *base); + #ifdef __cplusplus } #endif diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c index cc08b9f4..5672b234 100644 --- a/platform/linux-generic/odp_classification.c +++ b/platform/linux-generic/odp_classification.c @@ -17,6 +17,7 @@ #include <odp_classification_inlines.h> #include <odp_classification_internal.h> #include <odp/api/shared_memory.h> +#include <protocols/thash.h> #include <protocols/eth.h> #include <protocols/ip.h> #include <string.h> @@ -30,6 +31,17 @@
static cos_tbl_t *cos_tbl; static pmr_tbl_t *pmr_tbl; +static _cls_queue_grp_tbl_t *queue_grp_tbl; + +const rss_key default_rss = { + .u8 = { + 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2, + 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0, + 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4, + 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c, + 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa, + } +};
cos_t *get_cos_entry_internal(odp_cos_t cos_id) { @@ -45,6 +57,7 @@ int odp_classification_init_global(void) { odp_shm_t cos_shm; odp_shm_t pmr_shm; + odp_shm_t queue_grp_shm; int i;
cos_shm = odp_shm_reserve("shm_odp_cos_tbl", @@ -89,8 +102,22 @@ int odp_classification_init_global(void) LOCK_INIT(&pmr->s.lock); }
+ queue_grp_shm = odp_shm_reserve("shm_odp_cls_queue_grp_tbl", + sizeof(_cls_queue_grp_tbl_t), + sizeof(queue_entry_t *), 0); + + if (queue_grp_shm == ODP_SHM_INVALID) { + ODP_ERR("shm allocation failed for queue_grp_tbl"); + goto error_queue_grp; + } + + queue_grp_tbl = odp_shm_addr(queue_grp_shm); + memset(queue_grp_tbl, 0, sizeof(_cls_queue_grp_tbl_t)); + return 0;
+error_queue_grp: + odp_shm_free(queue_grp_shm); error_pmr: odp_shm_free(pmr_shm); error_cos: @@ -116,6 +143,12 @@ int odp_classification_term_global(void) rc = -1; }
+ ret = odp_shm_free(odp_shm_lookup("shm_odp_cls_queue_grp_tbl")); + if (ret < 0) { + ODP_ERR("shm free failed for shm_odp_cls_queue_grp_tbl"); + rc = -1; + } + return rc; }
@@ -124,6 +157,8 @@ void odp_cls_cos_param_init(odp_cls_cos_param_t *param) param->queue = ODP_QUEUE_INVALID; param->pool = ODP_POOL_INVALID; param->drop_policy = ODP_COS_DROP_NEVER; + param->num_queue = 1; + odp_queue_param_init(¶m->queue_param); }
void odp_cls_pmr_param_init(odp_pmr_param_t *param) @@ -154,24 +189,39 @@ int odp_cls_capability(odp_cls_capability_t *capability) return 0; }
+void _odp_cls_update_hash_proto(cos_t *cos, odp_pktin_hash_proto_t hash_proto) +{ + if (hash_proto.proto.ipv4 || hash_proto.proto.ipv4_tcp || + hash_proto.proto.ipv4_udp) + cos->s.hash_proto.ipv4 = 1; + if (hash_proto.proto.ipv6 || hash_proto.proto.ipv6_tcp || + hash_proto.proto.ipv6_udp) + cos->s.hash_proto.ipv6 = 1; + if (hash_proto.proto.ipv4_tcp || hash_proto.proto.ipv6_tcp) + cos->s.hash_proto.tcp = 1; + if (hash_proto.proto.ipv4_udp || hash_proto.proto.ipv6_udp) + cos->s.hash_proto.udp = 1; +} + odp_cos_t odp_cls_cos_create(const char *name, odp_cls_cos_param_t *param) { int i, j; - queue_t queue; + odp_queue_t queue; odp_cls_drop_t drop_policy; + cos_t *cos; + uint32_t tbl_index;
/* Packets are dropped if Queue or Pool is invalid*/ - if (param->queue == ODP_QUEUE_INVALID) - queue = QUEUE_NULL; - else - queue = queue_fn->from_ext(param->queue); + if (param->num_queue > ODP_COS_QUEUE_MAX) + return ODP_COS_INVALID;
drop_policy = param->drop_policy;
for (i = 0; i < ODP_COS_MAX_ENTRY; i++) { - LOCK(&cos_tbl->cos_entry[i].s.lock); - if (0 == cos_tbl->cos_entry[i].s.valid) { - char *cos_name = cos_tbl->cos_entry[i].s.name; + cos = &cos_tbl->cos_entry[i]; + LOCK(&cos->s.lock); + if (0 == cos->s.valid) { + char *cos_name = cos->s.name;
if (name == NULL) { cos_name[0] = 0; @@ -180,20 +230,43 @@ odp_cos_t odp_cls_cos_create(const char *name, odp_cls_cos_param_t *param) cos_name[ODP_COS_NAME_LEN - 1] = 0; } 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->s.pmr[j] = NULL; + cos->s.linked_cos[j] = NULL; } - cos_tbl->cos_entry[i].s.queue = queue; - cos_tbl->cos_entry[i].s.pool = param->pool; - 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); + + if (param->num_queue > 1) { + odp_queue_param_init(&cos->s.queue_param); + cos->s.queue_group = true; + cos->s.queue = ODP_QUEUE_INVALID; + cos->s.num_queue = param->num_queue; + _odp_cls_update_hash_proto(cos, + param->hash_proto); + tbl_index = cos->s.index * ODP_COS_QUEUE_MAX; + for (j = 0; j < ODP_COS_QUEUE_MAX; j++) { + queue = odp_queue_create(NULL, &cos->s. + queue_param); + if (queue == ODP_QUEUE_INVALID) { + UNLOCK(&cos->s.lock); + return ODP_COS_INVALID; + } + queue_grp_tbl->s.queue[tbl_index + j] = + queue; + } + + } else { + cos->s.queue = param->queue; + } + + 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; + UNLOCK(&cos->s.lock); return _odp_cast_scalar(odp_cos_t, i); } - UNLOCK(&cos_tbl->cos_entry[i].s.lock); + UNLOCK(&cos->s.lock); }
ODP_ERR("ODP_COS_MAX_ENTRY reached"); @@ -263,10 +336,7 @@ int odp_cos_queue_set(odp_cos_t cos_id, odp_queue_t queue_id) } /* Locking is not required as intermittent stale data during CoS modification is acceptable*/ - if (queue_id == ODP_QUEUE_INVALID) - cos->s.queue = QUEUE_NULL; - else - cos->s.queue = queue_fn->from_ext(queue_id); + cos->s.queue = queue_id; return 0; }
@@ -279,10 +349,45 @@ odp_queue_t odp_cos_queue(odp_cos_t cos_id) return ODP_QUEUE_INVALID; }
- if (cos->s.queue == QUEUE_NULL) - return ODP_QUEUE_INVALID; + return cos->s.queue; +} + +uint32_t odp_cls_cos_num_queue(odp_cos_t cos_id) +{ + cos_t *cos = get_cos_entry(cos_id); + + if (!cos) { + ODP_ERR("Invalid odp_cos_t handle"); + return 0; + } + + return cos->s.num_queue; +} + +uint32_t odp_cls_cos_queues(odp_cos_t cos_id, odp_queue_t queue[], + uint32_t num) +{ + uint32_t num_queues; + cos_t *cos; + uint32_t tbl_index; + uint32_t i; + + cos = get_cos_entry(cos_id); + if (!cos) { + ODP_ERR("Invalid odp_cos_t handle"); + return 0; + } + + if (num < cos->s.num_queue) + num_queues = num; + else + num_queues = cos->s.num_queue; + + tbl_index = cos->s.index * ODP_COS_QUEUE_MAX; + for (i = 0; i < num_queues; i++) + queue[i] = queue_grp_tbl->s.queue[tbl_index + i];
- return queue_fn->to_ext(cos->s.queue); + return num_queues; }
int odp_cos_drop_set(odp_cos_t cos_id, odp_cls_drop_t drop_policy) @@ -830,6 +935,8 @@ int cls_classify_packet(pktio_entry_t *entry, const uint8_t *base, odp_packet_hdr_t *pkt_hdr) { cos_t *cos; + uint32_t tbl_index; + uint32_t hash;
packet_parse_reset(pkt_hdr); packet_set_len(pkt_hdr, pkt_len); @@ -841,16 +948,95 @@ int cls_classify_packet(pktio_entry_t *entry, const uint8_t *base, if (cos == NULL) return -EINVAL;
- if (cos->s.queue == QUEUE_NULL || cos->s.pool == ODP_POOL_INVALID) + if (cos->s.queue == ODP_QUEUE_INVALID || + cos->s.pool == ODP_POOL_INVALID) return -EFAULT;
*pool = cos->s.pool; pkt_hdr->p.input_flags.dst_queue = 1; - pkt_hdr->dst_queue = cos->s.queue;
+ if (!cos->s.queue_group) { + pkt_hdr->dst_queue = queue_fn->from_ext(cos->s.queue); + return 0; + } + + hash = packet_rss_hash(pkt_hdr, cos->s.hash_proto, base); + /* ODP_COS_QUEUE_MAX is a power of 2 */ + hash = hash & (ODP_COS_QUEUE_MAX - 1); + tbl_index = (cos->s.index * ODP_COS_QUEUE_MAX) + hash; + pkt_hdr->dst_queue = queue_fn->from_ext(queue_grp_tbl-> + s.queue[tbl_index]); return 0; }
+uint32_t packet_rss_hash(odp_packet_hdr_t *pkt_hdr, + odp_cls_hash_proto_t hash_proto, + const uint8_t *base) +{ + thash_tuple_t tuple; + const _odp_ipv4hdr_t *ipv4; + const _odp_udphdr_t *udp; + const _odp_tcphdr_t *tcp; + const _odp_ipv6hdr_t *ipv6; + uint32_t hash; + uint32_t tuple_len; + + tuple_len = 0; + hash = 0; + if (pkt_hdr->p.input_flags.ipv4) { + if (hash_proto.ipv4) { + /* add ipv4 */ + ipv4 = (const _odp_ipv4hdr_t *)base + + pkt_hdr->p.l3_offset; + tuple.v4.src_addr = ipv4->src_addr; + tuple.v4.dst_addr = ipv4->dst_addr; + tuple_len += 2; + } + + if (pkt_hdr->p.input_flags.tcp && hash_proto.tcp) { + /* add tcp */ + tcp = (const _odp_tcphdr_t *)base + + pkt_hdr->p.l4_offset; + tuple.v4.sport = tcp->src_port; + tuple.v4.dport = tcp->dst_port; + tuple_len += 1; + } else if (pkt_hdr->p.input_flags.udp && hash_proto.udp) { + /* add udp */ + udp = (const _odp_udphdr_t *)base + + pkt_hdr->p.l4_offset; + tuple.v4.sport = udp->src_port; + tuple.v4.dport = udp->dst_port; + tuple_len += 1; + } + } else if (pkt_hdr->p.input_flags.ipv6) { + if (hash_proto.ipv6) { + /* add ipv6 */ + ipv6 = (const _odp_ipv6hdr_t *)base + + pkt_hdr->p.l3_offset; + thash_load_ipv6_addr(ipv6, &tuple); + tuple_len += 8; + } + if (pkt_hdr->p.input_flags.tcp && hash_proto.tcp) { + tcp = (const _odp_tcphdr_t *)base + + pkt_hdr->p.l4_offset; + tuple.v4.sport = tcp->src_port; + tuple.v4.dport = tcp->dst_port; + tuple_len += 1; + } else if (pkt_hdr->p.input_flags.udp && hash_proto.udp) { + /* add udp */ + udp = (const _odp_udphdr_t *)base + + pkt_hdr->p.l4_offset; + tuple.v4.sport = udp->src_port; + tuple.v4.dport = udp->dst_port; + tuple_len += 1; + } + } + if (tuple_len) + hash = thash_softrss((uint32_t *)&tuple, + tuple_len, default_rss); + return hash; +} + cos_t *match_qos_l3_cos(pmr_l3_cos_t *l3_cos, const uint8_t *pkt_addr, odp_packet_hdr_t *hdr) {
commit 8eeb3366d62c34665bcef2392b22b73489d70f88 Author: Balasubramanian Manoharan bala.manoharan@linaro.org Date: Tue Jul 25 16:42:14 2017 +0530
api: classification: add support for packet hashing in classification
Enable packet hashing per CoS to be able to distribute incoming packets to multiple queues linked with a CoS.
Signed-off-by: Balasubramanian Manoharan bala.manoharan@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/include/odp/api/spec/classification.h b/include/odp/api/spec/classification.h index 39831b24..0c4a95c5 100644 --- a/include/odp/api/spec/classification.h +++ b/include/odp/api/spec/classification.h @@ -4,7 +4,6 @@ * SPDX-License-Identifier: BSD-3-Clause */
- /** * @file * @@ -19,12 +18,13 @@ extern "C" { #endif
+#include <odp/api/packet_io.h> +#include <odp/api/support.h> /** @defgroup odp_classification ODP CLASSIFICATION * Classification operations. * @{ */
- /** * @typedef odp_cos_t * ODP Class of service handle @@ -126,6 +126,13 @@ typedef struct odp_cls_capability_t { /** Maximum number of CoS supported */ unsigned max_cos;
+ /** Maximun number of queue supported per CoS + * if the value is 1, then hashing is not supported*/ + unsigned max_hash_queues; + + /** Protocol header combination supported for Hashing */ + odp_pktin_hash_proto_t hash_protocols; + /** A Boolean to denote support of PMR range */ odp_bool_t pmr_range_supported; } odp_cls_capability_t; @@ -164,9 +171,41 @@ typedef enum { * Used to communicate class of service creation options */ typedef struct odp_cls_cos_param { - odp_queue_t queue; /**< Queue associated with CoS */ - odp_pool_t pool; /**< Pool associated with CoS */ - odp_cls_drop_t drop_policy; /**< Drop policy associated with CoS */ + /** Number of queues to be linked to this CoS. + * If the number is greater than 1 then hashing is enabled. + * If number is equal to 1 then hashing is disabled. + * When hashing is enabled the queues are created by the implementation + * and application need not configure any queue to the class of service. + * When hashing is disabled application has to configure the queue to + * the class of service. + * Depening on the implementation this number might be rounded-off to + * nearest supported value (e.g power of 2) + */ + uint32_t num_queue; + + /** Variant mapping for queue hash configurataion */ + union { + /** Mapping used when num_queue = 1, hashing is disabled in + * this case and application has to configure this queue and + * packets are delivered to this queue */ + odp_queue_t queue; + + /** Mapping used when num_queue > 1, hashing is enabled in + * this case and queues are created by the implementation */ + struct { + /** Queue parameters */ + odp_queue_param_t queue_param; + + /** Protocol header fields which are included in + * packet input hash calculation */ + odp_pktin_hash_proto_t hash_proto; + }; + }; + /** Pool associated with CoS */ + odp_pool_t pool; + + /** Drop policy associated with CoS */ + odp_cls_drop_t drop_policy; } odp_cls_cos_param_t;
/** @@ -209,6 +248,23 @@ int odp_cls_capability(odp_cls_capability_t *capability); odp_cos_t odp_cls_cos_create(const char *name, odp_cls_cos_param_t *param);
/** + * Queue hash result + * Returns the queue within a CoS in which a particular packet will be enqueued + * based on the packet parameters and hash protocol field configured with the + * class of service. + * + * @param cos class of service + * @param packet Packet handle + * + * @retval Returns the queue handle on which this packet will be + * enqueued. + * @retval ODP_QUEUE_INVALID for error case + * + * @note The packet has to be updated with valid header pointers L2, L3 and L4. + */ +odp_queue_t odp_cls_hash_result(odp_cos_t cos, odp_packet_t packet); + +/** * Discard a class-of-service along with all its associated resources * * @param[in] cos_id class-of-service instance. @@ -245,6 +301,31 @@ int odp_cos_queue_set(odp_cos_t cos_id, odp_queue_t queue_id); odp_queue_t odp_cos_queue(odp_cos_t cos_id);
/** + * Get the number of queues linked with the specific class-of-service + * + * @param cos_id class-of-service instance. + * + * @return Number of queues linked with the class-of-service. + */ +uint32_t odp_cls_cos_num_queue(odp_cos_t cos_id); + +/** + * Get the list of queue associated with the specific class-of-service + * + * @param[in] cos_id class-of-service instance. + * + * @param[out] queue Array of queue handles associated + * with the class-of-service. + * + * @param[in] num Maximum number of queue handles to output. + * + * @return Number of queues linked with CoS + * @retval 0 on failure + */ +uint32_t odp_cls_cos_queues(odp_cos_t cos_id, odp_queue_t queue[], + uint32_t num); + +/** * Assign packet drop policy for specific class-of-service * * @param[in] cos_id class-of-service instance.
commit 705062dc19a4ce5e6ae2224c21bc9e32dae64ebc Author: Balasubramanian Manoharan bala.manoharan@linaro.org Date: Tue Jul 25 16:42:15 2017 +0530
linux-generic: add toeplitz hash algorithm
Adds toeplitz hash algorithm implementation for RSS hashing
Signed-off-by: Balasubramanian Manoharan bala.manoharan@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index f43e14be..cfccaa98 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -206,6 +206,7 @@ noinst_HEADERS = \ ${srcdir}/include/protocols/ip.h \ ${srcdir}/include/protocols/ipsec.h \ ${srcdir}/include/protocols/tcp.h \ + ${srcdir}/include/protocols/thash.h \ ${srcdir}/include/protocols/udp.h \ ${srcdir}/Makefile.inc
diff --git a/platform/linux-generic/include/protocols/thash.h b/platform/linux-generic/include/protocols/thash.h new file mode 100644 index 00000000..c938e67e --- /dev/null +++ b/platform/linux-generic/include/protocols/thash.h @@ -0,0 +1,105 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * + * ODP Toeplitz hash function + */ + +#ifndef ODPH_THASH_H_ +#define ODPH_THASH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <protocols/ip.h> + +/** rss data type */ +typedef union { + uint8_t u8[40]; + uint32_t u32[10]; +} rss_key; + +/** IPv4 tuple + * + */ +typedef struct thash_ipv4_tuple { + uint32_t src_addr; + uint32_t dst_addr; + union { + struct { + uint16_t sport; + uint16_t dport; + }; + uint32_t sctp_tag; + }; +} thash_ipv4_tuple_t; + +/** IPv6 tuple */ +typedef struct thash_ipv6_tuple { + _odp_ipv6_addr_t src_addr; + _odp_ipv6_addr_t dst_addr; + union { + struct { + uint16_t sport; + uint16_t dport; + }; + uint32_t sctp_tag; + }; +} thash_ipv6_tuple_t; + +/** Thash tuple union */ +typedef union { + thash_ipv4_tuple_t v4; + thash_ipv6_tuple_t v6; +} thash_tuple_t; + +static inline +void thash_load_ipv6_addr(const _odp_ipv6hdr_t *ipv6, + thash_tuple_t *tuple) +{ + int i; + + for (i = 0; i < 4; i++) { + *(tuple->v6.src_addr.u32 + i) = + odp_be_to_cpu_32(*(ipv6->src_addr.u32 + i)); + + *(tuple->v6.dst_addr.u32 + i) = + odp_be_to_cpu_32(*(ipv6->dst_addr.u32 + i)); + } +} + +static inline +uint32_t thash_softrss(uint32_t *tuple, uint8_t len, + const rss_key key) +{ + uint32_t i, j, ret = 0; + + for (j = 0; j < len; j++) { + for (i = 0; i < 32; i++) { + if (tuple[j] & (1 << (31 - i))) { + ret ^= odp_cpu_to_be_32(((const uint32_t *) + key.u32)[j]) << i | (uint32_t)((uint64_t) + (odp_cpu_to_be_32(((const uint32_t *)key.u32) + [j + 1])) >> (32 - i)); + } + } + } + + return ret; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif
-----------------------------------------------------------------------
Summary of changes: include/odp/api/spec/classification.h | 91 ++++++- platform/linux-generic/Makefile.am | 1 + .../include/odp_classification_datamodel.h | 64 +++-- .../include/odp_classification_inlines.h | 2 +- .../include/odp_classification_internal.h | 7 + platform/linux-generic/include/protocols/thash.h | 105 ++++++++ platform/linux-generic/odp_classification.c | 278 +++++++++++++++++---- 7 files changed, 479 insertions(+), 69 deletions(-) create mode 100644 platform/linux-generic/include/protocols/thash.h
hooks/post-receive