netdev-dpdk: fix mbuf leaks
[cascardo/ovs.git] / ofproto / ofproto-dpif-rid.h
1 /*
2  * Copyright (c) 2014, 2015, 2016 Nicira, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef OFPROTO_DPIF_RID_H
18 #define OFPROTO_DPIF_RID_H
19
20 #include <stddef.h>
21 #include <stdint.h>
22
23 #include "cmap.h"
24 #include "list.h"
25 #include "ofp-actions.h"
26 #include "ofproto-dpif-mirror.h"
27 #include "ovs-thread.h"
28 #include "uuid.h"
29
30 struct ofproto_dpif;
31 struct rule;
32
33 /*
34  * Freezing and recirculation
35  * ==========================
36  *
37  * Freezing is a technique for halting and checkpointing packet translation in
38  * a way that it can be restarted again later.  This file has a couple of data
39  * structures related to freezing in general; their names begin with "frozen".
40  *
41  * Recirculation is the use of freezing to allow a frame to re-enter the
42  * datapath packet processing path to achieve more flexible packet processing,
43  * such as modifying header fields after MPLS POP action and selecting a slave
44  * port for bond ports.
45  *
46  *
47  * Data path and user space interface
48  * -----------------------------------
49  *
50  * Recirculation uses two uint32_t fields, recirc_id and dp_hash, and a RECIRC
51  * action.  recirc_id is used to select the next packet processing steps among
52  * multiple instances of recirculation.  When a packet initially enters the
53  * datapath it is assigned with recirc_id 0, which indicates no recirculation.
54  * Recirc_ids are managed by the user space, opaque to the datapath.
55  *
56  * On the other hand, dp_hash can only be computed by the datapath, opaque to
57  * the user space, as the datapath is free to choose the hashing algorithm
58  * without informing user space about it.  The dp_hash value should be
59  * wildcarded for newly received packets.  HASH action specifies whether the
60  * hash is computed, and if computed, how many fields are to be included in the
61  * hash computation.  The computed hash value is stored into the dp_hash field
62  * prior to recirculation.
63  *
64  * The RECIRC action sets the recirc_id field and then reprocesses the packet
65  * as if it was received again on the same input port.  RECIRC action works
66  * like a function call; actions listed after the RECIRC action will be
67  * executed after recirculation.  RECIRC action can be nested, but datapath
68  * implementation limits the number of nested recirculations to prevent
69  * unreasonable nesting depth or infinite loop.
70  *
71  * User space recirculation context
72  * ---------------------------------
73  *
74  * Recirculation is usually hidden from the OpenFlow controllers.  Action
75  * translation code deduces when recirculation is necessary and issues a
76  * datapath recirculation action.  All OpenFlow actions to be performed after
77  * recirculation are derived from the OpenFlow pipeline and are stored with the
78  * recirculation ID.  When the OpenFlow tables are changed in a way affecting
79  * the recirculation flows, new recirculation ID with new metadata and actions
80  * is allocated and the old one is timed out.
81  *
82  * Recirculation ID pool
83  * ----------------------
84  *
85  * Recirculation ID needs to be unique for all datapaths.  Recirculation ID
86  * pool keeps track of recirculation ids and stores OpenFlow pipeline
87  * translation context so that flow processing may continue after
88  * recirculation.
89  *
90  * A Recirculation ID can be any uint32_t value, except for that the value 0 is
91  * reserved for 'no recirculation' case.
92  *
93  * Thread-safety
94  * --------------
95  *
96  * All APIs are thread safe.
97  */
98
99 /* Metadata for restoring pipeline context after recirculation.  Helpers
100  * are inlined below to keep them together with the definition for easier
101  * updates. */
102 BUILD_ASSERT_DECL(FLOW_WC_SEQ == 35);
103
104 struct frozen_metadata {
105     /* Metadata in struct flow. */
106     const struct flow_tnl *tunnel; /* Encapsulating tunnel parameters. */
107     ovs_be64 metadata;            /* OpenFlow Metadata. */
108     uint64_t regs[FLOW_N_XREGS];  /* Registers. */
109     ofp_port_t in_port;           /* Incoming port. */
110 };
111
112 static inline void
113 frozen_metadata_from_flow(struct frozen_metadata *md,
114                           const struct flow *flow)
115 {
116     memset(md, 0, sizeof *md);
117     md->tunnel = &flow->tunnel;
118     md->metadata = flow->metadata;
119     memcpy(md->regs, flow->regs, sizeof md->regs);
120     md->in_port = flow->in_port.ofp_port;
121 }
122
123 static inline void
124 frozen_metadata_to_flow(const struct frozen_metadata *md,
125                         struct flow *flow)
126 {
127     if (md->tunnel && flow_tnl_dst_is_set(md->tunnel)) {
128         flow->tunnel = *md->tunnel;
129     } else {
130         memset(&flow->tunnel, 0, sizeof flow->tunnel);
131     }
132     flow->metadata = md->metadata;
133     memcpy(flow->regs, md->regs, sizeof flow->regs);
134     flow->in_port.ofp_port = md->in_port;
135 }
136
137 /* State that flow translation can save, to restore when translation
138  * resumes.  */
139 struct frozen_state {
140     /* Initial table for processing when thawing. */
141     uint8_t table_id;
142
143     /* Pipeline context for processing when thawing. */
144     struct uuid ofproto_uuid;     /* Bridge to resume from. */
145     struct frozen_metadata metadata; /* Flow metadata. */
146     union mf_subvalue *stack;     /* Stack if any. */
147     size_t n_stack;
148     mirror_mask_t mirrors;        /* Mirrors already output. */
149     bool conntracked;             /* Conntrack occurred prior to freeze. */
150
151     /* Actions to be translated when thawing. */
152     struct ofpact *ofpacts;
153     size_t ofpacts_len;           /* Size of 'ofpacts', in bytes. */
154     struct ofpact *action_set;
155     size_t action_set_len;        /* Size of 'action_set', in bytes. */
156 };
157
158 /* This maps a recirculation ID to saved state that flow translation can
159  * restore when recirculation occurs. */
160 struct recirc_id_node {
161     /* Index data. */
162     struct ovs_list exp_node OVS_GUARDED;
163     struct cmap_node id_node;
164     struct cmap_node metadata_node;
165     uint32_t id;
166     uint32_t hash;
167     struct ovs_refcount refcount;
168
169     /* Saved state.
170      *
171      * This state should not be modified after inserting a node in the pool,
172      * hence the 'const' to emphasize that. */
173     const struct frozen_state state;
174
175     /* Storage for tunnel metadata. */
176     struct flow_tnl state_metadata_tunnel;
177 };
178
179 void recirc_init(void);
180
181 /* This is only used for bonds and will go away when bonds implementation is
182  * updated to use this mechanism instead of internal rules. */
183 uint32_t recirc_alloc_id(struct ofproto_dpif *);
184
185 uint32_t recirc_alloc_id_ctx(const struct frozen_state *);
186 uint32_t recirc_find_id(const struct frozen_state *);
187 void recirc_free_id(uint32_t recirc_id);
188 void recirc_free_ofproto(struct ofproto_dpif *, const char *ofproto_name);
189
190 const struct recirc_id_node *recirc_id_node_find(uint32_t recirc_id);
191
192 static inline struct recirc_id_node *
193 recirc_id_node_from_state(const struct frozen_state *state)
194 {
195     return CONTAINER_OF(state, struct recirc_id_node, state);
196 }
197
198 static inline bool recirc_id_node_try_ref_rcu(const struct recirc_id_node *n_)
199 {
200     struct recirc_id_node *node = CONST_CAST(struct recirc_id_node *, n_);
201
202     return node ? ovs_refcount_try_ref_rcu(&node->refcount) : false;
203 }
204
205 void recirc_id_node_unref(const struct recirc_id_node *);
206
207 void recirc_run(void);
208
209 /* Recirculation IDs on which references are held. */
210 struct recirc_refs {
211     unsigned n_recircs;
212     union {
213         uint32_t recirc[2];   /* When n_recircs == 1 or 2 */
214         uint32_t *recircs;    /* When 'n_recircs' > 2 */
215     };
216 };
217
218 #define RECIRC_REFS_EMPTY_INITIALIZER ((struct recirc_refs) \
219                                        { 0, { { 0, 0 } } })
220 /* Helpers to abstract the recirculation union away. */
221 static inline void
222 recirc_refs_init(struct recirc_refs *rr)
223 {
224     *rr = RECIRC_REFS_EMPTY_INITIALIZER;
225 }
226
227 static inline void
228 recirc_refs_add(struct recirc_refs *rr, uint32_t id)
229 {
230     if (OVS_LIKELY(rr->n_recircs < ARRAY_SIZE(rr->recirc))) {
231         rr->recirc[rr->n_recircs++] = id;
232     } else {
233         if (rr->n_recircs == ARRAY_SIZE(rr->recirc)) {
234             uint32_t *recircs = xmalloc(sizeof rr->recirc + sizeof id);
235
236             memcpy(recircs, rr->recirc, sizeof rr->recirc);
237             rr->recircs = recircs;
238         } else {
239             rr->recircs = xrealloc(rr->recircs,
240                                    (rr->n_recircs + 1) * sizeof id);
241         }
242         rr->recircs[rr->n_recircs++] = id;
243     }
244 }
245
246 static inline void
247 recirc_refs_swap(struct recirc_refs *a, struct recirc_refs *b)
248 {
249     struct recirc_refs tmp;
250
251     tmp = *a;
252     *a = *b;
253     *b = tmp;
254 }
255
256 static inline void
257 recirc_refs_unref(struct recirc_refs *rr)
258 {
259     if (OVS_LIKELY(rr->n_recircs <= ARRAY_SIZE(rr->recirc))) {
260         for (int i = 0; i < rr->n_recircs; i++) {
261             recirc_free_id(rr->recirc[i]);
262         }
263     } else {
264         for (int i = 0; i < rr->n_recircs; i++) {
265             recirc_free_id(rr->recircs[i]);
266         }
267         free(rr->recircs);
268     }
269     rr->n_recircs = 0;
270 }
271
272 #endif