X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif-rid.h;h=135810d0b0270bf0d8f45395983de95d945885da;hb=fbf5d6ec3f88f4101753786d7a98b16c14cb648d;hp=9caa662ca5b1bf1212c3f1a83ea4d600bf59843f;hpb=2082425c2c95431a2f8f5d3f6b1d0ef8f242c186;p=cascardo%2Fovs.git diff --git a/ofproto/ofproto-dpif-rid.h b/ofproto/ofproto-dpif-rid.h index 9caa662ca..135810d0b 100644 --- a/ofproto/ofproto-dpif-rid.h +++ b/ofproto/ofproto-dpif-rid.h @@ -23,6 +23,7 @@ #include "cmap.h" #include "list.h" #include "ofp-actions.h" +#include "ofproto-dpif-mirror.h" #include "ovs-thread.h" struct ofproto_dpif; @@ -33,40 +34,40 @@ struct rule; * ============= * * Recirculation is a technique to allow a frame to re-enter the datapath - * packet processing path for one or multiple times to achieve more flexible - * packet processing, such modifying header fields after MPLS POP action and - * selecting bond a slave port for bond ports. + * packet processing path to achieve more flexible packet processing, such as + * modifying header fields after MPLS POP action and selecting a slave port for + * bond ports. * * Data path and user space interface * ----------------------------------- * * Recirculation uses two uint32_t fields, recirc_id and dp_hash, and a RECIRC - * action. The value recirc_id is used to select the next packet processing - * steps among multiple instances of recirculation. When a packet initially - * enters the data path it is assigned with recirc_id 0, which indicates no - * recirculation. Recirc_ids are managed by the user space, opaque to the - * data path. + * action. recirc_id is used to select the next packet processing steps among + * multiple instances of recirculation. When a packet initially enters the + * datapath it is assigned with recirc_id 0, which indicates no recirculation. + * Recirc_ids are managed by the user space, opaque to the datapath. * - * On the other hand, dp_hash can only be computed by the data path, opaque to - * the user space. In fact, user space may not able to recompute the hash - * value. The dp_hash value should be wildcarded for a newly received - * packet. HASH action specifies whether the hash is computed, and if - * computed, how many fields are to be included in the hash computation. The - * computed hash value is stored into the dp_hash field prior to recirculation. + * On the other hand, dp_hash can only be computed by the datapath, opaque to + * the user space, as the datapath is free to choose the hashing algorithm + * without informing user space about it. The dp_hash value should be + * wildcarded for newly received packets. HASH action specifies whether the + * hash is computed, and if computed, how many fields are to be included in the + * hash computation. The computed hash value is stored into the dp_hash field + * prior to recirculation. * * The RECIRC action sets the recirc_id field and then reprocesses the packet - * as if it was received on the same input port. RECIRC action works like a - * function call; actions listed behind the RECIRC action will be executed - * after its execution. RECIRC action can be nested, data path implementation - * limits the number of recirculation executed to prevent unreasonable nesting - * depth or infinite loop. + * as if it was received again on the same input port. RECIRC action works + * like a function call; actions listed after the RECIRC action will be + * executed after recirculation. RECIRC action can be nested, but datapath + * implementation limits the number of nested recirculations to prevent + * unreasonable nesting depth or infinite loop. * * User space recirculation context * --------------------------------- * - * Recirculation is hidden from the OpenFlow controllers. Action translation - * code deduces when recirculation is necessary and issues a data path - * recirculation action. All OpenFlow actions to be performed after + * Recirculation is usually hidden from the OpenFlow controllers. Action + * translation code deduces when recirculation is necessary and issues a + * datapath recirculation action. All OpenFlow actions to be performed after * recirculation are derived from the OpenFlow pipeline and are stored with the * recirculation ID. When the OpenFlow tables are changed in a way affecting * the recirculation flows, new recirculation ID with new metadata and actions @@ -75,9 +76,10 @@ struct rule; * Recirculation ID pool * ---------------------- * - * Recirculation ID needs to be unique for all data paths. Recirculation ID - * pool keeps track recirculation ids and stores OpenFlow pipeline translation - * context so that flow processing may continue after recirculation. + * Recirculation ID needs to be unique for all datapaths. Recirculation ID + * pool keeps track of recirculation ids and stores OpenFlow pipeline + * translation context so that flow processing may continue after + * recirculation. * * A Recirculation ID can be any uint32_t value, except for that the value 0 is * reserved for 'no recirculation' case. @@ -91,11 +93,11 @@ struct rule; /* Metadata for restoring pipeline context after recirculation. Helpers * are inlined below to keep them together with the definition for easier * updates. */ -BUILD_ASSERT_DECL(FLOW_WC_SEQ == 33); +BUILD_ASSERT_DECL(FLOW_WC_SEQ == 34); struct recirc_metadata { /* Metadata in struct flow. */ - struct flow_tnl tunnel; /* Encapsulating tunnel parameters. */ + const struct flow_tnl *tunnel; /* Encapsulating tunnel parameters. */ ovs_be64 metadata; /* OpenFlow Metadata. */ uint64_t regs[FLOW_N_XREGS]; /* Registers. */ ofp_port_t in_port; /* Incoming port. */ @@ -107,7 +109,7 @@ recirc_metadata_from_flow(struct recirc_metadata *md, const struct flow *flow) { memset(md, 0, sizeof *md); - md->tunnel = flow->tunnel; + md->tunnel = &flow->tunnel; md->metadata = flow->metadata; memcpy(md->regs, flow->regs, sizeof md->regs); md->in_port = flow->in_port.ofp_port; @@ -118,7 +120,11 @@ static inline void recirc_metadata_to_flow(const struct recirc_metadata *md, struct flow *flow) { - flow->tunnel = md->tunnel; + if (md->tunnel && md->tunnel->ip_dst) { + flow->tunnel = *md->tunnel; + } else { + memset(&flow->tunnel, 0, sizeof flow->tunnel); + } flow->metadata = md->metadata; memcpy(flow->regs, md->regs, sizeof flow->regs); flow->in_port.ofp_port = md->in_port; @@ -135,6 +141,8 @@ struct recirc_state { struct ofproto_dpif *ofproto; /* Post-recirculation bridge. */ struct recirc_metadata metadata; /* Flow metadata. */ struct ofpbuf *stack; /* Stack if any. */ + mirror_mask_t mirrors; /* Mirrors already output. */ + bool conntracked; /* Conntrack occurred prior to recirc. */ /* Actions to be translated on recirculation. */ uint32_t action_set_len; /* How much of 'ofpacts' consists of an @@ -159,6 +167,9 @@ struct recirc_id_node { * This state should not be modified after inserting a node in the pool, * hence the 'const' to emphasize that. */ const struct recirc_state state; + + /* Storage for tunnel metadata. */ + struct flow_tnl state_metadata_tunnel; }; void recirc_init(void); @@ -185,4 +196,67 @@ void recirc_id_node_unref(const struct recirc_id_node *); void recirc_run(void); +/* Recirculation IDs on which references are held. */ +struct recirc_refs { + unsigned n_recircs; + union { + uint32_t recirc[2]; /* When n_recircs == 1 or 2 */ + uint32_t *recircs; /* When 'n_recircs' > 2 */ + }; +}; + +#define RECIRC_REFS_EMPTY_INITIALIZER ((struct recirc_refs) \ + { 0, { { 0, 0 } } }) +/* Helpers to abstract the recirculation union away. */ +static inline void +recirc_refs_init(struct recirc_refs *rr) +{ + *rr = RECIRC_REFS_EMPTY_INITIALIZER; +} + +static inline void +recirc_refs_add(struct recirc_refs *rr, uint32_t id) +{ + if (OVS_LIKELY(rr->n_recircs < ARRAY_SIZE(rr->recirc))) { + rr->recirc[rr->n_recircs++] = id; + } else { + if (rr->n_recircs == ARRAY_SIZE(rr->recirc)) { + uint32_t *recircs = xmalloc(sizeof rr->recirc + sizeof id); + + memcpy(recircs, rr->recirc, sizeof rr->recirc); + rr->recircs = recircs; + } else { + rr->recircs = xrealloc(rr->recircs, + (rr->n_recircs + 1) * sizeof id); + } + rr->recircs[rr->n_recircs++] = id; + } +} + +static inline void +recirc_refs_swap(struct recirc_refs *a, struct recirc_refs *b) +{ + struct recirc_refs tmp; + + tmp = *a; + *a = *b; + *b = tmp; +} + +static inline void +recirc_refs_unref(struct recirc_refs *rr) +{ + if (OVS_LIKELY(rr->n_recircs <= ARRAY_SIZE(rr->recirc))) { + for (int i = 0; i < rr->n_recircs; i++) { + recirc_free_id(rr->recirc[i]); + } + } else { + for (int i = 0; i < rr->n_recircs; i++) { + recirc_free_id(rr->recircs[i]); + } + free(rr->recircs); + } + rr->n_recircs = 0; +} + #endif