#include "ovn/lib/actions.h"
#include "ovn/lib/expr.h"
#include "ovn/lib/ovn-sb-idl.h"
+#include "packets.h"
#include "simap.h"
VLOG_DEFINE_THIS_MODULE(lflow);
#undef MFF_LOG_REG
/* Connection tracking state. */
+ expr_symtab_add_field(&symtab, "ct_mark", MFF_CT_MARK, NULL, false);
+ expr_symtab_add_field(&symtab, "ct_label", MFF_CT_LABEL, NULL, false);
expr_symtab_add_field(&symtab, "ct_state", MFF_CT_STATE, NULL, false);
- expr_symtab_add_predicate(&symtab, "ct.trk", "ct_state[7]");
- expr_symtab_add_subfield(&symtab, "ct.new", "ct.trk", "ct_state[0]");
- expr_symtab_add_subfield(&symtab, "ct.est", "ct.trk", "ct_state[1]");
- expr_symtab_add_subfield(&symtab, "ct.rel", "ct.trk", "ct_state[2]");
- expr_symtab_add_subfield(&symtab, "ct.inv", "ct.trk", "ct_state[5]");
- expr_symtab_add_subfield(&symtab, "ct.rpl", "ct.trk", "ct_state[6]");
+ char ct_state_str[16];
+ snprintf(ct_state_str, sizeof ct_state_str, "ct_state[%d]", CS_TRACKED_BIT);
+ expr_symtab_add_predicate(&symtab, "ct.trk", ct_state_str);
+ snprintf(ct_state_str, sizeof ct_state_str, "ct_state[%d]", CS_NEW_BIT);
+ expr_symtab_add_subfield(&symtab, "ct.new", "ct.trk", ct_state_str);
+ snprintf(ct_state_str, sizeof ct_state_str, "ct_state[%d]", CS_ESTABLISHED_BIT);
+ expr_symtab_add_subfield(&symtab, "ct.est", "ct.trk", ct_state_str);
+ snprintf(ct_state_str, sizeof ct_state_str, "ct_state[%d]", CS_RELATED_BIT);
+ expr_symtab_add_subfield(&symtab, "ct.rel", "ct.trk", ct_state_str);
+ snprintf(ct_state_str, sizeof ct_state_str, "ct_state[%d]", CS_REPLY_DIR_BIT);
+ expr_symtab_add_subfield(&symtab, "ct.rpl", "ct.trk", ct_state_str);
+ snprintf(ct_state_str, sizeof ct_state_str, "ct_state[%d]", CS_INVALID_BIT);
+ expr_symtab_add_subfield(&symtab, "ct.inv", "ct.trk", ct_state_str);
/* Data fields. */
expr_symtab_add_field(&symtab, "eth.src", MFF_ETH_SRC, NULL, false);
\f
/* Logical datapaths and logical port numbers. */
+enum ldp_type {
+ LDP_TYPE_ROUTER,
+ LDP_TYPE_SWITCH,
+};
+
/* A logical datapath.
*
* 'ports' maps 'logical_port' names to 'tunnel_key' values in the OVN_SB
struct uuid uuid; /* UUID from Datapath_Binding row. */
uint32_t tunnel_key; /* 'tunnel_key' from Datapath_Binding row. */
struct simap ports; /* Logical port name to port number. */
+ enum ldp_type type; /* Type of logical datapath */
};
/* Contains "struct logical_datapath"s. */
uuid_hash(&binding->header_.uuid));
ldp->uuid = binding->header_.uuid;
ldp->tunnel_key = binding->tunnel_key;
+ const char *ls = smap_get(&binding->external_ids, "logical-switch");
+ ldp->type = ls ? LDP_TYPE_SWITCH : LDP_TYPE_ROUTER;
simap_init(&ldp->ports);
return ldp;
}
* into OpenFlow flows. See ovn-architecture(7) for more information. */
void
lflow_run(struct controller_ctx *ctx, struct hmap *flow_table,
- const struct simap *ct_zones)
+ const struct simap *ct_zones,
+ struct hmap *local_datapaths)
{
struct hmap flows = HMAP_INITIALIZER(&flows);
uint32_t conj_id_ofs = 1;
const struct sbrec_logical_flow *lflow;
SBREC_LOGICAL_FLOW_FOR_EACH (lflow, ctx->ovnsb_idl) {
- /* Find the "struct logical_datapath" asssociated with this
+ /* Find the "struct logical_datapath" associated with this
* Logical_Flow row. If there's no such struct, that must be because
* no logical ports are bound to that logical datapath, so there's no
* point in maintaining any flows for it anyway, so skip it. */
continue;
}
- /* Determine translation of logical table IDs to physical table IDs. */
bool ingress = !strcmp(lflow->pipeline, "ingress");
+
+ if (ldp->type == LDP_TYPE_SWITCH && !ingress) {
+ /* For a logical switch datapath, local_datapaths tells us if there
+ * are any local ports for this datapath. If not, processing
+ * logical flows for the egress pipeline of this datapath is
+ * unnecessary.
+ *
+ * We still need the ingress pipeline because even if there are no
+ * local ports, we still may need to execute the ingress pipeline
+ * after a packet leaves a logical router. Further optimization
+ * is possible, but not based on what we know with local_datapaths
+ * right now.
+ *
+ * A better approach would be a kind of "flood fill" algorithm:
+ *
+ * 1. Initialize set S to the logical datapaths that have a port
+ * located on the hypervisor.
+ *
+ * 2. For each patch port P in a logical datapath in S, add the
+ * logical datapath of the remote end of P to S. Iterate
+ * until S reaches a fixed point.
+ */
+
+ struct hmap_node *ld;
+ ld = hmap_first_with_hash(local_datapaths, ldp->tunnel_key);
+ if (!ld) {
+ continue;
+ }
+ }
+
+ /* Determine translation of logical table IDs to physical table IDs. */
uint8_t first_ptable = (ingress
? OFTABLE_LOG_INGRESS_PIPELINE
: OFTABLE_LOG_EGRESS_PIPELINE);
char *error;
ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
- error = actions_parse_string(lflow->actions, &symtab, &ldp->ports,
- ct_zones, first_ptable, LOG_PIPELINE_LEN,
- lflow->table_id, output_ptable,
- &ofpacts, &prereqs);
+ struct action_params ap = {
+ .symtab = &symtab,
+ .ports = &ldp->ports,
+ .ct_zones = ct_zones,
+
+ .n_tables = LOG_PIPELINE_LEN,
+ .first_ptable = first_ptable,
+ .cur_ltable = lflow->table_id,
+ .output_ptable = output_ptable,
+ };
+ error = actions_parse_string(lflow->actions, &ap, &ofpacts, &prereqs);
if (error) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
VLOG_WARN_RL(&rl, "error parsing actions \"%s\": %s",