diff --git a/doc/config-generic-update-rollback/Json_Change_Application_Design.md b/doc/config-generic-update-rollback/Json_Change_Application_Design.md
new file mode 100644
index 0000000000..d28267120c
--- /dev/null
+++ b/doc/config-generic-update-rollback/Json_Change_Application_Design.md
@@ -0,0 +1,400 @@
+# JSON Change Application
+
+# High Level Design Document
+
+#### Rev 0.1
+
+# Table of Contents
+- [Table of Contents](#table-of-contents)
+- [List of Tables](#list-of-tables)
+- [Revision](#revision)
+- [About this Manual](#about-this-manual)
+- [Scope](#scope)
+- [Definition/Abbreviation](#definition-abbreviation)
+ + [Table 1: Abbreviations](#table-1--abbreviations)
+- [1 Feature Overview](#1-feature-overview)
+ * [1.1 Requirements](#11-requirements)
+ + [1.1.1 Functional Requirements](#111-functional-requirements)
+ + [1.1.2 Configuration and Management Requirements](#112-configuration-and-management-requirements)
+ + [1.1.3 Scalability Requirements](#113-scalability-requirements)
+ + [1.1.4 Warm Boot Requirements](#114-warm-boot-requirements)
+ * [1.2 Design Overview](#12-design-overview)
+ + [1.2.1 Basic Approach](#121-basic-approach)
+- [2 Functionality](#2-functionality)
+ * [2.1 Target Deployment Use Cases](#21-target-deployment-use-cases)
+ * [2.2 Functional Description](#22-functional-description)
+ + [Stage-1 Generating Diff from JsonChange](#stage-1-generating-diff-from-jsonchange)
+ + [Stage-2 Update Table by Table in Alphabetical order](#stage-2-update-table-by-table-in-alphabetical-order)
+ + [Stage-3 Post-update Validation](#stage-3-post-update-validation)
+ - [Fail-safe Action](#fail-safe-action)
+ - [Logging](#logging)
+- [3 Design](#3-design)
+ * [3.1 Overview](#31-overview)
+ + [3.1.1 SONiC CLI](#311-sonic-cli)
+ + [3.1.2 Change Applier](#312-change-applier)
+ + [3.1.3 Metadata](#313-metadata)
+ + [3.1.4 Services](#314-services)
+ + [3.1.5 ConfigDB](#315-configdb)
+ * [3.2 User Interface](#32-user-interface)
+ + [3.2.1 Data Models](#321-data-models)
+ - [3.2.1.1 JsonChange](#3211-jsonchange)
+ - [3.2.1.2 Metadata](#3212-metadata)
+ + [3.2.2 CLI](#322-cli)
+- [4 Flow Diagrams](#4-flow-diagrams)
+- [5 Error Handling](#5-error-handling)
+- [6 Serviceability and Debug](#6-serviceability-and-debug)
+- [7 Warm Boot Support](#7-warm-boot-support)
+- [8 Scalability](#8-scalability)
+- [9 Unit Tests](#9-unit-tests)
+
+# List of Tables
+[Table 1: Abbreviations](#table-1-abbreviations)
+
+# Revision
+
+| Rev | Date | Author | Change Description |
+|:---:|:-----------:|:------------------:|---------------------|
+| 0.1 | 03/01/2021 | Mohamed Ghoneim | Initial version |
+
+# About this Manual
+This document provides a detailed description on the algorithm to implement JsonChange application described in [SONiC Generic Configuration Update and Rollback - HLD](SONiC_Generic_Config_Update_and_Rollback_Design.md#3115-change-applier)
+
+# Scope
+This document describes the algorithm of patch ordering described in [SONiC Generic Configuration Update and Rollback - HLD](SONiC_Generic_Config_Update_and_Rollback_Design.md#3115-change-applier) using YANG models. This document provides minor implementation details about the proposed solutions.
+
+# Definition/Abbreviation
+
+### Table 1: Abbreviations
+| **Term** | **Meaning** |
+| ------------------- | -------------------------- |
+| JsonPatch | JSON document structure for expressing a sequence of operations to apply to a JavaScript Object Notation (JSON) document. Check [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902). |
+| JsonChange | JsonChange is a JsonPatch in terms of the final outcome of the update. Ordering of JsonChange updates will not follow the operations order within a JsonPatch, but will update the JSON file in any arbitrary order. Check [JsonChange](SONiC_Generic_Config_Update_and_Rollback_Design.md#31141-jsonchange) for details. |
+
+# 1 Feature Overview
+Currently there is no unified interface on top of ConfigDB for updating table entries and making sure the changes are absorbed correctly by corresponding applications. Today there is 2 different ways SONiC applications absorb the configs.
+
+The first group of SONiC applications subscribe to ConfigDB change events, and absorb the changes automatically in parallel fashion. Since these applications absorb the changes in parallel of the ConfigDB updates, there is no easy way to verify if they absorbed the ConfigDB changes correctly.
+
+The second group of SONiC applications store its configuration in ConfigDB but do not subscribe to the ConfigDB change events. So any changes to their corresponding table entries in ConfigDB are not processed by the application immediately. In order to apply the configuration changes, corresponding service needs to be restarted. See below table for an example.
+
+```
+{
+ "SYSLOG_SERVER": ["rsyslog"],
+ "DHCP_SERVER": ["dhcp_relay"],
+ "NTP_SERVER": ["ntp-config.service", "ntp.service"],
+ "BGP_MONITORS": ["bgp"],
+ "BUFFER_PROFILE": ["swss"],
+ "RESTAPI": ["restapi"]
+}
+```
+
+An interface was introduced in [SONiC_Generic_Config_Update_and_Rollback_Design.md](SONiC_Generic_Config_Update_and_Rollback_Design.md#3115-change-applier) to address this issue. The interface will take care of:
+- Updating ConfigDB entries
+- Verifying changes are absorbed correctly by SONiC applications
+
+In this design document, we are going to discuss an approach to implement this interface.
+
+## 1.1 Requirements
+
+### 1.1.1 Functional Requirements
+- The input is a JsonChange and is described in [JsonChange](SONiC_Generic_Config_Update_and_Rollback_Design.md#31141-jsonchange).
+- The API has no return, and rely on raised errors to check for any problems while execution.
+- As per the definition of [JsonChange](SONiC_Generic_Config_Update_and_Rollback_Design.md#31141-jsonchange) ordering of the update is arbitrary and can be decided by the implementation.
+- It is assumed that the configuration lock was acquired before applying any changes to ConfigDB.
+
+### 1.1.2 Configuration and Management Requirements
+N/A
+
+### 1.1.3 Scalability Requirements
+N/A
+
+### 1.1.4 Warm Boot Requirements
+N/A
+
+## 1.2 Design Overview
+
+### 1.2.1 Basic Approach
+From [SONiC Generic Configuration Update and Rollback - HLD](SONiC_Generic_Config_Update_and_Rollback_Design.md#3115-change-applier), this is the target interface:
+
+```python
+void apply-change(JsonChange jsonChange)
+```
+
+|aspect |item |description
+|------------|-----------------------|-----------
+|inputs |JsonChange | It represents the changes that needs to applied to the device running config, described in [SONiC_Generic_Config_Update_and_Rollback_Design](SONiC_Generic_Config_Update_and_Rollback_Design.md#31141-jsonchange).
+|outputs |None |
+|errors |malformedChangeError | Will be raised if the input JsonChange is not valid according to [SONiC_Generic_Config_Update_and_Rollback_Design](SONiC_Generic_Config_Update_and_Rollback_Design.md#31141-jsonchange).
+| |other errors | Check [SONiC_Generic_Config_Update_and_Rollback_Design](SONiC_Generic_Config_Update_and_Rollback_Design.md#31141-apply-change) for exact list of errors to expect.
+|side-effects|updating running-config| This operation will cause changes to the running-config according to the input JsonChange.
+|assumptions |running-config locked| The implementor of this contract will interact with ConfigDB to updating the running-config, it is assumed the running-config is locked for changes for the lifespan of the operation.
+
+The important constraint in the above interface is the JsonChange, where ordering of applying the modifications is arbitrary.
+
+Let's take an example, assume the following is the running config:
+```json
+{
+ "DEVICE_NEIGHBOR": {
+ "Ethernet8": {
+ "name": "Servers1",
+ "port": "eth0"
+ },
+ "Ethernet80": {
+ "name": "Servers19",
+ "port": "eth0"
+ }
+ },
+ "DHCP_SERVER": {
+ "192.0.0.1": {},
+ "192.0.0.2": {}
+ },
+}
+```
+
+And the JsonChange is represented by the the following JsonPatch operations:
+```json
+[
+ { "op": "remove", "path": "/DHCP_SERVER/192.0.0.2" },
+ { "op": "add", "path": "/DHCP_SERVER/192.0.0.3", "value": {} },
+ { "op": "replace", "path": "/DEVICE_NEIGHBOR/Ethernet8/port", "value": "eth1" },
+ { "op": "replace", "path": "/DEVICE_NEIGHBOR/Ethernet80", "value": { "name": "Servers19", "port": "eth1" } }
+]
+```
+
+Then target config after applying JsonChange will be:
+```json
+{
+ "DEVICE_NEIGHBOR": {
+ "Ethernet8": {
+ "name": "Servers1",
+ "port": "eth1"
+ },
+ "Ethernet80": {
+ "name": "Servers19",
+ "port": "eth1"
+ }
+ },
+ "DHCP_SERVER": {
+ "192.0.0.1": {},
+ "192.0.0.3": {}
+ },
+}
+```
+
+The diff between target config and running config is:
+```diff
+ {
+ "DEVICE_NEIGHBOR": {
+ "Ethernet8": {
+ "name": "Servers1",
+- "port": "eth0"
++ "port": "eth1"
+ },
+ "Ethernet80": {
+ "name": "Servers19",
+- "port": "eth0"
++ "port": "eth1"
+ }
+ },
+ "DHCP_SERVER": {
+ "192.0.0.1": {},
+- "192.0.0.2": {}
++ "192.0.0.3": {}
+ },
+ }
+```
+
+There can be many ways to fix this config, let's express the modifications as JsonPatch operations for simplicity.
+
+The update can execute the following steps:
+```json
+[
+ { "op": "replace", "path": "/DEVICE_NEIGHBOR/Ethernet8/port", "value": "eth1" },
+ { "op": "replace", "path": "/DEVICE_NEIGHBOR/Ethernet80/port", "value": "eth1" },
+ { "op": "remove", "path": "/DHCP_SERVER/192.0.0.2" },
+ { "op": "add", "path": "/DHCP_SERVER/192.0.0.3", "value": {} }
+]
+```
+
+Or it can be updated using the following steps:
+```json
+ { "op": "remove", "path": "/DHCP_SERVER/192.0.0.2" },
+ { "op": "replace", "path": "/DEVICE_NEIGHBOR/Ethernet8/port", "value": "eth1" },
+ { "op": "replace", "path": "/DEVICE_NEIGHBOR/Ethernet80/port", "value": "eth1" },
+ { "op": "add", "path": "/DHCP_SERVER/192.0.0.3", "value": {} },
+```
+
+Applying JsonChange is all about the running config being converted to the target config, the steps to update can be arbitrary and are decided by the implementor of the `apply-change` interface.
+
+Our current design documents will use the "Table" as the main granular element of update. We will update "Table" by "Table" in alphabetical order. Each table update will take care of updating table entries in ConfigDB, restarting services if needed and verifying services have absorbed
+
+# 2 Functionality
+
+## 2.1 Target Deployment Use Cases
+
+This is going to be part of the `apply-patch` functionality described in [SONiC Generic Configuration Update and Rollback - HLD](SONiC_Generic_Config_Update_and_Rollback_Design.md)
+
+## 2.2 Functional Description
+
+The `apply-change` operation can be broadly classified into the following steps
+
+### Stage-1 Generating Diff from JsonChange
+SONiC current ConfigDB contents can be retrieved in a JSON file format. The JsonChange will be applied to the current config to generate the target config. The diff between target config and current config will be the main focus of the `change-applier`.
+
+### Stage-2 Update Table by Table in Alphabetical order
+Table entries will be update using ConfigDBConnector. Service corresponding to each table will restarted if they are not listening to ConfigDB changes. Services corresponding to each table will be verified that they have absorbed the changes correctly.
+
+Continuation to the example in [1.2.1 Basic Approach](#1.2.1-Basic-Approach), the update will do the following:
+1. Process tables in alphabetical order which is `DEVICE_NEIGHBOR` and then `DHCP_SERVER`
+2. Update table `DEVICE_NEIGHBOR`
+
+ a. Update table entries as such
+ ```diff
+ "DEVICE_NEIGHBOR": {
+ "Ethernet8": {
+ "name": "Servers1",
+ - "port": "eth0"
+ + "port": "eth1"
+ },
+ "Ethernet80": {
+ "name": "Servers19",
+ - "port": "eth0"
+ + "port": "eth1"
+ }
+ ```
+ b. Restart services associated with `DEVICE_NEIGHBOR` if not listening to ConfigDB changes
+
+ c. Verify services associated with `DEVICE_NEIGHBOR` have absorbed the changes correctly
+3. Update table `DHCP_SERVER`
+
+ a. Update table entries as such
+ ```diff
+ {
+ "DHCP_SERVER": {
+ "192.0.0.1": {},
+ - "192.0.0.2": {}
+ + "192.0.0.3": {}
+ }
+ }
+ ```
+ b. Restart services associated with `DHCP_SERVER` if not listening to ConfigDB changes
+
+ c. Verify services associated with `DHCP_SERVER` have absorbed the changes correctly
+
+### Stage-3 Post-update Validation
+The expectations after applying the JsonChange is that there will be no diff.
+
+The verification steps:
+1. Get the state of ConfigDB JSON before the update as a JSON object
+2. Compare that Target JSON object generated in Stage-1 with current ConfigDB JSON
+3. In case of mismatch, just report failure
+
+#### Fail-safe Action
+
+If an error is encountered during the `apply-change` operation, an error is reported and the system DOES NOT take any automatic action.
+
+#### Logging
+
+All the configuration update operations executed are stored in the systemd journal. They are also forwarded to the syslog. By storing the commands in the systemd-journal, the user will be able to search and display them easily at a later point in time.
+
+# 3 Design
+
+## 3.1 Overview
+
+
+### 3.1.1 SONiC CLI
+These are the CLI of SONiC switch to which makes it easy for the users to interact with the system. The CLI command we are interested in is `apply-patch` which will call `apply-change`. For further details check [SONiC_Generic_Config_Update_and_Rollback_Design](SONiC_Generic_Config_Update_and_Rollback_Design.md#311-applypatch).
+
+### 3.1.2 Change Applier
+This component provides an implementation of the interface `apply-change` discussed in [SONiC_Generic_Config_Update_and_Rollback_Design](SONiC_Generic_Config_Update_and_Rollback_Design.md#31151-apply-change).
+
+### 3.1.3 Metadata
+Metadata component contains info about which services correspond to which table. For each service it contains the CLI command used to manually restart the service, it also contains the CLI command used to verify the service has absorbed the change correctly.
+
+### 3.1.4 Services
+These are the SONiC services such as rsyslog, dhcp_relay, ntp-config.service, ntp.service, bgp, swss, restapi..etc.
+
+The 3 dots (`...`) in `ValidateService(services, validationCommand, ...)` indicate other parameters can be passed to help with detailed validation such as ConfigDB as JSON before and after the update.
+
+### 3.1.5 ConfigDB
+SONiC is managing configuration in a single source of truth - a redisDB instance that we refer as ConfigDB. Applications subscribe to ConfigDB and generate their running configuration correspondingly.
+
+For further details on the ConfigDB, check [SONiC Configuration Database Manual](https://github.com/Azure/SONiC/wiki/Configuration).
+
+## 3.2 User Interface
+N/A
+
+### 3.2.1 Data Models
+#### 3.2.1.1 JsonChange
+check [JsonChange](SONiC_Generic_Config_Update_and_Rollback_Design.md#31141-jsonchange)
+#### 3.2.1.2 Metadata
+
+A new file will be added to the system which will contain the `apply-change` metadata.
+
+The format of the file would be:
+```
+{
+ "tables: {
+ "": {
+ "services-to-restart": ["", "" ...],
+ "services-to-validate": ["", "" ...]
+ },
+ .
+ .
+ .
+ },
+ "services": {
+ "": {
+ "restart-command": "",
+ "validate-commands": ", , ..."
+ },
+ .
+ .
+ .
+ }
+}
+```
+
+The document contain info describing for each table the services that needs restarting and the services that do not need restarting. It also describes for each service the command needed to manually restart the service, and the command for validating the service have absorbed ConfigDB changes successfully.
+
+- tables - contains all the information need for the tables.
+- TABLE-NAME - The table name corresponding to tables from ConfigDB, will contain all the tables metadata. There can be multiple different TABLE-NAME keys/dictionaries.
+- services-to-restart - The list of services to restart after updating the current table. There can be multiple services to restart.
+- services-to-validate - The list of services to that needs validation after an update, it will be mainly the services that absorb changes automatically. There can be multiple services to validate.
+- services - contains all the information needed for the services.
+- SERVICE-NAME - The service name corresponding to services running on SONiC box, will contain all the services metadata. There can be multiple different SERVICE-NAME keys/dictionaries.
+- restart-command - The CLI command used to restart the corresponding service.
+- validate-commands - Multiple CLI commands used to validate the service has absorbed the change successfully. The validate commands can expect the config before and after the update to passed to the CLI commands for detailed validation if needed.
+
+### 3.2.2 CLI
+N/A
+
+# 4 Flow Diagrams
+N/A
+
+# 5 Error Handling
+
+Check [SONiC_Generic_Config_Update_and_Rollback_Design](SONiC_Generic_Config_Update_and_Rollback_Design.md#3115-change-applier) for formal list of errors defined for the interface `apply-change`.
+
+# 6 Serviceability and Debug
+All commands logs are stored in systemd-journal and syslog.
+
+# 7 Warm Boot Support
+N/A
+
+# 8 Scalability
+N/A
+
+# 9 Unit Tests
+| Test Case | Description |
+| --------- | ----------- |
+| 1 | Add a new table. |
+| 2 | Remove an existing table. |
+| 3 | Modify values of an existing table entry. |
+| 4 | Modify value of an existing item of an array value. |
+| 5 | Add a new item to an array value. |
+| 6 | Remove an item form an array value. |
+| 7 | Add a new key to an existing table .|
+| 8 | Remove a key from an existing table. |
+| 9 | Replace a mandatory item e.g. type under ACL_TABLE. |
+| 10 | Remove an item that has a default value e.g. stage under ACL_TABLE. |
diff --git a/doc/config-generic-update-rollback/Json_Patch_Ordering_using_YANG_Models_Design.md b/doc/config-generic-update-rollback/Json_Patch_Ordering_using_YANG_Models_Design.md
new file mode 100644
index 0000000000..969863c107
--- /dev/null
+++ b/doc/config-generic-update-rollback/Json_Patch_Ordering_using_YANG_Models_Design.md
@@ -0,0 +1,698 @@
+# JSON Patch Ordering using YANG Models
+
+# High Level Design Document
+
+#### Rev 0.1
+
+# Table of Contents
+- [Table of Contents](#table-of-contents)
+- [List of Tables](#list-of-tables)
+- [Revision](#revision)
+- [About this Manual](#about-this-manual)
+- [Scope](#scope)
+- [Definition/Abbreviation](#definition-abbreviation)
+ + [Table 1: Abbreviations](#table-1--abbreviations)
+- [1 Feature Overview](#1-feature-overview)
+ * [1.1 Requirements](#11-requirements)
+ + [1.1.1 Functional Requirements](#111-functional-requirements)
+ + [1.1.2 Configuration and Management Requirements](#112-configuration-and-management-requirements)
+ + [1.1.3 Scalability Requirements](#113-scalability-requirements)
+ + [1.1.4 Warm Boot Requirements](#114-warm-boot-requirements)
+ * [1.2 Design Overview](#12-design-overview)
+ + [1.2.1 Basic Approach](#121-basic-approach)
+ - [1.2.1.1 Generating Possible Transitions](#1211-generating-possible-transitions)
+ - [1.2.1.2 Validating Config State](#1212-validating-config-state)
+- [2 Functionality](#2-functionality)
+ * [2.1 Target Deployment Use Cases](#21-target-deployment-use-cases)
+ * [2.2 Functional Description](#22-functional-description)
+ + [2.2.1 Getting current config](#221-getting-current-config)
+ + [2.2.2 Simulating patch application](#222-simulating-patch-application)
+ + [2.2.3 Generating all possible moves](#223-generating-all-possible-moves)
+ - [2.2.3.1 Generating Low level changes](#2231-generating-low-level-changes)
+ - [2.2.3.2 Generating Upper Levels Moves](#2232-generating-upper-levels-moves)
+ - [2.2.3.3 Generating Other Moves](#2233-generating-other-moves)
+ + [2.2.4 Validating config and move](#224-validating-config-and-move)
+- [3 Design](#3-design)
+ * [3.1 Overview](#31-overview)
+ + [3.1.1 Using YANG Models to Validate Config State](#311-using-yang-models-to-validate-config-state)
+ + [3.1.2 Using YANG models to Generate Other Moves](#312-using-yang-models-to-generate-other-moves)
+ + [3.1.3 Using YANG models to Host Flags for Move Validation](#313-using-yang-models-to-host-flags-for-move-validation)
+ - [3.1.3.1 Extension: create-only](#3131-extension--create-only)
+ * [3.2 User Interface](#32-user-interface)
+ + [3.2.1 Data Models](#321-data-models)
+ + [3.2.2 CLI](#322-cli)
+- [4 Flow Diagrams](#4-flow-diagrams)
+- [5 Error Handling](#5-error-handling)
+- [6 Serviceability and Debug](#6-serviceability-and-debug)
+- [7 Warm Boot Support](#7-warm-boot-support)
+- [8 Scalability](#8-scalability)
+- [9 Unit Tests](#9-unit-tests)
+- [Appendix A Examples](#appendix-a-examples)
+ * [A.1 Adding a new entry](#a1-adding-a-new-entry)
+ * [A.2 Dynamic Port Breakout 1 to 4](#a2-dynamic-port-breakout-1-to-4)
+
+# List of Tables
+[Table 1: Abbreviations](#table-1-abbreviations)
+
+# Revision
+
+| Rev | Date | Author | Change Description |
+|:---:|:-----------:|:------------------:|---------------------|
+| 0.1 | 03/01/2021 | Mohamed Ghoneim | Initial version |
+
+# About this Manual
+This document provides a detailed description on the algorithm to implement patch ordering described in [SONiC Generic Configuration Update and Rollback - HLD](SONiC_Generic_Config_Update_and_Rollback_Design.md#3114-patch-orderer)
+
+# Scope
+This document describes the algorithm of patch ordering described in [SONiC Generic Configuration Update and Rollback - HLD](SONiC_Generic_Config_Update_and_Rollback_Design.md#3114-patch-orderer) using YANG models. This document provides minor implementation details about the proposed solutions.
+
+# Definition/Abbreviation
+
+### Table 1: Abbreviations
+| **Term** | **Meaning** |
+| ------------------- | -------------------------- |
+| JsonPatch | JSON document structure for expressing a sequence of operations to apply to a JavaScript Object Notation (JSON) document. Check [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902). |
+
+# 1 Feature Overview
+Please make sure you have reviewed SONiC Generic Configuration Update and Rollback design document especially [Patch Orderer](SONiC_Generic_Config_Update_and_Rollback_Design.md#3114-patch-orderer).
+
+In this design document, we are going to explore using YANG models to order a given JsonPatch of updates. The idea is to make sure the transitions applied to the configurations all result in valid configs according to [SONiC YANG models](https://github.com/Azure/sonic-buildimage/tree/master/src/sonic-yang-models).
+
+YANG models has multiple constrains that can affect ordering (check [YANG 1.1 (RFC7950)](https://tools.ietf.org/html/rfc7950)):
+* leafref built-in type
+* must statement
+* ... other statements
+
+These constrains should be helpful while generating the list of transitions needed.
+
+## 1.1 Requirements
+
+### 1.1.1 Functional Requirements
+- The patch of updates should follow a standard notation. The [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902) notation should be used.
+- The return of the function is a list of JsonChanges (check [JsonChange](SONiC_Generic_Config_Update_and_Rollback_Design.md#31141-jsonchange)).
+- Each application of a JsonChange should move the configuration from a valid state to another valid state.
+- A valid state is a config that is valid according to YANG models.
+- Each JsonChange change should assume the applier of the change will have no notion of ordering. i.e. ordering of updates is only guaranteed between different JsonChange, within the same JsonChange order of update is not guaranteed.
+- It is assumed that the configuration lock was acquired before starting patch ordering.
+
+### 1.1.2 Configuration and Management Requirements
+N/A
+
+### 1.1.3 Scalability Requirements
+N/A
+
+### 1.1.4 Warm Boot Requirements
+N/A
+
+## 1.2 Design Overview
+
+From [SONiC Generic Configuration Update and Rollback - HLD](SONiC_Generic_Config_Update_and_Rollback_Design.md#3114-patch-orderer), this is the target interface:
+
+```python
+list order-patch(JsonPatch jsonPatch)
+```
+
+|aspect |item |description
+|------------|---------------------|-----------
+|inputs |JsonPatch | It represents the changes that needs to applied to the device running config, described in [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902).
+|outputs |list<JsonChange>| The list will contain the steps to be followed to apply the input JsonPatch correctly. Each item in the list is assumed to be executed after the previous item, in the order given in the list.
+|errors |malformedPatchError | Will be raised if the input JsonPatch is not valid according to [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902).
+| |other errors | Check [SONiC Generic Configuration Update and Rollback - HLD](SONiC_Generic_Config_Update_and_Rollback_Design.md#3114-patch-orderer) for exact list of errors to expect.
+|side-effects|None |
+|assumptions |running-config locked| The implementor of this contract might interact with ConfigDB to get the running-config, it is assumed the running-config is locked for changes for the lifespan of the operation.
+
+The important constraint in the above interface is the JsonChange, where the application of a single JsonChange does not guarantee any ordering. If ordering is needed, multiple JsonChanges should be returned.
+
+This design document is exploring the option to use YANG models validations in order to verify each config state is valid.
+
+To represent this problem as a graph we will consider the following:
+- Nodes are configuration states which should be valid according to YANG models
+- Edges are the valid JsonChanges which should ignore any command ordering
+
+
+
+The problem now is just finding a path between the current config and the target config. A solution to the above graph might be:
+
+
+
+Note:
+- Green nodes/edges are valid.
+- Red nodes/edges are invalid.
+- Grey nodes/edges are not tried.
+
+### 1.2.1 Basic Approach
+This problem can be reduced to a [constraint satisfaction problem](https://en.wikipedia.org/wiki/Constraint_satisfaction_problem) which are usually solved by search in particular [backtracking](https://en.wikipedia.org/wiki/Backtracking) or [local search](https://en.wikipedia.org/wiki/Local_search_(constraint_satisfaction)). This means we can have a wide range of algorithms to choose from such as Depth-First Search (DFS), Breadth-First Search (BFS), Dynamic Programming (DP), A*, other search algorithms, greedy approaches, heuristics or a combination of all of these algorithms.
+
+There are at least 2 steps that are needed broadly for any algorithm.
+
+#### 1.2.1.1 Generating Possible Transitions
+A transition between config state to another config state will be done through JsonChanges.
+
+Each transition should be validated that it does not contain dependent changes. For example: VLAN_MEMBER can contain a reference to PORT table, in that case VLAN_MEMBER cannot be updated together with PORT table in the same JsonChange.
+
+If generating/validating transitions needs additional explicit flags/configs, these flags/configs should be added to YANG models as extensions.
+
+#### 1.2.1.2 Validating Config State
+A config state represents how the config looks like after applying a JsonChange. Validation of config state is simply the validation of the generated config using YANG models.
+
+# 2 Functionality
+
+## 2.1 Target Deployment Use Cases
+
+This is going to be part of the `apply-patch` functionality described in [SONiC Generic Configuration Update and Rollback - HLD](SONiC_Generic_Config_Update_and_Rollback_Design.md)
+
+## 2.2 Functional Description
+
+Let's discuss how a simple DFS solution will look like.
+```python
+def order-patch(patch):
+ current_config = get_current_config()
+ target_config = simulate_patch(patch, current_config)
+ return dfs(current_config, target_config)
+
+visited = {}
+def dfs(current_config, target_config):
+ if current_config == target_config:
+ return []
+ if current_config in visited:
+ return None
+ visited[curr_config] = True
+
+ moves = get_all_moves(current_config)
+ for move in moves:
+ if is_valid(move, current_config):
+ new_config = apply_move(move, current_config)
+ new_moves = dfs(new_config, target_config)
+ if new_moves != None:
+ return [move] + [new_moves]
+
+ return None
+```
+
+In the above approach, we are trying all possible moves and just returning the first successful list of moves. Use of `Visited` dictionary help cut down states that were already visited.
+
+### 2.2.1 Getting current config
+Gets the current config from ConfigDB, e.g. `show runningconfiguration all`
+
+### 2.2.2 Simulating patch application
+Can use jsonpatch python library to do that, e.g. `patch.apply(current_config)`
+
+### 2.2.3 Generating all possible moves
+#### 2.2.3.1 Generating Low level changes
+
+This means to include all moves at the lowest level of the JSON tree. For example showing the diff between Target Config and Current Config:
+```diff
+ {
+ "ACL_RULE": {
+ "SNMP_ACL|RULE_1": {
+ "PRIORITY": "9999",
+- "SRC_IP": "2.2.2.2/21",
++ "SRC_IP": "1.1.1.1/21",
+ "IP_PROTOCOL": "17",
+ "PACKET_ACTION": "ACCEPT"
+ },
+- "SNMP_ACL|RULE_2": {
+- "PRIORITY": "9998",
+- "SRC_IP": "2.2.2.2/20",
+- "IP_PROTOCOL": "17",
+- "PACKET_ACTION": "ACCEPT"
+- },
++ "SNMP_ACL|RULE_3": {
++ "PRIORITY": "9997",
++ "SRC_IP": "3.3.3.3/20",
++ "IP_PROTOCOL": "17",
++ "PACKET_ACTION": "ACCEPT"
++ },
+ "SNMP_ACL|DEFAULT_RULE": {
+ "PRIORITY": "1",
+ "ETHER_TYPE": "2048",
+ "PACKET_ACTION": "DROP"
+ }
+ },
+ "ACL_TABLE": {
+ "SNMP_ACL": {
+ "type": "CTRLPLANE",
+ "policy_desc": "SNMP_ACL",
+ "services": [
+ "SNMP"
+ ]
+ }
+ }
+ }
+```
+
+The lowest levels steps to try in the first run will be: (expressed as JsonPatch operations)
+
+Moves generated for `/ACL_RULE/SNMP_ACL|RULE_1`, which corresponds to modifying a leaf key/value pair.
+```json
+[
+ { "op": "replace", "path": "/ACL_RULE/SNMP_ACL|RULE_1/SRC_IP", "value": "1.1.1.1/21" }
+]
+```
+
+Moves generated for `/ACL_RULE/SNMP_ACL|RULE_2`, which is getting completely removed:
+```json
+[
+ { "op": "remove", "path": "/ACL_RULE/SNMP_ACL|RULE_2/PRIORITY" },
+ { "op": "remove", "path": "/ACL_RULE/SNMP_ACL|RULE_2/SRC_IP" },
+ { "op": "remove", "path": "/ACL_RULE/SNMP_ACL|RULE_2/IP_PROTOCOL" },
+ { "op": "remove", "path": "/ACL_RULE/SNMP_ACL|RULE_2/PACKET_ACTION" }
+]
+```
+
+Moves generated for `/ACL_RULE/SNMP_ACL|RULE_3`, which is getting completely added:
+```json
+[
+ { "op": "add", "path": "/ACL_RULE/SNMP_ACL|RULE_3", "value": { "PRIORITY": "9997" } },
+ { "op": "add", "path": "/ACL_RULE/SNMP_ACL|RULE_3", "value": { "SRC_IP": "2.2.2.2/20" } },
+ { "op": "add", "path": "/ACL_RULE/SNMP_ACL|RULE_3", "value": { "IP_PROTOCOL": "17" } },
+ { "op": "add", "path": "/ACL_RULE/SNMP_ACL|RULE_3", "value": { "PACKET_ACTION": "ACCEPT" } }
+]
+```
+
+#### 2.2.3.2 Generating Upper Levels Moves
+Recursively go through the the parent of the moves in the lower level, and try the following:
+- If the parent is still the same, `replace` the parent with its children
+- If the parent is remove, `remove` the parent
+- If the parent is added, `add` the parent with its children
+
+Move generated for `/ACL_RULE/SNMP_ACL|RULE_1`, will be `replace` since `/ACL_RULE/SNMP_ACL|RULE_1` itself is still the same.
+```json
+[
+ { "op": "replace", "path": "/ACL_RULE/SNMP_ACL|RULE_1", "value": { "PRIORITY": "9999", "SRC_IP": "1.1.1.1/21", "IP_PROTOCOL": "17","PACKET_ACTION": "ACCEPT" } }
+]
+```
+
+Move generated for `/ACL_RULE/SNMP_ACL|RULE_2`, will be `remove` since `/ACL_RULE/SNMP_ACL|RULE_2` itself is removed.
+```json
+[
+ { "op": "remove", "path": "/ACL_RULE/SNMP_ACL|RULE_2"}
+]
+```
+
+Move generated for `/ACL_RULE/SNMP_ACL|RULE_3`, will be `add` since `/ACL_RULE/SNMP_ACL|RULE_3` itself is added.
+```json
+[
+ { "op": "add", "path": "/ACL_RULE/SNMP_ACL|RULE_3", "value": { "PRIORITY": "9997", "SRC_IP": "3.3.3.3/20", "IP_PROTOCOL": "17","PACKET_ACTION": "ACCEPT" } }
+]
+```
+Next we recursively go up the tree, this includes at the level of `/ACL_RULE` table, and the whole config. Since both already exist the operation would be `replace`. Note that `"path": ""` where the path is empty represents the whole config.
+```json
+[
+ { "op": "replace", "path": "/ACL_RULE", "value": { "SNMP_ACL|RULE_1": { "PRIORITY": "9999", "SRC_IP": "1.1.1.1/21", "IP_PROTOCOL": "17", "PACKET_ACTION": "ACCEPT" }, "SNMP_ACL|RULE_3": { "PRIORITY": "9997", "SRC_IP": "3.3.3.3/20", "IP_PROTOCOL": "17", "PACKET_ACTION": "ACCEPT"}, "SNMP_ACL|DEFAULT_RULE": { "PRIORITY": "1", "ETHER_TYPE": "2048", "PACKET_ACTION": "DROP" } }},
+ { "op": "replace", "path": "", "value": { "ACL_RULE": { "SNMP_ACL|RULE_1": { "PRIORITY": "9999", "SRC_IP": "1.1.1.1/21", "IP_PROTOCOL": "17", "PACKET_ACTION": "ACCEPT" }, "SNMP_ACL|RULE_3": { "PRIORITY": "9997", "SRC_IP": "3.3.3.3/20", "IP_PROTOCOL": "17", "PACKET_ACTION": "ACCEPT"}, "SNMP_ACL|DEFAULT_RULE": { "PRIORITY": "1", "ETHER_TYPE": "2048", "PACKET_ACTION": "DROP" } }, "ACL_TABLE": { "SNMP_ACL": { "type": "CTRLPLANE", "policy_desc": "SNMP_ACL", "services": [ "SNMP" ] } } } }
+]
+```
+
+#### 2.2.3.3 Generating Other Moves
+- `replace` operation can be substituted by `remove`, which should be put back in the next level of recursion of the DFS, for example:
+ ```json
+ [
+ { "op": "replace", "path": "/ACL_RULE/SNMP_ACL|RULE_1", "value": { "PRIORITY": "9999", "SRC_IP": "1.1.1.1/21", "IP_PROTOCOL": "17","PACKET_ACTION": "ACCEPT" } }
+ ]
+ ```
+ Will generate:
+ ```json
+ [
+ { "op": "remove", "path": "/ACL_RULE/SNMP_ACL|RULE_1" }
+ ]
+ ```
+- Lines getting removed which have references, can be substituted by deleting their references first as it is required anyway, for example:
+ ```json
+ [
+ { "op": "remove", "path": "/PORT/Ethernet2" }
+ ]
+ ```
+ Will generate the following assuming PORT Ethernet2 is consumed by ACL_TABLE and VLAN_MEMBER:
+ ```json
+ [
+ { "op": "remove", "path": "/ACL_TABLE/NO-NSW-PACL-V4/ports/0" },
+ { "op": "remove", "path": "/VLAN_MEMBER/Vlan100|Ethernet2" }
+ ]
+ ```
+- There can be other moves as the quality of the moves will determine if there is a path to get to the Target Config from the Current Config.
+
+### 2.2.4 Validating config and move
+- Validates result config after applying the move against [SONiC YANG models](https://github.com/Azure/sonic-buildimage/tree/master/src/sonic-yang-models).
+- Validates the operation itself
+ - If we don't validate the operation, then we can always just replace the whole current_config with the whole target_config in one operation. This will always produce a valid result config.
+ - Validating the operation makes sure it does not contain 2 changes that have dependency as JsonChange appliers do not take of ordering.
+ - If ordering is necessary, the operation needs to be split into multiple JsonChanges.
+
+# 3 Design
+
+## 3.1 Overview
+A small modification to the [DFS algorithm](##2.2-Functional-Description) listed before is introducing memoization, where the function is optimizing for the shortest number of moves.
+```python
+def order-patch(patch):
+ current_config = get_current_config()
+ target_config = simulate_patch(patch, current_config)
+ return rec(current_config, target_config)
+
+visited = {}
+mem = {}
+def rec(current_config, target_config):
+ if current_config == target_config:
+ return []
+ if current_config in mem: # If already calculated, just return the result form memory
+ return mem[current_config]
+ if current_config in visited:
+ return None
+ visited[curr_config] = True
+
+ moves = get_all_moves(current_config)
+ best_moves = None
+ for move in moves:
+ if is_valid(move, current_config):
+ new_config = apply_move(move, current_config)
+ new_moves = rec(new_config, target_config)
+ if new_moves != None:
+ # Minimize on the number of moves
+ if best_moves == None or len(best_moves) > 1 + len(new_moves):
+ best_moves = [move] + [new_moves]
+
+ mem[current_config] = best_moves
+ return best_moves
+```
+
+This optimization can help reduce the number of result JsonChanges, and ultimately reduce the time needed to completely apply all the JsonChanges.
+
+SONiC YANG models are going to be used for the following:
+- Validating config state after applying a move
+- Generating other moves
+- Host flags/configs for move validation
+
+### 3.1.1 Using YANG Models to Validate Config State
+This is a straightforward task and can be done using [SONiC Libynag wrapper](https://github.com/Azure/sonic-buildimage/blob/master/src/sonic-yang-mgmt/sonic_yang.py), specifically `validate_data_tree`.
+
+### 3.1.2 Using YANG models to Generate Other Moves
+Check [2.2.3 Generating all possible moves](#223-generating-all-possible-moves) to learn more about what are the possible moves.
+
+YANG models can help with:
+- Lines getting removed which have references, can be substituted by deleting their references first as it is required anyway (check [2.2.3.3 Generating Other Moves](#2233-generating-other-moves) for details). Getting the dependency of some data can be done using [SONiC Libynag wrapper](https://github.com/Azure/sonic-buildimage/blob/master/src/sonic-yang-mgmt/sonic_yang.py), specifically `find_data_dependencies`.
+- Any other moves should be generated using YANG models, if YANG models data are not enough an extension to YANG models can be added to help with generating new moves.
+
+### 3.1.3 Using YANG models to Host Flags for Move Validation
+#### 3.1.3.1 Extension: create-only
+Some fields are not allowed to be modified and can only be created, such as `/PORT/Ethernet0/lanes` which is marked as `CREATE_ONLY` in [opencomputeproject/SAI/blob/master/inc/saiport.h](https://github.com/opencomputeproject/SAI/blob/master/inc/saiport.h#L624):
+```C
+ /**
+ * @brief Hardware Lane list
+ *
+ * @type sai_u32_list_t
+ * @flags MANDATORY_ON_CREATE | CREATE_ONLY | KEY
+ */
+ SAI_PORT_ATTR_HW_LANE_LIST,
+```
+
+The new extension `create-only` will be added to [YANG models SONiC extensions](https://github.com/Azure/sonic-buildimage/blob/master/src/sonic-yang-models/yang-models/sonic-extension.yang):
+```
+extension create-only {
+ description "During apply-patch operation the field can only be created (i.e. added) or re-created (i.e. removed then added) but cannot be modified (i.e. replaced).";
+}
+```
+
+`create-only` field moves will be evaluated as follows:
+1. Fail validation for `replace` move that is updating a field marked with `create-only`.
+2. Fail validation for `replace` move that is updating parent of a field that is marked with `create-only` and the `create-only` field is itself different.
+3. Pass validation for `replace` move that is updating parent of a field that is marked with `create-only` and the `create-only` field is itself the same.
+4. Rule 2,3 above will be also applied to the grand-parent, grand-grand-parent ...etc
+
+
+Let's take the example [A.2 Dynamic Port Breakout 1 to 4](#a2-dynamic-port-breakout-1-to-4) which has the following:
+```json
+[
+ {
+ "op": "replace",
+ "path": "/PORT/Ethernet0/lanes",
+ "value": "65"
+ }
+]
+```
+But the field `lanes` is `create-only` and cannot be modified i.e. replaced. The only way to update the `lanes` field is through deleting then adding its parent the `/PORT/Ethernet0`.
+
+In [port YANG model](https://github.com/Azure/sonic-buildimage/blob/master/src/sonic-yang-models/yang-models/sonic-port.yang), let's mark `lanes` with `create-only`:
+```diff
+ leaf lanes {
+ mandatory true;
++ ext:create-only;
+ type string {
+ length 1..128;
+ }
+ }
+```
+
+Now following the [DFS algorithm](#22-functional-description) described above:
+1. Generating all possible moves which includes low level moves, upper level moves and other moves. We will end up with:
+ ```json
+ [
+ { "op": "replace", "path": "/PORT/Ethernet0/lanes", "value": "65" },
+ { "op": "delete", "path": "/PORT/Ethernet0/lanes" },
+ { "op": "replace", "path": "/PORT/Ethernet0", "value": {"alias": "Eth1/1", "lanes": "65", "description": "", "speed": "10000"} },
+ { "op": "delete", "path": "/PORT/Ethernet0" }
+ ]
+ ```
+2. Validating the moves and result config states after applying the moves
+
+ A.
+ ```json
+ { "op": "replace", "path": "/PORT/Ethernet0/lanes", "value": "65" }
+ ```
+ the move validation will fail because a `replace` move is applied to a the field `lanes` which is `create-only`
+
+ B.
+ ```json
+ { "op": "delete", "path": "/PORT/Ethernet0/lanes" }
+ ```
+ the generated config validation will fail because the field `lanes` is `mandatory` and cannot be deleted.
+
+ C.
+ ```json
+ { "op": "replace", "path": "/PORT/Ethernet0", "value": {"alias": "Eth1/1", "lanes": "65", "description": "", "speed": "10000"} },
+ ```
+ the move validation will fail because a `replace` move is applied the `/PORT/Ethernet0` which is a parent to `lanes` which is a `create-only` field, and also `lanes` field is different
+
+ D.
+ ```json
+ { "op": "delete", "path": "/PORT/Ethernet0" }
+ ```
+ the move validation will pass.
+
+
+## 3.2 User Interface
+N/A
+
+### 3.2.1 Data Models
+check [JsonChange](SONiC_Generic_Config_Update_and_Rollback_Design.md#31141-jsonchange)
+
+### 3.2.2 CLI
+N/A
+
+# 4 Flow Diagrams
+N/A
+
+# 5 Error Handling
+
+Check [here](SONiC_Generic_Config_Update_and_Rollback_Design.md#3114-patch-orderer) for formal list of errors defined for the interface `order-patch`.
+
+# 6 Serviceability and Debug
+All commands logs are stored in systemd-journal and syslog.
+
+
+# 7 Warm Boot Support
+N/A
+
+
+# 8 Scalability
+N/A
+
+# 9 Unit Tests
+| Test Case | Description |
+| --------- | ----------- |
+| 1 | Add a new table. |
+| 2 | Remove an existing table. |
+| 3 | Modify values of an existing table entry. |
+| 4 | Modify value of an existing item an array value. |
+| 5 | Add a new item to an array value. |
+| 6 | Remove an item form an array value. |
+| 7 | Add a new key to an existing table .|
+| 8 | Remove a key from an existing table. |
+| 9 | Remove 2 items that depends on each other but in different tables e.g. /PORT/Ethernet2 and /VLAN_MEMBER/Vlan101|Ethernet2. |
+| 10 | Add 2 items that depends on each other but in different tables e.g. /PORT/Ethernet2 and /VLAN_MEMBER/Vlan101|Ethernet2. |
+| 11 | Remove 2 items that depends on each other in the same table e.g. /INTERFACE/INTERFACE_LIST and /INTERFACE/INTERFACE_PREFIX_LIST. |
+| 12 | Add 2 items that depends on each other in the same table e.g. /INTERFACE/INTERFACE_LIST and /INTERFACE/INTERFACE_PREFIX_LIST. |
+| 13 | Replace a mandatory item e.g. type under ACL_TABLE. |
+| 14 | Dynamic port breakout as described [here](https://github.com/Azure/SONiC/blob/master/doc/dynamic-port-breakout/sonic-dynamic-port-breakout-HLD.md).|
+| 15 | Remove an item that has a default value. |
+| 16 | Modifying items that rely depends on each other based on a `must` condition rather than direct connection such as `leafref` e.g. /CRM/acl_counter_high_threshold (check [here](https://github.com/Azure/sonic-buildimage/blob/master/src/sonic-yang-models/yang-models/sonic-crm.yang)). |
+
+
+
+# Appendix A Examples
+## A.1 Adding a new entry
+**Current running config**
+```json
+{
+ "DHCP_SERVER": {
+ "192.0.0.1": {},
+ "192.0.0.2": {},
+ "192.0.0.3": {},
+ "192.0.0.4": {}
+ }
+}
+```
+**JsonPatch**
+```json
+[
+ {
+ "path": "/DHCP_SERVER/192.0.0.5",
+ "op": "add",
+ "value": {}
+ }
+]
+```
+
+**Result Jsonchanges**
+```json
+[
+ [{"op": "add", "path": "/DHCP_SERVER/192.0.0.5", "value": {}}]
+]
+```
+
+## A.2 Dynamic Port Breakout 1 to 4
+**Current running config**
+```json
+{
+ "PORT": {
+ "Ethernet0": {
+ "alias": "Eth1",
+ "lanes": "65, 66, 67, 68",
+ "description": "Ethernet0 100G link",
+ "speed": "100000"
+ }
+ },
+ "ACL_TABLE": {
+ "NO-NSW-PACL-V4": {
+ "type": "L3",
+ "policy_desc": "NO-NSW-PACL-V4",
+ "ports": [
+ "Ethernet0"
+ ]
+ }
+ },
+ "VLAN_MEMBER": {
+ "Vlan100|Ethernet0": {
+ "tagging_mode": "untagged"
+ }
+ }
+}
+```
+**JsonPatch**
+```json
+[
+ {
+ "op": "add",
+ "path": "/PORT/Ethernet3",
+ "value": {
+ "alias": "Eth1/4",
+ "lanes": "68",
+ "description": "",
+ "speed": "10000"
+ }
+ },
+ {
+ "op": "add",
+ "path": "/PORT/Ethernet1",
+ "value": {
+ "alias": "Eth1/2",
+ "lanes": "66",
+ "description": "",
+ "speed": "10000"
+ }
+ },
+ {
+ "op": "add",
+ "path": "/PORT/Ethernet2",
+ "value": {
+ "alias": "Eth1/3",
+ "lanes": "67",
+ "description": "",
+ "speed": "10000"
+ }
+ },
+ {
+ "op": "replace",
+ "path": "/PORT/Ethernet0/lanes",
+ "value": "65"
+ },
+ {
+ "op": "replace",
+ "path": "/PORT/Ethernet0/alias",
+ "value": "Eth1/1"
+ },
+ {
+ "op": "replace",
+ "path": "/PORT/Ethernet0/description",
+ "value": ""
+ },
+ {
+ "op": "replace",
+ "path": "/PORT/Ethernet0/speed",
+ "value": "10000"
+ },
+ {
+ "op": "add",
+ "path": "/VLAN_MEMBER/Vlan100|Ethernet2",
+ "value": {
+ "tagging_mode": "untagged"
+ }
+ },
+ {
+ "op": "add",
+ "path": "/VLAN_MEMBER/Vlan100|Ethernet3",
+ "value": {
+ "tagging_mode": "untagged"
+ }
+ },
+ {
+ "op": "add",
+ "path": "/VLAN_MEMBER/Vlan100|Ethernet1",
+ "value": {
+ "tagging_mode": "untagged"
+ }
+ },
+ {
+ "op": "add",
+ "path": "/ACL_TABLE/NO-NSW-PACL-V4/ports/1",
+ "value": "Ethernet1"
+ },
+ {
+ "op": "add",
+ "path": "/ACL_TABLE/NO-NSW-PACL-V4/ports/2",
+ "value": "Ethernet2"
+ },
+ {
+ "op": "add",
+ "path": "/ACL_TABLE/NO-NSW-PACL-V4/ports/3",
+ "value": "Ethernet3"
+ }
+]
+```
+
+**Result Jsonchanges**
+```json
+[
+ [{"op": "remove", "path": "/ACL_TABLE/NO-NSW-PACL-V4/ports"}],
+ [{"op": "remove", "path": "/VLAN_MEMBER/Vlan100|Ethernet0"}],
+ [{"op": "remove", "path": "/PORT/Ethernet0"}],
+ [{"op": "add", "path": "/PORT/Ethernet1", "value": {"alias": "Eth1/2", "lanes": "66", "description": "", "speed": "10000"}}],
+ [{"op": "add", "path": "/PORT/Ethernet2", "value": {"alias": "Eth1/3", "lanes": "67", "description": "", "speed": "10000"}}],
+ [{"op": "add", "path": "/PORT/Ethernet0", "value": {"alias": "Eth1/1", "lanes": "65", "description": "", "speed": "10000"}}],
+ [{"op": "add", "path": "/PORT/Ethernet3", "value": {"alias": "Eth1/4", "lanes": "68", "description": "", "speed": "10000"}}],
+ [{"op": "add", "path": "/ACL_TABLE/NO-NSW-PACL-V4/ports", "value": ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"]}],
+ [{"op": "add", "path": "/VLAN_MEMBER/Vlan100|Ethernet1", "value": {"tagging_mode": "untagged"}}],
+ [{"op": "add", "path": "/VLAN_MEMBER/Vlan100|Ethernet2", "value": {"tagging_mode": "untagged"}}],
+ [{"op": "add", "path": "/VLAN_MEMBER/Vlan100|Ethernet3", "value": {"tagging_mode": "untagged"}}],
+ [{"op": "add", "path": "/VLAN_MEMBER/Vlan100|Ethernet0", "value": {"tagging_mode": "untagged"}}],
+]
+```
\ No newline at end of file
diff --git a/doc/config-generic-update-rollback/README.md b/doc/config-generic-update-rollback/README.md
new file mode 100644
index 0000000000..0b42356cfa
--- /dev/null
+++ b/doc/config-generic-update-rollback/README.md
@@ -0,0 +1,12 @@
+# Guide to reading the design documents
+The document is divided into 3 parts, please read them in order:
+1. [SONiC Generic Configuration Update and Rollback - HLD](SONiC_Generic_Config_Update_and_Rollback_Design.md)
+2. [Json_Change_Application_Design](Json_Change_Application_Design.md)
+3. [Json_Patch_Ordering_using_YANG_Models_Design](Json_Patch_Ordering_using_YANG_Models_Design.md)
+
+# Plan of implementation
+The implementation is going to be divided into the following steps:
+1. Implementing [SONiC Generic Configuration Update and Rollback - HLD](SONiC_Generic_Config_Update_and_Rollback_Design.md)
+2. Implementing [Json_Change_Application_Design](Json_Change_Application_Design.md)
+3. Implementing [Json_Patch_Ordering_using_YANG_Models_Design](Json_Patch_Ordering_using_YANG_Models_Design.md)
+4. Improving logging by making sure all the steps are logged to syslog as well as systemd journal
diff --git a/doc/config-generic-update-rollback/SONiC_Generic_Config_Update_and_Rollback_Design.md b/doc/config-generic-update-rollback/SONiC_Generic_Config_Update_and_Rollback_Design.md
new file mode 100644
index 0000000000..295f3ca842
--- /dev/null
+++ b/doc/config-generic-update-rollback/SONiC_Generic_Config_Update_and_Rollback_Design.md
@@ -0,0 +1,940 @@
+# SONiC Generic Configuration Update and Rollback
+
+# High Level Design Document
+
+#### Rev 0.1
+
+# Table of Contents
+- [Table of Contents](#table-of-contents)
+- [List of Tables](#list-of-tables)
+- [Revision](#revision)
+- [About this Manual](#about-this-manual)
+- [Scope](#scope)
+- [Definition/Abbreviation](#definition-abbreviation)
+ + [Table 1: Abbreviations](#table-1--abbreviations)
+- [1 Feature Overview](#1-feature-overview)
+ * [1.1 Requirements](#11-requirements)
+ + [1.1.1 Functional Requirements](#111-functional-requirements)
+ + [1.1.2 Configuration and Management Requirements](#112-configuration-and-management-requirements)
+ + [1.1.3 Scalability Requirements](#113-scalability-requirements)
+ + [1.1.4 Warm Boot Requirements](#114-warm-boot-requirements)
+ * [1.2 Design Overview](#12-design-overview)
+ + [1.2.1 Basic Approach](#121-basic-approach)
+ + [1.2.2 Container](#122-container)
+- [2 Functionality](#2-functionality)
+ * [2.1 Target Deployment Use Cases](#21-target-deployment-use-cases)
+ * [2.2 Functional Description](#22-functional-description)
+ + [2.2.1 Apply-Patch](#221-apply-patch)
+ - [Stage-1 JSON Patch Verification](#stage-1-json-patch-verification)
+ - [Stage-2 JSON Patch Ordering](#stage-2-json-patch-ordering)
+ - [Stage-3 Applying list of JsonChanges in order](#stage-3-applying-list-of-jsonchanges-in-order)
+ - [Stage-4 Post-update validation](#stage-4-post-update-validation)
+ - [Fail-safe Action](#fail-safe-action)
+ - [Logging](#logging)
+ + [2.2.2 Checkpoint](#222-checkpoint)
+ - [Stage-1 Get current ConfigDB JSON config](#stage-1-get-current-configdb-json-config)
+ - [Stage-2 Validating current ConfigDB JSON config using YANG models](#stage-2-validating-current-configdb-json-config-using-yang-models)
+ - [Stage-3 Save JSON config](#stage-3-save-json-config)
+ + [2.2.3 Rollback](#223-rollback)
+ - [Stage-1 Get current ConfigDB JSON config](#stage-1-get-current-configdb-json-config-1)
+ - [Stage-2 Get checkpoint JSON config](#stage-2-get-checkpoint-json-config)
+ - [Stage-3 Generate the diff as JsonPatch between current config and checkpoint](#stage-3-generate-the-diff-as-jsonpatch-between-current-config-and-checkpoint)
+ - [Stage-4 Apply-Patch](#stage-4-apply-patch)
+ - [Stage-5 Verify config rollback](#stage-5-verify-config-rollback)
+ - [Fail-safe Action](#fail-safe-action-1)
+ - [Logging](#logging-1)
+ + [2.2.4 Replace](#224-replace)
+ - [Stage-1 Get target config from the external user](#stage-1-get-target-config-from-the-external-user)
+ - [Stage-2 Validating the target config using YANG models](#stage-2-validating-the-target-config-using-yang-models)
+ - [Stage-3 Get current ConfigDB JSON config](#stage-3-get-current-configdb-json-config)
+ - [Stage-4 Generate the diff as JsonPatch between current config and target config](#stage-4-generate-the-diff-as-jsonpatch-between-current-config-and-target-config)
+ - [Stage-5 Apply-Patch](#stage-5-apply-patch)
+ - [Stage-6 Verify config replace](#stage-6-verify-config-replace)
+ - [Fail-safe Action](#fail-safe-action-2)
+ - [Logging](#logging-2)
+- [3 Design](#3-design)
+ * [3.1 Overview](#31-overview)
+ + [3.1.1 ApplyPatch](#311-applypatch)
+ - [3.1.1.1 User](#3111-user)
+ - [3.1.1.2 SONiC CLI](#3112-sonic-cli)
+ - [3.1.1.3 YANG models](#3113-yang-models)
+ - [3.1.1.4 Patch Orderer](#3114-patch-orderer)
+ * [3.1.1.4.1 JsonChange](#31141-jsonchange)
+ * [3.1.1.4.2 Order-Patch](#31142-order-patch)
+ - [3.1.1.5 Change Applier](#3115-change-applier)
+ * [3.1.1.5.1 Apply-Change](#31151-apply-change)
+ - [3.1.1.6 ConfigDB](#3116-configdb)
+ + [3.1.2 Checkpoint](#312-checkpoint)
+ - [3.1.2.1 User](#3121-user)
+ - [3.1.2.2 SONiC CLI](#3122-sonic-cli)
+ - [3.1.2.3 YANG models](#3123-yang-models)
+ - [3.1.2.4 ConfigDB](#3124-configdb)
+ - [3.1.2.5 File system](#3125-file-system)
+ + [3.1.3 Rollback](#313-rollback)
+ - [3.1.3.1 User](#3131-user)
+ - [3.1.3.2 SONiC CLI](#3132-sonic-cli)
+ - [3.1.3.4 File system](#3134-file-system)
+ - [3.1.3.4 ConfigDB](#3134-configdb)
+ + [3.1.4 Replace](#314-replace)
+ - [3.1.4.1 User](#3141-user)
+ - [3.1.4.2 SONiC CLI](#3142-sonic-cli)
+ - [3.1.4.3 YANG models](#3143-yang-models)
+ - [3.1.4.4 File system](#3144-file-system)
+ - [3.1.4.5 ConfigDB](#3145-configdb)
+ + [3.2 User Interface](#32-user-interface)
+ + [3.2.1 Data Models](#321-data-models)
+ - [3.2.1.1 JsonPatch](#3211-jsonpatch)
+ + [3.2.2 CLI](#322-cli)
+ - [3.2.2.1 Configuration Commands](#3221-configuration-commands)
+ - [3.2.2.2 Show Commands](#3222-show-commands)
+ - [3.2.2.3 Debug Commands](#3223-debug-commands)
+- [4 Flow Diagrams](#4-flow-diagrams)
+- [5 Error Handling](#5-error-handling)
+- [6 Serviceability and Debug](#6-serviceability-and-debug)
+- [7 Warm Boot Support](#7-warm-boot-support)
+- [8 Scalability](#8-scalability)
+- [9 Unit Tests](#9-unit-tests)
+ * [9.1 Unit Tests for Apply-Patch](#91-unit-tests-for-apply-patch)
+ * [9.2 Unit Tests for Checkpoint](#92-unit-tests-for-checkpoint)
+ * [9.3 Unit Tests for Rollback](#93-unit-tests-for-rollback)
+ * [9.4 Unit Tests for Replace](#94-unit-tests-for-replace)
+
+# List of Tables
+[Table 1: Abbreviations](#table-1-abbreviations)
+
+# Revision
+
+| Rev | Date | Author | Change Description |
+|:---:|:-----------:|:------------------:|---------------------|
+| 0.1 | 03/01/2021 | Mohamed Ghoneim | Initial version |
+
+# About this Manual
+This document provides a detailed description on the strategy to implement the SONiC configuration generic update and rollback feature.
+
+# Scope
+This document describes the high level design of a SONiC configuration generic update and rollback feature. This document provides minor implementation details about the proposed solutions.
+
+# Definition/Abbreviation
+
+### Table 1: Abbreviations
+| **Term** | **Meaning** |
+| -------- | -------------------------- |
+| ConfigDB | Configuration Database |
+| JSON | JavaScript Object Notation |
+
+# 1 Feature Overview
+
+Updating SONiC partial configurations **systematically** has been a challenge for a long time, as each part of the config has different requirements in terms of which files to push to the device, what commands to use, and if there are services that need manual restarting. For example updating `ACLs` is very different from updating `DHCP` configurations.
+
+*ACLs*: Updating ACLs require the following steps:
+- Pushing `acl.json` file to the device that contain the new ACL rules
+- Pushing `minigraph.xml` to the device that contains the new ACL interfaces
+- Execute `sudo acl-loader update full /etc/sonic/acl.json --table_name example_acl`
+
+*DHCP*: Updating DHCP config requires the following steps:
+- Pushing `minigraph.xml` to the device that contains the new ACL interfaces
+- Generating `dhcp_servers` JSON configs from the `minigraph.xml`, and saving it as a temporary file
+- Executing `sudo sonic-cfggen -j /tmp/dhcp.json --write-to-db`
+- Restart `dhcp_relay` service
+
+We have explored [SONiC CLI commands](https://github.com/Azure/sonic-utilities/blob/master/doc/Command-Reference.md) to make configuration changes. These CLI commands result in updates to the ConfigDB which are corresponding to the CLI command executed. For example, the config `vlan add 10` will create a new row in the VLAN table of the ConfigDB. But relying on the CLI commands to do partial update is also not feasible as there is no standard way of showing the config after the update. Setting up a different update mechanism for each part of the config is very time consuming and inefficient.
+
+The other challenge to updating a switch is recoverability via rollback. Rollback needs to be with minimum-disruption e.g. if reverting ACL updates DHCP should not be affected. Currently SONiC has a couple of operations that can be candidates for rollback `config load` and `config reload`.
+
+*config reload * : This command clears all the contents of the ConfigDB and loads the contents of config_db.json into the ConfigDB. After that all the Docker containers and Linux services are restarted to establish the user specified configuration state in the config_db.json file.
+
+- Pro's
+ - Assured way of affecting a configuration state change
+- Con's
+ - Brings the links down and resets the forwarding state. This operation is disruptive in nature
+ - Time consuming as it may take 2-3 minutes for all the services to come back online. The time taken may vary based on the switch CPU power.
+- Verdict
+ - Cannot be used as a rollback mechanism
+
+*config load *: This command loads the contents of config_db.json into the ConfigDB. The updates made to the ConfigDB are additive in nature and thus the new configuration state is a combination of the current running state and the partial configuration state specified by the user in the config_db.json file
+
+- Pro's
+ - Quick way to add new configuration changes
+ - It does not disrupt existing service whose configuration is not being modified. So it is non-disruptive in nature
+- Con's
+ - Can't remove existing configuration and can only be used to add/modify the existing configuration
+- Verdict
+ - Cannot be used as a rollback mechanism
+
+Since both `config load` and `config reload` are not suitable for a minimum-disruption rollback, we have to look for other approaches.
+
+In this design document, we will be exploring how to standardize the way to do partial updates, how to take checkpoints and finally how to rollback the configurations.
+
+In summary, this is the flow of an update:
+
+
+
+And the steps would be:
+```
+admin@sonic:~$ config checkpoint mycheckpoint
+admin@sonic:~$ echo "config changes to apply to ConfigDb" > some-config-changes.json-patch
+admin@sonic:~$ config apply-patch ./some-config-changes.json-patch
+admin@sonic:~$ config rollback mycheckpoint # in case of failures
+```
+
+## 1.1 Requirements
+
+### 1.1.1 Functional Requirements
+- A single, simple command to partially update SONiC configuration according to a patch of updates
+- A single, simple command to take a checkpoint of the full current SONiC config
+- A single, simple command to fully rollback current SONiC configs with to a checkpoint
+- [low-priority] A single simple command to fully replace current SONiC configs with a full config provided by an external user.
+- Other commands to list checkpoints, delete checkpoints
+- The patch of updates should follow a standard notation. The [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902) notation should be used
+- Config rollback should be with minimum disruption to the device e.g. if reverting ACL updates DHCP should not be affected i.e. minimum-disruption rollback
+- User should be able to preview the configuration difference before going ahead and committing the configuration changes
+- In case of errors, the system should just report an error and the user should take care of it
+- Only one session globally can update device config at a time i.e. no concurrent updates to configurations
+
+### 1.1.2 Configuration and Management Requirements
+- All commands argument to generated using Python-click to provide help menus and other out-of-the box features
+- Only root user must be allowed to execute the commands
+- Non-root users can execute commands with dry-run option
+- Each command must provide the following sub options:
+ - "dry-run" Perform a dry-run of the command showing exactly what will be executed on the device, without executing it
+ - "verbose" Provide additional information on the steps executed
+
+### 1.1.3 Scalability Requirements
+N/A
+
+### 1.1.4 Warm Boot Requirements
+N/A
+
+## 1.2 Design Overview
+
+
+
+### 1.2.1 Basic Approach
+SONiC ConfigDB contents can be retrieved in a JSON file format. Modifying JSON file should follow some rules in order to make it straightforward for the users. Fortunately there is already a formal way of defining JSON config updates. It is called JsonPatch, and is formally defined in [RFC 6902 JSON Patch](https://tools.ietf.org/html/rfc6902).
+
+On top of ConfigDBConnector we are going to implement [RFC 6902 JSON Patch](https://tools.ietf.org/html/rfc6902). This API we will call `apply-patch`. On top of that API, we will implement the `rollback` functionality. It will simply starts by getting the diff (patch) between the checkpoint and the current running config, then it will call the API `apply-patch` to update that patch.
+
+The [JsonPatch](https://pypi.org/project/jsonpatch/) python is an open source library that already implements the [RFC 6902 JSON Patch](https://tools.ietf.org/html/rfc6902). We can leverage this library to verify patch config, generate a diff between checkpoint and current running config, verify apply-patch and rollback work as expected by simulating the final output of the update and comparing with the observed output.
+
+**Example:**
+Assume running-config to be:
+```
+{
+ "DEVICE_NEIGHBOR": {
+ "Ethernet8": {
+ "name": "Servers1",
+ "port": "eth0"
+ },
+ "Ethernet96": {
+ "name": "Servers23",
+ "port": "eth0"
+ },
+ },
+ "DHCP_SERVERS": {
+ "1.1.1.1": {},
+ "2.2.2.2": {},
+ "3.3.3.3": {}
+ }
+}
+```
+
+and the ask to:
+- replace *port* under *Ethernet8* with *eth1*
+- add 4.4.4.4 to DHCP_SERVERS
+- remove 2.2.2.2 from DHCP_SERVERS
+
+The steps would be:
+
+1) Take the content of config DB here and store it as a checkpoint
+```
+admin@sonic:~$ config checkpoint mycheckpoint
+```
+2) Create a file on the device named `dhcp-changes.json-patch`, with the following content
+```
+[
+ {
+ "op": "replace",
+ "path": "/DEVICE_NEIGHBOR/Ethernet8/port",
+ "value": "eth1"
+ },
+ {
+ "op": "add",
+ "path": "/DHCP_SERVERS/4.4.4.4",
+ "value": {}
+ },
+ {
+ "op": "remove",
+ "path": "/DHCP_SERVERS/2.2.2.2"
+ }
+]
+```
+3) Apply patch using `apply-patch` command
+```
+admin@sonic:~$ config apply-patch ./dhcp-changes.json-patch
+```
+4) In case of failure, rollback the config using `rollback` command
+```
+admin@sonic:~$ config rollback mycheckpoint --verbose # verbose to see generated patch
+```
+This will internally do a diff, and generate patch of the needed changes and apply using `apply-patch`.
+The patch will be:
+```
+[
+ {
+ "op": "replace",
+ "path": "/DEVICE_NEIGHBOR/Ethernet8/port",
+ "value": "eth0"
+ },
+ {
+ "op": "remove",
+ "path": "/DHCP_SERVERS/4.4.4.4,",
+ "value": {}
+ },
+ {
+ "op": "add",
+ "path": "/DHCP_SERVERS/2.2.2.2"
+ },
+]
+```
+
+### 1.2.2 Container
+
+All the introduced commands will be part of the *python-sonic-utilities* package installed in Debian host O/S.
+
+# 2 Functionality
+
+## 2.1 Target Deployment Use Cases
+
+The `apply-patch` method should help with automating partial config updates, as external systems can generate the update patch, and apply.
+
+The `checkpoint` and `rollback` commands should help improve recoverability, can also be used by external systems to help revert failures during `apply-patch` operation.
+
+Human operators can also leverage the `checkpoint` and `rollback` functionalities while doing updates through the CLI using [SONiC CLI commands](https://github.com/Azure/sonic-utilities/blob/master/doc/Command-Reference.md).
+
+## 2.2 Functional Description
+
+### 2.2.1 Apply-Patch
+The SONiC `apply-patch` command can broadly classified into the following steps
+
+#### Stage-1 JSON Patch Verification
+Using [YANG SONiC models](https://github.com/Azure/sonic-buildimage/tree/master/src/sonic-yang-models), but the format of the JSON patch is not what YANG SONiC models is built to verify. We will verify using the following steps:
+1. Get current running config from ConfigDB as JSON
+2. Simulate the patch application on the current config JSON object
+3. Verify the the simulated output using YANG SONiC models
+
+#### Stage-2 JSON Patch Ordering
+There are many ideas to ordering the patch, I will pick a simple and straight forward idea to better understand this problem. Let's assume the main granular element is `Table`. Each table gets assigned an order index based on its semantic dependencies. Semantic dependencies mean tables referencing other tables, think of it as the result of doing a topological sorting of table dependencies. For example: `PORT` lots of table depend on it, but it does not depend on other tables so it gets a low index. `VLAN_MEMBER` depends on `PORT` so its gets a higher index, and so on. This helps make sure low order table absorb the changes first before dependent tables are updated.
+
+Let's assume the following order indices:
+```
+PORT = 1
+VLAN_MEMBER = 2
+ACL = 3
+```
+And the patch to update is the following:
+```
+[
+ { "op": "add", "path": "/ACL_TABLE/NO-NSW-PACL-V4/ports/0", "value": "Ethernet2" }
+ { "op": "add", "path": "/VLAN_MEMBER/Vlan100|Ethernet2", "value": { "tagging_mode": "untagged" } }
+ { "op": "add", "path": "/PORT/Ethernet2", "value": { "lanes": "65", "speed": "10000"} }
+]
+```
+
+Each operation belongs to a single table, the table name will be the first token in the path after the first `/`. For example the table of the first operation is `ACL_TABLE`. Let's add the table name to each operation.
+```
+[
+ { "table": "ACL_TABLE", "op": "add", "path": "/ACL_TABLE/NO-NSW-PACL-V4/ports/0", "value": "Ethernet2" }
+ { "table": "VLAN_MEMBER", "op": "add", "path": "/VLAN_MEMBER/Vlan100|Ethernet2", "value": { "tagging_mode": "untagged" } }
+ { "table": "PORT", "op": "add", "path": "/PORT/Ethernet2", "value": { "lanes": "65", "speed": "10000"} }
+]
+```
+
+Using the indices table above, let's assign an order index to each operation:
+```
+[
+ { "order": 3, "table": "ACL_TABLE", "op": "add", "path": "/ACL_TABLE/NO-NSW-PACL-V4/ports/0", "value": "Ethernet2" }
+ { "order": 2, "table": "VLAN_MEMBER", "op": "add", "path": "/VLAN_MEMBER/Vlan100|Ethernet2", "value": { "tagging_mode": "untagged" } }
+ { "order": 1, "table": "PORT", "op": "add", "path": "/PORT/Ethernet2", "value": { "lanes": "65", "speed": "10000"} }
+]
+```
+
+Now let's order the operations by "order":
+```
+[
+ { "order": 1, "table": "PORT", "op": "add", "path": "/PORT/Ethernet2", "value": { "lanes": "65", "speed": "10000"} }
+ { "order": 2, "table": "VLAN_MEMBER", "op": "add", "path": "/VLAN_MEMBER/Vlan100|Ethernet2", "value": { "tagging_mode": "untagged" } }
+ { "order": 3, "table": "ACL_TABLE", "op": "add", "path": "/ACL_TABLE/NO-NSW-PACL-V4/ports/0", "value": "Ethernet2" }
+]
+```
+This will be the final order of applying the changes.
+
+Unfortunately this solution does not always work especially for the case of deletion from PORT, VLAN_MEMBER, ACL_TABLE. Where if following the same logic we will have:
+```
+[
+ { "order": 1, "table": "PORT", "op": "remove", "path": "/PORT/Ethernet2" }
+ { "order": 2, "table": "VLAN_MEMBER", "op": "remove", "path": "/VLAN_MEMBER/Vlan100|Ethernet2" }
+ { "order": 3, "table": "ACL_TABLE", "op": "remove", "path": "/ACL_TABLE/NO-NSW-PACL-V4/ports/0" }
+]
+```
+This will not work, as the PORT table will complain that the port `Ethernet2` is still in use by a `VLAN_MEMBER`.
+
+Since this problem can be solved by many ways, and it needs to verified thoroughly, let's abstract it to a a contract which will be implemented later.
+
+The contract would be:
+```python
+list order-patch(JsonPatch jsonPatch)
+```
+
+Here is a summary explaining the `JsonChange` contract. Check [3.1.1.4.1 JsonChange](#31141-jsonchange) for detailed description.
+
+|aspect |description
+|------------|-----------
+|definition | JsonChange is a JsonPatch in terms of the final outcome of the update. Ordering of JsonChange updates will not follow the operations order within a JsonPatch, but will update the JSON file in any arbitrary order.
+
+
+Here is a summary explaining the `order-patch` contract, Check [3.1.1.4 Patch Orderer](#3114-patch-orderer) for detailed description.
+
+|aspect |item |description
+|------------|---------------------|-----------
+|inputs |JsonPatch | It represents the changes that needs to applied to the device running config, described in [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902).
+|outputs |list<JsonChange>| The list will contain the steps to be followed to apply the input JsonPatch correctly. Each item in the list is assumed to be executed after the previous item, in the order given in the list.
+|errors |malformedPatchError | Will be raised if the input JsonPatch is not valid according to [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902).
+| |other errors | Check [3.1.1.4.2 Order-Patch](#31142-order-patch) for exact list of errors to expect.
+|side-effects|None |
+|assumptions |running-config locked| The implementor of this contract might interact with ConfigDB to get the running-config, it is assumed the running-config is locked for changes for the lifespan of the operation.
+
+#### Stage-3 Applying list of JsonChanges in order
+There are a few SONiC applications which store their configuration in the ConfigDB. These applications do not subscribe to the ConfigDB change events. So any changes to their corresponding table entries as part of the patch apply process in the ConfigDB are not processed by the application immediately. In order to apply the configuration changes, corresponding service needs to be restarted. Listed below are some example tables from SONiC config, and the corresponding services that need to be manually restarted.
+
+
+**NOTE**: In the below table we have "Key": ["list-item1", ...]. Key in below example is the table name, corresponding list is the list of services that needs restarting post table update.
+
+```
+{
+ "SYSLOG_SERVER": ["rsyslog"],
+ "DHCP_SERVER": ["dhcp_relay"],
+ "NTP_SERVER": ["ntp-config.service", "ntp.service"]
+ "BGP_MONITORS": ["bgp"],
+ "BUFFER_PROFILE": ["swss"],
+ "RESTAPI": ["restapi"]
+}
+```
+
+Although some other services do not need manual restarting, and absorb the configs silently, there is no good way to make sure there is no errors encountered while the services absorbed the changes. Some of these services might report an error to syslog, others might crash ...etc.
+
+Currently there is no standard approach of updating ConfigDB that takes care of manual service restart and verifying services have absorbed change correctly.
+
+So we are going to introduce a new contract overlaying ConfigDB changes, that will take care of making correct changes to ConfigDB as well as verifying that corresponding services have absorbed the changes correctly.
+
+The contract would be:
+```python
+void apply-change(JsonChange jsonChange)
+```
+
+Check [3.1.1.4.1 JsonChange](#31141-jsonchange) for detailed description of JsonChange.
+
+Here is a summary explaining the `apply-change` contract, Check [3.1.1.4 Change Applier](#3115-change-applier) for detailed description.
+
+|aspect |item |description
+|------------|-----------------------|-----------
+|inputs |JsonChange | It represents the changes that needs to applied to the device running config, described in [3.1.1.4.1 JsonChange](#31141-jsonchange).
+|outputs |None |
+|errors |malformedChangeError | Will be raised if the input JsonChange is not valid according to [3.1.1.4.1 JsonChange](#31141-jsonchange).
+| |other errors | Check [3.1.1.4.1 apply-change](#31141-apply-change) for exact list of errors to expect.
+|side-effects|updating running-config| This operation will cause changes to the running-config according to the input JsonChange.
+|assumptions |running-config locked| The implementor of this contract will interact with ConfigDB to updating the running-config, it is assumed the running-config is locked for changes for the lifespan of the operation.
+
+#### Stage-4 Post-update validation
+The expectations after applying the JsonPatch is that it will adhere to [RFC 6902](https://tools.ietf.org/html/rfc6902).
+
+The verification steps
+1) Get the state of ConfigDB JSON before the update as a JSON object
+2) Simulate the JsonPatch application over this JSON object
+3) Compare that JSON object with current ConfigDB JSON
+4) In case of mismatch, just report failure
+
+#### Fail-safe Action
+
+If an error is encountered during the `apply-patch` operation, an error is reported and the system DOES NOT take any automatic action. The user can take a `checkpoint` before running `apply-patch` and if the operation failed, the user can `rollback`. Another idea is to introduce a `config-session` where a user enters a `config-session` mode does all the modifications, once they are happy with it, they `commit` the changes to ConfigDB. `config-session` can be built using `checkpoint` and `rollback` functionality, but this `config-session` idea is beyond the scope of this document.
+
+#### Logging
+
+All the configuration update operations executed and the output displayed by the `apply-patch` command are stored in the systemd journal. They are also forwarded to the syslog. By storing the commands in the systemd-journal, the user will be able to search and display them easily at a later point in time. The `show apply-patch log` command reads the systemd-journal to display information about the `apply-patch` command that was previously executed or currently in progress.
+
+### 2.2.2 Checkpoint
+The SONiC `checkpoint` command can broadly classified into the following steps
+
+#### Stage-1 Get current ConfigDB JSON config
+The *ConfigDBConnector* class is used to obtain the running configuration in JSON format
+
+#### Stage-2 Validating current ConfigDB JSON config using YANG models
+ConfigDB might be in invalid to begin with and later if used for rollback it will not work.
+
+#### Stage-3 Save JSON config
+Save the checkpoint to a dedicated location on the SONiC box
+
+### 2.2.3 Rollback
+The SONiC `rollback` command can broadly classified into the following steps
+
+#### Stage-1 Get current ConfigDB JSON config
+The *ConfigDBConnector* class is used to obtain the running configuration in JSON format
+
+#### Stage-2 Get checkpoint JSON config
+Load the checkpoint from the SONiC box
+
+#### Stage-3 Generate the diff as JsonPatch between current config and checkpoint
+The current ConfigDB JSON config is compared with the JSON config from the checkpoint. The comparison result should be in JsonPatch format.
+
+#### Stage-4 Apply-Patch
+Pass the generated JsonPatch to the apply-patch API
+
+#### Stage-5 Verify config rollback
+Compare the ConfigDB JSON after the update with the checkpoint JSON, there should be no differences.
+
+#### Fail-safe Action
+
+If an error is encountered during the `rollback` operation, an error is reported and the system DOES NOT take any automatic action. Rollback operation is itself an automated fail-safe action, if itself fails the caller should decide how to handle such failures e.g. generate an alert of high severity, or do `config reload`.
+
+#### Logging
+
+All the configuration update operations executed and the output displayed by the `rollback` command are stored in the systemd journal. They are also forwarded to the syslog. By storing the commands in the systemd-journal, the user will be able to search and display them easily at a later point in time. The `show rollback log` command reads the systemd-journal to display information about the `rollback` command that was previously executed or currently in progress.
+
+### 2.2.4 Replace
+The SONiC `replace` command can broadly classified into the following steps
+
+#### Stage-1 Get target config from the external user
+The external user to provide the full target ConfigDB config in JSON format.
+
+#### Stage-2 Validating the target config using YANG models
+The target config are unknown configs and need to be validating using YANG models
+
+#### Stage-3 Get current ConfigDB JSON config
+The *ConfigDBConnector* class is used to obtain the running configuration in JSON format
+
+#### Stage-4 Generate the diff as JsonPatch between current config and target config
+The current ConfigDB JSON config is compared with the target JSON config. The comparison result should be in JsonPatch format.
+
+#### Stage-5 Apply-Patch
+Pass the generated JsonPatch to the apply-patch API
+
+#### Stage-6 Verify config replace
+Compare the ConfigDB JSON after the update with the target JSON, there should be no differences.
+
+#### Fail-safe Action
+
+If an error is encountered during the `replace` operation, an error is reported and the system DOES NOT take any automatic action. The user can take a `checkpoint` before running `replace` and if the operation failed, the user can `rollback`.
+
+#### Logging
+
+All the configuration update operations executed and the output displayed by the `replace` command are stored in the systemd journal. They are also forwarded to the syslog. By storing the commands in the systemd-journal, the user will be able to search and display them easily at a later point in time. The `show replace log` command reads the systemd-journal to display information about the `replace` command that was previously executed or currently in progress.
+
+# 3 Design
+
+## 3.1 Overview
+
+### 3.1.1 ApplyPatch
+
+
+
+#### 3.1.1.1 User
+The user of the system, can simply be a human operator or a service that can talk to SONiC CLI. The user can only apply-patch if they have an admin permission. Users without admin permissions can only execute dry-run of the operations where they will be able to see the exact changes going to affect the device, without executing these changes.
+
+#### 3.1.1.2 SONiC CLI
+These are the CLI of SONiC switch to which makes it easy for the users to interact with the system. The CLI commands we are interested in are `config ...` and `show ...`, check [SONiC Command Line Interface Guide](https://github.com/Azure/sonic-utilities/blob/master/doc/Command-Reference.md) to learn more about SONiC CLI.
+
+For further details on the CLI setup, Check [3.2.2 CLI](#322-cli)
+
+#### 3.1.1.3 YANG models
+YANG is a data modeling language used to model configuration data, state data, Remote Procedure Calls, and notifications for network management protocols. For further details check [The YANG 1.1 Data Modeling Language](https://tools.ietf.org/html/rfc7950)
+
+SONiC is currently getting on-boarded to YANG data models to help verify and generate the configurations. We will leverage these YANG models to help verify the result of simulating the JsonPatch on ConfigDb, to make sure final outcome adheres to all the constrains defined in the YANG models. For further details check [YANG SONiC models](https://github.com/Azure/sonic-buildimage/tree/master/src/sonic-yang-models).
+
+#### 3.1.1.4 Patch Orderer
+This component is going to solve the problems discussed in [Stage-2 JSON Patch Ordering](#stage-2-json-patch-ordering). This component is going to help provide an order of execution to the JsonPatch, in such a way when the config is updated in this order, there will be no errors generated on the device. The exact implementation details of this component will not be included in this design document, but we are going to explain in details the contract for any implementation.
+
+The contract would be:
+```python
+list order-patch(JsonPatch jsonPatch)
+```
+
+##### 3.1.1.4.1 JsonChange
+
+|aspect |description
+|------------|-----------
+|definition | JsonChange is a JsonPatch in terms of the final outcome of the update. Ordering of JsonChange updates will not follow the operations order within a JsonPatch, but will update the JSON file in any arbitrary order.
+|validation | JsonChange is considered valid if its corresponding JsonPatch is valid according to [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902)
+
+Assume we have the following JsonPatch:
+```
+[
+ { "op": "add", "path": "/ACL_TABLE/NO-NSW-PACL-V4/ports/0", "value": "Ethernet2" }
+ { "op": "add", "path": "/VLAN_MEMBER/Vlan100|Ethernet2", "value": { "tagging_mode": "untagged" } }
+ { "op": "add", "path": "/PORT/Ethernet2", "value": { "lanes": "65", "speed": "10000"} }
+]
+```
+
+Operations specified in the JsonPatch will be executed in the order specified, but JsonChange can be applied in any arbitrary order as the implementation specify, for example:
+```
+[
+ { "op": "add", "path": "/PORT/Ethernet2", "value": { "lanes": "65", "speed": "10000"} }
+ { "op": "add", "path": "/VLAN_MEMBER/Vlan100|Ethernet2", "value": { "tagging_mode": "untagged" } }
+ { "op": "add", "path": "/ACL_TABLE/NO-NSW-PACL-V4/ports/0", "value": "Ethernet2" }
+]
+```
+or
+```
+[
+ { "op": "add", "path": "/PORT/Ethernet2", "value": { "lanes": "65", "speed": "10000"} }
+ { "op": "add", "path": "/VLAN_MEMBER/Vlan100|Ethernet2", "value": { "tagging_mode": "untagged" } }
+ { "op": "add", "path": "/ACL_TABLE/NO-NSW-PACL-V4/ports/0", "value": "Ethernet2" }
+]
+```
+
+The only condition of JsonChange is that the final outcome after applying the whole JsonPatch is the same.
+
+##### 3.1.1.4.2 Order-Patch
+
+|aspect |item |description
+|------------|-------------------------|-----------
+|inputs |JsonPatch | It represents the changes that needs to applied to the device running config, described in [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902).
+|outputs |list<JsonChange> | The list will contain the steps to be followed to apply the input JsonPatch correctly. Each item in the list is assumed to be executed after the previous item, in the order given in the list.
+|errors |malformedPatchError | Will be raised if the input JsonPatch is not valid according to [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902).
+| |unprocessableRequestError| Will be raised if the implementation of the `order-patch` is not able to provide a valid ordering according to its own ordering validations.
+| |resourceNotFoundError | Will be raised if running config failed to be read or in case any other external resource is not found nor available.
+| |conflictingStateError | Will be raised if the patch cannot be applied to the current state of the running config e.g. trying to add an item to a non-existing json dictionary.
+| |internalError | Will be raised if any other error is encountered that's different than the ones listed above.
+|side-effects|None |
+|assumptions |running-config locked | The implementor of this contract might interact with ConfigDB to get the running-config, it is assumed the ConfigDB is locked for changes for the lifespan of the operation.
+
+If `order-patch` has to force the update to follow very specific steps, it would have to provide multiple JsonChange objects in the return list of `order-patch`.
+
+`order-patch` is returning a list of JsonChanges instead of a simple JsonPatch with multiple operations because a JsonChange can group together multiple JsonPatch operations that share no dependency and can be executed together. This can help the implementor of `apply-change` to optimize the mechanism for applying JsonChange e.g. group changes under same parent together or reduce number of service restarts.
+
+For example:
+Assume JsonPatch contains:
+```
+[
+ { "op": "add", "path": "/DHCP_SERVERS/4.4.4.4", "value": {} },
+ { "op": "replace", "path": "/DEVICE_NEIGHBOR/Ethernet8/port", "value": "eth1" },
+ { "op": "add", "path": "/DHCP_SERVERS/2.2.2.2", "value": {} }
+]
+```
+We have 2 operations updating DHCP servers, and another operation for DEVICE_NEIGHBOR. We can assume DHCP and DEVICE_NEIGHBOR tables to be independent meaning they can updated at the same time. `order-patch` would return:
+```
+[
+ [
+ { "op": "add", "path": "/DHCP_SERVERS/4.4.4.4", "value": {} },
+ { "op": "replace", "path": "/DEVICE_NEIGHBOR/Ethernet8/port", "value": "eth1" },
+ { "op": "add", "path": "/DHCP_SERVERS/2.2.2.2", "value": {} }
+ ],
+]
+```
+Updating DHCP_SERVERS requires restarting `dhcp_relay` service, so if the above patch is to be executed in order, we will restart `dhcp_relay` service twice.
+But since the implementor of `apply-change` can order the operations in any way they see fit since they are OK to update together. They can decide move the DHCP updates together, and DHCP table twice, but restart `dhcp_relay` service only once.
+
+Let's take a visual example, assume we have a JsonPatch with 8 operations, and here is the topological order of the operation. Arrow from op-x to op-y means op-y depends on op-x.
+
+
+
+If we sort by on the operations we would have:
+
+
+
+But if we organize the operations into groups of JsonChange, we will have:
+
+
+
+This will allow the the implementor of `apply-change` to have the freedom to optimize the operations in any order they see fit.
+
+**NOTE:** Check Patch Orderer implementation design design details in [Json_Patch_Ordering_using_YANG_Models_Design](Json_Patch_Ordering_using_YANG_Models_Design.md) document.
+
+#### 3.1.1.5 Change Applier
+This component is going to solve the problems discussed in [Stage-3 Applying list of JsonChanges in order](#stage-3-applying-list-of-jsonchanges-in-order). This component is going to help provide a mechanism for updating a JsonChange taking into account manual service restarts, and update verification. The exact implementation details of this component will not be included in this design document, but we are going to explain in details the contract for any implementation.
+
+The contract would be:
+```python
+void apply-change(JsonChange jsonChange)
+```
+
+##### 3.1.1.5.1 Apply-Change
+|aspect |item |description
+|------------|-------------------------|-----------
+|inputs |JsonChange | It represents the changes that needs to applied to the device running config, described in [3.1.1.4.1 JsonChange](#31141-jsonchange).
+|outputs |None |
+|errors |malformedChangeError | Will be raised if the input JsonChange is not valid according to [3.1.1.4.1 JsonChange](#31141-jsonchange).
+| |resourceNotFoundError | Will be raised if running config failed to be read or in case any other external resource is not found nor available.
+| |unprocessableRequestError| Will be raised if the change is valid, all the resources are found but when applying the change it causes an error in the system.
+| |internalError | Will be raised if any other error is encountered that's different than the ones listed above.
+|side-effects|updating running-config | This operation will cause changes to the running-config according to the input JsonChange.
+|assumptions |running-config locked | The implementor of this contract will interact with ConfigDB to updating the running-config, it is assumed the ConfigDB is locked for changes for the lifespan of the operation.
+
+Since the order of executing the operation does not matter, the implementor of this component can work on optimizing the time to run the operation. For details check [3.1.1.4 Change Applier](#3115-change-applier).
+
+**NOTE:** Check Change Applier implementation design design details in [Json_Change_Application_Design](Json_Change_Application_Design.md) document.
+
+#### 3.1.1.6 ConfigDB
+SONiC is managing configuration in a single source of truth - a redisDB instance that we refer as ConfigDB. Applications subscribe to ConfigDB and generate their running configuration correspondingly.
+
+For further details on the ConfigDB, check [SONiC Configuration Database Manual](https://github.com/Azure/SONiC/wiki/Configuration).
+
+### 3.1.2 Checkpoint
+
+
+#### 3.1.2.1 User
+The user of the system, can simply be a human operator or a service that can talk to SONiC CLI. The user can only apply-patch if they have an admin permission.
+
+#### 3.1.2.2 SONiC CLI
+Same as [3.1.1.2 SONiC CLI](#3112-sonic-cli)
+
+#### 3.1.2.3 YANG models
+Same as [3.1.1.3 YANG models](#3113-yang-models)
+
+#### 3.1.2.4 ConfigDB
+same as [3.1.1.5 ConfigDB](#3115-configdb)
+
+#### 3.1.2.5 File system
+This will the file system where SONiC os is setup. Some suggestions prefer the path `/var/sonic/checkpoints`, but that is not decided yet. Will leave it to the implementor of this design document to decide.
+
+### 3.1.3 Rollback
+
+
+#### 3.1.3.1 User
+Same as [3.1.2.1 User](#3121-user)
+
+#### 3.1.3.2 SONiC CLI
+Same as [3.1.1.2 SONiC CLI](#3112-sonic-cli)
+
+#### 3.1.3.4 File system
+Same as [3.1.2.5 File system](#3125-file-system)
+
+#### 3.1.3.4 ConfigDB
+same as [3.1.1.5 ConfigDB](#3115-configdb)
+
+### 3.1.4 Replace
+
+
+#### 3.1.4.1 User
+Same as [3.1.2.1 User](#3121-user)
+
+#### 3.1.4.2 SONiC CLI
+Same as [3.1.1.2 SONiC CLI](#3112-sonic-cli)
+
+#### 3.1.4.3 YANG models
+Same as [3.1.1.3 YANG models](#3113-yang-models)
+
+#### 3.1.4.4 File system
+Same as [3.1.2.5 File system](#3125-file-system)
+
+#### 3.1.4.5 ConfigDB
+same as [3.1.1.5 ConfigDB](#3115-configdb)
+
+### 3.2 User Interface
+
+### 3.2.1 Data Models
+
+#### 3.2.1.1 JsonPatch
+
+The JsonPatch consistes of a list operation, and each operation follows this format:
+```
+ { "op": "", "path": "", "value": "", "from": "" }
+```
+For detailed information about the JSON patch operations refer to the section 4(Operations) of [RFC 6902](https://tools.ietf.org/html/rfc6902).
+
+
+
+**Operation Code**
+
+- replace - Set ConfigDB entry described in Path to be equal to the data specified in Value
+- add - Create a new ConfigDB entry described in Path and set it Value
+- remove - Delete the ConfigDB entry described in Path
+- copy - Copy the ConfigDB entry specified in the FromPath to create a ConfigDB entry specified in Path
+- move - Copy the ConfigDB entry specified in the FromPath to create a ConfigDB entry specified in Path and then delete the ConfigDB entry in FromPath
+
+**Path**
+
+Describes the location of the ConfigDB entry which is being processed. The path string can be dissected into below elements.
+
+- Table Name - The ConfigDB table corresponding to the entry
+- Key - The Key string to identify the row data within the ConfigDB table
+- Field - The column_key to identify the ConfigDB entry within the identified row data
+
+e.g "/VLAN_MEMBER/Vlan10|Ethernet0/tagging_mode"
+
+- Table: VLAN_MEMBER
+- Key: Vlan10|Ethernet0
+- Field: tagging_mode
+
+
+**FromPath**
+
+- Same as Path used in copy and move operations
+
+
+
+**Value**
+
+- Data that is used to patch the ConfigDB entry specified in path
+
+### 3.2.2 CLI
+
+#### 3.2.2.1 Configuration Commands
+
+**apply-patch**
+*Command Format*
+
+config apply-patch <*patch-filename*> [--dry-run] [--verbose]
+
+| Command Option | Purpose |
+| ----------------- | ------------------------------------------------------------ |
+|<*patch-filename*> | The file of the JsonPatch file to apply which follows [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902) specifications |
+|dry-run | Displays the generates commands going to be executed without running them. |
+|verbose | Provide additional details about each step executed as part of the operation. |
+
+*Command Usage*
+
+| Command | Purpose |
+| ------------------------------------------------- | ------------------------------------------------------------ |
+| config apply-patch *filename* | Applies the given JsonPatch file operations following the [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902) specifications. |
+| config apply-patch *filename* --dry-run | Displays the generates commands going to be executed without running them. |
+| config apply-patch *filename* --verbose | Applies the given JsonPatch file operations following the [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902) specifications. The CLI output will include additional details about each step executed as part of the operation. |
+| config apply-patch *filename* --dry-run --verbose | Displays the generates commands going to be executed without running them. The CLI output will include additional details about each step executed as part of the operation. |
+
+
+**checkpoint**
+
+*Command Format*
+
+config checkpoint <*checkpoint-name*> [--dry-run] [--verbose]
+
+| Command Option | Purpose |
+| ------------------- | ----------------------------------------------------------------------------- |
+|<*checkpoint-name*> | The name of the checkpoint where ConfigDB JSON config will saved under. |
+|dry-run | Displays the generates commands going to be executed without running them. |
+|verbose | Provide additional details about each step executed as part of the operation. |
+
+*Command Usage*
+
+| Command | Purpose |
+| -------------------------------------------------------- | ------------------------------------------------------------ |
+| config checkpoint *checkpoint-name* | Will save ConfigDB JSON config as a checkpoint with the name *checkpoint-name*. |
+| config checkpoint *filename* --dry-run | Displays the generates commands going to be executed without running them. |
+| config checkpoint *filename* --verbose | Will save ConfigDB JSON config as a checkpoint with the name *checkpoint-name*. The CLI output will include additional details about each step executed as part of the operation. |
+| config checkpoint *filename* --dry-run --verbose | Displays the generates commands going to be executed without running them. The CLI output will include additional details about each step executed as part of the operation. |
+
+**checkpoint**
+
+*Command Format*
+
+config rollback <*checkpoint-name*> [--dry-run] [--verbose]
+
+| Command Option | Purpose |
+| ------------------ | ----------------------------------------------------------------------------- |
+|<*checkpoint-name*> | The name of the checkpoint where ConfigDB JSON config will saved under |
+|dry-run | Displays the generates commands going to be executed without running them. |
+|verbose | Provide additional details about each step executed as part of the operation. |
+
+*Command Usage*
+
+| Command | Purpose |
+| ---------------------------------------------- | ------------------------------------------------------------ |
+| config rollback *checkpoint-name* | Rolls back the ConfigDB JSON config to the config saved under *checkpoint-name* checkpoint. |
+| config rollback *filename* --dry-run | Displays the generates commands going to be executed without running them. |
+| config rollback *filename* --verbose | Rolls back the ConfigDB JSON config to the config saved under *checkpoint-name* checkpoint. The CLI output will include additional details about each step executed as part of the operation.
+| config rollback *filename* --dry-run --verbose | Displays the generates commands going to be executed without running them. The CLI output will include additional details about each step executed as part of the operation. |
+
+#### 3.2.2.2 Show Commands
+
+**apply-patch**
+*Command Format*
+
+show apply-patch log [exec | verify | status]
+
+| Command | Purpose |
+| --------------------------- | ------------------------------------------------------------ |
+| show apply-patch log exec | Displays a log of all the ConfigDB operations executed including
those that failed. In case of a failed operation, it displays an
error message against the failed operation. |
+| show apply-patch log verify | Displays a log all the ConfigDB operations that failed,
along with an error message. It does not display the
operations that were successful. |
+| show apply-patch log status | Displays the status of last successful patch application
operation since switch reboot. |
+
+**rollback**
+*Command Format*
+
+show rollback log [exec | verify | status]
+
+| Command | Purpose |
+| ------------------------ | ------------------------------------------------------------ |
+| show rollback log exec | Displays a log of all the ConfigDB operations executed including
those that failed. In case of a failed operation, it displays an
error message against the failed operation. |
+| show rollback log verify | Displays a log all the ConfigDB operations that failed,
along with an error message. It does not display the
operations that were successful. |
+| show rollback log status | Displays the status of last successful config rollback
operation since switch reboot. |
+
+
+#### 3.2.2.3 Debug Commands
+
+Use the *verbose* option to view additional details while executing the different commands.
+
+# 4 Flow Diagrams
+
+# 5 Error Handling
+
+If an error is encountered during executing any of the commands, the error is reported to the user. The system does not do any recovery actions, and leaves it up to the user to decide.
+
+# 6 Serviceability and Debug
+All commands logs are stored in systemd-journal and syslog.
+
+
+# 7 Warm Boot Support
+N/A
+
+
+# 8 Scalability
+N/A
+
+# 9 Unit Tests
+## 9.1 Unit Tests for Apply-Patch
+| Test Case | Description |
+| --------- | ----------- |
+| 1 | Add a new table. |
+| 2 | Remove an existing table. |
+| 3 | Modify values of an existing table entry. |
+| 4 | Modify value of an existing item an array value. |
+| 5 | Add a new item to an array value. |
+| 6 | Remove an item form an array value. |
+| 7 | Add a new key to an existing table .|
+| 8 | Remove a key from an existing table. |
+| 9 | Remove 2 items that depends on each other but in different tables e.g. /PORT/Ethernet2 and /VLAN_MEMBER/Vlan101|Ethernet2. |
+| 10 | Add 2 items that depends on each other but in different tables e.g. /PORT/Ethernet2 and /VLAN_MEMBER/Vlan101|Ethernet2. |
+| 11 | Remove 2 items that depends on each other in the same table e.g. /INTERFACE/INTERFACE_LIST and /INTERFACE/INTERFACE_PREFIX_LIST. |
+| 12 | Add 2 items that depends on each other in the same table e.g. /INTERFACE/INTERFACE_LIST and /INTERFACE/INTERFACE_PREFIX_LIST. |
+| 13 | Replace a mandatory item e.g. type under ACL_TABLE. |
+| 14 | Dynamic port breakout as described [here](https://github.com/Azure/SONiC/blob/master/doc/dynamic-port-breakout/sonic-dynamic-port-breakout-HLD.md).|
+| 15 | Remove an item that has a default value. |
+| 16 | Modifying items that rely depends on each other based on a `must` condition rather than direct connection such as `leafref` e.g. /CRM/acl_counter_high_threshold (check [here](https://github.com/Azure/sonic-buildimage/blob/master/src/sonic-yang-models/yang-models/sonic-crm.yang)). |
+| 17 | Updating Syslog configs. |
+| 18 | Updating AAA configs. |
+| 19 | Updating DHCP configs. |
+| 20 | Updating IPv6 configs. |
+| 21 | Updating monitor configs (EverflowAlaysOn). |
+| 22 | Updating BGP speaker configs. |
+| 23 | Updating BGP listener configs. |
+| 24 | Updating Bounce Back Routing configs. |
+| 25 | Updating control-plane ACLs (NTP, SNMP, SSH) configs. |
+| 26 | Updating Ethernet interfaces configs. |
+| 27 | Updating VLAN interfaces configs. |
+| 28 | Updating port-channel interfaces configs. |
+| 29 | Updating loopback interfaces configs. |
+| 30 | Updating BGP prefix hijack configs. |
+
+## 9.2 Unit Tests for Checkpoint
+| Test Case | Description |
+| --------- | ----------- |
+| 1 | Invalid Configs according to YANG models should fail to be saved. |
+| 2 | Saving ConfigDB successfully to a file. |
+
+## 9.3 Unit Tests for Rollback
+| Test Case | Description |
+| --------- | ----------- |
+| 1 ..* | Rollback all unit-tests specified in [9.1 Unit Tests for Apply-Patch](#91-unit-tests-for-apply-patch). |
+
+## 9.4 Unit Tests for Replace
+| Test Case | Description |
+| --------- | ----------- |
+| 1 ..* | Use replace instead of apply-patch for unit-tests specified in [9.1 Unit Tests for Apply-Patch](#91-unit-tests-for-apply-patch). |
diff --git a/doc/config-generic-update-rollback/files/apply-change-design.png b/doc/config-generic-update-rollback/files/apply-change-design.png
new file mode 100644
index 0000000000..e0c52b7ab3
Binary files /dev/null and b/doc/config-generic-update-rollback/files/apply-change-design.png differ
diff --git a/doc/config-generic-update-rollback/files/apply-patch-design.png b/doc/config-generic-update-rollback/files/apply-patch-design.png
new file mode 100644
index 0000000000..5154fc2bc6
Binary files /dev/null and b/doc/config-generic-update-rollback/files/apply-patch-design.png differ
diff --git a/doc/config-generic-update-rollback/files/basic-target-design.png b/doc/config-generic-update-rollback/files/basic-target-design.png
new file mode 100644
index 0000000000..398aea2090
Binary files /dev/null and b/doc/config-generic-update-rollback/files/basic-target-design.png differ
diff --git a/doc/config-generic-update-rollback/files/checkpoint-design.png b/doc/config-generic-update-rollback/files/checkpoint-design.png
new file mode 100644
index 0000000000..4eb48ded59
Binary files /dev/null and b/doc/config-generic-update-rollback/files/checkpoint-design.png differ
diff --git a/doc/config-generic-update-rollback/files/config-transitions-diagram.png b/doc/config-generic-update-rollback/files/config-transitions-diagram.png
new file mode 100644
index 0000000000..e3f5527c64
Binary files /dev/null and b/doc/config-generic-update-rollback/files/config-transitions-diagram.png differ
diff --git a/doc/config-generic-update-rollback/files/jsonchanges-order.png b/doc/config-generic-update-rollback/files/jsonchanges-order.png
new file mode 100644
index 0000000000..e03f7154db
Binary files /dev/null and b/doc/config-generic-update-rollback/files/jsonchanges-order.png differ
diff --git a/doc/config-generic-update-rollback/files/jsonpatch-operations-order.png b/doc/config-generic-update-rollback/files/jsonpatch-operations-order.png
new file mode 100644
index 0000000000..b5e8b360aa
Binary files /dev/null and b/doc/config-generic-update-rollback/files/jsonpatch-operations-order.png differ
diff --git a/doc/config-generic-update-rollback/files/jsonpatch-topology.png b/doc/config-generic-update-rollback/files/jsonpatch-topology.png
new file mode 100644
index 0000000000..175e9cf839
Binary files /dev/null and b/doc/config-generic-update-rollback/files/jsonpatch-topology.png differ
diff --git a/doc/config-generic-update-rollback/files/replace-design.png b/doc/config-generic-update-rollback/files/replace-design.png
new file mode 100644
index 0000000000..477ce0156a
Binary files /dev/null and b/doc/config-generic-update-rollback/files/replace-design.png differ
diff --git a/doc/config-generic-update-rollback/files/rollback-design.png b/doc/config-generic-update-rollback/files/rollback-design.png
new file mode 100644
index 0000000000..2b905e818f
Binary files /dev/null and b/doc/config-generic-update-rollback/files/rollback-design.png differ
diff --git a/doc/config-generic-update-rollback/files/sonic-design.png b/doc/config-generic-update-rollback/files/sonic-design.png
new file mode 100644
index 0000000000..b9ef4b2bec
Binary files /dev/null and b/doc/config-generic-update-rollback/files/sonic-design.png differ
diff --git a/doc/config-generic-update-rollback/files/valid-config-transitions-diagram.png b/doc/config-generic-update-rollback/files/valid-config-transitions-diagram.png
new file mode 100644
index 0000000000..7430dfb37f
Binary files /dev/null and b/doc/config-generic-update-rollback/files/valid-config-transitions-diagram.png differ