net/mlx5: extend IPv6 flow item
[dpdk.git] / drivers / net / mlx5 / mlx5_flow.c
index 7b97a61..a885f6e 100644 (file)
@@ -163,7 +163,9 @@ static const struct mlx5_flow_items mlx5_flow_items[] = {
                .mask = &(const struct rte_flow_item_eth){
                        .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
                        .src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+                       .type = -1,
                },
+               .default_mask = &rte_flow_item_eth_mask,
                .mask_sz = sizeof(struct rte_flow_item_eth),
                .convert = mlx5_flow_create_eth,
                .dst_sz = sizeof(struct ibv_exp_flow_spec_eth),
@@ -175,6 +177,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = {
                .mask = &(const struct rte_flow_item_vlan){
                        .tci = -1,
                },
+               .default_mask = &rte_flow_item_vlan_mask,
                .mask_sz = sizeof(struct rte_flow_item_vlan),
                .convert = mlx5_flow_create_vlan,
                .dst_sz = 0,
@@ -191,12 +194,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = {
                                .next_proto_id = -1,
                        },
                },
-               .default_mask = &(const struct rte_flow_item_ipv4){
-                       .hdr = {
-                               .src_addr = -1,
-                               .dst_addr = -1,
-                       },
-               },
+               .default_mask = &rte_flow_item_ipv4_mask,
                .mask_sz = sizeof(struct rte_flow_item_ipv4),
                .convert = mlx5_flow_create_ipv4,
                .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv4_ext),
@@ -219,11 +217,15 @@ static const struct mlx5_flow_items mlx5_flow_items[] = {
                                        0xff, 0xff, 0xff, 0xff,
                                        0xff, 0xff, 0xff, 0xff,
                                },
+                               .vtc_flow = -1,
+                               .proto = -1,
+                               .hop_limits = -1,
                        },
                },
+               .default_mask = &rte_flow_item_ipv6_mask,
                .mask_sz = sizeof(struct rte_flow_item_ipv6),
                .convert = mlx5_flow_create_ipv6,
-               .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv6),
+               .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv6_ext),
        },
        [RTE_FLOW_ITEM_TYPE_UDP] = {
                .items = ITEMS(RTE_FLOW_ITEM_TYPE_VXLAN),
@@ -234,6 +236,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = {
                                .dst_port = -1,
                        },
                },
+               .default_mask = &rte_flow_item_udp_mask,
                .mask_sz = sizeof(struct rte_flow_item_udp),
                .convert = mlx5_flow_create_udp,
                .dst_sz = sizeof(struct ibv_exp_flow_spec_tcp_udp),
@@ -246,6 +249,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = {
                                .dst_port = -1,
                        },
                },
+               .default_mask = &rte_flow_item_tcp_mask,
                .mask_sz = sizeof(struct rte_flow_item_tcp),
                .convert = mlx5_flow_create_tcp,
                .dst_sz = sizeof(struct ibv_exp_flow_spec_tcp_udp),
