HC2VPP-88: translation layer for af_packet interface management 69/13169/5
authorMarek Gradzki <[email protected]>
Wed, 20 Jun 2018 14:37:06 +0000 (16:37 +0200)
committerMarek Gradzki <[email protected]>
Fri, 22 Jun 2018 08:04:34 +0000 (10:04 +0200)
Includes postman collection with RESTCONF examples.

Change-Id: If6f7ba1e2e7ab37433ebc5215e4731f1193c62a2
Signed-off-by: Marek Gradzki <[email protected]>
v3po/postman_rest_collection.json
v3po/v3po2vpp/asciidoc/Readme.adoc
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesStateReaderFactory.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesWriterFactory.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/AfPacketCustomizer.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/AfPacketCustomizer.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslator.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/AfPacketCustomizerTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/AfPacketCustomizerTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslatorTest.java

index bff5594..965682f 100644 (file)
@@ -1,18 +1,16 @@
 {
        "info": {
-               "_postman_id": "5bad4634-e5cf-900e-9733-0976aa9bea64",
+               "_postman_id": "4a6ffe04-00bb-41a4-b64e-94b012c0c211",
                "name": "Honeycomb V3PO RESTCONF calls",
                "description": "Common mgmt operations on VPP core using Honeycomb REST interface",
                "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
        },
        "item": [
                {
-                       "_postman_id": "20099c89-1295-492c-a90f-6d7b7e505d98",
                        "name": "Loopback",
-                       "description": "",
+                       "description": null,
                        "item": [
                                {
-                                       "_postman_id": "8f3021a4-4a3b-4ee9-b229-992d542f6e73",
                                        "name": "Add loopback ifc - cfg ",
                                        "request": {
                                                "method": "PUT",
@@ -50,7 +48,6 @@
                                        "response": []
                                },
                                {
-                                       "_postman_id": "2d32776a-56ed-4f4b-b436-14a0d6e33a77",
                                        "name": "Delete loopback ifc - cfg ",
                                        "request": {
                                                "method": "DELETE",
                        ]
                },
                {
-                       "_postman_id": "4d5c9ca1-b61d-46f8-8ec1-19bf71111c7f",
                        "name": "Bridge Domain management",
-                       "description": "",
+                       "description": null,
                        "item": [
                                {
-                                       "_postman_id": "ea275a44-43ed-4635-a40b-16e090c55ab3",
                                        "name": "Create bridge domain - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "4dd8b1f3-fdbb-4f1a-87c5-54b4b511f8f6",
                                        "name": "Show bridge domain - cfg",
                                        "request": {
                                                "method": "GET",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "0acf1e74-318c-4ced-b8fd-c043465629e5",
                                        "name": "Show bridge domain - oper",
                                        "request": {
                                                "method": "GET",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "bc795b3d-533e-4881-9dde-d9c174b29a58",
                                        "name": "Add local0 to bridge domain",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "9e460d4d-af88-4f15-b6e5-6d2e63c7bdb3",
                                        "name": "Show local0 - cfg",
                                        "request": {
                                                "method": "GET",
                                                                "value": "application/json"
                                                        }
                                                ],
-                                               "body": {},
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": ""
+                                               },
                                                "url": {
                                                        "raw": "http://localhost:8183/restconf/config/ietf-interfaces:interfaces/interface/local0/",
                                                        "protocol": "http",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "0982eadb-109d-42b1-bb3c-bad07c3e0ef6",
                                        "name": "Show local0 - oper",
                                        "request": {
                                                "method": "GET",
                                                                "value": "application/json"
                                                        }
                                                ],
-                                               "body": {},
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": ""
+                                               },
                                                "url": {
                                                        "raw": "http://localhost:8183/restconf/operational/ietf-interfaces:interfaces-state/interface/local0/",
                                                        "protocol": "http",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "05181eab-b3fd-48ff-92ce-6dbedc49b070",
                                        "name": "Add L2 FIB entry (forward)",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "b3a3ba1e-afa0-41cf-88dd-2412d213ba67",
                                        "name": "Delete L2 FIB entry",
                                        "request": {
                                                "method": "DELETE",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "4b3c51ed-c9aa-431c-8a0e-305788727322",
                                        "name": "Add L2 FIB entry (static, forward)",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "0b8acac3-f9ad-4943-9779-5364b5408bd0",
                                        "name": "Add L2 FIB entry (filter)",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "cccac9dd-7e79-4176-b523-dbc33a99266d",
                                        "name": "Remove local0 from bridge domain",
                                        "request": {
                                                "method": "DELETE",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "1b89aecc-2831-4dee-97d8-4b17b529e355",
                                        "name": "Add ARP termination table entry ",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "03a0cc22-5952-4a4c-8d10-30590bf1f021",
                                        "name": "Delete ARP termination table entry ",
                                        "request": {
                                                "method": "DELETE",
                        ]
                },
                {
-                       "_postman_id": "28e6d8b2-3cb9-4534-990e-69b1735ebd5b",
                        "name": "Context",
-                       "description": "",
+                       "description": null,
                        "item": [
                                {
-                                       "_postman_id": "3e08d4a5-5d4a-4a09-ba30-95f7dedd1eb0",
                                        "name": "List naming contexts - context",
                                        "request": {
                                                "method": "GET",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "691cc54c-d8a6-42de-a302-d64c18c9f4e2",
                                        "name": "List disabled interfaces - context",
                                        "request": {
                                                "method": "GET",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "17ce9fce-4de7-4eb7-acaa-16086e599629",
                                        "name": "List ACL contexts - context",
                                        "request": {
                                                "method": "GET",
                        ]
                },
                {
-                       "_postman_id": "37be85a9-2f50-43e5-8606-d517f6429aea",
                        "name": "ETH",
                        "description": "Example requests for management of Ethernet type interfaces",
                        "item": [
                                {
-                                       "_postman_id": "e05674d3-ec39-43bc-acba-96cb0319b8c5",
                                        "name": "Set interface mtu",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "c0665d69-6d64-4a68-8580-2d812e431961",
                                        "name": "Get interface cfg",
                                        "request": {
                                                "method": "GET",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "f0ef21c4-c8f0-4479-9a53-5cd6f2d167c6",
                                        "name": "Get interface - oper",
                                        "request": {
                                                "method": "GET",
                        ]
                },
                {
-                       "_postman_id": "d303e470-87e9-4e1c-9f57-0b1eb1e8d1b3",
                        "name": "GRE-TUNNEL",
-                       "description": "",
+                       "description": null,
                        "item": [
                                {
-                                       "_postman_id": "4df072e4-901e-4f82-b318-cd89e5b88ef3",
                                        "name": "Add gre ifc - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "6fc51538-e99d-4f8e-a11b-d39d04d1a5be",
                                        "name": "Delete gre ifc - cfg",
                                        "request": {
                                                "method": "DELETE",
                        ]
                },
                {
-                       "_postman_id": "c75d6e5b-a972-40c2-b149-8e9eee2a110c",
                        "name": "PBB",
-                       "description": "",
+                       "description": null,
                        "item": [
                                {
-                                       "_postman_id": "2bc0e030-c016-4cb3-8ce2-9424ca75d70e",
                                        "name": "Enable local0 + configure Pbb",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "43cdd8a0-708f-4d92-a08b-ef588bb2a9c0",
                                        "name": "Update ppb rewrite",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "1a18c8ca-344c-4fab-a5e5-858bd5ffac2e",
                                        "name": "Get ppb rewrite",
                                        "request": {
                                                "method": "GET",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "0b119f89-6436-4e53-837f-a7645dcfcfc9",
                                        "name": "Disable ppb rewrite",
                                        "request": {
                                                "method": "DELETE",
                        ]
                },
                {
-                       "_postman_id": "e6365da5-8f1e-41a4-a368-46db86851e3f",
                        "name": "IP",
-                       "description": "",
+                       "description": null,
                        "item": [
                                {
-                                       "_postman_id": "a6921252-acf0-409d-8861-317c30553f43",
                                        "name": "Ip Neighbour Get",
                                        "request": {
                                                "method": "GET",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "a310f762-5438-4b9c-86cf-ef98964693a8",
                                        "name": "Ip Neighbour Add",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "822e5779-6fb3-4358-825b-7b0c8d100846",
                                        "name": "Ip Neighbour Delete",
                                        "request": {
                                                "method": "DELETE",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "46eb69c2-48e2-4cc2-8649-1684104b705a",
                                        "name": "Read local0 - oper",
                                        "request": {
                                                "method": "GET",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "b78adf18-8ee3-419b-b08a-d95a633f4d2f",
                                        "name": "Set ipv4 local0 interface - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "5576d8e1-8dfe-4baf-9755-f3042424d3eb",
                                        "name": "Remove ipv4 from local0 interface - cfg",
                                        "request": {
                                                "method": "DELETE",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "799b95f1-a743-46d5-8c57-bd40cda7c636",
                                        "name": "Set ipv4 local0 interface - cfg netmask",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "71645064-7551-4556-a418-5cef82e53e9c",
                                        "name": "Read local0/ipv4 - oper",
                                        "request": {
                                                "method": "GET",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "87da0992-97d4-46ab-abea-85cc8f3cfb72",
                                        "name": "Read local0/ipv4 - cfg",
                                        "request": {
                                                "method": "GET",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "a270bf57-133f-4756-9777-15d477ec84cb",
                                        "name": "Set ipv4 for sub-interface - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "cad56b78-12b4-4968-bed1-b6fefb4b066d",
                                        "name": "Set local0 as unnumbered (use GigabitEthernet0/8/0)",
                                        "request": {
                                                "method": "PUT",
                        ]
                },
                {
-                       "_postman_id": "1c5a1eb8-1e0e-4c17-9865-974d76122b75",
                        "name": "Proxy Arp",
-                       "description": "",
+                       "description": null,
                        "item": [
                                {
-                                       "_postman_id": "6a8888c4-1e77-4017-9af4-a547c2be6308",
                                        "name": "Add arp proxy range #1",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "348eabc8-47e1-47a1-9044-28e2508473db",
                                        "name": "Add arp proxy range #2",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "2254cd6a-0022-4ada-b740-80f7e0995235",
                                        "name": "Enable proxy arp for local0",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "cc27a6ff-a194-4c5a-b665-28f50e0cec8b",
                                        "name": "Delete arp proxy range #1",
                                        "request": {
                                                "method": "DELETE",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "4a0e534e-31c4-400d-94c6-54ba8d0adad6",
                                        "name": "Delete arp proxy range #2",
                                        "request": {
                                                "method": "DELETE",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "c599da02-cc49-415a-b9cf-522da147f743",
                                        "name": "Disable proxy arp for local0",
                                        "request": {
                                                "method": "DELETE",
                        ]
                },
                {
-                       "_postman_id": "74f93062-2b4f-4e30-aed2-a39fe9a2183e",
                        "name": "SPAN",
-                       "description": "",
+                       "description": null,
                        "item": [
                                {
-                                       "_postman_id": "f5a08951-cff3-4a7e-9d96-9dedc343c034",
                                        "name": "Set port mirroring local0 -> GigabiteEthernet0/8/0",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "5e12862a-528a-4dac-8fd2-a3613dcf5f37",
                                        "name": "Read port mirroring",
                                        "request": {
                                                "method": "GET",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "baba13ea-47ac-4a8e-87f3-624728f68cda",
                                        "name": "Delete port mirroring local0 -> GigabiteEthernet0/8/0",
                                        "request": {
                                                "method": "DELETE",
                        ]
                },
                {
-                       "_postman_id": "55f58331-d246-46fd-9943-8d26264d8c34",
                        "name": "TAP",
-                       "description": "",
+                       "description": null,
                        "item": [
                                {
-                                       "_postman_id": "bad09c1a-de5c-41ce-a6f9-866e1471c72f",
                                        "name": "Add simple tap ifc -cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "433127d4-cf54-4b99-93ca-f2cedc02dcd4",
                                        "name": "Add complex tap ifc - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "3d90af20-03e9-40d6-9d8d-05f9dfef7866",
                                        "name": "Modify complex tap ifc - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "0cbcde4f-80e7-4a9c-a97e-48e91c39bbe0",
                                        "name": "Delete complex tap ifc - cfg",
                                        "request": {
                                                "method": "DELETE",
                        ]
                },
                {
-                       "_postman_id": "5e4f2f9f-2356-4f5d-b88c-a81e12f51dad",
                        "name": "VHOST",
-                       "description": "",
+                       "description": null,
                        "item": [
                                {
-                                       "_postman_id": "80c234b8-ca6c-42a7-8dfb-5967d1868eda",
                                        "name": "Add vhost user ifc - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "f406bdcd-4eaa-41ad-94a1-a5d8110d0022",
                                        "name": "Modify vhost user ifc - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "142af8b2-1ed3-466e-9006-42d8183fa3af",
                                        "name": "Delete vhost user ifc - cfg",
                                        "request": {
                                                "method": "DELETE",
                        ]
                },
                {
-                       "_postman_id": "b0012a4c-6871-460b-9a81-f438cb52763d",
                        "name": "VLAN",
-                       "description": "",
+                       "description": null,
                        "item": [
                                {
-                                       "_postman_id": "2805bb68-ddcc-4c7c-81d8-60dcd45578e9",
                                        "name": "Add sub interface - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "0d66d2e9-5502-454d-a98a-dd9f1ecc12ab",
                                        "name": "Enable GigabitEthernet0/9/0 interface - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "0b2e7523-9058-4150-9351-2131b6d378fd",
                                        "name": "Enable GigabitEthernet0/9/0.1 interface - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "340bcd77-72af-4808-88df-aed71b8c015c",
                                        "name": "Add sub interface to bridge-domain",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "043d9429-4c87-4e7a-9f59-5b59da05c051",
                                        "name": "Enable tag-rewrite push - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "e84519dd-acd7-46c0-949f-8de3d247ca3f",
                                        "name": "Enable tag-rewrite pop 1 - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "88f5d1f6-ae07-44b3-a43e-4f7b22fe9425",
                                        "name": "Enable tag-rewrite translate 1-2 - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "9c657ac7-fd34-4578-abd5-33ffc7e1bfbf",
                                        "name": "Disable tag-rewrite - cfg",
                                        "request": {
                                                "method": "DELETE",
                        ]
                },
                {
-                       "_postman_id": "a4941d69-03d1-4c75-a943-9f120ce5bb3d",
                        "name": "VXLAN-GPE-TUNNEL",
-                       "description": "",
+                       "description": null,
                        "item": [
                                {
-                                       "_postman_id": "ce1d25ee-dfec-424d-b03b-88b8ee40b2fa",
                                        "name": "Add vxlan-gpe - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "3b16e4d1-cd30-4707-a4d0-a8870f512408",
                                        "name": "Delete vxlan-gpe - cfg",
                                        "request": {
                                                "method": "DELETE",
                        ]
                },
                {
-                       "_postman_id": "56789d99-20d2-4470-8a5d-de9d7f7a8d50",
                        "name": "VXLAN-TUNNEL",
-                       "description": "",
+                       "description": null,
                        "item": [
                                {
-                                       "_postman_id": "27bc98e0-0aac-4f9b-8f6a-4d8845683821",
                                        "name": "Add virtual ifc - cfg",
                                        "request": {
                                                "method": "PUT",
                                        "response": []
                                },
                                {
-                                       "_postman_id": "7d6082c3-e098-42ff-8c35-48957473ca73",
                                        "name": "Delete virtual ifc - cfg",
                                        "request": {
                                                "method": "DELETE",
                        ]
                },
                {
-                       "_postman_id": "d32ff862-e554-4f4f-818a-5728794bb1b9",
+                       "name": "AF_PACKET",
+                       "description": "",
+                       "item": [
+                               {
+                                       "name": "Add af_packet interface",
+                                       "request": {
+                                               "method": "PUT",
+                                               "header": [
+                                                       {
+                                                               "key": "Authorization",
+                                                               "value": "Basic YWRtaW46YWRtaW4="
+                                                       },
+                                                       {
+                                                               "key": "Content-Type",
+                                                               "value": "application/json"
+                                                       }
+                                               ],
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": "{\r\n    \r\n        \"interface\": [\r\n            {\r\n                \"name\": \"veth0\",\r\n                \"description\": \"for testing purposes\",\r\n                \"type\": \"v3po:af-packet\",\r\n                \"af-packet\": {\r\n                \t\"host-interface-name\": \"veth0\"\r\n                }\r\n            }\r\n        ]\r\n    \r\n}"
+                                               },
+                                               "url": {
+                                                       "raw": "http://localhost:8183/restconf/config/ietf-interfaces:interfaces/interface/veth0",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "localhost"
+                                                       ],
+                                                       "port": "8183",
+                                                       "path": [
+                                                               "restconf",
+                                                               "config",
+                                                               "ietf-interfaces:interfaces",
+                                                               "interface",
+                                                               "veth0"
+                                                       ]
+                                               },
+                                               "description": "Creates host (af_packet) interface in VPP.\nRequires creating veth pair in the linux first:\n\nsudo ip link add veth0 type veth peer name veth1\n\nCorresponds to following CLI command:\n\nvppctl create host-interface name veth0\n\nMore info:\nhttps://wiki.fd.io/view/VPP/Tutorial_Routing_and_Switching#Virtual_Network_Setup"
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Modify af_packet interface",
+                                       "request": {
+                                               "method": "PUT",
+                                               "header": [
+                                                       {
+                                                               "key": "Authorization",
+                                                               "value": "Basic YWRtaW46YWRtaW4="
+                                                       },
+                                                       {
+                                                               "key": "Content-Type",
+                                                               "value": "application/json"
+                                                       }
+                                               ],
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": "{\r\n    \r\n        \"interface\": [\r\n            {\r\n                \"name\": \"veth0\",\r\n                \"description\": \"for testing purposes\",\r\n                \"type\": \"v3po:af-packet\",\r\n                \"af-packet\": {\r\n                \t\"host-interface-name\": \"veth0\",\r\n                    \"mac\" : \"01:02:03:04:05:06\"\r\n                }\r\n            }\r\n        ]\r\n    \r\n}"
+                                               },
+                                               "url": {
+                                                       "raw": "http://localhost:8183/restconf/config/ietf-interfaces:interfaces/interface/veth0",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "localhost"
+                                                       ],
+                                                       "port": "8183",
+                                                       "path": [
+                                                               "restconf",
+                                                               "config",
+                                                               "ietf-interfaces:interfaces",
+                                                               "interface",
+                                                               "veth0"
+                                                       ]
+                                               },
+                                               "description": "Updates mac address of af_packet interface.\n\nSince VPP does not support ad-packet update,\nthe request is internally translated into delete + create."
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Delete af_packet interface",
+                                       "request": {
+                                               "method": "DELETE",
+                                               "header": [
+                                                       {
+                                                               "key": "Authorization",
+                                                               "value": "Basic YWRtaW46YWRtaW4="
+                                                       },
+                                                       {
+                                                               "key": "Content-Type",
+                                                               "value": "application/json"
+                                                       }
+                                               ],
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": ""
+                                               },
+                                               "url": {
+                                                       "raw": "http://localhost:8183/restconf/config/ietf-interfaces:interfaces/interface/veth0",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "localhost"
+                                                       ],
+                                                       "port": "8183",
+                                                       "path": [
+                                                               "restconf",
+                                                               "config",
+                                                               "ietf-interfaces:interfaces",
+                                                               "interface",
+                                                               "veth0"
+                                                       ]
+                                               },
+                                               "description": "Deletes host (af_packet) interface in VPP.\n\nCorresponds to following CLI command:\n\nvppctl delete host-interface name veth0"
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Show af_packet interface configuration",
+                                       "request": {
+                                               "method": "GET",
+                                               "header": [
+                                                       {
+                                                               "key": "Authorization",
+                                                               "value": "Basic YWRtaW46YWRtaW4="
+                                                       },
+                                                       {
+                                                               "key": "Content-Type",
+                                                               "value": "application/json"
+                                                       }
+                                               ],
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": ""
+                                               },
+                                               "url": {
+                                                       "raw": "http://localhost:8183/restconf/config/ietf-interfaces:interfaces/interface/veth0",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "localhost"
+                                                       ],
+                                                       "port": "8183",
+                                                       "path": [
+                                                               "restconf",
+                                                               "config",
+                                                               "ietf-interfaces:interfaces",
+                                                               "interface",
+                                                               "veth0"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Show af_packet interface state",
+                                       "request": {
+                                               "method": "GET",
+                                               "header": [
+                                                       {
+                                                               "key": "Authorization",
+                                                               "value": "Basic YWRtaW46YWRtaW4="
+                                                       },
+                                                       {
+                                                               "key": "Content-Type",
+                                                               "value": "application/json"
+                                                       }
+                                               ],
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": ""
+                                               },
+                                               "url": {
+                                                       "raw": "http://localhost:8183/restconf/operational/ietf-interfaces:interfaces-state/interface/veth0",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "localhost"
+                                                       ],
+                                                       "port": "8183",
+                                                       "path": [
+                                                               "restconf",
+                                                               "operational",
+                                                               "ietf-interfaces:interfaces-state",
+                                                               "interface",
+                                                               "veth0"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               }
+                       ]
+               },
+               {
                        "name": "List ifcs - cfg",
                        "request": {
                                "method": "GET",
                        "response": []
                },
                {
-                       "_postman_id": "ffa170fe-f846-4abc-b5a8-4cd8383aa035",
                        "name": "List ifcs - oper",
                        "request": {
                                "method": "GET",
                        "response": []
                },
                {
-                       "_postman_id": "4e91b318-dba1-42a3-b48b-77324077d431",
                        "name": "Enable local0 interface - cfg",
                        "request": {
                                "method": "PUT",
                        "response": []
                },
                {
-                       "_postman_id": "3dded5ad-bbb4-41e5-80bd-cd63ae39d701",
                        "name": "Set vrf id for local0 - cfg",
                        "request": {
                                "method": "PUT",
index db779a1..639e2fb 100644 (file)
@@ -9,6 +9,7 @@ Current order of v3po-api writers is:
 
 . BridgeDomain
 . VhostUser
+. AfPacket
 . VxlanGpe
 . Tap
 . Vxlan
@@ -50,6 +51,7 @@ Contexts
 . Ethernet
 . Tap
 . VhostUser
+. AfPacket
 . Vxlan
 . VxlanGpe
 . L2
index eaacb13..8b27c91 100644 (file)
@@ -28,6 +28,7 @@ import io.fd.hc2vpp.v3po.interfacesstate.InterfaceRoutingCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.L2Customizer;
 import io.fd.hc2vpp.v3po.interfacesstate.TapCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.VhostUserCustomizer;
+import io.fd.hc2vpp.v3po.interfacesstate.AfPacketCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.VxlanCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.VxlanGpeCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
@@ -52,6 +53,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.SpanBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.Tap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.VhostUser;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.AfPacket;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.Vxlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.VxlanGpe;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.span.state.attributes.MirroredInterfaces;
@@ -119,6 +121,9 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
         //    VhostUser
         registry.add(new GenericInitReader<>(vppIfcAugId.child(VhostUser.class),
                 new VhostUserCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager)));
+        //    AfPacket
+        registry.add(new GenericInitReader<>(vppIfcAugId.child(AfPacket.class),
+                new AfPacketCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager)));
         //    Vxlan
         registry.add(new GenericInitReader<>(vppIfcAugId.child(Vxlan.class),
                 new VxlanCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager)));
index 6334004..9cc351e 100644 (file)
@@ -30,6 +30,7 @@ import io.fd.hc2vpp.v3po.interfaces.L2Customizer;
 import io.fd.hc2vpp.v3po.interfaces.LoopbackCustomizer;
 import io.fd.hc2vpp.v3po.interfaces.TapCustomizer;
 import io.fd.hc2vpp.v3po.interfaces.VhostUserCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.AfPacketCustomizer;
 import io.fd.hc2vpp.v3po.interfaces.VxlanCustomizer;
 import io.fd.hc2vpp.v3po.interfaces.VxlanGpeCustomizer;
 import io.fd.hc2vpp.v3po.interfaces.pbb.PbbRewriteCustomizer;
@@ -53,6 +54,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.Span;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.Tap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.VhostUser;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.AfPacket;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.Vxlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.VxlanGpe;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.span.attributes.MirroredInterfaces;
@@ -102,6 +104,10 @@ public final class InterfacesWriterFactory implements WriterFactory {
         final InstanceIdentifier<VhostUser> vhostId = VPP_IFC_AUG_ID.child(VhostUser.class);
         registry.addBefore(new GenericWriter<>(vhostId, new VhostUserCustomizer(jvpp, ifcNamingContext)),
                 ifcId);
+        // AfPacket(Needs to be executed before Interface customizer) =
+        final InstanceIdentifier<AfPacket> afpacketId = VPP_IFC_AUG_ID.child(AfPacket.class);
+        registry.addBefore(new GenericWriter<>(afpacketId, new AfPacketCustomizer(jvpp, ifcNamingContext)),
+                ifcId);
         // Vxlan(Needs to be executed before Interface customizer) =
         final InstanceIdentifier<Vxlan> vxlanId = VPP_IFC_AUG_ID.child(Vxlan.class);
         registry.addBefore(new GenericWriter<>(vxlanId, new VxlanCustomizer(jvpp, ifcNamingContext, ifcDisableContext)),
@@ -124,8 +130,8 @@ public final class InterfacesWriterFactory implements WriterFactory {
         registry.addBefore(new GenericWriter<>(greId, new GreCustomizer(jvpp, ifcNamingContext)),
                 ifcId);
 
-
-        final Set<InstanceIdentifier<?>> specificIfcTypes = Sets.newHashSet(vhostId, vxlanId, vxlanGpeId, tapId, loopbackId);
+        final Set<InstanceIdentifier<?>> specificIfcTypes =
+            Sets.newHashSet(vhostId, afpacketId, vxlanId, vxlanGpeId, tapId, loopbackId);
 
         // Ethernet =
         registry.add(new GenericWriter<>(VPP_IFC_AUG_ID.child(Ethernet.class),
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/AfPacketCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/AfPacketCustomizer.java
new file mode 100644 (file)
index 0000000..67d879b
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2018 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.interfaces;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.AbstractInterfaceTypeCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.MacTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.AfPacketCreate;
+import io.fd.vpp.jvpp.core.dto.AfPacketCreateReply;
+import io.fd.vpp.jvpp.core.dto.AfPacketDelete;
+import io.fd.vpp.jvpp.core.dto.AfPacketDeleteReply;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.AfPacket;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AfPacketCustomizer extends AbstractInterfaceTypeCustomizer<AfPacket>
+    implements MacTranslator, JvppReplyConsumer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AfPacketCustomizer.class);
+    private final NamingContext interfaceContext;
+
+    public AfPacketCustomizer(@Nonnull final FutureJVppCore vppApi, @Nonnull final NamingContext interfaceContext) {
+        super(vppApi);
+        this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    protected Class<? extends InterfaceType> getExpectedInterfaceType() {
+        return org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.AfPacket.class;
+    }
+
+    @Override
+    protected final void writeInterface(@Nonnull final InstanceIdentifier<AfPacket> id,
+                                        @Nonnull final AfPacket dataAfter, @Nonnull final WriteContext writeContext)
+        throws WriteFailedException {
+        final String swIfName = id.firstKeyOf(Interface.class).getName();
+        final int swIfIndex = createAfPacketIfc(id, swIfName, dataAfter);
+
+        // Add new interface to our interface context
+        interfaceContext.addName(swIfIndex, swIfName, writeContext.getMappingContext());
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<AfPacket> id,
+                                        @Nonnull final AfPacket dataBefore, @Nonnull final WriteContext writeContext)
+        throws WriteFailedException {
+        final String swIfName = id.firstKeyOf(Interface.class).getName();
+        deleteAfPacketIfc(id, swIfName, dataBefore);
+
+        // Remove interface from interface context
+        interfaceContext.removeName(swIfName, writeContext.getMappingContext());
+    }
+
+    private int createAfPacketIfc(final InstanceIdentifier<AfPacket> id, final String swIfName, final AfPacket afPacket)
+        throws WriteFailedException {
+        LOG.debug("Creating af_packet interface {}: {}", swIfName, afPacket);
+        final CompletionStage<AfPacketCreateReply> createAfPacketIfReplyCompletionStage =
+            getFutureJVpp().afPacketCreate(getCreateRequest(afPacket));
+        final AfPacketCreateReply reply =
+            getReplyForCreate(createAfPacketIfReplyCompletionStage.toCompletableFuture(), id, afPacket);
+        LOG.debug("Af_packet interface {} created successfully: {}", swIfName, afPacket);
+        return reply.swIfIndex;
+    }
+
+    private AfPacketCreate getCreateRequest(@Nonnull final AfPacket afPacket) {
+        final AfPacketCreate request = new AfPacketCreate();
+        checkArgument(afPacket.getHostInterfaceName() != null,
+            "host-interface-name is mandatory for af-packet interface");
+        request.hostIfName = afPacket.getHostInterfaceName().getBytes(StandardCharsets.UTF_8);
+        checkArgument(request.hostIfName.length <= 64,
+            "Interface name for af_packet interface should not be longer than 64 bytes, but was %s",
+            request.hostIfName.length);
+        final PhysAddress mac = afPacket.getMac();
+        if (mac == null) {
+            request.useRandomHwAddr = 1;
+            request.hwAddr = new byte[6];
+        } else {
+            request.useRandomHwAddr = 0;
+            request.hwAddr = parseMac(mac.getValue());
+        }
+        return request;
+    }
+
+    private void deleteAfPacketIfc(final InstanceIdentifier<AfPacket> id, final String swIfName,
+                                   final AfPacket afPacket) throws WriteFailedException {
+        LOG.debug("Deleting af_packet interface {}: {}", swIfName, afPacket);
+        final CompletionStage<AfPacketDeleteReply> deleteAfPacketIfReplyCompletionStage =
+            getFutureJVpp().afPacketDelete(getDeleteRequest(afPacket));
+
+        getReplyForDelete(deleteAfPacketIfReplyCompletionStage.toCompletableFuture(), id);
+        LOG.debug("Af_packet interface {} deleted successfully: {}", swIfName, afPacket);
+    }
+
+    private AfPacketDelete getDeleteRequest(@Nonnull final AfPacket afPacket) {
+        final AfPacketDelete request = new AfPacketDelete();
+        request.hostIfName = afPacket.getHostInterfaceName().getBytes(StandardCharsets.UTF_8);
+        return request;
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/AfPacketCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/AfPacketCustomizer.java
new file mode 100644 (file)
index 0000000..132ca7f
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2018 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.interfacesstate;
+
+import static java.lang.String.format;
+
+import com.google.common.annotations.VisibleForTesting;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
+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.RWUtils;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.honeycomb.translate.util.read.cache.StaticCacheKeyFactory;
+import io.fd.vpp.jvpp.core.dto.AfPacketDetails;
+import io.fd.vpp.jvpp.core.dto.AfPacketDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.AfPacketDump;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.AfPacket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.AfPacketBuilder;
+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 AfPacketCustomizer implements InitializingReaderCustomizer<AfPacket, AfPacketBuilder>,
+    InterfaceDataTranslator, JvppReplyConsumer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AfPacketCustomizer.class);
+    private NamingContext interfaceContext;
+    private final InterfaceCacheDumpManager dumpManager;
+    private final DumpCacheManager<AfPacketDetailsReplyDump, Void> afPacketDumpManager;
+
+    public AfPacketCustomizer(@Nonnull final FutureJVppCore jvpp,
+                              @Nonnull final NamingContext interfaceContext,
+                              @Nonnull final InterfaceCacheDumpManager dumpManager) {
+        this.interfaceContext = interfaceContext;
+        this.dumpManager = dumpManager;
+        this.afPacketDumpManager =
+            new DumpCacheManager.DumpCacheManagerBuilder<AfPacketDetailsReplyDump, Void>()
+                .withCacheKeyFactory(new StaticCacheKeyFactory(AfPacketCustomizer.class.getName() + "_dump",
+                    AfPacketDetailsReplyDump.class))
+                .withExecutor((identifier, params) -> {
+                    final CompletionStage<AfPacketDetailsReplyDump> cs = jvpp.afPacketDump(new AfPacketDump());
+                    return getReplyForRead(cs.toCompletableFuture(), identifier);
+                }).build();
+    }
+
+    @Override
+    public void merge(@Nonnull Builder<? extends DataObject> parentBuilder, @Nonnull AfPacket readValue) {
+        ((VppInterfaceStateAugmentationBuilder) parentBuilder).setAfPacket(readValue);
+    }
+
+    @Nonnull
+    @Override
+    public AfPacketBuilder getBuilder(@Nonnull InstanceIdentifier<AfPacket> id) {
+        return new AfPacketBuilder();
+    }
+
+    @Override
+    public void readCurrentAttributes(@Nonnull final InstanceIdentifier<AfPacket> id,
+                                      @Nonnull final AfPacketBuilder builder,
+                                      @Nonnull final ReadContext ctx) throws ReadFailedException {
+        final InterfaceKey key = id.firstKeyOf(Interface.class);
+        final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext());
+        final SwInterfaceDetails ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName());
+
+        if (!isInterfaceOfType(
+            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.AfPacket.class,
+            ifcDetails)) {
+            return;
+        }
+
+        final AfPacketDetailsReplyDump dump = afPacketDumpManager.getDump(id, ctx.getModificationCache())
+            .or(new AfPacketDetailsReplyDump());
+        // Relying here that parent InterfaceCustomizer was invoked first to fill in the context with initial ifc mapping
+        final AfPacketDetails afPacketDetails = dump.afPacketDetails.stream()
+            .filter(detail -> detail.swIfIndex == index)
+            .findFirst()
+            .orElseThrow(() -> new IllegalArgumentException(format("AfPacket interface %s not found", key.getName())));
+        LOG.trace("AfPacket interface: {} attributes returned from VPP: {}", key.getName(), afPacketDetails);
+
+        builder.setMac(new PhysAddress(vppPhysAddrToYang(ifcDetails.l2Address)));
+        builder.setHostInterfaceName(toString(afPacketDetails.hostIfName));
+
+        LOG.debug("AfPacket interface: {}, id: {} attributes read as: {}", key.getName(), index, builder);
+    }
+
+    @Nonnull
+    @Override
+    public Initialized<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.AfPacket> init(
+        @Nonnull final InstanceIdentifier<AfPacket> id,
+        @Nonnull final AfPacket readValue,
+        @Nonnull final ReadContext ctx) {
+        return Initialized.create(getCfgId(id),
+            new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.AfPacketBuilder()
+                .setHostInterfaceName(readValue.getHostInterfaceName())
+                .setMac(readValue.getMac())
+                .build());
+    }
+
+    @VisibleForTesting
+    static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.AfPacket> getCfgId(
+        final InstanceIdentifier<AfPacket> id) {
+        return InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class))
+            .augmentation(VppInterfaceAugmentation.class)
+            .child(
+                org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.AfPacket.class);
+    }
+}
\ No newline at end of file
index 75554d4..5a4fbdd 100644 (file)
@@ -34,6 +34,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.re
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Gauge64;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.AfPacket;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.GreTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.Loopback;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.Tap;
@@ -157,6 +158,10 @@ public interface InterfaceDataTranslator extends ByteDataTranslator, JvppReplyCo
             return VhostUser.class;
         }
 
+        if (interfaceName.startsWith("host-")) {
+            return AfPacket.class;
+        }
+
         if (interfaceName.startsWith("loop")) {
             return Loopback.class;
         }
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/AfPacketCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/AfPacketCustomizerTest.java
new file mode 100644 (file)
index 0000000..2834e91
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2018 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.interfaces;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+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.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.AfPacketCreate;
+import io.fd.vpp.jvpp.core.dto.AfPacketCreateReply;
+import io.fd.vpp.jvpp.core.dto.AfPacketDelete;
+import io.fd.vpp.jvpp.core.dto.AfPacketDeleteReply;
+import java.nio.charset.StandardCharsets;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.AfPacket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.AfPacketBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AfPacketCustomizerTest extends WriterCustomizerTest implements Ipv4Translator {
+
+    private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+    private static final int IFACE_ID = 1;
+    private static final String IFACE_NAME = "veth1";
+    private static final InstanceIdentifier<AfPacket> ID =
+        InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+            .augmentation(VppInterfaceAugmentation.class).child(AfPacket.class);
+    private AfPacketCustomizer customizer;
+
+    @Override
+    public void setUpTest() throws Exception {
+        InterfaceTypeTestUtils.setupWriteContext(writeContext,
+            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.AfPacket.class);
+        customizer = new AfPacketCustomizer(api, new NamingContext("generatedInterfaceName", IFC_TEST_INSTANCE));
+
+        final AfPacketCreateReply createReply = new AfPacketCreateReply();
+        createReply.swIfIndex = IFACE_ID;
+        when(api.afPacketCreate(any())).thenReturn(future(createReply));
+        when(api.afPacketDelete(any())).thenReturn(future(new AfPacketDeleteReply()));
+    }
+
+    @Test
+    public void testWriteRandomMac() throws WriteFailedException {
+        final AfPacketCreate expectedCreateRequest = new AfPacketCreate();
+        expectedCreateRequest.hostIfName = IFACE_NAME.getBytes(StandardCharsets.UTF_8);
+        expectedCreateRequest.useRandomHwAddr = 1;
+        expectedCreateRequest.hwAddr = new byte[6];
+
+        customizer.writeCurrentAttributes(ID, afPacket(), writeContext);
+
+        verify(api).afPacketCreate(expectedCreateRequest);
+        verify(mappingContext).put(mappingIid(IFACE_NAME, IFC_TEST_INSTANCE), mapping(IFACE_NAME, IFACE_ID).get());
+    }
+
+    @Test
+    public void testWriteExplicitMac() throws WriteFailedException {
+        final AfPacket afPacket = afPacket("01:02:03:04:05:06");
+
+        final AfPacketCreate expectedCreateRequest = new AfPacketCreate();
+        expectedCreateRequest.hostIfName = IFACE_NAME.getBytes(StandardCharsets.UTF_8);
+        expectedCreateRequest.useRandomHwAddr = 0;
+        expectedCreateRequest.hwAddr = new byte[] {1, 2, 3, 4, 5, 6};
+
+        customizer.writeCurrentAttributes(ID, afPacket, writeContext);
+
+        verify(api).afPacketCreate(expectedCreateRequest);
+        verify(mappingContext).put(mappingIid(IFACE_NAME, IFC_TEST_INSTANCE), mapping(IFACE_NAME, IFACE_ID).get());
+    }
+
+    @Test
+    public void testDelete() throws WriteFailedException {
+        final AfPacket afPacket = afPacket("02:03:04:05:06:07");
+        final AfPacketDelete expectedDeleteRequest = new AfPacketDelete();
+        expectedDeleteRequest.hostIfName = IFACE_NAME.getBytes(StandardCharsets.UTF_8);
+
+        customizer.deleteCurrentAttributes(ID, afPacket, writeContext);
+
+        verify(api).afPacketDelete(expectedDeleteRequest);
+        verify(mappingContext).delete(eq(mappingIid(IFACE_NAME, IFC_TEST_INSTANCE)));
+    }
+
+    private static AfPacket afPacket() {
+        return new AfPacketBuilder().setHostInterfaceName(IFACE_NAME).build();
+    }
+
+    private static AfPacket afPacket(String mac) {
+        return new AfPacketBuilder().setHostInterfaceName(IFACE_NAME).setMac(new PhysAddress(mac)).build();
+    }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/AfPacketCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/AfPacketCustomizerTest.java
new file mode 100644 (file)
index 0000000..809c4ae
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2018 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.interfacesstate;
+
+import static io.fd.hc2vpp.v3po.interfacesstate.AfPacketCustomizer.getCfgId;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.read.InitializingReaderCustomizerTest;
+import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.vpp.jvpp.core.dto.AfPacketDetails;
+import io.fd.vpp.jvpp.core.dto.AfPacketDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import java.util.Collections;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VppInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.AfPacket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.AfPacketBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AfPacketCustomizerTest extends InitializingReaderCustomizerTest<AfPacket, AfPacketBuilder>
+    implements InterfaceDumpHelper {
+    private static final String IFC_CTX_NAME = "ifc-test-instance";
+    private static final String IF_NAME = "host-veth1";
+    private static final int IF_INDEX = 1;
+    private static final InstanceIdentifier<AfPacket> IID =
+        InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+            .augmentation(VppInterfaceStateAugmentation.class).child(AfPacket.class);
+
+    private NamingContext interfaceContext;
+
+    @Mock
+    private InterfaceCacheDumpManager dumpCacheManager;
+
+    public AfPacketCustomizerTest() {
+        super(AfPacket.class, VppInterfaceStateAugmentationBuilder.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        interfaceContext = new NamingContext("generatedInterfaceName", IFC_CTX_NAME);
+        defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
+    }
+
+    @Override
+    protected ReaderCustomizer<AfPacket, AfPacketBuilder> initCustomizer() {
+        return new AfPacketCustomizer(api, interfaceContext, dumpCacheManager);
+    }
+
+    @Test
+    public void testRead() throws ReadFailedException {
+        final AfPacketBuilder builder = mock(AfPacketBuilder.class);
+        when(dumpCacheManager.getInterfaceDetail(IID, ctx, IF_NAME)).thenReturn(ifaceDetails());
+        when(api.afPacketDump(any())).thenReturn(future(afPacketReplyDump()));
+
+        getCustomizer().readCurrentAttributes(IID, builder, ctx);
+
+        verify(builder).setMac(new PhysAddress("01:02:03:04:05:06"));
+    }
+
+    @Test
+    public void testReadFailed() throws ReadFailedException {
+        final AfPacketBuilder builder = mock(AfPacketBuilder.class);
+        when(dumpCacheManager.getInterfaceDetail(IID, ctx, IF_NAME)).thenReturn(null);
+
+        getCustomizer().readCurrentAttributes(IID, builder, ctx);
+
+        verifyZeroInteractions(builder);
+    }
+
+    @Test
+    public void testInit() {
+        final AfPacket operData = new AfPacketBuilder()
+            .setHostInterfaceName(IF_NAME)
+            .setMac(new PhysAddress("11:22:33:44:55:66")).build();
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.AfPacket
+            cfgData =
+            new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.AfPacketBuilder()
+                .setHostInterfaceName(IF_NAME)
+                .setMac(new PhysAddress("11:22:33:44:55:66")).build();
+        invokeInitTest(IID, operData, getCfgId(IID), cfgData);
+    }
+
+    private SwInterfaceDetails ifaceDetails() {
+        final SwInterfaceDetails details = new SwInterfaceDetails();
+        details.swIfIndex = IF_INDEX;
+        details.interfaceName = IF_NAME.getBytes();
+        details.l2Address = new byte[] {1, 2, 3, 4, 5, 6};
+        return details;
+    }
+
+    private AfPacketDetailsReplyDump afPacketReplyDump() {
+        final AfPacketDetailsReplyDump reply = new AfPacketDetailsReplyDump();
+        final AfPacketDetails details0 = new AfPacketDetails();
+        details0.swIfIndex = IF_INDEX;
+        details0.hostIfName = IF_NAME.getBytes();
+        reply.afPacketDetails = Collections.singletonList(details0);
+        return reply;
+    }
+}
\ No newline at end of file
index 5595ebb..4125513 100644 (file)
@@ -32,6 +32,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.re
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.AfPacket;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.Tap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VhostUser;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VxlanGpeTunnel;
@@ -64,6 +65,7 @@ public class InterfaceDataTranslatorTest implements InterfaceDataTranslator {
         assertEquals(VxlanTunnel.class, getInterfaceType("vxlan0"));
         assertEquals(VxlanGpeTunnel.class, getInterfaceType("vxlan_gpe0"));
         assertEquals(VhostUser.class, getInterfaceType("VirtualEthernet0/0/0"));
+        assertEquals(AfPacket.class, getInterfaceType("host-veth0"));
         assertEquals(EthernetCsmacd.class, getInterfaceType("eth0.0"));
         assertEquals(EthernetCsmacd.class, getInterfaceType("local0"));
     }
@@ -74,6 +76,7 @@ public class InterfaceDataTranslatorTest implements InterfaceDataTranslator {
         assertTrue(isInterfaceOfType(VxlanTunnel.class, interfaceDetails("vxlan0")));
         assertTrue(isInterfaceOfType(VxlanGpeTunnel.class, interfaceDetails("vxlan_gpe0")));
         assertTrue(isInterfaceOfType(VhostUser.class, interfaceDetails("VirtualEthernet0/0/0")));
+        assertTrue(isInterfaceOfType(AfPacket.class, interfaceDetails("host-veth0")));
         assertTrue(isInterfaceOfType(EthernetCsmacd.class, interfaceDetails("eth0.0")));
         assertTrue(isInterfaceOfType(EthernetCsmacd.class, interfaceDetails("local0")));
     }