Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 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 OVN_ACTIONS_H
18 : : #define OVN_ACTIONS_H 1
19 : :
20 : : #include <stdbool.h>
21 : : #include <stdint.h>
22 : : #include "compiler.h"
23 : : #include "expr.h"
24 : : #include "openvswitch/dynamic-string.h"
25 : : #include "openvswitch/hmap.h"
26 : : #include "openvswitch/uuid.h"
27 : : #include "util.h"
28 : :
29 : : struct lexer;
30 : : struct ofpbuf;
31 : : struct shash;
32 : : struct simap;
33 : :
34 : : /* List of OVN logical actions.
35 : : *
36 : : * This macro is used directly only internally by this header and its
37 : : * corresponding .c file, but the list is still of interest to developers.
38 : : *
39 : : * Each OVNACT invocation has the following parameters:
40 : : *
41 : : * 1. <ENUM>, used below in the enum definition of OVNACT_<ENUM>, and
42 : : * elsewhere.
43 : : *
44 : : * 2. <STRUCT> corresponding to a structure "struct <STRUCT>", that must be a
45 : : * defined below. This structure must be an abstract definition of the
46 : : * action. Its first member must have type "struct ovnact" and name
47 : : * "ovnact". The structure must have a fixed length, that is, it may not
48 : : * end with a flexible array member.
49 : : */
50 : : #define OVNACTS \
51 : : OVNACT(OUTPUT, ovnact_null) \
52 : : OVNACT(NEXT, ovnact_next) \
53 : : OVNACT(LOAD, ovnact_load) \
54 : : OVNACT(MOVE, ovnact_move) \
55 : : OVNACT(EXCHANGE, ovnact_move) \
56 : : OVNACT(DEC_TTL, ovnact_null) \
57 : : OVNACT(CT_NEXT, ovnact_next) \
58 : : OVNACT(CT_COMMIT, ovnact_ct_commit) \
59 : : OVNACT(CT_DNAT, ovnact_ct_nat) \
60 : : OVNACT(CT_SNAT, ovnact_ct_nat) \
61 : : OVNACT(CT_LB, ovnact_ct_lb) \
62 : : OVNACT(ARP, ovnact_nest) \
63 : : OVNACT(ND_NA, ovnact_nest) \
64 : : OVNACT(GET_ARP, ovnact_get_mac_bind) \
65 : : OVNACT(PUT_ARP, ovnact_put_mac_bind) \
66 : : OVNACT(GET_ND, ovnact_get_mac_bind) \
67 : : OVNACT(PUT_ND, ovnact_put_mac_bind) \
68 : : OVNACT(PUT_DHCPV4_OPTS, ovnact_put_dhcp_opts) \
69 : : OVNACT(PUT_DHCPV6_OPTS, ovnact_put_dhcp_opts)
70 : :
71 : : /* enum ovnact_type, with a member OVNACT_<ENUM> for each action. */
72 : : enum OVS_PACKED_ENUM ovnact_type {
73 : : #define OVNACT(ENUM, STRUCT) OVNACT_##ENUM,
74 : : OVNACTS
75 : : #undef OVNACT
76 : : };
77 : :
78 : : /* Define N_OVNACTS to the number of types of ovnacts. */
79 : : enum {
80 : : #define OVNACT(ENUM, STRUCT) + 1
81 : : N_OVNACTS = OVNACTS
82 : : #undef OVNACT
83 : : };
84 : :
85 : : /* Header for an action.
86 : : *
87 : : * Each action is a structure "struct ovnact_*" that begins with "struct
88 : : * ovnact", usually followed by other data that describes the action. Actions
89 : : * are padded out to a multiple of OVNACT_ALIGNTO bytes in length.
90 : : */
91 : : struct ovnact {
92 : : /* We want the space advantage of an 8-bit type here on every
93 : : * implementation, without giving up the advantage of having a useful type
94 : : * on implementations that support packed enums. */
95 : : #ifdef HAVE_PACKED_ENUM
96 : : enum ovnact_type type; /* OVNACT_*. */
97 : : #else
98 : : uint8_t type; /* OVNACT_* */
99 : : #endif
100 : : uint8_t pad; /* Pad to multiple of 16 bits. */
101 : :
102 : : uint16_t len; /* Length of the action, in bytes, including
103 : : * struct ovnact, excluding padding. */
104 : : };
105 : : BUILD_ASSERT_DECL(sizeof(struct ovnact) == 4);
106 : :
107 : : /* Alignment. */
108 : : #define OVNACT_ALIGNTO 8
109 : : #define OVNACT_ALIGN(SIZE) ROUND_UP(SIZE, OVNACT_ALIGNTO)
110 : :
111 : : /* Returns the ovnact following 'ovnact'. */
112 : : static inline struct ovnact *
113 : 2969989 : ovnact_next(const struct ovnact *ovnact)
114 : : {
115 : 2969989 : return (void *) ((uint8_t *) ovnact + OVNACT_ALIGN(ovnact->len));
116 : : }
117 : :
118 : : struct ovnact *ovnact_next_flattened(const struct ovnact *);
119 : :
120 : : static inline struct ovnact *
121 : 4264041 : ovnact_end(const struct ovnact *ovnacts, size_t ovnacts_len)
122 : : {
123 : 4264041 : return (void *) ((uint8_t *) ovnacts + ovnacts_len);
124 : : }
125 : :
126 : : /* Assigns POS to each ovnact, in turn, in the OVNACTS_LEN bytes of ovnacts
127 : : * starting at OVNACTS. */
128 : : #define OVNACT_FOR_EACH(POS, OVNACTS, OVNACTS_LEN) \
129 : : for ((POS) = (OVNACTS); (POS) < ovnact_end(OVNACTS, OVNACTS_LEN); \
130 : : (POS) = ovnact_next(POS))
131 : :
132 : : /* Action structure for each OVNACT_*. */
133 : :
134 : : /* Action structure for actions that do not have any extra data beyond the
135 : : * action type. */
136 : : struct ovnact_null {
137 : : struct ovnact ovnact;
138 : : };
139 : :
140 : : /* OVNACT_NEXT, OVNACT_CT_NEXT. */
141 : : struct ovnact_next {
142 : : struct ovnact ovnact;
143 : : uint8_t ltable; /* Logical table ID of next table. */
144 : : };
145 : :
146 : : /* OVNACT_LOAD. */
147 : : struct ovnact_load {
148 : : struct ovnact ovnact;
149 : : struct expr_field dst;
150 : : union expr_constant imm;
151 : : };
152 : :
153 : : /* OVNACT_MOVE, OVNACT_EXCHANGE. */
154 : : struct ovnact_move {
155 : : struct ovnact ovnact;
156 : : struct expr_field lhs;
157 : : struct expr_field rhs;
158 : : };
159 : :
160 : : /* OVNACT_CT_COMMIT. */
161 : : struct ovnact_ct_commit {
162 : : struct ovnact ovnact;
163 : : uint32_t ct_mark, ct_mark_mask;
164 : : ovs_be128 ct_label, ct_label_mask;
165 : : };
166 : :
167 : : /* OVNACT_CT_DNAT, OVNACT_CT_SNAT. */
168 : : struct ovnact_ct_nat {
169 : : struct ovnact ovnact;
170 : : ovs_be32 ip;
171 : : uint8_t ltable; /* Logical table ID of next table. */
172 : : };
173 : :
174 : : struct ovnact_ct_lb_dst {
175 : : ovs_be32 ip;
176 : : uint16_t port;
177 : : };
178 : :
179 : : /* OVNACT_CT_LB. */
180 : : struct ovnact_ct_lb {
181 : : struct ovnact ovnact;
182 : : struct ovnact_ct_lb_dst *dsts;
183 : : size_t n_dsts;
184 : : uint8_t ltable; /* Logical table ID of next table. */
185 : : };
186 : :
187 : : /* OVNACT_ARP, OVNACT_ND_NA. */
188 : : struct ovnact_nest {
189 : : struct ovnact ovnact;
190 : : struct ovnact *nested;
191 : : size_t nested_len;
192 : : };
193 : :
194 : : /* OVNACT_GET_ARP, OVNACT_GET_ND. */
195 : : struct ovnact_get_mac_bind {
196 : : struct ovnact ovnact;
197 : : struct expr_field port; /* Logical port name. */
198 : : struct expr_field ip; /* 32-bit or 128-bit IP address. */
199 : : };
200 : :
201 : : /* OVNACT_PUT_ARP, ONVACT_PUT_ND. */
202 : : struct ovnact_put_mac_bind {
203 : : struct ovnact ovnact;
204 : : struct expr_field port; /* Logical port name. */
205 : : struct expr_field ip; /* 32-bit or 128-bit IP address. */
206 : : struct expr_field mac; /* 48-bit Ethernet address. */
207 : : };
208 : :
209 : : struct ovnact_dhcp_option {
210 : : const struct dhcp_opts_map *option;
211 : : struct expr_constant_set value;
212 : : };
213 : :
214 : : /* OVNACT_PUT_DHCPV4_OPTS, OVNACT_PUT_DHCPV6_OPTS. */
215 : : struct ovnact_put_dhcp_opts {
216 : : struct ovnact ovnact;
217 : : struct expr_field dst; /* 1-bit destination field. */
218 : : struct ovnact_dhcp_option *options;
219 : : size_t n_options;
220 : : };
221 : :
222 : : /* Internal use by the helpers below. */
223 : : void ovnact_init(struct ovnact *, enum ovnact_type, size_t len);
224 : : void *ovnact_put(struct ofpbuf *, enum ovnact_type, size_t len);
225 : :
226 : : /* For each OVNACT_<ENUM> with a corresponding struct <STRUCT>, this defines
227 : : * the following commonly useful functions:
228 : : *
229 : : * struct <STRUCT> *ovnact_put_<ENUM>(struct ofpbuf *ovnacts);
230 : : *
231 : : * Appends a new 'ovnact', of length OVNACT_<ENUM>_SIZE, to 'ovnacts',
232 : : * initializes it with ovnact_init_<ENUM>(), and returns it. Also sets
233 : : * 'ovnacts->header' to the returned action.
234 : : *
235 : : * struct <STRUCT> *ovnact_get_<ENUM>(const struct ovnact *ovnact);
236 : : *
237 : : * Returns 'ovnact' cast to "struct <STRUCT> *". 'ovnact->type' must be
238 : : * OVNACT_<ENUM>.
239 : : *
240 : : * as well as the following more rarely useful definitions:
241 : : *
242 : : * void ovnact_init_<ENUM>(struct <STRUCT> *ovnact);
243 : : *
244 : : * Initializes the parts of 'ovnact' that identify it as having type
245 : : * OVNACT_<ENUM> and length OVNACT_<ENUM>_SIZE and zeros the rest.
246 : : *
247 : : * <ENUM>_SIZE
248 : : *
249 : : * The size of the action structure, that is, sizeof(struct <STRUCT>)
250 : : * rounded up to a multiple of OVNACT_ALIGNTO.
251 : : */
252 : : #define OVNACT(ENUM, STRUCT) \
253 : : BUILD_ASSERT_DECL(offsetof(struct STRUCT, ovnact) == 0); \
254 : : \
255 : : enum { OVNACT_##ENUM##_SIZE = OVNACT_ALIGN(sizeof(struct STRUCT)) }; \
256 : : \
257 : : static inline struct STRUCT * \
258 : : ovnact_get_##ENUM(const struct ovnact *ovnact) \
259 : : { \
260 : : ovs_assert(ovnact->type == OVNACT_##ENUM); \
261 : : return ALIGNED_CAST(struct STRUCT *, ovnact); \
262 : : } \
263 : : \
264 : : static inline struct STRUCT * \
265 : : ovnact_put_##ENUM(struct ofpbuf *ovnacts) \
266 : : { \
267 : : return ovnact_put(ovnacts, OVNACT_##ENUM, \
268 : : OVNACT_##ENUM##_SIZE); \
269 : : } \
270 : : \
271 : : static inline void \
272 : : ovnact_init_##ENUM(struct STRUCT *ovnact) \
273 : : { \
274 : : ovnact_init(&ovnact->ovnact, OVNACT_##ENUM, \
275 : : OVNACT_##ENUM##_SIZE); \
276 : : }
277 [ # # ][ # # ]: 2938246 : OVNACTS
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
278 : : #undef OVNACT
279 : :
280 : : #define MAX_OVN_GROUPS 65535
281 : :
282 : : struct group_table {
283 : : unsigned long *group_ids; /* Used as a bitmap with value set
284 : : * for allocated group ids in either
285 : : * desired_groups or existing_groups. */
286 : : struct hmap desired_groups;
287 : : struct hmap existing_groups;
288 : : };
289 : :
290 : : struct group_info {
291 : : struct hmap_node hmap_node;
292 : : struct ds group;
293 : : uint32_t group_id;
294 : : bool new_group_id; /* 'True' if 'group_id' was reserved from
295 : : * group_table's 'group_ids' bitmap. */
296 : : };
297 : :
298 : : enum action_opcode {
299 : : /* "arp { ...actions... }".
300 : : *
301 : : * The actions, in OpenFlow 1.3 format, follow the action_header.
302 : : */
303 : : ACTION_OPCODE_ARP,
304 : :
305 : : /* "put_arp(port, ip, mac)"
306 : : *
307 : : * Arguments are passed through the packet metadata and data, as follows:
308 : : *
309 : : * MFF_REG0 = ip
310 : : * MFF_LOG_INPORT = port
311 : : * MFF_ETH_SRC = mac
312 : : */
313 : : ACTION_OPCODE_PUT_ARP,
314 : :
315 : : /* "result = put_dhcp_opts(offer_ip, option, ...)".
316 : : *
317 : : * Arguments follow the action_header, in this format:
318 : : * - A 32-bit or 64-bit OXM header designating the result field.
319 : : * - A 32-bit integer specifying a bit offset within the result field.
320 : : * - The 32-bit DHCP offer IP.
321 : : * - Any number of DHCP options.
322 : : */
323 : : ACTION_OPCODE_PUT_DHCP_OPTS,
324 : :
325 : : /* "nd_na { ...actions... }".
326 : : *
327 : : * The actions, in OpenFlow 1.3 format, follow the action_header.
328 : : */
329 : : ACTION_OPCODE_ND_NA,
330 : :
331 : : /* "put_nd(port, ip6, mac)"
332 : : *
333 : : * Arguments are passed through the packet metadata and data, as follows:
334 : : *
335 : : * MFF_XXREG0 = ip6
336 : : * MFF_LOG_INPORT = port
337 : : * MFF_ETH_SRC = mac
338 : : */
339 : : ACTION_OPCODE_PUT_ND,
340 : :
341 : : /* "result = put_dhcpv6_opts(option, ...)".
342 : : *
343 : : * Arguments follow the action_header, in this format:
344 : : * - A 32-bit or 64-bit OXM header designating the result field.
345 : : * - A 32-bit integer specifying a bit offset within the result field.
346 : : * - Any number of DHCPv6 options.
347 : : */
348 : : ACTION_OPCODE_PUT_DHCPV6_OPTS,
349 : : };
350 : :
351 : : /* Header. */
352 : : struct action_header {
353 : : ovs_be32 opcode; /* One of ACTION_OPCODE_* */
354 : : uint8_t pad[4];
355 : : };
356 : : BUILD_ASSERT_DECL(sizeof(struct action_header) == 8);
357 : :
358 : : struct ovnact_parse_params {
359 : : /* A table of "struct expr_symbol"s to support (as one would provide to
360 : : * expr_parse()). */
361 : : const struct shash *symtab;
362 : :
363 : : /* hmap of 'struct dhcp_opts_map' to support 'put_dhcp_opts' action */
364 : : const struct hmap *dhcp_opts;
365 : :
366 : : /* hmap of 'struct dhcp_opts_map' to support 'put_dhcpv6_opts' action */
367 : : const struct hmap *dhcpv6_opts;
368 : :
369 : : /* OVN maps each logical flow table (ltable), one-to-one, onto a physical
370 : : * OpenFlow flow table (ptable). A number of parameters describe this
371 : : * mapping and data related to flow tables:
372 : : *
373 : : * - 'first_ptable' and 'n_tables' define the range of OpenFlow tables
374 : : * to which the logical "next" action should be able to jump.
375 : : * Logical table 0 maps to OpenFlow table 'first_ptable', logical
376 : : * table 1 to 'first_ptable + 1', and so on. If 'n_tables' is 0
377 : : * then "next" is disallowed entirely.
378 : : *
379 : : * - 'cur_ltable' is an offset from 'first_ptable' (e.g. 0 <=
380 : : * cur_ltable < n_tables) of the logical flow that contains the
381 : : * actions. If cur_ltable + 1 < n_tables, then this defines the
382 : : * default table that "next" will jump to. */
383 : : uint8_t n_tables; /* Number of flow tables. */
384 : : uint8_t cur_ltable; /* 0 <= cur_ltable < n_tables. */
385 : : };
386 : :
387 : : bool ovnacts_parse(struct lexer *, const struct ovnact_parse_params *,
388 : : struct ofpbuf *ovnacts, struct expr **prereqsp);
389 : : char *ovnacts_parse_string(const char *s, const struct ovnact_parse_params *,
390 : : struct ofpbuf *ovnacts, struct expr **prereqsp)
391 : : OVS_WARN_UNUSED_RESULT;
392 : :
393 : : void ovnacts_format(const struct ovnact[], size_t ovnacts_len, struct ds *);
394 : :
395 : : struct ovnact_encode_params {
396 : : /* Looks up logical port 'port_name'. If found, stores its port number in
397 : : * '*portp' and returns true; otherwise, returns false. */
398 : : bool (*lookup_port)(const void *aux, const char *port_name,
399 : : unsigned int *portp);
400 : : const void *aux;
401 : :
402 : : /* 'true' if the flow is for a switch. */
403 : : bool is_switch;
404 : :
405 : : /* A map from a port name to its connection tracking zone. */
406 : : const struct simap *ct_zones;
407 : :
408 : : /* A struct to figure out the group_id for group actions. */
409 : : struct group_table *group_table;
410 : :
411 : : /* OVN maps each logical flow table (ltable), one-to-one, onto a physical
412 : : * OpenFlow flow table (ptable). A number of parameters describe this
413 : : * mapping and data related to flow tables:
414 : : *
415 : : * - 'first_ptable' and 'n_tables' define the range of OpenFlow tables
416 : : * to which the logical "next" action should be able to jump.
417 : : * Logical table 0 maps to OpenFlow table 'first_ptable', logical
418 : : * table 1 to 'first_ptable + 1', and so on. If 'n_tables' is 0
419 : : * then "next" is disallowed entirely.
420 : : *
421 : : * - 'cur_ltable' is an offset from 'first_ptable' (e.g. 0 <=
422 : : * cur_ltable < n_ptables) of the logical flow that contains the
423 : : * actions. If cur_ltable + 1 < n_tables, then this defines the
424 : : * default table that "next" will jump to.
425 : : *
426 : : * - 'output_ptable' should be the OpenFlow table to which the logical
427 : : * "output" action will resubmit. */
428 : : uint8_t first_ptable; /* First OpenFlow table. */
429 : : uint8_t output_ptable; /* OpenFlow table for 'output' to resubmit. */
430 : : uint8_t mac_bind_ptable; /* OpenFlow table for 'get_arp'/'get_nd' to
431 : : resubmit. */
432 : : };
433 : :
434 : : void ovnacts_encode(const struct ovnact[], size_t ovnacts_len,
435 : : const struct ovnact_encode_params *,
436 : : struct ofpbuf *ofpacts);
437 : :
438 : : void ovnacts_free(struct ovnact[], size_t ovnacts_len);
439 : :
440 : : #endif /* ovn/actions.h */
|