From 59f44a00aa4193fa5ecaf50d7b0166e0b55c7ed2 Mon Sep 17 00:00:00 2001 From: "Anish Narsian (from Dev Box)" Date: Thu, 6 Nov 2025 19:13:35 -0800 Subject: [PATCH 1/5] Add Consistent ECMP for vxlan tunnel HLD --- doc/vxlan/Consistent ECMP for Vxlan tunnel.md | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 doc/vxlan/Consistent ECMP for Vxlan tunnel.md diff --git a/doc/vxlan/Consistent ECMP for Vxlan tunnel.md b/doc/vxlan/Consistent ECMP for Vxlan tunnel.md new file mode 100644 index 00000000000..f5a4837bb63 --- /dev/null +++ b/doc/vxlan/Consistent ECMP for Vxlan tunnel.md @@ -0,0 +1,141 @@ +# Consistent ECMP for Vxlan Tunnels + +# Table of Contents + +- [Revision](#revision) +- [Scope](#scope) +- [Overview](#1-overview) +- [Schema Changes](#2-schema-changes) + - [Config and APP DB](#21-config-and-appdb) + - [STATE DB](#22-state-db) + - [CLI](#23-cli) +- [SWSS orchagent design](#3-swss-orchagent-design) +- [Test Plan](#4-test-plan) + + +# Revision + +| Rev | Date | Author | Change Description | +|:---:|:-----------:|:------------------:|-----------------------------------| +| 1.0 | 11/04/2025 | Anish Narsian | Added Consistent hashing support | + + +# Scope + +This document goes over an enhancement to VXLAN tunnel endpoint ECMP to add support for consistent hashing towards a group of tunnel endpoints that are nexthops for a given tunnel route. This is an extension to the existing VNET Vxlan support as defined in the [Vxlan HLD](https://github.com/sonic-net/SONiC/blob/master/doc/vxlan/Vxlan_hld.md) + + +# Abbreviations + +| Abbreviation | Meaning | +|--------------------------|-----------------| +| NH | Next hop | +| NHG | Next hop Group | +| FG | Fine Grained | +| ECMP | Equal Cost MultiPath | + +# 1 Overview +The details for enabling consistent hashing for Vxlan tunnel route(VNET_ROUTE_TUNNEL) are discussed in this document. + +Use-case: + Vxlan tunnel routes can contain a list of endpoints(next-hops) for overlay traffic to be routed to multiple underlay endpoints(next-hops). When there are multiple endpoints, ECMP is used to select the nexthop for this traffic to be encapsulated towards and sent out. This is primarily used in scenarios where throughput needs to be scaled beyond what a single vxlan endpoint is capable of. When these endpoints hold flow state, endpoint modifications(next-hop addition/removal), will result in most flows being rehashed and sent to a different endpoint than what they were originally going to, resulting in connection restart whenever a endpoint modification is performed. To limit connection restarts during endpoint/next hop modifications, we will enable consistent hashing for tunnel nexthops. + +# 2 Schema Changes + +## 2.1 Config and APP DB + +We modify Config DB's **VNET_ROUTE_TUNNEL** and correspondingly APP_DB's **VNET_ROUTE_TUNNEL_TABLE** to support consistent hashing, the schema can be found below: + +The following new fields have been added the **VNET_ROUTE_TUNNEL_TABLE** + - consistent_hashing_buckets + +``` + +VNET_ROUTE_TUNNEL_TABLE:{{vnet_name}}:{{prefix}} + “endpoint”: {{ip_address1},{ip_address2},...} + “endpoint_monitor”: {{ip_address1},{ip_address2},...} (OPTIONAL) + “mac_address”: {{mac_address1},{mac_address2},...} (OPTIONAL) + “monitoring”: {{“custom”}} (OPTIONAL) + “vni”: {{vni1},{vni2},...} (OPTIONAL) + “weight”: {{w1},{w2},...} (OPTIONAL) + “profile”: {{profile_name}} (OPTIONAL) + “primary”: {{ip_address1}, {ip_address2}} (OPTIONAL) + “profile”: {{profile_name}} (OPTIONAL) + “adv_prefix”: {{prefix}} (OPTIONAL) + “rx_monitor_timer”: {time in milliseconds} (OPTIONAL) + “tx_monitor_timer”: {time in milliseconds} (OPTIONAL) + “check_directly_connected”: {{true|false}} (OPTIONAL) + “consistent_hashing_buckets”: {{bucket_size}} (OPTIONAL) -> newly introduced +``` + + +``` +consistent_hashing_buckets = DIGITS ; if specified, consistent hashing will be used for nexthops to the vnet route tunnel, the bucket size should be determined by the caller based on # of nexthops and redundancy factor, which will define how many bucket entries each nexthop receives (Optional) +``` + +## 2.2 STATE DB + +The existing Fine grained ecmp state DB table will be modified to store a VRF/VNET name, so that IP space collisions across VRFs/VNETs can be supported + +``` +FG_ROUTE_TABLE|{{VRF/VNET-name}}|{{IPv4 OR IPv6 prefix}}: + "0": {{next-hop-key}} + "1": {{next-hop-key}} + ... + "{{hash_bucket_size -1}}": {{next-hop-key}} +``` + +## 2.3 CLI +*CLI command enhancement to be able to see consistent hashing buckets for a partricular VRF/VNET and prefix:* + +``` +show fgnhg hash-view +show fgnhg active-hops +``` + +*CLI output format: show fgnhg hash-view * +``` +-----------+-----------------+--------------------+----------------+ +| VNET/VRF | FG_NHG_PREFIX | Next Hop | Hash buckets | +===========+=================+====================+================+ +``` + +*CLI output format: show fgnhg hash-view * +``` +-----------+-----------------+--------------------+ +| VNET/VRF | FG_NHG_PREFIX | Active Next Hops | +===========+=================+====================+ +``` + +# 3 SWSS orchagent design +1. vnetorch will receive a call to create a VNET_ROUTE_TUNNEL_TABLE +2. vnetorch will check if consistent_hashing_buckets is set and if so call fgnhgorch to create internal FgNhgEntry with the following parameters: +2.a FGMatchMode will be PREFIX_BASED +2.b max_next_hops = configured_bucket_size = consistent_hashing_buckets +2.c The prefix for Fine grained behavior = prefix of the VNET_ROUTE_TUNNEL_TABLE +3. Next, vnetorch will call fgnhgorch to do the nexthop group creation with consistent hashing +4. For subsequent next-hop changes, vnetorch will continue calling fgnhgorch to handle the nexthop changes +5. At the time of VNET_ROUTE_TUNNEL_TABLE deletion, the nexthop and the internal FgNhgEntry will be deleted/cleaned up +6. For VNET_ROUTE_TUNNEL_TABLE modification where “consistent_hashing_buckets” is added for an existing tunnel route a transition from non fine grained to fine grained ecmp must occur and when “consistent_hashing_buckets” is removed then a transition from fine grained to non fine grained ecmp occurs. Both of these transitions result in a sai route update with new nexthop group/nexthop along with deleting any left over stale nexthop groups. + + +# 4 Test Plan for the enhacements +The following testing is planned for this feature: +- SWSS unit tests via virtual switch testing +- Data Plane tests via pytest + PTF + + +## SWSS unit tests: +1. Add VNET_ROUTE_TUNNEL_TABLE with consistent_hashing_buckets, and check that SAI objects are created for next-hop group and next-hop group member as fine grained ecmp +2. Remove endpoint in VNET_ROUTE_TUNNEL_TABLE, and ensure that only the next-hop group member associated with the removed endpoint is modified with another nexthop tunnel, and that the hash buckets are balanced +3. Add endpoint in VNET_ROUTE_TUNNEL_TABLE, and ensure that only total hash buckets/total endpoints buckets are impacted as a result of the change +4. Remove consistent_hashing_buckets paramater from VNET_ROUTE_TUNNEL_TABLE, and ensure that the fine grained next-hop group is cleaned up and a regular next-hop group is created, with the route pointing to the regular next-hop group +5. Add consistent_hashing_buckets paramater to VNET_ROUTE_TUNNEL_TABLE, and ensure that a fine grained next-hop group is created and the original regular next-hop group is cleaned up, with the route pointing to the fine grained next-hop group + +## Dataplane tests: +1. Do a base setup with VXLAN_TUNNEL, VNET, interface binded to the vnet +2. Add VNET_ROUTE_TUNNEL_TABLE with consistent_hashing_buckets, with 10 endpoints +3. Send 1000 unique flows and check that the resultant packet which goes out of the DUT contains varying outer dst IPs, track the flow to outer dst IP +4. Modify VNET_ROUTE_TUNNEL_TABLE to remove 1 endpoint IP, check that the only flows impacted in the 1000 unique flow to outer dst IP mapping are the ones associated with the withdrawn endpoint +5. Modify VNET_ROUTE_TUNNEL_TABLE to add 1 endpoint IP, check that only a small % of flows, ie <10% are impacted by this endpoint addition. +6. Validate that in all cases the flow distribution per endpoint is roughly equal \ No newline at end of file From a92533a292ff6e3b3a3937f35fdd3e50818a1ba8 Mon Sep 17 00:00:00 2001 From: "Anish Narsian (from Dev Box)" Date: Sun, 16 Nov 2025 15:39:54 -0800 Subject: [PATCH 2/5] Add images for programming flow --- doc/vxlan/Consistent ECMP for Vxlan tunnel.md | 16 ++++++++++++---- .../vxlan_hld/CreateTunnelConsistentHashing.png | Bin 0 -> 38914 bytes .../vxlan_hld/UpdateTunnelConsistentHashing.png | Bin 0 -> 34812 bytes 3 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 images/vxlan_hld/CreateTunnelConsistentHashing.png create mode 100644 images/vxlan_hld/UpdateTunnelConsistentHashing.png diff --git a/doc/vxlan/Consistent ECMP for Vxlan tunnel.md b/doc/vxlan/Consistent ECMP for Vxlan tunnel.md index f5a4837bb63..d7c556532be 100644 --- a/doc/vxlan/Consistent ECMP for Vxlan tunnel.md +++ b/doc/vxlan/Consistent ECMP for Vxlan tunnel.md @@ -9,8 +9,9 @@ - [Config and APP DB](#21-config-and-appdb) - [STATE DB](#22-state-db) - [CLI](#23-cli) -- [SWSS orchagent design](#3-swss-orchagent-design) -- [Test Plan](#4-test-plan) +- [Programming Flow](#3-programming-flow) +- [SWSS orchagent design](#4-swss-orchagent-design) +- [Test Plan](#5-test-plan) # Revision @@ -107,7 +108,14 @@ show fgnhg active-hops ===========+=================+====================+ ``` -# 3 SWSS orchagent design +# 3 Programming flow +*E2E creation flow for VNET_ROUTE_TUNNEL with consistent hashing* +![](../../images/vxlan_hld/CreateTunnelConsistentHashing.png) + +*E2E flow for updating tunnel endpoints list with consistent hashing* +![](../../images/vxlan_hld/UpdateTunnelConsistentHashing.png) + +# 4 SWSS orchagent design 1. vnetorch will receive a call to create a VNET_ROUTE_TUNNEL_TABLE 2. vnetorch will check if consistent_hashing_buckets is set and if so call fgnhgorch to create internal FgNhgEntry with the following parameters: 2.a FGMatchMode will be PREFIX_BASED @@ -119,7 +127,7 @@ show fgnhg active-hops 6. For VNET_ROUTE_TUNNEL_TABLE modification where “consistent_hashing_buckets” is added for an existing tunnel route a transition from non fine grained to fine grained ecmp must occur and when “consistent_hashing_buckets” is removed then a transition from fine grained to non fine grained ecmp occurs. Both of these transitions result in a sai route update with new nexthop group/nexthop along with deleting any left over stale nexthop groups. -# 4 Test Plan for the enhacements +# 5 Test Plan for the enhacements The following testing is planned for this feature: - SWSS unit tests via virtual switch testing - Data Plane tests via pytest + PTF diff --git a/images/vxlan_hld/CreateTunnelConsistentHashing.png b/images/vxlan_hld/CreateTunnelConsistentHashing.png new file mode 100644 index 0000000000000000000000000000000000000000..509cd8d8b9ea409d7f7411d57967015bb82f54e2 GIT binary patch literal 38914 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 literal 0 HcmV?d00001 diff --git a/images/vxlan_hld/UpdateTunnelConsistentHashing.png b/images/vxlan_hld/UpdateTunnelConsistentHashing.png new file mode 100644 index 0000000000000000000000000000000000000000..119629599d9ac6971b48f2c8f4c8ae28ad9779a2 GIT binary patch literal 34812 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 VQf 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 literal 0 HcmV?d00001 From 66fe2c625b3f5854017885b294945abf09f37f99 Mon Sep 17 00:00:00 2001 From: "Anish Narsian (from Dev Box)" Date: Sun, 16 Nov 2025 15:56:21 -0800 Subject: [PATCH 3/5] Add scale details --- doc/vxlan/Consistent ECMP for Vxlan tunnel.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/vxlan/Consistent ECMP for Vxlan tunnel.md b/doc/vxlan/Consistent ECMP for Vxlan tunnel.md index d7c556532be..18cf8e5a58e 100644 --- a/doc/vxlan/Consistent ECMP for Vxlan tunnel.md +++ b/doc/vxlan/Consistent ECMP for Vxlan tunnel.md @@ -32,15 +32,21 @@ This document goes over an enhancement to VXLAN tunnel endpoint ECMP to add supp |--------------------------|-----------------| | NH | Next hop | | NHG | Next hop Group | +| NHGM | Next hop Group Member | | FG | Fine Grained | | ECMP | Equal Cost MultiPath | # 1 Overview The details for enabling consistent hashing for Vxlan tunnel route(VNET_ROUTE_TUNNEL) are discussed in this document. -Use-case: +###### Use-case: Vxlan tunnel routes can contain a list of endpoints(next-hops) for overlay traffic to be routed to multiple underlay endpoints(next-hops). When there are multiple endpoints, ECMP is used to select the nexthop for this traffic to be encapsulated towards and sent out. This is primarily used in scenarios where throughput needs to be scaled beyond what a single vxlan endpoint is capable of. When these endpoints hold flow state, endpoint modifications(next-hop addition/removal), will result in most flows being rehashed and sent to a different endpoint than what they were originally going to, resulting in connection restart whenever a endpoint modification is performed. To limit connection restarts during endpoint/next hop modifications, we will enable consistent hashing for tunnel nexthops. +###### Scale: +| Component | Expected value | +|--------------------------|-----------------------------| +| NHG size| 512 - 2048 next hop group members(NHGMs) | + # 2 Schema Changes ## 2.1 Config and APP DB From c6f66d58f44719a4ad00444535a91e5217b35b88 Mon Sep 17 00:00:00 2001 From: Anish Narsian <44376847+anish-n@users.noreply.github.com> Date: Mon, 24 Nov 2025 11:24:22 -0800 Subject: [PATCH 4/5] Add yang model Added YANG model enhancements for VNET_ROUTE_TUNNEL, including modifications for endpoints, MAC addresses, VNIs, and new field consistent hashing buckets. --- doc/vxlan/Consistent ECMP for Vxlan tunnel.md | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/doc/vxlan/Consistent ECMP for Vxlan tunnel.md b/doc/vxlan/Consistent ECMP for Vxlan tunnel.md index 18cf8e5a58e..70d63a1802e 100644 --- a/doc/vxlan/Consistent ECMP for Vxlan tunnel.md +++ b/doc/vxlan/Consistent ECMP for Vxlan tunnel.md @@ -9,6 +9,7 @@ - [Config and APP DB](#21-config-and-appdb) - [STATE DB](#22-state-db) - [CLI](#23-cli) + - [YANG model](#24-yang-model) - [Programming Flow](#3-programming-flow) - [SWSS orchagent design](#4-swss-orchagent-design) - [Test Plan](#5-test-plan) @@ -114,6 +115,48 @@ show fgnhg active-hops ===========+=================+====================+ ``` +## 2.4 YANG Model +The following enhancements to the VNET_ROUTE_TUNNEL YANG model will be made, specifically endpoints, mac and vni are converted into a comma separated list as a string type, and consistent_hashing_buckets is added: + +``` + container VNET_ROUTE_TUNNEL { + description "ConfigDB VNET_ROUTE_TUNNEL table"; + + list VNET_ROUTE_TUNNEL_LIST { + key "vnet_name prefix"; + leaf vnet_name { + description "VNET name"; + type leafref { + path "/svnet:sonic-vnet/svnet:VNET/svnet:VNET_LIST/svnet:name"; + } + } + + leaf prefix { + description "IPv4 prefix in CIDR format"; + type stypes:sonic-ip4-prefix; + } + + leaf endpoint { + description "Comma separated list of endpoint/next hop tunnel IPs if multiple nexthops, or a single IP address"; + type string; + mandatory true; + } + leaf mac_address { + description "Comma separated list of inner dest mac in encapsulated packet if there are multiple nexthops/endpoints, or a single mac address"; + type string; + } + leaf vni { + description "Comma separated list of VNIs if there are multiple nexthops/endpoints, or a single VNI for the route/nh"; + type string; + } + leaf consistent_hashing_buckets { + description "Number of consistent hashing buckets to use, if consistent hashing is desired"; + type unit16; + } + } + } +``` + # 3 Programming flow *E2E creation flow for VNET_ROUTE_TUNNEL with consistent hashing* ![](../../images/vxlan_hld/CreateTunnelConsistentHashing.png) @@ -152,4 +195,4 @@ The following testing is planned for this feature: 3. Send 1000 unique flows and check that the resultant packet which goes out of the DUT contains varying outer dst IPs, track the flow to outer dst IP 4. Modify VNET_ROUTE_TUNNEL_TABLE to remove 1 endpoint IP, check that the only flows impacted in the 1000 unique flow to outer dst IP mapping are the ones associated with the withdrawn endpoint 5. Modify VNET_ROUTE_TUNNEL_TABLE to add 1 endpoint IP, check that only a small % of flows, ie <10% are impacted by this endpoint addition. -6. Validate that in all cases the flow distribution per endpoint is roughly equal \ No newline at end of file +6. Validate that in all cases the flow distribution per endpoint is roughly equal From ba84d682a670b7496d0d0a8e062a04ed7f6c71bd Mon Sep 17 00:00:00 2001 From: Anish Narsian <44376847+anish-n@users.noreply.github.com> Date: Mon, 24 Nov 2025 13:29:07 -0800 Subject: [PATCH 5/5] Update fine_grained_next_hop_hld --- doc/ecmp/fine_grained_next_hop_hld.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/ecmp/fine_grained_next_hop_hld.md b/doc/ecmp/fine_grained_next_hop_hld.md index 389fe8b40b8..c90b88dfafd 100644 --- a/doc/ecmp/fine_grained_next_hop_hld.md +++ b/doc/ecmp/fine_grained_next_hop_hld.md @@ -43,6 +43,7 @@ | 1.3 | 10/23/2020 | Anish Narsian | Interface nh oper state handler | | 1.4 | 12/21/2020 | Anish Narsian | Match Mode changes | | 1.5 | 09/16/2024 | Ashutosh Agrawal/Manas Mandal | Added prefix-based match mode | +| 1.6 | 11/24/2025 | Anish Narsian | VNET_TUNNEL_ROUTE consistent hashing | # About this Manual This document provides the high level design for the Fine Grained ECMP feature implementation in SONiC @@ -90,6 +91,9 @@ Phase #1 Phase #2 - CLI commands to configure Fine Grained ECMP +Phase #3: +- Ability to enable consistent hashing for Vxlan tunnel next hops(https://github.com/sonic-net/SONiC/pull/2099/files) + ## 1.2 Orchagent requirements ### FgNhg orchagent: - Should be able to create Fine Grained Next-hop groups @@ -99,6 +103,9 @@ Phase #2 ### Route orchagent: - Should be able to redirect route and next-hop modifications to fgNhg orchagent for prefixes or next-hops which have a Fine Grained definition +### Vnet orchagent: + - Should be able to redirect vxlan tunnel nexthop group creation and modification to fgNhg orchagent for prefixes which require Fine Grained behavior, more details https://github.com/sonic-net/SONiC/pull/2099/files + ## 1.3 CLI requirements - User should be able to add/delete/view Fine Grained Next-hop groups - User should be able to view the configured state of fine grained groups @@ -169,7 +176,7 @@ Please refer to the [schema](https://github.com/sonic-net/sonic-swss/blob/master Following new table will be added to State DB. Unless otherwise stated, the attributes are mandatory. FG_ROUTE_TABLE is used for some of the show commands associated with this feature as well as for warm boot support. ``` -FG_ROUTE_TABLE|{{IPv4 OR IPv6 prefix}}: +FG_ROUTE_TABLE|{{VRF/VNET-name}}|{{IPv4 OR IPv6 prefix}}: "0": {{next-hop-key}} "1": {{next-hop-key}} ... @@ -180,7 +187,7 @@ FG_ROUTE_TABLE|{{IPv4 OR IPv6 prefix}}: ### 2.2.1 StateDB Schemas ``` ; Defines schema for FG ROUTE TABLE state db attributes -key = FG_ROUTE_TABLE|{{IPv4 OR IPv6 prefix}} ; Prefix associated with this route +key = FG_ROUTE_TABLE|{{VRF/VNET-name}}|{{IPv4 OR IPv6 prefix}} ; VNET/VRF and Prefix associated with this route ; field = value INDEX = next-hop-key ; index in hash bucket associated with the next-hop-key(IP addr,if alias) ``` @@ -320,6 +327,8 @@ Following orchagents shall be modified. Flow diagrams are captured in a later se The overall data flow diagram is captured in Section 3 for all TABLE updates. Refer to section 4 for detailed information about redistribution performed during runtime scenarios. +### vnetorch +This is the swss orchestrator which receives VNET_ROUTE_TUNNEL_TABLE entires along with a need to configure consistent hashing, vnetorch will check if consistent_hashing_buckets is set in the kv pairs and if so call fgnhgorch to create an internal FgNhgEntry and the SAI nexthop group and group members, vnetorch will also assoicate the fine grained ecmp nexthop group with a route. More details https://github.com/sonic-net/SONiC/pull/2099/files ## 2.5 SAI The below table represents main SAI attributes which shall be used for Fine Grained ECMP @@ -350,6 +359,7 @@ The below table represents main SAI attributes which shall be used for Fine Grai - A guideline for the hash bucket size is to define a bucket size which will allow equal distribution of traffic regardless of the number of next-hops which are active. For example with 2 Firewall sets, each set containing 3 firewall members: each set can have equal redistribution by finding the lowest common multiple of 3 next-hops which is 3x2x1(this is equivalent to us saying that if there were 3 or 2 or 1 next-hop active, we could distribute the traffic equally amongst the next-hops). With 2 such sets we get a total of 3x2x1 + 3x2x1 = 12 hash buckets. - fgnhgorch is an observer for SUBJECT_TYPE_PORT_OPER_STATE_CHANGE events, these events are used in conjunction with the IP to interface mapping(INTERFACE attribute of the FG NHG member table), to trigger next-hop withdrawal/addition depending on which interface's operational state transitioned to down/up. The next-hop withdrawal/addition is performed per consistent and layered hashing rules. The INTERFACE attribute is optional, so this functionality is activated based on user configuration. - There are 2 match_modes supported for Fine Grained ECMP. A nexthop-based match mode implies that all prefixes that have next-hop IPs as a subset of the FG_NHG_MEMBER nh IPs defined by the user, will get Fine Grained ECMP behavior. If a route has next-hops which don't have an equivalent FG_NHG_MEMBER, then the route will get regular ECMP/next-hop behavior. A route-based match mode implies that only those prefixes which have FG_NHG_PREFIX defined will get Fine Grained ECMP behavior. The example configuration section has examples of both config types. +- Details for VNET_ROUTE_TUNNEL with fine grained ecmp can be found in https://github.com/sonic-net/SONiC/pull/2099/files # 5 Example configuration @@ -559,3 +569,4 @@ Test details: - Test both IPv4 and IPv6 above - The above test is configured via config_db entries directly, a further test mode to configure Fine Grained ECMP via minigraph will be present and tested - Test warm reboot to ensure there is no traffic disruption and ECMP groups are correctly applied post warm boot +