2 * Copyright (c) 2014, 2015 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 "ovs-thread.h"
35 * Recirculation is a technique to allow a frame to re-enter the datapath
36 * packet processing path for one or multiple times to achieve more flexible
37 * packet processing, such modifying header fields after MPLS POP action and
38 * selecting bond a slave port for bond ports.
40 * Data path and user space interface
41 * -----------------------------------
43 * Recirculation uses two uint32_t fields, recirc_id and dp_hash, and a RECIRC
44 * action. The value recirc_id is used to select the next packet processing
45 * steps among multiple instances of recirculation. When a packet initially
46 * enters the data path it is assigned with recirc_id 0, which indicates no
47 * recirculation. Recirc_ids are managed by the user space, opaque to the
50 * On the other hand, dp_hash can only be computed by the data path, opaque to
51 * the user space. In fact, user space may not able to recompute the hash
52 * value. The dp_hash value should be wildcarded for a newly received
53 * packet. HASH action specifies whether the hash is computed, and if
54 * computed, how many fields are to be included in the hash computation. The
55 * computed hash value is stored into the dp_hash field prior to recirculation.
57 * The RECIRC action sets the recirc_id field and then reprocesses the packet
58 * as if it was received on the same input port. RECIRC action works like a
59 * function call; actions listed behind the RECIRC action will be executed
60 * after its execution. RECIRC action can be nested, data path implementation
61 * limits the number of recirculation executed to prevent unreasonable nesting
62 * depth or infinite loop.
64 * User space recirculation context
65 * ---------------------------------
67 * Recirculation is hidden from the OpenFlow controllers. Action translation
68 * code deduces when recirculation is necessary and issues a data path
69 * recirculation action. All OpenFlow actions to be performed after
70 * recirculation are derived from the OpenFlow pipeline and are stored with the
71 * recirculation ID. When the OpenFlow tables are changed in a way affecting
72 * the recirculation flows, new recirculation ID with new metadata and actions
73 * is allocated and the old one is timed out.
75 * Recirculation ID pool
76 * ----------------------
78 * Recirculation ID needs to be unique for all data paths. Recirculation ID
79 * pool keeps track recirculation ids and stores OpenFlow pipeline translation
80 * context so that flow processing may continue after recirculation.
82 * A Recirculation ID can be any uint32_t value, except for that the value 0 is
83 * reserved for 'no recirculation' case.
88 * All APIs are thread safe.
91 /* Metadata for restoring pipeline context after recirculation. Helpers
92 * are inlined below to keep them together with the definition for easier
94 BUILD_ASSERT_DECL(FLOW_WC_SEQ
== 33);
96 struct recirc_metadata
{
97 /* Metadata in struct flow. */
98 struct flow_tnl tunnel
; /* Encapsulating tunnel parameters. */
99 ovs_be64 metadata
; /* OpenFlow Metadata. */
100 uint64_t regs
[FLOW_N_XREGS
]; /* Registers. */
101 ofp_port_t in_port
; /* Incoming port. */
102 ofp_port_t actset_output
; /* Output port in action set. */
106 recirc_metadata_from_flow(struct recirc_metadata
*md
,
107 const struct flow
*flow
)
109 memset(md
, 0, sizeof *md
);
110 md
->tunnel
= flow
->tunnel
;
111 md
->metadata
= flow
->metadata
;
112 memcpy(md
->regs
, flow
->regs
, sizeof md
->regs
);
113 md
->in_port
= flow
->in_port
.ofp_port
;
114 md
->actset_output
= flow
->actset_output
;
118 recirc_metadata_to_flow(const struct recirc_metadata
*md
,
121 flow
->tunnel
= md
->tunnel
;
122 flow
->metadata
= md
->metadata
;
123 memcpy(flow
->regs
, md
->regs
, sizeof flow
->regs
);
124 flow
->in_port
.ofp_port
= md
->in_port
;
125 flow
->actset_output
= md
->actset_output
;
128 /* Pool node fields should NOT be modified after placing the node in the pool.
130 struct recirc_id_node
{
131 struct ovs_list exp_node OVS_GUARDED
;
132 struct cmap_node id_node
;
133 struct cmap_node metadata_node
;
136 struct ovs_refcount refcount
;
138 /* Initial table for post-recirculation processing. */
141 /* Pipeline context for post-recirculation processing. */
142 struct ofproto_dpif
*ofproto
; /* Post-recirculation bridge. */
143 struct recirc_metadata metadata
; /* Flow metadata. */
144 struct ofpbuf
*stack
; /* Stack if any. */
146 /* Actions to be translated on recirculation. */
147 uint32_t action_set_len
; /* How much of 'ofpacts' consists of an
149 uint32_t ofpacts_len
; /* Size of 'ofpacts', in bytes. */
150 struct ofpact ofpacts
[]; /* Sequence of "struct ofpacts". */
153 void recirc_init(void);
155 /* This is only used for bonds and will go away when bonds implementation is
156 * updated to use this mechanism instead of internal rules. */
157 uint32_t recirc_alloc_id(struct ofproto_dpif
*);
159 uint32_t recirc_alloc_id_ctx(struct ofproto_dpif
*, uint8_t table_id
,
160 struct recirc_metadata
*, struct ofpbuf
*stack
,
161 uint32_t action_set_len
, uint32_t ofpacts_len
,
162 const struct ofpact
*);
163 uint32_t recirc_find_id(struct ofproto_dpif
*, uint8_t table_id
,
164 struct recirc_metadata
*, struct ofpbuf
*stack
,
165 uint32_t action_set_len
, uint32_t ofpacts_len
,
166 const struct ofpact
*);
167 void recirc_free_id(uint32_t recirc_id
);
168 void recirc_free_ofproto(struct ofproto_dpif
*, const char *ofproto_name
);
170 const struct recirc_id_node
*recirc_id_node_find(uint32_t recirc_id
);
172 static inline bool recirc_id_node_try_ref_rcu(const struct recirc_id_node
*n_
)
174 struct recirc_id_node
*node
= CONST_CAST(struct recirc_id_node
*, n_
);
176 return node
? ovs_refcount_try_ref_rcu(&node
->refcount
) : false;
179 void recirc_id_node_unref(const struct recirc_id_node
*);
181 void recirc_run(void);