Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1525569/?format=api
{ "id": 1525569, "url": "http://patchwork.ozlabs.org/api/patches/1525569/?format=api", "web_url": "http://patchwork.ozlabs.org/project/ovn/patch/20210907224516.489604-2-blp@ovn.org/", "project": { "id": 68, "url": "http://patchwork.ozlabs.org/api/projects/68/?format=api", "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": "<20210907224516.489604-2-blp@ovn.org>", "list_archive_url": null, "date": "2021-09-07T22:45:07", "name": "[ovs-dev,v2,01/10] ovn-northd-ddlog: Intern all strings in OVSDB tables.", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "50653f5ac85fc109f83eed1ac567fe70d011140b", "submitter": { "id": 67603, "url": "http://patchwork.ozlabs.org/api/people/67603/?format=api", "name": "Ben Pfaff", "email": "blp@ovn.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/ovn/patch/20210907224516.489604-2-blp@ovn.org/mbox/", "series": [ { "id": 261352, "url": "http://patchwork.ozlabs.org/api/series/261352/?format=api", "web_url": "http://patchwork.ozlabs.org/project/ovn/list/?series=261352", "date": "2021-09-07T22:45:06", "name": "3x performance improvement for ddlog with load balancer benchmark", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/261352/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1525569/comments/", "check": "fail", "checks": "http://patchwork.ozlabs.org/api/patches/1525569/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<ovs-dev-bounces@openvswitch.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "dev@openvswitch.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "ovs-dev@lists.linuxfoundation.org" ], "Authentication-Results": "ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=140.211.166.136; helo=smtp3.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN>)", "Received": [ "from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136])\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 ozlabs.org (Postfix) with ESMTPS id 4H40jV0pCSz9t10\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 8 Sep 2021 08:45:49 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby smtp3.osuosl.org (Postfix) with ESMTP id 035A261388;\n\tTue, 7 Sep 2021 22:45:46 +0000 (UTC)", "from smtp3.osuosl.org ([127.0.0.1])\n\tby localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id PNOyqAKSjZev; Tue, 7 Sep 2021 22:45:40 +0000 (UTC)", "from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp3.osuosl.org (Postfix) with ESMTPS id 22DF5607B1;\n\tTue, 7 Sep 2021 22:45:39 +0000 (UTC)", "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 99F0BC002C;\n\tTue, 7 Sep 2021 22:45:36 +0000 (UTC)", "from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 1E2B9C0027\n for <dev@openvswitch.org>; Tue, 7 Sep 2021 22:45:35 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by smtp2.osuosl.org (Postfix) with ESMTP id 4877A40243\n for <dev@openvswitch.org>; Tue, 7 Sep 2021 22:45:33 +0000 (UTC)", "from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n with ESMTP id GyL2ZPPUO_EH for <dev@openvswitch.org>;\n Tue, 7 Sep 2021 22:45:30 +0000 (UTC)", "from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net\n [217.70.183.201])\n by smtp2.osuosl.org (Postfix) with ESMTPS id 88F1940219\n for <dev@openvswitch.org>; Tue, 7 Sep 2021 22:45:29 +0000 (UTC)", "(Authenticated sender: blp@ovn.org)\n by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id CEFD51BF204;\n Tue, 7 Sep 2021 22:45:25 +0000 (UTC)" ], "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.8.0", "From": "Ben Pfaff <blp@ovn.org>", "To": "dev@openvswitch.org", "Date": "Tue, 7 Sep 2021 15:45:07 -0700", "Message-Id": "<20210907224516.489604-2-blp@ovn.org>", "X-Mailer": "git-send-email 2.31.1", "In-Reply-To": "<20210907224516.489604-1-blp@ovn.org>", "References": "<20210907224516.489604-1-blp@ovn.org>", "MIME-Version": "1.0", "Cc": "Leonid Ryzhyk <lryzhyk@vmware.com>, Ben Pfaff <blp@ovn.org>", "Subject": "[ovs-dev] [PATCH ovn v2 01/10] ovn-northd-ddlog: Intern all strings\n\tin OVSDB tables.", "X-BeenThere": "ovs-dev@openvswitch.org", "X-Mailman-Version": "2.1.15", "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": "From: Leonid Ryzhyk <lryzhyk@vmware.com>\n\nThe ovsdb2ddlog compiler now represents all OVSDB strings as `istring`\ninstead of `string`. This commit fixes type errors resulting from that\nchange. ovn-northd-ddlog should be somewhat faster and leaner now.\n\nSigned-off-by: Leonid Ryzhyk <lryzhyk@vmware.com>\nSigned-off-by: Ben Pfaff <blp@ovn.org>\n---\n configure.ac | 2 +-\n manpages.mk | 1 -\n northd/copp.dl | 32 +-\n northd/helpers.dl | 14 +-\n northd/ipam.dl | 17 +-\n northd/lrouter.dl | 133 ++--\n northd/lswitch.dl | 149 ++--\n northd/multicast.dl | 44 +-\n northd/ovn-nb.dlopts | 1 +\n northd/ovn-sb.dlopts | 1 +\n northd/ovn.dl | 7 +\n northd/ovn_northd.dl | 1541 +++++++++++++++++++++---------------------\n northd/ovsdb2ddlog2c | 6 +-\n tests/ovn-ic.at | 8 +-\n tests/ovn.at | 6 +-\n 15 files changed, 980 insertions(+), 982 deletions(-)", "diff": "diff --git a/configure.ac b/configure.ac\nindex df0b98295..4728fa0a6 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -169,7 +169,7 @@ OVS_CONDITIONAL_CC_OPTION([-Wno-unused-parameter], [HAVE_WNO_UNUSED_PARAMETER])\n OVS_ENABLE_WERROR\n OVS_ENABLE_SPARSE\n \n-OVS_CHECK_DDLOG([0.38])\n+OVS_CHECK_DDLOG([0.47])\n OVS_CHECK_PRAGMA_MESSAGE\n OVN_CHECK_OVS\n OVS_CTAGS_IDENTIFIERS\ndiff --git a/manpages.mk b/manpages.mk\nindex 3334b38f9..9f7a0ced3 100644\n--- a/manpages.mk\n+++ b/manpages.mk\n@@ -9,4 +9,3 @@ utilities/ovn-detrace.1.in:\n lib/common-syn.man:\n lib/common.man:\n lib/ovs.tmac:\n-\ndiff --git a/northd/copp.dl b/northd/copp.dl\nindex ffb9fb32e..c4f3b7e70 100644\n--- a/northd/copp.dl\n+++ b/northd/copp.dl\n@@ -12,19 +12,19 @@\n * limitations under the License.\n */\n \n-function cOPP_ARP() : string { \"arp\" }\n-function cOPP_ARP_RESOLVE() : string { \"arp-resolve\" }\n-function cOPP_DHCPV4_OPTS() : string { \"dhcpv4-opts\" }\n-function cOPP_DHCPV6_OPTS() : string { \"dhcpv6-opts\" }\n-function cOPP_DNS() : string { \"dns\" }\n-function cOPP_EVENT_ELB() : string { \"event-elb\" }\n-function cOPP_ICMP4_ERR() : string { \"icmp4-error\" }\n-function cOPP_ICMP6_ERR() : string { \"icmp6-error\" }\n-function cOPP_IGMP() : string { \"igmp\" }\n-function cOPP_ND_NA() : string { \"nd-na\" }\n-function cOPP_ND_NS() : string { \"nd-ns\" }\n-function cOPP_ND_NS_RESOLVE() : string { \"nd-ns-resolve\" }\n-function cOPP_ND_RA_OPTS() : string { \"nd-ra-opts\" }\n-function cOPP_TCP_RESET() : string { \"tcp-reset\" }\n-function cOPP_REJECT() : string { \"reject\" }\n-function cOPP_BFD() : string { \"bfd\" }\n+function cOPP_ARP() : istring { i\"arp\" }\n+function cOPP_ARP_RESOLVE() : istring { i\"arp-resolve\" }\n+function cOPP_DHCPV4_OPTS() : istring { i\"dhcpv4-opts\" }\n+function cOPP_DHCPV6_OPTS() : istring { i\"dhcpv6-opts\" }\n+function cOPP_DNS() : istring { i\"dns\" }\n+function cOPP_EVENT_ELB() : istring { i\"event-elb\" }\n+function cOPP_ICMP4_ERR() : istring { i\"icmp4-error\" }\n+function cOPP_ICMP6_ERR() : istring { i\"icmp6-error\" }\n+function cOPP_IGMP() : istring { i\"igmp\" }\n+function cOPP_ND_NA() : istring { i\"nd-na\" }\n+function cOPP_ND_NS() : istring { i\"nd-ns\" }\n+function cOPP_ND_NS_RESOLVE() : istring { i\"nd-ns-resolve\" }\n+function cOPP_ND_RA_OPTS() : istring { i\"nd-ra-opts\" }\n+function cOPP_TCP_RESET() : istring { i\"tcp-reset\" }\n+function cOPP_REJECT() : istring { i\"reject\" }\n+function cOPP_BFD() : istring { i\"bfd\" }\ndiff --git a/northd/helpers.dl b/northd/helpers.dl\nindex 757532e46..50e137d99 100644\n--- a/northd/helpers.dl\n+++ b/northd/helpers.dl\n@@ -21,15 +21,15 @@ import ovn\n output relation Warning[string]\n \n /* Switch-to-router logical port connections */\n-relation SwitchRouterPeer(lsp: uuid, lsp_name: string, lrp: uuid)\n+relation SwitchRouterPeer(lsp: uuid, lsp_name: istring, lrp: uuid)\n SwitchRouterPeer(lsp, lsp_name, lrp) :-\n- &nb::Logical_Switch_Port(._uuid = lsp, .name = lsp_name, .__type = \"router\", .options = options),\n- Some{var router_port} = options.get(\"router-port\"),\n+ &nb::Logical_Switch_Port(._uuid = lsp, .name = lsp_name, .__type = i\"router\", .options = options),\n+ Some{var router_port} = options.get(i\"router-port\"),\n &nb::Logical_Router_Port(.name = router_port, ._uuid = lrp).\n \n-function get_bool_def(m: Map<string, string>, k: string, def: bool): bool = {\n+function get_bool_def(m: Map<istring, istring>, k: istring, def: bool): bool = {\n m.get(k)\n- .and_then(|x| match (str_to_lower(x)) {\n+ .and_then(|x| match (x.to_lowercase()) {\n \"false\" -> Some{false},\n \"true\" -> Some{true},\n _ -> None\n@@ -37,8 +37,8 @@ function get_bool_def(m: Map<string, string>, k: string, def: bool): bool = {\n .unwrap_or(def)\n }\n \n-function get_int_def(m: Map<string, string>, k: string, def: integer): integer = {\n- m.get(k).and_then(parse_dec_u64).unwrap_or(def)\n+function get_int_def(m: Map<istring, istring>, k: istring, def: integer): integer = {\n+ m.get(k).and_then(|v| v.ival().parse_dec_u64()).unwrap_or(def)\n }\n \n function clamp(x: 'A, range: ('A, 'A)): 'A {\ndiff --git a/northd/ipam.dl b/northd/ipam.dl\nindex 4665a28cb..600c55f5c 100644\n--- a/northd/ipam.dl\n+++ b/northd/ipam.dl\n@@ -101,9 +101,9 @@ SwitchIPv4ReservedAddress(.lswitch = sw._uuid,\n var exclude_ips = {\n var exclude_ips = set_singleton(start_ipv4);\n exclude_ips.insert(start_ipv4 + total_ipv4s - 1);\n- match (map_get(sw.other_config, \"exclude_ips\")) {\n+ match (map_get(sw.other_config, i\"exclude_ips\")) {\n None -> exclude_ips,\n- Some{exclude_ip_list} -> match (parse_ip_list(exclude_ip_list)) {\n+ Some{exclude_ip_list} -> match (parse_ip_list(exclude_ip_list.ival())) {\n Left{err} -> {\n warn(\"logical switch ${uuid2str(sw._uuid)}: bad exclude_ips (${err})\");\n exclude_ips\n@@ -297,18 +297,17 @@ SwitchPortNewIPv4DynAddress(lsport, addr) :-\n * Dynamic MAC address allocation.\n */\n \n-function get_mac_prefix(options: Map<string,string>, uuid: uuid) : bit<48> =\n+function get_mac_prefix(options: Map<istring,istring>, uuid: uuid) : bit<48>\n {\n- match (map_get(options, \"mac_prefix\").and_then(scan_eth_addr_prefix)) {\n+ match (map_get(options, i\"mac_prefix\").and_then(|pref| pref.ival().scan_eth_addr_prefix())) {\n Some{prefix} -> prefix.ha,\n None -> eth_addr_pseudorandom(uuid, 16'h1234).ha & 48'hffffff000000\n }\n }\n-function put_mac_prefix(options: Map<string,string>, mac_prefix: bit<48>)\n- : Map<string,string> =\n+function put_mac_prefix(options: mut Map<istring,istring>, mac_prefix: bit<48>)\n {\n- map_insert_imm(options, \"mac_prefix\",\n- string_substr(to_string(EthAddr{mac_prefix}), 0, 8))\n+ map_insert(options, i\"mac_prefix\",\n+ string_substr(to_string(EthAddr{mac_prefix}), 0, 8).intern())\n }\n relation MacPrefix(mac_prefix: bit<48>)\n MacPrefix(get_mac_prefix(options, uuid)) :-\n@@ -436,7 +435,7 @@ SwitchPortNewMACDynAddress(lsp._uuid, mac_addr) :-\n None -> None,\n Some{addr} -> {\n if (sw.subnet.is_some() or sw.ipv6_prefix.is_some() or\n- map_get(sw.other_config, \"mac_only\") == Some{\"true\"}) {\n+ map_get(sw.other_config, i\"mac_only\") == Some{i\"true\"}) {\n Some{addr}\n } else {\n None\ndiff --git a/northd/lrouter.dl b/northd/lrouter.dl\nindex 1835d4c78..cc3dced5f 100644\n--- a/northd/lrouter.dl\n+++ b/northd/lrouter.dl\n@@ -20,6 +20,7 @@ import ovsdb\n import ovn\n import helpers\n import lswitch\n+import set\n \n function is_enabled(lr: nb::Logical_Router): bool { is_enabled(lr.enabled) }\n function is_enabled(lrp: Intern<nb::Logical_Router_Port>): bool { is_enabled(lrp.enabled) }\n@@ -90,11 +91,11 @@ FirstHopLogicalRouter(lrouter, lswitch) :-\n lrp in &nb::Logical_Router_Port(._uuid = lrp_uuid, .peer = None),\n LogicalSwitchRouterPort(lsp_uuid, lrp.name, lswitch).\n \n-relation LogicalSwitchRouterPort(lsp: uuid, lsp_router_port: string, ls: uuid)\n+relation LogicalSwitchRouterPort(lsp: uuid, lsp_router_port: istring, ls: uuid)\n LogicalSwitchRouterPort(lsp, lsp_router_port, ls) :-\n LogicalSwitchPort(lsp, ls),\n- &nb::Logical_Switch_Port(._uuid = lsp, .__type = \"router\", .options = options),\n- Some{var lsp_router_port} = options.get(\"router-port\").\n+ &nb::Logical_Switch_Port(._uuid = lsp, .__type = i\"router\", .options = options),\n+ Some{var lsp_router_port} = options.get(i\"router-port\").\n \n /* Undirected edges connecting one router and another.\n * This is a building block for ConnectedLogicalRouter. */\n@@ -134,7 +135,7 @@ Warning[message] :-\n Warning[message] :-\n lrp in &nb::Logical_Router_Port(),\n lrp.ha_chassis_group.is_some() or not lrp.gateway_chassis.is_empty(),\n- lrp.options.contains_key(\"chassis\"),\n+ lrp.options.contains_key(i\"chassis\"),\n var message = \"Bad configuration: distributed gateway port configured on \"\n \"port ${lrp.name} on L3 gateway router\".\n \n@@ -149,7 +150,7 @@ DistributedGatewayPort(lrp, lr_uuid) :-\n lr in nb::Logical_Router(._uuid = lr_uuid),\n LogicalRouterPort(lrp_uuid, lr._uuid),\n lrp in &nb::Logical_Router_Port(._uuid = lrp_uuid),\n- not lrp.options.contains_key(\"chassis\"),\n+ not lrp.options.contains_key(i\"chassis\"),\n var has_hcg = lrp.ha_chassis_group.is_some(),\n var has_gc = not lrp.gateway_chassis.is_empty(),\n has_hcg or has_gc.\n@@ -166,9 +167,9 @@ DistributedGatewayPort(lrp, lr_uuid) :-\n * were ever defined. */\n relation HAChassis(hacg_uuid: uuid,\n hac_uuid: uuid,\n- chassis_name: string,\n+ chassis_name: istring,\n priority: integer,\n- external_ids: Map<string,string>)\n+ external_ids: Map<istring,istring>)\n HAChassis(ha_chassis_group_uuid(lrp._uuid), gw_chassis_uuid,\n chassis_name, priority, external_ids) :-\n DistributedGatewayPort(.lrp = lrp),\n@@ -178,7 +179,7 @@ HAChassis(ha_chassis_group_uuid(lrp._uuid), gw_chassis_uuid,\n .chassis_name = chassis_name,\n .priority = priority,\n .external_ids = eids),\n- var external_ids = eids.insert_imm(\"chassis-name\", chassis_name).\n+ var external_ids = eids.insert_imm(i\"chassis-name\", chassis_name).\n HAChassis(ha_chassis_group_uuid(ha_chassis_group._uuid), ha_chassis_uuid,\n chassis_name, priority, external_ids) :-\n DistributedGatewayPort(.lrp = lrp),\n@@ -189,7 +190,7 @@ HAChassis(ha_chassis_group_uuid(ha_chassis_group._uuid), ha_chassis_uuid,\n .chassis_name = chassis_name,\n .priority = priority,\n .external_ids = eids),\n- var external_ids = eids.insert_imm(\"chassis-name\", chassis_name).\n+ var external_ids = eids.insert_imm(i\"chassis-name\", chassis_name).\n \n /* HAChassisGroup is an abstraction for sb::HA_Chassis_Group that papers over\n * the two southbound ways to configure it via nb::Gateway_Chassis and\n@@ -202,8 +203,8 @@ HAChassis(ha_chassis_group_uuid(ha_chassis_group._uuid), ha_chassis_uuid,\n * we omit it so that multiple references get merged.)\n */\n relation HAChassisGroup(uuid: uuid,\n- name: string,\n- external_ids: Map<string,string>)\n+ name: istring,\n+ external_ids: Map<istring,istring>)\n HAChassisGroup(ha_chassis_group_uuid(lrp._uuid), lrp.name, map_empty()) :-\n DistributedGatewayPort(.lrp = lrp),\n lrp.ha_chassis_group == None,\n@@ -274,22 +275,22 @@ LogicalRouterNAT0(lr, nat, external_ip, external_mac) :-\n nb::Logical_Router(._uuid = lr, .nat = nats),\n var nat_uuid = FlatMap(nats),\n nat in &nb::NAT(._uuid = nat_uuid),\n- Some{var external_ip} = ip46_parse(nat.external_ip),\n+ Some{var external_ip} = ip46_parse(nat.external_ip.ival()),\n var external_mac = match (nat.external_mac) {\n- Some{s} -> eth_addr_from_string(s),\n+ Some{s} -> eth_addr_from_string(s.ival()),\n None -> None\n }.\n Warning[\"Bad ip address ${nat.external_ip} in nat configuration for router ${lr_name}.\"] :-\n nb::Logical_Router(._uuid = lr, .nat = nats, .name = lr_name),\n var nat_uuid = FlatMap(nats),\n nat in &nb::NAT(._uuid = nat_uuid),\n- None = ip46_parse(nat.external_ip).\n+ None = ip46_parse(nat.external_ip.ival()).\n Warning[\"Bad MAC address ${s} in nat configuration for router ${lr_name}.\"] :-\n nb::Logical_Router(._uuid = lr, .nat = nats, .name = lr_name),\n var nat_uuid = FlatMap(nats),\n nat in &nb::NAT(._uuid = nat_uuid),\n Some{var s} = nat.external_mac,\n- None = eth_addr_from_string(s).\n+ None = eth_addr_from_string(s.ival()).\n \n relation LogicalRouterNAT(lr: uuid, nat: NAT)\n LogicalRouterNAT(lr, NAT{nat, external_ip, external_mac, None}) :-\n@@ -321,10 +322,10 @@ LogicalRouterNATs(lr, vec_empty()) :-\n nb::Logical_Router(._uuid = lr),\n not LogicalRouterNAT(lr, _).\n \n-function get_force_snat_ip(options: Map<string,string>, key_type: string): Set<v46_ip> =\n+function get_force_snat_ip(options: Map<istring,istring>, key_type: istring): Set<v46_ip> =\n {\n var ips = set_empty();\n- match (options.get(key_type ++ \"_force_snat_ip\")) {\n+ match (options.get(i\"${key_type}_force_snat_ip\")) {\n None -> (),\n Some{s} -> {\n for (token in s.split(\" \")) {\n@@ -338,24 +339,24 @@ function get_force_snat_ip(options: Map<string,string>, key_type: string): Set<v\n ips\n }\n \n-function has_force_snat_ip(options: Map<string, string>, key_type: string): bool {\n+function has_force_snat_ip(options: Map<istring, istring>, key_type: istring): bool {\n not get_force_snat_ip(options, key_type).is_empty()\n }\n \n-function lb_force_snat_router_ip(lr_options: Map<string, string>): bool {\n- lr_options.get(\"lb_force_snat_ip\") == Some{\"router_ip\"} and\n- lr_options.contains_key(\"chassis\")\n+function lb_force_snat_router_ip(lr_options: Map<istring, istring>): bool {\n+ lr_options.get(i\"lb_force_snat_ip\") == Some{i\"router_ip\"} and\n+ lr_options.contains_key(i\"chassis\")\n }\n \n typedef LBForceSNAT = NoForceSNAT\n | ForceSNAT\n | SkipSNAT\n \n-function snat_for_lb(lr_options: Map<string, string>, lb: Intern<nb::Load_Balancer>): LBForceSNAT {\n- if (lb.options.get_bool_def(\"skip_snat\", false)) {\n+function snat_for_lb(lr_options: Map<istring, istring>, lb: Intern<nb::Load_Balancer>): LBForceSNAT {\n+ if (lb.options.get_bool_def(i\"skip_snat\", false)) {\n return SkipSNAT\n };\n- if (not get_force_snat_ip(lr_options, \"lb\").is_empty() or lb_force_snat_router_ip(lr_options)) {\n+ if (not get_force_snat_ip(lr_options, i\"lb\").is_empty() or lb_force_snat_router_ip(lr_options)) {\n return ForceSNAT\n };\n return NoForceSNAT\n@@ -372,15 +373,15 @@ function snat_for_lb(lr_options: Map<string, string>, lb: Intern<nb::Load_Balanc\n relation LogicalRouterSnatIP(lr: uuid, snat_ip: v46_ip, nat: Option<NAT>)\n LogicalRouterSnatIP(lr._uuid, force_snat_ip, None) :-\n lr in nb::Logical_Router(),\n- var dnat_force_snat_ips = get_force_snat_ip(lr.options, \"dnat\"),\n+ var dnat_force_snat_ips = get_force_snat_ip(lr.options, i\"dnat\"),\n var lb_force_snat_ips = if (lb_force_snat_router_ip(lr.options)) {\n set_empty()\n } else {\n- get_force_snat_ip(lr.options, \"lb\")\n+ get_force_snat_ip(lr.options, i\"lb\")\n },\n var force_snat_ip = FlatMap(dnat_force_snat_ips.union(lb_force_snat_ips)).\n LogicalRouterSnatIP(lr, snat_ip, Some{nat}) :-\n- LogicalRouterNAT(lr, nat@NAT{.nat = &nb::NAT{.__type = \"snat\"}, .external_ip = snat_ip}).\n+ LogicalRouterNAT(lr, nat@NAT{.nat = &nb::NAT{.__type = i\"snat\"}, .external_ip = snat_ip}).\n \n function group_to_setunionmap(g: Group<'K1, ('K2,Set<'V>)>): Map<'K2,Set<'V>> {\n var map = map_empty();\n@@ -420,13 +421,13 @@ LogicalRouterLBs(lr, vec_empty()) :-\n \n // LogicalRouterCopp maps from each LR to its collection of Copp meters,\n // dropping any Copp meter whose meter name doesn't exist.\n-relation LogicalRouterCopp(lr: uuid, meters: Map<string,string>)\n+relation LogicalRouterCopp(lr: uuid, meters: Map<istring,istring>)\n LogicalRouterCopp(lr, meters) :- LogicalRouterCopp0(lr, meters).\n LogicalRouterCopp(lr, map_empty()) :-\n nb::Logical_Router(._uuid = lr),\n not LogicalRouterCopp0(lr, _).\n \n-relation LogicalRouterCopp0(lr: uuid, meters: Map<string,string>)\n+relation LogicalRouterCopp0(lr: uuid, meters: Map<istring,istring>)\n LogicalRouterCopp0(lr, meters) :-\n nb::Logical_Router(._uuid = lr, .copp = Some{copp_uuid}),\n nb::Copp(._uuid = copp_uuid, .meters = meters),\n@@ -445,18 +446,18 @@ LogicalRouterCopp0(lr, meters) :-\n * should always be learned\n */\n \n-function chassis_redirect_name(port_name: string): string = \"cr-${port_name}\"\n+function chassis_redirect_name(port_name: istring): string = \"cr-${port_name}\"\n \n typedef Router = Router {\n /* Fields copied from nb::Logical_Router. */\n _uuid: uuid,\n- name: string,\n+ name: istring,\n policies: Set<uuid>,\n enabled: Option<bool>,\n nat: Set<uuid>,\n load_balancer: Set<uuid>,\n- options: Map<string,string>,\n- external_ids: Map<string,string>,\n+ options: Map<istring,istring>,\n+ external_ids: Map<istring,istring>,\n \n /* Additional computed fields. */\n l3dgw_ports: Vec<Intern<nb::Logical_Router_Port>>,\n@@ -467,7 +468,7 @@ typedef Router = Router {\n mcast_cfg: Intern<McastRouterCfg>,\n learn_from_arp_request: bool,\n force_lb_snat: bool,\n- copp: Map<string, string>,\n+ copp: Map<istring, istring>,\n }\n \n relation Router[Intern<Router>]\n@@ -483,7 +484,7 @@ Router[Router{\n .external_ids = lr.external_ids,\n \n .l3dgw_ports = l3dgw_ports,\n- .is_gateway = lr.options.contains_key(\"chassis\"),\n+ .is_gateway = lr.options.contains_key(i\"chassis\"),\n .nats = nats,\n .snat_ips = snat_ips,\n .lbs = lbs,\n@@ -499,7 +500,7 @@ Router[Router{\n LogicalRouterSnatIPs(lr._uuid, snat_ips),\n LogicalRouterCopp(lr._uuid, copp),\n mcast_cfg in &McastRouterCfg(.datapath = lr._uuid),\n- var learn_from_arp_request = lr.options.get_bool_def(\"always_learn_from_arp_request\", true),\n+ var learn_from_arp_request = lr.options.get_bool_def(i\"always_learn_from_arp_request\", true),\n var force_lb_snat = lb_force_snat_router_ip(lr.options).\n \n /* RouterLB: many-to-many relation between logical routers and nb::LB */\n@@ -513,16 +514,15 @@ RouterLB(router, lb) :-\n relation RouterLBVIP(\n router: Intern<Router>,\n lb: Intern<nb::Load_Balancer>,\n- vip: string,\n- backends: string)\n+ vip: istring,\n+ backends: istring)\n \n RouterLBVIP(router, lb, vip, backends) :-\n RouterLB(router, lb@(&nb::Load_Balancer{.vips = vips})),\n- var kv = FlatMap(vips),\n- (var vip, var backends) = kv.\n+ (var vip, var backends) = FlatMap(vips).\n \n /* Router-to-router logical port connections */\n-relation RouterRouterPeer(rport1: uuid, rport2: uuid, rport2_name: string)\n+relation RouterRouterPeer(rport1: uuid, rport2: uuid, rport2_name: istring)\n \n RouterRouterPeer(rport1, rport2, peer_name) :-\n &nb::Logical_Router_Port(._uuid = rport1, .peer = peer),\n@@ -532,11 +532,11 @@ RouterRouterPeer(rport1, rport2, peer_name) :-\n /* Router port can peer with anothe router port, a switch port or have\n * no peer.\n */\n-typedef RouterPeer = PeerRouter{rport: uuid, name: string}\n- | PeerSwitch{sport: uuid, name: string}\n+typedef RouterPeer = PeerRouter{rport: uuid, name: istring}\n+ | PeerSwitch{sport: uuid, name: istring}\n | PeerNone\n \n-function router_peer_name(peer: RouterPeer): Option<string> = {\n+function router_peer_name(peer: RouterPeer): Option<istring> = {\n match (peer) {\n PeerRouter{_, n} -> Some{n},\n PeerSwitch{_, n} -> Some{n},\n@@ -563,14 +563,14 @@ RouterPortPeer(rport, PeerNone) :-\n * most of the options in that column. (northd unconditionally sets the\n * ipv6_prefix_delegation and ipv6_prefix options, so we remove them for\n * faster convergence.) */\n-relation RouterPortSbOptions(lrp_uuid: uuid, options: Map<string,string>)\n+relation RouterPortSbOptions(lrp_uuid: uuid, options: Map<istring,istring>)\n RouterPortSbOptions(lrp._uuid, options) :-\n lrp in &nb::Logical_Router_Port(),\n pb in sb::Port_Binding(._uuid = lrp._uuid),\n var options = {\n var options = pb.options;\n- options.remove(\"ipv6_prefix\");\n- options.remove(\"ipv6_prefix_delegation\");\n+ options.remove(i\"ipv6_prefix\");\n+ options.remove(i\"ipv6_prefix_delegation\");\n options\n }.\n RouterPortSbOptions(lrp._uuid, map_empty()) :-\n@@ -595,7 +595,7 @@ typedef RouterPort = RouterPort {\n is_redirect: bool,\n peer: RouterPeer,\n mcast_cfg: Intern<McastPortCfg>,\n- sb_options: Map<string,string>,\n+ sb_options: Map<istring,istring>,\n has_bfd: bool\n }\n \n@@ -603,7 +603,7 @@ relation RouterPort[Intern<RouterPort>]\n \n RouterPort[RouterPort{\n .lrp = lrp,\n- .json_name = json_string_escape(lrp.name),\n+ .json_name = json_escape(lrp.name),\n .networks = networks,\n .router = router,\n .is_redirect = is_redirect,\n@@ -613,7 +613,7 @@ RouterPort[RouterPort{\n .has_bfd = has_bfd\n }.intern()] :-\n lrp in &nb::Logical_Router_Port(),\n- Some{var networks} = extract_lrp_networks(lrp.mac, lrp.networks),\n+ Some{var networks} = extract_lrp_networks(lrp.mac.ival(), lrp.networks.map(ival)),\n LogicalRouterPort(lrp._uuid, lrouter_uuid),\n router in &Router(._uuid = lrouter_uuid),\n RouterPortIsRedirect(lrp._uuid, is_redirect),\n@@ -636,11 +636,8 @@ RouterPortNetworksIPv6Addr(port, addr) :-\n \n /* StaticRoute: Collects and parses attributes of a static route. */\n typedef route_policy = SrcIp | DstIp\n-function route_policy_from_string(s: Option<string>): route_policy = {\n- match (s) {\n- Some{\"src-ip\"} -> SrcIp,\n- _ -> DstIp\n- }\n+function route_policy_from_string(s: Option<istring>): route_policy = {\n+ if (s == Some{i\"src-ip\"}) { SrcIp } else { DstIp }\n }\n function to_string(policy: route_policy): string = {\n match (policy) {\n@@ -664,15 +661,13 @@ StaticRouteDown(lrsr_uuid) :-\n bfd in nb::BFD(._uuid = bfd_uuid, .dst_ip = nexthop),\n match (bfd.status) {\n None -> true,\n- Some{\"admin_down\"} -> true,\n- Some{\"down\"} -> true,\n- _ -> false\n+ Some{status} -> (status == i\"admin_down\" or status == i\"down\")\n }.\n \n relation &StaticRoute(lrsr: nb::Logical_Router_Static_Route,\n key: route_key,\n nexthop: v46_ip,\n- output_port: Option<string>,\n+ output_port: Option<istring>,\n ecmp_symmetric_reply: bool)\n \n &StaticRoute(.lrsr = lrsr,\n@@ -683,29 +678,29 @@ relation &StaticRoute(lrsr: nb::Logical_Router_Static_Route,\n lrsr in nb::Logical_Router_Static_Route(),\n not StaticRouteDown(lrsr._uuid),\n var policy = route_policy_from_string(lrsr.policy),\n- Some{(var nexthop, var nexthop_plen)} = ip46_parse_cidr(lrsr.nexthop),\n+ Some{(var nexthop, var nexthop_plen)} = ip46_parse_cidr(lrsr.nexthop.ival()),\n match (nexthop) {\n IPv4{_} -> nexthop_plen == 32,\n IPv6{_} -> nexthop_plen == 128\n },\n- Some{(var ip_prefix, var plen)} = ip46_parse_cidr(lrsr.ip_prefix),\n+ Some{(var ip_prefix, var plen)} = ip46_parse_cidr(lrsr.ip_prefix.ival()),\n match ((nexthop, ip_prefix)) {\n (IPv4{_}, IPv4{_}) -> true,\n (IPv6{_}, IPv6{_}) -> true,\n _ -> false\n },\n- var esr = lrsr.options.get_bool_def(\"ecmp_symmetric_reply\", false).\n+ var esr = lrsr.options.get_bool_def(i\"ecmp_symmetric_reply\", false).\n \n relation &StaticRouteEmptyNextHop(lrsr: nb::Logical_Router_Static_Route,\n key: route_key,\n- output_port: Option<string>)\n+ output_port: Option<istring>)\n &StaticRouteEmptyNextHop(.lrsr = lrsr,\n .key = RouteKey{policy, ip_prefix, plen},\n .output_port = lrsr.output_port) :-\n- lrsr in nb::Logical_Router_Static_Route(.nexthop = \"\"),\n+ lrsr in nb::Logical_Router_Static_Route(.nexthop = i\"\"),\n not StaticRouteDown(lrsr._uuid),\n var policy = route_policy_from_string(lrsr.policy),\n- Some{(var ip_prefix, var plen)} = ip46_parse_cidr(lrsr.ip_prefix).\n+ Some{(var ip_prefix, var plen)} = ip46_parse_cidr(lrsr.ip_prefix.ival()).\n \n /* Returns the IP address of the router port 'op' that\n * overlaps with 'ip'. If one is not found, returns None. */\n@@ -745,7 +740,7 @@ relation RouterStaticRoute_(\n router : Intern<Router>,\n key : route_key,\n nexthop : v46_ip,\n- output_port : Option<string>,\n+ output_port : Option<istring>,\n ecmp_symmetric_reply : bool)\n \n RouterStaticRoute_(.router = router,\n@@ -761,7 +756,7 @@ RouterStaticRoute_(.router = router,\n relation RouterStaticRouteEmptyNextHop_(\n router : Intern<Router>,\n key : route_key,\n- output_port : Option<string>)\n+ output_port : Option<istring>)\n \n RouterStaticRouteEmptyNextHop_(.router = router,\n .key = route.key,\n@@ -874,9 +869,9 @@ relation &DiscardRoute(lrsr: nb::Logical_Router_Static_Route,\n key: route_key)\n &DiscardRoute(.lrsr = lrsr,\n .key = RouteKey{policy, ip_prefix, plen}) :-\n- lrsr in nb::Logical_Router_Static_Route(.nexthop = \"discard\"),\n+ lrsr in nb::Logical_Router_Static_Route(.nexthop = i\"discard\"),\n var policy = route_policy_from_string(lrsr.policy),\n- Some{(var ip_prefix, var plen)} = ip46_parse_cidr(lrsr.ip_prefix).\n+ Some{(var ip_prefix, var plen)} = ip46_parse_cidr(lrsr.ip_prefix.ival()).\n \n relation RouterDiscardRoute_(\n router : Intern<Router>,\ndiff --git a/northd/lswitch.dl b/northd/lswitch.dl\nindex 868ae115f..ad6475a91 100644\n--- a/northd/lswitch.dl\n+++ b/northd/lswitch.dl\n@@ -21,6 +21,7 @@ import multicast\n import helpers\n import ipam\n import vec\n+import set\n \n function is_enabled(lsp: Intern<nb::Logical_Switch_Port>): bool { is_enabled(lsp.enabled) }\n function is_enabled(sp: SwitchPort): bool { sp.lsp.is_enabled() }\n@@ -67,7 +68,7 @@ relation LogicalSwitchPortWithUnknownAddress(ls: uuid, lsp: uuid)\n LogicalSwitchPortWithUnknownAddress(ls_uuid, lsp_uuid) :-\n LogicalSwitchPort(lsp_uuid, ls_uuid),\n lsp in &nb::Logical_Switch_Port(._uuid = lsp_uuid),\n- lsp.is_enabled() and lsp.addresses.contains(\"unknown\").\n+ lsp.is_enabled() and lsp.addresses.contains(i\"unknown\").\n \n // \"Pitfalls of projections\" in ddlog-new-feature.rst explains why this\n // is an output relation:\n@@ -78,18 +79,17 @@ LogicalSwitchHasUnknownPorts(ls, false) :-\n not LogicalSwitchPortWithUnknownAddress(ls, _).\n \n /* PortStaticAddresses: static IP addresses associated with each Logical_Switch_Port */\n-relation PortStaticAddresses(lsport: uuid, ip4addrs: Set<string>, ip6addrs: Set<string>)\n+relation PortStaticAddresses(lsport: uuid, ip4addrs: Set<istring>, ip6addrs: Set<istring>)\n \n PortStaticAddresses(.lsport = port_uuid,\n- .ip4addrs = ip4_addrs.union(),\n- .ip6addrs = ip6_addrs.union()) :-\n+ .ip4addrs = ip4_addrs.union().map(intern),\n+ .ip6addrs = ip6_addrs.union().map(intern)) :-\n &nb::Logical_Switch_Port(._uuid = port_uuid, .addresses = addresses),\n- var address = FlatMap(if (addresses.is_empty()) { set_singleton(\"\") } else { addresses }),\n- (var ip4addrs, var ip6addrs) = if (not is_dynamic_lsp_address(address)) {\n- split_addresses(address)\n+ var address = FlatMap(if (addresses.is_empty()) { set_singleton(i\"\") } else { addresses }),\n+ (var ip4addrs, var ip6addrs) = if (not is_dynamic_lsp_address(address.ival())) {\n+ split_addresses(address.ival())\n } else { (set_empty(), set_empty()) },\n- var static_addrs = (ip4addrs, ip6addrs).group_by(port_uuid).group_unzip(),\n- (var ip4_addrs, var ip6_addrs) = static_addrs.\n+ (var ip4_addrs, var ip6_addrs) = (ip4addrs, ip6addrs).group_by(port_uuid).group_unzip().\n \n relation PortInGroup(port: uuid, group: uuid)\n \n@@ -115,7 +115,7 @@ relation LogicalSwitchStatefulACL(ls: uuid, acl: uuid)\n \n LogicalSwitchStatefulACL(ls, acl) :-\n LogicalSwitchACL(ls, acl),\n- &nb::ACL(._uuid = acl, .action = \"allow-related\").\n+ &nb::ACL(._uuid = acl, .action = i\"allow-related\").\n \n // \"Pitfalls of projections\" in ddlog-new-feature.rst explains why this\n // is an output relation:\n@@ -144,14 +144,14 @@ LogicalSwitchHasACLs(ls, false) :-\n * to the logical switch's set of localnet ports. Each localnet\n * port is expressed as a tuple of its UUID and its name.\n */\n-relation LogicalSwitchLocalnetPort0(ls_uuid: uuid, lsp: (uuid, string))\n+relation LogicalSwitchLocalnetPort0(ls_uuid: uuid, lsp: (uuid, istring))\n LogicalSwitchLocalnetPort0(ls_uuid, (lsp_uuid, lsp.name)) :-\n ls in &nb::Logical_Switch(._uuid = ls_uuid),\n var lsp_uuid = FlatMap(ls.ports),\n lsp in &nb::Logical_Switch_Port(._uuid = lsp_uuid),\n- lsp.__type == \"localnet\".\n+ lsp.__type == i\"localnet\".\n \n-relation LogicalSwitchLocalnetPorts(ls_uuid: uuid, localnet_ports: Vec<(uuid, string)>)\n+relation LogicalSwitchLocalnetPorts(ls_uuid: uuid, localnet_ports: Vec<(uuid, istring)>)\n LogicalSwitchLocalnetPorts(ls_uuid, localnet_ports) :-\n LogicalSwitchLocalnetPort0(ls_uuid, lsp),\n var localnet_ports = lsp.group_by(ls_uuid).to_vec().\n@@ -191,7 +191,7 @@ LogicalSwitchHasNonRouterPort0(ls_uuid) :-\n ls in &nb::Logical_Switch(._uuid = ls_uuid),\n var lsp_uuid = FlatMap(ls.ports),\n lsp in &nb::Logical_Switch_Port(._uuid = lsp_uuid),\n- lsp.__type != \"router\".\n+ lsp.__type != i\"router\".\n \n // \"Pitfalls of projections\" in ddlog-new-feature.rst explains why this\n // is an output relation:\n@@ -204,13 +204,13 @@ LogicalSwitchHasNonRouterPort(ls, false) :-\n \n // LogicalSwitchCopp maps from each LS to its collection of Copp meters,\n // dropping any Copp meter whose meter name doesn't exist.\n-relation LogicalSwitchCopp(ls: uuid, meters: Map<string,string>)\n+relation LogicalSwitchCopp(ls: uuid, meters: Map<istring,istring>)\n LogicalSwitchCopp(ls, meters) :- LogicalSwitchCopp0(ls, meters).\n LogicalSwitchCopp(ls, map_empty()) :-\n &nb::Logical_Switch(._uuid = ls),\n not LogicalSwitchCopp0(ls, _).\n \n-relation LogicalSwitchCopp0(ls: uuid, meters: Map<string,string>)\n+relation LogicalSwitchCopp0(ls: uuid, meters: Map<istring,istring>)\n LogicalSwitchCopp0(ls, meters) :-\n &nb::Logical_Switch(._uuid = ls, .copp = Some{copp_uuid}),\n nb::Copp(._uuid = copp_uuid, .meters = meters),\n@@ -224,10 +224,10 @@ LogicalSwitchCopp0(ls, meters) :-\n typedef Switch = Switch {\n /* Fields copied from nb::Logical_Switch_Port. */\n _uuid: uuid,\n- name: string,\n+ name: istring,\n load_balancer: Set<uuid>,\n- other_config: Map<string,string>,\n- external_ids: Map<string,string>,\n+ other_config: Map<istring,istring>,\n+ external_ids: Map<istring,istring>,\n \n /* Additional computed fields. */\n has_stateful_acl: bool,\n@@ -235,12 +235,12 @@ typedef Switch = Switch {\n has_lb_vip: bool,\n has_dns_records: bool,\n has_unknown_ports: bool,\n- localnet_ports: Vec<(uuid, string)>, // UUID and name of each localnet port.\n+ localnet_ports: Vec<(uuid, istring)>, // UUID and name of each localnet port.\n subnet: Option<(in_addr/*subnet*/, in_addr/*mask*/, bit<32>/*start_ipv4*/, bit<32>/*total_ipv4s*/)>,\n ipv6_prefix: Option<in6_addr>,\n mcast_cfg: Intern<McastSwitchCfg>,\n is_vlan_transparent: bool,\n- copp: Map<string, string>,\n+ copp: Map<istring, istring>,\n \n /* Does this switch have at least one port with type != \"router\"? */\n has_non_router_port: bool\n@@ -291,10 +291,10 @@ Switch[Switch{\n LogicalSwitchCopp(ls._uuid, copp),\n mcast_cfg in &McastSwitchCfg(.datapath = ls._uuid),\n var subnet =\n- match (ls.other_config.get(\"subnet\")) {\n+ match (ls.other_config.get(i\"subnet\")) {\n None -> None,\n Some{subnet_str} -> {\n- match (ip_parse_masked(subnet_str)) {\n+ match (ip_parse_masked(subnet_str.ival())) {\n Left{err} -> {\n warn(\"bad 'subnet' ${subnet_str}\");\n None\n@@ -311,11 +311,11 @@ Switch[Switch{\n }\n },\n var ipv6_prefix =\n- match (ls.other_config.get(\"ipv6_prefix\")) {\n+ match (ls.other_config.get(i\"ipv6_prefix\")) {\n None -> None,\n- Some{prefix} -> ipv6_parse_prefix(prefix)\n+ Some{prefix} -> ipv6_parse_prefix(prefix.ival())\n },\n- var is_vlan_transparent = ls.other_config.get_bool_def(\"vlan-passthru\", false).\n+ var is_vlan_transparent = ls.other_config.get_bool_def(i\"vlan-passthru\", false).\n \n /* SwitchLB: many-to-many relation between logical switches and nb::LB */\n relation SwitchLB(sw_uuid: uuid, lb: Intern<nb::Load_Balancer>)\n@@ -325,7 +325,7 @@ SwitchLB(sw_uuid, lb) :-\n lb in &nb::Load_Balancer(._uuid = lb_id).\n \n /* Load balancer VIPs associated with switch */\n-relation SwitchLBVIP(sw_uuid: uuid, lb: Intern<nb::Load_Balancer>, vip: string, backends: string)\n+relation SwitchLBVIP(sw_uuid: uuid, lb: Intern<nb::Load_Balancer>, vip: istring, backends: istring)\n SwitchLBVIP(sw_uuid, lb, vip, backends) :-\n SwitchLB(sw_uuid, lb@(&nb::Load_Balancer{.vips = vips})),\n var kv = FlatMap(vips),\n@@ -349,8 +349,8 @@ LogicalSwitchHasLBVIP(sw_uuid, false) :-\n */\n relation LBVIP0(\n lb: Intern<nb::Load_Balancer>,\n- vip_key: string,\n- backend_ips: string,\n+ vip_key: istring,\n+ backend_ips: istring,\n health_check: Intern<nb::Load_Balancer_Health_Check>)\n LBVIP0(lb, vip_key, backend_ips, health_check) :-\n lb in &nb::Load_Balancer(),\n@@ -361,8 +361,8 @@ LBVIP0(lb, vip_key, backend_ips, health_check) :-\n \n relation LBVIP1(\n lb: Intern<nb::Load_Balancer>,\n- vip_key: string,\n- backend_ips: string,\n+ vip_key: istring,\n+ backend_ips: istring,\n health_check: Option<Intern<nb::Load_Balancer_Health_Check>>)\n LBVIP1(lb, vip_key, backend_ips, Some{health_check}) :-\n LBVIP0(lb, vip_key, backend_ips, health_check).\n@@ -374,8 +374,8 @@ LBVIP1(lb, vip_key, backend_ips, None) :-\n \n typedef LBVIP = LBVIP {\n lb: Intern<nb::Load_Balancer>,\n- vip_key: string,\n- backend_ips: string,\n+ vip_key: istring,\n+ backend_ips: istring,\n health_check: Option<Intern<nb::Load_Balancer_Health_Check>>,\n vip_addr: v46_ip,\n vip_port: bit<16>,\n@@ -386,13 +386,13 @@ relation LBVIP[Intern<LBVIP>]\n \n LBVIP[LBVIP{lb, vip_key, backend_ips, health_check, vip_addr, vip_port, backends}.intern()] :-\n LBVIP1(lb, vip_key, backend_ips, health_check),\n- Some{(var vip_addr, var vip_port)} = ip_address_and_port_from_lb_key(vip_key),\n+ Some{(var vip_addr, var vip_port)} = ip_address_and_port_from_lb_key(vip_key.ival()),\n var backends = backend_ips.split(\",\").filter_map(\n |ip| parse_vip_backend(ip, lb.ip_port_mappings)).\n \n typedef svc_monitor = SvcMonitor{\n- port_name: string, // Might name a switch or router port.\n- src_ip: string\n+ port_name: istring, // Might name a switch or router port.\n+ src_ip: istring\n }\n \n /* Backends for load balancer virtual IPs.\n@@ -407,25 +407,24 @@ typedef lb_vip_backend = LBVIPBackend{\n svc_monitor: Option<svc_monitor>}\n \n function parse_vip_backend(backend_ip: string,\n- mappings: Map<string,string>): Option<lb_vip_backend> {\n+ mappings: Map<istring,istring>): Option<lb_vip_backend> {\n match (ip_address_and_port_from_lb_key(backend_ip)) {\n Some{(ip, port)} -> Some{LBVIPBackend{ip, port, parse_ip_port_mapping(mappings, ip)}},\n _ -> None\n }\n }\n \n-function parse_ip_port_mapping(mappings: Map<string,string>, ip: v46_ip)\n+function parse_ip_port_mapping(mappings: Map<istring,istring>, ip: v46_ip)\n : Option<svc_monitor> {\n- for (kv in mappings) {\n- (var key, var value) = kv;\n- if (ip46_parse(key) == Some{ip}) {\n- var strs = string_split(value, \":\");\n+ for ((key, value) in mappings) {\n+ if (ip46_parse(key.ival()) == Some{ip}) {\n+ var strs = value.split(\":\");\n if (strs.len() != 2) {\n return None\n };\n \n return match ((strs.nth(0), strs.nth(1))) {\n- (Some{port_name}, Some{src_ip}) -> Some{SvcMonitor{port_name, src_ip}},\n+ (Some{port_name}, Some{src_ip}) -> Some{SvcMonitor{port_name.intern(), src_ip.intern()}},\n _ -> None\n }\n }\n@@ -433,23 +432,23 @@ function parse_ip_port_mapping(mappings: Map<string,string>, ip: v46_ip)\n return None\n }\n \n-function is_online(status: Option<string>): bool = {\n+function is_online(status: Option<istring>): bool = {\n match (status) {\n- Some{s} -> s == \"online\",\n+ Some{s} -> s == i\"online\",\n _ -> true\n }\n }\n-function default_protocol(protocol: Option<string>): string = {\n+function default_protocol(protocol: Option<istring>): istring = {\n match (protocol) {\n Some{x} -> x,\n- None -> \"tcp\"\n+ None -> i\"tcp\"\n }\n }\n \n typedef LBVIPWithStatus = LBVIPWithStatus {\n lb: Intern<nb::Load_Balancer>,\n- vip_key: string,\n- backend_ips: string,\n+ vip_key: istring,\n+ backend_ips: istring,\n health_check: Option<Intern<nb::Load_Balancer_Health_Check>>,\n vip_addr: v46_ip,\n vip_port: bit<16>,\n@@ -479,7 +478,7 @@ LBVIPBackendStatus0(lbvip, backend, is_online(sm.status)) :-\n var backend = FlatMap(lbvip.backends),\n Some{var svc_monitor} = backend.svc_monitor,\n sm in &sb::Service_Monitor(.port = backend.port as integer),\n- ip46_parse(sm.ip) == Some{backend.ip},\n+ ip46_parse(sm.ip.ival()) == Some{backend.ip},\n svc_monitor.port_name == sm.logical_port,\n default_protocol(lb.protocol) == default_protocol(sm.protocol).\n \n@@ -500,7 +499,7 @@ relation SwitchPortDHCPv4Options(\n \n SwitchPortDHCPv4Options(port, options) :-\n port in &SwitchPort(.lsp = lsp),\n- port.lsp.__type != \"external\",\n+ port.lsp.__type != i\"external\",\n Some{var dhcpv4_uuid} = lsp.dhcpv4_options,\n options in &nb::DHCP_Options(._uuid = dhcpv4_uuid).\n \n@@ -511,7 +510,7 @@ relation SwitchPortDHCPv6Options(\n \n SwitchPortDHCPv6Options(port, options) :-\n port in &SwitchPort(.lsp = lsp),\n- port.lsp.__type != \"external\",\n+ port.lsp.__type != i\"external\",\n Some{var dhcpv6_uuid} = lsp.dhcpv6_options,\n options in &nb::DHCP_Options(._uuid = dhcpv6_uuid).\n \n@@ -553,10 +552,10 @@ relation &SwitchACL(sw: Intern<Switch>,\n acl in &nb::ACL(._uuid = acl_uuid),\n ACLHasFairMeter(acl, has_fair_meter).\n \n-function oVN_FEATURE_PORT_UP_NOTIF(): string { \"port-up-notif\" }\n+function oVN_FEATURE_PORT_UP_NOTIF(): istring { i\"port-up-notif\" }\n relation SwitchPortUp0(lsp: uuid)\n SwitchPortUp0(lsp) :-\n- &nb::Logical_Switch_Port(._uuid = lsp, .__type = \"router\").\n+ &nb::Logical_Switch_Port(._uuid = lsp, .__type = i\"router\").\n SwitchPortUp0(lsp) :-\n &nb::Logical_Switch_Port(._uuid = lsp, .name = lsp_name, .__type = __type),\n sb::Port_Binding(.logical_port = lsp_name, .up = up, .chassis = Some{chassis_uuid}),\n@@ -574,7 +573,7 @@ SwitchPortUp(lsp, false) :- &nb::Logical_Switch_Port(._uuid = lsp), not SwitchPo\n relation SwitchPortHAChassisGroup0(lsp_uuid: uuid, hac_group_uuid: uuid)\n SwitchPortHAChassisGroup0(lsp_uuid, ha_chassis_group_uuid(ls_uuid)) :-\n lsp in &nb::Logical_Switch_Port(._uuid = lsp_uuid),\n- lsp.__type == \"external\",\n+ lsp.__type == i\"external\",\n Some{var hac_group_uuid} = lsp.ha_chassis_group,\n ha_chassis_group in nb::HA_Chassis_Group(._uuid = hac_group_uuid),\n /* If the group is empty, then HA_Chassis_Group record will not be created in SB,\n@@ -603,7 +602,7 @@ SwitchPortHAChassisGroup(lsp_uuid, None) :-\n */\n typedef SwitchPort = SwitchPort {\n lsp: Intern<nb::Logical_Switch_Port>,\n- json_name: string,\n+ json_name: istring,\n sw: Intern<Switch>,\n peer: Option<Intern<RouterPort>>,\n static_addresses: Vec<lport_addresses>,\n@@ -612,8 +611,8 @@ typedef SwitchPort = SwitchPort {\n static_dynamic_ipv4: Option<in_addr>,\n static_dynamic_ipv6: Option<in6_addr>,\n ps_addresses: Vec<lport_addresses>,\n- ps_eth_addresses: Vec<string>,\n- parent_name: Option<string>,\n+ ps_eth_addresses: Vec<istring>,\n+ parent_name: Option<istring>,\n needs_dynamic_ipv4address: bool,\n needs_dynamic_macaddress: bool,\n needs_dynamic_ipv6address: bool,\n@@ -627,7 +626,7 @@ relation SwitchPort[Intern<SwitchPort>]\n \n SwitchPort[SwitchPort{\n .lsp = lsp,\n- .json_name = json_string_escape(lsp.name),\n+ .json_name = lsp.name.json_escape().intern(),\n .sw = sw,\n .peer = peer,\n .static_addresses = static_addresses,\n@@ -658,8 +657,8 @@ SwitchPort[SwitchPort{\n var static_addresses = {\n var static_addresses = vec_empty();\n for (addr in lsp.addresses) {\n- if ((addr != \"router\") and (not is_dynamic_lsp_address(addr))) {\n- match (extract_lsp_addresses(addr)) {\n+ if ((addr != i\"router\") and (not is_dynamic_lsp_address(addr.ival()))) {\n+ match (extract_lsp_addresses(addr.ival())) {\n None -> (),\n Some{lport_addr} -> static_addresses.push(lport_addr)\n }\n@@ -670,7 +669,7 @@ SwitchPort[SwitchPort{\n var ps_addresses = {\n var ps_addresses = vec_empty();\n for (addr in lsp.port_security) {\n- match (extract_lsp_addresses(addr)) {\n+ match (extract_lsp_addresses(addr.ival())) {\n None -> (),\n Some{lport_addr} -> ps_addresses.push(lport_addr)\n }\n@@ -680,13 +679,13 @@ SwitchPort[SwitchPort{\n var ps_eth_addresses = {\n var ps_eth_addresses = vec_empty();\n for (ps_addr in ps_addresses) {\n- ps_eth_addresses.push(\"${ps_addr.ea}\")\n+ ps_eth_addresses.push(i\"${ps_addr.ea}\")\n };\n ps_eth_addresses\n },\n var dynamic_address = match (lsp.dynamic_addresses) {\n None -> None,\n- Some{lport_addr} -> extract_lsp_addresses(lport_addr)\n+ Some{lport_addr} -> extract_lsp_addresses(lport_addr.ival())\n },\n (var static_dynamic_mac,\n var static_dynamic_ipv4,\n@@ -694,7 +693,7 @@ SwitchPort[SwitchPort{\n var has_dyn_lsp_addr) = {\n var dynamic_address_request = None;\n for (addr in lsp.addresses) {\n- dynamic_address_request = parse_dynamic_address_request(addr);\n+ dynamic_address_request = parse_dynamic_address_request(addr.ival());\n if (dynamic_address_request.is_some()) {\n break\n }\n@@ -709,11 +708,11 @@ SwitchPort[SwitchPort{\n static_dynamic_ipv4 == None,\n var needs_dynamic_macaddress = has_dyn_lsp_addr and peer == None and static_dynamic_mac == None and\n (subnet.is_some() or ipv6_prefix.is_some() or\n- other_config.get(\"mac_only\") == Some{\"true\"}),\n+ other_config.get(i\"mac_only\") == Some{i\"true\"}),\n var needs_dynamic_ipv6address = has_dyn_lsp_addr and peer == None and ipv6_prefix.is_some() and static_dynamic_ipv6 == None,\n var parent_name = match (lsp.parent_name) {\n None -> None,\n- Some{pname} -> if (pname == \"\") { None } else { Some{pname} }\n+ Some{pname} -> if (pname == i\"\") { None } else { Some{pname} }\n },\n /* Port needs dynamic tag if it has a parent and its `tag_request` is 0. */\n var needs_dynamic_tag = parent_name.is_some() and lsp.tag_request == Some{0},\n@@ -761,7 +760,7 @@ SwitchPortAddresses(port, addrs) :-\n Some{var addrs} = {\n var opt_addrs = None;\n for (addr in lsp.addresses) {\n- if (addr == \"router\") {\n+ if (addr == i\"router\") {\n opt_addrs = Some{rport.networks}\n } else ()\n };\n@@ -793,13 +792,13 @@ SwitchPortIPv6Address(port, ea, addr) :-\n * of this mac when sending out the packets to monitor the services\n * defined in Service_Monitor Southbound table. Since these packets\n * all locally handled, having just one mac is good enough. */\n-function get_svc_monitor_mac(options: Map<string,string>, uuid: uuid)\n+function get_svc_monitor_mac(options: Map<istring,istring>, uuid: uuid)\n : eth_addr =\n {\n var existing_mac = match (\n- options.get(\"svc_monitor_mac\"))\n+ options.get(i\"svc_monitor_mac\"))\n {\n- Some{mac} -> scan_eth_addr(mac),\n+ Some{mac} -> scan_eth_addr(mac.ival()),\n None -> None\n };\n match (existing_mac) {\n@@ -807,17 +806,17 @@ function get_svc_monitor_mac(options: Map<string,string>, uuid: uuid)\n None -> eth_addr_pseudorandom(uuid, 'h5678)\n }\n }\n-function put_svc_monitor_mac(options: Map<string,string>,\n- svc_monitor_mac: eth_addr) : Map<string,string> =\n+function put_svc_monitor_mac(options: mut Map<istring,istring>,\n+ svc_monitor_mac: eth_addr)\n {\n- options.insert_imm(\"svc_monitor_mac\", to_string(svc_monitor_mac))\n+ options.insert(i\"svc_monitor_mac\", svc_monitor_mac.to_string().intern());\n }\n relation SvcMonitorMac(mac: eth_addr)\n SvcMonitorMac(get_svc_monitor_mac(options, uuid)) :-\n nb::NB_Global(._uuid = uuid, .options = options).\n \n relation UseCtInvMatch[bool]\n-UseCtInvMatch[options.get_bool_def(\"use_ct_inv_match\", true)] :-\n+UseCtInvMatch[options.get_bool_def(i\"use_ct_inv_match\", true)] :-\n nb::NB_Global(.options = options).\n UseCtInvMatch[true] :-\n Unit(),\ndiff --git a/northd/multicast.dl b/northd/multicast.dl\nindex ef365b408..074caf654 100644\n--- a/northd/multicast.dl\n+++ b/northd/multicast.dl\n@@ -36,9 +36,9 @@ typedef McastSwitchCfg = McastSwitchCfg {\n enabled : bool,\n querier : bool,\n flood_unreg : bool,\n- eth_src : string,\n- ip4_src : string,\n- ip6_src : string,\n+ eth_src : istring,\n+ ip4_src : istring,\n+ ip6_src : istring,\n table_size : integer,\n idle_timeout : integer,\n query_interval: integer,\n@@ -53,24 +53,24 @@ relation McastSwitchCfg[Intern<McastSwitchCfg>]\n \n McastSwitchCfg[McastSwitchCfg {\n .datapath = ls_uuid,\n- .enabled = other_config.get_bool_def(\"mcast_snoop\", false),\n- .querier = other_config.get_bool_def(\"mcast_querier\", true),\n- .flood_unreg = other_config.get_bool_def(\"mcast_flood_unregistered\", false),\n- .eth_src = other_config.get(\"mcast_eth_src\").unwrap_or(\"\"),\n- .ip4_src = other_config.get(\"mcast_ip4_src\").unwrap_or(\"\"),\n- .ip6_src = other_config.get(\"mcast_ip6_src\").unwrap_or(\"\"),\n- .table_size = other_config.get_int_def(\"mcast_table_size\", mCAST_DEFAULT_MAX_ENTRIES()),\n+ .enabled = other_config.get_bool_def(i\"mcast_snoop\", false),\n+ .querier = other_config.get_bool_def(i\"mcast_querier\", true),\n+ .flood_unreg = other_config.get_bool_def(i\"mcast_flood_unregistered\", false),\n+ .eth_src = other_config.get(i\"mcast_eth_src\").unwrap_or(i\"\"),\n+ .ip4_src = other_config.get(i\"mcast_ip4_src\").unwrap_or(i\"\"),\n+ .ip6_src = other_config.get(i\"mcast_ip6_src\").unwrap_or(i\"\"),\n+ .table_size = other_config.get_int_def(i\"mcast_table_size\", mCAST_DEFAULT_MAX_ENTRIES()),\n .idle_timeout = idle_timeout,\n .query_interval = query_interval,\n .query_max_resp = query_max_resp\n }.intern()] :-\n &nb::Logical_Switch(._uuid = ls_uuid,\n .other_config = other_config),\n- var idle_timeout = other_config.get_int_def(\"mcast_idle_timeout\", mCAST_DEFAULT_IDLE_TIMEOUT_S())\n+ var idle_timeout = other_config.get_int_def(i\"mcast_idle_timeout\", mCAST_DEFAULT_IDLE_TIMEOUT_S())\n .clamp(mCAST_IDLE_TIMEOUT_S_RANGE()),\n- var query_interval = other_config.get_int_def(\"mcast_query_interval\", idle_timeout / 2)\n+ var query_interval = other_config.get_int_def(i\"mcast_query_interval\", idle_timeout / 2)\n .clamp(mCAST_QUERY_INTERVAL_S_RANGE()),\n- var query_max_resp = other_config.get_int_def(\"mcast_query_max_response\",\n+ var query_max_resp = other_config.get_int_def(i\"mcast_query_max_response\",\n mCAST_DEFAULT_QUERY_MAX_RESPONSE_S()).\n \n /* IP Multicast per router configuration. */\n@@ -83,7 +83,7 @@ relation McastRouterCfg[Intern<McastRouterCfg>]\n \n McastRouterCfg[McastRouterCfg{lr_uuid, mcast_relay}.intern()] :-\n nb::Logical_Router(._uuid = lr_uuid, .options = options),\n- var mcast_relay = options.get_bool_def(\"mcast_relay\", false).\n+ var mcast_relay = options.get_bool_def(i\"mcast_relay\", false).\n \n /* IP Multicast port configuration. */\n typedef McastPortCfg = McastPortCfg {\n@@ -97,12 +97,12 @@ relation McastPortCfg[Intern<McastPortCfg>]\n \n McastPortCfg[McastPortCfg{lsp_uuid, false, flood, flood_reports}.intern()] :-\n &nb::Logical_Switch_Port(._uuid = lsp_uuid, .options = options),\n- var flood = options.get_bool_def(\"mcast_flood\", false),\n- var flood_reports = options.get_bool_def(\"mcast_flood_reports\", false).\n+ var flood = options.get_bool_def(i\"mcast_flood\", false),\n+ var flood_reports = options.get_bool_def(i\"mcast_flood_reports\", false).\n \n McastPortCfg[McastPortCfg{lrp_uuid, true, flood, flood}.intern()] :-\n &nb::Logical_Router_Port(._uuid = lrp_uuid, .options = options),\n- var flood = options.get_bool_def(\"mcast_flood\", false).\n+ var flood = options.get_bool_def(i\"mcast_flood\", false).\n \n /* Mapping between Switch and the set of router port uuids on which to flood\n * IP multicast for relay.\n@@ -185,7 +185,7 @@ RouterMcastFloodPorts(router, set_empty()) :-\n \n /* Flattened IGMP group. One record per address-port tuple. */\n relation IgmpSwitchGroupPort(\n- address: string,\n+ address: istring,\n switch : Intern<Switch>,\n port : uuid\n )\n@@ -205,7 +205,7 @@ IgmpSwitchGroupPort(address, switch, localnet_port.0) :-\n * address-switch tuple from all chassis.\n */\n relation IgmpSwitchMulticastGroup(\n- address: string,\n+ address: istring,\n switch : Intern<Switch>,\n ports : Set<uuid>\n )\n@@ -219,7 +219,7 @@ IgmpSwitchMulticastGroup(address, switch, ports) :-\n * connected to the router.\n */\n relation IgmpRouterGroupPort(\n- address: string,\n+ address: istring,\n router : Intern<Router>,\n port : uuid\n )\n@@ -230,7 +230,7 @@ IgmpRouterGroupPort(address, rtr_port.router, rtr_port.lrp._uuid) :-\n /* For IPv6 only relay routable multicast groups\n * (RFC 4291 2.7).\n */\n- match (ipv6_parse(address)) {\n+ match (ipv6_parse(address.ival())) {\n Some{ipv6} -> ipv6.is_routable_multicast(),\n None -> true\n },\n@@ -242,7 +242,7 @@ IgmpRouterGroupPort(address, rtr_port.router, rtr_port.lrp._uuid) :-\n * a given address-router tuple from all connected switches.\n */\n relation IgmpRouterMulticastGroup(\n- address: string,\n+ address: istring,\n router : Intern<Router>,\n ports : Set<uuid>\n )\ndiff --git a/northd/ovn-nb.dlopts b/northd/ovn-nb.dlopts\nindex c22130004..9a460adef 100644\n--- a/northd/ovn-nb.dlopts\n+++ b/northd/ovn-nb.dlopts\n@@ -1,3 +1,4 @@\n+--intern-strings\n -o BFD\n --rw BFD.status\n -o Logical_Router_Port\ndiff --git a/northd/ovn-sb.dlopts b/northd/ovn-sb.dlopts\nindex ea4952758..99b65f101 100644\n--- a/northd/ovn-sb.dlopts\n+++ b/northd/ovn-sb.dlopts\n@@ -1,3 +1,4 @@\n+--intern-strings\n -o Address_Set\n -o BFD\n -o DHCP_Options\ndiff --git a/northd/ovn.dl b/northd/ovn.dl\nindex 3c7a734dd..3585eb3dc 100644\n--- a/northd/ovn.dl\n+++ b/northd/ovn.dl\n@@ -375,6 +375,13 @@ extern function ovn_internal_version(): string\n */\n extern function json_string_escape(s: string): string\n \n+function json_escape(s: string): string {\n+ s.json_string_escape()\n+}\n+function json_escape(s: istring): string {\n+ s.ival().json_string_escape()\n+}\n+\n /* For a 'key' of the form \"IP:port\" or just \"IP\", returns\n * (v46_ip, port) tuple. */\n extern function ip_address_and_port_from_lb_key(k: string): Option<(v46_ip, bit<16>)>\ndiff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl\nindex ff92c989c..4402b17d2 100644\n--- a/northd/ovn_northd.dl\n+++ b/northd/ovn_northd.dl\n@@ -48,29 +48,29 @@ sb::Out_Meter(._uuid = hash128(name),\n .unit = meter.unit,\n .bands = meter.bands) :-\n ACLWithFairMeter(acl, meter),\n- var name = acl_log_meter_name(meter.name, acl._uuid).\n+ var name = acl_log_meter_name(meter.name, acl._uuid).intern().\n \n /* Proxy table for Out_Datapath_Binding: contains all Datapath_Binding fields,\n * except tunnel id, which is allocated separately (see TunKeyAllocation). */\n relation OutProxy_Datapath_Binding (\n _uuid: uuid,\n- external_ids: Map<string,string>\n+ external_ids: Map<istring,istring>\n )\n \n /* Datapath_Binding table */\n OutProxy_Datapath_Binding(uuid, external_ids) :-\n &nb::Logical_Switch(._uuid = uuid, .name = name, .external_ids = ids,\n .other_config = other_config),\n- var uuid_str = uuid2str(uuid),\n+ var uuid_str = uuid2str(uuid).intern(),\n var external_ids = {\n- var eids = [\"logical-switch\" -> uuid_str, \"name\" -> name];\n- match (ids.get(\"neutron:network_name\")) {\n+ var eids = [i\"logical-switch\" -> uuid_str, i\"name\" -> name];\n+ match (ids.get(i\"neutron:network_name\")) {\n None -> (),\n- Some{nnn} -> eids.insert(\"name2\", nnn)\n+ Some{nnn} -> eids.insert(i\"name2\", nnn)\n };\n- match (other_config.get(\"interconn-ts\")) {\n+ match (other_config.get(i\"interconn-ts\")) {\n None -> (),\n- Some{value} -> eids.insert(\"interconn-ts\", value)\n+ Some{value} -> eids.insert(i\"interconn-ts\", value)\n };\n eids\n }.\n@@ -79,20 +79,20 @@ OutProxy_Datapath_Binding(uuid, external_ids) :-\n lr in nb::Logical_Router(._uuid = uuid, .name = name, .external_ids = ids,\n .options = options),\n lr.is_enabled(),\n- var uuid_str = uuid2str(uuid),\n+ var uuid_str = uuid2str(uuid).intern(),\n var external_ids = {\n- var eids = [\"logical-router\" -> uuid_str, \"name\" -> name];\n- match (ids.get(\"neutron:router_name\")) {\n+ var eids = [i\"logical-router\" -> uuid_str, i\"name\" -> name];\n+ match (ids.get(i\"neutron:router_name\")) {\n None -> (),\n- Some{nnn} -> eids.insert(\"name2\", nnn)\n+ Some{nnn} -> eids.insert(i\"name2\", nnn)\n };\n- match (options.get(\"snat-ct-zone\").and_then(parse_dec_u64)) {\n+ match (options.get(i\"snat-ct-zone\").and_then(parse_dec_u64)) {\n None -> (),\n- Some{zone} -> eids.insert(\"snat-ct-zone\", \"${zone}\")\n+ Some{zone} -> eids.insert(i\"snat-ct-zone\", i\"${zone}\")\n };\n- var learn_from_arp_request = options.get_bool_def(\"always_learn_from_arp_request\", true);\n+ var learn_from_arp_request = options.get_bool_def(i\"always_learn_from_arp_request\", true);\n if (not learn_from_arp_request) {\n- eids.insert(\"always_learn_from_arp_request\", \"false\")\n+ eids.insert(i\"always_learn_from_arp_request\", i\"false\")\n };\n eids\n }.\n@@ -110,17 +110,17 @@ sb::Out_Datapath_Binding(uuid, tunkey, load_balancers, external_ids) :-\n * except tunnel id, which is allocated separately (see PortTunKeyAllocation). */\n relation OutProxy_Port_Binding (\n _uuid: uuid,\n- logical_port: string,\n- __type: string,\n+ logical_port: istring,\n+ __type: istring,\n gateway_chassis: Set<uuid>,\n ha_chassis_group: Option<uuid>,\n- options: Map<string,string>,\n+ options: Map<istring,istring>,\n datapath: uuid,\n- parent_port: Option<string>,\n+ parent_port: Option<istring>,\n tag: Option<integer>,\n- mac: Set<string>,\n- nat_addresses: Set<string>,\n- external_ids: Map<string,string>\n+ mac: Set<istring>,\n+ nat_addresses: Set<istring>,\n+ external_ids: Map<istring,istring>\n )\n \n /* Case 1: Create a Port_Binding per logical switch port that is not of type \"router\" */\n@@ -142,20 +142,19 @@ OutProxy_Port_Binding(._uuid = lsp._uuid,\n None -> lsp.tag,\n Some{t} -> Some{t}\n },\n- lsp.__type != \"router\",\n+ lsp.__type != i\"router\",\n var eids = {\n var eids = lsp.external_ids;\n- match (lsp.external_ids.get(\"neutron:port_name\")) {\n+ match (lsp.external_ids.get(i\"neutron:port_name\")) {\n None -> (),\n- Some{name} -> eids.insert(\"name\", name)\n+ Some{name} -> eids.insert(i\"name\", name)\n };\n eids\n },\n var options = {\n var options = lsp.options;\n- match (sw.other_config.get(\"vlan-passthru\")) {\n- Some{\"true\"} -> options.insert(\"vlan-passthru\", \"true\"),\n- _ -> ()\n+ if (sw.other_config.get(i\"vlan-passthru\") == Some{i\"true\"}) {\n+ options.insert(i\"vlan-passthru\", i\"true\")\n };\n options\n }.\n@@ -177,47 +176,50 @@ OutProxy_Port_Binding(._uuid = lsp._uuid,\n &SwitchPort(.lsp = lsp, .sw = sw, .peer = peer),\n var eids = {\n var eids = lsp.external_ids;\n- match (lsp.external_ids.get(\"neutron:port_name\")) {\n+ match (lsp.external_ids.get(i\"neutron:port_name\")) {\n None -> (),\n- Some{name} -> eids.insert(\"name\", name)\n+ Some{name} -> eids.insert(i\"name\", name)\n };\n eids\n },\n- Some{var router_port} = lsp.options.get(\"router-port\"),\n- var opt_chassis = peer.and_then(|p| p.router.options.get(\"chassis\")),\n+ Some{var router_port} = lsp.options.get(i\"router-port\"),\n+ var opt_chassis = peer.and_then(|p| p.router.options.get(i\"chassis\")),\n var l3dgw_port = peer.and_then(|p| p.router.l3dgw_ports.nth(0)),\n (var __type, var options) = {\n- var options = [\"peer\" -> router_port];\n+ var options = [i\"peer\" -> router_port];\n match (opt_chassis) {\n None -> {\n- (\"patch\", options)\n+ (i\"patch\", options)\n },\n Some{chassis} -> {\n- options.insert(\"l3gateway-chassis\", chassis);\n- (\"l3gateway\", options)\n+ options.insert(i\"l3gateway-chassis\", chassis);\n+ (i\"l3gateway\", options)\n }\n }\n },\n var base_nat_addresses = {\n- match (lsp.options.get(\"nat-addresses\")) {\n+ match (lsp.options.get(i\"nat-addresses\")) {\n None -> { set_empty() },\n- Some{\"router\"} -> match ((l3dgw_port, opt_chassis, peer)) {\n- (None, None, _) -> set_empty(),\n- (_, _, None) -> set_empty(),\n- (_, _, Some{rport}) -> get_nat_addresses(rport, false)\n- },\n Some{nat_addresses} -> {\n- /* Only accept manual specification of ethernet address\n- * followed by IPv4 addresses on type \"l3gateway\" ports. */\n- if (opt_chassis.is_some()) {\n- match (extract_lsp_addresses(nat_addresses)) {\n- None -> {\n- warn(\"Error extracting nat-addresses.\");\n- set_empty()\n- },\n- Some{_} -> { set_singleton(nat_addresses) }\n+ if (nat_addresses == i\"router\") {\n+ match ((l3dgw_port, opt_chassis, peer)) {\n+ (None, None, _) -> set_empty(),\n+ (_, _, None) -> set_empty(),\n+ (_, _, Some{rport}) -> get_nat_addresses(rport, false)\n }\n- } else { set_empty() }\n+ } else {\n+ /* Only accept manual specification of ethernet address\n+ * followed by IPv4 addresses on type \"l3gateway\" ports. */\n+ if (opt_chassis.is_some()) {\n+ match (extract_lsp_addresses(nat_addresses.ival())) {\n+ None -> {\n+ warn(\"Error extracting nat-addresses.\");\n+ set_empty()\n+ },\n+ Some{_} -> { set_singleton(nat_addresses) }\n+ }\n+ } else { set_empty() }\n+ }\n }\n }\n },\n@@ -239,13 +241,13 @@ OutProxy_Port_Binding(._uuid = lsp._uuid,\n * */\n var garp_nat_addresses = match (peer) {\n Some{rport} -> match (\n- (rport.lrp.options.get_bool_def(\"reside-on-redirect-chassis\", false)\n+ (rport.lrp.options.get_bool_def(i\"reside-on-redirect-chassis\", false)\n and l3dgw_port.is_some()) or\n rport.is_redirect or\n- (rport.router.options.contains_key(\"chassis\") and\n+ (rport.router.options.contains_key(i\"chassis\") and\n not sw.localnet_ports.is_empty())) {\n false -> set_empty(),\n- true -> set_singleton(get_garp_nat_addresses(rport))\n+ true -> set_singleton(get_garp_nat_addresses(rport).intern())\n },\n None -> set_empty()\n },\n@@ -261,46 +263,46 @@ OutProxy_Port_Binding(._uuid = lrp._uuid,\n .datapath = router._uuid,\n .parent_port = None,\n .tag = None, // always empty for router ports\n- .mac = set_singleton(\"${lrp.mac} ${lrp.networks.join(\\\" \\\")}\"),\n+ .mac = set_singleton(i\"${lrp.mac} ${lrp.networks.map(ival).to_vec().join(\\\" \\\")}\"),\n .nat_addresses = set_empty(),\n .external_ids = lrp.external_ids) :-\n rp in &RouterPort(.lrp = lrp, .router = router, .peer = peer),\n RouterPortRAOptionsComplete(lrp._uuid, options0),\n- (var __type, var options1) = match (router.options.get(\"chassis\")) {\n+ (var __type, var options1) = match (router.options.get(i\"chassis\")) {\n /* TODO: derived ports */\n- None -> (\"patch\", map_empty()),\n- Some{lrchassis} -> (\"l3gateway\", [\"l3gateway-chassis\" -> lrchassis])\n+ None -> (i\"patch\", map_empty()),\n+ Some{lrchassis} -> (i\"l3gateway\", [i\"l3gateway-chassis\" -> lrchassis])\n },\n var options2 = match (router_peer_name(peer)) {\n None -> map_empty(),\n- Some{peer_name} -> [\"peer\" -> peer_name]\n+ Some{peer_name} -> [i\"peer\" -> peer_name]\n },\n var options3 = match ((peer, rp.networks.ipv6_addrs.is_empty())) {\n (PeerSwitch{_, _}, false) -> {\n var enabled = lrp.is_enabled();\n- var pd = lrp.options.get_bool_def(\"prefix_delegation\", false);\n- var p = lrp.options.get_bool_def(\"prefix\", false);\n- [\"ipv6_prefix_delegation\" -> \"${pd and enabled}\",\n- \"ipv6_prefix\" -> \"${p and enabled}\"]\n+ var pd = lrp.options.get_bool_def(i\"prefix_delegation\", false);\n+ var p = lrp.options.get_bool_def(i\"prefix\", false);\n+ [i\"ipv6_prefix_delegation\" -> i\"${pd and enabled}\",\n+ i\"ipv6_prefix\" -> i\"${p and enabled}\"]\n },\n _ -> map_empty()\n },\n PreserveIPv6RAPDList(lrp._uuid, ipv6_ra_pd_list),\n var options4 = match (ipv6_ra_pd_list) {\n None -> map_empty(),\n- Some{value} -> [\"ipv6_ra_pd_list\" -> value]\n+ Some{value} -> [i\"ipv6_ra_pd_list\" -> value]\n },\n RouterPortIsRedirect(lrp._uuid, is_redirect),\n var options5 = match (is_redirect) {\n false -> map_empty(),\n- true -> [\"chassis-redirect-port\" -> chassis_redirect_name(lrp.name)]\n+ true -> [i\"chassis-redirect-port\" -> chassis_redirect_name(lrp.name).intern()]\n },\n var options = options0.union(options1).union(options2).union(options3).union(options4).union(options5),\n var eids = {\n var eids = lrp.external_ids;\n- match (lrp.external_ids.get(\"neutron:port_name\")) {\n+ match (lrp.external_ids.get(i\"neutron:port_name\")) {\n None -> (),\n- Some{name} -> eids.insert(\"name\", name)\n+ Some{name} -> eids.insert(i\"name\", name)\n };\n eids\n }.\n@@ -308,21 +310,20 @@ OutProxy_Port_Binding(._uuid = lrp._uuid,\n */\n function get_router_load_balancer_ips(router: Intern<Router>,\n routable_only: bool) :\n- (Set<string>, Set<string>) =\n+ (Set<istring>, Set<istring>) =\n {\n var all_ips_v4 = set_empty();\n var all_ips_v6 = set_empty();\n for (lb in router.lbs) {\n- if (routable_only and not lb.options.get_bool_def(\"add_route\", false)) {\n+ if (routable_only and not lb.options.get_bool_def(i\"add_route\", false)) {\n continue;\n };\n- for (kv in lb.vips) {\n- (var vip, _) = kv;\n+ for ((vip, _) in lb.vips) {\n /* node->key contains IP:port or just IP. */\n- match (ip_address_and_port_from_lb_key(vip)) {\n+ match (ip_address_and_port_from_lb_key(vip.ival())) {\n None -> (),\n- Some{(IPv4{ipv4}, _)} -> all_ips_v4.insert(\"${ipv4}\"),\n- Some{(IPv6{ipv6}, _)} -> all_ips_v6.insert(\"${ipv6}\")\n+ Some{(IPv4{ipv4}, _)} -> all_ips_v4.insert(i\"${ipv4}\"),\n+ Some{(IPv6{ipv6}, _)} -> all_ips_v6.insert(i\"${ipv6}\")\n }\n }\n };\n@@ -337,11 +338,11 @@ function get_router_load_balancer_ips(router: Intern<Router>,\n * external IP addresses of all NAT rules defined on that router, and all\n * of the IP addresses used in load balancer VIPs defined on that router.\n */\n-function get_nat_addresses(rport: Intern<RouterPort>, routable_only: bool): Set<string> =\n+function get_nat_addresses(rport: Intern<RouterPort>, routable_only: bool): Set<istring> =\n {\n var addresses = set_empty();\n var has_redirect = not rport.router.l3dgw_ports.is_empty();\n- match (eth_addr_from_string(rport.lrp.mac)) {\n+ match (eth_addr_from_string(rport.lrp.mac.ival())) {\n None -> addresses,\n Some{mac} -> {\n var c_addresses = \"${mac}\";\n@@ -350,19 +351,19 @@ function get_nat_addresses(rport: Intern<RouterPort>, routable_only: bool): Set<\n /* Get NAT IP addresses. */\n for (nat in rport.router.nats) {\n if (routable_only and\n- (nat.nat.__type == \"snat\" or\n- not nat.nat.options.get_bool_def(\"add_route\", false))) {\n+ (nat.nat.__type == i\"snat\" or\n+ not nat.nat.options.get_bool_def(i\"add_route\", false))) {\n continue;\n };\n /* Determine whether this NAT rule satisfies the conditions for\n * distributed NAT processing. */\n- if (has_redirect and nat.nat.__type == \"dnat_and_snat\" and\n+ if (has_redirect and nat.nat.__type == i\"dnat_and_snat\" and\n nat.nat.logical_port.is_some() and nat.external_mac.is_some()) {\n /* Distributed NAT rule. */\n- var logical_port = option_unwrap_or_default(nat.nat.logical_port);\n- var external_mac = option_unwrap_or_default(nat.external_mac);\n- addresses.insert(\"${external_mac} ${nat.external_ip} \"\n- \"is_chassis_resident(${json_string_escape(logical_port)})\")\n+ var logical_port = nat.nat.logical_port.unwrap_or_default();\n+ var external_mac = nat.external_mac.unwrap_or_default();\n+ addresses.insert(i\"${external_mac} ${nat.external_ip} \"\n+ \"is_chassis_resident(${json_escape(logical_port)})\")\n } else {\n /* Centralized NAT rule, either on gateway router or distributed\n * router.\n@@ -409,11 +410,11 @@ function get_nat_addresses(rport: Intern<RouterPort>, routable_only: bool): Set<\n if (has_redirect) {\n c_addresses = c_addresses ++ match (rport.router.l3dgw_ports.nth(0)) {\n None -> \"\",\n- Some {var gw_port} -> \" is_chassis_resident(${json_string_escape(chassis_redirect_name(gw_port.name))})\"\n+ Some {var gw_port} -> \" is_chassis_resident(${json_escape(chassis_redirect_name(gw_port.name))})\"\n }\n } else ();\n \n- addresses.insert(c_addresses)\n+ addresses.insert(c_addresses.intern())\n } else ();\n addresses\n }\n@@ -428,15 +429,15 @@ function get_garp_nat_addresses(rport: Intern<RouterPort>): string = {\n match (rport.router.l3dgw_ports.nth(0)) {\n None -> (),\n Some {var gw_port} -> garp_info.push(\n- \"is_chassis_resident(${json_string_escape(chassis_redirect_name(gw_port.name))})\")\n+ \"is_chassis_resident(${json_escape(chassis_redirect_name(gw_port.name))})\")\n };\n garp_info.join(\" \")\n }\n \n /* Extra options computed for router ports by the logical flow generation code */\n-relation RouterPortRAOptions(lrp: uuid, options: Map<string, string>)\n+relation RouterPortRAOptions(lrp: uuid, options: Map<istring, istring>)\n \n-relation RouterPortRAOptionsComplete(lrp: uuid, options: Map<string, string>)\n+relation RouterPortRAOptionsComplete(lrp: uuid, options: Map<istring, istring>)\n \n RouterPortRAOptionsComplete(lrp, options) :-\n RouterPortRAOptions(lrp, options).\n@@ -446,7 +447,7 @@ RouterPortRAOptionsComplete(lrp, map_empty()) :-\n \n function has_distributed_nat(nats: Vec<NAT>): bool {\n for (nat in nats) {\n- if (nat.nat.__type == \"dnat_and_snat\") {\n+ if (nat.nat.__type == i\"dnat_and_snat\") {\n return true\n }\n };\n@@ -461,31 +462,31 @@ function has_distributed_nat(nats: Vec<NAT>): bool {\n OutProxy_Port_Binding(// lrp._uuid is already in use; generate a new UUID by\n // hashing it.\n ._uuid = hash128(lrp._uuid),\n- .logical_port = chassis_redirect_name(lrp.name),\n- .__type = \"chassisredirect\",\n+ .logical_port = chassis_redirect_name(lrp.name).intern(),\n+ .__type = i\"chassisredirect\",\n .gateway_chassis = set_empty(),\n .ha_chassis_group = Some{hacg_uuid},\n .options = options,\n .datapath = lr_uuid,\n .parent_port = None,\n .tag = None, //always empty for router ports\n- .mac = set_singleton(\"${lrp.mac} ${lrp.networks.join(\\\" \\\")}\"),\n+ .mac = set_singleton(i\"${lrp.mac} ${lrp.networks.map(ival).to_vec().join(\\\" \\\")}\"),\n .nat_addresses = set_empty(),\n .external_ids = lrp.external_ids) :-\n DistributedGatewayPort(lrp, lr_uuid),\n DistributedGatewayPortHAChassisGroup(lrp, hacg_uuid),\n- var redirect_type = match (lrp.options.get(\"redirect-type\")) {\n- Some{var value} -> [\"redirect-type\" -> value],\n+ var redirect_type = match (lrp.options.get(i\"redirect-type\")) {\n+ Some{var value} -> [i\"redirect-type\" -> value],\n _ -> map_empty()\n },\n LogicalRouterNATs(lr_uuid, nats),\n var always_redirect = if (has_distributed_nat(nats) or\n- lrp.options.get(\"redirect-type\") == Some{\"bridged\"}) {\n+ lrp.options.get(i\"redirect-type\") == Some{i\"bridged\"}) {\n map_empty()\n } else {\n- [\"always-redirect\" -> \"true\"]\n+ [i\"always-redirect\" -> i\"true\"]\n },\n- var options = redirect_type.union(always_redirect).insert_imm(\"distributed-port\", lrp.name).\n+ var options = redirect_type.union(always_redirect).insert_imm(i\"distributed-port\", lrp.name).\n \n /*\n * We want to preserve 'up' (set by ovn-controller) for Port_Binding rows.\n@@ -523,7 +524,7 @@ sb::Out_Port_Binding(._uuid = pbinding._uuid,\n PortBindingUp(pbinding._uuid, up),\n var options0 = match (qid) {\n None -> pbinding.options,\n- Some{id} -> pbinding.options.insert_imm(\"qdisc_queue_id\", \"${id}\")\n+ Some{id} -> pbinding.options.insert_imm(i\"qdisc_queue_id\", i\"${id}\")\n }.\n \n /* Referenced chassis.\n@@ -578,28 +579,28 @@ HAChassisGroupRefChassisSet(hacg_uuid, chassis_uuids) :-\n /* HA_Chassis_Group and HA_Chassis. */\n sb::Out_HA_Chassis_Group(hacg_uuid, hacg_name, ha_chassis, ref_chassis, eids) :-\n HAChassis(hacg_uuid, hac_uuid, chassis_name, _, _),\n- var chassis_uuid = ha_chassis_uuid(chassis_name, hac_uuid),\n+ var chassis_uuid = ha_chassis_uuid(chassis_name.ival(), hac_uuid),\n var ha_chassis = chassis_uuid.group_by(hacg_uuid).to_set(),\n HAChassisGroup(hacg_uuid, hacg_name, eids),\n HAChassisGroupRefChassisSet(hacg_uuid, ref_chassis).\n \n-sb::Out_HA_Chassis(ha_chassis_uuid(chassis_name, hac_uuid), chassis, priority, eids) :-\n+sb::Out_HA_Chassis(ha_chassis_uuid(chassis_name.ival(), hac_uuid), chassis, priority, eids) :-\n HAChassis(_, hac_uuid, chassis_name, priority, eids),\n chassis_rec in sb::Chassis(.name = chassis_name),\n var chassis = Some{chassis_rec._uuid}.\n-sb::Out_HA_Chassis(ha_chassis_uuid(chassis_name, hac_uuid), None, priority, eids) :-\n+sb::Out_HA_Chassis(ha_chassis_uuid(chassis_name.ival(), hac_uuid), None, priority, eids) :-\n HAChassis(_, hac_uuid, chassis_name, priority, eids),\n not chassis_rec in sb::Chassis(.name = chassis_name).\n \n-relation HAChassisToChassis(name: string, chassis: Option<uuid>)\n+relation HAChassisToChassis(name: istring, chassis: Option<uuid>)\n HAChassisToChassis(name, Some{chassis}) :-\n sb::Chassis(._uuid = chassis, .name = name).\n HAChassisToChassis(name, None) :-\n nb::HA_Chassis(.chassis_name = name),\n not sb::Chassis(.name = name).\n-sb::Out_HA_Chassis(ha_chassis_uuid(ha_chassis.chassis_name, hac_uuid), chassis, priority, eids) :-\n+sb::Out_HA_Chassis(ha_chassis_uuid(ha_chassis.chassis_name.ival(), hac_uuid), chassis, priority, eids) :-\n sp in &SwitchPort(),\n- sp.lsp.__type == \"external\",\n+ sp.lsp.__type == i\"external\",\n Some{var ha_chassis_group_uuid} = sp.lsp.ha_chassis_group,\n ha_chassis_group in nb::HA_Chassis_Group(._uuid = ha_chassis_group_uuid),\n var hac_uuid = FlatMap(ha_chassis_group.ha_chassis),\n@@ -607,14 +608,14 @@ sb::Out_HA_Chassis(ha_chassis_uuid(ha_chassis.chassis_name, hac_uuid), chassis,\n HAChassisToChassis(ha_chassis.chassis_name, chassis).\n sb::Out_HA_Chassis_Group(_uuid, name, ha_chassis, set_empty() /* XXX? */, eids) :-\n sp in &SwitchPort(),\n- sp.lsp.__type == \"external\",\n+ sp.lsp.__type == i\"external\",\n var ls_uuid = sp.sw._uuid,\n Some{var ha_chassis_group_uuid} = sp.lsp.ha_chassis_group,\n ha_chassis_group in nb::HA_Chassis_Group(._uuid = ha_chassis_group_uuid, .name = name,\n .external_ids = eids),\n var hac_uuid = FlatMap(ha_chassis_group.ha_chassis),\n ha_chassis in nb::HA_Chassis(._uuid = hac_uuid),\n- var ha_chassis_uuid_name = ha_chassis_uuid(ha_chassis.chassis_name, hac_uuid),\n+ var ha_chassis_uuid_name = ha_chassis_uuid(ha_chassis.chassis_name.ival(), hac_uuid),\n var ha_chassis = ha_chassis_uuid_name.group_by((ls_uuid, name, eids)).to_set(),\n var _uuid = ha_chassis_group_uuid(ls_uuid).\n \n@@ -642,7 +643,7 @@ sb::Out_SB_Global(._uuid = sb_global._uuid,\n relation ChassisPrivate(\n cp: sb::Chassis_Private,\n is_remote: bool)\n-ChassisPrivate(cp, c.other_config.get_bool_def(\"is-remote\", false)) :-\n+ChassisPrivate(cp, c.other_config.get_bool_def(i\"is-remote\", false)) :-\n cp in sb::Chassis_Private(.chassis = Some{uuid}),\n c in sb::Chassis(._uuid = uuid).\n ChassisPrivate(cp, false),\n@@ -708,10 +709,14 @@ OutNBGlobal0[nb::Out_NB_Global{._uuid = _uuid,\n MacPrefix(mac_prefix),\n SvcMonitorMac(svc_monitor_mac),\n OvnMaxDpKeyLocal[max_tunid],\n- var options0 = put_mac_prefix(nbg.options, mac_prefix),\n- var options1 = put_svc_monitor_mac(options0, svc_monitor_mac),\n- var options2 = options1.insert_imm(\"max_tunid\", \"${max_tunid}\"),\n- var options = options2.insert_imm(\"northd_internal_version\", ovn_internal_version()).\n+ var options = {\n+ var options = nbg.options;\n+ options.put_mac_prefix(mac_prefix);\n+ options.put_svc_monitor_mac(svc_monitor_mac);\n+ options.insert(i\"max_tunid\", i\"${max_tunid}\");\n+ options.insert(i\"northd_internal_version\", ovn_internal_version().intern());\n+ options\n+ }.\n \n relation OutNBGlobal1[nb::Out_NB_Global]\n OutNBGlobal1[x] :- OutNBGlobal0[x].\n@@ -740,12 +745,12 @@ SbCfg[sb_cfg] :- nb::Out_NB_Global(.sb_cfg = sb_cfg).\n output relation Northd_Probe_Interval[s64]\n Northd_Probe_Interval[interval] :-\n nb in nb::NB_Global(),\n- var interval = nb.options.get(\"northd_probe_interval\").and_then(parse_dec_i64).unwrap_or(-1).\n+ var interval = nb.options.get(i\"northd_probe_interval\").and_then(parse_dec_i64).unwrap_or(-1).\n \n relation CheckLspIsUp[bool]\n CheckLspIsUp[check_lsp_is_up] :-\n nb in nb::NB_Global(),\n- var check_lsp_is_up = not nb.options.get_bool_def(\"ignore_lsp_down\", false).\n+ var check_lsp_is_up = not nb.options.get_bool_def(i\"ignore_lsp_down\", false).\n CheckLspIsUp[true] :-\n Unit(),\n not nb in nb::NB_Global().\n@@ -763,13 +768,13 @@ sb::Out_Address_Set(._uuid = nb_as._uuid,\n nb_as in &nb::Address_Set().\n \n sb::Out_Address_Set(._uuid = hash128(\"svc_monitor_mac\"),\n- .name = \"svc_monitor_mac\",\n- .addresses = set_singleton(\"${svc_monitor_mac}\")) :-\n+ .name = i\"svc_monitor_mac\",\n+ .addresses = set_singleton(i\"${svc_monitor_mac}\")) :-\n SvcMonitorMac(svc_monitor_mac).\n \n sb::Out_Address_Set(hash128(as_name), as_name, pg_ip4addrs.union()) :-\n PortGroupPort(.pg_name = pg_name, .port = port_uuid),\n- var as_name = pg_name ++ \"_ip4\",\n+ var as_name = i\"${pg_name}_ip4\",\n // avoid name collisions with user-defined Address_Sets\n not &nb::Address_Set(.name = as_name),\n PortStaticAddresses(.lsport = port_uuid, .ip4addrs = stat),\n@@ -779,7 +784,7 @@ sb::Out_Address_Set(hash128(as_name), as_name, pg_ip4addrs.union()) :-\n None -> set_empty(),\n Some{lpaddress} -> match (lpaddress.ipv4_addrs.nth(0)) {\n None -> set_empty(),\n- Some{addr} -> set_singleton(\"${addr.addr}\")\n+ Some{addr} -> set_singleton(i\"${addr.addr}\")\n }\n },\n //PortDynamicAddresses(.lsport = port_uuid, .ip4addrs = dynamic),\n@@ -788,13 +793,13 @@ sb::Out_Address_Set(hash128(as_name), as_name, pg_ip4addrs.union()) :-\n \n sb::Out_Address_Set(hash128(as_name), as_name, set_empty()) :-\n nb::Port_Group(.ports = set_empty(), .name = pg_name),\n- var as_name = pg_name ++ \"_ip4\",\n+ var as_name = i\"${pg_name}_ip4\",\n // avoid name collisions with user-defined Address_Sets\n not &nb::Address_Set(.name = as_name).\n \n sb::Out_Address_Set(hash128(as_name), as_name, pg_ip6addrs.union()) :-\n PortGroupPort(.pg_name = pg_name, .port = port_uuid),\n- var as_name = pg_name ++ \"_ip6\",\n+ var as_name = i\"${pg_name}_ip6\",\n // avoid name collisions with user-defined Address_Sets\n not &nb::Address_Set(.name = as_name),\n PortStaticAddresses(.lsport = port_uuid, .ip6addrs = stat),\n@@ -804,7 +809,7 @@ sb::Out_Address_Set(hash128(as_name), as_name, pg_ip6addrs.union()) :-\n None -> set_empty(),\n Some{lpaddress} -> match (lpaddress.ipv6_addrs.nth(0)) {\n None -> set_empty(),\n- Some{addr} -> set_singleton(\"${addr.addr}\")\n+ Some{addr} -> set_singleton(i\"${addr.addr}\")\n }\n },\n //PortDynamicAddresses(.lsport = port_uuid, .ip6addrs = dynamic),\n@@ -813,7 +818,7 @@ sb::Out_Address_Set(hash128(as_name), as_name, pg_ip6addrs.union()) :-\n \n sb::Out_Address_Set(hash128(as_name), as_name, set_empty()) :-\n nb::Port_Group(.ports = set_empty(), .name = pg_name),\n- var as_name = pg_name ++ \"_ip6\",\n+ var as_name = i\"${pg_name}_ip6\",\n // avoid name collisions with user-defined Address_Sets\n not &nb::Address_Set(.name = as_name).\n \n@@ -828,7 +833,7 @@ sb::Out_Address_Set(hash128(as_name), as_name, set_empty()) :-\n \n relation PortGroupPort(\n pg_uuid: uuid,\n- pg_name: string,\n+ pg_name: istring,\n port: uuid)\n \n PortGroupPort(pg_uuid, pg_name, port) :-\n@@ -841,7 +846,7 @@ sb::Out_Port_Group(._uuid = hash128(sb_name), .name = sb_name, .ports = port_nam\n .name = port_name},\n .sw = &Switch{._uuid = ls_uuid}),\n TunKeyAllocation(.datapath = ls_uuid, .tunkey = tunkey),\n- var sb_name = \"${tunkey}_${nb_name}\",\n+ var sb_name = i\"${tunkey}_${nb_name}\",\n var port_names = port_name.group_by((_uuid, sb_name)).to_set().\n \n /*\n@@ -852,29 +857,29 @@ sb::Out_Port_Group(._uuid = hash128(sb_name), .name = sb_name, .ports = port_nam\n * - dynamically created rows based on IGMP groups learned by controllers.\n */\n \n-function mC_FLOOD(): (string, integer) =\n- (\"_MC_flood\", 32768)\n+function mC_FLOOD(): (istring, integer) =\n+ (i\"_MC_flood\", 32768)\n \n-function mC_UNKNOWN(): (string, integer) =\n- (\"_MC_unknown\", 32769)\n+function mC_UNKNOWN(): (istring, integer) =\n+ (i\"_MC_unknown\", 32769)\n \n-function mC_MROUTER_FLOOD(): (string, integer) =\n- (\"_MC_mrouter_flood\", 32770)\n+function mC_MROUTER_FLOOD(): (istring, integer) =\n+ (i\"_MC_mrouter_flood\", 32770)\n \n-function mC_MROUTER_STATIC(): (string, integer) =\n- (\"_MC_mrouter_static\", 32771)\n+function mC_MROUTER_STATIC(): (istring, integer) =\n+ (i\"_MC_mrouter_static\", 32771)\n \n-function mC_STATIC(): (string, integer) =\n- (\"_MC_static\", 32772)\n+function mC_STATIC(): (istring, integer) =\n+ (i\"_MC_static\", 32772)\n \n-function mC_FLOOD_L2(): (string, integer) =\n- (\"_MC_flood_l2\", 32773)\n+function mC_FLOOD_L2(): (istring, integer) =\n+ (i\"_MC_flood_l2\", 32773)\n \n-function mC_IP_MCAST_MIN(): (string, integer) =\n- (\"_MC_ip_mcast_min\", 32774)\n+function mC_IP_MCAST_MIN(): (istring, integer) =\n+ (i\"_MC_ip_mcast_min\", 32774)\n \n-function mC_IP_MCAST_MAX(): (string, integer) =\n- (\"_MC_ip_mcast_max\", 65535)\n+function mC_IP_MCAST_MAX(): (istring, integer) =\n+ (i\"_MC_ip_mcast_max\", 65535)\n \n \n // TODO: check that Multicast_Group.ports should not include derived ports\n@@ -885,7 +890,7 @@ function mC_IP_MCAST_MAX(): (string, integer) =\n * MulticastGroupTunKeyAllocation). */\n relation OutProxy_Multicast_Group (\n datapath: uuid,\n- name: string,\n+ name: istring,\n ports: Set<uuid>\n )\n \n@@ -910,7 +915,7 @@ sb::Out_Multicast_Group (._uuid = hash128((datapath,name)),\n .ports = port_ids) :-\n &SwitchPort(.lsp = lsp, .sw = sw),\n lsp.is_enabled(),\n- lsp.__type != \"router\",\n+ lsp.__type != i\"router\",\n var datapath = sw._uuid,\n var port_ids = lsp._uuid.group_by((datapath)).to_set(),\n (var name, var tunnel_key) = mC_FLOOD_L2().\n@@ -1015,261 +1020,261 @@ sb::Out_MAC_Binding (._uuid = mb._uuid,\n */\n sb::Out_DHCP_Options (\n ._uuid = 128'h7d9d898a_179b_4898_8382_b73bec391f23,\n- .name = \"offerip\",\n+ .name = i\"offerip\",\n .code = 0,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'hea5e7d14_fd97_491c_8004_a120bdbc4306,\n- .name = \"netmask\",\n+ .name = i\"netmask\",\n .code = 1,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'hdab5e39b_6702_4245_9573_6c142aa3724c,\n- .name = \"router\",\n+ .name = i\"router\",\n .code = 3,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h340b4bc5_c5c3_43d1_ae77_564da69c8fcc,\n- .name = \"dns_server\",\n+ .name = i\"dns_server\",\n .code = 6,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'hcd1ab302_cbb2_4eab_9ec5_ec1c8541bd82,\n- .name = \"log_server\",\n+ .name = i\"log_server\",\n .code = 7,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h1c7ea6a0_fe6b_48c1_a920_302583c1ff08,\n- .name = \"lpr_server\",\n+ .name = i\"lpr_server\",\n .code = 9,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'hae312373_2261_41b5_a2c4_186f426dd929,\n- .name = \"hostname\",\n+ .name = i\"hostname\",\n .code = 12,\n- .__type = \"str\"\n+ .__type = i\"str\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'hae35e575_226a_4ab5_a1c4_166f426dd999,\n- .name = \"domain_name\",\n+ .name = i\"domain_name\",\n .code = 15,\n- .__type = \"str\"\n+ .__type = i\"str\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'had0ec3e0_8be9_4c77_bceb_f8954a34c7ba,\n- .name = \"swap_server\",\n+ .name = i\"swap_server\",\n .code = 16,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h884c2e02_6e99_4d12_aef7_8454ebf8a3b7,\n- .name = \"policy_filter\",\n+ .name = i\"policy_filter\",\n .code = 21,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h57cc2c61_fd2a_41c6_b6b1_6ce9a8901f86,\n- .name = \"router_solicitation\",\n+ .name = i\"router_solicitation\",\n .code = 32,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h48249097_03f0_46c1_a32a_2dd57cd4d0f8,\n- .name = \"nis_server\",\n+ .name = i\"nis_server\",\n .code = 41,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h333fe07e_bdd1_4371_aa4f_a412bc60f3a2,\n- .name = \"ntp_server\",\n+ .name = i\"ntp_server\",\n .code = 42,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h6207109c_49d0_4348_8238_dd92afb69bf0,\n- .name = \"server_id\",\n+ .name = i\"server_id\",\n .code = 54,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h2090b783_26d3_4c1d_830c_54c1b6c5d846,\n- .name = \"tftp_server\",\n+ .name = i\"tftp_server\",\n .code = 66,\n- .__type = \"host_id\"\n+ .__type = i\"host_id\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'ha18ff399_caea_406e_af7e_321c6f74e581,\n- .name = \"classless_static_route\",\n+ .name = i\"classless_static_route\",\n .code = 121,\n- .__type = \"static_routes\"\n+ .__type = i\"static_routes\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'hb81ad7b4_62f0_40c7_a9a3_f96677628767,\n- .name = \"ms_classless_static_route\",\n+ .name = i\"ms_classless_static_route\",\n .code = 249,\n- .__type = \"static_routes\"\n+ .__type = i\"static_routes\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h0c2e144e_4b5f_4e21_8978_0e20bac9a6ea,\n- .name = \"ip_forward_enable\",\n+ .name = i\"ip_forward_enable\",\n .code = 19,\n- .__type = \"bool\"\n+ .__type = i\"bool\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h6feb1926_9469_4b40_bfbf_478b9888cd3a,\n- .name = \"router_discovery\",\n+ .name = i\"router_discovery\",\n .code = 31,\n- .__type = \"bool\"\n+ .__type = i\"bool\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'hcb776249_e8b1_4502_b33b_fa294d44077d,\n- .name = \"ethernet_encap\",\n+ .name = i\"ethernet_encap\",\n .code = 36,\n- .__type = \"bool\"\n+ .__type = i\"bool\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'ha2df9eaa_aea9_497f_b339_0c8ec3e39a07,\n- .name = \"default_ttl\",\n+ .name = i\"default_ttl\",\n .code = 23,\n- .__type = \"uint8\"\n+ .__type = i\"uint8\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'hb44b45a9_5004_4ef5_8e6a_aa8629e1afb1,\n- .name = \"tcp_ttl\",\n+ .name = i\"tcp_ttl\",\n .code = 37,\n- .__type = \"uint8\"\n+ .__type = i\"uint8\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h50f01ca7_c650_46f0_8f50_39a67ec657da,\n- .name = \"mtu\",\n+ .name = i\"mtu\",\n .code = 26,\n- .__type = \"uint16\"\n+ .__type = i\"uint16\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h9d31c057_6085_4810_96af_eeac7d3c5308,\n- .name = \"lease_time\",\n+ .name = i\"lease_time\",\n .code = 51,\n- .__type = \"uint32\"\n+ .__type = i\"uint32\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'hea1e2e7a_9585_46ee_ad49_adfdefc0c4ef,\n- .name = \"T1\",\n+ .name = i\"T1\",\n .code = 58,\n- .__type = \"uint32\"\n+ .__type = i\"uint32\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'hbc83a233_554b_453a_afca_1eadf76810d2,\n- .name = \"T2\",\n+ .name = i\"T2\",\n .code = 59,\n- .__type = \"uint32\"\n+ .__type = i\"uint32\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h1ab3eeca_0523_4101_9076_eea77d0232f4,\n- .name = \"bootfile_name\",\n+ .name = i\"bootfile_name\",\n .code = 67,\n- .__type = \"str\"\n+ .__type = i\"str\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'ha5c20b69_f7f3_4fa8_b550_8697aec6cbb7,\n- .name = \"wpad\",\n+ .name = i\"wpad\",\n .code = 252,\n- .__type = \"str\"\n+ .__type = i\"str\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h1516bcb6_cc93_4233_a63f_bd29c8601831,\n- .name = \"path_prefix\",\n+ .name = i\"path_prefix\",\n .code = 210,\n- .__type = \"str\"\n+ .__type = i\"str\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'hc98e13cd_f653_473c_85c1_850dcad685fc,\n- .name = \"tftp_server_address\",\n+ .name = i\"tftp_server_address\",\n .code = 150,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'hfbe06e70_b43d_4dd9_9b21_2f27eb5da5df,\n- .name = \"arp_cache_timeout\",\n+ .name = i\"arp_cache_timeout\",\n .code = 35,\n- .__type = \"uint32\"\n+ .__type = i\"uint32\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h2af54a3c_545c_4104_ae1c_432caa3e085e,\n- .name = \"tcp_keepalive_interval\",\n+ .name = i\"tcp_keepalive_interval\",\n .code = 38,\n- .__type = \"uint32\"\n+ .__type = i\"uint32\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h4b2144e8_8d3f_4d96_9032_fe23c1866cd4,\n- .name = \"domain_search_list\",\n+ .name = i\"domain_search_list\",\n .code = 119,\n- .__type = \"domains\"\n+ .__type = i\"domains\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'hb7236164_eea4_4bf2_9306_8619a9e3ad1d,\n- .name = \"broadcast_address\",\n+ .name = i\"broadcast_address\",\n .code = 28,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h32224b72_1561_4279_b430_982423b62a69,\n- .name = \"netbios_name_server\",\n+ .name = i\"netbios_name_server\",\n .code = 44,\n- .__type = \"ipv4\"\n+ .__type = i\"ipv4\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h691db4ae_624e_43e2_9f4a_5ed9de58f0e5,\n- .name = \"netbios_node_type\",\n+ .name = i\"netbios_node_type\",\n .code = 46,\n- .__type = \"uint8\"\n+ .__type = i\"uint8\"\n ).\n \n sb::Out_DHCP_Options (\n ._uuid = 128'h2d738583_96f4_4a78_99a1_f8f7fe328f3f,\n- .name = \"bootfile_name_alt\",\n+ .name = i\"bootfile_name_alt\",\n .code = 254,\n- .__type = \"str\"\n+ .__type = i\"str\"\n ).\n \n \n@@ -1278,30 +1283,30 @@ sb::Out_DHCP_Options (\n */\n sb::Out_DHCPv6_Options (\n ._uuid = 128'h100b2659_0ec0_4da7_9ec3_25997f92dc00,\n- .name = \"server_id\",\n+ .name = i\"server_id\",\n .code = 2,\n- .__type = \"mac\"\n+ .__type = i\"mac\"\n ).\n \n sb::Out_DHCPv6_Options (\n ._uuid = 128'h53f49b50_db75_4b0d_83df_50d31009ca9c,\n- .name = \"ia_addr\",\n+ .name = i\"ia_addr\",\n .code = 5,\n- .__type = \"ipv6\"\n+ .__type = i\"ipv6\"\n ).\n \n sb::Out_DHCPv6_Options (\n ._uuid = 128'he3619685_d4f7_42ad_936b_4f4440b7eeb4,\n- .name = \"dns_server\",\n+ .name = i\"dns_server\",\n .code = 23,\n- .__type = \"ipv6\"\n+ .__type = i\"ipv6\"\n ).\n \n sb::Out_DHCPv6_Options (\n ._uuid = 128'hcb8a4e7f_a312_4cb1_a846_e474d9f0c531,\n- .name = \"domain_search\",\n+ .name = i\"domain_search\",\n .code = 24,\n- .__type = \"str\"\n+ .__type = i\"str\"\n ).\n \n \n@@ -1309,19 +1314,18 @@ sb::Out_DHCPv6_Options (\n * DNS: copied from NB + datapaths column pointer to LS datapaths that use the record\n */\n \n-function map_to_lowercase(m_in: Map<string,string>): Map<string,string> {\n+function map_to_lowercase(m_in: Map<istring,istring>): Map<istring,istring> {\n var m_out = map_empty();\n- for (node in m_in) {\n- (var k, var v) = node;\n- m_out.insert(string_to_lowercase(k), string_to_lowercase(v))\n+ for ((k, v) in m_in) {\n+ m_out.insert(k.to_lowercase().intern(), v.to_lowercase().intern())\n };\n m_out\n }\n \n-sb::Out_DNS(._uuid = hash128(nbdns._uuid),\n+sb::Out_DNS(._uuid = hash128(nbdns._uuid),\n .records = map_to_lowercase(nbdns.records),\n .datapaths = datapaths,\n- .external_ids = nbdns.external_ids.insert_imm(\"dns_id\", uuid2str(nbdns._uuid))) :-\n+ .external_ids = nbdns.external_ids.insert_imm(i\"dns_id\", uuid2str(nbdns._uuid).intern())) :-\n nb::DNS[nbdns],\n LogicalSwitchDNS(ls_uuid, nbdns._uuid),\n var datapaths = ls_uuid.group_by(nbdns).to_set().\n@@ -1332,77 +1336,77 @@ sb::Out_DNS(._uuid = hash128(nbdns._uuid),\n \n sb::Out_RBAC_Permission (\n ._uuid = 128'h7df3749a_1754_4a78_afa4_3abf526fe510,\n- .table = \"Chassis\",\n- .authorization = set_singleton(\"name\"),\n+ .table = i\"Chassis\",\n+ .authorization = set_singleton(i\"name\"),\n .insert_delete = true,\n- .update = [\"nb_cfg\", \"external_ids\", \"encaps\",\n- \"vtep_logical_switches\", \"other_config\",\n- \"transport_zones\"].to_set()\n+ .update = [i\"nb_cfg\", i\"external_ids\", i\"encaps\",\n+ i\"vtep_logical_switches\", i\"other_config\",\n+ i\"transport_zones\"].to_set()\n ).\n \n sb::Out_RBAC_Permission (\n ._uuid = 128'h07e623f7_137c_4a11_9084_3b3f89cb4a54,\n- .table = \"Chassis_Private\",\n- .authorization = set_singleton(\"name\"),\n+ .table = i\"Chassis_Private\",\n+ .authorization = set_singleton(i\"name\"),\n .insert_delete = true,\n- .update = [\"nb_cfg\", \"nb_cfg_timestamp\", \"chassis\", \"external_ids\"].to_set()\n+ .update = [i\"nb_cfg\", i\"nb_cfg_timestamp\", i\"chassis\", i\"external_ids\"].to_set()\n ).\n \n sb::Out_RBAC_Permission (\n ._uuid = 128'h94bec860_431e_4d95_82e7_3b75d8997241,\n- .table = \"Encap\",\n- .authorization = set_singleton(\"chassis_name\"),\n+ .table = i\"Encap\",\n+ .authorization = set_singleton(i\"chassis_name\"),\n .insert_delete = true,\n- .update = [\"type\", \"options\", \"ip\"].to_set()\n+ .update = [i\"type\", i\"options\", i\"ip\"].to_set()\n ).\n \n sb::Out_RBAC_Permission (\n ._uuid = 128'hd8ceff1a_2b11_48bd_802f_4a991aa4e908,\n- .table = \"Port_Binding\",\n- .authorization = set_singleton(\"\"),\n+ .table = i\"Port_Binding\",\n+ .authorization = set_singleton(i\"\"),\n .insert_delete = false,\n- .update = [\"chassis\", \"encap\", \"up\", \"virtual_parent\"].to_set()\n+ .update = [i\"chassis\", i\"encap\", i\"up\", i\"virtual_parent\"].to_set()\n ).\n \n sb::Out_RBAC_Permission (\n ._uuid = 128'h6ffdc696_8bfb_4d82_b620_a00d39270b2f,\n- .table = \"MAC_Binding\",\n- .authorization = set_singleton(\"\"),\n+ .table = i\"MAC_Binding\",\n+ .authorization = set_singleton(i\"\"),\n .insert_delete = true,\n- .update = [\"logical_port\", \"ip\", \"mac\", \"datapath\"].to_set()\n+ .update = [i\"logical_port\", i\"ip\", i\"mac\", i\"datapath\"].to_set()\n ).\n \n sb::Out_RBAC_Permission (\n ._uuid = 128'h39231c7e_4bf1_41d0_ada4_1d8a319c0da3,\n- .table = \"Service_Monitor\",\n- .authorization = set_singleton(\"\"),\n+ .table = i\"Service_Monitor\",\n+ .authorization = set_singleton(i\"\"),\n .insert_delete = false,\n- .update = set_singleton(\"status\")\n+ .update = set_singleton(i\"status\")\n ).\n \n sb::Out_RBAC_Permission (\n ._uuid = 128'h5256f48e_172c_4d85_8f04_e199fa817633,\n- .table = \"IGMP_Group\",\n- .authorization = set_singleton(\"\"),\n+ .table = i\"IGMP_Group\",\n+ .authorization = set_singleton(i\"\"),\n .insert_delete = true,\n- .update = [\"address\", \"chassis\", \"datapath\", \"ports\"].to_set()\n+ .update = [i\"address\", i\"chassis\", i\"datapath\", i\"ports\"].to_set()\n ).\n \n sb::Out_RBAC_Permission (\n ._uuid = 128'h2e5cbf3d_26f6_4f8a_9926_d6f77f61654f,\n- .table = \"Controller_Event\",\n- .authorization = set_singleton(\"\"),\n+ .table = i\"Controller_Event\",\n+ .authorization = set_singleton(i\"\"),\n .insert_delete = true,\n- .update = [\"chassis\", \"event_info\", \"event_type\",\n- \"seq_num\"].to_set()\n+ .update = [i\"chassis\", i\"event_info\", i\"event_type\",\n+ i\"seq_num\"].to_set()\n ).\n \n sb::Out_RBAC_Permission (\n ._uuid = 128'hb70964fc_322f_4ae5_aee4_ff6afadcc126,\n- .table = \"FDB\",\n- .authorization = set_singleton(\"\"),\n+ .table = i\"FDB\",\n+ .authorization = set_singleton(i\"\"),\n .insert_delete = true,\n- .update = [\"dp_key\", \"mac\", \"port_key\"].to_set()\n+ .update = [i\"dp_key\", i\"mac\", i\"port_key\"].to_set()\n ).\n \n /*\n@@ -1410,17 +1414,17 @@ sb::Out_RBAC_Permission (\n */\n sb::Out_RBAC_Role (\n ._uuid = 128'ha406b472_5de8_4456_9f38_bf344c911b22,\n- .name = \"ovn-controller\",\n+ .name = i\"ovn-controller\",\n .permissions = [\n- \"Chassis\" -> 128'h7df3749a_1754_4a78_afa4_3abf526fe510,\n- \"Chassis_Private\" -> 128'h07e623f7_137c_4a11_9084_3b3f89cb4a54,\n- \"Controller_Event\" -> 128'h2e5cbf3d_26f6_4f8a_9926_d6f77f61654f,\n- \"Encap\" -> 128'h94bec860_431e_4d95_82e7_3b75d8997241,\n- \"FDB\" -> 128'hb70964fc_322f_4ae5_aee4_ff6afadcc126,\n- \"IGMP_Group\" -> 128'h5256f48e_172c_4d85_8f04_e199fa817633,\n- \"Port_Binding\" -> 128'hd8ceff1a_2b11_48bd_802f_4a991aa4e908,\n- \"MAC_Binding\" -> 128'h6ffdc696_8bfb_4d82_b620_a00d39270b2f,\n- \"Service_Monitor\"-> 128'h39231c7e_4bf1_41d0_ada4_1d8a319c0da3]\n+ i\"Chassis\" -> 128'h7df3749a_1754_4a78_afa4_3abf526fe510,\n+ i\"Chassis_Private\" -> 128'h07e623f7_137c_4a11_9084_3b3f89cb4a54,\n+ i\"Controller_Event\" -> 128'h2e5cbf3d_26f6_4f8a_9926_d6f77f61654f,\n+ i\"Encap\" -> 128'h94bec860_431e_4d95_82e7_3b75d8997241,\n+ i\"FDB\" -> 128'hb70964fc_322f_4ae5_aee4_ff6afadcc126,\n+ i\"IGMP_Group\" -> 128'h5256f48e_172c_4d85_8f04_e199fa817633,\n+ i\"Port_Binding\" -> 128'hd8ceff1a_2b11_48bd_802f_4a991aa4e908,\n+ i\"MAC_Binding\" -> 128'h6ffdc696_8bfb_4d82_b620_a00d39270b2f,\n+ i\"Service_Monitor\"-> 128'h39231c7e_4bf1_41d0_ada4_1d8a319c0da3]\n \n ).\n \n@@ -1430,23 +1434,23 @@ nb::Out_Logical_Switch_Port(._uuid = lsp._uuid,\n .dynamic_addresses = dynamic_addresses,\n .up = Some{up}) :-\n SwitchPortNewDynamicAddress(&SwitchPort{.lsp = lsp, .up = up}, opt_dyn_addr),\n- var dynamic_addresses = opt_dyn_addr.and_then(|a| Some{\"${a}\"}),\n+ var dynamic_addresses = opt_dyn_addr.and_then(|a| Some{i\"${a}\"}),\n SwitchPortNewDynamicTag(lsp._uuid, opt_tag),\n var tag = match (opt_tag) {\n None -> lsp.tag,\n Some{t} -> Some{t}\n }.\n \n-relation LRPIPv6Prefix0(lrp_uuid: uuid, ipv6_prefix: string)\n-LRPIPv6Prefix0(lrp._uuid, ipv6_prefix) :-\n+relation LRPIPv6Prefix0(lrp_uuid: uuid, ipv6_prefix: istring)\n+LRPIPv6Prefix0(lrp._uuid, ipv6_prefix.intern()) :-\n lrp in &nb::Logical_Router_Port(),\n- lrp.options.get_bool_def(\"prefix\", false),\n+ lrp.options.get_bool_def(i\"prefix\", false),\n sb::Port_Binding(.logical_port = lrp.name, .options = options),\n- Some{var ipv6_ra_pd_list} = options.get(\"ipv6_ra_pd_list\"),\n- var parts = string_split(ipv6_ra_pd_list, \",\"),\n+ Some{var ipv6_ra_pd_list} = options.get(i\"ipv6_ra_pd_list\"),\n+ var parts = ipv6_ra_pd_list.split(\",\"),\n Some{var ipv6_prefix} = parts.nth(1).\n \n-relation LRPIPv6Prefix(lrp_uuid: uuid, ipv6_prefix: Option<string>)\n+relation LRPIPv6Prefix(lrp_uuid: uuid, ipv6_prefix: Option<istring>)\n LRPIPv6Prefix(lrp_uuid, Some{ipv6_prefix}) :-\n LRPIPv6Prefix0(lrp_uuid, ipv6_prefix).\n LRPIPv6Prefix(lrp_uuid, None) :-\n@@ -1463,74 +1467,74 @@ typedef Pipeline = Ingress | Egress\n typedef Stage = Stage {\n pipeline : Pipeline,\n table_id : bit<8>,\n- table_name : string\n+ table_name : istring\n }\n \n /* Logical switch ingress stages. */\n-function s_SWITCH_IN_PORT_SEC_L2(): Intern<Stage> { Stage{Ingress, 0, \"ls_in_port_sec_l2\"}.intern() }\n-function s_SWITCH_IN_PORT_SEC_IP(): Intern<Stage> { Stage{Ingress, 1, \"ls_in_port_sec_ip\"}.intern() }\n-function s_SWITCH_IN_PORT_SEC_ND(): Intern<Stage> { Stage{Ingress, 2, \"ls_in_port_sec_nd\"}.intern() }\n-function s_SWITCH_IN_LOOKUP_FDB(): Intern<Stage> { Stage{Ingress, 3, \"ls_in_lookup_fdb\"}.intern() }\n-function s_SWITCH_IN_PUT_FDB(): Intern<Stage> { Stage{Ingress, 4, \"ls_in_put_fdb\"}.intern() }\n-function s_SWITCH_IN_PRE_ACL(): Intern<Stage> { Stage{Ingress, 5, \"ls_in_pre_acl\"}.intern() }\n-function s_SWITCH_IN_PRE_LB(): Intern<Stage> { Stage{Ingress, 6, \"ls_in_pre_lb\"}.intern() }\n-function s_SWITCH_IN_PRE_STATEFUL(): Intern<Stage> { Stage{Ingress, 7, \"ls_in_pre_stateful\"}.intern() }\n-function s_SWITCH_IN_ACL_HINT(): Intern<Stage> { Stage{Ingress, 8, \"ls_in_acl_hint\"}.intern() }\n-function s_SWITCH_IN_ACL(): Intern<Stage> { Stage{Ingress, 9, \"ls_in_acl\"}.intern() }\n-function s_SWITCH_IN_QOS_MARK(): Intern<Stage> { Stage{Ingress, 10, \"ls_in_qos_mark\"}.intern() }\n-function s_SWITCH_IN_QOS_METER(): Intern<Stage> { Stage{Ingress, 11, \"ls_in_qos_meter\"}.intern() }\n-function s_SWITCH_IN_STATEFUL(): Intern<Stage> { Stage{Ingress, 12, \"ls_in_stateful\"}.intern() }\n-function s_SWITCH_IN_PRE_HAIRPIN(): Intern<Stage> { Stage{Ingress, 13, \"ls_in_pre_hairpin\"}.intern() }\n-function s_SWITCH_IN_NAT_HAIRPIN(): Intern<Stage> { Stage{Ingress, 14, \"ls_in_nat_hairpin\"}.intern() }\n-function s_SWITCH_IN_HAIRPIN(): Intern<Stage> { Stage{Ingress, 15, \"ls_in_hairpin\"}.intern() }\n-function s_SWITCH_IN_ARP_ND_RSP(): Intern<Stage> { Stage{Ingress, 16, \"ls_in_arp_rsp\"}.intern() }\n-function s_SWITCH_IN_DHCP_OPTIONS(): Intern<Stage> { Stage{Ingress, 17, \"ls_in_dhcp_options\"}.intern() }\n-function s_SWITCH_IN_DHCP_RESPONSE(): Intern<Stage> { Stage{Ingress, 18, \"ls_in_dhcp_response\"}.intern() }\n-function s_SWITCH_IN_DNS_LOOKUP(): Intern<Stage> { Stage{Ingress, 19, \"ls_in_dns_lookup\"}.intern() }\n-function s_SWITCH_IN_DNS_RESPONSE(): Intern<Stage> { Stage{Ingress, 20, \"ls_in_dns_response\"}.intern() }\n-function s_SWITCH_IN_EXTERNAL_PORT(): Intern<Stage> { Stage{Ingress, 21, \"ls_in_external_port\"}.intern() }\n-function s_SWITCH_IN_L2_LKUP(): Intern<Stage> { Stage{Ingress, 22, \"ls_in_l2_lkup\"}.intern() }\n-function s_SWITCH_IN_L2_UNKNOWN(): Intern<Stage> { Stage{Ingress, 23, \"ls_in_l2_unknown\"}.intern() }\n+function s_SWITCH_IN_PORT_SEC_L2(): Intern<Stage> { Stage{Ingress, 0, i\"ls_in_port_sec_l2\"}.intern() }\n+function s_SWITCH_IN_PORT_SEC_IP(): Intern<Stage> { Stage{Ingress, 1, i\"ls_in_port_sec_ip\"}.intern() }\n+function s_SWITCH_IN_PORT_SEC_ND(): Intern<Stage> { Stage{Ingress, 2, i\"ls_in_port_sec_nd\"}.intern() }\n+function s_SWITCH_IN_LOOKUP_FDB(): Intern<Stage> { Stage{Ingress, 3, i\"ls_in_lookup_fdb\"}.intern() }\n+function s_SWITCH_IN_PUT_FDB(): Intern<Stage> { Stage{Ingress, 4, i\"ls_in_put_fdb\"}.intern() }\n+function s_SWITCH_IN_PRE_ACL(): Intern<Stage> { Stage{Ingress, 5, i\"ls_in_pre_acl\"}.intern() }\n+function s_SWITCH_IN_PRE_LB(): Intern<Stage> { Stage{Ingress, 6, i\"ls_in_pre_lb\"}.intern() }\n+function s_SWITCH_IN_PRE_STATEFUL(): Intern<Stage> { Stage{Ingress, 7, i\"ls_in_pre_stateful\"}.intern() }\n+function s_SWITCH_IN_ACL_HINT(): Intern<Stage> { Stage{Ingress, 8, i\"ls_in_acl_hint\"}.intern() }\n+function s_SWITCH_IN_ACL(): Intern<Stage> { Stage{Ingress, 9, i\"ls_in_acl\"}.intern() }\n+function s_SWITCH_IN_QOS_MARK(): Intern<Stage> { Stage{Ingress, 10, i\"ls_in_qos_mark\"}.intern() }\n+function s_SWITCH_IN_QOS_METER(): Intern<Stage> { Stage{Ingress, 11, i\"ls_in_qos_meter\"}.intern() }\n+function s_SWITCH_IN_STATEFUL(): Intern<Stage> { Stage{Ingress, 12, i\"ls_in_stateful\"}.intern() }\n+function s_SWITCH_IN_PRE_HAIRPIN(): Intern<Stage> { Stage{Ingress, 13, i\"ls_in_pre_hairpin\"}.intern() }\n+function s_SWITCH_IN_NAT_HAIRPIN(): Intern<Stage> { Stage{Ingress, 14, i\"ls_in_nat_hairpin\"}.intern() }\n+function s_SWITCH_IN_HAIRPIN(): Intern<Stage> { Stage{Ingress, 15, i\"ls_in_hairpin\"}.intern() }\n+function s_SWITCH_IN_ARP_ND_RSP(): Intern<Stage> { Stage{Ingress, 16, i\"ls_in_arp_rsp\"}.intern() }\n+function s_SWITCH_IN_DHCP_OPTIONS(): Intern<Stage> { Stage{Ingress, 17, i\"ls_in_dhcp_options\"}.intern() }\n+function s_SWITCH_IN_DHCP_RESPONSE(): Intern<Stage> { Stage{Ingress, 18, i\"ls_in_dhcp_response\"}.intern() }\n+function s_SWITCH_IN_DNS_LOOKUP(): Intern<Stage> { Stage{Ingress, 19, i\"ls_in_dns_lookup\"}.intern() }\n+function s_SWITCH_IN_DNS_RESPONSE(): Intern<Stage> { Stage{Ingress, 20, i\"ls_in_dns_response\"}.intern() }\n+function s_SWITCH_IN_EXTERNAL_PORT(): Intern<Stage> { Stage{Ingress, 21, i\"ls_in_external_port\"}.intern() }\n+function s_SWITCH_IN_L2_LKUP(): Intern<Stage> { Stage{Ingress, 22, i\"ls_in_l2_lkup\"}.intern() }\n+function s_SWITCH_IN_L2_UNKNOWN(): Intern<Stage> { Stage{Ingress, 23, i\"ls_in_l2_unknown\"}.intern() }\n \n /* Logical switch egress stages. */\n-function s_SWITCH_OUT_PRE_LB(): Intern<Stage> { Stage{ Egress, 0, \"ls_out_pre_lb\"}.intern() }\n-function s_SWITCH_OUT_PRE_ACL(): Intern<Stage> { Stage{ Egress, 1, \"ls_out_pre_acl\"}.intern() }\n-function s_SWITCH_OUT_PRE_STATEFUL(): Intern<Stage> { Stage{ Egress, 2, \"ls_out_pre_stateful\"}.intern() }\n-function s_SWITCH_OUT_ACL_HINT(): Intern<Stage> { Stage{ Egress, 3, \"ls_out_acl_hint\"}.intern() }\n-function s_SWITCH_OUT_ACL(): Intern<Stage> { Stage{ Egress, 4, \"ls_out_acl\"}.intern() }\n-function s_SWITCH_OUT_QOS_MARK(): Intern<Stage> { Stage{ Egress, 5, \"ls_out_qos_mark\"}.intern() }\n-function s_SWITCH_OUT_QOS_METER(): Intern<Stage> { Stage{ Egress, 6, \"ls_out_qos_meter\"}.intern() }\n-function s_SWITCH_OUT_STATEFUL(): Intern<Stage> { Stage{ Egress, 7, \"ls_out_stateful\"}.intern() }\n-function s_SWITCH_OUT_PORT_SEC_IP(): Intern<Stage> { Stage{ Egress, 8, \"ls_out_port_sec_ip\"}.intern() }\n-function s_SWITCH_OUT_PORT_SEC_L2(): Intern<Stage> { Stage{ Egress, 9, \"ls_out_port_sec_l2\"}.intern() }\n+function s_SWITCH_OUT_PRE_LB(): Intern<Stage> { Stage{ Egress, 0, i\"ls_out_pre_lb\"}.intern() }\n+function s_SWITCH_OUT_PRE_ACL(): Intern<Stage> { Stage{ Egress, 1, i\"ls_out_pre_acl\"}.intern() }\n+function s_SWITCH_OUT_PRE_STATEFUL(): Intern<Stage> { Stage{ Egress, 2, i\"ls_out_pre_stateful\"}.intern() }\n+function s_SWITCH_OUT_ACL_HINT(): Intern<Stage> { Stage{ Egress, 3, i\"ls_out_acl_hint\"}.intern() }\n+function s_SWITCH_OUT_ACL(): Intern<Stage> { Stage{ Egress, 4, i\"ls_out_acl\"}.intern() }\n+function s_SWITCH_OUT_QOS_MARK(): Intern<Stage> { Stage{ Egress, 5, i\"ls_out_qos_mark\"}.intern() }\n+function s_SWITCH_OUT_QOS_METER(): Intern<Stage> { Stage{ Egress, 6, i\"ls_out_qos_meter\"}.intern() }\n+function s_SWITCH_OUT_STATEFUL(): Intern<Stage> { Stage{ Egress, 7, i\"ls_out_stateful\"}.intern() }\n+function s_SWITCH_OUT_PORT_SEC_IP(): Intern<Stage> { Stage{ Egress, 8, i\"ls_out_port_sec_ip\"}.intern() }\n+function s_SWITCH_OUT_PORT_SEC_L2(): Intern<Stage> { Stage{ Egress, 9, i\"ls_out_port_sec_l2\"}.intern() }\n \n /* Logical router ingress stages. */\n-function s_ROUTER_IN_ADMISSION(): Intern<Stage> { Stage{Ingress, 0, \"lr_in_admission\"}.intern() }\n-function s_ROUTER_IN_LOOKUP_NEIGHBOR(): Intern<Stage> { Stage{Ingress, 1, \"lr_in_lookup_neighbor\"}.intern() }\n-function s_ROUTER_IN_LEARN_NEIGHBOR(): Intern<Stage> { Stage{Ingress, 2, \"lr_in_learn_neighbor\"}.intern() }\n-function s_ROUTER_IN_IP_INPUT(): Intern<Stage> { Stage{Ingress, 3, \"lr_in_ip_input\"}.intern() }\n-function s_ROUTER_IN_UNSNAT(): Intern<Stage> { Stage{Ingress, 4, \"lr_in_unsnat\"}.intern() }\n-function s_ROUTER_IN_DEFRAG(): Intern<Stage> { Stage{Ingress, 5, \"lr_in_defrag\"}.intern() }\n-function s_ROUTER_IN_DNAT(): Intern<Stage> { Stage{Ingress, 6, \"lr_in_dnat\"}.intern() }\n-function s_ROUTER_IN_ECMP_STATEFUL(): Intern<Stage> { Stage{Ingress, 7, \"lr_in_ecmp_stateful\"}.intern() }\n-function s_ROUTER_IN_ND_RA_OPTIONS(): Intern<Stage> { Stage{Ingress, 8, \"lr_in_nd_ra_options\"}.intern() }\n-function s_ROUTER_IN_ND_RA_RESPONSE(): Intern<Stage> { Stage{Ingress, 9, \"lr_in_nd_ra_response\"}.intern() }\n-function s_ROUTER_IN_IP_ROUTING(): Intern<Stage> { Stage{Ingress, 10, \"lr_in_ip_routing\"}.intern() }\n-function s_ROUTER_IN_IP_ROUTING_ECMP(): Intern<Stage> { Stage{Ingress, 11, \"lr_in_ip_routing_ecmp\"}.intern() }\n-function s_ROUTER_IN_POLICY(): Intern<Stage> { Stage{Ingress, 12, \"lr_in_policy\"}.intern() }\n-function s_ROUTER_IN_POLICY_ECMP(): Intern<Stage> { Stage{Ingress, 13, \"lr_in_policy_ecmp\"}.intern() }\n-function s_ROUTER_IN_ARP_RESOLVE(): Intern<Stage> { Stage{Ingress, 14, \"lr_in_arp_resolve\"}.intern() }\n-function s_ROUTER_IN_CHK_PKT_LEN(): Intern<Stage> { Stage{Ingress, 15, \"lr_in_chk_pkt_len\"}.intern() }\n-function s_ROUTER_IN_LARGER_PKTS(): Intern<Stage> { Stage{Ingress, 16, \"lr_in_larger_pkts\"}.intern() }\n-function s_ROUTER_IN_GW_REDIRECT(): Intern<Stage> { Stage{Ingress, 17, \"lr_in_gw_redirect\"}.intern() }\n-function s_ROUTER_IN_ARP_REQUEST(): Intern<Stage> { Stage{Ingress, 18, \"lr_in_arp_request\"}.intern() }\n+function s_ROUTER_IN_ADMISSION(): Intern<Stage> { Stage{Ingress, 0, i\"lr_in_admission\"}.intern() }\n+function s_ROUTER_IN_LOOKUP_NEIGHBOR(): Intern<Stage> { Stage{Ingress, 1, i\"lr_in_lookup_neighbor\"}.intern() }\n+function s_ROUTER_IN_LEARN_NEIGHBOR(): Intern<Stage> { Stage{Ingress, 2, i\"lr_in_learn_neighbor\"}.intern() }\n+function s_ROUTER_IN_IP_INPUT(): Intern<Stage> { Stage{Ingress, 3, i\"lr_in_ip_input\"}.intern() }\n+function s_ROUTER_IN_UNSNAT(): Intern<Stage> { Stage{Ingress, 4, i\"lr_in_unsnat\"}.intern() }\n+function s_ROUTER_IN_DEFRAG(): Intern<Stage> { Stage{Ingress, 5, i\"lr_in_defrag\"}.intern() }\n+function s_ROUTER_IN_DNAT(): Intern<Stage> { Stage{Ingress, 6, i\"lr_in_dnat\"}.intern() }\n+function s_ROUTER_IN_ECMP_STATEFUL(): Intern<Stage> { Stage{Ingress, 7, i\"lr_in_ecmp_stateful\"}.intern() }\n+function s_ROUTER_IN_ND_RA_OPTIONS(): Intern<Stage> { Stage{Ingress, 8, i\"lr_in_nd_ra_options\"}.intern() }\n+function s_ROUTER_IN_ND_RA_RESPONSE(): Intern<Stage> { Stage{Ingress, 9, i\"lr_in_nd_ra_response\"}.intern() }\n+function s_ROUTER_IN_IP_ROUTING(): Intern<Stage> { Stage{Ingress, 10, i\"lr_in_ip_routing\"}.intern() }\n+function s_ROUTER_IN_IP_ROUTING_ECMP(): Intern<Stage> { Stage{Ingress, 11, i\"lr_in_ip_routing_ecmp\"}.intern() }\n+function s_ROUTER_IN_POLICY(): Intern<Stage> { Stage{Ingress, 12, i\"lr_in_policy\"}.intern() }\n+function s_ROUTER_IN_POLICY_ECMP(): Intern<Stage> { Stage{Ingress, 13, i\"lr_in_policy_ecmp\"}.intern() }\n+function s_ROUTER_IN_ARP_RESOLVE(): Intern<Stage> { Stage{Ingress, 14, i\"lr_in_arp_resolve\"}.intern() }\n+function s_ROUTER_IN_CHK_PKT_LEN(): Intern<Stage> { Stage{Ingress, 15, i\"lr_in_chk_pkt_len\"}.intern() }\n+function s_ROUTER_IN_LARGER_PKTS(): Intern<Stage> { Stage{Ingress, 16, i\"lr_in_larger_pkts\"}.intern() }\n+function s_ROUTER_IN_GW_REDIRECT(): Intern<Stage> { Stage{Ingress, 17, i\"lr_in_gw_redirect\"}.intern() }\n+function s_ROUTER_IN_ARP_REQUEST(): Intern<Stage> { Stage{Ingress, 18, i\"lr_in_arp_request\"}.intern() }\n \n /* Logical router egress stages. */\n-function s_ROUTER_OUT_UNDNAT(): Intern<Stage> { Stage{ Egress, 0, \"lr_out_undnat\"}.intern() }\n-function s_ROUTER_OUT_POST_UNDNAT(): Intern<Stage> { Stage{ Egress, 1, \"lr_out_post_undnat\"}.intern() }\n-function s_ROUTER_OUT_SNAT(): Intern<Stage> { Stage{ Egress, 2, \"lr_out_snat\"}.intern() }\n-function s_ROUTER_OUT_EGR_LOOP(): Intern<Stage> { Stage{ Egress, 3, \"lr_out_egr_loop\"}.intern() }\n-function s_ROUTER_OUT_DELIVERY(): Intern<Stage> { Stage{ Egress, 4, \"lr_out_delivery\"}.intern() }\n+function s_ROUTER_OUT_UNDNAT(): Intern<Stage> { Stage{ Egress, 0, i\"lr_out_undnat\"}.intern() }\n+function s_ROUTER_OUT_POST_UNDNAT(): Intern<Stage> { Stage{ Egress, 1, i\"lr_out_post_undnat\"}.intern() }\n+function s_ROUTER_OUT_SNAT(): Intern<Stage> { Stage{ Egress, 2, i\"lr_out_snat\"}.intern() }\n+function s_ROUTER_OUT_EGR_LOOP(): Intern<Stage> { Stage{ Egress, 3, i\"lr_out_egr_loop\"}.intern() }\n+function s_ROUTER_OUT_DELIVERY(): Intern<Stage> { Stage{ Egress, 4, i\"lr_out_delivery\"}.intern() }\n \n /*\n * OVS register usage:\n@@ -1604,28 +1608,28 @@ function s_ROUTER_OUT_DELIVERY(): Intern<Stage> { Stage{ Egress, 4, \"lr_o\n */\n \n /* Register definitions specific to routers. */\n-function rEG_NEXT_HOP(): string = \"reg0\" /* reg0 for IPv4, xxreg0 for IPv6 */\n-function rEG_SRC(): string = \"reg1\" /* reg1 for IPv4, xxreg1 for IPv6 */\n+function rEG_NEXT_HOP(): istring = i\"reg0\" /* reg0 for IPv4, xxreg0 for IPv6 */\n+function rEG_SRC(): istring = i\"reg1\" /* reg1 for IPv4, xxreg1 for IPv6 */\n \n /* Register definitions specific to switches. */\n-function rEGBIT_CONNTRACK_DEFRAG() : string = \"reg0[0]\"\n-function rEGBIT_CONNTRACK_COMMIT() : string = \"reg0[1]\"\n-function rEGBIT_CONNTRACK_NAT() : string = \"reg0[2]\"\n-function rEGBIT_DHCP_OPTS_RESULT() : string = \"reg0[3]\"\n-function rEGBIT_DNS_LOOKUP_RESULT(): string = \"reg0[4]\"\n-function rEGBIT_ND_RA_OPTS_RESULT(): string = \"reg0[5]\"\n-function rEGBIT_HAIRPIN() : string = \"reg0[6]\"\n-function rEGBIT_ACL_HINT_ALLOW_NEW(): string = \"reg0[7]\"\n-function rEGBIT_ACL_HINT_ALLOW() : string = \"reg0[8]\"\n-function rEGBIT_ACL_HINT_DROP() : string = \"reg0[9]\"\n-function rEGBIT_ACL_HINT_BLOCK() : string = \"reg0[10]\"\n-function rEGBIT_LKUP_FDB() : string = \"reg0[11]\"\n-function rEGBIT_HAIRPIN_REPLY() : string = \"reg0[12]\"\n-function rEGBIT_ACL_LABEL() : string = \"reg0[13]\"\n-\n-function rEG_ORIG_DIP_IPV4() : string = \"reg1\"\n-function rEG_ORIG_DIP_IPV6() : string = \"xxreg1\"\n-function rEG_ORIG_TP_DPORT() : string = \"reg2[0..15]\"\n+function rEGBIT_CONNTRACK_DEFRAG() : istring = i\"reg0[0]\"\n+function rEGBIT_CONNTRACK_COMMIT() : istring = i\"reg0[1]\"\n+function rEGBIT_CONNTRACK_NAT() : istring = i\"reg0[2]\"\n+function rEGBIT_DHCP_OPTS_RESULT() : istring = i\"reg0[3]\"\n+function rEGBIT_DNS_LOOKUP_RESULT(): istring = i\"reg0[4]\"\n+function rEGBIT_ND_RA_OPTS_RESULT(): istring = i\"reg0[5]\"\n+function rEGBIT_HAIRPIN() : istring = i\"reg0[6]\"\n+function rEGBIT_ACL_HINT_ALLOW_NEW(): istring = i\"reg0[7]\"\n+function rEGBIT_ACL_HINT_ALLOW() : istring = i\"reg0[8]\"\n+function rEGBIT_ACL_HINT_DROP() : istring = i\"reg0[9]\"\n+function rEGBIT_ACL_HINT_BLOCK() : istring = i\"reg0[10]\"\n+function rEGBIT_LKUP_FDB() : istring = i\"reg0[11]\"\n+function rEGBIT_HAIRPIN_REPLY() : istring = i\"reg0[12]\"\n+function rEGBIT_ACL_LABEL() : istring = i\"reg0[13]\"\n+\n+function rEG_ORIG_DIP_IPV4() : istring = i\"reg1\"\n+function rEG_ORIG_DIP_IPV6() : istring = i\"xxreg1\"\n+function rEG_ORIG_TP_DPORT() : istring = i\"reg2[0..15]\"\n \n /* Register definitions for switches and routers. */\n \n@@ -1633,27 +1637,27 @@ function rEG_ORIG_TP_DPORT() : string = \"reg2[0..15]\"\n * loopback. This allows certain checks to be bypassed, such as a\n * logical router dropping packets with source IP address equals\n * one of the logical router's own IP addresses. */\n-function rEGBIT_EGRESS_LOOPBACK() : string = \"reg9[0]\"\n+function rEGBIT_EGRESS_LOOPBACK() : istring = i\"reg9[0]\"\n /* Register to store the result of check_pkt_larger action. */\n-function rEGBIT_PKT_LARGER() : string = \"reg9[1]\"\n-function rEGBIT_LOOKUP_NEIGHBOR_RESULT() : string = \"reg9[2]\"\n-function rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() : string = \"reg9[3]\"\n+function rEGBIT_PKT_LARGER() : istring = i\"reg9[1]\"\n+function rEGBIT_LOOKUP_NEIGHBOR_RESULT() : istring = i\"reg9[2]\"\n+function rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() : istring = i\"reg9[3]\"\n \n /* Register to store the eth address associated to a router port for packets\n * received in S_ROUTER_IN_ADMISSION.\n */\n-function rEG_INPORT_ETH_ADDR() : string = \"xreg0[0..47]\"\n+function rEG_INPORT_ETH_ADDR() : istring = i\"xreg0[0..47]\"\n \n /* Register for ECMP bucket selection. */\n-function rEG_ECMP_GROUP_ID() : string = \"reg8[0..15]\"\n-function rEG_ECMP_MEMBER_ID() : string = \"reg8[16..31]\"\n+function rEG_ECMP_GROUP_ID() : istring = i\"reg8[0..15]\"\n+function rEG_ECMP_MEMBER_ID() : istring = i\"reg8[16..31]\"\n \n function rEG_ORIG_TP_DPORT_ROUTER() : string = \"reg9[16..31]\"\n \n /* Register used for setting a label for ACLs in a Logical Switch. */\n-function rEG_LABEL() : string = \"reg3\"\n+function rEG_LABEL() : istring = i\"reg3\"\n \n-function fLAGBIT_NOT_VXLAN() : string = \"flags[1] == 0\"\n+function fLAGBIT_NOT_VXLAN() : istring = i\"flags[1] == 0\"\n \n function mFF_N_LOG_REGS() : bit<32> = 10\n \n@@ -1678,8 +1682,8 @@ relation Flow(\n priority: integer,\n __match: istring,\n actions: istring,\n- io_port: Option<string>,\n- controller_meter: Option<string>,\n+ io_port: Option<istring>,\n+ controller_meter: Option<istring>,\n stage_hint: bit<32>\n )\n \n@@ -1692,7 +1696,7 @@ function stage_hint(_uuid: uuid): bit<32> {\n relation UseLogicalDatapathGroups[bool]\n UseLogicalDatapathGroups[use_logical_dp_groups] :-\n nb in nb::NB_Global(),\n- var use_logical_dp_groups = nb.options.get_bool_def(\"use_logical_dp_groups\", true).\n+ var use_logical_dp_groups = nb.options.get_bool_def(i\"use_logical_dp_groups\", true).\n UseLogicalDatapathGroups[false] :-\n Unit(),\n not nb in nb::NB_Global().\n@@ -1703,22 +1707,22 @@ relation AggregatedFlow (\n priority: integer,\n __match: istring,\n actions: istring,\n- io_port: Option<string>,\n- controller_meter: Option<string>,\n+ io_port: Option<istring>,\n+ controller_meter: Option<istring>,\n stage_hint: bit<32>\n )\n-function make_flow_tags(io_port: Option<string>): Map<string,string> {\n+function make_flow_tags(io_port: Option<istring>): Map<istring,istring> {\n match (io_port) {\n None -> map_empty(),\n- Some{s} -> [ \"in_out_port\" -> s ]\n+ Some{s} -> [ i\"in_out_port\" -> s ]\n }\n }\n-function make_flow_external_ids(stage_hint: bit<32>, stage: Intern<Stage>): Map<string,string> {\n+function make_flow_external_ids(stage_hint: bit<32>, stage: Intern<Stage>): Map<istring,istring> {\n if (stage_hint == 0) {\n- [\"stage-name\" -> stage.table_name]\n+ [i\"stage-name\" -> stage.table_name]\n } else {\n- [\"stage-name\" -> stage.table_name,\n- \"stage-hint\" -> \"${hex(stage_hint)}\"]\n+ [i\"stage-name\" -> stage.table_name,\n+ i\"stage-hint\" -> i\"${hex(stage_hint)}\"]\n }\n }\n AggregatedFlow(.logical_datapaths = g.to_set(),\n@@ -1743,11 +1747,11 @@ AggregatedFlow(.logical_datapaths = set_singleton(logical_datapath),\n UseLogicalDatapathGroups[false],\n Flow(logical_datapath, stage, priority, __match, actions, io_port, controller_meter, stage_hint).\n \n-function to_string(pipeline: Pipeline): string {\n+function to_istring(pipeline: Pipeline): istring {\n if (pipeline == Ingress) {\n- \"ingress\"\n+ i\"ingress\"\n } else {\n- \"egress\"\n+ i\"egress\"\n }\n }\n \n@@ -1758,12 +1762,12 @@ for (f in AggregatedFlow()) {\n ._uuid = hash128((dp, f.stage, f.priority, f.__match, f.actions, f.controller_meter, f.io_port, f.stage_hint)),\n .logical_datapath = Some{dp},\n .logical_dp_group = None,\n- .pipeline = f.stage.pipeline.to_string(),\n+ .pipeline = f.stage.pipeline.to_istring(),\n .table_id = f.stage.table_id as integer,\n .priority = f.priority,\n .controller_meter = f.controller_meter,\n- .__match = f.__match.ival(),\n- .actions = f.actions.ival(),\n+ .__match = f.__match,\n+ .actions = f.actions,\n .tags = make_flow_tags(f.io_port),\n .external_ids = make_flow_external_ids(f.stage_hint, f.stage))\n } else {\n@@ -1772,12 +1776,12 @@ for (f in AggregatedFlow()) {\n ._uuid = hash128((group_uuid, f.stage, f.priority, f.__match, f.actions, f.controller_meter, f.io_port, f.stage_hint)),\n .logical_datapath = None,\n .logical_dp_group = Some{group_uuid},\n- .pipeline = f.stage.pipeline.to_string(),\n+ .pipeline = f.stage.pipeline.to_istring(),\n .table_id = f.stage.table_id as integer,\n .priority = f.priority,\n .controller_meter = f.controller_meter,\n- .__match = f.__match.ival(),\n- .actions = f.actions.ival(),\n+ .__match = f.__match,\n+ .actions = f.actions,\n .tags = make_flow_tags(f.io_port),\n .external_ids = make_flow_external_ids(f.stage_hint, f.stage));\n sb::Out_Logical_DP_Group(._uuid = group_uuid, .datapaths = f.logical_datapaths)\n@@ -1811,17 +1815,17 @@ Flow(.logical_datapath = sw._uuid,\n \"flags.loopback = 1; \"\n \"output;\".\n \n-function escape_child_ports(child_port: Set<string>): string {\n+function escape_child_ports(child_port: Set<istring>): string {\n var escaped = vec_with_capacity(child_port.size());\n for (s in child_port) {\n- escaped.push(json_string_escape(s))\n+ escaped.push(json_escape(s))\n };\n escaped.join(\",\")\n }\n Flow(.logical_datapath = sw._uuid,\n .stage = s_SWITCH_IN_L2_LKUP(),\n .priority = 50,\n- .__match = __match.intern(),\n+ .__match = __match,\n .actions = actions.intern(),\n .stage_hint = 0,\n .io_port = None,\n@@ -1831,7 +1835,7 @@ Flow(.logical_datapath = sw._uuid,\n var fg_uuid = FlatMap(forwarding_groups),\n fg in nb::Forwarding_Group(._uuid = fg_uuid),\n not fg.child_port.is_empty(),\n- var __match = \"eth.dst == ${fg.vmac}\",\n+ var __match = i\"eth.dst == ${fg.vmac}\",\n var actions = \"fwd_group(\" ++\n if (fg.liveness) { \"liveness=\\\"true\\\",\" } else { \"\" } ++\n \"childports=\" ++ escape_child_ports(fg.child_port) ++ \");\".\n@@ -1952,12 +1956,12 @@ for (&Switch(._uuid =ls_uuid)) {\n /* stateless filters always take precedence over stateful ACLs. */\n for (&SwitchACL(.sw = sw@&Switch{._uuid = ls_uuid}, .acl = acl, .has_fair_meter = fair_meter)) {\n if (sw.has_stateful_acl) {\n- if (acl.action == \"allow-stateless\") {\n- if (acl.direction == \"from-lport\") {\n+ if (acl.action == i\"allow-stateless\") {\n+ if (acl.direction == i\"from-lport\") {\n Flow(.logical_datapath = ls_uuid,\n .stage = s_SWITCH_IN_PRE_ACL(),\n .priority = acl.priority + oVN_ACL_PRI_OFFSET(),\n- .__match = acl.__match.intern(),\n+ .__match = acl.__match,\n .actions = i\"next;\",\n .stage_hint = stage_hint(acl._uuid),\n .io_port = None,\n@@ -1966,7 +1970,7 @@ for (&SwitchACL(.sw = sw@&Switch{._uuid = ls_uuid}, .acl = acl, .has_fair_meter\n Flow(.logical_datapath = ls_uuid,\n .stage = s_SWITCH_OUT_PRE_ACL(),\n .priority = acl.priority + oVN_ACL_PRI_OFFSET(),\n- .__match = acl.__match.intern(),\n+ .__match = acl.__match,\n .actions = i\"next;\",\n .stage_hint = stage_hint(acl._uuid),\n .io_port = None,\n@@ -1980,7 +1984,7 @@ for (&SwitchACL(.sw = sw@&Switch{._uuid = ls_uuid}, .acl = acl, .has_fair_meter\n * send all IP packets through the conntrack action, which handles\n * defragmentation, in order to match L4 headers. */\n \n-for (&SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = \"router\"},\n+for (&SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = i\"router\"},\n .json_name = lsp_name,\n .sw = &Switch{._uuid = ls_uuid, .has_stateful_acl = true})) {\n /* Can't use ct() for router ports. Consider the\n@@ -2013,7 +2017,7 @@ for (&SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = \"router\"},\n .controller_meter = None)\n }\n \n-for (&SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = \"localnet\"},\n+for (&SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = i\"localnet\"},\n .json_name = lsp_name,\n .sw = &Switch{._uuid = ls_uuid, .has_stateful_acl = true})) {\n Flow(.logical_datapath = ls_uuid,\n@@ -2144,7 +2148,7 @@ for (&Switch(._uuid = ls_uuid)) {\n }\n \n for (&SwitchPort(.lsp = lsp, .json_name = lsp_name, .sw = &Switch{._uuid = ls_uuid}))\n-if (lsp.__type == \"router\" or lsp.__type == \"localnet\") {\n+if (lsp.__type == i\"router\" or lsp.__type == i\"localnet\") {\n Flow(.logical_datapath = ls_uuid,\n .stage = s_SWITCH_IN_PRE_LB(),\n .priority = 110,\n@@ -2164,16 +2168,13 @@ if (lsp.__type == \"router\" or lsp.__type == \"localnet\") {\n }\n \n /* Empty LoadBalancer Controller event */\n-function build_empty_lb_event_flow(key: string, lb: Intern<nb::Load_Balancer>): Option<(istring, istring)> {\n- (var ip, var port) = match (ip_address_and_port_from_lb_key(key)) {\n+function build_empty_lb_event_flow(key: istring, lb: Intern<nb::Load_Balancer>): Option<(istring, istring)> {\n+ (var ip, var port) = match (ip_address_and_port_from_lb_key(key.ival())) {\n Some{(ip, port)} -> (ip, port),\n _ -> return None\n };\n \n- var protocol = match (lb.protocol) {\n- Some{\"tcp\"} -> \"tcp\",\n- _ -> \"udp\"\n- };\n+ var protocol = if (lb.protocol == Some{i\"tcp\"}) { \"tcp\" } else { \"udp\" };\n var vip = match (port) {\n 0 -> \"${ip}\",\n _ -> \"${ip.to_bracketed_string()}:${port}\"\n@@ -2206,9 +2207,9 @@ function build_empty_lb_event_flow(key: string, lb: Intern<nb::Load_Balancer>):\n relation LoadBalancerEmptyEvents(lb: Intern<nb::Load_Balancer>)\n LoadBalancerEmptyEvents(lb) :-\n nb::NB_Global(.options = global_options),\n- var global_events = global_options.get_bool_def(\"controller_event\", false),\n+ var global_events = global_options.get_bool_def(i\"controller_event\", false),\n lb in &nb::Load_Balancer(.options = local_options),\n- var local_events = local_options.get_bool_def(\"event\", false),\n+ var local_events = local_options.get_bool_def(i\"event\", false),\n global_events or local_events.\n \n Flow(.logical_datapath = sw._uuid,\n@@ -2221,9 +2222,9 @@ Flow(.logical_datapath = sw._uuid,\n .stage_hint = stage_hint(lb._uuid)) :-\n SwitchLBVIP(.sw_uuid = sw_uuid, .lb = lb, .vip = vip, .backends = backends),\n LoadBalancerEmptyEvents(lb),\n- not lb.options.get_bool_def(\"reject\", false),\n+ not lb.options.get_bool_def(i\"reject\", false),\n sw in &Switch(._uuid = sw_uuid),\n- backends == \"\",\n+ backends == i\"\",\n Some {(var __match, var __action)} = build_empty_lb_event_flow(vip, lb).\n \n /* 'REGBIT_CONNTRACK_NAT' is set to let the pre-stateful table send\n@@ -2368,9 +2369,9 @@ for (&Switch(._uuid = ls_uuid)) {\n .controller_meter = None)\n }\n \n-function acl_log_meter_name(meter_name: string, acl_uuid: uuid): string =\n+function acl_log_meter_name(meter_name: istring, acl_uuid: uuid): string =\n {\n- meter_name ++ \"__\" ++ uuid2str(acl_uuid)\n+ \"${meter_name}__${uuid2str(acl_uuid)}\"\n }\n \n function build_acl_log(acl: Intern<nb::ACL>, fair_meter: bool): string =\n@@ -2381,14 +2382,14 @@ function build_acl_log(acl: Intern<nb::ACL>, fair_meter: bool): string =\n var strs = vec_empty();\n match (acl.name) {\n None -> (),\n- Some{name} -> strs.push(\"name=${json_string_escape(name)}\")\n+ Some{name} -> strs.push(\"name=${json_escape(name)}\")\n };\n /* If a severity level isn't specified, default to \"info\". */\n match (acl.severity) {\n None -> strs.push(\"severity=info\"),\n Some{severity} -> strs.push(\"severity=${severity}\")\n };\n- match (acl.action) {\n+ match (acl.action.ival()) {\n \"drop\" -> {\n strs.push(\"verdict=drop\")\n },\n@@ -2410,9 +2411,9 @@ function build_acl_log(acl: Intern<nb::ACL>, fair_meter: bool): string =\n Some{meter} -> {\n var name = match (fair_meter) {\n true -> acl_log_meter_name(meter, acl._uuid),\n- false -> meter\n+ false -> meter.ival()\n };\n- strs.push(\"meter=${json_string_escape(name)}\")\n+ strs.push(\"meter=${json_escape(name)}\")\n },\n None -> ()\n };\n@@ -2435,9 +2436,9 @@ relation Reject(\n stage: Intern<Stage>,\n acl: Intern<nb::ACL>,\n fair_meter: bool,\n- controller_meter: Option<string>,\n- extra_match: string,\n- extra_actions: string)\n+ controller_meter: Option<istring>,\n+ extra_match: istring,\n+ extra_actions: istring)\n \n /* build_reject_acl_rules() */\n function next_to_stage(stage: Intern<Stage>): string {\n@@ -2449,14 +2450,8 @@ function next_to_stage(stage: Intern<Stage>): string {\n }\n for (Reject(lsuuid, pipeline, stage, acl, fair_meter, controller_meter,\n extra_match_, extra_actions_)) {\n- var extra_match = match (extra_match_) {\n- \"\" -> \"\",\n- s -> \"(${s}) && \"\n- } in\n- var extra_actions = match (extra_actions_) {\n- \"\" -> \"\",\n- s -> \"${s} \"\n- } in\n+ var extra_match = if (extra_match_ == i\"\") { \"\" } else { \"(${extra_match_}) && \" } in\n+ var extra_actions = if (extra_actions_ == i\"\") { \"\" } else { \"${extra_actions_} \" } in\n var next_stage = match (pipeline) {\n Ingress -> s_SWITCH_OUT_QOS_MARK(),\n Egress -> s_SWITCH_IN_L2_LKUP()\n@@ -2786,13 +2781,13 @@ for (sw in &Switch(._uuid = ls_uuid)) {\n for (&SwitchACL(.sw = sw, .acl = acl, .has_fair_meter = fair_meter)) {\n /* consider_acl */\n var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in\n- var ingress = acl.direction == \"from-lport\" in\n+ var ingress = acl.direction == i\"from-lport\" in\n var stage = if (ingress) { s_SWITCH_IN_ACL() } else { s_SWITCH_OUT_ACL() } in\n var pipeline = if ingress Ingress else Egress in\n var stage_hint = stage_hint(acl._uuid) in\n var acl_log = build_acl_log(acl, fair_meter) in\n var acl_match = acl.__match.intern() in\n- if (acl.action == \"allow\" or acl.action == \"allow-related\") {\n+ if (acl.action == i\"allow\" or acl.action == i\"allow-related\") {\n /* If there are any stateful flows, we must even commit \"allow\"\n * actions. This is because, while the initiater's\n * direction may not have any stateful rules, the server's\n@@ -2802,7 +2797,7 @@ for (&SwitchACL(.sw = sw, .acl = acl, .has_fair_meter = fair_meter)) {\n Flow(.logical_datapath = sw._uuid,\n .stage = stage,\n .priority = acl.priority + oVN_ACL_PRI_OFFSET(),\n- .__match = acl.__match.intern(),\n+ .__match = acl.__match,\n .actions = i\"${acl_log}next;\",\n .stage_hint = stage_hint,\n .io_port = None,\n@@ -2859,16 +2854,16 @@ for (&SwitchACL(.sw = sw, .acl = acl, .has_fair_meter = fair_meter)) {\n .io_port = None,\n .controller_meter = None)\n }\n- } else if (acl.action == \"allow-stateless\") {\n+ } else if (acl.action == i\"allow-stateless\") {\n Flow(.logical_datapath = sw._uuid,\n .stage = stage,\n .priority = acl.priority + oVN_ACL_PRI_OFFSET(),\n- .__match = acl.__match.intern(),\n+ .__match = acl.__match,\n .actions = i\"${acl_log}next;\",\n .stage_hint = stage_hint,\n .io_port = None,\n .controller_meter = None)\n- } else if (acl.action == \"drop\" or acl.action == \"reject\") {\n+ } else if (acl.action == i\"drop\" or acl.action == i\"reject\") {\n /* The implementation of \"drop\" differs if stateful ACLs are in\n * use for this datapath. In that case, the actions differ\n * depending on whether the connection was previously committed\n@@ -2878,8 +2873,8 @@ for (&SwitchACL(.sw = sw, .acl = acl, .has_fair_meter = fair_meter)) {\n /* If the packet is not tracked or not part of an established\n * connection, then we can simply reject/drop it. */\n var __match = \"${rEGBIT_ACL_HINT_DROP()} == 1\" in\n- if (acl.action == \"reject\") {\n- Reject(sw._uuid, pipeline, stage, acl, fair_meter, controller_meter, __match, \"\")\n+ if (acl.action == i\"reject\") {\n+ Reject(sw._uuid, pipeline, stage, acl, fair_meter, controller_meter, __match.intern(), i\"\")\n } else {\n Flow(.logical_datapath = sw._uuid,\n .stage = stage,\n@@ -2903,8 +2898,8 @@ for (&SwitchACL(.sw = sw, .acl = acl, .has_fair_meter = fair_meter)) {\n */\n var __match = \"${rEGBIT_ACL_HINT_BLOCK()} == 1\" in\n var actions = \"ct_commit { ct_label.blocked = 1; }; \" in\n- if (acl.action == \"reject\") {\n- Reject(sw._uuid, pipeline, stage, acl, fair_meter, controller_meter, __match, actions)\n+ if (acl.action == i\"reject\") {\n+ Reject(sw._uuid, pipeline, stage, acl, fair_meter, controller_meter, __match.intern(), actions.intern())\n } else {\n Flow(.logical_datapath = sw._uuid,\n .stage = stage,\n@@ -2919,13 +2914,13 @@ for (&SwitchACL(.sw = sw, .acl = acl, .has_fair_meter = fair_meter)) {\n /* There are no stateful ACLs in use on this datapath,\n * so a \"reject/drop\" ACL is simply the \"reject/drop\"\n * logical flow action in all cases. */\n- if (acl.action == \"reject\") {\n- Reject(sw._uuid, pipeline, stage, acl, fair_meter, controller_meter, \"\", \"\")\n+ if (acl.action == i\"reject\") {\n+ Reject(sw._uuid, pipeline, stage, acl, fair_meter, controller_meter, i\"\", i\"\")\n } else {\n Flow(.logical_datapath = sw._uuid,\n .stage = stage,\n .priority = acl.priority + oVN_ACL_PRI_OFFSET(),\n- .__match = acl.__match.intern(),\n+ .__match = acl.__match,\n .actions = i\"${acl_log}/* drop */\",\n .stage_hint = stage_hint,\n .io_port = None,\n@@ -2940,14 +2935,14 @@ for (&SwitchACL(.sw = sw, .acl = acl, .has_fair_meter = fair_meter)) {\n * */\n for (SwitchPortDHCPv4Options(.port = &SwitchPort{.lsp = lsp, .sw = sw},\n .dhcpv4_options = dhcpv4_options@&nb::DHCP_Options{.options = options})\n- if lsp.__type != \"external\") {\n+ if lsp.__type != i\"external\") {\n (Some{var server_id}, Some{var server_mac}, Some{var lease_time}) =\n- (options.get(\"server_id\"), options.get(\"server_mac\"), options.get(\"lease_time\")) in\n+ (options.get(i\"server_id\"), options.get(i\"server_mac\"), options.get(i\"lease_time\")) in\n var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in\n Flow(.logical_datapath = sw._uuid,\n .stage = s_SWITCH_OUT_ACL(),\n .priority = 34000,\n- .__match = i\"outport == ${json_string_escape(lsp.name)} \"\n+ .__match = i\"outport == ${json_escape(lsp.name)} \"\n \"&& eth.src == ${server_mac} \"\n \"&& ip4.src == ${server_id} && udp && udp.src == 67 \"\n \"&& udp.dst == 68\",\n@@ -2959,9 +2954,9 @@ for (SwitchPortDHCPv4Options(.port = &SwitchPort{.lsp = lsp, .sw = sw},\n \n for (SwitchPortDHCPv6Options(.port = &SwitchPort{.lsp = lsp, .sw = sw},\n .dhcpv6_options = dhcpv6_options@&nb::DHCP_Options{.options=options} )\n- if lsp.__type != \"external\") {\n- Some{var server_mac} = options.get(\"server_id\") in\n- Some{var ea} = eth_addr_from_string(server_mac) in\n+ if lsp.__type != i\"external\") {\n+ Some{var server_mac} = options.get(i\"server_id\") in\n+ Some{var ea} = eth_addr_from_string(server_mac.ival()) in\n var server_ip = ea.to_ipv6_lla() in\n /* Get the link local IP of the DHCPv6 server from the\n * server MAC. */\n@@ -2969,7 +2964,7 @@ for (SwitchPortDHCPv6Options(.port = &SwitchPort{.lsp = lsp, .sw = sw},\n Flow(.logical_datapath = sw._uuid,\n .stage = s_SWITCH_OUT_ACL(),\n .priority = 34000,\n- .__match = i\"outport == ${json_string_escape(lsp.name)} \"\n+ .__match = i\"outport == ${json_escape(lsp.name)} \"\n \"&& eth.src == ${server_mac} \"\n \"&& ip6.src == ${server_ip} && udp && udp.src == 547 \"\n \"&& udp.dst == 546\",\n@@ -2979,12 +2974,11 @@ for (SwitchPortDHCPv6Options(.port = &SwitchPort{.lsp = lsp, .sw = sw},\n .controller_meter = None)\n }\n \n-relation QoSAction(qos: uuid, key_action: string, value_action: integer)\n+relation QoSAction(qos: uuid, key_action: istring, value_action: integer)\n \n QoSAction(qos, k, v) :-\n &nb::QoS(._uuid = qos, .action = actions),\n- var action = FlatMap(actions),\n- (var k, var v) = action.\n+ (var k, var v) = FlatMap(actions).\n \n /* QoS rules */\n for (&Switch(._uuid = ls_uuid)) {\n@@ -3023,16 +3017,16 @@ for (&Switch(._uuid = ls_uuid)) {\n }\n \n for (SwitchQoS(.sw = sw, .qos = qos)) {\n- var ingress = if (qos.direction == \"from-lport\") true else false in\n+ var ingress = if (qos.direction == i\"from-lport\") true else false in\n var pipeline = if ingress \"ingress\" else \"egress\" in {\n var stage = if (ingress) { s_SWITCH_IN_QOS_MARK() } else { s_SWITCH_OUT_QOS_MARK() } in\n /* FIXME: Can value_action be negative? */\n for (QoSAction(qos._uuid, key_action, value_action)) {\n- if (key_action == \"dscp\") {\n+ if (key_action == i\"dscp\") {\n Flow(.logical_datapath = sw._uuid,\n .stage = stage,\n .priority = qos.priority,\n- .__match = qos.__match.intern(),\n+ .__match = qos.__match,\n .actions = i\"ip.dscp = ${value_action}; next;\",\n .stage_hint = stage_hint(qos._uuid),\n .io_port = None,\n@@ -3043,12 +3037,11 @@ for (SwitchQoS(.sw = sw, .qos = qos)) {\n (var burst, var rate) = {\n var rate = 0;\n var burst = 0;\n- for (bw in qos.bandwidth) {\n+ for ((key_bandwidth, value_bandwidth) in qos.bandwidth) {\n /* FIXME: Can value_bandwidth be negative? */\n- (var key_bandwidth, var value_bandwidth) = bw;\n- if (key_bandwidth == \"rate\") {\n+ if (key_bandwidth == i\"rate\") {\n rate = value_bandwidth\n- } else if (key_bandwidth == \"burst\") {\n+ } else if (key_bandwidth == i\"burst\") {\n burst = value_bandwidth\n } else ()\n };\n@@ -3068,7 +3061,7 @@ for (SwitchQoS(.sw = sw, .qos = qos)) {\n Flow(.logical_datapath = sw._uuid,\n .stage = stage,\n .priority = qos.priority,\n- .__match = qos.__match.intern(),\n+ .__match = qos.__match,\n .actions = meter_action,\n .stage_hint = stage_hint(qos._uuid),\n .io_port = None,\n@@ -3150,12 +3143,12 @@ for (&Switch(._uuid = ls_uuid)) {\n * REGBIT_CONNTRACK_COMMIT. */\n function get_match_for_lb_key(ip_address: v46_ip,\n port: bit<16>,\n- protocol: Option<string>,\n+ protocol: Option<istring>,\n redundancy: bool,\n use_nexthop_reg: bool,\n use_dest_tp_reg: bool): string = {\n var port_match = if (port != 0) {\n- var proto = if (protocol == Some{\"udp\"}) {\n+ var proto = if (protocol == Some{i\"udp\"}) {\n \"udp\"\n } else {\n \"tcp\"\n@@ -3195,21 +3188,22 @@ function get_match_for_lb_key(ip_address: v46_ip,\n /* New connections in Ingress table. */\n \n function ct_lb(backends: string,\n- selection_fields: Set<string>, protocol: Option<string>): string {\n+ selection_fields: Set<istring>, protocol: Option<istring>): string {\n var args = vec_with_capacity(2);\n args.push(\"backends=${backends}\");\n \n if (not selection_fields.is_empty()) {\n var hash_fields = vec_with_capacity(selection_fields.size());\n for (sf in selection_fields) {\n- var hf = match ((sf, protocol)) {\n+ var hf = match ((sf.ival(), protocol)) {\n (\"tp_src\", Some{p}) -> \"${p}_src\",\n (\"tp_dst\", Some{p}) -> \"${p}_dst\",\n- _ -> sf\n+ _ -> sf.ival()\n };\n hash_fields.push(hf);\n };\n- args.push(\"hash_fields=\" ++ json_string_escape(hash_fields.join(\",\")));\n+ hash_fields.sort();\n+ args.push(\"hash_fields=\" ++ json_escape(hash_fields.join(\",\")));\n };\n \n \"ct_lb(\" ++ args.join(\"; \") ++ \");\"\n@@ -3217,28 +3211,27 @@ function ct_lb(backends: string,\n function build_lb_vip_actions(lbvip: Intern<LBVIPWithStatus>,\n stage: Intern<Stage>,\n actions0: string): (string, bool) {\n- var up_backends = set_empty();\n+ var up_backends = vec_with_capacity(lbvip.backends.size());\n for (pair in lbvip.backends) {\n (var backend, var up) = pair;\n if (up) {\n- if (backend.port != 0) {\n- up_backends.insert(\"${backend.ip.to_bracketed_string()}:${backend.port}\")\n- } else {\n- up_backends.insert(\"${backend.ip.to_bracketed_string()}\")\n- }\n+ up_backends.push((backend.ip, backend.port))\n }\n };\n \n if (up_backends.is_empty()) {\n- if (lbvip.lb.options.get_bool_def(\"reject\", false)) {\n+ if (lbvip.lb.options.get_bool_def(i\"reject\", false)) {\n return (\"reg0 = 0; reject { outport <-> inport; ${next_to_stage(stage)};};\", true)\n } else if (lbvip.health_check.is_some()) {\n return (\"drop;\", false)\n } // else fall through\n };\n \n- var actions = ct_lb(up_backends.to_vec().join(\",\"), lbvip.lb.selection_fields,\n- lbvip.lb.protocol);\n+ var up_backends_s = up_backends.sort_imm().map(|x| match (x) {\n+ (ip, 0) -> \"${ip.to_bracketed_string()}\",\n+ (ip, port) -> \"${ip.to_bracketed_string()}:${port}\"\n+ }).join(\",\");\n+ var actions = ct_lb(up_backends_s, lbvip.lb.selection_fields, lbvip.lb.protocol);\n (actions0 ++ actions, false)\n }\n Flow(.logical_datapath = sw._uuid,\n@@ -3363,14 +3356,14 @@ for (&Switch(._uuid = ls_uuid, .has_lb_vip = true)) {\n ingress table PORT_SEC_IP: ingress port security - IP (priority 90 and 80)\n ingress table PORT_SEC_ND: ingress port security - ND (priority 90 and 80) */\n for (&SwitchPort(.lsp = lsp, .sw = sw, .json_name = json_name, .ps_eth_addresses = ps_eth_addresses)\n- if lsp.is_enabled() and lsp.__type != \"external\") {\n+ if lsp.is_enabled() and lsp.__type != i\"external\") {\n for (pbinding in sb::Out_Port_Binding(.logical_port = lsp.name)) {\n var __match = if (ps_eth_addresses.is_empty()) {\n i\"inport == ${json_name}\"\n } else {\n i\"inport == ${json_name} && eth.src == {${ps_eth_addresses.join(\\\" \\\")}}\"\n } in\n- var actions = match (pbinding.options.get(\"qdisc_queue_id\")) {\n+ var actions = match (pbinding.options.get(i\"qdisc_queue_id\")) {\n None -> i\"next;\",\n Some{id} -> i\"set_queue(${id}); next;\"\n } in\n@@ -3403,7 +3396,7 @@ for (&SwitchPort(.lsp = lsp, .sw = sw, .json_name = json_name, .ps_eth_addresses\n for (SwitchPortPSAddresses(.port = port@&SwitchPort{.sw = sw}, .ps_addrs = ps)\n if port.is_enabled() and\n (ps.ipv4_addrs.len() > 0 or ps.ipv6_addrs.len() > 0) and\n- port.lsp.__type != \"external\")\n+ port.lsp.__type != i\"external\")\n {\n if (ps.ipv4_addrs.len() > 0) {\n var dhcp_match = i\"inport == ${port.json_name}\"\n@@ -3510,7 +3503,7 @@ for (SwitchPortPSAddresses(.port = port@&SwitchPort{.sw = sw}, .ps_addrs = ps)\n * - Priority 80 flow to drop ARP and IPv6 ND packets.\n */\n for (SwitchPortPSAddresses(.port = port@&SwitchPort{.sw = sw}, .ps_addrs = ps)\n- if port.is_enabled() and port.lsp.__type != \"external\")\n+ if port.is_enabled() and port.lsp.__type != i\"external\")\n {\n var no_ip = ps.ipv4_addrs.is_empty() and ps.ipv6_addrs.is_empty() in\n {\n@@ -3588,7 +3581,7 @@ for (&Switch(._uuid = ls_uuid)) {\n * rationale. */\n for (&SwitchPort(.lsp = lsp, .sw = sw, .json_name = json_name)\n if lsp.is_enabled() and\n- (lsp.__type == \"localnet\" or lsp.__type == \"vtep\"))\n+ (lsp.__type == i\"localnet\" or lsp.__type == i\"vtep\"))\n {\n Flow(.logical_datapath = sw._uuid,\n .stage = s_SWITCH_IN_ARP_ND_RSP(),\n@@ -3623,12 +3616,12 @@ function lsp_is_up(lsp: Intern<nb::Logical_Switch_Port>): bool = {\n .stage_hint = stage_hint(lsp._uuid),\n .io_port = Some{vp.lsp.name},\n .controller_meter = None) :-\n- sp in &SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = \"virtual\"}),\n- Some{var virtual_ip} = lsp.options.get(\"virtual-ip\"),\n- Some{var virtual_parents} = lsp.options.get(\"virtual-parents\"),\n- Some{var ip} = ip_parse(virtual_ip),\n- var vparent = FlatMap(string_split(virtual_parents, \",\")),\n- vp in &SwitchPort(.lsp = &nb::Logical_Switch_Port{.name = vparent}),\n+ sp in &SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = i\"virtual\"}),\n+ Some{var virtual_ip} = lsp.options.get(i\"virtual-ip\"),\n+ Some{var virtual_parents} = lsp.options.get(i\"virtual-parents\"),\n+ Some{var ip} = ip_parse(virtual_ip.ival()),\n+ var vparent = FlatMap(virtual_parents.split(\",\")),\n+ vp in &SwitchPort(.lsp = &nb::Logical_Switch_Port{.name = vparent.intern()}),\n vp.sw == sp.sw.\n \n /*\n@@ -3642,9 +3635,9 @@ for (CheckLspIsUp[check_lsp_is_up]) {\n .ea = ea, .addr = addr)\n if lsp.is_enabled() and\n ((lsp_is_up(lsp) or not check_lsp_is_up)\n- or lsp.__type == \"router\" or lsp.__type == \"localport\") and\n- lsp.__type != \"external\" and lsp.__type != \"virtual\" and\n- not lsp.addresses.contains(\"unknown\") and\n+ or lsp.__type == i\"router\" or lsp.__type == i\"localport\") and\n+ lsp.__type != i\"external\" and lsp.__type != i\"virtual\" and\n+ not lsp.addresses.contains(i\"unknown\") and\n not sw.is_vlan_transparent)\n {\n var __match = \"arp.tpa == ${addr.addr} && arp.op == 1\" in\n@@ -3704,10 +3697,10 @@ Flow(.logical_datapath = sw._uuid,\n sp in &SwitchPort(.sw = sw, .peer = Some{rp}),\n rp.is_enabled(),\n var proxy_ips = {\n- match (sp.lsp.options.get(\"arp_proxy\")) {\n+ match (sp.lsp.options.get(i\"arp_proxy\")) {\n None -> \"\",\n Some {addresses} -> {\n- match (extract_ip_addresses(addresses)) {\n+ match (extract_ip_addresses(addresses.ival())) {\n None -> \"\",\n Some{addr} -> {\n var ip4_addrs = vec_empty();\n@@ -3738,12 +3731,12 @@ Flow(.logical_datapath = sw._uuid,\n for (SwitchPortIPv6Address(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = sw},\n .ea = ea, .addr = addr)\n if lsp.is_enabled() and\n- (lsp_is_up(lsp) or lsp.__type == \"router\" or lsp.__type == \"localport\") and\n- lsp.__type != \"external\" and lsp.__type != \"virtual\" and\n+ (lsp_is_up(lsp) or lsp.__type == i\"router\" or lsp.__type == i\"localport\") and\n+ lsp.__type != i\"external\" and lsp.__type != i\"virtual\" and\n not sw.is_vlan_transparent)\n {\n var __match = \"nd_ns && ip6.dst == {${addr.addr}, ${addr.solicited_node()}} && nd.target == ${addr.addr}\" in\n- var actions = i\"${if (lsp.__type == \\\"router\\\") \\\"nd_na_router\\\" else \\\"nd_na\\\"} { \"\n+ var actions = i\"${if (lsp.__type == i\\\"router\\\") \\\"nd_na_router\\\" else \\\"nd_na\\\"} { \"\n \"eth.src = ${ea}; \"\n \"ip6.src = ${addr.addr}; \"\n \"nd.target = ${addr.addr}; \"\n@@ -3819,9 +3812,9 @@ function build_dhcpv4_action(\n lsp_json_key: string,\n dhcpv4_options: Intern<nb::DHCP_Options>,\n offer_ip: in_addr,\n- lsp_options: Map<string,string>) : Option<(istring, istring, string)> =\n+ lsp_options: Map<istring,istring>) : Option<(istring, istring, string)> =\n {\n- match (ip_parse_masked(dhcpv4_options.cidr)) {\n+ match (ip_parse_masked(dhcpv4_options.cidr.ival())) {\n Left{err} -> {\n /* cidr defined is invalid */\n None\n@@ -3833,29 +3826,28 @@ function build_dhcpv4_action(\n */\n None\n } else {\n- match ((dhcpv4_options.options.get(\"server_id\"),\n- dhcpv4_options.options.get(\"server_mac\"),\n- dhcpv4_options.options.get(\"lease_time\")))\n+ match ((dhcpv4_options.options.get(i\"server_id\"),\n+ dhcpv4_options.options.get(i\"server_mac\"),\n+ dhcpv4_options.options.get(i\"lease_time\")))\n {\n (Some{var server_ip}, Some{var server_mac}, Some{var lease_time}) -> {\n var options_map = dhcpv4_options.options;\n \n /* server_mac is not DHCPv4 option, delete it from the smap. */\n- options_map.remove(\"server_mac\");\n- options_map.insert(\"netmask\", \"${mask}\");\n+ options_map.remove(i\"server_mac\");\n+ options_map.insert(i\"netmask\", i\"${mask}\");\n \n- match (lsp_options.get(\"hostname\")) {\n+ match (lsp_options.get(i\"hostname\")) {\n None -> (),\n- Some{port_hostname} -> options_map.insert(\"hostname\", \"${port_hostname}\")\n+ Some{port_hostname} -> options_map.insert(i\"hostname\", port_hostname)\n };\n \n- /* We're not using SMAP_FOR_EACH because we want a consistent order of the\n- * options on different architectures (big or little endian, SSE4.2) */\n var options = vec_empty();\n for (node in options_map) {\n (var k, var v) = node;\n options.push(\"${k} = ${v}\")\n };\n+ options.sort();\n var options_action = \"${rEGBIT_DHCP_OPTS_RESULT()} = put_dhcp_opts(offerip = ${offer_ip}, \" ++\n options.join(\", \") ++ \"); next;\";\n var response_action = i\"eth.dst = eth.src; eth.src = ${server_mac}; \"\n@@ -3884,7 +3876,7 @@ function build_dhcpv6_action(\n dhcpv6_options: Intern<nb::DHCP_Options>,\n offer_ip: in6_addr): Option<(istring, istring)> =\n {\n- match (ipv6_parse_masked(dhcpv6_options.cidr)) {\n+ match (ipv6_parse_masked(dhcpv6_options.cidr.ival())) {\n Left{err} -> {\n /* cidr defined is invalid */\n //warn(\"cidr is invalid - ${err}\");\n@@ -3898,13 +3890,13 @@ function build_dhcpv6_action(\n None\n } else {\n /* \"server_id\" should be the MAC address. */\n- match (dhcpv6_options.options.get(\"server_id\")) {\n+ match (dhcpv6_options.options.get(i\"server_id\")) {\n None -> {\n warn(\"server_id not present in the DHCPv6 options for lport ${lsp_json_key}\");\n None\n },\n Some{server_mac} -> {\n- match (eth_addr_from_string(server_mac)) {\n+ match (eth_addr_from_string(server_mac.ival())) {\n None -> {\n warn(\"server_id not present in the DHCPv6 options for lport ${lsp_json_key}\");\n None\n@@ -3917,19 +3909,16 @@ function build_dhcpv6_action(\n \n /* Check whether the dhcpv6 options should be configured as stateful.\n * Only reply with ia_addr option for dhcpv6 stateful address mode. */\n- if (not dhcpv6_options.options.get_bool_def(\"dhcpv6_stateless\", false)) {\n+ if (not dhcpv6_options.options.get_bool_def(i\"dhcpv6_stateless\", false)) {\n options.push(\"ia_addr = ${ia_addr}\")\n } else ();\n \n- /* We're not using SMAP_FOR_EACH because we want a consistent order of the\n- * options on different architectures (big or little endian, SSE4.2) */\n- // FIXME: enumerate map in ascending order of keys. Is this good enough?\n- for (node in dhcpv6_options.options) {\n- (var k, var v) = node;\n- if (k != \"dhcpv6_stateless\") {\n+ for ((k, v) in dhcpv6_options.options) {\n+ if (k != i\"dhcpv6_stateless\") {\n options.push(\"${k} = ${v}\")\n } else ()\n };\n+ options.sort();\n \n var options_action = \"${rEGBIT_DHCP_OPTS_RESULT()} = put_dhcpv6_opts(\" ++\n options.join(\", \") ++\n@@ -3948,17 +3937,17 @@ function build_dhcpv6_action(\n }\n }\n \n-/* If 'names' has one element, returns json_string_escape() for it.\n- * Otherwise, returns json_string_escape() of all of its elements inside \"{...}\".\n+/* If 'names' has one element, returns json_escape() for it.\n+ * Otherwise, returns json_escape() of all of its elements inside \"{...}\".\n */\n-function json_string_escape_vec(names: Vec<string>): string\n+function json_escape_vec(names: Vec<string>): string\n {\n match ((names.len(), names.nth(0))) {\n- (1, Some{name}) -> json_string_escape(name),\n+ (1, Some{name}) -> json_escape(name),\n _ -> {\n var json_names = vec_with_capacity(names.len());\n for (name in names) {\n- json_names.push(json_string_escape(name));\n+ json_names.push(json_escape(name));\n };\n \"{\" ++ json_names.join(\", \") ++ \"}\"\n }\n@@ -3981,8 +3970,8 @@ function json_string_escape_vec(names: Vec<string>): string\n */\n function match_dhcp_input(lsp: Intern<SwitchPort>): (string, string) =\n {\n- if (lsp.lsp.__type == \"external\" and not lsp.sw.localnet_ports.is_empty()) {\n- (\"inport == \" ++ json_string_escape_vec(lsp.sw.localnet_ports.map(|x| x.1)) ++ \" && \",\n+ if (lsp.lsp.__type == i\"external\" and not lsp.sw.localnet_ports.is_empty()) {\n+ (\"inport == \" ++ json_escape_vec(lsp.sw.localnet_ports.map(|x| x.1.ival())) ++ \" && \",\n \" && is_chassis_resident(${lsp.json_name})\")\n } else {\n (\"inport == ${lsp.json_name} && \", \"\")\n@@ -3994,15 +3983,15 @@ function match_dhcp_input(lsp: Intern<SwitchPort>): (string, string) =\n for (lsp in &SwitchPort\n /* Don't add the DHCP flows if the port is not enabled or if the\n * port is a router port. */\n- if (lsp.is_enabled() and lsp.lsp.__type != \"router\")\n+ if (lsp.is_enabled() and lsp.lsp.__type != i\"router\")\n /* If it's an external port and there is no localnet port\n * and if it doesn't belong to an HA chassis group ignore it. */\n- and (lsp.lsp.__type != \"external\"\n+ and (lsp.lsp.__type != i\"external\"\n or (not lsp.sw.localnet_ports.is_empty()\n and lsp.lsp.ha_chassis_group.is_some())))\n {\n for (lps in LogicalSwitchPort(.lport = lsp.lsp._uuid, .lswitch = lsuuid)) {\n- var json_key = json_string_escape(lsp.lsp.name) in\n+ var json_key = json_escape(lsp.lsp.name) in\n (var pfx, var sfx) = match_dhcp_input(lsp) in\n {\n /* DHCPv4 options enabled for this port */\n@@ -4227,7 +4216,7 @@ for (sw in &Switch(._uuid = ls_uuid, .mcast_cfg = mcast_cfg)\n var flood_static = not flood_ports.is_empty() in\n var igmp_act = {\n if (flood_reports) {\n- var mrouter_static = json_string_escape(mC_MROUTER_STATIC().0);\n+ var mrouter_static = json_escape(mC_MROUTER_STATIC().0);\n i\"clone { \"\n \"outport = ${mrouter_static}; \"\n \"output; \"\n@@ -4259,7 +4248,7 @@ for (sw in &Switch(._uuid = ls_uuid, .mcast_cfg = mcast_cfg)\n /* Flood all IP multicast traffic destined to 224.0.0.X to\n * all ports - RFC 4541, section 2.1.2, item 2.\n */\n- var flood = json_string_escape(mC_FLOOD().0) in\n+ var flood = json_escape(mC_FLOOD().0) in\n Flow(.logical_datapath = ls_uuid,\n .stage = s_SWITCH_IN_L2_LKUP(),\n .priority = 85,\n@@ -4272,7 +4261,7 @@ for (sw in &Switch(._uuid = ls_uuid, .mcast_cfg = mcast_cfg)\n /* Flood all IPv6 multicast traffic destined to reserved\n * multicast IPs (RFC 4291, 2.7.1).\n */\n- var flood = json_string_escape(mC_FLOOD().0) in\n+ var flood = json_escape(mC_FLOOD().0) in\n Flow(.logical_datapath = ls_uuid,\n .stage = s_SWITCH_IN_L2_LKUP(),\n .priority = 85,\n@@ -4290,7 +4279,7 @@ for (sw in &Switch(._uuid = ls_uuid, .mcast_cfg = mcast_cfg)\n if (not mcast_cfg.flood_unreg) {\n var relay_act = {\n if (flood_relay) {\n- var rtr_flood = json_string_escape(mC_MROUTER_FLOOD().0);\n+ var rtr_flood = json_escape(mC_MROUTER_FLOOD().0);\n \"clone { \"\n \"outport = ${rtr_flood}; \"\n \"output; \"\n@@ -4301,7 +4290,7 @@ for (sw in &Switch(._uuid = ls_uuid, .mcast_cfg = mcast_cfg)\n } in\n var static_act = {\n if (flood_static) {\n- var mc_static = json_string_escape(mC_STATIC().0);\n+ var mc_static = json_escape(mC_STATIC().0);\n \"outport =${mc_static}; output;\"\n } else {\n \"\"\n@@ -4338,7 +4327,7 @@ for (IgmpSwitchMulticastGroup(.address = address, .switch = sw)) {\n * RFC 4291, section 2.7.1: Skip groups that correspond to all\n * hosts.\n */\n- Some{var ip} = ip46_parse(address) in\n+ Some{var ip} = ip46_parse(address.ival()) in\n (var skip_address) = match (ip) {\n IPv4{ipv4} -> ipv4.is_local_multicast(),\n IPv6{ipv6} -> ipv6.is_all_hosts()\n@@ -4348,8 +4337,8 @@ for (IgmpSwitchMulticastGroup(.address = address, .switch = sw)) {\n for (SwitchMcastFloodPorts(sw, flood_ports)) {\n var flood_relay = not relay_ports.is_empty() in\n var flood_static = not flood_ports.is_empty() in\n- var mc_rtr_flood = json_string_escape(mC_MROUTER_FLOOD().0) in\n- var mc_static = json_string_escape(mC_STATIC().0) in\n+ var mc_rtr_flood = json_escape(mC_MROUTER_FLOOD().0) in\n+ var mc_static = json_escape(mC_STATIC().0) in\n var relay_act = {\n if (flood_relay) {\n \"clone { \"\n@@ -4394,7 +4383,7 @@ for (IgmpSwitchMulticastGroup(.address = address, .switch = sw)) {\n Flow(.logical_datapath = sp.sw._uuid,\n .stage = s_SWITCH_IN_EXTERNAL_PORT(),\n .priority = 100,\n- .__match = (i\"inport == ${json_string_escape(localnet_port.1)} && \"\n+ .__match = (i\"inport == ${json_escape(localnet_port.1)} && \"\n \"eth.src == ${lp_addr.ea} && \"\n \"!is_chassis_resident(${sp.json_name}) && \"\n \"arp.tpa == ${rp_addr.addr} && arp.op == 1\"),\n@@ -4403,16 +4392,16 @@ Flow(.logical_datapath = sp.sw._uuid,\n .io_port = Some{localnet_port.1},\n .controller_meter = None) :-\n sp in &SwitchPort(),\n- sp.lsp.__type == \"external\",\n+ sp.lsp.__type == i\"external\",\n var localnet_port = FlatMap(sp.sw.localnet_ports),\n var lp_addr = FlatMap(sp.static_addresses),\n rp in &SwitchPort(.sw = sp.sw),\n- rp.lsp.__type == \"router\",\n+ rp.lsp.__type == i\"router\",\n SwitchPortIPv4Address(.port = rp, .addr = rp_addr).\n Flow(.logical_datapath = sp.sw._uuid,\n .stage = s_SWITCH_IN_EXTERNAL_PORT(),\n .priority = 100,\n- .__match = (i\"inport == ${json_string_escape(localnet_port.1)} && \"\n+ .__match = (i\"inport == ${json_escape(localnet_port.1)} && \"\n \"eth.src == ${lp_addr.ea} && \"\n \"!is_chassis_resident(${sp.json_name}) && \"\n \"nd_ns && ip6.dst == {${rp_addr.addr}, ${rp_addr.solicited_node()}} && \"\n@@ -4422,16 +4411,16 @@ Flow(.logical_datapath = sp.sw._uuid,\n .io_port = Some{localnet_port.1},\n .controller_meter = None) :-\n sp in &SwitchPort(),\n- sp.lsp.__type == \"external\",\n+ sp.lsp.__type == i\"external\",\n var localnet_port = FlatMap(sp.sw.localnet_ports),\n var lp_addr = FlatMap(sp.static_addresses),\n rp in &SwitchPort(.sw = sp.sw),\n- rp.lsp.__type == \"router\",\n+ rp.lsp.__type == i\"router\",\n SwitchPortIPv6Address(.port = rp, .addr = rp_addr).\n Flow(.logical_datapath = sp.sw._uuid,\n .stage = s_SWITCH_IN_EXTERNAL_PORT(),\n .priority = 100,\n- .__match = (i\"inport == ${json_string_escape(localnet_port.1)} && \"\n+ .__match = (i\"inport == ${json_escape(localnet_port.1)} && \"\n \"eth.src == ${lp_addr.ea} && \"\n \"eth.dst == ${ea} && \"\n \"!is_chassis_resident(${sp.json_name})\"),\n@@ -4440,17 +4429,17 @@ Flow(.logical_datapath = sp.sw._uuid,\n .io_port = Some{localnet_port.1},\n .controller_meter = None) :-\n sp in &SwitchPort(),\n- sp.lsp.__type == \"external\",\n+ sp.lsp.__type == i\"external\",\n var localnet_port = FlatMap(sp.sw.localnet_ports),\n var lp_addr = FlatMap(sp.static_addresses),\n rp in &SwitchPort(.sw = sp.sw),\n- rp.lsp.__type == \"router\",\n+ rp.lsp.__type == i\"router\",\n SwitchPortAddresses(.port = rp, .addrs = LPortAddress{.ea = ea}).\n \n /* Ingress table L2_LKUP: Destination lookup, broadcast and multicast handling\n * (priority 100). */\n for (ls in &nb::Logical_Switch) {\n- var mc_flood = json_string_escape(mC_FLOOD().0) in\n+ var mc_flood = json_escape(mC_FLOOD().0) in\n Flow(.logical_datapath = ls._uuid,\n .stage = s_SWITCH_IN_L2_LKUP(),\n .priority = 70,\n@@ -4465,7 +4454,7 @@ for (ls in &nb::Logical_Switch) {\n */\n for (SwitchPortStaticAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = sw},\n .addrs = addrs)\n- if lsp.__type != \"external\") {\n+ if lsp.__type != i\"external\") {\n Flow(.logical_datapath = sw._uuid,\n .stage = s_SWITCH_IN_L2_LKUP(),\n .priority = 50,\n@@ -4520,7 +4509,7 @@ Flow(.logical_datapath = sw._uuid,\n sp in &SwitchPort(.sw = sw@&Switch{.has_non_router_port = true}, .peer = Some{rp}),\n rp.is_enabled(),\n var eth_src_set = {\n- var eth_src_set = set_singleton(\"${rp.networks.ea}\");\n+ var eth_src_set = set_singleton(i\"${rp.networks.ea}\");\n for (nat in rp.router.nats) {\n match (nat.nat.external_mac) {\n Some{mac} ->\n@@ -4534,7 +4523,7 @@ Flow(.logical_datapath = sw._uuid,\n },\n var eth_src = \"{\" ++ eth_src_set.to_vec().join(\", \") ++ \"}\",\n var __match = i\"eth.src == ${eth_src} && (arp.op == 1 || nd_ns)\",\n- var mc_flood_l2 = json_string_escape(mC_FLOOD_L2().0),\n+ var mc_flood_l2 = json_escape(mC_FLOOD_L2().0),\n var actions = i\"outport = ${mc_flood_l2}; output;\".\n \n /* Forward ARP requests for owned IP addresses (L3, VIP, NAT) only to this\n@@ -4542,7 +4531,7 @@ Flow(.logical_datapath = sw._uuid,\n * Priority: 80.\n */\n function get_arp_forward_ips(rp: Intern<RouterPort>):\n- (Set<string>, Set<string>, Set<string>, Set<string>) =\n+ (Set<istring>, Set<istring>, Set<istring>, Set<istring>) =\n {\n var reachable_ips_v4 = set_empty();\n var reachable_ips_v6 = set_empty();\n@@ -4555,7 +4544,7 @@ function get_arp_forward_ips(rp: Intern<RouterPort>):\n /* Check if the ovn port has a network configured on which we could\n * expect ARP requests for the LB VIP.\n */\n- match (ip_parse(a)) {\n+ match (ip_parse(a.ival())) {\n Some{ipv4} -> if (lrouter_port_ip_reachable(rp, IPv4{ipv4})) {\n reachable_ips_v4.insert(a)\n } else {\n@@ -4568,7 +4557,7 @@ function get_arp_forward_ips(rp: Intern<RouterPort>):\n /* Check if the ovn port has a network configured on which we could\n * expect NS requests for the LB VIP.\n */\n- match (ipv6_parse(a)) {\n+ match (ipv6_parse(a.ival())) {\n Some{ipv6} -> if (lrouter_port_ip_reachable(rp, IPv6{ipv6})) {\n reachable_ips_v6.insert(a)\n } else {\n@@ -4579,7 +4568,7 @@ function get_arp_forward_ips(rp: Intern<RouterPort>):\n };\n \n for (nat in rp.router.nats) {\n- if (nat.nat.__type != \"snat\") {\n+ if (nat.nat.__type != i\"snat\") {\n /* Check if the ovn port has a network configured on which we could\n * expect ARP requests/NS for the DNAT external_ip.\n */\n@@ -4598,10 +4587,10 @@ function get_arp_forward_ips(rp: Intern<RouterPort>):\n };\n \n for (a in rp.networks.ipv4_addrs) {\n- reachable_ips_v4.insert(\"${a.addr}\")\n+ reachable_ips_v4.insert(i\"${a.addr}\")\n };\n for (a in rp.networks.ipv6_addrs) {\n- reachable_ips_v6.insert(\"${a.addr}\")\n+ reachable_ips_v6.insert(i\"${a.addr}\")\n };\n \n (reachable_ips_v4, reachable_ips_v6, unreachable_ips_v4, unreachable_ips_v6)\n@@ -4609,10 +4598,10 @@ function get_arp_forward_ips(rp: Intern<RouterPort>):\n \n relation &SwitchPortARPForwards(\n port: Intern<SwitchPort>,\n- reachable_ips_v4: Set<string>,\n- reachable_ips_v6: Set<string>,\n- unreachable_ips_v4: Set<string>,\n- unreachable_ips_v6: Set<string>\n+ reachable_ips_v4: Set<istring>,\n+ reachable_ips_v6: Set<istring>,\n+ unreachable_ips_v4: Set<istring>,\n+ unreachable_ips_v6: Set<istring>\n )\n \n &SwitchPortARPForwards(.port = port,\n@@ -4647,7 +4636,7 @@ Flow(.logical_datapath = sw._uuid,\n rp.is_enabled(),\n &SwitchPortARPForwards(.port = sp, .reachable_ips_v4 = ips_v4),\n var ipv4 = FlatMap(ips_v4),\n- var mc_flood_l2 = json_string_escape(mC_FLOOD_L2().0).\n+ var mc_flood_l2 = json_escape(mC_FLOOD_L2().0).\n Flow(.logical_datapath = sw._uuid,\n .stage = s_SWITCH_IN_L2_LKUP(),\n .priority = 80,\n@@ -4665,7 +4654,7 @@ Flow(.logical_datapath = sw._uuid,\n rp.is_enabled(),\n &SwitchPortARPForwards(.port = sp, .reachable_ips_v6 = ips_v6),\n var ipv6 = FlatMap(ips_v6),\n- var mc_flood_l2 = json_string_escape(mC_FLOOD_L2().0).\n+ var mc_flood_l2 = json_escape(mC_FLOOD_L2().0).\n \n Flow(.logical_datapath = sw._uuid,\n .stage = s_SWITCH_IN_L2_LKUP(),\n@@ -4679,7 +4668,7 @@ Flow(.logical_datapath = sw._uuid,\n rp.is_enabled(),\n &SwitchPortARPForwards(.port = sp, .unreachable_ips_v4 = ips_v4),\n var ipv4 = FlatMap(ips_v4),\n- var flood = json_string_escape(mC_FLOOD().0).\n+ var flood = json_escape(mC_FLOOD().0).\n \n Flow(.logical_datapath = sw._uuid,\n .stage = s_SWITCH_IN_L2_LKUP(),\n@@ -4693,11 +4682,11 @@ Flow(.logical_datapath = sw._uuid,\n rp.is_enabled(),\n &SwitchPortARPForwards(.port = sp, .unreachable_ips_v6 = ips_v6),\n var ipv6 = FlatMap(ips_v6),\n- var flood = json_string_escape(mC_FLOOD().0).\n+ var flood = json_escape(mC_FLOOD().0).\n \n for (SwitchPortNewDynamicAddress(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = sw},\n .address = Some{addrs})\n- if lsp.__type != \"external\") {\n+ if lsp.__type != i\"external\") {\n Flow(.logical_datapath = sw._uuid,\n .stage = s_SWITCH_IN_L2_LKUP(),\n .priority = 50,\n@@ -4715,9 +4704,9 @@ for (&SwitchPort(.lsp = lsp,\n .is_redirect = is_redirect,\n .router = &Router{._uuid = lr_uuid,\n .l3dgw_ports = l3dgw_ports}}})\n- if (lsp.addresses.contains(\"router\") and lsp.__type != \"external\"))\n+ if (lsp.addresses.contains(i\"router\") and lsp.__type != i\"external\"))\n {\n- Some{var mac} = scan_eth_addr(lrp.mac) in {\n+ Some{var mac} = scan_eth_addr(lrp.mac.ival()) in {\n var add_chassis_resident_check =\n not sw.localnet_ports.is_empty() and\n (/* The peer of this port represents a distributed\n@@ -4732,13 +4721,13 @@ for (&SwitchPort(.lsp = lsp,\n * this logical switch should be run on the chassis\n * hosting the gateway port.\n */\n- lrp.options.get_bool_def(\"reside-on-redirect-chassis\", false)) in\n+ lrp.options.get_bool_def(i\"reside-on-redirect-chassis\", false)) in\n var __match = if (add_chassis_resident_check) {\n var redirect_port_name = if (is_redirect) {\n- json_string_escape(chassis_redirect_name(lrp.name))\n+ json_escape(chassis_redirect_name(lrp.name))\n } else {\n match (l3dgw_ports.nth(0)) {\n- Some {var gw_port} -> json_string_escape(chassis_redirect_name(gw_port.name)),\n+ Some {var gw_port} -> json_escape(chassis_redirect_name(gw_port.name)),\n None -> \"\"\n }\n };\n@@ -4762,11 +4751,11 @@ for (&SwitchPort(.lsp = lsp,\n * distributed logical routers. */\n if (is_redirect) {\n for (LogicalRouterNAT(.lr = lr_uuid, .nat = nat)) {\n- if (nat.nat.__type == \"dnat_and_snat\") {\n+ if (nat.nat.__type == i\"dnat_and_snat\") {\n Some{var lport} = nat.nat.logical_port in\n Some{var emac} = nat.nat.external_mac in\n- Some{var nat_mac} = eth_addr_from_string(emac) in\n- var __match = i\"eth.dst == ${nat_mac} && is_chassis_resident(${json_string_escape(lport)})\" in\n+ Some{var nat_mac} = eth_addr_from_string(emac.ival()) in\n+ var __match = i\"eth.dst == ${nat_mac} && is_chassis_resident(${json_escape(lport)})\" in\n Flow(.logical_datapath = sw._uuid,\n .stage = s_SWITCH_IN_L2_LKUP(),\n .priority = 50,\n@@ -4805,7 +4794,7 @@ for (sw in &Switch(._uuid = ls_uuid)) {\n .priority = 50,\n .__match = i\"outport == \\\"none\\\"\",\n .actions = if (sw.has_unknown_ports) {\n- var mc_unknown = json_string_escape(mC_UNKNOWN().0);\n+ var mc_unknown = json_escape(mC_UNKNOWN().0);\n i\"outport = ${mc_unknown}; output;\"\n } else {\n i\"drop;\"\n@@ -4862,7 +4851,7 @@ Flow(.logical_datapath = ls_uuid,\n .io_port = Some{sp.lsp.name},\n .controller_meter = None) :-\n LogicalSwitchPortWithUnknownAddress(ls_uuid, lsp_uuid),\n- sp in &SwitchPort(.lsp = &nb::Logical_Switch_Port{._uuid = lsp_uuid, .__type = \"\"},\n+ sp in &SwitchPort(.lsp = &nb::Logical_Switch_Port{._uuid = lsp_uuid, .__type = i\"\"},\n .ps_addresses = vec_empty()).\n \n Flow(.logical_datapath = ls_uuid,\n@@ -4902,21 +4891,21 @@ Flow(.logical_datapath = sw._uuid,\n .controller_meter = None) :-\n &SwitchPort(.sw = sw, .lsp = lsp, .json_name = json_name, .ps_eth_addresses = ps_eth_addresses),\n lsp.is_enabled(),\n- lsp.__type != \"external\",\n+ lsp.__type != i\"external\",\n var __match = if (ps_eth_addresses.is_empty()) {\n i\"outport == ${json_name}\"\n } else {\n i\"outport == ${json_name} && eth.dst == {${ps_eth_addresses.join(\\\" \\\")}}\"\n },\n pbinding in sb::Out_Port_Binding(.logical_port = lsp.name),\n- var queue_action = match ((lsp.__type,\n- pbinding.options.get(\"qdisc_queue_id\"))) {\n+ var queue_action = match ((lsp.__type.ival(),\n+ pbinding.options.get(i\"qdisc_queue_id\"))) {\n (\"localnet\", Some{queue_id}) -> \"set_queue(${queue_id});\",\n _ -> \"\"\n }.\n \n for (&SwitchPort(.lsp = lsp, .json_name = json_name, .sw = sw)) {\n- if (not lsp.is_enabled() and lsp.__type != \"external\") {\n+ if (not lsp.is_enabled() and lsp.__type != i\"external\") {\n Flow(.logical_datapath = sw._uuid,\n .stage = s_SWITCH_OUT_PORT_SEC_L2(),\n .priority = 150,\n@@ -4931,7 +4920,7 @@ for (&SwitchPort(.lsp = lsp, .json_name = json_name, .sw = sw)) {\n for (SwitchPortPSAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = sw},\n .ps_addrs = ps)\n if (ps.ipv4_addrs.len() > 0 or ps.ipv6_addrs.len() > 0)\n- and lsp.__type != \"external\")\n+ and lsp.__type != i\"external\")\n {\n if (ps.ipv4_addrs.len() > 0) {\n var addrs = {\n@@ -5018,7 +5007,7 @@ for (&RouterPort(.lrp = lrp,\n * This will save us from having to match on inport further down in\n * the pipeline.\n */\n- var gw_mtu = lrp.options.get_int_def(\"gateway_mtu\", 0) in\n+ var gw_mtu = lrp.options.get_int_def(i\"gateway_mtu\", 0) in\n var mtu = gw_mtu + vLAN_ETH_HEADER_LEN() in\n var actions = if (gw_mtu > 0) {\n \"${rEGBIT_PKT_LARGER()} = check_pkt_larger(${mtu}); \"\n@@ -5039,7 +5028,7 @@ for (&RouterPort(.lrp = lrp,\n if is_redirect {\n /* Traffic with eth.dst = l3dgw_port->lrp_networks.ea\n * should only be received on the \"redirect-chassis\". */\n- \" && is_chassis_resident(${json_string_escape(chassis_redirect_name(lrp.name))})\"\n+ \" && is_chassis_resident(${json_escape(chassis_redirect_name(lrp.name))})\"\n } else { \"\" } in\n Flow(.logical_datapath = router._uuid,\n .stage = s_ROUTER_IN_ADMISSION(),\n@@ -5183,7 +5172,7 @@ var rLNIR = rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() in\n /* Check if we need to learn mac-binding from ARP requests. */\n for (RouterPortNetworksIPv4Addr(rp@&RouterPort{.router = router}, addr)) {\n var chassis_residence = match (rp.is_redirect) {\n- true -> \" && is_chassis_resident(${json_string_escape(chassis_redirect_name(rp.lrp.name))})\",\n+ true -> \" && is_chassis_resident(${json_escape(chassis_redirect_name(rp.lrp.name))})\",\n false -> \"\"\n } in\n var rLNR = rEGBIT_LOOKUP_NEIGHBOR_RESULT() in\n@@ -5381,7 +5370,7 @@ AddChassisResidentCheck_(lrp._uuid, res) :-\n * hosting the gateway port and it should reply to the\n * ARP requests for the router port IPs.\n */\n- lrp.options.get_bool_def(\"reside-on-redirect-chassis\", false)\n+ lrp.options.get_bool_def(i\"reside-on-redirect-chassis\", false)\n }.\n \n \n@@ -5450,7 +5439,7 @@ LogicalRouterNatArpNdFlow(router, nat) :-\n /* Skip SNAT entries for now, we handle unique SNAT IPs separately\n * below.\n */\n- __type != \"snat\".\n+ __type != i\"snat\".\n /* Now handle SNAT entries too, one per unique SNAT IP. */\n LogicalRouterNatArpNdFlow(router, nat) :-\n router in &Router(.snat_ips = snat_ips),\n@@ -5478,7 +5467,7 @@ LogicalRouterPortNatArpNdFlow(router, nat, l3dgw_port) :-\n /* Skip SNAT entries for now, we handle unique SNAT IPs separately\n * below.\n */\n- nat.nat.__type != \"snat\".\n+ nat.nat.__type != i\"snat\".\n /* Now handle SNAT entries too, one per unique SNAT IP. */\n LogicalRouterPortNatArpNdFlow(router, nat, l3dgw_port) :-\n router in &Router(.l3dgw_ports = l3dgw_ports, .snat_ips = snat_ips),\n@@ -5497,13 +5486,13 @@ LogicalRouterArpNdFlow(router, nat, Some{lrp}, mac, None, true, 91) :-\n (var mac, var extra_match) = match ((nat.external_mac, nat.nat.logical_port)) {\n (Some{external_mac}, Some{logical_port}) -> (\n /* distributed NAT case, use nat->external_mac */\n- external_mac.to_string(),\n+ external_mac.to_string().intern(),\n /* Traffic with eth.src = nat->external_mac should only be\n * sent from the chassis where nat->logical_port is\n * resident, so that upstream MAC learning points to the\n * correct chassis. Also need to avoid generation of\n * multiple ARP responses from different chassis. */\n- \"is_chassis_resident(${json_string_escape(logical_port)})\"\n+ i\"is_chassis_resident(${json_escape(logical_port)})\"\n ),\n _ -> (\n rEG_INPORT_ETH_ADDR(),\n@@ -5513,8 +5502,8 @@ LogicalRouterArpNdFlow(router, nat, Some{lrp}, mac, None, true, 91) :-\n * Also need to avoid generation of multiple ARP responses\n * from different chassis. */\n match (router.l3dgw_ports.nth(0)) {\n- None -> \"\",\n- Some {var gw_port} -> \"is_chassis_resident(${json_string_escape(chassis_redirect_name(gw_port.name))})\"\n+ None -> i\"\",\n+ Some {var gw_port} -> i\"is_chassis_resident(${json_escape(chassis_redirect_name(gw_port.name))})\"\n }\n )\n }.\n@@ -5524,15 +5513,15 @@ relation LogicalRouterArpNdFlow(\n router: Intern<Router>,\n nat: NAT,\n lrp: Option<Intern<nb::Logical_Router_Port>>,\n- mac: string,\n- extra_match: Option<string>,\n+ mac: istring,\n+ extra_match: Option<istring>,\n drop: bool,\n priority: integer)\n-LogicalRouterArpFlow(router, lrp, \"${ipv4}\", mac, extra_match, drop, priority,\n+LogicalRouterArpFlow(router, lrp, i\"${ipv4}\", mac, extra_match, drop, priority,\n stage_hint(nat.nat._uuid)) :-\n LogicalRouterArpNdFlow(router, nat@NAT{.external_ip = IPv4{ipv4}}, lrp,\n mac, extra_match, drop, priority).\n-LogicalRouterNdFlow(router, lrp, \"nd_na\", ipv6, true, mac, extra_match, drop, priority,\n+LogicalRouterNdFlow(router, lrp, i\"nd_na\", ipv6, true, mac, extra_match, drop, priority,\n stage_hint(nat.nat._uuid)) :-\n LogicalRouterArpNdFlow(router, nat@NAT{.external_ip = IPv6{ipv6}}, lrp,\n mac, extra_match, drop, priority).\n@@ -5540,9 +5529,9 @@ LogicalRouterNdFlow(router, lrp, \"nd_na\", ipv6, true, mac, extra_match, drop, pr\n relation LogicalRouterArpFlow(\n lr: Intern<Router>,\n lrp: Option<Intern<nb::Logical_Router_Port>>,\n- ip: string,\n- mac: string,\n- extra_match: Option<string>,\n+ ip: istring,\n+ mac: istring,\n+ extra_match: Option<istring>,\n drop: bool,\n priority: integer,\n stage_hint: bit<32>)\n@@ -5560,10 +5549,10 @@ Flow(.logical_datapath = lr._uuid,\n var __match = {\n var clauses = vec_with_capacity(3);\n match (lrp) {\n- Some{p} -> clauses.push(\"inport == ${json_string_escape(p.name)}\"),\n+ Some{p} -> clauses.push(i\"inport == ${json_escape(p.name)}\"),\n None -> ()\n };\n- clauses.push(\"arp.op == 1 && arp.tpa == ${ip}\");\n+ clauses.push(i\"arp.op == 1 && arp.tpa == ${ip}\");\n clauses.append(extra_match.to_vec());\n clauses.join(\" && \")\n },\n@@ -5584,11 +5573,11 @@ Flow(.logical_datapath = lr._uuid,\n relation LogicalRouterNdFlow(\n lr: Intern<Router>,\n lrp: Option<Intern<nb::Logical_Router_Port>>,\n- action: string,\n+ action: istring,\n ip: in6_addr,\n sn_ip: bool,\n- mac: string,\n- extra_match: Option<string>,\n+ mac: istring,\n+ extra_match: Option<istring>,\n drop: bool,\n priority: integer,\n stage_hint: bit<32>)\n@@ -5607,13 +5596,13 @@ Flow(.logical_datapath = lr._uuid,\n var __match = {\n var clauses = vec_with_capacity(4);\n match (lrp) {\n- Some{p} -> clauses.push(\"inport == ${json_string_escape(p.name)}\"),\n+ Some{p} -> clauses.push(i\"inport == ${json_escape(p.name)}\"),\n None -> ()\n };\n if (sn_ip) {\n- clauses.push(\"ip6.dst == {${ip}, ${ip.solicited_node()}}\")\n+ clauses.push(i\"ip6.dst == {${ip}, ${ip.solicited_node()}}\")\n };\n- clauses.push(\"nd_ns && nd.target == ${ip}\");\n+ clauses.push(i\"nd_ns && nd.target == ${ip}\");\n clauses.append(extra_match.to_vec());\n clauses.join(\" && \")\n },\n@@ -5664,20 +5653,20 @@ for (RouterPortNetworksIPv4Addr(.port = &RouterPort{.lrp = lrp,\n \"arp.spa == ${addr.match_network()}\" ++\n if (add_chassis_resident_check) {\n var redirect_port_name = if (is_redirect) {\n- json_string_escape(chassis_redirect_name(lrp.name))\n+ json_escape(chassis_redirect_name(lrp.name))\n } else {\n match (router.l3dgw_ports.nth(0)) {\n None -> \"\",\n- Some {var gw_port} -> json_string_escape(chassis_redirect_name(gw_port.name))\n+ Some {var gw_port} -> json_escape(chassis_redirect_name(gw_port.name))\n }\n };\n \" && is_chassis_resident(${redirect_port_name})\"\n } else \"\" in\n LogicalRouterArpFlow(.lr = router,\n .lrp = Some{lrp},\n- .ip = \"${addr.addr}\",\n+ .ip = i\"${addr.addr}\",\n .mac = rEG_INPORT_ETH_ADDR(),\n- .extra_match = Some{__match},\n+ .extra_match = Some{__match.intern()},\n .drop = false,\n .priority = 90,\n .stage_hint = stage_hint(lrp._uuid))\n@@ -5690,14 +5679,14 @@ for (&RouterPort(.lrp = lrp,\n .networks = networks,\n .is_redirect = is_redirect))\n var residence_check = match (is_redirect) {\n- true -> Some{\"is_chassis_resident(${json_string_escape(chassis_redirect_name(lrp.name))})\"},\n+ true -> Some{i\"is_chassis_resident(${json_escape(chassis_redirect_name(lrp.name))})\"},\n false -> None\n } in {\n (var all_ips_v4, _) = get_router_load_balancer_ips(router, false) in {\n if (not all_ips_v4.is_empty()) {\n LogicalRouterArpFlow(.lr = router,\n .lrp = Some{lrp},\n- .ip = \"{ \" ++ all_ips_v4.join(\", \") ++ \" }\",\n+ .ip = i\"{ ${all_ips_v4.map(ival).to_vec().join(\\\", \\\")} }\",\n .mac = rEG_INPORT_ETH_ADDR(),\n .extra_match = residence_check,\n .drop = false,\n@@ -5706,11 +5695,11 @@ var residence_check = match (is_redirect) {\n }\n };\n for (RouterLBVIP(.router = &Router{._uuid= lr_uuid}, .vip = vip)) {\n- Some{(var ip_address, _)} = ip_address_and_port_from_lb_key(vip) in {\n+ Some{(var ip_address, _)} = ip_address_and_port_from_lb_key(vip.ival()) in {\n IPv6{var ipv6} = ip_address in\n LogicalRouterNdFlow(.lr = router,\n .lrp = Some{lrp},\n- .action = \"nd_na\",\n+ .action = i\"nd_na\",\n .ip = ipv6,\n .sn_ip = false,\n .mac = rEG_INPORT_ETH_ADDR(),\n@@ -5887,11 +5876,11 @@ for (RouterPortNetworksIPv6Addr(.port = &RouterPort{.lrp = lrp,\n * upstream MAC learning points to the gateway chassis.\n * Also need to avoid generation of multiple ND replies\n * from different chassis. */\n- Some{\"is_chassis_resident(${json_string_escape(chassis_redirect_name(lrp.name))})\"}\n+ Some{i\"is_chassis_resident(${json_escape(chassis_redirect_name(lrp.name))})\"}\n } else None in\n LogicalRouterNdFlow(.lr = router,\n .lrp = Some{lrp},\n- .action = \"nd_na_router\",\n+ .action = i\"nd_na_router\",\n .ip = addr.addr,\n .sn_ip = true,\n .mac = rEG_INPORT_ETH_ADDR(),\n@@ -6078,11 +6067,11 @@ Flow(.logical_datapath = lr,\n .io_port = None,\n .controller_meter = None) :-\n LogicalRouterLB(lr, lb),\n- lb.options.get_bool_def(\"skip_snat\", false)\n+ lb.options.get_bool_def(i\"skip_snat\", false)\n .\n \n function lrouter_nat_is_stateless(nat: NAT): bool = {\n- Some{\"true\"} == nat.nat.options.get(\"stateless\")\n+ Some{i\"true\"} == nat.nat.options.get(i\"stateless\")\n }\n \n /* Handles the match criteria and actions in logical flow\n@@ -6240,9 +6229,9 @@ for (rp in &RouterPort(.router = &Router{._uuid = lr_uuid, .options = lr_options\n }\n }\n \n-relation VirtualLogicalPort(logical_port: Option<string>)\n+relation VirtualLogicalPort(logical_port: Option<istring>)\n VirtualLogicalPort(Some{logical_port}) :-\n- lsp in &nb::Logical_Switch_Port(.name = logical_port, .__type = \"virtual\").\n+ lsp in &nb::Logical_Switch_Port(.name = logical_port, .__type = i\"virtual\").\n \n /* NAT rules are only valid on Gateway routers and routers with\n * l3dgw_port (router has a port with \"redirect-chassis\"\n@@ -6257,8 +6246,8 @@ for (r in &Router(._uuid = lr_uuid,\n var xx = nat.external_ip.xxreg() in\n /* Check the validity of nat->logical_ip. 'logical_ip' can\n * be a subnet when the type is \"snat\". */\n- Some{(_, var mask)} = ip46_parse_masked(nat.nat.logical_ip) in\n- true == match ((mask.is_all_ones(), nat.nat.__type)) {\n+ Some{(_, var mask)} = ip46_parse_masked(nat.nat.logical_ip.ival()) in\n+ true == match ((mask.is_all_ones(), nat.nat.__type.ival())) {\n (_, \"snat\") -> true,\n (false, _) -> {\n warn(\"bad ip ${nat.nat.logical_ip} for dnat in router ${uuid2str(lr_uuid)}\");\n@@ -6268,13 +6257,13 @@ for (r in &Router(._uuid = lr_uuid,\n } in\n /* For distributed router NAT, determine whether this NAT rule\n * satisfies the conditions for distributed NAT processing. */\n- var mac = match ((not l3dgw_ports.is_empty() and nat.nat.__type == \"dnat_and_snat\",\n+ var mac = match ((not l3dgw_ports.is_empty() and nat.nat.__type == i\"dnat_and_snat\",\n nat.nat.logical_port, nat.external_mac)) {\n (true, Some{_}, Some{mac}) -> Some{mac},\n _ -> None\n } in\n var stateless = (lrouter_nat_is_stateless(nat)\n- and nat.nat.__type == \"dnat_and_snat\") in\n+ and nat.nat.__type == i\"dnat_and_snat\") in\n {\n /* Ingress UNSNAT table: It is for already established connections'\n * reverse traffic. i.e., SNAT has already been done in egress\n@@ -6285,7 +6274,7 @@ for (r in &Router(._uuid = lr_uuid,\n * because when the packet was DNATed in ingress pipeline, it did\n * not know about the possibility of eventual additional SNAT in\n * egress pipeline. */\n- if (nat.nat.__type == \"snat\" or nat.nat.__type == \"dnat_and_snat\") {\n+ if (nat.nat.__type == i\"snat\" or nat.nat.__type == i\"dnat_and_snat\") {\n if (l3dgw_ports.is_empty()) {\n /* Gateway router. */\n var actions = if (stateless) {\n@@ -6308,11 +6297,11 @@ for (r in &Router(._uuid = lr_uuid,\n /* Traffic received on l3dgw_port is subject to NAT. */\n var __match =\n \"ip && ${ipX}.dst == ${nat.nat.external_ip}\"\n- \" && inport == ${json_string_escape(gwport.name)}\" ++\n+ \" && inport == ${json_escape(gwport.name)}\" ++\n if (mac == None) {\n /* Flows for NAT rules that are centralized are only\n * programmed on the \"redirect-chassis\". */\n- \" && is_chassis_resident(${json_string_escape(chassis_redirect_name(gwport.name))})\"\n+ \" && is_chassis_resident(${json_escape(chassis_redirect_name(gwport.name))})\"\n } else { \"\" } in\n var actions = if (stateless) {\n i\"${ipX}.dst=${nat.nat.logical_ip}; next;\"\n@@ -6334,12 +6323,12 @@ for (r in &Router(._uuid = lr_uuid,\n * IP address that needs to be DNATted from a external IP address\n * to a logical IP address. */\n var ip_and_ports = \"${nat.nat.logical_ip}\" ++\n- if (nat.nat.external_port_range != \"\") {\n+ if (nat.nat.external_port_range != i\"\") {\n \" ${nat.nat.external_port_range}\"\n } else {\n \"\"\n } in\n- if (nat.nat.__type == \"dnat\" or nat.nat.__type == \"dnat_and_snat\") {\n+ if (nat.nat.__type == i\"dnat\" or nat.nat.__type == i\"dnat_and_snat\") {\n l3dgw_ports.is_empty() in\n var __match = \"ip && ${ipX}.dst == ${nat.nat.external_ip}\" in\n (var ext_ip_match, var ext_flow) = lrouter_nat_add_ext_ip_match(\n@@ -6352,7 +6341,7 @@ for (r in &Router(._uuid = lr_uuid,\n Some{var f} = ext_flow in Flow[f];\n \n var flag_action =\n- if (has_force_snat_ip(r.options, \"dnat\")) {\n+ if (has_force_snat_ip(r.options, i\"dnat\")) {\n /* Indicate to the future tables that a DNAT has taken\n * place and a force SNAT needs to be done in the\n * Egress SNAT table. */\n@@ -6377,11 +6366,11 @@ for (r in &Router(._uuid = lr_uuid,\n Some {var gwport} = l3dgw_ports.nth(0) in\n var __match =\n \"ip && ${ipX}.dst == ${nat.nat.external_ip}\"\n- \" && inport == ${json_string_escape(gwport.name)}\" ++\n+ \" && inport == ${json_escape(gwport.name)}\" ++\n if (mac == None) {\n /* Flows for NAT rules that are centralized are only\n * programmed on the \"redirect-chassis\". */\n- \" && is_chassis_resident(${json_string_escape(chassis_redirect_name(gwport.name))})\"\n+ \" && is_chassis_resident(${json_escape(chassis_redirect_name(gwport.name))})\"\n } else { \"\" } in\n (var ext_ip_match, var ext_flow) = lrouter_nat_add_ext_ip_match(\n r, nat, __match, ipX, true, mask) in\n@@ -6408,8 +6397,8 @@ for (r in &Router(._uuid = lr_uuid,\n \n /* ARP resolve for NAT IPs. */\n Some {var gwport} = l3dgw_ports.nth(0) in {\n- var gwport_name = json_string_escape(gwport.name) in {\n- if (nat.nat.__type == \"snat\") {\n+ var gwport_name = json_escape(gwport.name) in {\n+ if (nat.nat.__type == i\"snat\") {\n var __match = i\"inport == ${gwport_name} && \"\n \"${ipX}.src == ${nat.nat.external_ip}\" in\n Flow(.logical_datapath = lr_uuid,\n@@ -6426,7 +6415,7 @@ for (r in &Router(._uuid = lr_uuid,\n var __match = i\"outport == ${gwport_name} && \"\n \"${nexthop_reg} == ${nat.nat.external_ip}\" in\n var dst_mac = match (mac) {\n- Some{value} -> \"${value}\",\n+ Some{value} -> i\"${value}\",\n None -> gwport.mac\n } in\n Flow(.logical_datapath = lr_uuid,\n@@ -6447,15 +6436,15 @@ for (r in &Router(._uuid = lr_uuid,\n *\n * Note that this only applies for NAT on a distributed router.\n */\n- if ((nat.nat.__type == \"dnat\" or nat.nat.__type == \"dnat_and_snat\")) {\n+ if ((nat.nat.__type == i\"dnat\" or nat.nat.__type == i\"dnat_and_snat\")) {\n Some {var gwport} = l3dgw_ports.nth(0) in\n var __match =\n \"ip && ${ipX}.src == ${nat.nat.logical_ip}\"\n- \" && outport == ${json_string_escape(gwport.name)}\" ++\n+ \" && outport == ${json_escape(gwport.name)}\" ++\n if (mac == None) {\n /* Flows for NAT rules that are centralized are only\n * programmed on the \"redirect-chassis\". */\n- \" && is_chassis_resident(${json_string_escape(chassis_redirect_name(gwport.name))})\"\n+ \" && is_chassis_resident(${json_escape(chassis_redirect_name(gwport.name))})\"\n } else { \"\" } in\n var actions =\n match (mac) {\n@@ -6481,12 +6470,12 @@ for (r in &Router(._uuid = lr_uuid,\n * source ip address that needs to be SNATted to a external ip\n * address. */\n var ip_and_ports = \"${nat.nat.external_ip}\" ++\n- if (nat.nat.external_port_range != \"\") {\n+ if (nat.nat.external_port_range != i\"\") {\n \" ${nat.nat.external_port_range}\"\n } else {\n \"\"\n } in\n- if (nat.nat.__type == \"snat\" or nat.nat.__type == \"dnat_and_snat\") {\n+ if (nat.nat.__type == i\"snat\" or nat.nat.__type == i\"dnat_and_snat\") {\n l3dgw_ports.is_empty() in\n var __match = \"ip && ${ipX}.src == ${nat.nat.logical_ip}\" in\n (var ext_ip_match, var ext_flow) = lrouter_nat_add_ext_ip_match(\n@@ -6517,11 +6506,11 @@ for (r in &Router(._uuid = lr_uuid,\n Some {var gwport} = l3dgw_ports.nth(0) in\n var __match =\n \"ip && ${ipX}.src == ${nat.nat.logical_ip}\"\n- \" && outport == ${json_string_escape(gwport.name)}\" ++\n+ \" && outport == ${json_escape(gwport.name)}\" ++\n if (mac == None) {\n /* Flows for NAT rules that are centralized are only\n * programmed on the \"redirect-chassis\". */\n- \" && is_chassis_resident(${json_string_escape(chassis_redirect_name(gwport.name))})\"\n+ \" && is_chassis_resident(${json_escape(chassis_redirect_name(gwport.name))})\"\n } else { \"\" } in\n (var ext_ip_match, var ext_flow) = lrouter_nat_add_ext_ip_match(\n r, nat, __match, ipX, false, mask) in\n@@ -6564,8 +6553,8 @@ for (r in &Router(._uuid = lr_uuid,\n Some{var gwport} = l3dgw_ports.nth(0) in\n Some{var logical_port} = nat.nat.logical_port in\n var __match =\n- i\"eth.dst == ${mac_addr} && inport == ${json_string_escape(gwport.name)}\"\n- \" && is_chassis_resident(${json_string_escape(logical_port)})\" in\n+ i\"eth.dst == ${mac_addr} && inport == ${json_escape(gwport.name)}\"\n+ \" && is_chassis_resident(${json_escape(logical_port)})\" in\n /* Store the ethernet address of the port receiving the packet.\n * This will save us from having to match on inport further\n * down in the pipeline.\n@@ -6594,8 +6583,8 @@ for (r in &Router(._uuid = lr_uuid,\n Some{var external_mac} = nat.nat.external_mac in\n var __match =\n i\"${ipX}.src == ${nat.nat.logical_ip} && \"\n- \"outport == ${json_string_escape(gwport.name)} && \"\n- \"is_chassis_resident(${json_string_escape(logical_port)})\" in\n+ \"outport == ${json_escape(gwport.name)} && \"\n+ \"is_chassis_resident(${json_escape(logical_port)})\" in\n var actions =\n i\"eth.src = ${external_mac}; \"\n \"${xx}${rEG_SRC()} = ${nat.nat.external_ip}; \"\n@@ -6615,7 +6604,7 @@ for (r in &Router(._uuid = lr_uuid,\n .stage = s_ROUTER_IN_GW_REDIRECT(),\n .priority = 80,\n .__match = i\"${ipX}.src == ${nat.nat.logical_ip} && \"\n- \"outport == ${json_string_escape(gwport.name)}\",\n+ \"outport == ${json_escape(gwport.name)}\",\n .actions = i\"drop;\",\n .stage_hint = stage_hint(nat.nat._uuid),\n .io_port = None,\n@@ -6631,12 +6620,12 @@ for (r in &Router(._uuid = lr_uuid,\n /* Distributed router. */\n Some{var port} = match (mac) {\n Some{_} -> match (nat.nat.logical_port) {\n- Some{name} -> Some{json_string_escape(name)},\n+ Some{name} -> Some{json_escape(name)},\n None -> None: Option<string>\n },\n- None -> Some{json_string_escape(chassis_redirect_name(gwport.name))}\n+ None -> Some{json_escape(chassis_redirect_name(gwport.name))}\n } in\n- var __match = i\"${ipX}.dst == ${nat.nat.external_ip} && outport == ${json_string_escape(gwport.name)} && is_chassis_resident(${port})\" in\n+ var __match = i\"${ipX}.dst == ${nat.nat.external_ip} && outport == ${json_escape(gwport.name)} && is_chassis_resident(${port})\" in\n var regs = {\n var regs = vec_empty();\n for (j in range_vec(0, mFF_N_LOG_REGS(), 01)) {\n@@ -6665,13 +6654,13 @@ for (r in &Router(._uuid = lr_uuid,\n \n /* Handle force SNAT options set in the gateway router. */\n if (l3dgw_ports.is_empty()) {\n- var dnat_force_snat_ips = get_force_snat_ip(r.options, \"dnat\") in\n+ var dnat_force_snat_ips = get_force_snat_ip(r.options, i\"dnat\") in\n if (not dnat_force_snat_ips.is_empty())\n LogicalRouterForceSnatFlows(.logical_router = lr_uuid,\n .ips = dnat_force_snat_ips,\n .context = \"dnat\");\n \n- var lb_force_snat_ips = get_force_snat_ip(r.options, \"lb\") in\n+ var lb_force_snat_ips = get_force_snat_ip(r.options, i\"lb\") in\n if (not lb_force_snat_ips.is_empty())\n LogicalRouterForceSnatFlows(.logical_router = lr_uuid,\n .ips = lb_force_snat_ips,\n@@ -6700,7 +6689,7 @@ for (RouterLBVIP(\n .backends = backends)\n if not l3dgw_ports.is_empty() or is_gateway)\n {\n- if (backends == \"\" and not lb.options.get_bool_def(\"reject\", false)) {\n+ if (backends == i\"\" and not lb.options.get_bool_def(i\"reject\", false)) {\n for (LoadBalancerEmptyEvents(lb)) {\n Some {(var __match, var __action)} =\n build_empty_lb_event_flow(vip, lb) in\n@@ -6718,11 +6707,11 @@ for (RouterLBVIP(\n /* A set to hold all ips that need defragmentation and tracking. */\n \n /* vip contains IP:port or just IP. */\n- Some{(var ip_address, var port)} = ip_address_and_port_from_lb_key(vip) in\n+ Some{(var ip_address, var port)} = ip_address_and_port_from_lb_key(vip.ival()) in\n var ipX = ip_address.ipX() in\n var proto = match (lb.protocol) {\n Some{proto} -> proto,\n- _ -> \"tcp\"\n+ _ -> i\"tcp\"\n } in {\n /* If there are any load balancing rules, we should send\n * the packet to conntrack for defragmentation and\n@@ -6776,15 +6765,15 @@ for (RouterLBVIP(\n (110, \"\")\n } in\n var __match = match1 ++ match2 ++\n- match ((l3dgw_ports.nth(0), backends != \"\" or lb.options.get_bool_def(\"reject\", false))) {\n- (Some{gw_port}, true) -> \" && is_chassis_resident(${json_string_escape(chassis_redirect_name(gw_port.name))})\",\n+ match ((l3dgw_ports.nth(0), backends != i\"\" or lb.options.get_bool_def(i\"reject\", false))) {\n+ (Some{gw_port}, true) -> \" && is_chassis_resident(${json_escape(chassis_redirect_name(gw_port.name))})\",\n _ -> \"\"\n } in\n var snat_for_lb = snat_for_lb(r.options, lb) in\n {\n /* A match and actions for established connections. */\n var est_match = \"ct.est && \" ++ match1 ++ match2 ++ \" && ct_label.natted == 1\" ++\n- match ((l3dgw_ports.nth(0), backends != \"\" or lb.options.get_bool_def(\"reject\", false))) {\n+ match ((l3dgw_ports.nth(0), backends != i\"\" or lb.options.get_bool_def(i\"reject\", false))) {\n (Some {var gw_port}, true) -> \" && is_chassis_resident(${json_string_escape(chassis_redirect_name(gw_port.name))})\",\n _ -> \"\"\n } in\n@@ -6835,7 +6824,7 @@ for (RouterLBVIP(\n */\n var conds = {\n var conds = vec_empty();\n- for (ip_str in string_split(backends, \",\")) {\n+ for (ip_str in backends.split(\",\")) {\n match (ip_address_and_port_from_lb_key(ip_str)) {\n None -> () /* FIXME: put a break here */,\n Some{(ip_address_, port_)} -> conds.push(\n@@ -6852,8 +6841,8 @@ for (RouterLBVIP(\n not conds.is_empty() in\n var undnat_match =\n \"${ip_address.ipX()} && (\" ++ conds.join(\" || \") ++\n- \") && outport == ${json_string_escape(gwport.name)} && \"\n- \"is_chassis_resident(${json_string_escape(chassis_redirect_name(gwport.name))})\" in\n+ \") && outport == ${json_escape(gwport.name)} && \"\n+ \"is_chassis_resident(${json_escape(chassis_redirect_name(gwport.name))})\" in\n var action =\n match (snat_for_lb) {\n SkipSNAT -> i\"flags.skip_snat_for_lb = 1; ct_dnat;\",\n@@ -6893,7 +6882,7 @@ Flow(.logical_datapath = r._uuid,\n = \"ct.new && \" ++\n get_match_for_lb_key(lbvip.vip_addr, lbvip.vip_port, lb.protocol, true, true, true) ++\n match (r.l3dgw_ports.nth(0)) {\n- Some{gw_port} -> \" && is_chassis_resident(${json_string_escape(chassis_redirect_name(gw_port.name))})\",\n+ Some{gw_port} -> \" && is_chassis_resident(${json_escape(chassis_redirect_name(gw_port.name))})\",\n _ -> \"\"\n },\n var priority = if (lbvip.vip_port != 0) 120 else 110,\n@@ -6925,64 +6914,64 @@ function nD_RA_MIN_INTERVAL_RANGE(max: integer): (integer, integer) = (3, ((max\n \n function nD_MTU_DEFAULT(): integer = 0\n \n-function copy_ra_to_sb(port: RouterPort, address_mode: string): Map<string, string> =\n+function copy_ra_to_sb(port: RouterPort, address_mode: istring): Map<istring, istring> =\n {\n var options = port.sb_options;\n \n- options.insert(\"ipv6_ra_send_periodic\", \"true\");\n- options.insert(\"ipv6_ra_address_mode\", address_mode);\n+ options.insert(i\"ipv6_ra_send_periodic\", i\"true\");\n+ options.insert(i\"ipv6_ra_address_mode\", address_mode);\n \n var max_interval = port.lrp.ipv6_ra_configs\n- .get_int_def(\"max_interval\", nD_RA_MAX_INTERVAL_DEFAULT())\n+ .get_int_def(i\"max_interval\", nD_RA_MAX_INTERVAL_DEFAULT())\n .clamp(nD_RA_MAX_INTERVAL_RANGE());\n- options.insert(\"ipv6_ra_max_interval\", \"${max_interval}\");\n+ options.insert(i\"ipv6_ra_max_interval\", i\"${max_interval}\");\n \n var min_interval = port.lrp.ipv6_ra_configs\n- .get_int_def(\"min_interval\", nd_ra_min_interval_default(max_interval))\n+ .get_int_def(i\"min_interval\", nd_ra_min_interval_default(max_interval))\n .clamp(nD_RA_MIN_INTERVAL_RANGE(max_interval));\n- options.insert(\"ipv6_ra_min_interval\", \"${min_interval}\");\n+ options.insert(i\"ipv6_ra_min_interval\", i\"${min_interval}\");\n \n- var mtu = port.lrp.ipv6_ra_configs.get_int_def(\"mtu\", nD_MTU_DEFAULT());\n+ var mtu = port.lrp.ipv6_ra_configs.get_int_def(i\"mtu\", nD_MTU_DEFAULT());\n \n /* RFC 2460 requires the MTU for IPv6 to be at least 1280 */\n if (mtu != 0 and mtu >= 1280) {\n- options.insert(\"ipv6_ra_mtu\", \"${mtu}\")\n+ options.insert(i\"ipv6_ra_mtu\", i\"${mtu}\")\n };\n \n var prefixes = vec_empty();\n for (addr in port.networks.ipv6_addrs) {\n if (addr.is_lla()) {\n- options.insert(\"ipv6_ra_src_addr\", \"${addr.addr}\")\n+ options.insert(i\"ipv6_ra_src_addr\", i\"${addr.addr}\")\n } else {\n prefixes.push(addr.match_network())\n }\n };\n- match (port.sb_options.get(\"ipv6_ra_pd_list\")) {\n- Some{value} -> prefixes.push(value),\n+ match (port.sb_options.get(i\"ipv6_ra_pd_list\")) {\n+ Some{value} -> prefixes.push(value.ival()),\n _ -> ()\n };\n- options.insert(\"ipv6_ra_prefixes\", prefixes.join(\" \"));\n+ options.insert(i\"ipv6_ra_prefixes\", prefixes.join(\" \").intern());\n \n- match (port.lrp.ipv6_ra_configs.get(\"rdnss\")) {\n- Some{value} -> options.insert(\"ipv6_ra_rdnss\", value),\n+ match (port.lrp.ipv6_ra_configs.get(i\"rdnss\")) {\n+ Some{value} -> options.insert(i\"ipv6_ra_rdnss\", value),\n _ -> ()\n };\n \n- match (port.lrp.ipv6_ra_configs.get(\"dnssl\")) {\n- Some{value} -> options.insert(\"ipv6_ra_dnssl\", value),\n+ match (port.lrp.ipv6_ra_configs.get(i\"dnssl\")) {\n+ Some{value} -> options.insert(i\"ipv6_ra_dnssl\", value),\n _ -> ()\n };\n \n- options.insert(\"ipv6_ra_src_eth\", \"${port.networks.ea}\");\n+ options.insert(i\"ipv6_ra_src_eth\", i\"${port.networks.ea}\");\n \n- var prf = match (port.lrp.ipv6_ra_configs.get(\"router_preference\")) {\n- Some{prf} -> if (prf == \"HIGH\" or prf == \"LOW\") prf else \"MEDIUM\",\n- _ -> \"MEDIUM\"\n+ var prf = match (port.lrp.ipv6_ra_configs.get(i\"router_preference\")) {\n+ Some{prf} -> if (prf == i\"HIGH\" or prf == i\"LOW\") prf else i\"MEDIUM\",\n+ _ -> i\"MEDIUM\"\n };\n- options.insert(\"ipv6_ra_prf\", prf);\n+ options.insert(i\"ipv6_ra_prf\", prf);\n \n- match (port.lrp.ipv6_ra_configs.get(\"route_info\")) {\n- Some{s} -> options.insert(\"ipv6_ra_route_info\", s),\n+ match (port.lrp.ipv6_ra_configs.get(i\"route_info\")) {\n+ Some{s} -> options.insert(i\"ipv6_ra_route_info\", s),\n _ -> ()\n };\n \n@@ -6999,17 +6988,17 @@ for (&RouterPort[port@RouterPort{.lrp = lrp@&nb::Logical_Router_Port{.peer = Non\n .peer = PeerSwitch{}}]\n if (not networks.ipv6_addrs.is_empty()))\n {\n- Some{var address_mode} = lrp.ipv6_ra_configs.get(\"address_mode\") in\n+ Some{var address_mode} = lrp.ipv6_ra_configs.get(i\"address_mode\") in\n /* FIXME: we need a nicer wat to write this */\n true ==\n- if ((address_mode != \"slaac\") and\n- (address_mode != \"dhcpv6_stateful\") and\n- (address_mode != \"dhcpv6_stateless\")) {\n+ if ((address_mode != i\"slaac\") and\n+ (address_mode != i\"dhcpv6_stateful\") and\n+ (address_mode != i\"dhcpv6_stateless\")) {\n warn(\"Invalid address mode [${address_mode}] defined\");\n false\n } else { true } in\n {\n- if (lrp.ipv6_ra_configs.get_bool_def(\"send_periodic\", false)) {\n+ if (lrp.ipv6_ra_configs.get_bool_def(i\"send_periodic\", false)) {\n RouterPortRAOptions(lrp._uuid, copy_ra_to_sb(port, address_mode))\n };\n \n@@ -7028,7 +7017,7 @@ for (&RouterPort[port@RouterPort{.lrp = lrp@&nb::Logical_Router_Port{.peer = Non\n {\n var __match = i\"inport == ${json_name} && ip6.dst == ff02::2 && nd_rs\" in\n /* As per RFC 2460, 1280 is minimum IPv6 MTU. */\n- var mtu = match(lrp.ipv6_ra_configs.get(\"mtu\")) {\n+ var mtu = match(lrp.ipv6_ra_configs.get(i\"mtu\")) {\n Some{mtu_s} -> {\n match (parse_dec_u64(mtu_s)) {\n None -> 0,\n@@ -7039,13 +7028,12 @@ for (&RouterPort[port@RouterPort{.lrp = lrp@&nb::Logical_Router_Port{.peer = Non\n } in\n var actions0 =\n \"${rEGBIT_ND_RA_OPTS_RESULT()} = put_nd_ra_opts(\"\n- \"addr_mode = ${json_string_escape(address_mode)}, \"\n+ \"addr_mode = ${json_escape(address_mode)}, \"\n \"slla = ${networks.ea}\" ++\n if (mtu > 0) { \", mtu = ${mtu}\" } else { \"\" } in\n- var router_preference = match (lrp.ipv6_ra_configs.get(\"router_preference\")) {\n- Some{\"MEDIUM\"} -> \"\",\n- None -> \"\",\n- Some{prf} -> \", router_preference = \\\"${prf}\\\"\"\n+ var router_preference = match (lrp.ipv6_ra_configs.get(i\"router_preference\")) {\n+ Some{prf} -> if (prf == i\"MEDIUM\") { \"\" } else { \", router_preference = \\\"${prf}\\\"\" },\n+ None -> \"\"\n } in\n var actions = actions0 ++ router_preference ++ prefix ++ \"); next;\" in\n Flow(.logical_datapath = router._uuid,\n@@ -7269,7 +7257,7 @@ relation RouterPortRoutableAddresses(\n addresses: Set<lport_addresses>)\n RouterPortRoutableAddresses(port.lrp._uuid, addresses) :-\n port in &RouterPort(.is_redirect = true),\n- var addresses = get_nat_addresses(port, true).filter_map(extract_addresses),\n+ var addresses = get_nat_addresses(port, true).filter_map(|addrs| addrs.ival().extract_addresses()),\n addresses != set_empty().\n \n /* Return a vector of pairs (1, set[0]), ... (n, set[n - 1]). */\n@@ -7445,7 +7433,7 @@ Flow(.logical_datapath = router._uuid,\n for (IgmpRouterMulticastGroup(address, rtr, ports)) {\n for (RouterMcastFloodPorts(rtr, flood_ports) if rtr.mcast_cfg.relay) {\n var flood_static = not flood_ports.is_empty() in\n- var mc_static = json_string_escape(mC_STATIC().0) in\n+ var mc_static = json_escape(mC_STATIC().0) in\n var static_act = {\n if (flood_static) {\n \"clone { \"\n@@ -7457,14 +7445,14 @@ for (IgmpRouterMulticastGroup(address, rtr, ports)) {\n \"\"\n }\n } in\n- Some{var ip} = ip46_parse(address) in\n+ Some{var ip} = ip46_parse(address.ival()) in\n var ipX = ip.ipX() in\n Flow(.logical_datapath = rtr._uuid,\n .stage = s_ROUTER_IN_IP_ROUTING(),\n .priority = 500,\n .__match = i\"${ipX} && ${ipX}.dst == ${address} \",\n .actions =\n- i\"${static_act}outport = ${json_string_escape(address)}; \"\n+ i\"${static_act}outport = ${json_escape(address)}; \"\n \"ip.ttl--; next;\",\n .stage_hint = 0,\n .io_port = None,\n@@ -7476,7 +7464,7 @@ for (IgmpRouterMulticastGroup(address, rtr, ports)) {\n * Priority 450. Otherwise drop any multicast traffic.\n */\n for (RouterMcastFloodPorts(rtr, flood_ports) if rtr.mcast_cfg.relay) {\n- var mc_static = json_string_escape(mC_STATIC().0) in\n+ var mc_static = json_escape(mC_STATIC().0) in\n var flood_static = not flood_ports.is_empty() in\n var actions = if (flood_static) {\n i\"clone { \"\n@@ -7529,8 +7517,8 @@ for (&Router(._uuid = lr_uuid)) {\n }\n \n /* Convert routing policies to flows. */\n-function pkt_mark_policy(options: Map<string,string>): string {\n- var pkt_mark = options.get(\"pkt_mark\").and_then(parse_dec_u64).unwrap_or(0);\n+function pkt_mark_policy(options: Map<istring,istring>): string {\n+ var pkt_mark = options.get(i\"pkt_mark\").and_then(parse_dec_u64).unwrap_or(0);\n if (pkt_mark > 0 and pkt_mark < (1 << 32)) {\n \"pkt.mark = ${pkt_mark}; \"\n } else {\n@@ -7540,7 +7528,7 @@ function pkt_mark_policy(options: Map<string,string>): string {\n Flow(.logical_datapath = r._uuid,\n .stage = s_ROUTER_IN_POLICY(),\n .priority = policy.priority,\n- .__match = policy.__match.intern(),\n+ .__match = policy.__match,\n .actions = actions.intern(),\n .stage_hint = stage_hint(policy._uuid),\n .io_port = None,\n@@ -7548,13 +7536,13 @@ Flow(.logical_datapath = r._uuid,\n r in &Router(),\n var policy_uuid = FlatMap(r.policies),\n policy in nb::Logical_Router_Policy(._uuid = policy_uuid),\n- policy.action == \"reroute\",\n+ policy.action == i\"reroute\",\n Some{var nexthop_s} = match (policy.nexthops.size()) {\n 0 -> policy.nexthop,\n 1 -> policy.nexthops.nth(0),\n _ -> None /* >1 nexthops handled separately as ECMP. */\n },\n- Some{var nexthop} = ip46_parse(nexthop_s),\n+ Some{var nexthop} = ip46_parse(nexthop_s.ival()),\n out_port in &RouterPort(.router = r),\n Some{var src_ip} = find_lrp_member_ip(out_port.networks, nexthop),\n /*\n@@ -7575,7 +7563,7 @@ Flow(.logical_datapath = r._uuid,\n \n /* Returns true if the addresses in 'addrs' are all IPv4 or all IPv6,\n false if they are a mix. */\n-function all_same_addr_family(addrs: Set<string>): bool {\n+function all_same_addr_family(addrs: Set<istring>): bool {\n var addr_families = set_empty();\n for (a in addrs) {\n addr_families.insert(a.contains(\".\"))\n@@ -7592,9 +7580,9 @@ EcmpReroutePolicy(r, policy, ecmp_group_id) :-\n r in &Router(),\n var policy_uuid = FlatMap(r.policies),\n policy in nb::Logical_Router_Policy(._uuid = policy_uuid),\n- policy.action == \"reroute\",\n+ policy.action == i\"reroute\",\n policy.nexthops.size() > 1,\n- var policies = policy.group_by(r).to_vec(),\n+ var policies = policy.group_by(r).to_vec().map(|x| (x.nexthop, x)).sort_imm().map(|x| x.1),\n var ecmp_group_ids = range_vec(1, policies.len() + 1, 1),\n var numbered_policies = policies.zip(ecmp_group_ids),\n var pair = FlatMap(numbered_policies),\n@@ -7610,7 +7598,7 @@ Flow(.logical_datapath = r._uuid,\n .controller_meter = None) :-\n EcmpReroutePolicy(r, policy, ecmp_group_id),\n var member_ids = range_vec(1, policy.nexthops.size() + 1, 1),\n- var numbered_nexthops = policy.nexthops.to_vec().zip(member_ids),\n+ var numbered_nexthops = policy.nexthops.map(ival).to_vec().zip(member_ids),\n var pair = FlatMap(numbered_nexthops),\n (var nexthop_s, var member_id) = pair,\n Some{var nexthop} = ip46_parse(nexthop_s),\n@@ -7629,7 +7617,7 @@ Flow(.logical_datapath = r._uuid,\n Flow(.logical_datapath = r._uuid,\n .stage = s_ROUTER_IN_POLICY(),\n .priority = policy.priority,\n- .__match = policy.__match.intern(),\n+ .__match = policy.__match,\n .actions = actions,\n .stage_hint = stage_hint(policy._uuid),\n .io_port = None,\n@@ -7649,7 +7637,7 @@ Flow(.logical_datapath = r._uuid,\n Flow(.logical_datapath = r._uuid,\n .stage = s_ROUTER_IN_POLICY(),\n .priority = policy.priority,\n- .__match = policy.__match.intern(),\n+ .__match = policy.__match,\n .actions = i\"drop;\",\n .stage_hint = stage_hint(policy._uuid),\n .io_port = None,\n@@ -7657,11 +7645,11 @@ Flow(.logical_datapath = r._uuid,\n r in &Router(),\n var policy_uuid = FlatMap(r.policies),\n policy in nb::Logical_Router_Policy(._uuid = policy_uuid),\n- policy.action == \"drop\".\n+ policy.action == i\"drop\".\n Flow(.logical_datapath = r._uuid,\n .stage = s_ROUTER_IN_POLICY(),\n .priority = policy.priority,\n- .__match = policy.__match.intern(),\n+ .__match = policy.__match,\n .actions = (pkt_mark_policy(policy.options) ++ \"${rEG_ECMP_GROUP_ID()} = 0; next;\").intern(),\n .stage_hint = stage_hint(policy._uuid),\n .io_port = None,\n@@ -7669,7 +7657,7 @@ Flow(.logical_datapath = r._uuid,\n r in &Router(),\n var policy_uuid = FlatMap(r.policies),\n policy in nb::Logical_Router_Policy(._uuid = policy_uuid),\n- policy.action == \"allow\".\n+ policy.action == i\"allow\".\n \n \n /* XXX destination unreachable */\n@@ -7753,14 +7741,14 @@ Flow(.logical_datapath = router._uuid,\n .stage = s_ROUTER_IN_ARP_RESOLVE(),\n .priority = 50,\n .__match = i\"outport == ${rp.json_name} && \"\n- \"!is_chassis_resident(${json_string_escape(chassis_redirect_name(l3dgw_port.name))})\",\n+ \"!is_chassis_resident(${json_escape(chassis_redirect_name(l3dgw_port.name))})\",\n .actions = i\"eth.dst = ${rp.networks.ea}; next;\",\n .stage_hint = stage_hint(lrp._uuid),\n .io_port = None,\n .controller_meter = None) :-\n rp in &RouterPort(.lrp = lrp, .router = router),\n Some{var l3dgw_port} = router.l3dgw_ports.nth(0),\n- Some{\"bridged\"} = lrp.options.get(\"redirect-type\").\n+ Some{i\"bridged\"} == lrp.options.get(i\"redirect-type\").\n \n \n /* Drop IP traffic destined to router owned IPs. Part of it is dropped\n@@ -7815,7 +7803,7 @@ Flow(.logical_datapath = peer.router._uuid,\n FirstHopRouterPortRoutableAddresses(port, peer_uuid),\n peer in &RouterPort(.lrp = lrp),\n lrp._uuid == peer_uuid,\n- not peer.router.options.get_bool_def(\"dynamic_neigh_routers\", false),\n+ not peer.router.options.get_bool_def(i\"dynamic_neigh_routers\", false),\n var addr = FlatMap(addresses),\n var ips = addr.ipv4_addrs.map(|a| a.addr.to_string()).join(\", \").\n \n@@ -7828,7 +7816,7 @@ for (SwitchPortIPv4Address(\n .port = &SwitchPort{.lsp = lsp, .sw = sw},\n .ea = ea,\n .addr = addr)\n- if lsp.__type != \"router\" and lsp.__type != \"virtual\" and lsp.is_enabled())\n+ if lsp.__type != i\"router\" and lsp.__type != i\"virtual\" and lsp.is_enabled())\n {\n for (&SwitchPort(.sw = &Switch{._uuid = sw._uuid},\n .peer = Some{peer@&RouterPort{.router = peer_router}}))\n@@ -7850,7 +7838,7 @@ for (SwitchPortIPv6Address(\n .port = &SwitchPort{.lsp = lsp, .sw = sw},\n .ea = ea,\n .addr = addr)\n- if lsp.__type != \"router\" and lsp.__type != \"virtual\" and lsp.is_enabled())\n+ if lsp.__type != i\"router\" and lsp.__type != i\"virtual\" and lsp.is_enabled())\n {\n for (&SwitchPort(.sw = &Switch{._uuid = sw._uuid},\n .peer = Some{peer@&RouterPort{.router = peer_router}}))\n@@ -7873,11 +7861,10 @@ for (SwitchPortIPv6Address(\n *\n * This is meant for sets of 0 or 1 elements, like the OVSDB integration\n * with DDlog uses. */\n-function is_empty_set_or_string(s: Option<string>): bool = {\n+function is_empty_set_or_string(s: Option<istring>): bool = {\n match (s) {\n None -> true,\n- Some{\"\"} -> true,\n- _ -> false\n+ Some{s} -> s == i\"\"\n }\n }\n \n@@ -7897,10 +7884,10 @@ Flow(.logical_datapath = peer.router._uuid,\n .stage_hint = stage_hint(sp.lsp._uuid),\n .io_port = None,\n .controller_meter = None) :-\n- sp in &SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = \"virtual\"}),\n- Some{var virtual_ip_s} = lsp.options.get(\"virtual-ip\"),\n- Some{var virtual_parents} = lsp.options.get(\"virtual-parents\"),\n- Some{var virtual_ip} = ip_parse(virtual_ip_s),\n+ sp in &SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = i\"virtual\"}),\n+ Some{var virtual_ip_s} = lsp.options.get(i\"virtual-ip\"),\n+ Some{var virtual_parents} = lsp.options.get(i\"virtual-parents\"),\n+ Some{var virtual_ip} = ip_parse(virtual_ip_s.ival()),\n pb in sb::Port_Binding(.logical_port = sp.lsp.name),\n is_empty_set_or_string(pb.virtual_parent) or pb.chassis == None,\n sp2 in &SwitchPort(.sw = sp.sw, .peer = Some{peer}),\n@@ -7914,10 +7901,10 @@ Flow(.logical_datapath = peer.router._uuid,\n .stage_hint = stage_hint(sp.lsp._uuid),\n .io_port = None,\n .controller_meter = None) :-\n- sp in &SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = \"virtual\"}),\n- Some{var virtual_ip_s} = lsp.options.get(\"virtual-ip\"),\n- Some{var virtual_parents} = lsp.options.get(\"virtual-parents\"),\n- Some{var virtual_ip} = ip_parse(virtual_ip_s),\n+ sp in &SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = i\"virtual\"}),\n+ Some{var virtual_ip_s} = lsp.options.get(i\"virtual-ip\"),\n+ Some{var virtual_parents} = lsp.options.get(i\"virtual-parents\"),\n+ Some{var virtual_ip} = ip_parse(virtual_ip_s.ival()),\n pb in sb::Port_Binding(.logical_port = sp.lsp.name),\n not (is_empty_set_or_string(pb.virtual_parent) or pb.chassis == None),\n Some{var virtual_parent} = pb.virtual_parent,\n@@ -7936,7 +7923,7 @@ for (&SwitchPort(.lsp = lsp1,\n .peer = Some{peer1@&RouterPort{.router = peer_router}},\n .sw = sw)\n if lsp1.is_enabled() and\n- not peer_router.options.get_bool_def(\"dynamic_neigh_routers\", false))\n+ not peer_router.options.get_bool_def(i\"dynamic_neigh_routers\", false))\n {\n for (&SwitchPort(.lsp = lsp2, .peer = Some{peer2},\n .sw = &Switch{._uuid = sw._uuid})\n@@ -8031,7 +8018,7 @@ Flow(.logical_datapath = lr_uuid,\n .controller_meter = None) :-\n r in &Router(._uuid = lr_uuid),\n gw_mtu_rp in &RouterPort(.router = r),\n- var gw_mtu = gw_mtu_rp.lrp.options.get_int_def(\"gateway_mtu\", 0),\n+ var gw_mtu = gw_mtu_rp.lrp.options.get_int_def(i\"gateway_mtu\", 0),\n gw_mtu > 0,\n var mtu = gw_mtu + vLAN_ETH_HEADER_LEN().\n Flow(.logical_datapath = lr_uuid,\n@@ -8057,7 +8044,7 @@ Flow(.logical_datapath = lr_uuid,\n .stage_hint = stage_hint(rp.lrp._uuid)) :-\n r in &Router(._uuid = lr_uuid),\n gw_mtu_rp in &RouterPort(.router = r),\n- var gw_mtu = gw_mtu_rp.lrp.options.get_int_def(\"gateway_mtu\", 0),\n+ var gw_mtu = gw_mtu_rp.lrp.options.get_int_def(i\"gateway_mtu\", 0),\n gw_mtu > 0,\n var mtu = gw_mtu + vLAN_ETH_HEADER_LEN(),\n rp in &RouterPort(.router = r),\n@@ -8087,7 +8074,7 @@ Flow(.logical_datapath = lr_uuid,\n .stage_hint = stage_hint(rp.lrp._uuid)) :-\n r in &Router(._uuid = lr_uuid),\n gw_mtu_rp in &RouterPort(.router = r),\n- var gw_mtu = gw_mtu_rp.lrp.options.get_int_def(\"gateway_mtu\", 0),\n+ var gw_mtu = gw_mtu_rp.lrp.options.get_int_def(i\"gateway_mtu\", 0),\n gw_mtu > 0,\n var mtu = gw_mtu + vLAN_ETH_HEADER_LEN(),\n rp in &RouterPort(.router = r),\n@@ -8117,7 +8104,7 @@ Flow(.logical_datapath = lr_uuid,\n .stage_hint = stage_hint(rp.lrp._uuid)) :-\n r in &Router(._uuid = lr_uuid),\n gw_mtu_rp in &RouterPort(.router = r),\n- var gw_mtu = gw_mtu_rp.lrp.options.get_int_def(\"gateway_mtu\", 0),\n+ var gw_mtu = gw_mtu_rp.lrp.options.get_int_def(i\"gateway_mtu\", 0),\n gw_mtu > 0,\n var mtu = gw_mtu + vLAN_ETH_HEADER_LEN(),\n rp in &RouterPort(.router = r),\n@@ -8147,7 +8134,7 @@ Flow(.logical_datapath = lr_uuid,\n .stage_hint = stage_hint(rp.lrp._uuid)) :-\n r in &Router(._uuid = lr_uuid),\n gw_mtu_rp in &RouterPort(.router = r),\n- var gw_mtu = gw_mtu_rp.lrp.options.get_int_def(\"gateway_mtu\", 0),\n+ var gw_mtu = gw_mtu_rp.lrp.options.get_int_def(i\"gateway_mtu\", 0),\n gw_mtu > 0,\n var mtu = gw_mtu + vLAN_ETH_HEADER_LEN(),\n rp in &RouterPort(.router = r),\n@@ -8171,8 +8158,8 @@ for (&Router(._uuid = lr_uuid))\n Flow(.logical_datapath = lr_uuid,\n .stage = s_ROUTER_IN_GW_REDIRECT(),\n .priority = 50,\n- .__match = i\"outport == ${json_string_escape(lrp.name)}\",\n- .actions = i\"outport = ${json_string_escape(chassis_redirect_name(lrp.name))}; next;\",\n+ .__match = i\"outport == ${json_escape(lrp.name)}\",\n+ .actions = i\"outport = ${json_escape(chassis_redirect_name(lrp.name))}; next;\",\n .stage_hint = stage_hint(lrp._uuid),\n .io_port = None,\n .controller_meter = None)\n@@ -8319,7 +8306,7 @@ relation IsVxlanMode0()\n IsVxlanMode0() :-\n sb::Chassis(.encaps = encaps),\n var encap_uuid = FlatMap(encaps),\n- sb::Encap(._uuid = encap_uuid, .__type = \"vxlan\").\n+ sb::Encap(._uuid = encap_uuid, .__type = i\"vxlan\").\n \n relation IsVxlanMode[bool]\n IsVxlanMode[true] :-\n@@ -8334,7 +8321,7 @@ relation OvnMaxDpKeyLocal[integer]\n OvnMaxDpKeyLocal[oVN_MAX_DP_VXLAN_KEY()] :- IsVxlanMode[true].\n OvnMaxDpKeyLocal[oVN_MAX_DP_KEY() - oVN_MAX_DP_GLOBAL_NUM()] :- IsVxlanMode[false].\n \n-function get_dp_tunkey(map: Map<string,string>, key: string): Option<integer> {\n+function get_dp_tunkey(map: Map<istring,istring>, key: istring): Option<integer> {\n map.get(key)\n .and_then(parse_dec_u64)\n .and_then(|x| if (x > 0 and x < (2<<24)) {\n@@ -8348,10 +8335,10 @@ function get_dp_tunkey(map: Map<string,string>, key: string): Option<integer> {\n relation RequestedTunKey(datapath: uuid, tunkey: integer)\n RequestedTunKey(uuid, tunkey) :-\n ls in &nb::Logical_Switch(._uuid = uuid),\n- Some{var tunkey} = get_dp_tunkey(ls.other_config, \"requested-tnl-key\").\n+ Some{var tunkey} = get_dp_tunkey(ls.other_config, i\"requested-tnl-key\").\n RequestedTunKey(uuid, tunkey) :-\n lr in nb::Logical_Router(._uuid = uuid),\n- Some{var tunkey} = get_dp_tunkey(lr.options, \"requested-tnl-key\").\n+ Some{var tunkey} = get_dp_tunkey(lr.options, i\"requested-tnl-key\").\n Warning[message] :-\n RequestedTunKey(datapath, tunkey),\n var count = datapath.group_by((tunkey)).size(),\n@@ -8416,7 +8403,7 @@ TunKeyAllocation(datapath, tunkey) :-\n * Port IDs in a per-datapath space in the range 1...2**15-1\n */\n \n-function get_port_tunkey(map: Map<string,string>, key: string): Option<integer> {\n+function get_port_tunkey(map: Map<istring,istring>, key: istring): Option<integer> {\n map.get(key)\n .and_then(parse_dec_u64)\n .and_then(|x| if (x > 0 and x < (2<<15)) {\n@@ -8432,12 +8419,12 @@ RequestedPortTunKey(datapath, port, tunkey) :-\n sp in &SwitchPort(),\n var datapath = sp.sw._uuid,\n var port = sp.lsp._uuid,\n- Some{var tunkey} = get_port_tunkey(sp.lsp.options, \"requested-tnl-key\").\n+ Some{var tunkey} = get_port_tunkey(sp.lsp.options, i\"requested-tnl-key\").\n RequestedPortTunKey(datapath, port, tunkey) :-\n rp in &RouterPort(),\n var datapath = rp.router._uuid,\n var port = rp.lrp._uuid,\n- Some{var tunkey} = get_port_tunkey(rp.lrp.options, \"requested-tnl-key\").\n+ Some{var tunkey} = get_port_tunkey(rp.lrp.options, i\"requested-tnl-key\").\n Warning[message] :-\n RequestedPortTunKey(datapath, port, tunkey),\n var count = port.group_by((datapath, tunkey)).size(),\n@@ -8514,7 +8501,7 @@ AllocatedMulticastGroupTunKeys(datapath_uuid, keys) :-\n \n // Multicast_Group's not yet in the Realized table.\n relation NotYetAllocatedMulticastGroupTunKeys(datapath_uuid: uuid,\n- all_logical_ids: Vec<string>)\n+ all_logical_ids: Vec<istring>)\n \n NotYetAllocatedMulticastGroupTunKeys(datapath_uuid, all_names) :-\n OutProxy_Multicast_Group(.name = name, .datapath = datapath_uuid),\n@@ -8522,7 +8509,7 @@ NotYetAllocatedMulticastGroupTunKeys(datapath_uuid, all_names) :-\n var all_names = name.group_by(datapath_uuid).to_vec().\n \n // Perform the allocation\n-relation MulticastGroupTunKeyAllocation(datapath_uuid: uuid, group: string, tunkey: integer)\n+relation MulticastGroupTunKeyAllocation(datapath_uuid: uuid, group: istring, tunkey: integer)\n \n // transfer existing allocations from the realized table\n MulticastGroupTunKeyAllocation(datapath_uuid, group, tunkey) :-\n@@ -8567,8 +8554,8 @@ MulticastGroupTunKeyAllocation(datapath_uuid, group, tunkey) :-\n * have a queue ID. For those we use the port's own UUID as the chassis UUID.\n */\n \n-function port_has_qos_params(opts: Map<string, string>): bool = {\n- opts.contains_key(\"qos_max_rate\") or opts.contains_key(\"qos_burst\")\n+function port_has_qos_params(opts: Map<istring, istring>): bool = {\n+ opts.contains_key(i\"qos_max_rate\") or opts.contains_key(i\"qos_burst\")\n }\n \n \n@@ -8577,13 +8564,13 @@ relation PortRequiresQID(port: uuid, chassis: uuid)\n \n PortRequiresQID(pb._uuid, chassis) :-\n pb in OutProxy_Port_Binding(),\n- pb.__type != \"localnet\",\n+ pb.__type != i\"localnet\",\n port_has_qos_params(pb.options),\n sb::Port_Binding(._uuid = pb._uuid, .chassis = chassis_set),\n Some{var chassis} = chassis_set.\n PortRequiresQID(pb._uuid, pb._uuid) :-\n pb in OutProxy_Port_Binding(),\n- pb.__type == \"localnet\",\n+ pb.__type == i\"localnet\",\n port_has_qos_params(pb.options),\n sb::Port_Binding(._uuid = pb._uuid).\n \n@@ -8597,16 +8584,16 @@ relation AllocatedQIDs(chassis: uuid, allocated_ids: Map<uuid, integer>)\n \n AllocatedQIDs(chassis, allocated_ids) :-\n pb in sb::Port_Binding(),\n- pb.__type != \"localnet\",\n+ pb.__type != i\"localnet\",\n Some{var chassis} = pb.chassis,\n- Some{var qid_str} = pb.options.get(\"qdisc_queue_id\"),\n+ Some{var qid_str} = pb.options.get(i\"qdisc_queue_id\"),\n Some{var qid} = parse_dec_u64(qid_str),\n var allocated_ids = (pb._uuid, qid).group_by(chassis).to_map().\n AllocatedQIDs(chassis, allocated_ids) :-\n pb in sb::Port_Binding(),\n- pb.__type == \"localnet\",\n+ pb.__type == i\"localnet\",\n var chassis = pb._uuid,\n- Some{var qid_str} = pb.options.get(\"qdisc_queue_id\"),\n+ Some{var qid_str} = pb.options.get(i\"qdisc_queue_id\"),\n Some{var qid} = parse_dec_u64(qid_str),\n var allocated_ids = (pb._uuid, qid).group_by(chassis).to_map().\n \n@@ -8634,10 +8621,10 @@ QueueIDAllocation(port, Some{qid}) :-\n * This allows ovn-northd to preserve options:ipv6_ra_pd_list, which is set by\n * ovn-controller.\n */\n-relation PreserveIPv6RAPDList(lrp_uuid: uuid, ipv6_ra_pd_list: Option<string>)\n+relation PreserveIPv6RAPDList(lrp_uuid: uuid, ipv6_ra_pd_list: Option<istring>)\n PreserveIPv6RAPDList(lrp_uuid, ipv6_ra_pd_list) :-\n sb::Port_Binding(._uuid = lrp_uuid, .options = options),\n- var ipv6_ra_pd_list = options.get(\"ipv6_ra_pd_list\").\n+ var ipv6_ra_pd_list = options.get(i\"ipv6_ra_pd_list\").\n PreserveIPv6RAPDList(lrp_uuid, None) :-\n &nb::Logical_Router_Port(._uuid = lrp_uuid),\n not sb::Port_Binding(._uuid = lrp_uuid).\n@@ -8653,7 +8640,7 @@ PreserveIPv6RAPDList(lrp_uuid, None) :-\n * 3. For ports that do not have a tag_request, but have a tag statically assigned\n * by directly setting the `tag` field, use this value.\n */\n-relation SwitchPortReservedTag(parent_name: string, tags: integer)\n+relation SwitchPortReservedTag(parent_name: istring, tags: integer)\n \n SwitchPortReservedTag(parent_name, tag) :-\n &SwitchPort(.lsp = lsp, .needs_dynamic_tag = needs_dynamic_tag, .parent_name = Some{parent_name}),\n@@ -8666,7 +8653,7 @@ SwitchPortReservedTag(parent_name, tag) :-\n }\n }.\n \n-relation SwitchPortReservedTags(parent_name: string, tags: Set<integer>)\n+relation SwitchPortReservedTags(parent_name: istring, tags: Set<integer>)\n \n SwitchPortReservedTags(parent_name, tags) :-\n SwitchPortReservedTag(parent_name, tag),\n@@ -8734,7 +8721,7 @@ sb::Out_IP_Multicast(._uuid = cfg.datapath,\n McastSwitchCfg[cfg].\n \n \n-relation PortExists(name: string)\n+relation PortExists(name: istring)\n PortExists(name) :- &nb::Logical_Switch_Port(.name = name).\n PortExists(name) :- &nb::Logical_Router_Port(.name = name).\n \n@@ -8743,7 +8730,7 @@ sb::Out_Load_Balancer(._uuid = lb._uuid,\n .vips = lb.vips,\n .protocol = lb.protocol,\n .datapaths = datapaths,\n- .external_ids = [\"lb_id\" -> uuid2str(lb_uuid)],\n+ .external_ids = [i\"lb_id\" -> uuid2str(lb_uuid).intern()],\n .options = options) :-\n nb in &nb::Logical_Switch(._uuid = ls_uuid, .load_balancer = lb_uuids),\n var lb_uuid = FlatMap(lb_uuids),\n@@ -8752,14 +8739,14 @@ sb::Out_Load_Balancer(._uuid = lb._uuid,\n /* Store the fact that northd provides the original (destination IP +\n * transport port) tuple.\n */\n- var options = lb.options.insert_imm(\"hairpin_orig_tuple\", \"true\").\n+ var options = lb.options.insert_imm(i\"hairpin_orig_tuple\", i\"true\").\n \n sb::Out_Service_Monitor(._uuid = hash128((svc_monitor.port_name, lbvipbackend.ip, lbvipbackend.port, protocol)),\n- .ip = \"${lbvipbackend.ip}\",\n+ .ip = i\"${lbvipbackend.ip}\",\n .protocol = Some{protocol},\n .port = lbvipbackend.port as integer,\n .logical_port = svc_monitor.port_name,\n- .src_mac = to_string(svc_monitor_mac),\n+ .src_mac = i\"${svc_monitor_mac}\",\n .src_ip = svc_monitor.src_ip,\n .options = health_check.options,\n .external_ids = map_empty()) :-\n@@ -8770,13 +8757,13 @@ sb::Out_Service_Monitor(._uuid = hash128((svc_monitor.port_name, lbvipbackend.ip\n Some{var svc_monitor} = lbvipbackend.svc_monitor,\n PortExists(svc_monitor.port_name),\n var protocol = default_protocol(lb.protocol),\n- protocol != \"sctp\".\n+ protocol != i\"sctp\".\n \n Warning[\"SCTP load balancers do not currently support \"\n \"health checks. Not creating health checks for \"\n \"load balancer ${uuid2str(lb._uuid)}\"] :-\n LBVIP[lbvip@&LBVIP{.lb = lb}],\n- default_protocol(lb.protocol) == \"sctp\",\n+ default_protocol(lb.protocol) == i\"sctp\",\n Some{var health_check} = lbvip.health_check,\n var lbvipbackend = FlatMap(lbvip.backends),\n Some{var svc_monitor} = lbvipbackend.svc_monitor.\n@@ -8803,8 +8790,8 @@ function bFD_UDP_SRC_PORT_MAX(): integer { 65535 }\n // Get already assigned BFD source ports.\n // If there's a conflict, make an arbitrary choice.\n relation AssignedSrcPort(\n- logical_port: string,\n- dst_ip: string,\n+ logical_port: istring,\n+ dst_ip: istring,\n src_port: integer)\n AssignedSrcPort(logical_port, dst_ip, src_port) :-\n sb::BFD(.logical_port = logical_port, .dst_ip = dst_ip, .src_port = src_port),\n@@ -8822,7 +8809,7 @@ AllocatedSrcPorts(src_ports) :- AllocatedSrcPorts0(src_ports).\n AllocatedSrcPorts(set_empty()) :- Unit(), not AllocatedSrcPorts0(_).\n \n // (logical_port, dst_ip) pairs not yet in the Realized table\n-relation NotYetAllocatedSrcPorts(pairs: Vec<(string, string)>)\n+relation NotYetAllocatedSrcPorts(pairs: Vec<(istring, istring)>)\n NotYetAllocatedSrcPorts(pairs) :-\n nb::BFD(.logical_port = logical_port, .dst_ip = dst_ip),\n not AssignedSrcPort(logical_port, dst_ip, _),\n@@ -8830,8 +8817,8 @@ NotYetAllocatedSrcPorts(pairs) :-\n \n // Perform the allocation\n relation SrcPortAllocation(\n- logical_port: string,\n- dst_ip: string,\n+ logical_port: istring,\n+ dst_ip: istring,\n src_port: integer)\n SrcPortAllocation(logical_port, dst_ip, src_port) :- AssignedSrcPort(logical_port, dst_ip, src_port).\n SrcPortAllocation(logical_port, dst_ip, src_port) :-\n@@ -8842,9 +8829,9 @@ SrcPortAllocation(logical_port, dst_ip, src_port) :-\n ((var logical_port, var dst_ip), var src_port) = allocation.\n \n relation SouthboundBFDStatus(\n- logical_port: string,\n- dst_ip: string,\n- status: Option<string>\n+ logical_port: istring,\n+ dst_ip: istring,\n+ status: Option<istring>\n )\n SouthboundBFDStatus(bfd.logical_port, bfd.dst_ip, Some{bfd.status}) :- bfd in sb::BFD().\n SouthboundBFDStatus(logical_port, dst_ip, None) :-\n@@ -8864,9 +8851,9 @@ sb::Out_BFD(._uuid = hash,\n .detect_mult = nb.detect_mult.unwrap_or(bFD_DEF_DETECT_MULT()),\n .status = status,\n .external_ids = map_empty(),\n- .options = [\"nb_status\" -> nb.status.unwrap_or(\"\"),\n- \"sb_status\" -> sb_status.unwrap_or(\"\"),\n- \"referenced\" -> referenced.to_string()]) :-\n+ .options = [i\"nb_status\" -> nb.status.unwrap_or(i\"\"),\n+ i\"sb_status\" -> sb_status.unwrap_or(i\"\"),\n+ i\"referenced\" -> i\"${referenced}\"]) :-\n nb in nb::BFD(),\n SrcPortAllocation(nb.logical_port, nb.dst_ip, src_port),\n SouthboundBFDStatus(nb.logical_port, nb.dst_ip, sb_status),\n@@ -8891,22 +8878,22 @@ BFDReferenced(bfd_uuid, false) :-\n // - 'sb_status0': 'status' in the existing sb::BFD record (None, if none exists yet)\n // computes and returns (nb_status, sb_status), which are the values to use next in these records\n function bfd_new_status(referenced: bool,\n- nb_status0: Option<string>,\n- sb_status0: Option<string>): (string, string) {\n- var nb_status = nb_status0.unwrap_or(\"admin_down\");\n+ nb_status0: Option<istring>,\n+ sb_status0: Option<istring>): (istring, istring) {\n+ var nb_status = nb_status0.unwrap_or(i\"admin_down\");\n match (sb_status0) {\n- Some{sb_status} -> if (nb_status != \"admin_down\" and sb_status != \"admin_down\") {\n+ Some{sb_status} -> if (nb_status != i\"admin_down\" and sb_status != i\"admin_down\") {\n nb_status = sb_status\n },\n _ -> ()\n };\n var sb_status = nb_status;\n if (referenced) {\n- if (nb_status == \"admin_down\") {\n- nb_status = \"down\"\n+ if (nb_status == i\"admin_down\") {\n+ nb_status = i\"down\"\n }\n } else {\n- nb_status = \"admin_down\"\n+ nb_status = i\"admin_down\"\n };\n warn(\"nb_status=${nb_status} sb_status=${sb_status} referenced=${referenced}\");\n (nb_status, sb_status)\n@@ -8925,7 +8912,7 @@ function lrouter_bfd_flows(lr_uuid: uuid,\n lrp_uuid: uuid,\n ipX: string,\n networks: string,\n- controller_meter: Option<string>)\n+ controller_meter: Option<istring>)\n : (Flow, Flow)\n {\n (Flow{.logical_datapath = lr_uuid,\ndiff --git a/northd/ovsdb2ddlog2c b/northd/ovsdb2ddlog2c\nindex e489c3c76..fa994c99e 100755\n--- a/northd/ovsdb2ddlog2c\n+++ b/northd/ovsdb2ddlog2c\n@@ -37,6 +37,7 @@ The following ovsdb2ddlog options are supported:\n --ro=TABLE.COLUMN Ignored.\n --rw=TABLE.COLUMN Ignored.\n --intern-table=TABLE Ignored.\n+ --intern-strings Ignored.\n --output-file=FILE.inc Write output to FILE.inc. If this option is not specified, output will be written to stdout.\n \n The following options are also available:\n@@ -56,7 +57,8 @@ if __name__ == \"__main__\":\n 'intern-table=',\n 'ro=',\n 'rw=',\n- 'output-file='])\n+ 'output-file=',\n+ 'intern-strings'])\n except getopt.GetoptError as geo:\n sys.stderr.write(\"%s: %s\\n\" % (argv0, geo.msg))\n sys.exit(1)\n@@ -79,7 +81,7 @@ if __name__ == \"__main__\":\n output_tables.add(value)\n elif key == '--output-only-table':\n output_only_tables.add(value)\n- elif key in ['--ro', '--rw', '--intern-table']:\n+ elif key in ['--ro', '--rw', '--intern-table', '--intern-strings']:\n pass\n elif key == '--output-file':\n output_file = value\ndiff --git a/tests/ovn-ic.at b/tests/ovn-ic.at\nindex 32f4e9d02..7601ebb45 100644\n--- a/tests/ovn-ic.at\n+++ b/tests/ovn-ic.at\n@@ -223,7 +223,13 @@ OVS_WAIT_WHILE([ovn_as az2 ovn-sbctl show | grep lsp-ts1-lr1])\n \n ovn-nbctl set logical_router_port lrp-lr1-ts1 mac=\"\\\"aa:aa:aa:aa:aa:02\\\"\" \\\n networks=\"169.254.100.2/24 169.254.200.3/24\"\n-OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl show | grep \"aa:aa:aa:aa:aa:02 169.254.100.2/24 169.254.200.3/24\"])\n+OVS_WAIT_FOR_OUTPUT([ovn_as az2 ovn-nbctl show | uuidfilt], [0], [dnl\n+switch <0> (ts1)\n+ port lsp-ts1-lr1\n+ type: remote\n+ addresses: [[\"aa:aa:aa:aa:aa:02 169.254.100.2/24 169.254.200.3/24\"]]\n+])\n+\n \n # Delete the router port from az1, the remote port in az2 should still remain\n # but just lost address.\ndiff --git a/tests/ovn.at b/tests/ovn.at\nindex 5104a6895..bf1a3b119 100644\n--- a/tests/ovn.at\n+++ b/tests/ovn.at\n@@ -6150,10 +6150,12 @@ test_dhcp() {\n compare_dhcp_packets() {\n received=$($PYTHON \"$ovs_srcdir/utilities/ovs-pcap.in\" hv1/vif$1-tx.pcap)\n expected=$(cat $1.expected)\n+ echo \"received=$received\"\n+ echo \"expected=$expected\"\n \n if test \"$received\" != \"$expected\"; then\n- AT_CHECK_UNQUOTED([echo \"$received\"; tcpdump_hex \"$received\"], [0],\n- [$(echo \"$expected\"; tcpdump_hex \"$expected\")])\n+ (echo \"$expected\"; tcpdump_hex \"$expected\") > expout\n+ AT_CHECK([echo \"$received\"; tcpdump_hex \"$received\"], [0], [expout])\n fi\n }\n \n", "prefixes": [ "ovs-dev", "v2", "01/10" ] }