mirror of https://gerrit.osmocom.org/libosmocore
[gprs] NS: Add signals in the event of BLOCK/UNBLOCK/RESET
The signals will be sent upon reception of NS-BLOCK/UNBLOCK/RESET PDUs We also export functions to generate/send BLOCK/UNBLOCK and RESET.
This commit is contained in:
parent
b8a6a83be6
commit
834f26d62c
|
@ -167,6 +167,9 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
|
||||||
/* main function for higher layers (BSSGP) to send NS messages */
|
/* main function for higher layers (BSSGP) to send NS messages */
|
||||||
int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg);
|
int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg);
|
||||||
|
|
||||||
|
int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause);
|
||||||
|
int gprs_ns_tx_block(struct gprs_nsvc *nsvc, uint8_t cause);
|
||||||
|
int gprs_ns_tx_unblock(struct gprs_nsvc *nsvc);
|
||||||
|
|
||||||
/* Listen for incoming GPRS packets */
|
/* Listen for incoming GPRS packets */
|
||||||
int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port);
|
int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port);
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
#include <osmocore/talloc.h>
|
#include <osmocore/talloc.h>
|
||||||
#include <osmocore/select.h>
|
#include <osmocore/select.h>
|
||||||
#include <openbsc/debug.h>
|
#include <openbsc/debug.h>
|
||||||
|
#include <openbsc/signal.h>
|
||||||
#include <openbsc/gprs_ns.h>
|
#include <openbsc/gprs_ns.h>
|
||||||
#include <openbsc/gprs_bssgp.h>
|
#include <openbsc/gprs_bssgp.h>
|
||||||
|
|
||||||
|
@ -128,6 +129,17 @@ static struct gprs_nsvc *nsvc_create(struct gprs_ns_inst *nsi, uint16_t nsvci)
|
||||||
return nsvc;
|
return nsvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ns_dispatch_signal(struct nsvc *nsvc, unsigned int signal,
|
||||||
|
uint8_t cause)
|
||||||
|
{
|
||||||
|
struct ns_signal_data nssd;
|
||||||
|
|
||||||
|
nssd.nsvc = nsvc;
|
||||||
|
nssd.cause = cause;
|
||||||
|
|
||||||
|
dispatch_signal(SS_NS, signal, &nssd);
|
||||||
|
}
|
||||||
|
|
||||||
/* Section 10.3.2, Table 13 */
|
/* Section 10.3.2, Table 13 */
|
||||||
static const struct value_string ns_cause_str[] = {
|
static const struct value_string ns_cause_str[] = {
|
||||||
{ NS_CAUSE_TRANSIT_FAIL, "Transit network failure" },
|
{ NS_CAUSE_TRANSIT_FAIL, "Transit network failure" },
|
||||||
|
@ -183,7 +195,7 @@ static int gprs_ns_tx_simple(struct gprs_nsvc *nsvc, uint8_t pdu_type)
|
||||||
return gprs_ns_tx(nsvc, msg);
|
return gprs_ns_tx(nsvc, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause)
|
int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause)
|
||||||
{
|
{
|
||||||
struct msgb *msg = msgb_alloc(NS_ALLOC_SIZE, "GPRS/NS");
|
struct msgb *msg = msgb_alloc(NS_ALLOC_SIZE, "GPRS/NS");
|
||||||
struct gprs_ns_hdr *nsh;
|
struct gprs_ns_hdr *nsh;
|
||||||
|
@ -204,6 +216,32 @@ static int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int gprs_ns_tx_block(struct gprs_nsvc *nsvc, uint8_t cause)
|
||||||
|
{
|
||||||
|
struct msgb *msg = msgb_alloc(NS_ALLOC_SIZE, "GPRS/NS");
|
||||||
|
struct gprs_ns_hdr *nsh;
|
||||||
|
uint16_t nsvci = htons(nsvc->nsvci);
|
||||||
|
|
||||||
|
if (!msg)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* be conservative and mark it as blocked even now! */
|
||||||
|
nsvc->state |= NSE_S_BLOCKED;
|
||||||
|
|
||||||
|
nsh = (struct gprs_ns_hdr *) msgb_put(msg, sizeof(*nsh));
|
||||||
|
nsh->pdu_type = NS_PDUT_BLOCK;
|
||||||
|
|
||||||
|
msgb_tvlv_put(msg, NS_IE_CAUSE, 1, &cause);
|
||||||
|
msgb_tvlv_put(msg, NS_IE_VCI, 2, (uint8_t *) &nsvci);
|
||||||
|
|
||||||
|
return gprs_ns_tx(nsvc, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int gprs_ns_tx_unblock(struct gprs_nsvc *nsvc)
|
||||||
|
{
|
||||||
|
return gprs_ns_tx_simple(nsvc, NS_PDUT_UNBLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
#define NS_ALIVE_RETRIES 10 /* after 3 failed retransmit we declare BTS as dead */
|
#define NS_ALIVE_RETRIES 10 /* after 3 failed retransmit we declare BTS as dead */
|
||||||
|
|
||||||
static const uint8_t timer_mode_tout[_NSVC_TIMER_NR] = {
|
static const uint8_t timer_mode_tout[_NSVC_TIMER_NR] = {
|
||||||
|
@ -393,9 +431,41 @@ static int gprs_ns_rx_reset(struct gprs_nsvc *nsvc, struct msgb *msg)
|
||||||
/* start the test procedure */
|
/* start the test procedure */
|
||||||
nsvc_start_timer(nsvc, NSVC_TIMER_TNS_ALIVE);
|
nsvc_start_timer(nsvc, NSVC_TIMER_TNS_ALIVE);
|
||||||
|
|
||||||
|
/* inform interested parties about the fact that this NSVC
|
||||||
|
* has received RESET */
|
||||||
|
ns_dispatch_signal(nsvc, S_NS_RESET, cause);
|
||||||
|
|
||||||
return gprs_ns_tx_reset_ack(nsvc);
|
return gprs_ns_tx_reset_ack(nsvc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int gprs_ns_rx_block(struct gprs_nsvc *nsvc, struct msgb *msg)
|
||||||
|
{
|
||||||
|
struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h;
|
||||||
|
struct tlv_parsed tp;
|
||||||
|
uint8_t *cause;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
DEBUGP(DNS, "NSEI=%u Rx NS BLOCK\n", nsvc->nsei);
|
||||||
|
|
||||||
|
nsvc->state |= NSE_S_BLOCKED;
|
||||||
|
|
||||||
|
rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data, msgb_l2len(msg), 0, 0);
|
||||||
|
|
||||||
|
if (!TLVP_PRESENT(&tp, NS_IE_CAUSE) ||
|
||||||
|
!TLVP_PRESENT(&tp, NS_IE_VCI)) {
|
||||||
|
/* FIXME: respond with NS_CAUSE_MISSING_ESSENT_IE */
|
||||||
|
LOGP(DNS, LOGL_ERROR, "NS RESET Missing mandatory IE\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cause = (uint8_t *) TLVP_VAL(&tp, NS_IE_CAUSE);
|
||||||
|
//nsvci = (uint16_t *) TLVP_VAL(&tp, NS_IE_VCI);
|
||||||
|
|
||||||
|
ns_dispatch_signal(nsvc, S_NS_BLOCK, cause);
|
||||||
|
|
||||||
|
return gprs_ns_tx_simple(nsvc, NS_PDUT_BLOCK_ACK);
|
||||||
|
}
|
||||||
|
|
||||||
/* main entry point, here incoming NS frames enter */
|
/* main entry point, here incoming NS frames enter */
|
||||||
int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
|
int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
|
||||||
struct sockaddr_in *saddr)
|
struct sockaddr_in *saddr)
|
||||||
|
@ -467,6 +537,7 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
|
||||||
/* Section 7.2: unblocking procedure */
|
/* Section 7.2: unblocking procedure */
|
||||||
DEBUGP(DNS, "NSEI=%u Rx NS UNBLOCK\n", nsvc->nsei);
|
DEBUGP(DNS, "NSEI=%u Rx NS UNBLOCK\n", nsvc->nsei);
|
||||||
nsvc->state &= ~NSE_S_BLOCKED;
|
nsvc->state &= ~NSE_S_BLOCKED;
|
||||||
|
ns_dispatch_signal(nsvc, S_NS_UNBLOCK, 0);
|
||||||
rc = gprs_ns_tx_simple(nsvc, NS_PDUT_UNBLOCK_ACK);
|
rc = gprs_ns_tx_simple(nsvc, NS_PDUT_UNBLOCK_ACK);
|
||||||
break;
|
break;
|
||||||
case NS_PDUT_UNBLOCK_ACK:
|
case NS_PDUT_UNBLOCK_ACK:
|
||||||
|
@ -477,9 +548,7 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
|
||||||
nsvc->state = NSE_S_ALIVE;
|
nsvc->state = NSE_S_ALIVE;
|
||||||
break;
|
break;
|
||||||
case NS_PDUT_BLOCK:
|
case NS_PDUT_BLOCK:
|
||||||
DEBUGP(DNS, "NSEI=%u Rx NS BLOCK\n", nsvc->nsei);
|
rc = gprs_ns_rx_block(nsvc, msg);
|
||||||
nsvc->state |= NSE_S_BLOCKED;
|
|
||||||
rc = gprs_ns_tx_simple(nsvc, NS_PDUT_UNBLOCK_ACK);
|
|
||||||
break;
|
break;
|
||||||
case NS_PDUT_BLOCK_ACK:
|
case NS_PDUT_BLOCK_ACK:
|
||||||
DEBUGP(DNS, "NSEI=%u Rx NS BLOCK ACK\n", nsvc->nsei);
|
DEBUGP(DNS, "NSEI=%u Rx NS BLOCK ACK\n", nsvc->nsei);
|
||||||
|
|
Loading…
Reference in New Issue