This commit implements ARP/ND responder flows for IC-learned service monitors,
similar to existing local service monitors. Key changes include:

1. Extracted common ARP/ND response logic into helper function
   `build_arp_nd_service_monitor_lflow()` to avoid code duplication
2. Split service monitor flow generation into two separate functions:
   - `build_lswitch_arp_nd_local_svc_mon()` for local service monitors
   - `build_lswitch_arp_nd_ic_learned_svc_mon()` for IC-learned monitors
3. Added flow generation for IC-learned monitors in main flow build path
4. Maintained existing behavior for local service monitors
5. Updated parallel and non-parallel build paths consistently

Signed-off-by: Alexandra Rukomoinikova <arukomoinikova@k2.cloud>
---
 northd/northd.c | 160 +++++++++++++++++++++++++++++++-----------------
 1 file changed, 104 insertions(+), 56 deletions(-)

diff --git a/northd/northd.c b/northd/northd.c
index b0d43511c..a7be29619 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -9883,6 +9883,48 @@ build_lswitch_lflows_admission_control(struct 
ovn_datapath *od,
                   lflow_ref);
 }
 
+static void
+build_arp_nd_service_monitor_lflow(const char *svc_monitor_mac,
+                                   const char *svc_src_ip,
+                                   struct ds *action,
+                                   struct ds *match,
+                                   bool is_ipv4)
+{
+    if (is_ipv4) {
+        ds_put_format(match, "arp.tpa == %s && arp.op == 1",
+                      svc_src_ip);
+        ds_put_format(action,
+            "eth.dst = eth.src; "
+            "eth.src = %s; "
+            "arp.op = 2; /* ARP reply */ "
+            "arp.tha = arp.sha; "
+            "arp.sha = %s; "
+            "arp.tpa = arp.spa; "
+            "arp.spa = %s; "
+            "outport = inport; "
+            "flags.loopback = 1; "
+            "output;",
+            svc_monitor_mac, svc_monitor_mac,
+            svc_src_ip);
+    } else {
+        ds_put_format(match, "nd_ns && nd.target == %s",
+                      svc_src_ip);
+        ds_put_format(action,
+            "nd_na { "
+            "eth.dst = eth.src; "
+            "eth.src = %s; "
+            "ip6.src = %s; "
+            "nd.target = %s; "
+            "nd.tll = %s; "
+            "outport = inport; "
+            "flags.loopback = 1; "
+            "output; "
+            "};",
+            svc_monitor_mac, svc_src_ip,
+            svc_src_ip, svc_monitor_mac);
+    }
+}
+
 /* Ingress table 19: ARP/ND responder, skip requests coming from localnet
  * ports. (priority 100); see ovn-northd.8.xml for the rationale. */
 
