diff mbox series

[ovs-dev,v3,1/2] northd: sync lb applied to logical routers in sb db lb table

Message ID a525827a8939498807cd71c0814956a4894d2faa.1695740554.git.lorenzo.bianconi@redhat.com
State Accepted
Delegated to: Dumitru Ceara
Headers show
Series sync lb applied to logical routers in sb db lb table | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/github-robot-_ovn-kubernetes fail github build: failed

Commit Message

Lorenzo Bianconi Sept. 26, 2023, 3:18 p.m. UTC
Introduce lr_datapath_group column in the load_balancer table of the SB
db.
Sync load_balancers applied to logical_routers to Load_Balancer table in
the SouthBound database.

Reviewed-by: Ales Musil <amusil@redhat.com>
Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2193323
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
---
 controller/local_data.c     |   8 +++
 controller/ovn-controller.c |   6 ++
 northd/en-sync-sb.c         |   3 +-
 northd/northd.c             |  90 ++++++++++++++++++++-------
 northd/northd.h             |   4 +-
 ovn-sb.ovsschema            |   6 +-
 ovn-sb.xml                  |   6 ++
 tests/ovn-northd.at         |  17 +++++-
 tests/system-ovn.at         | 117 ++++++++++++++++++++++++++++++++++++
 9 files changed, 230 insertions(+), 27 deletions(-)

Comments

Dumitru Ceara Oct. 10, 2023, 1:35 p.m. UTC | #1
On 9/26/23 17:18, Lorenzo Bianconi wrote:
> Introduce lr_datapath_group column in the load_balancer table of the SB
> db.
> Sync load_balancers applied to logical_routers to Load_Balancer table in
> the SouthBound database.
> 
> Reviewed-by: Ales Musil <amusil@redhat.com>
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2193323
> Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
> ---

Thanks, Lorenzo, Ales and Ilya!

We ran this through scale tests internally (ovn-heater and OpenShift)
and didn't notice a worrying performance hit.  I applied the patch to
main with the following minor changes:

