| #ifndef __router_private_h__ |
| #define __router_private_h__ 1 |
| /* |
| * 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. |
| */ |
| |
| /**@file |
| * Router Private type definitions |
| *@internal |
| */ |
| |
| #include <qpid/dispatch/enum.h> |
| #include <qpid/dispatch/router.h> |
| #include <qpid/dispatch/message.h> |
| #include <qpid/dispatch/bitmask.h> |
| #include <qpid/dispatch/hash.h> |
| #include <qpid/dispatch/log.h> |
| #include "dispatch_private.h" |
| #include "entity.h" |
| |
| qd_error_t qd_router_python_setup(qd_router_t *router); |
| void qd_router_python_free(qd_router_t *router); |
| qd_error_t qd_pyrouter_tick(qd_router_t *router); |
| qd_error_t qd_router_configure_address(qd_router_t *router, qd_entity_t *entity); |
| qd_error_t qd_router_configure_waypoint(qd_router_t *router, qd_entity_t *entity); |
| qd_error_t qd_router_configure_lrp(qd_router_t *router, qd_entity_t *entity); |
| |
| void qd_router_configure_free(qd_router_t *router); |
| |
| typedef enum { |
| QD_ROUTER_MODE_STANDALONE, ///< Standalone router. No routing protocol participation |
| QD_ROUTER_MODE_INTERIOR, ///< Interior router. Full participation in routing protocol. |
| QD_ROUTER_MODE_EDGE, ///< Edge router. No transit-router capability. |
| QD_ROUTER_MODE_ENDPOINT ///< No routing except for internal modules (agent, etc.). |
| } qd_router_mode_t; |
| ENUM_DECLARE(qd_router_mode); |
| |
| typedef enum { |
| QD_LINK_ENDPOINT, ///< A link to a connected endpoint |
| QD_LINK_WAYPOINT, ///< A link to a configured waypoint |
| QD_LINK_ROUTER, ///< A link to a peer router in the same area |
| QD_LINK_AREA ///< A link to a peer router in a different area (area boundary) |
| } qd_link_type_t; |
| ENUM_DECLARE(qd_link_type); |
| |
| typedef struct qd_routed_event_t { |
| DEQ_LINKS(struct qd_routed_event_t); |
| qd_router_delivery_t *delivery; |
| qd_message_t *message; |
| bool settle; |
| uint64_t disposition; |
| } qd_routed_event_t; |
| |
| extern const char *QD_ROUTER_NODE_TYPE; |
| extern const char *QD_ROUTER_ADDRESS_TYPE; |
| extern const char *QD_ROUTER_LINK_TYPE; |
| |
| ALLOC_DECLARE(qd_routed_event_t); |
| DEQ_DECLARE(qd_routed_event_t, qd_routed_event_list_t); |
| |
| DEQ_DECLARE(qd_router_delivery_t, qd_router_delivery_list_t); |
| |
| struct qd_router_link_t { |
| DEQ_LINKS(qd_router_link_t); |
| int mask_bit; ///< Unique mask bit if this is an inter-router link |
| qd_link_type_t link_type; |
| qd_direction_t link_direction; |
| qd_address_t *owning_addr; ///< [ref] Address record that owns this link |
| qd_waypoint_t *waypoint; ///< [ref] Waypoint that owns this link |
| qd_link_t *link; ///< [own] Link pointer |
| qd_router_link_t *connected_link; ///< [ref] If this is a link-route, reference the connected link |
| qd_router_link_ref_t *ref; ///< Pointer to a containing reference object |
| char *target; ///< Target address for incoming links |
| qd_routed_event_list_t event_fifo; ///< FIFO of outgoing delivery/link events (no messages) |
| qd_routed_event_list_t msg_fifo; ///< FIFO of outgoing message deliveries |
| qd_router_delivery_list_t deliveries; ///< [own] outstanding unsettled deliveries |
| }; |
| |
| ALLOC_DECLARE(qd_router_link_t); |
| DEQ_DECLARE(qd_router_link_t, qd_router_link_list_t); |
| void qd_router_link_free_LH(qd_router_link_t *); |
| |
| struct qd_router_node_t { |
| DEQ_LINKS(qd_router_node_t); |
| qd_address_t *owning_addr; |
| int mask_bit; |
| qd_router_node_t *next_hop; ///< Next hop node _if_ this is not a neighbor node |
| qd_router_link_t *peer_link; ///< Outgoing link _if_ this is a neighbor node |
| uint32_t ref_count; |
| qd_bitmask_t *valid_origins; |
| }; |
| |
| ALLOC_DECLARE(qd_router_node_t); |
| DEQ_DECLARE(qd_router_node_t, qd_router_node_list_t); |
| |
| struct qd_router_ref_t { |
| DEQ_LINKS(qd_router_ref_t); |
| qd_router_node_t *router; |
| }; |
| |
| ALLOC_DECLARE(qd_router_ref_t); |
| DEQ_DECLARE(qd_router_ref_t, qd_router_ref_list_t); |
| |
| |
| struct qd_router_link_ref_t { |
| DEQ_LINKS(qd_router_link_ref_t); |
| qd_router_link_t *link; |
| }; |
| |
| ALLOC_DECLARE(qd_router_link_ref_t); |
| DEQ_DECLARE(qd_router_link_ref_t, qd_router_link_ref_list_t); |
| |
| |
| struct qd_lrp_t { |
| DEQ_LINKS(qd_lrp_t); |
| char *prefix; |
| qd_lrp_container_t *container; |
| }; |
| |
| DEQ_DECLARE(qd_lrp_t, qd_lrp_list_t); |
| |
| |
| struct qd_lrp_container_t { |
| DEQ_LINKS(qd_lrp_container_t); |
| qd_dispatch_t *qd; |
| qd_config_connector_t *cc; |
| qd_lrp_list_t lrps; |
| qd_timer_t *timer; |
| qd_connection_t *conn; |
| }; |
| |
| DEQ_DECLARE(qd_lrp_container_t, qd_lrp_container_list_t); |
| |
| |
| struct qd_router_lrp_ref_t { |
| DEQ_LINKS(qd_router_lrp_ref_t); |
| qd_lrp_t *lrp; |
| }; |
| |
| ALLOC_DECLARE(qd_router_lrp_ref_t); |
| DEQ_DECLARE(qd_router_lrp_ref_t, qd_router_lrp_ref_list_t); |
| |
| |
| struct qd_router_conn_t { |
| int ref_count; |
| int mask_bit; |
| }; |
| |
| ALLOC_DECLARE(qd_router_conn_t); |
| |
| /** A router address */ |
| struct qd_address_t { |
| DEQ_LINKS(qd_address_t); |
| qd_router_message_cb_t on_message; ///< In-Process Message Consumer |
| void *on_message_context; ///< In-Process Consumer context |
| qd_router_lrp_ref_list_t lrps; ///< Local link-route destinations |
| qd_router_link_ref_list_t rlinks; ///< Locally-Connected Consumers |
| qd_router_ref_list_t rnodes; ///< Remotely-Connected Consumers |
| qd_hash_handle_t *hash_handle; ///< Linkage back to the hash table entry |
| qd_address_semantics_t semantics; |
| qd_address_t *redirect; |
| qd_address_t *static_cc; |
| qd_address_t *dynamic_cc; |
| bool toggle; |
| bool waypoint; |
| bool block_deletion; |
| qd_router_forwarder_t *forwarder; |
| |
| // |
| // TODO - Add support for asynchronous address lookup: |
| // - Add a FIFO for routed_events holding the message and delivery |
| // - Add an indication that the address is awaiting a lookup response |
| // |
| |
| /**@name Statistics */ |
| ///@{ |
| uint64_t deliveries_ingress; |
| uint64_t deliveries_egress; |
| uint64_t deliveries_transit; |
| uint64_t deliveries_to_container; |
| uint64_t deliveries_from_container; |
| ///@} |
| }; |
| |
| ALLOC_DECLARE(qd_address_t); |
| DEQ_DECLARE(qd_address_t, qd_address_list_t); |
| |
| /** Constructor for qd_address_t */ |
| qd_address_t* qd_address(qd_address_semantics_t semantics); |
| |
| struct qd_config_phase_t { |
| DEQ_LINKS(qd_config_phase_t); |
| char phase; |
| qd_address_semantics_t semantics; |
| }; |
| |
| DEQ_DECLARE(qd_config_phase_t, qd_config_phase_list_t); |
| |
| struct qd_config_address_t { |
| DEQ_LINKS(qd_config_address_t); |
| char *prefix; |
| char last_phase; |
| qd_config_phase_list_t phases; |
| }; |
| |
| DEQ_DECLARE(qd_config_address_t, qd_config_address_list_t); |
| |
| /** |
| * A waypoint is a point on a multi-phase route where messages can exit and re-enter the router. |
| * |
| * NOTE: a message received by a waypoint is first sent OUT and then received back IN. |
| */ |
| struct qd_waypoint_t { |
| DEQ_LINKS(qd_waypoint_t); |
| char *address; |
| char in_phase; ///< Phase for re-entering message. |
| char out_phase; ///< Phase for exiting message. |
| char *connector_name; ///< On-demand connector name for outgoing messages. |
| qd_config_connector_t *connector; ///< Connector for outgoing messages. |
| qd_connection_t *connection; ///< Connection for outgoing messages. |
| qd_link_t *in_link; ///< Link for re-entering messages. |
| qd_link_t *out_link; ///< Link for exiting messages. |
| qd_address_t *in_address; ///< Address for re-entering messages. |
| qd_address_t *out_address; ///< Address for exiting messages. |
| bool connected; ///< True if connected. |
| }; |
| |
| DEQ_DECLARE(qd_waypoint_t, qd_waypoint_list_t); |
| |
| |
| struct qd_router_t { |
| qd_dispatch_t *qd; |
| qd_log_source_t *log_source; |
| qd_router_mode_t router_mode; |
| const char *router_area; |
| const char *router_id; |
| qd_node_t *node; |
| |
| qd_address_list_t addrs; |
| qd_hash_t *addr_hash; |
| qd_address_t *router_addr; |
| qd_address_t *routerma_addr; |
| qd_address_t *hello_addr; |
| |
| qd_router_link_list_t links; |
| qd_router_node_list_t routers; |
| qd_lrp_container_list_t lrp_containers; |
| qd_router_link_t **out_links_by_mask_bit; |
| qd_router_node_t **routers_by_mask_bit; |
| |
| qd_bitmask_t *neighbor_free_mask; |
| sys_mutex_t *lock; |
| qd_timer_t *timer; |
| uint64_t dtag; |
| |
| qd_config_address_list_t config_addrs; |
| qd_waypoint_list_t waypoints; |
| }; |
| |
| void qd_router_check_addr(qd_router_t *router, qd_address_t *addr, int was_local); |
| void qd_router_add_link_ref_LH(qd_router_link_ref_list_t *ref_list, qd_router_link_t *link); |
| void qd_router_del_link_ref_LH(qd_router_link_ref_list_t *ref_list, qd_router_link_t *link); |
| |
| void qd_router_add_node_ref_LH(qd_router_ref_list_t *ref_list, qd_router_node_t *rnode); |
| void qd_router_del_node_ref_LH(qd_router_ref_list_t *ref_list, qd_router_node_t *rnode); |
| |
| void qd_router_add_lrp_ref_LH(qd_router_lrp_ref_list_t *ref_list, qd_lrp_t *lrp); |
| void qd_router_del_lrp_ref_LH(qd_router_lrp_ref_list_t *ref_list, qd_lrp_t *lrp); |
| |
| void qd_router_mobile_added(qd_router_t *router, qd_field_iterator_t *iter); |
| void qd_router_mobile_removed(qd_router_t *router, const char *addr); |
| void qd_router_link_lost(qd_router_t *router, int link_mask_bit); |
| |
| qd_address_semantics_t router_semantics_for_addr(qd_router_t *router, qd_field_iterator_t *iter, |
| char in_phase, char *out_phase); |
| qd_address_t *qd_router_address_lookup_LH(qd_router_t *router, |
| qd_field_iterator_t *addr_iter, |
| bool *is_local, bool *is_direct); |
| |
| /** |
| * Important: qd_router_link_new_delivery must never be called twice in a row |
| * without an intervening pn_link_advance. The Disatch architecture |
| * provides a hook for discovering when an outgoing link is writable |
| * and has credit. When a link is writable, a delivery is |
| * allocated, written, and advanced in one operation. If a backlog |
| * of pending deliveries is created, an assertion will be thrown. |
| */ |
| qd_router_delivery_t *qd_router_link_new_delivery(qd_router_link_t *link, pn_delivery_tag_t tag); |
| qd_router_delivery_t *qd_router_delivery(qd_router_link_t *link, pn_delivery_t *pnd); |
| void qd_router_delivery_set_undeliverable_LH(qd_router_delivery_t *delivery); |
| void qd_router_delivery_free_LH(qd_router_delivery_t *delivery, uint64_t final_disposition); |
| void qd_router_delivery_link_peers_LH(qd_router_delivery_t *left, qd_router_delivery_t *right); |
| void qd_router_delivery_unlink_LH(qd_router_delivery_t *delivery); |
| void qd_router_delivery_fifo_enter_LH(qd_router_delivery_t *delivery); |
| bool qd_router_delivery_fifo_exit_LH(qd_router_delivery_t *delivery); |
| qd_router_delivery_t *qd_router_delivery_peer(qd_router_delivery_t *delivery); |
| void qd_router_delivery_set_context(qd_router_delivery_t *delivery, void *context); |
| void *qd_router_delivery_context(qd_router_delivery_t *delivery); |
| pn_delivery_t *qd_router_delivery_pn(qd_router_delivery_t *delivery); |
| void qd_router_delivery_settle(qd_router_delivery_t *delivery); |
| bool qd_router_delivery_settled(qd_router_delivery_t *delivery); |
| bool qd_router_delivery_disp_changed(qd_router_delivery_t *delivery); |
| uint64_t qd_router_delivery_disp(qd_router_delivery_t *delivery); |
| qd_router_link_t *qd_router_delivery_link(qd_router_delivery_t *delivery); |
| |
| #endif |