Show a patch.

Update a patch.

Update a patch.

GET /api/patches/1554071/
Content-Type: application/json
Vary: Accept

    "id": 1554071,
    "url": "",
    "web_url": "",
    "project": {
        "id": 68,
        "url": "",
        "name": "Open Virtual Network development",
        "link_name": "ovn",
        "list_id": "",
        "list_email": "",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    "msgid": "<>",
    "list_archive_url": null,
    "date": "2021-11-11T19:13:06",
    "name": "[ovs-dev,v7,5/5] ic: don't learn routes which have local GW",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "70eb109b51d03e813e6ca2050de133734319cf4f",
    "submitter": {
        "id": 80943,
        "url": "",
        "name": "Vladislav Odintsov",
        "email": ""
    "delegate": null,
    "mbox": "",
    "series": [
            "id": 271600,
            "url": "",
            "web_url": "",
            "date": "2021-11-11T19:13:01",
            "name": "Add multiple routing tables support to Logical Routers",
            "version": 7,
            "mbox": ""
    "comments": "",
    "check": "success",
    "checks": "",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<>",
        "X-Original-To": [
        "Delivered-To": [
        "Authentication-Results": [
            ";\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.a=rsa-sha256\n header.s=20210112 header.b=mRLCiUJH;\n\tdkim-atps=neutral",
            ";\n spf=pass (sender SPF authorized)\n (client-ip=;;\n; receiver=<UNKNOWN>)",
            " (amavisd-new);\n dkim=pass (2048-bit key)"
        "Received": [
            "from ( [])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest\n SHA256)\n\t(No client certificate requested)\n\tby (Postfix) with ESMTPS id 4HqrwS4hbVz9s1l\n\tfor <>; Fri, 12 Nov 2021 06:13:28 +1100 (AEDT)",
            "from localhost (localhost [])\n\tby (Postfix) with ESMTP id 9103B81C38;\n\tThu, 11 Nov 2021 19:13:24 +0000 (UTC)",
            "from ([])\n\tby localhost ( []) (amavisd-new, port 10024)\n\twith ESMTP id qMGcCdV9HbLh; Thu, 11 Nov 2021 19:13:23 +0000 (UTC)",
            "from (\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby (Postfix) with ESMTPS id A0C8081CAD;\n\tThu, 11 Nov 2021 19:13:22 +0000 (UTC)",
            "from (localhost [])\n\tby (Postfix) with ESMTP id 71D69C0019;\n\tThu, 11 Nov 2021 19:13:22 +0000 (UTC)",
            "from ( [IPv6:2605:bc80:3010::133])\n by (Postfix) with ESMTP id 3449AC000E\n for <>; Thu, 11 Nov 2021 19:13:21 +0000 (UTC)",
            "from localhost (localhost [])\n by (Postfix) with ESMTP id F1D6B4046D\n for <>; Thu, 11 Nov 2021 19:13:20 +0000 (UTC)",
            "from ([])\n by localhost ( []) (amavisd-new, port 10024)\n with ESMTP id dvkmEi-n7c81 for <>;\n Thu, 11 Nov 2021 19:13:18 +0000 (UTC)",
            "from (\n [IPv6:2a00:1450:4864:20::135])\n by (Postfix) with ESMTPS id B14F340472\n for <>; Thu, 11 Nov 2021 19:13:17 +0000 (UTC)",
            "by with SMTP id b40so16452140lfv.10\n for <>; Thu, 11 Nov 2021 11:13:17 -0800 (PST)",
            "from localhost.localdomain (\n [])\n by with ESMTPSA id p26sm106915ljj.70.2021.\n (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128);\n Thu, 11 Nov 2021 11:13:15 -0800 (PST)"
        "X-Virus-Scanned": [
            "amavisd-new at",
            "amavisd-new at"
        "X-Greylist": "whitelisted by SQLgrey-1.8.0",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20210112;\n h=from:to:cc:subject:date:message-id:in-reply-to:references\n :mime-version:content-transfer-encoding;\n bh=cJbZqFLaZMmzrFduHtkVFI2V8YXTQ66GTeGA3jZYlVo=;\n b=mRLCiUJHKVfezkKtNxzbMKB7nP5tTAegeBiY8Fdg2udbZKQ/qyya1kwLGha+n7mWkS\n nW6LiSpa4DjRMQ+cLQoxiRK3+CMy7UMmUGj0Asbnrjw1B7znygebbEi2qRfFwg4ShCgx\n ovuo2WUw9/G38a6idFGoczygzpAqOz5EanM+PJdmt6r8ur2Q0c+EYZ9NIdEKQ2ZyacZP\n YljoQ58CsgkYWqiASe9sIJlUr9HRS4vrbW8bgDIS9YUov827fn43x95UoEjw67OpkRLx\n J1HBKBy/gWJmQYx5jeVrCTu3V5HR6g9BYdCCAA2V+5B93G09kQyIaEmkHrKZbWgdvkjq\n FxlQ==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n; s=20210112;\n h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n :references:mime-version:content-transfer-encoding;\n bh=cJbZqFLaZMmzrFduHtkVFI2V8YXTQ66GTeGA3jZYlVo=;\n b=wqcAV+gh5/NrXvgP7FQmFT4RxryKpEb7AQmO73f8lMY2I3G58AExATDSYrvrSgA3YP\n AchfdW4HFY9glNPd0J+AlS1PjnLN2NILuFs7w2E8KdwxYbdl/dUpRkUx4UAHa4HuUpdc\n XeMb9k12afPr/AH7WgObUi/HAS2PAJ6g0fn0LrSuXV83Tw8qkkDTcjBihu+pGbnDAW/z\n kq28VdkH/Tg1wfR7PDt8aSabAzVVmPDVbeX2311xiCZVA45Z/1J+Xg340y7KITcNubfN\n ensOPFqFpDq55AY4htYYfY+c+fsVALIIVj+Xo/inyjBbPvAOBwf/qihL69IBB/Qanotb\n uyzA==",
        "X-Gm-Message-State": "AOAM5321t+DGqz/5nOuANpdoJFqD/gXHmpgFgU7jdmhuDNSonSX2Uh3z\n umNbFP3NgSxJzjRfA/Du7C79L73si0+PlA==",
        "X-Google-Smtp-Source": "\n ABdhPJxRPsqPgZGtJQzWfstMcaloF2b0r7QOJiNEEBYqB8Oy2lFpv5RjGAqqKvJEZturpXp4igqNWw==",
        "X-Received": "by 2002:a05:6512:108a:: with SMTP id\n j10mr8378038lfg.557.1636657995444;\n Thu, 11 Nov 2021 11:13:15 -0800 (PST)",
        "From": "Vladislav Odintsov <>",
        "To": "",
        "Date": "Thu, 11 Nov 2021 22:13:06 +0300",
        "Message-Id": "<>",
        "X-Mailer": "git-send-email 2.30.0",
        "In-Reply-To": "<>",
        "References": "<>",
        "MIME-Version": "1.0",
        "Cc": "Vladislav Odintsov <>",
        "Subject": "[ovs-dev] [PATCH ovn v7 5/5] ic: don't learn routes which have\n\tlocal GW",
        "X-BeenThere": "",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "<>",
        "List-Unsubscribe": "<>,\n <>",
        "List-Archive": "<>",
        "List-Post": "<>",
        "List-Help": "<>",
        "List-Subscribe": "<>,\n <>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "",
        "Sender": "\"dev\" <>"
    "content": "In case we have ovn-ic-interconnected Logical_Routers\nand install same ip_prefix route with GW in local AZ\nin each LR in each AZ, this route would be learned in\nother AZs and L3 loop is possible.\nThere could be next routes output:\n\n[az1 ~]$ ovn-nbctl lr-route-list lr0\nIPv4 Routes\nRoute Table global:\n          dst-ip ecmp\n        dst-ip (learned) ecmp\n\n[az2 ~]$ ovn-nbctl lr-route-list lr0\nIPv4 Routes\nRoute Table global:\n          dst-ip ecmp\n        dst-ip (learned) ecmp\n\nSo, there is a possible routing loop. Packets going\nto could go from AZ1 to AZ2 and on AZ2\nthey can be routed back.\n\nThis commit adds check for installed local (non-learned)\nroutes. If OVN IC route's ip_prefix, route_table are\nthe same with already installed non-learned NB route, such\nroute wouldn't be learned.\n\nSigned-off-by: Vladislav Odintsov <>\n---\n ic/ovn-ic.c           | 30 ++++++++++++++++++++++++--\n tests/       | 49 +++++++++++++++++++++++++++++++++++++++++++\n utilities/ovn-nbctl.c |  4 +++-\n 3 files changed, 80 insertions(+), 3 deletions(-)",
    "diff": "diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c\nindex f40468e92..a9b797af2 100644\n--- a/ic/ovn-ic.c\n+++ b/ic/ovn-ic.c\n@@ -1209,7 +1209,25 @@ add_network_to_routes_ad(struct hmap *routes_ad, const char *network,\n }\n \n static bool\n-route_need_learn(struct in6_addr *prefix, unsigned int plen,\n+route_has_local_gw(const struct nbrec_logical_router *lr,\n+                   const char *route_table, const char *ip_prefix) {\n+\n+    const struct nbrec_logical_router_static_route *route;\n+    for (int i = 0; i < lr->n_static_routes; i++) {\n+        route = lr->static_routes[i];\n+        if (!smap_get(&route->external_ids, \"ic-learned-route\") &&\n+            !strcmp(route->route_table, route_table) &&\n+            !strcmp(route->ip_prefix, ip_prefix)) {\n+            return true;\n+        }\n+    }\n+    return false;\n+}\n+\n+static bool\n+route_need_learn(const struct nbrec_logical_router *lr,\n+                 const struct icsbrec_route *isb_route,\n+                 struct in6_addr *prefix, unsigned int plen,\n                  const struct smap *nb_options)\n {\n     if (!smap_get_bool(nb_options, \"ic-route-learn\", false)) {\n@@ -1229,6 +1247,12 @@ route_need_learn(struct in6_addr *prefix, unsigned int plen,\n         return false;\n     }\n \n+    if (route_has_local_gw(lr, isb_route->route_table, isb_route->ip_prefix)) {\n+        VLOG_DBG(\"Skip learning %s (rtb:%s) route, as we've got one with \"\n+                 \"local GW\", isb_route->ip_prefix, isb_route->route_table);\n+        return false;\n+    }\n+\n     return true;\n }\n \n@@ -1333,9 +1357,11 @@ sync_learned_routes(struct ic_context *ctx,\n                              isb_route->nexthop);\n                 continue;\n             }\n-            if (!route_need_learn(&prefix, plen, &nb_global->options)) {\n+            if (!route_need_learn(ic_lr->lr, isb_route, &prefix, plen,\n+                                  &nb_global->options)) {\n                 continue;\n             }\n+\n             struct ic_route_info *route_learned\n                 = ic_route_find(&ic_lr->routes_learned, &prefix, plen,\n                                 &nexthop, isb_route->origin,\ndiff --git a/tests/ b/tests/\nindex 1340874d5..a189a8fed 100644\n--- a/tests/\n+++ b/tests/\n@@ -928,3 +928,52 @@ OVN_CLEANUP_IC([az1], [az2])\n \n AT_CLEANUP\n ])\n+\n+OVN_FOR_EACH_NORTHD([\n+AT_SETUP([ovn-ic -- same routes destination])\n+\n+ovn_init_ic_db\n+ovn-ic-nbctl ts-add ts1\n+\n+for i in 1 2; do\n+    ovn_start az$i\n+    ovn_as az$i\n+\n+    # Enable route learning at AZ level\n+    ovn-nbctl set nb_global . options:ic-route-learn=true\n+    ovn-nbctl set nb_global . options:ic-route-learn-default=true\n+    # Enable route advertising at AZ level\n+    ovn-nbctl set nb_global . options:ic-route-adv=true\n+    ovn-nbctl set nb_global . options:ic-route-adv-default=true\n+\n+    lr=lr1$i\n+    ovn-nbctl lr-add $lr\n+\n+    lrp=lrp-$lr-ts1\n+    lsp=lsp-ts1-$lr\n+    # Create LRP and connect to TS\n+    ovn-nbctl lrp-add $lr $lrp aa:aa:aa:aa:aa:0$i 169.254.100.$i/24\n+    ovn-nbctl lsp-add ts1 $lsp \\\n+        -- lsp-set-addresses $lsp router \\\n+        -- lsp-set-type $lsp router \\\n+        -- lsp-set-options $lsp router-port=$lrp\n+    ovn-nbctl lrp-add $lr lrp-local-subnet 00:00:00:00:00:0$i 192.168.$i.1/24\n+    ovn-nbctl list logical-router-static-route\n+    check ovn-nbctl lr-route-add $lr 192.168.$i.10\n+    check ovn-nbctl lr-route-add $lr 192.168.$i.11\n+done\n+\n+AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep dst-ip | sort], [0], [dnl\n+           dst-ip\n+         dst-ip\n+     dst-ip (learned)\n+])\n+\n+AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr12 | grep dst-ip | sort], [0], [dnl\n+           dst-ip\n+         dst-ip\n+     dst-ip (learned)\n+])\n+\n+AT_CLEANUP\n+])\ndiff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c\nindex 8bdcb19a3..17bb5d41d 100644\n--- a/utilities/ovn-nbctl.c\n+++ b/utilities/ovn-nbctl.c\n@@ -4104,6 +4104,8 @@ nbctl_pre_lr_route_add(struct ctl_context *ctx)\n                          &nbrec_logical_router_static_route_col_options);\n     ovsdb_idl_add_column(ctx->idl,\n                          &nbrec_logical_router_static_route_col_route_table);\n+    ovsdb_idl_add_column(ctx->idl,\n+                         &nbrec_logical_router_static_route_col_external_ids);\n }\n \n static char * OVS_WARN_UNUSED_RESULT\n@@ -4233,7 +4235,7 @@ nbctl_lr_route_add(struct ctl_context *ctx)\n     }\n \n     if (!ecmp) {\n-        if (route) {\n+        if (route && !smap_get(&route->external_ids, \"ic-learned-route\")) {\n             if (!may_exist) {\n                 ctl_error(ctx, \"duplicate prefix: %s (policy: %s). Use option\"\n                           \" --ecmp to allow this for ECMP routing.\",\n",
    "prefixes": [