DPDK-flow_classify 增加mac地址匹配

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(&eth_spec, 0, sizeof(eth_spec));
    memcpy((void *)&eth_spec.hdr.src_addr.addr_bytes[0],(void *)&ntuple_filter->src_mac1,sizeof(ntuple_filter->src_mac1));
    memcpy((void *)&eth_spec.hdr.src_addr.addr_bytes[2],(void *)&ntuple_filter->src_mac2,sizeof(ntuple_filter->src_mac2));
    memcpy((void *)&eth_spec.hdr.dst_addr.addr_bytes[0],(void *)&ntuple_filter->dst_mac1,sizeof(ntuple_filter->dst_mac1));
    memcpy((void *)&eth_spec.hdr.dst_addr.addr_bytes[4],(void *)&ntuple_filter->dst_mac2,sizeof(ntuple_filter->dst_mac2));
    memset(&eth_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 = &eth_spec;
    eth_item.mask = &eth_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,&eth_mask->hdr.src_addr.addr_bytes[0],2);
        memcpy(&filter->src_mac2_mask,&eth_mask->hdr.src_addr.addr_bytes[2],4);
        memcpy(&filter->dst_mac1_mask,&eth_mask->hdr.dst_addr.addr_bytes[0],4);
        memcpy(&filter->dst_mac2_mask,&eth_mask->hdr.dst_addr.addr_bytes[4],2);

        eth_spec = item->spec;
        memcpy(&filter->src_mac1,&eth_spec->hdr.src_addr.addr_bytes[0],2);
        memcpy(&filter->src_mac2,&eth_spec->hdr.src_addr.addr_bytes[2],4);
        memcpy(&filter->dst_mac1,&eth_spec->hdr.dst_addr.addr_bytes[0],4);
        memcpy(&filter->dst_mac2,&eth_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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值