From: Numan Siddique <[email protected]>
Signed-off-by: Numan Siddique <[email protected]>
---
br-controller/automake.mk | 2 +
br-controller/en-lflow.h | 7 +-
br-controller/en-pflow.c | 192 ++++++++++++++++++++++++++
br-controller/en-pflow.h | 16 +++
br-controller/ovn-br-controller.8.xml | 28 ++++
br-controller/ovn-br-controller.c | 6 +
6 files changed, 249 insertions(+), 2 deletions(-)
create mode 100644 br-controller/en-pflow.c
create mode 100644 br-controller/en-pflow.h
diff --git a/br-controller/automake.mk b/br-controller/automake.mk
index ea515a85e4..4baea4f6fe 100644
--- a/br-controller/automake.mk
+++ b/br-controller/automake.mk
@@ -6,6 +6,8 @@ br_controller_ovn_br_controller_SOURCES = \
br-controller/en-bridge-data.h \
br-controller/en-lflow.c \
br-controller/en-lflow.h \
+ br-controller/en-pflow.c \
+ br-controller/en-pflow.h \
br-controller/ovn-br-controller.c
br_controller_ovn_br_controller_LDADD = lib/libovn.la
$(OVS_LIBDIR)/libopenvswitch.la
diff --git a/br-controller/en-lflow.h b/br-controller/en-lflow.h
index 39daa30174..0b9f1deb1a 100644
--- a/br-controller/en-lflow.h
+++ b/br-controller/en-lflow.h
@@ -9,8 +9,11 @@
#include "lib/inc-proc-eng.h"
-#define BR_OFTABLE_LOG_INGRESS_PIPELINE 8
-#define BR_OFTABLE_SAVE_INPORT 64
+/* OpenFlow table numbers. */
+#define BR_OFTABLE_PHY_TO_LOG 0
+#define BR_OFTABLE_LOG_INGRESS_PIPELINE 8
+#define BR_OFTABLE_SAVE_INPORT 120
+#define BR_OFTABLE_LOG_TO_PHY 121
enum engine_node_state en_lflow_output_run(struct engine_node *, void *data);
void *en_lflow_output_init(struct engine_node *node, struct engine_arg *arg);
diff --git a/br-controller/en-pflow.c b/br-controller/en-pflow.c
new file mode 100644
index 0000000000..5f4c5b914f
--- /dev/null
+++ b/br-controller/en-pflow.c
@@ -0,0 +1,192 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* OVS includes. */
+#include "lib/coverage.h"
+#include "lib/flow.h"
+#include "lib/simap.h"
+#include "lib/vswitch-idl.h"
+#include "openvswitch/match.h"
+#include "openvswitch/ofp-actions.h"
+#include "openvswitch/ofpbuf.h"
+#include "openvswitch/ofp-parse.h"
+
+#include "openvswitch/vlog.h"
+#include "openvswitch/uuid.h"
+
+/* OVN includes. */
+#include "br-flow-mgr.h"
+#include "en-lflow.h"
+#include "en-pflow.h"
+#include "en-bridge-data.h"
+#include "include/ovn/logical-fields.h"
+#include "lib/ovn-br-idl.h"
+
+VLOG_DEFINE_THIS_MODULE(en_pflow);
+
+
+static void pflow_run(const struct shash *ovn_bridges);
+static void physical_flows_add(const struct ovn_bridge *);
+
+static void put_load(uint64_t value, enum mf_field_id dst, int ofs, int n_bits,
+ struct ofpbuf *);
+static void put_resubmit(uint8_t table_id, struct ofpbuf *);
+
+static void add_interface_flows(const char *bridge,
+ const struct ovsrec_interface *iface_rec,
+ int64_t, struct ofpbuf *);
+
+/* Public functions. */
+void *en_pflow_output_init(struct engine_node *node OVS_UNUSED,
+ struct engine_arg *arg OVS_UNUSED)
+{
+ return NULL;
+}
+
+void en_pflow_output_cleanup(void *data_ OVS_UNUSED)
+{
+}
+
+enum engine_node_state
+en_pflow_output_run(struct engine_node *node, void *data_ OVS_UNUSED)
+{
+ struct ed_type_bridge_data *br_data =
+ engine_get_input_data("bridge_data", node);
+
+ pflow_run(&br_data->bridges);
+
+ return EN_UPDATED;
+}
+
+/* Static functions. */
+static void
+pflow_run(const struct shash *ovn_bridges)
+{
+ br_flow_switch_physical_oflow_tables();
+ struct shash_node *shash_node;
+ SHASH_FOR_EACH (shash_node, ovn_bridges) {
+ physical_flows_add(shash_node->data);
+ }
+}
+
+static void
+physical_flows_add(const struct ovn_bridge *br)
+{
+ if (!br->ovs_br) {
+ return;
+ }
+
+ struct ofpbuf ofpacts;
+ ofpbuf_init(&ofpacts, 0);
+
+ struct match match = MATCH_CATCHALL_INITIALIZER;
+
+ /* Table 0 and 65, priority 0, actions=NORMAL
+ * ===================================
+ *
+ */
+ ofpact_put_OUTPUT(&ofpacts)->port = OFPP_NORMAL;
+ br_flow_add_physical_oflow(br->db_br->name, BR_OFTABLE_PHY_TO_LOG, 0,
+ br->ovs_br->header_.uuid.parts[0],
+ &match, &ofpacts, &br->ovs_br->header_.uuid);
+ br_flow_add_physical_oflow(br->db_br->name, BR_OFTABLE_LOG_TO_PHY, 0,
+ br->ovs_br->header_.uuid.parts[0],
+ &match, &ofpacts, &br->ovs_br->header_.uuid);
+
+ ofpbuf_clear(&ofpacts);
+ put_resubmit(BR_OFTABLE_LOG_TO_PHY, &ofpacts);
+ br_flow_add_physical_oflow(br->db_br->name, BR_OFTABLE_SAVE_INPORT, 0,
+ br->ovs_br->header_.uuid.parts[0],
+ &match, &ofpacts, &br->ovs_br->header_.uuid);
+
+ for (size_t i = 0; i < br->ovs_br->n_ports; i++) {
+ const struct ovsrec_port *port_rec = br->ovs_br->ports[i];
+
+ for (size_t j = 0; j < port_rec->n_interfaces; j++) {
+ const struct ovsrec_interface *iface_rec;
+
+ iface_rec = port_rec->interfaces[j];
+ int64_t ofport = iface_rec->n_ofport ? *iface_rec->ofport : 0;
+ if (ofport > 0 && ofport != ofp_to_u16(OFPP_LOCAL) &&
+ smap_get_bool(&iface_rec->external_ids,
+ "ovnbr-managed", true)) {
+ add_interface_flows(br->db_br->name, iface_rec,
+ ofport, &ofpacts);
+ }
+ }
+ }
+
+ ofpbuf_uninit(&ofpacts);
+}
+
+static void
+put_load(uint64_t value, enum mf_field_id dst, int ofs, int n_bits,
+ struct ofpbuf *ofpacts)
+{
+ struct ofpact_set_field *sf = ofpact_put_set_field(ofpacts,
+ mf_from_id(dst), NULL,
+ NULL);
+ ovs_be64 n_value = htonll(value);
+ bitwise_copy(&n_value, 8, 0, sf->value, sf->field->n_bytes, ofs, n_bits);
+ bitwise_one(ofpact_set_field_mask(sf), sf->field->n_bytes, ofs, n_bits);
+}
+
+static void
+put_resubmit(uint8_t table_id, struct ofpbuf *ofpacts)
+{
+ struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(ofpacts);
+ resubmit->in_port = OFPP_IN_PORT;
+ resubmit->table_id = table_id;
+}
+
+static void
+add_interface_flows(const char *bridge,
+ const struct ovsrec_interface *iface_rec,
+ int64_t ofport, struct ofpbuf *ofpacts_p)
+{
+ struct match match = MATCH_CATCHALL_INITIALIZER;
+ match_set_in_port(&match, u16_to_ofp(ofport));
+
+ ofpbuf_clear(ofpacts_p);
+ put_load(ofport, MFF_LOG_INPORT, 0, 32, ofpacts_p);
+
+ uint32_t iface_metadata =
+ smap_get_uint(&iface_rec->external_ids, "ovn-iface-metadata", 0);
+ if (iface_metadata) {
+ put_load(iface_metadata, MFF_METADATA, 0, 32, ofpacts_p);
+ }
+
+ put_resubmit(BR_OFTABLE_LOG_INGRESS_PIPELINE, ofpacts_p);
+ br_flow_add_physical_oflow(bridge, BR_OFTABLE_PHY_TO_LOG, 100,
+ iface_rec->header_.uuid.parts[0],
+ &match, ofpacts_p,
+ &iface_rec->header_.uuid);
+
+
+ match_init_catchall(&match);
+ match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, ofport);
+
+ ofpbuf_clear(ofpacts_p);
+ ofpact_put_OUTPUT(ofpacts_p)->port = u16_to_ofp(ofport);
+ br_flow_add_physical_oflow(bridge, BR_OFTABLE_LOG_TO_PHY, 100,
+ iface_rec->header_.uuid.parts[0],
+ &match, ofpacts_p,
+ &iface_rec->header_.uuid);
+}
diff --git a/br-controller/en-pflow.h b/br-controller/en-pflow.h
new file mode 100644
index 0000000000..85edf53c17
--- /dev/null
+++ b/br-controller/en-pflow.h
@@ -0,0 +1,16 @@
+#ifndef EN_PFLOW_H
+#define EN_PFLOW_H 1
+
+#include <config.h>
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "lib/inc-proc-eng.h"
+
+enum engine_node_state en_pflow_output_run(struct engine_node *, void *data);
+void *en_pflow_output_init(struct engine_node *node, struct engine_arg *arg);
+void en_pflow_output_cleanup(void *data);
+
+#endif /* EN_PFLOW_H */
diff --git a/br-controller/ovn-br-controller.8.xml
b/br-controller/ovn-br-controller.8.xml
index cfc88a8aae..6816ece8f7 100644
--- a/br-controller/ovn-br-controller.8.xml
+++ b/br-controller/ovn-br-controller.8.xml
@@ -48,4 +48,32 @@
</p>
</dd>
</dl>
+
+ <p>
+ <code>ovn-br-controller</code> reads the following values from the
+ <code>Open_vSwitch</code> database of the local OVS instance:
+ </p>
+
+ <dl>
+ <dt>
+ <code>external_ids:ovnbr-managed</code> from
+ <ref table="Interface" db="Open_vSwitch"/> table
+ </dt>
+ <dd>
+ <p>
+ If the value is <code>true</code>, then this interface is managed by
+ <code>ovn-br-controller</code> if this interface is connected to
+ the OVS bridge managed by <code>ovn-br-controller</code>.
+ </p>
+
+ <p>
+ Default value is true if this option is not defined.
+ </p>
+
+ <p>
+ CMS should set the value of this option to <code>false</code>
+ if it doesn't want <code>ovn-br-controller</code> to manage it.
+ </p>
+ </dd>
+ </dl>
</manpage>
diff --git a/br-controller/ovn-br-controller.c
b/br-controller/ovn-br-controller.c
index 7cfe6ac23d..ae0e192429 100644
--- a/br-controller/ovn-br-controller.c
+++ b/br-controller/ovn-br-controller.c
@@ -37,6 +37,7 @@
/* OVN includes. */
#include "en-bridge-data.h"
#include "en-lflow.h"
+#include "en-pflow.h"
#include "lib/ovn-br-idl.h"
#include "lib/inc-proc-eng.h"
#include "lib/ovn-util.h"
@@ -171,6 +172,7 @@ main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
/* Define inc-proc-engine nodes. */
ENGINE_NODE(bridge_data);
ENGINE_NODE(lflow_output);
+ ENGINE_NODE(pflow_output);
ENGINE_NODE(br_controller_output);
#define BRCTL_NODE(NAME) ENGINE_NODE_BR(NAME);
@@ -191,7 +193,11 @@ main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
engine_add_input(&en_lflow_output, &en_bridge_data, NULL);
engine_add_input(&en_lflow_output, &en_ovnbr_logical_flow, NULL);
+
+ engine_add_input(&en_pflow_output, &en_bridge_data, NULL);
+
engine_add_input(&en_br_controller_output, &en_lflow_output, NULL);
+ engine_add_input(&en_br_controller_output, &en_pflow_output, NULL);
struct engine_arg engine_arg = {
.ovs_idl = ovs_idl_loop.idl,
--
2.51.0
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev