Hi Mark! i fixed the comments in the second version of the patch series, 
except that in this patch, i will answer it below.
And also, I wanted to write a system test with traffic checking, but I 
didn't succeed at all 😭 I didn't find any examples in code with 
cross-az system tests, only with checking packet tracing. I haven't 
figured out how to do this yet, I hope I'll figure it out later and I 
can make it to the release without this system test.

On 06.08.2025 22:51, Mark Michelson wrote:
> Hi Alexandra, see in-line for comments.
>
> On 7/31/25 8:01 AM, Alexandra Rukomoinikova wrote:
>> 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);
>
> Please add a NULL check for op here. If ip_port_mappings are 
> misconfigured, and a non-existent logical port name is used, then this 
> could result in a NULL return.
>
>> +
>> +        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);
>
> In build_lswitch_arp_nd_service_monitor(), there are checks performed 
> to ensure that health checks are enabled for a particular VIP before 
> installing the ARP responder flow. I'm curious why such checks are not 
> performed for remote service monitors.
In the build_lswitch_arp_nd_service_monitor() function we iterate over 
the lb and see if the health check is enabled for backend, backend_nb - 
set to true health_check when initializing the service monitor.
In my build_lswitch_arp_nd_ic_learned_svc_mon function we iterate on the 
learned service monitors, their initialization was done by northd in 
another availability zone, so here we can consider by default that such 
a health check service is initialized. I hope I explained clearly what I 
wanted to say)
>
>> +
>> +        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,
>

-- 
regards,
Alexandra.

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

Reply via email to