/* * Copyright (c) 2013 Big Switch Networks, Inc. * * Licensed under the Eclipse Public License, Version 1.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ package org.sdnplatform.ovsdb; import org.codehaus.jackson.JsonNode; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ExceptionEvent; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.handler.timeout.IdleStateAwareChannelUpstreamHandler; import org.jboss.netty.handler.timeout.IdleStateEvent; import org.sdnplatform.ovsdb.internal.JSONMsg; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class OVSDBServerHandler extends IdleStateAwareChannelUpstreamHandler { protected static Logger logger = LoggerFactory.getLogger(OVSDBServerHandler.class); Channel ch; OVSDBImplTest ot; public OVSDBServerHandler(OVSDBImplTest ot) { this.ot = ot; } @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) { ch = ctx.getChannel(); JsonNode jn = (JsonNode)e.getMessage(); logger.debug(e.toString()); if (jn.get("method") != null) { String method = jn.get("method").getValueAsText(); if (method.equals("monitor")) { processShowRequest(jn); } else if (method.equals("transact")) { processTransaction(jn); } } } @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { if (e.getCause() instanceof IllegalStateException) { logger.debug("Illegal State exception {}", e.getCause().toString()); } else { super.exceptionCaught(ctx, e); } } @Override public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) throws Exception { ot.shutdownOVSDBServer(); } private void processShowRequest(JsonNode jn) { int msgid = jn.get("id").getValueAsInt(); logger.debug("received show request with id {}", msgid); int testid = ot.getCurrentTestID(); logger.debug("got current testid in show {}", testid); if (testid < 13 || testid >= 22) { JSONServerReply sr = new JSONServerReply(testid,msgid); ch.write(sr); } else { logger.debug("unknown test case"); } } private void processTransaction(JsonNode jn) { int msgid = jn.get("id").getValueAsInt(); int testid = ot.getCurrentTestID(); logger.debug("rcvd current testid {}", testid); if (testid >= 13 && testid < 17 ) { logger.debug("received add-port request with id {}", msgid); JSONServerReply sr = new JSONServerReply(testid,msgid); ch.write(sr); } else if (testid >= 17 && testid < 21) { logger.debug("received del-port request with id {}", msgid); JSONServerReply sr = new JSONServerReply(testid,msgid); ch.write(sr); } else if (testid == 21) { logger.debug("received add-port for non tunnel port id{}", msgid); JSONServerReply sr = new JSONServerReply(testid, msgid); ch.write(sr); } else if (testid == 24) { logger.debug("received set-dpid msg id{}", msgid); JSONServerReply sr = new JSONServerReply(testid+1, msgid+1); ch.write(sr); } else { logger.debug("unknown test case"); } } private class JSONServerReply extends JSONMsg{ String replystr; int msgid; public JSONServerReply(int testid, int msgid) { this.msgid = msgid; if (testid < 10) createGarbageShowReply(testid); else if (testid < 13) createValidShowReply(testid); else if (testid < 17) createAddPortReply(testid); else if (testid < 21) createDelPortReply(testid); else if (testid == 21) createAddNonTunnelPortReply(testid); else if (testid >= 22) createGetSetDpidReply(testid); } private void createGarbageShowReply(int testid) { switch (testid) { case 0: // unknown value replystr = " {\"error\":null,\"id\":"+msgid+ ",\"result\":{ "+ " blah }} "; break; case 1: // missing value replystr = " {\"error\":null,\"id\":"+msgid+ ",\"result\":{ "+ " \"blah\" }}"; break; case 2: //unknown record "blah" replystr = " {\"error\":null,\"id\":"+msgid+ ",\"blah\":{ }}"; break; case 3: //missing value replystr = " {\"error\":,\"id\":"+msgid+ ",\"result\":{ }}"; break; case 4: //missing comma separator replystr = " {\"error\":null\"id\":"+msgid+ ",\"result\":{ }}"; break; case 5: //missing id replystr = " {\"id\":null}"; break; case 6: // blank reply replystr = "{}"; break; case 7: replystr = "blah"; break; case 8: replystr = " {\"error\":null,\"id\":"+msgid+ ",\"result\":{ "+ "\"Prt\":{} }} "; break; case 9: replystr = " {\"error\":null,\"id\":"+msgid+ ",\"result\":{ "+ "\"Port\":[] }} "; break; } } private void createValidShowReply(int testid) { switch (testid) { case 10: replystr = " {\"error\":null,\"id\":"+msgid+ ",\"result\":{ "+ " }} "; break; case 11: replystr = " {\"error\":null,\"id\":"+msgid+ ",\"result\":{ "+ "\"Port\":{} }} "; break; case 12: replystr = "{\"id\":0,\"error\":null,\"result\":"+ "{\"Port\":{\"355b1c92-f0d8-44f2-bfbb-9e65feb0ac05\":{" + "\"new\":{\"trunks\":[\"set\",[]],\"interfaces\":[\"uuid" + "\",\"523a3b14-2b1d-4fbf-95e8-78228"+ "951b365\"],\"name\":\"eth1\",\"tag\":[\"set\",[]]}}," + "\"e8df8c86-c106-41d3-98b2-71bdd83b7628\":{\"new\":{" + "\"trunks\":[\"set\",[]],\"interfaces\":[\"uuid\"," + "\"ba0c4e7d-7dd5-4dd1-a66f-5488d82e91e3\"],\"name\":" + "\"tunnelswitch\",\"tag\":[\"set\",[]]}}},"+ "\"Controller\":{\"b017abcc-6d49-4cc8-9d42-5973175e4f26" + "\":{\"new\":{\"target\":\"tcp:172.16.22.1\""+ ",\"is_connected\":false}}},"+ "\"Interface\":{\"523a3b14-2b1d-4fbf-95e8-78228951b365\"" + ":{\"new\":{\"name\":\"eth1\",\"type\":\"\",\"options\"" + ":[\"map\",[]]}},\"ba0c4e7d-7dd5-4dd1-a66f-5488d82e91e3" + "\":{\"new\":{\"name\":\"tunnelswitch\",\"type\":" + "\"internal\",\"options\":[\"map\",[]]}}},"+ "\"Open_vSwitch\":{\"aa8711b0-a2ea-4acd-926f-" + "9dbc0831a6c3\":{\""+ "new\":{\"ovs_version\":[\"set\",[]],\"cur_cfg\":6," + "\"bridges\":[\"uuid\",\"755e444d-5455-44ff-9c2e-5" + "636f9bfb8e2\"],\"manager_options\":[\"set\",[]]}}},"+ "\"Bridge\":{\"755e444d-5455-44ff-9c2e-5636f9bfb8e2\":" + "{\"new\":{\"name\":\"tunnelswitch\",\"ports\":[\"set\"," + "[[\"uuid\",\"355b1c92-f0d8-44f2-bfbb-9e65feb0ac05\"]," + "[\"uuid\",\"e8df8c86-c106-4"+ "1d3-98b2-71bdd83b7628\"]]],\"other_config\":[\"map\"," + "[[\"datapath-id\",\"0000000000000018\"],[\"datapath" + "_type\",\"system\"],[\"tunnel-ip\",\"192.168.158.129\"" + "]]],\"controller\":[\"uuid\",\"b017abcc-6d49-4cc8-" + "9d42-5973175e4f26\"],\"fail_mode\":\"secure\"}}}}}"; break; } } private void createAddPortReply(int testid) { switch (testid) { case 13: // successful addition replystr = "{\"id\":"+msgid+",\"error\":null," + "\"result\":[{},{}," + "{},{},{\"uuid\":[\"uuid\",\"d241e4c1-1b65-431a" + "-83ad-71c3d5ba3809\"]},{\"count\":1},{\"uuid\"" + ":[\"uuid\",\"bd49f36c-ff34-41ca-8d83-4d6da7" + "1b5fc2\"]},{\"count\":1},{\"rows\":[{" + "\"next_cfg\":1}]},{}]}"; break; case 14: // error on adding same port replystr = "{\"id\":"+msgid+",\"error\":null,\"" + "result\":[{}," + "{},{},{},{},{\"uuid\":[\"uuid\",\"5012ab9f-" + "0df4-4c5d-aa92-a0b3f68d62b9\"]},{\"count\":1}" + ",{\"uuid\":[\"uuid\",\"99c6e7b3-8718-4d0e-" + "b186-1cd70932dd58\"]},{\"count\":1},{\"rows\"" + ":[{\"next_cfg\":8}]},{},{\"error\":" + "\"constraint violation\",\"details\":" + "\"Transaction causes multiple rows in Port " + "table to have identical values (tunn2) for " + "index on column name. First row, with " + "UUID 79e7c1c5-71ba-4853-89ae-976d79dfa1c3, " + "existed in the database before this transaction " + "and was not modified by the transaction. Second"+ "row, with UUID 5012ab9f-0df4-4c5d-aa92-" + "a0b3f68d62b9, " + "was inserted by this transaction.\"}]}"; break; case 15: // empty reply replystr = "{\"id\":"+msgid+",\"error\":null,\"" + "result\":[]}"; break; case 16: // garbage reply replystr = "{\"id\":"+msgid+",\"error\":null,\"" + "result\":[{},{},{},{},{}, {blah}, {}, {}, {}]}"; break; } } private void createDelPortReply(int testid) { switch (testid) { case 17: // successful deletion replystr = "{\"id\":"+msgid+",\"error\":null,\"result\":" + "[{},{},{},{},{},{},{\"count\":1},{\"count\":1}," + "{\"rows\":[{\"next_cfg\":37}]},{}]}"; break; case 18: // error on deleting unknown port replystr = "{\"id\":"+msgid+",\"error\":null,\"result\"" + ":[{}," + "{},{},{},{\"error\":\"timed out\",\"details\":" + "\"wait timed out\"},null,null,null,null]}"; break; case 19: // empty reply replystr = "{\"id\":"+msgid+",\"error\":null,\"" + "result\":[]}"; break; case 20: // garbage reply replystr = "{\"id\":"+msgid+",\"error\":null,\"" + "result\":[{},{},{},{},{}, blah, {}, {}, {}]}"; break; } } private void createAddNonTunnelPortReply(int testid) { switch(testid) { case 21: // successful addition replystr = "{\"id\":"+msgid+",\"error\":null," + "\"result\":[{},{}," + "{},{},{\"uuid\":[\"uuid\",\"d241e4c1-ccdd-431a" + "-83ad-71c3d5ba3809\"]},{\"count\":1},{\"uuid\"" + ":[\"uuid\",\"bd49f36c-ff34-41ca-ddcc-4d6da7" + "1b5fc2\"]},{\"count\":1},{\"rows\":[{" + "\"next_cfg\":1}]},{}]}"; break; } } private void createGetSetDpidReply(int testid) { switch(testid) { case 22: // dpid not set anywhere // valid controller-ip replystr = "{\"id\":0,\"error\":null,\"result\":{"+ "\"Port\":{" + "\"c5538a39-8074-403d-bdef-a298f07903cf\":{\"new\":" + "{\"trunks\":[\"set\",[]],\"interfaces\":[\"uuid\"," + "\"a8d4f4aa-67e7-4539-923c-987a7e4ada52\"],\"name\":"+ "\"virbr0\",\"tag\":[\"set\",[]]}}," + "\"52742937-27a8-46ec-8ced-c68d2b6153f7\":{\"new\":"+ "{\"trunks\":[\"set\",[]],\"interfaces\":[\"uuid\","+ "\"e5c62049-0299-467c-b3bc-da2b4ca01f52\"],\"name\":"+ "\"eth1\",\"tag\":[\"set\",[]]}}," + "\"8214a945-f4ee-4671-98af-5c75272aa569\":{\"new\":"+ "{\"trunks\":[\"set\",[]],\"interfaces\":[\"uuid\","+ "\"cde08e29-f0e8-447d-9c1b-650206f19800\"],\"name\":"+ "\"ovs-br0\",\"tag\":[\"set\",[]]}}},"+ "\"Controller\":"+ "{\"924b152e-6a68-4fec-871f-71c28a6e57d1\":{\"new\":"+ "{\"target\":\"tcp:192.168.247.132\",\"is_" + "connected\":true}}},"+ "\"Interface\":{"+ "\"e5c62049-0299-467c-b3bc-da2b4ca01f52\":{\"new\":" + "{\"name\":\"eth1\",\"type\":\"\",\"options\":[" + "\"map\",[]]}}," + "\"a8d4f4aa-67e7-4539-923c-987a7e4ada52\":{\"new\":" + "{\"name\":\"virbr0\",\"type\":\"internal\",\"opti" + "ons\":[\"map\",[]]}},"+ "\"cde08e29-f0e8-447d-9c1b-650206f19800\":{\"new\":"+ "{\"name\":\"ovs-br0\",\"type\":\"internal\",\"opti" + "ons\":[\"map\",[]]}}}," + "\"Open_vSwitch\":{"+ "\"f4949a56-f807-4e82-b20d-601619b18cd6\":{\"new\":" + "{\"ovs_version\":\"1.3.0+build0\",\"cur_cfg\":14," + "\"bridges\":[\"set\",[[\"uuid\",\"0447bb39-6839" + "-44bc-9653-49d7d86c295a\"],[\"uuid\",\"862a0dc7" + "-20de-415c-8377-20529c7f6cde\"]]],\"manager_" + "options\":[\"set\",[]]}}}," + "\"Bridge\":{" + "\"862a0dc7-20de-415c-8377-20529c7f6cde\":{\"new\":" + "{\"name\":\"ovs-br0\"," + "\"datapath_id\":\"\"," + "\"ports\":[\"set\",[[\"uuid\"," + "\"52742937-27a8-46ec-8ced-c68d2b6153f7\"],[\"uuid\"," + "\"8214a945-f4ee-4671-98af-5c75272aa569\"]]],\"other_" + "config\":[\"map\",[[\"datapath-id\",\"" + "\"], [\"tunnel-ip\",\"192.168.20.138\"]]]," + "\"controller\":[\"uuid\",\"924b152e-6a68-4fec-871f" + "-71c28a6e57d1\"],\"fail_mode\":\"secure\"}},"+ "\"0447bb39-6839-44bc-9653-49d7d86c295a\":{\"new\":" + "{\"name\":\"virbr0\",\"ports\":[\"uuid\",\"c5538a39" + "-8074-403d-bdef-a298f07903cf\"],\"other_config\":" + "[\"map\",[]],\"controller\":[\"set\",[]],\"fail_" + "mode\":[\"set\",[]]}}}}}"; break; case 23: //other-config missing and datapath_id not set // multiple controller ips replystr = "{\"id\":0,\"error\":null,\"result\":{"+ "\"Port\":{" + "\"c5538a39-8074-403d-bdef-a298f07903cf\":{\"new\":" + "{\"trunks\":[\"set\",[]],\"interfaces\":[\"uuid\"," + "\"a8d4f4aa-67e7-4539-923c-987a7e4ada52\"],\"name\":"+ "\"virbr0\",\"tag\":[\"set\",[]]}}," + "\"52742937-27a8-46ec-8ced-c68d2b6153f7\":{\"new\":"+ "{\"trunks\":[\"set\",[]],\"interfaces\":[\"uuid\","+ "\"e5c62049-0299-467c-b3bc-da2b4ca01f52\"],\"name\":"+ "\"eth1\",\"tag\":[\"set\",[]]}}," + "\"8214a945-f4ee-4671-98af-5c75272aa569\":{\"new\":"+ "{\"trunks\":[\"set\",[]],\"interfaces\":[\"uuid\","+ "\"cde08e29-f0e8-447d-9c1b-650206f19800\"],\"name\":"+ "\"ovs-br0\",\"tag\":[\"set\",[]]}}},"+ "\"Controller\":{"+ "\"924b152e-6a68-4fec-871f-71c28a6e57d1\":{\"new\":"+ "{\"target\":\"tcp:192.168.247.132\",\"is_" + "connected\":true}}," + "\"00ba152e-6a68-4fec-871f-71c28a6e57d1\":{\"new\":"+ "{\"target\":\"tcp:192.168.204.111\",\"is_" + "connected\":true}}" + "},"+ "\"Interface\":{"+ "\"e5c62049-0299-467c-b3bc-da2b4ca01f52\":{\"new\":" + "{\"name\":\"eth1\",\"type\":\"\",\"options\":[" + "\"map\",[]]}}," + "\"a8d4f4aa-67e7-4539-923c-987a7e4ada52\":{\"new\":" + "{\"name\":\"virbr0\",\"type\":\"internal\",\"opti" + "ons\":[\"map\",[]]}},"+ "\"cde08e29-f0e8-447d-9c1b-650206f19800\":{\"new\":"+ "{\"name\":\"ovs-br0\",\"type\":\"internal\",\"opti" + "ons\":[\"map\",[]]}}}," + "\"Open_vSwitch\":{"+ "\"f4949a56-f807-4e82-b20d-601619b18cd6\":{\"new\":" + "{\"ovs_version\":\"1.3.0+build0\",\"cur_cfg\":14," + "\"bridges\":[\"set\",[[\"uuid\",\"0447bb39-6839" + "-44bc-9653-49d7d86c295a\"],[\"uuid\",\"862a0dc7" + "-20de-415c-8377-20529c7f6cde\"]]],\"manager_" + "options\":[\"set\",[]]}}}," + "\"Bridge\":{" + "\"862a0dc7-20de-415c-8377-20529c7f6cde\":{\"new\":" + "{\"name\":\"ovs-br0\"," + "\"datapath_id\":" + "\"\"," + "\"ports\":[\"set\",[[\"uuid\"," + "\"52742937-27a8-46ec-8ced-c68d2b6153f7\"],[\"uuid\"," + "\"8214a945-f4ee-4671-98af-5c75272aa569\"]]],\"other_" + "config\":[\"map\",[" + "[\"tunnel-ip\",\"192.168.20.138\"]]]," + "\"controller\":[\"uuid\",\"924b152e-6a68-4fec-871f" + "-71c28a6e57d1\"],\"fail_mode\":\"secure\"}},"+ "\"0447bb39-6839-44bc-9653-49d7d86c295a\":{\"new\":" + "{\"name\":\"virbr0\",\"ports\":[\"uuid\",\"c5538a39" + "-8074-403d-bdef-a298f07903cf\"],\"other_config\":" + "[\"map\",[]],\"controller\":[\"set\",[]],\"fail_" + "mode\":[\"set\",[]]}}}}}"; break; case 24: //other config missing but datapath_id set // no controller ips replystr = "{\"id\":0,\"error\":null,\"result\":{"+ "\"Port\":{" + "\"c5538a39-8074-403d-bdef-a298f07903cf\":{\"new\":" + "{\"trunks\":[\"set\",[]],\"interfaces\":[\"uuid\"," + "\"a8d4f4aa-67e7-4539-923c-987a7e4ada52\"],\"name\":"+ "\"virbr0\",\"tag\":[\"set\",[]]}}," + "\"52742937-27a8-46ec-8ced-c68d2b6153f7\":{\"new\":"+ "{\"trunks\":[\"set\",[]],\"interfaces\":[\"uuid\","+ "\"e5c62049-0299-467c-b3bc-da2b4ca01f52\"],\"name\":"+ "\"eth1\",\"tag\":[\"set\",[]]}}," + "\"8214a945-f4ee-4671-98af-5c75272aa569\":{\"new\":"+ "{\"trunks\":[\"set\",[]],\"interfaces\":[\"uuid\","+ "\"cde08e29-f0e8-447d-9c1b-650206f19800\"],\"name\":"+ "\"ovs-br0\",\"tag\":[\"set\",[]]}}},"+ "\"Controller\":"+ "{\"924b152e-6a68-4fec-871f-71c28a6e57d1\":{\"new\":"+ "{\"target\":\"\",\"is_" + "connected\":false}}},"+ "\"Interface\":{"+ "\"e5c62049-0299-467c-b3bc-da2b4ca01f52\":{\"new\":" + "{\"name\":\"eth1\",\"type\":\"\",\"options\":[" + "\"map\",[]]}}," + "\"a8d4f4aa-67e7-4539-923c-987a7e4ada52\":{\"new\":" + "{\"name\":\"virbr0\",\"type\":\"internal\",\"opti" + "ons\":[\"map\",[]]}},"+ "\"cde08e29-f0e8-447d-9c1b-650206f19800\":{\"new\":"+ "{\"name\":\"ovs-br0\",\"type\":\"internal\",\"opti" + "ons\":[\"map\",[]]}}}," + "\"Open_vSwitch\":{"+ "\"f4949a56-f807-4e82-b20d-601619b18cd6\":{\"new\":" + "{\"ovs_version\":\"1.3.0+build0\",\"cur_cfg\":14," + "\"bridges\":[\"set\",[[\"uuid\",\"0447bb39-6839" + "-44bc-9653-49d7d86c295a\"],[\"uuid\",\"862a0dc7" + "-20de-415c-8377-20529c7f6cde\"]]],\"manager_" + "options\":[\"set\",[]]}}}," + "\"Bridge\":{" + "\"862a0dc7-20de-415c-8377-20529c7f6cde\":{\"new\":" + "{\"name\":\"ovs-br0\"," + "\"datapath_id\":" + "\"0000000033333334\"," + "\"ports\":[\"set\",[[\"uuid\"," + "\"52742937-27a8-46ec-8ced-c68d2b6153f7\"],[\"uuid\"," + "\"8214a945-f4ee-4671-98af-5c75272aa569\"]]],\"other_" + "config\":[\"map\",[" + "[\"tunnel-ip\",\"192.168.20.138\"]]]," + "\"controller\":[\"uuid\",\"924b152e-6a68-4fec-871f" + "-71c28a6e57d1\"],\"fail_mode\":\"secure\"}},"+ "\"0447bb39-6839-44bc-9653-49d7d86c295a\":{\"new\":" + "{\"name\":\"virbr0\",\"ports\":[\"uuid\",\"c5538a39" + "-8074-403d-bdef-a298f07903cf\"],\"other_config\":" + "[\"map\",[]],\"controller\":[\"set\",[]],\"fail_" + "mode\":[\"set\",[]]}}}}}"; break; case 25: //valid set reply replystr = "{\"method\":\"update\",\"id\":null,\"params\":[null,{" + "\"Bridge\":{\"28a4b61c-a392-476f-bb63-841d12aaf11d\":" + "{\"old\":{\"other_config\":[\"map\",[" + "[\"datapath-id\",\"0000000033333334\"],[\"datapath" + "_type\",\"system\"],[\"tunnel-ip\",\"192.168.158.132\"]]" + "]},\"new\":{\"name\":\"ovs-br0\",\"other_config\":" + "[\"map\",[[\"datapath-id\",\"0000000000000003\"]," + "[\"datapath_type\",\"system\"],[\"tunnel-ip\",\"192.168." + "158.132\"]]]}}}}]}{\"id\":1,\"error\":null,\"result\"" + ":[{\"count\":1},{}]}"; break; } } @Override public int getLengthU() { return replystr.length(); } @Override public void writeTo(ChannelBuffer buf) { logger.info("sent server reply"); buf.writeBytes(replystr.getBytes()); } } }