/* data has arrived on the udp socket */ static int udp_read_cb(struct osmo_fd *ofd) { struct msgb *msg = msgb_alloc_headroom(SYSMOBTS_PRIM_SIZE, 128, "udp_rx"); struct l1fwd_hdl *l1fh = ofd->data; struct femtol1_hdl *fl1h = l1fh->fl1h; int rc; if (!msg) return -ENOMEM; msg->l1h = msg->data; l1fh->remote_sa_len[ofd->priv_nr] = sizeof(l1fh->remote_sa[ofd->priv_nr]); rc = recvfrom(ofd->fd, msg->l1h, msgb_tailroom(msg), 0, (struct sockaddr *) &l1fh->remote_sa[ofd->priv_nr], &l1fh->remote_sa_len[ofd->priv_nr]); if (rc < 0) { perror("read from udp"); msgb_free(msg); return rc; } else if (rc == 0) { perror("len=0 read from udp"); msgb_free(msg); return rc; } msgb_put(msg, rc); DEBUGP(DL1C, "UDP: Received %u bytes for queue %d\n", rc, ofd->priv_nr); /* put the message into the right queue */ rc = osmo_wqueue_enqueue(&fl1h->write_q[ofd->priv_nr], msg); return rc; }
/* callback when there's a new L1 primitive coming in from the HW */ int l1if_handle_l1prim(int wq, struct femtol1_hdl *fl1h, struct msgb *msg) { struct l1fwd_hdl *l1fh = fl1h->priv; /* Enqueue message to UDP socket */ return osmo_wqueue_enqueue(&l1fh->udp_wq[wq], msg); }
/* callback when there's a new SYS primitive coming in from the HW */ int l1if_handle_sysprim(struct femtol1_hdl *fl1h, struct msgb *msg) { struct l1fwd_hdl *l1fh = fl1h->priv; /* Enqueue message to UDP socket */ return osmo_wqueue_enqueue(&l1fh->udp_wq[MQ_SYS_WRITE], msg); }
/* callback when there's a new SYS primitive coming in from the HW */ int l1if_handle_sysprim(struct femtol1_hdl *fl1h, struct msgb *msg) { struct l1fwd_hdl *l1fh = fl1h->priv; /* Enqueue message to UDP socket */ if (osmo_wqueue_enqueue(&l1fh->udp_wq[MQ_SYS_WRITE], msg) != 0) { LOGP(DL1C, LOGL_ERROR, "MQ_SYS_WRITE ful. dropping msg\n"); msgb_free(msg); return -EAGAIN; } return 0; }
/* callback when there's a new L1 primitive coming in from the HW */ int l1if_handle_l1prim(int wq, struct femtol1_hdl *fl1h, struct msgb *msg) { struct l1fwd_hdl *l1fh = fl1h->priv; /* Enqueue message to UDP socket */ if (osmo_wqueue_enqueue(&l1fh->udp_wq[wq], msg) != 0) { LOGP(DL1C, LOGL_ERROR, "Write queue %d full. dropping msg\n", wq); msgb_free(msg); return -EAGAIN; } return 0; }
static void test_wqueue_limit(void) { struct msgb *msg; struct osmo_wqueue wqueue; int rc; osmo_wqueue_init(&wqueue, 0); OSMO_ASSERT(wqueue.max_length == 0); OSMO_ASSERT(wqueue.current_length == 0); OSMO_ASSERT(wqueue.read_cb == NULL); OSMO_ASSERT(wqueue.write_cb == NULL); OSMO_ASSERT(wqueue.except_cb == NULL); /* try to add and fail */ msg = msgb_alloc(4096, "msg1"); rc = osmo_wqueue_enqueue(&wqueue, msg); OSMO_ASSERT(rc < 0); /* add one and fail on the second */ wqueue.max_length = 1; rc = osmo_wqueue_enqueue(&wqueue, msg); OSMO_ASSERT(rc == 0); OSMO_ASSERT(wqueue.current_length == 1); msg = msgb_alloc(4096, "msg2"); rc = osmo_wqueue_enqueue(&wqueue, msg); OSMO_ASSERT(rc < 0); /* add one more */ wqueue.max_length = 2; rc = osmo_wqueue_enqueue(&wqueue, msg); OSMO_ASSERT(rc == 0); OSMO_ASSERT(wqueue.current_length == 2); /* release everything */ osmo_wqueue_clear(&wqueue); OSMO_ASSERT(wqueue.current_length == 0); OSMO_ASSERT(wqueue.max_length == 2); /* Add two, fail on the third, free it and the queue */ msg = msgb_alloc(4096, "msg3"); rc = osmo_wqueue_enqueue(&wqueue, msg); OSMO_ASSERT(rc == 0); OSMO_ASSERT(wqueue.current_length == 1); msg = msgb_alloc(4096, "msg4"); rc = osmo_wqueue_enqueue(&wqueue, msg); OSMO_ASSERT(rc == 0); OSMO_ASSERT(wqueue.current_length == 2); msg = msgb_alloc(4096, "msg5"); rc = osmo_wqueue_enqueue(&wqueue, msg); OSMO_ASSERT(rc < 0); OSMO_ASSERT(wqueue.current_length == 2); msgb_free(msg); osmo_wqueue_clear(&wqueue); }
static int process_meas_rep(struct gsm_meas_rep *mr) { struct msgb *msg; struct meas_feed_meas *mfm; struct gsm_subscriber *subscr; /* ignore measurements as long as we don't know who it is */ if (!mr->lchan || !mr->lchan->conn || !mr->lchan->conn->subscr) return 0; subscr = mr->lchan->conn->subscr; msg = msgb_alloc(sizeof(struct meas_feed_meas), "Meas. Feed"); if (!msg) return 0; /* fill in the header */ mfm = (struct meas_feed_meas *) msgb_put(msg, sizeof(*mfm)); mfm->hdr.msg_type = MEAS_FEED_MEAS; mfm->hdr.version = MEAS_FEED_VERSION; /* fill in MEAS_FEED_MEAS specific header */ strncpy(mfm->imsi, subscr->imsi, sizeof(mfm->imsi)-1); mfm->imsi[sizeof(mfm->imsi)-1] = '\0'; strncpy(mfm->name, subscr->name, sizeof(mfm->name)-1); mfm->name[sizeof(mfm->name)-1] = '\0'; strncpy(mfm->scenario, g_mfs.scenario, sizeof(mfm->scenario)); mfm->scenario[sizeof(mfm->scenario)-1] = '\0'; /* copy the entire measurement report */ memcpy(&mfm->mr, mr, sizeof(mfm->mr)); /* copy channel information */ /* we assume that the measurement report always belong to some timeslot */ mfm->lchan_type = (uint8_t)mr->lchan->type; mfm->pchan_type = (uint8_t)mr->lchan->ts->pchan; mfm->bts_nr = mr->lchan->ts->trx->bts->nr; mfm->trx_nr = mr->lchan->ts->trx->nr; mfm->ts_nr = mr->lchan->ts->nr; mfm->ss_nr = mr->lchan->nr; /* and send it to the socket */ if (osmo_wqueue_enqueue(&g_mfs.wqueue, msg) != 0) msgb_free(msg); return 0; }
static int pack_and_send(struct esme *esme, uint32_t type, void *ptr) { struct msgb *msg = msgb_alloc(4096, "SMPP_Tx"); int rc, rlen; if (!msg) return -ENOMEM; rc = smpp34_pack(type, msg->tail, msgb_tailroom(msg), &rlen, ptr); if (rc != 0) { LOGP(DSMPP, LOGL_ERROR, "[%s] Error during smpp34_pack(): %s\n", esme->system_id, smpp34_strerror); msgb_free(msg); return -EINVAL; } msgb_put(msg, rlen); return osmo_wqueue_enqueue(&esme->wqueue, msg); }
/*! \brief Send a \ref msgb through a GSMTAP source * \param[in] gti GSMTAP instance * \param[in] msg message buffer */ int gsmtap_sendmsg(struct gsmtap_inst *gti, struct msgb *msg) { if (!gti) return -ENODEV; if (gti->ofd_wq_mode) return osmo_wqueue_enqueue(>i->wq, msg); else { /* try immediate send and return error if any */ int rc; rc = write(gsmtap_inst_fd(gti), msg->data, msg->len); if (rc <= 0) { return rc; } else if (rc >= msg->len) { msgb_free(msg); return 0; } else { /* short write */ return -EIO; } } }
static int _l1if_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, int is_system_prim, l1if_compl_cb *cb, void *data) { struct wait_l1_conf *wlc; struct osmo_wqueue *wqueue; unsigned int timeout_secs; /* allocate new wsc and store reference to mutex and conf_id */ wlc = talloc_zero(fl1h, struct wait_l1_conf); wlc->cb = cb; wlc->cb_data = data; /* Make sure we actually have received a REQUEST type primitive */ if (is_system_prim == 0) { GsmL1_Prim_t *l1p = msgb_l1prim(msg); LOGP(DL1P, LOGL_INFO, "Tx L1 prim %s\n", get_value_string(lc15bts_l1prim_names, l1p->id)); if (lc15bts_get_l1prim_type(l1p->id) != L1P_T_REQ) { LOGP(DL1C, LOGL_ERROR, "L1 Prim %s is not a Request!\n", get_value_string(lc15bts_l1prim_names, l1p->id)); talloc_free(wlc); return -EINVAL; } wlc->is_sys_prim = 0; wlc->conf_prim_id = lc15bts_get_l1prim_conf(l1p->id); wlc->conf_hLayer3 = l1p_get_hLayer3(l1p); wqueue = &fl1h->write_q[MQ_L1_WRITE]; timeout_secs = 30; } else { Litecell15_Prim_t *sysp = msgb_sysprim(msg); LOGP(DL1C, LOGL_INFO, "Tx SYS prim %s\n", get_value_string(lc15bts_sysprim_names, sysp->id)); if (lc15bts_get_sysprim_type(sysp->id) != L1P_T_REQ) { LOGP(DL1C, LOGL_ERROR, "SYS Prim %s is not a Request!\n", get_value_string(lc15bts_sysprim_names, sysp->id)); talloc_free(wlc); return -EINVAL; } wlc->is_sys_prim = 1; wlc->conf_prim_id = lc15bts_get_sysprim_conf(sysp->id); wqueue = &fl1h->write_q[MQ_SYS_WRITE]; timeout_secs = 30; } /* enqueue the message in the queue and add wsc to list */ if (osmo_wqueue_enqueue(wqueue, msg) != 0) { /* So we will get a timeout but the log message might help */ LOGP(DL1C, LOGL_ERROR, "Write queue for %s full. dropping msg.\n", is_system_prim ? "system primitive" : "gsm"); msgb_free(msg); } llist_add(&wlc->list, &fl1h->wlc_list); /* schedule a timer for timeout_secs seconds. If DSP fails to respond, we terminate */ wlc->timer.data = wlc; wlc->timer.cb = l1if_req_timeout; osmo_timer_schedule(&wlc->timer, timeout_secs, 0); return 0; }