HC2VPP-168 - Gpe native entries support(write only) 25/7125/6
authorJan Srnicek <[email protected]>
Fri, 16 Jun 2017 06:32:59 +0000 (08:32 +0200)
committerMarek Gradzki <[email protected]>
Mon, 19 Jun 2017 05:36:32 +0000 (05:36 +0000)
 requires https://gerrit.fd.io/r/#/c/7168 to be merged

Change-Id: I5b734af662e651df5753f64f14b6b44d863ecbe8
Signed-off-by: Jan Srnicek <[email protected]>
lisp/gpe_postman_collection.json
lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/write/GpeWriterFactory.java
lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/write/NativeForwardPathCustomizer.java [new file with mode: 0644]
lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/write/NativeForwardPathsTableCustomizer.java [new file with mode: 0644]
lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/gpe/translate/GpeModuleTest.java
lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/gpe/translate/write/NativeForwardPathCustomizerTest.java [new file with mode: 0644]
lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/gpe/translate/write/NativeForwardPathsTableCustomizerTest.java [new file with mode: 0644]

index 126650d..d2ef1d4 100644 (file)
@@ -3,6 +3,7 @@
        "name": "Lisp gpe RESTCONF collection",
        "description": "",
        "order": [
+               "f0ae8c21-de3e-2ec1-c816-4cc2e970a839",
                "6a934021-ad9b-d1ef-4059-8639caddc2bf",
                "7ff012c8-9065-008b-4552-cf0de8846426",
                "2b9b1bec-1e40-b7c9-4756-c2eee3936d73",
                "12fac9c2-162d-7274-5f90-6e943f7a9433",
                "5682b704-dc88-8186-c0ed-f7bb952f8150"
        ],
