blob: 04e1bdf0c115d3af6179c1fde5142a5c1dce77a6 [file] [log] [blame]
#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