diff --git a/northd/northd.c b/northd/northd.c
index 00abf680f8..f5dabf70c0 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -4652,13 +4652,12 @@ sync_lbs(struct ovsdb_idl_txn *ovnsb_txn,
         sbrec_load_balancer_set_vips(sbrec_lb,
                                      ovn_northd_lb_get_vips(lb_dps->lb));
         sbrec_load_balancer_set_protocol(sbrec_lb, lb_dps->lb->nlb->protocol);
-        if (lb_dpg) {
-            sbrec_load_balancer_set_datapath_group(sbrec_lb, lb_dpg->dp_group);
-        }
-        if (lb_lr_dpg) {
-            sbrec_load_balancer_set_lr_datapath_group(sbrec_lb,
-                                                      lb_lr_dpg->dp_group);
-        }
+        sbrec_load_balancer_set_datapath_group(
+            sbrec_lb, lb_dpg ? lb_dpg->dp_group : NULL
+        );
+        sbrec_load_balancer_set_lr_datapath_group(
+            sbrec_lb, lb_lr_dpg ? lb_lr_dpg->dp_group : NULL
+        );
         sbrec_load_balancer_set_options(sbrec_lb, &options);
         /* Clearing 'datapaths' column, since 'dp_group' is in use. */
         sbrec_load_balancer_set_datapaths(sbrec_lb, NULL, 0);
diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
index a66db998f1..49407081a8 100644
--- a/ovn-sb.ovsschema
+++ b/ovn-sb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_Southbound",
-    "version": "20.27.4",
-    "cksum": "146375056 30745",
+    "version": "20.28.0",
+    "cksum": "2567491918 30745",
     "tables": {
         "SB_Global": {
             "columns": {
             "columns": {
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index 2b52d72231..d70ad89863 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -11798,14 +11798,11 @@ check ovn-nbctl lsp-add public public-vm \
 ADD_NAMESPACES(sw0-vm)
 ADD_VETH(sw0-vm, sw0-vm, br-int, "192.168.1.2/24", "00:00:01:01:02:04", \
          "192.168.1.1")
-OVS_WAIT_UNTIL([test "$(ip netns exec sw0-vm ip a | grep fe80 | grep tentative)" = ""])
 
 ADD_NAMESPACES(public-vm)
 ADD_VETH(public-vm, public-vm, br-int, "172.16.1.2/24", "00:00:02:01:02:04", \
          "172.16.1.1")
 
-OVS_WAIT_UNTIL([test "$(ip netns exec public-vm ip a | grep fe80 | grep tentative)" = ""])
-
 # Start webservers in 'server'.
 OVS_START_L7([sw0-vm], [http])
 
@@ -11825,7 +11822,7 @@ OVS_WAIT_FOR_OUTPUT([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.150) |
 1
 ])
 
-check ovn-nbctl lb-del lb1
+check ovn-nbctl --wait=hv lb-del lb1
 
 OVS_WAIT_FOR_OUTPUT([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.150) | wc -l ], [0], [dnl
 0
@@ -11845,7 +11842,7 @@ OVS_WAIT_FOR_OUTPUT([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.151) |
 1
 ])
 
-check ovn-nbctl lb-del lb2
+check ovn-nbctl --wait=hv lb-del lb2
 
 OVS_WAIT_FOR_OUTPUT([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.151) | wc -l ], [0], [dnl
 1
---

Regards,
Dumitru
Ales Musil Oct. 10, 2023, 2:27 p.m. UTC | #2
On Tue, Oct 10, 2023 at 3:36 PM Dumitru Ceara <dceara@redhat.com> wrote:

> On 9/26/23 17:18, Lorenzo Bianconi wrote:
> > Introduce lr_datapath_group column in the load_balancer table of the SB
> > db.
> > Sync load_balancers applied to logical_routers to Load_Balancer table in
> > the SouthBound database.
> >
> > Reviewed-by: Ales Musil <amusil@redhat.com>
> > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2193323
> > Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
> > ---
>
> Thanks, Lorenzo, Ales and Ilya!
>
> We ran this through scale tests internally (ovn-heater and OpenShift)
> and didn't notice a worrying performance hit.  I applied the patch to
> main with the following minor changes:
>
> diff --git a/northd/northd.c b/northd/northd.c
> index 00abf680f8..f5dabf70c0 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -4652,13 +4652,12 @@ sync_lbs(struct ovsdb_idl_txn *ovnsb_txn,
>          sbrec_load_balancer_set_vips(sbrec_lb,
>                                       ovn_northd_lb_get_vips(lb_dps->lb));
>          sbrec_load_balancer_set_protocol(sbrec_lb,
> lb_dps->lb->nlb->protocol);
> -        if (lb_dpg) {
> -            sbrec_load_balancer_set_datapath_group(sbrec_lb,
> lb_dpg->dp_group);
> -        }
> -        if (lb_lr_dpg) {
> -            sbrec_load_balancer_set_lr_datapath_group(sbrec_lb,
> -
> lb_lr_dpg->dp_group);
> -        }
> +        sbrec_load_balancer_set_datapath_group(
> +            sbrec_lb, lb_dpg ? lb_dpg->dp_group : NULL
> +        );
> +        sbrec_load_balancer_set_lr_datapath_group(
> +            sbrec_lb, lb_lr_dpg ? lb_lr_dpg->dp_group : NULL
> +        );
>          sbrec_load_balancer_set_options(sbrec_lb, &options);
>          /* Clearing 'datapaths' column, since 'dp_group' is in use. */
>          sbrec_load_balancer_set_datapaths(sbrec_lb, NULL, 0);
> diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
> index a66db998f1..49407081a8 100644
> --- a/ovn-sb.ovsschema
> +++ b/ovn-sb.ovsschema
> @@ -1,7 +1,7 @@
>  {
>      "name": "OVN_Southbound",
> -    "version": "20.27.4",
> -    "cksum": "146375056 30745",
> +    "version": "20.28.0",
> +    "cksum": "2567491918 30745",
>      "tables": {
>          "SB_Global": {
>              "columns": {
>              "columns": {
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index 2b52d72231..d70ad89863 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -11798,14 +11798,11 @@ check ovn-nbctl lsp-add public public-vm \
>  ADD_NAMESPACES(sw0-vm)
>  ADD_VETH(sw0-vm, sw0-vm, br-int, "192.168.1.2/24", "00:00:01:01:02:04", \
>           "192.168.1.1")
> -OVS_WAIT_UNTIL([test "$(ip netns exec sw0-vm ip a | grep fe80 | grep
> tentative)" = ""])
>
>  ADD_NAMESPACES(public-vm)
>  ADD_VETH(public-vm, public-vm, br-int, "172.16.1.2/24",
> "00:00:02:01:02:04", \
>           "172.16.1.1")
>
> -OVS_WAIT_UNTIL([test "$(ip netns exec public-vm ip a | grep fe80 | grep
> tentative)" = ""])
> -
>  # Start webservers in 'server'.
>  OVS_START_L7([sw0-vm], [http])
>
> @@ -11825,7 +11822,7 @@ OVS_WAIT_FOR_OUTPUT([ovs-appctl
> dpctl/dump-conntrack | FORMAT_CT(172.16.1.150) |
>  1
>  ])
>
> -check ovn-nbctl lb-del lb1
> +check ovn-nbctl --wait=hv lb-del lb1
>
>  OVS_WAIT_FOR_OUTPUT([ovs-appctl dpctl/dump-conntrack |
> FORMAT_CT(172.16.1.150) | wc -l ], [0], [dnl
>  0
> @@ -11845,7 +11842,7 @@ OVS_WAIT_FOR_OUTPUT([ovs-appctl
> dpctl/dump-conntrack | FORMAT_CT(172.16.1.151) |
>  1
>  ])
>
> -check ovn-nbctl lb-del lb2
> +check ovn-nbctl --wait=hv lb-del lb2
>
>  OVS_WAIT_FOR_OUTPUT([ovs-appctl dpctl/dump-conntrack |
> FORMAT_CT(172.16.1.151) | wc -l ], [0], [dnl
>  1
> ---
>
> Regards,
> Dumitru
>
>

Hi Dumitru,

would you mind backporting this series to 23.09 too? This was posted way
before any kind of freeze and it would be very nice to have it in 23.09.

Thanks,
Ales
Dumitru Ceara Oct. 10, 2023, 3:23 p.m. UTC | #3
On 10/10/23 16:27, Ales Musil wrote:
> Hi Dumitru,
> 
> would you mind backporting this series to 23.09 too? This was posted way
> before any kind of freeze and it would be very nice to have it in 23.09.
> 
> Thanks,
> Ales

Hi Ales,

Ok, that's reasonable.  Before I do that, however, it seems we need a
follow up fix.  Would you mind reviewing this too please?

https://patchwork.ozlabs.org/project/ovn/patch/20231010152020.372098-1-dceara@redhat.com/

Regards,
Dumitru
Ilya Maximets Oct. 10, 2023, 3:34 p.m. UTC | #4
On 10/10/23 16:27, Ales Musil wrote:
> 
> 
> On Tue, Oct 10, 2023 at 3:36 PM Dumitru Ceara <dceara@redhat.com <mailto:dceara@redhat.com>> wrote:
> 
>     On 9/26/23 17:18, Lorenzo Bianconi wrote:
>     > Introduce lr_datapath_group column in the load_balancer table of the SB
>     > db.
>     > Sync load_balancers applied to logical_routers to Load_Balancer table in
>     > the SouthBound database.
>     >
>     > Reviewed-by: Ales Musil <amusil@redhat.com <mailto:amusil@redhat.com>>
>     > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2193323 <https://bugzilla.redhat.com/show_bug.cgi?id=2193323>
>     > Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com <mailto:lorenzo.bianconi@redhat.com>>
>     > ---
> 
>     Thanks, Lorenzo, Ales and Ilya!
> 
>     We ran this through scale tests internally (ovn-heater and OpenShift)
>     and didn't notice a worrying performance hit.  I applied the patch to
>     main with the following minor changes:
> 

<snip>

>     ---
> 
>     Regards,
>     Dumitru
> 
> 
> 
> Hi Dumitru,
> 
> would you mind backporting this series to 23.09 too? This was posted way before
> any kind of freeze and it would be very nice to have it in 23.09.

FWIW, the freeze part is irrelevant because the release have already happened.

Not saying this feature/bagfix should not be backported, just picking on words. :)
General considerations regarding potential breaking changes should be applied
here instead.

Best regards, Ilya Maximets.
Dumitru Ceara Oct. 11, 2023, 12:48 p.m. UTC | #5
On 10/10/23 17:34, Ilya Maximets wrote:
> On 10/10/23 16:27, Ales Musil wrote:
>>
>>
>> On Tue, Oct 10, 2023 at 3:36 PM Dumitru Ceara <dceara@redhat.com <mailto:dceara@redhat.com>> wrote:
>>
>>     On 9/26/23 17:18, Lorenzo Bianconi wrote:
>>     > Introduce lr_datapath_group column in the load_balancer table of the SB
>>     > db.
>>     > Sync load_balancers applied to logical_routers to Load_Balancer table in
>>     > the SouthBound database.
>>     >
>>     > Reviewed-by: Ales Musil <amusil@redhat.com <mailto:amusil@redhat.com>>
>>     > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2193323 <https://bugzilla.redhat.com/show_bug.cgi?id=2193323>
>>     > Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com <mailto:lorenzo.bianconi@redhat.com>>
>>     > ---
>>
>>     Thanks, Lorenzo, Ales and Ilya!
>>
>>     We ran this through scale tests internally (ovn-heater and OpenShift)
>>     and didn't notice a worrying performance hit.  I applied the patch to
>>     main with the following minor changes:
>>
> 
> <snip>
> 
>>     ---
>>
>>     Regards,
>>     Dumitru
>>
>>
>>
>> Hi Dumitru,
>>
>> would you mind backporting this series to 23.09 too? This was posted way before
>> any kind of freeze and it would be very nice to have it in 23.09.
> 
> FWIW, the freeze part is irrelevant because the release have already happened.
> 
> Not saying this feature/bagfix should not be backported, just picking on words. :)
> General considerations regarding potential breaking changes should be applied
> here instead.
> 

The change is backwards compatible (the new column via a feature flag..)
and with the follow up fix applied [0] is safe to be backported.

I pushed this series to 23.09 too.

Thanks, Lorenzo, Ales and Ilya!

Regards,
Dumitru

[0]
https://patchwork.ozlabs.org/project/ovn/patch/20231010152020.372098-1-dceara@redhat.com/
diff mbox series

Patch

diff --git a/controller/local_data.c b/controller/local_data.c
index cf0b21bb1..01cfbdefe 100644
--- a/controller/local_data.c
+++ b/controller/local_data.c
@@ -670,5 +670,13 @@  lb_is_local(const struct sbrec_load_balancer *sbrec_lb,
         }
     }
 
+    dp_group = sbrec_lb->lr_datapath_group;
+    for (size_t i = 0; dp_group && i < dp_group->n_datapaths; i++) {
+        if (get_local_datapath(local_datapaths,
+                               dp_group->datapaths[i]->tunnel_key)) {
+            return true;
+        }
+    }
+
     return false;
 }
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index 859d9cab9..7acf42367 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -2809,6 +2809,12 @@  load_balancers_by_dp_init(const struct hmap *local_datapaths,
                                          lb->datapath_group->datapaths[i],
                                          lb, lbs);
         }
+        for (size_t i = 0; lb->lr_datapath_group
+                           && i < lb->lr_datapath_group->n_datapaths; i++) {
+            load_balancers_by_dp_add_one(local_datapaths,
+                                         lb->lr_datapath_group->datapaths[i],
+                                         lb, lbs);
+        }
     }
     return lbs;
 }
diff --git a/northd/en-sync-sb.c b/northd/en-sync-sb.c
index aae396a43..1a7e07051 100644
--- a/northd/en-sync-sb.c
+++ b/northd/en-sync-sb.c
@@ -220,7 +220,8 @@  en_sync_to_sb_lb_run(struct engine_node *node, void *data OVS_UNUSED)
     struct northd_data *northd_data = engine_get_input_data("northd", node);
 
     sync_lbs(eng_ctx->ovnsb_idl_txn, sb_load_balancer_table,
-             &northd_data->ls_datapaths, &northd_data->lb_datapaths_map);
+             &northd_data->ls_datapaths, &northd_data->lr_datapaths,
+             &northd_data->lb_datapaths_map);
     engine_set_node_state(node, EN_UPDATED);
 }
 
diff --git a/northd/northd.c b/northd/northd.c
index 528027d07..bc6f2893e 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -4510,6 +4510,7 @@  struct sb_lb {
 
     const struct sbrec_load_balancer *slb;
     struct ovn_dp_group *dpg;
+    struct ovn_dp_group *lr_dpg;
     struct uuid lb_uuid;
 };
 
@@ -4532,10 +4533,12 @@  find_slb_in_sb_lbs(struct hmap *sb_lbs, const struct uuid *lb_uuid)
 void
 sync_lbs(struct ovsdb_idl_txn *ovnsb_txn,
          const struct sbrec_load_balancer_table *sbrec_load_balancer_table,
-         struct ovn_datapaths *ls_datapaths, struct hmap *lb_dps_map)
+         struct ovn_datapaths *ls_datapaths,
+         struct ovn_datapaths *lr_datapaths,
+         struct hmap *lb_dps_map)
 {
-    struct hmap dp_groups = HMAP_INITIALIZER(&dp_groups);
-    size_t bitmap_len = ods_size(ls_datapaths);
+    struct hmap ls_dp_groups = HMAP_INITIALIZER(&ls_dp_groups);
+    struct hmap lr_dp_groups = HMAP_INITIALIZER(&lr_dp_groups);
     struct ovn_lb_datapaths *lb_dps;
     struct hmap sb_lbs = HMAP_INITIALIZER(&sb_lbs);
 
@@ -4553,7 +4556,8 @@  sync_lbs(struct ovsdb_idl_txn *ovnsb_txn,
         }
 
         /* Delete any SB load balancer entries that refer to NB load balancers
-         * that don't exist anymore or are not applied to switches anymore.
+         * that don't exist anymore or are not applied to switches/routers
+         * anymore.
          *
          * There is also a special case in which duplicate LBs might be created
          * in the SB, e.g., due to the fact that OVSDB only ensures
@@ -4561,7 +4565,8 @@  sync_lbs(struct ovsdb_idl_txn *ovnsb_txn,
          * are not indexed in any way.
          */
         lb_dps = ovn_lb_datapaths_find(lb_dps_map, &lb_uuid);
-        if (!lb_dps || !lb_dps->n_nb_ls || !hmapx_add(&existing_lbs, lb_dps)) {
+        if (!lb_dps || (!lb_dps->n_nb_ls && !lb_dps->n_nb_lr) ||
+            !hmapx_add(&existing_lbs, lb_dps)) {
             sbrec_load_balancer_delete(sbrec_lb);
             continue;
         }
@@ -4572,12 +4577,22 @@  sync_lbs(struct ovsdb_idl_txn *ovnsb_txn,
         hmap_insert(&sb_lbs, &sb_lb->hmap_node, uuid_hash(&lb_uuid));
 
         /* Find or create datapath group for this load balancer. */
-        sb_lb->dpg = ovn_dp_group_get_or_create(ovnsb_txn, &dp_groups,
-                                                sb_lb->slb->datapath_group,
-                                                lb_dps->n_nb_ls,
-                                                lb_dps->nb_ls_map,
-                                                bitmap_len, true,
-                                                ls_datapaths, NULL);
+        if (lb_dps->n_nb_ls) {
+            sb_lb->dpg = ovn_dp_group_get_or_create(
+                    ovnsb_txn, &ls_dp_groups,
+                    sb_lb->slb->datapath_group,
+                    lb_dps->n_nb_ls, lb_dps->nb_ls_map,
+                    ods_size(ls_datapaths), true,
+                    ls_datapaths, NULL);
+        }
+        if (lb_dps->n_nb_lr) {
+            sb_lb->lr_dpg = ovn_dp_group_get_or_create(
+                    ovnsb_txn, &lr_dp_groups,
+                    sb_lb->slb->lr_datapath_group,
+                    lb_dps->n_nb_lr, lb_dps->nb_lr_map,
+                    ods_size(lr_datapaths), false,
+                    NULL, lr_datapaths);
+        }
     }
     hmapx_destroy(&existing_lbs);
 
@@ -4585,7 +4600,7 @@  sync_lbs(struct ovsdb_idl_txn *ovnsb_txn,
      * the SB load balancer columns. */
     HMAP_FOR_EACH (lb_dps, hmap_node, lb_dps_map) {
 
-        if (!lb_dps->n_nb_ls) {
+        if (!lb_dps->n_nb_ls && !lb_dps->n_nb_lr) {
             continue;
         }
 
@@ -4598,8 +4613,8 @@  sync_lbs(struct ovsdb_idl_txn *ovnsb_txn,
 
         struct sb_lb *sb_lb = find_slb_in_sb_lbs(&sb_lbs,
                                             &lb_dps->lb->nlb->header_.uuid);
-        ovs_assert(!sb_lb || (sb_lb->slb && sb_lb->dpg));
-        struct ovn_dp_group *lb_dpg = NULL;
+        ovs_assert(!sb_lb || (sb_lb->slb && (sb_lb->dpg || sb_lb->lr_dpg)));
+        struct ovn_dp_group *lb_dpg = NULL, *lb_lr_dpg = NULL;
         if (!sb_lb) {
             sbrec_lb = sbrec_load_balancer_insert(ovnsb_txn);
             char *lb_id = xasprintf(
@@ -4611,15 +4626,25 @@  sync_lbs(struct ovsdb_idl_txn *ovnsb_txn,
         } else {
             sbrec_lb = sb_lb->slb;
             lb_dpg = sb_lb->dpg;
+            lb_lr_dpg = sb_lb->lr_dpg;
         }
 
         /* Find or create datapath group for this load balancer. */
-        if (!lb_dpg) {
-            lb_dpg = ovn_dp_group_get_or_create(ovnsb_txn, &dp_groups,
-                                                sbrec_lb->datapath_group,
-                                                lb_dps->n_nb_ls,
-                                                lb_dps->nb_ls_map, bitmap_len,
-                                                true, ls_datapaths, NULL);
+        if (!lb_dpg && lb_dps->n_nb_ls) {
+            lb_dpg = ovn_dp_group_get_or_create(
+                    ovnsb_txn, &ls_dp_groups,
+                    sbrec_lb->datapath_group,
+                    lb_dps->n_nb_ls, lb_dps->nb_ls_map,
+                    ods_size(ls_datapaths), true,
+                    ls_datapaths, NULL);
+        }
+        if (!lb_lr_dpg && lb_dps->n_nb_lr) {
+            lb_lr_dpg = ovn_dp_group_get_or_create(
+                    ovnsb_txn, &lr_dp_groups,
+                    sbrec_lb->lr_datapath_group,
+                    lb_dps->n_nb_lr, lb_dps->nb_lr_map,
+                    ods_size(lr_datapaths), false,
+                    NULL, lr_datapaths);
         }
 
         /* Update columns. */
@@ -4627,7 +4652,13 @@  sync_lbs(struct ovsdb_idl_txn *ovnsb_txn,
         sbrec_load_balancer_set_vips(sbrec_lb,
                                      ovn_northd_lb_get_vips(lb_dps->lb));
         sbrec_load_balancer_set_protocol(sbrec_lb, lb_dps->lb->nlb->protocol);
-        sbrec_load_balancer_set_datapath_group(sbrec_lb, lb_dpg->dp_group);
+        if (lb_dpg) {
+            sbrec_load_balancer_set_datapath_group(sbrec_lb, lb_dpg->dp_group);
+        }
+        if (lb_lr_dpg) {
+            sbrec_load_balancer_set_lr_datapath_group(sbrec_lb,
+                                                      lb_lr_dpg->dp_group);
+        }
         sbrec_load_balancer_set_options(sbrec_lb, &options);
         /* Clearing 'datapaths' column, since 'dp_group' is in use. */
         sbrec_load_balancer_set_datapaths(sbrec_lb, NULL, 0);
@@ -4635,11 +4666,17 @@  sync_lbs(struct ovsdb_idl_txn *ovnsb_txn,
     }
 
     struct ovn_dp_group *dpg;
-    HMAP_FOR_EACH_POP (dpg, node, &dp_groups) {
+    HMAP_FOR_EACH_POP (dpg, node, &ls_dp_groups) {
+        bitmap_free(dpg->bitmap);
+        free(dpg);
+    }
+    hmap_destroy(&ls_dp_groups);
+
+    HMAP_FOR_EACH_POP (dpg, node, &lr_dp_groups) {
         bitmap_free(dpg->bitmap);
         free(dpg);
     }
-    hmap_destroy(&dp_groups);
+    hmap_destroy(&lr_dp_groups);
 
     struct sb_lb *sb_lb;
     HMAP_FOR_EACH_POP (sb_lb, hmap_node, &sb_lbs) {
@@ -4654,6 +4691,13 @@  sync_lbs(struct ovsdb_idl_txn *ovnsb_txn,
     HMAP_FOR_EACH (od, key_node, &ls_datapaths->datapaths) {
         ovs_assert(od->nbs);
 
+        if (od->sb->n_load_balancers) {
+            sbrec_datapath_binding_set_load_balancers(od->sb, NULL, 0);
+        }
+    }
+    HMAP_FOR_EACH (od, key_node, &lr_datapaths->datapaths) {
+        ovs_assert(od->nbr);
+
         if (od->sb->n_load_balancers) {
             sbrec_datapath_binding_set_load_balancers(od->sb, NULL, 0);
         }
diff --git a/northd/northd.h b/northd/northd.h
index 05f4140d7..429dbdd21 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -364,7 +364,9 @@  const char *northd_get_svc_monitor_mac(void);
 const struct ovn_datapath *northd_get_datapath_for_port(
     const struct hmap *ls_ports, const char *port_name);
 void sync_lbs(struct ovsdb_idl_txn *, const struct sbrec_load_balancer_table *,
-              struct ovn_datapaths *ls_datapaths, struct hmap *lbs);
+              struct ovn_datapaths *ls_datapaths,
+              struct ovn_datapaths *lr_datapaths,
+              struct hmap *lbs);
 
 void sync_pbs(struct ovsdb_idl_txn *, struct hmap *ls_ports);
 bool sync_pbs_for_northd_ls_changes(struct tracked_ls_changes *);
diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
index 7b20aa21b..a66db998f 100644
--- a/ovn-sb.ovsschema
+++ b/ovn-sb.ovsschema
@@ -1,7 +1,7 @@ 
 {
     "name": "OVN_Southbound",
     "version": "20.27.4",
-    "cksum": "3194181501 30531",
+    "cksum": "146375056 30745",
     "tables": {
         "SB_Global": {
             "columns": {
@@ -534,6 +534,10 @@ 
                     {"type": {"key": {"type": "uuid",
                                       "refTable": "Logical_DP_Group"},
                               "min": 0, "max": 1}},
+                "lr_datapath_group":
+                    {"type": {"key": {"type": "uuid",
+                                      "refTable": "Logical_DP_Group"},
+                              "min": 0, "max": 1}},
                 "options": {
                      "type": {"key": "string",
                               "value": "string",
diff --git a/ovn-sb.xml b/ovn-sb.xml
index 46aedf973..df762ee96 100644
--- a/ovn-sb.xml
+++ b/ovn-sb.xml
@@ -4892,6 +4892,12 @@  tcp.flags = RST;
       means that the same load balancer applies to all datapaths in a group.
     </column>
 
+    <column name="lr_datapath_group">
+      The group of logical router datapaths to which this load balancer
+      applies to. This means that the same load balancer applies to all
+      datapaths in a group.
+    </column>
+
     <group title="Load_Balancer options">
     <column name="options" key="hairpin_snat_ip">
       IP to be used as source IP for packets that have been hair-pinned after
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 13c8a0d42..c8fff00a5 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -2898,6 +2898,15 @@  sb:load_balancer vips,protocol name=lbg0
 
 check ovn-nbctl lr-add lr0 -- add logical_router lr0 load_balancer_group $lbg
 check ovn-nbctl --wait=sb lr-lb-add lr0 lb0
+check_row_count sb:load_balancer 2
+
+lr0_sb_uuid=$(fetch_column datapath_binding _uuid external_ids:name=lr0)
+lb0_lr_dp_group=$(fetch_column sb:load_balancer lr_datapath_group name=lb0)
+
+AT_CHECK_UNQUOTED([ovn-sbctl --bare --columns _uuid,datapaths find Logical_DP_Group dnl
+                    | grep -A1 $lb0_lr_dp_group | tail -1], [0], [dnl
+$lr0_sb_uuid
+])
 
 echo
 echo "__file__:__line__: Check that SB lb0 has only sw0 in datapaths column."
@@ -2943,7 +2952,13 @@  check_row_count sb:load_balancer 2
 lbg1=$(fetch_column nb:load_balancer _uuid name=lbg1)
 check ovn-nbctl add load_balancer_group $lbg load_balancer $lbg1
 check ovn-nbctl --wait=sb lr-lb-add lr0 lb1
-check_row_count sb:load_balancer 3
+check_row_count sb:load_balancer 4
+
+lb1_lr_dp_group=$(fetch_column sb:load_balancer lr_datapath_group name=lb1)
+AT_CHECK_UNQUOTED([ovn-sbctl --bare --columns _uuid,datapaths find Logical_DP_Group dnl
+                    | grep -A1 $lb1_lr_dp_group | tail -1], [0], [dnl
+$lr0_sb_uuid
+])
 
 echo
 echo "__file__:__line__: Associate lb1 to sw1 and check that lb1 is created in SB DB."
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index 75611c1d5..2b52d7223 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -11751,3 +11751,120 @@  OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
 
 AT_CLEANUP
 ])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([ct_flush on logical router load balancer])
+AT_KEYWORDS([ct-lr-flush])
+CHECK_CONNTRACK()
+CHECK_CONNTRACK_NAT()
+ovn_start
+OVS_TRAFFIC_VSWITCHD_START()
+ADD_BR([br-int])
+
+# Set external-ids in br-int needed for ovn-controller
+ovs-vsctl \
+        -- set Open_vSwitch . external-ids:system-id=hv1 \
+        -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
+        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
+        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
+        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
+
+start_daemon ovn-controller
+
+check ovn-nbctl lr-add R1
+
+check ovn-nbctl ls-add sw0
+check ovn-nbctl ls-add public
+
+check ovn-nbctl lrp-add R1 rp-sw0 00:00:01:01:02:03 192.168.1.1/24
+check ovn-nbctl lrp-add R1 rp-public 00:00:02:01:02:03 172.16.1.1/24
+
+check ovn-nbctl set logical_router R1 options:chassis=hv1
+
+check ovn-nbctl lsp-add sw0 sw0-rp -- set Logical_Switch_Port sw0-rp \
+    type=router options:router-port=rp-sw0 \
+    -- lsp-set-addresses sw0-rp router
+
+check ovn-nbctl lsp-add sw0 sw0-vm \
+    -- lsp-set-addresses sw0-vm "00:00:01:01:02:04 192.168.1.2/24"
+
+check ovn-nbctl lsp-add public public-rp -- set Logical_Switch_Port public-rp \
+    type=router options:router-port=rp-public \
+    -- lsp-set-addresses public-rp router
+
+check ovn-nbctl lsp-add public public-vm \
+   -- lsp-set-addresses public-vm "00:00:02:01:02:04 172.16.1.2/24"
+
+ADD_NAMESPACES(sw0-vm)
+ADD_VETH(sw0-vm, sw0-vm, br-int, "192.168.1.2/24", "00:00:01:01:02:04", \
+         "192.168.1.1")
+OVS_WAIT_UNTIL([test "$(ip netns exec sw0-vm ip a | grep fe80 | grep tentative)" = ""])
+
+ADD_NAMESPACES(public-vm)
+ADD_VETH(public-vm, public-vm, br-int, "172.16.1.2/24", "00:00:02:01:02:04", \
+         "172.16.1.1")
+
+OVS_WAIT_UNTIL([test "$(ip netns exec public-vm ip a | grep fe80 | grep tentative)" = ""])
+
+# Start webservers in 'server'.
+OVS_START_L7([sw0-vm], [http])
+
+# Create a load balancer and associate to R1
+check ovn-nbctl lb-add lb1 172.16.1.150:80 192.168.1.2:80 \
+    -- set load_balancer lb1 options:ct_flush="true"
+check ovn-nbctl lr-lb-add R1 lb1
+
+check ovn-nbctl --wait=hv sync
+
+for i in $(seq 1 5); do
+    echo Request $i
+    NS_CHECK_EXEC([public-vm], [wget 172.16.1.150 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
+done
+
+OVS_WAIT_FOR_OUTPUT([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.150) | wc -l ], [0], [dnl
+1
+])
+
+check ovn-nbctl lb-del lb1
+
+OVS_WAIT_FOR_OUTPUT([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.150) | wc -l ], [0], [dnl
+0
+])
+
+check ovn-nbctl lb-add lb2 172.16.1.151:80 192.168.1.2:80
+check ovn-nbctl lr-lb-add R1 lb2
+
+check ovn-nbctl --wait=hv sync
+
+for i in $(seq 1 5); do
+    echo Request $i
+    NS_CHECK_EXEC([public-vm], [wget 172.16.1.151 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
+done
+
+OVS_WAIT_FOR_OUTPUT([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.151) | wc -l ], [0], [dnl
+1
+])
+
+check ovn-nbctl lb-del lb2
+
+OVS_WAIT_FOR_OUTPUT([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.151) | wc -l ], [0], [dnl
+1
+])
+
+OVS_APP_EXIT_AND_WAIT([ovn-controller])
+
+as ovn-sb
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+
+as ovn-nb
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+
+as northd
+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE])
+
+as
+OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
+/Failed to acquire.*/d
+/connection dropped.*/d"])
+AT_CLEANUP
+])