Modified: qpid/dispatch/trunk/src/router_pynode.c URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/router_pynode.c?rev=1653556&r1=1653555&r2=1653556&view=diff ============================================================================== --- qpid/dispatch/trunk/src/router_pynode.c (original) +++ qpid/dispatch/trunk/src/router_pynode.c Wed Jan 21 15:22:57 2015 @@ -43,151 +43,200 @@ typedef struct { } RouterAdapter; -static char *qd_add_router(qd_router_t *router, const char *address, int router_maskbit, int link_maskbit) +static PyObject *qd_add_router(PyObject *self, PyObject *args) { - if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) - return "Router bit mask out of range"; - - if (link_maskbit >= qd_bitmask_width() || link_maskbit < -1) - return "Link bit mask out of range"; + RouterAdapter *adapter = (RouterAdapter*) self; + qd_router_t *router = adapter->router; + const char *address; + int router_maskbit; + char *error = 0; - sys_mutex_lock(router->lock); - if (router->routers_by_mask_bit[router_maskbit] != 0) { - sys_mutex_unlock(router->lock); - return "Adding router over already existing router"; - } + if (!PyArg_ParseTuple(args, "si", &address, &router_maskbit)) + return 0; - if (link_maskbit >= 0 && router->out_links_by_mask_bit[link_maskbit] == 0) { - sys_mutex_unlock(router->lock); - return "Adding neighbor router with invalid link reference"; - } + do { + if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { + error = "Router bit mask out of range"; + break; + } - // - // Hash lookup the address to ensure there isn't an existing router address. - // - qd_field_iterator_t *iter = qd_field_iterator_string(address, ITER_VIEW_ADDRESS_HASH); - qd_address_t *addr; + sys_mutex_lock(router->lock); + if (router->routers_by_mask_bit[router_maskbit] != 0) { + sys_mutex_unlock(router->lock); + error = "Adding router over already existing router"; + break; + } - qd_hash_retrieve(router->addr_hash, iter, (void**) &addr); - assert(addr == 0); + // + // Hash lookup the address to ensure there isn't an existing router address. + // + qd_field_iterator_t *iter = qd_field_iterator_string(address, ITER_VIEW_ADDRESS_HASH); + qd_address_t *addr; + + qd_hash_retrieve(router->addr_hash, iter, (void**) &addr); + assert(addr == 0); + + // + // Create an address record for this router and insert it in the hash table. + // This record will be found whenever a "foreign" topological address to this + // remote router is looked up. + // + addr = qd_address(); + addr->semantics = router_addr_semantics; + qd_hash_insert(router->addr_hash, iter, addr, &addr->hash_handle); + DEQ_INSERT_TAIL(router->addrs, addr); + qd_entity_cache_add(QD_ROUTER_ADDRESS_TYPE, addr); + qd_field_iterator_free(iter); - // - // Create an address record for this router and insert it in the hash table. - // This record will be found whenever a "foreign" topological address to this - // remote router is looked up. - // - addr = qd_address(); - addr->semantics = router_addr_semantics; - qd_hash_insert(router->addr_hash, iter, addr, &addr->hash_handle); - DEQ_INSERT_TAIL(router->addrs, addr); - qd_entity_cache_add(QD_ROUTER_ADDRESS_TYPE, addr); - qd_field_iterator_free(iter); + // + // Create a router-node record to represent the remote router. + // + qd_router_node_t *rnode = new_qd_router_node_t(); + DEQ_ITEM_INIT(rnode); + rnode->owning_addr = addr; + rnode->mask_bit = router_maskbit; + rnode->next_hop = 0; + rnode->peer_link = 0; + rnode->ref_count = 0; + rnode->valid_origins = qd_bitmask(0); + + DEQ_INSERT_TAIL(router->routers, rnode); + qd_entity_cache_add(QD_ROUTER_NODE_TYPE, rnode); + + // + // Link the router record to the address record. + // + qd_router_add_node_ref_LH(&addr->rnodes, rnode); + + // + // Link the router record to the router address records. + // + qd_router_add_node_ref_LH(&router->router_addr->rnodes, rnode); + qd_router_add_node_ref_LH(&router->routerma_addr->rnodes, rnode); + + // + // Add the router record to the mask-bit index. + // + router->routers_by_mask_bit[router_maskbit] = rnode; - // - // Create a router-node record to represent the remote router. - // - qd_router_node_t *rnode = new_qd_router_node_t(); - DEQ_ITEM_INIT(rnode); - rnode->owning_addr = addr; - rnode->mask_bit = router_maskbit; - rnode->next_hop = 0; - rnode->peer_link = 0; - rnode->ref_count = 0; - rnode->valid_origins = qd_bitmask(0); + sys_mutex_unlock(router->lock); + } while (0); - DEQ_INSERT_TAIL(router->routers, rnode); - qd_entity_cache_add(QD_ROUTER_NODE_TYPE, rnode); + if (error) { + PyErr_SetString(PyExc_Exception, error); + return 0; + } - // - // Link the router record to the address record. - // - qd_router_add_node_ref_LH(&addr->rnodes, rnode); + Py_INCREF(Py_None); + return Py_None; +} - // - // Link the router record to the router address record. - // - qd_router_add_node_ref_LH(&router->router_addr->rnodes, rnode); - // - // Add the router record to the mask-bit index. - // - router->routers_by_mask_bit[router_maskbit] = rnode; +static PyObject* qd_del_router(PyObject *self, PyObject *args) +{ + RouterAdapter *adapter = (RouterAdapter*) self; + qd_router_t *router = adapter->router; + int router_maskbit; + char *error = 0; - // - // If this is a neighbor router, add the peer_link reference to the - // router record. - // - if (link_maskbit >= 0) - rnode->peer_link = router->out_links_by_mask_bit[link_maskbit]; + if (!PyArg_ParseTuple(args, "i", &router_maskbit)) + return 0; - sys_mutex_unlock(router->lock); - return 0; -} + do { + if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { + error = "Router bit mask out of range"; + break; + } + sys_mutex_lock(router->lock); + if (router->routers_by_mask_bit[router_maskbit] == 0) { + sys_mutex_unlock(router->lock); + error = "Deleting nonexistent router"; + break; + } -static char *qd_del_router(qd_router_t *router, int router_maskbit) -{ - if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) - return "Router bit mask out of range"; + qd_router_node_t *rnode = router->routers_by_mask_bit[router_maskbit]; + qd_address_t *oaddr = rnode->owning_addr; + assert(oaddr); - sys_mutex_lock(router->lock); - if (router->routers_by_mask_bit[router_maskbit] == 0) { - sys_mutex_unlock(router->lock); - return "Deleting nonexistent router"; - } + qd_entity_cache_remove(QD_ROUTER_ADDRESS_TYPE, oaddr); + qd_entity_cache_remove(QD_ROUTER_NODE_TYPE, rnode); - qd_router_node_t *rnode = router->routers_by_mask_bit[router_maskbit]; - qd_address_t *oaddr = rnode->owning_addr; - assert(oaddr); + // + // Unlink the router node from the address record + // + qd_router_del_node_ref_LH(&oaddr->rnodes, rnode); + + // + // While the router node has a non-zero reference count, look for addresses + // to unlink the node from. + // + qd_address_t *addr = DEQ_HEAD(router->addrs); + while (addr && rnode->ref_count > 0) { + qd_router_del_node_ref_LH(&addr->rnodes, rnode); + addr = DEQ_NEXT(addr); + } + assert(rnode->ref_count == 0); - qd_entity_cache_remove(QD_ROUTER_ADDRESS_TYPE, oaddr); - qd_entity_cache_remove(QD_ROUTER_NODE_TYPE, rnode); + // + // Free the router node and the owning address records. + // + qd_bitmask_free(rnode->valid_origins); + DEQ_REMOVE(router->routers, rnode); + free_qd_router_node_t(rnode); + + qd_hash_remove_by_handle(router->addr_hash, oaddr->hash_handle); + DEQ_REMOVE(router->addrs, oaddr); + qd_hash_handle_free(oaddr->hash_handle); + router->routers_by_mask_bit[router_maskbit] = 0; + free_qd_address_t(oaddr); - // - // Unlink the router node from the address record - // - qd_router_del_node_ref_LH(&oaddr->rnodes, rnode); + sys_mutex_unlock(router->lock); + } while(0); - // - // While the router node has a non-zero reference count, look for addresses - // to unlink the node from. - // - qd_address_t *addr = DEQ_HEAD(router->addrs); - while (addr && rnode->ref_count > 0) { - qd_router_del_node_ref_LH(&addr->rnodes, rnode); - addr = DEQ_NEXT(addr); + if (error) { + PyErr_SetString(PyExc_Exception, error); + return 0; } - assert(rnode->ref_count == 0); - // - // Free the router node and the owning address records. - // - qd_bitmask_free(rnode->valid_origins); - DEQ_REMOVE(router->routers, rnode); - free_qd_router_node_t(rnode); - - qd_hash_remove_by_handle(router->addr_hash, oaddr->hash_handle); - DEQ_REMOVE(router->addrs, oaddr); - qd_hash_handle_free(oaddr->hash_handle); - router->routers_by_mask_bit[router_maskbit] = 0; - free_qd_address_t(oaddr); - - sys_mutex_unlock(router->lock); - return 0; + Py_INCREF(Py_None); + return Py_None; } -static PyObject* qd_add_remote_router(PyObject *self, PyObject *args) +static PyObject* qd_set_link(PyObject *self, PyObject *args) { RouterAdapter *adapter = (RouterAdapter*) self; qd_router_t *router = adapter->router; - const char *address; int router_maskbit; + int link_maskbit; + char *error = 0; - if (!PyArg_ParseTuple(args, "si", &address, &router_maskbit)) + if (!PyArg_ParseTuple(args, "ii", &router_maskbit, &link_maskbit)) return 0; - char *error = qd_add_router(router, address, router_maskbit, -1); + do { + if (link_maskbit >= qd_bitmask_width() || link_maskbit < 0) { + error = "Link bit mask out of range"; + break; + } + + sys_mutex_lock(router->lock); + if (router->out_links_by_mask_bit[link_maskbit] == 0) { + sys_mutex_unlock(router->lock); + error = "Adding neighbor router with invalid link reference"; + break; + } + + // + // Add the peer_link reference to the router record. + // + qd_router_node_t *rnode = router->routers_by_mask_bit[router_maskbit]; + rnode->peer_link = router->out_links_by_mask_bit[link_maskbit]; + + sys_mutex_unlock(router->lock); + } while (0); + if (error) { PyErr_SetString(PyExc_Exception, error); return 0; @@ -198,16 +247,23 @@ static PyObject* qd_add_remote_router(Py } -static PyObject* qd_del_remote_router(PyObject *self, PyObject *args) +static PyObject* qd_remove_link(PyObject *self, PyObject *args) { RouterAdapter *adapter = (RouterAdapter*) self; qd_router_t *router = adapter->router; - int router_maskbit; + int router_maskbit; + char *error = 0; if (!PyArg_ParseTuple(args, "i", &router_maskbit)) return 0; - char *error = qd_del_router(router, router_maskbit); + do { + sys_mutex_lock(router->lock); + qd_router_node_t *rnode = router->routers_by_mask_bit[router_maskbit]; + rnode->peer_link = 0; + sys_mutex_unlock(router->lock); + } while (0); + if (error) { PyErr_SetString(PyExc_Exception, error); return 0; @@ -224,33 +280,45 @@ static PyObject* qd_set_next_hop(PyObjec qd_router_t *router = adapter->router; int router_maskbit; int next_hop_maskbit; + char *error = 0; if (!PyArg_ParseTuple(args, "ii", &router_maskbit, &next_hop_maskbit)) return 0; - if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { - PyErr_SetString(PyExc_Exception, "Router bit mask out of range"); - return 0; - } + do { + if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { + error = "Router bit mask out of range"; + break; + } - if (next_hop_maskbit >= qd_bitmask_width() || next_hop_maskbit < 0) { - PyErr_SetString(PyExc_Exception, "Next Hop bit mask out of range"); - return 0; - } + if (next_hop_maskbit >= qd_bitmask_width() || next_hop_maskbit < 0) { + error = "Next Hop bit mask out of range"; + break; + } - if (router->routers_by_mask_bit[router_maskbit] == 0) { - PyErr_SetString(PyExc_Exception, "Router Not Found"); - return 0; - } + sys_mutex_lock(router->lock); + if (router->routers_by_mask_bit[router_maskbit] == 0) { + sys_mutex_unlock(router->lock); + error = "Router Not Found"; + break; + } - if (router->routers_by_mask_bit[next_hop_maskbit] == 0) { - PyErr_SetString(PyExc_Exception, "Next Hop Not Found"); - return 0; - } + if (router->routers_by_mask_bit[next_hop_maskbit] == 0) { + sys_mutex_unlock(router->lock); + error = "Next Hop Not Found"; + break; + } - if (router_maskbit != next_hop_maskbit) { - qd_router_node_t *rnode = router->routers_by_mask_bit[router_maskbit]; - rnode->next_hop = router->routers_by_mask_bit[next_hop_maskbit]; + if (router_maskbit != next_hop_maskbit) { + qd_router_node_t *rnode = router->routers_by_mask_bit[router_maskbit]; + rnode->next_hop = router->routers_by_mask_bit[next_hop_maskbit]; + } + sys_mutex_unlock(router->lock); + } while (0); + + if (error) { + PyErr_SetString(PyExc_Exception, error); + return 0; } Py_INCREF(Py_None); @@ -258,55 +326,38 @@ static PyObject* qd_set_next_hop(PyObjec } -static PyObject* qd_set_valid_origins(PyObject *self, PyObject *args) +static PyObject* qd_remove_next_hop(PyObject *self, PyObject *args) { RouterAdapter *adapter = (RouterAdapter*) self; qd_router_t *router = adapter->router; int router_maskbit; - PyObject *origin_list; - Py_ssize_t idx; - - if (!PyArg_ParseTuple(args, "iO", &router_maskbit, &origin_list)) - return 0; - - if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { - PyErr_SetString(PyExc_Exception, "Router bit mask out of range"); - return 0; - } - - if (router->routers_by_mask_bit[router_maskbit] == 0) { - PyErr_SetString(PyExc_Exception, "Router Not Found"); - return 0; - } + char *error = 0; - if (!PyList_Check(origin_list)) { - PyErr_SetString(PyExc_Exception, "Expected List as argument 2"); + if (!PyArg_ParseTuple(args, "i", &router_maskbit)) return 0; - } - - Py_ssize_t origin_count = PyList_Size(origin_list); - qd_router_node_t *rnode = router->routers_by_mask_bit[router_maskbit]; - int maskbit; - for (idx = 0; idx < origin_count; idx++) { - maskbit = PyInt_AS_LONG(PyList_GetItem(origin_list, idx)); - - if (maskbit >= qd_bitmask_width() || maskbit < 0) { - PyErr_SetString(PyExc_Exception, "Origin bit mask out of range"); - return 0; + do { + if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { + error = "Router bit mask out of range"; + break; } - if (router->routers_by_mask_bit[maskbit] == 0) { - PyErr_SetString(PyExc_Exception, "Origin router Not Found"); - return 0; + sys_mutex_lock(router->lock); + if (router->routers_by_mask_bit[router_maskbit] == 0) { + sys_mutex_unlock(router->lock); + error = "Router Not Found"; + break; } - } - qd_bitmask_clear_all(rnode->valid_origins); - qd_bitmask_set_bit(rnode->valid_origins, 0); // This router is a valid origin for all destinations - for (idx = 0; idx < origin_count; idx++) { - maskbit = PyInt_AS_LONG(PyList_GetItem(origin_list, idx)); - qd_bitmask_set_bit(rnode->valid_origins, maskbit); + qd_router_node_t *rnode = router->routers_by_mask_bit[router_maskbit]; + rnode->next_hop = 0; + + sys_mutex_unlock(router->lock); + } while (0); + + if (error) { + PyErr_SetString(PyExc_Exception, error); + return 0; } Py_INCREF(Py_None); @@ -314,38 +365,66 @@ static PyObject* qd_set_valid_origins(Py } -static PyObject* qd_add_neighbor_router(PyObject *self, PyObject *args) +static PyObject* qd_set_valid_origins(PyObject *self, PyObject *args) { RouterAdapter *adapter = (RouterAdapter*) self; qd_router_t *router = adapter->router; - const char *address; int router_maskbit; - int link_maskbit; + PyObject *origin_list; + Py_ssize_t idx; + char *error = 0; - if (!PyArg_ParseTuple(args, "sii", &address, &router_maskbit, &link_maskbit)) + if (!PyArg_ParseTuple(args, "iO", &router_maskbit, &origin_list)) return 0; - char *error = qd_add_router(router, address, router_maskbit, link_maskbit); - if (error) { - PyErr_SetString(PyExc_Exception, error); - return 0; - } + do { + if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { + error = "Router bit mask out of range"; + break; + } - Py_INCREF(Py_None); - return Py_None; -} + if (!PyList_Check(origin_list)) { + error = "Expected List as argument 2"; + break; + } + + sys_mutex_lock(router->lock); + if (router->routers_by_mask_bit[router_maskbit] == 0) { + sys_mutex_unlock(router->lock); + error = "Router Not Found"; + break; + } + Py_ssize_t origin_count = PyList_Size(origin_list); + qd_router_node_t *rnode = router->routers_by_mask_bit[router_maskbit]; + int maskbit; + + for (idx = 0; idx < origin_count; idx++) { + maskbit = PyInt_AS_LONG(PyList_GetItem(origin_list, idx)); + + if (maskbit >= qd_bitmask_width() || maskbit < 0) { + error = "Origin bit mask out of range"; + break; + } + + if (router->routers_by_mask_bit[maskbit] == 0) { + error = "Origin router Not Found"; + break; + } + } -static PyObject* qd_del_neighbor_router(PyObject *self, PyObject *args) -{ - RouterAdapter *adapter = (RouterAdapter*) self; - qd_router_t *router = adapter->router; - int router_maskbit; + if (error == 0) { + qd_bitmask_clear_all(rnode->valid_origins); + qd_bitmask_set_bit(rnode->valid_origins, 0); // This router is a valid origin for all destinations + for (idx = 0; idx < origin_count; idx++) { + maskbit = PyInt_AS_LONG(PyList_GetItem(origin_list, idx)); + qd_bitmask_set_bit(rnode->valid_origins, maskbit); + } + } - if (!PyArg_ParseTuple(args, "i", &router_maskbit)) - return 0; + sys_mutex_unlock(router->lock); + } while (0); - char *error = qd_del_router(router, router_maskbit); if (error) { PyErr_SetString(PyExc_Exception, error); return 0; @@ -478,15 +557,16 @@ static PyObject* qd_get_agent(PyObject * } static PyMethodDef RouterAdapter_methods[] = { - {"add_remote_router", qd_add_remote_router, METH_VARARGS, "A new remote/reachable router has been discovered"}, - {"del_remote_router", qd_del_remote_router, METH_VARARGS, "We've lost reachability to a remote router"}, - {"set_next_hop", qd_set_next_hop, METH_VARARGS, "Set the next hop for a remote router"}, - {"set_valid_origins", qd_set_valid_origins, METH_VARARGS, "Set the valid origins for a remote router"}, - {"add_neighbor_router", qd_add_neighbor_router, METH_VARARGS, "A new neighbor router has been discovered"}, - {"del_neighbor_router", qd_del_neighbor_router, METH_VARARGS, "We've lost reachability to a neighbor router"}, - {"map_destination", qd_map_destination, METH_VARARGS, "Add a newly discovered destination mapping"}, - {"unmap_destination", qd_unmap_destination, METH_VARARGS, "Delete a destination mapping"}, - {"get_agent", qd_get_agent, METH_VARARGS, "Get the management agent"}, + {"add_router", qd_add_router, METH_VARARGS, "A new remote/reachable router has been discovered"}, + {"del_router", qd_del_router, METH_VARARGS, "We've lost reachability to a remote router"}, + {"set_link", qd_set_link, METH_VARARGS, "Set the link for a neighbor router"}, + {"remove_link", qd_remove_link, METH_VARARGS, "Remove the link for a neighbor router"}, + {"set_next_hop", qd_set_next_hop, METH_VARARGS, "Set the next hop for a remote router"}, + {"remove_next_hop", qd_remove_next_hop, METH_VARARGS, "Remove the next hop for a remote router"}, + {"set_valid_origins", qd_set_valid_origins, METH_VARARGS, "Set the valid origins for a remote router"}, + {"map_destination", qd_map_destination, METH_VARARGS, "Add a newly discovered destination mapping"}, + {"unmap_destination", qd_unmap_destination, METH_VARARGS, "Delete a destination mapping"}, + {"get_agent", qd_get_agent, METH_VARARGS, "Get the management agent"}, {0, 0, 0, 0} }; @@ -544,7 +624,7 @@ static PyTypeObject RouterAdapterType = qd_error_t qd_router_python_setup(qd_router_t *router) { qd_error_clear(); - log_source = qd_log_source("PYROUTER"); + log_source = qd_log_source("ROUTER"); // // If we are not operating as an interior router, don't start the
Modified: qpid/dispatch/trunk/tests/config-2/A.conf URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/config-2/A.conf?rev=1653556&r1=1653555&r2=1653556&view=diff ============================================================================== --- qpid/dispatch/trunk/tests/config-2/A.conf (original) +++ qpid/dispatch/trunk/tests/config-2/A.conf Wed Jan 21 15:22:57 2015 @@ -85,3 +85,9 @@ fixed-address { prefix: / fanout: multiple } + +log { + module: ROUTER + enable: trace+ +} + Modified: qpid/dispatch/trunk/tests/config-2/B.conf URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/config-2/B.conf?rev=1653556&r1=1653555&r2=1653556&view=diff ============================================================================== --- qpid/dispatch/trunk/tests/config-2/B.conf (original) +++ qpid/dispatch/trunk/tests/config-2/B.conf Wed Jan 21 15:22:57 2015 @@ -85,3 +85,8 @@ fixed-address { prefix: / fanout: multiple } + +log { + module: ROUTER + enable: trace+ +} Modified: qpid/dispatch/trunk/tests/config-3-linear/A.conf URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/config-3-linear/A.conf?rev=1653556&r1=1653555&r2=1653556&view=diff ============================================================================== --- qpid/dispatch/trunk/tests/config-3-linear/A.conf (original) +++ qpid/dispatch/trunk/tests/config-3-linear/A.conf Wed Jan 21 15:22:57 2015 @@ -64,5 +64,13 @@ router { router-id: QDR.A } +log { + module: ROUTER + enable: trace+ +} +log { + module: ROUTER_LS + enable: trace+ +} Modified: qpid/dispatch/trunk/tests/config-3-linear/B.conf URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/config-3-linear/B.conf?rev=1653556&r1=1653555&r2=1653556&view=diff ============================================================================== --- qpid/dispatch/trunk/tests/config-3-linear/B.conf (original) +++ qpid/dispatch/trunk/tests/config-3-linear/B.conf Wed Jan 21 15:22:57 2015 @@ -65,3 +65,13 @@ router { mode: interior router-id: QDR.B } + +log { + module: ROUTER + enable: trace+ +} + +log { + module: ROUTER_LS + enable: trace+ +} Modified: qpid/dispatch/trunk/tests/config-3-linear/C.conf URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/config-3-linear/C.conf?rev=1653556&r1=1653555&r2=1653556&view=diff ============================================================================== --- qpid/dispatch/trunk/tests/config-3-linear/C.conf (original) +++ qpid/dispatch/trunk/tests/config-3-linear/C.conf Wed Jan 21 15:22:57 2015 @@ -58,3 +58,13 @@ router { mode: interior router-id: QDR.C } + +log { + module: ROUTER + enable: trace+ +} + +log { + module: ROUTER_LS + enable: trace+ +} Added: qpid/dispatch/trunk/tests/config-6/A.conf URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/config-6/A.conf?rev=1653556&view=auto ============================================================================== --- qpid/dispatch/trunk/tests/config-6/A.conf (added) +++ qpid/dispatch/trunk/tests/config-6/A.conf Wed Jan 21 15:22:57 2015 @@ -0,0 +1,81 @@ +## +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you under the Apache License, Version 2.0 (the +## "License"); you may not use this file except in compliance +## with the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +## KIND, either express or implied. See the License for the +## specific language governing permissions and limitations +## under the License +## + + +## +## Container section - Configures the general operation of the AMQP container. +## +container { + worker-threads: 4 + container-name: QDR.A +} + + +## +## Listeners and Connectors +## +listener { + role: inter-router + addr: 0.0.0.0 + port: 20001 + sasl-mechanisms: ANONYMOUS +} + +connector { + role: inter-router + addr: 0.0.0.0 + port: 20002 + sasl-mechanisms: ANONYMOUS +} + +connector { + role: inter-router + addr: 0.0.0.0 + port: 20003 + sasl-mechanisms: ANONYMOUS +} + +connector { + role: inter-router + addr: 0.0.0.0 + port: 20004 + sasl-mechanisms: ANONYMOUS +} + +router { + mode: interior + area: A + router-id: QDR.A +} + +fixed-address { + prefix: /closest/ + fanout: single + bias: closest +} + +log { + module: ROUTER + enable: trace+ +} + +log { + module: ROUTER_MA + enable: trace+ +} Added: qpid/dispatch/trunk/tests/config-6/B.conf URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/config-6/B.conf?rev=1653556&view=auto ============================================================================== --- qpid/dispatch/trunk/tests/config-6/B.conf (added) +++ qpid/dispatch/trunk/tests/config-6/B.conf Wed Jan 21 15:22:57 2015 @@ -0,0 +1,74 @@ +## +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you under the Apache License, Version 2.0 (the +## "License"); you may not use this file except in compliance +## with the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +## KIND, either express or implied. See the License for the +## specific language governing permissions and limitations +## under the License +## + + +## +## Container section - Configures the general operation of the AMQP container. +## +container { + worker-threads: 4 + container-name: QDR.B +} + + +## +## Listeners and Connectors +## +listener { + role: inter-router + addr: 0.0.0.0 + port: 20002 + sasl-mechanisms: ANONYMOUS +} + +connector { + role: inter-router + addr: 0.0.0.0 + port: 20003 + sasl-mechanisms: ANONYMOUS +} + +connector { + role: inter-router + addr: 0.0.0.0 + port: 20004 + sasl-mechanisms: ANONYMOUS +} + +router { + mode: interior + area: A + router-id: QDR.B +} + +fixed-address { + prefix: /closest/ + fanout: single + bias: closest +} + +log { + module: ROUTER + enable: trace+ +} + +log { + module: ROUTER_MA + enable: trace+ +} Added: qpid/dispatch/trunk/tests/config-6/C.conf URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/config-6/C.conf?rev=1653556&view=auto ============================================================================== --- qpid/dispatch/trunk/tests/config-6/C.conf (added) +++ qpid/dispatch/trunk/tests/config-6/C.conf Wed Jan 21 15:22:57 2015 @@ -0,0 +1,69 @@ +## +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you under the Apache License, Version 2.0 (the +## "License"); you may not use this file except in compliance +## with the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +## KIND, either express or implied. See the License for the +## specific language governing permissions and limitations +## under the License +## + + +## +## Container section - Configures the general operation of the AMQP container. +## +container { + worker-threads: 4 + container-name: QDR.C +} + + +## +## Listeners and Connectors +## +listener { + role: inter-router + addr: 0.0.0.0 + port: 20003 + sasl-mechanisms: ANONYMOUS +} + +connector { + role: inter-router + addr: 0.0.0.0 + port: 20004 + sasl-mechanisms: ANONYMOUS +} + +router { + mode: interior + area: A + router-id: QDR.C +} + +fixed-address { + prefix: /closest/ + fanout: single + bias: closest +} + +log { + module: ROUTER + enable: trace+ +} + +log { + module: ROUTER_MA + enable: trace+ +} + + Added: qpid/dispatch/trunk/tests/config-6/D.conf URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/config-6/D.conf?rev=1653556&view=auto ============================================================================== --- qpid/dispatch/trunk/tests/config-6/D.conf (added) +++ qpid/dispatch/trunk/tests/config-6/D.conf Wed Jan 21 15:22:57 2015 @@ -0,0 +1,62 @@ +## +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you under the Apache License, Version 2.0 (the +## "License"); you may not use this file except in compliance +## with the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +## KIND, either express or implied. See the License for the +## specific language governing permissions and limitations +## under the License +## + + +## +## Container section - Configures the general operation of the AMQP container. +## +container { + worker-threads: 4 + container-name: QDR.D +} + + +## +## Listeners and Connectors +## +listener { + role: inter-router + addr: 0.0.0.0 + port: 20004 + sasl-mechanisms: ANONYMOUS +} + +router { + mode: interior + area: A + router-id: QDR.D +} + +fixed-address { + prefix: /closest/ + fanout: single + bias: closest +} + +log { + module: ROUTER + enable: trace+ +} + +log { + module: ROUTER_MA + enable: trace+ +} + + Added: qpid/dispatch/trunk/tests/config-6/X.conf URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/config-6/X.conf?rev=1653556&view=auto ============================================================================== --- qpid/dispatch/trunk/tests/config-6/X.conf (added) +++ qpid/dispatch/trunk/tests/config-6/X.conf Wed Jan 21 15:22:57 2015 @@ -0,0 +1,75 @@ +## +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you under the Apache License, Version 2.0 (the +## "License"); you may not use this file except in compliance +## with the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +## KIND, either express or implied. See the License for the +## specific language governing permissions and limitations +## under the License +## + + +## +## Container section - Configures the general operation of the AMQP container. +## +container { + worker-threads: 4 + container-name: QDR.X +} + + +## +## Listeners and Connectors +## +listener { + addr: 0.0.0.0 + port: amqp + sasl-mechanisms: ANONYMOUS +} + +connector { + role: inter-router + addr: 0.0.0.0 + port: 20001 + sasl-mechanisms: ANONYMOUS +} + +connector { + role: inter-router + addr: 0.0.0.0 + port: 20002 + sasl-mechanisms: ANONYMOUS +} + +router { + mode: interior + area: A + router-id: QDR.X +} + +fixed-address { + prefix: /closest/ + fanout: single + bias: closest +} + +log { + module: ROUTER + enable: trace+ +} + +log { + module: ROUTER_MA + enable: trace+ +} + + Added: qpid/dispatch/trunk/tests/config-6/Y.conf URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/config-6/Y.conf?rev=1653556&view=auto ============================================================================== --- qpid/dispatch/trunk/tests/config-6/Y.conf (added) +++ qpid/dispatch/trunk/tests/config-6/Y.conf Wed Jan 21 15:22:57 2015 @@ -0,0 +1,73 @@ +## +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you under the Apache License, Version 2.0 (the +## "License"); you may not use this file except in compliance +## with the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +## KIND, either express or implied. See the License for the +## specific language governing permissions and limitations +## under the License +## + + +## +## Container section - Configures the general operation of the AMQP container. +## +container { + worker-threads: 4 + container-name: QDR.Y +} + + +## +## Listeners and Connectors +## +listener { + addr: 0.0.0.0 + port: 20005 + sasl-mechanisms: ANONYMOUS +} + +connector { + role: inter-router + addr: 0.0.0.0 + port: 20003 + sasl-mechanisms: ANONYMOUS +} + +connector { + role: inter-router + addr: 0.0.0.0 + port: 20004 + sasl-mechanisms: ANONYMOUS +} + +router { + mode: interior + area: A + router-id: QDR.Y +} + +fixed-address { + prefix: /closest/ + fanout: single + bias: closest +} + +log { + module: ROUTER + enable: trace+ +} + +log { + module: ROUTER_MA + enable: trace+ +} Copied: qpid/dispatch/trunk/tests/config-6/topology.txt (from r1650165, qpid/dispatch/trunk/tests/config-3-linear/topology.txt) URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/config-6/topology.txt?p2=qpid/dispatch/trunk/tests/config-6/topology.txt&p1=qpid/dispatch/trunk/tests/config-3-linear/topology.txt&r1=1650165&r2=1653556&rev=1653556&view=diff ============================================================================== --- qpid/dispatch/trunk/tests/config-3-linear/topology.txt (original) +++ qpid/dispatch/trunk/tests/config-6/topology.txt Wed Jan 21 15:22:57 2015 @@ -19,12 +19,24 @@ +----------+ +----------+ +----------+ - |QDR.A | |QDR.B | |QDR.C | + |QDR.X | |QDR.A | |QDR.C | |port: | |port: | |port: | - | 20001 |--------->| 20002 |--------->| 20003 | - | | | | | | - | | | | | | - +----------+ +----------+ +----------+ + | 5672 |--------->| 20001 |--------->| 20003 | + | | | | | |<------+ + | |--+ | | +---->| | | + +----------+ | +----------+ | +----------+ | + | | | | | | + | | +--------------+ | | + | | | | | | + | v | v v | + | +----------+ | +----------+ | +----------+ + | |QDR.B |----+ |QDR.D | +--|QDR.Y | + +------>|port: | |port: | |port: | + | 20002 |--------->| 20004 |<---------| 20005 | + | | | | | | + | | | | | | + +----------+ +----------+ +----------+ + * The direction of the arrow shows the direction of the connection setup Connector --> Listener Modified: qpid/dispatch/trunk/tests/router_engine_test.py URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/router_engine_test.py?rev=1653556&r1=1653555&r2=1653556&view=diff ============================================================================== --- qpid/dispatch/trunk/tests/router_engine_test.py (original) +++ qpid/dispatch/trunk/tests/router_engine_test.py Wed Jan 21 15:22:57 2015 @@ -24,7 +24,7 @@ import unittest sys.path.append(os.path.join(os.environ["SOURCE_DIR"], "python")) sys.path.append(os.path.join(os.path.dirname(__file__), "mock")) # Mock modules for tests -from qpid_dispatch_internal.router.engine import NeighborEngine, PathEngine, NodeTracker +from qpid_dispatch_internal.router.engine import HelloProtocol, PathEngine, NodeTracker from qpid_dispatch_internal.router.data import LinkState, MessageHELLO from qpid_dispatch.management.entity import EntityBase from system_test import main_module @@ -52,14 +52,12 @@ class Adapter(object): class DataTest(unittest.TestCase): def test_link_state(self): - ls = LinkState(None, 'R1', 'area', 1, ['R2', 'R3']) + ls = LinkState(None, 'R1', 1, ['R2', 'R3']) self.assertEqual(ls.id, 'R1') - self.assertEqual(ls.area, 'area') self.assertEqual(ls.ls_seq, 1) self.assertEqual(ls.peers, ['R2', 'R3']) ls.bump_sequence() self.assertEqual(ls.id, 'R1') - self.assertEqual(ls.area, 'area') self.assertEqual(ls.ls_seq, 2) self.assertEqual(ls.peers, ['R2', 'R3']) @@ -80,22 +78,19 @@ class DataTest(unittest.TestCase): encoded = ls.to_dict() new_ls = LinkState(encoded) self.assertEqual(new_ls.id, 'R1') - self.assertEqual(new_ls.area, 'area') self.assertEqual(new_ls.ls_seq, 2) self.assertEqual(new_ls.peers, ['R2', 'R4']) def test_hello_message(self): - msg1 = MessageHELLO(None, 'R1', 'area', ['R2', 'R3', 'R4']) + msg1 = MessageHELLO(None, 'R1', ['R2', 'R3', 'R4']) self.assertEqual(msg1.get_opcode(), "HELLO") self.assertEqual(msg1.id, 'R1') - self.assertEqual(msg1.area, 'area') self.assertEqual(msg1.seen_peers, ['R2', 'R3', 'R4']) encoded = msg1.to_dict() msg2 = MessageHELLO(encoded) self.assertEqual(msg2.get_opcode(), "HELLO") self.assertEqual(msg2.id, 'R1') - self.assertEqual(msg2.area, 'area') self.assertEqual(msg2.seen_peers, ['R2', 'R3', 'R4']) self.assertTrue(msg2.is_seen('R3')) self.assertFalse(msg2.is_seen('R9')) @@ -133,149 +128,32 @@ class NodeTrackerTest(unittest.TestCase) self.address = None self.router_bit = None self.link_bit = None - self.area = "area" self.calls = 0 - def test_node_tracker_limits(self): - tracker = NodeTracker(self, 5) - - self.reset() - tracker.new_neighbor('A', 1, 0) - self.assertEqual(self.address, 'amqp:/_topo/area/A') - self.assertEqual(self.link_bit, 1) - self.assertEqual(self.router_bit, 1) - self.assertEqual(self.calls, 1) - - self.reset() - tracker.new_neighbor('B', 5, 0) - self.assertEqual(self.address, 'amqp:/_topo/area/B') - self.assertEqual(self.link_bit, 5) - self.assertEqual(self.router_bit, 2) - self.assertEqual(self.calls, 1) - - self.reset() - tracker.new_neighbor('C', 6, 0) - self.assertEqual(self.address, 'amqp:/_topo/area/C') - self.assertEqual(self.link_bit, 6) - self.assertEqual(self.router_bit, 3) - self.assertEqual(self.calls, 1) - - self.reset() - tracker.new_neighbor('D', 7, 0) - self.assertEqual(self.address, 'amqp:/_topo/area/D') - self.assertEqual(self.link_bit, 7) - self.assertEqual(self.router_bit, 4) - self.assertEqual(self.calls, 1) - - self.reset() - try: - tracker.new_neighbor('E', 9, 0) - self.fail("We shouldn't be here") - except: - pass - - self.reset() - tracker.lost_neighbor('C') - self.assertEqual(self.router_bit, 3) - self.assertEqual(self.calls, 1) - - self.reset() - tracker.new_neighbor('E', 9, 0) - self.assertEqual(self.address, 'amqp:/_topo/area/E') - self.assertEqual(self.link_bit, 9) - self.assertEqual(self.router_bit, 3) - self.assertEqual(self.calls, 1) - - - def test_node_tracker_remote_neighbor(self): - tracker = NodeTracker(self, 5) - - self.reset() - tracker.new_node('A', 0) - self.assertEqual(self.address, 'amqp:/_topo/area/A') - self.assertFalse(self.link_bit) - self.assertEqual(self.router_bit, 1) - self.assertEqual(self.calls, 1) - - self.reset() - tracker.new_neighbor('A', 3, 0) - self.assertEqual(self.address, 'amqp:/_topo/area/A') - self.assertEqual(self.link_bit, 3) - self.assertEqual(self.router_bit, 1) - self.assertEqual(self.calls, 2) - - self.reset() - tracker.lost_node('A') - self.assertFalse(self.address) - self.assertFalse(self.link_bit) - self.assertFalse(self.router_bit) - self.assertEqual(self.calls, 0) - - self.reset() - tracker.lost_neighbor('A') - self.assertEqual(self.router_bit, 1) - self.assertEqual(self.calls, 1) - - - def test_node_tracker_neighbor_remote(self): - tracker = NodeTracker(self, 5) - - self.reset() - tracker.new_neighbor('A', 3, 0) - self.assertEqual(self.address, 'amqp:/_topo/area/A') - self.assertEqual(self.link_bit, 3) - self.assertEqual(self.router_bit, 1) - self.assertEqual(self.calls, 1) - - self.reset() - tracker.new_node('A', 0) - self.assertFalse(self.address) - self.assertFalse(self.link_bit) - self.assertFalse(self.router_bit) - self.assertEqual(self.calls, 0) - - self.reset() - tracker.lost_neighbor('A') - self.assertEqual(self.address, 'amqp:/_topo/area/A') - self.assertEqual(self.router_bit, 1) - self.assertEqual(self.calls, 2) - - self.reset() - tracker.lost_node('A') - self.assertEqual(self.router_bit, 1) - self.assertEqual(self.calls, 1) - class NeighborTest(unittest.TestCase): def log(self, level, text): pass + def log_hello(self, level, text): + pass + def send(self, dest, msg): self.sent.append((dest, msg)) - def local_link_state_changed(self, link_state): - self.local_link_state = link_state - - def new_neighbor(self, rid, lbit, instance): - self.neighbors[rid] = None - - def lost_neighbor(self, rid): - self.neighbors.pop(rid) - - def touch_node(self, rid, instance): - pass + def neighbor_refresh(self, node_id, instance, link_id, now): + self.neighbors[node_id] = (instance, link_id, now) def setUp(self): self.sent = [] - self.local_link_state = None + self.neighbors = {} self.id = "R1" - self.area = "area" self.instance = 0 # Fake configuration self.config = EntityBase({ - 'helloInterval' : 1.0, - 'helloMaxAge' : 3.0, - 'raInterval' : 30.0, + 'helloInterval' : 1.0, + 'helloMaxAge' : 3.0, + 'raInterval' : 30.0, 'remoteLsMaxAge' : 60.0, 'mobileAddrMaxAge' : 60.0 }) self.neighbors = {} @@ -283,7 +161,7 @@ class NeighborTest(unittest.TestCase): def test_hello_sent(self): self.sent = [] self.local_link_state = None - self.engine = NeighborEngine(self) + self.engine = HelloProtocol(self, self) self.engine.tick(0.5) self.assertEqual(self.sent, []) self.engine.tick(1.5) @@ -292,15 +170,14 @@ class NeighborTest(unittest.TestCase): self.assertEqual(dest, "amqp:/_local/qdhello") self.assertEqual(msg.get_opcode(), "HELLO") self.assertEqual(msg.id, self.id) - self.assertEqual(msg.area, self.area) self.assertEqual(msg.seen_peers, []) self.assertEqual(self.local_link_state, None) def test_sees_peer(self): self.sent = [] - self.local_link_state = None - self.engine = NeighborEngine(self) - self.engine.handle_hello(MessageHELLO(None, 'R2', 'area', []), 2.0, 0) + self.neighbors = {} + self.engine = HelloProtocol(self, self) + self.engine.handle_hello(MessageHELLO(None, 'R2', []), 2.0, 0) self.engine.tick(5.0) self.assertEqual(len(self.sent), 1) dest, msg = self.sent.pop(0) @@ -308,65 +185,40 @@ class NeighborTest(unittest.TestCase): def test_establish_peer(self): self.sent = [] - self.local_link_state = None - self.engine = NeighborEngine(self) - self.engine.handle_hello(MessageHELLO(None, 'R2', 'area', ['R1']), 0.5, 0) + self.neighbors = {} + self.engine = HelloProtocol(self, self) + self.engine.handle_hello(MessageHELLO(None, 'R2', ['R1']), 0.5, 0) self.engine.tick(1.0) self.engine.tick(2.0) self.engine.tick(3.0) - self.assertEqual(self.local_link_state.id, 'R1') - self.assertEqual(self.local_link_state.area, 'area') - self.assertEqual(self.local_link_state.ls_seq, 1) - self.assertEqual(self.local_link_state.peers, ['R2']) + self.assertEqual(len(self.neighbors), 1) + self.assertEqual(self.neighbors.keys(), ['R2']) def test_establish_multiple_peers(self): self.sent = [] - self.local_link_state = None - self.engine = NeighborEngine(self) - self.engine.handle_hello(MessageHELLO(None, 'R2', 'area', ['R1']), 0.5, 0) + self.neighbors = {} + self.engine = HelloProtocol(self, self) + self.engine.handle_hello(MessageHELLO(None, 'R2', ['R1']), 0.5, 0) self.engine.tick(1.0) - self.engine.handle_hello(MessageHELLO(None, 'R3', 'area', ['R1', 'R2']), 1.5, 0) + self.engine.handle_hello(MessageHELLO(None, 'R3', ['R1', 'R2']), 1.5, 0) self.engine.tick(2.0) - self.engine.handle_hello(MessageHELLO(None, 'R4', 'area', ['R1']), 2.5, 0) - self.engine.handle_hello(MessageHELLO(None, 'R5', 'area', ['R2']), 2.5, 0) - self.engine.handle_hello(MessageHELLO(None, 'R6', 'area', ['R1']), 2.5, 0) + self.engine.handle_hello(MessageHELLO(None, 'R4', ['R1']), 2.5, 0) + self.engine.handle_hello(MessageHELLO(None, 'R5', ['R2']), 2.5, 0) + self.engine.handle_hello(MessageHELLO(None, 'R6', ['R1']), 2.5, 0) self.engine.tick(3.0) - self.assertEqual(self.local_link_state.id, 'R1') - self.assertEqual(self.local_link_state.area, 'area') - self.assertEqual(self.local_link_state.ls_seq, 3) - self.local_link_state.peers.sort() - self.assertEqual(self.local_link_state.peers, ['R2', 'R3', 'R4', 'R6']) - - def test_timeout_peer(self): - self.sent = [] - self.local_link_state = None - self.engine = NeighborEngine(self) - self.engine.handle_hello(MessageHELLO(None, 'R2', 'area', ['R3', 'R1']), 2.0, 0) - self.engine.tick(5.0) - self.engine.tick(17.1) - self.assertEqual(self.local_link_state.id, 'R1') - self.assertEqual(self.local_link_state.area, 'area') - self.assertEqual(self.local_link_state.ls_seq, 2) - self.assertEqual(self.local_link_state.peers, []) + keys = self.neighbors.keys() + keys.sort() + self.assertEqual(keys, ['R2', 'R3', 'R4', 'R6']) class PathTest(unittest.TestCase): def setUp(self): self.id = 'R1' - self.area = 'area' - self.next_hops = None - self.valid_origins = None self.engine = PathEngine(self) def log(self, level, text): pass - def next_hops_changed(self, nh): - self.next_hops = nh - - def valid_origins_changed(self, vo): - self.valid_origins = vo - def test_topology1(self): """ @@ -375,19 +227,18 @@ class PathTest(unittest.TestCase): +====+ +----+ +----+ """ - collection = { 'R1': LinkState(None, 'R1', 'area', 1, ['R2']), - 'R2': LinkState(None, 'R2', 'area', 1, ['R1', 'R3']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R2']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 2) - self.assertEqual(self.next_hops['R2'], 'R2') - self.assertEqual(self.next_hops['R3'], 'R2') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.assertEqual(self.valid_origins['R2'], []) - self.assertEqual(self.valid_origins['R3'], []) + collection = { 'R1': LinkState(None, 'R1', 1, ['R2']), + 'R2': LinkState(None, 'R2', 1, ['R1', 'R3']), + 'R3': LinkState(None, 'R3', 1, ['R2']) } + next_hops, valid_origins = self.engine.calculate_routes(collection) + self.assertEqual(len(next_hops), 2) + self.assertEqual(next_hops['R2'], 'R2') + self.assertEqual(next_hops['R3'], 'R2') + + valid_origins['R2'].sort() + valid_origins['R3'].sort() + self.assertEqual(valid_origins['R2'], []) + self.assertEqual(valid_origins['R3'], []) def test_topology2(self): """ @@ -401,31 +252,30 @@ class PathTest(unittest.TestCase): +----+ +----+ +----+ """ - collection = { 'R1': LinkState(None, 'R1', 'area', 1, ['R2']), - 'R2': LinkState(None, 'R2', 'area', 1, ['R1', 'R3', 'R4']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R2', 'R5']), - 'R4': LinkState(None, 'R4', 'area', 1, ['R2', 'R5']), - 'R5': LinkState(None, 'R5', 'area', 1, ['R3', 'R4', 'R6']), - 'R6': LinkState(None, 'R6', 'area', 1, ['R5']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 5) - self.assertEqual(self.next_hops['R2'], 'R2') - self.assertEqual(self.next_hops['R3'], 'R2') - self.assertEqual(self.next_hops['R4'], 'R2') - self.assertEqual(self.next_hops['R5'], 'R2') - self.assertEqual(self.next_hops['R6'], 'R2') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.valid_origins['R4'].sort() - self.valid_origins['R5'].sort() - self.valid_origins['R6'].sort() - self.assertEqual(self.valid_origins['R2'], []) - self.assertEqual(self.valid_origins['R3'], []) - self.assertEqual(self.valid_origins['R4'], []) - self.assertEqual(self.valid_origins['R5'], []) - self.assertEqual(self.valid_origins['R6'], []) + collection = { 'R1': LinkState(None, 'R1', 1, ['R2']), + 'R2': LinkState(None, 'R2', 1, ['R1', 'R3', 'R4']), + 'R3': LinkState(None, 'R3', 1, ['R2', 'R5']), + 'R4': LinkState(None, 'R4', 1, ['R2', 'R5']), + 'R5': LinkState(None, 'R5', 1, ['R3', 'R4', 'R6']), + 'R6': LinkState(None, 'R6', 1, ['R5']) } + next_hops, valid_origins = self.engine.calculate_routes(collection) + self.assertEqual(len(next_hops), 5) + self.assertEqual(next_hops['R2'], 'R2') + self.assertEqual(next_hops['R3'], 'R2') + self.assertEqual(next_hops['R4'], 'R2') + self.assertEqual(next_hops['R5'], 'R2') + self.assertEqual(next_hops['R6'], 'R2') + + valid_origins['R2'].sort() + valid_origins['R3'].sort() + valid_origins['R4'].sort() + valid_origins['R5'].sort() + valid_origins['R6'].sort() + self.assertEqual(valid_origins['R2'], []) + self.assertEqual(valid_origins['R3'], []) + self.assertEqual(valid_origins['R4'], []) + self.assertEqual(valid_origins['R5'], []) + self.assertEqual(valid_origins['R6'], []) def test_topology3(self): """ @@ -439,31 +289,30 @@ class PathTest(unittest.TestCase): +====+ +----+ +----+ """ - collection = { 'R2': LinkState(None, 'R2', 'area', 1, ['R3']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R1', 'R2', 'R4']), - 'R4': LinkState(None, 'R4', 'area', 1, ['R3', 'R5']), - 'R1': LinkState(None, 'R1', 'area', 1, ['R3', 'R5']), - 'R5': LinkState(None, 'R5', 'area', 1, ['R1', 'R4', 'R6']), - 'R6': LinkState(None, 'R6', 'area', 1, ['R5']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 5) - self.assertEqual(self.next_hops['R2'], 'R3') - self.assertEqual(self.next_hops['R3'], 'R3') - self.assertEqual(self.next_hops['R4'], 'R3') - self.assertEqual(self.next_hops['R5'], 'R5') - self.assertEqual(self.next_hops['R6'], 'R5') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.valid_origins['R4'].sort() - self.valid_origins['R5'].sort() - self.valid_origins['R6'].sort() - self.assertEqual(self.valid_origins['R2'], ['R5', 'R6']) - self.assertEqual(self.valid_origins['R3'], ['R5', 'R6']) - self.assertEqual(self.valid_origins['R4'], []) - self.assertEqual(self.valid_origins['R5'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R6'], ['R2', 'R3']) + collection = { 'R2': LinkState(None, 'R2', 1, ['R3']), + 'R3': LinkState(None, 'R3', 1, ['R1', 'R2', 'R4']), + 'R4': LinkState(None, 'R4', 1, ['R3', 'R5']), + 'R1': LinkState(None, 'R1', 1, ['R3', 'R5']), + 'R5': LinkState(None, 'R5', 1, ['R1', 'R4', 'R6']), + 'R6': LinkState(None, 'R6', 1, ['R5']) } + next_hops, valid_origins = self.engine.calculate_routes(collection) + self.assertEqual(len(next_hops), 5) + self.assertEqual(next_hops['R2'], 'R3') + self.assertEqual(next_hops['R3'], 'R3') + self.assertEqual(next_hops['R4'], 'R3') + self.assertEqual(next_hops['R5'], 'R5') + self.assertEqual(next_hops['R6'], 'R5') + + valid_origins['R2'].sort() + valid_origins['R3'].sort() + valid_origins['R4'].sort() + valid_origins['R5'].sort() + valid_origins['R6'].sort() + self.assertEqual(valid_origins['R2'], ['R5', 'R6']) + self.assertEqual(valid_origins['R3'], ['R5', 'R6']) + self.assertEqual(valid_origins['R4'], []) + self.assertEqual(valid_origins['R5'], ['R2', 'R3']) + self.assertEqual(valid_origins['R6'], ['R2', 'R3']) def test_topology4(self): """ @@ -477,34 +326,33 @@ class PathTest(unittest.TestCase): +====+ +----+ +----+ """ - collection = { 'R2': LinkState(None, 'R2', 'area', 1, ['R3']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R1', 'R2', 'R4']), - 'R4': LinkState(None, 'R4', 'area', 1, ['R3', 'R5']), - 'R1': LinkState(None, 'R1', 'area', 1, ['R3', 'R5']), - 'R5': LinkState(None, 'R5', 'area', 1, ['R1', 'R4', 'R6']), - 'R6': LinkState(None, 'R6', 'area', 1, ['R5', 'R7']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 6) - self.assertEqual(self.next_hops['R2'], 'R3') - self.assertEqual(self.next_hops['R3'], 'R3') - self.assertEqual(self.next_hops['R4'], 'R3') - self.assertEqual(self.next_hops['R5'], 'R5') - self.assertEqual(self.next_hops['R6'], 'R5') - self.assertEqual(self.next_hops['R7'], 'R5') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.valid_origins['R4'].sort() - self.valid_origins['R5'].sort() - self.valid_origins['R6'].sort() - self.valid_origins['R7'].sort() - self.assertEqual(self.valid_origins['R2'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R3'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R4'], []) - self.assertEqual(self.valid_origins['R5'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R6'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R7'], ['R2', 'R3']) + collection = { 'R2': LinkState(None, 'R2', 1, ['R3']), + 'R3': LinkState(None, 'R3', 1, ['R1', 'R2', 'R4']), + 'R4': LinkState(None, 'R4', 1, ['R3', 'R5']), + 'R1': LinkState(None, 'R1', 1, ['R3', 'R5']), + 'R5': LinkState(None, 'R5', 1, ['R1', 'R4', 'R6']), + 'R6': LinkState(None, 'R6', 1, ['R5', 'R7']) } + next_hops, valid_origins = self.engine.calculate_routes(collection) + self.assertEqual(len(next_hops), 6) + self.assertEqual(next_hops['R2'], 'R3') + self.assertEqual(next_hops['R3'], 'R3') + self.assertEqual(next_hops['R4'], 'R3') + self.assertEqual(next_hops['R5'], 'R5') + self.assertEqual(next_hops['R6'], 'R5') + self.assertEqual(next_hops['R7'], 'R5') + + valid_origins['R2'].sort() + valid_origins['R3'].sort() + valid_origins['R4'].sort() + valid_origins['R5'].sort() + valid_origins['R6'].sort() + valid_origins['R7'].sort() + self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) + self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) + self.assertEqual(valid_origins['R4'], []) + self.assertEqual(valid_origins['R5'], ['R2', 'R3']) + self.assertEqual(valid_origins['R6'], ['R2', 'R3']) + self.assertEqual(valid_origins['R7'], ['R2', 'R3']) def test_topology5(self): """ @@ -518,34 +366,33 @@ class PathTest(unittest.TestCase): +====+ +----+ +----+ """ - collection = { 'R2': LinkState(None, 'R2', 'area', 1, ['R3', 'R1']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R1', 'R2', 'R4']), - 'R4': LinkState(None, 'R4', 'area', 1, ['R3', 'R5']), - 'R1': LinkState(None, 'R1', 'area', 1, ['R3', 'R5', 'R2']), - 'R5': LinkState(None, 'R5', 'area', 1, ['R1', 'R4', 'R6']), - 'R6': LinkState(None, 'R6', 'area', 1, ['R5', 'R7']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 6) - self.assertEqual(self.next_hops['R2'], 'R2') - self.assertEqual(self.next_hops['R3'], 'R3') - self.assertEqual(self.next_hops['R4'], 'R3') - self.assertEqual(self.next_hops['R5'], 'R5') - self.assertEqual(self.next_hops['R6'], 'R5') - self.assertEqual(self.next_hops['R7'], 'R5') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.valid_origins['R4'].sort() - self.valid_origins['R5'].sort() - self.valid_origins['R6'].sort() - self.valid_origins['R7'].sort() - self.assertEqual(self.valid_origins['R2'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R3'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R4'], []) - self.assertEqual(self.valid_origins['R5'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R6'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R7'], ['R2', 'R3']) + collection = { 'R2': LinkState(None, 'R2', 1, ['R3', 'R1']), + 'R3': LinkState(None, 'R3', 1, ['R1', 'R2', 'R4']), + 'R4': LinkState(None, 'R4', 1, ['R3', 'R5']), + 'R1': LinkState(None, 'R1', 1, ['R3', 'R5', 'R2']), + 'R5': LinkState(None, 'R5', 1, ['R1', 'R4', 'R6']), + 'R6': LinkState(None, 'R6', 1, ['R5', 'R7']) } + next_hops, valid_origins = self.engine.calculate_routes(collection) + self.assertEqual(len(next_hops), 6) + self.assertEqual(next_hops['R2'], 'R2') + self.assertEqual(next_hops['R3'], 'R3') + self.assertEqual(next_hops['R4'], 'R3') + self.assertEqual(next_hops['R5'], 'R5') + self.assertEqual(next_hops['R6'], 'R5') + self.assertEqual(next_hops['R7'], 'R5') + + valid_origins['R2'].sort() + valid_origins['R3'].sort() + valid_origins['R4'].sort() + valid_origins['R5'].sort() + valid_origins['R6'].sort() + valid_origins['R7'].sort() + self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) + self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) + self.assertEqual(valid_origins['R4'], []) + self.assertEqual(valid_origins['R5'], ['R2', 'R3']) + self.assertEqual(valid_origins['R6'], ['R2', 'R3']) + self.assertEqual(valid_origins['R7'], ['R2', 'R3']) def test_topology5_with_asymmetry1(self): """ @@ -559,34 +406,33 @@ class PathTest(unittest.TestCase): +====+ +----+ +----+ """ - collection = { 'R2': LinkState(None, 'R2', 'area', 1, ['R3']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R1', 'R2', 'R4']), - 'R4': LinkState(None, 'R4', 'area', 1, ['R3', 'R5']), - 'R1': LinkState(None, 'R1', 'area', 1, ['R3', 'R5', 'R2']), - 'R5': LinkState(None, 'R5', 'area', 1, ['R1', 'R4', 'R6']), - 'R6': LinkState(None, 'R6', 'area', 1, ['R5', 'R7']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 6) - self.assertEqual(self.next_hops['R2'], 'R2') - self.assertEqual(self.next_hops['R3'], 'R3') - self.assertEqual(self.next_hops['R4'], 'R3') - self.assertEqual(self.next_hops['R5'], 'R5') - self.assertEqual(self.next_hops['R6'], 'R5') - self.assertEqual(self.next_hops['R7'], 'R5') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.valid_origins['R4'].sort() - self.valid_origins['R5'].sort() - self.valid_origins['R6'].sort() - self.valid_origins['R7'].sort() - self.assertEqual(self.valid_origins['R2'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R3'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R4'], []) - self.assertEqual(self.valid_origins['R5'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R6'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R7'], ['R2', 'R3']) + collection = { 'R2': LinkState(None, 'R2', 1, ['R3']), + 'R3': LinkState(None, 'R3', 1, ['R1', 'R2', 'R4']), + 'R4': LinkState(None, 'R4', 1, ['R3', 'R5']), + 'R1': LinkState(None, 'R1', 1, ['R3', 'R5', 'R2']), + 'R5': LinkState(None, 'R5', 1, ['R1', 'R4', 'R6']), + 'R6': LinkState(None, 'R6', 1, ['R5', 'R7']) } + next_hops, valid_origins = self.engine.calculate_routes(collection) + self.assertEqual(len(next_hops), 6) + self.assertEqual(next_hops['R2'], 'R2') + self.assertEqual(next_hops['R3'], 'R3') + self.assertEqual(next_hops['R4'], 'R3') + self.assertEqual(next_hops['R5'], 'R5') + self.assertEqual(next_hops['R6'], 'R5') + self.assertEqual(next_hops['R7'], 'R5') + + valid_origins['R2'].sort() + valid_origins['R3'].sort() + valid_origins['R4'].sort() + valid_origins['R5'].sort() + valid_origins['R6'].sort() + valid_origins['R7'].sort() + self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) + self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) + self.assertEqual(valid_origins['R4'], []) + self.assertEqual(valid_origins['R5'], ['R2', 'R3']) + self.assertEqual(valid_origins['R6'], ['R2', 'R3']) + self.assertEqual(valid_origins['R7'], ['R2', 'R3']) def test_topology5_with_asymmetry2(self): """ @@ -600,34 +446,33 @@ class PathTest(unittest.TestCase): +====+ +----+ +----+ """ - collection = { 'R2': LinkState(None, 'R2', 'area', 1, ['R3', 'R1']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R1', 'R2', 'R4']), - 'R4': LinkState(None, 'R4', 'area', 1, ['R3', 'R5']), - 'R1': LinkState(None, 'R1', 'area', 1, ['R3', 'R5']), - 'R5': LinkState(None, 'R5', 'area', 1, ['R1', 'R4', 'R6']), - 'R6': LinkState(None, 'R6', 'area', 1, ['R5', 'R7']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 6) - self.assertEqual(self.next_hops['R2'], 'R3') - self.assertEqual(self.next_hops['R3'], 'R3') - self.assertEqual(self.next_hops['R4'], 'R3') - self.assertEqual(self.next_hops['R5'], 'R5') - self.assertEqual(self.next_hops['R6'], 'R5') - self.assertEqual(self.next_hops['R7'], 'R5') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.valid_origins['R4'].sort() - self.valid_origins['R5'].sort() - self.valid_origins['R6'].sort() - self.valid_origins['R7'].sort() - self.assertEqual(self.valid_origins['R2'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R3'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R4'], []) - self.assertEqual(self.valid_origins['R5'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R6'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R7'], ['R2', 'R3']) + collection = { 'R2': LinkState(None, 'R2', 1, ['R3', 'R1']), + 'R3': LinkState(None, 'R3', 1, ['R1', 'R2', 'R4']), + 'R4': LinkState(None, 'R4', 1, ['R3', 'R5']), + 'R1': LinkState(None, 'R1', 1, ['R3', 'R5']), + 'R5': LinkState(None, 'R5', 1, ['R1', 'R4', 'R6']), + 'R6': LinkState(None, 'R6', 1, ['R5', 'R7']) } + next_hops, valid_origins = self.engine.calculate_routes(collection) + self.assertEqual(len(next_hops), 6) + self.assertEqual(next_hops['R2'], 'R3') + self.assertEqual(next_hops['R3'], 'R3') + self.assertEqual(next_hops['R4'], 'R3') + self.assertEqual(next_hops['R5'], 'R5') + self.assertEqual(next_hops['R6'], 'R5') + self.assertEqual(next_hops['R7'], 'R5') + + valid_origins['R2'].sort() + valid_origins['R3'].sort() + valid_origins['R4'].sort() + valid_origins['R5'].sort() + valid_origins['R6'].sort() + valid_origins['R7'].sort() + self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) + self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) + self.assertEqual(valid_origins['R4'], []) + self.assertEqual(valid_origins['R5'], ['R2', 'R3']) + self.assertEqual(valid_origins['R6'], ['R2', 'R3']) + self.assertEqual(valid_origins['R7'], ['R2', 'R3']) def test_topology5_with_asymmetry3(self): """ @@ -641,28 +486,27 @@ class PathTest(unittest.TestCase): +====+ +----+ +----+ """ - collection = { 'R2': LinkState(None, 'R2', 'area', 1, ['R3', 'R1']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R1', 'R2', 'R4']), - 'R4': LinkState(None, 'R4', 'area', 1, ['R3', 'R5']), - 'R1': LinkState(None, 'R1', 'area', 1, ['R3', 'R5']), - 'R5': LinkState(None, 'R5', 'area', 1, ['R1', 'R4']), - 'R6': LinkState(None, 'R6', 'area', 1, ['R5', 'R7']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 4) - self.assertEqual(self.next_hops['R2'], 'R3') - self.assertEqual(self.next_hops['R3'], 'R3') - self.assertEqual(self.next_hops['R4'], 'R3') - self.assertEqual(self.next_hops['R5'], 'R5') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.valid_origins['R4'].sort() - self.valid_origins['R5'].sort() - self.assertEqual(self.valid_origins['R2'], ['R5']) - self.assertEqual(self.valid_origins['R3'], ['R5']) - self.assertEqual(self.valid_origins['R4'], []) - self.assertEqual(self.valid_origins['R5'], ['R2', 'R3']) + collection = { 'R2': LinkState(None, 'R2', 1, ['R3', 'R1']), + 'R3': LinkState(None, 'R3', 1, ['R1', 'R2', 'R4']), + 'R4': LinkState(None, 'R4', 1, ['R3', 'R5']), + 'R1': LinkState(None, 'R1', 1, ['R3', 'R5']), + 'R5': LinkState(None, 'R5', 1, ['R1', 'R4']), + 'R6': LinkState(None, 'R6', 1, ['R5', 'R7']) } + next_hops, valid_origins = self.engine.calculate_routes(collection) + self.assertEqual(len(next_hops), 4) + self.assertEqual(next_hops['R2'], 'R3') + self.assertEqual(next_hops['R3'], 'R3') + self.assertEqual(next_hops['R4'], 'R3') + self.assertEqual(next_hops['R5'], 'R5') + + valid_origins['R2'].sort() + valid_origins['R3'].sort() + valid_origins['R4'].sort() + valid_origins['R5'].sort() + self.assertEqual(valid_origins['R2'], ['R5']) + self.assertEqual(valid_origins['R3'], ['R5']) + self.assertEqual(valid_origins['R4'], []) + self.assertEqual(valid_origins['R5'], ['R2', 'R3']) if __name__ == '__main__': --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
