Repository: qpid-dispatch Updated Branches: refs/heads/master 279c1b4c6 -> ba8e158d6
DISPATCH-10 - Added configuration of inter-router cost up to the point of communicating cost in LSU messages. Cost is not yet used in computing routes. Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/9f232923 Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/9f232923 Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/9f232923 Branch: refs/heads/master Commit: 9f232923d120e2421214917268780b4c86cf959d Parents: 279c1b4 Author: Ted Ross <[email protected]> Authored: Wed Apr 20 15:08:23 2016 -0400 Committer: Ted Ross <[email protected]> Committed: Fri Apr 22 17:49:43 2016 -0400 ---------------------------------------------------------------------- include/qpid/dispatch/router_core.h | 4 +- include/qpid/dispatch/server.h | 7 + python/qpid_dispatch/management/qdrouter.json | 7 + .../display_name/display_name.py | 5 +- .../qpid_dispatch_internal/management/agent.py | 4 +- python/qpid_dispatch_internal/router/data.py | 14 +- python/qpid_dispatch_internal/router/engine.py | 8 +- python/qpid_dispatch_internal/router/hello.py | 4 +- python/qpid_dispatch_internal/router/node.py | 8 +- src/connection_manager.c | 1 + src/python_embedded.c | 4 +- src/router_core/connections.c | 2 + src/router_core/forwarder.c | 3 +- src/router_core/management_agent.c | 2 +- src/router_core/router_core_private.h | 4 +- src/router_node.c | 7 +- tests/router_engine_test.py | 128 +++++++++---------- 17 files changed, 119 insertions(+), 93 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/include/qpid/dispatch/router_core.h ---------------------------------------------------------------------- diff --git a/include/qpid/dispatch/router_core.h b/include/qpid/dispatch/router_core.h index 0291f64..81dd2f9 100644 --- a/include/qpid/dispatch/router_core.h +++ b/include/qpid/dispatch/router_core.h @@ -88,7 +88,7 @@ void qdr_core_route_table_handlers(qdr_core_t *core, * In-process messaging functions ****************************************************************************** */ -typedef void (*qdr_receive_t) (void *context, qd_message_t *msg, int link_maskbit); +typedef void (*qdr_receive_t) (void *context, qd_message_t *msg, int link_maskbit, int inter_router_cost); qdr_subscription_t *qdr_core_subscribe(qdr_core_t *core, const char *address, @@ -149,6 +149,7 @@ typedef enum { * @param core Pointer to the core object * @param incoming True iff this connection is associated with a listener, False if a connector * @param role The configured role of this connection + * @param cost If the role is inter_router, this is the configured cost for the connection. * @param label Optional label provided in the connection's configuration. This is used to * correlate the connection with waypoints and link-route destinations that use the connection. * @param strip_annotations_in True if configured to remove annotations on inbound messages. @@ -159,6 +160,7 @@ typedef enum { qdr_connection_t *qdr_connection_opened(qdr_core_t *core, bool incoming, qdr_connection_role_t role, + int cost, const char *label, const char *remote_container_id, bool strip_annotations_in, http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/include/qpid/dispatch/server.h ---------------------------------------------------------------------- diff --git a/include/qpid/dispatch/server.h b/include/qpid/dispatch/server.h index 5a85e63..4683288 100644 --- a/include/qpid/dispatch/server.h +++ b/include/qpid/dispatch/server.h @@ -400,6 +400,13 @@ typedef struct qd_server_config_t { char *role; /** + * If the role is "inter-router", the cost can be set to a number greater than + * or equal to one. Inter-router cost is used to influence the routing algorithm + * such that it prefers lower-cost paths. + */ + int inter_router_cost; + + /** * The maximum size of an AMQP frame in octets. */ uint32_t max_frame_size; http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/python/qpid_dispatch/management/qdrouter.json ---------------------------------------------------------------------- diff --git a/python/qpid_dispatch/management/qdrouter.json b/python/qpid_dispatch/management/qdrouter.json index 69d5192..f5cce7a 100644 --- a/python/qpid_dispatch/management/qdrouter.json +++ b/python/qpid_dispatch/management/qdrouter.json @@ -43,6 +43,13 @@ "default": "normal", "description": "The role of an established connection. In the normal role, the connection is assumed to be used for AMQP clients that are doing normal message delivery over the connection. In the inter-router role, the connection is assumed to be to another router in the network. Inter-router discovery and routing protocols can only be used over inter-router connections. route-container role can be used for router-container connections, for example, a router-broker connection. on-demand role has been deprecated.", "create": true + }, + "cost": { + "type": "integer", + "default": "1", + "required": false, + "create": true, + "description": "For the 'inter-router' role only. This value assigns a cost metric to the inter-router connection. The default (and minimum) value is one. Higher values represent higher costs. The cost is used to influence the routing algorithm as it attempts to use the path with the lowest total cost from ingress to egress." } } }, http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/python/qpid_dispatch_internal/display_name/display_name.py ---------------------------------------------------------------------- diff --git a/python/qpid_dispatch_internal/display_name/display_name.py b/python/qpid_dispatch_internal/display_name/display_name.py index 340e69d..5ecb867 100644 --- a/python/qpid_dispatch_internal/display_name/display_name.py +++ b/python/qpid_dispatch_internal/display_name/display_name.py @@ -95,14 +95,15 @@ class DisplayNameService(object): return body - def receive(self, message, link_id): + def receive(self, message, unused_link_id, unused_cost): """ This is the IOAdapter's callback function. Will be invoked when the IOAdapter receives a request. Will only accept QUERY requests. Matches the passed in profilename and userid to user name. If a matching user name is not found, returns the passed in userid as the user name. :param message: - :param link_id: + :param unused_link_id: + :param unused_cost """ body = {} http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/python/qpid_dispatch_internal/management/agent.py ---------------------------------------------------------------------- diff --git a/python/qpid_dispatch_internal/management/agent.py b/python/qpid_dispatch_internal/management/agent.py index 336ef86..b050b8a 100644 --- a/python/qpid_dispatch_internal/management/agent.py +++ b/python/qpid_dispatch_internal/management/agent.py @@ -751,7 +751,7 @@ class Agent(object): except: self.log(LOG_ERROR, "Can't respond to %s: %s"%(request, format_exc())) - def receive(self, request, link_id): + def receive(self, request, unused_link_id, unused_cost): """Called when a management request is received.""" def error(e, trace): """Raise an error""" @@ -766,7 +766,7 @@ class Agent(object): with self.request_lock: try: self.entities.refresh_from_c() - self.log(LOG_DEBUG, "Agent request %s on link %s"%(request, link_id)) + self.log(LOG_DEBUG, "Agent request %s"% request) status, body = self.handle(request) self.respond(request, status=status, body=body) except ManagementError, e: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/python/qpid_dispatch_internal/router/data.py ---------------------------------------------------------------------- diff --git a/python/qpid_dispatch_internal/router/data.py b/python/qpid_dispatch_internal/router/data.py index 040f14b..5b739b8 100644 --- a/python/qpid_dispatch_internal/router/data.py +++ b/python/qpid_dispatch_internal/router/data.py @@ -52,7 +52,7 @@ class LinkState(object): self.id = getMandatory(body, 'id', str) self.area = '0' self.ls_seq = getMandatory(body, 'ls_seq', long) - self.peers = getMandatory(body, 'peers', list) + self.peers = getMandatory(body, 'peers', dict) else: self.id = _id self.area = '0' @@ -68,20 +68,20 @@ class LinkState(object): 'ls_seq' : self.ls_seq, 'peers' : self.peers} - def add_peer(self, _id): - if self.peers.count(_id) == 0: - self.peers.append(_id) + def add_peer(self, _id, _cost): + if _id not in self.peers: + self.peers[_id] = _cost return True return False def del_peer(self, _id): - if self.peers.count(_id) > 0: - self.peers.remove(_id) + if _id in self.peers: + self.peers.pop(_id) return True return False def del_all_peers(self): - self.peers = [] + self.peers = {} self.ls_seq = 0 def has_peers(self): http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/python/qpid_dispatch_internal/router/engine.py ---------------------------------------------------------------------- diff --git a/python/qpid_dispatch_internal/router/engine.py b/python/qpid_dispatch_internal/router/engine.py index 8905bac..5849d09 100644 --- a/python/qpid_dispatch_internal/router/engine.py +++ b/python/qpid_dispatch_internal/router/engine.py @@ -126,7 +126,7 @@ class RouterEngine: except Exception: self.log(LOG_ERROR, "Exception in timer processing\n%s" % format_exc(LOG_STACK_LIMIT)) - def handleControlMessage(self, opcode, body, link_id): + def handleControlMessage(self, opcode, body, link_id, cost): """ """ try: @@ -134,7 +134,7 @@ class RouterEngine: if opcode == 'HELLO': msg = MessageHELLO(body) self.log_hello(LOG_TRACE, "RCVD: %r" % msg) - self.hello_protocol.handle_hello(msg, now, link_id) + self.hello_protocol.handle_hello(msg, now, link_id, cost) elif opcode == 'RA': msg = MessageRA(body) @@ -164,12 +164,12 @@ class RouterEngine: except Exception: self.log(LOG_ERROR, "Control message error: opcode=%s body=%r\n%s" % (opcode, body, format_exc(LOG_STACK_LIMIT))) - def receive(self, message, link_id): + def receive(self, message, link_id, cost): """ This is the IoAdapter message-receive handler """ try: - self.handleControlMessage(message.properties['opcode'], message.body, link_id) + self.handleControlMessage(message.properties['opcode'], message.body, link_id, cost) except Exception: self.log(LOG_ERROR, "Exception in raw message processing: properties=%r body=%r\n%s" % (message.properties, message.body, format_exc(LOG_STACK_LIMIT))) http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/python/qpid_dispatch_internal/router/hello.py ---------------------------------------------------------------------- diff --git a/python/qpid_dispatch_internal/router/hello.py b/python/qpid_dispatch_internal/router/hello.py index 6dbed13..0b214a9 100644 --- a/python/qpid_dispatch_internal/router/hello.py +++ b/python/qpid_dispatch_internal/router/hello.py @@ -44,7 +44,7 @@ class HelloProtocol(object): self.container.log_hello(LOG_TRACE, "SENT: %r" % msg) - def handle_hello(self, msg, now, link_id): + def handle_hello(self, msg, now, link_id, cost): if msg.id == self.id: if not self.dup_reported and (msg.instance != self.container.instance): self.dup_reported = True @@ -52,7 +52,7 @@ class HelloProtocol(object): return self.hellos[msg.id] = now if msg.is_seen(self.id): - self.node_tracker.neighbor_refresh(msg.id, msg.instance, link_id, now) + self.node_tracker.neighbor_refresh(msg.id, msg.instance, link_id, cost, now) def _expire_hellos(self, now): http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/python/qpid_dispatch_internal/router/node.py ---------------------------------------------------------------------- diff --git a/python/qpid_dispatch_internal/router/node.py b/python/qpid_dispatch_internal/router/node.py index 0719898..7ae08fd 100644 --- a/python/qpid_dispatch_internal/router/node.py +++ b/python/qpid_dispatch_internal/router/node.py @@ -33,7 +33,7 @@ class NodeTracker(object): self.container = container self.my_id = container.id self.max_routers = max_routers - self.link_state = LinkState(None, self.my_id, 0, []) + self.link_state = LinkState(None, self.my_id, 0, {}) self.link_state_changed = False self.recompute_topology = False self.last_topology_change = 0 @@ -184,7 +184,7 @@ class NodeTracker(object): self.container.link_state_engine.send_ra(now) - def neighbor_refresh(self, node_id, instance, link_id, now): + def neighbor_refresh(self, node_id, instance, link_id, cost, now): """ Invoked when the hello protocol has received positive confirmation of continued bi-directional connectivity with a neighbor router. @@ -204,7 +204,7 @@ class NodeTracker(object): if node.set_link_id(link_id): self.nodes_by_link_id[link_id] = node node.request_link_state() - if self.link_state.add_peer(node_id): + if self.link_state.add_peer(node_id, cost): self.link_state_changed = True ## @@ -364,7 +364,7 @@ class RouterNode(object): self.maskbit = self.parent._allocate_maskbit() self.neighbor_refresh_time = 0.0 self.peer_link_id = None - self.link_state = LinkState(None, self.id, 0, []) + self.link_state = LinkState(None, self.id, 0, {}) self.next_hop_router = None self.valid_origins = None self.mobile_addresses = [] http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/src/connection_manager.c ---------------------------------------------------------------------- diff --git a/src/connection_manager.c b/src/connection_manager.c index 44a22a9..66466f1 100644 --- a/src/connection_manager.c +++ b/src/connection_manager.c @@ -139,6 +139,7 @@ static qd_error_t load_server_config(qd_dispatch_t *qd, qd_server_config_t *conf config->port = qd_entity_get_string(entity, "port"); CHECK(); config->name = qd_entity_opt_string(entity, "name", 0); CHECK(); config->role = qd_entity_get_string(entity, "role"); CHECK(); + config->inter_router_cost = qd_entity_opt_long(entity, "cost", 1); CHECK(); config->protocol_family = qd_entity_opt_string(entity, "protocolFamily", 0); CHECK(); config->max_frame_size = qd_entity_get_long(entity, "maxFrameSize"); CHECK(); config->idle_timeout_seconds = qd_entity_get_long(entity, "idleTimeoutSeconds"); CHECK(); http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/src/python_embedded.c ---------------------------------------------------------------------- diff --git a/src/python_embedded.c b/src/python_embedded.c index 4946856..2d5d50b 100644 --- a/src/python_embedded.c +++ b/src/python_embedded.c @@ -488,7 +488,7 @@ static qd_error_t iter_to_py_attr(qd_field_iterator_t *iter, return qd_error_code(); } -static void qd_io_rx_handler(void *context, qd_message_t *msg, int link_id) +static void qd_io_rx_handler(void *context, qd_message_t *msg, int link_id, int inter_router_cost) { IoAdapter *self = (IoAdapter*) context; @@ -513,7 +513,7 @@ static void qd_io_rx_handler(void *context, qd_message_t *msg, int link_id) iter_to_py_attr(qd_message_field_iterator(msg, QD_FIELD_APPLICATION_PROPERTIES), py_iter_parse, py_msg, "properties"); iter_to_py_attr(qd_message_field_iterator(msg, QD_FIELD_BODY), py_iter_parse, py_msg, "body"); - PyObject *value = PyObject_CallFunction(self->handler, "Ol", py_msg, link_id); + PyObject *value = PyObject_CallFunction(self->handler, "Oll", py_msg, link_id, inter_router_cost); Py_DECREF(py_msg); Py_XDECREF(value); http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/src/router_core/connections.c ---------------------------------------------------------------------- diff --git a/src/router_core/connections.c b/src/router_core/connections.c index 88de922..0a4f1ed 100644 --- a/src/router_core/connections.c +++ b/src/router_core/connections.c @@ -58,6 +58,7 @@ qdr_terminus_t *qdr_terminus_router_data(void) qdr_connection_t *qdr_connection_opened(qdr_core_t *core, bool incoming, qdr_connection_role_t role, + int cost, const char *label, const char *remote_container_id, bool strip_annotations_in, @@ -72,6 +73,7 @@ qdr_connection_t *qdr_connection_opened(qdr_core_t *core, conn->user_context = 0; conn->incoming = incoming; conn->role = role; + conn->inter_router_cost = cost; conn->strip_annotations_in = strip_annotations_in; conn->strip_annotations_out = strip_annotations_out; conn->link_capacity = link_capacity; http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/src/router_core/forwarder.c ---------------------------------------------------------------------- diff --git a/src/router_core/forwarder.c b/src/router_core/forwarder.c index a012875..274beb0 100644 --- a/src/router_core/forwarder.c +++ b/src/router_core/forwarder.c @@ -118,7 +118,7 @@ void qdr_forward_deliver_CT(qdr_core_t *core, qdr_link_t *link, qdr_delivery_t * void qdr_forward_on_message(qdr_core_t *core, qdr_general_work_t *work) { - work->on_message(work->on_message_context, work->msg, work->maskbit); + work->on_message(work->on_message_context, work->msg, work->maskbit, work->inter_router_cost); qd_message_free(work->msg); } @@ -130,6 +130,7 @@ void qdr_forward_on_message_CT(qdr_core_t *core, qdr_subscription_t *sub, qdr_li work->on_message_context = sub->on_message_context; work->msg = qd_message_copy(msg); work->maskbit = link ? link->conn->mask_bit : 0; + work->inter_router_cost = link ? link->conn->inter_router_cost : 1; qdr_post_general_work_CT(core, work); } http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/src/router_core/management_agent.c ---------------------------------------------------------------------- diff --git a/src/router_core/management_agent.c b/src/router_core/management_agent.c index e048c85..0eef56a 100644 --- a/src/router_core/management_agent.c +++ b/src/router_core/management_agent.c @@ -442,7 +442,7 @@ static bool qd_can_handle_request(qd_parsed_field_t *properties_fld, * Handler for the management agent. * */ -void qdr_management_agent_on_message(void *context, qd_message_t *msg, int unused_link_id) +void qdr_management_agent_on_message(void *context, qd_message_t *msg, int unused_link_id, int unused_cost) { qdr_core_t *core = (qdr_core_t*) context; qd_field_iterator_t *app_properties_iter = qd_message_field_iterator(msg, QD_FIELD_APPLICATION_PROPERTIES); http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/src/router_core/router_core_private.h ---------------------------------------------------------------------- diff --git a/src/router_core/router_core_private.h b/src/router_core/router_core_private.h index 62b8136..8abfba8 100644 --- a/src/router_core/router_core_private.h +++ b/src/router_core/router_core_private.h @@ -368,6 +368,7 @@ struct qdr_general_work_t { qdr_general_work_handler_t handler; qdr_field_t *field; int maskbit; + int inter_router_cost; qdr_receive_t on_message; void *on_message_context; qd_message_t *msg; @@ -412,6 +413,7 @@ struct qdr_connection_t { void *user_context; bool incoming; qdr_connection_role_t role; + int inter_router_cost; qdr_conn_identifier_t *conn_id; bool strip_annotations_in; bool strip_annotations_out; @@ -562,7 +564,7 @@ struct qdr_core_t { void *router_core_thread(void *arg); uint64_t qdr_identifier(qdr_core_t* core); -void qdr_management_agent_on_message(void *context, qd_message_t *msg, int unused_link_id); +void qdr_management_agent_on_message(void *context, qd_message_t *msg, int unused_link_id, int unused_cost); void qdr_route_table_setup_CT(qdr_core_t *core); void qdr_agent_setup_CT(qdr_core_t *core); void qdr_forwarder_setup_CT(qdr_core_t *core); http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/src/router_node.c ---------------------------------------------------------------------- diff --git a/src/router_node.c b/src/router_node.c index af66278..8cba85e 100644 --- a/src/router_node.c +++ b/src/router_node.c @@ -43,6 +43,7 @@ static char *node_id; */ static void qd_router_connection_get_config(const qd_connection_t *conn, qdr_connection_role_t *role, + int *cost, const char **name, bool *strip_annotations_in, bool *strip_annotations_out, @@ -59,6 +60,7 @@ static void qd_router_connection_get_config(const qd_connection_t *conn, *strip_annotations_in = false; *strip_annotations_out = false; *role = QDR_ROLE_INTER_ROUTER; + *cost = cf->inter_router_cost; } else if (cf && (strcmp(cf->role, container_role) == 0 || strcmp(cf->role, on_demand_role) == 0)) // backward compat *role = QDR_ROLE_ROUTE_CONTAINER; @@ -497,16 +499,17 @@ static int AMQP_link_detach_handler(void* context, qd_link_t *link, qd_detach_ty static void AMQP_opened_handler(qd_router_t *router, qd_connection_t *conn, bool inbound) { qdr_connection_role_t role = 0; + int cost = 1; bool strip_annotations_in = false; bool strip_annotations_out = false; int link_capacity = 1; const char *name = 0; pn_connection_t *pn_conn = qd_connection_pn(conn); - qd_router_connection_get_config(conn, &role, &name, + qd_router_connection_get_config(conn, &role, &cost, &name, &strip_annotations_in, &strip_annotations_out, &link_capacity); - qdr_connection_t *qdrc = qdr_connection_opened(router->router_core, inbound, role, name, + qdr_connection_t *qdrc = qdr_connection_opened(router->router_core, inbound, role, cost, name, pn_connection_remote_container(pn_conn), strip_annotations_in, strip_annotations_out, link_capacity); http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9f232923/tests/router_engine_test.py ---------------------------------------------------------------------- diff --git a/tests/router_engine_test.py b/tests/router_engine_test.py index c78cfd9..76ae101 100644 --- a/tests/router_engine_test.py +++ b/tests/router_engine_test.py @@ -52,34 +52,34 @@ class Adapter(object): class DataTest(unittest.TestCase): def test_link_state(self): - ls = LinkState(None, 'R1', 1, ['R2', 'R3']) + ls = LinkState(None, 'R1', 1, {'R2':1, 'R3':1}) self.assertEqual(ls.id, 'R1') self.assertEqual(ls.ls_seq, 1) - self.assertEqual(ls.peers, ['R2', 'R3']) + self.assertEqual(ls.peers, {'R2':1, 'R3':1}) ls.bump_sequence() self.assertEqual(ls.id, 'R1') self.assertEqual(ls.ls_seq, 2) - self.assertEqual(ls.peers, ['R2', 'R3']) + self.assertEqual(ls.peers, {'R2':1, 'R3':1}) - result = ls.add_peer('R4') + result = ls.add_peer('R4', 5) self.assertTrue(result) - self.assertEqual(ls.peers, ['R2', 'R3', 'R4']) - result = ls.add_peer('R2') + self.assertEqual(ls.peers, {'R2':1, 'R3':1, 'R4':5}) + result = ls.add_peer('R2', 1) self.assertFalse(result) - self.assertEqual(ls.peers, ['R2', 'R3', 'R4']) + self.assertEqual(ls.peers, {'R2':1, 'R3':1, 'R4':5}) result = ls.del_peer('R3') self.assertTrue(result) - self.assertEqual(ls.peers, ['R2', 'R4']) + self.assertEqual(ls.peers, {'R2':1, 'R4':5}) result = ls.del_peer('R5') self.assertFalse(result) - self.assertEqual(ls.peers, ['R2', 'R4']) + self.assertEqual(ls.peers, {'R2':1, 'R4':5}) encoded = ls.to_dict() new_ls = LinkState(encoded) self.assertEqual(new_ls.id, 'R1') self.assertEqual(new_ls.ls_seq, 2) - self.assertEqual(new_ls.peers, ['R2', 'R4']) + self.assertEqual(new_ls.peers, {'R2':1, 'R4':5}) def test_hello_message(self): @@ -141,8 +141,8 @@ class NeighborTest(unittest.TestCase): def send(self, dest, msg): self.sent.append((dest, msg)) - def neighbor_refresh(self, node_id, instance, link_id, now): - self.neighbors[node_id] = (instance, link_id, now) + def neighbor_refresh(self, node_id, instance, link_id, cost, now): + self.neighbors[node_id] = (instance, link_id, cost, now) def setUp(self): self.sent = [] @@ -177,7 +177,7 @@ class NeighborTest(unittest.TestCase): self.sent = [] self.neighbors = {} self.engine = HelloProtocol(self, self) - self.engine.handle_hello(MessageHELLO(None, 'R2', []), 2.0, 0) + self.engine.handle_hello(MessageHELLO(None, 'R2', []), 2.0, 0, 1) self.engine.tick(5.0) self.assertEqual(len(self.sent), 1) dest, msg = self.sent.pop(0) @@ -187,7 +187,7 @@ class NeighborTest(unittest.TestCase): self.sent = [] self.neighbors = {} self.engine = HelloProtocol(self, self) - self.engine.handle_hello(MessageHELLO(None, 'R2', ['R1']), 0.5, 0) + self.engine.handle_hello(MessageHELLO(None, 'R2', ['R1']), 0.5, 0, 1) self.engine.tick(1.0) self.engine.tick(2.0) self.engine.tick(3.0) @@ -198,13 +198,13 @@ class NeighborTest(unittest.TestCase): self.sent = [] self.neighbors = {} self.engine = HelloProtocol(self, self) - self.engine.handle_hello(MessageHELLO(None, 'R2', ['R1']), 0.5, 0) + self.engine.handle_hello(MessageHELLO(None, 'R2', ['R1']), 0.5, 0, 1) self.engine.tick(1.0) - self.engine.handle_hello(MessageHELLO(None, 'R3', ['R1', 'R2']), 1.5, 0) + self.engine.handle_hello(MessageHELLO(None, 'R3', ['R1', 'R2']), 1.5, 0, 1) self.engine.tick(2.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.handle_hello(MessageHELLO(None, 'R4', ['R1']), 2.5, 0, 1) + self.engine.handle_hello(MessageHELLO(None, 'R5', ['R2']), 2.5, 0, 1) + self.engine.handle_hello(MessageHELLO(None, 'R6', ['R1']), 2.5, 0, 1) self.engine.tick(3.0) keys = self.neighbors.keys() keys.sort() @@ -227,9 +227,9 @@ class PathTest(unittest.TestCase): +====+ +----+ +----+ """ - collection = { 'R1': LinkState(None, 'R1', 1, ['R2']), - 'R2': LinkState(None, 'R2', 1, ['R1', 'R3']), - 'R3': LinkState(None, 'R3', 1, ['R2']) } + collection = { 'R1': LinkState(None, 'R1', 1, {'R2':1}), + 'R2': LinkState(None, 'R2', 1, {'R1':1, 'R3':1}), + 'R3': LinkState(None, 'R3', 1, {'R2':1}) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 2) self.assertEqual(next_hops['R2'], 'R2') @@ -252,12 +252,12 @@ class PathTest(unittest.TestCase): +----+ +----+ +----+ """ - 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']) } + collection = { 'R1': LinkState(None, 'R1', 1, {'R2':1}), + 'R2': LinkState(None, 'R2', 1, {'R1':1, 'R3':1, 'R4':1}), + 'R3': LinkState(None, 'R3', 1, {'R2':1, 'R5':1}), + 'R4': LinkState(None, 'R4', 1, {'R2':1, 'R5':1}), + 'R5': LinkState(None, 'R5', 1, {'R3':1, 'R4':1, 'R6':1}), + 'R6': LinkState(None, 'R6', 1, {'R5':1}) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 5) self.assertEqual(next_hops['R2'], 'R2') @@ -289,12 +289,12 @@ class PathTest(unittest.TestCase): +====+ +----+ +----+ """ - 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']) } + collection = { 'R2': LinkState(None, 'R2', 1, {'R3':1}), + 'R3': LinkState(None, 'R3', 1, {'R1':1, 'R2':1, 'R4':1}), + 'R4': LinkState(None, 'R4', 1, {'R3':1, 'R5':1}), + 'R1': LinkState(None, 'R1', 1, {'R3':1, 'R5':1}), + 'R5': LinkState(None, 'R5', 1, {'R1':1, 'R4':1, 'R6':1}), + 'R6': LinkState(None, 'R6', 1, {'R5':1}) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 5) self.assertEqual(next_hops['R2'], 'R3') @@ -326,12 +326,12 @@ class PathTest(unittest.TestCase): +====+ +----+ +----+ """ - 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']) } + collection = { 'R2': LinkState(None, 'R2', 1, {'R3':1}), + 'R3': LinkState(None, 'R3', 1, {'R1':1, 'R2':1, 'R4':1}), + 'R4': LinkState(None, 'R4', 1, {'R3':1, 'R5':1}), + 'R1': LinkState(None, 'R1', 1, {'R3':1, 'R5':1}), + 'R5': LinkState(None, 'R5', 1, {'R1':1, 'R4':1, 'R6':1}), + 'R6': LinkState(None, 'R6', 1, {'R5':1, 'R7':1}) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R3') @@ -366,12 +366,12 @@ class PathTest(unittest.TestCase): +====+ +----+ +----+ """ - 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']) } + collection = { 'R2': LinkState(None, 'R2', 1, {'R3':1, 'R1':1}), + 'R3': LinkState(None, 'R3', 1, {'R1':1, 'R2':1, 'R4':1}), + 'R4': LinkState(None, 'R4', 1, {'R3':1, 'R5':1}), + 'R1': LinkState(None, 'R1', 1, {'R3':1, 'R5':1, 'R2':1}), + 'R5': LinkState(None, 'R5', 1, {'R1':1, 'R4':1, 'R6':1}), + 'R6': LinkState(None, 'R6', 1, {'R5':1, 'R7':1}) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R2') @@ -406,12 +406,12 @@ class PathTest(unittest.TestCase): +====+ +----+ +----+ """ - 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']) } + collection = { 'R2': LinkState(None, 'R2', 1, {'R3':1}), + 'R3': LinkState(None, 'R3', 1, {'R1':1, 'R2':1, 'R4':1}), + 'R4': LinkState(None, 'R4', 1, {'R3':1, 'R5':1}), + 'R1': LinkState(None, 'R1', 1, {'R3':1, 'R5':1, 'R2':1}), + 'R5': LinkState(None, 'R5', 1, {'R1':1, 'R4':1, 'R6':1}), + 'R6': LinkState(None, 'R6', 1, {'R5':1, 'R7':1}) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R2') @@ -446,12 +446,12 @@ class PathTest(unittest.TestCase): +====+ +----+ +----+ """ - 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']) } + collection = { 'R2': LinkState(None, 'R2', 1, {'R3':1, 'R1':1}), + 'R3': LinkState(None, 'R3', 1, {'R1':1, 'R2':1, 'R4':1}), + 'R4': LinkState(None, 'R4', 1, {'R3':1, 'R5':1}), + 'R1': LinkState(None, 'R1', 1, {'R3':1, 'R5':1}), + 'R5': LinkState(None, 'R5', 1, {'R1':1, 'R4':1, 'R6':1}), + 'R6': LinkState(None, 'R6', 1, {'R5':1, 'R7':1}) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R3') @@ -486,12 +486,12 @@ class PathTest(unittest.TestCase): +====+ +----+ +----+ """ - 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']) } + collection = { 'R2': LinkState(None, 'R2', 1, {'R3':1, 'R1':1}), + 'R3': LinkState(None, 'R3', 1, {'R1':1, 'R2':1, 'R4':1}), + 'R4': LinkState(None, 'R4', 1, {'R3':1, 'R5':1}), + 'R1': LinkState(None, 'R1', 1, {'R3':1, 'R5':1}), + 'R5': LinkState(None, 'R5', 1, {'R1':1, 'R4':1}), + 'R6': LinkState(None, 'R6', 1, {'R5':1, 'R7':1}) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 4) self.assertEqual(next_hops['R2'], 'R3') --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
