Add logic to process logical switch port health checks in northd.

Signed-off-by: Alexandra Rukomoinikova <[email protected]>
---
 v2 --> v3: fixed Dumitru's comments
            split port_addresses_contains_ip func into two separate check for 
IPv4/6
---
 lib/ovn-util.c                   |  56 +++++++++
 lib/ovn-util.h                   |   4 +
 northd/en-northd.c               |   2 +
 northd/inc-proc-northd.c         |   5 +-
 northd/northd.c                  | 187 +++++++++++++++++++++++++++----
 northd/northd.h                  |   3 +
 tests/ovn-inc-proc-graph-dump.at |   2 +
 tests/ovn-northd.at              |  90 +++++++++++++++
 8 files changed, 324 insertions(+), 25 deletions(-)

diff --git a/lib/ovn-util.c b/lib/ovn-util.c
index f34c37a79..e743e41e7 100644
--- a/lib/ovn-util.c
+++ b/lib/ovn-util.c
@@ -521,6 +521,62 @@ find_lport_address(const struct lport_addresses *laddrs, 
const char *ip_s)
     return NULL;
 }
 
+static bool
+contains_ipv4_address(const struct lport_addresses *lsp_addrs,
+                      unsigned int n_lsp_addrs, ovs_be32 ip4)
+{
+    for (unsigned int i = 0; i < n_lsp_addrs; i++) {
+        const struct lport_addresses *laddrs = &lsp_addrs[i];
+        const size_t n = laddrs->n_ipv4_addrs;
+
+        for (size_t j = 0; j < n; j++) {
+            if (laddrs->ipv4_addrs[j].addr == ip4) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+static bool
+contains_ipv6_address(const struct lport_addresses *lsp_addrs,
+                      unsigned int n_lsp_addrs,
+                      const struct in6_addr *ip6)
+{
+    for (unsigned int i = 0; i < n_lsp_addrs; i++) {
+        const struct lport_addresses *laddrs = &lsp_addrs[i];
+        const size_t n = laddrs->n_ipv6_addrs;
+
+        for (size_t j = 0; j < n; j++) {
+            if (IN6_ARE_ADDR_EQUAL(&laddrs->ipv6_addrs[j].addr, ip6)) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+bool
+lport_addresses_contains_ip(const struct lport_addresses *lsp_addrs,
+                            unsigned int n_lsp_addrs,
+                            const char *ip_s)
+{
+    struct in6_addr ip6;
+    ovs_be32 ip4;
+
+    if (ip_parse(ip_s, &ip4)) {
+        return contains_ipv4_address(lsp_addrs, n_lsp_addrs, ip4);
+    }
+
+    if (ipv6_parse(ip_s, &ip6)) {
+        return contains_ipv6_address(lsp_addrs, n_lsp_addrs, &ip6);
+    }
+
+    return false;
+}
+
 /* Go through 'addresses' and add found IPv4 addresses to 'ipv4_addrs' and
  * IPv6 addresses to 'ipv6_addrs'. */
 void
diff --git a/lib/ovn-util.h b/lib/ovn-util.h
index 0efeb217c..0239ec2ec 100644
--- a/lib/ovn-util.h
+++ b/lib/ovn-util.h
@@ -130,6 +130,10 @@ const char *find_lport_address(const struct 
lport_addresses *laddrs,
 void split_addresses(const char *addresses, struct svec *ipv4_addrs,
                      struct svec *ipv6_addrs);
 
+bool lport_addresses_contains_ip(const struct lport_addresses *lport_address,
+                                 unsigned int n_lsp_addrs,
+                                 const char *ip_s);
+
 char *alloc_nat_zone_key(const char *name, const char *type);
 
 const char *default_nb_db(void);
diff --git a/northd/en-northd.c b/northd/en-northd.c
index 92be3eb2f..ef74175a2 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -80,6 +80,8 @@ northd_get_input_data(struct engine_node *node,
         EN_OVSDB_GET(engine_get_input("NB_network_function", node));
     input_data->nbrec_network_function_group_table =
         EN_OVSDB_GET(engine_get_input("NB_network_function_group", node));
+    input_data->nbrec_lsp_hc_table = EN_OVSDB_GET(engine_get_input(
+        "NB_logical_switch_port_health_check", node));
 
     input_data->sbrec_port_binding_table =
         EN_OVSDB_GET(engine_get_input("SB_port_binding", node));
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index 21e6aedcc..732066638 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -75,7 +75,8 @@ static unixctl_cb_func chassis_features_list;
     NB_NODE(chassis_template_var) \
     NB_NODE(sampling_app) \
     NB_NODE(network_function) \
-    NB_NODE(network_function_group)
+    NB_NODE(network_function_group) \
+    NB_NODE(logical_switch_port_health_check)
 
     enum nb_engine_node {
 #define NB_NODE(NAME) NB_##NAME,
@@ -256,6 +257,8 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
     engine_add_input(&en_northd, &en_nb_chassis_template_var, NULL);
     engine_add_input(&en_northd, &en_nb_network_function, NULL);
     engine_add_input(&en_northd, &en_nb_network_function_group, NULL);
+    engine_add_input(&en_northd, &en_nb_logical_switch_port_health_check,
+                     NULL);
 
     engine_add_input(&en_northd, &en_sb_chassis, NULL);
     engine_add_input(&en_northd, &en_sb_mirror, NULL);
diff --git a/northd/northd.c b/northd/northd.c
index 7fe36b850..90d8edfe9 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -3592,7 +3592,76 @@ build_lb_datapaths(const struct hmap *lbs, const struct 
hmap *lb_groups,
 }
 
 static void
-build_svcs(
+ovn_lsp_svc_monitors_process_port(struct ovsdb_idl_txn *ovnsb_txn,
+                                  const struct ovn_port *op,
+                                  const char *svc_monitor_mac,
+                                  const struct eth_addr *svc_monitor_mac_ea,
+                                  struct hmap *local_svc_monitors_map,
+                                  struct sset *svc_monitor_lsps)
+{
+    sset_add(svc_monitor_lsps, op->key);
+
+    for (size_t i = 0; i < op->nbsp->n_health_checks; i++) {
+        struct nbrec_logical_switch_port_health_check *lsp_hc =
+            op->nbsp->health_checks[i];
+        struct service_monitor_info *mon_info = NULL;
+
+        /* Check if this address is still on the port */
+        bool lsp_contain_ip =
+            lport_addresses_contains_ip(op->lsp_addrs, op->n_lsp_addrs,
+                                        lsp_hc->address);
+
+        /* Remove outdated records */
+        if (!lsp_contain_ip) {
+            mon_info = get_service_mon(local_svc_monitors_map,
+                                       NULL, lsp_hc->address,
+                                       op->key, lsp_hc->port,
+                                       lsp_hc->protocol);
+            if (mon_info) {
+                sbrec_service_monitor_delete(mon_info->sbrec_mon);
+                hmap_remove(local_svc_monitors_map, &mon_info->hmap_node);
+                free(mon_info);
+            }
+            continue;
+        }
+
+        mon_info = create_or_get_service_mon(ovnsb_txn,
+                                             local_svc_monitors_map,
+                                             NULL, "logical-switch-port",
+                                             lsp_hc->address, op->key, NULL,
+                                             lsp_hc->port, lsp_hc->protocol,
+                                             (op->sb && op->sb->chassis) ?
+                                              op->sb->chassis->name : NULL,
+                                             false);
+
+        mon_info->required = true;
+        set_service_mon_options(mon_info->sbrec_mon,
+                                &lsp_hc->options, NULL);
+
+        struct eth_addr ea;
+        if (!mon_info->sbrec_mon->src_mac ||
+            !eth_addr_from_string(mon_info->sbrec_mon->src_mac, &ea) ||
+            !eth_addr_equals(ea, *svc_monitor_mac_ea)) {
+            sbrec_service_monitor_set_src_mac(mon_info->sbrec_mon,
+                                              svc_monitor_mac);
+        }
+
+        if (!mon_info->sbrec_mon->src_ip ||
+            strcmp(mon_info->sbrec_mon->src_ip, lsp_hc->src_ip)) {
+            sbrec_service_monitor_set_src_ip(mon_info->sbrec_mon,
+                                             lsp_hc->src_ip);
+        }
+
+        if ((!op->sb->n_up || !op->sb->up[0]) &&
+            mon_info->sbrec_mon->status &&
+            !strcmp(mon_info->sbrec_mon->status, "online")) {
+            sbrec_service_monitor_set_status(mon_info->sbrec_mon, "offline");
+        }
+    }
+}
+
+static void
+build_svc_monitors_data(
     struct ovsdb_idl_txn *ovnsb_txn,
     struct ovsdb_idl_index *sbrec_service_monitor_by_learned_type,
     const char *svc_monitor_mac,
@@ -3604,7 +3673,8 @@ build_svcs(
     const struct nbrec_network_function_table *nbrec_network_function_table,
     struct sset *svc_monitor_lsps,
     struct hmap *local_svc_monitors_map,
-    struct hmap *ic_learned_svc_monitors_map)
+    struct hmap *ic_learned_svc_monitors_map,
+    struct hmapx *monitored_ports_map)
 {
     const struct sbrec_service_monitor *sbrec_mon;
     struct sbrec_service_monitor *key =
@@ -3654,6 +3724,16 @@ build_svcs(
         }
     }
 
+    struct hmapx_node *hmapx_node;
+    const struct ovn_port *op;
+    HMAPX_FOR_EACH (hmapx_node, monitored_ports_map) {
+        op = hmapx_node->data;
+        ovn_lsp_svc_monitors_process_port(ovnsb_txn, op, svc_monitor_mac,
+                                          svc_monitor_mac_ea,
+                                          local_svc_monitors_map,
+                                          svc_monitor_lsps);
+    }
+
     struct service_monitor_info *mon_info;
     HMAP_FOR_EACH_SAFE (mon_info, hmap_node, local_svc_monitors_map) {
         if (!mon_info->required) {
@@ -4134,6 +4214,16 @@ ovn_port_allocate_key(struct ovn_port *op)
     return true;
 }
 
+static inline void
+add_hc_monitored_port(struct ovn_port *op, struct hmapx *monitored_ports_map)
+{
+    if (op->nbsp &&
+        op->nbsp->n_health_checks &&
+        lsp_is_enabled(op->nbsp)) {
+        hmapx_add(monitored_ports_map, op);
+    }
+}
+
 /* Updates the southbound Port_Binding table so that it contains the logical
  * switch ports specified by the northbound database.
  *
@@ -4150,7 +4240,8 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn,
     struct ovsdb_idl_index *sbrec_chassis_by_hostname,
     struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name,
     struct hmap *ls_datapaths, struct hmap *lr_datapaths,
-    struct hmap *ls_ports, struct hmap *lr_ports)
+    struct hmap *ls_ports, struct hmap *lr_ports,
+    struct hmapx *monitored_ports_map)
 {
     struct ovs_list sb_only, nb_only, both;
     /* XXX: Add tag_alloc_table and queue_id_bitmap as part of northd_data
@@ -4225,6 +4316,7 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn,
                               op, queue_id_bitmap,
                               &active_ha_chassis_grps);
         op->od->is_transit_router |= is_transit_router_port(op);
+        add_hc_monitored_port(op, monitored_ports_map);
         ovs_list_remove(&op->list);
     }
 
@@ -4239,6 +4331,7 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn,
                               &active_ha_chassis_grps);
         sbrec_port_binding_set_logical_port(op->sb, op->key);
         op->od->is_transit_router |= is_transit_router_port(op);
+        add_hc_monitored_port(op, monitored_ports_map);
         ovs_list_remove(&op->list);
     }
 
@@ -4420,6 +4513,11 @@ lsp_can_be_inc_processed(const struct 
nbrec_logical_switch_port *nbsp)
         }
     }
 
+     /* Attaching health check to port is not supported for now. */
+    if (nbsp->n_health_checks) {
+        return false;
+    }
+
     return true;
 }
 
@@ -15613,6 +15711,39 @@ build_arp_resolve_flows_for_lsp(
     }
 }
 
+static void
+build_arp_nd_lflow_for_lsp_svc_hc(struct ovn_port *op,
+                                  const char *svc_monitor_mac,
+                                  struct lflow_table *lflows,
+                                  struct ds *match,
+                                  struct ds *actions)
+{
+    const struct nbrec_logical_switch_port *nbsp = op->nbsp;
+    for (size_t i = 0; i < nbsp->n_health_checks; i++) {
+        struct nbrec_logical_switch_port_health_check *lsp_hc =
+            nbsp->health_checks[i];
+
+        /* Check if this address is still on the port */
+        if (!lport_addresses_contains_ip(op->lsp_addrs, op->n_lsp_addrs,
+                                         lsp_hc->address)) {
+            continue;
+        }
+
+        ds_clear(match);
+        ds_clear(actions);
+
+        bool is_ipv4 = strchr(lsp_hc->src_ip, '.') ? true : false;
+
+        build_arp_nd_service_monitor_lflow(svc_monitor_mac, lsp_hc->src_ip,
+                                           actions, match, is_ipv4);
+
+        ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 110,
+                      ds_cstr(match), ds_cstr(actions),
+                      op->lflow_ref,
+                      WITH_HINT(&op->nbsp->header_));
+    }
+}
+
 #define ICMP4_NEED_FRAG_FORMAT                           \
     "icmp4_error {"                                      \
     "%s"                                                 \
@@ -19165,6 +19296,7 @@ build_lswitch_and_lrouter_iterate_by_lsp(struct 
ovn_port *op,
                                          const struct shash *meter_groups,
                                          struct ds *match,
                                          struct ds *actions,
+                                         const char *svc_monitor_mac,
                                          struct lflow_table *lflows)
 {
     ovs_assert(op->nbsp);
@@ -19182,12 +19314,13 @@ build_lswitch_and_lrouter_iterate_by_lsp(struct 
ovn_port *op,
     build_lswitch_dhcp_options_and_response(op, lflows, meter_groups);
     build_lswitch_external_port(op, lflows);
     build_lswitch_icmp_packet_toobig_admin_flows(op, lflows, match, actions);
-    build_lswitch_ip_unicast_lookup(op, lflows, actions,
-                                    match);
+    build_lswitch_ip_unicast_lookup(op, lflows, actions, match);
     build_lswitch_dhcp_relay_flows(op, ls_ports, lflows, match, actions);
 
     /* Build Logical Router Flows. */
     build_arp_resolve_flows_for_lsp(op, lflows, lr_ports, match, actions);
+    build_arp_nd_lflow_for_lsp_svc_hc(op, svc_monitor_mac, lflows,
+                                      match, actions);
 }
 
 /* Helper function to combine all lflow generation which is iterated by logical
@@ -19295,12 +19428,10 @@ build_lflows_thread(void *arg)
                     if (stop_parallel_processing()) {
                         return NULL;
                     }
-                    build_lswitch_and_lrouter_iterate_by_lsp(op, lsi->ls_ports,
-                                                             lsi->lr_ports,
-                                                             lsi->meter_groups,
-                                                             &lsi->match,
-                                                             &lsi->actions,
-                                                             lsi->lflows);
+                    build_lswitch_and_lrouter_iterate_by_lsp(
+                        op, lsi->ls_ports, lsi->lr_ports, lsi->meter_groups,
+                        &lsi->match, &lsi->actions, lsi->svc_monitor_mac,
+                        lsi->lflows);
                     build_lbnat_lflows_iterate_by_lsp(
                         op, lsi->lr_stateful_table, &lsi->match,
                         &lsi->actions, lsi->lflows);
@@ -19584,6 +19715,7 @@ build_lswitch_and_lrouter_flows(
                                                      lsi.meter_groups,
                                                      &lsi.match,
                                                      &lsi.actions,
+                                                     lsi.svc_monitor_mac,
                                                      lsi.lflows);
             build_lbnat_lflows_iterate_by_lsp(op, lsi.lr_stateful_table,
                                               &lsi.match,
@@ -19841,6 +19973,7 @@ lflow_handle_northd_port_changes(struct ovsdb_idl_txn 
*ovnsb_txn,
                                                  lflow_input->lr_ports,
                                                  lflow_input->meter_groups,
                                                  &match, &actions,
+                                                 lflow_input->svc_monitor_mac,
                                                  lflows);
         /* Sync the new flows to SB. */
         bool handled = lflow_ref_sync_lflows(
@@ -19898,7 +20031,9 @@ lflow_handle_northd_port_changes(struct ovsdb_idl_txn 
*ovnsb_txn,
         build_lswitch_and_lrouter_iterate_by_lsp(op, lflow_input->ls_ports,
                                                  lflow_input->lr_ports,
                                                  lflow_input->meter_groups,
-                                                 &match, &actions, lflows);
+                                                 &match, &actions,
+                                                 lflow_input->svc_monitor_mac,
+                                                 lflows);
 
         /* Sync the newly added flows to SB. */
         bool handled = lflow_ref_sync_lflows(
@@ -20601,6 +20736,7 @@ northd_init(struct northd_data *data)
     hmap_init(&data->lb_group_datapaths_map);
     sset_init(&data->svc_monitor_lsps);
     hmap_init(&data->local_svc_monitors_map);
+    hmapx_init(&data->monitored_ports_map);
     init_northd_tracked_data(data);
 }
 
@@ -20686,6 +20822,7 @@ northd_destroy(struct northd_data *data)
                                 &data->ls_ports, &data->lr_ports);
 
     sset_destroy(&data->svc_monitor_lsps);
+    hmapx_destroy(&data->monitored_ports_map);
     destroy_northd_tracked_data(data);
 }
 
@@ -20791,21 +20928,23 @@ ovnnb_db_run(struct northd_input *input_data,
                 input_data->sbrec_chassis_by_hostname,
                 input_data->sbrec_ha_chassis_grp_by_name,
                 &data->ls_datapaths.datapaths, &data->lr_datapaths.datapaths,
-                &data->ls_ports, &data->lr_ports);
+                &data->ls_ports, &data->lr_ports,
+                &data->monitored_ports_map);
     build_lb_port_related_data(&data->lr_datapaths, &data->ls_datapaths,
                                &data->lb_datapaths_map,
                                &data->lb_group_datapaths_map);
-    build_svcs(ovnsb_txn,
-               input_data->sbrec_service_monitor_by_learned_type,
-               input_data->svc_monitor_mac,
-               &input_data->svc_monitor_mac_ea,
-               input_data->svc_monitor_mac_dst,
-               input_data->svc_monitor_ip,
-               input_data->svc_monitor_ip_dst,
-               &data->ls_ports, &data->lb_datapaths_map,
-               input_data->nbrec_network_function_table,
-               &data->svc_monitor_lsps, &data->local_svc_monitors_map,
-               input_data->ic_learned_svc_monitors_map);
+    build_svc_monitors_data(ovnsb_txn,
+        input_data->sbrec_service_monitor_by_learned_type,
+        input_data->svc_monitor_mac,
+        &input_data->svc_monitor_mac_ea,
+        input_data->svc_monitor_mac_dst,
+        input_data->svc_monitor_ip,
+        input_data->svc_monitor_ip_dst,
+        &data->ls_ports, &data->lb_datapaths_map,
+        input_data->nbrec_network_function_table,
+        &data->svc_monitor_lsps, &data->local_svc_monitors_map,
+        input_data->ic_learned_svc_monitors_map,
+        &data->monitored_ports_map);
     build_lb_count_dps(&data->lb_datapaths_map);
     build_network_function_active(
         input_data->nbrec_network_function_group_table,
diff --git a/northd/northd.h b/northd/northd.h
index 25c8a909a..c2571fb30 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -44,6 +44,8 @@ struct northd_input {
     const struct nbrec_network_function_table *nbrec_network_function_table;
     const struct nbrec_network_function_group_table
         *nbrec_network_function_group_table;
+    const struct nbrec_logical_switch_port_health_check_table
+        *nbrec_lsp_hc_table;
 
     /* Southbound table references */
     const struct sbrec_port_binding_table *sbrec_port_binding_table;
@@ -203,6 +205,7 @@ struct northd_data {
     struct hmap lb_group_datapaths_map;
     struct sset svc_monitor_lsps;
     struct hmap local_svc_monitors_map;
+    struct hmapx monitored_ports_map;
 
     /* Change tracking data. */
     struct northd_tracked_data trk_data;
diff --git a/tests/ovn-inc-proc-graph-dump.at b/tests/ovn-inc-proc-graph-dump.at
index 3fe7b8fbd..ff2c8c0c7 100644
--- a/tests/ovn-inc-proc-graph-dump.at
+++ b/tests/ovn-inc-proc-graph-dump.at
@@ -18,6 +18,7 @@ digraph "Incremental-Processing-Engine" {
        NB_chassis_template_var [[style=filled, shape=box, fillcolor=white, 
label="NB_chassis_template_var"]];
        NB_network_function [[style=filled, shape=box, fillcolor=white, 
label="NB_network_function"]];
        NB_network_function_group [[style=filled, shape=box, fillcolor=white, 
label="NB_network_function_group"]];
+       NB_logical_switch_port_health_check [[style=filled, shape=box, 
fillcolor=white, label="NB_logical_switch_port_health_check"]];
        SB_chassis [[style=filled, shape=box, fillcolor=white, 
label="SB_chassis"]];
        SB_mirror [[style=filled, shape=box, fillcolor=white, 
label="SB_mirror"]];
        SB_meter [[style=filled, shape=box, fillcolor=white, label="SB_meter"]];
@@ -75,6 +76,7 @@ digraph "Incremental-Processing-Engine" {
        NB_chassis_template_var -> northd [[label=""]];
        NB_network_function -> northd [[label=""]];
        NB_network_function_group -> northd [[label=""]];
+       NB_logical_switch_port_health_check -> northd [[label=""]];
        SB_chassis -> northd [[label=""]];
        SB_mirror -> northd [[label=""]];
        SB_meter -> northd [[label=""]];
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 605d2ec4f..b4bf75fee 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -19810,3 +19810,93 @@ AT_CHECK([grep "ls1-to-spine" ls1flows | 
ovn_strip_lflows | sort], [0], [dnl
 
 OVN_CLEANUP_NORTHD
 AT_CLEANUP
+
+AT_SETUP([Logical Switch Port Health Check - lflow/service monitor 
synchronization])
+ovn_start
+
+check ovn-nbctl ls-add ls1
+check ovn-nbctl lsp-add ls1 lport1 -- \
+    lsp-set-addresses lport1 "f0:00:0f:01:02:04 192.168.0.10" 
"f0:00:0f:01:02:06 192.168.0.11"
+
+check ovn-nbctl set NB_Global . options:svc_monitor_mac="11:11:11:11:11:11"
+
+# Create service monitor for all lsp addresses.
+check ovn-nbctl lsp-hc-add lport1 icmp 192.168.0.255 192.168.0.10
+check ovn-nbctl lsp-hc-add lport1 icmp 192.168.0.255 192.168.0.11
+
+# Check lflow and service monitor synchronization
+AT_CHECK([ovn-sbctl lflow-list ls1 | grep 'ls_in_arp_rsp'| grep "priority=110" 
| ovn_strip_lflows], [0], [dnl
+  table=??(ls_in_arp_rsp      ), priority=110  , match=(arp.tpa == 
192.168.0.255 && arp.op == 1), action=(eth.dst = eth.src; eth.src = 
11:11:11:11:11:11; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 
11:11:11:11:11:11; arp.tpa = arp.spa; arp.spa = 192.168.0.255; outport = 
inport; flags.loopback = 1; output;)
+])
+
+check_row_count sb:Service_Monitor 2
+check_column "false false" sb:Service_Monitor ic_learned logical_port=lport1
+check_column "false false" sb:Service_Monitor remote logical_port=lport1
+check_column "192.168.0.10 192.168.0.11" sb:Service_Monitor ip 
logical_port=lport1
+check_column "icmp icmp" sb:Service_Monitor protocol logical_port=lport1
+check_column "192.168.0.255 192.168.0.255" sb:Service_Monitor src_ip 
logical_port=lport1
+check_column "0 0" sb:Service_Monitor port logical_port=lport1
+check_column "logical-switch-port logical-switch-port" sb:Service_Monitor type 
logical_port=lport1
+check_column "11:11:11:11:11:11 11:11:11:11:11:11" sb:Service_Monitor src_mac 
logical_port=lport1
+
+# Create one more service monitor for all lsp addresses.
+check ovn-nbctl lsp-hc-add lport1 tcp 192.168.0.254 80 192.168.0.10
+check ovn-nbctl lsp-hc-add lport1 tcp 192.168.0.254 80 192.168.0.11
+
+AT_CHECK([ovn-sbctl lflow-list ls1 | grep 'ls_in_arp_rsp'| grep "priority=110" 
| ovn_strip_lflows], [0], [dnl
+  table=??(ls_in_arp_rsp      ), priority=110  , match=(arp.tpa == 
192.168.0.254 && arp.op == 1), action=(eth.dst = eth.src; eth.src = 
11:11:11:11:11:11; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 
11:11:11:11:11:11; arp.tpa = arp.spa; arp.spa = 192.168.0.254; outport = 
inport; flags.loopback = 1; output;)
+  table=??(ls_in_arp_rsp      ), priority=110  , match=(arp.tpa == 
192.168.0.255 && arp.op == 1), action=(eth.dst = eth.src; eth.src = 
11:11:11:11:11:11; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 
11:11:11:11:11:11; arp.tpa = arp.spa; arp.spa = 192.168.0.255; outport = 
inport; flags.loopback = 1; output;)
+])
+
+# Check options propogations
+hc_lport1_uuid=$(fetch_column nb:logical_switch_port_health_check _uuid 
address="192.168.0.10" protocol="tcp")
+
+check ovn-nbctl set logical_switch_port_health_check $hc_lport1_uuid 
options:interval=3
+check ovn-nbctl set logical_switch_port_health_check $hc_lport1_uuid 
options:timeout=30
+check ovn-nbctl set logical_switch_port_health_check $hc_lport1_uuid 
options:success_count=1
+check ovn-nbctl set logical_switch_port_health_check $hc_lport1_uuid 
options:failure_count=2
+
+sm_lport1_uuid=$(fetch_column sb:service_monitor _uuid protocol="tcp" 
ip="192.168.0.10")
+
+AT_CHECK([ovn-sbctl get Service_Monitor $sm_lport1_uuid options:interval],
+[0], ["3"
+])
+AT_CHECK([ovn-sbctl get Service_Monitor $sm_lport1_uuid options:failure_count],
+[0], ["2"
+])
+AT_CHECK([ovn-sbctl get Service_Monitor $sm_lport1_uuid options:success_count],
+[0], ["1"
+])
+AT_CHECK([ovn-sbctl get Service_Monitor $sm_lport1_uuid options:timeout],
+[0], ["30"
+])
+
+check ovn-nbctl lsp-del lport1
+check_row_count sb:Service_Monitor 0
+AT_CHECK([ovn-sbctl lflow-list ls1 | grep 'ls_in_arp_rsp'| grep "priority=110" 
| ovn_strip_lflows], [0], [dnl])
+
+# Create a port with health checks in one transaction - checking the 
processing of incremental processing
+check ovn-nbctl lsp-add ls1 lport1 -- \
+    lsp-set-addresses lport1 "f0:00:0f:01:02:04 192.168.0.10" 
"f0:00:0f:01:02:06 192.168.0.11" -- \
+    lsp-hc-add lport1 icmp 192.168.0.255 192.168.0.10 -- \
+    lsp-hc-add lport1 icmp 192.168.0.255 192.168.0.11
+
+check_row_count sb:Service_Monitor 2
+AT_CHECK([ovn-sbctl lflow-list ls1 | grep 'ls_in_arp_rsp'| grep "priority=110" 
| ovn_strip_lflows], [0], [dnl
+  table=??(ls_in_arp_rsp      ), priority=110  , match=(arp.tpa == 
192.168.0.255 && arp.op == 1), action=(eth.dst = eth.src; eth.src = 
11:11:11:11:11:11; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 
11:11:11:11:11:11; arp.tpa = arp.spa; arp.spa = 192.168.0.255; outport = 
inport; flags.loopback = 1; output;)
+])
+
+check_row_count sb:Service_Monitor 2
+
+# Change the addresses on the switch port - expect records in SBDB to be 
deleted.
+lport1=$(fetch_column nb:logical_switch_port _uuid  name="lport1")
+check ovn-nbctl clear logical_switch_port $lport1 addresses
+
+check_row_count sb:Service_Monitor 0
+AT_CHECK([ovn-sbctl lflow-list ls1 | grep 'ls_in_arp_rsp'| grep "priority=110" 
| ovn_strip_lflows], [0], [])
+
+check ovn-nbctl lsp-set-addresses lport1 "f0:00:0f:01:02:04 192.168.0.10" 
"f0:00:0f:01:02:06 192.168.0.11"
+check_row_count sb:Service_Monitor 2
+
+AT_CLEANUP
+])
-- 
2.48.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to