laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/34985?usp=email )
Change subject: LAPD: Add support for RTS based polling and T200 ...................................................................... LAPD: Add support for RTS based polling and T200 The T200 timer is started when the current frame is polled at PH-READY-TO-SEND event. A flag is used to enable this feature. The user of LAPD core must track frame numbers to check the timeout condition. Then it must call the external timeout function. Related: OS#4074 Change-Id: Ib961b5a44911b99b0487641533301749c0286995 --- M TODO-RELEASE M include/osmocom/isdn/lapd_core.h M src/isdn/lapd_core.c M src/isdn/libosmoisdn.map 4 files changed, 135 insertions(+), 14 deletions(-) Approvals: laforge: Looks good to me, approved Jenkins Builder: Verified daniel: Looks good to me, but someone else must approve diff --git a/TODO-RELEASE b/TODO-RELEASE index b67161d..1d56d45 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -9,3 +9,4 @@ #library what description / commit summary line core ADD osmo_sock_multiaddr_{add,del}_local_addr() core ADD gsmtap_inst_fd2() core, DEPRECATE gsmtap_inst_fd() +isdn ABI change add states and flags for external T200 handling diff --git a/include/osmocom/isdn/lapd_core.h b/include/osmocom/isdn/lapd_core.h index e4e8b46..776d4f4 100644 --- a/include/osmocom/isdn/lapd_core.h +++ b/include/osmocom/isdn/lapd_core.h @@ -84,6 +84,16 @@ LAPD_STATE_TIMER_RECOV, }; +/*! lapd_flags */ +#define LAPD_F_RTS 0x0001 + +/*! LAPD T200 state in RTS mode */ +enum lapd_t200_rts { + LAPD_T200_RTS_OFF = 0, + LAPD_T200_RTS_PENDING, + LAPD_T200_RTS_RUNNING, +}; + /*! LAPD message format (I / S / U) */ enum lapd_format { LAPD_FORM_UKN = 0, @@ -133,6 +143,7 @@ struct lapd_cr_ent rem2loc; } cr; enum lapd_mode mode; /*!< current mode of link */ + unsigned int lapd_flags; /*!< \ref lapd_flags to change processing */ int use_sabme; /*!< use SABME instead of SABM */ int reestablish; /*!< enable reestablish support */ int n200, n200_est_rel; /*!< number of retranmissions */ @@ -149,6 +160,7 @@ uint8_t peer_busy; /*!< receiver busy on remote side */ int t200_sec, t200_usec; /*!< retry timer (default 1 sec) */ int t203_sec, t203_usec; /*!< retry timer (default 10 secs) */ + enum lapd_t200_rts t200_rts; /*!< state of T200 in RTS mode */ struct osmo_timer_list t200; /*!< T200 timer */ struct osmo_timer_list t203; /*!< T203 timer */ uint8_t retrans_ctr; /*!< re-transmission counter */ @@ -169,8 +181,11 @@ void lapd_dl_set_name(struct lapd_datalink *dl, const char *name); void lapd_dl_exit(struct lapd_datalink *dl); void lapd_dl_reset(struct lapd_datalink *dl); +int lapd_dl_set_flags(struct lapd_datalink *dl, unsigned int flags); int lapd_set_mode(struct lapd_datalink *dl, enum lapd_mode mode); int lapd_ph_data_ind(struct msgb *msg, struct lapd_msg_ctx *lctx); +int lapd_ph_rts_ind(struct lapd_msg_ctx *lctx); int lapd_recv_dlsap(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx); +int lapd_t200_timeout(struct lapd_datalink *dl); /*! @} */ diff --git a/src/isdn/lapd_core.c b/src/isdn/lapd_core.c index 57a0225..34748a4 100644 --- a/src/isdn/lapd_core.c +++ b/src/isdn/lapd_core.c @@ -204,11 +204,35 @@ static void lapd_start_t200(struct lapd_datalink *dl) { - if (osmo_timer_pending(&dl->t200)) - return; - LOGDL(dl, LOGL_INFO, "start T200 (timeout=%d.%06ds)\n", - dl->t200_sec, dl->t200_usec); - osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec); + if ((dl->lapd_flags & LAPD_F_RTS)) { + if (dl->t200_rts != LAPD_T200_RTS_OFF) + return; + LOGDL(dl, LOGL_INFO, "Start T200. (pending until triggered by RTS)\n"); + dl->t200_rts = LAPD_T200_RTS_PENDING; + } else { + if (osmo_timer_pending(&dl->t200)) + return; + LOGDL(dl, LOGL_INFO, "Start T200 (timeout=%d.%06ds).\n", dl->t200_sec, dl->t200_usec); + osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec); + } +} + +/*! Handle timeout condition of T200 in RTS mode. + * The caller (LAPDm code) implements the T200 timer and must detect timeout condition. + * The function gets called by LAPDm code when it detects a timeout of T200. + * \param[in] dl caller-allocated datalink structure */ +int lapd_t200_timeout(struct lapd_datalink *dl) +{ + OSMO_ASSERT((dl->lapd_flags & LAPD_F_RTS)); + + if (dl->t200_rts != LAPD_T200_RTS_RUNNING) + return -EINVAL; + + dl->t200_rts = LAPD_T200_RTS_OFF; + + lapd_t200_cb(dl); + + return 0; } static void lapd_start_t203(struct lapd_datalink *dl) @@ -221,10 +245,24 @@ static void lapd_stop_t200(struct lapd_datalink *dl) { - if (!osmo_timer_pending(&dl->t200)) - return; + if ((dl->lapd_flags & LAPD_F_RTS)) { + if (dl->t200_rts == LAPD_T200_RTS_OFF) + return; + dl->t200_rts = LAPD_T200_RTS_OFF; + } else { + if (!osmo_timer_pending(&dl->t200)) + return; + osmo_timer_del(&dl->t200); + } LOGDL(dl, LOGL_INFO, "stop T200\n"); - osmo_timer_del(&dl->t200); +} + +static bool lapd_is_t200_started(struct lapd_datalink *dl) +{ + if ((dl->lapd_flags & LAPD_F_RTS)) + return (dl->t200_rts != LAPD_T200_RTS_OFF); + else + return osmo_timer_pending(&dl->t200); } static void lapd_stop_t203(struct lapd_datalink *dl) @@ -359,6 +397,21 @@ lapd_dl_newstate(dl, LAPD_STATE_IDLE); } +/*! Set lapd_flags to change behaviour + * \param[in] dl \ref lapd_datalink instance + * \param[in] flags \ref lapd_flags */ +int lapd_dl_set_flags(struct lapd_datalink *dl, unsigned int flags) +{ + if (lapd_is_t200_started(dl) && (flags & LAPD_F_RTS) != (dl->lapd_flags & LAPD_F_RTS)) { + LOGDL(dl, LOGL_ERROR, "Changing RTS flag not allowed while T200 is running.\n"); + return -EINVAL; + } + + dl->lapd_flags = flags; + + return 0; +} + /* reset and de-allocate history buffer */ void lapd_dl_exit(struct lapd_datalink *dl) { @@ -806,11 +859,8 @@ /* Stop T203, if running */ lapd_stop_t203(dl); /* Start T203, if T200 is not running in MF EST state, if enabled */ - if (!osmo_timer_pending(&dl->t200) - && (dl->t203_sec || dl->t203_usec) - && (dl->state == LAPD_STATE_MF_EST)) { + if (!lapd_is_t200_started(dl) && (dl->t203_sec || dl->t203_usec) && (dl->state == LAPD_STATE_MF_EST)) lapd_start_t203(dl); - } } /* L1 -> L2 */ @@ -1732,6 +1782,31 @@ return rc; } +/*! Enqueue next LAPD frame and run pending T200. (Must be called when frame is ready to send.) + * The caller (LAPDm code) calls this function before it sends the next frame. + * If there is no frame in the TX queue, LAPD will enqueue next I-frame, if possible. + * If the T200 is pending, it is changed to running state. + * \param[in] lctx LAPD context + * \param[out] rc set to 1, if timer T200 state changed to running, set to 0, if not. */ +int lapd_ph_rts_ind(struct lapd_msg_ctx *lctx) +{ + struct lapd_datalink *dl = lctx->dl; + + /* If there is no pending frame, try to enqueue next I frame. */ + if (llist_empty(&dl->tx_queue) && (dl->state == LAPD_STATE_MF_EST || dl->state == LAPD_STATE_TIMER_RECOV)) { + /* Send an I frame, if there are pending outgoing messages. */ + lapd_send_i(dl, __LINE__, true); + } + + /* Run T200 at RTS, if pending. Tell caller that is has been started. (rc = 1) */ + if (dl->t200_rts == LAPD_T200_RTS_PENDING) { + dl->t200_rts = LAPD_T200_RTS_RUNNING; + return 1; + } + + return 0; +} + /* L3 -> L2 */ /* send unit data */ @@ -1861,6 +1936,12 @@ if (!rts) LOGDL(dl, LOGL_INFO, "%s() called from line %d\n", __func__, line); + if ((dl->lapd_flags & LAPD_F_RTS) && !llist_empty(&dl->tx_queue)) { + if (!rts) + LOGDL(dl, LOGL_INFO, "There is a frame in the TX queue, not checking for sending I frame.\n"); + return rc; + } + next_frame: if (dl->peer_busy) { @@ -1978,7 +2059,7 @@ /* If timer T200 is not running at the time right before transmitting a * frame, when the PH-READY-TO-SEND primitive is received from the * physical layer., it shall be set. */ - if (!osmo_timer_pending(&dl->t200)) { + if (!lapd_is_t200_started(dl)) { /* stop Timer T203, if running */ lapd_stop_t203(dl); /* start Timer T200 */ @@ -1987,7 +2068,11 @@ dl->send_ph_data_req(&nctx, msg); - rc = 0; /* we sent something */ + /* When using RTS, we send only one frame. */ + if ((dl->lapd_flags & LAPD_F_RTS)) + return 0; + + rc = 0; /* We sent an I frame, so sending RR frame is not required. */ goto next_frame; } diff --git a/src/isdn/libosmoisdn.map b/src/isdn/libosmoisdn.map index 3269771..c29240b 100644 --- a/src/isdn/libosmoisdn.map +++ b/src/isdn/libosmoisdn.map @@ -7,11 +7,14 @@ lapd_dl_init2; lapd_dl_set_name; lapd_dl_reset; +lapd_dl_set_flags; lapd_msgb_alloc; lapd_ph_data_ind; +lapd_ph_rts_ind; lapd_recv_dlsap; lapd_set_mode; lapd_state_names; +lapd_t200_timeout; osmo_i460_demux_in; osmo_i460_mux_enqueue; -- To view, visit https://gerrit.osmocom.org/c/libosmocore/+/34985?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Change-Id: Ib961b5a44911b99b0487641533301749c0286995 Gerrit-Change-Number: 34985 Gerrit-PatchSet: 10 Gerrit-Owner: jolly <andr...@eversberg.eu> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: daniel <dwillm...@sysmocom.de> Gerrit-Reviewer: laforge <lafo...@osmocom.org> Gerrit-Reviewer: neels <nhofm...@sysmocom.de> Gerrit-MessageType: merged