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