void domain_mgmt_init(void) { errval_t err; /* Register notification endpoint with kernel */ struct capref epcap; struct lmp_endpoint *notifyep; // XXX: This has to be huge so we can receive a batch of // notifications when deleting CNodes recursively. err = endpoint_create(100 * 12, &epcap, ¬ifyep); if (err_is_fail(err)) { USER_PANIC_ERR(err, "failed creating endpoint"); } // register to receive on this endpoint struct event_closure cl = { .handler = handle_notification, .arg = notifyep, }; err = lmp_endpoint_register(notifyep, get_default_waitset(), cl); assert(err_is_ok(err)); err = invoke_monitor_register(epcap); if(err_is_fail(err)) { USER_PANIC_ERR(err, "Could not register with kernel"); } else { #ifdef DEBUG_MONITOR_ALL debug_printf("monitor ep registered\n"); #endif } }
/** * \brief A monitor receives request to setup a connection * with another newly booted monitor from a third monitor */ static void bind_monitor_request_scc(struct intermon_binding *b, coreid_t core_id, intermon_caprep_t caprep, chanid_t chan_id, coreid_t from_core_id) { struct intermon_ump_ipi_binding *umpb = NULL; errval_t err; /* Create the cap */ struct capability cap_raw; caprep_to_capability(&caprep, &cap_raw); if (cap_raw.type != ObjType_Frame) { err = MON_ERR_WRONG_CAP_TYPE; goto error; } struct capref frame; err = slot_alloc(&frame); if (err_is_fail(err)) { goto error; } ram_set_affinity(cap_raw.u.frame.base, cap_raw.u.frame.base + ((genpaddr_t)1 << cap_raw.u.frame.bits)); err = frame_alloc(&frame, ((genpaddr_t)1 << cap_raw.u.frame.bits), NULL); ram_set_affinity(0,0); /* err = monitor_cap_create(frame, &cap_raw, core_id); */ if (err_is_fail(err)) { goto error; } struct frame_identity frameid = { .base = 0, .bits = 0 }; err = invoke_frame_identify(frame, &frameid); assert(err == SYS_ERR_OK); printf("bind_monitor_request: URPC physical frame at 0x%llx\n", frameid.base); /* Setup the connection */ void *buf; err = vspace_map_one_frame_attr(&buf, MON_URPC_SIZE, frame, VREGION_FLAGS_READ_WRITE_NOCACHE, NULL, NULL); if (err_is_fail(err)) { err = err_push(err, LIB_ERR_VSPACE_MAP); goto error; } // Create remote notify cap struct capref notify_cap; err = notification_create_cap(chan_id, core_id, ¬ify_cap); assert(err == SYS_ERR_OK); // Allocate my own notification caps struct capref ep, my_notify_cap; struct lmp_endpoint *iep; int chanid; err = endpoint_create(LMP_RECV_LENGTH, &ep, &iep); assert(err_is_ok(err)); err = notification_allocate(ep, &chanid); assert(err == SYS_ERR_OK); err = notification_create_cap(chanid, my_core_id, &my_notify_cap); assert(err == SYS_ERR_OK); // setup our side of the binding umpb = malloc(sizeof(struct intermon_ump_ipi_binding)); assert(umpb != NULL); err = intermon_ump_ipi_init(umpb, get_default_waitset(), buf + MON_URPC_CHANNEL_LEN, MON_URPC_CHANNEL_LEN, buf, MON_URPC_CHANNEL_LEN, notify_cap, my_notify_cap, ep, iep); assert(err_is_ok(err)); // Identify UMP frame for tracing struct frame_identity umpid; err = invoke_frame_identify(frame, &umpid); assert(err_is_ok(err)); umpb->ump_state.chan.recvid = (uintptr_t)umpid.base; umpb->ump_state.chan.sendid = (uintptr_t)(umpid.base + MON_URPC_CHANNEL_LEN); // connect it to our request handlers err = intermon_init(&umpb->b, core_id); assert(err_is_ok(err)); /* Send reply */ reply: assert(umpb != NULL); bind_monitor_reply_scc_cont(&umpb->b, err, chanid); return; error: assert(!"Argh"); // FIXME: cleanup! goto reply; } /** * \brief The monitor that proxied the request for one monitor to * setup a connection with another monitor gets the reply */ static void bind_monitor_reply_scc(struct intermon_binding *binding, errval_t err, chanid_t chan_id, coreid_t core_id) { struct intermon_ump_ipi_binding *b = (struct intermon_ump_ipi_binding *)binding; // Create notify cap to that core struct capref notify_cap; err = notification_create_cap(chan_id, core_id, ¬ify_cap); assert(err == SYS_ERR_OK); // And assign it to the binding err = ipi_notify_set(&b->ipi_notify, notify_cap); assert(err_is_ok(err)); if (err_is_fail(err)) { // XXX DEBUG_ERR(err, "Got error in bind monitor reply"); } } /******* stack-ripped bind_monitor_proxy_scc *******/ static void bind_monitor_request_scc_handler(struct intermon_binding *b, struct intermon_msg_queue_elem *e); struct bind_monitor_request_scc_state { struct intermon_msg_queue_elem elem; struct intermon_bind_monitor_request_scc__args args; }; static void bind_monitor_request_scc_cont(struct intermon_binding *dst_binding, coreid_t src_core_id, intermon_caprep_t caprep, chanid_t chan_id, coreid_t core_id) { errval_t err; err = dst_binding->tx_vtbl. bind_monitor_request_scc(dst_binding, NOP_CONT, src_core_id, caprep, chan_id, core_id); if (err_is_fail(err)) { if(err_no(err) == FLOUNDER_ERR_TX_BUSY) { struct bind_monitor_request_scc_state *me = malloc(sizeof(struct bind_monitor_request_scc_state)); assert(me != NULL); struct intermon_state *ist = dst_binding->st; assert(ist != NULL); me->args.core_id = src_core_id; me->args.cap = caprep; me->args.chan_id = chan_id; me->args.from_core_id = core_id; me->elem.cont = bind_monitor_request_scc_handler; err = intermon_enqueue_send(dst_binding, &ist->queue, get_default_waitset(), &me->elem.queue); assert(err_is_ok(err)); return; } DEBUG_ERR(err, "forwarding bind request failed"); } }
/** * \brief Notification of a newly booted monitor. * Setup our connection and request the sender to proxy * the bind request to the monitor */ static void new_monitor_notify(struct intermon_binding *b, coreid_t core_id) { errval_t err; /* Setup the connection */ ram_set_affinity(SHARED_MEM_MIN + (PERCORE_MEM_SIZE * my_core_id), SHARED_MEM_MIN + (PERCORE_MEM_SIZE * (my_core_id + 1))); struct capref frame; err = frame_alloc(&frame, MON_URPC_SIZE, NULL); if (err_is_fail(err)) { DEBUG_ERR(err, "frame_alloc failed"); return; // FIXME: cleanup } ram_set_affinity(0, 0); // Reset affinity void *buf; err = vspace_map_one_frame_attr(&buf, MON_URPC_SIZE, frame, VREGION_FLAGS_READ_WRITE_NOCACHE, NULL, NULL); if (err_is_fail(err)) { DEBUG_ERR(err, "vspace_map_one_frame failed"); assert(buf); // XXX } // XXX: Clear the frame (kernel can't do it for us) memset(buf, 0, MON_URPC_SIZE); // Allocate my own notification caps struct capref ep, my_notify_cap; struct lmp_endpoint *iep; int chanid; err = endpoint_create(LMP_RECV_LENGTH, &ep, &iep); assert(err_is_ok(err)); err = notification_allocate(ep, &chanid); assert(err == SYS_ERR_OK); err = notification_create_cap(chanid, my_core_id, &my_notify_cap); assert(err == SYS_ERR_OK); // init our end of the binding and channel struct intermon_ump_ipi_binding *ump_binding = malloc(sizeof(struct intermon_ump_ipi_binding)); assert(ump_binding != NULL); err = intermon_ump_ipi_init(ump_binding, get_default_waitset(), buf, MON_URPC_CHANNEL_LEN, buf + MON_URPC_CHANNEL_LEN, MON_URPC_CHANNEL_LEN, NULL_CAP, my_notify_cap, ep, iep); assert(err_is_ok(err)); /* if (err_is_fail(err)) { */ /* cap_destroy(frame); */ /* return err_push(err, LIB_ERR_UMP_CHAN_BIND); */ /* } */ // Identify UMP frame for tracing struct frame_identity umpid = { .base = 0, .bits = 0 }; err = invoke_frame_identify(frame, &umpid); assert(err_is_ok(err)); ump_binding->ump_state.chan.recvid = (uintptr_t)umpid.base; ump_binding->ump_state.chan.sendid = (uintptr_t)(umpid.base + MON_URPC_CHANNEL_LEN); err = intermon_init(&ump_binding->b, core_id); assert(err_is_ok(err)); /* Identify the frame cap */ struct capability frame_cap; err = monitor_cap_identify(frame, &frame_cap); if (err_is_fail(err)) { DEBUG_ERR(err, "monitor_cap_identify failed"); return; // FIXME: cleanup } intermon_caprep_t caprep; capability_to_caprep(&frame_cap, &caprep); /* reply to the sending monitor to proxy request */ err = b->tx_vtbl.bind_monitor_proxy_scc(b, NOP_CONT, core_id, caprep, chanid, my_core_id); if (err_is_fail(err)) { DEBUG_ERR(err, "bind proxy request failed"); } } errval_t arch_intermon_init(struct intermon_binding *b) { b->rx_vtbl.bind_monitor_request_scc = bind_monitor_request_scc; b->rx_vtbl.bind_monitor_reply_scc = bind_monitor_reply_scc; b->rx_vtbl.bind_monitor_proxy_scc = bind_monitor_proxy_scc; b->rx_vtbl.new_monitor_notify = new_monitor_notify; return SYS_ERR_OK; }
DDS_DataReader DDS_Subscriber_create_datareader (DDS_Subscriber sp, DDS_TopicDescription topic, const DDS_DataReaderQos *qos, const DDS_DataReaderListener *listener, DDS_StatusMask mask) { Domain_t *dp; Topic_t *tp; Participant_t *pp; Reader_t *rp; Cache_t cp; EntityId_t eid; #ifdef DDS_NATIVE_SECURITY unsigned secure; DDS_ReturnCode_t ret; #endif const TypeSupport_t *ts; int error; ctrc_begind (DCPS_ID, DCPS_S_C_DR, &sp, sizeof (sp)); ctrc_contd (&topic, sizeof (topic)); ctrc_contd (&qos, sizeof (qos)); ctrc_contd (&listener, sizeof (listener)); ctrc_contd (&mask, sizeof (mask)); ctrc_endd (); prof_start (dcps_create_reader); if (!subscriber_ptr (sp, NULL)) return (NULL); dp = sp->domain; if (!dp || lock_take (dp->lock)) return (NULL); if (sp->domain != dp) goto inv_topic; /*DDS_RETCODE_BAD_PARAMETER*/ tp = topic_ptr (topic, 1, NULL); if (!tp) goto inv_topic; rp = NULL; /* Don't check whether reader is already created! Multiple readers and or writers on the same topic are definitely allowed! */ if (qos == DDS_DATAREADER_QOS_DEFAULT) qos = &sp->def_reader_qos; else if (qos != DDS_DATAREADER_QOS_USE_TOPIC_QOS && !qos_valid_reader_qos (qos)) goto done; #ifdef DDS_SECURITY /* Check if security policy allows this datareader. */ #ifdef DDS_NATIVE_SECURITY if (sec_check_create_reader (dp->participant.p_permissions, str_ptr (tp->name), NULL, qos, sp->qos.partition, NULL, &secure)) { #else if (check_create_reader (dp->participant.p_permissions, tp, qos, sp->qos.partition)) { #endif log_printf (DCPS_ID, 0, "create_datareader: reader create not allowed!\r\n"); goto done; } #endif /* Create an Entity Identifier. */ ts = tp->type->type_support; if ((sp->entity.flags & EF_BUILTIN) != 0) { eid.id [0] = eid.id [1] = 0; eid.id [2] = 0x10 + tp->type->index; eid.id [ENTITY_KIND_INDEX] = ENTITY_KIND_BUILTIN | ENTITY_KIND_READER_KEY; } else { ++dcps_entity_count; eid.id [0] = (dcps_entity_count >> 16) & 0xff; eid.id [1] = (dcps_entity_count >> 8) & 0xff; eid.id [2] = dcps_entity_count & 0xff; if (ts->ts_keys) eid.id [ENTITY_KIND_INDEX] = ENTITY_KIND_USER | ENTITY_KIND_READER_KEY; else eid.id [ENTITY_KIND_INDEX] = ENTITY_KIND_USER | ENTITY_KIND_READER; } pp = &dp->participant; rp = (Reader_t *) endpoint_create (pp, sp, &eid, NULL); if (!rp) { warn_printf ("create_datareader: out of memory for DataReader structure.\r\n"); goto done; } #ifdef RW_LOCKS lock_take (rp->r_lock); #endif if ((sp->entity.flags & EF_BUILTIN) != 0) rp->r_flags |= EF_BUILTIN; if (qos == DDS_DATAREADER_QOS_USE_TOPIC_QOS) { rp->r_qos = tp->qos; tp->qos->users++; qos_init_time_based_filter (&rp->r_time_based_filter); qos_init_reader_data_lifecycle (&rp->r_data_lifecycle); } else { rp->r_qos = qos_reader_new (qos); rp->r_time_based_filter = qos->time_based_filter; rp->r_data_lifecycle = qos->reader_data_lifecycle; } if (!rp->r_qos) goto free_pool; rp->r_mask = mask; if (listener) rp->r_listener = *listener; else memset (&rp->r_listener, 0, sizeof (rp->r_listener)); memset (&rp->r_rdm_status, 0, sizeof (rp->r_rdm_status)); memset (&rp->r_riq_status, 0, sizeof (rp->r_riq_status)); memset (&rp->r_sl_status, 0, sizeof (rp->r_sl_status)); memset (&rp->r_sr_status, 0, sizeof (rp->r_sr_status)); memset (&rp->r_lc_status, 0, sizeof (rp->r_lc_status)); memset (&rp->r_sm_status, 0, sizeof (rp->r_sm_status)); rp->r_changes.buffer = NULL; rp->r_changes.length = rp->r_changes.maximum = 0; rp->r_prev_info = NULL; rp->r_prev_data = NULL; rp->r_n_prev = 0; rp->r_topic = tp; rp->r_next = tp->readers; tp->readers = &rp->r_ep; #ifdef DDS_NATIVE_SECURITY /* Set security attributes. */ rp->r_access_prot = 0; rp->r_disc_prot = 0; rp->r_submsg_prot = 0; rp->r_payload_prot = 0; rp->r_crypto_type = 0; rp->r_crypto = 0; if (secure && (dp->participant.p_sec_caps & (SECC_DDS_SEC | (SECC_DDS_SEC << SECC_LOCAL))) != 0) { log_printf (DCPS_ID, 0, "DDS: Reader security attributes: 0x%x\r\n", secure); rp->r_access_prot = (secure & DDS_SECA_ACCESS_PROTECTED) != 0; rp->r_disc_prot = (secure & DDS_SECA_DISC_PROTECTED) != 0; rp->r_submsg_prot = (secure & DDS_SECA_SUBMSG_PROTECTED) != 0; rp->r_payload_prot = (secure & DDS_SECA_PAYLOAD_PROTECTED) != 0; if (rp->r_submsg_prot || rp->r_payload_prot) { rp->r_crypto_type = secure >> DDS_SECA_ENCRYPTION_SHIFT; rp->r_crypto = sec_register_local_datareader (dp->participant.p_crypto, rp, &ret); } }
void sedp_publication_event (Reader_t *rp, NotificationType_t t, int cdd, int secure) { Domain_t *dp = rp->r_subscriber->domain; Participant_t *pp; ChangeData_t change; DiscoveredWriterData *info = NULL, tinfo; Topic_t *tp; DiscoveredWriter_t *dwp; Reader_t *mrp; UniQos_t qos; InfoType_t type; GUID_t *guidp; int error; if (t != NT_DATA_AVAILABLE) return; rp->r_status &= ~DDS_DATA_AVAILABLE_STATUS; for (;;) { if (info) { pid_writer_data_cleanup (info); xfree (info); info = NULL; } /*dtrc_print0 ("SEDP-Pub: get samples ");*/ error = disc_get_data (rp, &change); if (error) { /*dtrc_print0 ("- none\r\n");*/ break; } /*dtrc_print1 ("- valid(%u)\r\n", change.kind);*/ if (change.kind != ALIVE) { error = hc_get_key (rp->r_cache, change.h, &tinfo, 0); if (error) continue; guidp = &tinfo.proxy.guid; type = EI_DELETE; hc_inst_free (rp->r_cache, change.h); } else { info = change.data; if (!info->topic_name || !info->type_name) { hc_inst_free (rp->r_cache, change.h); continue; } type = EI_NEW; guidp = &info->proxy.guid; } pp = entity_participant (change.writer); if (!pp || /* Not found. */ pp == &dp->participant || /* Own sent info. */ entity_ignored (pp->p_flags)) { /* Ignored. */ if (pp != &dp->participant && !cdd) warn_printf ("sedp_publication_rx: invalid change.writer field!\r\n"); hc_inst_free (rp->r_cache, change.h); dtrc_print0 ("SEDP-Pub: unneeded!\r\n"); continue; /* Filter out unneeded info. */ } /* Publication from remote participant. */ if (type == EI_DELETE) { dwp = (DiscoveredWriter_t *) endpoint_lookup (pp, &guidp->entity_id); if (!dwp) { dtrc_print0 ("SEDP-Pub: DELETE && doesn't exist!\r\n"); continue; /* If doesn't exist - no action. */ } if (!dwp->dw_topic) { endpoint_delete (pp, &dwp->dw_ep); continue; /* Ignored topic -- only endpoint. */ } if (sedp_log) log_printf (SEDP_ID, 0, "SEDP: Deleted %spublication (%s/%s) from peer!\r\n", (secure) ? "secure " : "", str_ptr (dwp->dw_topic->name), str_ptr (dwp->dw_topic->type->type_name)); disc_publication_remove (pp, dwp); hc_inst_free (rp->r_cache, change.h); continue; } /* Do we know this topic? */ tp = topic_lookup (&dp->participant, str_ptr (info->topic_name)); if (tp && entity_ignored (tp->entity.flags)) { hc_inst_free (rp->r_cache, change.h); dtrc_print1 ("SEDP: ignored topic (%s)!\r\n", str_ptr (info->topic_name)); continue; /* Ignored topic. */ } /* Do we know this endpoint already? */ dwp = (DiscoveredWriter_t *) endpoint_lookup (pp, &guidp->entity_id); if (dwp) { if (entity_ignored (dwp->dw_flags) || cdd) { hc_inst_free (rp->r_cache, change.h); continue; /* Ignored endpoint. */ } dtrc_print1 ("Already exists (%s)!\r\n", str_ptr (info->topic_name)); type = EI_UPDATE; disc_publication_update (pp, dwp, info); if (sedp_log) log_printf (SEDP_ID, 0, "SEDP: Updated %spublication (%s/%s) from peer!\r\n", (secure) ? "secure " : "", str_ptr (info->topic_name), str_ptr (info->type_name)); hc_inst_free (rp->r_cache, change.h); } else { /* Get QoS parameters. */ qos_disc_writer_set (&qos, &info->qos); mrp = NULL; /* Create new endpoint. */ dwp = (DiscoveredWriter_t *) endpoint_create (pp, pp, &guidp->entity_id, NULL); if (!dwp) { dtrc_print1 ("SEDP: Create endpoint (%s) not possible - exit!\r\n", str_ptr (info->topic_name)); hc_inst_free (rp->r_cache, change.h); qos_disc_writer_restore (&info->qos, &qos); continue; /* Can't create -- just ignore. */ } disc_publication_add (pp, dwp, &qos, tp, mrp, info); hc_inst_free (rp->r_cache, change.h); if (sedp_log) log_printf (SEDP_ID, 0, "SEDP: New %spublication (%s/%s) from %s!\r\n", (secure) ? "secure " : "", str_ptr (info->topic_name), str_ptr (info->type_name), (cdd) ? "CDD" : "peer"); } } if (info) { pid_writer_data_cleanup (info); xfree (info); } }