@@ -256,6 +260,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = {
                .mask = &(const struct rte_flow_item_vxlan){
                        .vni = "\xff\xff\xff",
                },
+               .default_mask = &rte_flow_item_vxlan_mask,
                .mask_sz = sizeof(struct rte_flow_item_vxlan),
                .convert = mlx5_flow_create_vxlan,
                .dst_sz = sizeof(struct ibv_exp_flow_spec_tunnel),
@@ -410,17 +415,6 @@ priv_flow_validate(struct priv *priv,
 
                if (items->type == RTE_FLOW_ITEM_TYPE_VOID)
                        continue;
-               /* Handle special situation for VLAN. */
-               if (items->type == RTE_FLOW_ITEM_TYPE_VLAN) {
-                       if (((const struct rte_flow_item_vlan *)items)->tci >
-                           ETHER_MAX_VLAN_ID) {
-                               rte_flow_error_set(error, ENOTSUP,
-                                                  RTE_FLOW_ERROR_TYPE_ITEM,
-                                                  items,
-                                                  "wrong VLAN id value");
-                               return -rte_errno;
-                       }
-               }
                for (i = 0;
                     cur_item->items &&
                     cur_item->items[i] != RTE_FLOW_ITEM_TYPE_END;
@@ -435,7 +429,7 @@ priv_flow_validate(struct priv *priv,
                cur_item = token;
                err = mlx5_flow_item_validate(items,
                                              (const uint8_t *)cur_item->mask,
-                                             sizeof(cur_item->mask_sz));
+                                             cur_item->mask_sz);
                if (err)
                        goto exit_item_not_supported;
                if (flow->ibv_attr && cur_item->convert) {
@@ -467,7 +461,13 @@ priv_flow_validate(struct priv *priv,
                                (const struct rte_flow_action_mark *)
                                actions->conf;
 
-                       if (mark && (mark->id >= MLX5_FLOW_MARK_MAX)) {
+                       if (!mark) {
+                               rte_flow_error_set(error, EINVAL,
+                                                  RTE_FLOW_ERROR_TYPE_ACTION,
+                                                  actions,
+                                                  "mark must be defined");
+                               return -rte_errno;
+                       } else if (mark->id >= MLX5_FLOW_MARK_MAX) {
                                rte_flow_error_set(error, ENOTSUP,
                                                   RTE_FLOW_ERROR_TYPE_ACTION,
                                                   actions,
@@ -556,13 +556,16 @@ mlx5_flow_create_eth(const struct rte_flow_item *item,
                mask = default_mask;
        memcpy(eth->val.dst_mac, spec->dst.addr_bytes, ETHER_ADDR_LEN);
        memcpy(eth->val.src_mac, spec->src.addr_bytes, ETHER_ADDR_LEN);
+       eth->val.ether_type = spec->type;
        memcpy(eth->mask.dst_mac, mask->dst.addr_bytes, ETHER_ADDR_LEN);
        memcpy(eth->mask.src_mac, mask->src.addr_bytes, ETHER_ADDR_LEN);
+       eth->mask.ether_type = mask->type;
        /* Remove unwanted bits from values. */
        for (i = 0; i < ETHER_ADDR_LEN; ++i) {
                eth->val.dst_mac[i] &= eth->mask.dst_mac[i];
                eth->val.src_mac[i] &= eth->mask.src_mac[i];
        }
+       eth->val.ether_type &= eth->mask.ether_type;
        return 0;
 }
 
@@ -668,15 +671,14 @@ mlx5_flow_create_ipv6(const struct rte_flow_item *item,
        const struct rte_flow_item_ipv6 *spec = item->spec;
        const struct rte_flow_item_ipv6 *mask = item->mask;
        struct mlx5_flow *flow = (struct mlx5_flow *)data;
-       struct ibv_exp_flow_spec_ipv6 *ipv6;
-       unsigned int ipv6_size = sizeof(struct ibv_exp_flow_spec_ipv6);
-       unsigned int i;
+       struct ibv_exp_flow_spec_ipv6_ext *ipv6;
+       unsigned int ipv6_size = sizeof(struct ibv_exp_flow_spec_ipv6_ext);
 
        ++flow->ibv_attr->num_of_specs;
        flow->ibv_attr->priority = 1;
        ipv6 = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
-       *ipv6 = (struct ibv_exp_flow_spec_ipv6) {
-               .type = flow->inner | IBV_EXP_FLOW_SPEC_IPV6,
+       *ipv6 = (struct ibv_exp_flow_spec_ipv6_ext) {
+               .type = flow->inner | IBV_EXP_FLOW_SPEC_IPV6_EXT,
                .size = ipv6_size,
        };
        if (!spec)
@@ -691,11 +693,12 @@ mlx5_flow_create_ipv6(const struct rte_flow_item *item,
               RTE_DIM(ipv6->mask.src_ip));
        memcpy(ipv6->mask.dst_ip, mask->hdr.dst_addr,
               RTE_DIM(ipv6->mask.dst_ip));
-       /* Remove unwanted bits from values. */
-       for (i = 0; i < RTE_DIM(ipv6->val.src_ip); ++i) {
-               ipv6->val.src_ip[i] &= ipv6->mask.src_ip[i];
-               ipv6->val.dst_ip[i] &= ipv6->mask.dst_ip[i];
-       }
+       ipv6->mask.flow_label = mask->hdr.vtc_flow;
+       ipv6->mask.next_hdr = mask->hdr.proto;
+       ipv6->mask.hop_limit = mask->hdr.hop_limits;
+       ipv6->val.flow_label &= ipv6->mask.flow_label;
+       ipv6->val.next_hdr &= ipv6->mask.next_hdr;
+       ipv6->val.hop_limit &= ipv6->mask.hop_limit;
        return 0;
 }
 
@@ -906,6 +909,12 @@ priv_flow_create_action_queue(struct priv *priv,
                                                 .pd = priv->pd,
                                                 .cq = rte_flow->cq,
                                                 });
+               if (!rte_flow->wq) {
+                       rte_flow_error_set(error, ENOMEM,
+                                          RTE_FLOW_ERROR_TYPE_HANDLE,
+                                          NULL, "cannot allocate WQ");
+                       goto error;
+               }
        } else {
                rxq = container_of((*priv->rxqs)[action->queue_id],
                                   struct rxq_ctrl, rxq);
@@ -952,6 +961,8 @@ priv_flow_create_action_queue(struct priv *priv,
                                   NULL, "cannot allocate QP");
                goto error;
        }
+       if (!priv->started)
+               return rte_flow;
        rte_flow->ibv_flow = ibv_exp_create_flow(rte_flow->qp,
                                                 rte_flow->ibv_attr);
        if (!rte_flow->ibv_flow) {
@@ -970,7 +981,6 @@ error:
                ibv_exp_destroy_wq(rte_flow->wq);
        if (!rte_flow->rxq && rte_flow->cq)
                ibv_destroy_cq(rte_flow->cq);
-       rte_free(rte_flow->ibv_attr);
        rte_free(rte_flow);
        return NULL;
 }
@@ -1064,6 +1074,8 @@ priv_flow_create(struct priv *priv,
        }
        rte_flow = priv_flow_create_action_queue(priv, flow.ibv_attr,
                                                 &action, error);
+       if (!rte_flow)
+               goto exit;
        return rte_flow;
 exit:
        rte_free(flow.ibv_attr);