This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Harald Welte gerrit-no-reply at lists.osmocom.orgReview at https://gerrit.osmocom.org/1101 Implement new 'raw' input type for E1 timeslots In the past, the A-bis E1 input system only unederstood LAPD signalling time-slots and trau-slots with 16kBps sub-slots. This adds the notion of a 'raw' transparent 64kBps slot, without any furthe de-multiplexing nor any HLDC inside. Change-Id: I0c25c2688eddd0c55c15b280a8c6e8a49629516b --- M include/osmocom/abis/e1_input.h M src/e1_input.c M src/input/dahdi.c M src/input/misdn.c 4 files changed, 214 insertions(+), 3 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmo-abis refs/changes/01/1101/1 diff --git a/include/osmocom/abis/e1_input.h b/include/osmocom/abis/e1_input.h index 8ef33d5..7568f19 100644 --- a/include/osmocom/abis/e1_input.h +++ b/include/osmocom/abis/e1_input.h @@ -64,6 +64,7 @@ E1INP_TS_TYPE_NONE, E1INP_TS_TYPE_SIGN, E1INP_TS_TYPE_TRAU, + E1INP_TS_TYPE_RAW, }; const char *e1inp_tstype_name(enum e1inp_ts_type tp); const struct value_string e1inp_ts_type_names[5]; @@ -94,6 +95,12 @@ /* subchannel muxer for frames to E1 */ struct subch_mux mux; } trau; + struct { + /* call-back for every received frame */ + void (*recv_cb)(struct e1inp_ts *ts, struct msgb *msg); + /* queue of pending to-be-transmitted msgbs */ + struct llist_head tx_queue; + } raw; }; union { struct { @@ -203,9 +210,6 @@ /* fine a previously registered driver */ struct e1inp_driver *e1inp_driver_find(const char *name); -/* register a line with the E1 core */ -int e1inp_line_register(struct e1inp_line *line); - /* get a line by its ID */ struct e1inp_line *e1inp_line_find(uint8_t e1_nr); @@ -243,6 +247,11 @@ int (*trau_rcv_cb)(struct subch_demux *dmx, int ch, uint8_t *data, int len, void *_priv)); +/* configure and initialize one timeslot dedicated to RAW frames */ +int e1inp_ts_config_raw(struct e1inp_ts *ts, struct e1inp_line *line, + void (*raw_recv_cb)(struct e1inp_ts *ts, + struct msgb *msg)); + /* Receive a packet from the E1 driver */ int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg, uint8_t tei, uint8_t sapi); diff --git a/src/e1_input.c b/src/e1_input.c index df990d5..75ae36e 100644 --- a/src/e1_input.c +++ b/src/e1_input.c @@ -217,6 +217,7 @@ { E1INP_TS_TYPE_NONE, "None" }, { E1INP_TS_TYPE_SIGN, "Signalling" }, { E1INP_TS_TYPE_TRAU, "TRAU" }, + { E1INP_TS_TYPE_RAW, "RAW" }, { 0, NULL } }; @@ -296,6 +297,21 @@ else ts->sign.delay = 100000; INIT_LLIST_HEAD(&ts->sign.sign_links); + return 0; +} + +int e1inp_ts_config_raw(struct e1inp_ts *ts, struct e1inp_line *line, + void (*raw_recv_cb)(struct e1inp_ts *ts, + struct msgb *msg)) +{ + if (ts->type == E1INP_TS_TYPE_RAW && ts->line && line) + return 0; + + ts->type = E1INP_TS_TYPE_RAW; + ts->line = line; + ts->raw.recv_cb = raw_recv_cb; + INIT_LLIST_HEAD(&ts->raw.tx_queue); + return 0; } @@ -531,6 +547,9 @@ ret = subch_demux_in(&ts->trau.demux, msg->l2h, msgb_l2len(msg)); msgb_free(msg); break; + case E1INP_TS_TYPE_RAW: + ts->raw.recv_cb(ts, msg); + break; default: ret = -EINVAL; LOGP(DLMI, LOGL_ERROR, "unknown TS type %u\n", ts->type); @@ -654,6 +673,10 @@ } msgb_put(msg, 40); break; + case E1INP_TS_TYPE_RAW: + /* Get msgb from tx_queue */ + msg = msgb_dequeue(&e1i_ts->raw.tx_queue); + break; default: LOGP(DLMI, LOGL_ERROR, "unsupported E1 TS type %u\n", e1i_ts->type); return NULL; diff --git a/src/input/dahdi.c b/src/input/dahdi.c index ab06908..db00f5f 100644 --- a/src/input/dahdi.c +++ b/src/input/dahdi.c @@ -360,6 +360,79 @@ return ret; } +/* write to a raw channel TS */ +static int handle_ts_raw_write(struct osmo_fd *bfd) +{ + struct e1inp_line *line = bfd->data; + unsigned int ts_nr = bfd->priv_nr; + struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1]; + struct msgb *msg; + int ret; + + /* get the next msg for this timeslot */ + msg = e1inp_tx_ts(e1i_ts, NULL); + if (!msg) + return 0; + + if (msg->len != D_BCHAN_TX_GRAN) { + /* This might lead to a transmit underrun, as we call tx + * from the rx path, as there's no select/poll on dahdi + * */ + LOGP(DLINP, LOGL_NOTICE, "unexpected msg->len = %u, " + "expected %u\n", msg->len, D_BCHAN_TX_GRAN); + } + + DEBUGP(DLMIB, "RAW CHAN TX: %s\n", + osmo_hexdump(msg->data, msg->len)); + + if (0/*invertbits*/) { + flip_buf_bits(msg->data, msg->len); + } + + ret = write(bfd->fd, msg->data, msg->len); + if (ret < msg->len) + LOGP(DLINP, LOGL_DEBUG, "send returns %d instead of %d\n", + ret, msg->len); + msgb_free(msg); + + return ret; +} + +static int handle_ts_raw_read(struct osmo_fd *bfd) +{ + struct e1inp_line *line = bfd->data; + unsigned int ts_nr = bfd->priv_nr; + struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1]; + struct msgb *msg = msgb_alloc(D_TSX_ALLOC_SIZE, "DAHDI Raw TS"); + int ret; + + if (!msg) + return -ENOMEM; + + ret = read(bfd->fd, msg->data, D_TSX_ALLOC_SIZE); + if (ret < 0 || ret != D_TSX_ALLOC_SIZE) { + LOGP(DLINP, LOGL_DEBUG, "read error %d %s\n", + ret, strerror(errno)); + return ret; + } + + if (0/*invertbits*/) { + flip_buf_bits(msg->data, ret); + } + + msgb_put(msg, ret); + + msg->l2h = msg->data; + DEBUGP(DLMIB, "RAW CHAN RX: %s\n", + osmo_hexdump(msgb_l2(msg), ret)); + ret = e1inp_rx_ts(e1i_ts, msg, 0, 0); + /* physical layer indicates that data has been sent, + * we thus can send some more data */ + ret = handle_ts_raw_write(bfd); + + return ret; +} + /* callback from select.c in case one of the fd's can be read/written */ static int dahdi_fd_cb(struct osmo_fd *bfd, unsigned int what) { @@ -385,6 +458,17 @@ rc = handle_tsX_read(bfd); if (what & BSC_FD_WRITE) rc = handle_tsX_write(bfd); + /* We never include the DAHDI B-Channel FD into the + * writeset, since it doesn't support poll() based + * write flow control */ + break; + case E1INP_TS_TYPE_RAW: + if (what & BSC_FD_EXCEPT) + handle_dahdi_exception(e1i_ts); + if (what & BSC_FD_READ) + rc = handle_ts_raw_read(bfd); + if (what & BSC_FD_WRITE) + rc = handle_ts_raw_write(bfd); /* We never include the DAHDI B-Channel FD into the * writeset, since it doesn't support poll() based * write flow control */ @@ -537,6 +621,7 @@ e1i_ts, &lapd_profile_abis); break; case E1INP_TS_TYPE_TRAU: + case E1INP_TS_TYPE_RAW: /* close/release LAPD instance, if any */ if (e1i_ts->lapd) { lapd_instance_free(e1i_ts->lapd); diff --git a/src/input/misdn.c b/src/input/misdn.c index 330e3b3..391cd18 100644 --- a/src/input/misdn.c +++ b/src/input/misdn.c @@ -391,6 +391,92 @@ return ret; } +/* write to a raw channel TS */ +static int handle_ts_raw_write(struct osmo_fd *bfd, unsigned int len) +{ + struct e1inp_line *line = bfd->data; + unsigned int ts_nr = bfd->priv_nr; + struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1]; + struct msgb *msg; + struct mISDNhead *hh; + int ret; + + /* get the next msg for this timeslot */ + msg = e1inp_tx_ts(e1i_ts, NULL); + if (!msg) + return 0; + + if (msg->len != len) { + /* This might lead to a transmit underrun, as we call tx + * from the rx path, as there's no select/poll on dahdi + * */ + LOGP(DLINP, LOGL_NOTICE, "unexpected msg->len = %u, " + "expected %u\n", msg->len, len); + } + + DEBUGP(DLMIB, "RAW CHAN TX: %s\n", + osmo_hexdump(msg->data, msg->len)); + + hh = (struct mISDNhead *) msgb_push(msg, sizeof(*hh)); + hh->prim = PH_DATA_REQ; + hh->id = 0; + + ret = write(bfd->fd, msg->data, msg->len); + if (ret < msg->len) + LOGP(DLINP, LOGL_DEBUG, "send returns %d instead of %d\n", + ret, msg->len); + msgb_free(msg); + + return ret; +} + +static int handle_ts_raw_read(struct osmo_fd *bfd) +{ + struct e1inp_line *line = bfd->data; + unsigned int ts_nr = bfd->priv_nr; + struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1]; + struct msgb *msg = msgb_alloc(TSX_ALLOC_SIZE, "mISDN Tx RAW"); + struct mISDNhead *hh; + int ret; + + if (!msg) + return -ENOMEM; + + hh = (struct mISDNhead *) msg->data; + + ret = recv(bfd->fd, msg->data, TSX_ALLOC_SIZE, 0); + if (ret < 0) { + fprintf(stderr, "recvfrom error %s\n", strerror(errno)); + return ret; + } + + msgb_put(msg, ret); + + if (hh->prim != PH_CONTROL_IND) + DEBUGP(DLMIB, "<= RAW CHAN len = %d, prim(0x%x) id(0x%x): %s\n", + ret, hh->prim, hh->id, + get_value_string(prim_names, hh->prim)); + + switch (hh->prim) { + case PH_DATA_IND: + msg->l2h = msg->data + MISDN_HEADER_LEN; + DEBUGP(DLMIB, "RAW CHAN RX: %s\n", + osmo_hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN)); + /* the number of bytes received indicates that data to send */ + handle_ts_raw_write(bfd, msgb_l2len(msg)); + return e1inp_rx_ts(e1i_ts, msg, 0, 0); + case PH_ACTIVATE_IND: + case PH_DATA_CNF: + break; + default: + break; + } + /* FIXME: why do we free signalling msgs in the caller, and trau not? */ + msgb_free(msg); + + return ret; +} + /* callback from select.c in case one of the fd's can be read/written */ static int misdn_fd_cb(struct osmo_fd *bfd, unsigned int what) { @@ -413,6 +499,13 @@ /* We never include the mISDN B-Channel FD into the * writeset, since it doesn't support poll() based * write flow control */ + break; + case E1INP_TS_TYPE_RAW: + if (what & BSC_FD_READ) + rc = handle_ts_raw_read(bfd); + /* We never include the mISDN B-Channel FD into the + * writeset, since it doesn't support poll() based + * write flow control */ break; default: fprintf(stderr, "unknown E1 TS type %u\n", e1i_ts->type); @@ -524,6 +617,7 @@ bfd->when = BSC_FD_READ; break; case E1INP_TS_TYPE_TRAU: + case E1INP_TS_TYPE_RAW: bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW); /* We never include the mISDN B-Channel FD into the * writeset, since it doesn't support poll() based -- To view, visit https://gerrit.osmocom.org/1101 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I0c25c2688eddd0c55c15b280a8c6e8a49629516b Gerrit-PatchSet: 1 Gerrit-Project: libosmo-abis Gerrit-Branch: master Gerrit-Owner: Harald Welte <laforge at gnumonks.org>