static int rte_table_acl_build(struct rte_table_acl *acl, struct rte_acl_ctx **acl_ctx) { struct rte_acl_ctx *ctx = NULL; uint32_t n_rules, i; int status; /* Create low level ACL table */ ctx = rte_acl_create(&acl->acl_params); if (ctx == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot create low level ACL table\n", __func__); return -1; } /* Add rules to low level ACL table */ n_rules = 0; for (i = 1; i < acl->n_rules; i++) { if (acl->acl_rule_list[i] != NULL) { status = rte_acl_add_rules(ctx, acl->acl_rule_list[i], 1); if (status != 0) { RTE_LOG(ERR, TABLE, "%s: Cannot add rule to low level ACL table\n", __func__); rte_acl_free(ctx); return -1; } n_rules++; } } if (n_rules == 0) { rte_acl_free(ctx); *acl_ctx = NULL; return 0; } /* Build low level ACl table */ status = rte_acl_build(ctx, &acl->cfg); if (status != 0) { RTE_LOG(ERR, TABLE, "%s: Cannot build the low level ACL table\n", __func__); rte_acl_free(ctx); return -1; } rte_acl_dump(ctx); *acl_ctx = ctx; return 0; }
static struct rte_acl_ctx * setup_acl(struct rte_acl_rule *acl_base, unsigned int acl_num, int ipv6, int socketid) { char name[PATH_MAX]; struct rte_acl_param acl_param; struct rte_acl_config acl_build_param; struct rte_acl_ctx *context; int dim = ipv6 ? RTE_DIM(ipv6_defs) : RTE_DIM(ipv4_defs); static uint32_t ctx_count[NB_SOCKETS] = {0}; if (!acl_num) return NULL; /* Create ACL contexts */ snprintf(name, sizeof(name), "%s%d-%d", ipv6 ? L3FWD_ACL_IPV6_NAME : L3FWD_ACL_IPV4_NAME, socketid, ctx_count[socketid]++); acl_param.name = name; acl_param.socket_id = socketid; acl_param.rule_size = RTE_ACL_RULE_SZ(dim); acl_param.max_rule_num = MAX_ACL_RULE_NUM; if ((context = rte_acl_create(&acl_param)) == NULL) { acl_log("Failed to create ACL context\n"); goto err; } if (acl_parm_config.aclavx2 && rte_acl_set_ctx_classify(context, RTE_ACL_CLASSIFY_AVX2) != 0) { acl_log("Failed to setup classify method for ACL context\n"); goto err; } if (rte_acl_add_rules(context, acl_base, acl_num) < 0) { acl_log("add rules failed\n"); goto err; } /* Perform builds */ memset(&acl_build_param, 0, sizeof(acl_build_param)); acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES; acl_build_param.num_fields = dim; memcpy(&acl_build_param.defs, ipv6 ? ipv6_defs : ipv4_defs, ipv6 ? sizeof(ipv6_defs) : sizeof(ipv4_defs)); if (rte_acl_build(context, &acl_build_param) != 0) { acl_log("Failed to build ACL trie\n"); goto err; } rte_acl_dump(context); return context; err: rte_acl_free(context); return NULL; }
struct rte_acl_ctx * mg_5tuple_create_filter(int socket_id, uint32_t num_rules){ // FIXME: is prm on stack OK? or does this have to be on HEAP? struct rte_acl_param prm = { .name = "ACL_5tuple_filter", .socket_id = socket_id, .rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ipv4_defs)), /* number of fields per rule. */ .max_rule_num = num_rules, /* maximum number of rules in the AC context. */ }; return rte_acl_create(&prm); } void mg_5tuple_destruct_filter(struct rte_acl_ctx * acl){ rte_acl_free(acl); }
static int rte_table_acl_free(void *table) { struct rte_table_acl *acl = (struct rte_table_acl *) table; /* Check input parameters */ if (table == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } /* Free previously allocated resources */ if (acl->ctx != NULL) rte_acl_free(acl->ctx); rte_free(acl); return 0; }
static int rte_table_acl_entry_delete( void *table, void *key, int *key_found, void *entry) { struct rte_table_acl *acl = (struct rte_table_acl *) table; struct rte_table_acl_rule_delete_params *rule = (struct rte_table_acl_rule_delete_params *) key; struct rte_acl_rule *deleted_rule = NULL; struct rte_acl_ctx *ctx; uint32_t pos, pos_valid, i; int status; /* Check input parameters */ if (table == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } if (key == NULL) { RTE_LOG(ERR, TABLE, "%s: key parameter is NULL\n", __func__); return -EINVAL; } if (key_found == NULL) { RTE_LOG(ERR, TABLE, "%s: key_found parameter is NULL\n", __func__); return -EINVAL; } /* Look for the rule in the table */ pos = 0; pos_valid = 0; for (i = 1; i < acl->n_rules; i++) { if (acl->acl_rule_list[i] != NULL) { /* Compare the key fields */ status = memcmp(&acl->acl_rule_list[i]->field[0], &rule->field_value[0], acl->cfg.num_fields * sizeof(struct rte_acl_field)); /* Rule found: remove from table */ if (status == 0) { pos = i; pos_valid = 1; deleted_rule = acl->acl_rule_list[i]; acl->acl_rule_list[i] = NULL; } } } /* Return if rule not found */ if (pos_valid == 0) { *key_found = 0; return 0; } /* Build low level ACL table */ acl->name_id ^= 1; acl->acl_params.name = acl->name[acl->name_id]; status = rte_table_acl_build(acl, &ctx); if (status != 0) { /* Roll back changes */ acl->acl_rule_list[pos] = deleted_rule; acl->name_id ^= 1; return -EINVAL; } /* Commit changes */ if (acl->ctx != NULL) rte_acl_free(acl->ctx); acl->ctx = ctx; *key_found = 1; if (entry != NULL) memcpy(entry, &acl->memory[pos * acl->entry_size], acl->entry_size); return 0; }
static int rte_table_acl_entry_add( void *table, void *key, void *entry, int *key_found, void **entry_ptr) { struct rte_table_acl *acl = (struct rte_table_acl *) table; struct rte_table_acl_rule_add_params *rule = (struct rte_table_acl_rule_add_params *) key; struct rte_pipeline_acl_rule acl_rule; struct rte_acl_rule *rule_location; struct rte_acl_ctx *ctx; uint32_t free_pos, free_pos_valid, i; int status; /* Check input parameters */ if (table == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } if (key == NULL) { RTE_LOG(ERR, TABLE, "%s: key parameter is NULL\n", __func__); return -EINVAL; } if (entry == NULL) { RTE_LOG(ERR, TABLE, "%s: entry parameter is NULL\n", __func__); return -EINVAL; } if (key_found == NULL) { RTE_LOG(ERR, TABLE, "%s: key_found parameter is NULL\n", __func__); return -EINVAL; } if (entry_ptr == NULL) { RTE_LOG(ERR, TABLE, "%s: entry_ptr parameter is NULL\n", __func__); return -EINVAL; } if (rule->priority > RTE_ACL_MAX_PRIORITY) { RTE_LOG(ERR, TABLE, "%s: Priority is too high\n", __func__); return -EINVAL; } /* Setup rule data structure */ memset(&acl_rule, 0, sizeof(acl_rule)); acl_rule.data.category_mask = 1; acl_rule.data.priority = RTE_ACL_MAX_PRIORITY - rule->priority; acl_rule.data.userdata = 0; /* To be set up later */ memcpy(&acl_rule.field[0], &rule->field_value[0], acl->cfg.num_fields * sizeof(struct rte_acl_field)); /* Look to see if the rule exists already in the table */ free_pos = 0; free_pos_valid = 0; for (i = 1; i < acl->n_rules; i++) { if (acl->acl_rule_list[i] == NULL) { if (free_pos_valid == 0) { free_pos = i; free_pos_valid = 1; } continue; } /* Compare the key fields */ status = memcmp(&acl->acl_rule_list[i]->field[0], &rule->field_value[0], acl->cfg.num_fields * sizeof(struct rte_acl_field)); /* Rule found: update data associated with the rule */ if (status == 0) { *key_found = 1; *entry_ptr = &acl->memory[i * acl->entry_size]; memcpy(*entry_ptr, entry, acl->entry_size); return 0; } } /* Return if max rules */ if (free_pos_valid == 0) { RTE_LOG(ERR, TABLE, "%s: Max number of rules reached\n", __func__); return -ENOSPC; } /* Add the new rule to the rule set */ acl_rule.data.userdata = free_pos; rule_location = (struct rte_acl_rule *) &acl->acl_rule_memory[free_pos * acl->acl_params.rule_size]; memcpy(rule_location, &acl_rule, acl->acl_params.rule_size); acl->acl_rule_list[free_pos] = rule_location; /* Build low level ACL table */ acl->name_id ^= 1; acl->acl_params.name = acl->name[acl->name_id]; status = rte_table_acl_build(acl, &ctx); if (status != 0) { /* Roll back changes */ acl->acl_rule_list[free_pos] = NULL; acl->name_id ^= 1; return -EINVAL; } /* Commit changes */ if (acl->ctx != NULL) rte_acl_free(acl->ctx); acl->ctx = ctx; *key_found = 0; *entry_ptr = &acl->memory[free_pos * acl->entry_size]; memcpy(*entry_ptr, entry, acl->entry_size); return 0; }