HC2VPP-87: Expose IPSEC management 04/16104/21
authorTibor Král <[email protected]>
Wed, 14 Nov 2018 17:20:02 +0000 (18:20 +0100)
committerTibor Král <[email protected]>
Wed, 16 Jan 2019 09:07:28 +0000 (10:07 +0100)
Change-Id: Ib13a2cdba5a0902581c455de67cc0ee64d20598d
Signed-off-by: Tibor Král <[email protected]>
41 files changed:
ipsec/Ipsec_postman_collection.json [new file with mode: 0644]
ipsec/ipsec-api/pom.xml [new file with mode: 0644]
ipsec/ipsec-api/src/main/yang/[email protected] [new file with mode: 0644]
ipsec/ipsec-api/src/main/yang/[email protected] [new file with mode: 0644]
ipsec/ipsec-impl/pom.xml [new file with mode: 0644]
ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/IpsecModule.java [new file with mode: 0644]
ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecReaderFactory.java [new file with mode: 0644]
ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizer.java [new file with mode: 0644]
ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizer.java [new file with mode: 0644]
ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizer.java [new file with mode: 0644]
ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizer.java [new file with mode: 0644]
ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizer.java [new file with mode: 0644]
ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizer.java [new file with mode: 0644]
ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizer.java [new file with mode: 0644]
ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecWriterFactory.java [new file with mode: 0644]
ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/IpsecModuleTest.java [new file with mode: 0644]
ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/helpers/SchemaContextTestHelper.java [new file with mode: 0644]
ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizerTest.java [new file with mode: 0644]
ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizerTest.java [new file with mode: 0644]
ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizerTest.java [new file with mode: 0644]
ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizerTest.java [new file with mode: 0644]
ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizerTest.java [new file with mode: 0644]
ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizerTest.java [new file with mode: 0644]
ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizerTest.java [new file with mode: 0644]
ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_after.json [new file with mode: 0644]
ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_before.json [new file with mode: 0644]
ipsec/ipsec-impl/src/test/resources/ikev2/addIkev2Profile.json [new file with mode: 0644]
ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_ipv4.json [new file with mode: 0644]
ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_rfc822.json [new file with mode: 0644]
ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_fqdn.json [new file with mode: 0644]
ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_ipv6.json [new file with mode: 0644]
ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry.json [new file with mode: 0644]
ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_after.json [new file with mode: 0644]
ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_before.json [new file with mode: 0644]
ipsec/ipsec-impl/src/test/resources/sadEntries/delSadEntry.json [new file with mode: 0644]
ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd.json [new file with mode: 0644]
ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_after.json [new file with mode: 0644]
ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_before.json [new file with mode: 0644]
ipsec/pom.xml [new file with mode: 0644]
pom.xml
vpp-integration/minimal-distribution/pom.xml