@@ -10253,12 +10295,12 @@ build_lswitch_arp_nd_responder_default(struct 
ovn_datapath *od,
 /* Ingress table 19: ARP/ND responder for service monitor source ip.
  * (priority 110)*/
 static void
-build_lswitch_arp_nd_service_monitor(const struct ovn_lb_datapaths *lb_dps,
-                                     const struct hmap *ls_ports,
-                                     const char *svc_monitor_mac,
-                                     struct lflow_table *lflows,
-                                     struct ds *actions,
-                                     struct ds *match)
+build_lswitch_arp_nd_local_svc_mon(const struct ovn_lb_datapaths *lb_dps,
+                                   const struct hmap *ls_ports,
+                                   const char *svc_monitor_mac,
+                                   struct lflow_table *lflows,
+                                   struct ds *actions,
+                                   struct ds *match)
 {
     const struct ovn_northd_lb *lb = lb_dps->lb;
     for (size_t i = 0; i < lb->n_vips; i++) {
@@ -10284,41 +10326,11 @@ build_lswitch_arp_nd_service_monitor(const struct 
ovn_lb_datapaths *lb_dps,
 
             ds_clear(match);
             ds_clear(actions);
-            if (IN6_IS_ADDR_V4MAPPED(&lb_vip->vip)) {
-                ds_put_format(match, "arp.tpa == %s && arp.op == 1",
-                              backend_nb->svc_mon_src_ip);
-                ds_put_format(actions,
-                    "eth.dst = eth.src; "
-                    "eth.src = %s; "
-                    "arp.op = 2; /* ARP reply */ "
-                    "arp.tha = arp.sha; "
-                    "arp.sha = %s; "
-                    "arp.tpa = arp.spa; "
-                    "arp.spa = %s; "
-                    "outport = inport; "
-                    "flags.loopback = 1; "
-                    "output;",
-                    svc_monitor_mac, svc_monitor_mac,
-                    backend_nb->svc_mon_src_ip);
-            } else {
-                ds_put_format(match, "nd_ns && nd.target == %s",
-                              backend_nb->svc_mon_src_ip);
-                ds_put_format(actions,
-                        "nd_na { "
-                        "eth.dst = eth.src; "
-                        "eth.src = %s; "
-                        "ip6.src = %s; "
-                        "nd.target = %s; "
-                        "nd.tll = %s; "
-                        "outport = inport; "
-                        "flags.loopback = 1; "
-                        "output; "
-                        "};",
-                        svc_monitor_mac,
-                        backend_nb->svc_mon_src_ip,
-                        backend_nb->svc_mon_src_ip,
-                        svc_monitor_mac);
-            }
+
+            build_arp_nd_service_monitor_lflow(svc_monitor_mac,
+                backend_nb->svc_mon_src_ip, actions, match,
+                IN6_IS_ADDR_V4MAPPED(&lb_vip->vip) ? true : false);
+
             ovn_lflow_add_with_hint(lflows,
                                     op->od,
                                     S_SWITCH_IN_ARP_ND_RSP, 110,
@@ -10329,6 +10341,37 @@ build_lswitch_arp_nd_service_monitor(const struct 
ovn_lb_datapaths *lb_dps,
     }
 }
 
+static void
+build_lswitch_arp_nd_ic_learned_svc_mon(struct hmap *ic_learned_svcs_map,
+                                        const struct hmap *ls_ports,
+                                        const char *svc_monitor_mac,
+                                        struct lflow_table *lflows,
+                                        struct lflow_ref *lflow_ref)
+{
+    struct ds action = DS_EMPTY_INITIALIZER;
+    struct ds match = DS_EMPTY_INITIALIZER;
+
+    struct service_monitor_info *mon_info;
+    HMAP_FOR_EACH (mon_info, hmap_node, ic_learned_svcs_map) {
+        struct ovn_port *op = ovn_port_find(ls_ports,
+                                            mon_info->sbrec_mon->logical_port);
+
+        bool is_ipv4 = strchr(mon_info->sbrec_mon->ip, '.') ? true : false;
+
+        build_arp_nd_service_monitor_lflow(svc_monitor_mac,
+                                           mon_info->sbrec_mon->src_ip,
+                                           &action, &match, is_ipv4);
+
+        ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP,
+                      110, ds_cstr(&match), ds_cstr(&action), lflow_ref);
+
+        ds_clear(&match);
+        ds_clear(&action);
+    }
+
+    ds_destroy(&match);
+    ds_destroy(&action);
+}
 
 /* Logical switch ingress table 20 and 21: DHCP options and response
  * priority 100 flows. */
@@ -18307,12 +18350,12 @@ build_lflows_thread(void *arg)
                     if (stop_parallel_processing()) {
                         return NULL;
                     }
-                    build_lswitch_arp_nd_service_monitor(lb_dps,
-                                                         lsi->ls_ports,
-                                                         lsi->svc_monitor_mac,
-                                                         lsi->lflows,
-                                                         &lsi->match,
-                                                         &lsi->actions);
+                    build_lswitch_arp_nd_local_svc_mon(lb_dps,
+                                                       lsi->ls_ports,
+                                                       lsi->svc_monitor_mac,
+                                                       lsi->lflows,
+                                                       &lsi->match,
+                                                       &lsi->actions);
                     build_lrouter_defrag_flows_for_lb(lb_dps, lsi->lflows,
                                                       lsi->lr_datapaths,
                                                       &lsi->match);
@@ -18554,10 +18597,10 @@ build_lswitch_and_lrouter_flows(
         stopwatch_stop(LFLOWS_PORTS_STOPWATCH_NAME, time_msec());
         stopwatch_start(LFLOWS_LBS_STOPWATCH_NAME, time_msec());
         HMAP_FOR_EACH (lb_dps, hmap_node, lb_dps_map) {
-            build_lswitch_arp_nd_service_monitor(lb_dps, lsi.ls_ports,
-                                                 lsi.svc_monitor_mac,
-                                                 lsi.lflows, &lsi.actions,
-                                                 &lsi.match);
+            build_lswitch_arp_nd_local_svc_mon(lb_dps, lsi.ls_ports,
+                                               lsi.svc_monitor_mac,
+                                               lsi.lflows, &lsi.actions,
+                                               &lsi.match);
             build_lrouter_defrag_flows_for_lb(lb_dps, lsi.lflows,
                                               lsi.lr_datapaths, &lsi.match);
             build_lrouter_flows_for_lb(lb_dps, lsi.lflows, lsi.meter_groups,
@@ -18689,7 +18732,12 @@ void build_lflows(struct ovsdb_idl_txn *ovnsb_txn,
     build_igmp_lflows(input_data->igmp_groups,
                       &input_data->ls_datapaths->datapaths,
                       lflows, input_data->igmp_lflow_ref);
-
+    build_lswitch_arp_nd_ic_learned_svc_mon(
+        input_data->ic_learned_svcs,
+        input_data->ls_ports,
+        input_data->svc_monitor_mac,
+        lflows,
+        input_data->ic_leared_svcs_lflow_ref);
     if (parallelization_state == STATE_INIT_HASH_SIZES) {
         parallelization_state = STATE_USE_PARALLELIZATION;
     }
@@ -18923,10 +18971,10 @@ lflow_handle_northd_lb_changes(struct ovsdb_idl_txn 
*ovnsb_txn,
         struct ds match = DS_EMPTY_INITIALIZER;
         struct ds actions = DS_EMPTY_INITIALIZER;
 
-        build_lswitch_arp_nd_service_monitor(lb_dps, lflow_input->ls_ports,
-                                             lflow_input->svc_monitor_mac,
-                                             lflows, &actions,
-                                             &match);
+        build_lswitch_arp_nd_local_svc_mon(lb_dps, lflow_input->ls_ports,
+                                           lflow_input->svc_monitor_mac,
+                                           lflows, &actions,
+                                           &match);
         build_lrouter_defrag_flows_for_lb(lb_dps, lflows,
                                           lflow_input->lr_datapaths, &match);
         build_lrouter_flows_for_lb(lb_dps, lflows,
-- 
2.48.1

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to