Statefull reset and unblock BVCs and sending flow control messages
The flow control interval can be set via VTY.
This commit is contained in:
parent
4b39dd1c00
commit
cd8a83a42c
|
@ -25,8 +25,13 @@ struct sgsn_instance *sgsn;
|
|||
void *tall_bsc_ctx;
|
||||
struct bssgp_bvc_ctx *bctx = NULL;
|
||||
struct gprs_nsvc *nsvc = NULL;
|
||||
static int bvc_sig_reset = 0, bvc_reset = 0, bvc_unblocked = 0;
|
||||
extern uint16_t spoof_mcc, spoof_mnc;
|
||||
|
||||
struct osmo_timer_list bvc_timer;
|
||||
|
||||
static void bvc_timeout(void *_priv);
|
||||
|
||||
int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
|
||||
{
|
||||
struct bssgp_ud_hdr *budh;
|
||||
|
@ -295,6 +300,11 @@ int gprs_bssgp_pcu_rx_sign(struct msgb *msg, struct tlv_parsed *tp, struct bssgp
|
|||
break;
|
||||
case BSSGP_PDUT_BVC_RESET_ACK:
|
||||
LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_BVC_RESET_ACK\n");
|
||||
if (!bvc_sig_reset)
|
||||
bvc_sig_reset = 1;
|
||||
else
|
||||
bvc_reset = 1;
|
||||
bvc_timeout(NULL);
|
||||
break;
|
||||
case BSSGP_PDUT_PAGING_PS:
|
||||
LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_PAGING_PS\n");
|
||||
|
@ -316,6 +326,8 @@ int gprs_bssgp_pcu_rx_sign(struct msgb *msg, struct tlv_parsed *tp, struct bssgp
|
|||
break;
|
||||
case BSSGP_PDUT_BVC_UNBLOCK_ACK:
|
||||
LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_BVC_UNBLOCK_ACK\n");
|
||||
bvc_unblocked = 1;
|
||||
bvc_timeout(NULL);
|
||||
break;
|
||||
case BSSGP_PDUT_SGSN_INVOKE_TRACE:
|
||||
LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_SGSN_INVOKE_TRACE\n");
|
||||
|
@ -362,7 +374,9 @@ int gprs_bssgp_pcu_rcvmsg(struct msgb *msg)
|
|||
/* look-up or create the BTS context for this BVC */
|
||||
bctx = btsctx_by_bvci_nsei(ns_bvci, msgb_nsei(msg));
|
||||
|
||||
if (!bctx && pdu_type != BSSGP_PDUT_BVC_RESET_ACK)
|
||||
if (!bctx
|
||||
&& pdu_type != BSSGP_PDUT_BVC_RESET_ACK
|
||||
&& pdu_type != BSSGP_PDUT_BVC_UNBLOCK_ACK)
|
||||
{
|
||||
LOGP(DBSSGP, LOGL_NOTICE, "NSEI=%u/BVCI=%u Rejecting PDU "
|
||||
"type %u for unknown BVCI\n", msgb_nsei(msg), ns_bvci,
|
||||
|
@ -438,14 +452,22 @@ static int nsvc_signal_cb(unsigned int subsys, unsigned int signal,
|
|||
case S_NS_UNBLOCK:
|
||||
if (!nsvc_unblocked) {
|
||||
nsvc_unblocked = 1;
|
||||
LOGP(DPCU, LOGL_NOTICE, "NS-VC is unblocked.\n");
|
||||
bssgp_tx_bvc_reset(bctx, bctx->bvci,
|
||||
BSSGP_CAUSE_PROTO_ERR_UNSPEC);
|
||||
LOGP(DPCU, LOGL_NOTICE, "NS-VC %d is unblocked.\n",
|
||||
nsvc);
|
||||
bvc_sig_reset = 0;
|
||||
bvc_reset = 0;
|
||||
bvc_unblocked = 0;
|
||||
bvc_timeout(NULL);
|
||||
}
|
||||
break;
|
||||
case S_NS_BLOCK:
|
||||
if (nsvc_unblocked) {
|
||||
nsvc_unblocked = 0;
|
||||
if (osmo_timer_pending(&bvc_timer))
|
||||
osmo_timer_del(&bvc_timer);
|
||||
bvc_sig_reset = 0;
|
||||
bvc_reset = 0;
|
||||
bvc_unblocked = 0;
|
||||
LOGP(DPCU, LOGL_NOTICE, "NS-VC is blocked.\n");
|
||||
}
|
||||
break;
|
||||
|
@ -454,6 +476,52 @@ static int nsvc_signal_cb(unsigned int subsys, unsigned int signal,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int gprs_bssgp_tx_fc_bvc(void)
|
||||
{
|
||||
if (!bctx) {
|
||||
LOGP(DBSSGP, LOGL_ERROR, "No bctx\n");
|
||||
return -EIO;
|
||||
}
|
||||
/* FIXME: use real values */
|
||||
return bssgp_tx_fc_bvc(bctx, 1, 6553500, 819100, 50000, 50000,
|
||||
NULL, NULL);
|
||||
// return bssgp_tx_fc_bvc(bctx, 1, 84000, 25000, 48000, 45000,
|
||||
// NULL, NULL);
|
||||
}
|
||||
|
||||
static void bvc_timeout(void *_priv)
|
||||
{
|
||||
struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
|
||||
|
||||
if (!bvc_sig_reset) {
|
||||
LOGP(DBSSGP, LOGL_INFO, "Sending reset on BVCI 0\n");
|
||||
bssgp_tx_bvc_reset(bctx, 0, BSSGP_CAUSE_OML_INTERV);
|
||||
osmo_timer_schedule(&bvc_timer, 1, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bvc_reset) {
|
||||
LOGP(DBSSGP, LOGL_INFO, "Sending reset on BVCI %d\n",
|
||||
bctx->bvci);
|
||||
bssgp_tx_bvc_reset(bctx, bctx->bvci, BSSGP_CAUSE_OML_INTERV);
|
||||
osmo_timer_schedule(&bvc_timer, 1, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bvc_unblocked) {
|
||||
LOGP(DBSSGP, LOGL_INFO, "Sending unblock on BVCI %d\n",
|
||||
bctx->bvci);
|
||||
bssgp_tx_bvc_unblock(bctx);
|
||||
osmo_timer_schedule(&bvc_timer, 1, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
LOGP(DBSSGP, LOGL_DEBUG, "Sending flow control info on BVCI %d\n",
|
||||
bctx->bvci);
|
||||
gprs_bssgp_tx_fc_bvc();
|
||||
osmo_timer_schedule(&bvc_timer, bts->fc_interval, 0);
|
||||
}
|
||||
|
||||
/* create BSSGP/NS layer instances */
|
||||
int gprs_bssgp_create(uint32_t sgsn_ip, uint16_t sgsn_port, uint16_t nsei,
|
||||
uint16_t nsvci, uint16_t bvci, uint16_t mcc, uint16_t mnc, uint16_t lac,
|
||||
|
@ -501,6 +569,9 @@ int gprs_bssgp_create(uint32_t sgsn_ip, uint16_t sgsn_port, uint16_t nsei,
|
|||
|
||||
// bssgp_tx_bvc_reset(bctx, bctx->bvci, BSSGP_CAUSE_PROTO_ERR_UNSPEC);
|
||||
|
||||
bvc_timer.cb = bvc_timeout;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -509,6 +580,9 @@ void gprs_bssgp_destroy(void)
|
|||
if (!bssgp_nsi)
|
||||
return;
|
||||
|
||||
if (osmo_timer_pending(&bvc_timer))
|
||||
osmo_timer_del(&bvc_timer);
|
||||
|
||||
osmo_signal_unregister_handler(SS_L_NS, nsvc_signal_cb, NULL);
|
||||
|
||||
nsvc = NULL;
|
||||
|
|
|
@ -62,6 +62,7 @@ struct gprs_rlcmac_trx {
|
|||
};
|
||||
|
||||
struct gprs_rlcmac_bts {
|
||||
uint8_t fc_interval;
|
||||
uint8_t cs1;
|
||||
uint8_t cs2;
|
||||
uint8_t cs3;
|
||||
|
|
|
@ -142,6 +142,7 @@ int main(int argc, char *argv[])
|
|||
if (!gprs_rlcmac_bts)
|
||||
return -ENOMEM;
|
||||
gprs_rlcmac_bts->initial_cs = 1;
|
||||
bts->fc_interval = 1;
|
||||
bts->initial_cs = 1;
|
||||
bts->cs1 = 1;
|
||||
bts->t3142 = 20;
|
||||
|
|
|
@ -79,6 +79,8 @@ static int config_write_pcu(struct vty *vty)
|
|||
struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
|
||||
|
||||
vty_out(vty, "pcu%s", VTY_NEWLINE);
|
||||
vty_out(vty, " flow-control-interval %d%s", bts->fc_interval,
|
||||
VTY_NEWLINE);
|
||||
if (bts->force_cs)
|
||||
vty_out(vty, " cs %d%s", bts->initial_cs, VTY_NEWLINE);
|
||||
if (bts->force_llc_lifetime == 0xffff)
|
||||
|
@ -106,6 +108,19 @@ DEFUN(cfg_pcu,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_pcu_fc_interval,
|
||||
cfg_pcu_fc_interval_cmd,
|
||||
"flow-control-interval <1..10>",
|
||||
"Interval between sending subsequent Flow Control PDUs\n"
|
||||
"Tiem in seconds\n")
|
||||
{
|
||||
struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
|
||||
|
||||
bts->fc_interval = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_pcu_cs,
|
||||
cfg_pcu_cs_cmd,
|
||||
"cs <1-4>",
|
||||
|
@ -242,6 +257,7 @@ int pcu_vty_init(const struct log_info *cat)
|
|||
install_node(&pcu_node, config_write_pcu);
|
||||
install_element(CONFIG_NODE, &cfg_pcu_cmd);
|
||||
install_default(PCU_NODE);
|
||||
install_element(PCU_NODE, &cfg_pcu_no_two_phase_cmd);
|
||||
install_element(PCU_NODE, &cfg_pcu_cs_cmd);
|
||||
install_element(PCU_NODE, &cfg_pcu_no_cs_cmd);
|
||||
install_element(PCU_NODE, &cfg_pcu_queue_lifetime_cmd);
|
||||
|
@ -249,7 +265,7 @@ int pcu_vty_init(const struct log_info *cat)
|
|||
install_element(PCU_NODE, &cfg_pcu_no_queue_lifetime_cmd);
|
||||
install_element(PCU_NODE, &cfg_pcu_alloc_cmd);
|
||||
install_element(PCU_NODE, &cfg_pcu_two_phase_cmd);
|
||||
install_element(PCU_NODE, &cfg_pcu_no_two_phase_cmd);
|
||||
install_element(PCU_NODE, &cfg_pcu_fc_interval_cmd);
|
||||
install_element(PCU_NODE, &ournode_end_cmd);
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue