static void qdr_set_next_hop_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { int router_maskbit = action->args.route_table.router_maskbit; int nh_router_maskbit = action->args.route_table.nh_router_maskbit; if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "set_next_hop: Router maskbit out of range: %d", router_maskbit); return; } if (nh_router_maskbit >= qd_bitmask_width() || nh_router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "set_next_hop: Next hop router maskbit out of range: %d", router_maskbit); return; } if (core->routers_by_mask_bit[router_maskbit] == 0) { qd_log(core->log, QD_LOG_CRITICAL, "set_next_hop: Router not found"); return; } if (core->routers_by_mask_bit[nh_router_maskbit] == 0) { qd_log(core->log, QD_LOG_CRITICAL, "set_next_hop: Next hop router not found"); return; } if (router_maskbit != nh_router_maskbit) { qdr_node_t *rnode = core->routers_by_mask_bit[router_maskbit]; rnode->next_hop = core->routers_by_mask_bit[nh_router_maskbit]; } }
static void qdr_set_link_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { int router_maskbit = action->args.route_table.router_maskbit; int link_maskbit = action->args.route_table.link_maskbit; if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "set_link: Router maskbit out of range: %d", router_maskbit); return; } if (link_maskbit >= qd_bitmask_width() || link_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "set_link: Link maskbit out of range: %d", link_maskbit); return; } if (core->control_links_by_mask_bit[link_maskbit] == 0) { qd_log(core->log, QD_LOG_CRITICAL, "set_link: Invalid link reference: %d", link_maskbit); return; } if (core->routers_by_mask_bit[router_maskbit] == 0) { qd_log(core->log, QD_LOG_CRITICAL, "set_link: Router not found"); return; } // // Add the peer_link reference to the router record. // qdr_node_t *rnode = core->routers_by_mask_bit[router_maskbit]; rnode->peer_control_link = core->control_links_by_mask_bit[link_maskbit]; rnode->peer_data_link = core->data_links_by_mask_bit[link_maskbit]; }
void qdr_route_table_setup_CT(qdr_core_t *core) { DEQ_INIT(core->addrs); DEQ_INIT(core->routers); core->addr_hash = qd_hash(12, 32, 0); core->conn_id_hash = qd_hash(6, 4, 0); if (core->router_mode == QD_ROUTER_MODE_INTERIOR) { core->hello_addr = qdr_add_local_address_CT(core, 'L', "qdhello", QD_TREATMENT_MULTICAST_FLOOD); core->router_addr_L = qdr_add_local_address_CT(core, 'L', "qdrouter", QD_TREATMENT_MULTICAST_FLOOD); core->routerma_addr_L = qdr_add_local_address_CT(core, 'L', "qdrouter.ma", QD_TREATMENT_MULTICAST_ONCE); core->router_addr_T = qdr_add_local_address_CT(core, 'T', "qdrouter", QD_TREATMENT_MULTICAST_FLOOD); core->routerma_addr_T = qdr_add_local_address_CT(core, 'T', "qdrouter.ma", QD_TREATMENT_MULTICAST_ONCE); core->neighbor_free_mask = qd_bitmask(1); core->routers_by_mask_bit = NEW_PTR_ARRAY(qdr_node_t, qd_bitmask_width()); core->control_links_by_mask_bit = NEW_PTR_ARRAY(qdr_link_t, qd_bitmask_width()); core->data_links_by_mask_bit = NEW_PTR_ARRAY(qdr_link_t, qd_bitmask_width()); for (int idx = 0; idx < qd_bitmask_width(); idx++) { core->routers_by_mask_bit[idx] = 0; core->control_links_by_mask_bit[idx] = 0; core->data_links_by_mask_bit[idx] = 0; } } }
static PyObject* qd_set_valid_origins(PyObject *self, PyObject *args) { RouterAdapter *adapter = (RouterAdapter*) self; qd_router_t *router = adapter->router; int router_maskbit; PyObject *origin_list; Py_ssize_t idx; char *error = 0; if (!PyArg_ParseTuple(args, "iO", &router_maskbit, &origin_list)) return 0; do { if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { error = "Router bit mask out of range"; break; } if (!PyList_Check(origin_list)) { error = "Expected List as argument 2"; break; } Py_ssize_t origin_count = PyList_Size(origin_list); qd_bitmask_t *core_bitmask = qd_bitmask(0); 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 (error == 0) { qd_bitmask_set_bit(core_bitmask, 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(core_bitmask, maskbit); } } else { qd_bitmask_free(core_bitmask); break; } qdr_core_set_valid_origins(router->router_core, router_maskbit, core_bitmask); } while (0); if (error) { PyErr_SetString(PyExc_Exception, error); return 0; } Py_INCREF(Py_None); return Py_None; }
void qd_tracemask_remove_link(qd_tracemask_t *tm, int router_maskbit) { sys_rwlock_wrlock(tm->lock); assert(router_maskbit < qd_bitmask_width() && tm->router_by_mask_bit[router_maskbit] != 0); if (router_maskbit < qd_bitmask_width() && tm->router_by_mask_bit[router_maskbit] != 0) { qdtm_router_t *router = tm->router_by_mask_bit[router_maskbit]; router->link_maskbit = -1; } sys_rwlock_unlock(tm->lock); }
qd_tracemask_t *qd_tracemask(void) { qd_tracemask_t *tm = NEW(qd_tracemask_t); tm->lock = sys_rwlock(); tm->hash = qd_hash(8, 1, 0); tm->router_by_mask_bit = NEW_PTR_ARRAY(qdtm_router_t, qd_bitmask_width()); for (int i = 0; i < qd_bitmask_width(); i++) tm->router_by_mask_bit[i] = 0; return tm; }
void qd_tracemask_del_router(qd_tracemask_t *tm, int maskbit) { sys_rwlock_wrlock(tm->lock); assert(maskbit < qd_bitmask_width() && tm->router_by_mask_bit[maskbit] != 0); if (maskbit < qd_bitmask_width() && tm->router_by_mask_bit[maskbit] != 0) { qdtm_router_t *router = tm->router_by_mask_bit[maskbit]; qd_hash_remove_by_handle(tm->hash, router->hash_handle); tm->router_by_mask_bit[maskbit] = 0; free_qdtm_router_t(router); } sys_rwlock_unlock(tm->lock); }
void qd_tracemask_add_router(qd_tracemask_t *tm, const char *address, int maskbit) { qd_field_iterator_t *iter = qd_address_iterator_string(address, ITER_VIEW_ADDRESS_HASH); sys_rwlock_wrlock(tm->lock); assert(maskbit < qd_bitmask_width() && tm->router_by_mask_bit[maskbit] == 0); if (maskbit < qd_bitmask_width() && tm->router_by_mask_bit[maskbit] == 0) { qdtm_router_t *router = new_qdtm_router_t(); router->maskbit = maskbit; router->link_maskbit = -1; qd_hash_insert(tm->hash, iter, router, &router->hash_handle); tm->router_by_mask_bit[maskbit] = router; } sys_rwlock_unlock(tm->lock); qd_field_iterator_free(iter); }
static void qdr_set_valid_origins_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { int router_maskbit = action->args.route_table.router_maskbit; qd_bitmask_t *valid_origins = action->args.route_table.router_set; if (discard) { qd_bitmask_free(valid_origins); return; } do { if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "set_valid_origins: Router maskbit out of range: %d", router_maskbit); break; } if (core->routers_by_mask_bit[router_maskbit] == 0) { qd_log(core->log, QD_LOG_CRITICAL, "set_valid_origins: Router not found"); break; } qdr_node_t *rnode = core->routers_by_mask_bit[router_maskbit]; if (rnode->valid_origins) qd_bitmask_free(rnode->valid_origins); rnode->valid_origins = valid_origins; valid_origins = 0; } while (false); if (valid_origins) qd_bitmask_free(valid_origins); }
void qd_tracemask_free(qd_tracemask_t *tm) { for (int i = 0; i < qd_bitmask_width(); i++) { if (tm->router_by_mask_bit[i]) qd_tracemask_del_router(tm, i); } qd_hash_free(tm->hash); sys_rwlock_free(tm->lock); free(tm); }
static void qdr_del_router_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { int router_maskbit = action->args.route_table.router_maskbit; if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "del_router: Router maskbit out of range: %d", router_maskbit); return; } if (core->routers_by_mask_bit[router_maskbit] == 0) { qd_log(core->log, QD_LOG_CRITICAL, "del_router: Deleting nonexistent router: %d", router_maskbit); return; } qdr_node_t *rnode = core->routers_by_mask_bit[router_maskbit]; qdr_address_t *oaddr = rnode->owning_addr; assert(oaddr); // // Unlink the router node from the address record // qd_bitmask_clear_bit(oaddr->rnodes, router_maskbit); qd_bitmask_clear_bit(core->router_addr_T->rnodes, router_maskbit); qd_bitmask_clear_bit(core->routerma_addr_T->rnodes, router_maskbit); rnode->ref_count -= 3; // // While the router node has a non-zero reference count, look for addresses // to unlink the node from. // qdr_address_t *addr = DEQ_HEAD(core->addrs); while (addr && rnode->ref_count > 0) { if (qd_bitmask_clear_bit(addr->rnodes, router_maskbit)) // // If the cleared bit was originally set, decrement the ref count // rnode->ref_count--; addr = DEQ_NEXT(addr); } assert(rnode->ref_count == 0); // // Free the router node and the owning address records. // qd_bitmask_free(rnode->valid_origins); DEQ_REMOVE(core->routers, rnode); free_qdr_node_t(rnode); qd_hash_remove_by_handle(core->addr_hash, oaddr->hash_handle); DEQ_REMOVE(core->addrs, oaddr); qd_hash_handle_free(oaddr->hash_handle); core->routers_by_mask_bit[router_maskbit] = 0; free_qdr_address_t(oaddr); }
static void qdr_remove_next_hop_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { int router_maskbit = action->args.route_table.router_maskbit; if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "remove_next_hop: Router maskbit out of range: %d", router_maskbit); return; } qdr_node_t *rnode = core->routers_by_mask_bit[router_maskbit]; rnode->next_hop = 0; }
static void qdr_map_destination_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { // // TODO - handle the class-prefix and phase explicitly // int router_maskbit = action->args.route_table.router_maskbit; qdr_field_t *address = action->args.route_table.address; if (discard) { qdr_field_free(address); return; } do { if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "map_destination: Router maskbit out of range: %d", router_maskbit); break; } if (core->routers_by_mask_bit[router_maskbit] == 0) { qd_log(core->log, QD_LOG_CRITICAL, "map_destination: Router not found"); break; } qd_field_iterator_t *iter = address->iterator; qdr_address_t *addr = 0; qd_hash_retrieve(core->addr_hash, iter, (void**) &addr); if (!addr) { addr = qdr_address_CT(core, qdr_treatment_for_address_hash_CT(core, iter)); qd_hash_insert(core->addr_hash, iter, addr, &addr->hash_handle); DEQ_ITEM_INIT(addr); DEQ_INSERT_TAIL(core->addrs, addr); } qdr_node_t *rnode = core->routers_by_mask_bit[router_maskbit]; qd_bitmask_set_bit(addr->rnodes, router_maskbit); rnode->ref_count++; qdr_addr_start_inlinks_CT(core, addr); // // TODO - If this affects a waypoint, create the proper side effects // } while (false); qdr_field_free(address); }
static void qdr_remove_link_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { int router_maskbit = action->args.route_table.router_maskbit; if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "remove_link: Router maskbit out of range: %d", router_maskbit); return; } if (core->routers_by_mask_bit[router_maskbit] == 0) { qd_log(core->log, QD_LOG_CRITICAL, "remove_link: Router not found"); return; } qdr_node_t *rnode = core->routers_by_mask_bit[router_maskbit]; rnode->peer_control_link = 0; rnode->peer_data_link = 0; }
static void qdr_unmap_destination_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { int router_maskbit = action->args.route_table.router_maskbit; qdr_field_t *address = action->args.route_table.address; if (discard) { qdr_field_free(address); return; } do { if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "unmap_destination: Router maskbit out of range: %d", router_maskbit); break; } if (core->routers_by_mask_bit[router_maskbit] == 0) { qd_log(core->log, QD_LOG_CRITICAL, "unmap_destination: Router not found"); break; } qdr_node_t *rnode = core->routers_by_mask_bit[router_maskbit]; qd_field_iterator_t *iter = address->iterator; qdr_address_t *addr = 0; qd_hash_retrieve(core->addr_hash, iter, (void**) &addr); if (!addr) { qd_log(core->log, QD_LOG_CRITICAL, "unmap_destination: Address not found"); break; } qd_bitmask_clear_bit(addr->rnodes, router_maskbit); rnode->ref_count--; // // TODO - If this affects a waypoint, create the proper side effects // qdr_check_addr_CT(core, addr, false); } while (false); qdr_field_free(address); }
static PyObject* qd_unmap_destination(PyObject *self, PyObject *args) { RouterAdapter *adapter = (RouterAdapter*) self; qd_router_t *router = adapter->router; const char *addr_string; int maskbit; if (!PyArg_ParseTuple(args, "si", &addr_string, &maskbit)) return 0; if (maskbit >= qd_bitmask_width() || maskbit < 0) { PyErr_SetString(PyExc_Exception, "Router bit mask out of range"); return 0; } qdr_core_unmap_destination(router->router_core, maskbit, addr_string); Py_INCREF(Py_None); return Py_None; }
qd_error_t qd_router_python_setup(qd_router_t *router) { qd_error_clear(); log_source = qd_log_source("ROUTER"); qdr_core_route_table_handlers(router->router_core, router, qd_router_mobile_added, qd_router_mobile_removed, qd_router_link_lost); // // If we are not operating as an interior router, don't start the // router module. // if (router->router_mode != QD_ROUTER_MODE_INTERIOR) return QD_ERROR_NONE; PyObject *pDispatchModule = qd_python_module(); RouterAdapterType.tp_new = PyType_GenericNew; PyType_Ready(&RouterAdapterType); QD_ERROR_PY_RET(); PyTypeObject *raType = &RouterAdapterType; Py_INCREF(raType); PyModule_AddObject(pDispatchModule, "RouterAdapter", (PyObject*) &RouterAdapterType); // // Attempt to import the Python Router module // PyObject* pId; PyObject* pArea; PyObject* pMaxRouters; PyObject* pModule; PyObject* pClass; PyObject* pArgs; pModule = PyImport_ImportModule("qpid_dispatch_internal.router"); QD_ERROR_PY_RET(); pClass = PyObject_GetAttrString(pModule, "RouterEngine"); Py_DECREF(pModule); QD_ERROR_PY_RET(); PyObject *adapterType = PyObject_GetAttrString(pDispatchModule, "RouterAdapter"); QD_ERROR_PY_RET(); PyObject *adapterInstance = PyObject_CallObject(adapterType, 0); QD_ERROR_PY_RET(); ((RouterAdapter*) adapterInstance)->router = router; // // Constructor Arguments for RouterEngine // pArgs = PyTuple_New(4); // arg 0: adapter instance PyTuple_SetItem(pArgs, 0, adapterInstance); // arg 1: router_id pId = PyString_FromString(router->router_id); PyTuple_SetItem(pArgs, 1, pId); // arg 2: area_id pArea = PyString_FromString(router->router_area); PyTuple_SetItem(pArgs, 2, pArea); // arg 3: max_routers pMaxRouters = PyInt_FromLong((long) qd_bitmask_width()); PyTuple_SetItem(pArgs, 3, pMaxRouters); // // Instantiate the router // pyRouter = PyInstance_New(pClass, pArgs, 0); Py_DECREF(pArgs); Py_DECREF(adapterType); QD_ERROR_PY_RET(); pyTick = PyObject_GetAttrString(pyRouter, "handleTimerTick"); QD_ERROR_PY_RET(); pyAdded = PyObject_GetAttrString(pyRouter, "addressAdded"); QD_ERROR_PY_RET(); pyRemoved = PyObject_GetAttrString(pyRouter, "addressRemoved"); QD_ERROR_PY_RET(); pyLinkLost = PyObject_GetAttrString(pyRouter, "linkLost"); QD_ERROR_PY_RET(); return qd_error_code(); }
static void qdr_add_router_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { int router_maskbit = action->args.route_table.router_maskbit; qdr_field_t *address = action->args.route_table.address; if (discard) { qdr_field_free(address); return; } do { if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "add_router: Router maskbit out of range: %d", router_maskbit); break; } if (core->routers_by_mask_bit[router_maskbit] != 0) { qd_log(core->log, QD_LOG_CRITICAL, "add_router: Router maskbit already in use: %d", router_maskbit); break; } // // Hash lookup the address to ensure there isn't an existing router address. // qd_field_iterator_t *iter = address->iterator; qdr_address_t *addr; qd_address_iterator_reset_view(iter, ITER_VIEW_ADDRESS_HASH); qd_hash_retrieve(core->addr_hash, iter, (void**) &addr); if (addr) { qd_log(core->log, QD_LOG_CRITICAL, "add_router: Data inconsistency for router-maskbit %d", router_maskbit); assert(addr == 0); // Crash in debug mode. This should never happen break; } // // 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 = qdr_address_CT(core, QD_TREATMENT_ANYCAST_CLOSEST); qd_hash_insert(core->addr_hash, iter, addr, &addr->hash_handle); DEQ_INSERT_TAIL(core->addrs, addr); // // Create a router-node record to represent the remote router. // qdr_node_t *rnode = new_qdr_node_t(); DEQ_ITEM_INIT(rnode); rnode->owning_addr = addr; rnode->mask_bit = router_maskbit; rnode->next_hop = 0; rnode->peer_control_link = 0; rnode->peer_data_link = 0; rnode->ref_count = 0; rnode->valid_origins = qd_bitmask(0); DEQ_INSERT_TAIL(core->routers, rnode); // // Link the router record to the address record. // qd_bitmask_set_bit(addr->rnodes, router_maskbit); // // Link the router record to the router address records. // Use the T-class addresses only. // qd_bitmask_set_bit(core->router_addr_T->rnodes, router_maskbit); qd_bitmask_set_bit(core->routerma_addr_T->rnodes, router_maskbit); // // Bump the ref-count by three for each of the above links. // rnode->ref_count += 3; // // Add the router record to the mask-bit index. // core->routers_by_mask_bit[router_maskbit] = rnode; } while (false); qdr_field_free(address); }
static void qdr_insert_address_columns_CT(qdr_core_t *core, qdr_address_t *addr, qd_composed_field_t *body, int column_index) { switch(column_index) { case QDR_ADDRESS_NAME: case QDR_ADDRESS_IDENTITY: case QDR_ADDRESS_KEY: if (addr->hash_handle) qd_compose_insert_string(body, (const char*) qd_hash_key_by_handle(addr->hash_handle)); else qd_compose_insert_null(body); break; case QDR_ADDRESS_TYPE: qd_compose_insert_string(body, "org.apache.qpid.dispatch.router.address"); break; case QDR_ADDRESS_DISTRIBUTION: { switch (addr->treatment) { case QD_TREATMENT_MULTICAST_FLOOD: qd_compose_insert_string(body, "flood"); break; case QD_TREATMENT_MULTICAST_ONCE: qd_compose_insert_string(body, "multicast"); break; case QD_TREATMENT_ANYCAST_CLOSEST: qd_compose_insert_string(body, "closest"); break; case QD_TREATMENT_ANYCAST_BALANCED: qd_compose_insert_string(body, "balanced"); break; case QD_TREATMENT_LINK_BALANCED: qd_compose_insert_string(body, "linkBalanced"); break; } break; } case QDR_ADDRESS_IN_PROCESS: qd_compose_insert_uint(body, DEQ_SIZE(addr->subscriptions)); break; case QDR_ADDRESS_SUBSCRIBER_COUNT: qd_compose_insert_uint(body, DEQ_SIZE(addr->rlinks)); break; case QDR_ADDRESS_REMOTE_COUNT: qd_compose_insert_uint(body, qd_bitmask_cardinality(addr->rnodes)); break; case QDR_ADDRESS_CONTAINER_COUNT: qd_compose_insert_uint(body, DEQ_SIZE(addr->conns)); break; case QDR_ADDRESS_REMOTE_HOST_ROUTERS: { qd_compose_start_list(body); int c; int bit; for (QD_BITMASK_EACH(addr->rnodes, bit, c)) { qdr_node_t *rnode = core->routers_by_mask_bit[bit]; if (rnode && rnode->owning_addr) { const char *ar = (char*) qd_hash_key_by_handle(rnode->owning_addr->hash_handle); qd_compose_insert_string(body, ar + 1); // Remove the 'R' prefix from the router address } } qd_compose_end_list(body); break; } case QDR_ADDRESS_DELIVERIES_INGRESS: qd_compose_insert_ulong(body, addr->deliveries_ingress); break; case QDR_ADDRESS_DELIVERIES_EGRESS: qd_compose_insert_ulong(body, addr->deliveries_egress); break; case QDR_ADDRESS_DELIVERIES_TRANSIT: qd_compose_insert_ulong(body, addr->deliveries_transit); break; case QDR_ADDRESS_DELIVERIES_TO_CONTAINER: qd_compose_insert_ulong(body, addr->deliveries_to_container); break; case QDR_ADDRESS_DELIVERIES_FROM_CONTAINER: qd_compose_insert_ulong(body, addr->deliveries_from_container); break; case QDR_ADDRESS_TRANSIT_OUTSTANDING: if (addr->outstanding_deliveries) { qd_compose_start_list(body); for (int i = 0; i < qd_bitmask_width(); i++) qd_compose_insert_long(body, addr->outstanding_deliveries[i]); qd_compose_end_list(body); } else qd_compose_insert_null(body); break; case QDR_ADDRESS_TRACKED_DELIVERIES: qd_compose_insert_long(body, addr->tracked_deliveries); break; default: qd_compose_insert_null(body); break; } }