+static int
+table_match_fields_check(struct rte_swx_pipeline *p,
+ struct rte_swx_pipeline_table_params *params,
+ struct header **header,
+ uint32_t *min_offset_field_id,
+ uint32_t *max_offset_field_id)
+{
+ struct header *h0 = NULL;
+ struct field *hf, *mf;
+ uint32_t *offset = NULL, min_offset, max_offset, min_offset_pos, max_offset_pos, i;
+ int status = 0;
+
+ /* Return if no match fields. */
+ if (!params->n_fields) {
+ if (params->fields) {
+ status = -EINVAL;
+ goto end;
+ }
+
+ return 0;
+ }
+
+ /* Memory allocation. */
+ offset = calloc(params->n_fields, sizeof(uint32_t));
+ if (!offset) {
+ status = -ENOMEM;
+ goto end;
+ }
+
+ /* Check that all the match fields belong to either the same header or
+ * to the meta-data.
+ */
+ hf = header_field_parse(p, params->fields[0].name, &h0);
+ mf = metadata_field_parse(p, params->fields[0].name);
+ if (!hf && !mf) {
+ status = -EINVAL;
+ goto end;
+ }
+
+ offset[0] = h0 ? hf->offset : mf->offset;
+
+ for (i = 1; i < params->n_fields; i++)
+ if (h0) {
+ struct header *h;
+
+ hf = header_field_parse(p, params->fields[i].name, &h);
+ if (!hf || (h->id != h0->id)) {
+ status = -EINVAL;
+ goto end;
+ }
+
+ offset[i] = hf->offset;
+ } else {
+ mf = metadata_field_parse(p, params->fields[i].name);
+ if (!mf) {
+ status = -EINVAL;
+ goto end;
+ }
+
+ offset[i] = mf->offset;
+ }
+
+ /* Check that there are no duplicated match fields. */
+ for (i = 0; i < params->n_fields; i++) {
+ uint32_t j;
+
+ for (j = 0; j < i; j++)
+ if (offset[j] == offset[i]) {
+ status = -EINVAL;
+ goto end;
+ }
+ }
+
+ /* Find the min and max offset fields. */
+ min_offset = offset[0];
+ max_offset = offset[0];
+ min_offset_pos = 0;
+ max_offset_pos = 0;
+
+ for (i = 1; i < params->n_fields; i++) {
+ if (offset[i] < min_offset) {
+ min_offset = offset[i];
+ min_offset_pos = i;
+ }
+
+ if (offset[i] > max_offset) {
+ max_offset = offset[i];
+ max_offset_pos = i;
+ }
+ }
+
+ /* Return. */
+ if (header)
+ *header = h0;
+
+ if (min_offset_field_id)
+ *min_offset_field_id = min_offset_pos;
+
+ if (max_offset_field_id)
+ *max_offset_field_id = max_offset_pos;
+
+end:
+ free(offset);
+ return status;
+}
+