diff --git a/ipsec/Ipsec_postman_collection.json b/ipsec/Ipsec_postman_collection.json
new file mode 100644 (file)
index 0000000..cbe0759
--- /dev/null
@@ -0,0 +1,486 @@
+{
+       "info": {
+               "_postman_id": "d17abd36-ad9a-4b5f-bb10-fe09c412dbe6",
+               "name": "IPsec",
+               "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
+       },
+       "item": [
+               {
+                       "name": "Add Sad Entry - ESP",
+                       "request": {
+                               "method": "PUT",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n\t\"sad-entries\": [\n\t\t{\n\t\t\t\"sa-id\":10,\n\t\t\t\"spi\": 1001,\n\t\t\t\"anti-replay-window\": 88,\n\t\t\t\"direction\": \"outbound\",\n\t\t\t\"security-protocol\": \"esp\",\n\t\t\t\"esp\": {\n\t\t\t\t\"authentication\" : {\n\t\t\t\t\t\"hmac-sha1-96\" : {\n\t\t\t\t\t\t\"key-str\" : \"0123456789012345\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"encryption\" : {\n\t\t\t\t\t\"aes-128-cbc\": {\n\t\t\t\t\t\t\"key-str\" : \"0123456789012345\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"source-address\": {\n\t\t\t\t\"ipv4-address\": \"192.168.100.3\"\n\t\t\t},\n\t\t\t\"destination-address\": {\n\t\t\t\t\"ipv4-address\": \"192.168.100.2\"\n\t\t\t}\n\t\t}\n\t]\n}\n"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ipsec/sad/sad-entries/1001/outbound",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "config",
+                                               "hc2vpp-ietf-ipsec:ipsec",
+                                               "sad",
+                                               "sad-entries",
+                                               "1001",
+                                               "outbound"
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "Add Sad Entry - ESP inbound",
+                       "request": {
+                               "method": "PUT",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n\t\"sad-entries\": [\n\t\t{\n\t\t\t\"sa-id\":20,\n\t\t\t\"spi\": 1002,\n\t\t\t\"anti-replay-window\": 88,\n\t\t\t\"direction\": \"inbound\",\n\t\t\t\"security-protocol\": \"esp\",\n\t\t\t\"esp\": {\n\t\t\t\t\"authentication\" : {\n\t\t\t\t\t\"hmac-sha1-96\" : {\n\t\t\t\t\t\t\"key-str\" : \"0123456789012345\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"encryption\" : {\n\t\t\t\t\t\"aes-128-cbc\": {\n\t\t\t\t\t\t\"key-str\" : \"0123456789012345\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"source-address\": {\n\t\t\t\t\"ipv4-address\": \"192.168.100.3\"\n\t\t\t},\n\t\t\t\"destination-address\": {\n\t\t\t\t\"ipv4-address\": \"192.168.100.2\"\n\t\t\t}\n\t\t}\n\t]\n}\n"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ipsec/sad/sad-entries/1002/inbound",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "config",
+                                               "hc2vpp-ietf-ipsec:ipsec",
+                                               "sad",
+                                               "sad-entries",
+                                               "1002",
+                                               "inbound"
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "Add Sad Entry- AH",
+                       "request": {
+                               "method": "PUT",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n\t\"sad-entries\": [\n\t\t{\n\t\t\t\"sa-id\":50,\n\t\t\t\"spi\": 1005,\n\t\t\t\"anti-replay-window\": 55,\n\t\t\t\"direction\": \"inbound\",\n\t\t\t\"security-protocol\": \"ah\",\n\t\t\t\"ah\": {\n\t\t\t\t\"hmac-sha1-96\" : {\n\t\t\t\t\t\"key-str\" : \"0123456789055555\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"source-address\": {\n\t\t\t\t\"ipv4-address\": \"192.168.100.5\"\n\t\t\t},\n\t\t\t\"destination-address\": {\n\t\t\t\t\"ipv4-address\": \"192.168.100.55\"\n\t\t\t}\n\t\t}\n\t]\n}\n"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ipsec/sad/sad-entries/1005/inbound",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "config",
+                                               "hc2vpp-ietf-ipsec:ipsec",
+                                               "sad",
+                                               "sad-entries",
+                                               "1005",
+                                               "inbound"
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "Add SPD",
+                       "request": {
+                               "method": "PUT",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n\t\"spd\": [\n\t\t{\n\t\t\t\"spd-id\":10,\n\t\t\t\"spd-entries\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\":\"testEntry1\",\n\t\t\t\t\t\"priority\":10,\n\t\t\t\t\t\"direction\":\"inbound\",\n\t\t\t\t\t\"operation\":\"bypass\",\n\t\t\t\t\t\"laddr-start\":\"192.168.4.4\",\n\t\t\t\t\t\"laddr-stop\":\"192.168.4.4\",\n\t\t\t\t\t\"raddr-start\":\"192.168.3.3\",\n\t\t\t\t\t\"raddr-stop\":\"192.168.3.3\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"name\":\"testEntry2\",\n\t\t\t\t\t\"priority\":100,\n\t\t\t\t\t\"direction\":\"outbound\",\n\t\t\t\t\t\"operation\":\"discard\",\n\t\t\t\t\t\"laddr-start\":\"192.168.5.5\",\n\t\t\t\t\t\"laddr-stop\":\"192.168.5.5\",\n\t\t\t\t\t\"raddr-start\":\"192.168.6.6\",\n\t\t\t\t\t\"raddr-stop\":\"192.168.6.6\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}\n"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ipsec/spd/10",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "config",
+                                               "hc2vpp-ietf-ipsec:ipsec",
+                                               "spd",
+                                               "10"
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "Add Ikev2 profile SHARED-KEY",
+                       "request": {
+                               "method": "PUT",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n\t\"policy\": [\n\t\t{\n\t\t\t\"name\":\"testPolicy\",\n\t\t\t\"lifetime\": 0,\n\t\t\t\"connection-type\":\"both\",\n\t\t\t\"description\": \"policy profile named testPolicy\",\n\t\t\t\"authentication\": {\n\t\t\t\t\"preshared-key\":\"true\"\n\t\t\t},\n\t\t\t\"pre-shared-key\":\"Vpp0123456789123\",\n\t\t\t\"traffic-selectors\": [\n\t\t\t\t{\n\t\t\t\t\t\"ts-name\":\"ts1\",\n\t\t\t\t\t\"protocol\":0,\n\t\t\t\t\t\"local-address-low\":\"192.168.124.0\",\n\t\t\t\t\t\"local-address-high\":\"192.168.124.255\",\n\t\t\t\t\t\"local-port-low\":0,\n\t\t\t\t\t\"local-port-high\":65535\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}\n"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ikev2/policy/testPolicy",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "config",
+                                               "hc2vpp-ietf-ipsec:ikev2",
+                                               "policy",
+                                               "testPolicy"
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "Add Ikev2 profile RSA",
+                       "request": {
+                               "method": "PUT",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n\t\"policy\": [\n\t\t{\n\t\t\t\"name\":\"testPolicyRsa\",\n\t\t\t\"lifetime\": 0,\n\t\t\t\"connection-type\":\"both\",\n\t\t\t\"description\": \"policy profile named testPolicyRsa\",\n\t\t\t\"authentication\": {\n\t\t\t\t\"rsa-signature\":\"true\"\n\t\t\t},\n\t\t\t\"certificate\":\"/home/localadmin/certs/server-cert.pem\"\n\t\t}\n\t]\n}\n"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ikev2/policy/testPolicyRsa",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "config",
+                                               "hc2vpp-ietf-ipsec:ikev2",
+                                               "policy",
+                                               "testPolicyRsa"
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "Add Ikev2 profile local ID FQDN",
+                       "request": {
+                               "method": "PUT",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n\t\"identity\": {\n\t\t\"local\": {\n\t\t\t\"fqdn-string\":\"vpp.home\"\n\t\t}\n\t}\n}\n"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ikev2/policy/testPolicy/identity",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "config",
+                                               "hc2vpp-ietf-ipsec:ikev2",
+                                               "policy",
+                                               "testPolicy",
+                                               "identity"
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "Add Ikev2 profile remote ID IPv4",
+                       "request": {
+                               "method": "PUT",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n\t\"identity\": {\n\t\t\"remote\": {\n\t\t\t\"ipv4-address\":\"192.168.123.20\"\n\t\t}\n\t}\n}\n"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ikev2/policy/testPolicy/identity",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "config",
+                                               "hc2vpp-ietf-ipsec:ikev2",
+                                               "policy",
+                                               "testPolicy",
+                                               "identity"
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "Show SAD 1001 outbound - config",
+                       "request": {
+                               "method": "GET",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-family\": \"vpp-fib-table-management:ipv4\",\n\t\t\t\"rx-vrf-id\": 0,\n\t\t\t\"server-address\": \"1.2.3.4\",\n\t\t\t\"gateway-address\": \"5.6.7.8\"}\n\t]\n}\n"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ipsec/sad/sad-entries/1001/outbound",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "config",
+                                               "hc2vpp-ietf-ipsec:ipsec",
+                                               "sad",
+                                               "sad-entries",
+                                               "1001",
+                                               "outbound"
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "Show IPSEC - oper",
+                       "request": {
+                               "method": "GET",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-family\": \"vpp-fib-table-management:ipv4\",\n\t\t\t\"rx-vrf-id\": 0,\n\t\t\t\"server-address\": \"1.2.3.4\",\n\t\t\t\"gateway-address\": \"5.6.7.8\"}\n\t]\n}\n"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/operational/hc2vpp-ietf-ipsec:ipsec-state/",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "operational",
+                                               "hc2vpp-ietf-ipsec:ipsec-state",
+                                               ""
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "Show IPSEC - oper SPD",
+                       "request": {
+                               "method": "GET",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-family\": \"vpp-fib-table-management:ipv4\",\n\t\t\t\"rx-vrf-id\": 0,\n\t\t\t\"server-address\": \"1.2.3.4\",\n\t\t\t\"gateway-address\": \"5.6.7.8\"}\n\t]\n}\n"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/operational/hc2vpp-ietf-ipsec:ipsec-state/spd/10/spd-interfaces/",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "operational",
+                                               "hc2vpp-ietf-ipsec:ipsec-state",
+                                               "spd",
+                                               "10",
+                                               "spd-interfaces",
+                                               ""
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "Show IPSEC Config",
+                       "request": {
+                               "method": "GET",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-family\": \"vpp-fib-table-management:ipv4\",\n\t\t\t\"rx-vrf-id\": 0,\n\t\t\t\"server-address\": \"1.2.3.4\",\n\t\t\t\"gateway-address\": \"5.6.7.8\"}\n\t]\n}\n"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ipsec/",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "config",
+                                               "hc2vpp-ietf-ipsec:ipsec",
+                                               ""
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "Show Ikev2",
+                       "request": {
+                               "method": "GET",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-family\": \"vpp-fib-table-management:ipv4\",\n\t\t\t\"rx-vrf-id\": 0,\n\t\t\t\"server-address\": \"1.2.3.4\",\n\t\t\t\"gateway-address\": \"5.6.7.8\"}\n\t]\n}\n"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ikev2/",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "config",
+                                               "hc2vpp-ietf-ipsec:ikev2",
+                                               ""
+                                       ]
+                               }
+                       },
+                       "response": []
+               }
+       ]
+}
\ No newline at end of file
diff --git a/ipsec/ipsec-api/pom.xml b/ipsec/ipsec-api/pom.xml
new file mode 100644 (file)
index 0000000..169f55c
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2019 PANTHEON.tech.
+
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <parent>
+    <groupId>io.fd.hc2vpp.common</groupId>
+    <artifactId>api-parent</artifactId>
+    <version>1.19.01-SNAPSHOT</version>
+    <relativePath>../../common/api-parent</relativePath>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>io.fd.hc2vpp.ipsec</groupId>
+  <artifactId>ipsec-api</artifactId>
+  <name>${project.artifactId}</name>
+  <version>1.19.01-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <naming.context.version>1.19.01-SNAPSHOT</naming.context.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>ietf-yang-types-20130715</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>ietf-inet-types-2013-07-15</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.fd.hc2vpp.v3po</groupId>
+      <artifactId>v3po-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
new file mode 100644 (file)
index 0000000..6df2c65
--- /dev/null
@@ -0,0 +1,3679 @@
+module hc2vpp-ietf-ipsec {
+  namespace "urn:ietf:params:xml:ns:yang:ietf-ipsec";
+  prefix "eipsec";
+
+  import ietf-inet-types {
+    prefix inet;
+  }
+
+  import ietf-yang-types {
+    prefix yang;
+  }
+
+  organization "Ericsson AB.
+                Huawei Technologies India Pvt Ltd.";
+
+  contact "Web:   <http://www.ericsson.com>";
+
+  description
+    "This YANG module defines the configuration and operational
+     state data for Internet Protocol Security (IPSec) on
+     IETF draft.
+     Copyright (c) 2016 Ericsson AB.
+     All rights reserved.";
+
+  revision 2018-12-14 {
+    description
+      "HC2VPP modifications for use case with VPP.
+      See https://jira.fd.io/browse/HC2VPP-399";
+  }
+
+  revision 2016-03-09 {
+    description
+      "Third revision.
+       Fix YANG compiling error because it used internal
+       data model econtext and should be removed in the
+       draft.
+       Fix warnings.
+       Run validation on
+       http://www.netconfcentral.org/yangdumpresults";
+    reference
+      "Update since second revision.";
+  }
+  revision 2015-09-13 {
+    description
+      "Second revision.";
+    reference
+      "updates since initial revision.
+      combining:
+       draft-tran-ipecme-yang-ipsec-00.
+       draft-wang-ipsecme-ike-yang-00.
+       draft-wang-ipsecme-ipsec-yang-00.";
+  }
+  revision 2015-05-14 {
+    description
+      "Initial revision.";
+    reference
+      "May 14, 2015  draft-tran-ipecme-yang-ipsec-00.
+       May 22, 2015  draft-wang-ipsecme-ike-yang-00.
+       June 15, 2015 draft-wang-ipsecme-ipsec-yang-00.";
+  }
+  /*--------------------*/
+  /* Feature            */
+  /*--------------------*/
+
+  feature ikev1 {
+    description
+      "Feature IKEv1";
+  }
+
+  feature ike-proposal-state {
+    description
+      "IKEv2 Proposal Operational State";
+  }
+
+  feature ike-policy-state {
+    description
+      "IKEv1 Policy Operational State";
+  }
+
+  feature ikev1-state {
+    description
+      "IKEv1 Operational State";
+  }
+
+  feature ike-reauth-failure {
+    description
+      "IKEv1 Reauthorization Failure";
+  }
+
+  feature ike-rekey-failure {
+    description
+      "IKEv1 Rekey Failure";
+  }
+
+
+  feature ikev2 {
+    description
+      "Feature IKEv2";
+
+  }
+
+  feature ikev2-global {
+    description
+      "Feature IKEv2 Global Parameters";
+
+  }
+
+  feature ikev2-peer {
+    description
+      "Feature IKEv2 Peer";
+
+  }
+
+  feature ikev2-proposal {
+    description
+      "Feature IKEv2 Proposal";
+
+  }
+
+  feature ikev2-policy {
+    description
+      "Feature IKEv2 Policy";
+
+  }
+
+  feature ikev2-proposal-state {
+    description
+      "IKEv2 Proposal Operational State";
+  }
+
+  feature ikev2-state {
+    description
+      "IKEv2 Operational State";
+  }
+
+  feature ipsec {
+    description
+      "Feature IPsec";
+
+  }
+
+  feature ipsec-acl {
+    description
+      "Feature IPsec ACL";
+
+  }
+  feature ipsec-sad {
+    description
+      "Feature IPsec SAD";
+
+  }
+
+  feature ipsec-proposal {
+    description
+      "Feature IPsec Proposal";
+
+  }
+
+  feature ipsec-spd {
+    description
+      "Feature IPsec SPD";
+
+  }
+
+  feature ipsec-policy-state {
+    description
+      "IPsec Policy Operational State";
+  }
+
+  feature ipsec-proposal-state {
+    description
+      "IPsec Proposal Operational State";
+  }
+
+  feature ipsec-alarms-state {
+    description
+      "IPsec Alarm State Operational State";
+  }
+
+  feature ipsec-sa-ah-state {
+    description
+      "IPsec SA AH Operational State";
+  }
+
+  feature ipsec-sa-state {
+    description
+      "IPsec SA Operational State";
+  }
+
+  feature ipsec-tunnel {
+    description
+      "IPsec Tunnel";
+  }
+
+  feature ipsec-local-address-range {
+    description
+      "IPsec Local Address Range";
+  }
+
+  feature ipsec-remote-address-range {
+    description
+      "IPsec Remote Address Range";
+  }
+
+  feature ipsec-next-protocol-range {
+    description
+      "IPsec Next Protocol Range";
+  }
+
+  feature ipsec-local-port-range {
+    description
+      "IPsec Local Port Range";
+  }
+
+  feature ipsec-remote-port-range {
+    description
+      "IPsec Remote Port Range";
+  }
+
+  feature ipsec-ah-authentication {
+    description
+      "IPsec AH Authentication";
+  }
+
+  feature ipsec-esp-integrity {
+    description
+      "IPsec ESP Integrity";
+  }
+
+  feature ipsec-esp-encrypt {
+    description
+      "IPsec ESP encryption";
+  }
+
+  feature ipsec-stat {
+    description
+      "IPsec Stats";
+  }
+
+  feature ipsec-state {
+    description
+      "IPsec Operational State";
+  }
+
+  feature ipsec-rekey-failure {
+    description
+      "IPsec Rekey Failure";
+  }
+
+  feature ipsec-redundancy {
+    description
+      "IPsec Redundancy State";
+  }
+
+  feature sad {
+    description
+      "Security Association (SA) Database";
+  }
+
+  feature spd {
+    description
+      "Security Policy Database";
+  }
+
+  feature ipsec-global-stats {
+    description
+      "IPsec Global Stats";
+  }
+
+  feature clear-ipsec-group {
+    description
+      "Clear IPsec group";
+  }
+
+  feature clear-ike-group {
+    description
+      "Clear IKE group";
+  }
+
+  feature clear-ikev2-group {
+    description
+      "Clear IKEv2 group";
+  }
+
+  feature reset-ipv4 {
+    description
+      "Reset IPv4";
+  }
+
+  feature reset-ipv6 {
+    description
+      "Reset IPv6";
+  }
+
+  feature reset-global {
+    description
+      "Reset Global";
+  }
+
+  feature peer-authentication-failure {
+    description
+      "Peer Authentication Failure";
+  }
+  /*--------------------*/
+  /* Typedefs           */
+  /*--------------------*/
+
+  typedef authentication-method-t {
+    type enumeration {
+      enum psk {
+        value 0;
+        description
+          "Pre-Sharing Keys.";
+      }
+      enum certificate {
+        value 1;
+        description
+          "Certificate.";
+      }
+    }
+    description
+      "Available authentication methods.";
+  }
+
+  /* IKEv2 Exchange Types (ET) */
+  typedef ikev2-exchange-type-t {
+    type enumeration {
+      enum ikev2-et-ike-sa-init {
+        value 34;
+        description
+          "ikev2-et-ike-sa-init - RFC 7296.";
+      }
+      enum ikev2-et-ike-auth {
+        value 35;
+        description
+          "ikev2-et-ike-auth - RFC 7296.";
+      }
+      enum ikev2-et-create-child-sa {
+        value 36;
+        description
+          "ikev2-et-create-child-sa - RFC 7296.";
+      }
+      enum ikev2-et-informational {
+        value 37;
+        description
+          "ikev2-et-informational - RFC 7296.";
+      }
+      enum ikev2-et-ike-session-resume {
+        value 38;
+        description
+          "ikev2-et-ike-session-resume - RFC 7296.";
+      }
+      enum ikev2-et-gsa-auth {
+        value 39;
+        description
+          "ikev2-et-gsa-auth - RFC 7296.";
+      }
+      enum ikev2-et-gsa-registration {
+        value 40;
+        description
+          "ikev2-et-gsa-registration - RFC 7296.";
+      }
+      enum ikev2-et-gsa-rekey {
+        value 41;
+        description
+          "ikev2-et-gsa-rekey - RFC 7296.";
+      }
+    }
+    description
+      "IKEv2 Exchange Types (ET).";
+  }
+
+   /* Transform Type Values (TTV), RFC 7296 */
+   typedef transform-type-value-t {
+    type enumeration {
+      enum ttv-reserved-0 {
+        value 0;
+        description
+          "ttv-reserved-0 - Transform Type Value Reserved "+
+          "(RFC 7296).";
+      }
+      enum ttv-encr {
+        value 1;
+        description
+          "ttv-encr - Transform Type Value 1,
+           Encryption Algorithm "+
+          "(ENCR) used in IKE and ESP.";
+      }
+      enum ttv-prf {
+        value 2;
+        description
+          "ttv-prf - Transform Type Value 2, "+
+          "Pseudo-Random Function(PRF) used in IKE.";
+      }
+      enum ttv-integ {
+        value 3;
+        description
+          "ttv-integ - Transform Type Value 3, Integrity Algorithm"+
+          " (INTEG) used in IKE, AH, optional ESP.";
+      }
+      enum ttv-dh {
+        value 4;
+        description
+          "ttv-dh - Transform Type Value 4, Diffie-Hellman (DH) "+
+          "used in IKE, optional AH and ESP.";
+      }
+      enum ttv-esn {
+        value 5;
+        description
+          "ttv-esn - Transform Type Value 5, Extended Sequence "+
+          "Numbers (ESN) used in AH and ESP.";
+      }
+    }
+    description
+      "Transform Type Values (RFC 7296).";
+  }
+
+   /* IKEv2 Transform Attribute Types (TAT) */
+   typedef ikev2-transform-attribute-type-t {
+    type enumeration {
+      enum ikev2-tat-reserved-0 {
+        value 0;
+        description
+          "ikev2-tat-reserved-0 - IKEv2 Transform Attribute "+
+          "Type Reserved-0 (RFC 7296).";
+      }
+      enum ikev2-tat-reserved-1 {
+        value 1;
+        description
+          "ikev2-tat-reserved-1 - IKEv2 Transform Attribute "+
+          "Type Reserved-1 (RFC 7296).";
+      }
+      enum ikev2-tat-reserved-13 {
+        value 13;
+        description
+          "ikev2-tat-reserved-13 - IKEv2 Transform Attribute "+
+          "Type Reserved-13 (RFC 7296).";
+      }
+      enum ikev2-tat-key-length {
+        value 41;
+        description
+          "ikev2-tat-key-length - IKEv2 Transform Attribute "+
+          "Type KEY LENGTH (in bits) (RFC 7296).";
+      }
+    }
+    description
+      "IKEv2 Transform Attribute Types (TAT) (RFC 7296).";
+  }
+
+   /* Transform Type 1 (Encryption Algorithm Transform IDs) */
+  typedef ike-encryption-algorithm-t {
+    type enumeration {
+      enum encr-reserved-0 {
+        value 0;
+        description
+          "encr-reserved-0 --> RFC_5996.";
+      }
+      enum encr-des-iv4 {
+        value 1;
+        description
+          "encr-des-iv4 --> RFC_5996.";
+      }
+      enum encr-des {
+        value 2;
+        description
+          "encr-des --> RFC_5996.";
+      }
+      enum encr-3des {
+        value 3;
+        description
+          "encr-3des --> RFC_5996.";
+      }
+      enum encr-rc5 {
+        value 4;
+        description
+          "encr-rc5 --> RFC_5996.";
+      }
+      enum encr-idea {
+        value 5;
+        description
+          "encr-idea --> RFC_5996.";
+      }
+      enum encr-cast {
+        value 6;
+        description
+          "encr-cast --> RFC_5996.";
+      }
+      enum encr-blowfish {
+        value 7;
+        description
+          "encr-blowfish --> RFC_5996.";
+      }
+      enum encr-3idea {
+        value 8;
+        description
+          "encr-3idea --> RFC_5996.";
+      }
+      enum encr-des-iv32 {
+        value 9;
+        description
+          "encr-des-iv32 --> RFC_5996.";
+      }
+      enum encr-reserved-10 {
+        value 10;
+        description
+          "encr-reserved-10 --> RFC_5996.";
+      }
+      enum encr-null {
+        value 11;
+        description
+          "encr-null --> RFC_5996.";
+      }
+      enum encr-aes-cbc {
+        value 12;
+        description
+          "encr-aes-cbc --> RFC_5996.";
+      }
+      enum encr-aes-ctr {
+        value 13;
+        description
+          "encr-aes-ctr --> RFC_5996.";
+      }
+      enum encr-aes-ccm-8 {
+        value 14;
+        description
+          "encr-aes-ccm-8 --> RFC_5996.";
+      }
+      enum encr-aes-ccm-12 {
+        value 15;
+        description
+          "encr-aes-ccm-12 --> RFC_5996.";
+      }
+      enum encr-aes-ccm-16 {
+        value 16;
+        description
+          "encr-aes-ccm-16 --> RFC_5996.";
+      }
+      enum encr-reserved-17 {
+        value 17;
+        description
+          "encr-reserved-17 --> RFC_5996.";
+      }
+      enum encr-aes-gcm-8-icv {
+        value 18;
+        description
+          "encr-aes-gcm-8-icv --> RFC_5996.";
+      }
+      enum encr-aes-gcm-12-icv {
+        value 19;
+        description
+          "encr-aes-gcm-12-icv --> RFC_5996.";
+      }
+      enum encr-aes-gcm-16-icv {
+        value 20;
+        description
+          "encr-aes-gcm-16-icv--> RFC_5996.";
+      }
+      enum encr-null-auth-aes-gmac {
+        value 21;
+        description
+          "encr-null-auth-aes-gmac --> RFC_5996.";
+      }
+      enum encr-ieee-p1619-xts-aes {
+        value 22;
+        description
+          "encr-ieee-p1619-xts-aes --> Reserved for "+
+          "IEEE P1619 XTS-AES.";
+      }
+      enum encr-camellia-cbc {
+        value 23;
+        description
+          "encr-camellia-cbc --> RFC_5996.";
+      }
+      enum encr-camellia-ctr {
+        value 24;
+        description
+          "encr-camellia-ctr --> RFC_5996.";
+      }
+      enum encr-camellia-ccm-8-icv {
+        value 25;
+        description
+          "encr-camellia-ccm-8-icv --> RFC_5996.";
+      }
+      enum encr-camellia-ccm-12-icv {
+        value 26;
+        description
+          "encr-camellia-ccm-12-icv --> RFC_5996.";
+      }
+      enum encr-camellia-ccm-16-icv {
+        value 27;
+        description
+          "encr-camellia-ccm-16-icv --> RFC_5996.";
+      }
+      enum encr-aes-cbc-128 {
+        value 1024;
+        description
+          "encr-aes-cbc-128 --> RFC_5996.";
+      }
+      enum encr-aes-cbc-192 {
+        value 1025;
+        description
+          "encr-aes-cbc-192 --> RFC_5996.";
+      }
+      enum encr-aes-cbc-256 {
+        value 1026;
+        description
+          "encr-aes-cbc-256 --> RFC_5996.";
+      }
+      enum encr-blowfish-128 {
+        value 1027;
+        description
+          "encr-blowfish-128 --> RFC_5996.";
+      }
+      enum encr-blowfish-192 {
+        value 1028;
+        description
+          "encr-blowfish-192 --> RFC_5996.";
+      }
+      enum encr-blowfish-256 {
+        value 1029;
+        description
+          "encr-blowfish-256 --> RFC_5996.";
+      }
+      enum encr-blowfish-448 {
+        value 1030;
+        description
+          "encr-blowfish-448 --> RFC_5996.";
+      }
+      enum encr-camellia-128 {
+        value 1031;
+        description
+          "encr-camellia-128 --> RFC_5996.";
+      }
+      enum encr-camellia-192 {
+        value 1032;
+        description
+          "encr-camellia-192 --> RFC_5996.";
+      }
+      enum encr-camellia-256 {
+        value 1033;
+        description
+          "encr-camellia-256 --> RFC_5996.";
+      }
+    }
+    description
+      "Transform Type 1 - Internet Key Exchange (IKE) "+
+      "encryption algorithms.";
+  }
+
+  /* Transform Type 2 (Pseudo-Random Function PRF) */
+  typedef pseudo-random-function-t {
+    type enumeration {
+      enum prf-reserved-0 {
+        value 0;
+        description
+          "prf-reserved-0 --> RFC_2104.";
+      }
+      enum prf-hmac-md5 {
+        value 1;
+        description
+          "prf-hmac-md5 --> RFC_2104.";
+      }
+      enum prf-hmac-sha1 {
+        value 2;
+        description
+          "prf-hmac-sha1 --> RFC2104.";
+      }
+      enum prf-hmac-tiger {
+        value 3;
+        description
+          "prf-hmac-tiger --> RFC2104.";
+      }
+      enum prf-aes128-xcbc {
+        value 4;
+        description
+          "prf-aes128-xcbc --> RFC_4434.";
+      }
+      enum prf-hmac-sha2-256 {
+        value 5;
+        description
+          "prf-hmac-sha2-256 --> RFC_4434.";
+      }
+      enum prf-hmac-sha2-384 {
+        value 6;
+        description
+          "prf-hmac-sha2-384 --> RFC_4434.";
+      }
+      enum prf-hmac-sha2-512 {
+        value 7;
+        description
+          "prf-hmac-sha2-512 --> RFC_4434.";
+      }
+      enum prf-aes128-cmac {
+        value 8;
+        description
+          "prf-aes128-cmac --> RFC_4615.";
+      }
+    }
+    description
+      "Available Pseudo-Random Functions (PRF).";
+  }
+
+   /* Transform Type 3 (Integrity Algorithm) */
+  typedef ike-integrity-algorithm-t {
+    type enumeration {
+      enum auth-none {
+        value 0;
+        description
+          "auth-none --> RFC_5996.";
+      }
+      enum auth-hmac-md5-96 {
+        value 1;
+        description
+          "auth-hmac-md5-96 --> RFC_5996.";
+      }
+      enum auth-hmac-sha1-96 {
+        value 2;
+        description
+          "auth-hmac-sha1-96 --> RFC_5996.";
+      }
+      enum auth-des-mac {
+        value 3;
+        description
+          "auth-des-mac --> RFC_5996.";
+      }
+      enum auth-kpdk-md5 {
+        value 4;
+        description
+          "auth-kpdk-md5 --> RFC_5996.";
+      }
+      enum auth-aes-xcbc-96 {
+        value 5;
+        description
+          "auth-aes-xcbc-96 --> RFC_5996.";
+      }
+      enum auth-hmac-md5-128 {
+        value 6;
+        description
+          "auth-hmac-md5-128 --> RFC_5996.";
+      }
+      enum auth-hmac-sha1-160 {
+        value 7;
+        description
+          "auth-hmac-sha1-160 --> RFC_5996.";
+      }
+      enum auth-aes-cmac-96 {
+        value 8;
+        description
+          "auth-aes-cmac-96 --> RFC_5996.";
+      }
+      enum auth-aes-128-gmac {
+        value 9;
+        description
+          "auth-aes-128-gmac --> RFC_5996.";
+      }
+      enum auth-aes-192-gmac {
+        value 10;
+        description
+          "auth-aes-192-gmac --> RFC_5996.";
+      }
+      enum auth-aes-256-gmac {
+        value 11;
+        description
+          "auth-aes-256-gmac --> RFC_5996.";
+      }
+      enum auth-hmac-sha2-256-128 {
+        value 12;
+        description
+          "auth-hmac-sha2-256-128 --> RFC_5996.";
+      }
+      enum auth-hmac-sha2-384-192 {
+        value 13;
+        description
+          "auth-hmac-sha2-384-192 --> RFC_5996.";
+      }
+      enum auth-hmac-sha2-512-256 {
+        value 14;
+        description
+          "auth-hmac-sha2-512-256 --> RFC_5996.";
+      }
+      enum auth-hmac-sha2-256-96 {
+        value 1024;
+        description
+          "auth-hmac-sha2-256-96.";
+      }
+    }
+    description
+      "Transform Type 3 - Internet Key Exchange (IKE) "+
+      "Integrity Algorithms.";
+  }
+
+  /* Transform Type 4 (Diffie-Hellman Group) */
+  typedef diffie-hellman-group-t {
+    type enumeration {
+      enum group-none {
+        value 0;
+        description
+          "group-none --> RFC_5996.";
+      }
+      enum modp-768-group-1 {
+        value 1;
+        description
+          "modp-768-group-1 --> RFC_5996.";
+      }
+      enum modp-1024-group-2 {
+        value 2;
+        description
+          "modp-1024-group-2 --> RFC_5996.";
+      }
+      enum modp-1536-group-5 {
+        value 5;
+        description
+          "modp-1536-group-5 --> RFC_3526.";
+      }
+      enum modp-2048-group-14 {
+        value 14;
+        description
+          "modp-2048-group-14 --> RFC_3526.";
+      }
+      enum modp-3072-group-15 {
+        value 15;
+        description
+          "modp-3072-group-15 --> RFC_3526.";
+      }
+      enum modp-4096-group-16 {
+        value 16;
+        description
+          "modp-4096-group-16 --> RFC_3526.";
+      }
+      enum modp-6144-group-17 {
+        value 17;
+        description
+          "modp-6144-group-17 --> RFC_3526.";
+      }
+      enum modp-8192-group-18 {
+        value 18;
+        description
+          "modp-8192-group-18 --> RFC_3526.";
+      }
+      enum recp-256-group-19 {
+        value 19;
+        description
+          "recp-256-group-19 --> RFC_6989. 256-bit"+
+          " Random ECP Group.";
+      }
+      enum recp-384-group-20 {
+        value 20;
+        description
+          "recp-384-group-20 --> RFC_6989. 384-bit"+
+          " Random ECP Group.";
+      }
+      enum recp-521-group-21 {
+        value 21;
+        description
+          "recp-521-group-21 --> RFC_6989. 521-bit"+
+          " Random ECP Group.";
+      }
+      enum modp-1024-160-pos-group-22 {
+        value 22;
+        description
+          "modp-1024-160-pos-group-22 --> RFC_6989."+
+          " 1024-bit MODP Group with"+
+          " 160-bit Prime Order Subgroup (POS).";
+      }
+      enum modp-2048-224-pos-group-23 {
+        value 23;
+        description
+          "modp-2048-224-pos-group-23 --> RFC_6989."+
+          " 2048-bit MODP Group with"+
+          " 224-bit Prime Order Subgroup (POS).";
+      }
+      enum modp-2048-256-pos-group-24 {
+        value 24;
+        description
+          "modp-2048-256-pos-group-24 --> RFC_6989."+
+          " 2048-bit MODP Group with"+
+          " 256-bit Prime Order Subgroup (POS).";
+      }
+      enum recp-192-group-25 {
+        value 25;
+        description
+          "recp-192-group-25 --> RFC_6989."+
+          " 192-bit Random ECP Group.";
+      }
+      enum recp-224-group-26 {
+        value 26;
+        description
+          "recp-224-group-26 --> RFC_6989."+
+          " 224-bit Random ECP Group.";
+      }
+    }
+    description
+      "Diffie-Hellman Groups (RFC 5996).";
+  }
+
+
+  /* Transform Type 5 (Extended Sequence Numbers
+     Transform ESN IDs) */
+  typedef extended-sequence-number-t {
+    type enumeration {
+      enum esn-none {
+        value 0;
+        description
+          "esn-none - Extended Sequence Number None --> RFC_7296.";
+      }
+      enum esn-1 {
+        value 1;
+        description
+          "esn-1 - Extended Sequence Number --> RFC_7296.";
+      }
+    }
+    description
+      "Extended Sequence Number (RFC 7296).";
+  }
+
+
+  typedef connection-type-t {
+    type enumeration {
+      enum initiator-only {
+        value 0;
+        description
+          "initiator-only: ME will act as initiator for"+
+          " bringing up IKEv2"+
+          " session with its IKE peer.";
+      }
+      enum responder-only {
+        value 1;
+        description
+          "responder-only: ME will act as responder for"+
+          " bringing up IKEv2"+
+          " session with its IKE peer.";
+      }
+      enum both {
+        value 2;
+        description
+          "both: ME can act as initiator or responder.";
+      }
+    }
+    description
+      "Connection type for IKE session.";
+  }
+
+  typedef transport-protocol-name-t {
+    type enumeration {
+      enum tcp {
+        value 1;
+        description
+          "Transmission Control Protocol (TCP) Transport Protocol.";
+      }
+      enum udp {
+        value 2;
+        description
+          "User Datagram Protocol (UDP) Transport Protocol";
+      }
+      enum sctp {
+        value 3;
+        description
+          "Stream Control Transmission Protocol (SCTP) Transport "+
+          "Protocol";
+      }
+      enum icmp {
+        value 4;
+        description
+          "Internet Control Message Protocol (ICMP) Transport "+
+          "Protocol";
+      }
+    }
+    description
+      "Enumeration of well known transport protocols.";
+  }
+
+  typedef preshared-key-t {
+    type string;
+    description
+      "Derived string used as Pre-Shared Key.";
+  }
+
+  typedef pad-type-t {
+    type enumeration {
+      enum dns-name {
+        value 1;
+        description
+          "DNS name (specific or partial)";
+      }
+      enum distinguished-name {
+        value 2;
+        description
+          "Distinguished Name (complete or sub-tree constrained)";
+      }
+      enum rfc-822 {
+        value 3;
+        description
+          "RFC 822 email address (complete or partially qualified)";
+      }
+      enum ipv4-range {
+        value 4;
+        description
+          "IPv4 Address Range";
+      }
+      enum ipv6-range {
+        value 5;
+        description
+          "IPv6 Address Range";
+      }
+      enum key-id {
+        value 6;
+        description
+          "Key ID (exact match only)";
+      }
+    }
+    description
+      "PAD Type";
+  }
+
+
+  /*-------------------------------------------------- */
+  /* draft-wang-ipsecme-ipsec-yang-00: ietf-ipsec-type */
+  /*-------------------------------------------------- */
+  typedef ipsec-mode {
+    type enumeration {
+      enum "transport" {
+        description
+          "Transport mode";
+      }
+      enum "tunnel" {
+        description
+          "Tunnel mode";
+      }
+    }
+    description
+      "type define of ipsec mode";
+  }
+
+  typedef ipsec-protocol {
+    type enumeration {
+      enum "ah" {
+        description
+          "AH Protocol";
+      }
+      enum "esp" {
+        description
+          "ESP Protocol";
+      }
+    }
+    description
+      "type define of ipsec security protocol";
+  }
+
+  typedef ipsec-spi {
+    type uint32 {
+      range "1..max";
+    }
+    description
+      "SPI";
+  }
+
+  typedef ipsec-spd-name {
+   type enumeration {
+    enum id_rfc_822_addr {
+        description
+          "Fully qualified user name string.";
+      }
+      enum id_fqdn {
+        description
+          "Fully qualified DNS name.";
+      }
+      enum id_der_asn1_dn {
+        description
+          "X.500 distinguished name.";
+      }
+      enum id_key {
+        description
+          "IKEv2 Key ID.";
+      }
+    }
+    description
+      "IPsec SPD name type";
+  }
+
+  typedef ipsec-traffic-direction {
+    type enumeration {
+      enum inbound {
+        description
+          "Inbound traffic";
+      }
+      enum outbound {
+        description
+          "Outbound traffic";
+      }
+    }
+    description
+      "IPsec traffic direction";
+  }
+
+  typedef ipsec-spd-operation {
+    type enumeration {
+      enum protect {
+        description
+          "PROTECT the traffic with IPsec";
+      }
+      enum bypass {
+        description
+          "BYPASS the traffic";
+      }
+      enum discard {
+        description
+          "DISCARD the traffic";
+      }
+    }
+    description
+      "The operation when traffic matches IPsec security policy";
+  }
+
+
+  /*---------------------------------------------------- */
+  /* draft-wang-ipsecme-ipsec-yang-00: ietf-ipsec-crypto */
+  /*---------------------------------------------------- */
+  typedef ipsec-authentication-algorithm {
+    type enumeration {
+      enum "null" {
+        value 0;
+        description
+          "null";
+      }
+      enum "md5" {
+        value 1;
+        description
+          "MD5 authentication algorithm";
+      }
+      enum "sha1" {
+        value 2;
+        description
+          "SHA1 authentication algorithm";
+      }
+      enum "sha2-256" {
+        value 3;
+        description
+          "SHA2-256 authentication algorithm";
+      }
+      enum "sha2-384" {
+        value 4;
+        description
+          "SHA2-384 authentication algorithm";
+      }
+      enum "sha2-512" {
+        value 5;
+        description
+          "SHA2-512 authentication algorithm";
+      }
+    }
+    description
+      "typedef for ipsec authentication algorithm";
+  }
+
+  typedef ipsec-encryption-algorithm {
+    type enumeration {
+      enum "null" {
+        description
+          "null";
+      }
+      enum "des" {
+        description
+          "DES encryption algorithm";
+      }
+      enum "3des" {
+        description
+          "3DES encryption algorithm";
+      }
+      enum "aes-128" {
+        description
+          "AES-128 encryption algorithm";
+      }
+      enum "aes-192" {
+        description
+          "AES-192 encryption algorithm";
+      }
+      enum "aes-256" {
+        description
+          "AES-256 encryption algorithm";
+      }
+    }
+    description
+     "typedef for ipsec encryption algorithm";
+  }
+
+  /*-------------------------------------------------- */
+  /* draft-wang-ipsecme-ike-yang-00: ietf-ipsec-type */
+  /*-------------------------------------------------- */
+  typedef ike-integrity-algorithm {
+    type enumeration {
+      enum "hmac-md5-96" {
+        description
+          "HMAC-MD5-96 Integrity Algorithm";
+      }
+      enum "hmac-sha1-96" {
+        description
+          "HMAC-SHA1-96 Integrity Algorithm";
+      }
+      enum "hmac-sha2-256" {
+        description
+          "HMAC-SHA2-256 Integrity Algorithm";
+      }
+      enum "hmac-sha2-384" {
+        description
+          "HMAC-SHA2-384 Integrity Algorithm";
+      }
+      enum "hmac-sha2-512" {
+        description
+          "HMAC-SHA2-512 Integrity Algorithm";
+      }
+    }
+    description
+      "typedef for ike integrity algorithm.";
+  }
+
+  typedef ike-encryption-algorithm {
+    type enumeration {
+      enum "des-cbc" {
+        description
+          "DES-CBC Encryption algorithm";
+      }
+      enum "3des-cbc" {
+        description
+          "3DES-CBC Encryption algorithm";
+      }
+      enum "aes-cbc-128" {
+        description
+          "AES-CBC-128 Encryption algorithm";
+      }
+      enum "aes-cbc-192" {
+        description
+          "AES-CBC-192 Encryption algorithm";
+      }
+      enum "aes-cbc-256" {
+        description
+          "AES-CBC-256 Encryption algorithm";
+      }
+    }
+    description
+      "typedef for ike encryption algorithm.";
+  }
+
+  typedef ike-prf-algorithm {
+    type enumeration {
+      enum "hmac-md5-96" {
+        description
+          "HMAC-MD5-96 PRF Algorithm";
+      }
+      enum "hmac-sha1-96" {
+        description
+          "HMAC-SHA1-96 PRF Algorithm";
+      }
+      enum "hmac-sha2-256" {
+        description
+          "HMAC-SHA2-256 PRF Algorithm";
+      }
+      enum "hmac-sha2-384" {
+        description
+          "HMAC-SHA2-384 PRF Algorithm";
+      }
+      enum "hmac-sha2-512" {
+        description
+          "HMAC-SHA2-512 PRF Algorithm";
+      }
+    }
+    description
+      "typedef for ike prf algorithm.";
+  }
+
+  typedef ike-dh-group {
+    type enumeration {
+      enum "dh-group-none" {
+        description
+          "None Diffie-Hellman group";
+      }
+      enum "dh-group-1" {
+        description
+          "768 bits Diffie-Hellman group";
+      }
+      enum "dh-group-2" {
+        description
+          "1024 bits Diffie-Hellman group";
+      }
+      enum "dh-group-5" {
+        description
+          "1536 bits Diffie-Hellman group";
+      }
+      enum "dh-group-14" {
+        description
+          "2048 bits Diffie-Hellman group";
+      }
+    }
+    description
+      "typedef for ike dh group";
+  }
+
+
+  typedef ike-peer-name-ref {
+    type leafref {
+      path "/ikev2/ike-peer/ike-peer-entries/peer-name";
+    }
+    description "reference to ike peer name";
+  }
+
+  typedef ike-proposal-number-ref {
+    type leafref {
+      path "/ikev2/proposal/name";
+    }
+    description "reference to ike proposal name";
+  }
+
+  typedef ipsec-proposal-name-ref{
+    type leafref {
+      path "/ipsec/proposal/ipsec-proposal/name";
+    }
+    description "reference to ike proposal name";
+  }
+
+  typedef ike-auth-method {
+    type enumeration {
+      enum pre-share {
+        description
+          "Select pre-shared key message as the
+           authentication method";
+      }
+      enum rsa-digital-signature {
+        description
+          "Select rsa digital signature as the
+           authentication method";
+      }
+      enum dss-digital-signature {
+        description
+          "Select dss digital signature as the
+           authentication method";
+      }
+    }
+    description "IKE authentication methods";
+  }
+
+  /*--------------------*/
+  /*   grouping         */
+  /*--------------------*/
+
+   /* The following groupings are used in both configuration data
+     and operational state data */
+  grouping name-grouping {
+    description
+      "This grouping provides a leaf identifying the name.";
+    leaf name {
+      type string;
+      description
+        "Name of a identifying.";
+    }
+    leaf description {
+      type string;
+      description
+        "Specify the description.";
+    }
+  }
+
+  grouping sequence-number-grouping {
+    description
+      "This grouping provides a leaf identifying
+       a sequence number.";
+    leaf sequence-number {
+      type uint32 {
+        range "1..4294967295";
+      }
+      description
+        "Specify the sequence number.";
+    }
+  }
+
+  grouping description-grouping {
+    description
+      "description for free use.";
+    leaf description {
+      type string;
+      description
+        "description for free use.";
+    }
+  }
+
+  grouping traffic-selector-grouping {
+    description
+      "Traffic selector to be used for SA negotiation.";
+    leaf traffic-selector-id {
+      type string;
+      mandatory true;
+      description
+        "Traffic selector identifier.";
+    }
+    leaf protocol-name {
+      type transport-protocol-name-t;
+      description
+        "Specifies the protocol selector.";
+    }
+    leaf address-range {
+      type string;
+      mandatory true;
+      description
+        "Specifies the IPv4 or IPv6 address range.";
+    }
+  }
+
+
+
+  grouping ike-general-proposal-grouping {
+    description
+      "IKE proposal.";
+    leaf name {
+       type string;
+       mandatory true;
+       description
+         "IKE Proposal identify.";
+    }
+    leaf description {
+      type string;
+      description
+        "Specify the description.";
+    }
+
+    leaf dh-group {
+      type diffie-hellman-group-t;
+      mandatory true;
+      description
+        "Specifies a Diffie-Hellman group.";
+    }
+    container encryption {
+      description
+        "Specify IKE Proposal encryption configuration";
+      leaf algorithm {
+         type ike-encryption-algorithm-t;
+         description
+           "Specifies an Encryption Algorithm.";
+      }
+    }
+  }
+
+  grouping ike-proposal-grouping {
+    description
+      "Configure the IKE Proposal";
+    uses ike-general-proposal-grouping;
+
+    leaf lifetime {
+      type uint32;
+       mandatory true;
+      description
+        "Configure lifetime for IKE SAs
+         0: for no timeout.
+         300 .. 99999999:  IKE SA lifetime in seconds.";
+    }
+    container authentication {
+      description
+        "Specify IKE Proposal authentication configuration";
+      leaf algorithm {
+        type ike-integrity-algorithm-t;
+        description
+          "Specify the authentication algorithm";
+      }
+      leaf preshared-key {
+        type empty;
+        description
+          "Use pre-shared key based authentication";
+      }
+      leaf rsa-signature {
+        type empty;
+        description
+          "Use signature based authentication by using
+           PKI certificates";
+      }
+    }
+  }
+
+  grouping ikev2-proposal-grouping {
+    description
+      "Holds an IKEv2 transform proposal used during "+
+      "IKEv2 SA negotiation.  Multiple IKEv2 Transforms "+
+      " can be proposed during an IKEv2 session initiation "+
+      "in an ordered list.";
+    uses ike-general-proposal-grouping;
+
+    leaf pseudo-random-function {
+      type pseudo-random-function-t;
+      mandatory true;
+      description
+        "Specifies Pseudo Random Function for IKEv2 key exchange";
+    }
+    container authentication {
+      description
+        "Specify IKEv2 Proposal authentication configuration";
+      leaf algorithm {
+        type ike-integrity-algorithm-t;
+        description
+          "Specify the authentication algorithm";
+      }
+    }
+  }
+
+  grouping ipsec-proposal-grouping {
+    description
+      "Configure IPSec Proposal";
+    leaf name {
+       type string;
+       mandatory true;
+       description
+         "IPSec proposal identifier.";
+    }
+    leaf ah {
+      type ike-integrity-algorithm-t;
+      description
+        "Configure Authentication Header (AH).";
+    }
+    container esp {
+      description
+        "Configure Encapsulating Security Payload (ESP).";
+      leaf authentication {
+        type ike-integrity-algorithm-t;
+        description
+          "Configure ESP authentication";
+      }
+      leaf encryption {
+        type ike-encryption-algorithm-t;
+        description
+          "Configure ESP encryption";
+      }
+    }
+    leaf ip-comp{
+      type empty;
+      description
+        "Enable IPSec proposal IP-COMP which uses the IP Payload "+
+        "compression protocol to compress IP Security (IPSec) "+
+        "packets before encryption";
+    }
+    container lifetime {
+      description
+        "Configure lifetime for IPSEC SAs";
+      leaf kbytes {
+        type uint32 {
+          range "128..2147483647";
+        }
+        description
+          "Enter lifetime kbytes for IPSEC SAs";
+      }
+      leaf seconds {
+        type uint32 {
+          range "300..99999999";
+        }
+        description
+          "Enter lifetime seconds for IPSEC SAs
+          0: lifetime of 0 for no timeout
+          300..99999999: IPSec SA lifetime in seconds";
+      }
+    }
+  }
+
+  grouping identity-grouping {
+    description
+      "Identification type. It is an union identity, "+
+      "possible type as follows: "+
+      "a) ID_FQDN: A fully-qualified domain name string. "+
+      "  An example of a ID_FQDN is, example.com. "+
+      "  The string MUST not contain any terminators "+
+      "(e.g., NULL, CR, etc.). "+
+      "b) ID_RFC822_ADDR: A fully-qualified RFC822 email "+
+      "   address string, An example of a ID_RFC822_ADDR is, "+
+      "   [email protected]. The string MUST not contain "+
+      "   any terminators. "+
+      "c) ID_IPV4_ADDR: A single four (4) octet IPv4 address. "+
+      "d) ID_IPV6_ADDR: A single sixteen (16) octet IPv6 address. "+
+      "e) DN_X509: Distinguished name in the X.509 tradition.";
+    choice identity {
+      description
+        "Choice of identity.";
+      leaf ipv4-address {
+        type inet:ipv4-address;
+        description
+          "Specifies the identity as a single four (4)
+           octet IPv4 address.
+           An example is, 10.10.10.10. ";
+      }
+      leaf ipv6-address {
+        type inet:ipv6-address;
+        description
+          "Specifies the identity as a single sixteen (16) "+
+          "octet IPv6 address. "+
+          "An example is, "+
+          "FF01::101, 2001:DB8:0:0:8:800:200C:417A .";
+      }
+      leaf fqdn-string {
+        type inet:domain-name;
+        description
+          "Specifies the identity as a Fully-Qualified
+           Domain Name (FQDN) string.
+           An example is: example.com.
+           The string MUST not contain any terminators
+           (e.g., NULL, CR, etc.).";
+      }
+      leaf rfc822-address-string {
+        type string;
+        description
+          "Specifies the identity as a fully-qualified RFC822
+           email address string.
+           An example is, [email protected].
+           The string MUST not contain any terminators
+           (e.g., NULL, CR, etc.).";
+      }
+      leaf dnX509 {
+        type string;
+        description
+          "Specifies the identity as a distinguished name
+           in the X.509 tradition.";
+      }
+    }
+  } /* grouping identity-grouping */
+
+  grouping ike-general-policy-profile-grouping {
+    description
+      "IKE policy.";
+    leaf connection-type {
+      type connection-type-t;
+      mandatory true;
+      description
+        "Specify the IKE connection type";
+    }
+    leaf pre-shared-key {
+      type union {
+        type string {
+          length "16";
+        }
+        /* TODO HC2VPP-399: Removed length from hex-string which caused
+           failures when building using ODL yangtools
+           */
+        type yang:hex-string;
+      }
+      description
+        "Specify IKE pre-shared-key value";
+    }
+    leaf validate-certificate-identity {
+      type empty;
+      description
+        "Validate Remote-ID payload against the
+        ID's available in the certificate";
+    }
+    list seq {
+      key seq-id;
+      description
+        "list of sequence of policy.";
+      leaf seq-id {
+        type uint32 {
+          range "1..429496729";
+        }
+        description
+          "Sequence Number";
+      }
+      leaf proposal {
+        type leafref {
+          path "/eipsec:ikev1/eipsec:proposal"+
+               "/eipsec:name";
+        }
+        description
+          "IKE Proposal reference.";
+      }
+    }
+    container identity {
+      description
+        "Specify IKE identity value";
+      container local {
+        description
+          "Specify the identity of the local IP Security (IPSec)
+          tunnel endpoint in an Internet Key Exchange (IKE)
+          policy to use when negotiating IKE request with a
+          remote peer.";
+        uses identity-grouping;
+      }
+      container remote {
+        description
+          "Specify the identity of the remote IP Security (IPSec)
+          tunnel endpoint in an
+           Internet Key Exchange (IKE) policy to use when
+           negotiating IKE request with a remote peer.";
+        uses identity-grouping;
+      }
+    }
+  }
+
+  grouping ike-policy-mode-grouping {
+    description
+      "IKE Policy Mode";
+    container mode {
+      description
+        "Specify IKE mode configuration";
+      leaf aggressive {
+        type empty;
+        description
+          "Set IKE Aggressive mode";
+      }
+      leaf main {
+        type empty;
+        description
+          "Set IKE Main mode";
+      }
+    }
+  }
+
+  grouping ike-policy-profile-grouping {
+    description
+      "Configure IKE policy";
+    leaf name {
+      type string;
+      mandatory true;
+      description
+        "Specify an IKE policy name";
+    }
+    uses ike-policy-mode-grouping;
+    uses ike-general-policy-profile-grouping;
+  }
+
+  grouping ikev2-policy-profile-grouping {
+    description
+      "Common information for multiple IKE sessions
+      to be instantiated on a managed element.;
+       One or more Ikev2Session instances might refer
+       to this instance.";
+    leaf name {
+      type string;
+      mandatory true;
+      description
+        "Value component of the RDN.";
+    }
+    container authentication {
+      description
+        "Specify IKE Proposal authentication configuration";
+      leaf preshared-key {
+        type empty;
+        description
+          "Use pre-shared key based authentication";
+      }
+      leaf rsa-signature {
+        type empty;
+        description
+          "Use signature based authentication by using
+          PKI certificates";
+      }
+    }
+    leaf lifetime {
+      type uint32;
+      mandatory true;
+      description
+        "Configure lifetime for IKE SAs
+         0: for no timeout.
+         300 .. 99999999:  IKE SA lifetime in seconds.";
+    }
+
+    container address-allocation {
+      must "../connection-type = 'responder-only'" {
+        description
+          "address-allocation can be configured only with
+          responder-only in ike2 policy";
+      }
+      leaf aaa {
+        type empty;
+        description
+          "IRAC address allocation by AAA";
+      }
+      description
+        "Specify IKE IRAS address allocation option";
+    }
+
+    uses ike-general-policy-profile-grouping;
+
+    leaf description {
+      type string;
+      description
+        "Specify the description.";
+    }
+  }
+
+  grouping ipsec-policy-grouping {
+    description
+      "Holds configuration information for IPSec policies.";
+    leaf name {
+      type string;
+      mandatory true;
+      description
+        "IPSec Policy Identification";
+    }
+    leaf description {
+      type string;
+      description
+        "Specify the description.";
+    }
+
+    leaf anti-replay-window {
+      type uint32 {
+        range "0 | 32..1024";
+      }
+      description
+        "Configure replay window size
+        0: to disable anti-replay-window
+        32..1024: IPSec anti-replay-window size in multiple of 32";
+    }
+    container perfect-forward-secrecy {
+      description
+        "Configure Perfect Forward Secrecy (PFS) for IPSec Policy";
+      leaf dh-group {
+        type diffie-hellman-group-t;
+        description
+          "Configure Diffie-Hellman group for
+           perfect-forward-secrecy";
+      }
+    }
+    list seq {
+      key seq-id;
+      description
+        "Specify IPSEC proposal sequence number";
+      leaf seq-id {
+        type uint32;
+        description
+          "Sequence ID";
+      }
+      leaf description {
+        type string;
+        description
+          "Specify the description.";
+      }
+
+      leaf proposal {
+        type leafref {
+          path "/eipsec:ipsec/"+
+               "eipsec:proposal/eipsec:ipsec-proposal/eipsec:name";
+        }
+        description
+          "IKE proposal reference.";
+      }
+    }
+  }
+
+  grouping key-string-grouping {
+    description
+      "Configure key for authentication algorithm";
+    leaf key-str {
+      type union {
+        type string {
+          length "16";
+        }
+        /* TODO HC2VPP-399: Removed length from hex-string which caused
+           failures when building using ODL yangtools
+           */
+        type yang:hex-string;
+      }
+      description
+        "Key string input is either string value (length of 16)
+        or hexadecimal (length of 40)";
+    }
+  }
+
+  grouping ipsec-sa-ah-grouping {
+    description
+      "Configure Authentication Header (AH) for
+       Security Association (SA)";
+    container ah {
+      description
+        "Configure Authentication Header (AH) for SA";
+      choice authentication-algorithm {
+        description
+          "choice for authentication algorithm to set for AH";
+        case hmac-aes-xcbc {
+          container hmac-aes-xcbc {
+            description
+              "Set the authentication algorithm to hmac-aes-xcbc";
+            uses key-string-grouping;
+          }
+        }
+        case hmac-md5-96 {
+          container hmac-md5-96 {
+            description
+              "Set the authentication algorithm to hmac-md5-96";
+            uses key-string-grouping;
+          }
+        }
+        case hmac-sha1-96 {
+          container hmac-sha1-96 {
+            description
+              "Set the authentication algorithm to hmac-sha1-96";
+            uses key-string-grouping;
+          }
+        }
+        case key-string {
+          container key-string {
+            description
+              "Configure key for authentication algorithm";
+            uses key-string-grouping;
+          }
+        }
+      }
+    }
+  }
+
+  grouping ipsec-sa-esp-grouping {
+    description
+      "Configure IPSec Encapsulation Security Payload (ESP)";
+    container esp {
+      description
+        "Set IPSec Encapsulation Security Payloer (ESP)";
+      container authentication {
+        description
+          "Configure authentication for IPSec
+           Encapsulation Secutiry Payload (ESP)";
+        choice authentication-algorithm {
+          description
+            "choice for authentication algorithm to set";
+          case hmac-aes-xcbc {
+            container hmac-aes-xcbc {
+              description
+                "Set the authentication algorithm to hmac-aes-xcbc";
+              uses key-string-grouping;
+            }
+          }
+          case hmac-md5-96 {
+            container hmac-md5-96 {
+              description
+                "Set the authentication algorithm to hmac-md5-96";
+              uses key-string-grouping;
+            }
+          }
+          case hmac-sha1-96 {
+            container hmac-sha1-96 {
+              description
+                "Set the authentication algorithm to hmac-sha1-96";
+              uses key-string-grouping;
+            }
+          }
+          case key-string {
+            container key-string {
+              description
+                "Configure key for authentication algorithm";
+              uses key-string-grouping;
+            }
+          }
+        }
+      }
+      container encryption {
+        description
+          "Configure encryption for IPSec
+           Encapsulation Secutiry Payload (ESP)";
+        choice encryption-algorithm {
+          description
+            "type of encryption";
+          case des3-cbc {
+            container des3-cbd {
+              description
+                "Set the encryption algorithm to des3-cbc";
+              uses key-string-grouping;
+            }
+          }
+          case aes-128-cbc {
+            container aes-128-cbc {
+              description
+                "Set the encryption algorithm to aes-128-cbc";
+              uses key-string-grouping;
+            }
+          }
+          case aes-192-cbc {
+            container aes-192-cbc {
+              description
+                "Set the encryption algorithm to aes-192-cbc";
+              uses key-string-grouping;
+            }
+          }
+          case aes-256-cbc {
+            container aes-256-cbc {
+              description
+                "Set the encryption algorithm to aes-256-cbc";
+              uses key-string-grouping;
+            }
+          }
+          case des-cbc {
+            container des-cbc {
+              description
+                "Set the encryption algorithm to des-cbc";
+              uses key-string-grouping;
+            }
+          }
+          case key-string {
+            container key-string {
+              description
+                "Configure key for encryption algorithm";
+              uses key-string-grouping;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  grouping ipsec-acl-dest-grouping {
+    description
+      "IPSEC ACL destination.";
+    /* For destination */
+    choice dest-address {
+      description
+        "destination address.";
+      case dest-ipv4-address {
+        leaf destination-ipv4-address {
+          type inet:ipv4-address;
+          description
+            "Destination IPv4 Address A.B.C.D/0..32.";
+        }
+      }
+      case dest-any {
+        leaf dest-any {
+          type empty;
+          description
+            "Match Any Destination IPv4 Address.";
+        }
+      }
+    }
+  }
+
+  grouping ipsec-acl-seq-protocol-number-grouping {
+    description
+      "IPSec ACL Sequence protocol number.";
+    leaf number {
+      type uint16 {
+        range "0..255";
+      }
+      description
+        "Specify protocol number.";
+    }
+    choice argument {
+      description
+        "Source IPv4 address.";
+      case source-ipv4-address {
+        leaf source-ipv4-address {
+          type inet:ipv4-address;
+          description
+            "Source IPv4 Address A.B.C.D/0..32.";
+        }
+      }
+      case any {
+        /* For source */
+        leaf source-any {
+          type empty;
+          description
+            "Match Any Source IPv4 Address.";
+        }
+      }
+    }
+  }
+
+  grouping ipsec-acl-seq-ip-address-grouping {
+    description
+      "IPSec ACL Sequence IP Address.";
+    leaf source-ipv4-address {
+      type inet:ipv4-address;
+      description
+        "Source is IPv4 Address A.B.C.D/0..32.";
+    }
+  }
+
+  grouping ipsec-acl-seq-any-grouping {
+    description
+      "IPSec ACL Sequence Any.";
+    leaf any {
+      type empty;
+      description
+        "Source is Any.";
+    }
+  }
+
+  grouping ipsec-acl-seq-tcp-grouping {
+    description
+      "IPSec ACL Sequence TCP.";
+    leaf tcp {
+      type empty;
+      description
+        "Source is TCP protocol.";
+    }
+  }
+
+  grouping ipsec-acl-seq-udp-grouping {
+    description
+      "IPSec ACL Sequence for UDP.";
+    leaf udp {
+      type empty;
+      description
+        "Source is UDP protocol.";
+    }
+  }
+
+  grouping ipsec-acl-grouping {
+    description
+      "IPSec ACL";
+    list access-list {
+      if-feature ipsec-acl;
+      key "name sequence-number";
+      uses name-grouping;
+      uses sequence-number-grouping;
+      description
+        "Configure the IPSec access-list.";
+      choice protocol {
+        description
+          "IPSec ACL protocol.";
+        case number {
+          uses ipsec-acl-seq-protocol-number-grouping;
+        }
+        case source-ipv4-address {
+          uses ipsec-acl-seq-ip-address-grouping;
+        }
+        case any {
+          uses ipsec-acl-seq-any-grouping;
+        }
+        case tcp {
+          uses ipsec-acl-seq-tcp-grouping;
+        }
+        case udp {
+          uses ipsec-acl-seq-udp-grouping;
+        }
+      }
+      uses ipsec-acl-dest-grouping;
+    }
+  }
+
+  grouping ipsec-df-bit-grouping {
+    description
+      "IPSec Dont Fragment (DF) bit for IP header.";
+    container df-bit {
+      description
+        "Configure Don't Fragment (DF) bit for IP Header.";
+      leaf clear {
+        type empty;
+        description
+          "Clear DF bit for outer IP header.";
+      }
+      leaf propagate {
+        type empty;
+        description
+          "Propagate DF bit for outer IP header.";
+      }
+      leaf set {
+        type empty;
+        description
+          "Set DF bit for outer IP header.";
+      }
+    }
+  }
+
+  grouping ipsec-profile-grouping {
+    description
+      "IPSec profile.";
+    list profile {
+      key "name";
+      uses name-grouping;
+      uses ipsec-df-bit-grouping;
+      description
+        "Configure the IPSec Profile.";
+      leaf mtu {
+        type uint32 {
+          range "256..1600";
+        }
+        description
+          "Set the MTU.";
+      }
+      list seq {
+        key "sequence-number";
+        uses sequence-number-grouping;
+        description
+          "IPSec Access List sequence number.";
+        leaf policy {
+          type leafref {
+          //TODO: fixed path (HC2VPP-399)
+            path "/eipsec:ipsec/eipsec:spd/"+
+                  "eipsec:spd-entries/eipsec:name";
+          }
+          description
+            "Specify IPSec policy name.";
+        }
+      }
+    }
+  }
+
+  grouping ip-address-grouping {
+    description
+      "IP Address grouping";
+
+    choice ip-address {
+      description
+        "Choice of IPv4 or IPv6.";
+      leaf ipv4-address {
+        type inet:ipv4-address;
+        description
+          "Specifies the identity as a single four (4)
+           octet IPv4 address.
+           An example is, 10.10.10.10. ";
+      }
+      leaf ipv6-address {
+        type inet:ipv6-address;
+        description
+          "Specifies the identity as a single sixteen (16) "+
+          "octet IPv6 address. "+
+          "An example is, "+
+          "FF01::101, 2001:DB8:0:0:8:800:200C:417A .";
+      }
+    }
+  }
+
+  grouping ipsec-sa-grouping {
+    description
+      "Configure Security Association (SA)";
+    leaf spi {
+      type uint32;
+      description
+        "Specify Security Parameter Index";
+    }
+    leaf anti-replay-window {
+      type uint16 {
+        range "0 | 32..1024";
+      }
+      description
+        "Specify replay window size";
+    }
+    leaf ip-comp {
+      type empty;
+      description
+        "Enables IPCOMP, which uses the IP payload compression
+         protocol to compress IP security (IPsec) packets
+         before encryption";
+    }
+
+    container local-peer {
+      description
+        "Specify the local peer IP address";
+      uses ip-address-grouping;
+    }
+    container remote-peer {
+      description
+        "Specify the remote peer IP address";
+      uses ip-address-grouping;
+    }
+    leaf sa-mode {
+      type ipsec-mode;
+      description
+        "SA Mode: tunnel or transport mode";
+    }
+    leaf security-protocol {
+      type ipsec-protocol;
+      description
+        "Security protocol of IPsec SA: Either AH or ESP.";
+    }
+    leaf sequence-number {
+      type uint64;
+      description
+        "Current sequence number of IPsec packet.";
+    }
+    leaf sequence-number-overflow-flag {
+      type boolean;
+      description
+        "The flag indicating whether overflow of the sequence
+         number counter should prevent transmission of additional
+         packets on the SA, or whether rollover is permitted.";
+    }
+    leaf path-mtu {
+      type uint16;
+      description
+        "maximum size of an IPsec packet that can be transmitted
+         without fragmentation";
+    }
+    container life-time {
+      leaf life-time-in-seconds {
+        type uint32;
+        description
+          "SA life time in seconds";
+      }
+      leaf remain-life-time-in-seconds {
+        type uint32;
+        description
+          "Remain SA life time in seconds";
+      }
+      leaf life-time-in-byte {
+        type uint32;
+        description
+          "SA life time in bytes";
+      }
+      leaf remain-life-time-in-byte {
+        type uint32;
+        description
+          "Remain SA life time in bytes";
+      }
+      description
+        "SA life time information";
+    }
+    leaf upper-protocol {
+      type string;
+      description
+        "Upper-layer protocol to be used";
+    }
+    leaf direction {
+      type ipsec-traffic-direction;
+      description
+        "It indicates whether the SA is inbound SA or
+         out bound SA.";
+    }
+    container source-address {
+      description
+        "Specify the source IP address and
+         port of protected traffic";
+      uses ip-address-grouping;
+      leaf port-number {
+        type uint32;
+        description
+          "port of protected traffic";
+      }
+    }
+    container destination-address {
+      description
+        "Specify the destination IP address and
+         port of protected traffic";
+      uses ip-address-grouping;
+      leaf port-number {
+        type uint32;
+        description
+          "port of protected traffic";
+      }
+    }
+    leaf nat-traversal-flag {
+      type boolean;
+      description
+        "Whether the SA is used to protect traffic that needs
+         nat traversal";
+    }
+    uses ipsec-sa-ah-grouping;
+    uses ipsec-sa-esp-grouping;
+  }
+
+
+  /* draft-wang-ipsecme-ike-yang-00 */
+  grouping ipsec-common-configuration {
+    choice df-flag {
+      default copy;
+      case set {
+        leaf set {
+          type empty;
+          description
+            "Set the df bit when encapsulate IPsec tunnel.";
+        }
+      }
+      case clear {
+        leaf clear {
+          type empty;
+          description
+            "Clear the df bit when encapsulate IPsec tunnel.";
+        }
+      }
+      case copy {
+        leaf copy {
+          type empty;
+          description
+            "Copy the inner IP header df bit.";
+        }
+      }
+      description
+        "It indicates how to process the df bit when encapsulate
+         IPsec tunnel.";
+    }
+    leaf stateful-frag-check {
+      type boolean;
+      default false;
+      description "Whether stateful fragment checking applies.";
+    }
+    leaf life-time-kb {
+      type uint32;
+      units "KB";
+      default 2000000;
+      description "IPsec SA Life time in KB.";
+    }
+    leaf life-time-second {
+      type uint32;
+      units "Second";
+      default 18400;
+      description "IPsec SA Life time in Seconds";
+    }
+    choice anti-replay {
+      default enable;
+      case enable {
+        leaf enable {
+          type empty;
+          description "Enable Anti-replay";
+        }
+        choice anti-replay-windows-size {
+          case size-32;
+          case size-64;
+          case size-128;
+          case size-256;
+          case size-512;
+          case size-1024;
+          default size-1024;
+          description "It indicate the size of anti-replay window";
+        }
+      }
+      case disable {
+        leaf disable {
+          type empty;
+          description "Disable Anti-replay";
+        }
+      }
+      description "Whether enable or disable anti-replay";
+    }
+    leaf inbound-dscp {
+      type uint16 {
+        range "0..63";
+      }
+      default 0;
+      description "Inbound DSCP value";
+    }
+    leaf outbound-dscp {
+      type uint16 {
+        range "0..63";
+      }
+      default 0;
+      description "Outbound DSCP value";
+    }
+    description "Common IPsec configurations";
+  }
+
+  /*--------------------*/
+  /* Configuration Data */
+  /*--------------------*/
+  container ikev1 {
+    if-feature ikev1;
+    description
+      "Configuration IPSec IKEv1";
+    /* The following is for <configure> */
+    list proposal {
+       key "name";
+       uses ike-proposal-grouping;
+       description
+         "Configure IKE proposal";
+    }
+    leaf keepalive {
+      type empty;
+      description
+        "Enables sending Dead Peer Detection (DPD) messages "+
+        "to Internet Key Exchange (IKE) peers.";
+    }
+    list policy {
+      key "name";
+      uses ike-policy-profile-grouping;
+      description
+        "Configure IKE Policy Profile.";
+    }
+  }
+
+  container ikev2 {
+    if-feature ikev2;
+    description
+      "Configuration IPSec IKEv2";
+    /* The following is for <configure> */
+    /* draft-wang-ipsecme-ike-yang-00 */
+    container ike-global-configuration {
+      if-feature ikev2-global;
+      description "Global IKE configurations";
+      uses ipsec-common-configuration;
+      leaf local-name {
+        type string;
+        description
+          "Global local name configuration, if it is not configed,
+           ip address will be used as default. If configing special
+           local name for special peer, it will overwrite the global
+           name configuration when negotion with that peer.";
+      }
+      leaf nat-keepalive-interval {
+        type uint16 {
+          range "5..300";
+        }
+        units "Seconds";
+        default 20;
+        description "Global nat keepalive interval";
+      }
+      leaf dpd-interval {
+        type uint16 {
+          range "10..3600";
+        }
+        units "Seconds";
+        default 30;
+        description "Global DPD interval";
+      }
+    }
+    container ike-peer {
+      if-feature ikev2-peer;
+      description "IKE peer information";
+      list ike-peer-entries {
+        key "peer-name";
+        description "IKE peer information";
+        leaf peer-name {
+          type string;
+          mandatory true;
+          description "Name of IKE peer";
+        }
+        leaf ike-proposal-number {
+          type ike-proposal-number-ref;
+          description "IKE proposal number referenced by IKE peer";
+        }
+        leaf PresharedKey {
+          type string;
+          description "Preshare key";
+        }
+        leaf nat-traversal {
+          type boolean;
+          default false;
+          description "Enable/Disable nat traversal";
+        }
+        choice local-id-type {
+          default ip;
+          case ip {
+            leaf ip {
+              type empty;
+              description "IP address";
+            }
+          }
+          case fqdn {
+            leaf fqdn {
+              type empty;
+              description "Fully Qualifed Domain name ";
+            }
+          }
+          case dn {
+            leaf dn {
+              type empty;
+              description "Domain name";
+            }
+          }
+          case user_fqdn {
+            leaf user_fqdn {
+              type empty;
+              description "User FQDN";
+            }
+          }
+          description "Local ID type";
+        }
+        leaf local-id {
+          type string;
+          description
+            "Local ID Name. When IP is used as local ID type,
+             it is ignored. If it is not configurated,
+             global local name will be used.";
+        }
+        leaf remote-id {
+          type "string";
+          description "ID of IKE peer";
+        }
+        leaf low-remote-address {
+          type inet:ip-address;
+          description "Low range of remote address";
+        }
+        leaf high-remote-address {
+          type inet:ip-address;
+          description "High range of remote address";
+        }
+        leaf certificate {
+          type string;
+          description "Certificate file name";
+        }
+        leaf auth-address-begin {
+          type inet:ip-address;
+          description
+            "The begin range of authenticated peer address";
+        }
+        leaf auth-address-end {
+          type inet:ip-address;
+          description
+            "The end range of authenticated peer address";
+        }
+      }
+    }//End of IKEPeerEntries
+
+
+    list proposal {
+       if-feature ikev2-proposal;
+       key "name";
+       uses ikev2-proposal-grouping;
+       description
+         "Configure IKEv2 proposal";
+    }
+    list policy {
+      if-feature ikev2-policy;
+      key "name";
+      uses ikev2-policy-profile-grouping;
+      description
+        "IKEv2 Policy Profile";
+    }
+  }
+
+  container ipsec {
+    if-feature ipsec;
+    description
+      "Configuration IPsec";
+    container sad {
+      if-feature ipsec-sad;
+      description
+        "Configure the IPSec Security Association Database (SAD)";
+      list sad-entries {
+        key "spi direction";
+        description
+          "Configure IPsec Security Association Database(SAD)";
+        uses ipsec-sa-grouping;
+      }
+    }
+    container proposal {
+      if-feature ipsec-proposal;
+      description
+        "IPSec Proposal Profile";
+      list ipsec-proposal {
+        key "name";
+        uses ipsec-proposal-grouping;
+        description
+          "Configure the IP Security (IPSec) proposal";
+      }
+    }
+    /*
+      TODO HC2VPP-399: modified spd container to list to support multiple spds for VPP
+    */
+    list spd {
+      key "spd-id";
+      if-feature ipsec-spd;
+      description
+        "List of Security Policy Databases (SPD)";
+      leaf spd-id {
+        type int32;
+      }
+      list spd-entries {
+        key "name";
+        ordered-by user;
+        uses ipsec-policy-grouping;
+        description
+          "Specify an IPSec policy name";
+      }
+    }
+    container pad {
+      description
+        "Configure Peer Authorization Database (PAD)";
+      list pad-entries {
+        key "pad-type pad-id";
+        ordered-by user;
+        uses identity-grouping;
+        description
+          "Peer Authorization Database (PAD)";
+        leaf pad-id {
+          type uint32;
+           description
+             "PAD identity";
+        }
+        leaf pad-type {
+          type pad-type-t;
+          description
+            " PAD type";
+        }
+        leaf ike-peer-name {
+          type string;
+          description
+            "IKE Peer Name";
+        }
+        container peer-authentication {
+          description
+            "Specify IKE peer authentication configuration";
+          leaf algorithm {
+            type ike-integrity-algorithm-t;
+            description
+              "Specify the authentication algorithm";
+          }
+          leaf preshared-key {
+            type empty;
+            description
+              "Use pre-shared key based authentication";
+          }
+          leaf rsa-signature {
+            type empty;
+            description
+              "Use signature based authentication by using
+               PKI certificates";
+          }
+        }
+      }
+    }
+  }
+
+
+
+  /*--------------------------*/
+  /* Operational State Data   */
+  /*--------------------------*/
+  grouping ike-proposal-state-components {
+    description
+      "IKE Proposal operational state";
+    list proposal {
+      if-feature ike-proposal-state;
+      description
+        "Operational data for IKE Proposal";
+      leaf name {
+        type string {
+          length "1..50";
+        }
+        description
+          "Name of the IKE proposal.";
+      }
+      leaf lifetime {
+        type uint32;
+        units "seconds";
+        description
+          "lifetime";
+      }
+      leaf encryption {
+        type ike-encryption-algorithm-t;
+        description
+          "Encryption algorithm";
+      }
+      leaf dh-group {
+        type diffie-hellman-group-t;
+        description
+          "Diffie-Hellman group.";
+      }
+      leaf authentication {
+        type ike-integrity-algorithm-t;
+        description
+          "authentication";
+      }
+    }
+  }
+
+  grouping ike-policy-state-grouping {
+    description
+      "IKE Policy State.";
+    list policy {
+      if-feature ike-policy-state;
+      description
+        "Operational data for IKE policy";
+      leaf name {
+        type string {
+          length "1..50";
+        }
+        description
+          "Name of the IKE Policy.";
+      }
+      leaf description {
+        type string;
+        description
+          "Description for IKE Policy.";
+      }
+      leaf mode {
+        type enumeration {
+          enum aggressive {
+            description
+              "Aggressive mode.";
+          }
+          enum main {
+            description
+              "Main mode.";
+          }
+        }
+        description
+          "IKE policy mode.";
+      }
+      leaf connection-type {
+        type connection-type-t;
+        description
+          "IKE policy connection type.";
+      }
+      leaf local-identity {
+        type inet:ipv4-address-no-zone;
+        description
+          "IP address of the local identity.";
+      }
+      leaf remote-identity {
+        type inet:ipv4-address-no-zone;
+        description
+          "IP address of the remote identity.";
+      }
+      leaf pre-shared-key {
+        type string;
+        description
+          "Pre-shared key";
+      }
+      leaf seq {
+        type uint32;
+        description
+          "sequence number";
+      }
+      leaf proposal {
+        type string;
+        description
+          "proposal name";
+      }
+    }
+  }
+
+  grouping ikev2-proposal-state-components {
+    description
+      "IKEv2 Operational state";
+    list proposal {
+      if-feature ikev2-proposal-state;
+      description
+        "IKEv2 proposal operational data";
+      leaf name {
+        type string;
+        description
+          "Name of IKEv2 Proposal.";
+      }
+      leaf pseudo-random-function {
+        type pseudo-random-function-t;
+        description
+          "Pseudo Random Function for IKEv2.";
+      }
+      leaf authentication {
+        type ike-integrity-algorithm-t;
+        description
+          "authentication";
+      }
+      leaf encryption {
+        type ike-encryption-algorithm-t;
+        description
+          "Encryption algorithm";
+      }
+      leaf dh-group {
+        type diffie-hellman-group-t;
+        mandatory true;
+        description
+          "Diffie-Hellman group.";
+      }
+    }
+  }
+
+  grouping ipsec-policy-state-grouping {
+    description
+      "IPSec operational state";
+    list policy {
+      if-feature ipsec-policy-state;
+      description
+        "IPSec policy operational data";
+      leaf name {
+        type string;
+        description
+          "IPSec Policy name.";
+      }
+      leaf anti-replay-window {
+        type uint32;
+        description
+          "replay window size";
+      }
+      leaf perfect-forward-secrecy {
+        type diffie-hellman-group-t;
+        description
+          "Diffie-Hellman group for perfect-forward-secrecy";
+      }
+      list seq {
+        description
+          "Sequence number";
+        leaf seq-id {
+          type uint32;
+          description
+            "Sequence number";
+        }
+        leaf proposal-name {
+          type string;
+          description
+            "IPSec proposal name";
+        }
+      }
+    }
+  }
+  grouping ipsec-proposal-state-grouping {
+    description
+      "IPSec proposal operational data";
+    list proposal {
+      if-feature ipsec-proposal-state;
+      description
+        "IPSec proposal operational data";
+      leaf name {
+        type string;
+        description
+          "IPSec Proposal name";
+      }
+      leaf ah {
+        type ike-integrity-algorithm-t;
+        description
+          "Authentication Header (AH).";
+      }
+      container esp {
+        description
+          "Encapsulating Security Payload (ESP).";
+        leaf authentication {
+          type ike-integrity-algorithm-t;
+          description
+            "ESP authentication";
+        }
+        leaf encryption {
+          type ike-encryption-algorithm-t;
+          description
+            "ESP encryption";
+        }
+      }
+      leaf ip-comp{
+        type empty;
+        description
+          "IPSec proposal IP-COMP which uses the IP Payload "+
+          "compression protocol to compress IP Security (IPSec) "+
+          "packets before encryption";
+      }
+      container lifetime {
+        description
+          "lifetime for IPSEC SAs";
+        leaf kbytes {
+          type uint32;
+          description
+            "lifetime kbytes for IPSEC SAs";
+
+        }
+        leaf seconds {
+          type uint32;
+          description
+            "lifetime seconds for IPSEC SAs";
+        }
+      }
+    }
+  }
+
+  grouping ipsec-alarms-state-grouping {
+    description
+      "IPSec alarms operational data";
+    leaf hold-down {
+      if-feature ipsec-alarms-state;
+      type uint32;
+      description
+        "Hold-down value";
+    }
+  }
+
+  grouping ipsec-sa-ah-state-grouping {
+    description
+      "IPSec SA's AH operational data";
+
+    leaf spi {
+      if-feature ipsec-sa-ah-state;
+      type uint32;
+      description
+        "Security Parameter Index (SPI) value";
+    }
+    leaf description {
+      if-feature ipsec-sa-ah-state;
+      type string;
+      description
+        "the description.";
+    }
+    leaf authentication-algorithm {
+      if-feature ipsec-sa-ah-state;
+      type ike-integrity-algorithm-t;
+      description
+        "Authentication algorithm";
+    }
+    leaf encryption-algorithm {
+      if-feature ipsec-sa-ah-state;
+      type ike-encryption-algorithm-t;
+      description
+        "Encryption algorithm";
+    }
+  }
+
+  grouping ipsec-sa-state-grouping {
+    description
+      "IPSec Security Association Operational data";
+    list sa {
+      if-feature ipsec-sa-state;
+      description
+        "IPSec SA operational data";
+      leaf name {
+        type string;
+        description
+          "Specify IPSec Security Association (SA) name";
+      }
+      leaf anti-replay-window {
+        type uint16;
+        description
+          "replay window size";
+      }
+      leaf ip-comp {
+        type empty;
+        description
+          "Enables IPCOMP, which uses the IP payload compression
+           protocol to compress IP security (IPsec) packets before
+           encryption";
+      }
+      uses ipsec-sa-ah-state-grouping;
+    }
+  }
+
+  /* draft-wang-ipsecme-ipsec-yang-00 */
+  grouping ipsec-tunnel-mode-info {
+    description
+      "common infomations when using IPsec tunnel mode";
+    leaf local-address {
+      if-feature ipsec-tunnel;
+      type string;
+      description
+        "Local address of IPsec tunnel mode";
+    }
+    leaf remote-address {
+      if-feature ipsec-tunnel;
+      type string;
+      description
+        "Remote address of IPsec tunnel mode";
+    }
+    leaf bypass-df {
+      if-feature ipsec-tunnel;
+      type enumeration {
+        enum "set" {
+          description
+            "Set the df bit";
+        }
+        enum "clear" {
+          description
+            "Clear the df bit";
+        }
+        enum "copy" {
+          description
+            "Copy the df bit from inner header";
+        }
+      }
+      description
+        "This flag indicates how to process tunnel mode df flag";
+    }
+    leaf dscp-flag {
+      if-feature ipsec-tunnel;
+      type boolean;
+      description
+        "This flag indicate whether bypass DSCP or map to
+         unprotected DSCP values (array) if needed to
+         restrict bypass of DSCP values.";
+    }
+    leaf stateful-frag-check-flag {
+      if-feature ipsec-tunnel;
+      type boolean;
+      description
+        "This flag indicates whether stateful fragment checking
+         will be used.";
+    }
+  }
+  grouping traffic-selector {
+    description
+      "IPsec traffic selector information";
+    leaf local-address-low {
+      if-feature ipsec-local-address-range;
+      type inet:ip-address;
+      description
+        "Low range of local address";
+    }
+    leaf local-address-high {
+      if-feature ipsec-local-address-range;
+      type inet:ip-address;
+      description
+        "High range of local address";
+    }
+    leaf remote-address-low {
+      if-feature ipsec-remote-address-range;
+      type inet:ip-address;
+      description
+        "Low range of remote address";
+    }
+    leaf remote-address-high {
+      if-feature ipsec-remote-address-range;
+      type inet:ip-address;
+      description
+        "High range of remote address";
+    }
+    leaf next-protocol-low {
+      if-feature ipsec-next-protocol-range;
+      type uint16;
+      description
+        "Low range of next protocol";
+    }
+    leaf next-protocol-high {
+      if-feature ipsec-next-protocol-range;
+      type uint16;
+      description
+        "High range of next protocol";
+    }
+    leaf local-port-low {
+      if-feature ipsec-local-port-range;
+      type inet:port-number;
+      description
+        "Low range of local port";
+    }
+    leaf local-port-high {
+      if-feature ipsec-local-port-range;
+      type inet:port-number;
+      description
+        "High range of local port";
+    }
+    leaf remote-port-high {
+      if-feature ipsec-remote-port-range;
+      type inet:port-number;
+      description
+        "Low range of remote port";
+    }
+    leaf remote-port-low {
+      if-feature ipsec-remote-port-range;
+      type inet:port-number;
+      description
+        "High range of remote port";
+    }
+  }
+  grouping ipsec-algorithm-info {
+    description
+      "IPsec algorithm information used by SPD and SAD";
+    leaf ah-auth-algorithm {
+      if-feature ipsec-ah-authentication;
+      type ipsec-authentication-algorithm;
+      description
+        "Authentication algorithm used by AH";
+    }
+    leaf esp-integrity-algorithm {
+      if-feature ipsec-esp-integrity;
+      type ipsec-authentication-algorithm;
+      description
+        "Integrity algorithm used by ESP";
+    }
+    leaf esp-encrypt-algorithm {
+      if-feature ipsec-esp-encrypt;
+      type ipsec-encryption-algorithm;
+      description
+        "Encryption algorithm used by ESP";
+    }
+  }
+  grouping ipsec-stat {
+    leaf inbound-packets {
+      if-feature ipsec-stat;
+      type uint64;
+      config false;
+      description "Inbound Packet count";
+    }
+    leaf outbound-packets {
+      if-feature ipsec-stat;
+      type uint64;
+      config false;
+      description "Outbound Packet count";
+    }
+    leaf inbound-bytes {
+      if-feature ipsec-stat;
+      type uint64;
+      config false;
+      description "Inbound Packet bytes";
+    }
+    leaf outbound-bytes {
+      if-feature ipsec-stat;
+      type uint64;
+      config false;
+      description "Outbound Packet bytes";
+    }
+    leaf inbound-drop-packets {
+      if-feature ipsec-stat;
+      type uint64;
+      config false;
+      description "Inbound dropped packets count";
+    }
+    leaf outbound-drop-packets {
+      if-feature ipsec-stat;
+      type uint64;
+      config false;
+      description "Outbound dropped packets count";
+    }
+    container dropped-packet-detail {
+      if-feature ipsec-stat;
+      description "The detail information of dropped packets";
+      leaf sa-non-exist {
+        type uint64;
+        config false;
+        description
+          "The dropped packets counts caused by SA non-exist.";
+      }
+      leaf queue-full {
+        type uint64;
+        config false;
+        description
+          "The dropped packets counts caused by full processing
+           queue";
+      }
+      leaf auth-failure {
+        type uint64;
+        config false;
+        description
+          "The dropped packets counts caused by authentication
+           failure";
+      }
+      leaf malform {
+        type uint64;
+        config false;
+        description "The dropped packets counts of malform";
+      }
+      leaf replay {
+        type uint64;
+        config false;
+        description "The dropped packets counts of replay";
+      }
+      leaf large-packet {
+        type uint64;
+        config false;
+        description "The dropped packets counts of too large";
+      }
+      leaf invalid-sa {
+        type uint64;
+        config false;
+        description "The dropped packets counts of invalid SA";
+      }
+      leaf policy-deny {
+        type uint64;
+        config false;
+        description
+          "The dropped packets counts of denyed by policy";
+      }
+      leaf other-reason {
+        type uint64;
+        config false;
+        description
+          "The dropped packets counts of other reason";
+      }
+    }
+    description "IPsec statistics information";
+  }
+
+
+  container ike-state {
+    if-feature ikev1-state;
+    config "false";
+    uses ike-proposal-state-components;
+    uses ike-policy-state-grouping;
+    description
+      "Contain the operational data for IKE.";
+  }
+  container ikev2-state {
+    if-feature ikev2-state;
+    config "false";
+    uses ikev2-proposal-state-components;
+    uses ike-policy-state-grouping;
+    description
+      "Contain the operational data for IKEv2.";
+  }
+  container ipsec-state {
+    if-feature ipsec-state;
+    config "false";
+    uses ipsec-policy-state-grouping;
+    uses ipsec-proposal-state-grouping;
+    uses ipsec-alarms-state-grouping;
+    uses ipsec-sa-state-grouping;
+    container redundancy {
+      if-feature ipsec-redundancy;
+      description
+        "Configure redundancy for IPSec";
+      leaf inter-chassis {
+        type empty;
+        description
+          "Set redundancy at chassis level";
+      }
+    }
+
+    description
+      "Contain the operational data for IPSec.";
+  }
+
+  /* draft-wang-ipsecme-ipsec-yang-00 */
+  container sad {
+    if-feature sad;
+    config false;
+    description
+      "The IPsec SA database";
+    list sad-entries {
+      key "spi security-protocol direction";
+      description
+        "The SA entries information";
+      leaf spi {
+        type ipsec-spi;
+        description
+          "Security parameter index of SA entry.";
+      }
+      leaf security-protocol {
+        type ipsec-protocol;
+        description
+          "Security protocol of IPsec SA.";
+      }
+      leaf direction {
+        type ipsec-traffic-direction;
+        description
+          "It indicates whether the SA is inbound SA or
+           out bound SA.";
+      }
+      leaf sa-type {
+        type enumeration {
+          enum "manual" {
+            description
+              "Manual IPsec SA";
+          }
+          enum "isakmp" {
+            description
+              "ISAKMP IPsec SA";
+          }
+        }
+        description
+          "It indicates whether the SA is created by manual
+           or by dynamic protocol.";
+      }
+      leaf sequence-number {
+        type uint64;
+        description
+          "Current sequence number of IPsec packet.";
+      }
+      leaf sequence-number-overflow-flag {
+        type boolean;
+        description
+          "The flag indicating whether overflow of the sequence
+           number counter should prevent transmission of additional
+           packets on the SA, or whether rollover is permitted.";
+      }
+      leaf anti-replay-enable-flag {
+        type boolean;
+        description
+          "It indicates whether anti-replay is enable or disable.";
+      }
+      leaf anti-replay-window-size {
+        type uint64;
+        description
+          "The size of anti-replay window.";
+      }
+      uses ipsec-algorithm-info;
+      container life-time {
+        leaf life-time-in-seconds {
+          type uint32;
+          description
+            "SA life time in seconds";
+        }
+        leaf remain-life-time-in-seconds {
+          type uint32;
+          description
+            "Remain SA life time in seconds";
+        }
+        leaf life-time-in-byte {
+          type uint32;
+          description
+            "SA life time in bytes";
+        }
+        leaf remain-life-time-in-byte {
+          type uint32;
+          description
+            "Remain SA life time in bytes";
+        }
+        description
+          "SA life time information";
+      }
+      leaf protocol-mode {
+        type ipsec-mode;
+        description
+          "It indicates whether tunnel mode or transport mode
+           will be used.";
+      }
+      container tunnel-mode-process-info {
+        when "../protocol-mode = 'tunnel'" {
+          description
+            "External information of SA when SA works in
+             tunnel mode.";
+        }
+        uses ipsec-tunnel-mode-info;
+        description
+          "External information of SA when SA works in
+           tunnel mode.";
+      }
+      leaf-list dscp {
+        type uint8 {
+          range "0..63";
+        }
+        description
+          "When traffic matchs SPD, the DSCP values used to
+           filter traffic";
+      }
+      leaf path-mtu {
+        type uint16;
+        description
+          "Path MTU valie";
+      }
+      leaf nat-traversal-flag {
+        type boolean;
+        description
+          "Whether the SA is used to protect traffic that needs
+           nat traversal";
+      }
+    }
+  }
+  container spd {
+    if-feature spd;
+    config false;
+    description
+      "IPsec security policy database information";
+    list spd-entries {
+      description
+        "IPsec SPD entry information";
+      list name {
+        description
+          "SPD name information.";
+        leaf name-type {
+          type ipsec-spd-name;
+          description
+            "SPD name type.";
+        }
+        leaf name-string {
+          when "../name-type = 'id_rfc_822_addr' or ../name-type =
+                'id_fqdn'" {
+            description
+              "when name type is id_rfc_822_addr or id_fqdn, the
+               name are saved in string";
+          }
+          type string;
+          description
+            "SPD name content";
+        }
+        leaf name-binary {
+          when "../name-type = 'id_der_asn1_dn' or ../name-type =
+                'id_key'" {
+            description
+              "when name type is id_der_asn1_dn or id_key, the name
+               are saved in binary";
+          }
+          type binary;
+          description
+            "SPD name content";
+        }
+      }
+      leaf pfp-flag {
+        type boolean;
+        description
+          "populate from packet flag";
+      }
+      list traffic-selector {
+        min-elements 1;
+        uses traffic-selector;
+        description
+          "Traffic selectors of SAD entry";
+      }
+      leaf operation {
+        type ipsec-spd-operation;
+        description
+          "It indicates how to process the traffic when it matches
+           the security policy.";
+      }
+      container protect-operation {
+        when "../operation = 'protect'" {
+          description
+            "How to protect the traffic when the SPD operation
+             is protect";
+        }
+        leaf spd-ipsec-mode {
+          type ipsec-mode;
+          description
+            "It indicates which mode is chosen when the traffic need
+            be protected by IPsec.";
+        }
+        leaf esn-flag {
+          type boolean;
+          description
+            "It indicates whether ESN is used.";
+        }
+        leaf spd-ipsec-protocol {
+          type ipsec-protocol;
+          description
+            "It indicates which protocol (AH or ESP) is chosen.";
+        }
+        container tunnel-mode-additional {
+          when "../spd-ipsec-mode = 'tunnel'" {
+            description
+              "Additional informations when choose tunnel mode";
+          }
+          uses ipsec-tunnel-mode-info;
+          description
+            "When use tunnel mode, the additional information of
+             SPD.";
+        }
+        list spd-algorithm {
+          min-elements 1;
+          uses ipsec-algorithm-info;
+          description
+            "Algorithms defined in SPD, ordered by decreasing
+             priority.";
+        }
+        description
+          "How to protect the traffic when the SPD operation is
+           protect";
+      }
+    }
+  }
+
+  container ipsec-global-statistics {
+    if-feature ipsec-global-stats;
+    config false;
+    description "IPsec global statistics";
+    container ipv4 {
+      description "IPsec statistics of IPv4";
+      uses ipsec-stat;
+    }
+    container ipv6 {
+      description "IPsec statistics of IPv6";
+      uses ipsec-stat;
+    }
+    container global {
+      description "IPsec statistics of global";
+      uses ipsec-stat;
+    }
+  }
+
+
+  /*--------------------*/
+  /* RPC                */
+  /*--------------------*/
+  rpc clear-ipsec-group {
+    if-feature clear-ipsec-group;
+    description
+      "RPC for clear ipsec states";
+    input {
+      leaf alarm-hold-down {
+        type uint8;
+        description
+          "IPSec alarm hold-down";
+      }
+      leaf ipsec-policy-name {
+        type leafref {
+          path "/eipsec:ipsec/eipsec:spd/"+
+               "eipsec:spd-entries/eipsec:name";
+        }
+        description
+          "IPSec Policy name.";
+      }
+    }
+  }
+
+  rpc clear-ike-group {
+    if-feature clear-ike-group;
+    description
+      "RPC for clear IKE states";
+    input {
+      leaf proposal {
+        type leafref {
+          path "/eipsec:ikev1/eipsec:proposal/"+
+               "eipsec:name";
+        }
+        description
+          "IPSec IKE Proposal name.";
+      }
+    }
+  }
+
+  rpc clear-ikev2-group {
+    if-feature clear-ikev2-group;
+    description
+      "RPC for clear IKEv2 states";
+    input {
+      leaf proposal {
+        type leafref {
+          path "/eipsec:ikev2/eipsec:proposal/"+
+               "eipsec:name";
+        }
+        description
+          "IPSec IKEv2 Proposal name.";
+      }
+    }
+  }
+
+  /* draft-wang-ipsecme-ipsec-yang-00 */
+  rpc reset-ipv4 {
+    if-feature reset-ipv4;
+    description "Reset IPsec IPv4 statistics";
+    input {
+      leaf ipv4 {
+        type empty;
+        description "Reset IPsec IPv4 statistics";
+      }
+    }
+    output {
+      leaf status {
+        type string;
+        description "Operation status";
+      }
+    }
+  }
+  rpc reset-ipv6 {
+    if-feature reset-ipv6;
+    description "Reset IPsec IPv6 statistics";
+    input {
+      leaf ipv6 {
+        type empty;
+        description "Reset IPsec IPv6 statistics";
+      }
+    }
+    output {
+      leaf status {
+        type string;
+        description "Operation status";
+      }
+    }
+  }
+  rpc reset-global {
+    if-feature reset-global;
+    description "Reset IPsec global statistics";
+    input {
+      leaf ipv6 {
+        type empty;
+        description "Reset IPsec global statistics";
+      }
+    }
+    output {
+      leaf status {
+        type string;
+        description "Operation status";
+      }
+    }
+  }
+
+  notification dpd-failure{
+    description "IKE peer DPD detect failure";
+    leaf peer-id {
+      type string;
+      description "Peer ID";
+    }
+  }
+
+  notification peer-authentication-failure {
+    if-feature peer-authentication-failure;
+    description "Peer authentication fail when negotication";
+    leaf peer-id {
+      type string;
+      description "The ID of remote peer";
+    }
+  }
+
+  notification ike-reauth-failure {
+    if-feature ike-reauth-failure;
+    description "IKE peer reauthentication fail";
+    leaf peer-id {
+      type string;
+      description "The ID of remote peer";
+    }
+  }
+
+  notification ike-rekey-failure {
+    if-feature ike-rekey-failure;
+    description "IKE SA rekey failure";
+    leaf peer-id {
+      type string;
+      description "The ID of remote peer";
+    }
+    leaf old-i-spi {
+      type uint64;
+      description "old SPI";
+    }
+    leaf old-r-spi {
+      type uint64;
+      description "old SPI";
+    }
+  }
+
+  notification ipsec-rekey-failure {
+    if-feature ipsec-rekey-failure;
+    description "IPsec SA rekey failure";
+    leaf peer-id {
+      type string;
+      description "The ID of remote peer";
+    }
+    leaf old-inbound-spi {
+      type ipsec-spi;
+      description "old inbound SPI";
+    }
+    leaf old-outbound-spi {
+      type ipsec-spi;
+      description "old outbound SPI";
+    }
+  }
+} /* module ericsson-ipsec */
new file mode 100644 (file)
index 0000000..72ade37
--- /dev/null
@@ -0,0 +1,147 @@
+module vpp-ipsec {
+  yang-version 1;
+  namespace "http://fd.io/hc2vpp/yang/vpp-ipsec";
+  prefix "vpp-ipsec";
+
+  import hc2vpp-ietf-ipsec {
+    prefix "hc2vpp-ietf-ipsec";
+  }
+
+  import ietf-inet-types {
+    prefix inet;
+  }
+
+  import yang-ext {
+    prefix "ext";
+  }
+
+  import ietf-interfaces {
+    prefix "if";
+  }
+
+  revision "2018-12-13" {
+    description "Initial revision of ipsec model";
+  }
+
+  grouping vpp-ipsec-spd-entry-grouping {
+    description
+      "common information when using IPsec tunnel mode";
+    leaf spi {
+      type int32;
+    }
+
+    leaf priority {
+      type int32;
+    }
+
+    leaf direction {
+      type hc2vpp-ietf-ipsec:ipsec-traffic-direction;
+    }
+
+    leaf is-ipv6 {
+      type boolean;
+    }
+
+    leaf operation {
+      type hc2vpp-ietf-ipsec:ipsec-spd-operation;
+    }
+
+    leaf protect-sa-id {
+      type int32;
+    }
+
+    leaf laddr-start {
+      type inet:ip-address;
+    }
+
+    leaf laddr-stop {
+      type inet:ip-address;
+    }
+
+    leaf raddr-start {
+      type inet:ip-address;
+    }
+
+    leaf raddr-stop {
+      type inet:ip-address;
+    }
+  }
+
+  grouping spd-interfaces-grouping {
+    container spd-interfaces {
+      list interface {
+        key "interface-ref";
+
+        leaf interface-ref {
+          type if:interface-ref;
+        }
+      }
+    }
+  }
+
+  grouping ikev2-policy-aug-grouping {
+    leaf certificate {
+      type string;
+      description "Local file with RSA signature";
+    }
+
+    list traffic-selectors {
+      key "ts-name";
+      description "List of traffic selectors of profile";
+      leaf ts-name {
+        type string;
+      }
+      uses hc2vpp-ietf-ipsec:traffic-selector;
+      leaf protocol {
+        type uint8;
+        description "Protocol. If zero not relevant.";
+      }
+    }
+  }
+
+  augment /hc2vpp-ietf-ipsec:ipsec/hc2vpp-ietf-ipsec:sad/hc2vpp-ietf-ipsec:sad-entries {
+    ext:augment-identifier "ipsec-sad-entries-augmentation";
+    leaf sa-id {
+      type int32;
+    }
+  }
+
+  augment /hc2vpp-ietf-ipsec:ikev2/hc2vpp-ietf-ipsec:ike-global-configuration {
+    ext:augment-identifier "ipsec-ike-global-conf-augmentation";
+    leaf local-key-file {
+      type string;
+      description "Local file with RSA signature";
+    }
+  }
+
+  augment /hc2vpp-ietf-ipsec:ikev2/hc2vpp-ietf-ipsec:policy {
+    ext:augment-identifier "ipsec-ikev2-policy-augmentation";
+      uses ikev2-policy-aug-grouping;
+  }
+
+  augment /hc2vpp-ietf-ipsec:ipsec/hc2vpp-ietf-ipsec:spd {
+    ext:augment-identifier "ipsec-spd-enabled-interfaces-augmentation";
+    uses spd-interfaces-grouping;
+  }
+
+  augment /hc2vpp-ietf-ipsec:ipsec/hc2vpp-ietf-ipsec:spd/hc2vpp-ietf-ipsec:spd-entries {
+    ext:augment-identifier "ipsec-spd-entries-augmentation";
+    uses vpp-ipsec-spd-entry-grouping;
+  }
+
+  augment /hc2vpp-ietf-ipsec:ipsec-state {
+    ext:augment-identifier "ipsec-state-spd-augmentation";
+    list spd {
+      key "spd-id";
+
+      leaf spd-id {
+        type int32;
+      }
+      list spd-entries {
+        uses vpp-ipsec-spd-entry-grouping;
+      }
+
+      uses spd-interfaces-grouping;
+    }
+  }
+}
diff --git a/ipsec/ipsec-impl/pom.xml b/ipsec/ipsec-impl/pom.xml
new file mode 100644 (file)
index 0000000..9cf3dd9
--- /dev/null
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2019 PANTHEON.tech.
+
+ 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.
+-->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>io.fd.hc2vpp.common</groupId>
+        <artifactId>vpp-impl-parent</artifactId>
+        <relativePath>../../vpp-common/vpp-impl-parent</relativePath>
+        <version>1.19.01-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>io.fd.hc2vpp.ipsec</groupId>
+    <artifactId>ipsec-impl</artifactId>
+    <name>${project.artifactId}</name>
+    <version>1.19.01-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>ipsec-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!--VPP common-->
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>translate-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>translate-spi</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.fd.honeycomb</groupId>
+            <artifactId>cfg-init</artifactId>
+        </dependency>
+
+        <!-- Translation -->
+        <dependency>
+            <groupId>io.fd.hc2vpp.common</groupId>
+            <artifactId>vpp-translate-utils</artifactId>
+        </dependency>
+
+        <!-- DI -->
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.jmob</groupId>
+            <artifactId>guice.conf</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.inject.extensions</groupId>
+            <artifactId>guice-multibindings</artifactId>
+        </dependency>
+        <!-- Testing dependencies-->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-all</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.inject.extensions</groupId>
+            <artifactId>guice-testlib</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.hc2vpp.common</groupId>
+            <artifactId>vpp-translate-test</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.fd.honeycomb.infra</groupId>
+            <artifactId>test-tools</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>RELEASE</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/IpsecModule.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/IpsecModule.java
new file mode 100644 (file)
index 0000000..36dd8ae
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Singleton;
+import com.google.inject.multibindings.Multibinder;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.hc2vpp.ipsec.read.IpsecReaderFactory;
+import io.fd.hc2vpp.ipsec.write.IpsecWriterFactory;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Module class instantiating IpSec plugin components.
+ */
+public class IpsecModule extends AbstractModule {
+
+    private static final Logger LOG = LoggerFactory.getLogger(IpsecModule.class);
+    private static final String SAD_ENTRIES_MAPPING = "sad-entries-mapping";
+
+    @Override
+    protected void configure() {
+        LOG.info("Installing IPSec module");
+
+        bind(MultiNamingContext.class).toInstance(new MultiNamingContext(SAD_ENTRIES_MAPPING, 1));
+        LOG.info("Injecting writers factories");
+        final Multibinder<WriterFactory> writerFactoryBinder = Multibinder.newSetBinder(binder(), WriterFactory.class);
+        writerFactoryBinder.addBinding().to(IpsecWriterFactory.class).in(Singleton.class);
+
+        LOG.info("Injecting readers factories");
+        final Multibinder<ReaderFactory> readerFactoryBinder = Multibinder.newSetBinder(binder(), ReaderFactory.class);
+        readerFactoryBinder.addBinding().to(IpsecReaderFactory.class).in(Singleton.class);
+
+        LOG.info("Module IPSec successfully configured");
+    }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecReaderFactory.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecReaderFactory.java
new file mode 100644 (file)
index 0000000..e148022
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.read;
+
+import com.google.common.collect.Sets;
+import com.google.inject.Inject;
+import io.fd.honeycomb.translate.impl.read.GenericInitListReader;
+import io.fd.honeycomb.translate.impl.read.GenericReader;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.Spd;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.spd.SpdEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.state.grouping.Sa;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Factory producing readers for IpSec plugin's data.
+ */
+public final class IpsecReaderFactory implements ReaderFactory {
+
+    private static final InstanceIdentifier<IpsecState> IPSEC_STATE_ID = InstanceIdentifier.create(IpsecState.class);
+    private FutureJVppCore vppApi;
+
+    @Inject
+    public IpsecReaderFactory(final FutureJVppCore vppApi) {
+        this.vppApi = vppApi;
+    }
+
+    @Override
+    public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) {
+        registry.subtreeAdd(Sets
+                .newHashSet(InstanceIdentifier.create(IpsecState.class).child(Sa.class),
+                        InstanceIdentifier.create(IpsecState.class).augmentation(IpsecStateSpdAugmentation.class)
+                                .child(Spd.class)), new GenericReader<>(IPSEC_STATE_ID,
+                new IpsecStateCustomizer(vppApi)));
+        registry.addStructuralReader(IPSEC_STATE_ID.augmentation(IpsecStateSpdAugmentation.class),
+                IpsecStateSpdAugmentationBuilder.class);
+        registry.subtreeAdd(Sets
+                        .newHashSet(InstanceIdentifier.create(Spd.class).child(SpdEntries.class)),
+                new GenericInitListReader<>(
+                        IPSEC_STATE_ID.augmentation(IpsecStateSpdAugmentation.class).child(Spd.class),
+                        new IpsecStateSpdCustomizer(vppApi)));
+    }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizer.java
new file mode 100644 (file)
index 0000000..4755c7a
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.read;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.Initialized;
+import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
+import io.fd.vpp.jvpp.core.dto.IpsecSaDetails;
+import io.fd.vpp.jvpp.core.dto.IpsecSaDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.IpsecSaDump;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.LinkedList;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentation;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeEncryptionAlgorithmT;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeIntegrityAlgorithmT;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.state.grouping.Sa;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.state.grouping.SaBuilder;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IpsecStateCustomizer extends FutureJVppCustomizer
+        implements JvppReplyConsumer, InitializingReaderCustomizer<IpsecState, IpsecStateBuilder>, Ipv4Translator,
+        Ipv6Translator {
+
+    private final DumpCacheManager<IpsecSaDetailsReplyDump, Void> ipsecSaDetailsReplyDumpManager;
+
+    public IpsecStateCustomizer(final FutureJVppCore vppApi) {
+        super(vppApi);
+        this.ipsecSaDetailsReplyDumpManager =
+                new DumpCacheManager.DumpCacheManagerBuilder<IpsecSaDetailsReplyDump, Void>()
+                        .withExecutor(new IpsecStateCustomizer.IpsecStateSaDetailsDumpExecutor(vppApi))
+                        .acceptOnly(IpsecSaDetailsReplyDump.class)
+                        .build();
+    }
+
+    @Nonnull
+    @Override
+    public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<IpsecState> id,
+                                                  @Nonnull final IpsecState readValue, @Nonnull final ReadContext ctx) {
+        return Initialized.create(id, readValue);
+    }
+
+    @Nonnull
+    @Override
+    public IpsecStateBuilder getBuilder(@Nonnull final InstanceIdentifier<IpsecState> id) {
+        return new IpsecStateBuilder();
+    }
+
+    @Override
+    public void readCurrentAttributes(@Nonnull final InstanceIdentifier<IpsecState> id,
+                                      @Nonnull final IpsecStateBuilder builder,
+                                      @Nonnull final ReadContext ctx) throws ReadFailedException {
+        final Optional<IpsecSaDetailsReplyDump> dumpSa =
+                ipsecSaDetailsReplyDumpManager.getDump(id, ctx.getModificationCache());
+
+        if (dumpSa.isPresent()) {
+            LinkedList<Sa> listSa = new LinkedList<>();
+            IpsecSaDetailsReplyDump reply = dumpSa.get();
+            for (IpsecSaDetails details : reply.ipsecSaDetails) {
+                SaBuilder saBuilder = new SaBuilder();
+                saBuilder.setSpi(Integer.toUnsignedLong(details.spi))
+                        .setAntiReplayWindow(Long.valueOf(details.replayWindow).intValue())
+                        .setAuthenticationAlgorithm(IkeIntegrityAlgorithmT.forValue(details.integAlg))
+                        .setEncryptionAlgorithm(IkeEncryptionAlgorithmT.forValue(details.cryptoAlg));
+                listSa.add(saBuilder.build());
+            }
+            builder.setSa(listSa);
+        }
+    }
+
+    @Override
+    public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final IpsecState readValue) {
+        IpsecStateBuilder ipsecParentBuilder = (IpsecStateBuilder) parentBuilder;
+        ipsecParentBuilder.setHoldDown(readValue.getHoldDown())
+                .setPolicy(readValue.getPolicy())
+                .setProposal(readValue.getProposal())
+                .setRedundancy(readValue.getRedundancy())
+                .setSa(readValue.getSa())
+                .addAugmentation(IpsecStateSpdAugmentation.class,
+                        readValue.augmentation(IpsecStateSpdAugmentation.class));
+    }
+
+    static final class IpsecStateSaDetailsDumpExecutor
+            implements EntityDumpExecutor<IpsecSaDetailsReplyDump, Void>, JvppReplyConsumer {
+
+        private final FutureJVppCore jvpp;
+
+        IpsecStateSaDetailsDumpExecutor(final FutureJVppCore jvpp) {
+            this.jvpp = jvpp;
+        }
+
+        @Nonnull
+        @Override
+        public IpsecSaDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params)
+                throws ReadFailedException {
+            IpsecSaDump dump = new IpsecSaDump();
+            dump.saId = -1;
+            return getReplyForRead(jvpp.ipsecSaDump(dump).toCompletableFuture(), identifier);
+        }
+    }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizer.java
new file mode 100644 (file)
index 0000000..45f54cd
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.read;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.Initialized;
+import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdDetails;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdDump;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdsDetails;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdsDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdsDump;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.Spd;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.SpdBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.SpdKey;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.spd.SpdEntries;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.spd.SpdEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecSpdOperation;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecTrafficDirection;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IpsecStateSpdCustomizer extends FutureJVppCustomizer
+        implements JvppReplyConsumer, InitializingListReaderCustomizer<Spd, SpdKey, SpdBuilder>, Ipv4Translator,
+        Ipv6Translator {
+
+    private static final Logger LOG = LoggerFactory.getLogger(IpsecStateSpdCustomizer.class);
+    private final DumpCacheManager<IpsecSpdDetailsReplyDump, Void> ipsecSpdDetailsReplyDumpManager;
+    private final DumpCacheManager<IpsecSpdsDetailsReplyDump, Void> ipsecSpdsReplyDumpManager;
+
+    public IpsecStateSpdCustomizer(final FutureJVppCore vppApi) {
+        super(vppApi);
+        IpsecStateSpdsReplyDumpExecutor spdsExecutor =
+                new IpsecStateSpdCustomizer.IpsecStateSpdsReplyDumpExecutor(vppApi);
+        this.ipsecSpdsReplyDumpManager = new DumpCacheManager.DumpCacheManagerBuilder<IpsecSpdsDetailsReplyDump, Void>()
+                .withExecutor(spdsExecutor)
+                .acceptOnly(IpsecSpdsDetailsReplyDump.class)
+                .build();
+
+        this.ipsecSpdDetailsReplyDumpManager =
+                new DumpCacheManager.DumpCacheManagerBuilder<IpsecSpdDetailsReplyDump, Void>()
+                        .withExecutor(
+                                new IpsecStateSpdCustomizer.IpsecStateSpdDetailsDumpExecutor(vppApi, spdsExecutor))
+                        .acceptOnly(IpsecSpdDetailsReplyDump.class)
+                        .build();
+    }
+
+    @Nonnull
+    @Override
+    public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<Spd> id,
+                                                  @Nonnull final Spd readValue,
+                                                  @Nonnull final ReadContext ctx) {
+        return Initialized.create(id, readValue);
+    }
+
+    @Nonnull
+    @Override
+    public SpdBuilder getBuilder(@Nonnull final InstanceIdentifier<Spd> id) {
+        return new SpdBuilder();
+    }
+
+    @Override
+    public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final SpdBuilder builder,
+                                      @Nonnull final ReadContext ctx) throws ReadFailedException {
+        SpdKey key = id.firstKeyOf(Spd.class);
+        builder.withKey(key);
+        builder.setSpdId(key.getSpdId());
+        Optional<IpsecSpdDetailsReplyDump> spdDump =
+                ipsecSpdDetailsReplyDumpManager.getDump(id, ctx.getModificationCache());
+        if (spdDump.isPresent()) {
+            List<SpdEntries> spdEntries =
+                    spdDump.get().ipsecSpdDetails.stream().map(details -> translateDetailToEntry(details))
+                            .collect(Collectors.toList());
+            builder.setSpdEntries(spdEntries);
+        }
+    }
+
+    @Nonnull
+    @Override
+    public List<SpdKey> getAllIds(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final ReadContext context)
+            throws ReadFailedException {
+        List<SpdKey> spdKeys = new LinkedList<>();
+        Optional<IpsecSpdsDetailsReplyDump> spdsDump =
+                ipsecSpdsReplyDumpManager.getDump(id, context.getModificationCache());
+        if (spdsDump.isPresent()) {
+            spdKeys = spdsDump.get().ipsecSpdsDetails.stream().map(details -> new SpdKey(details.spdId))
+                    .collect(Collectors.toList());
+        }
+
+        LOG.debug("SPDs found in VPP: {}", spdKeys);
+        return spdKeys;
+    }
+
+    @Override
+    public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final List<Spd> readData) {
+        ((IpsecStateSpdAugmentationBuilder) builder).setSpd(readData);
+    }
+
+    private SpdEntries translateDetailToEntry(final IpsecSpdDetails details) {
+
+        SpdEntriesBuilder builder = new SpdEntriesBuilder();
+        builder.setDirection(IpsecTrafficDirection.forValue(details.isOutbound))
+                .setIsIpv6(ByteDataTranslator.INSTANCE.byteToBoolean(details.isIpv6))
+                .setPriority(details.priority);
+        switch (details.policy) {
+            case 0:
+                builder.setOperation(IpsecSpdOperation.Bypass);
+                break;
+            case 1:
+                builder.setOperation(IpsecSpdOperation.Discard);
+                break;
+            case 3:
+                builder.setOperation(IpsecSpdOperation.Protect);
+                builder.setProtectSaId(details.saId);
+                break;
+        }
+
+        if (builder.isIsIpv6()) {
+            processIpv6AddressRanges(builder, details);
+        } else {
+            processIpv4AddressRanges(builder, details);
+        }
+
+        return builder.build();
+    }
+
+    private void processIpv4AddressRanges(final SpdEntriesBuilder builder, final IpsecSpdDetails details) {
+        if (details.localStartAddr != null && details.localStartAddr.length > 0) {
+            builder.setLaddrStart(IpAddressBuilder.getDefaultInstance(
+                    new IpAddressNoZone(arrayToIpv4AddressNoZone(details.localStartAddr)).stringValue()));
+        }
+        if (details.localStopAddr != null && details.localStopAddr.length > 0) {
+            builder.setLaddrStop(IpAddressBuilder.getDefaultInstance(
+                    new IpAddressNoZone(arrayToIpv4AddressNoZone(details.localStopAddr)).stringValue()));
+        }
+        if (details.remoteStartAddr != null && details.remoteStartAddr.length > 0) {
+            builder.setRaddrStart(IpAddressBuilder.getDefaultInstance(
+                    new IpAddressNoZone(arrayToIpv4AddressNoZone(details.remoteStartAddr)).stringValue()));
+        }
+        if (details.remoteStopAddr != null && details.remoteStopAddr.length > 0) {
+            builder.setRaddrStop(IpAddressBuilder.getDefaultInstance(
+                    new IpAddressNoZone(arrayToIpv4AddressNoZone(details.remoteStopAddr)).stringValue()));
+        }
+    }
+
+    private void processIpv6AddressRanges(final SpdEntriesBuilder builder, final IpsecSpdDetails details) {
+        if (details.localStartAddr != null && details.localStartAddr.length > 0) {
+            builder.setLaddrStart(IpAddressBuilder.getDefaultInstance(
+                    new IpAddressNoZone(arrayToIpv6AddressNoZone(details.localStartAddr)).stringValue()));
+        }
+        if (details.localStopAddr != null && details.localStopAddr.length > 0) {
+            builder.setLaddrStop(IpAddressBuilder.getDefaultInstance(
+                    new IpAddressNoZone(arrayToIpv6AddressNoZone(details.localStopAddr)).stringValue()));
+        }
+        if (details.remoteStartAddr != null && details.remoteStartAddr.length > 0) {
+            builder.setRaddrStart(IpAddressBuilder.getDefaultInstance(
+                    new IpAddressNoZone(arrayToIpv6AddressNoZone(details.remoteStartAddr)).stringValue()));
+        }
+        if (details.remoteStopAddr != null && details.remoteStopAddr.length > 0) {
+            builder.setRaddrStop(IpAddressBuilder.getDefaultInstance(
+                    new IpAddressNoZone(arrayToIpv6AddressNoZone(details.remoteStopAddr)).stringValue()));
+        }
+    }
+
+    public static class IpsecStateSpdDetailsDumpExecutor
+            implements EntityDumpExecutor<IpsecSpdDetailsReplyDump, Void>, JvppReplyConsumer {
+        private FutureJVppCore jvpp;
+        private IpsecStateSpdsReplyDumpExecutor spdsDumpExecutor;
+
+        public IpsecStateSpdDetailsDumpExecutor(
+                final FutureJVppCore vppApi, final IpsecStateSpdsReplyDumpExecutor spdsDumpExecutor) {
+            this.jvpp = vppApi;
+            this.spdsDumpExecutor = spdsDumpExecutor;
+        }
+
+        @Nonnull
+        @Override
+        public IpsecSpdDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params)
+                throws ReadFailedException {
+            IpsecSpdDetailsReplyDump fullReplyDump = new IpsecSpdDetailsReplyDump();
+            fullReplyDump.ipsecSpdDetails = new LinkedList<>();
+
+            Optional<IpsecSpdsDetailsReplyDump> spdsReply =
+                    Optional.of(spdsDumpExecutor.executeDump(identifier, params));
+            IpsecSpdsDetailsReplyDump spdDump = spdsReply.get();
+            for (IpsecSpdsDetails spdsDetail : spdDump.ipsecSpdsDetails) {
+                IpsecSpdDump dump = new IpsecSpdDump();
+                dump.spdId = spdsDetail.spdId;
+                dump.saId = -1;
+                IpsecSpdDetailsReplyDump reply =
+                        getReplyForRead(jvpp.ipsecSpdDump(dump).toCompletableFuture(), identifier);
+                fullReplyDump.ipsecSpdDetails.addAll(reply.ipsecSpdDetails);
+            }
+
+            return fullReplyDump;
+        }
+    }
+
+    private class IpsecStateSpdsReplyDumpExecutor implements EntityDumpExecutor<IpsecSpdsDetailsReplyDump, Void> {
+        private final FutureJVppCore jvpp;
+
+        public IpsecStateSpdsReplyDumpExecutor(
+                final FutureJVppCore vppApi) {
+            this.jvpp = vppApi;
+        }
+
+        @Nonnull
+        @Override
+        public IpsecSpdsDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params)
+                throws ReadFailedException {
+            return getReplyForRead(jvpp.ipsecSpdsDump(new IpsecSpdsDump()).toCompletableFuture(), identifier);
+        }
+    }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizer.java
new file mode 100644 (file)
index 0000000..6886b9b
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.write;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.Ikev2SetLocalKey;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkeGlobalConfAugmentation;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.IkeGlobalConfiguration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class Ikev2GlobalConfigurationCustomizer extends FutureJVppCustomizer
+        implements WriterCustomizer<IkeGlobalConfiguration>, JvppReplyConsumer {
+    public Ikev2GlobalConfigurationCustomizer(final FutureJVppCore vppApi) {
+        super(vppApi);
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<IkeGlobalConfiguration> id,
+                                       @Nonnull final IkeGlobalConfiguration dataAfter,
+                                       @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        IpsecIkeGlobalConfAugmentation fileAUg = dataAfter.augmentation(IpsecIkeGlobalConfAugmentation.class);
+        if (fileAUg != null) {
+            if (fileAUg.getLocalKeyFile() != null) {
+                Ikev2SetLocalKey request = new Ikev2SetLocalKey();
+                request.keyFile = fileAUg.getLocalKeyFile().getBytes();
+                getReplyForWrite(getFutureJVpp().ikev2SetLocalKey(request).toCompletableFuture(), id);
+            }
+        }
+    }
+
+    @Override
+    public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<IkeGlobalConfiguration> id,
+                                        @Nonnull final IkeGlobalConfiguration dataBefore,
+                                        @Nonnull final IkeGlobalConfiguration dataAfter,
+                                        @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        writeCurrentAttributes(id, dataAfter, writeContext);
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<IkeGlobalConfiguration> id,
+                                        @Nonnull final IkeGlobalConfiguration dataBefore,
+                                        @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        // VPP doesn't support deletion of local key file
+    }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizer.java
new file mode 100644 (file)
index 0000000..300ea6b
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.write;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+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.Ikev2ProfileAddDel;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetAuth;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetTs;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.nio.ByteBuffer;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkev2PolicyAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ikev2.policy.aug.grouping.TrafficSelectors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeGeneralPolicyProfileGrouping;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.PolicyKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.policy.profile.grouping.Authentication;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class Ikev2PolicyCustomizer extends FutureJVppCustomizer
+        implements ListWriterCustomizer<Policy, PolicyKey>, JvppReplyConsumer, ByteDataTranslator, Ipv4Translator {
+
+    public Ikev2PolicyCustomizer(final FutureJVppCore vppApi) {
+        super(vppApi);
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> id, @Nonnull final Policy dataAfter,
+                                       @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        final Ikev2ProfileAddDel request = new Ikev2ProfileAddDel();
+        request.isAdd = BYTE_TRUE;
+        request.name = dataAfter.getName().getBytes();
+        getReplyForWrite(getFutureJVpp().ikev2ProfileAddDel(request).toCompletableFuture(), id);
+        addAuthorization(dataAfter, id);
+        addTrafficSelectors(dataAfter, id);
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> id, @Nonnull final Policy dataBefore,
+                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        final Ikev2ProfileAddDel request = new Ikev2ProfileAddDel();
+        request.isAdd = BYTE_FALSE;
+        request.name = dataBefore.getName().getBytes();
+        getReplyForWrite(getFutureJVpp().ikev2ProfileAddDel(request).toCompletableFuture(), id);
+    }
+
+    @Override
+    public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> id, @Nonnull final Policy dataBefore,
+                                        @Nonnull final Policy dataAfter, @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        addAuthorization(dataAfter, id);
+        addTrafficSelectors(dataAfter, id);
+    }
+
+    private void addTrafficSelectors(final Policy dataAfter, final InstanceIdentifier<Policy> id)
+            throws WriteFailedException {
+        IpsecIkev2PolicyAugmentation aug = dataAfter.augmentation(IpsecIkev2PolicyAugmentation.class);
+        if (aug == null) {
+            return;
+        }
+        if (aug.getTrafficSelectors() != null) {
+            for (TrafficSelectors selector : aug.getTrafficSelectors()) {
+                Ikev2ProfileSetTs addTsRequest = new Ikev2ProfileSetTs();
+                if (selector.getLocalAddressHigh() != null && selector.getLocalAddressLow() != null) {
+                    addTsRequest.isLocal = BYTE_TRUE;
+                    addTsRequest.startAddr = ByteBuffer
+                            .wrap(ipv4AddressNoZoneToArray(selector.getLocalAddressLow().getIpv4Address().getValue()))
+                            .getInt();
+                    addTsRequest.endAddr = ByteBuffer
+                            .wrap(ipv4AddressNoZoneToArray(selector.getLocalAddressHigh().getIpv4Address().getValue()))
+                            .getInt();
+                    if (selector.getLocalPortHigh() != null && selector.getLocalPortLow() != null) {
+                        addTsRequest.startPort = selector.getLocalPortLow().getValue().shortValue();
+                        addTsRequest.endPort = selector.getLocalPortHigh().getValue().shortValue();
+                    }
+                } else if (selector.getRemoteAddressHigh() != null && selector.getRemoteAddressLow() != null) {
+                    addTsRequest.isLocal = BYTE_FALSE;
+                    addTsRequest.startAddr = ByteBuffer
+                            .wrap(ipv4AddressNoZoneToArray(selector.getRemoteAddressLow().getIpv4Address().getValue()))
+                            .getInt();
+                    addTsRequest.endAddr = ByteBuffer
+                            .wrap(ipv4AddressNoZoneToArray(selector.getRemoteAddressHigh().getIpv4Address().getValue()))
+                            .getInt();
+                    if (selector.getRemotePortHigh() != null && selector.getRemotePortLow() != null) {
+                        addTsRequest.startPort = selector.getRemotePortLow().getValue().shortValue();
+                        addTsRequest.endPort = selector.getRemotePortHigh().getValue().shortValue();
+                    }
+                }
+                if (selector.getProtocol() != null) {
+                    addTsRequest.proto = selector.getProtocol().byteValue();
+                }
+                if (dataAfter.getName() != null) {
+                    addTsRequest.name = dataAfter.getName().getBytes();
+                }
+                getReplyForWrite(getFutureJVpp().ikev2ProfileSetTs(addTsRequest).toCompletableFuture(), id);
+            }
+        }
+    }
+
+    private void addAuthorization(final Policy data, final InstanceIdentifier<Policy> id)
+            throws WriteFailedException {
+        Authentication auth = data.getAuthentication();
+        if (auth != null) {
+            if (auth.isPresharedKey() != null && data.getPreSharedKey() != null) {
+                setProfilePreSharedKeyAuth(data.key().getName(), data.getPreSharedKey(), id);
+            } else if (auth.isRsaSignature() != null) {
+                IpsecIkev2PolicyAugmentation aug = data.augmentation(IpsecIkev2PolicyAugmentation.class);
+                if (aug != null && aug.getCertificate() != null) {
+                    setProfileRSAAuth(data.key().getName(), aug.getCertificate(), id);
+                }
+            }
+        }
+    }
+
+    private void setProfileRSAAuth(final String name, final String fileName, final InstanceIdentifier<Policy> id)
+            throws WriteFailedException {
+        Ikev2ProfileSetAuth request = new Ikev2ProfileSetAuth();
+        request.name = name.getBytes();
+        request.data = fileName.getBytes();
+        request.authMethod = BYTE_TRUE;
+        getReplyForWrite(getFutureJVpp().ikev2ProfileSetAuth(request).toCompletableFuture(), id);
+    }
+
+    private void setProfilePreSharedKeyAuth(final String name,
+                                            final IkeGeneralPolicyProfileGrouping.PreSharedKey preSharedKey,
+                                            final InstanceIdentifier<Policy> id) throws WriteFailedException {
+        final Ikev2ProfileSetAuth request = new Ikev2ProfileSetAuth();
+        request.authMethod = BYTE_FALSE;
+        if (preSharedKey.getHexString() != null) {
+            request.isHex = BYTE_TRUE;
+        }
+        request.data = preSharedKey.stringValue().getBytes();
+        request.name = name.getBytes();
+        getReplyForWrite(getFutureJVpp().ikev2ProfileSetAuth(request).toCompletableFuture(), id);
+    }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizer.java
new file mode 100644 (file)
index 0000000..4c11f16
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.write;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetId;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.identity.FqdnString;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.identity.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.identity.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.identity.Rfc822AddressString;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.Identity;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class Ikev2PolicyIdentityCustomizer extends FutureJVppCustomizer
+        implements WriterCustomizer<Identity>, JvppReplyConsumer, ByteDataTranslator, Ipv4Translator, Ipv6Translator {
+
+    public Ikev2PolicyIdentityCustomizer(final FutureJVppCore vppApi) {
+        super(vppApi);
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Identity> id,
+                                       @Nonnull final Identity dataAfter,
+                                       @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        String name = id.firstKeyOf(Policy.class).getName();
+        if (dataAfter.getLocal() != null) {
+            setProfileId(id, name, dataAfter.getLocal().getIdentity(), true);
+        }
+
+        if (dataAfter.getRemote() != null) {
+            setProfileId(id, name, dataAfter.getRemote().getIdentity(), false);
+        }
+    }
+
+    @Override
+    public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Identity> id,
+                                        @Nonnull final Identity dataBefore,
+                                        @Nonnull final Identity dataAfter, @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        writeCurrentAttributes(id, dataAfter, writeContext);
+    }
+
+    private void setProfileId(final InstanceIdentifier<Identity> id,
+                              final String profileName,
+                              final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.Identity data,
+                              final boolean isLocalId) throws WriteFailedException {
+        final Ikev2ProfileSetId request = new Ikev2ProfileSetId();
+        request.name = profileName.getBytes();
+        transformIdentityToRequest(data, request);
+        request.isLocal = isLocalId
+                ? BYTE_TRUE
+                : BYTE_FALSE;
+        getReplyForWrite(getFutureJVpp().ikev2ProfileSetId(request).toCompletableFuture(), id);
+    }
+
+    private void transformIdentityToRequest(
+            final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.Identity
+                    identityData, final Ikev2ProfileSetId request) {
+        if (identityData instanceof Ipv4Address) {
+            request.idType = 1;
+            request.data = ipv4AddressNoZoneToArray(((Ipv4Address) identityData).getIpv4Address().getValue());
+        } else if (identityData instanceof FqdnString) {
+            request.idType = 2;
+            request.data = ((FqdnString) identityData).getFqdnString().getValue().getBytes();
+        } else if (identityData instanceof Rfc822AddressString) {
+            request.idType = 3;
+            request.data = ((Rfc822AddressString) identityData).getRfc822AddressString().getBytes();
+        } else if (identityData instanceof Ipv6Address) {
+            request.idType = 5;
+            request.data = ipv6AddressNoZoneToArray(((Ipv6Address) identityData).getIpv6Address());
+        }
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Identity> id,
+                                        @Nonnull final Identity dataBefore,
+                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        // VPP doesn't support deletion of Ikev2 Profile ID
+    }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizer.java
new file mode 100644 (file)
index 0000000..d7bbee3
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.write;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+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.IpsecSadAddDelEntry;
+import io.fd.vpp.jvpp.core.dto.IpsecSadAddDelEntryReply;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSadEntriesAugmentation;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ip.address.grouping.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ip.address.grouping.ip.address.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ip.address.grouping.ip.address.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.Ah;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.AuthenticationAlgorithm;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.Esp;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.HmacMd596;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.HmacSha196;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.EncryptionAlgorithm;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes128Cbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes192Cbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes256Cbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.DesCbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntriesKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IpsecSadEntryCustomizer extends FutureJVppCustomizer
+        implements ListWriterCustomizer<SadEntries, SadEntriesKey>,
+        JvppReplyConsumer, ByteDataTranslator, Ipv6Translator, Ipv4Translator {
+
+    private static final Logger LOG = LoggerFactory.getLogger(IpsecSadEntryCustomizer.class);
+    private MultiNamingContext sadEntryMapping;
+
+    IpsecSadEntryCustomizer(final FutureJVppCore vppApi, final MultiNamingContext sadEntryMapping) {
+        super(vppApi);
+        this.sadEntryMapping = sadEntryMapping;
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<SadEntries> id,
+                                       @Nonnull final SadEntries dataAfter,
+                                       @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        addDelEntry(id, dataAfter, writeContext, true);
+    }
+
+    @Override
+    public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<SadEntries> id,
+                                        @Nonnull final SadEntries dataBefore,
+                                        @Nonnull final SadEntries dataAfter, @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        writeCurrentAttributes(id, dataAfter, writeContext);
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<SadEntries> id,
+                                        @Nonnull final SadEntries dataBefore,
+                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        addDelEntry(id, dataBefore, writeContext, false);
+    }
+
+    private void addDelEntry(final InstanceIdentifier<SadEntries> id,
+                             final SadEntries dataAfter,
+                             final WriteContext writeContext, boolean adding) throws WriteFailedException {
+        final IpsecSadAddDelEntry entry = new IpsecSadAddDelEntry();
+        IpsecSadEntriesAugmentation augment = dataAfter.augmentation(IpsecSadEntriesAugmentation.class);
+        if (augment != null && augment.getSaId() != null) {
+            entry.sadId = augment.getSaId();
+        }
+        if (dataAfter.getSpi() != null) {
+            entry.spi = dataAfter.getSpi().intValue();
+        }
+        if (dataAfter.getAntiReplayWindow() != null) {
+            entry.useAntiReplay = dataAfter.getAntiReplayWindow() > 0
+                    ? BYTE_TRUE
+                    : BYTE_FALSE;
+        }
+
+        if (dataAfter.getSaMode() != null) {
+            entry.isTunnel = Integer.valueOf(dataAfter.getSaMode().getIntValue()).byteValue();
+        }
+        entry.isAdd = adding
+                ? ByteDataTranslator.BYTE_TRUE
+                : ByteDataTranslator.BYTE_FALSE;
+        if (dataAfter.getEsp() != null) {
+            entry.protocol = 1;
+            fillEspAuthentication(entry, dataAfter.getEsp());
+            fillEspEncryption(entry, dataAfter.getEsp());
+
+        } else if (dataAfter.getAh() != null) {
+            entry.protocol = 0;
+            fillAhAuthentication(entry, dataAfter.getAh());
+        }
+
+        fillAddresses(entry, dataAfter);
+
+        LOG.debug("IPSec config change id={} request={}", id, entry);
+        final CompletionStage<IpsecSadAddDelEntryReply> ipsecSadEntryAddDellReplyFuture =
+                getFutureJVpp().ipsecSadAddDelEntry(entry);
+        getReplyForWrite(ipsecSadEntryAddDellReplyFuture.toCompletableFuture(), id);
+        if (adding) {
+            sadEntryMapping.addChild(dataAfter.key().getDirection().getName(), entry.sadId,
+                    String.valueOf(dataAfter.key().getSpi()), writeContext.getMappingContext());
+        } else {
+            sadEntryMapping
+                    .removeChild(dataAfter.key().getDirection().getName(), String.valueOf(dataAfter.key().getSpi()),
+                            writeContext.getMappingContext());
+        }
+    }
+
+    private void fillAhAuthentication(IpsecSadAddDelEntry targetEntry, Ah data) {
+        //0 = None, 1 = MD5-96, 2 = SHA1-96, 3 = SHA-256, 4 = SHA-384, 5=SHA-512
+        AuthenticationAlgorithm authAlg = data.getAuthenticationAlgorithm();
+        if (authAlg != null) {
+            String integKey;
+            if (authAlg instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacMd596) {
+                integKey =
+                        ((org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacMd596) authAlg)
+                                .getHmacMd596().getKeyStr().stringValue();
+                targetEntry.integrityAlgorithm = 1;
+            } else if (authAlg instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacSha196) {
+                integKey =
+                        ((org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacSha196) authAlg)
+                                .getHmacSha196().getKeyStr().stringValue();
+                targetEntry.integrityAlgorithm = 2;
+            } else {
+                targetEntry.integrityAlgorithm = 0;
+                return;
+            }
+            targetEntry.integrityKey = integKey.getBytes();
+        }
+    }
+
+    private void fillEspAuthentication(IpsecSadAddDelEntry targetEntry, Esp data) {
+        //0 = None, 1 = MD5-96, 2 = SHA1-96, 3 = SHA-256, 4 = SHA-384, 5=SHA-512
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Authentication
+                authAlg = data.getAuthentication();
+        if (authAlg != null) {
+            String integKey;
+            if (authAlg.getAuthenticationAlgorithm() instanceof HmacMd596) {
+                integKey = ((HmacMd596) authAlg.getAuthenticationAlgorithm()).getHmacMd596().getKeyStr().stringValue();
+                targetEntry.integrityAlgorithm = 1;
+            } else if (authAlg.getAuthenticationAlgorithm() instanceof HmacSha196) {
+                integKey =
+                        ((HmacSha196) authAlg.getAuthenticationAlgorithm()).getHmacSha196().getKeyStr().stringValue();
+                targetEntry.integrityAlgorithm = 2;
+            } else {
+                targetEntry.integrityAlgorithm = 0;
+                return;
+            }
+            targetEntry.integrityKey = integKey.getBytes();
+        }
+    }
+
+    private void fillEspEncryption(IpsecSadAddDelEntry targetEntry, Esp data) {
+        //0 = Null, 1 = AES-CBC-128, 2 = AES-CBC-192, 3 = AES-CBC-256, 4 = 3DES-CBC
+        if (data.getEncryption() != null && data.getEncryption().getEncryptionAlgorithm() != null) {
+            String cryptoKey = "";
+            EncryptionAlgorithm encrAlg = data.getEncryption().getEncryptionAlgorithm();
+            if (encrAlg instanceof Aes128Cbc) {
+                cryptoKey = ((Aes128Cbc) encrAlg).getAes128Cbc().getKeyStr().stringValue();
+                targetEntry.cryptoAlgorithm = 1;
+            } else if (encrAlg instanceof Aes192Cbc) {
+                cryptoKey = ((Aes192Cbc) encrAlg).getAes192Cbc().getKeyStr().stringValue();
+                targetEntry.cryptoAlgorithm = 2;
+            } else if (encrAlg instanceof Aes256Cbc) {
+                cryptoKey = ((Aes256Cbc) encrAlg).getAes256Cbc().getKeyStr().stringValue();
+                targetEntry.cryptoAlgorithm = 3;
+            } else if (encrAlg instanceof DesCbc) {
+                cryptoKey = ((DesCbc) encrAlg).getDesCbc().getKeyStr().stringValue();
+                targetEntry.cryptoAlgorithm = 4;
+            } else {
+                targetEntry.cryptoAlgorithm = 0;
+                return;
+            }
+            targetEntry.cryptoKey = cryptoKey.getBytes();
+        }
+    }
+
+    private void fillAddresses(IpsecSadAddDelEntry targetEntry, SadEntries data) {
+        if (data.getSourceAddress() != null && data.getSourceAddress().getIpAddress() != null) {
+            IpAddress sourceAddr = data.getSourceAddress().getIpAddress();
+            if (sourceAddr instanceof Ipv4Address) {
+                Ipv4Address ipv4 = (Ipv4Address) sourceAddr;
+                targetEntry.isTunnelIpv6 = 0;
+                targetEntry.tunnelSrcAddress = ipv4AddressNoZoneToArray(ipv4.getIpv4Address().getValue());
+            } else if (sourceAddr instanceof Ipv6Address) {
+                Ipv6Address ipv6 = (Ipv6Address) sourceAddr;
+                targetEntry.isTunnelIpv6 = 1;
+                targetEntry.tunnelSrcAddress = ipv6AddressNoZoneToArray(ipv6.getIpv6Address());
+            }
+        }
+
+        if (data.getDestinationAddress() != null && data.getDestinationAddress().getIpAddress() != null) {
+            IpAddress destAddr = data.getDestinationAddress().getIpAddress();
+
+            if (destAddr instanceof Ipv4Address) {
+                Ipv4Address ipv4 = (Ipv4Address) destAddr;
+                targetEntry.isTunnelIpv6 = 0;
+                targetEntry.tunnelDstAddress = ipv4AddressNoZoneToArray(ipv4.getIpv4Address().getValue());
+            } else if (destAddr instanceof Ipv6Address) {
+                Ipv6Address ipv6 = (Ipv6Address) destAddr;
+                targetEntry.isTunnelIpv6 = 1;
+                targetEntry.tunnelDstAddress = ipv6AddressNoZoneToArray(ipv6.getIpv6Address());
+            }
+        }
+    }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizer.java
new file mode 100644 (file)
index 0000000..771cf67
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.write;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+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.IpsecSpdAddDel;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDelEntry;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSpdEntriesAugmentation;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Spd;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.SpdKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.spd.SpdEntries;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IpsecSpdCustomizer extends FutureJVppCustomizer
+        implements ListWriterCustomizer<Spd, SpdKey>, JvppReplyConsumer, ByteDataTranslator,
+        Ipv6Translator, Ipv4Translator {
+
+    public IpsecSpdCustomizer(final FutureJVppCore vppApi) {
+        super(vppApi);
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final Spd dataAfter,
+                                       @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        IpsecSpdAddDel spdCreate = new IpsecSpdAddDel();
+        spdCreate.isAdd = ByteDataTranslator.BYTE_TRUE;
+        spdCreate.spdId = dataAfter.getSpdId();
+        getReplyForWrite(getFutureJVpp().ipsecSpdAddDel(spdCreate).toCompletableFuture(), id);
+        if (dataAfter.getSpdEntries() != null) {
+            for (SpdEntries entry : dataAfter.getSpdEntries()) {
+                addSpdEntry(id, dataAfter.getSpdId(), entry);
+            }
+        }
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final Spd dataBefore,
+                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        IpsecSpdAddDel spdDelete = new IpsecSpdAddDel();
+        spdDelete.isAdd = ByteDataTranslator.BYTE_FALSE;
+        spdDelete.spdId = dataBefore.getSpdId();
+        getReplyForWrite(getFutureJVpp().ipsecSpdAddDel(spdDelete).toCompletableFuture(), id);
+    }
+
+    @Override
+    public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final Spd dataBefore,
+                                        @Nonnull final Spd dataAfter, @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        if (dataAfter.getSpdEntries() != null) {
+            for (SpdEntries entry : dataAfter.getSpdEntries()) {
+                addSpdEntry(id, dataAfter.getSpdId(), entry);
+            }
+        }
+    }
+
+    private void addSpdEntry(final InstanceIdentifier<Spd> id, int spdId, final SpdEntries entry)
+            throws WriteFailedException {
+        IpsecSpdAddDelEntry request = new IpsecSpdAddDelEntry();
+        request.spdId = spdId;
+        request.isAdd = ByteDataTranslator.BYTE_TRUE;
+        IpsecSpdEntriesAugmentation entryAug = entry.augmentation(IpsecSpdEntriesAugmentation.class);
+        if (entryAug == null) {
+            return;
+        }
+
+        if (entryAug.isIsIpv6() != null) {
+            request.isIpv6 = (byte) (entryAug.isIsIpv6()
+                    ? 1
+                    : 0);
+        }
+        if (entryAug.getDirection() != null) {
+            request.isOutbound = (byte) entryAug.getDirection().getIntValue();
+        }
+
+        if (entryAug.getPriority() != null) {
+            request.priority = entryAug.getPriority();
+        }
+
+        if (entryAug.getOperation() != null) {
+            final String operation = entryAug.getOperation().getName();
+            if (operation.equalsIgnoreCase("bypass")) {
+                request.policy = (byte) 0;
+            } else if (operation.equalsIgnoreCase("discard")) {
+                request.policy = (byte) 1;
+            } else if (operation.equalsIgnoreCase("protect")) {
+                request.policy = (byte) 3;
+            }
+        }
+
+        if (entryAug.getLaddrStart() != null) {
+            if (entryAug.getLaddrStart().getIpv4Address() != null) {
+                request.localAddressStart =
+                        ipv4AddressNoZoneToArray(entryAug.getLaddrStart().getIpv4Address().getValue());
+            } else if (entryAug.getLaddrStart().getIpv6Address() != null) {
+                request.localAddressStart = ipv6AddressNoZoneToArray(entryAug.getLaddrStart().getIpv6Address());
+            }
+        }
+        if (entryAug.getLaddrStop() != null) {
+            if (entryAug.getLaddrStop().getIpv4Address() != null) {
+                request.localAddressStop =
+                        ipv4AddressNoZoneToArray(entryAug.getLaddrStop().getIpv4Address().getValue());
+            } else if (entryAug.getLaddrStop().getIpv6Address() != null) {
+                request.localAddressStop = ipv6AddressNoZoneToArray(entryAug.getLaddrStop().getIpv6Address());
+            }
+        }
+        if (entryAug.getRaddrStop() != null) {
+            if (entryAug.getRaddrStop().getIpv4Address() != null) {
+                request.remoteAddressStop =
+                        ipv4AddressNoZoneToArray(entryAug.getRaddrStop().getIpv4Address().getValue());
+            } else if (entryAug.getRaddrStop().getIpv6Address() != null) {
+                request.remoteAddressStop = ipv6AddressNoZoneToArray(entryAug.getRaddrStop().getIpv6Address());
+            }
+        }
+
+        if (entryAug.getRaddrStart() != null) {
+            if (entryAug.getRaddrStart().getIpv4Address() != null) {
+                request.remoteAddressStart =
+                        ipv4AddressNoZoneToArray(entryAug.getRaddrStart().getIpv4Address().getValue());
+            } else if (entryAug.getRaddrStart().getIpv6Address() != null) {
+                request.remoteAddressStart = ipv6AddressNoZoneToArray(entryAug.getRaddrStart().getIpv6Address());
+            }
+        }
+        getReplyForWrite(getFutureJVpp().ipsecSpdAddDelEntry(request).toCompletableFuture(), id);
+    }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecWriterFactory.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecWriterFactory.java
new file mode 100644 (file)
index 0000000..8b164ac
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.write;
+
+import com.google.common.collect.Sets;
+import com.google.inject.Inject;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.honeycomb.translate.impl.write.GenericListWriter;
+import io.fd.honeycomb.translate.impl.write.GenericWriter;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkeGlobalConfAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkev2PolicyAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSadEntriesAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSpdEntriesAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ikev2.policy.aug.grouping.TrafficSelectors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ikev2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ipsec;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.Identity;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.identity.Local;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.identity.Remote;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.IkeGlobalConfiguration;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Sad;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Spd;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.Ah;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.Esp;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Authentication;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Encryption;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.hmac.md5._96.HmacMd596;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.hmac.sha1._96.HmacSha196;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._128.cbc.Aes128Cbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._192.cbc.Aes192Cbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._256.cbc.Aes256Cbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.des.cbc.DesCbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.grouping.DestinationAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.grouping.SourceAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.spd.SpdEntries;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Factory producing writers for IpSec plugin's data.
+ */
+public final class IpsecWriterFactory implements WriterFactory {
+
+    private static final InstanceIdentifier<Ikev2> IKE2_ID = InstanceIdentifier.create(Ikev2.class);
+    private static final InstanceIdentifier<Ipsec> IPSEC_ID = InstanceIdentifier.create(Ipsec.class);
+    private static final InstanceIdentifier<Sad> SAD_ID = IPSEC_ID.child(Sad.class);
+    private static final InstanceIdentifier<SadEntries> SAD_ENTRIES_ID = SAD_ID.child(SadEntries.class);
+    private static final InstanceIdentifier<Spd> SPD_ID = IPSEC_ID.child(Spd.class);
+
+    private final FutureJVppCore vppApi;
+    private MultiNamingContext sadEntriesMapping;
+
+    @Inject
+    public IpsecWriterFactory(final FutureJVppCore vppApi, final MultiNamingContext sadEntriesMappingContext) {
+        this.vppApi = vppApi;
+        this.sadEntriesMapping = sadEntriesMappingContext;
+    }
+
+    @Override
+    public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
+        registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(SadEntries.class).child(SourceAddress.class),
+                InstanceIdentifier.create(SadEntries.class).child(DestinationAddress.class),
+                InstanceIdentifier.create(SadEntries.class).child(Ah.class)
+                        .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.hmac.sha1._96.HmacSha196.class),
+                InstanceIdentifier.create(SadEntries.class).child(Ah.class)
+                        .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.hmac.md5._96.HmacMd596.class),
+                InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Authentication.class)
+                        .child(HmacSha196.class),
+                InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Authentication.class)
+                        .child(HmacMd596.class),
+                InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Encryption.class)
+                        .child(Aes128Cbc.class),
+                InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Encryption.class)
+                        .child(Aes192Cbc.class),
+                InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Encryption.class)
+                        .child(Aes256Cbc.class),
+                InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Encryption.class)
+                        .child(DesCbc.class),
+                InstanceIdentifier.create(SadEntries.class).augmentation(IpsecSadEntriesAugmentation.class)),
+                new GenericListWriter<>(SAD_ENTRIES_ID, new IpsecSadEntryCustomizer(vppApi, sadEntriesMapping)));
+        registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(Spd.class).child(SpdEntries.class),
+                InstanceIdentifier.create(Spd.class).child(SpdEntries.class)
+                        .augmentation(IpsecSpdEntriesAugmentation.class)),
+                new GenericListWriter<>(SPD_ID, new IpsecSpdCustomizer(vppApi)));
+        registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(IkeGlobalConfiguration.class)
+                        .augmentation(IpsecIkeGlobalConfAugmentation.class)),
+                new GenericWriter<>(IKE2_ID.child(IkeGlobalConfiguration.class),
+                        new Ikev2GlobalConfigurationCustomizer(vppApi)));
+        registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(Policy.class).child(
+                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.policy.profile.grouping.Authentication.class),
+                InstanceIdentifier.create(Policy.class).augmentation(IpsecIkev2PolicyAugmentation.class),
+                InstanceIdentifier.create(Policy.class).augmentation(IpsecIkev2PolicyAugmentation.class)
+                        .child(TrafficSelectors.class)),
+                new GenericListWriter<>(IKE2_ID.child(Policy.class), new Ikev2PolicyCustomizer(vppApi)));
+        registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(Identity.class).child(Local.class),
+                InstanceIdentifier.create(Identity.class).child(Remote.class)),
+                new GenericWriter<>(IKE2_ID.child(Policy.class).child(Identity.class),
+                        new Ikev2PolicyIdentityCustomizer(vppApi)));
+    }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/IpsecModuleTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/IpsecModuleTest.java
new file mode 100644 (file)
index 0000000..42817d4
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.Matchers.empty;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.testing.fieldbinder.Bind;
+import com.google.inject.testing.fieldbinder.BoundFieldModule;
+import io.fd.hc2vpp.ipsec.read.IpsecReaderFactory;
+import io.fd.hc2vpp.ipsec.write.IpsecWriterFactory;
+import io.fd.honeycomb.translate.impl.read.registry.CompositeReaderRegistryBuilder;
+import io.fd.honeycomb.translate.impl.write.registry.FlatWriterRegistryBuilder;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.util.YangDAG;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.HashSet;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+
+public class IpsecModuleTest {
+
+    @Bind
+    @Mock
+    private FutureJVppCore futureJVppCore;
+
+    @Inject
+    private Set<WriterFactory> writerFactories = new HashSet<>();
+
+    @Inject
+    private Set<ReaderFactory> readerFactories = new HashSet<>();
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        Guice.createInjector(new IpsecModule(), BoundFieldModule.of(this)).injectMembers(this);
+    }
+
+    @Test
+    public void testWriterFactories() throws Exception {
+        assertThat(writerFactories, is(not(empty())));
+        final FlatWriterRegistryBuilder registryBuilder = new FlatWriterRegistryBuilder(new YangDAG());
+        writerFactories.stream().forEach(factory -> factory.init(registryBuilder));
+        assertNotNull(registryBuilder.build());
+        assertEquals(1, writerFactories.size());
+        assertTrue(writerFactories.iterator().next() instanceof IpsecWriterFactory);
+    }
+
+    @Test
+    public void testReaderFactories() throws Exception {
+        assertThat(readerFactories, is(not(empty())));
+        final CompositeReaderRegistryBuilder registryBuilder = new CompositeReaderRegistryBuilder(new YangDAG());
+        readerFactories.stream().forEach(factory -> factory.init(registryBuilder));
+        assertNotNull(registryBuilder.build());
+        assertEquals(1, readerFactories.size());
+        assertTrue(readerFactories.iterator().next() instanceof IpsecReaderFactory);
+    }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/helpers/SchemaContextTestHelper.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/helpers/SchemaContextTestHelper.java
new file mode 100644 (file)
index 0000000..bce8a98
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.helpers;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.honeycomb.test.tools.annotations.InjectablesProcessor;
+import io.fd.honeycomb.test.tools.annotations.SchemaContextProvider;
+import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
+
+public interface SchemaContextTestHelper extends InjectablesProcessor {
+
+    @SchemaContextProvider
+    default ModuleInfoBackedContext getSchemaContext() {
+        return provideSchemaContextFor(ImmutableSet.of(
+                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.$YangModuleInfoImpl
+                        .getInstance(),
+                org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.$YangModuleInfoImpl
+                        .getInstance()
+        ));
+    }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizerTest.java
new file mode 100644 (file)
index 0000000..9b8f915
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.read;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.vpp.jvpp.core.dto.IpsecSaDetails;
+import io.fd.vpp.jvpp.core.dto.IpsecSaDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.IpsecSaDump;
+import java.util.LinkedList;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.state.grouping.Sa;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IpsecStateCustomizerTest extends ReaderCustomizerTest<IpsecState, IpsecStateBuilder>
+        implements ByteDataTranslator, Ipv4Translator, Ipv6Translator {
+
+    private static InstanceIdentifier<IpsecState> IPSEC_STATE_ID = InstanceIdentifier.create(IpsecState.class);
+    private static final String LOCAL_ADDR_START = "192.168.11.1";
+    private static final String REMOTE_ADDR_START = "192.168.22.1";
+    private static final String TUNNEL_SRC_ADDR = LOCAL_ADDR_START;
+    private static final String TUNNEL_DST_ADDR = REMOTE_ADDR_START;
+    private static final int REPLY_WINDOW = 88;
+    private static final int SA_ID = 10;
+    private static final int SPI = 1001;
+    private static final int CRYPTO_ALG = 1;
+    private static final String CRYPTO_KEY = "123456789";
+    private static final int INTEG_ALG = 2;
+    private static final String INTEG_KEY = "987654321";
+    private static final int PROTOCOL = 1;
+    private static final int LAST_SEQ_INB = 8;
+    private static final int HOLD_DOWN = 88;
+
+    public IpsecStateCustomizerTest() {
+        super(IpsecState.class, IpsecStateBuilder.class);
+    }
+
+    @Override
+    protected ReaderCustomizer<IpsecState, IpsecStateBuilder> initCustomizer() {
+        return new IpsecStateCustomizer(api);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        final IpsecSaDetailsReplyDump saDetailsReply = new IpsecSaDetailsReplyDump();
+        LinkedList<IpsecSaDetails> saDetails = new LinkedList<>();
+        IpsecSaDetails saDetail = new IpsecSaDetails();
+        saDetail.spi = SPI;
+        saDetail.saId = SA_ID;
+        saDetail.cryptoAlg = CRYPTO_ALG;
+        saDetail.cryptoKey = CRYPTO_KEY.getBytes();
+        saDetail.integAlg = INTEG_ALG;
+        saDetail.integKey = INTEG_KEY.getBytes();
+        saDetail.isTunnel = BYTE_TRUE;
+        saDetail.isTunnelIp6 = BYTE_FALSE;
+        saDetail.protocol = PROTOCOL;
+        saDetail.lastSeqInbound = LAST_SEQ_INB;
+        saDetail.replayWindow = REPLY_WINDOW;
+        saDetail.useAntiReplay = BYTE_TRUE;
+        saDetail.tunnelSrcAddr = ipv4AddressNoZoneToArray(TUNNEL_SRC_ADDR);
+        saDetail.tunnelDstAddr = ipv4AddressNoZoneToArray(TUNNEL_DST_ADDR);
+        saDetails.add(saDetail);
+        saDetailsReply.ipsecSaDetails = saDetails;
+        IpsecSaDump saDump = new IpsecSaDump();
+        saDump.saId = SA_ID;
+        when(api.ipsecSaDump(any())).thenReturn(future(saDetailsReply));
+    }
+
+    @Test
+    public void testReadSa() throws ReadFailedException {
+        final IpsecStateBuilder builder = new IpsecStateBuilder();
+        getCustomizer().readCurrentAttributes(IPSEC_STATE_ID, builder, ctx);
+        assertEquals(builder.getSa().size(), 1);
+        Sa sa = builder.getSa().get(0);
+        assertEquals(sa.getAntiReplayWindow().intValue(), REPLY_WINDOW);
+        assertEquals(sa.getAuthenticationAlgorithm().getIntValue(), INTEG_ALG);
+        assertEquals(sa.getEncryptionAlgorithm().getIntValue(), CRYPTO_ALG);
+        assertEquals(sa.getSpi().intValue(), SPI);
+    }
+
+    @Test
+    public void testMerge() throws Exception {
+        final IpsecStateBuilder parentBuilder = new IpsecStateBuilder();
+        final IpsecStateBuilder builderForNewdata = new IpsecStateBuilder();
+        builderForNewdata.setHoldDown(new Long(HOLD_DOWN));
+        getCustomizer().merge(parentBuilder, builderForNewdata.build());
+        assertEquals(parentBuilder.getHoldDown().intValue(), HOLD_DOWN);
+    }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizerTest.java
new file mode 100644 (file)
index 0000000..bf08fa8
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.read;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdDetails;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdsDetails;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdsDetailsReplyDump;
+import java.util.LinkedList;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.Spd;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.SpdBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.SpdKey;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.spd.SpdEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecState;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IpsecStateSpdCustomizerTest extends ReaderCustomizerTest<Spd, SpdBuilder>
+        implements ByteDataTranslator, Ipv4Translator, Ipv6Translator {
+
+    private static InstanceIdentifier<Spd> SPD_IID = InstanceIdentifier.create(IpsecState.class)
+            .augmentation(IpsecStateSpdAugmentation.class).child(Spd.class, new SpdKey(10));
+
+    private static final String LOCAL_ADDR_START = "192.168.11.1";
+    private static final String LOCAL_ADDR_END = "192.168.11.255";
+    private static final short PORT_START = 0;
+    private static final short PORT_END = Short.MAX_VALUE;
+    private static final int POLICY_PROTECT = 3;
+    private static final int SPD_ID = 10;
+    private static final int SA_ID = 10;
+    private static final int PROTOCOL = 1;
+    private static final int PRIORITY = 100;
+
+    public IpsecStateSpdCustomizerTest() {
+        super(Spd.class, SpdBuilder.class);
+    }
+
+    @Override
+    protected ReaderCustomizer<Spd, SpdBuilder> initCustomizer() {
+        return new IpsecStateSpdCustomizer(api);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        final IpsecSpdDetailsReplyDump spdDetailsReply = new IpsecSpdDetailsReplyDump();
+        LinkedList<IpsecSpdDetails> spdDetails = new LinkedList<>();
+        IpsecSpdDetails spdDetail = new IpsecSpdDetails();
+        spdDetail.isIpv6 = BYTE_FALSE;
+        spdDetail.isOutbound = BYTE_TRUE;
+        spdDetail.spdId = SPD_ID;
+        spdDetail.protocol = PROTOCOL;
+        spdDetail.localStartAddr = ipv4AddressNoZoneToArray(LOCAL_ADDR_START);
+        spdDetail.localStopAddr = ipv4AddressNoZoneToArray(LOCAL_ADDR_END);
+        spdDetail.localStartPort = PORT_START;
+        spdDetail.localStopPort = PORT_END;
+        spdDetail.policy = POLICY_PROTECT;
+        spdDetail.saId = SA_ID;
+        spdDetail.priority = PRIORITY;
+        spdDetails.add(spdDetail);
+        spdDetailsReply.ipsecSpdDetails = spdDetails;
+        when(api.ipsecSpdDump(any())).thenReturn(future(spdDetailsReply));
+
+        IpsecSpdsDetailsReplyDump spdsReply = new IpsecSpdsDetailsReplyDump();
+        IpsecSpdsDetails spdsDetail = new IpsecSpdsDetails();
+        spdsDetail.spdId = SPD_ID;
+        spdsReply.ipsecSpdsDetails.add(spdsDetail);
+        when(api.ipsecSpdsDump(any())).thenReturn(future(spdsReply));
+    }
+
+    @Test
+    public void testReadSpd() throws ReadFailedException {
+        final SpdBuilder builder = new SpdBuilder();
+        getCustomizer().readCurrentAttributes(SPD_IID, builder, ctx);
+        assertEquals(builder.getSpdEntries().size(), 1);
+        SpdEntries spdEntries = builder.getSpdEntries().get(0);
+        assertEquals(spdEntries.getDirection().getName(), "outbound");
+        assertEquals(spdEntries.getPriority().intValue(), PRIORITY);
+    }
+
+    @Test
+    public void testMerge() throws Exception {
+        final IpsecStateSpdAugmentationBuilder parentBuilder = new IpsecStateSpdAugmentationBuilder();
+        final IpsecStateSpdAugmentationBuilder builderForNewData = new IpsecStateSpdAugmentationBuilder();
+        SpdBuilder spdBuilder = new SpdBuilder();
+        spdBuilder.setSpdId(SPD_ID);
+        getCustomizer().merge(parentBuilder, spdBuilder.build());
+        assertEquals(parentBuilder.getSpd().size(), 1);
+        assertEquals(parentBuilder.getSpd().get(0).getSpdId().intValue(), SPD_ID);
+    }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizerTest.java
new file mode 100644 (file)
index 0000000..cf9e8b1
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.write;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.Ikev2SetLocalKey;
+import io.fd.vpp.jvpp.core.dto.Ikev2SetLocalKeyReply;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkeGlobalConfAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkeGlobalConfAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ikev2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.IkeGlobalConfiguration;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.IkeGlobalConfigurationBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class Ikev2GlobalConfigurationCustomizerTest extends WriterCustomizerTest
+        implements SchemaContextTestHelper {
+    InstanceIdentifier<IkeGlobalConfiguration> IID = InstanceIdentifier.create(Ikev2.class)
+            .child(IkeGlobalConfiguration.class);
+    private Ikev2GlobalConfigurationCustomizer customizer;
+    private static final String LOCAL_KEY_FILE = "/home/localadmin/certs/client-key.pem";
+
+    @Override
+    protected void setUpTest() throws Exception {
+        customizer = new Ikev2GlobalConfigurationCustomizer(api);
+        when(api.ikev2SetLocalKey(any())).thenReturn(future(new Ikev2SetLocalKeyReply()));
+    }
+
+    @Test
+    public void testWrite() throws WriteFailedException {
+        IkeGlobalConfigurationBuilder dataAfterBuilder = new IkeGlobalConfigurationBuilder();
+        IpsecIkeGlobalConfAugmentationBuilder augBuilder = new IpsecIkeGlobalConfAugmentationBuilder();
+        augBuilder.setLocalKeyFile(LOCAL_KEY_FILE);
+        dataAfterBuilder.addAugmentation(IpsecIkeGlobalConfAugmentation.class, augBuilder.build());
+        customizer.writeCurrentAttributes(IID, dataAfterBuilder.build(), writeContext);
+        Ikev2SetLocalKey request = new Ikev2SetLocalKey();
+        request.keyFile = LOCAL_KEY_FILE.getBytes();
+        verify(api).ikev2SetLocalKey(request);
+    }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizerTest.java
new file mode 100644 (file)
index 0000000..0c7b65f
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.write;
+
+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.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper;
+import io.fd.honeycomb.test.tools.HoneycombTestRunner;
+import io.fd.honeycomb.test.tools.annotations.InjectTestData;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileAddDel;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileAddDelReply;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetAuth;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetAuthReply;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetTs;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetTsReply;
+import java.nio.ByteBuffer;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkev2PolicyAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ikev2.policy.aug.grouping.TrafficSelectors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ikev2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.PolicyKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.policy.profile.grouping.Authentication;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@RunWith(HoneycombTestRunner.class)
+public class Ikev2PolicyCustomizerTest extends WriterCustomizerTest implements SchemaContextTestHelper,
+        ByteDataTranslator, Ipv4Translator, Ipv6Translator {
+
+    private static final String IKEV2_PATH = "/hc2vpp-ietf-ipsec:ikev2";
+    private Ikev2PolicyCustomizer customizer;
+
+    @Override
+    protected void setUpTest() throws Exception {
+        customizer = new Ikev2PolicyCustomizer(api);
+        when(api.ikev2ProfileAddDel(any())).thenReturn(future(new Ikev2ProfileAddDelReply()));
+        when(api.ikev2ProfileSetTs(any())).thenReturn(future(new Ikev2ProfileSetTsReply()));
+        when(api.ikev2ProfileSetAuth(any())).thenReturn(future(new Ikev2ProfileSetAuthReply()));
+    }
+
+    @Test
+    public void testWrite(@InjectTestData(resourcePath = "/ikev2/addIkev2Profile.json", id = IKEV2_PATH) Ikev2 ikev2)
+            throws WriteFailedException {
+        Policy policy = ikev2.getPolicy().get(0);
+        customizer.writeCurrentAttributes(getId(policy.getName()), policy, writeContext);
+        Ikev2ProfileAddDel profileAddrequest = new Ikev2ProfileAddDel();
+        profileAddrequest.isAdd = BYTE_TRUE;
+        profileAddrequest.name = policy.getName().getBytes();
+
+        verify(api).ikev2ProfileAddDel(profileAddrequest);
+        verify(api).ikev2ProfileSetTs(translateTStoRequest(policy.augmentation(IpsecIkev2PolicyAugmentation.class)
+                .getTrafficSelectors().get(0), policy.getName()));
+        verify(api).ikev2ProfileSetAuth(translateAuthToRequest(policy));
+    }
+
+    @Test
+    public void testUpdate(
+            @InjectTestData(resourcePath = "/ikev2/addDelProfile_before.json", id = IKEV2_PATH) Ikev2 ikev2Before,
+            @InjectTestData(resourcePath = "/ikev2/addDelProfile_after.json", id = IKEV2_PATH) Ikev2 ikev2After)
+            throws WriteFailedException {
+        final Policy before = ikev2Before.getPolicy().get(0);
+        final Policy after = ikev2After.getPolicy().get(0);
+        customizer.updateCurrentAttributes(getId(before.getName()), before, after, writeContext);
+
+        verify(api, times(0)).ikev2ProfileAddDel(any());
+        verify(api).ikev2ProfileSetTs(translateTStoRequest(after.augmentation(IpsecIkev2PolicyAugmentation.class)
+                .getTrafficSelectors().get(0), after.getName()));
+        verify(api).ikev2ProfileSetAuth(translateAuthToRequest(after));
+    }
+
+    @Test
+    public void testDelete(@InjectTestData(resourcePath = "/ikev2/addIkev2Profile.json", id = IKEV2_PATH) Ikev2 ikev2)
+            throws WriteFailedException {
+        Policy policy = ikev2.getPolicy().get(0);
+        customizer.deleteCurrentAttributes(getId(policy.getName()), policy, writeContext);
+        final Ikev2ProfileAddDel request = new Ikev2ProfileAddDel();
+        request.name = policy.getName().getBytes();
+        request.isAdd = BYTE_FALSE;
+        verify(api).ikev2ProfileAddDel(request);
+        verify(api, times(0)).ikev2ProfileSetTs(any());
+        verify(api, times(0)).ikev2ProfileSetAuth(any());
+    }
+
+    private InstanceIdentifier<Policy> getId(final String name) {
+        return InstanceIdentifier.create(Ikev2.class).child(Policy.class, new PolicyKey(name));
+    }
+
+    private Ikev2ProfileSetTs translateTStoRequest(final TrafficSelectors selector, final String policyName) {
+        Ikev2ProfileSetTs addTsRequest = new Ikev2ProfileSetTs();
+        if (selector.getLocalAddressHigh() != null && selector.getLocalAddressLow() != null) {
+            addTsRequest.isLocal = ByteDataTranslator.BYTE_TRUE;
+            addTsRequest.startAddr = ByteBuffer
+                    .wrap(ipv4AddressNoZoneToArray(selector.getLocalAddressLow().getIpv4Address().getValue())).getInt();
+            addTsRequest.endAddr = ByteBuffer
+                    .wrap(ipv4AddressNoZoneToArray(selector.getLocalAddressHigh().getIpv4Address().getValue()))
+                    .getInt();
+            if (selector.getLocalPortHigh() != null && selector.getLocalPortLow() != null) {
+                addTsRequest.startPort = selector.getLocalPortLow().getValue().shortValue();
+                addTsRequest.endPort = selector.getLocalPortHigh().getValue().shortValue();
+            }
+        } else if (selector.getRemoteAddressHigh() != null && selector.getRemoteAddressLow() != null) {
+            addTsRequest.isLocal = ByteDataTranslator.BYTE_FALSE;
+            addTsRequest.startAddr = ByteBuffer
+                    .wrap(ipv4AddressNoZoneToArray(selector.getRemoteAddressLow().getIpv4Address().getValue()))
+                    .getInt();
+            addTsRequest.endAddr = ByteBuffer
+                    .wrap(ipv4AddressNoZoneToArray(selector.getRemoteAddressHigh().getIpv4Address().getValue()))
+                    .getInt();
+            if (selector.getRemotePortHigh() != null && selector.getRemotePortLow() != null) {
+                addTsRequest.startPort = selector.getRemotePortLow().getValue().shortValue();
+                addTsRequest.endPort = selector.getRemotePortHigh().getValue().shortValue();
+            }
+        }
+        if (selector.getProtocol() != null) {
+            addTsRequest.proto = selector.getProtocol().byteValue();
+        }
+        if (policyName != null) {
+            addTsRequest.name = policyName.getBytes();
+        }
+        return addTsRequest;
+    }
+
+    private Ikev2ProfileSetAuth translateAuthToRequest(Policy policy) {
+        final Ikev2ProfileSetAuth request = new Ikev2ProfileSetAuth();
+        Authentication auth = policy.getAuthentication();
+        if (auth != null) {
+            request.name = policy.getName().getBytes();
+            if (auth.isPresharedKey() != null && policy.getPreSharedKey() != null) {
+                request.authMethod = ByteDataTranslator.BYTE_FALSE;
+                if (policy.getPreSharedKey().getHexString() != null) {
+                    request.isHex = ByteDataTranslator.BYTE_TRUE;
+                }
+                request.data = policy.getPreSharedKey().stringValue().getBytes();
+            } else if (auth.isRsaSignature() != null) {
+                IpsecIkev2PolicyAugmentation aug = policy.augmentation(IpsecIkev2PolicyAugmentation.class);
+                if (aug != null && aug.getCertificate() != null) {
+                    request.data = aug.getCertificate().getBytes();
+                    request.authMethod = ByteDataTranslator.BYTE_TRUE;
+                }
+            }
+        }
+        return request;
+    }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizerTest.java
new file mode 100644 (file)
index 0000000..bb8f0d7
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.write;
+
+import static org.mockito.ArgumentMatchers.any;
+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.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper;
+import io.fd.honeycomb.test.tools.HoneycombTestRunner;
+import io.fd.honeycomb.test.tools.annotations.InjectTestData;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetId;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetIdReply;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ikev2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.Identity;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.PolicyKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@RunWith(HoneycombTestRunner.class)
+public class Ikev2PolicyIdentityCustomizerTest extends WriterCustomizerTest implements SchemaContextTestHelper,
+        ByteDataTranslator, Ipv4Translator, Ipv6Translator {
+
+    private static final String POLICY_NAME = "testPolicy";
+    private static final String IPV4_TYPE_DATA = "192.168.123.22";
+    private static final String IPV6_TYPE_DATA = "2001:DB8:0:0:8:800:200C:417A";
+    private static final String FQDN_TYPE_DATA = "vpp.home";
+    private static final String RFC822_TYPE_DATA = "[email protected]";
+    private static final String IDENTITY_PATH =
+            "/hc2vpp-ietf-ipsec:ikev2/hc2vpp-ietf-ipsec:policy[hc2vpp-ietf-ipsec:name='" + POLICY_NAME +
+                    "']/hc2vpp-ietf-ipsec:identity";
+    private Ikev2PolicyIdentityCustomizer customizer;
+
+    @Override
+    protected void setUpTest() throws Exception {
+        customizer = new Ikev2PolicyIdentityCustomizer(api);
+        when(api.ikev2ProfileSetId(any())).thenReturn(future(new Ikev2ProfileSetIdReply()));
+    }
+
+    @Test
+    public void testWriteLocalIpv4(
+            @InjectTestData(resourcePath = "/ikev2/identity/identity_local_ipv4.json", id = IDENTITY_PATH) Identity identity)
+            throws WriteFailedException {
+        customizer.writeCurrentAttributes(getId(), identity, writeContext);
+        Ikev2ProfileSetId request = new Ikev2ProfileSetId();
+        request.name = POLICY_NAME.getBytes();
+        request.idType = (byte) 1;
+        request.isLocal = BYTE_TRUE;
+        request.data = ipv4AddressNoZoneToArray(IPV4_TYPE_DATA);
+        verify(api).ikev2ProfileSetId(request);
+    }
+
+    @Test
+    public void testWriteRemoteFqdn(
+            @InjectTestData(resourcePath = "/ikev2/identity/identity_remote_fqdn.json", id = IDENTITY_PATH) Identity identity)
+            throws WriteFailedException {
+        customizer.writeCurrentAttributes(getId(), identity, writeContext);
+        Ikev2ProfileSetId request = new Ikev2ProfileSetId();
+        request.name = POLICY_NAME.getBytes();
+        request.idType = (byte) 2;
+        request.isLocal = BYTE_FALSE;
+        request.data = FQDN_TYPE_DATA.getBytes();
+        verify(api).ikev2ProfileSetId(request);
+    }
+
+    @Test
+    public void testWriteLocalIpv6(
+            @InjectTestData(resourcePath = "/ikev2/identity/identity_remote_ipv6.json", id = IDENTITY_PATH) Identity identity)
+            throws WriteFailedException {
+        customizer.writeCurrentAttributes(getId(), identity, writeContext);
+        Ikev2ProfileSetId request = new Ikev2ProfileSetId();
+        request.name = POLICY_NAME.getBytes();
+        request.idType = (byte) 5;
+        request.isLocal = BYTE_FALSE;
+        request.data = ipv6AddressNoZoneToArray(new Ipv6Address(IPV6_TYPE_DATA));
+        verify(api).ikev2ProfileSetId(request);
+    }
+
+    @Test
+    public void testUpdate(
+            @InjectTestData(resourcePath = "/ikev2/identity/identity_local_ipv4.json", id = IDENTITY_PATH) Identity before,
+            @InjectTestData(resourcePath = "/ikev2/identity/identity_local_rfc822.json", id = IDENTITY_PATH) Identity after)
+            throws WriteFailedException {
+        customizer.updateCurrentAttributes(getId(), before, after, writeContext);
+        Ikev2ProfileSetId request = new Ikev2ProfileSetId();
+        request.name = POLICY_NAME.getBytes();
+        request.idType = (byte) 3;
+        request.isLocal = BYTE_TRUE;
+        request.data = RFC822_TYPE_DATA.getBytes();
+        verify(api).ikev2ProfileSetId(request);
+    }
+
+    private InstanceIdentifier<Identity> getId() {
+        return InstanceIdentifier.create(Ikev2.class).child(Policy.class, new PolicyKey(POLICY_NAME))
+                .child(Identity.class);
+    }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizerTest.java
new file mode 100644 (file)
index 0000000..912f50f
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.write;
+
+import static org.mockito.ArgumentMatchers.any;
+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.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper;
+import io.fd.honeycomb.test.tools.HoneycombTestRunner;
+import io.fd.honeycomb.test.tools.annotations.InjectTestData;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.IpsecSadAddDelEntry;
+import io.fd.vpp.jvpp.core.dto.IpsecSadAddDelEntryReply;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeEncryptionAlgorithmT;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeIntegrityAlgorithmT;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ipsec;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecTrafficDirection;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.KeyStringGrouping;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Sad;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.AhBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.AuthenticationAlgorithm;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.EspBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Authentication;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.AuthenticationBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Encryption;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.EncryptionBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.HmacMd596Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.HmacSha196Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes128CbcBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes192CbcBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes256CbcBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.DesCbcBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntriesKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@RunWith(HoneycombTestRunner.class)
+public class IpsecSadEntryCustomizerTest extends WriterCustomizerTest implements SchemaContextTestHelper,
+        ByteDataTranslator, Ipv4Translator, Ipv6Translator {
+
+    private static final String SAD_PATH = "/hc2vpp-ietf-ipsec:ipsec/hc2vpp-ietf-ipsec:sad";
+    private static final InstanceIdentifier<Sad> SAD_IID =
+            InstanceIdentifier.create(Ipsec.class).child(Sad.class);
+    private static final String INTEG_KEY = "0123456789012346";
+    private static final String CRYPTO_KEY = "9876543210987654";
+    private static final String TNL_SRC_ADDR = "192.168.1.1";
+    private static final String TNL_DST_ADDR = "192.168.1.2";
+    private static final int SPI_1002 = 1002;
+    private static final int SAD_ID = 10;
+
+    private IpsecSadEntryCustomizer customizer;
+    @Mock
+    private MultiNamingContext namingCntext;
+
+    @Override
+    protected void setUpTest() throws Exception {
+        customizer = new IpsecSadEntryCustomizer(api, namingCntext);
+        when(api.ipsecSadAddDelEntry(any())).thenReturn(future(new IpsecSadAddDelEntryReply()));
+    }
+
+    @Test
+    public void testWrite(@InjectTestData(resourcePath = "/sadEntries/addDelSadEntry.json", id = SAD_PATH) Sad sad)
+            throws WriteFailedException {
+        final SadEntries data = sad.getSadEntries().get(0);
+        final IpsecSadAddDelEntry request = new IpsecSadAddDelEntry();
+        request.isAdd = BYTE_TRUE;
+        request.spi = SPI_1002;
+        request.sadId = SAD_ID;
+        request.isTunnel = BYTE_TRUE;
+        request.isTunnelIpv6 = BYTE_FALSE;
+        request.integrityKey = INTEG_KEY.getBytes();
+        request.cryptoKey = CRYPTO_KEY.getBytes();
+        request.useAntiReplay = 0;
+        request.tunnelSrcAddress = ipv4AddressNoZoneToArray(TNL_SRC_ADDR);
+        request.tunnelDstAddress = ipv4AddressNoZoneToArray(TNL_DST_ADDR);
+
+        // ESP
+        request.protocol = BYTE_TRUE; //0 = AH, 1 = ESP
+        // - auth MD5-96
+        //  - crypto Aes-Cbc-128
+        testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacMd596,
+                IkeEncryptionAlgorithmT.EncrAesCbc128, request);
+        //  - crypto Aes-Cbc-192
+        testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacMd596,
+                IkeEncryptionAlgorithmT.EncrAesCbc192, request);
+        //  - crypto Aes-Cbc-256
+        testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacMd596,
+                IkeEncryptionAlgorithmT.EncrAesCbc256, request);
+        //  - crypto DesCbc
+        testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacMd596,
+                IkeEncryptionAlgorithmT.EncrDes, request);
+
+        // - auth SHA1-96
+        //  - crypto Aes-Cbc-128
+        testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacSha196,
+                IkeEncryptionAlgorithmT.EncrAesCbc128, request);
+        //  - crypto Aes-Cbc-192
+        testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacSha196,
+                IkeEncryptionAlgorithmT.EncrAesCbc192, request);
+        //  - crypto Aes-Cbc-256
+        testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacSha196,
+                IkeEncryptionAlgorithmT.EncrAesCbc256, request);
+        //  - crypto DesCbc
+        testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacSha196,
+                IkeEncryptionAlgorithmT.EncrDes, request);
+
+        // AH
+        request.protocol = BYTE_FALSE;
+        request.cryptoAlgorithm = 0;
+        request.cryptoKey = null;
+        request.cryptoKeyLength = 0;
+        // - auth SHA1-96
+        testAhAuthorization(data, IkeIntegrityAlgorithmT.AuthHmacSha196, request);
+        // - auth MD5-96
+        testAhAuthorization(data, IkeIntegrityAlgorithmT.AuthHmacMd596, request);
+    }
+
+    @Test
+    public void testUpdate(
+            @InjectTestData(resourcePath = "/sadEntries/addDelSadEntry_Ipv6_before.json", id = SAD_PATH) Sad relaysBefore,
+            @InjectTestData(resourcePath = "/sadEntries/addDelSadEntry_Ipv6_after.json", id = SAD_PATH) Sad relayAfter)
+            throws WriteFailedException {
+        final SadEntries before = relaysBefore.getSadEntries().get(0);
+        final SadEntries after = relayAfter.getSadEntries().get(0);
+        final Long spi = after.getSpi();
+        customizer.updateCurrentAttributes(getId(IpsecTrafficDirection.Outbound, spi), before, after, writeContext);
+        final IpsecSadAddDelEntry request = new IpsecSadAddDelEntry();
+        request.isAdd = BYTE_TRUE;
+        request.spi = SPI_1002;
+        request.sadId = SAD_ID;
+        request.protocol = BYTE_FALSE;
+        request.isTunnel = BYTE_FALSE;
+        request.isTunnelIpv6 = BYTE_TRUE;
+        request.integrityAlgorithm = 1;
+        request.integrityKey = INTEG_KEY.getBytes();
+        request.useAntiReplay = BYTE_TRUE;
+        request.tunnelSrcAddress = ipv6AddressNoZoneToArray(Ipv6Address.getDefaultInstance("2001::11"));
+        request.tunnelDstAddress = ipv6AddressNoZoneToArray(Ipv6Address.getDefaultInstance("2001::12"));
+        verify(api).ipsecSadAddDelEntry(request);
+    }
+
+    @Test
+    public void testDelete(@InjectTestData(resourcePath = "/sadEntries/delSadEntry.json", id = SAD_PATH) Sad sad)
+            throws WriteFailedException {
+        final SadEntries data = sad.getSadEntries().get(0);
+        final Long spi = data.getSpi();
+        customizer.deleteCurrentAttributes(getId(IpsecTrafficDirection.Outbound, spi), data, writeContext);
+        final IpsecSadAddDelEntry request = new IpsecSadAddDelEntry();
+        request.isAdd = BYTE_FALSE;
+        request.spi = SPI_1002;
+        request.sadId = SAD_ID;
+        verify(api).ipsecSadAddDelEntry(request);
+    }
+
+    private InstanceIdentifier<SadEntries> getId(final IpsecTrafficDirection direction, final Long spi) {
+        return SAD_IID.child(SadEntries.class, new SadEntriesKey(direction, spi));
+    }
+
+    private void testAhAuthorization(final SadEntries otherData, final IkeIntegrityAlgorithmT authAlg,
+                                     final IpsecSadAddDelEntry request) throws WriteFailedException {
+        SadEntriesBuilder builder = new SadEntriesBuilder(otherData);
+        builder.setEsp(null);
+        AhBuilder ahBuilder = new AhBuilder();
+        ahBuilder.setAuthenticationAlgorithm(getAhAuthentication(authAlg));
+        builder.setAh(ahBuilder.build());
+        customizer.writeCurrentAttributes(getId(IpsecTrafficDirection.Outbound, Integer.toUnsignedLong(SPI_1002)),
+                builder.build(), writeContext);
+        verify(api).ipsecSadAddDelEntry(request);
+    }
+
+    private void testEspAuthEncrCombination(final SadEntries otherData, final IkeIntegrityAlgorithmT authAlg,
+                                            final IkeEncryptionAlgorithmT encrAlg, final IpsecSadAddDelEntry request)
+            throws WriteFailedException {
+        SadEntriesBuilder builder = new SadEntriesBuilder(otherData);
+        builder.setAh(null);
+        EspBuilder espBuilder = new EspBuilder();
+        espBuilder.setAuthentication(getEspAuthentication(authAlg))
+                .setEncryption(getEspEncryption(encrAlg));
+        builder.setEsp(espBuilder.build());
+        customizer.writeCurrentAttributes(getId(IpsecTrafficDirection.Outbound, Integer.toUnsignedLong(SPI_1002)),
+                builder.build(), writeContext);
+
+        if (encrAlg == IkeEncryptionAlgorithmT.EncrAesCbc128) {
+            request.cryptoAlgorithm = 1;
+        } else if (encrAlg == IkeEncryptionAlgorithmT.EncrAesCbc192) {
+            request.cryptoAlgorithm = 2;
+        } else if (encrAlg == IkeEncryptionAlgorithmT.EncrAesCbc256) {
+            request.cryptoAlgorithm = 3;
+        } else if (encrAlg == IkeEncryptionAlgorithmT.EncrDes) {
+            request.cryptoAlgorithm = 4;
+        } else {
+            request.cryptoAlgorithm = 0;
+        }
+
+        if (authAlg == IkeIntegrityAlgorithmT.AuthHmacMd596) {
+            request.integrityAlgorithm = 1;
+        } else if (authAlg == IkeIntegrityAlgorithmT.AuthHmacSha196) {
+            request.integrityAlgorithm = 2;
+        } else {
+            request.integrityAlgorithm = 0;
+        }
+
+        verify(api).ipsecSadAddDelEntry(request);
+    }
+
+    private Encryption getEspEncryption(IkeEncryptionAlgorithmT alg) {
+        if (alg == IkeEncryptionAlgorithmT.EncrAesCbc128) {
+            return new EncryptionBuilder().setEncryptionAlgorithm(new Aes128CbcBuilder().
+                    setAes128Cbc(
+                            new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._128.cbc.Aes128CbcBuilder()
+                                    .setKeyStr(new KeyStringGrouping.KeyStr(CRYPTO_KEY))
+                                    .build()).build()).build();
+        } else if (alg == IkeEncryptionAlgorithmT.EncrAesCbc192) {
+            return new EncryptionBuilder().setEncryptionAlgorithm(new Aes192CbcBuilder().
+                    setAes192Cbc(
+                            new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._192.cbc.Aes192CbcBuilder()
+                                    .setKeyStr(new KeyStringGrouping.KeyStr(CRYPTO_KEY))
+                                    .build()).build()).build();
+        } else if (alg == IkeEncryptionAlgorithmT.EncrAesCbc256) {
+            return new EncryptionBuilder().setEncryptionAlgorithm(new Aes256CbcBuilder().
+                    setAes256Cbc(
+                            new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._256.cbc.Aes256CbcBuilder()
+                                    .setKeyStr(new KeyStringGrouping.KeyStr(CRYPTO_KEY))
+                                    .build()).build()).build();
+        } else if (alg == IkeEncryptionAlgorithmT.EncrDes) {
+            return new EncryptionBuilder().setEncryptionAlgorithm(new DesCbcBuilder().setDesCbc(
+                    new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.des.cbc.DesCbcBuilder()
+                            .setKeyStr(new KeyStringGrouping.KeyStr(CRYPTO_KEY))
+                            .build()).build()).build();
+        }
+
+        return null;
+    }
+
+    private Authentication getEspAuthentication(IkeIntegrityAlgorithmT alg) {
+        if (alg == IkeIntegrityAlgorithmT.AuthHmacSha196) {
+            return new AuthenticationBuilder().setAuthenticationAlgorithm(new HmacSha196Builder().setHmacSha196(
+                    new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.hmac.sha1._96.HmacSha196Builder()
+                            .setKeyStr(new KeyStringGrouping.KeyStr(INTEG_KEY)).build()).build()).build();
+        } else if (alg == IkeIntegrityAlgorithmT.AuthHmacMd596) {
+            return new AuthenticationBuilder().setAuthenticationAlgorithm(new HmacMd596Builder().setHmacMd596(
+                    new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.hmac.md5._96.HmacMd596Builder()
+                            .setKeyStr(new KeyStringGrouping.KeyStr(INTEG_KEY)).build()).build()).build();
+        }
+        return null;
+    }
+
+    private AuthenticationAlgorithm getAhAuthentication(IkeIntegrityAlgorithmT alg) {
+        if (alg == IkeIntegrityAlgorithmT.AuthHmacSha196) {
+            return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacSha196Builder()
+                    .setHmacSha196(
+                            new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.hmac.sha1._96.HmacSha196Builder()
+                                    .setKeyStr(new KeyStringGrouping.KeyStr(INTEG_KEY)).build()).build();
+        } else if (alg == IkeIntegrityAlgorithmT.AuthHmacMd596) {
+            return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacMd596Builder()
+                    .setHmacMd596(
+                            new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.hmac.md5._96.HmacMd596Builder()
+                                    .setKeyStr(new KeyStringGrouping.KeyStr(INTEG_KEY)).build()).build();
+        }
+        return null;
+    }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizerTest.java
new file mode 100644 (file)
index 0000000..a4b2940
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.ipsec.write;
+
+import static org.mockito.ArgumentMatchers.any;
+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.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper;
+import io.fd.honeycomb.test.tools.HoneycombTestRunner;
+import io.fd.honeycomb.test.tools.annotations.InjectTestData;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDel;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDelEntry;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDelEntryReply;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDelReply;
+import java.util.Collections;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSpdEntriesAugmentation;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ipsec;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Spd;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.SpdBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.SpdKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.spd.SpdEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.spd.SpdEntriesBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@RunWith(HoneycombTestRunner.class)
+public class IpsecSpdCustomizerTest extends WriterCustomizerTest implements SchemaContextTestHelper,
+        ByteDataTranslator, Ipv4Translator, Ipv6Translator {
+
+    private static final int SPD_ID = 10;
+    private static final String IPSEC_PATH = "/hc2vpp-ietf-ipsec:ipsec";
+    private IpsecSpdCustomizer customizer;
+
+    @Override
+    protected void setUpTest() throws Exception {
+        customizer = new IpsecSpdCustomizer(api);
+        when(api.ipsecSpdAddDel(any())).thenReturn(future(new IpsecSpdAddDelReply()));
+        when(api.ipsecSpdAddDelEntry(any())).thenReturn(future(new IpsecSpdAddDelEntryReply()));
+    }
+
+    @Test
+    public void testWrite(@InjectTestData(resourcePath = "/spdEntries/addDelSpd.json", id = IPSEC_PATH) Ipsec ipsec)
+            throws WriteFailedException {
+        Spd spd = ipsec.getSpd().get(0);
+        customizer.writeCurrentAttributes(getSpdId(SPD_ID), spd, writeContext);
+        final IpsecSpdAddDel createSpdRequest = new IpsecSpdAddDel();
+        createSpdRequest.isAdd = BYTE_TRUE;
+        createSpdRequest.spdId = SPD_ID;
+
+        verify(api).ipsecSpdAddDel(createSpdRequest);
+        verify(api).ipsecSpdAddDelEntry(translateSpdEntry(spd.getSpdEntries().get(0), SPD_ID, true));
+        verify(api).ipsecSpdAddDelEntry(translateSpdEntry(spd.getSpdEntries().get(1), SPD_ID, true));
+    }
+
+    @Test
+    public void testUpdate(
+            @InjectTestData(resourcePath = "/spdEntries/addDelSpd_before.json", id = IPSEC_PATH) Ipsec ipsecBefore,
+            @InjectTestData(resourcePath = "/spdEntries/addDelSpd_after.json", id = IPSEC_PATH) Ipsec ipsecAfter)
+            throws WriteFailedException {
+        Spd before = ipsecBefore.getSpd().get(0);
+        Spd after = ipsecAfter.getSpd().get(0);
+        customizer.updateCurrentAttributes(getSpdId(SPD_ID), before, after, writeContext);
+        verify(api).ipsecSpdAddDelEntry(translateSpdEntry(after.getSpdEntries().get(0), SPD_ID, true));
+    }
+
+    @Test
+    public void testDelete()
+            throws WriteFailedException {
+        SpdBuilder spdBuilder = new SpdBuilder();
+        spdBuilder.setSpdId(SPD_ID)
+                .withKey(new SpdKey(SPD_ID))
+                .setSpdEntries(Collections.singletonList(new SpdEntriesBuilder().build()));
+        customizer.deleteCurrentAttributes(getSpdId(SPD_ID), spdBuilder.build(), writeContext);
+        IpsecSpdAddDel request = new IpsecSpdAddDel();
+        request.spdId = SPD_ID;
+        request.isAdd = BYTE_FALSE;
+        verify(api).ipsecSpdAddDel(request);
+    }
+
+    private InstanceIdentifier<Spd> getSpdId(final int spdId) {
+        return InstanceIdentifier.create(Ipsec.class).child(Spd.class, new SpdKey(spdId));
+    }
+
+    private IpsecSpdAddDelEntry translateSpdEntry(final SpdEntries entry, int spdId, boolean isAdd) {
+        IpsecSpdAddDelEntry request = new IpsecSpdAddDelEntry();
+        request.spdId = spdId;
+        request.isAdd = isAdd
+                ? BYTE_TRUE
+                : BYTE_FALSE;
+        IpsecSpdEntriesAugmentation aug = entry.augmentation(IpsecSpdEntriesAugmentation.class);
+        if (aug != null) {
+            if (aug.isIsIpv6() != null) {
+                request.isIpv6 = (byte) (aug.isIsIpv6()
+                        ? 1
+                        : 0);
+            }
+
+            if (aug.getDirection() != null) {
+                request.isOutbound = (byte) aug.getDirection().getIntValue();
+            }
+
+            if (aug.getPriority() != null) {
+                request.priority = aug.getPriority();
+            }
+
+            if (aug.getOperation() != null) {
+                final String operation = aug.getOperation().getName();
+                if (operation.equalsIgnoreCase("bypass")) {
+                    request.policy = (byte) 0;
+                } else if (operation.equalsIgnoreCase("discard")) {
+                    request.policy = (byte) 1;
+                } else if (operation.equalsIgnoreCase("protect")) {
+                    request.policy = (byte) 3;
+                }
+            }
+
+            if (aug.getLaddrStart() != null) {
+                if (aug.getLaddrStart().getIpv4Address() != null) {
+                    request.localAddressStart =
+                            ipv4AddressNoZoneToArray(aug.getLaddrStart().getIpv4Address().getValue());
+                } else if (aug.getLaddrStart().getIpv6Address() != null) {
+                    request.localAddressStart = ipv6AddressNoZoneToArray(aug.getLaddrStart().getIpv6Address());
+                }
+            }
+
+            if (aug.getLaddrStop() != null) {
+                if (aug.getLaddrStop().getIpv4Address() != null) {
+                    request.localAddressStop = ipv4AddressNoZoneToArray(aug.getLaddrStop().getIpv4Address().getValue());
+                } else if (aug.getLaddrStop().getIpv6Address() != null) {
+                    request.localAddressStop = ipv6AddressNoZoneToArray(aug.getLaddrStop().getIpv6Address());
+                }
+            }
+
+            if (aug.getRaddrStop() != null) {
+                if (aug.getRaddrStop().getIpv4Address() != null) {
+                    request.remoteAddressStop =
+                            ipv4AddressNoZoneToArray(aug.getRaddrStop().getIpv4Address().getValue());
+                } else if (aug.getRaddrStop().getIpv6Address() != null) {
+                    request.remoteAddressStop = ipv6AddressNoZoneToArray(aug.getRaddrStop().getIpv6Address());
+                }
+            }
+
+            if (aug.getRaddrStart() != null) {
+                if (aug.getRaddrStart().getIpv4Address() != null) {
+                    request.remoteAddressStart =
+                            ipv4AddressNoZoneToArray(aug.getRaddrStart().getIpv4Address().getValue());
+                } else if (aug.getRaddrStart().getIpv6Address() != null) {
+                    request.remoteAddressStart = ipv6AddressNoZoneToArray(aug.getRaddrStart().getIpv6Address());
+                }
+            }
+        }
+        return request;
+    }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_after.json b/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_after.json
new file mode 100644 (file)
index 0000000..ac5f8c7
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "ikev2": {
+    "policy": [
+      {
+        "name": "testPolicy",
+        "lifetime": 0,
+        "connection-type": "both",
+        "authentication" : {
+          "rsa-signature" : "true"
+        },
+        "certificate": "/home/localadmin/certs/server-cert.pem",
+        "traffic-selectors": [
+          {
+            "ts-name":"TS1",
+            "protocol":0,
+            "remote-address-low":"192.168.124.0",
+            "remote-address-high":"192.168.124.255",
+            "remote-port-low":0,
+            "remote-port-high":65535
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_before.json b/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_before.json
new file mode 100644 (file)
index 0000000..3dfa393
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "ikev2": {
+    "policy": [
+      {
+        "name": "testPolicy",
+        "lifetime": 0,
+        "connection-type": "both",
+        "authentication" : {
+          "preshared-key" : "true"
+        },
+        "pre-shared-key": "0123456789012345",
+        "traffic-selectors": [
+          {
+            "ts-name":"TS1",
+            "protocol":0,
+            "local-address-low":"192.168.124.0",
+            "local-address-high":"192.168.124.255",
+            "local-port-low":0,
+            "local-port-high":65535
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/addIkev2Profile.json b/ipsec/ipsec-impl/src/test/resources/ikev2/addIkev2Profile.json
new file mode 100644 (file)
index 0000000..3dfa393
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "ikev2": {
+    "policy": [
+      {
+        "name": "testPolicy",
+        "lifetime": 0,
+        "connection-type": "both",
+        "authentication" : {
+          "preshared-key" : "true"
+        },
+        "pre-shared-key": "0123456789012345",
+        "traffic-selectors": [
+          {
+            "ts-name":"TS1",
+            "protocol":0,
+            "local-address-low":"192.168.124.0",
+            "local-address-high":"192.168.124.255",
+            "local-port-low":0,
+            "local-port-high":65535
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_ipv4.json b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_ipv4.json
new file mode 100644 (file)
index 0000000..f068bd7
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "identity" : {
+    "local":
+    {
+      "ipv4-address": "192.168.123.22"
+    }
+  }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_rfc822.json b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_rfc822.json
new file mode 100644 (file)
index 0000000..6e152d9
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "identity" : {
+    "local":
+    {
+      "rfc822-address-string": "[email protected]"
+    }
+  }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_fqdn.json b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_fqdn.json
new file mode 100644 (file)
index 0000000..514f841
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "identity" : {
+    "remote":
+    {
+      "fqdn-string": "vpp.home"
+    }
+  }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_ipv6.json b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_ipv6.json
new file mode 100644 (file)
index 0000000..0674d35
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "identity" : {
+    "remote":
+    {
+      "ipv6-address": "2001:DB8:0:0:8:800:200C:417A"
+    }
+  }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry.json b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry.json
new file mode 100644 (file)
index 0000000..c522ba2
--- /dev/null
@@ -0,0 +1,32 @@
+{
+    "sad": {
+      "sad-entries": [
+        {
+          "spi": 1002,
+          "direction": "outbound",
+          "sa-id": 10,
+          "security-protocol": "esp",
+          "sa-mode": "tunnel",
+          "esp": {
+            "authentication": {
+              "hmac-sha1-96": {
+                "key-str": "0123456789012346"
+              }
+            },
+            "encryption": {
+              "aes-128-cbc": {
+                "key-str": "9876543210987654"
+              }
+            }
+          },
+          "source-address": {
+            "ipv4-address": "192.168.1.1"
+          },
+          "destination-address": {
+            "ipv4-address": "192.168.1.2"
+          },
+          "anti-replay-window": 0
+        }
+      ]
+    }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_after.json b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_after.json
new file mode 100644 (file)
index 0000000..fa618a3
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "sad": {
+    "sad-entries": [
+      {
+        "spi": 1002,
+        "direction": "inbound",
+        "sa-id": 10,
+        "security-protocol": "ah",
+        "sa-mode": "transport",
+        "ah": {
+          "hmac-md5-96": {
+            "key-str": "0123456789012346"
+          }
+        },
+        "source-address": {
+          "ipv6-address": "2001::11"
+        },
+        "destination-address": {
+          "ipv6-address": "2001::12"
+        },
+        "anti-replay-window": 32
+      }
+    ]
+  }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_before.json b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_before.json
new file mode 100644 (file)
index 0000000..a88a146
--- /dev/null
@@ -0,0 +1,32 @@
+{
+    "sad": {
+      "sad-entries": [
+        {
+          "spi": 1002,
+          "direction": "outbound",
+          "sa-id": 10,
+          "security-protocol": "esp",
+          "sa-mode": "tunnel",
+          "esp": {
+            "authentication": {
+              "hmac-sha1-96": {
+                "key-str": "0123456789012346"
+              }
+            },
+            "encryption": {
+              "aes-128-cbc": {
+                "key-str": "9876543210987654"
+              }
+            }
+          },
+          "source-address": {
+            "ipv6-address": "2001::1"
+          },
+          "destination-address": {
+            "ipv6-address": "2001::10"
+          },
+          "anti-replay-window": 32
+        }
+      ]
+    }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/sadEntries/delSadEntry.json b/ipsec/ipsec-impl/src/test/resources/sadEntries/delSadEntry.json
new file mode 100644 (file)
index 0000000..23998d6
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "sad": {
+      "sad-entries": [
+        {
+          "spi": 1002,
+          "direction": "outbound",
+          "sa-id": 10
+        }
+      ]
+    }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd.json b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd.json
new file mode 100644 (file)
index 0000000..85fe81d
--- /dev/null
@@ -0,0 +1,31 @@
+{
+  "ipsec" : {
+    "spd": [
+      {
+        "spd-id": 10,
+        "spd-entries": [
+          {
+            "name": "test",
+            "priority":100,
+            "direction":"outbound",
+            "operation":"bypass",
+            "laddr-start":"192.168.124.0",
+            "laddr-stop":"192.168.124.255",
+            "raddr-start":"192.168.125.0",
+            "raddr-stop":"192.168.125.255"
+          },
+          {
+            "name": "TestSPDEntryIpv6",
+            "priority":100,
+            "direction":"inbound",
+            "operation":"bypass",
+            "laddr-start":"2001::1",
+            "laddr-stop":"2001::100",
+            "raddr-start":"2001::101",
+            "raddr-stop":"2001::200"
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_after.json b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_after.json
new file mode 100644 (file)
index 0000000..600dde4
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "ipsec" : {
+    "spd": [
+      {
+        "spd-entries": [
+          {
+            "name": "TestSPDEntryUpdate",
+            "priority":80,
+            "direction":"inbound",
+            "operation":"bypass",
+            "laddr-start":"2001::1",
+            "laddr-stop":"2001::100",
+            "raddr-start":"2001::101",
+            "raddr-stop":"2001::200"
+          }
+        ],
+        "spd-id": 10
+      }
+    ]
+  }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_before.json b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_before.json
new file mode 100644 (file)
index 0000000..be14bd6
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "ipsec" : {
+    "spd": [
+      {
+        "spd-entries": [
+          {
+            "name": "TestSPDEntryUpdate",
+            "priority":100,
+            "direction":"outbound",
+            "operation":"discard",
+            "laddr-start":"192.168.124.0",
+            "laddr-stop":"192.168.124.255",
+            "raddr-start":"192.168.125.0",
+            "raddr-stop":"192.168.125.255"
+          }
+        ],
+        "spd-id": 10
+      }
+    ]
+  }
+}
diff --git a/ipsec/pom.xml b/ipsec/pom.xml
new file mode 100644 (file)
index 0000000..471ade9
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2019 PANTHEON.tech.
+
+ 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.
+-->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <groupId>io.fd.hc2vpp.common</groupId>
+    <artifactId>hc2vpp-parent</artifactId>
+    <version>1.19.01-SNAPSHOT</version>
+    <relativePath>../common/hc2vpp-parent</relativePath>
+  </parent>
+
+  <groupId>io.fd.hc2vpp.ipsec</groupId>
+  <artifactId>ipsec-aggregator</artifactId>
+  <version>1.19.01-SNAPSHOT</version>
+  <name>${project.artifactId}</name>
+  <packaging>pom</packaging>
+  <modelVersion>4.0.0</modelVersion>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <description>Aggregator for Hc2vpp IPSec plugin</description>
+
+  <modules>
+    <module>ipsec-api</module>
+    <module>ipsec-impl</module>
+  </modules>
+
+  <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-install-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/pom.xml b/pom.xml
index 9b6714d..565c50b 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -57,5 +57,6 @@
     <module>bgp</module>
     <module>mpls</module>
     <module>srv6</module>
+    <module>ipsec</module>
   </modules>
 </project>
index 286bfda..ef3e37e 100644 (file)
@@ -67,6 +67,7 @@
       io.fd.hc2vpp.policer.PolicerModule,
       io.fd.hc2vpp.mpls.MplsModule,
       io.fd.hc2vpp.srv6.Srv6Module,
+      io.fd.hc2vpp.ipsec.IpsecModule
       <!-- Nsh module by default disabled, because it needs vpp-nsh plugin, which is not part of vpp codebase.-->
       // io.fd.hc2vpp.vppnsh.impl.VppNshModule,
       <!-- iOAM module by default disabled, because it needs ioam plugin (not part of vpp codebase.)-->
       <artifactId>bgp-prefix-sid</artifactId>
       <version>${hc2vpp.bgp.version}</version>
     </dependency>
+    <dependency>
+      <groupId>io.fd.hc2vpp.ipsec</groupId>
+      <artifactId>ipsec-impl</artifactId>
+      <version>${project.version}</version>
+    </dependency>
   </dependencies>
 </project>