-       "folders": [],
-       "timestamp": 1495177828276,
+       "folders": [
+               {
+                       "id": "a2b53670-baa2-92ae-6309-08d23db0a70d",
+                       "name": "Native entries",
+                       "description": "",
+                       "order": [
+                               "33fc474a-30f2-ec43-eb3d-7de056dbcda0",
+                               "108cdf05-a647-ee74-f59e-e224f5827073"
+                       ],
+                       "owner": "658985"
+               }
+       ],
+       "timestamp": 0,
        "owner": "658985",
        "public": false,
        "requests": [
                {
-                       "id": "12fac9c2-162d-7274-5f90-6e943f7a9433",
+                       "id": "108cdf05-a647-ee74-f59e-e224f5827073",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
-                       "url": "http://localhost:8183/restconf/config/gpe:gpe/gpe-feature-data/gpe-entry-table/gpe-entry/gpe-entry-2",
+                       "headerData": [
+                               {
+                                       "key": "Authorization",
+                                       "value": "Basic YWRtaW46YWRtaW4=",
+                                       "description": "",
+                                       "enabled": true
+                               },
+                               {
+                                       "key": "Content-Type",
+                                       "value": "application/json",
+                                       "description": "",
+                                       "enabled": true
+                               }
+                       ],
+                       "url": "http://localhost:8183/restconf/config/gpe:native-forward-paths-tables/native-forward-paths-table/4",
+                       "queryParams": [],
                        "preRequestScript": null,
                        "pathVariables": {},
-                       "method": "DELETE",
+                       "pathVariableData": [],
+                       "method": "PUT",
                        "data": [],
                        "dataMode": "raw",
-                       "version": 2,
                        "tests": null,
                        "currentHelper": "normal",
                        "helperAttributes": {},
-                       "time": 1495183032877,
+                       "time": 1497354248641,
+                       "name": "Get table 4",
+                       "description": "",
+                       "collectionId": "71b7e698-4b8c-0ad6-38af-8304b6a5c4e0",
+                       "isFromCollection": true,
+                       "collectionRequestId": "9e99cfa4-474d-1f4d-26b3-c6caa7460d4b",
+                       "folder": "a2b53670-baa2-92ae-6309-08d23db0a70d",
+                       "rawModeData": "{\n\t\"native-forward-paths-table\":{\n\t  \"table-id\":\"4\",\n\t  \"native-forward-path\":[\n\t  \t{\n\t  \t\t\"next-hop-address\":\"192.168.2.1\",\n\t  \t\t\"next-hop-interface\":\"local0\"\n\t  \t},\n\t  \t{\n\t  \t\t\"next-hop-address\":\"192.168.3.1\"\n\t  \t},\n\t  \t{\n\t  \t\t\"next-hop-address\":\"2001:0db8:0a0b:12f0:0000:0000:0000:0001\"\n\t  \t}\n\t  \t]\n\t}\n}"
+               },
+               {
+                       "folder": null,
+                       "id": "12fac9c2-162d-7274-5f90-6e943f7a9433",
                        "name": "Delete gpe entry- negative mapping",
+                       "dataMode": "raw",
+                       "data": [],
+                       "descriptionFormat": null,
                        "description": "",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "method": "DELETE",
+                       "pathVariables": {},
+                       "url": "http://localhost:8183/restconf/config/gpe:gpe/gpe-feature-data/gpe-entry-table/gpe-entry/gpe-entry-2",
+                       "preRequestScript": null,
+                       "tests": null,
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "queryParams": null,
+                       "headerData": null,
+                       "pathVariableData": null,
                        "collectionId": "71b7e698-4b8c-0ad6-38af-8304b6a5c4e0",
-                       "responses": [],
-                       "rawModeData": "{\n\t\"gpe\":{\n\t\t\"gpe-feature-data\":{\n\t\t\t\"enable\":true\n\t\t}\n\t}\n}"
+                       "rawModeData": "{\n  \"gpe\":{\n    \"gpe-feature-data\":{\n      \"enable\":true\n    }\n  }\n}"
                },
                {
+                       "folder": null,
                        "id": "1bbf9810-f369-a2a1-95cc-5f42529480fe",
+                       "name": "Get gpe entry- negative mapping",
+                       "dataMode": "raw",
+                       "data": [],
+                       "descriptionFormat": null,
+                       "description": "",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "method": "GET",
+                       "pathVariables": {},
                        "url": "http://localhost:8183/restconf/operational/gpe:gpe-state/gpe-feature-data/gpe-entry-table/gpe-entry/gpe-entry-2",
                        "preRequestScript": null,
-                       "pathVariables": {},
-                       "method": "GET",
-                       "data": [],
-                       "dataMode": "raw",
-                       "version": 2,
                        "tests": null,
                        "currentHelper": "normal",
                        "helperAttributes": {},
-                       "time": 1495182951887,
-                       "name": "Get gpe entry- negative mapping",
-                       "description": "",
+                       "queryParams": null,
+                       "headerData": null,
+                       "pathVariableData": null,
                        "collectionId": "71b7e698-4b8c-0ad6-38af-8304b6a5c4e0",
-                       "responses": [],
-                       "rawModeData": "{\n\t\"gpe\":{\n\t\t\"gpe-feature-data\":{\n\t\t\t\"enable\":true\n\t\t}\n\t}\n}"
+                       "rawModeData": "{\n  \"gpe\":{\n    \"gpe-feature-data\":{\n      \"enable\":true\n    }\n  }\n}"
                },
                {
+                       "folder": null,
                        "id": "2b9b1bec-1e40-b7c9-4756-c2eee3936d73",
+                       "name": "Add gpe entry - negative mapping",
+                       "dataMode": "raw",
+                       "data": [],
+                       "descriptionFormat": null,
+                       "description": "gpe entry add vni 10 vrf 1 leid 192.100.2.1/24 reid 192.100.3.1/24 negative action 2\n\n to verify \n \nshow gpe entry",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "method": "PUT",
+                       "pathVariables": {},
                        "url": "http://localhost:8183/restconf/config/gpe:gpe/gpe-feature-data/gpe-entry-table/gpe-entry/gpe-entry-2",
                        "preRequestScript": null,
+                       "tests": null,
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "queryParams": null,
+                       "headerData": null,
+                       "pathVariableData": null,
+                       "collectionId": "71b7e698-4b8c-0ad6-38af-8304b6a5c4e0",
+                       "rawModeData": "{\n  \"gpe-entry\":\n  {\n    \"id\":\"gpe-entry-2\",\n    \"dp-table\":\"2\",\n    \"vni\":11,\n    \"local-eid\":{\n      \"address-type\":\"ietf-lisp-address-types:ipv4-prefix-afi\",\n           \"virtual-network-id\":\"11\",\n           \"ipv4-prefix\":\"192.100.2.1/24\"\n    },\n    \"remote-eid\":{\n      \"address-type\":\"ietf-lisp-address-types:ipv4-prefix-afi\",\n           \"virtual-network-id\":\"11\",\n           \"ipv4-prefix\":\"192.100.3.1/24\"\n    },\n    \"action\":\"send-map-request\"\n  }  \n}"
+               },
+               {
+                       "id": "33fc474a-30f2-ec43-eb3d-7de056dbcda0",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "headerData": [
+                               {
+                                       "key": "Authorization",
+                                       "value": "Basic YWRtaW46YWRtaW4=",
+                                       "description": "",
+                                       "enabled": true
+                               },
+                               {
+                                       "key": "Content-Type",
+                                       "value": "application/json",
+                                       "description": "",
+                                       "enabled": true
+                               }
+                       ],
+                       "url": "http://localhost:8183/restconf/config/gpe:native-forward-paths-tables/native-forward-paths-table/4",
+                       "queryParams": [],
+                       "preRequestScript": null,
                        "pathVariables": {},
+                       "pathVariableData": [],
                        "method": "PUT",
                        "data": [],
                        "dataMode": "raw",
                        "tests": null,
                        "currentHelper": "normal",
                        "helperAttributes": {},
-                       "time": 1495182586472,
-                       "name": "Add gpe entry - negative mapping",
-                       "description": "gpe entry add vni 10 vrf 1 leid 192.100.2.1/24 reid 192.100.3.1/24 negative action 2\n\n to verify \n \nshow gpe entry",
+                       "time": 1497354971312,
+                       "name": "Add table with entries",
+                       "description": "",
                        "collectionId": "71b7e698-4b8c-0ad6-38af-8304b6a5c4e0",
-                       "responses": [],
-                       "rawModeData": "{\n\t\"gpe-entry\":\n\t{\n\t\t\"id\":\"gpe-entry-2\",\n\t\t\"dp-table\":\"2\",\n\t\t\"vni\":11,\n\t\t\"local-eid\":{\n\t\t\t\"address-type\":\"ietf-lisp-address-types:ipv4-prefix-afi\",\n       \t\t\"virtual-network-id\":\"11\",\n       \t\t\"ipv4-prefix\":\"192.100.2.1/24\"\n\t\t},\n\t\t\"remote-eid\":{\n\t\t\t\"address-type\":\"ietf-lisp-address-types:ipv4-prefix-afi\",\n       \t\t\"virtual-network-id\":\"11\",\n       \t\t\"ipv4-prefix\":\"192.100.3.1/24\"\n\t\t},\n\t\t\"action\":\"send-map-request\"\n\t}\t\n}"
+                       "isFromCollection": true,
+                       "collectionRequestId": "72c8c426-ac72-0c24-a4c1-9b5903f7fbd1",
+                       "folder": "a2b53670-baa2-92ae-6309-08d23db0a70d",
+                       "rawModeData": "{\n\t\"native-forward-paths-table\":{\n\t  \"table-id\":\"4\",\n\t  \"native-forward-path\":[\n\t  \t{\n\t  \t\t\"next-hop-address\":\"192.168.2.1\",\n\t  \t\t\"next-hop-interface\":\"local0\"\n\t  \t},\n\t  \t{\n\t  \t\t\"next-hop-address\":\"192.168.3.1\"\n\t  \t},\n\t  \t{\n\t  \t\t\"next-hop-address\":\"2001:0db8:0a0b:12f0:0000:0000:0000:0001\"\n\t  \t}\n\t  \t]\n\t}\n}"
                },
                {
+                       "folder": null,
                        "id": "3b529c6c-f4f0-7e69-c61f-4dc8f16d3c65",
+                       "name": "Delete gpe entry- positive mapping",
+                       "dataMode": "raw",
+                       "data": [],
+                       "descriptionFormat": null,
+                       "description": "",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "method": "DELETE",
+                       "pathVariables": {},
                        "url": "http://localhost:8183/restconf/config/gpe:gpe/gpe-feature-data/gpe-entry-table/gpe-entry/gpe-entry-1",
                        "preRequestScript": null,
-                       "pathVariables": {},
-                       "method": "DELETE",
-                       "data": [],
-                       "dataMode": "raw",
-                       "version": 2,
                        "tests": null,
                        "currentHelper": "normal",
                        "helperAttributes": {},
-                       "time": 1495183024381,
-                       "name": "Delete gpe entry- positive mapping",
-                       "description": "",
+                       "queryParams": null,
+                       "headerData": null,
+                       "pathVariableData": null,
                        "collectionId": "71b7e698-4b8c-0ad6-38af-8304b6a5c4e0",
-                       "responses": [],
-                       "rawModeData": "{\n\t\"gpe\":{\n\t\t\"gpe-feature-data\":{\n\t\t\t\"enable\":true\n\t\t}\n\t}\n}"
+                       "rawModeData": "{\n  \"gpe\":{\n    \"gpe-feature-data\":{\n      \"enable\":true\n    }\n  }\n}"
                },
                {
+                       "folder": null,
                        "id": "478e1140-d6e6-56ab-e9b7-11628a06b8ee",
+                       "name": "Get gpe status",
+                       "dataMode": "raw",
+                       "data": [],
+                       "descriptionFormat": null,
+                       "description": "",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "method": "GET",
+                       "pathVariables": {},
                        "url": "http://localhost:8183/restconf/operational/gpe:gpe-state",
                        "preRequestScript": null,
-                       "pathVariables": {},
-                       "method": "GET",
-                       "data": [],
-                       "dataMode": "raw",
-                       "version": 2,
                        "tests": null,
                        "currentHelper": "normal",
                        "helperAttributes": {},
-                       "time": 1495179312251,
-                       "name": "Get gpe status",
-                       "description": "",
+                       "queryParams": null,
+                       "headerData": null,
+                       "pathVariableData": null,
                        "collectionId": "71b7e698-4b8c-0ad6-38af-8304b6a5c4e0",
-                       "responses": [],
-                       "rawModeData": "{\n\t\"gpe\":{\n\t\t\"gpe-feature-data\":{\n\t\t\t\"enable\":true\n\t\t}\n\t}\n}"
+                       "rawModeData": "{\n  \"gpe\":{\n    \"gpe-feature-data\":{\n      \"enable\":true\n    }\n  }\n}"
                },
                {
+                       "folder": null,
                        "id": "5682b704-dc88-8186-c0ed-f7bb952f8150",
+                       "name": "Disable gpe",
+                       "dataMode": "raw",
+                       "data": [],
+                       "descriptionFormat": null,
+                       "description": "",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "method": "DELETE",
+                       "pathVariables": {},
                        "url": "http://localhost:8183/restconf/config/gpe:gpe",
                        "preRequestScript": null,
-                       "pathVariables": {},
-                       "method": "DELETE",
-                       "data": [],
-                       "dataMode": "raw",
-                       "version": 2,
                        "tests": null,
                        "currentHelper": "normal",
                        "helperAttributes": {},
-                       "time": 1495183089692,
-                       "name": "Disable gpe",
-                       "description": "",
+                       "queryParams": null,
+                       "headerData": null,
+                       "pathVariableData": null,
                        "collectionId": "71b7e698-4b8c-0ad6-38af-8304b6a5c4e0",
-                       "responses": [],
-                       "rawModeData": "{\n\t\"gpe\":{\n\t\t\"gpe-feature-data\":{\n\t\t\t\"enable\":true\n\t\t}\n\t}\n}"
+                       "rawModeData": "{\n  \"gpe\":{\n    \"gpe-feature-data\":{\n      \"enable\":true\n    }\n  }\n}"
                },
                {
+                       "folder": null,
                        "id": "6a934021-ad9b-d1ef-4059-8639caddc2bf",
+                       "name": "Enable gpe",
+                       "dataMode": "raw",
+                       "data": [],
+                       "descriptionFormat": "html",
+                       "description": "vppstl gpe enable\n\n to verify\n\nvppctl show lisp status",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "method": "PUT",
+                       "pathVariables": {},
                        "url": "http://localhost:8183/restconf/config/gpe:gpe",
                        "preRequestScript": null,
-                       "pathVariables": {},
-                       "method": "PUT",
-                       "data": [],
-                       "dataMode": "raw",
-                       "version": 2,
                        "tests": null,
                        "currentHelper": "normal",
                        "helperAttributes": {},
-                       "time": 1495177918949,
-                       "name": "Enable gpe",
-                       "description": "vppstl gpe enable\n\n to verify\n\nvppctl show lisp status",
+                       "queryParams": null,
+                       "headerData": null,
+                       "pathVariableData": null,
                        "collectionId": "71b7e698-4b8c-0ad6-38af-8304b6a5c4e0",
-                       "responses": [],
-                       "rawModeData": "{\n\t\"gpe\":{\n\t\t\"gpe-feature-data\":{\n\t\t\t\"enable\":true\n\t\t}\n\t}\n}"
+                       "rawModeData": "{\n  \"gpe\":{\n    \"gpe-feature-data\":{\n      \"enable\":true\n    }\n  }\n}"
                },
                {
+                       "folder": null,
                        "id": "7ff012c8-9065-008b-4552-cf0de8846426",
+                       "name": "Add gpe entry - positive mapping",
+                       "dataMode": "raw",
+                       "data": [],
+                       "descriptionFormat": "html",
+                       "description": "gpe entry add vni 10 vrf 1 leid 192.168.2.1/24 reid 192.168.3.1/24 loc-pair 192.168.7.7 192.168.7.8 w 3\n\n to verify\n \nshow gpe entry\n",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "method": "PUT",
+                       "pathVariables": {},
                        "url": "http://localhost:8183/restconf/config/gpe:gpe/gpe-feature-data/gpe-entry-table/gpe-entry/gpe-entry-1",
                        "preRequestScript": null,
-                       "pathVariables": {},
-                       "method": "PUT",
-                       "data": [],
-                       "dataMode": "raw",
                        "tests": null,
                        "currentHelper": "normal",
                        "helperAttributes": {},
-                       "time": 1495178391833,
-                       "name": "Add gpe entry - positive mapping",
-                       "description": "gpe entry add vni 10 vrf 1 leid 192.168.2.1/24 reid 192.168.3.1/24 loc-pair 192.168.7.7 192.168.7.8 w 3\n\n to verify\n \nshow gpe entry\n",
+                       "queryParams": null,
+                       "headerData": null,
+                       "pathVariableData": null,
                        "collectionId": "71b7e698-4b8c-0ad6-38af-8304b6a5c4e0",
-                       "responses": [],
-                       "rawModeData": "{\n\t\"gpe-entry\":\n\t{\n\t\t\"id\":\"gpe-entry-1\",\n\t\t\"dp-table\":\"1\",\n\t\t\"vni\":10,\n\t\t\"local-eid\":{\n\t\t\t\"address-type\":\"ietf-lisp-address-types:ipv4-prefix-afi\",\n       \t\t\"virtual-network-id\":\"10\",\n       \t\t\"ipv4-prefix\":\"192.168.2.1/24\"\n\t\t},\n\t\t\"remote-eid\":{\n\t\t\t\"address-type\":\"ietf-lisp-address-types:ipv4-prefix-afi\",\n       \t\t\"virtual-network-id\":\"10\",\n       \t\t\"ipv4-prefix\":\"192.168.3.1/24\"\n\t\t},\n\t\t\"locator-pairs\":[\n\t\t\t{\n\t\t\t\t\"id\":\"gpe-entry-locator-1\",\n\t\t\t\t\"locator-pair\":{\n\t\t\t\t\t\"local-locator\":\"192.168.7.7\",\n\t\t\t\t\t\"remote-locator\":\"192.168.7.8\",\n\t\t\t\t\t\"weight\":3\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"id\":\"gpe-entry-locator-2\",\n\t\t\t\t\"locator-pair\":{\n\t\t\t\t\t\"local-locator\":\"192.168.9.7\",\n\t\t\t\t\t\"remote-locator\":\"192.168.9.8\",\n\t\t\t\t\t\"weight\":2\n\t\t\t\t}\n\t\t\t}\t\n\t\t]\n\t}\t\n}"
+                       "rawModeData": "{\n  \"gpe-entry\":\n  {\n    \"id\":\"gpe-entry-1\",\n    \"dp-table\":\"1\",\n    \"vni\":10,\n    \"local-eid\":{\n      \"address-type\":\"ietf-lisp-address-types:ipv4-prefix-afi\",\n           \"virtual-network-id\":\"10\",\n           \"ipv4-prefix\":\"192.168.2.1/24\"\n    },\n    \"remote-eid\":{\n      \"address-type\":\"ietf-lisp-address-types:ipv4-prefix-afi\",\n           \"virtual-network-id\":\"10\",\n           \"ipv4-prefix\":\"192.168.3.1/24\"\n    },\n    \"locator-pairs\":[\n      {\n        \"id\":\"gpe-entry-locator-1\",\n        \"locator-pair\":{\n          \"local-locator\":\"192.168.7.7\",\n          \"remote-locator\":\"192.168.7.8\",\n          \"weight\":3\n        }\n      },\n      {\n        \"id\":\"gpe-entry-locator-2\",\n        \"locator-pair\":{\n          \"local-locator\":\"192.168.9.7\",\n          \"remote-locator\":\"192.168.9.8\",\n          \"weight\":2\n        }\n      }  \n    ]\n  }  \n}"
                },
                {
+                       "folder": null,
                        "id": "afd22ac4-448b-157a-de99-cdb353859546",
+                       "name": "Get gpe entry- positive mapping",
+                       "dataMode": "raw",
+                       "data": [],
+                       "descriptionFormat": null,
+                       "description": "",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "method": "GET",
+                       "pathVariables": {},
                        "url": "http://localhost:8183/restconf/operational/gpe:gpe-state/gpe-feature-data/gpe-entry-table/gpe-entry/gpe-entry-1",
                        "preRequestScript": null,
+                       "tests": null,
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "queryParams": null,
+                       "headerData": null,
+                       "pathVariableData": null,
+                       "collectionId": "71b7e698-4b8c-0ad6-38af-8304b6a5c4e0",
+                       "rawModeData": "{\n  \"gpe\":{\n    \"gpe-feature-data\":{\n      \"enable\":true\n    }\n  }\n}"
+               },
+               {
+                       "id": "f0ae8c21-de3e-2ec1-c816-4cc2e970a839",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "headerData": [
+                               {
+                                       "key": "Authorization",
+                                       "value": "Basic YWRtaW46YWRtaW4=",
+                                       "description": "",
+                                       "enabled": true
+                               },
+                               {
+                                       "key": "Content-Type",
+                                       "value": "application/json",
+                                       "description": "",
+                                       "enabled": true
+                               }
+                       ],
+                       "url": "http://localhost:8183/restconf/operational/naming-context:contexts",
+                       "queryParams": [],
+                       "preRequestScript": "",
                        "pathVariables": {},
+                       "pathVariableData": [],
                        "method": "GET",
                        "data": [],
                        "dataMode": "raw",
-                       "version": 2,
-                       "tests": null,
+                       "tests": "",
                        "currentHelper": "normal",
                        "helperAttributes": {},
-                       "time": 1495180295687,
-                       "name": "Get gpe entry- positive mapping",
+                       "time": 1496403090883,
+                       "name": "ctx",
                        "description": "",
                        "collectionId": "71b7e698-4b8c-0ad6-38af-8304b6a5c4e0",
-                       "responses": [],
-                       "rawModeData": "{\n\t\"gpe\":{\n\t\t\"gpe-feature-data\":{\n\t\t\t\"enable\":true\n\t\t}\n\t}\n}"
+                       "rawModeData": "{\r\n    \r\n        \"interface\": [\r\n            {\r\n                \"name\": \"testInterface\",\r\n                \"description\": \"for testing purposes\",\r\n                \"type\": \"iana-if-type:ethernetCsmacd\",\r\n                \"enabled\": \"true\",\r\n                \"link-up-down-trap-enable\": \"enabled\",\r\n                \"ietf-ip:ipv4\": {\r\n                    \"enabled\": \"true\",\r\n                    \"mtu\": \"1500\",\r\n                    \"address\": [\r\n                        {\r\n                            \"ip\": \"1.2.3.0\",\r\n                            \"netmask\": \"255.255.255.0\"\r\n                        }\r\n                    ]\r\n                }\r\n            }\r\n        ]\r\n    \r\n}"
                }
        ]
 }
