2 * Copyright (c) 2014, 2015, 2016 Nicira, Inc.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #ifndef OFPROTO_DPIF_RID_H
18 #define OFPROTO_DPIF_RID_H
25 #include "ofp-actions.h"
26 #include "ofproto-dpif-mirror.h"
27 #include "ovs-thread.h"
37 * Recirculation is a technique to allow a frame to re-enter the datapath
38 * packet processing path to achieve more flexible packet processing, such as
39 * modifying header fields after MPLS POP action and selecting a slave port for
42 * Data path and user space interface
43 * -----------------------------------
45 * Recirculation uses two uint32_t fields, recirc_id and dp_hash, and a RECIRC
46 * action. recirc_id is used to select the next packet processing steps among
47 * multiple instances of recirculation. When a packet initially enters the
48 * datapath it is assigned with recirc_id 0, which indicates no recirculation.
49 * Recirc_ids are managed by the user space, opaque to the datapath.
51 * On the other hand, dp_hash can only be computed by the datapath, opaque to
52 * the user space, as the datapath is free to choose the hashing algorithm
53 * without informing user space about it. The dp_hash value should be
54 * wildcarded for newly received packets. HASH action specifies whether the
55 * hash is computed, and if computed, how many fields are to be included in the
56 * hash computation. The computed hash value is stored into the dp_hash field
57 * prior to recirculation.
59 * The RECIRC action sets the recirc_id field and then reprocesses the packet
60 * as if it was received again on the same input port. RECIRC action works
61 * like a function call; actions listed after the RECIRC action will be
62 * executed after recirculation. RECIRC action can be nested, but datapath
63 * implementation limits the number of nested recirculations to prevent
64 * unreasonable nesting depth or infinite loop.
66 * User space recirculation context
67 * ---------------------------------
69 * Recirculation is usually hidden from the OpenFlow controllers. Action
70 * translation code deduces when recirculation is necessary and issues a
71 * datapath recirculation action. All OpenFlow actions to be performed after
72 * recirculation are derived from the OpenFlow pipeline and are stored with the
73 * recirculation ID. When the OpenFlow tables are changed in a way affecting
74 * the recirculation flows, new recirculation ID with new metadata and actions
75 * is allocated and the old one is timed out.
77 * Recirculation ID pool
78 * ----------------------
80 * Recirculation ID needs to be unique for all datapaths. Recirculation ID
81 * pool keeps track of recirculation ids and stores OpenFlow pipeline
82 * translation context so that flow processing may continue after
85 * A Recirculation ID can be any uint32_t value, except for that the value 0 is
86 * reserved for 'no recirculation' case.
91 * All APIs are thread safe.
94 /* Metadata for restoring pipeline context after recirculation. Helpers
95 * are inlined below to keep them together with the definition for easier
97 BUILD_ASSERT_DECL(FLOW_WC_SEQ == 35);
99 struct recirc_metadata {
100 /* Metadata in struct flow. */
101 const struct flow_tnl *tunnel; /* Encapsulating tunnel parameters. */
102 ovs_be64 metadata; /* OpenFlow Metadata. */
103 uint64_t regs[FLOW_N_XREGS]; /* Registers. */
104 ofp_port_t in_port; /* Incoming port. */
108 recirc_metadata_from_flow(struct recirc_metadata *md,
109 const struct flow *flow)
111 memset(md, 0, sizeof *md);
112 md->tunnel = &flow->tunnel;
113 md->metadata = flow->metadata;
114 memcpy(md->regs, flow->regs, sizeof md->regs);
115 md->in_port = flow->in_port.ofp_port;
119 recirc_metadata_to_flow(const struct recirc_metadata *md,
122 if (md->tunnel && flow_tnl_dst_is_set(md->tunnel)) {
123 flow->tunnel = *md->tunnel;
125 memset(&flow->tunnel, 0, sizeof flow->tunnel);
127 flow->metadata = md->metadata;
128 memcpy(flow->regs, md->regs, sizeof flow->regs);
129 flow->in_port.ofp_port = md->in_port;
132 /* State that flow translation can save, to restore when recirculation
134 struct recirc_state {
135 /* Initial table for post-recirculation processing. */
138 /* Pipeline context for post-recirculation processing. */
139 struct uuid ofproto_uuid; /* Post-recirculation bridge. */
140 struct recirc_metadata metadata; /* Flow metadata. */
141 union mf_subvalue *stack; /* Stack if any. */
143 mirror_mask_t mirrors; /* Mirrors already output. */
144 bool conntracked; /* Conntrack occurred prior to recirc. */
146 /* Actions to be translated on recirculation. */
147 struct ofpact *ofpacts;
148 size_t ofpacts_len; /* Size of 'ofpacts', in bytes. */
149 struct ofpact *action_set;
150 size_t action_set_len; /* Size of 'action_set', in bytes. */
153 /* This maps a recirculation ID to saved state that flow translation can
154 * restore when recirculation occurs. */
155 struct recirc_id_node {
157 struct ovs_list exp_node OVS_GUARDED;
158 struct cmap_node id_node;
159 struct cmap_node metadata_node;
162 struct ovs_refcount refcount;
166 * This state should not be modified after inserting a node in the pool,
167 * hence the 'const' to emphasize that. */
168 const struct recirc_state state;
170 /* Storage for tunnel metadata. */
171 struct flow_tnl state_metadata_tunnel;
174 void recirc_init(void);
176 /* This is only used for bonds and will go away when bonds implementation is
177 * updated to use this mechanism instead of internal rules. */
178 uint32_t recirc_alloc_id(struct ofproto_dpif *);
180 uint32_t recirc_alloc_id_ctx(const struct recirc_state *);
181 uint32_t recirc_find_id(const struct recirc_state *);
182 void recirc_free_id(uint32_t recirc_id);
183 void recirc_free_ofproto(struct ofproto_dpif *, const char *ofproto_name);
185 const struct recirc_id_node *recirc_id_node_find(uint32_t recirc_id);
187 static inline struct recirc_id_node *
188 recirc_id_node_from_state(const struct recirc_state *state)
190 return CONTAINER_OF(state, struct recirc_id_node, state);
193 static inline bool recirc_id_node_try_ref_rcu(const struct recirc_id_node *n_)
195 struct recirc_id_node *node = CONST_CAST(struct recirc_id_node *, n_);
197 return node ? ovs_refcount_try_ref_rcu(&node->refcount) : false;
200 void recirc_id_node_unref(const struct recirc_id_node *);
202 void recirc_run(void);
204 /* Recirculation IDs on which references are held. */
208 uint32_t recirc[2]; /* When n_recircs == 1 or 2 */
209 uint32_t *recircs; /* When 'n_recircs' > 2 */
213 #define RECIRC_REFS_EMPTY_INITIALIZER ((struct recirc_refs) \
215 /* Helpers to abstract the recirculation union away. */
217 recirc_refs_init(struct recirc_refs *rr)
219 *rr = RECIRC_REFS_EMPTY_INITIALIZER;
223 recirc_refs_add(struct recirc_refs *rr, uint32_t id)
225 if (OVS_LIKELY(rr->n_recircs < ARRAY_SIZE(rr->recirc))) {
226 rr->recirc[rr->n_recircs++] = id;
228 if (rr->n_recircs == ARRAY_SIZE(rr->recirc)) {
229 uint32_t *recircs = xmalloc(sizeof rr->recirc + sizeof id);
231 memcpy(recircs, rr->recirc, sizeof rr->recirc);
232 rr->recircs = recircs;
234 rr->recircs = xrealloc(rr->recircs,
235 (rr->n_recircs + 1) * sizeof id);
237 rr->recircs[rr->n_recircs++] = id;
242 recirc_refs_swap(struct recirc_refs *a, struct recirc_refs *b)
244 struct recirc_refs tmp;
252 recirc_refs_unref(struct recirc_refs *rr)
254 if (OVS_LIKELY(rr->n_recircs <= ARRAY_SIZE(rr->recirc))) {
255 for (int i = 0; i < rr->n_recircs; i++) {
256 recirc_free_id(rr->recirc[i]);
259 for (int i = 0; i < rr->n_recircs; i++) {
260 recirc_free_id(rr->recircs[i]);