X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=lib%2Fofp-actions.h;h=24143d324323eeb86e3c8967d90f5c8ebd562037;hb=HEAD;hp=89bf8678ef66aa13cd6d6f90f42729cbb76fcfca;hpb=c0621c394f09882b7d210102d0389c60b353d630;p=cascardo%2Fovs.git diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h index 89bf8678e..24143d324 100644 --- a/lib/ofp-actions.h +++ b/lib/ofp-actions.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, 2014 Nicira, Inc. + * Copyright (c) 2012, 2013, 2014, 2015, 2016 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,7 +31,7 @@ * This macro is used directly only internally by this header, but the list is * still of interest to developers. * - * Each DEFINE_OFPACT invocation has the following parameters: + * Each OFPACT invocation has the following parameters: * * 1. , used below in the enum definition of OFPACT_, and * elsewhere. @@ -48,81 +48,92 @@ * * - If "struct " is variable-length, it must be the name of the * flexible array member. + * + * 4. , a quoted string that gives the name of the action, for use in + * parsing actions from text. */ -#define OFPACTS \ - /* Output. */ \ - DEFINE_OFPACT(OUTPUT, ofpact_output, ofpact) \ - DEFINE_OFPACT(GROUP, ofpact_group, ofpact) \ - DEFINE_OFPACT(CONTROLLER, ofpact_controller, ofpact) \ - DEFINE_OFPACT(ENQUEUE, ofpact_enqueue, ofpact) \ - DEFINE_OFPACT(OUTPUT_REG, ofpact_output_reg, ofpact) \ - DEFINE_OFPACT(BUNDLE, ofpact_bundle, slaves) \ - \ - /* Header changes. */ \ - DEFINE_OFPACT(SET_FIELD, ofpact_set_field, ofpact) \ - DEFINE_OFPACT(SET_VLAN_VID, ofpact_vlan_vid, ofpact) \ - DEFINE_OFPACT(SET_VLAN_PCP, ofpact_vlan_pcp, ofpact) \ - DEFINE_OFPACT(STRIP_VLAN, ofpact_null, ofpact) \ - DEFINE_OFPACT(PUSH_VLAN, ofpact_null, ofpact) \ - DEFINE_OFPACT(SET_ETH_SRC, ofpact_mac, ofpact) \ - DEFINE_OFPACT(SET_ETH_DST, ofpact_mac, ofpact) \ - DEFINE_OFPACT(SET_IPV4_SRC, ofpact_ipv4, ofpact) \ - DEFINE_OFPACT(SET_IPV4_DST, ofpact_ipv4, ofpact) \ - DEFINE_OFPACT(SET_IP_DSCP, ofpact_dscp, ofpact) \ - DEFINE_OFPACT(SET_IP_ECN, ofpact_ecn, ofpact) \ - DEFINE_OFPACT(SET_IP_TTL, ofpact_ip_ttl, ofpact) \ - DEFINE_OFPACT(SET_L4_SRC_PORT, ofpact_l4_port, ofpact) \ - DEFINE_OFPACT(SET_L4_DST_PORT, ofpact_l4_port, ofpact) \ - DEFINE_OFPACT(REG_MOVE, ofpact_reg_move, ofpact) \ - DEFINE_OFPACT(REG_LOAD, ofpact_reg_load, ofpact) \ - DEFINE_OFPACT(STACK_PUSH, ofpact_stack, ofpact) \ - DEFINE_OFPACT(STACK_POP, ofpact_stack, ofpact) \ - DEFINE_OFPACT(DEC_TTL, ofpact_cnt_ids, cnt_ids) \ - DEFINE_OFPACT(SET_MPLS_LABEL, ofpact_mpls_label, ofpact) \ - DEFINE_OFPACT(SET_MPLS_TC, ofpact_mpls_tc, ofpact) \ - DEFINE_OFPACT(SET_MPLS_TTL, ofpact_mpls_ttl, ofpact) \ - DEFINE_OFPACT(DEC_MPLS_TTL, ofpact_null, ofpact) \ - DEFINE_OFPACT(PUSH_MPLS, ofpact_push_mpls, ofpact) \ - DEFINE_OFPACT(POP_MPLS, ofpact_pop_mpls, ofpact) \ - \ - /* Metadata. */ \ - DEFINE_OFPACT(SET_TUNNEL, ofpact_tunnel, ofpact) \ - DEFINE_OFPACT(SET_QUEUE, ofpact_queue, ofpact) \ - DEFINE_OFPACT(POP_QUEUE, ofpact_null, ofpact) \ - DEFINE_OFPACT(FIN_TIMEOUT, ofpact_fin_timeout, ofpact) \ - \ - /* Flow table interaction. */ \ - DEFINE_OFPACT(RESUBMIT, ofpact_resubmit, ofpact) \ - DEFINE_OFPACT(LEARN, ofpact_learn, specs) \ - \ - /* Arithmetic. */ \ - DEFINE_OFPACT(MULTIPATH, ofpact_multipath, ofpact) \ - \ - /* Other. */ \ - DEFINE_OFPACT(NOTE, ofpact_note, data) \ - DEFINE_OFPACT(EXIT, ofpact_null, ofpact) \ - DEFINE_OFPACT(SAMPLE, ofpact_sample, ofpact) \ - \ - /* Instructions */ \ - DEFINE_OFPACT(METER, ofpact_meter, ofpact) \ - DEFINE_OFPACT(CLEAR_ACTIONS, ofpact_null, ofpact) \ - DEFINE_OFPACT(WRITE_ACTIONS, ofpact_nest, ofpact) \ - DEFINE_OFPACT(WRITE_METADATA, ofpact_metadata, ofpact) \ - DEFINE_OFPACT(GOTO_TABLE, ofpact_goto_table, ofpact) +#define OFPACTS \ + /* Output. */ \ + OFPACT(OUTPUT, ofpact_output, ofpact, "output") \ + OFPACT(GROUP, ofpact_group, ofpact, "group") \ + OFPACT(CONTROLLER, ofpact_controller, userdata, "controller") \ + OFPACT(ENQUEUE, ofpact_enqueue, ofpact, "enqueue") \ + OFPACT(OUTPUT_REG, ofpact_output_reg, ofpact, "output_reg") \ + OFPACT(BUNDLE, ofpact_bundle, slaves, "bundle") \ + \ + /* Header changes. */ \ + OFPACT(SET_FIELD, ofpact_set_field, ofpact, "set_field") \ + OFPACT(SET_VLAN_VID, ofpact_vlan_vid, ofpact, "set_vlan_vid") \ + OFPACT(SET_VLAN_PCP, ofpact_vlan_pcp, ofpact, "set_vlan_pcp") \ + OFPACT(STRIP_VLAN, ofpact_null, ofpact, "strip_vlan") \ + OFPACT(PUSH_VLAN, ofpact_null, ofpact, "push_vlan") \ + OFPACT(SET_ETH_SRC, ofpact_mac, ofpact, "mod_dl_src") \ + OFPACT(SET_ETH_DST, ofpact_mac, ofpact, "mod_dl_dst") \ + OFPACT(SET_IPV4_SRC, ofpact_ipv4, ofpact, "mod_nw_src") \ + OFPACT(SET_IPV4_DST, ofpact_ipv4, ofpact, "mod_nw_dst") \ + OFPACT(SET_IP_DSCP, ofpact_dscp, ofpact, "mod_nw_tos") \ + OFPACT(SET_IP_ECN, ofpact_ecn, ofpact, "mod_nw_ecn") \ + OFPACT(SET_IP_TTL, ofpact_ip_ttl, ofpact, "mod_nw_ttl") \ + OFPACT(SET_L4_SRC_PORT, ofpact_l4_port, ofpact, "mod_tp_src") \ + OFPACT(SET_L4_DST_PORT, ofpact_l4_port, ofpact, "mod_tp_dst") \ + OFPACT(REG_MOVE, ofpact_reg_move, ofpact, "move") \ + OFPACT(STACK_PUSH, ofpact_stack, ofpact, "push") \ + OFPACT(STACK_POP, ofpact_stack, ofpact, "pop") \ + OFPACT(DEC_TTL, ofpact_cnt_ids, cnt_ids, "dec_ttl") \ + OFPACT(SET_MPLS_LABEL, ofpact_mpls_label, ofpact, "set_mpls_label") \ + OFPACT(SET_MPLS_TC, ofpact_mpls_tc, ofpact, "set_mpls_tc") \ + OFPACT(SET_MPLS_TTL, ofpact_mpls_ttl, ofpact, "set_mpls_ttl") \ + OFPACT(DEC_MPLS_TTL, ofpact_null, ofpact, "dec_mpls_ttl") \ + OFPACT(PUSH_MPLS, ofpact_push_mpls, ofpact, "push_mpls") \ + OFPACT(POP_MPLS, ofpact_pop_mpls, ofpact, "pop_mpls") \ + \ + /* Metadata. */ \ + OFPACT(SET_TUNNEL, ofpact_tunnel, ofpact, "set_tunnel") \ + OFPACT(SET_QUEUE, ofpact_queue, ofpact, "set_queue") \ + OFPACT(POP_QUEUE, ofpact_null, ofpact, "pop_queue") \ + OFPACT(FIN_TIMEOUT, ofpact_fin_timeout, ofpact, "fin_timeout") \ + \ + /* Flow table interaction. */ \ + OFPACT(RESUBMIT, ofpact_resubmit, ofpact, "resubmit") \ + OFPACT(LEARN, ofpact_learn, specs, "learn") \ + OFPACT(CONJUNCTION, ofpact_conjunction, ofpact, "conjunction") \ + \ + /* Arithmetic. */ \ + OFPACT(MULTIPATH, ofpact_multipath, ofpact, "multipath") \ + \ + /* Other. */ \ + OFPACT(NOTE, ofpact_note, data, "note") \ + OFPACT(EXIT, ofpact_null, ofpact, "exit") \ + OFPACT(SAMPLE, ofpact_sample, ofpact, "sample") \ + OFPACT(UNROLL_XLATE, ofpact_unroll_xlate, ofpact, "unroll_xlate") \ + OFPACT(CT, ofpact_conntrack, ofpact, "ct") \ + OFPACT(NAT, ofpact_nat, ofpact, "nat") \ + \ + /* Debugging actions. \ + * \ + * These are intentionally undocumented, subject to change, and \ + * only accepted if ovs-vswitchd is started with --enable-dummy. */ \ + OFPACT(DEBUG_RECIRC, ofpact_null, ofpact, "debug_recirc") \ + \ + /* Instructions. */ \ + OFPACT(METER, ofpact_meter, ofpact, "meter") \ + OFPACT(CLEAR_ACTIONS, ofpact_null, ofpact, "clear_actions") \ + OFPACT(WRITE_ACTIONS, ofpact_nest, ofpact, "write_actions") \ + OFPACT(WRITE_METADATA, ofpact_metadata, ofpact, "write_metadata") \ + OFPACT(GOTO_TABLE, ofpact_goto_table, ofpact, "goto_table") /* enum ofpact_type, with a member OFPACT_ for each action. */ enum OVS_PACKED_ENUM ofpact_type { -#define DEFINE_OFPACT(ENUM, STRUCT, MEMBER) OFPACT_##ENUM, +#define OFPACT(ENUM, STRUCT, MEMBER, NAME) OFPACT_##ENUM, OFPACTS -#undef DEFINE_OFPACT +#undef OFPACT }; -/* N_OFPACTS, the number of values of "enum ofpact_type". */ +/* Define N_OFPACTS to the number of types of ofpacts. */ enum { - N_OFPACTS = -#define DEFINE_OFPACT(ENUM, STRUCT, MEMBER) + 1 - OFPACTS -#undef DEFINE_OFPACT +#define OFPACT(ENUM, STRUCT, MEMBER, NAME) + 1 + N_OFPACTS = OFPACTS +#undef OFPACT }; /* Header for an action. @@ -131,14 +142,14 @@ enum { * ofpact", usually followed by other data that describes the action. Actions * are padded out to a multiple of OFPACT_ALIGNTO bytes in length. * - * The 'compat' member is special: + * The 'raw' member is special: * * - Most "struct ofpact"s correspond to one particular kind of OpenFlow * action, at least in a given OpenFlow version. For example, * OFPACT_SET_VLAN_VID corresponds to OFPAT10_SET_VLAN_VID in OpenFlow * 1.0. * - * For such actions, the 'compat' member is not meaningful and generally + * For such actions, the 'raw' member is not meaningful and generally * should be zero. * * - A few "struct ofpact"s correspond to multiple OpenFlow actions. For @@ -149,33 +160,53 @@ enum { * (Otherwise, we'd violate the promise made in DESIGN, in the "Action * Reproduction" section.) * - * For such actions, the 'compat' member should be the original action - * type. (If the action didn't originate from OpenFlow, then setting - * 'compat' to zero should be fine: code to translate the ofpact to - * OpenFlow must tolerate this case.) + * For such actions, the 'raw' member should be the "enum ofp_raw_action" + * originally extracted from the OpenFlow action. (If the action didn't + * originate from OpenFlow, then setting 'raw' to zero should be fine: + * code to translate the ofpact to OpenFlow must tolerate this case.) */ struct ofpact { + /* We want the space advantage of an 8-bit type here on every + * implementation, without giving up the advantage of having a useful type + * on implementations that support packed enums. */ +#ifdef HAVE_PACKED_ENUM enum ofpact_type type; /* OFPACT_*. */ - enum ofputil_action_code compat; /* Original type when added, if any. */ +#else + uint8_t type; /* OFPACT_* */ +#endif + + uint8_t raw; /* Original type when added, if any. */ uint16_t len; /* Length of the action, in bytes, including * struct ofpact, excluding padding. */ }; - -#ifdef __GNUC__ -/* Make sure that OVS_PACKED_ENUM really worked. */ BUILD_ASSERT_DECL(sizeof(struct ofpact) == 4); -#endif /* Alignment. */ #define OFPACT_ALIGNTO 8 #define OFPACT_ALIGN(SIZE) ROUND_UP(SIZE, OFPACT_ALIGNTO) +/* Expands to an anonymous union that contains: + * + * - MEMBERS in a nested anonymous struct. + * + * - An array as large as MEMBERS plus padding to a multiple of 8 bytes. + * + * The effect is to pad MEMBERS to a multiple of 8 bytes. */ +#define OFPACT_PADDED_MEMBERS(MEMBERS) \ + union { \ + struct { MEMBERS }; \ + uint8_t pad[OFPACT_ALIGN(sizeof(struct { MEMBERS }))]; \ + } + +/* Returns the ofpact following 'ofpact'. */ static inline struct ofpact * ofpact_next(const struct ofpact *ofpact) { return (void *) ((uint8_t *) ofpact + OFPACT_ALIGN(ofpact->len)); } +struct ofpact *ofpact_next_flattened(const struct ofpact *); + static inline struct ofpact * ofpact_end(const struct ofpact *ofpacts, size_t ofpacts_len) { @@ -187,6 +218,15 @@ ofpact_end(const struct ofpact *ofpacts, size_t ofpacts_len) #define OFPACT_FOR_EACH(POS, OFPACTS, OFPACTS_LEN) \ for ((POS) = (OFPACTS); (POS) < ofpact_end(OFPACTS, OFPACTS_LEN); \ (POS) = ofpact_next(POS)) + +/* Assigns POS to each ofpact, in turn, in the OFPACTS_LEN bytes of ofpacts + * starting at OFPACTS. + * + * For ofpacts that contain nested ofpacts, this visits each of the inner + * ofpacts as well. */ +#define OFPACT_FOR_EACH_FLATTENED(POS, OFPACTS, OFPACTS_LEN) \ + for ((POS) = (OFPACTS); (POS) < ofpact_end(OFPACTS, OFPACTS_LEN); \ + (POS) = ofpact_next_flattened(POS)) /* Action structure for each OFPACT_*. */ @@ -218,6 +258,16 @@ struct ofpact_controller { uint16_t max_len; /* Maximum length to send to controller. */ uint16_t controller_id; /* Controller ID to send packet-in. */ enum ofp_packet_in_reason reason; /* Reason to put in packet-in. */ + + /* If true, this action freezes packet traversal of the OpenFlow tables and + * adds a continuation to the packet-in message, that a controller can use + * to resume that traversal. */ + bool pause; + + /* Arbitrary data to include in the packet-in message (currently, only in + * NXT_PACKET_IN2). */ + uint16_t userdata_len; + uint8_t userdata[]; }; /* OFPACT_ENQUEUE. @@ -234,8 +284,31 @@ struct ofpact_enqueue { * Used for NXAST_OUTPUT_REG. */ struct ofpact_output_reg { struct ofpact ofpact; - struct mf_subfield src; uint16_t max_len; + struct mf_subfield src; +}; + +/* Bundle slave choice algorithm to apply. + * + * In the descriptions below, 'slaves' is the list of possible slaves in the + * order they appear in the OpenFlow action. */ +enum nx_bd_algorithm { + /* Chooses the first live slave listed in the bundle. + * + * O(n_slaves) performance. */ + NX_BD_ALG_ACTIVE_BACKUP = 0, + + /* Highest Random Weight. + * + * for i in [0,n_slaves): + * weights[i] = hash(flow, i) + * slave = { slaves[i] such that weights[i] >= weights[j] for all j != i } + * + * Redistributes 1/n_slaves of traffic when a slave's liveness changes. + * O(n_slaves) performance. + * + * Uses the 'fields' and 'basis' parameters. */ + NX_BD_ALG_HRW = 1 }; /* OFPACT_BUNDLE. @@ -293,7 +366,7 @@ struct ofpact_vlan_pcp { * Used for OFPAT10_SET_DL_SRC, OFPAT10_SET_DL_DST. */ struct ofpact_mac { struct ofpact ofpact; - uint8_t mac[ETH_ADDR_LEN]; + struct eth_addr mac; }; /* OFPACT_SET_IPV4_SRC, OFPACT_SET_IPV4_DST. @@ -354,23 +427,15 @@ struct ofpact_stack { struct mf_subfield subfield; }; -/* OFPACT_REG_LOAD. - * - * Used for NXAST_REG_LOAD. */ -struct ofpact_reg_load { - struct ofpact ofpact; - struct mf_subfield dst; - union mf_subvalue subvalue; /* Least-significant bits are used. */ -}; - /* OFPACT_SET_FIELD. * - * Used for OFPAT12_SET_FIELD. */ + * Used for NXAST_REG_LOAD and OFPAT12_SET_FIELD. */ struct ofpact_set_field { struct ofpact ofpact; const struct mf_field *field; bool flow_has_vlan; /* VLAN present at action validation time. */ union mf_value value; + union mf_value mask; }; /* OFPACT_PUSH_VLAN/MPLS/PBB @@ -435,11 +500,53 @@ struct ofpact_meter { * * Used for OFPIT11_WRITE_ACTIONS. */ struct ofpact_nest { - struct ofpact ofpact; - uint8_t pad[PAD_SIZE(sizeof(struct ofpact), OFPACT_ALIGNTO)]; + OFPACT_PADDED_MEMBERS(struct ofpact ofpact;); struct ofpact actions[]; }; BUILD_ASSERT_DECL(offsetof(struct ofpact_nest, actions) % OFPACT_ALIGNTO == 0); +BUILD_ASSERT_DECL(offsetof(struct ofpact_nest, actions) + == sizeof(struct ofpact_nest)); + +/* Bits for 'flags' in struct nx_action_conntrack. + * + * If NX_CT_F_COMMIT is set, then the connection entry is moved from the + * unconfirmed to confirmed list in the tracker. */ +enum nx_conntrack_flags { + NX_CT_F_COMMIT = 1 << 0, +}; + +/* Magic value for struct nx_action_conntrack 'recirc_table' field, to specify + * that the packet should not be recirculated. */ +#define NX_CT_RECIRC_NONE OFPTT_ALL + +#if !defined(IPPORT_FTP) +#define IPPORT_FTP 21 +#endif + +/* OFPACT_CT. + * + * Used for NXAST_CT. */ +struct ofpact_conntrack { + OFPACT_PADDED_MEMBERS( + struct ofpact ofpact; + uint16_t flags; + uint16_t zone_imm; + struct mf_subfield zone_src; + uint16_t alg; + uint8_t recirc_table; + ); + struct ofpact actions[0]; +}; +BUILD_ASSERT_DECL(offsetof(struct ofpact_conntrack, actions) + % OFPACT_ALIGNTO == 0); +BUILD_ASSERT_DECL(offsetof(struct ofpact_conntrack, actions) + == sizeof(struct ofpact_conntrack)); + +static inline size_t +ofpact_ct_get_action_len(const struct ofpact_conntrack *oc) +{ + return oc->ofpact.len - offsetof(struct ofpact_conntrack, actions); +} static inline size_t ofpact_nest_get_action_len(const struct ofpact_nest *on) @@ -450,6 +557,42 @@ ofpact_nest_get_action_len(const struct ofpact_nest *on) void ofpacts_execute_action_set(struct ofpbuf *action_list, const struct ofpbuf *action_set); +/* Bits for 'flags' in struct nx_action_nat. + */ +enum nx_nat_flags { + NX_NAT_F_SRC = 1 << 0, + NX_NAT_F_DST = 1 << 1, + NX_NAT_F_PERSISTENT = 1 << 2, + NX_NAT_F_PROTO_HASH = 1 << 3, + NX_NAT_F_PROTO_RANDOM = 1 << 4, +}; + +/* OFPACT_NAT. + * + * Used for NXAST_NAT. */ +struct ofpact_nat { + struct ofpact ofpact; + uint8_t range_af; /* AF_UNSPEC, AF_INET, or AF_INET6 */ + uint16_t flags; /* NX_NAT_F_* */ + struct { + struct { + uint16_t min; + uint16_t max; + } proto; + union { + struct { + ovs_be32 min; + ovs_be32 max; + } ipv4; + struct { + struct in6_addr min; + struct in6_addr max; + } ipv6; + } addr; + } range; +}; + + /* OFPACT_RESUBMIT. * * Used for NXAST_RESUBMIT, NXAST_RESUBMIT_TABLE. */ @@ -471,6 +614,51 @@ struct ofpact_learn_spec { struct mf_subfield dst; /* NX_LEARN_DST_MATCH, NX_LEARN_DST_LOAD only. */ }; + +/* Bits for 'flags' in struct nx_action_learn. + * + * If NX_LEARN_F_SEND_FLOW_REM is set, then the learned flows will have their + * OFPFF_SEND_FLOW_REM flag set. + * + * If NX_LEARN_F_DELETE_LEARNED is set, then removing this action will delete + * all the flows from the learn action's 'table_id' that have the learn + * action's 'cookie'. Important points: + * + * - The deleted flows include those created by this action, those created + * by other learn actions with the same 'table_id' and 'cookie', those + * created by flow_mod requests by a controller in the specified table + * with the specified cookie, and those created through any other + * means. + * + * - If multiple flows specify "learn" actions with + * NX_LEARN_F_DELETE_LEARNED with the same 'table_id' and 'cookie', then + * no deletion occurs until all of those "learn" actions are deleted. + * + * - Deleting a flow that contains a learn action is the most obvious way + * to delete a learn action. Modifying a flow's actions, or replacing it + * by a new flow, can also delete a learn action. Finally, replacing a + * learn action with NX_LEARN_F_DELETE_LEARNED with a learn action + * without that flag also effectively deletes the learn action and can + * trigger flow deletion. + * + * NX_LEARN_F_DELETE_LEARNED was added in Open vSwitch 2.4. */ +enum nx_learn_flags { + NX_LEARN_F_SEND_FLOW_REM = 1 << 0, + NX_LEARN_F_DELETE_LEARNED = 1 << 1, +}; + +#define NX_LEARN_N_BITS_MASK 0x3ff + +#define NX_LEARN_SRC_FIELD (0 << 13) /* Copy from field. */ +#define NX_LEARN_SRC_IMMEDIATE (1 << 13) /* Copy from immediate value. */ +#define NX_LEARN_SRC_MASK (1 << 13) + +#define NX_LEARN_DST_MATCH (0 << 11) /* Add match criterion. */ +#define NX_LEARN_DST_LOAD (1 << 11) /* Add NXAST_REG_LOAD action. */ +#define NX_LEARN_DST_OUTPUT (2 << 11) /* Add OFPAT_OUTPUT action. */ +#define NX_LEARN_DST_RESERVED (3 << 11) /* Not yet defined. */ +#define NX_LEARN_DST_MASK (3 << 11) + /* OFPACT_LEARN. * * Used for NXAST_LEARN. */ @@ -481,8 +669,8 @@ struct ofpact_learn { uint16_t hard_timeout; /* Max time before discarding (seconds). */ uint16_t priority; /* Priority level of flow entry. */ uint8_t table_id; /* Table to insert flow entry. */ - uint64_t cookie; /* Cookie for new flow. */ - enum ofputil_flow_mod_flags flags; + ovs_be64 cookie; /* Cookie for new flow. */ + enum nx_learn_flags flags; /* NX_LEARN_F_*. */ uint16_t fin_idle_timeout; /* Idle timeout after FIN, if nonzero. */ uint16_t fin_hard_timeout; /* Hard timeout after FIN, if nonzero. */ @@ -490,6 +678,70 @@ struct ofpact_learn { struct ofpact_learn_spec specs[]; }; +/* Multipath link choice algorithm to apply. + * + * In the descriptions below, 'n_links' is max_link + 1. */ +enum nx_mp_algorithm { + /* link = hash(flow) % n_links. + * + * Redistributes all traffic when n_links changes. O(1) performance. See + * RFC 2992. + * + * Use UINT16_MAX for max_link to get a raw hash value. */ + NX_MP_ALG_MODULO_N = 0, + + /* link = hash(flow) / (MAX_HASH / n_links). + * + * Redistributes between one-quarter and one-half of traffic when n_links + * changes. O(1) performance. See RFC 2992. + */ + NX_MP_ALG_HASH_THRESHOLD = 1, + + /* Highest Random Weight. + * + * for i in [0,n_links): + * weights[i] = hash(flow, i) + * link = { i such that weights[i] >= weights[j] for all j != i } + * + * Redistributes 1/n_links of traffic when n_links changes. O(n_links) + * performance. If n_links is greater than a threshold (currently 64, but + * subject to change), Open vSwitch will substitute another algorithm + * automatically. See RFC 2992. */ + NX_MP_ALG_HRW = 2, + + /* Iterative Hash. + * + * i = 0 + * repeat: + * i = i + 1 + * link = hash(flow, i) % arg + * while link > max_link + * + * Redistributes 1/n_links of traffic when n_links changes. O(1) + * performance when arg/max_link is bounded by a constant. + * + * Redistributes all traffic when arg changes. + * + * arg must be greater than max_link and for best performance should be no + * more than approximately max_link * 2. If arg is outside the acceptable + * range, Open vSwitch will automatically substitute the least power of 2 + * greater than max_link. + * + * This algorithm is specific to Open vSwitch. + */ + NX_MP_ALG_ITER_HASH = 3, +}; + +/* OFPACT_CONJUNCTION. + * + * Used for NXAST_CONJUNCTION. */ +struct ofpact_conjunction { + struct ofpact ofpact; + uint8_t clause; + uint8_t n_clauses; + uint32_t id; +}; + /* OFPACT_MULTIPATH. * * Used for NXAST_MULTIPATH. */ @@ -583,6 +835,17 @@ struct ofpact_group { uint32_t group_id; }; +/* OFPACT_UNROLL_XLATE. + * + * Used only internally. */ +struct ofpact_unroll_xlate { + struct ofpact ofpact; + + /* Metadata in xlate context, visible to controller via PACKET_INs. */ + uint8_t rule_table_id; /* 0xFF if none. */ + ovs_be64 rule_cookie; /* OVS_BE64_MAX if none. */ +}; + /* Converting OpenFlow to ofpacts. */ enum ofperr ofpacts_pull_openflow_actions(struct ofpbuf *openflow, unsigned int actions_len, @@ -600,7 +863,6 @@ enum ofperr ofpacts_check_consistency(struct ofpact[], size_t ofpacts_len, struct flow *, ofp_port_t max_ports, uint8_t table_id, uint8_t n_tables, enum ofputil_protocol usable_protocols); -enum ofperr ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len); enum ofperr ofpact_check_output_port(ofp_port_t port, ofp_port_t max_ports); /* Converting ofpacts to OpenFlow. */ @@ -611,6 +873,11 @@ void ofpacts_put_openflow_instructions(const struct ofpact[], struct ofpbuf *openflow, enum ofp_version ofp_version); +/* Sets of supported actions. */ +ovs_be32 ofpact_bitmap_to_openflow(uint64_t ofpacts_bitmap, enum ofp_version); +uint64_t ofpact_bitmap_from_openflow(ovs_be32 ofpat_bitmap, enum ofp_version); +void ofpact_bitmap_format(uint64_t ofpacts_bitmap, struct ds *); + /* Working with ofpacts. */ bool ofpacts_output_to_port(const struct ofpact[], size_t ofpacts_len, ofp_port_t port); @@ -618,12 +885,18 @@ bool ofpacts_output_to_group(const struct ofpact[], size_t ofpacts_len, uint32_t group_id); bool ofpacts_equal(const struct ofpact a[], size_t a_len, const struct ofpact b[], size_t b_len); +const struct mf_field *ofpact_get_mf_dst(const struct ofpact *ofpact); uint32_t ofpacts_get_meter(const struct ofpact[], size_t ofpacts_len); -/* Formatting ofpacts. - * - * (For parsing ofpacts, see ofp-parse.h.) */ +/* Formatting and parsing ofpacts. */ void ofpacts_format(const struct ofpact[], size_t ofpacts_len, struct ds *); +char *ofpacts_parse_actions(const char *, struct ofpbuf *ofpacts, + enum ofputil_protocol *usable_protocols) + OVS_WARN_UNUSED_RESULT; +char *ofpacts_parse_instructions(const char *, struct ofpbuf *ofpacts, + enum ofputil_protocol *usable_protocols) + OVS_WARN_UNUSED_RESULT; +const char *ofpact_name(enum ofpact_type); /* Internal use by the helpers below. */ void ofpact_init(struct ofpact *, enum ofpact_type, size_t len); @@ -634,15 +907,15 @@ void *ofpact_put(struct ofpbuf *, enum ofpact_type, size_t len); * * struct *ofpact_put_(struct ofpbuf *ofpacts); * - * Appends a new 'ofpact', of length OFPACT__RAW_SIZE, to 'ofpacts', + * Appends a new 'ofpact', of length OFPACT__SIZE, to 'ofpacts', * initializes it with ofpact_init_(), and returns it. Also sets - * 'ofpacts->l2' to the returned action. + * 'ofpacts->header' to the returned action. * * After using this function to add a variable-length action, add the * elements of the flexible array (e.g. with ofpbuf_put()), then use - * ofpact_update_len() to update the length embedded into the action. - * (Keep in mind the need to refresh the structure from 'ofpacts->l2' after - * adding data to 'ofpacts'.) + * ofpact_finish() to pad the action to a multiple of OFPACT_ALIGNTO bytes + * and update its embedded length field. (Keep in mind the need to refresh + * the structure from 'ofpacts->header' after adding data to 'ofpacts'.) * * struct *ofpact_get_(const struct ofpact *ofpact); * @@ -654,29 +927,22 @@ void *ofpact_put(struct ofpbuf *, enum ofpact_type, size_t len); * void ofpact_init_(struct *ofpact); * * Initializes the parts of 'ofpact' that identify it as having type - * OFPACT_ and length OFPACT__RAW_SIZE and zeros the rest. - * - * _RAW_SIZE - * - * The size of the action structure. For a fixed-length action, this is - * sizeof(struct ). For a variable-length action, this is the - * offset to the variable-length part. + * OFPACT_ and length OFPACT__SIZE and zeros the rest. * * _SIZE * - * An integer constant, the value of OFPACT__RAW_SIZE rounded up to a - * multiple of OFPACT_ALIGNTO. + * The size of the action structure. For a fixed-length action, this is + * sizeof(struct ) rounded up to a multiple of OFPACT_ALIGNTO. For + * a variable-length action, this is the offset to the variable-length + * part. */ -#define DEFINE_OFPACT(ENUM, STRUCT, MEMBER) \ +#define OFPACT(ENUM, STRUCT, MEMBER, NAME) \ BUILD_ASSERT_DECL(offsetof(struct STRUCT, ofpact) == 0); \ \ - enum { OFPACT_##ENUM##_RAW_SIZE \ + enum { OFPACT_##ENUM##_SIZE \ = (offsetof(struct STRUCT, MEMBER) \ ? offsetof(struct STRUCT, MEMBER) \ - : sizeof(struct STRUCT)) }; \ - \ - enum { OFPACT_##ENUM##_SIZE \ - = ROUND_UP(OFPACT_##ENUM##_RAW_SIZE, OFPACT_ALIGNTO) }; \ + : OFPACT_ALIGN(sizeof(struct STRUCT))) }; \ \ static inline struct STRUCT * \ ofpact_get_##ENUM(const struct ofpact *ofpact) \ @@ -689,21 +955,23 @@ void *ofpact_put(struct ofpbuf *, enum ofpact_type, size_t len); ofpact_put_##ENUM(struct ofpbuf *ofpacts) \ { \ return ofpact_put(ofpacts, OFPACT_##ENUM, \ - OFPACT_##ENUM##_RAW_SIZE); \ + OFPACT_##ENUM##_SIZE); \ } \ \ static inline void \ ofpact_init_##ENUM(struct STRUCT *ofpact) \ { \ ofpact_init(&ofpact->ofpact, OFPACT_##ENUM, \ - OFPACT_##ENUM##_RAW_SIZE); \ + OFPACT_##ENUM##_SIZE); \ } OFPACTS -#undef DEFINE_OFPACT +#undef OFPACT -/* Functions to use after adding ofpacts to a buffer. */ -void ofpact_update_len(struct ofpbuf *, struct ofpact *); -void ofpact_pad(struct ofpbuf *); +/* Call after adding the variable-length part to a variable-length action. */ +void ofpact_finish(struct ofpbuf *, struct ofpact *); + +/* Additional functions for composing ofpacts. */ +struct ofpact_set_field *ofpact_put_reg_load(struct ofpbuf *ofpacts); /* OpenFlow 1.1 instructions. * The order is sorted in execution order. Not in the value of OFPIT11_xxx. @@ -753,4 +1021,8 @@ enum ovs_instruction_type ovs_instruction_type_from_ofpact_type( enum ofperr ovs_instruction_type_from_inst_type( enum ovs_instruction_type *instruction_type, const uint16_t inst_type); +ovs_be32 ovsinst_bitmap_to_openflow(uint32_t ovsinst_bitmap, enum ofp_version); +uint32_t ovsinst_bitmap_from_openflow(ovs_be32 ofpit_bitmap, + enum ofp_version); + #endif /* ofp-actions.h */