\ No newline at end of file
index ae5db02..18bea7c 100644 (file)
@@ -32,6 +32,9 @@ import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.Gpe;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.NativeForwardPathsTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables.NativeForwardPathsTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables._native.forward.paths.table.NativeForwardPath;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.gpe.entry.table.grouping.GpeEntryTable;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.gpe.entry.table.grouping.gpe.entry.table.GpeEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.gpe.entry.table.grouping.gpe.entry.table.gpe.entry.LocalEid;
@@ -52,7 +55,7 @@ public class GpeWriterFactory implements WriterFactory {
             GPE_FEATURE_ID = GPE_ID.child(GpeFeatureData.class);
     private static final InstanceIdentifier<GpeEntry>
             GPE_ENTRY_ID = GPE_FEATURE_ID.child(GpeEntryTable.class).child(GpeEntry.class);
-    public static final InstanceIdentifier<Interface>
+    private static final InstanceIdentifier<Interface>
             IFC_ID = InstanceIdentifier.create(Interfaces.class).child(Interface.class);
 
     @Inject
@@ -69,6 +72,10 @@ public class GpeWriterFactory implements WriterFactory {
     @Named(GpeModule.GPE_TO_LOCATOR_PAIR_CTX)
     private GpeLocatorPairMappingContext gpeLocatorPairMappingContext;
 
+    @Inject
+    @Named("interface-context")
+    private NamingContext interfaceContext;
+
 
     @Override
     public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
@@ -92,6 +99,13 @@ public class GpeWriterFactory implements WriterFactory {
                 IFC_ID.augmentation(SubinterfaceAugmentation.class).child(SubInterfaces.class)
                         .child(SubInterface.class));
 
-
+        final InstanceIdentifier<NativeForwardPathsTable> nativeEntryTableId =
+                InstanceIdentifier.create(NativeForwardPathsTables.class).child(NativeForwardPathsTable.class);
+        // gpe_add_del_iface is used to create fib table, so must be written before interfaces, to ensure
+        // byproduct iface is created before there's an attempt to set its flags
+        registry.addBefore(new GenericListWriter<>(nativeEntryTableId, new NativeForwardPathsTableCustomizer(api)),
+                IFC_ID);
+        registry.add(new GenericListWriter<>(nativeEntryTableId.child(NativeForwardPath.class),
+                new NativeForwardPathCustomizer(api, interfaceContext)));
     }
 }
