{"id":2232250,"url":"http://patchwork.ozlabs.org/api/patches/2232250/?format=json","web_url":"http://patchwork.ozlabs.org/project/ovn/patch/20260504035709.95643-1-enginrect@gmail.com/","project":{"id":68,"url":"http://patchwork.ozlabs.org/api/projects/68/?format=json","name":"Open Virtual Network development","link_name":"ovn","list_id":"ovs-dev.openvswitch.org","list_email":"ovs-dev@openvswitch.org","web_url":"http://openvswitch.org/","scm_url":"","webscm_url":"","list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<20260504035709.95643-1-enginrect@gmail.com>","list_archive_url":null,"date":"2026-05-04T03:57:09","name":"[ovs-dev,v2] northd: Generate HM reply punt lflow for type=external backends.","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"d0a99cbf5aa1e558f49d6c75c6dc43a55a84a927","submitter":{"id":93318,"url":"http://patchwork.ozlabs.org/api/people/93318/?format=json","name":"JayGue Lee","email":"enginrect@gmail.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/ovn/patch/20260504035709.95643-1-enginrect@gmail.com/mbox/","series":[{"id":502606,"url":"http://patchwork.ozlabs.org/api/series/502606/?format=json","web_url":"http://patchwork.ozlabs.org/project/ovn/list/?series=502606","date":"2026-05-04T03:57:09","name":"[ovs-dev,v2] northd: Generate HM reply punt lflow for type=external backends.","version":2,"mbox":"http://patchwork.ozlabs.org/series/502606/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2232250/comments/","check":"success","checks":"http://patchwork.ozlabs.org/api/patches/2232250/checks/","tags":{},"related":[],"headers":{"Return-Path":"<ovs-dev-bounces@openvswitch.org>","X-Original-To":["incoming@patchwork.ozlabs.org","ovs-dev@openvswitch.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","ovs-dev@lists.linuxfoundation.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=bylQ2HUa;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)","smtp3.osuosl.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key)\n header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104\n header.b=bylQ2HUa","smtp4.osuosl.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com","smtp4.osuosl.org;\n dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.a=rsa-sha256 header.s=20251104 header.b=bylQ2HUa"],"Received":["from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g87Bn4HDhz1yJV\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 04 May 2026 13:57:21 +1000 (AEST)","from localhost (localhost [127.0.0.1])\n\tby smtp3.osuosl.org (Postfix) with ESMTP id 5721F612F4;\n\tMon,  4 May 2026 03:57:19 +0000 (UTC)","from smtp3.osuosl.org ([127.0.0.1])\n by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id i8TyXqmweTF0; Mon,  4 May 2026 03:57:17 +0000 (UTC)","from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp3.osuosl.org (Postfix) with ESMTPS id 783D7612F1;\n\tMon,  4 May 2026 03:57:17 +0000 (UTC)","from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 50BDCC04EA;\n\tMon,  4 May 2026 03:57:17 +0000 (UTC)","from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 8C497C04E9\n for <ovs-dev@openvswitch.org>; Mon,  4 May 2026 03:57:16 +0000 (UTC)","from localhost (localhost [127.0.0.1])\n by smtp4.osuosl.org (Postfix) with ESMTP id 78D2E416D5\n for <ovs-dev@openvswitch.org>; Mon,  4 May 2026 03:57:16 +0000 (UTC)","from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id Jehz9m7BAQGG for <ovs-dev@openvswitch.org>;\n Mon,  4 May 2026 03:57:15 +0000 (UTC)","from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com\n [IPv6:2607:f8b0:4864:20::102f])\n by smtp4.osuosl.org (Postfix) with ESMTPS id 8DF27416CD\n for <ovs-dev@openvswitch.org>; Mon,  4 May 2026 03:57:15 +0000 (UTC)","by mail-pj1-x102f.google.com with SMTP id\n 98e67ed59e1d1-36526b81c21so126147a91.0\n for <ovs-dev@openvswitch.org>; Sun, 03 May 2026 20:57:15 -0700 (PDT)","from localhost ([1.234.165.150]) by smtp.gmail.com with ESMTPSA id\n d2e1a72fcca58-83515b864c7sm11216719b3a.59.2026.05.03.20.57.12\n for <ovs-dev@openvswitch.org>\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Sun, 03 May 2026 20:57:13 -0700 (PDT)"],"X-Virus-Scanned":["amavis at osuosl.org","amavis at osuosl.org"],"X-Comment":"SPF check N/A for local connections - client-ip=140.211.9.56;\n helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ","DKIM-Filter":["OpenDKIM Filter v2.11.0 smtp3.osuosl.org 783D7612F1","OpenDKIM Filter v2.11.0 smtp4.osuosl.org 8DF27416CD"],"Received-SPF":"Pass (mailfrom) identity=mailfrom;\n client-ip=2607:f8b0:4864:20::102f; helo=mail-pj1-x102f.google.com;\n envelope-from=enginrect@gmail.com; receiver=<UNKNOWN>","DMARC-Filter":"OpenDMARC Filter v1.4.2 smtp4.osuosl.org 8DF27416CD","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1777867034; x=1778471834; darn=openvswitch.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:to:from:from:to:cc:subject:date:message-id\n :reply-to; bh=pmui5rtGOrU9IAUASYhfNKxMm4lE5BC157Y5iOXeCwg=;\n b=bylQ2HUaLsbQemgKzv1qPPOn0BqAtrdTw044xnBTixABpwtpQhzsDsHtRErIOQoYRU\n CBJvzIKuxG2fGxRkJl1RsS8yVPMr17eWVDjqpuxlS+U0AZYzJ3nSLrCUyQ2f0JX2haAe\n V6Jk1ScAZBkG3gGQzjcAk4Oylut0xTc2mr6au8FFxB6FNmE2l9oFolGT2Zp90s0b6PPT\n gBXfmrQFu9pdnb7b7z7j7jfb2ZP0rsQxKQTU5++dWL9Ej8cV20XSq93c5hd3cX6tp4Lr\n 6lCEQm9iNiO8ri96xzPLADzcJZAxpw8/B2tversXyBPCZ+pzL4b25JshhYbzZttUynAr\n AtdA==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777867034; x=1778471834;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to\n :cc:subject:date:message-id:reply-to;\n bh=pmui5rtGOrU9IAUASYhfNKxMm4lE5BC157Y5iOXeCwg=;\n b=ZVi44WNc9Itr1WrjOYvrWJ97BUvwJWfNGIBXPnj0zUwwy9j14JO6Zk6nL+Qsjcn4B8\n ACNrOubial1l5WDladYG0InL/uMBC3pgugqB3muF1OeyqOifuxvNL6fr1lz9DWZXVFZW\n 2urqkZqDPHiqe4V0YrVVHbbrwMSnMDEKgVY7j75MRuRaMSS+sb39Rnwiuxe4IIGG5Auf\n u8JRt1TlLh0kF3b5C8jN95WU0Qp3p6f2yLd/m0ClGCTakwYdc8ZFM1hzQK02rZ+Bz/Dp\n eDoYvzAn/x9UGKmUnTjrWXSarNgZwlIiVhYBdDi77ySN0Axh3cqB0tw0sdxi1V0uDo0g\n FWiw==","X-Gm-Message-State":"AOJu0Yw6oEDnPRxGjalpJIzv0ZeRDlZZr7VF2JgvZU30Xd6S+xb1qXd4\n OLDvpnwLMgVfNL5Uy3Oa/Tt8tTPZYp2K3l/VvgTybFVvtsq/yrC2yDuLYzfmOQ==","X-Gm-Gg":"AeBDievAdEO2tbuzEhC7LWrHFDNOukZFpTbUVNs1Gk+CYjx4SxqM+sa7jXDww6f0KuD\n McHwmXGfk1iWsafhqoRPZOGlcLfQYQ+VEHUZDGq8GTnPST1fy4C5Nr51he5cMWKZBJUkEATpuGi\n DobIGm2oRo5uKnQ5fQZ7lxkoZIlv6JODj+W9zGAi9+5aP1Am94pR3m0GzoWRsF2DPpt+qyeXpen\n rU+yfidsyTOUw7iKFvnqiFvDQcnzucVsKbK3tWB5Sk9EcEQrP1BD3P2UD/+JqWzlM+3kTG63C3u\n kHHf3g8jrTmj35N5KkzX1gf5Xbq+XteJecZNtbsMowbWTf5wkh2QkGDzEJwQo9CTWXSg48a8ruB\n F+S99hJ5lA71Sz+NuHu3rO8V18vGpuAfJYYA+7ebni0AudM9obl8w+EskGHNLcASx1l04zfcTVh\n K6mAYX7pQRkbXzUhw0D3ltkzpmcXMaZDFFp4wOGCLqs/vf7c3JUzJYDr4=","X-Received":"by 2002:a05:6a00:a90e:b0:82c:20ec:6589 with SMTP id\n d2e1a72fcca58-8352d21908fmr3868840b3a.3.1777867033847;\n Sun, 03 May 2026 20:57:13 -0700 (PDT)","From":"JayGue Lee <enginrect@gmail.com>","To":"ovs-dev@openvswitch.org","Date":"Mon,  4 May 2026 12:57:09 +0900","Message-ID":"<20260504035709.95643-1-enginrect@gmail.com>","X-Mailer":"git-send-email 2.49.0","In-Reply-To":"<20260504000641.86477-1-enginrect@gmail.com>","References":"<20260504000641.86477-1-enginrect@gmail.com>","MIME-Version":"1.0","Subject":"[ovs-dev] [PATCH ovn v2] northd: Generate HM reply punt lflow for\n type=external backends.","X-BeenThere":"ovs-dev@openvswitch.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"<ovs-dev.openvswitch.org>","List-Unsubscribe":"<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>","List-Archive":"<http://mail.openvswitch.org/pipermail/ovs-dev/>","List-Post":"<mailto:ovs-dev@openvswitch.org>","List-Help":"<mailto:ovs-dev-request@openvswitch.org?subject=help>","List-Subscribe":"<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"ovs-dev-bounces@openvswitch.org","Sender":"\"dev\" <ovs-dev-bounces@openvswitch.org>"},"content":"build_lb_health_check_response_lflows() builds a per-backend\nservice_monitor reply punt lflow with the match:\n\n    inport == \"<backend_lsp>\" && ip4.dst == <svc_mon_src_ip> &&\n    ip4.src == <backend_ip>   && eth.dst == <svc_mon_lrp_mac> &&\n    tcp.src == <backend_port>\n\nWhen the backend's LSP is type=external on a Logical_Switch that has\na localnet port (the typical configuration produced by Neutron /\novn-octavia-provider for baremetal pool members on a provider VLAN),\nthe response packet re-enters br-int through the localnet LSP, so\nMFF_LOG_INPORT at S_SWITCH_IN_L2_LKUP is set to the localnet LSP's\ntunnel_key, not the backend LSP's.  The existing inport == \"...\"\nclause therefore never matches, the response is never punted to\novn-controller via ACTION_OPCODE_HANDLE_SVC_CHECK, and the\nService_Monitor.status of those backends stays \"offline\"\nindefinitely -- even though the backend physically replies on the\nwire.\n\nFix this by emitting an additional reply punt lflow on every\npeer_switch_od that has a localnet port AND a type=external backend\nLSP.  The new lflow drops the inport == \"...\" constraint, replaces\nit with eth.src == <backend_mac>, and uses\n\n    outport = \"<backend_lsp>\";\n    handle_svc_check(outport);\n    outport = \"\";\n\nso MFF_LOG_INPORT is loaded with the backend LSP's tunnel_key for\nthe controller dispatch (handle_svc_check(outport) borrows reg15\ninto reg14 via push/pop), and outport is then cleared to prevent\nthe cleared MFF_LOG_OUTPORT from leaking into egress and reflecting\nthe reply back to the backend.\n\nThe patch does not introduce or change any OVN action, so\nOVN_INTERNAL_MINOR_VER is not bumped.\n\nSigned-off-by: JayGue Lee <enginrect@gmail.com>\n---\nv2:\n- Fixed SIGSEGV reported by the ovsrobot CI on v1.  v1 used\n  ovn_port_find(&peer_switch_od->ports, ...) to look up the backend\n  ovn_port by its LSP name.  ovn_port_find() walks the hmap with\n  HMAP_FOR_EACH_WITH_HASH using the 'key_node' hmap_node, but\n  ovn_datapath::ports is keyed on 'dp_node' (per ovn_port_alloc()\n  paths in northd.c that hmap_insert() with &op->dp_node), so the\n  iteration container_of()'s a wrong field offset and produces a\n  garbage struct ovn_port * that crashes on the first deref.  Switch\n  to an inline HMAP_FOR_EACH (op, dp_node, &peer_switch_od->ports)\n  loop matching by op->key, which is the established pattern used\n  elsewhere in northd.c (e.g. ovn_port_find_port_or_child()) for\n  per-datapath port lookups.\n- No functional change in the lflow that is generated; only the way\n  the corresponding ovn_port is located.\n\n NEWS                |  7 ++++\n northd/northd.c     | 83 +++++++++++++++++++++++++++++++++++++++++++\n tests/ovn-northd.at | 86 +++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 176 insertions(+)","diff":"diff --git a/NEWS b/NEWS\nindex 8633ba8..b2a956c 100644\n--- a/NEWS\n+++ b/NEWS\n@@ -3,6 +3,13 @@ Post v26.03.0\n    - Dynamic Routing:\n      * Add support for hub-and-spoke propagation via the \"hub-spoke\" option\n        in dynamic-routing-redistribute settings.\n+   - Fixed Load_Balancer health checks for backends referenced via a\n+     Logical_Switch_Port whose type is \"external\" on a Logical_Switch that\n+     also has a localnet port (typical Neutron / ovn-octavia-provider\n+     baremetal pool member configuration).  Previously such backends\n+     remained permanently offline in Service_Monitor.status because the\n+     per-backend reply punt lflow's \"inport == <backend_lsp>\" match did\n+     not fit traffic that re-enters br-int through the localnet port.\n \n OVN v26.03.0 - xxx xx xxxx\n --------------------------\ndiff --git a/northd/northd.c b/northd/northd.c\nindex 0b52db6..879bfd1 100644\n--- a/northd/northd.c\n+++ b/northd/northd.c\n@@ -8962,6 +8962,89 @@ build_lb_health_check_response_lflows(\n             ovn_lflow_add(lflows, peer_switch_od, S_SWITCH_IN_L2_LKUP, 110,\n                           ds_cstr(match), \"handle_svc_check(inport);\",\n                           lb_dps->lflow_ref, WITH_CTRL_METER(meter));\n+\n+            /* The lflow above only matches replies whose ingress logical\n+             * inport is the backend LSP itself.  This holds for backends\n+             * behind tunnels or local OVS ports.  For backends whose LSP\n+             * is type=external on a Logical_Switch that has a localnet\n+             * port (typical for Neutron / ovn-octavia-provider baremetal\n+             * pool members on a provider VLAN), the reply re-enters\n+             * br-int through the localnet port; MFF_LOG_INPORT therefore\n+             * holds the localnet LSP's tunnel_key and the lflow above\n+             * never matches.  pinctrl_handle_svc_check() then fails its\n+             * (dp_key, port_key) lookup and Service_Monitor.status stays\n+             * 'offline' indefinitely, even though the backend is fully\n+             * reachable on the wire.\n+             *\n+             * Emit an additional reply punt lflow that:\n+             *  - identifies the backend by eth.src instead of inport,\n+             *  - loads the backend LSP's tunnel_key into MFF_LOG_INPORT\n+             *    via 'outport = \"<lsp>\"; handle_svc_check(outport);'\n+             *    (the latter borrows MFF_LOG_OUTPORT's value into\n+             *    MFF_LOG_INPORT for the controller dispatch),\n+             *  - resets outport to \"\" so the cleared MFF_LOG_OUTPORT\n+             *    does not leak into egress and reflect the reply back\n+             *    to the backend.\n+             */\n+            if (vector_is_empty(&peer_switch_od->localnet_ports)) {\n+                continue;\n+            }\n+            /* peer_switch_od->ports is an hmap keyed by 'dp_node' (not the\n+             * 'key_node' that ovn_port_find() expects), so iterate it with\n+             * HMAP_FOR_EACH directly to find the backend LSP by name. */\n+            struct ovn_port *backend_op = NULL;\n+            struct ovn_port *op;\n+            HMAP_FOR_EACH (op, dp_node, &peer_switch_od->ports) {\n+                if (op->nbsp && op->key\n+                    && !strcmp(op->key, backend_nb->logical_port)) {\n+                    backend_op = op;\n+                    break;\n+                }\n+            }\n+            if (!backend_op || !backend_op->nbsp || !backend_op->nbsp->type\n+                || strcmp(backend_op->nbsp->type, \"external\")\n+                || !backend_op->n_lsp_addrs) {\n+                continue;\n+            }\n+\n+            ds_clear(match);\n+            ds_clear(action);\n+\n+            const char *bm_mac = backend_op->lsp_addrs[0].ea_s;\n+            if (addr_is_ipv6(backend_nb->svc_mon_src_ip)) {\n+                ds_put_format(match, \"eth.src == %s && ip6.dst == %s && \"\n+                              \"ip6.src == %s && eth.dst == %s && \",\n+                              bm_mac,\n+                              backend_nb->svc_mon_src_ip,\n+                              backend->ip_str,\n+                              backend_nb->svc_mon_lrp->lrp_networks.ea_s);\n+                if (!strcmp(protocol, \"tcp\")) {\n+                    ds_put_format(match, \"tcp.src == %s\",\n+                                  backend->port_str);\n+                } else {\n+                    ds_put_cstr(match, \"icmp6.type == 1\");\n+                }\n+            } else {\n+                ds_put_format(match, \"eth.src == %s && ip4.dst == %s && \"\n+                              \"ip4.src == %s && eth.dst == %s && \",\n+                              bm_mac,\n+                              backend_nb->svc_mon_src_ip,\n+                              backend->ip_str,\n+                              backend_nb->svc_mon_lrp->lrp_networks.ea_s);\n+                if (!strcmp(protocol, \"tcp\")) {\n+                    ds_put_format(match, \"tcp.src == %s\",\n+                                  backend->port_str);\n+                } else {\n+                    ds_put_cstr(match, \"icmp4.type == 3\");\n+                }\n+            }\n+            ds_put_format(action,\n+                          \"outport = \\\"%s\\\"; handle_svc_check(outport); \"\n+                          \"outport = \\\"\\\";\",\n+                          backend_nb->logical_port);\n+            ovn_lflow_add(lflows, peer_switch_od, S_SWITCH_IN_L2_LKUP, 110,\n+                          ds_cstr(match), ds_cstr(action),\n+                          lb_dps->lflow_ref, WITH_CTRL_METER(meter));\n         }\n     }\n }\ndiff --git a/tests/ovn-northd.at b/tests/ovn-northd.at\nindex 1d7bd6c..c95ce39 100644\n--- a/tests/ovn-northd.at\n+++ b/tests/ovn-northd.at\n@@ -20672,3 +20672,89 @@ check_column \"$global_svc_mon_mac\" sb:Service_Monitor src_mac port=2\n OVN_CLEANUP_NORTHD\n AT_CLEANUP\n ])\n+\n+OVN_FOR_EACH_NORTHD_NO_HV_PARALLELIZATION([\n+AT_SETUP([Load balancer health checks - external LSP backend on localnet LS])\n+ovn_start\n+\n+dnl Topology:\n+dnl   lr0  --  ls-tenant (vm-port: type=\"\", 10.0.0.10)\n+dnl     \\---  ls-prov   (bm-port: type=external, 192.168.0.10\n+dnl                       MAC 02:bb:bb:00:00:01;\n+dnl                      provnet-physnet1: type=localnet)\n+dnl\n+dnl LB lb0 attached to lr0:\n+dnl   vip 10.10.10.10:80 -> 10.0.0.10:80,192.168.0.10:80 (tcp)\n+dnl   ip_port_mappings: 10.0.0.10  = vm-port:10.0.0.1\n+dnl                     192.168.0.10 = bm-port:192.168.0.1\n+dnl\n+dnl Expectation:\n+dnl   1) On ls-tenant the existing per-backend reply lflow is emitted\n+dnl      with `inport == \"vm-port\"`.\n+dnl   2) On ls-prov  the existing per-backend reply lflow is emitted\n+dnl      with `inport == \"bm-port\"` AND, additionally, the new lflow\n+dnl      added by this commit is emitted with `eth.src == <bm-mac>`\n+dnl      and action `outport = \"bm-port\"; handle_svc_check(outport);\n+dnl      outport = \"\";`.\n+\n+check ovn-nbctl                                                 \\\n+    -- lr-add lr0                                               \\\n+      -- lrp-add lr0 lr0-tenant 02:00:00:00:01:01 10.0.0.1/24   \\\n+      -- lrp-add lr0 lr0-prov   02:00:00:00:02:01 192.168.0.1/24\n+\n+check ovn-nbctl                                                 \\\n+    -- ls-add ls-tenant                                         \\\n+      -- lsp-add ls-tenant ls-tenant-lr0                        \\\n+      -- lsp-set-type      ls-tenant-lr0 router                 \\\n+      -- lsp-set-options   ls-tenant-lr0 router-port=lr0-tenant \\\n+      -- lsp-set-addresses ls-tenant-lr0 router                 \\\n+      -- lsp-add ls-tenant vm-port                              \\\n+      -- lsp-set-addresses vm-port \"02:aa:aa:00:00:01 10.0.0.10\"\n+\n+check ovn-nbctl                                                 \\\n+    -- ls-add ls-prov                                           \\\n+      -- lsp-add ls-prov ls-prov-lr0                            \\\n+      -- lsp-set-type      ls-prov-lr0 router                   \\\n+      -- lsp-set-options   ls-prov-lr0 router-port=lr0-prov     \\\n+      -- lsp-set-addresses ls-prov-lr0 router                   \\\n+      -- lsp-add ls-prov bm-port                                \\\n+      -- lsp-set-type      bm-port external                     \\\n+      -- lsp-set-addresses bm-port \"02:bb:bb:00:00:01 192.168.0.10\" \\\n+      -- lsp-add ls-prov provnet-physnet1                       \\\n+      -- lsp-set-type      provnet-physnet1 localnet            \\\n+      -- lsp-set-addresses provnet-physnet1 unknown             \\\n+      -- lsp-set-options   provnet-physnet1 network_name=physnet1\n+\n+check ovn-nbctl --wait=sb lb-add lb0 \\\n+    10.10.10.10:80 10.0.0.10:80,192.168.0.10:80 tcp\n+lb0=$(fetch_column nb:Load_Balancer _uuid name=lb0)\n+check ovn-nbctl                                                          \\\n+    -- set load_balancer $lb0 ip_port_mappings:10.0.0.10=vm-port:10.0.0.1 \\\n+    -- set load_balancer $lb0 ip_port_mappings:192.168.0.10=bm-port:192.168.0.1\n+\n+check_uuid ovn-nbctl --id=@hc create Load_Balancer_Health_Check    \\\n+    vip=\"10.10.10.10\\:80\" -- add Load_Balancer $lb0 health_check @hc\n+check ovn-nbctl --wait=sb lr-lb-add lr0 lb0\n+\n+dnl Existing per-backend reply lflow on the tenant (VM) datapath.\n+AT_CHECK([ovn-sbctl lflow-list ls-tenant | grep handle_svc_check | ovn_strip_lflows], [0], [dnl\n+  table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), action=(handle_svc_check(inport);)\n+  table=??(ls_in_l2_lkup      ), priority=110  , match=(inport == \"vm-port\" && ip4.dst == 10.0.0.1 && ip4.src == 10.0.0.10 && eth.dst == 02:00:00:00:01:01 && tcp.src == 80), action=(handle_svc_check(inport);)\n+])\n+\n+dnl On the provider datapath, BOTH the existing per-backend reply lflow\n+dnl AND the new external-LSP reply lflow added by this commit must be\n+dnl present.  The new lflow uses eth.src to identify the backend (so it\n+dnl matches replies that re-enter via the localnet port) and forces\n+dnl MFF_LOG_INPORT to the backend LSP's tunnel_key by going through\n+dnl outport, then resets outport to \"\" to avoid reflecting the reply\n+dnl back to the backend.\n+AT_CHECK([ovn-sbctl lflow-list ls-prov | grep handle_svc_check | ovn_strip_lflows], [0], [dnl\n+  table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), action=(handle_svc_check(inport);)\n+  table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.src == 02:bb:bb:00:00:01 && ip4.dst == 192.168.0.1 && ip4.src == 192.168.0.10 && eth.dst == 02:00:00:00:02:01 && tcp.src == 80), action=(outport = \"bm-port\"; handle_svc_check(outport); outport = \"\";)\n+  table=??(ls_in_l2_lkup      ), priority=110  , match=(inport == \"bm-port\" && ip4.dst == 192.168.0.1 && ip4.src == 192.168.0.10 && eth.dst == 02:00:00:00:02:01 && tcp.src == 80), action=(handle_svc_check(inport);)\n+])\n+\n+OVN_CLEANUP_NORTHD\n+AT_CLEANUP\n+])\n","prefixes":["ovs-dev","v2"]}