From: Eric Multanen Date: Fri, 25 Mar 2016 16:06:29 +0000 (-0700) Subject: BUG 5746 - Ovsdb QoS and Queue model enhancements X-Git-Tag: release/boron~70^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=6ade04efd8899ba18249dfa705e5b64b13ef3ca8;p=ovsdb.git BUG 5746 - Ovsdb QoS and Queue model enhancements Update the QoS and Queue model to improve managability of QoS and Queue tables via MD-SAL config model. Adds code to update operational md-sal using updated model. Adds code to allow creation of queue and qos in same transaction and assign queue to the qos row via named-uuid. QoS and Queue entries can be managed by ODL ID values instead of needing to know the operational UUID value. Adds code to support assignment of QoS to port by MD-SAL QoS ID. Adds a QoS entry list to the termination point model so updates and delete operations can be made directly on the list instead of updating the termination point. Support for ingress policing rate and burst configuration for interfaces is added. Includes updated Postman examples. v2 - clarify some logic based on comment feedback add additional qos types: linux-sfq, linux-codel linux-fq_codel, egress-policer v3 - rebase, whitespace v4 - address review comments v5 - Changes to address review comments: Use a queue-ref (instance identifier instead of queue-id in the qos queue list. Use a qos-ref (instance identifier instead of qos-id in the port qos list. Use a key of '1' for the single item port qos list. Add instance identifer to the external-ids column of the qos and queue tables instead of just id value. Use key of 'opendaylight-iid'. Updated the postman collection to account for changes Clarified the comment and code of method bytesToHexString in TransactUtils.java. Still to do: - update unit tests - update integration tests Change-Id: I71ac462afe5a881c621fad9a3c5603e1aab8d021 Signed-off-by: Eric Multanen --- diff --git a/resources/commons/Qos-and-Queue-Collection.json.postman_collection b/resources/commons/Qos-and-Queue-Collection.json.postman_collection index d1a1de72c..4f420c69a 100644 --- a/resources/commons/Qos-and-Queue-Collection.json.postman_collection +++ b/resources/commons/Qos-and-Queue-Collection.json.postman_collection @@ -1,30 +1,35 @@ { - "id": "af60f3ad-e690-74ea-1a5a-2ed6f4013755", + "id": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", "name": "Qos and Queue Collection", "description": "This collection demonstrates how to:\n\n- create Qos and Queue entries in the OVSDB\n- add or delete Queue entries from a Qos entry\n- add or delete a Qos entry from a termination point\n- delete Qos and Queue entries", "order": [ - "8470a026-b32c-a292-49a2-a523fe831881", - "f1627096-7541-0c7e-e998-cd29e90f2547", - "78f912b9-eb93-6df1-e6bd-b175a8ee097a", - "17f45b0e-bdd2-6c7b-18a9-26df17d2ca20", - "194fbaf3-362e-54c9-2daf-c9b76f38ee57", - "64210287-3ec5-48f3-7ee5-447c09cc3c84", - "9d1dc5b0-99a2-9d31-29b6-35dcc0cf24fa", - "760bb52a-e621-bf9c-7053-e72a94899fa9", - "501cf348-4095-3826-1081-c1b3ba428f3c", - "61f5f3d5-1014-b211-b9bf-80a6b269d9b4", - "c3549a74-512b-7e93-a5e8-0219e1956c99", - "18641f3c-2f50-9761-c780-3f6ee358c616", - "fbecd07b-135b-6070-0178-71af93998104" + "400b68fe-7e92-8da8-29ed-ffc964e03eb3", + "479d3281-ac30-3b30-d727-80b0b8505140", + "d263138d-3ef5-733b-4337-87de3eccbecc", + "0105b240-9b36-79be-0251-9c2510563c71", + "a0b5092f-2bd2-3d6d-7891-a25df8d55d31", + "bdfa43fb-1d49-2433-da72-9a13f564680f", + "a0eb2758-39dd-2603-ba63-fd96abe51a9d", + "6034d635-e823-b733-e4b5-a9e2cefb27bd", + "9aa6926b-70db-1d22-dc30-db269e424bec", + "4298de9f-d2e0-a7c0-da4b-71ce9ecc7260", + "8ff38d91-00ee-e7c6-ef1a-e3d236f59641", + "ba67cc34-62d4-60e7-86be-7a187b4a9334", + "1468ceac-807b-d3c3-f07a-a6fd86c98ea0", + "a2f4d7cd-1de9-806e-e2e4-03ac2b618e66", + "14a55d30-ab5d-4007-3905-791a111457eb", + "494db14f-97e9-ce5b-5964-5504c9630a20", + "6293d31b-ea45-d504-ebac-8d765f46cb45", + "8dd9ab66-f999-6376-8584-ddc9729fb60c" ], "folders": [], "timestamp": 1454567977189, - "owner": "", - "remoteLink": "", + "owner": 0, "public": false, + "hasRequests": true, "requests": [ { - "id": "17f45b0e-bdd2-6c7b-18a9-26df17d2ca20", + "id": "0105b240-9b36-79be-0251-9c2510563c71", "headers": "Content-Type: application/json\n", "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1/ovsdb:qos-entries/QOS-1/", "preRequestScript": "", @@ -39,14 +44,14 @@ "time": 1454572576470, "name": "Add a QpS entry to a qos-entries list", "description": "This restconf request will create or update a Qos entry for the ovsdb node 'HOST1'.", - "collectionId": "af60f3ad-e690-74ea-1a5a-2ed6f4013755", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", "responses": [], "rawModeData": "{\n \"ovsdb:qos-entries\": [\n {\n \"qos-id\": \"QOS-1\",\n \"qos-type\": \"ovsdb:qos-type-linux-htb\",\n \"qos-other-config\": [\n {\n \"other-config-key\": \"max-rate\",\n \"other-config-value\": \"3300000\"\n }\n ]\n }\n ]\n}" }, { - "id": "18641f3c-2f50-9761-c780-3f6ee358c616", + "id": "1468ceac-807b-d3c3-f07a-a6fd86c98ea0", "headers": "", - "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1/ovsdb:queues/QUEUE-1/", + "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1/ovsdb:qos-entries/QOS-1/", "preRequestScript": "", "pathVariables": {}, "method": "DELETE", @@ -56,16 +61,16 @@ "tests": "", "currentHelper": "normal", "helperAttributes": {}, - "time": 1454572803238, - "name": "Delete a Queue entry from an ovsdb node", - "description": "This restconf command will delete a Qos entry.", - "collectionId": "af60f3ad-e690-74ea-1a5a-2ed6f4013755", + "time": 1454572816260, + "name": "Delete a QoS entry from a node", + "description": "This restconf command will delete a Qos entry from an ovsdb node.", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", "responses": [] }, { - "id": "194fbaf3-362e-54c9-2daf-c9b76f38ee57", - "headers": "Content-Type: application/json\n", - "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1/ovsdb:queues/QUEUE-1/", + "id": "14a55d30-ab5d-4007-3905-791a111457eb", + "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\nAccept: application/json\n", + "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fbr-test/termination-point/testport/", "preRequestScript": "", "pathVariables": {}, "method": "PUT", @@ -75,34 +80,35 @@ "tests": "", "currentHelper": "normal", "helperAttributes": {}, - "time": 1454572671919, - "name": "Add a Queue entry to the queues list of aovsdb node 'HOST1'", - "description": "This restconf request will create or update a Queue entry on ovsdb node 'HOST1'.", - "collectionId": "af60f3ad-e690-74ea-1a5a-2ed6f4013755", + "time": 1466010716484, + "name": "Add existing QoS ID to a termination point", + "description": "This restconf request will specify the QoS ID of a Qos entry to associate with a port (termination point).\n\nThe QoS ID is the ODL identifier for identifying the QoS entry. The actual UUID of the QoS entry will looked up and used to update the OVSDB port qos attributes.", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", "responses": [], - "rawModeData": "{\n \"ovsdb:queues\": [\n {\n \"queue-id\": \"QUEUE-1\",\n \"dscp\": 25,\n \"queues-other-config\": [\n {\n \"queue-other-config-key\": \"max-rate\",\n \"queue-other-config-value\": \"3600000\"\n }\n ]\n }\n ]\n}" + "rawModeData": "{\n \"network-topology:termination-point\": [\n \t{\n \t \t\t\"ovsdb:name\": \"testport\",\n \t\t\t\"tp-id\": \"testport\",\n \t\t\t\"ovsdb:qos-entry\": [\n {\n \"qos-key\": 1,\n \"qos-ref\": \"/network-topology:network-topology/network-topology:topology[network-topology:topology-id='ovsdb:1']/network-topology:node[network-topology:node-id='ovsdb:HOST1']/ovsdb:qos-entries[ovsdb:qos-id='QOS-1']\"\n }\n ]\n \t\t}\n ]\n}" }, { - "id": "501cf348-4095-3826-1081-c1b3ba428f3c", - "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n", - "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1/ovsdb:qos-entries/QOS-1/queue-list/0/", + "id": "400b68fe-7e92-8da8-29ed-ffc964e03eb3", + "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/json\nContent-Type: application/json\n", + "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/", "preRequestScript": "", "pathVariables": {}, - "method": "DELETE", + "method": "POST", "data": [], - "dataMode": "params", + "dataMode": "raw", "version": 2, "tests": "", "currentHelper": "normal", "helperAttributes": {}, - "time": 1454572752090, - "name": "Delete a Queue entry from a Qos entry", - "description": "This restconf command will delete a queue entry from a qos entry.\n\nThe queue entry is identified by it's key value (the queue number) in\nthe queue-list which is part of the qos entry.", - "collectionId": "af60f3ad-e690-74ea-1a5a-2ed6f4013755", - "responses": [] + "time": 1454573115055, + "name": "POST to create OVSDB NODE HOST1", + "description": "Fire this Restconf request if you want to initiate the connection to ovsdb node from controller. It assumes that ovsdb node is listening for tcp connection in passive mode. To configure the ovsdb node for listening incoming connection, please fire following command at ovsdb node machine\n\n\"ovs-vsctl set-manager tcp:16640\"", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", + "responses": [], + "rawModeData": "\r\n {\r\n \"node\": [\r\n {\r\n \"node-id\": \"ovsdb:HOST1\",\r\n \"connection-info\": {\r\n \"ovsdb:remote-ip\": \"{{HYPERVISOR-IP}}\",\r\n \"ovsdb:remote-port\": \"{{HYPERVISOR-OVSDB-PORT}}\"\r\n }\r\n }\r\n ]\r\n }\r\n" }, { - "id": "61f5f3d5-1014-b211-b9bf-80a6b269d9b4", + "id": "4298de9f-d2e0-a7c0-da4b-71ce9ecc7260", "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\nAccept: application/json\n", "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fbr-test/termination-point/testport/", "preRequestScript": "", @@ -115,33 +121,54 @@ "currentHelper": "normal", "helperAttributes": {}, "time": 1454572769501, - "name": "Add existing QoS UUID to existing termination point", - "description": "This restconf request will specify the UUID of a Qos entry to associate with a port.\n\nThe Qos UUID is the actual operational value of a Qos entry.", - "collectionId": "af60f3ad-e690-74ea-1a5a-2ed6f4013755", + "name": "Add existing QoS UUID to existing termination point (deprecated)", + "description": "This restconf request will specify the UUID of a Qos entry to associate with a port.\n\nThe Qos UUID is the actual operational value of a Qos entry.\n\nNote: The QoS model also has a QoS ID. The preferred method for associating a QoS entry to a termination point is to use the QoS ID.", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", "responses": [], "rawModeData": "{\n \"network-topology:termination-point\": [\n \t{\n \t \t\t\"ovsdb:name\": \"testport\",\n \t\t\t\"tp-id\": \"testport\",\n \t\t\t\"qos\": \"4126e461-020d-497d-97b7-c8f409d1c9b9\"\n \t\t}\n ]\n}" }, { - "id": "64210287-3ec5-48f3-7ee5-447c09cc3c84", - "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n", - "url": "http://{{CONTROLLER-IP}}:8181/restconf/operational/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1/ovsdb:qos-entries/QOS-1/", + "id": "479d3281-ac30-3b30-d727-80b0b8505140", + "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n", + "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fbr-test", "preRequestScript": "", "pathVariables": {}, - "method": "GET", + "method": "PUT", "data": [], - "dataMode": "params", + "dataMode": "raw", "version": 2, "tests": "", "currentHelper": "normal", "helperAttributes": {}, - "time": 1454572690160, - "name": "Get Operational QoS Entry from Qos Entry list", - "description": "This restconf queries the operational md-sal for a specific Qos entry which was previously created by restconf (e.g. 'QOS-1').\n\nThis is useful for determining the actual UUID of the Qos entry in order to assign it to a port (i.e. termination point).", - "collectionId": "af60f3ad-e690-74ea-1a5a-2ed6f4013755", - "responses": [] + "time": 1461790310464, + "name": "Create bridge br-test on HOST1", + "description": "Create bridge \"br-test\" on OVSDB node \"ovsdb:HOST1\"", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", + "responses": [], + "rawModeData": "{\n \"network-topology:node\": [\n {\n \"node-id\": \"ovsdb:HOST1/bridge/br-test\",\n \"ovsdb:bridge-name\": \"br-test\",\n \"ovsdb:managed-by\": \"/network-topology:network-topology/network-topology:topology[network-topology:topology-id='ovsdb:1']/network-topology:node[network-topology:node-id='ovsdb:HOST1']\"\n }\n ]\n}" + }, + { + "id": "494db14f-97e9-ce5b-5964-5504c9630a20", + "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\nAccept: application/json\n", + "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fbr-test/termination-point/testport/qos-entry/1", + "preRequestScript": "", + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "version": 2, + "tests": "", + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1466012030265, + "name": "Delete QoS Entry from a termination point", + "description": "This restconf request specifies the QopS ID of a Qos entry to delete from the QoS entry list of the termination point.", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", + "responses": [], + "rawModeData": "" }, { - "id": "760bb52a-e621-bf9c-7053-e72a94899fa9", + "id": "6034d635-e823-b733-e4b5-a9e2cefb27bd", "headers": "Content-Type: application/json\n", "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1/ovsdb:qos-entries/QOS-1/", "preRequestScript": "", @@ -154,14 +181,55 @@ "currentHelper": "normal", "helperAttributes": {}, "time": 1454572737919, - "name": "Add a Queue List to a QoS entry", - "description": "This restconf adds a Queue to a Qos entry by specifying a queue-list\nin the Qos entry which uses the operational queue UUID value.", - "collectionId": "af60f3ad-e690-74ea-1a5a-2ed6f4013755", + "name": "Add a Queue List to a QoS entry (deprecated)", + "description": "This restconf adds a Queue to a Qos entry by specifying a queue-list\nin the Qos entry which uses the operational queue UUID value.\n\nNote - Queues can now be added to QoS entries using the ODL Queue ID value.", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", "responses": [], "rawModeData": "{\n \"ovsdb:qos-entries\": [\n {\n \"qos-id\": \"QOS-1\",\n \"queue-list\": [\n {\n \"queue-number\": \"0\",\n \"queue-uuid\": \"8100a05f-d3fa-4e65-bbd1-6e886713f592\"\n }\n ]\n }\n ]\n}" }, { - "id": "78f912b9-eb93-6df1-e6bd-b175a8ee097a", + "id": "6293d31b-ea45-d504-ebac-8d765f46cb45", + "headers": "Content-Type: application/json\n", + "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1/ovsdb:qos-entries/QOS-1/", + "preRequestScript": "", + "pathVariables": {}, + "method": "PUT", + "data": [], + "dataMode": "raw", + "version": 2, + "tests": "", + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1465849834924, + "name": "Add existing Queue ID entry to a QoS entry", + "description": "Add a Queue to a QoS entry using the ODL Queue ID as the identifier for the Queue entry.", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", + "responses": [], + "rawModeData": "{\n \"ovsdb:qos-entries\": [\n {\n \"qos-id\": \"QOS-1\",\n \"queue-list\": [\n {\n \"queue-number\": \"0\",\n \"queue-ref\": \"/network-topology:network-topology/network-topology:topology[network-topology:topology-id='ovsdb:1']/network-topology:node[network-topology:node-id='ovsdb:HOST1']/ovsdb:queues[ovsdb:queue-id='QUEUE-1']\"\n }\n ]\n }\n ]\n}" + }, + { + "id": "8dd9ab66-f999-6376-8584-ddc9729fb60c", + "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\nAccept: application/json\n", + "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fbr-test/termination-point/testport/", + "pathVariables": {}, + "preRequestScript": "", + "method": "PUT", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", + "data": [], + "dataMode": "raw", + "name": "Set ingress policing attributes of a termination point", + "description": "Set the ingress policing attributes of an ovsdb interface by updating the termination point.\ningress-policing-rate\ningress-policing-burst\n\nNote - This is an update to a termination point's attributes. If there is also a QoS entry configured for the termination point, then it must be supplied in the body as well. Otherwise, not including the QoS entry in the body will result in the QoS entry being removed from the port.", + "descriptionFormat": "html", + "time": 1463685062091, + "version": 2, + "responses": [], + "tests": "", + "currentHelper": "normal", + "helperAttributes": {}, + "rawModeData": "{\n \"network-topology:termination-point\": [\n \t{\n\t \t\t\"ovsdb:name\": \"testport\",\n \t\t\t\"tp-id\": \"testport\",\n \"ovsdb:ingress-policing-rate\": 1000,\n \"ovsdb:ingress-policing-burst\": 2000\n\t\t}\n ]\n}" + }, + { + "id": "8ff38d91-00ee-e7c6-ef1a-e3d236f59641", "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\nAccept: application/json\n", "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fbr-test/termination-point/testport/", "preRequestScript": "", @@ -173,35 +241,54 @@ "tests": "", "currentHelper": "normal", "helperAttributes": {}, - "time": 1454573176142, - "name": "Create Termination Point", - "description": "This restconf request creates port/interface (`testport`) and attach it to give bridge 'br-test'. \n", - "collectionId": "af60f3ad-e690-74ea-1a5a-2ed6f4013755", + "time": 1454572787173, + "name": "Delete a QoS UUID from a termination point (deprecated)", + "description": "This restconf request will delete a Qos entry from a port (termination point).\n\nNote - this is done by doing a PUT operation on the termination port with the Qos\nentry cleared.\n\nNote - The model now provides a QoS entry list (max number of one entry) as part of the termination point model. This allows perfroaming a DELETE operation on the list entry instead of doing a PUT on the termination point.", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", "responses": [], - "rawModeData": "{\n \"network-topology:termination-point\": [\n \t{\n\t \t\t\"ovsdb:name\": \"testport\",\n \t\t\t\"tp-id\": \"testport\"\n\t\t}\n ]\n}" + "rawModeData": "{\n \"network-topology:termination-point\": [\n \t{\n \t \t\t\"ovsdb:name\": \"testport\",\n \t\t\t\"tp-id\": \"testport\"\n \t\t}\n ]\n}" }, { - "id": "8470a026-b32c-a292-49a2-a523fe831881", - "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/json\nContent-Type: application/json\n", - "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/", + "id": "9aa6926b-70db-1d22-dc30-db269e424bec", + "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n", + "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1/ovsdb:qos-entries/QOS-1/queue-list/0/", "preRequestScript": "", "pathVariables": {}, - "method": "POST", + "method": "DELETE", + "data": [], + "dataMode": "params", + "version": 2, + "tests": "", + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1454572752090, + "name": "Delete a Queue entry from a Qos entry", + "description": "This restconf command will delete a queue entry from a qos entry.\n\nThe queue entry is identified by it's key value (the queue number) in\nthe queue-list which is part of the qos entry.", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", + "responses": [] + }, + { + "id": "a0b5092f-2bd2-3d6d-7891-a25df8d55d31", + "headers": "Content-Type: application/json\n", + "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1/ovsdb:queues/QUEUE-1/", + "preRequestScript": "", + "pathVariables": {}, + "method": "PUT", "data": [], "dataMode": "raw", "version": 2, "tests": "", "currentHelper": "normal", "helperAttributes": {}, - "time": 1454573115055, - "name": "POST to create OVSDB NODE HOST1", - "description": "Fire this Restconf request if you want to initiate the connection to ovsdb node from controller. It assumes that ovsdb node is listening for tcp connection in passive mode. To configure the ovsdb node for listening incoming connection, please fire following command at ovsdb node machine\n\n\"ovs-vsctl set-manager tcp:16640\"", - "collectionId": "af60f3ad-e690-74ea-1a5a-2ed6f4013755", + "time": 1454572671919, + "name": "Add a Queue entry to the queues list of aovsdb node 'HOST1'", + "description": "This restconf request will create or update a Queue entry on ovsdb node 'HOST1'.", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", "responses": [], - "rawModeData": "\r\n {\r\n \"node\": [\r\n {\r\n \"node-id\": \"ovsdb:HOST1\",\r\n \"connection-info\": {\r\n \"ovsdb:remote-ip\": \"{{HYPERVISOR-IP}}\",\r\n \"ovsdb:remote-port\": \"{{HYPERVISOR-OVSDB-PORT}}\"\r\n }\r\n }\r\n ]\r\n }\r\n" + "rawModeData": "{\n \"ovsdb:queues\": [\n {\n \"queue-id\": \"QUEUE-1\",\n \"dscp\": 25,\n \"queues-other-config\": [\n {\n \"queue-other-config-key\": \"max-rate\",\n \"queue-other-config-value\": \"3600000\"\n }\n ]\n }\n ]\n}" }, { - "id": "9d1dc5b0-99a2-9d31-29b6-35dcc0cf24fa", + "id": "a0eb2758-39dd-2603-ba63-fd96abe51a9d", "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n", "url": "http://{{CONTROLLER-IP}}:8181/restconf/operational/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1/ovsdb:queues/QUEUE-1/", "preRequestScript": "", @@ -215,14 +302,14 @@ "helperAttributes": {}, "time": 1454572710554, "name": "Get a specific operaiontal Queue entry", - "description": "This restconf command will query the operational md-sal for a specified Queue entry (e.g. 'QUEUE-1') which has previously been added to the config md-sal.\n\nThis is useful in order to get the actual UUID of the Queue entry in order to assign it to a Qos entry.", - "collectionId": "af60f3ad-e690-74ea-1a5a-2ed6f4013755", + "description": "This restconf command will query the operational md-sal for a specified Queue entry (e.g. 'QUEUE-1') which has previously been added to the config md-sal.", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", "responses": [] }, { - "id": "c3549a74-512b-7e93-a5e8-0219e1956c99", - "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\nAccept: application/json\n", - "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fbr-test/termination-point/testport/", + "id": "a2f4d7cd-1de9-806e-e2e4-03ac2b618e66", + "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n", + "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1", "preRequestScript": "", "pathVariables": {}, "method": "PUT", @@ -232,51 +319,70 @@ "tests": "", "currentHelper": "normal", "helperAttributes": {}, - "time": 1454572787173, - "name": "Delete a QoS UUID from a termination point", - "description": "This restconf request will delete a Qos entry from a port (termination point).\n\nNote - this is done by doing a PUT operation on the termination port with the Qos\nentry cleared.", - "collectionId": "af60f3ad-e690-74ea-1a5a-2ed6f4013755", + "time": 1466012434801, + "name": "Create a QoS and linked Queue entry to an OVSDB Node", + "description": "This restconf command will create new QoS and Queue entries. The Queue entry is assigned to the QoS queueu list.", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", "responses": [], - "rawModeData": "{\n \"network-topology:termination-point\": [\n \t{\n \t \t\t\"ovsdb:name\": \"testport\",\n \t\t\t\"tp-id\": \"testport\"\n \t\t}\n ]\n}" + "rawModeData": "{\r\n \"network-topology:node\": [\r\n {\r\n \"node-id\": \"ovsdb:HOST1\",\r\n \"ovsdb:qos-entries\": [\r\n {\r\n \"qos-id\": \"QOS-1\",\r\n \"qos-other-config\": [\r\n {\r\n \"other-config-key\": \"max-rate\",\r\n \"other-config-value\": \"3300000\"\r\n }\r\n ],\r\n \"qos-type\": \"ovsdb:qos-type-linux-htb\",\r\n \"queue-list\": [\r\n {\r\n \"queue-number\": \"0\",\r\n \"queue-ref\": \"/network-topology:network-topology/network-topology:topology[network-topology:topology-id='ovsdb:1']/network-topology:node[network-topology:node-id='ovsdb:HOST1']/ovsdb:queues[ovsdb:queue-id='QUEUE-1']\"\r\n }\r\n ]\r\n }\r\n ],\r\n \"ovsdb:queues\": [\r\n {\r\n \"queue-id\": \"QUEUE-1\",\r\n \"dscp\" : 51,\r\n \"queues-other-config\": [\r\n {\r\n \"queue-other-config-key\": \"max-rate\",\r\n \"queue-other-config-value\": \"1230000\"\r\n },\r\n {\r\n \"queue-other-config-key\": \"min-rate\",\r\n \"queue-other-config-value\": \"1000000\"\r\n }\r\n ],\r\n \"queues-external-ids\": [\r\n {\r\n \"queues-external-id-key\": \"Big\",\r\n \"queues-external-id-value\": \"Dog\"\r\n }\r\n ]\r\n }\r\n ]\r\n }\r\n ]\r\n}" }, { - "id": "f1627096-7541-0c7e-e998-cd29e90f2547", - "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n", - "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fbr-test", + "id": "ba67cc34-62d4-60e7-86be-7a187b4a9334", + "headers": "", + "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1/ovsdb:queues/QUEUE-1/", "preRequestScript": "", "pathVariables": {}, - "method": "PUT", + "method": "DELETE", "data": [], - "dataMode": "raw", + "dataMode": "params", "version": 2, "tests": "", "currentHelper": "normal", "helperAttributes": {}, - "time": 1454572634841, - "name": "Create bridge br-test on HOST1", - "description": "Create bridge \"br-test\" on OVSDB node \"ovsdb:HOST1\"", - "collectionId": "af60f3ad-e690-74ea-1a5a-2ed6f4013755", - "responses": [], - "rawModeData": "{\n \"network-topology:node\": [\n {\n \"node-id\": \"ovsdb:HOST1/bridge/br-test\",\n \"ovsdb:bridge-name\": \"br=test\",\n \"ovsdb:managed-by\": \"/network-topology:network-topology/network-topology:topology[network-topology:topology-id='ovsdb:1']/network-topology:node[network-topology:node-id='ovsdb:HOST1']\"\n }\n ]\n}" + "time": 1454572803238, + "name": "Delete a Queue entry from an ovsdb node", + "description": "This restconf command will delete a Qos entry.", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", + "responses": [] }, { - "id": "fbecd07b-135b-6070-0178-71af93998104", - "headers": "", - "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1/ovsdb:qos-entries/QOS-1/", + "id": "bdfa43fb-1d49-2433-da72-9a13f564680f", + "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n", + "url": "http://{{CONTROLLER-IP}}:8181/restconf/operational/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1/ovsdb:qos-entries/QOS-1/", "preRequestScript": "", "pathVariables": {}, - "method": "DELETE", + "method": "GET", "data": [], "dataMode": "params", "version": 2, "tests": "", "currentHelper": "normal", "helperAttributes": {}, - "time": 1454572816260, - "name": "Delete a QoS entry from a node", - "description": "This restconf command will delete a Qos entry from an ovsdb node.", - "collectionId": "af60f3ad-e690-74ea-1a5a-2ed6f4013755", + "time": 1454572690160, + "name": "Get Operational QoS Entry from Qos Entry list", + "description": "This restconf queries the operational md-sal for a specific Qos entry which was previously created by restconf (e.g. 'QOS-1').", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", "responses": [] + }, + { + "id": "d263138d-3ef5-733b-4337-87de3eccbecc", + "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\nAccept: application/json\n", + "url": "http://{{CONTROLLER-IP}}:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fbr-test/termination-point/testport/", + "preRequestScript": "", + "pathVariables": {}, + "method": "PUT", + "data": [], + "dataMode": "raw", + "version": 2, + "tests": "", + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1454573176142, + "name": "Create Termination Point", + "description": "This restconf request creates a port/interface (`testport`) and attaches it to bridge 'br-test'. \n", + "collectionId": "b96ed27e-7aee-47e1-daa6-e3dbe3f176af", + "responses": [], + "rawModeData": "{\n \"network-topology:termination-point\": [\n \t{\n\t \t\t\"ovsdb:name\": \"testport\",\n \t\t\t\"tp-id\": \"testport\"\n\t\t}\n ]\n}" } ] } diff --git a/schemas/openvswitch/src/main/java/org/opendaylight/ovsdb/schema/openvswitch/Interface.java b/schemas/openvswitch/src/main/java/org/opendaylight/ovsdb/schema/openvswitch/Interface.java index e0bd8a20a..2f2d0d32e 100644 --- a/schemas/openvswitch/src/main/java/org/opendaylight/ovsdb/schema/openvswitch/Interface.java +++ b/schemas/openvswitch/src/main/java/org/opendaylight/ovsdb/schema/openvswitch/Interface.java @@ -42,14 +42,14 @@ public interface Interface extends TypedBaseTable { void setOptions(Map options); @TypedColumn(name="ingress_policing_rate", method=MethodType.GETCOLUMN, fromVersion="1.0.0") - Column> getIngressPolicingRateColumn(); + Column getIngressPolicingRateColumn(); @TypedColumn(name="ingress_policing_rate", method=MethodType.SETDATA, fromVersion="1.0.0") - void setIngressPolicingRate(Set ingressPolicingRate); + void setIngressPolicingRate(Long ingressPolicingRate); @TypedColumn(name="ingress_policing_burst", method=MethodType.GETCOLUMN, fromVersion="1.0.0") - Column> getIngressPolicingBurstColumn(); + Column getIngressPolicingBurstColumn(); @TypedColumn(name="ingress_policing_burst", method=MethodType.SETDATA, fromVersion="1.0.0") - void setIngressPolicingBurst(Set ingressPolicingBurst); + void setIngressPolicingBurst(Long ingressPolicingBurst); @TypedColumn(name="mac_in_use", method=MethodType.GETCOLUMN, fromVersion="7.1.0") Column> getMacInUseColumn(); diff --git a/southbound/southbound-api/src/main/yang/ovsdb.yang b/southbound/southbound-api/src/main/yang/ovsdb.yang index d303a2b30..b5ca74a6c 100755 --- a/southbound/southbound-api/src/main/yang/ovsdb.yang +++ b/southbound/southbound-api/src/main/yang/ovsdb.yang @@ -34,6 +34,16 @@ module ovsdb { type instance-identifier; } + typedef ovsdb-qos-ref { + description "A reference to a ovsdb QoS entry"; + type instance-identifier; + } + + typedef ovsdb-queue-ref { + description "A reference to an ovsdb queue entry"; + type instance-identifier; + } + typedef ovsdb-bridge-name { type string; } @@ -514,9 +524,15 @@ module ovsdb { type uint32; } + leaf queue-ref { + description "Instance identifier to a Queue in the MD-SAL."; + type ovsdb-queue-ref; + } + leaf queue-uuid { description "The unique identifier of the queue record."; type yang:uuid; + status deprecated; } } list qos-external-ids { @@ -786,6 +802,26 @@ module ovsdb { base qos-type-base; } + identity qos-type-linux-sfq { + description "linux stochastic fairness queueing classifier"; + base qos-type-base; + } + + identity qos-type-linux-codel { + description "linux controlled delay classifier"; + base qos-type-base; + } + + identity qos-type-linux-fq-codel { + description "linux fair queueing controlled delay classifier"; + base qos-type-base; + } + + identity qos-type-egress-policer { + description "DPDK user space egress policer"; + base qos-type-base; + } + grouping ovsdb-port-interface-attributes { leaf port-uuid { description "The unique identifier of the OVSDB port"; @@ -1239,8 +1275,40 @@ module ovsdb { leaf qos { description "The unique identifier of the QoS entry for this port."; + status deprecated; type yang:uuid; } + + list qos-entry { + key "qos-key"; + max-elements 1; + leaf qos-key { + description "Fixed key to reference the QoS entry in MD-SAL."; + type uint32 { + range "1..1"; + } + mandatory true; + } + leaf qos-ref { + description "Instance identifier of a QoS entry in the MD-SAL."; + type ovsdb-qos-ref; + mandatory true; + } + } + + leaf ingress-policing-rate { + description "Maximum rate for data received on this interface in kbps. + Data received faster than this rate is dropped. Set to 0 (default) + to disable policing"; + type uint32; + } + + leaf ingress-policing-burst { + description "Maximum burst size for data received on this interface in kb. + The default burst size if set to 0 is 1000 kb. This value has no + effect if ingress-policing-rate is 0."; + type uint32; + } } augment "/topo:network-topology/topo:topology/topo:node" { diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundConstants.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundConstants.java index 0b3d0a08f..4f2883523 100755 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundConstants.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundConstants.java @@ -40,8 +40,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeSystem; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeNetdev; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.QosTypeBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.QosTypeEgressPolicer; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.QosTypeLinuxHfsc; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.QosTypeLinuxHtb; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.QosTypeLinuxCodel; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.QosTypeLinuxFqCodel; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.QosTypeLinuxSfq; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; import com.google.common.collect.ImmutableBiMap; @@ -53,7 +57,10 @@ public class SouthboundConstants { public static final String BRIDGE_URI_PREFIX = "bridge"; public static final String TP_URI_PREFIX = "terminationpoint"; public static final String QOS_URI_PREFIX = "qos"; + public static final String QOS_NAMED_UUID_PREFIX = "QOS"; + public static final Integer PORT_QOS_LIST_KEY = 1; public static final String QUEUE_URI_PREFIX = "queue"; + public static final String QUEUE_NAMED_UUID_PREFIX = "QUEUE"; public static final String AUTOATTACH_URI_PREFIX = "autoattach"; public static final String AUTOATTACH_SUPPORTED_OVS_SCHEMA_VERSION = "7.11.2"; public static final Integer DEFAULT_OVSDB_PORT = 6640; @@ -62,10 +69,20 @@ public class SouthboundConstants { public static final String UUID = "uuid"; public static final String QOS_LINUX_HTB = "linux-htb"; public static final String QOS_LINUX_HFSC = "linux-hfsc"; + // The following four QoS types are present in OVS 2.5+ + // Refer to http://openvswitch.org/support/dist-docs/ovs-vswitchd.conf.db.5.txt + public static final String QOS_LINUX_SFQ = "linux-sfq"; + public static final String QOS_LINUX_CODEL = "linux-codel"; + public static final String QOS_LINUX_FQ_CODEL = "linux-fq_codel"; + public static final String QOS_EGRESS_POLICER = "egress-policer"; public static final ImmutableBiMap,String> QOS_TYPE_MAP = new ImmutableBiMap.Builder,String>() .put(QosTypeLinuxHtb.class,QOS_LINUX_HTB) .put(QosTypeLinuxHfsc.class,QOS_LINUX_HFSC) + .put(QosTypeLinuxSfq.class,QOS_LINUX_SFQ) + .put(QosTypeLinuxCodel.class,QOS_LINUX_CODEL) + .put(QosTypeLinuxFqCodel.class,QOS_LINUX_FQ_CODEL) + .put(QosTypeEgressPolicer.class,QOS_EGRESS_POLICER) .build(); public static final ImmutableBiMap,String> OVSDB_PROTOCOL_MAP @@ -111,8 +128,6 @@ public class SouthboundConstants { .put(DatapathTypeNetdev.class,"netdev") .build(); public static final String IID_EXTERNAL_ID_KEY = "opendaylight-iid"; - public static final String QOS_ID_EXTERNAL_ID_KEY = "opendaylight-qos-id"; - public static final String QUEUE_ID_EXTERNAL_ID_KEY = "opendaylight-queue-id"; public static final String AUTOATTACH_ID_EXTERNAL_ID_KEY = "opendaylight-autoattach-id"; public enum VLANMODES { diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QosUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QosUpdateCommand.java index 4f1cb86da..e3322fd6f 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QosUpdateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QosUpdateCommand.java @@ -23,15 +23,21 @@ import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils; import org.opendaylight.ovsdb.schema.openvswitch.Qos; import org.opendaylight.ovsdb.southbound.SouthboundConstants; import org.opendaylight.ovsdb.southbound.SouthboundMapper; +import org.opendaylight.ovsdb.southbound.SouthboundUtil; import org.opendaylight.ovsdb.utils.yang.YangUtils; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbQueueRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntries; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfig; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueList; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; @@ -71,6 +77,7 @@ public class QosUpdateCommand implements TransactCommand { } OvsdbNodeAugmentation operNode = state.getBridgeNode(iid).get().getAugmentation(OvsdbNodeAugmentation.class); List operQosEntries = operNode.getQosEntries(); + List operQueues = operNode.getQueues(); if (qosEntries != null) { for (QosEntries qosEntry : qosEntries) { @@ -80,17 +87,15 @@ public class QosUpdateCommand implements TransactCommand { qos.setType(SouthboundMapper.createQosType(qosEntry.getQosType())); } - Uuid qosUuid = getQosEntryUuid(operQosEntries, qosEntry.getQosId()); - UUID uuid = null; - if (qosUuid != null) { - uuid = new UUID(qosUuid.getValue()); - } - List queueList = qosEntry.getQueueList(); MapnewQueueList = new HashMap<>(); if (queueList != null && !queueList.isEmpty()) { for (QueueList queue : queueList) { - newQueueList.put(queue.getQueueNumber(), new UUID(queue.getQueueUuid().getValue())); + if (queue.getQueueRef() != null) { + newQueueList.put(queue.getQueueNumber(), new UUID(getQueueUuid(queue.getQueueRef(), operNode))); + } else if (queue.getQueueUuid() != null) { + newQueueList.put(queue.getQueueNumber(), new UUID(queue.getQueueUuid().getValue())); + } } } qos.setQueues(newQueueList); @@ -102,7 +107,11 @@ public class QosUpdateCommand implements TransactCommand { } catch (NullPointerException e) { LOG.warn("Incomplete Qos external IDs", e); } - externalIdsMap.put(SouthboundConstants.QOS_ID_EXTERNAL_ID_KEY, qosEntry.getQosId().getValue()); + externalIdsMap.put(SouthboundConstants.IID_EXTERNAL_ID_KEY, + SouthboundUtil.serializeInstanceIdentifier( + SouthboundMapper.createInstanceIdentifier(iid.firstKeyOf(Node.class, NodeKey.class).getNodeId()) + .augmentation(OvsdbNodeAugmentation.class) + .child(QosEntries.class, new QosEntriesKey(qosEntry.getQosId())))); qos.setExternalIds(externalIdsMap); try { @@ -111,9 +120,14 @@ public class QosUpdateCommand implements TransactCommand { } catch (NullPointerException e) { LOG.warn("Incomplete Qos other_config", e); } - if (uuid == null) { - transaction.add(op.insert(qos)).build(); + + Uuid operQosUuid = getQosEntryUuid(operQosEntries, qosEntry.getQosId()); + if (operQosUuid == null) { + UUID namedUuid = new UUID(SouthboundConstants.QOS_NAMED_UUID_PREFIX + + TransactUtils.bytesToHexString(qosEntry.getQosId().getValue().getBytes())); + transaction.add(op.insert(qos).withId(namedUuid.toString())).build(); } else { + UUID uuid = new UUID(operQosUuid.getValue()); Qos extraQos = TyperUtils.getTypedRowWrapper( transaction.getDatabaseSchema(), Qos.class, null); extraQos.getUuidColumn().setData(uuid); @@ -125,6 +139,19 @@ public class QosUpdateCommand implements TransactCommand { } } + private String getQueueUuid(OvsdbQueueRef queueRef, OvsdbNodeAugmentation operNode) { + QueuesKey queueKey = queueRef.getValue().firstKeyOf(Queues.class); + if (operNode.getQueues() != null && !operNode.getQueues().isEmpty()) { + for (Queues queue : operNode.getQueues()) { + if (queue.getQueueId().equals(queueKey.getQueueId())) { + return queue.getQueueUuid().getValue(); + } + } + } + return SouthboundConstants.QUEUE_NAMED_UUID_PREFIX + + TransactUtils.bytesToHexString(queueKey.getQueueId().getValue().getBytes()); + } + private Uuid getQosEntryUuid(List operQosEntries, Uri qosId) { if (operQosEntries != null && !operQosEntries.isEmpty()) { for (QosEntries qosEntry : operQosEntries) { diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QueueUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QueueUpdateCommand.java index 6018b8572..8d9ea9979 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QueueUpdateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QueueUpdateCommand.java @@ -24,14 +24,18 @@ import org.opendaylight.ovsdb.lib.operations.TransactionBuilder; import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils; import org.opendaylight.ovsdb.schema.openvswitch.Queue; import org.opendaylight.ovsdb.southbound.SouthboundConstants; +import org.opendaylight.ovsdb.southbound.SouthboundMapper; +import org.opendaylight.ovsdb.southbound.SouthboundUtil; import org.opendaylight.ovsdb.utils.yang.YangUtils; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfig; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; @@ -87,12 +91,6 @@ public class QueueUpdateCommand implements TransactCommand { } } - Uuid queueUuid = getQueueEntryUuid(operQueues, queueEntry.getQueueId()); - UUID uuid = null; - if (queueUuid != null) { - uuid = new UUID(queueUuid.getValue()); - } - Map externalIdsMap = new HashMap<>(); try { YangUtils.copyYangKeyValueListToMap(externalIdsMap, queueEntry.getQueuesExternalIds(), @@ -100,7 +98,11 @@ public class QueueUpdateCommand implements TransactCommand { } catch (NullPointerException e) { LOG.warn("Incomplete Queue external IDs", e); } - externalIdsMap.put(SouthboundConstants.QUEUE_ID_EXTERNAL_ID_KEY, queueEntry.getQueueId().getValue()); + externalIdsMap.put(SouthboundConstants.IID_EXTERNAL_ID_KEY, + SouthboundUtil.serializeInstanceIdentifier( + SouthboundMapper.createInstanceIdentifier(iid.firstKeyOf(Node.class, NodeKey.class).getNodeId()) + .augmentation(OvsdbNodeAugmentation.class) + .child(Queues.class, new QueuesKey(queueEntry.getQueueId())))); queue.setExternalIds(externalIdsMap); try { @@ -109,10 +111,15 @@ public class QueueUpdateCommand implements TransactCommand { } catch (NullPointerException e) { LOG.warn("Incomplete Queue other_config", e); } - if (uuid == null) { - transaction.add(op.insert(queue)).build(); + + Uuid operQueueUuid = getQueueEntryUuid(operQueues, queueEntry.getQueueId()); + if (operQueueUuid == null) { + UUID namedUuid = new UUID(SouthboundConstants.QUEUE_NAMED_UUID_PREFIX + + TransactUtils.bytesToHexString(queueEntry.getQueueId().getValue().getBytes())); + transaction.add(op.insert(queue).withId(namedUuid.toString())).build(); } else { - transaction.add(op.update(queue)).build(); + UUID uuid = new UUID(operQueueUuid.getValue()); + //transaction.add(op.update(queue)).build(); Queue extraQueue = TyperUtils.getTypedRowWrapper( transaction.getDatabaseSchema(), Queue.class, null); extraQueue.getUuidColumn().setData(uuid); diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointUpdateCommand.java index 3e91aab5e..0425d39e8 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointUpdateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointUpdateCommand.java @@ -16,20 +16,32 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.ExecutionException; import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.ovsdb.lib.error.SchemaVersionMismatchException; import org.opendaylight.ovsdb.lib.notation.UUID; import org.opendaylight.ovsdb.lib.operations.TransactionBuilder; import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils; import org.opendaylight.ovsdb.schema.openvswitch.Interface; import org.opendaylight.ovsdb.schema.openvswitch.Port; +import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance; import org.opendaylight.ovsdb.southbound.SouthboundConstants; +import org.opendaylight.ovsdb.southbound.SouthboundProvider; import org.opendaylight.ovsdb.utils.yang.YangUtils; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes.VlanMode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbQosRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntries; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfd; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceLldp; @@ -44,7 +56,9 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Optional; import com.google.common.collect.Sets; +import com.google.common.util.concurrent.CheckedFuture; public class TerminationPointUpdateCommand implements TransactCommand { @@ -53,27 +67,27 @@ public class TerminationPointUpdateCommand implements TransactCommand { @Override public void execute(TransactionBuilder transaction, BridgeOperationalState state, AsyncDataChangeEvent, DataObject> events) { - execute(transaction, TransactUtils.extractCreatedOrUpdated(events, OvsdbTerminationPointAugmentation.class)); + execute(transaction, state, TransactUtils.extractCreatedOrUpdated(events, OvsdbTerminationPointAugmentation.class)); } @Override public void execute(TransactionBuilder transaction, BridgeOperationalState state, Collection> modifications) { - execute(transaction, + execute(transaction, state, TransactUtils.extractCreatedOrUpdated(modifications, OvsdbTerminationPointAugmentation.class)); } - private void execute(TransactionBuilder transaction, + private void execute(TransactionBuilder transaction, BridgeOperationalState state, Map, OvsdbTerminationPointAugmentation> createdOrUpdated) { LOG.trace("TerminationPointUpdateCommand called"); for (Entry, OvsdbTerminationPointAugmentation> terminationPointEntry : createdOrUpdated.entrySet()) { - updateTerminationPoint(transaction, terminationPointEntry.getKey(), terminationPointEntry.getValue()); + updateTerminationPoint(transaction, state, terminationPointEntry.getKey(), terminationPointEntry.getValue()); } } - public void updateTerminationPoint(TransactionBuilder transaction, + public void updateTerminationPoint(TransactionBuilder transaction, BridgeOperationalState state, InstanceIdentifier iid, OvsdbTerminationPointAugmentation terminationPoint) { if (terminationPoint != null) { @@ -95,9 +109,10 @@ public class TerminationPointUpdateCommand implements TransactCommand { iid.firstIdentifierOf(OvsdbTerminationPointAugmentation.class), terminationPoint.getName()); // Update port + OvsdbBridgeAugmentation operBridge = state.getBridgeNode(iid).get().getAugmentation(OvsdbBridgeAugmentation.class); Port port = TyperUtils.getTypedRowWrapper( transaction.getDatabaseSchema(), Port.class); - updatePort(terminationPoint, port); + updatePort(terminationPoint, port, operBridge); Port extraPort = TyperUtils.getTypedRowWrapper( transaction.getDatabaseSchema(), Port.class); extraPort.setName(""); @@ -117,32 +132,74 @@ public class TerminationPointUpdateCommand implements TransactCommand { updateInterfaceExternalIds(terminationPoint, ovsInterface); updateInterfaceLldp(terminationPoint, ovsInterface); updateInterfaceBfd(terminationPoint, ovsInterface); + updateInterfacePolicing(terminationPoint, ovsInterface); } private void updatePort( final OvsdbTerminationPointAugmentation terminationPoint, - final Port port) { + final Port port, + final OvsdbBridgeAugmentation operBridge) { updatePortOtherConfig(terminationPoint, port); updatePortVlanTag(terminationPoint, port); updatePortVlanTrunk(terminationPoint, port); updatePortVlanMode(terminationPoint, port); updatePortExternalIds(terminationPoint, port); - updatePortQos(terminationPoint, port); + updatePortQos(terminationPoint, port, operBridge); } private void updatePortQos( final OvsdbTerminationPointAugmentation terminationPoint, - final Port port) { + final Port port, + final OvsdbBridgeAugmentation operBridge) { Set uuidSet = Sets.newHashSet(); - Uuid qosUuid = terminationPoint.getQos(); - if (qosUuid != null) { - uuidSet.add(new UUID(qosUuid.getValue())); + + // First check if QosEntry is present and use that + if (terminationPoint.getQosEntry() != null && !terminationPoint.getQosEntry().isEmpty()) { + OvsdbQosRef qosRef = terminationPoint.getQosEntry().iterator().next().getQosRef(); + Uri qosId = qosRef.getValue().firstKeyOf(QosEntries.class).getQosId(); + OvsdbNodeAugmentation operNode = getOperNode(operBridge); + if (operNode != null && operNode.getQosEntries() != null && + !operNode.getQosEntries().isEmpty()) { + for (QosEntries qosEntry : operNode.getQosEntries()) { + if (qosEntry.getQosId().equals(qosId)) { + uuidSet.add(new UUID(qosEntry.getQosUuid().getValue())); + } + } + } + if (uuidSet.size() == 0) { + uuidSet.add(new UUID(SouthboundConstants.QOS_NAMED_UUID_PREFIX + + TransactUtils.bytesToHexString(qosId.getValue().getBytes()))); + } + } else { + // Second check if Qos is present and use that (deprecated) + // Do not bother to check if QosEntry and Qos are consistent if both are present + Uuid qosUuid = terminationPoint.getQos(); + if (qosUuid != null) { + uuidSet.add(new UUID(qosUuid.getValue())); + } } port.setQos(uuidSet); } + private OvsdbNodeAugmentation getOperNode(final OvsdbBridgeAugmentation operBridge) { + @SuppressWarnings("unchecked") + InstanceIdentifier iidNode = (InstanceIdentifier)operBridge.getManagedBy().getValue(); + OvsdbNodeAugmentation operNode = null; + ReadOnlyTransaction transaction = SouthboundProvider.getDb().newReadOnlyTransaction(); + CheckedFuture, ReadFailedException> future = + transaction.read(LogicalDatastoreType.OPERATIONAL, iidNode); + try { + Optional nodeOptional = future.get(); + if (nodeOptional.isPresent()) { + operNode = nodeOptional.get().getAugmentation(OvsdbNodeAugmentation.class); + } + } catch (InterruptedException | ExecutionException e) { + LOG.warn("Error reading from datastore", e); + } + return operNode; + } private void updateOfPort( final OvsdbTerminationPointAugmentation terminationPoint, @@ -255,6 +312,20 @@ public class TerminationPointUpdateCommand implements TransactCommand { } } + private void updateInterfacePolicing( + final OvsdbTerminationPointAugmentation terminationPoint, + final Interface ovsInterface) { + + Long ingressPolicingRate = terminationPoint.getIngressPolicingRate(); + if (ingressPolicingRate != null) { + ovsInterface.setIngressPolicingRate(ingressPolicingRate); + } + Long ingressPolicingBurst = terminationPoint.getIngressPolicingBurst(); + if (ingressPolicingBurst != null) { + ovsInterface.setIngressPolicingBurst(ingressPolicingBurst); + } + } + private void updatePortExternalIds( final OvsdbTerminationPointAugmentation terminationPoint, final Port port) { diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactUtils.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactUtils.java index 26b9581fa..3accf490c 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactUtils.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactUtils.java @@ -492,4 +492,41 @@ public class TransactUtils { mutate.setMutations(mutations); return mutate; } + + /** + * This method builds a string by concatenating the 2 character + * hexadecimal representation of each byte from the input byte array. + * + * For example: an input byte array containing: + * bytes[0] = 'a' + * bytes[1] = 'b' + * bytes[2] = 'c' + * bytes[3] = '-' + * bytes[4] = '1' + * bytes[5] = '2' + * bytes[6] = '3' + * returns the string "6162632d313233" + * + * @param bytes + * The byte array to convert to string + * @return The hexadecimal representation of the byte array. If bytes is + * null, the string "" is returned + */ + public static String bytesToHexString(byte[] bytes) { + + if (bytes == null) { + return ""; + } + + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < bytes.length; i++) { + short u8byte = (short) (bytes[i] & 0xff); + String tmp = Integer.toHexString(u8byte); + if (tmp.length() == 1) { + buf.append("0"); + } + buf.append(tmp); + } + return buf.toString(); + } } diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbPortUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbPortUpdateCommand.java index 81c39e861..da65b5b13 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbPortUpdateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbPortUpdateCommand.java @@ -30,18 +30,22 @@ import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils; import org.opendaylight.ovsdb.schema.openvswitch.Bridge; import org.opendaylight.ovsdb.schema.openvswitch.Interface; import org.opendaylight.ovsdb.schema.openvswitch.Port; +import org.opendaylight.ovsdb.schema.openvswitch.Qos; import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance; import org.opendaylight.ovsdb.southbound.SouthboundConstants; import org.opendaylight.ovsdb.southbound.SouthboundMapper; import org.opendaylight.ovsdb.southbound.SouthboundUtil; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbQosRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntries; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfd; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdKey; @@ -62,6 +66,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIdsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.QosEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.QosEntryBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.QosEntryKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Trunks; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.TrunksBuilder; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; @@ -87,6 +94,7 @@ public class OvsdbPortUpdateCommand extends AbstractTransactionCommand { private Map interfaceUpdatedRows; private Map interfaceOldRows; private Map bridgeUpdatedRows; + private Map qosUpdatedRows; public OvsdbPortUpdateCommand(OvsdbConnectionInstance key, TableUpdates updates, DatabaseSchema dbSchema) { super(key, updates, dbSchema); @@ -95,6 +103,7 @@ public class OvsdbPortUpdateCommand extends AbstractTransactionCommand { interfaceUpdatedRows = TyperUtils.extractRowsUpdated(Interface.class, updates, dbSchema); interfaceOldRows = TyperUtils.extractRowsOld(Interface.class, updates, dbSchema); bridgeUpdatedRows = TyperUtils.extractRowsUpdated(Bridge.class, updates, dbSchema); + qosUpdatedRows = TyperUtils.extractRowsUpdated(Qos.class, updates, dbSchema); } @Override @@ -127,7 +136,7 @@ public class OvsdbPortUpdateCommand extends AbstractTransactionCommand { getInstanceIdentifier(bridgeIid.get(), portUpdate.getValue()); OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder(); - buildTerminationPoint(tpAugmentationBuilder,portUpdate.getValue()); + buildTerminationPoint(transaction, tpPath, tpAugmentationBuilder, node, portUpdate); UUID interfaceUUID = (UUID)portUpdate.getValue().getInterfacesColumn().getData().toArray()[0]; if (interfaceUpdatedRows.containsKey(interfaceUUID)) { buildTerminationPoint(tpAugmentationBuilder, @@ -170,14 +179,16 @@ public class OvsdbPortUpdateCommand extends AbstractTransactionCommand { } } - private void buildTerminationPoint(OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder, - Port portUpdate) { + private void buildTerminationPoint(ReadWriteTransaction transaction, + InstanceIdentifier tpPath, + OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder, + Node node, Entry portUpdate) { tpAugmentationBuilder - .setName(portUpdate.getName()); + .setName(portUpdate.getValue().getName()); tpAugmentationBuilder.setPortUuid(new Uuid( - portUpdate.getUuid().toString())); - updatePort(portUpdate, tpAugmentationBuilder); + portUpdate.getValue().getUuid().toString())); + updatePort(transaction, node, tpPath, portUpdate, tpAugmentationBuilder); } private void buildTerminationPoint(OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder, @@ -238,15 +249,16 @@ public class OvsdbPortUpdateCommand extends AbstractTransactionCommand { updateInterface(interfaceUpdate, type,ovsdbTerminationPointBuilder); } - private void updatePort(final Port port, + private void updatePort(final ReadWriteTransaction transaction, final Node node, + final InstanceIdentifier tpPath, final Entry port, final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) { - updateVlan(port, ovsdbTerminationPointBuilder); - updateVlanTrunks(port, ovsdbTerminationPointBuilder); - updateVlanMode(port, ovsdbTerminationPointBuilder); - updateQos(port, ovsdbTerminationPointBuilder); - updatePortExternalIds(port, ovsdbTerminationPointBuilder); - updatePortOtherConfig(port, ovsdbTerminationPointBuilder); + updateVlan(port.getValue(), ovsdbTerminationPointBuilder); + updateVlanTrunks(port.getValue(), ovsdbTerminationPointBuilder); + updateVlanMode(port.getValue(), ovsdbTerminationPointBuilder); + updateQos(transaction, node, tpPath, port, ovsdbTerminationPointBuilder); + updatePortExternalIds(port.getValue(), ovsdbTerminationPointBuilder); + updatePortOtherConfig(port.getValue(), ovsdbTerminationPointBuilder); } private void updateInterface(final Interface interf, @@ -265,6 +277,7 @@ public class OvsdbPortUpdateCommand extends AbstractTransactionCommand { updateInterfaceLldp(interf, ovsdbTerminationPointBuilder); updateInterfaceBfd(interf, ovsdbTerminationPointBuilder); updateInterfaceBfdStatus(interf, ovsdbTerminationPointBuilder); + updateInterfacePolicing(interf, ovsdbTerminationPointBuilder); } private void updateVlan(final Port port, @@ -320,17 +333,81 @@ public class OvsdbPortUpdateCommand extends AbstractTransactionCommand { } } - private void updateQos(final Port port, - final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) { - if (port.getQosColumn() == null) { + private void updateQos(final ReadWriteTransaction transaction, final Node node, InstanceIdentifier tpPath, + final Entry port, final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) { + if (port.getValue() == null) { return; } - Collection qosUuidCol = port.getQosColumn().getData(); + Collection qosUuidCol = port.getValue().getQosColumn().getData(); if (!qosUuidCol.isEmpty()) { - Iterator itr = qosUuidCol.iterator(); - UUID qosUuid = itr.next(); + UUID qosUuid = qosUuidCol.iterator().next(); ovsdbTerminationPointBuilder.setQos(new Uuid(qosUuid.toString())); + + NodeId nodeId = node.getNodeId(); + OvsdbNodeAugmentation ovsdbNode = node.getAugmentation(OvsdbNodeAugmentation.class); + + // Delete an older QoS entry + if (portOldRows.containsKey(port.getKey()) && + portOldRows.get(port.getKey()).getQosColumn() != null) { + Collection oldQos = portOldRows.get(port.getKey()).getQosColumn().getData(); + if (!oldQos.isEmpty()) { + UUID oldQosUuid = oldQos.iterator().next(); + if (!oldQosUuid.equals(qosUuid)) { + InstanceIdentifier oldQosIid = getQosIid(nodeId, ovsdbNode, oldQosUuid); + if (oldQosIid != null) { + InstanceIdentifier oldPortQosIid = tpPath + .augmentation(OvsdbTerminationPointAugmentation.class) + .child(QosEntry.class, + new QosEntryKey(new Long(SouthboundConstants.PORT_QOS_LIST_KEY))); +// new QosEntryKey(new OvsdbQosRef(oldQosIid))); + transaction.delete(LogicalDatastoreType.OPERATIONAL, oldPortQosIid); + } + } + } + } + + InstanceIdentifier qosIid = getQosIid(nodeId, ovsdbNode, qosUuid); + if (qosIid != null) { + List qosList = new ArrayList<>(); + OvsdbQosRef qosRef = new OvsdbQosRef(qosIid); + qosList.add(new QosEntryBuilder() + .setKey(new QosEntryKey(new Long(SouthboundConstants.PORT_QOS_LIST_KEY))) + .setQosRef(qosRef).build()); + ovsdbTerminationPointBuilder.setQosEntry(qosList); + } + } + } + + private InstanceIdentifier getQosIid(NodeId nodeId, OvsdbNodeAugmentation ovsdbNode, UUID qosUuid) { + // Search for the QoS entry first in the operational datastore + for (QosEntries qosEntry : ovsdbNode.getQosEntries()) { + if (qosEntry.getQosUuid().equals(new Uuid(qosUuid.toString()))) { + return SouthboundMapper.createInstanceIdentifier(nodeId) + .augmentation(OvsdbNodeAugmentation.class) + .child(QosEntries.class, new QosEntriesKey(qosEntry.getQosId())); + } + } + + // Search for the QoS entry in the current OVS updates + for (Entry qosUpdate : qosUpdatedRows.entrySet()) { + Qos qos = qosUpdate.getValue(); + if (qos.getUuid().equals(qosUuid)) { + if (qos.getExternalIdsColumn().getData().containsKey(SouthboundConstants.IID_EXTERNAL_ID_KEY)) { + return (InstanceIdentifier) SouthboundUtil.deserializeInstanceIdentifier( + qos.getExternalIdsColumn().getData().get(SouthboundConstants.IID_EXTERNAL_ID_KEY)); + } else { + return SouthboundMapper.createInstanceIdentifier(nodeId) + .augmentation(OvsdbNodeAugmentation.class) + .child(QosEntries.class, new QosEntriesKey( + new Uri(SouthboundConstants.QOS_URI_PREFIX + "://" + qosUuid.toString()))); + } + } } + LOG.debug("QoS UUID {} assigned to port not found in operational node {} or QoS updates", qosUuid, ovsdbNode); + return SouthboundMapper.createInstanceIdentifier(nodeId) + .augmentation(OvsdbNodeAugmentation.class) + .child(QosEntries.class, new QosEntriesKey( + new Uri(SouthboundConstants.QOS_URI_PREFIX + "://" + qosUuid.toString()))); } private void updateOfPort(final Interface interf, @@ -548,6 +625,38 @@ public class OvsdbPortUpdateCommand extends AbstractTransactionCommand { } } + private void updateInterfacePolicing(final Interface interf, + final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) { + + Long ingressPolicingRate = null; + if (interf.getIngressPolicingRateColumn() != null) { + ingressPolicingRate = interf.getIngressPolicingRateColumn().getData(); + } + if (ingressPolicingRate != null) { + if (ingressPolicingRate >= 0) { + ovsdbTerminationPointBuilder + .setIngressPolicingRate(ingressPolicingRate); + } else { + LOG.debug("Received negative value for ingressPolicingRate from ovsdb for {} {}", + interf.getName(),ingressPolicingRate); + } + } + + Long ingressPolicingBurst = null; + if (interf.getIngressPolicingBurstColumn() != null) { + ingressPolicingBurst = interf.getIngressPolicingBurstColumn().getData(); + } + if (ingressPolicingBurst != null) { + if (ingressPolicingBurst >= 0) { + ovsdbTerminationPointBuilder + .setIngressPolicingBurst(ingressPolicingBurst); + } else { + LOG.debug("Received negative value for ingressPolicingBurst from ovsdb for {} {}", + interf.getName(),ingressPolicingBurst); + } + } + } + private boolean portQosCleared(Entry portUpdate) { if (portUpdate.getValue().getQosColumn() == null) { return false; diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbQosUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbQosUpdateCommand.java index 231c72227..7fff0ba22 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbQosUpdateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbQosUpdateCommand.java @@ -22,6 +22,7 @@ import org.opendaylight.ovsdb.lib.notation.UUID; import org.opendaylight.ovsdb.lib.schema.DatabaseSchema; import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils; import org.opendaylight.ovsdb.schema.openvswitch.Qos; +import org.opendaylight.ovsdb.schema.openvswitch.Queue; import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance; import org.opendaylight.ovsdb.southbound.SouthboundConstants; import org.opendaylight.ovsdb.southbound.SouthboundMapper; @@ -29,7 +30,11 @@ import org.opendaylight.ovsdb.southbound.SouthboundUtil; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbQueueRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntries; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIdsBuilder; @@ -53,12 +58,14 @@ public class OvsdbQosUpdateCommand extends AbstractTransactionCommand { private Map updatedQosRows; private Map oldQosRows; + private Map updatedQueueRows; public OvsdbQosUpdateCommand(OvsdbConnectionInstance key, TableUpdates updates, DatabaseSchema dbSchema) { super(key, updates, dbSchema); updatedQosRows = TyperUtils.extractRowsUpdated(Qos.class,getUpdates(), getDbSchema()); oldQosRows = TyperUtils.extractRowsOld(Qos.class, getUpdates(), getDbSchema()); + updatedQueueRows = TyperUtils.extractRowsUpdated(Queue.class, getUpdates(), getDbSchema()); } @Override @@ -98,7 +105,7 @@ public class OvsdbQosUpdateCommand extends AbstractTransactionCommand { SouthboundMapper.createQosType(qos.getTypeColumn().getData().toString())); setOtherConfig(transaction, qosEntryBuilder, oldQos, qos, nodeIId); setExternalIds(transaction, qosEntryBuilder, oldQos, qos, nodeIId); - setQueueList(transaction, qosEntryBuilder, oldQos, qos, nodeIId); + setQueueList(transaction, qosEntryBuilder, oldQos, qos, nodeIId, ovsdbNode.get()); QosEntries qosEntry = qosEntryBuilder.build(); LOG.debug("Update Ovsdb Node {} with qos entries {}",ovsdbNode.get(), qosEntry); @@ -114,10 +121,52 @@ public class OvsdbQosUpdateCommand extends AbstractTransactionCommand { private String getQosId(Qos qos) { if (qos.getExternalIdsColumn() != null && qos.getExternalIdsColumn().getData() != null - && qos.getExternalIdsColumn().getData().containsKey(SouthboundConstants.QOS_ID_EXTERNAL_ID_KEY)) { - return qos.getExternalIdsColumn().getData().get(SouthboundConstants.QOS_ID_EXTERNAL_ID_KEY); + && qos.getExternalIdsColumn().getData().containsKey(SouthboundConstants.IID_EXTERNAL_ID_KEY)) { + InstanceIdentifier qosIid = (InstanceIdentifier) SouthboundUtil.deserializeInstanceIdentifier( + qos.getExternalIdsColumn().getData().get(SouthboundConstants.IID_EXTERNAL_ID_KEY)); + if (qosIid != null) { + QosEntriesKey qosEntriesKey = qosIid.firstKeyOf(QosEntries.class); + if (qosEntriesKey != null) { + return qosEntriesKey.getQosId().getValue(); + } + } + } + return SouthboundConstants.QOS_URI_PREFIX + "://" + qos.getUuid().toString(); + } + + private Queue getQueue(UUID queueUuid) + { + for (Entry entry : updatedQueueRows.entrySet()) { + if (entry.getKey().equals(queueUuid)) { + return entry.getValue(); + } + } + return null; + } + + private InstanceIdentifier getQueueIid(UUID queueUuid, Node ovsdbNode) { + Queue queue = getQueue(queueUuid); + if (queue != null && queue.getExternalIdsColumn() != null + && queue.getExternalIdsColumn().getData() != null + && queue.getExternalIdsColumn().getData().containsKey(SouthboundConstants.IID_EXTERNAL_ID_KEY)) { + return (InstanceIdentifier) SouthboundUtil.deserializeInstanceIdentifier( + queue.getExternalIdsColumn().getData().get(SouthboundConstants.IID_EXTERNAL_ID_KEY)); } else { - return SouthboundConstants.QOS_URI_PREFIX + "://" + qos.getUuid().toString(); + OvsdbNodeAugmentation node = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class); + if (node.getQueues() != null && !node.getQueues().isEmpty()) { + for (Queues q : node.getQueues()) { + if (q.getQueueUuid().equals(new Uuid(queueUuid.toString()))) { + return SouthboundMapper.createInstanceIdentifier(ovsdbNode.getNodeId()) + .augmentation(OvsdbNodeAugmentation.class) + .child(Queues.class, new QueuesKey(q.getQueueId())); + } + } + } + LOG.debug("A Queue with UUID {} was not found in Ovsdb Node {}", queueUuid, node); + return SouthboundMapper.createInstanceIdentifier(ovsdbNode.getNodeId()) + .augmentation(OvsdbNodeAugmentation.class) + .child(Queues.class, new QueuesKey( + new Uri(SouthboundConstants.QUEUE_URI_PREFIX + "://" + queueUuid.toString()))); } } @@ -223,7 +272,7 @@ public class OvsdbQosUpdateCommand extends AbstractTransactionCommand { private void setQueueList(ReadWriteTransaction transaction, QosEntriesBuilder qosEntryBuilder, Qos oldQos, Qos qos, - InstanceIdentifier nodeIId) { + InstanceIdentifier nodeIId, Node ovsdbNode) { Map oldQueueList = null; Map queueList = null; @@ -237,7 +286,7 @@ public class OvsdbQosUpdateCommand extends AbstractTransactionCommand { removeOldQueues(transaction, qosEntryBuilder, oldQueueList, qos, nodeIId); } if (queueList != null && !queueList.isEmpty()) { - setNewQueues(qosEntryBuilder, queueList); + setNewQueues(qosEntryBuilder, queueList, ovsdbNode); } } @@ -257,13 +306,18 @@ public class OvsdbQosUpdateCommand extends AbstractTransactionCommand { } private void setNewQueues(QosEntriesBuilder qosEntryBuilder, - Map queueList) { + Map queueList, Node ovsdbNode) { Set> queueEntries = queueList.entrySet(); List newQueueList = new ArrayList<>(); for (Entry queueEntry : queueEntries) { + InstanceIdentifier queueIid = getQueueIid(queueEntry.getValue(), ovsdbNode); + if (queueIid != null) { newQueueList.add( - new QueueListBuilder().setQueueNumber(queueEntry.getKey()) + new QueueListBuilder() + .setQueueNumber(queueEntry.getKey()) + .setQueueRef(new OvsdbQueueRef(queueIid)) .setQueueUuid(new Uuid(queueEntry.getValue().toString())).build()); + } } qosEntryBuilder.setQueueList(newQueueList); } diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbQueueUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbQueueUpdateCommand.java index 6ba260928..2a30c49dc 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbQueueUpdateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbQueueUpdateCommand.java @@ -29,6 +29,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types. import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIdsBuilder; @@ -110,11 +111,17 @@ public class OvsdbQueueUpdateCommand extends AbstractTransactionCommand { private String getQueueId(Queue queue) { if (queue.getExternalIdsColumn() != null && queue.getExternalIdsColumn().getData() != null - && queue.getExternalIdsColumn().getData().containsKey(SouthboundConstants.QUEUE_ID_EXTERNAL_ID_KEY)) { - return queue.getExternalIdsColumn().getData().get(SouthboundConstants.QUEUE_ID_EXTERNAL_ID_KEY); - } else { - return SouthboundConstants.QUEUE_URI_PREFIX + "://" + queue.getUuid().toString(); + && queue.getExternalIdsColumn().getData().containsKey(SouthboundConstants.IID_EXTERNAL_ID_KEY)) { + InstanceIdentifier queueIid = (InstanceIdentifier) SouthboundUtil.deserializeInstanceIdentifier( + queue.getExternalIdsColumn().getData().get(SouthboundConstants.IID_EXTERNAL_ID_KEY)); + if (queueIid != null) { + QueuesKey queuesKey = queueIid.firstKeyOf(Queues.class); + if (queuesKey != null) { + return queuesKey.getQueueId().getValue(); + } + } } + return SouthboundConstants.QUEUE_URI_PREFIX + "://" + queue.getUuid().toString(); } private void setOtherConfig(ReadWriteTransaction transaction, diff --git a/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointUpdateCommandTest.java b/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointUpdateCommandTest.java index d6379dda9..176a1b5bd 100644 --- a/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointUpdateCommandTest.java +++ b/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointUpdateCommandTest.java @@ -40,7 +40,9 @@ import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils; import org.opendaylight.ovsdb.schema.openvswitch.Interface; import org.opendaylight.ovsdb.schema.openvswitch.Port; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes.VlanMode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.powermock.api.mockito.PowerMockito; import org.powermock.api.support.membermodification.MemberMatcher; @@ -48,6 +50,8 @@ import org.powermock.api.support.membermodification.MemberModifier; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; +import com.google.common.base.Optional; + @RunWith(PowerMockRunner.class) @PrepareForTest({TerminationPointUpdateCommand.class, TransactUtils.class, TyperUtils.class, VlanMode.class, TerminationPointCreateCommand.class, InstanceIdentifier.class}) public class TerminationPointUpdateCommandTest { @@ -68,9 +72,10 @@ public class TerminationPointUpdateCommandTest { PowerMockito.mockStatic(TransactUtils.class); PowerMockito.when(TransactUtils.extractCreated(any(AsyncDataChangeEvent.class), eq(OvsdbTerminationPointAugmentation.class))).thenReturn(created); MemberModifier.suppress(MemberMatcher.method(TerminationPointUpdateCommand.class, "updateTerminationPoint", - TransactionBuilder.class, InstanceIdentifier.class, OvsdbTerminationPointAugmentation.class)); + TransactionBuilder.class, BridgeOperationalState.class, + InstanceIdentifier.class, OvsdbTerminationPointAugmentation.class)); doNothing().when(terminationPointUpdateCommand) - .updateTerminationPoint(any(TransactionBuilder.class), any(InstanceIdentifier.class), any(OvsdbTerminationPointAugmentation.class)); + .updateTerminationPoint(any(TransactionBuilder.class), any(BridgeOperationalState.class), any(InstanceIdentifier.class), any(OvsdbTerminationPointAugmentation.class)); Map, OvsdbTerminationPointAugmentation> updated = new HashMap<>(); updated.put(mock(InstanceIdentifier.class), mock(OvsdbTerminationPointAugmentation.class)); @@ -85,9 +90,14 @@ public class TerminationPointUpdateCommandTest { @Test public void testUpdateTerminationPoint() throws Exception { TransactionBuilder transaction = mock(TransactionBuilder.class); + BridgeOperationalState state = mock(BridgeOperationalState.class); InstanceIdentifier iid = mock(InstanceIdentifier.class); OvsdbTerminationPointAugmentation terminationPoint = mock(OvsdbTerminationPointAugmentation.class); when(terminationPoint.getName()).thenReturn(TERMINATION_POINT_NAME); + Optional optNode = (Optional)mock(Optional.class); + when(state.getBridgeNode(any(InstanceIdentifier.class))).thenReturn(optNode); + when(state.getBridgeNode(any(InstanceIdentifier.class)).get()).thenReturn(mock(Node.class)); + when(state.getBridgeNode(any(InstanceIdentifier.class)).get().getAugmentation(OvsdbBridgeAugmentation.class)).thenReturn(mock(OvsdbBridgeAugmentation.class)); // Test updateInterface() Interface ovsInterface = mock(Interface.class); @@ -124,7 +134,7 @@ public class TerminationPointUpdateCommandTest { when(op.update(any(Port.class))).thenReturn(update); when(extraPort.getNameColumn()).thenReturn(column); - terminationPointUpdateCommand.updateTerminationPoint(transaction, iid, terminationPoint); + terminationPointUpdateCommand.updateTerminationPoint(transaction, state, iid, terminationPoint); verify(transaction, times(2)).add(any(Operation.class)); } diff --git a/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbPortUpdateCommandTest.java b/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbPortUpdateCommandTest.java index ab067cdbb..77a35c70b 100644 --- a/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbPortUpdateCommandTest.java +++ b/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbPortUpdateCommandTest.java @@ -24,6 +24,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.Map.Entry; import org.junit.Before; import org.junit.Test; @@ -197,7 +198,8 @@ import com.google.common.util.concurrent.CheckedFuture; OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = mock(OvsdbTerminationPointAugmentationBuilder.class); PowerMockito.whenNew(OvsdbTerminationPointAugmentationBuilder.class).withNoArguments().thenReturn(tpAugmentationBuilder); - PowerMockito.suppress(MemberMatcher.method(OvsdbPortUpdateCommand.class, "buildTerminationPoint", OvsdbTerminationPointAugmentationBuilder.class, Port.class)); + PowerMockito.suppress(MemberMatcher.method(OvsdbPortUpdateCommand.class, "buildTerminationPoint", ReadWriteTransaction.class, + InstanceIdentifier.class, OvsdbTerminationPointAugmentationBuilder.class, Node.class, Entry.class)); Column> interfacesColumn = mock(Column.class); when(port.getInterfacesColumn()).thenReturn(interfacesColumn); @@ -240,21 +242,31 @@ import com.google.common.util.concurrent.CheckedFuture; verify(transaction, times(2)).merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(TerminationPoint.class)); } + @SuppressWarnings("unchecked") @Test public void testBuildTerminationPoint() throws Exception { OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = mock(OvsdbTerminationPointAugmentationBuilder.class); Port portUpdate = mock(Port.class); + ReadWriteTransaction transaction = mock(ReadWriteTransaction.class); + InstanceIdentifier tpPath = mock(InstanceIdentifier.class); + Entry portEntry = mock(Entry.class); + Node node = mock(Node.class); + when(portEntry.getValue()).thenReturn(mock(Port.class)); + when(portEntry.getValue().getName()).thenReturn(PORT_NAME); + when(portEntry.getValue().getUuid()).thenReturn(mock(UUID.class)); when(portUpdate.getName()).thenReturn(PORT_NAME); when(portUpdate.getUuid()).thenReturn(mock(UUID.class)); PowerMockito.whenNew(Uuid.class).withAnyArguments().thenReturn(mock(Uuid.class)); when(tpAugmentationBuilder.setName(anyString())).thenReturn(tpAugmentationBuilder); when(tpAugmentationBuilder.setPortUuid(any(Uuid.class))).thenReturn(tpAugmentationBuilder); - MemberModifier.suppress(MemberMatcher.method(OvsdbPortUpdateCommand.class, "updatePort", Port.class, OvsdbTerminationPointAugmentationBuilder.class)); + MemberModifier.suppress(MemberMatcher.method(OvsdbPortUpdateCommand.class, "updatePort", + ReadWriteTransaction.class, Node.class, InstanceIdentifier.class, Entry.class, OvsdbTerminationPointAugmentationBuilder.class)); - Whitebox.invokeMethod(ovsdbPortUpdateCommand, "buildTerminationPoint", tpAugmentationBuilder, portUpdate); + Whitebox.invokeMethod(ovsdbPortUpdateCommand, "buildTerminationPoint", transaction, tpPath, tpAugmentationBuilder, node, portEntry); verify(tpAugmentationBuilder).setName(anyString()); verify(tpAugmentationBuilder).setPortUuid(any(Uuid.class)); - PowerMockito.verifyPrivate(ovsdbPortUpdateCommand).invoke("updatePort", any(Port.class), any(OvsdbTerminationPointAugmentationBuilder.class)); + PowerMockito.verifyPrivate(ovsdbPortUpdateCommand).invoke("updatePort", any(ReadWriteTransaction.class), any(Node.class), + any(InstanceIdentifier.class), any(Entry.class), any(OvsdbTerminationPointAugmentationBuilder.class)); } @Test @@ -402,9 +414,13 @@ import com.google.common.util.concurrent.CheckedFuture; PowerMockito.verifyPrivate(ovsdbPortUpdateCommand).invoke("updateInterfaceOtherConfig", any(Interface.class), any(OvsdbTerminationPointAugmentationBuilder.class)); } + @SuppressWarnings("unchecked") @Test public void testUpdatePort() throws Exception { - Port port = mock(Port.class); + ReadWriteTransaction transaction = mock(ReadWriteTransaction.class); + Node node = mock(Node.class); + InstanceIdentifier tpPath = (InstanceIdentifier) mock(InstanceIdentifier.class); + Entry port = mock(Entry.class); OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder = mock(OvsdbTerminationPointAugmentationBuilder.class); MemberModifier.suppress(MemberMatcher.method(OvsdbPortUpdateCommand.class, "updateVlan", Port.class, OvsdbTerminationPointAugmentationBuilder.class)); @@ -413,7 +429,7 @@ import com.google.common.util.concurrent.CheckedFuture; MemberModifier.suppress(MemberMatcher.method(OvsdbPortUpdateCommand.class, "updatePortExternalIds", Port.class, OvsdbTerminationPointAugmentationBuilder.class)); MemberModifier.suppress(MemberMatcher.method(OvsdbPortUpdateCommand.class, "updatePortOtherConfig", Port.class, OvsdbTerminationPointAugmentationBuilder.class)); - Whitebox.invokeMethod(ovsdbPortUpdateCommand, "updatePort", port, ovsdbTerminationPointBuilder); + Whitebox.invokeMethod(ovsdbPortUpdateCommand, "updatePort", transaction, node, tpPath, port, ovsdbTerminationPointBuilder); PowerMockito.verifyPrivate(ovsdbPortUpdateCommand).invoke("updateVlan", any(Port.class), any(OvsdbTerminationPointAugmentationBuilder.class)); PowerMockito.verifyPrivate(ovsdbPortUpdateCommand).invoke("updateVlanTrunks", any(Port.class), any(OvsdbTerminationPointAugmentationBuilder.class)); diff --git a/southbound/southbound-it/src/test/java/org/opendaylight/ovsdb/southbound/it/SouthboundIT.java b/southbound/southbound-it/src/test/java/org/opendaylight/ovsdb/southbound/it/SouthboundIT.java index eb0824c57..f2827211e 100644 --- a/southbound/southbound-it/src/test/java/org/opendaylight/ovsdb/southbound/it/SouthboundIT.java +++ b/southbound/southbound-it/src/test/java/org/opendaylight/ovsdb/southbound/it/SouthboundIT.java @@ -2124,7 +2124,7 @@ public class SouthboundIT extends AbstractMdsalTestBase { private Queues getQueue(Uri queueId, OvsdbNodeAugmentation node) { for (Queues queue : node.getQueues()) { - if (queue.getKey().getQueueId().equals(queueId)) + if (queue.getKey().getQueueId().getValue().equals(queueId.getValue())) return queue; } return null;