diff --git a/lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/write/NativeForwardPathCustomizer.java b/lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/write/NativeForwardPathCustomizer.java
new file mode 100644 (file)
index 0000000..0dcb434
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.lisp.gpe.translate.write;
+
+import static io.fd.hc2vpp.lisp.gpe.translate.write.NativeForwardPathsTableCustomizer.tableId;
+
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.GpeAddDelNativeFwdRpath;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.Optional;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables._native.forward.paths.table.NativeForwardPath;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables._native.forward.paths.table.NativeForwardPathKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class NativeForwardPathCustomizer extends FutureJVppCustomizer
+        implements ListWriterCustomizer<NativeForwardPath, NativeForwardPathKey>, AddressTranslator, JvppReplyConsumer {
+
+    private final NamingContext interfaceContext;
+
+    public NativeForwardPathCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+                                       @Nonnull final NamingContext interfaceContext) {
+        super(futureJVppCore);
+        this.interfaceContext = interfaceContext;
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<NativeForwardPath> id,
+                                       @Nonnull final NativeForwardPath dataAfter,
+                                       @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        createNativePath(id, dataAfter, writeContext);
+    }
+
+
+    @Override
+    public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<NativeForwardPath> id,
+                                        @Nonnull final NativeForwardPath dataBefore,
+                                        @Nonnull final NativeForwardPath dataAfter,
+                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        deleteNativePath(id, dataBefore, writeContext);
+        createNativePath(id, dataAfter, writeContext);
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<NativeForwardPath> id,
+                                        @Nonnull final NativeForwardPath dataBefore,
+                                        @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        deleteNativePath(id, dataBefore, writeContext);
+    }
+
+    private GpeAddDelNativeFwdRpath getRequest(final boolean isAdd,
+                                               final int tableId,
+                                               final NativeForwardPath data,
+                                               final MappingContext mappingContext) {
+        GpeAddDelNativeFwdRpath request = new GpeAddDelNativeFwdRpath();
+
+        final IpAddress nextHopAddress = data.getNextHopAddress();
+
+        request.tableId = tableId;
+        request.isAdd = booleanToByte(isAdd);
+        request.isIp4 = booleanToByte(!isIpv6(nextHopAddress));
+        request.nhAddr = ipAddressToArray(nextHopAddress);
+        request.nhSwIfIndex = Optional.ofNullable(data.getNextHopInterface())
+                .map(String::trim)
+                .map(ifaceName -> interfaceContext.getIndex(ifaceName, mappingContext))
+                .orElse(~0);
+
+        return request;
+    }
+
+    private void createNativePath(final InstanceIdentifier<NativeForwardPath> id,
+                                  final NativeForwardPath data,
+                                  final WriteContext ctx) throws WriteFailedException {
+        getReplyForCreate(getFutureJVpp()
+                .gpeAddDelNativeFwdRpath(getRequest(true, tableId(id), data, ctx.getMappingContext()))
+                .toCompletableFuture(), id, data);
+    }
+
+    private void deleteNativePath(final InstanceIdentifier<NativeForwardPath> id,
+                                  final NativeForwardPath data,
+                                  final WriteContext ctx) throws WriteFailedException {
+        getReplyForDelete(getFutureJVpp()
+                .gpeAddDelNativeFwdRpath(getRequest(false, tableId(id), data, ctx.getMappingContext()))
+                .toCompletableFuture(), id);
+    }
+}
diff --git a/lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/write/NativeForwardPathsTableCustomizer.java b/lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/write/NativeForwardPathsTableCustomizer.java
new file mode 100644 (file)
index 0000000..a9030a7
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.lisp.gpe.translate.write;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.GpeAddDelIface;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables.NativeForwardPathsTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables.NativeForwardPathsTableKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Uses api to create gpe interfaces, which creates fib table as by-product.
+ * There is currently no other lisp-specific way to define fib table, as native paths expects existing table id
+ */
+public class NativeForwardPathsTableCustomizer extends FutureJVppCustomizer
+        implements ListWriterCustomizer<NativeForwardPathsTable, NativeForwardPathsTableKey>, ByteDataTranslator,
+        JvppReplyConsumer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NativeForwardPathsTableCustomizer.class);
+
+    public NativeForwardPathsTableCustomizer(@Nonnull final FutureJVppCore futureJVppCore) {
+        super(futureJVppCore);
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<NativeForwardPathsTable> id,
+                                       @Nonnull final NativeForwardPathsTable dataAfter,
+                                       @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        createFibTable(id, dataAfter);
+    }
+
+
+    @Override
+    public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<NativeForwardPathsTable> id,
+                                        @Nonnull final NativeForwardPathsTable dataBefore,
+                                        @Nonnull final NativeForwardPathsTable dataAfter,
+                                        @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        // not sure if update makes sense, but just in case
+        deleteFibTable(id);
+        createFibTable(id, dataAfter);
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<NativeForwardPathsTable> id,
+                                        @Nonnull final NativeForwardPathsTable dataBefore,
+                                        @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        deleteFibTable(id);
+    }
+
+    private void createFibTable(final InstanceIdentifier<NativeForwardPathsTable> id,
+                                final NativeForwardPathsTable data) throws WriteFailedException {
+        getReplyForCreate(getFutureJVpp().gpeAddDelIface(getRequest(true, id)).toCompletableFuture(), id, data);
+    }
+
+    private void deleteFibTable(final InstanceIdentifier<NativeForwardPathsTable> id) throws WriteFailedException {
+        getReplyForDelete(getFutureJVpp().gpeAddDelIface(getRequest(false, id)).toCompletableFuture(), id);
+    }
+
+    /**
+     * Maps dpTable and vni to tableId,this also allows to dump lisp specific tables by dumping vni's
+     */
+    private GpeAddDelIface getRequest(final boolean add, final InstanceIdentifier<NativeForwardPathsTable> id) {
+        GpeAddDelIface request = new GpeAddDelIface();
+        request.isL2 = 0;
+        // expects reversed order
+        request.dpTable = tableId(id);
+        request.vni = request.dpTable; // vni must be unique for every table
+        request.isAdd = booleanToByte(add);
+        return request;
+    }
+
+    static int tableId(final InstanceIdentifier<?> id) {
+        return id.firstKeyOf(NativeForwardPathsTable.class).getTableId().intValue();
+    }
+}
index 2d5dd8b..982239c 100644 (file)
@@ -25,8 +25,10 @@ import static org.mockito.MockitoAnnotations.initMocks;
 
 import com.google.inject.Guice;
 import com.google.inject.Inject;
