[ovs-dev] [PATCH 1/3] OVN: introduce Controller_Event table
Lorenzo Bianconi
lorenzo.bianconi at redhat.com
Fri Jun 14 15:53:21 UTC 2019
Add Controller_Event table to OVN SBDB in order to
report CMS related event.
Introduce event_table hashmap array and controller_event related
structures to ovn-controller in order to track pending events
forwarded by ovs-vswitchd. Moreover integrate event_table hashmap
array with event_table ovn-sbdb table
Signed-off-by: Mark Michelson <mmichels at redhat.com>
Co-authored-by: Mark Michelson <mmichels at redhat.com>
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at redhat.com>
---
include/ovn/logical-fields.h | 26 ++++++
ovn/controller/ovn-controller.c | 10 ++
ovn/controller/pinctrl.c | 158 ++++++++++++++++++++++++++++++++
ovn/controller/pinctrl.h | 2 +
ovn/ovn-sb.ovsschema | 21 ++++-
ovn/ovn-sb.xml | 42 +++++++++
6 files changed, 256 insertions(+), 3 deletions(-)
diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h
index 164b338b5..edfff2456 100644
--- a/include/ovn/logical-fields.h
+++ b/include/ovn/logical-fields.h
@@ -20,6 +20,32 @@
struct shash;
+enum ovn_controller_event {
+ OVN_EVENT_EMPTY_LB_BACKENDS = 0,
+ OVN_EVENT_MAX,
+};
+
+static inline char *
+event_to_string(enum ovn_controller_event event)
+{
+ switch (event) {
+ case OVN_EVENT_EMPTY_LB_BACKENDS:
+ return "empty_lb_backends";
+ case OVN_EVENT_MAX:
+ default:
+ return "";
+ }
+}
+
+static inline int
+string_to_event(const char *s)
+{
+ if (!strcmp(s, "empty_lb_backends")) {
+ return OVN_EVENT_EMPTY_LB_BACKENDS;
+ }
+ return -1;
+}
+
/* Logical fields.
*
* These values are documented in ovn-architecture(7), please update the
diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c
index 60190161f..c2d96df0c 100644
--- a/ovn/controller/ovn-controller.c
+++ b/ovn/controller/ovn-controller.c
@@ -132,6 +132,8 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
* Monitor Logical_Flow, MAC_Binding, Multicast_Group, and DNS tables for
* local datapaths.
*
+ * Monitor Controller_Event rows for local chassis.
+ *
* We always monitor patch ports because they allow us to see the linkages
* between related logical datapaths. That way, when we know that we have
* a VIF on a particular logical switch, we immediately know to monitor all
@@ -141,6 +143,7 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
struct ovsdb_idl_condition mb = OVSDB_IDL_CONDITION_INIT(&mb);
struct ovsdb_idl_condition mg = OVSDB_IDL_CONDITION_INIT(&mg);
struct ovsdb_idl_condition dns = OVSDB_IDL_CONDITION_INIT(&dns);
+ struct ovsdb_idl_condition ce = OVSDB_IDL_CONDITION_INIT(&ce);
sbrec_port_binding_add_clause_type(&pb, OVSDB_F_EQ, "patch");
/* XXX: We can optimize this, if we find a way to only monitor
* ports that have a Gateway_Chassis that point's to our own
@@ -164,6 +167,9 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
sbrec_port_binding_add_clause_options(&pb, OVSDB_F_INCLUDES, &l2);
const struct smap l3 = SMAP_CONST1(&l3, "l3gateway-chassis", id);
sbrec_port_binding_add_clause_options(&pb, OVSDB_F_INCLUDES, &l3);
+
+ sbrec_controller_event_add_clause_chassis(&ce, OVSDB_F_EQ,
+ &chassis->header_.uuid);
}
if (local_ifaces) {
const char *name;
@@ -190,11 +196,13 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
sbrec_mac_binding_set_condition(ovnsb_idl, &mb);
sbrec_multicast_group_set_condition(ovnsb_idl, &mg);
sbrec_dns_set_condition(ovnsb_idl, &dns);
+ sbrec_controller_event_set_condition(ovnsb_idl, &ce);
ovsdb_idl_condition_destroy(&pb);
ovsdb_idl_condition_destroy(&lf);
ovsdb_idl_condition_destroy(&mb);
ovsdb_idl_condition_destroy(&mg);
ovsdb_idl_condition_destroy(&dns);
+ ovsdb_idl_condition_destroy(&ce);
}
static const char *
@@ -1943,6 +1951,8 @@ main(int argc, char *argv[])
sbrec_port_binding_by_name,
sbrec_mac_binding_by_lport_ip,
sbrec_dns_table_get(ovnsb_idl_loop.idl),
+ sbrec_controller_event_table_get(
+ ovnsb_idl_loop.idl),
br_int, chassis,
&ed_runtime_data.local_datapaths,
&ed_runtime_data.active_tunnels);
diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c
index a442738a0..6d0f962de 100644
--- a/ovn/controller/pinctrl.c
+++ b/ovn/controller/pinctrl.c
@@ -226,6 +226,160 @@ static bool may_inject_pkts(void);
COVERAGE_DEFINE(pinctrl_drop_put_mac_binding);
COVERAGE_DEFINE(pinctrl_drop_buffered_packets_map);
+COVERAGE_DEFINE(pinctrl_drop_controller_event);
+
+struct empty_lb_backends_event {
+ struct hmap_node hmap_node;
+ long long int timestamp;
+
+ char *vip;
+ char *protocol;
+ char *load_balancer;
+};
+
+static struct hmap event_table[OVN_EVENT_MAX];
+static int64_t event_seq_num;
+
+static void init_event_table(void)
+{
+ for (size_t i = 0; i < OVN_EVENT_MAX; i++) {
+ hmap_init(&event_table[i]);
+ }
+}
+
+#define EVENT_TIMEOUT 50000
+static void
+empty_lb_backends_event_gc(bool flush)
+{
+ struct empty_lb_backends_event *cur_ce, *next_ce;
+ long long int now = time_msec();
+
+ HMAP_FOR_EACH_SAFE (cur_ce, next_ce, hmap_node,
+ &event_table[OVN_EVENT_EMPTY_LB_BACKENDS]) {
+ if ((now < cur_ce->timestamp + EVENT_TIMEOUT) && !flush) {
+ continue;
+ }
+
+ free(cur_ce->vip);
+ free(cur_ce->protocol);
+ free(cur_ce->load_balancer);
+ hmap_remove(&event_table[OVN_EVENT_EMPTY_LB_BACKENDS],
+ &cur_ce->hmap_node);
+ free(cur_ce);
+ }
+}
+
+static void event_table_gc(bool flush)
+{
+ empty_lb_backends_event_gc(flush);
+}
+
+static void event_table_destroy(void)
+{
+ event_table_gc(true);
+ for (size_t i = 0; i < OVN_EVENT_MAX; i++) {
+ hmap_destroy(&event_table[i]);
+ }
+}
+
+static struct empty_lb_backends_event *
+pinctrl_find_empty_lb_backends_event(char *vip, char *protocol,
+ char *load_balancer, uint32_t hash)
+{
+ struct empty_lb_backends_event *ce;
+ HMAP_FOR_EACH_WITH_HASH (ce, hmap_node, hash,
+ &event_table[OVN_EVENT_EMPTY_LB_BACKENDS]) {
+ if (!strcmp(ce->vip, vip) &&
+ !strcmp(ce->protocol, protocol) &&
+ !strcmp(ce->load_balancer, load_balancer)) {
+ return ce;
+ }
+ }
+ return NULL;
+}
+
+static const struct sbrec_controller_event *
+empty_lb_backends_lookup(struct empty_lb_backends_event *event,
+ const struct sbrec_controller_event_table *ce_table,
+ const struct sbrec_chassis *chassis)
+{
+ const struct sbrec_controller_event *sbrec_event;
+ const char *event_type = event_to_string(OVN_EVENT_EMPTY_LB_BACKENDS);
+ char ref_uuid[UUID_LEN + 1];
+ sprintf(ref_uuid, UUID_FMT, UUID_ARGS(&chassis->header_.uuid));
+
+ SBREC_CONTROLLER_EVENT_TABLE_FOR_EACH (sbrec_event, ce_table) {
+ if (strcmp(sbrec_event->event_type, event_type)) {
+ continue;
+ }
+
+ char chassis_uuid[UUID_LEN + 1];
+ sprintf(chassis_uuid, UUID_FMT,
+ UUID_ARGS(&sbrec_event->chassis->header_.uuid));
+ if (strcmp(ref_uuid, chassis_uuid)) {
+ continue;
+ }
+
+ const char *vip = smap_get(&sbrec_event->event_info, "vip");
+ const char *protocol = smap_get(&sbrec_event->event_info, "protocol");
+ const char *load_balancer = smap_get(&sbrec_event->event_info,
+ "load_balancer");
+
+ if (!strcmp(event->vip, vip) &&
+ !strcmp(event->protocol, protocol) &&
+ !strcmp(event->load_balancer, load_balancer)) {
+ return sbrec_event;
+ }
+ }
+
+ return NULL;
+}
+
+static void
+controller_event_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
+ const struct sbrec_controller_event_table *ce_table,
+ const struct sbrec_chassis *chassis)
+ OVS_REQUIRES(pinctrl_mutex)
+{
+ if (!ovnsb_idl_txn) {
+ goto out;
+ }
+
+ struct empty_lb_backends_event *empty_lbs;
+ HMAP_FOR_EACH (empty_lbs, hmap_node,
+ &event_table[OVN_EVENT_EMPTY_LB_BACKENDS]) {
+ const struct sbrec_controller_event *event;
+
+ event = empty_lb_backends_lookup(empty_lbs, ce_table, chassis);
+ if (!event) {
+ struct smap event_info = SMAP_INITIALIZER(&event_info);
+
+ smap_add(&event_info, "vip", empty_lbs->vip);
+ smap_add(&event_info, "protocol", empty_lbs->protocol);
+ smap_add(&event_info, "load_balancer", empty_lbs->load_balancer);
+
+ event = sbrec_controller_event_insert(ovnsb_idl_txn);
+ sbrec_controller_event_set_event_type(event,
+ event_to_string(OVN_EVENT_EMPTY_LB_BACKENDS));
+ sbrec_controller_event_set_seq_num(event, ++event_seq_num);
+ sbrec_controller_event_set_event_info(event, &event_info);
+ sbrec_controller_event_set_handled(event, false);
+ sbrec_controller_event_set_chassis(event, chassis);
+ }
+ }
+
+ const struct sbrec_controller_event *cur_event, *next_event;
+ /* flush 'handled' rows */
+ SBREC_CONTROLLER_EVENT_TABLE_FOR_EACH_SAFE (cur_event, next_event,
+ ce_table) {
+ if (cur_event->handled) {
+ sbrec_controller_event_delete(cur_event);
+ }
+ }
+
+out:
+ event_table_gc(!!ovnsb_idl_txn);
+}
void
pinctrl_init(void)
@@ -234,6 +388,7 @@ pinctrl_init(void)
init_send_garps();
init_ipv6_ras();
init_buffered_packets_map();
+ init_event_table();
pinctrl.br_int_name = NULL;
pinctrl_handler_seq = seq_create();
pinctrl_main_seq = seq_create();
@@ -1897,6 +2052,7 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
struct ovsdb_idl_index *sbrec_port_binding_by_name,
struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
const struct sbrec_dns_table *dns_table,
+ const struct sbrec_controller_event_table *ce_table,
const struct ovsrec_bridge *br_int,
const struct sbrec_chassis *chassis,
const struct hmap *local_datapaths,
@@ -1922,6 +2078,7 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
prepare_ipv6_ras(sbrec_port_binding_by_datapath,
sbrec_port_binding_by_name, local_datapaths);
sync_dns_cache(dns_table);
+ controller_event_run(ovnsb_idl_txn, ce_table, chassis);
run_buffered_binding(sbrec_port_binding_by_datapath,
sbrec_mac_binding_by_lport_ip,
local_datapaths);
@@ -2270,6 +2427,7 @@ pinctrl_destroy(void)
destroy_send_garps();
destroy_ipv6_ras();
destroy_buffered_packets_map();
+ event_table_destroy();
destroy_put_mac_bindings();
destroy_dns_cache();
seq_destroy(pinctrl_main_seq);
diff --git a/ovn/controller/pinctrl.h b/ovn/controller/pinctrl.h
index f61d7056e..fdef27a6d 100644
--- a/ovn/controller/pinctrl.h
+++ b/ovn/controller/pinctrl.h
@@ -29,6 +29,7 @@ struct ovsdb_idl_txn;
struct ovsrec_bridge;
struct sbrec_chassis;
struct sbrec_dns_table;
+struct sbrec_controller_event_table;
void pinctrl_init(void);
void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
@@ -38,6 +39,7 @@ void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
struct ovsdb_idl_index *sbrec_port_binding_by_name,
struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
const struct sbrec_dns_table *,
+ const struct sbrec_controller_event_table *,
const struct ovsrec_bridge *, const struct sbrec_chassis *,
const struct hmap *local_datapaths,
const struct sset *active_tunnels);
diff --git a/ovn/ovn-sb.ovsschema b/ovn/ovn-sb.ovsschema
index 2b543c6f5..1699808b2 100644
--- a/ovn/ovn-sb.ovsschema
+++ b/ovn/ovn-sb.ovsschema
@@ -1,7 +1,7 @@
{
"name": "OVN_Southbound",
- "version": "2.3.0",
- "cksum": "3092285199 17409",
+ "version": "2.4.0",
+ "cksum": "282590218 18154",
"tables": {
"SB_Global": {
"columns": {
@@ -349,4 +349,19 @@
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"indexes": [["name"]],
- "isRoot": true}}}
+ "isRoot": true},
+ "Controller_Event": {
+ "columns": {
+ "event_type": {"type": {"key": {"type": "string",
+ "enum": ["set", ["empty_lb_backends"]]}}},
+ "event_info": {"type": {"key": "string", "value": "string",
+ "min": 0, "max": "unlimited"}},
+ "chassis": {"type": {"key": {"type": "uuid",
+ "refTable": "Chassis",
+ "refType": "weak"},
+ "min": 0, "max": 1}},
+ "seq_num": {"type": {"key": "integer"}},
+ "handled": {"type": "boolean"}
+ },
+ "isRoot": true
+ }}}
diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml
index 1a2bc1da9..d5f78829e 100644
--- a/ovn/ovn-sb.xml
+++ b/ovn/ovn-sb.xml
@@ -3474,4 +3474,46 @@ tcp.flags = RST;
</column>
</group>
</table>
+ <table name="Controller_Event" title="Controller Event table">
+ <p>
+ Database table used by <code>ovn-controller</code> to report CMS
+ related events. Please note there is no guarantee a given event is
+ written exactly once in the db. It is CMS responsability to squash
+ duplicated lines or to filter out duplicated events
+ </p>
+ <column name="event_type"
+ type='{"type": "string", "enum": ["set", ["empty_lb_backends"]]}'>
+ Event type occurred
+ </column>
+ <column name="event_info">
+ <p>
+ Key-value pairs used to specify event info to the CMS.
+ Possible values are:
+ </p>
+ <ul>
+ <li>
+ <code>vip</code>: VIP reported for the <code>empty_lb_backends</code>
+ event
+ </li>
+ <li>
+ <code>protocol</code>: Transport protocol reported for the
+ <code>empty_lb_backends</code> event
+ </li>
+ <li>
+ <code>load_balancer</code>: UUID of the load balancer reported for
+ the <code>empty_lb_backends</code> event
+ </li>
+ </ul>
+ </column>
+ <column name="chassis">
+ This column is a a <ref table="Chassis"/> record to identify the chassis
+ that has managed a given event.
+ </column>
+ <column name="seq_num" type='{"type": "integer"}'>
+ Event sequence number. It is used to detect possible event duplicantion
+ </column>
+ <column name="handled" type='{"type": "boolean"}'>
+ Value used to indicate if the event has been consumed by the CMS
+ </column>
+ </table>
</database>
--
2.21.0
More information about the dev
mailing list