net/tap: add preliminary support for flow API
[dpdk.git] / drivers / net / tap / tap_flow.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright 2017 6WIND S.A.
5  *   Copyright 2017 Mellanox.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of 6WIND S.A. nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <sys/queue.h>
35
36 #include <rte_malloc.h>
37 #include <rte_eth_tap.h>
38 #include <tap_flow.h>
39
40 struct rte_flow {
41         LIST_ENTRY(rte_flow) next; /* Pointer to the next rte_flow structure */
42 };
43
44 static int
45 tap_flow_validate(struct rte_eth_dev *dev,
46                   const struct rte_flow_attr *attr,
47                   const struct rte_flow_item items[],
48                   const struct rte_flow_action actions[],
49                   struct rte_flow_error *error);
50
51 static struct rte_flow *
52 tap_flow_create(struct rte_eth_dev *dev,
53                 const struct rte_flow_attr *attr,
54                 const struct rte_flow_item items[],
55                 const struct rte_flow_action actions[],
56                 struct rte_flow_error *error);
57
58 static int
59 tap_flow_destroy(struct rte_eth_dev *dev,
60                  struct rte_flow *flow,
61                  struct rte_flow_error *error);
62
63 static const struct rte_flow_ops tap_flow_ops = {
64         .validate = tap_flow_validate,
65         .create = tap_flow_create,
66         .destroy = tap_flow_destroy,
67         .flush = tap_flow_flush,
68 };
69
70 /**
71  * Validate a flow.
72  *
73  * @see rte_flow_validate()
74  * @see rte_flow_ops
75  */
76 static int
77 tap_flow_validate(struct rte_eth_dev *dev __rte_unused,
78                   const struct rte_flow_attr *attr __rte_unused,
79                   const struct rte_flow_item items[] __rte_unused,
80                   const struct rte_flow_action actions[] __rte_unused,
81                   struct rte_flow_error *error)
82 {
83         return -rte_flow_error_set(error, ENOTSUP,
84                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
85                                    NULL, "not implemented yet");
86 }
87
88 /**
89  * Create a flow.
90  *
91  * @see rte_flow_create()
92  * @see rte_flow_ops
93  */
94 static struct rte_flow *
95 tap_flow_create(struct rte_eth_dev *dev,
96                 const struct rte_flow_attr *attr,
97                 const struct rte_flow_item items[],
98                 const struct rte_flow_action actions[],
99                 struct rte_flow_error *error)
100 {
101         struct pmd_internals *pmd = dev->data->dev_private;
102         struct rte_flow *flow = NULL;
103
104         if (tap_flow_validate(dev, attr, items, actions, error))
105                 return NULL;
106         flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
107         if (!flow) {
108                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
109                                    NULL, "cannot allocate memory for rte_flow");
110                 return NULL;
111         }
112         LIST_INSERT_HEAD(&pmd->flows, flow, next);
113         return flow;
114 }
115
116 /**
117  * Destroy a flow.
118  *
119  * @see rte_flow_destroy()
120  * @see rte_flow_ops
121  */
122 static int
123 tap_flow_destroy(struct rte_eth_dev *dev __rte_unused,
124                  struct rte_flow *flow,
125                  struct rte_flow_error *error __rte_unused)
126 {
127         LIST_REMOVE(flow, next);
128         rte_free(flow);
129         return 0;
130 }
131
132 /**
133  * Destroy all flows.
134  *
135  * @see rte_flow_flush()
136  * @see rte_flow_ops
137  */
138 int
139 tap_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
140 {
141         struct pmd_internals *pmd = dev->data->dev_private;
142         struct rte_flow *flow;
143
144         while (!LIST_EMPTY(&pmd->flows)) {
145                 flow = LIST_FIRST(&pmd->flows);
146                 if (tap_flow_destroy(dev, flow, error) < 0)
147                         return -1;
148         }
149         return 0;
150 }
151
152 /**
153  * Manage filter operations.
154  *
155  * @param dev
156  *   Pointer to Ethernet device structure.
157  * @param filter_type
158  *   Filter type.
159  * @param filter_op
160  *   Operation to perform.
161  * @param arg
162  *   Pointer to operation-specific structure.
163  *
164  * @return
165  *   0 on success, negative errno value on failure.
166  */
167 int
168 tap_dev_filter_ctrl(struct rte_eth_dev *dev,
169                     enum rte_filter_type filter_type,
170                     enum rte_filter_op filter_op,
171                     void *arg)
172 {
173         switch (filter_type) {
174         case RTE_ETH_FILTER_GENERIC:
175                 if (filter_op != RTE_ETH_FILTER_GET)
176                         return -EINVAL;
177                 *(const void **)arg = &tap_flow_ops;
178                 return 0;
179         default:
180                 RTE_LOG(ERR, PMD, "%p: filter type (%d) not supported",
181                         (void *)dev, filter_type);
182         }
183         return -EINVAL;
184 }
185