+import com.google.inject.name.Named;
 import com.google.inject.testing.fieldbinder.Bind;
 import com.google.inject.testing.fieldbinder.BoundFieldModule;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.lisp.gpe.GpeModule;
 import io.fd.honeycomb.translate.impl.read.registry.CompositeReaderRegistryBuilder;
 import io.fd.honeycomb.translate.impl.write.registry.FlatWriterRegistryBuilder;
@@ -52,9 +54,14 @@ public class GpeModuleTest {
     @Inject
     private Set<WriterFactory> writerFactories = new HashSet<>();
 
+    @Named("interface-context")
+    @Bind
+    private NamingContext interfaceContext;
+
     @Before
     public void setUp() throws Exception {
         initMocks(this);
+        interfaceContext = new NamingContext("interfaceContext", "interfaceContext");
         Guice.createInjector(new GpeModule(), BoundFieldModule.of(this)).injectMembers(this);
     }
 
diff --git a/lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/gpe/translate/write/NativeForwardPathCustomizerTest.java b/lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/gpe/translate/write/NativeForwardPathCustomizerTest.java
new file mode 100644 (file)
index 0000000..2ce9789
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.lisp.gpe.translate.write;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.GpeAddDelNativeFwdRpath;
+import io.fd.vpp.jvpp.core.dto.GpeAddDelNativeFwdRpathReply;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.NativeForwardPathsTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables.NativeForwardPathsTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables.NativeForwardPathsTableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables._native.forward.paths.table.NativeForwardPath;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables._native.forward.paths.table.NativeForwardPathBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables._native.forward.paths.table.NativeForwardPathKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class NativeForwardPathCustomizerTest extends WriterCustomizerTest {
+
+    private static final long TABLE_ID = 1L;
+    private static final String IFC_CTX = "ifc-ctx";
+    private static final String ETH_0 = "eth-0";
+    private static final String ETH_1 = "eth-1";
+    private static final int ETH_0_IDX = 2;
+    private static final int ETH_1_IDX = 7;
+    private static final byte[] V4_WITH_IF_ADDR = {-64, -88, 2, 1};
+    private static final byte[] V4_WITHOUT_IF_ADDR = {-64, -88, 2, 3};
+    private static final byte[] V6_WITH_IF_ADDR = {32, 1, 13, -72, 10, 11, 18, -16, 0, 0, 0, 0, 0, 0, 0, 1};
+
+    private NamingContext ifcCtx;
+    private NativeForwardPathCustomizer customizer;
+    private InstanceIdentifier<NativeForwardPath> validId;
+
+    @Captor
+    private ArgumentCaptor<GpeAddDelNativeFwdRpath> requestCaptor;
+
+    @Override
+    protected void setUpTest() throws Exception {
+        ifcCtx = new NamingContext("iface", IFC_CTX);
+        defineMapping(mappingContext, ETH_0, ETH_0_IDX, IFC_CTX);
+        defineMapping(mappingContext, ETH_1, ETH_1_IDX, IFC_CTX);
+        customizer = new NativeForwardPathCustomizer(api, ifcCtx);
+        validId = InstanceIdentifier.create(NativeForwardPathsTables.class)
+                .child(NativeForwardPathsTable.class, new NativeForwardPathsTableKey(TABLE_ID))
+                .child(NativeForwardPath.class,
+                        new NativeForwardPathKey(new IpAddress(new Ipv4Address("192.168.2.1"))));
+        when(api.gpeAddDelNativeFwdRpath(any())).thenReturn(future(new GpeAddDelNativeFwdRpathReply()));
+    }
+
+    @Test
+    public void testWriteV4WithIfc() throws WriteFailedException {
+        customizer.writeCurrentAttributes(validId, v4WithIfc(), writeContext);
+        verify(api, times(1)).gpeAddDelNativeFwdRpath(requestCaptor.capture());
+        final GpeAddDelNativeFwdRpath request = requestCaptor.getValue();
+        assertEquals(desiredRequest(1, 1, V4_WITH_IF_ADDR, ETH_0_IDX, (int) TABLE_ID), request);
+    }
+
+    @Test
+    public void testWriteV4WithoutIfc() throws WriteFailedException {
+        customizer.writeCurrentAttributes(validId, v4WithoutIfc(), writeContext);
+        verify(api, times(1)).gpeAddDelNativeFwdRpath(requestCaptor.capture());
+        final GpeAddDelNativeFwdRpath request = requestCaptor.getValue();
+        assertEquals(desiredRequest(1, 1, V4_WITHOUT_IF_ADDR, ~0, (int) TABLE_ID), request);
+    }
+
+    @Test
+    public void testWriteV6() throws WriteFailedException {
+        customizer.writeCurrentAttributes(validId, v6WithIfc(), writeContext);
+        verify(api, times(1)).gpeAddDelNativeFwdRpath(requestCaptor.capture());
+        final GpeAddDelNativeFwdRpath request = requestCaptor.getValue();
+        assertEquals(desiredRequest(1, 0, V6_WITH_IF_ADDR, ETH_1_IDX, (int) TABLE_ID), request);
+    }
+
+    private static GpeAddDelNativeFwdRpath desiredRequest(final int add, final int isV4,
+                                                          final byte[] addr, final int swIfIndex,
+                                                          final int tableId) {
+        GpeAddDelNativeFwdRpath request = new GpeAddDelNativeFwdRpath();
+        request.isAdd = (byte) add;
+        request.isIp4 = (byte) isV4;
+        request.nhAddr = addr;
+        request.nhSwIfIndex = swIfIndex;
+        request.tableId = tableId;
+
+        return request;
+    }
+
+    private static NativeForwardPath v6WithIfc() {
+        return new NativeForwardPathBuilder()
+                .setNextHopAddress(new IpAddress(new Ipv6Address("2001:0db8:0a0b:12f0:0000:0000:0000:0001")))
+                .setNextHopInterface(ETH_1)
+                .build();
+    }
+
+    private static NativeForwardPath v4WithoutIfc() {
+        return new NativeForwardPathBuilder()
+                .setNextHopAddress(new IpAddress(new Ipv4Address("192.168.2.3")))
+                .build();
+    }
+
+    private static NativeForwardPath v4WithIfc() {
+        return new NativeForwardPathBuilder()
+                .setNextHopAddress(new IpAddress(new Ipv4Address("192.168.2.1")))
+                .setNextHopInterface(ETH_0)
+                .build();
+    }
+}
\ No newline at end of file
diff --git a/lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/gpe/translate/write/NativeForwardPathsTableCustomizerTest.java b/lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/gpe/translate/write/NativeForwardPathsTableCustomizerTest.java
new file mode 100644 (file)
index 0000000..923aaad
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.lisp.gpe.translate.write;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.GpeAddDelIface;
+import io.fd.vpp.jvpp.core.dto.GpeAddDelIfaceReply;
+import io.fd.vpp.jvpp.core.dto.GpeAddDelNativeFwdRpathReply;
+import java.util.List;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.NativeForwardPathsTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables.NativeForwardPathsTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables.NativeForwardPathsTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables.NativeForwardPathsTableKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class NativeForwardPathsTableCustomizerTest extends WriterCustomizerTest {
+
+    private static final long TABLE_ID = 1L;
+    private NativeForwardPathsTableCustomizer customizer;
+    private InstanceIdentifier<NativeForwardPathsTable> validId;
+
+    @Captor
+    private ArgumentCaptor<GpeAddDelIface> requestCaptor;
+
+    @Override
+    protected void setUpTest() throws Exception {
+        customizer = new NativeForwardPathsTableCustomizer(api);
+        validId = InstanceIdentifier.create(NativeForwardPathsTables.class)
+                .child(NativeForwardPathsTable.class, new NativeForwardPathsTableKey(TABLE_ID));
+        when(api.gpeAddDelIface(any())).thenReturn(future(new GpeAddDelIfaceReply()));
+    }
+
+    @Test
+    public void testWriteValid() throws WriteFailedException {
+        when(api.gpeAddDelNativeFwdRpath(any())).thenReturn(future(new GpeAddDelNativeFwdRpathReply()));
+        customizer.writeCurrentAttributes(validId, validTable(), writeContext);
+        verify(api, times(1)).gpeAddDelIface(requestCaptor.capture());
+
+        final List<GpeAddDelIface> requests = requestCaptor.getAllValues();
+
+        assertEquals(desiredRequest(1, 1), requests.get(0));
+    }
+
+    @Test
+    public void testDeleteValid() throws WriteFailedException {
+        when(api.gpeAddDelNativeFwdRpath(any())).thenReturn(future(new GpeAddDelNativeFwdRpathReply()));
+        customizer.deleteCurrentAttributes(validId, validTable(), writeContext);
+        verify(api, times(1)).gpeAddDelIface(requestCaptor.capture());
+
+        final List<GpeAddDelIface> requests = requestCaptor.getAllValues();
+
+        assertEquals(desiredRequest(0, 1), requests.get(0));
+    }
+
+    @Test
+    public void testUpdateValid() throws WriteFailedException {
+        when(api.gpeAddDelNativeFwdRpath(any())).thenReturn(future(new GpeAddDelNativeFwdRpathReply()));
+        customizer.updateCurrentAttributes(validId, validTableBefore(), validTable(), writeContext);
+        verify(api, times(2)).gpeAddDelIface(requestCaptor.capture());
+
+        final List<GpeAddDelIface> requests = requestCaptor.getAllValues();
+
+        // removes one from old data
+        assertEquals(desiredRequest(0, 1), requests.get(0));
+
+        // defines 3 new
+        assertEquals(desiredRequest(1, 1), requests.get(1));
+    }
+
+
+    private GpeAddDelIface desiredRequest(final int isAdd, final int tableId) {
+        GpeAddDelIface request = new GpeAddDelIface();
+
+        request.isL2 = 0;
+        request.dpTable = tableId;
+        request.vni = request.dpTable;
+        request.isAdd = (byte) isAdd;
+        return request;
+    }
+
+    private NativeForwardPathsTable validTableBefore() {
+        return new NativeForwardPathsTableBuilder()
+                .setTableId(TABLE_ID)
+                .build();
+    }
+
+    private NativeForwardPathsTable validTable() {
+        return new NativeForwardPathsTableBuilder()
+                .setTableId(TABLE_ID)
+                .build();
+    }
+}
\ No newline at end of file