-/* Copyright (c) 2015 Nicira, Inc.
+/* Copyright (c) 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.
#include <config.h>
#include "lflow.h"
+#include "lport.h"
#include "dynamic-string.h"
#include "ofctrl.h"
#include "ofp-actions.h"
#include "ofpbuf.h"
#include "openvswitch/vlog.h"
-#include "ovn/controller/ovn-controller.h"
+#include "ovn-controller.h"
#include "ovn/lib/actions.h"
#include "ovn/lib/expr.h"
#include "ovn/lib/ovn-sb-idl.h"
expr_symtab_add_field(symtab, name, id, NULL, false);
}
-static void
-symtab_init(void)
+void
+lflow_init(void)
{
shash_init(&symtab);
expr_symtab_add_field(&symtab, "sctp.dst", MFF_SCTP_DST, "sctp", 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
- * Port_Binding table within the logical datapath. */
-struct logical_datapath {
- struct hmap_node hmap_node; /* Indexed on 'uuid'. */
- 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 */
+struct lookup_port_aux {
+ const struct lport_index *lports;
+ const struct mcgroup_index *mcgroups;
+ const struct sbrec_datapath_binding *dp;
};
-/* Contains "struct logical_datapath"s. */
-static struct hmap logical_datapaths = HMAP_INITIALIZER(&logical_datapaths);
-
-/* Finds and returns the logical_datapath for 'binding', or NULL if no such
- * logical_datapath exists. */
-static struct logical_datapath *
-ldp_lookup(const struct sbrec_datapath_binding *binding)
-{
- struct logical_datapath *ldp;
- HMAP_FOR_EACH_IN_BUCKET (ldp, hmap_node, uuid_hash(&binding->header_.uuid),
- &logical_datapaths) {
- if (uuid_equals(&ldp->uuid, &binding->header_.uuid)) {
- return ldp;
- }
- }
- return NULL;
-}
-
-/* Creates a new logical_datapath for the given 'binding'. */
-static struct logical_datapath *
-ldp_create(const struct sbrec_datapath_binding *binding)
-{
- struct logical_datapath *ldp;
-
- ldp = xmalloc(sizeof *ldp);
- hmap_insert(&logical_datapaths, &ldp->hmap_node,
- 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;
-}
-
-static struct logical_datapath *
-ldp_lookup_or_create(const struct sbrec_datapath_binding *binding)
-{
- struct logical_datapath *ldp = ldp_lookup(binding);
- return ldp ? ldp : ldp_create(binding);
-}
-
-static void
-ldp_free(struct logical_datapath *ldp)
+static bool
+lookup_port_cb(const void *aux_, const char *port_name, unsigned int *portp)
{
- simap_destroy(&ldp->ports);
- hmap_remove(&logical_datapaths, &ldp->hmap_node);
- free(ldp);
-}
+ const struct lookup_port_aux *aux = aux_;
-/* Iterates through all of the records in the Port_Binding table, updating the
- * table of logical_datapaths to match the values found in active
- * Port_Bindings. */
-static void
-ldp_run(struct controller_ctx *ctx)
-{
- struct logical_datapath *ldp;
- HMAP_FOR_EACH (ldp, hmap_node, &logical_datapaths) {
- simap_clear(&ldp->ports);
+ const struct sbrec_port_binding *pb
+ = lport_lookup_by_name(aux->lports, port_name);
+ if (pb && pb->datapath == aux->dp) {
+ *portp = pb->tunnel_key;
+ return true;
}
- const struct sbrec_port_binding *binding;
- SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) {
- struct logical_datapath *ldp = ldp_lookup_or_create(binding->datapath);
-
- simap_put(&ldp->ports, binding->logical_port, binding->tunnel_key);
+ const struct sbrec_multicast_group *mg
+ = mcgroup_lookup_by_dp_name(aux->mcgroups, aux->dp, port_name);
+ if (mg) {
+ *portp = mg->tunnel_key;
+ return true;
}
- const struct sbrec_multicast_group *mc;
- SBREC_MULTICAST_GROUP_FOR_EACH (mc, ctx->ovnsb_idl) {
- struct logical_datapath *ldp = ldp_lookup_or_create(mc->datapath);
- simap_put(&ldp->ports, mc->name, mc->tunnel_key);
- }
-
- struct logical_datapath *next_ldp;
- HMAP_FOR_EACH_SAFE (ldp, next_ldp, hmap_node, &logical_datapaths) {
- if (simap_is_empty(&ldp->ports)) {
- ldp_free(ldp);
- }
- }
-}
-
-static void
-ldp_destroy(void)
-{
- struct logical_datapath *ldp, *next_ldp;
- HMAP_FOR_EACH_SAFE (ldp, next_ldp, hmap_node, &logical_datapaths) {
- ldp_free(ldp);
- }
-}
-\f
-void
-lflow_init(void)
-{
- symtab_init();
+ return false;
}
static bool
-lookup_port_cb(const void *ldp_, const char *port_name, unsigned int *portp)
+is_switch(const struct sbrec_datapath_binding *ldp)
{
- const struct logical_datapath *ldp = ldp_;
- const struct simap_node *node = simap_find(&ldp->ports, port_name);
- if (!node) {
- return false;
- }
- *portp = node->data;
- return true;
+ return smap_get(&ldp->external_ids, "logical-switch") != NULL;
+
}
/* Translates logical flows in the Logical_Flow table in the OVN_SB database
* 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,
- struct hmap *local_datapaths)
+lflow_run(struct controller_ctx *ctx, const struct lport_index *lports,
+ const struct mcgroup_index *mcgroups,
+ const struct hmap *local_datapaths,
+ const struct simap *ct_zones, struct hmap *flow_table)
{
struct hmap flows = HMAP_INITIALIZER(&flows);
uint32_t conj_id_ofs = 1;
- ldp_run(ctx);
-
const struct sbrec_logical_flow *lflow;
SBREC_LOGICAL_FLOW_FOR_EACH (lflow, ctx->ovnsb_idl) {
- /* 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. */
- const struct logical_datapath *ldp;
- ldp = ldp_lookup(lflow->logical_datapath);
+ /* Determine translation of logical table IDs to physical table IDs. */
+ bool ingress = !strcmp(lflow->pipeline, "ingress");
+
+ const struct sbrec_datapath_binding *ldp = lflow->logical_datapath;
if (!ldp) {
continue;
}
-
- bool ingress = !strcmp(lflow->pipeline, "ingress");
-
- if (ldp->type == LDP_TYPE_SWITCH && !ingress) {
+ if (!ingress && is_switch(ldp)) {
/* 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
char *error;
ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
+ struct lookup_port_aux aux = {
+ .lports = lports,
+ .mcgroups = mcgroups,
+ .dp = lflow->logical_datapath
+ };
struct action_params ap = {
.symtab = &symtab,
.lookup_port = lookup_port_cb,
- .aux = ldp,
+ .aux = &aux,
.ct_zones = ct_zones,
.n_tables = LOG_PIPELINE_LEN,
expr = expr_simplify(expr);
expr = expr_normalize(expr);
- uint32_t n_conjs = expr_to_matches(expr, lookup_port_cb, ldp,
+ uint32_t n_conjs = expr_to_matches(expr, lookup_port_cb, &aux,
&matches);
expr_destroy(expr);
/* Prepare the OpenFlow matches for adding to the flow table. */
struct expr_match *m;
HMAP_FOR_EACH (m, hmap_node, &matches) {
- match_set_metadata(&m->match, htonll(ldp->tunnel_key));
+ match_set_metadata(&m->match,
+ htonll(lflow->logical_datapath->tunnel_key));
if (m->match.wc.masks.conj_id) {
m->match.flow.conj_id += conj_id_ofs;
}
lflow_destroy(void)
{
expr_symtab_destroy(&symtab);
- ldp_destroy();
}