/* * Add ipv4vlan rules to an existing ACL context. * This function is not multi-thread safe. * * @param ctx * ACL context to add patterns to. * @param rules * Array of rules to add to the ACL context. * Note that all fields in rte_acl_ipv4vlan_rule structures are expected * to be in host byte order. * @param num * Number of elements in the input array of rules. * @return * - -ENOMEM if there is no space in the ACL context for these rules. * - -EINVAL if the parameters are invalid. * - Zero if operation completed successfully. */ static int rte_acl_ipv4vlan_add_rules(struct rte_acl_ctx *ctx, const struct rte_acl_ipv4vlan_rule *rules, uint32_t num) { int32_t rc; uint32_t i; struct acl_ipv4vlan_rule rv; if (ctx == NULL || rules == NULL) return -EINVAL; /* check input rules. */ for (i = 0; i != num; i++) { rc = acl_ipv4vlan_check_rule(rules + i); if (rc != 0) { RTE_LOG(ERR, ACL, "%s: rule #%u is invalid\n", __func__, i + 1); return rc; } } /* perform conversion to the internal format and add to the context. */ for (i = 0, rc = 0; i != num && rc == 0; i++) { acl_ipv4vlan_convert_rule(rules + i, &rv); rc = rte_acl_add_rules(ctx, (struct rte_acl_rule *)&rv, 1); } return rc; }
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; }
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 * acl4_init(const char *name, int socketid, const struct acl4_rules *rules, unsigned rules_nb) { char s[PATH_MAX]; struct rte_acl_param acl_param; struct rte_acl_config acl_build_param; struct rte_acl_ctx *ctx; printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM); memset(&acl_param, 0, sizeof(acl_param)); /* Create ACL contexts */ snprintf(s, sizeof(s), "%s_%d", name, socketid); printf("IPv4 %s entries [%u]:\n", s, rules_nb); dump_ipv4_rules(rules, rules_nb, 1); acl_param.name = s; acl_param.socket_id = socketid; acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ipv4_defs)); acl_param.max_rule_num = MAX_ACL_RULE_NUM; ctx = rte_acl_create(&acl_param); if (ctx == NULL) rte_exit(EXIT_FAILURE, "Failed to create ACL context\n"); if (rte_acl_add_rules(ctx, (const struct rte_acl_rule *)rules, rules_nb) < 0) rte_exit(EXIT_FAILURE, "add rules failed\n"); /* Perform builds */ memset(&acl_build_param, 0, sizeof(acl_build_param)); acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES; acl_build_param.num_fields = RTE_DIM(ipv4_defs); memcpy(&acl_build_param.defs, ipv4_defs, sizeof(ipv4_defs)); if (rte_acl_build(ctx, &acl_build_param) != 0) rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n"); rte_acl_dump(ctx); return ctx; }
int mg_5tuple_add_rule(struct rte_acl_ctx * acx, struct mg_5tuple_rule * mgrule, int32_t priority, uint32_t category_mask, uint32_t value){ // FIXME: stack or heap? struct acl_ipv4_rule acl_rules[1]; printf("add mask = %x\n", category_mask); printf("add value = %u\n", value); acl_rules[0].data.userdata = value; acl_rules[0].data.category_mask = category_mask; acl_rules[0].data.priority = priority; acl_rules[0].field[0].value.u8 = mgrule->proto; acl_rules[0].field[0].mask_range.u8 = 0xff; acl_rules[0].field[1].value.u32 = mgrule->ip_src; acl_rules[0].field[1].mask_range.u32 = mgrule->ip_src_prefix; acl_rules[0].field[2].value.u32 = mgrule->ip_dst; acl_rules[0].field[2].mask_range.u32 = mgrule->ip_dst_prefix; acl_rules[0].field[3].value.u16 = mgrule->port_src; acl_rules[0].field[3].mask_range.u16 = mgrule->port_src_range; acl_rules[0].field[4].value.u16 = mgrule->port_dst; acl_rules[0].field[4].mask_range.u16 = mgrule->port_dst_range; return rte_acl_add_rules(acx, (struct rte_acl_rule *)(acl_rules), RTE_DIM(acl_rules)); }