1、rte_ip.h
首先定义mac地址的组装
#define RTE_MAC_4(a, b, c, d) ((uint32_t)(((a) & 0xff) << 24) | \
(((b) & 0xff) << 16) | \
(((c) & 0xff) << 8) | \
((d) & 0xff))
#define RTE_MAC_2(a, b) ((uint16_t)(((a) & 0xff) << 8) | ((b) & 0xff))
2、rte_flow_classify.h
结构体rte_flow_classify_ipv4_5tuple中增加关于mac的存储的变量
struct rte_flow_classify_ipv4_5tuple {
uint32_t dst_ip; /**< Destination IP address in big endian. */
uint32_t dst_ip_mask; /**< Mask of destination IP address. */
uint32_t src_ip; /**< Source IP address in big endian. */
uint32_t src_ip_mask; /**< Mask of destination IP address. */
uint16_t dst_port; /**< Destination port in big endian. */
uint16_t dst_port_mask; /**< Mask of destination port. */
uint16_t src_port; /**< Source Port in big endian. */
uint16_t src_port_mask; /**< Mask of source port. */
/* 新增关于mac的变量 */
uint32_t dst_mac1;
uint32_t dst_mac1_mask;
uint16_t dst_mac2;
uint16_t dst_mac2_mask;
uint32_t src_mac1;
uint32_t src_mac1_mask;
uint16_t src_mac2;
uint16_t src_mac2_mask;
/* ----------end-------------*/
uint8_t proto; /**< L4 protocol. */
uint8_t proto_mask; /**< Mask of L4 protocol. */
};
3、flow_classify.c
增加枚举类型:
enum {
PROTO_FIELD_IPV4,
/**--------------------start mac ------------------**/
DMAC1_FIELD_IPV4,
DMAC2_FIELD_IPV4,
SMAC1_FIELD_IPV4,
SMAC2_FIELD_IPV4,
/*-----------------------------end mac--------------*/
SRC_FIELD_IPV4,
DST_FIELD_IPV4,
SRCP_FIELD_IPV4,
DSTP_FIELD_IPV4,
NUM_FIELDS_IPV4
};
enum {
PROTO_INPUT_IPV4,
/**--------------------start mac ------------------**/
MAC1_INPUT_IPV4,
MAC2_INPUT_IPV4,
MAC3_INPUT_IPV4,
/*-----------------------------end mac--------------*/
SRC_INPUT_IPV4,
DST_INPUT_IPV4,
SRCP_DESTP_INPUT_IPV4,
};
结构体中定义需要匹配的字段
static struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
/* first input field - always one byte long. */
{
.type = RTE_ACL_FIELD_TYPE_BITMASK,
.size = sizeof(uint8_t),
.field_index = PROTO_FIELD_IPV4,
.input_index = PROTO_INPUT_IPV4,
.offset = sizeof(struct rte_ether_hdr) +
offsetof(struct rte_ipv4_hdr, next_proto_id),
},
/*------------------start mac-----------------------*/
{
.type = RTE_ACL_FIELD_TYPE_BITMASK,
.size = sizeof(uint32_t),
.field_index = DMAC1_FIELD_IPV4,
.input_index = MAC1_INPUT_IPV4,
.offset = 0,
},
{
.type = RTE_ACL_FIELD_TYPE_BITMASK,
.size = sizeof(uint16_t),
.field_index = DMAC2_FIELD_IPV4,
.input_index = MAC2_INPUT_IPV4,
.offset = sizeof(uint32_t),
},
{
.type = RTE_ACL_FIELD_TYPE_BITMASK,
.size = sizeof(uint16_t),
.field_index = SMAC1_FIELD_IPV4,
.input_index = MAC2_INPUT_IPV4,
.offset = sizeof(uint32_t) + sizeof(uint16_t),
},
{
.type = RTE_ACL_FIELD_TYPE_BITMASK,
.size = sizeof(uint32_t),
.field_index = SMAC2_FIELD_IPV4,
.input_index = MAC3_INPUT_IPV4,
.offset = sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t),
},
/*------------------end mac-----------------------*/
/* next input field (IPv4 source address) - 4 consecutive bytes. */
{
/* rte_flow uses a bit mask for IPv4 addresses */
.type = RTE_ACL_FIELD_TYPE_BITMASK,
.size = sizeof(uint32_t),
.field_index = SRC_FIELD_IPV4,
.input_index = SRC_INPUT_IPV4,
.offset = sizeof(struct rte_ether_hdr) +
offsetof(struct rte_ipv4_hdr, src_addr),
},
/* next input field (IPv4 destination address) - 4 consecutive bytes. */
{
/* rte_flow uses a bit mask for IPv4 addresses */
.type = RTE_ACL_FIELD_TYPE_BITMASK,
.size = sizeof(uint32_t),
.field_index = DST_FIELD_IPV4,
.input_index = DST_INPUT_IPV4,
.offset = sizeof(struct rte_ether_hdr) +
offsetof(struct rte_ipv4_hdr, dst_addr),
},
/*
* Next 2 fields (src & dst ports) form 4 consecutive bytes.
* They share the same input index.
*/
{
/* rte_flow uses a bit mask for protocol ports */
.type = RTE_ACL_FIELD_TYPE_BITMASK,
.size = sizeof(uint16_t),
.field_index = SRCP_FIELD_IPV4,
.input_index = SRCP_DESTP_INPUT_IPV4,
.offset = sizeof(struct rte_ether_hdr) +
sizeof(struct rte_ipv4_hdr) +
offsetof(struct rte_tcp_hdr, src_port),
},
{
/* rte_flow uses a bit mask for protocol ports */
.type = RTE_ACL_FIELD_TYPE_BITMASK,
.size = sizeof(uint16_t),
.field_index = DSTP_FIELD_IPV4,
.input_index = SRCP_DESTP_INPUT_IPV4,
.offset = sizeof(struct rte_ether_hdr) +
sizeof(struct rte_ipv4_hdr) +
offsetof(struct rte_tcp_hdr, dst_port),
},
};
增加解析mac地址 函数
static int
parse_dmac_addr(char *in, uint32_t *mac_addr, uint16_t *mac_addr_low)
{
uint32_t a, b, c, d, e, f;
if (get_cb_field(&in, &a, 16, UINT8_MAX, ':'))
return -EINVAL;
if (get_cb_field(&in, &b, 16, UINT8_MAX, ':'))
return -EINVAL;
if (get_cb_field(&in, &c, 16, UINT8_MAX, ':'))
return -EINVAL;
if (get_cb_field(&in, &d, 16, UINT8_MAX, ':'))
return -EINVAL;
if (get_cb_field(&in, &e, 16, UINT8_MAX, ':'))
return -EINVAL;
if (get_cb_field(&in, &f, 16, UINT8_MAX, 0))
return -EINVAL;
mac_addr[0] = RTE_MAC_4(a, b, c, d);
mac_addr_low[0] = RTE_MAC_2(e,f);
return 0;
}
static int
parse_smac_addr(char *in, uint16_t *mac_addr_high, uint32_t *mac_addr)
{
uint32_t a, b, c, d, e, f;
if (get_cb_field(&in, &a, 16, UINT8_MAX, ':'))
return -EINVAL;
if (get_cb_field(&in, &b, 16, UINT8_MAX, ':'))
return -EINVAL;
if (get_cb_field(&in, &c, 16, UINT8_MAX, ':'))
return -EINVAL;
if (get_cb_field(&in, &d, 16, UINT8_MAX, ':'))
return -EINVAL;
if (get_cb_field(&in, &e, 16, UINT8_MAX, ':'))
return -EINVAL;
if (get_cb_field(&in, &f, 16, UINT8_MAX, 0))
return -EINVAL;
mac_addr_high[0] = RTE_MAC_2(a,b);
mac_addr[0] = RTE_MAC_4(c, d, e, f);
return 0;
}
parse_ipv4_5tuple_rule函数中增加解析mac的函数
static int
parse_ipv4_5tuple_rule(char *str, struct rte_eth_ntuple_filter *ntuple_filter)
{
/*...此处省略前面代码....*/
if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim,
sizeof(cb_port_delim)) != 0)
return -EINVAL;
if (get_cb_field(&in[CB_FLD_DST_PORT_MASK], &temp, 0, UINT16_MAX, 0))
return -EINVAL;
ntuple_filter->dst_port_mask = (uint16_t)temp;
if (get_cb_field(&in[CB_FLD_PROTO], &temp, 0, UINT8_MAX, '/'))
return -EINVAL;
ntuple_filter->proto = (uint8_t)temp;
if (get_cb_field(&in[CB_FLD_PROTO], &temp, 0, UINT8_MAX, 0))
return -EINVAL;
ntuple_filter->proto_mask = (uint8_t)temp;
/* ----------------start mac--------------------*/
ret = parse_smac_addr(in[CB_FLD_SRC_MAC],
&ntuple_filter->src_mac1,
&ntuple_filter->src_mac2);
ntuple_filter->src_mac1_mask = 16;
ntuple_filter->src_mac2_mask = 32;
if (ret != 0) {
flow_classify_log("failed to read source mac/mask: %s\n",
in[CB_FLD_SRC_ADDR]);
return ret;
}
ret = parse_dmac_addr(in[CB_FLD_DST_MAC],
&ntuple_filter->dst_mac1,
&ntuple_filter->dst_mac2);
ntuple_filter->dst_mac1_mask = 32;
ntuple_filter->dst_mac2_mask = 16;
if (ret != 0) {
flow_classify_log("failed to read source mac/mask: %s\n",
in[CB_FLD_SRC_ADDR]);
return ret;
}
/* ----------------end mac--------------------*/
if (get_cb_field(&in[CB_FLD_PRIORITY], &temp, 0, UINT16_MAX, 0))
return -EINVAL;
ntuple_filter->priority = (uint16_t)temp;
if (ntuple_filter->priority > FLOW_CLASSIFY_MAX_PRIORITY)
ret = -EINVAL;
/*...此处省略后面代码.....*/
}
static int
add_classify_rule(struct rte_eth_ntuple_filter *ntuple_filter,
struct flow_classifier *cls_app)
{
int ret = -1;
int key_found;
struct rte_flow_error error;
/*-----------------------start mac -------------------------------*/
struct rte_flow_item_eth eth_spec;
struct rte_flow_item_eth eth_mask;
struct rte_flow_item eth_item;
/*-----------------------end mac -------------------------------*/
struct rte_flow_item_ipv4 ipv4_spec;
struct rte_flow_item_ipv4 ipv4_mask;
struct rte_flow_item ipv4_udp_item;
struct rte_flow_item ipv4_tcp_item;
struct rte_flow_item ipv4_sctp_item;
struct rte_flow_item_udp udp_spec;
struct rte_flow_item_udp udp_mask;
struct rte_flow_item udp_item;
struct rte_flow_item_tcp tcp_spec;
struct rte_flow_item_tcp tcp_mask;
struct rte_flow_item tcp_item;
struct rte_flow_item_sctp sctp_spec;
struct rte_flow_item_sctp sctp_mask;
struct rte_flow_item sctp_item;
struct rte_flow_item pattern_ipv4_5tuple[4];
struct rte_flow_classify_rule *rule;
uint8_t ipv4_proto;
if (num_classify_rules >= MAX_NUM_CLASSIFY) {
printf(
"\nINFO: classify rule capacity %d reached\n",
num_classify_rules);
return ret;
}
/*------------------start mac--------------------------------*/
memset(ð_spec, 0, sizeof(eth_spec));
memcpy((void *)ð_spec.hdr.src_addr.addr_bytes[0],(void *)&ntuple_filter->src_mac1,sizeof(ntuple_filter->src_mac1));
memcpy((void *)ð_spec.hdr.src_addr.addr_bytes[2],(void *)&ntuple_filter->src_mac2,sizeof(ntuple_filter->src_mac2));
memcpy((void *)ð_spec.hdr.dst_addr.addr_bytes[0],(void *)&ntuple_filter->dst_mac1,sizeof(ntuple_filter->dst_mac1));
memcpy((void *)ð_spec.hdr.dst_addr.addr_bytes[4],(void *)&ntuple_filter->dst_mac2,sizeof(ntuple_filter->dst_mac2));
memset(ð_mask,0,sizeof(eth_mask));
uint64_t temp;
temp = convert_depth_to_bitmask_64(ntuple_filter->src_mac1_mask + ntuple_filter->src_mac2_mask);
memcpy((void *)eth_mask.hdr.src_addr.addr_bytes,(void *)&temp,6);
temp = convert_depth_to_bitmask_64(ntuple_filter->dst_mac1_mask + ntuple_filter->dst_mac2_mask);
memcpy((void *)eth_mask.hdr.dst_addr.addr_bytes,(void *)&temp,6);
eth_item.type = RTE_FLOW_ITEM_TYPE_ETH;
eth_item.spec = ð_spec;
eth_item.mask = ð_mask;
eth_item.last = NULL;
/*--------------------------end mac---------------------------------*/
/* set up parameters for validate and add */
memset(&ipv4_spec, 0, sizeof(ipv4_spec));
ipv4_spec.hdr.next_proto_id = ntuple_filter->proto;
ipv4_spec.hdr.src_addr = ntuple_filter->src_ip;
ipv4_spec.hdr.dst_addr = ntuple_filter->dst_ip;
ipv4_proto = ipv4_spec.hdr.next_proto_id;
}
4、rte_flow_classify.c
static struct rte_flow_classify_rule *
allocate_acl_ipv4_5tuple_rule(struct rte_flow_classifier *cls)
{
/*----------------前面代码省略-----------------------*/
/* key add values */
rule->u.key.key_add.priority = cls->ntuple_filter.priority;
rule->u.key.key_add.field_value[PROTO_FIELD_IPV4].mask_range.u8 =
cls->ntuple_filter.proto_mask;
rule->u.key.key_add.field_value[PROTO_FIELD_IPV4].value.u8 =
cls->ntuple_filter.proto;
rule->rules.u.ipv4_5tuple.proto = cls->ntuple_filter.proto;
rule->rules.u.ipv4_5tuple.proto_mask = cls->ntuple_filter.proto_mask;
/*--------------------start mac----------------------------*/
rule->u.key.key_add.field_value[SMAC1_FIELD_IPV4].mask_range.u16 =
cls->ntuple_filter.src_mac1_mask;
rule->u.key.key_add.field_value[SMAC1_FIELD_IPV4].value.u16 =
cls->ntuple_filter.src_mac1;
rule->rules.u.ipv4_5tuple.src_mac1_mask = cls->ntuple_filter.src_mac1_mask;
rule->rules.u.ipv4_5tuple.src_mac1 = cls->ntuple_filter.src_mac1;
rule->u.key.key_add.field_value[SMAC2_FIELD_IPV4].mask_range.u32 =
cls->ntuple_filter.src_mac2_mask;
rule->u.key.key_add.field_value[SMAC2_FIELD_IPV4].value.u32 =
cls->ntuple_filter.src_mac2;
rule->rules.u.ipv4_5tuple.src_mac2_mask = cls->ntuple_filter.src_mac2_mask;
rule->rules.u.ipv4_5tuple.src_mac2 = cls->ntuple_filter.src_mac2;
rule->u.key.key_add.field_value[DMAC1_FIELD_IPV4].mask_range.u32 =
cls->ntuple_filter.dst_mac1_mask;
rule->u.key.key_add.field_value[DMAC1_FIELD_IPV4].value.u32 =
cls->ntuple_filter.dst_mac1;
rule->rules.u.ipv4_5tuple.dst_mac1_mask = cls->ntuple_filter.dst_mac1_mask;
rule->rules.u.ipv4_5tuple.dst_mac1 = cls->ntuple_filter.dst_mac1;
rule->u.key.key_add.field_value[DMAC2_FIELD_IPV4].mask_range.u16 =
cls->ntuple_filter.dst_mac2_mask;
rule->u.key.key_add.field_value[DMAC2_FIELD_IPV4].value.u16 =
cls->ntuple_filter.dst_mac2;
rule->rules.u.ipv4_5tuple.dst_mac2_mask = cls->ntuple_filter.dst_mac2_mask;
rule->rules.u.ipv4_5tuple.dst_mac2 = cls->ntuple_filter.dst_mac2;
/*--------------------end mac----------------------------*/
rule->u.key.key_add.field_value[SRC_FIELD_IPV4].mask_range.u32 =
cls->ntuple_filter.src_ip_mask;
rule->u.key.key_add.field_value[SRC_FIELD_IPV4].value.u32 =
cls->ntuple_filter.src_ip;
rule->rules.u.ipv4_5tuple.src_ip_mask = cls->ntuple_filter.src_ip_mask;
rule->rules.u.ipv4_5tuple.src_ip = cls->ntuple_filter.src_ip;
/*------------------后面代码省略---------------------------*/
}
5、rte_flow_classify_parse.c
static int
classify_parse_ntuple_filter(const struct rte_flow_attr *attr,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
struct rte_eth_ntuple_filter *filter,
struct rte_flow_error *error)
{
const struct rte_flow_item *item;
const struct rte_flow_action *act;
/*------------------------start mac--------------------------*/
const struct rte_flow_item_eth *eth_spec;
const struct rte_flow_item_eth *eth_mask;
/*------------------------end mac--------------------------*/
const struct rte_flow_item_ipv4 *ipv4_spec;
const struct rte_flow_item_ipv4 *ipv4_mask;
const struct rte_flow_item_tcp *tcp_spec;
const struct rte_flow_item_tcp *tcp_mask;
const struct rte_flow_item_udp *udp_spec;
const struct rte_flow_item_udp *udp_mask;
const struct rte_flow_item_sctp *sctp_spec;
const struct rte_flow_item_sctp *sctp_mask;
const struct rte_flow_action_count *count;
const struct rte_flow_action_mark *mark_spec;
uint32_t index;
/* parse pattern */
index = 0;
/* the first not void item can be MAC or IPv4 */
NEXT_ITEM_OF_PATTERN(item, pattern, index);
if (item->type != RTE_FLOW_ITEM_TYPE_ETH &&
item->type != RTE_FLOW_ITEM_TYPE_IPV4) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
item, "Not supported by ntuple filter");
return -EINVAL;
}
/* Skip Ethernet */
if (item->type == RTE_FLOW_ITEM_TYPE_ETH) {
/*Not supported last point for range*/
if (item->last) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
item,
"Not supported last point for range");
return -EINVAL;
}
eth_mask = item->mask;
/* modify supported mac filter --add*/
if (!item->spec || !item->mask) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
item,
"Invalid ntuple mac mask");
return -EINVAL;
}
/*-----------------------start mac---------------------------*/
memcpy(&filter->src_mac1_mask,ð_mask->hdr.src_addr.addr_bytes[0],2);
memcpy(&filter->src_mac2_mask,ð_mask->hdr.src_addr.addr_bytes[2],4);
memcpy(&filter->dst_mac1_mask,ð_mask->hdr.dst_addr.addr_bytes[0],4);
memcpy(&filter->dst_mac2_mask,ð_mask->hdr.dst_addr.addr_bytes[4],2);
eth_spec = item->spec;
memcpy(&filter->src_mac1,ð_spec->hdr.src_addr.addr_bytes[0],2);
memcpy(&filter->src_mac2,ð_spec->hdr.src_addr.addr_bytes[2],4);
memcpy(&filter->dst_mac1,ð_spec->hdr.dst_addr.addr_bytes[0],4);
memcpy(&filter->dst_mac2,ð_spec->hdr.dst_addr.addr_bytes[4],2);
/*-----------------------end mac---------------------------*/
/* check if the next not void item is IPv4 */
index++;
NEXT_ITEM_OF_PATTERN(item, pattern, index);
if (item->type != RTE_FLOW_ITEM_TYPE_IPV4) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
item,
"Not supported by ntuple filter");
return -EINVAL;
}
}
}
6、配置文件规则
src_ip/masklen dst_ip/masklen src_port : mask dst_port : mask proto/mask src_mac dst mac priority
2.2.2.3/24 2.2.2.7/24 32 : 0xffff 33 : 0xffff 17/0xff 34:cd:34:35:54:45 35:cd:34:35:54:43 0
7、修改dpdk相关的本身一个bug
static int
action_apply(struct rte_flow_classifier *cls,
struct rte_flow_classify_rule *rule,
struct rte_flow_classify_stats *stats)
{
struct rte_flow_classify_ipv4_5tuple_stats *ntuple_stats;
struct rte_flow_classify_table_entry *entry = &rule->entry;
uint64_t count = 0;
uint32_t action_mask = entry->action.action_mask;
int i, ret = -EINVAL;
if (action_mask & (1LLU << RTE_FLOW_ACTION_TYPE_COUNT)) {
for (i = 0; i < cls->nb_pkts; i++) {
/*--------------修改bug--------------------------*/
if((NULL != cls->entries) && (NULL != cls->entries[i])){
if (rule->id == cls->entries[i]->rule_id)
count++;
}
/*---------------修改bug end-------------------------*/
}
if (count) {
ret = 0;
ntuple_stats = stats->stats;
ntuple_stats->counter1 = count;
ntuple_stats->ipv4_5tuple = rule->rules.u.ipv4_5tuple;
}
}
return ret;
}