/* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2010-2018 Intel Corporation */ #include #include #include #include #include #include "rte_eth_softnic_internals.h" /** * Input port */ int softnic_port_in_action_profile_init(struct pmd_internals *p) { TAILQ_INIT(&p->port_in_action_profile_list); return 0; } void softnic_port_in_action_profile_free(struct pmd_internals *p) { for ( ; ; ) { struct softnic_port_in_action_profile *profile; profile = TAILQ_FIRST(&p->port_in_action_profile_list); if (profile == NULL) break; TAILQ_REMOVE(&p->port_in_action_profile_list, profile, node); free(profile); } } struct softnic_port_in_action_profile * softnic_port_in_action_profile_find(struct pmd_internals *p, const char *name) { struct softnic_port_in_action_profile *profile; if (name == NULL) return NULL; TAILQ_FOREACH(profile, &p->port_in_action_profile_list, node) if (strcmp(profile->name, name) == 0) return profile; return NULL; } struct softnic_port_in_action_profile * softnic_port_in_action_profile_create(struct pmd_internals *p, const char *name, struct softnic_port_in_action_profile_params *params) { struct softnic_port_in_action_profile *profile; struct rte_port_in_action_profile *ap; int status; /* Check input params */ if (name == NULL || softnic_port_in_action_profile_find(p, name) || params == NULL) return NULL; if ((params->action_mask & (1LLU << RTE_PORT_IN_ACTION_LB)) && params->lb.f_hash == NULL) { switch (params->lb.key_size) { case 8: params->lb.f_hash = rte_table_hash_crc_key8; break; case 16: params->lb.f_hash = rte_table_hash_crc_key16; break; case 24: params->lb.f_hash = rte_table_hash_crc_key24; break; case 32: params->lb.f_hash = rte_table_hash_crc_key32; break; case 40: params->lb.f_hash = rte_table_hash_crc_key40; break; case 48: params->lb.f_hash = rte_table_hash_crc_key48; break; case 56: params->lb.f_hash = rte_table_hash_crc_key56; break; case 64: params->lb.f_hash = rte_table_hash_crc_key64; break; default: return NULL; } params->lb.seed = 0; } /* Resource */ ap = rte_port_in_action_profile_create(0); if (ap == NULL) return NULL; if (params->action_mask & (1LLU << RTE_PORT_IN_ACTION_FLTR)) { status = rte_port_in_action_profile_action_register(ap, RTE_PORT_IN_ACTION_FLTR, ¶ms->fltr); if (status) { rte_port_in_action_profile_free(ap); return NULL; } } if (params->action_mask & (1LLU << RTE_PORT_IN_ACTION_LB)) { status = rte_port_in_action_profile_action_register(ap, RTE_PORT_IN_ACTION_LB, ¶ms->lb); if (status) { rte_port_in_action_profile_free(ap); return NULL; } } status = rte_port_in_action_profile_freeze(ap); if (status) { rte_port_in_action_profile_free(ap); return NULL; } /* Node allocation */ profile = calloc(1, sizeof(struct softnic_port_in_action_profile)); if (profile == NULL) { rte_port_in_action_profile_free(ap); return NULL; } /* Node fill in */ strlcpy(profile->name, name, sizeof(profile->name)); memcpy(&profile->params, params, sizeof(*params)); profile->ap = ap; /* Node add to list */ TAILQ_INSERT_TAIL(&p->port_in_action_profile_list, profile, node); return profile; } /** * Table */ int softnic_table_action_profile_init(struct pmd_internals *p) { TAILQ_INIT(&p->table_action_profile_list); return 0; } void softnic_table_action_profile_free(struct pmd_internals *p) { for ( ; ; ) { struct softnic_table_action_profile *profile; profile = TAILQ_FIRST(&p->table_action_profile_list); if (profile == NULL) break; TAILQ_REMOVE(&p->table_action_profile_list, profile, node); free(profile); } } struct softnic_table_action_profile * softnic_table_action_profile_find(struct pmd_internals *p, const char *name) { struct softnic_table_action_profile *profile; if (name == NULL) return NULL; TAILQ_FOREACH(profile, &p->table_action_profile_list, node) if (strcmp(profile->name, name) == 0) return profile; return NULL; } struct softnic_table_action_profile * softnic_table_action_profile_create(struct pmd_internals *p, const char *name, struct softnic_table_action_profile_params *params) { struct softnic_table_action_profile *profile; struct rte_table_action_profile *ap; int status; /* Check input params */ if (name == NULL || softnic_table_action_profile_find(p, name) || params == NULL || ((params->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) == 0)) return NULL; if ((params->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) && params->lb.f_hash == NULL) { switch (params->lb.key_size) { case 8: params->lb.f_hash = rte_table_hash_crc_key8; break; case 16: params->lb.f_hash = rte_table_hash_crc_key16; break; case 24: params->lb.f_hash = rte_table_hash_crc_key24; break; case 32: params->lb.f_hash = rte_table_hash_crc_key32; break; case 40: params->lb.f_hash = rte_table_hash_crc_key40; break; case 48: params->lb.f_hash = rte_table_hash_crc_key48; break; case 56: params->lb.f_hash = rte_table_hash_crc_key56; break; case 64: params->lb.f_hash = rte_table_hash_crc_key64; break; default: return NULL; } params->lb.seed = 0; } /* Resource */ ap = rte_table_action_profile_create(¶ms->common); if (ap == NULL) return NULL; if (params->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { status = rte_table_action_profile_action_register(ap, RTE_TABLE_ACTION_FWD, NULL); if (status) { rte_table_action_profile_free(ap); return NULL; } } if (params->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) { status = rte_table_action_profile_action_register(ap, RTE_TABLE_ACTION_LB, ¶ms->lb); if (status) { rte_table_action_profile_free(ap); return NULL; } } if (params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { status = rte_table_action_profile_action_register(ap, RTE_TABLE_ACTION_MTR, ¶ms->mtr); if (status) { rte_table_action_profile_free(ap); return NULL; } } if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) { status = rte_table_action_profile_action_register(ap, RTE_TABLE_ACTION_TM, ¶ms->tm); if (status) { rte_table_action_profile_free(ap); return NULL; } } if (params->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { status = rte_table_action_profile_action_register(ap, RTE_TABLE_ACTION_ENCAP, ¶ms->encap); if (status) { rte_table_action_profile_free(ap); return NULL; } } if (params->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { status = rte_table_action_profile_action_register(ap, RTE_TABLE_ACTION_NAT, ¶ms->nat); if (status) { rte_table_action_profile_free(ap); return NULL; } } if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) { status = rte_table_action_profile_action_register(ap, RTE_TABLE_ACTION_TTL, ¶ms->ttl); if (status) { rte_table_action_profile_free(ap); return NULL; } } if (params->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) { status = rte_table_action_profile_action_register(ap, RTE_TABLE_ACTION_STATS, ¶ms->stats); if (status) { rte_table_action_profile_free(ap); return NULL; } } if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) { status = rte_table_action_profile_action_register(ap, RTE_TABLE_ACTION_TIME, NULL); if (status) { rte_table_action_profile_free(ap); return NULL; } } if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) { status = rte_table_action_profile_action_register(ap, RTE_TABLE_ACTION_TAG, NULL); if (status) { rte_table_action_profile_free(ap); return NULL; } } if (params->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) { status = rte_table_action_profile_action_register(ap, RTE_TABLE_ACTION_DECAP, NULL); if (status) { rte_table_action_profile_free(ap); return NULL; } } if (params->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) { status = rte_table_action_profile_action_register(ap, RTE_TABLE_ACTION_SYM_CRYPTO, ¶ms->sym_crypto); if (status) { rte_table_action_profile_free(ap); return NULL; } } status = rte_table_action_profile_freeze(ap); if (status) { rte_table_action_profile_free(ap); return NULL; } /* Node allocation */ profile = calloc(1, sizeof(struct softnic_table_action_profile)); if (profile == NULL) { rte_table_action_profile_free(ap); return NULL; } /* Node fill in */ strlcpy(profile->name, name, sizeof(profile->name)); memcpy(&profile->params, params, sizeof(*params)); profile->ap = ap; /* Node add to list */ TAILQ_INSERT_TAIL(&p->table_action_profile_list, profile, node); return profile; }