[ovs-dev] [PATCH ovn 4/6] controller: MAC learning: Add OF rules for the FDB entries.
numans at ovn.org
numans at ovn.org
Fri Feb 5 07:00:04 UTC 2021
From: Numan Siddique <numans at ovn.org>
This patch adds the OF rules in table 71 and 72 to support
'get_fdb' and 'lookup_fdb' actions.
Signed-off-by: Numan Siddique <numans at ovn.org>
---
controller/lflow.c | 103 ++++++++++++++++++++++++++++++++++++
controller/lflow.h | 2 +
controller/ovn-controller.c | 27 +++++++++-
3 files changed, 131 insertions(+), 1 deletion(-)
diff --git a/controller/lflow.c b/controller/lflow.c
index baf6932d51..6c74fe9c85 100644
--- a/controller/lflow.c
+++ b/controller/lflow.c
@@ -1080,6 +1080,18 @@ put_load(const uint8_t *data, size_t len,
bitwise_one(ofpact_set_field_mask(sf), sf->field->n_bytes, ofs, n_bits);
}
+static void
+put_load64(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
consider_neighbor_flow(struct ovsdb_idl_index *sbrec_port_binding_by_name,
const struct hmap *local_datapaths,
@@ -1419,6 +1431,61 @@ lflow_handle_changed_neighbors(
}
}
+static void
+consider_fdb_flows(const struct sbrec_fdb *fdb,
+ const struct hmap *local_datapaths,
+ struct ovn_desired_flow_table *flow_table)
+{
+ if (!get_local_datapath(local_datapaths, fdb->dp_key)) {
+ return;
+ }
+
+ struct eth_addr mac;
+ if (!eth_addr_from_string(fdb->mac, &mac)) {
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
+ VLOG_WARN_RL(&rl, "bad 'mac' %s", fdb->mac);
+ return;
+ }
+
+ struct match match = MATCH_CATCHALL_INITIALIZER;
+ match_set_metadata(&match, htonll(fdb->dp_key));
+ match_set_dl_dst(&match, mac);
+
+ uint64_t stub[1024 / 8];
+ struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub);
+ put_load64(fdb->port_key, MFF_LOG_OUTPORT, 0, 32, &ofpacts);
+ ofctrl_add_flow(flow_table, OFTABLE_GET_FDB, 100,
+ fdb->header_.uuid.parts[0], &match, &ofpacts,
+ &fdb->header_.uuid);
+ ofpbuf_clear(&ofpacts);
+
+ uint8_t value = 1;
+ put_load(&value, sizeof value, MFF_LOG_FLAGS,
+ MLF_LOOKUP_FDB_BIT, 1, &ofpacts);
+
+ struct match lookup_match = MATCH_CATCHALL_INITIALIZER;
+ match_set_metadata(&lookup_match, htonll(fdb->dp_key));
+ match_set_dl_src(&lookup_match, mac);
+ match_set_reg(&lookup_match, MFF_LOG_INPORT - MFF_REG0, fdb->port_key);
+ ofctrl_add_flow(flow_table, OFTABLE_LOOKUP_FDB, 100,
+ fdb->header_.uuid.parts[0], &lookup_match, &ofpacts,
+ &fdb->header_.uuid);
+ ofpbuf_uninit(&ofpacts);
+}
+
+/* Adds an OpenFlow flow to flow tables for each MAC binding in the OVN
+ * southbound database. */
+static void
+add_fdb_flows(const struct sbrec_fdb_table *fdb_table,
+ const struct hmap *local_datapaths,
+ struct ovn_desired_flow_table *flow_table)
+{
+ const struct sbrec_fdb *fdb;
+ SBREC_FDB_TABLE_FOR_EACH (fdb, fdb_table) {
+ consider_fdb_flows(fdb, local_datapaths, flow_table);
+ }
+}
+
/* Translates logical flows in the Logical_Flow table in the OVN_SB database
* into OpenFlow flows. See ovn-architecture(7) for more information. */
@@ -1446,6 +1513,8 @@ lflow_run(struct lflow_ctx_in *l_ctx_in, struct lflow_ctx_out *l_ctx_out)
l_ctx_out->flow_table);
add_lb_hairpin_flows(l_ctx_in->lb_table, l_ctx_in->local_datapaths,
l_ctx_out->flow_table);
+ add_fdb_flows(l_ctx_in->fdb_table, l_ctx_in->local_datapaths,
+ l_ctx_out->flow_table);
}
void
@@ -1597,3 +1666,37 @@ lflow_handle_changed_lbs(struct lflow_ctx_in *l_ctx_in,
return true;
}
+
+bool
+lflow_handle_changed_fdbs(struct lflow_ctx_in *l_ctx_in,
+ struct lflow_ctx_out *l_ctx_out)
+{
+ const struct sbrec_fdb *fdb;
+
+ SBREC_FDB_TABLE_FOR_EACH_TRACKED (fdb, l_ctx_in->fdb_table) {
+ if (sbrec_fdb_is_deleted(fdb)) {
+ VLOG_DBG("Remove fdb flows for deleted fdb "UUID_FMT,
+ UUID_ARGS(&fdb->header_.uuid));
+ ofctrl_remove_flows(l_ctx_out->flow_table, &fdb->header_.uuid);
+ }
+ }
+
+ SBREC_FDB_TABLE_FOR_EACH_TRACKED (fdb, l_ctx_in->fdb_table) {
+ if (sbrec_fdb_is_deleted(fdb)) {
+ continue;
+ }
+
+ if (!sbrec_fdb_is_new(fdb)) {
+ VLOG_DBG("Remove fdb flows for updated fdb "UUID_FMT,
+ UUID_ARGS(&fdb->header_.uuid));
+ ofctrl_remove_flows(l_ctx_out->flow_table, &fdb->header_.uuid);
+ }
+
+ VLOG_DBG("Add fdb flows for fdb "UUID_FMT,
+ UUID_ARGS(&fdb->header_.uuid));
+ consider_fdb_flows(fdb, l_ctx_in->local_datapaths,
+ l_ctx_out->flow_table);
+ }
+
+ return true;
+}
diff --git a/controller/lflow.h b/controller/lflow.h
index d790d518d8..9f8bed4938 100644
--- a/controller/lflow.h
+++ b/controller/lflow.h
@@ -138,6 +138,7 @@ struct lflow_ctx_in {
const struct sbrec_logical_flow_table *logical_flow_table;
const struct sbrec_logical_dp_group_table *logical_dp_group_table;
const struct sbrec_multicast_group_table *mc_group_table;
+ const struct sbrec_fdb_table *fdb_table;
const struct sbrec_chassis *chassis;
const struct sbrec_load_balancer_table *lb_table;
const struct hmap *local_datapaths;
@@ -169,6 +170,7 @@ void lflow_handle_changed_neighbors(
const struct hmap *local_datapaths,
struct ovn_desired_flow_table *);
bool lflow_handle_changed_lbs(struct lflow_ctx_in *, struct lflow_ctx_out *);
+bool lflow_handle_changed_fdbs(struct lflow_ctx_in *, struct lflow_ctx_out *);
void lflow_destroy(void);
void lflow_cache_init(struct hmap *);
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index 42858d60fa..32f3f69324 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -923,7 +923,8 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl)
SB_NODE(dhcp_options, "dhcp_options") \
SB_NODE(dhcpv6_options, "dhcpv6_options") \
SB_NODE(dns, "dns") \
- SB_NODE(load_balancer, "load_balancer")
+ SB_NODE(load_balancer, "load_balancer") \
+ SB_NODE(fdb, "fdb")
enum sb_engine_node {
#define SB_NODE(NAME, NAME_STR) SB_##NAME,
@@ -1854,6 +1855,10 @@ static void init_lflow_ctx(struct engine_node *node,
(struct sbrec_load_balancer_table *)EN_OVSDB_GET(
engine_get_input("SB_load_balancer", node));
+ struct sbrec_fdb_table *fdb_table =
+ (struct sbrec_fdb_table *)EN_OVSDB_GET(
+ engine_get_input("SB_fdb", node));
+
struct ovsrec_open_vswitch_table *ovs_table =
(struct ovsrec_open_vswitch_table *)EN_OVSDB_GET(
engine_get_input("OVS_open_vswitch", node));
@@ -1891,6 +1896,7 @@ static void init_lflow_ctx(struct engine_node *node,
l_ctx_in->logical_flow_table = logical_flow_table;
l_ctx_in->logical_dp_group_table = logical_dp_group_table;
l_ctx_in->mc_group_table = multicast_group_table;
+ l_ctx_in->fdb_table = fdb_table,
l_ctx_in->chassis = chassis;
l_ctx_in->lb_table = lb_table;
l_ctx_in->local_datapaths = &rt_data->local_datapaths;
@@ -2331,6 +2337,23 @@ flow_output_sb_load_balancer_handler(struct engine_node *node, void *data)
return handled;
}
+static bool
+flow_output_sb_fdb_handler(struct engine_node *node, void *data)
+{
+ struct ed_type_runtime_data *rt_data =
+ engine_get_input_data("runtime_data", node);
+
+ struct ed_type_flow_output *fo = data;
+ struct lflow_ctx_in l_ctx_in;
+ struct lflow_ctx_out l_ctx_out;
+ init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
+
+ bool handled = lflow_handle_changed_fdbs(&l_ctx_in, &l_ctx_out);
+
+ engine_set_node_state(node, EN_UPDATED);
+ return handled;
+}
+
struct ovn_controller_exit_args {
bool *exiting;
bool *restart;
@@ -2592,6 +2615,8 @@ main(int argc, char *argv[])
engine_add_input(&en_flow_output, &en_sb_dns, NULL);
engine_add_input(&en_flow_output, &en_sb_load_balancer,
flow_output_sb_load_balancer_handler);
+ engine_add_input(&en_flow_output, &en_sb_fdb,
+ flow_output_sb_fdb_handler);
engine_add_input(&en_ct_zones, &en_ovs_open_vswitch, NULL);
engine_add_input(&en_ct_zones, &en_ovs_bridge, NULL);
--
2.29.2
More information about the dev
mailing list