[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