Last active
August 6, 2018 18:14
-
-
Save petrroll/5a462d65253b18b5e78c2c7efba2cb8c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* classifies generated packets using build contexts */ | |
static int acl_classify(void) | |
{ | |
struct rte_acl_ctx* acl_ctx = g_acl_ctx; | |
for (int i = 0; i < g_bench_config.classifications_nb; i++) | |
{ | |
// get pointer to beginning of 5tuple in ipv4_hdr | |
const uint8_t* packet_5tuple_hdr = ((const uint8_t*)packet_ctx->ipv4header + OFF_IPV42PROTO); | |
u_int32_t result; | |
// classify packet using ACL context and 5tuple | |
if (unlikely(rte_acl_classify(vni_acl_ctx, &packet_5tuple_hdr, &result, 1, 1) != 0)) | |
rte_exit(EXIT_FAILURE, "Failed to classify packet.\n"); | |
#ifdef DEBUG | |
if (g_bench_config.d_classification) | |
{ | |
printf("%i\t%i |", i % g_gen_packets.packets_nb, result); | |
print_one_ipv4_ctxhdr(packet_ctx); | |
} | |
#endif // DEBUG | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# The second number of the PACKET_MATCH row is result -> matched id. If it's -1 the catch-all rule matched. If it's 0 no rule matched. | |
make && sudo time ./build/app/acl-bench -- -r 10000 -c 1 -p 1 -n 1 -m -t | |
Rules number: 100 | |
Contexts rebuilds: 1 | |
Packets number: 1 | |
Classifications number: 1 | |
IPv4 ACL entries 100: | |
... | |
RULE: 10000:1.33.65.123/4 17.9.123.145/0 1:65535 1:65535 0x11/0xff 0xffffffff |0|-1| | |
PACKET_MATCH: 0 0 |0|1.33.65.123:10083 -> 17.9.123.145:40757 | 17 | |
make && sudo time ./build/app/acl-bench -- -r 1000 -c 1 -p 1 -n 1 -m -t | |
Rules number: 1000 | |
Contexts rebuilds: 1 | |
Packets number: 1 | |
Classifications number: 1 | |
IPv4 ACL entries 1000: | |
... | |
RULE: 1000:1.33.65.123/4 17.9.123.145/0 1:65535 1:65535 0x11/0xff 0xffffffff |0|-1| | |
PACKET_MATCH: 0 -1 |0|1.33.65.123:10083 -> 17.9.123.145:40757 | 17 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static inline void fill_ipv4_hdr_portswrap(struct ipv4_hdr_portswrap* hdr, uint8_t proto_id, uint32_t src_addr, uint32_t dst_addr, uint16_t src_port, uint16_t dst_port) | |
{ | |
hdr->ipv4hdr.next_proto_id = proto_id; | |
// change bits to network order | |
hdr->ipv4hdr.src_addr = rte_bswap32(src_addr); | |
hdr->ipv4hdr.dst_addr = rte_bswap32(dst_addr); | |
hdr->src_port = rte_bswap16(src_port); | |
hdr->dst_port = rte_bswap16(dst_port); | |
} | |
/* Generates a random ipv4 packet header + subsequent TCP/UDP port info */ | |
static int generate_ipv4_hdr_portswrap(struct ipv4_hdr_portswrap* hdr, int i) | |
{ | |
UNUSED(i); | |
fill_ipv4_hdr_portswrap( | |
hdr, 17, | |
rand_ipv4(), rand_ipv4(), | |
rand_max(1 << 16), rand_max(1 << 16)); | |
// rewrite the randomly generated packet with my own specified one that should always get matched by the catch_all rule // | |
fill_ipv4_hdr_portswrap( | |
hdr, 17, | |
IPv4(1,33,65,123), IPv4(17,9,123,145), | |
10083, 40757); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <rte_ip.h> | |
#define OFF_IPV42PROTO (offsetof(struct ipv4_hdr, next_proto_id)) | |
#define MBUF_IPV4_2PROTO(m) \ | |
rte_pktmbuf_mtod_offset((m), uint8_t *, OFF_IPV42PROTO) | |
/* Wrapper around ipv4_hdr structure that adds subsequent fields for src/dst ports. | |
* Contains all packet data required for ACL matching. | |
*/ | |
struct ipv4_hdr_portswrap { | |
struct ipv4_hdr ipv4hdr; | |
uint16_t src_port; | |
uint16_t dst_port; | |
} __attribute__((__packed__)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Field index in rule*/ | |
enum { | |
PROTO_FIELD_IPV4, | |
SRC_FIELD_IPV4, | |
DST_FIELD_IPV4, | |
SRCP_FIELD_IPV4, | |
DSTP_FIELD_IPV4, | |
NUM_FIELDS_IPV4 | |
}; | |
/* | |
* Defines what 4-byte chunks in input the fields belong to. | |
* - PROTO | |
* - VLAN (TAG and DOMAIN) | |
* - SRC IP ADDRESS | |
* - DST IP ADDRESS | |
* - PORTS (SRC and DST) | |
*/ | |
enum { | |
RTE_ACL_IPV4VLAN_PROTO, | |
RTE_ACL_IPV4VLAN_VLAN, | |
RTE_ACL_IPV4VLAN_SRC, | |
RTE_ACL_IPV4VLAN_DST, | |
RTE_ACL_IPV4VLAN_PORTS, | |
RTE_ACL_IPV4VLAN_NUM | |
}; | |
struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = { | |
{ | |
.type = RTE_ACL_FIELD_TYPE_BITMASK, | |
.size = sizeof(uint8_t), | |
.field_index = PROTO_FIELD_IPV4, | |
.input_index = RTE_ACL_IPV4VLAN_PROTO, | |
.offset = 0, | |
}, | |
{ | |
.type = RTE_ACL_FIELD_TYPE_MASK, | |
.size = sizeof(uint32_t), | |
.field_index = SRC_FIELD_IPV4, | |
.input_index = RTE_ACL_IPV4VLAN_SRC, | |
.offset = offsetof(struct ipv4_hdr, src_addr) - | |
offsetof(struct ipv4_hdr, next_proto_id), | |
}, | |
{ | |
.type = RTE_ACL_FIELD_TYPE_MASK, | |
.size = sizeof(uint32_t), | |
.field_index = DST_FIELD_IPV4, | |
.input_index = RTE_ACL_IPV4VLAN_DST, | |
.offset = offsetof(struct ipv4_hdr, dst_addr) - | |
offsetof(struct ipv4_hdr, next_proto_id), | |
}, | |
{ | |
.type = RTE_ACL_FIELD_TYPE_RANGE, | |
.size = sizeof(uint16_t), | |
.field_index = SRCP_FIELD_IPV4, | |
.input_index = RTE_ACL_IPV4VLAN_PORTS, | |
.offset = sizeof(struct ipv4_hdr) - | |
offsetof(struct ipv4_hdr, next_proto_id), | |
}, | |
{ | |
.type = RTE_ACL_FIELD_TYPE_RANGE, | |
.size = sizeof(uint16_t), | |
.field_index = DSTP_FIELD_IPV4, | |
.input_index = RTE_ACL_IPV4VLAN_PORTS, | |
.offset = sizeof(struct ipv4_hdr) - | |
offsetof(struct ipv4_hdr, next_proto_id) + | |
sizeof(uint16_t), | |
}, | |
}; | |
RTE_ACL_RULE_DEF(acl4_rule, NUM_FIELDS_IPV4); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Allocates array & populates it with generated rules. */ | |
static int add_rules(struct rte_acl_rule** acl_base, int* acl_num, int (*generate_rule)(struct rte_acl_rule*, int i), uint32_t rule_size) | |
{ | |
struct rte_acl_rule* rules = NULL; | |
int rules_num = g_bench_config.rules_nb; | |
rules = calloc(rules_num, rule_size); | |
if (rules == NULL) | |
rte_exit(EXIT_FAILURE, "Couldn't allocate enough to generate rules.\n"); | |
// generate random rules | |
struct rte_acl_rule* rule_slot = NULL; | |
for(int i = 0; i < rules_num - 1; i++) // don't generate last rule -> special one that catches everything | |
{ | |
rule_slot = (struct rte_acl_rule *)((uint8_t*)(rules) + i * rule_size); //uint8_t cast -> the (i * rule_size) addition is interpreted in bytes | |
generate_rule(rule_slot, i); | |
rule_slot->data.priority = (i + 1); | |
rule_slot->data.category_mask = -1; | |
} | |
// generate rule that captures all packets | |
rule_slot = (struct rte_acl_rule *)((uint8_t*)(rules)+(rules_num - 1) * rule_size); //uint8_t cast -> the (i * rule_size) addition is interpreted in bytes | |
generate_rule_catch_all(rule_slot, -2); // -2 -> -1 to user.data -> max number | |
rule_slot->data.priority = RTE_ACL_MIN_PRIORITY; | |
rule_slot->data.category_mask = -1; | |
*acl_base = rules; | |
*acl_num = rules_num; | |
return 0; | |
} | |
/* | |
* Rule generator. | |
*/ | |
static inline void fill_rule(struct rte_acl_rule* rule, | |
uint32_t src_address, uint32_t src_address_mask, | |
uint32_t dst_address, uint32_t dst_address_mask, | |
uint16_t src_port_min, uint16_t src_port_max, | |
uint16_t dst_port_min, uint16_t dst_port_max, | |
uint16_t protocol, uint16_t protocol_mask, | |
uint32_t usr_data) | |
{ | |
rule->field[SRC_FIELD_IPV4].value.u32 = src_address; | |
rule->field[SRC_FIELD_IPV4].mask_range.u32 = src_address_mask; | |
rule->field[DST_FIELD_IPV4].value.u32 = dst_address; | |
rule->field[DST_FIELD_IPV4].mask_range.u32 = dst_address_mask; | |
rule->field[SRCP_FIELD_IPV4].value.u16 = src_port_min; //range -> low | |
rule->field[SRCP_FIELD_IPV4].mask_range.u16 = src_port_max; //range -> high | |
rule->field[DSTP_FIELD_IPV4].value.u16 = dst_port_min; //range -> low | |
rule->field[DSTP_FIELD_IPV4].mask_range.u16 = dst_port_max; //range -> high | |
rule->field[PROTO_FIELD_IPV4].value.u16 = protocol; | |
rule->field[PROTO_FIELD_IPV4].mask_range.u16 = protocol_mask; | |
rule->data.userdata = usr_data; | |
} | |
int generate_rule(struct rte_acl_rule* rule, int i) | |
{ | |
uint16_t src_port = rand_max(1 << 16); | |
uint16_t dst_port = rand_max(1 << 16); | |
fill_rule(rule, | |
rand_ipv4(), rand_max(32), | |
rand_ipv4(), rand_max(32), | |
src_port, rand_min_max(src_port, 1 << 16), | |
dst_port, rand_min_max(dst_port, 1 << 16), | |
17, -1, | |
(i + 1)); | |
return 0; | |
} | |
int generate_rule_catch_all(struct rte_acl_rule* rule, int i) | |
{ | |
UNUSED(i); | |
fill_rule(rule, | |
IPv4(1, 33, 65, 123), 4, //the lower the mask is the less rules there can be for the matching to actually work | |
IPv4(17, 9, 123, 145), 0, | |
1, (1 << 16) - 1, | |
1, (1 << 16) - 1, | |
17, -1, | |
-1); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment