From: Numan Siddique <[email protected]> This patch - Adds a new table 'FDB' in Southbound database. - Adds a new pinctrl_handler action - ACTION_OPCODE_PUT_FDB which learns the port-to-mac bindings and stores it in the 'FDB' table. This handler will be used later. - Upcoming patch adds necessary OVN actions to learn the port-to-mac bindings.
Unlike MAC_Binding Southbound table, FDB table stores the datapath tunnel key and port key. This makes it easier for ovn-controller to program the OF rules and it doesn't need to do any logical port lookup in the Port_Binding table. Signed-off-by: Numan Siddique <[email protected]> --- controller/mac-learn.c | 79 ++++++++++++++++++++++++ controller/mac-learn.h | 20 ++++++ controller/ovn-controller.c | 5 ++ controller/pinctrl.c | 118 ++++++++++++++++++++++++++++++++++++ controller/pinctrl.h | 1 + include/ovn/actions.h | 4 ++ ovn-sb.ovsschema | 17 +++++- ovn-sb.xml | 24 ++++++++ 8 files changed, 266 insertions(+), 2 deletions(-) diff --git a/controller/mac-learn.c b/controller/mac-learn.c index 36a6d6e589..27634dca8b 100644 --- a/controller/mac-learn.c +++ b/controller/mac-learn.c @@ -19,11 +19,13 @@ /* OpenvSwitch lib includes. */ #include "openvswitch/vlog.h" +#include "lib/packets.h" #include "lib/smap.h" VLOG_DEFINE_THIS_MODULE(mac_learn); #define MAX_MAC_BINDINGS 1000 +#define MAX_FDB_ENTRIES 1000 static size_t mac_binding_hash(uint32_t dp_key, uint32_t port_key, struct in6_addr *); @@ -31,7 +33,12 @@ static struct mac_binding *mac_binding_find(struct hmap *mac_bindings, uint32_t dp_key, uint32_t port_key, struct in6_addr *ip, size_t hash); +static size_t fdb_entry_hash(uint32_t dp_key, struct eth_addr *); +static struct fdb_entry *fdb_entry_find(struct hmap *fdbs, uint32_t dp_key, + struct eth_addr *mac, size_t hash); + +/* mac_binding functions. */ void ovn_mac_bindings_init(struct hmap *mac_bindings) { @@ -79,6 +86,55 @@ ovn_mac_binding_add(struct hmap *mac_bindings, uint32_t dp_key, return mb; } +/* fdb functions. */ +void +ovn_fdb_init(struct hmap *fdbs) +{ + hmap_init(fdbs); +} + +void +ovn_fdbs_flush(struct hmap *fdbs) +{ + struct fdb_entry *fdb_e; + HMAP_FOR_EACH_POP (fdb_e, hmap_node, fdbs) { + free(fdb_e); + } +} + +void +ovn_fdbs_destroy(struct hmap *fdbs) +{ + ovn_fdbs_flush(fdbs); + hmap_destroy(fdbs); +} + +struct fdb_entry * +ovn_fdb_add(struct hmap *fdbs, uint32_t dp_key, struct eth_addr mac, + uint32_t port_key) +{ + uint32_t hash = fdb_entry_hash(dp_key, &mac); + + struct fdb_entry *fdb_e = + fdb_entry_find(fdbs, dp_key, &mac, hash); + if (!fdb_e) { + if (hmap_count(fdbs) >= MAX_FDB_ENTRIES) { + return NULL; + } + + fdb_e = xzalloc(sizeof *fdb_e); + fdb_e->dp_key = dp_key; + fdb_e->mac = mac; + hmap_insert(fdbs, &fdb_e->hmap_node, hash); + } + fdb_e->port_key = port_key; + + return fdb_e; + +} + +/* mac_binding related static functions. */ + static size_t mac_binding_hash(uint32_t dp_key, uint32_t port_key, struct in6_addr *ip) { @@ -99,3 +155,26 @@ mac_binding_find(struct hmap *mac_bindings, uint32_t dp_key, return NULL; } + +/* fdb related static functions. */ + +static size_t +fdb_entry_hash(uint32_t dp_key, struct eth_addr *mac) +{ + uint64_t mac64 = eth_addr_to_uint64(*mac); + return hash_2words(dp_key, hash_uint64(mac64)); +} + +static struct fdb_entry * +fdb_entry_find(struct hmap *fdbs, uint32_t dp_key, + struct eth_addr *mac, size_t hash) +{ + struct fdb_entry *fdb_e; + HMAP_FOR_EACH_WITH_HASH (fdb_e, hmap_node, hash, fdbs) { + if (fdb_e->dp_key == dp_key && eth_addr_equals(fdb_e->mac, *mac)) { + return fdb_e; + } + } + + return NULL; +} diff --git a/controller/mac-learn.h b/controller/mac-learn.h index 3a8520c360..7a7897e4db 100644 --- a/controller/mac-learn.h +++ b/controller/mac-learn.h @@ -43,4 +43,24 @@ struct mac_binding *ovn_mac_binding_add(struct hmap *mac_bindings, struct eth_addr mac); + +struct fdb_entry { + struct hmap_node hmap_node; /* In a hmap. */ + + /* Key. */ + uint32_t dp_key; + struct eth_addr mac; + + /* value. */ + uint32_t port_key; +}; + +void ovn_fdb_init(struct hmap *fdbs); +void ovn_fdbs_flush(struct hmap *fdbs); +void ovn_fdbs_destroy(struct hmap *fdbs); + +struct fdb_entry *ovn_fdb_add(struct hmap *fdbs, + uint32_t dp_key, struct eth_addr mac, + uint32_t port_key); + #endif /* OVN_MAC_LEARN_H */ \ No newline at end of file diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index ef3e0e95ea..42858d60fa 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -2462,6 +2462,10 @@ main(int argc, char *argv[]) = ip_mcast_index_create(ovnsb_idl_loop.idl); struct ovsdb_idl_index *sbrec_igmp_group = igmp_group_index_create(ovnsb_idl_loop.idl); + struct ovsdb_idl_index *sbrec_fdb_by_dp_key_mac + = ovsdb_idl_index_create2(ovnsb_idl_loop.idl, + &sbrec_fdb_col_mac, + &sbrec_fdb_col_dp_key); ovsdb_idl_track_add_all(ovnsb_idl_loop.idl); ovsdb_idl_omit_alert(ovnsb_idl_loop.idl, @@ -2864,6 +2868,7 @@ main(int argc, char *argv[]) sbrec_mac_binding_by_lport_ip, sbrec_igmp_group, sbrec_ip_multicast, + sbrec_fdb_by_dp_key_mac, sbrec_dns_table_get(ovnsb_idl_loop.idl), sbrec_controller_event_table_get( ovnsb_idl_loop.idl), diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 723d2a6522..116ab65334 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -340,6 +340,22 @@ static void bfd_monitor_run(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct sbrec_chassis *chassis, const struct sset *active_tunnels) OVS_REQUIRES(pinctrl_mutex); +static void init_fdb_entries(void); +static void destroy_fdb_entries(void); +static const struct sbrec_fdb *fdb_lookup( + struct ovsdb_idl_index *sbrec_fdb_by_dp_key_mac, + uint32_t dp_key, const char *mac); +static void run_put_fdb(struct ovsdb_idl_txn *ovnsb_idl_txn, + struct ovsdb_idl_index *sbrec_fdb_by_dp_key_mac, + const struct fdb_entry *fdb_e) + OVS_REQUIRES(pinctrl_mutex); +static void run_put_fdbs(struct ovsdb_idl_txn *ovnsb_idl_txn, + struct ovsdb_idl_index *sbrec_fdb_by_dp_key_mac) + OVS_REQUIRES(pinctrl_mutex); +static void wait_put_fdbs(struct ovsdb_idl_txn *ovnsb_idl_txn); +static void pinctrl_handle_put_fdb(const struct flow *md, + const struct flow *headers) + OVS_REQUIRES(pinctrl_mutex); COVERAGE_DEFINE(pinctrl_drop_put_mac_binding); COVERAGE_DEFINE(pinctrl_drop_buffered_packets_map); @@ -506,6 +522,7 @@ pinctrl_init(void) init_put_vport_bindings(); init_svc_monitors(); bfd_monitor_init(); + init_fdb_entries(); pinctrl.br_int_name = NULL; pinctrl_handler_seq = seq_create(); pinctrl_main_seq = seq_create(); @@ -3020,6 +3037,12 @@ process_packet_in(struct rconn *swconn, const struct ofp_header *msg) ovs_mutex_unlock(&pinctrl_mutex); break; + case ACTION_OPCODE_PUT_FDB: + ovs_mutex_lock(&pinctrl_mutex); + pinctrl_handle_put_fdb(&pin.flow_metadata.flow, &headers); + ovs_mutex_unlock(&pinctrl_mutex); + break; + case ACTION_OPCODE_PUT_DHCPV6_OPTS: pinctrl_handle_put_dhcpv6_opts(swconn, &packet, &pin, &userdata, &continuation); @@ -3297,6 +3320,7 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip, struct ovsdb_idl_index *sbrec_igmp_groups, struct ovsdb_idl_index *sbrec_ip_multicast_opts, + struct ovsdb_idl_index *sbrec_fdb_by_dp_key_mac, const struct sbrec_dns_table *dns_table, const struct sbrec_controller_event_table *ce_table, const struct sbrec_service_monitor_table *svc_mon_table, @@ -3333,6 +3357,7 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, chassis); bfd_monitor_run(ovnsb_idl_txn, bfd_table, sbrec_port_binding_by_name, chassis, active_tunnels); + run_put_fdbs(ovnsb_idl_txn, sbrec_fdb_by_dp_key_mac); ovs_mutex_unlock(&pinctrl_mutex); } @@ -3856,6 +3881,7 @@ pinctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn) wait_put_vport_bindings(ovnsb_idl_txn); int64_t new_seq = seq_read(pinctrl_main_seq); seq_wait(pinctrl_main_seq, new_seq); + wait_put_fdbs(ovnsb_idl_txn); } /* Called by ovn-controller. */ @@ -3877,6 +3903,7 @@ pinctrl_destroy(void) ip_mcast_snoop_destroy(); destroy_svc_monitors(); bfd_monitor_destroy(); + destroy_fdb_entries(); seq_destroy(pinctrl_main_seq); seq_destroy(pinctrl_handler_seq); } @@ -7530,3 +7557,94 @@ pinctrl_handle_svc_check(struct rconn *swconn, const struct flow *ip_flow, svc_mon->next_send_time = time_msec() + svc_mon->interval; } } + +static struct hmap put_fdbs; + +/* MAC learning (fdb) related functions. Runs within the main + * ovn-controller thread context. */ + +static void +init_fdb_entries(void) +{ + ovn_fdb_init(&put_fdbs); +} + +static void +destroy_fdb_entries(void) +{ + ovn_fdbs_destroy(&put_fdbs); +} + +static const struct sbrec_fdb * +fdb_lookup(struct ovsdb_idl_index *sbrec_fdb_by_dp_key_mac, uint32_t dp_key, + const char *mac) +{ + struct sbrec_fdb *fdb = sbrec_fdb_index_init_row(sbrec_fdb_by_dp_key_mac); + sbrec_fdb_index_set_dp_key(fdb, dp_key); + sbrec_fdb_index_set_mac(fdb, mac); + + const struct sbrec_fdb *retval + = sbrec_fdb_index_find(sbrec_fdb_by_dp_key_mac, fdb); + + sbrec_fdb_index_destroy_row(fdb); + + return retval; +} + +static void +run_put_fdb(struct ovsdb_idl_txn *ovnsb_idl_txn, + struct ovsdb_idl_index *sbrec_fdb_by_dp_key_mac, + const struct fdb_entry *fdb_e) +{ + /* Convert ethernet argument to string form for database. */ + char mac_string[ETH_ADDR_STRLEN + 1]; + snprintf(mac_string, sizeof mac_string, + ETH_ADDR_FMT, ETH_ADDR_ARGS(fdb_e->mac)); + + /* Update or add an FDB entry. */ + const struct sbrec_fdb *sb_fdb = + fdb_lookup(sbrec_fdb_by_dp_key_mac, fdb_e->dp_key, mac_string); + if (!sb_fdb) { + sb_fdb = sbrec_fdb_insert(ovnsb_idl_txn); + sbrec_fdb_set_dp_key(sb_fdb, fdb_e->dp_key); + sbrec_fdb_set_mac(sb_fdb, mac_string); + } + sbrec_fdb_set_port_key(sb_fdb, fdb_e->port_key); +} + +static void +run_put_fdbs(struct ovsdb_idl_txn *ovnsb_idl_txn, + struct ovsdb_idl_index *sbrec_fdb_by_dp_key_mac) + OVS_REQUIRES(pinctrl_mutex) +{ + if (!ovnsb_idl_txn) { + return; + } + + const struct fdb_entry *fdb_e; + HMAP_FOR_EACH (fdb_e, hmap_node, &put_fdbs) { + run_put_fdb(ovnsb_idl_txn, sbrec_fdb_by_dp_key_mac, fdb_e); + } + ovn_fdbs_flush(&put_fdbs); +} + + +static void +wait_put_fdbs(struct ovsdb_idl_txn *ovnsb_idl_txn) +{ + if (ovnsb_idl_txn && !hmap_is_empty(&put_fdbs)) { + poll_immediate_wake(); + } +} + +/* Called with in the pinctrl_handler thread context. */ +static void +pinctrl_handle_put_fdb(const struct flow *md, const struct flow *headers) + OVS_REQUIRES(pinctrl_mutex) +{ + uint32_t dp_key = ntohll(md->metadata); + uint32_t port_key = md->regs[MFF_LOG_INPORT - MFF_REG0]; + + ovn_fdb_add(&put_fdbs, dp_key, headers->dl_src, port_key); + notify_pinctrl_main(); +} diff --git a/controller/pinctrl.h b/controller/pinctrl.h index 8555d983db..cc0a51984a 100644 --- a/controller/pinctrl.h +++ b/controller/pinctrl.h @@ -42,6 +42,7 @@ void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip, struct ovsdb_idl_index *sbrec_igmp_groups, struct ovsdb_idl_index *sbrec_ip_multicast_opts, + struct ovsdb_idl_index *sbrec_fdb_by_dp_key_mac, const struct sbrec_dns_table *, const struct sbrec_controller_event_table *, const struct sbrec_service_monitor_table *, diff --git a/include/ovn/actions.h b/include/ovn/actions.h index be87e61352..a2d28c6a3f 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -641,6 +641,10 @@ enum action_opcode { * The actions, in OpenFlow 1.3 format, follow the action_header. */ ACTION_OPCODE_SCTP_ABORT, + + /* put_fdb(inport, eth.src). + */ + ACTION_OPCODE_PUT_FDB, }; /* Header. */ diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema index 0d20f08266..246e3908a0 100644 --- a/ovn-sb.ovsschema +++ b/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", - "version": "20.15.0", - "cksum": "539683023 25965", + "version": "20.16.0", + "cksum": "1219580357 26536", "tables": { "SB_Global": { "columns": { @@ -513,6 +513,19 @@ "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, "indexes": [["logical_port", "dst_ip", "src_port", "disc"]], + "isRoot": true}, + "FDB": { + "columns": { + "mac": {"type": "string"}, + "dp_key": { + "type": {"key": {"type": "integer", + "minInteger": 1, + "maxInteger": 16777215}}}, + "port_key": { + "type": {"key": {"type": "integer", + "minInteger": 1, + "maxInteger": 16777215}}}}, + "indexes": [["mac", "dp_key"]], "isRoot": true} } } diff --git a/ovn-sb.xml b/ovn-sb.xml index 2f251bd5c2..b8912b33c8 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -4330,4 +4330,28 @@ tcp.flags = RST; </column> </group> </table> + + <table name="FDB" title="Port to MAC bindings"> + <p> + This table is primarily used to learn the MACs observed on a VIF + which belongs to a <code>Logical_Switch_Port</code> record in + <code>OVN_Northbound</code> whose port security is disabled + and 'unknown' address set. If port security is disabled on a + <code>Logical_Switch_Port</code> record, OVN should allow traffic + with any source mac from the VIF. This table will be used to deliver + a packet to the VIF, If a packet's <code>eth.dst</code> is learnt. + </p> + + <column name="mac"> + The learnt mac address. + </column> + + <column name="dp_key"> + The key of the datapath on which this FDB was learnt. + </column> + + <column name="port_key"> + The key of the port binding on which this FDB was learnt. + </column> + </table> </database> -- 2.29.2 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
