mirror of https://gerrit.osmocom.org/libosmocore
bssgp_bvc_fsm: Add basic BVC flow control rx/tx support
The FSM doesn't actually implement the flow control logic, it only decodes / dispatches and encodes messages. Related: OS#4891 Change-Id: Ie59be6761177c43456898be9148727f15861a622
This commit is contained in:
parent
4394bb9629
commit
1fcfce86cb
|
@ -4,6 +4,7 @@
|
||||||
struct gprs_ns2_inst;
|
struct gprs_ns2_inst;
|
||||||
struct osmo_fsm_inst;
|
struct osmo_fsm_inst;
|
||||||
struct gprs_ra_id;
|
struct gprs_ra_id;
|
||||||
|
struct bssgp2_flow_ctrl;
|
||||||
|
|
||||||
enum bssp_ptp_bvc_fsm_state {
|
enum bssp_ptp_bvc_fsm_state {
|
||||||
BSSGP_BVCFSM_S_NULL,
|
BSSGP_BVCFSM_S_NULL,
|
||||||
|
@ -22,10 +23,13 @@ enum bssgp_ptp_bvc_fsm_event {
|
||||||
BSSGP_BVCFSM_E_RX_UNBLOCK_ACK,
|
BSSGP_BVCFSM_E_RX_UNBLOCK_ACK,
|
||||||
BSSGP_BVCFSM_E_RX_RESET,
|
BSSGP_BVCFSM_E_RX_RESET,
|
||||||
BSSGP_BVCFSM_E_RX_RESET_ACK,
|
BSSGP_BVCFSM_E_RX_RESET_ACK,
|
||||||
|
BSSGP_BVCFSM_E_RX_FC_BVC,
|
||||||
|
BSSGP_BVCFSM_E_RX_FC_BVC_ACK,
|
||||||
/* Requests of the local user */
|
/* Requests of the local user */
|
||||||
BSSGP_BVCFSM_E_REQ_BLOCK, /* data: uint8_t *cause */
|
BSSGP_BVCFSM_E_REQ_BLOCK, /* data: uint8_t *cause */
|
||||||
BSSGP_BVCFSM_E_REQ_UNBLOCK,
|
BSSGP_BVCFSM_E_REQ_UNBLOCK,
|
||||||
BSSGP_BVCFSM_E_REQ_RESET, /* data: uint8_t *cause */
|
BSSGP_BVCFSM_E_REQ_RESET, /* data: uint8_t *cause */
|
||||||
|
BSSGP_BVCFSM_E_REQ_FC_BVC, /* data: struct bssgp2_flow_ctrl */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bssgp_bvc_fsm_ops {
|
struct bssgp_bvc_fsm_ops {
|
||||||
|
@ -35,6 +39,7 @@ struct bssgp_bvc_fsm_ops {
|
||||||
/* call-back notifying the user of a BVC-RESET event */
|
/* call-back notifying the user of a BVC-RESET event */
|
||||||
void (*reset_notification)(uint16_t nsei, uint16_t bvci, const struct gprs_ra_id *ra_id,
|
void (*reset_notification)(uint16_t nsei, uint16_t bvci, const struct gprs_ra_id *ra_id,
|
||||||
uint16_t cell_id, uint8_t cause, void *priv);
|
uint16_t cell_id, uint8_t cause, void *priv);
|
||||||
|
void (*rx_fc_bvc)(uint16_t nsei, uint16_t bvci, const struct bssgp2_flow_ctrl *fc, void *priv);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct osmo_fsm_inst *
|
struct osmo_fsm_inst *
|
||||||
|
|
|
@ -101,9 +101,12 @@ static const struct value_string ptp_bvc_event_names[] = {
|
||||||
{ BSSGP_BVCFSM_E_RX_UNBLOCK_ACK, "RX-BVC-UNBLOCK-ACK" },
|
{ BSSGP_BVCFSM_E_RX_UNBLOCK_ACK, "RX-BVC-UNBLOCK-ACK" },
|
||||||
{ BSSGP_BVCFSM_E_RX_RESET, "RX-BVC-RESET" },
|
{ BSSGP_BVCFSM_E_RX_RESET, "RX-BVC-RESET" },
|
||||||
{ BSSGP_BVCFSM_E_RX_RESET_ACK, "RX-BVC-RESET-ACK" },
|
{ BSSGP_BVCFSM_E_RX_RESET_ACK, "RX-BVC-RESET-ACK" },
|
||||||
|
{ BSSGP_BVCFSM_E_RX_FC_BVC, "RX-FLOW-CONTROL-BVC" },
|
||||||
|
{ BSSGP_BVCFSM_E_RX_FC_BVC_ACK, "RX-FLOW-CONTROL-BVC-ACK" },
|
||||||
{ BSSGP_BVCFSM_E_REQ_BLOCK, "REQ-BLOCK" },
|
{ BSSGP_BVCFSM_E_REQ_BLOCK, "REQ-BLOCK" },
|
||||||
{ BSSGP_BVCFSM_E_REQ_UNBLOCK, "REQ-UNBLOCK" },
|
{ BSSGP_BVCFSM_E_REQ_UNBLOCK, "REQ-UNBLOCK" },
|
||||||
{ BSSGP_BVCFSM_E_REQ_RESET, "REQ-RESET" },
|
{ BSSGP_BVCFSM_E_REQ_RESET, "REQ-RESET" },
|
||||||
|
{ BSSGP_BVCFSM_E_REQ_FC_BVC, "REQ-FLOW-CONTROL-BVC" },
|
||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -132,6 +135,8 @@ struct bvc_fsm_priv {
|
||||||
uint32_t advertised;
|
uint32_t advertised;
|
||||||
uint32_t received;
|
uint32_t received;
|
||||||
uint32_t negotiated;
|
uint32_t negotiated;
|
||||||
|
/* only used if BSSGP_XFEAT_GBIT is negotiated */
|
||||||
|
enum bssgp_fc_granularity fc_granularity;
|
||||||
} features;
|
} features;
|
||||||
|
|
||||||
/* Cell Identification used by BSS when
|
/* Cell Identification used by BSS when
|
||||||
|
@ -391,9 +396,11 @@ static void bssgp_bvc_fsm_wait_reset_ack(struct osmo_fsm_inst *fi, uint32_t even
|
||||||
|
|
||||||
static void bssgp_bvc_fsm_unblocked(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
static void bssgp_bvc_fsm_unblocked(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
{
|
{
|
||||||
|
struct bssgp2_flow_ctrl rx_fc, *tx_fc;
|
||||||
struct bvc_fsm_priv *bfp = fi->priv;
|
struct bvc_fsm_priv *bfp = fi->priv;
|
||||||
const struct tlv_parsed *tp = NULL;
|
const struct tlv_parsed *tp = NULL;
|
||||||
struct msgb *rx = NULL, *tx;
|
struct msgb *rx = NULL, *tx;
|
||||||
|
int rc;
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case BSSGP_BVCFSM_E_RX_UNBLOCK_ACK:
|
case BSSGP_BVCFSM_E_RX_UNBLOCK_ACK:
|
||||||
|
@ -459,6 +466,33 @@ static void bssgp_bvc_fsm_unblocked(struct osmo_fsm_inst *fi, uint32_t event, vo
|
||||||
fi_tx_sig(fi, tx);
|
fi_tx_sig(fi, tx);
|
||||||
osmo_fsm_inst_state_chg(fi, BSSGP_BVCFSM_S_BLOCKED, T1_SECS, T1);
|
osmo_fsm_inst_state_chg(fi, BSSGP_BVCFSM_S_BLOCKED, T1_SECS, T1);
|
||||||
break;
|
break;
|
||||||
|
case BSSGP_BVCFSM_E_RX_FC_BVC:
|
||||||
|
rx = data;
|
||||||
|
tp = (const struct tlv_parsed *) msgb_bcid(rx);
|
||||||
|
/* we assume osmo_tlv_prot_* has been used before calling here to ensure this */
|
||||||
|
OSMO_ASSERT(bfp->role_sgsn);
|
||||||
|
rc = bssgp2_dec_fc_bvc(&rx_fc, tp);
|
||||||
|
if (rc < 0) {
|
||||||
|
_tx_status(fi, BSSGP_CAUSE_SEM_INCORR_PDU, rx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (bfp->ops->rx_fc_bvc)
|
||||||
|
bfp->ops->rx_fc_bvc(bfp->nsei, bfp->bvci, &rx_fc, bfp->ops_priv);
|
||||||
|
tx = bssgp2_enc_fc_bvc_ack(rx_fc.tag);
|
||||||
|
fi_tx_ptp(fi, tx);
|
||||||
|
break;
|
||||||
|
case BSSGP_BVCFSM_E_RX_FC_BVC_ACK:
|
||||||
|
rx = data;
|
||||||
|
tp = (const struct tlv_parsed *) msgb_bcid(rx);
|
||||||
|
/* we assume osmo_tlv_prot_* has been used before calling here to ensure this */
|
||||||
|
OSMO_ASSERT(!bfp->role_sgsn);
|
||||||
|
break;
|
||||||
|
case BSSGP_BVCFSM_E_REQ_FC_BVC:
|
||||||
|
tx_fc = data;
|
||||||
|
tx = bssgp2_enc_fc_bvc(tx_fc, bfp->features.negotiated & (BSSGP_XFEAT_GBIT << 8) ?
|
||||||
|
&bfp->features.fc_granularity : NULL);
|
||||||
|
fi_tx_ptp(fi, tx);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,7 +614,10 @@ static const struct osmo_fsm_state bssgp_bvc_fsm_states[] = {
|
||||||
.in_event_mask = S(BSSGP_BVCFSM_E_RX_BLOCK) |
|
.in_event_mask = S(BSSGP_BVCFSM_E_RX_BLOCK) |
|
||||||
S(BSSGP_BVCFSM_E_RX_UNBLOCK) |
|
S(BSSGP_BVCFSM_E_RX_UNBLOCK) |
|
||||||
S(BSSGP_BVCFSM_E_RX_UNBLOCK_ACK) |
|
S(BSSGP_BVCFSM_E_RX_UNBLOCK_ACK) |
|
||||||
S(BSSGP_BVCFSM_E_REQ_BLOCK),
|
S(BSSGP_BVCFSM_E_REQ_BLOCK) |
|
||||||
|
S(BSSGP_BVCFSM_E_RX_FC_BVC) |
|
||||||
|
S(BSSGP_BVCFSM_E_RX_FC_BVC_ACK) |
|
||||||
|
S(BSSGP_BVCFSM_E_REQ_FC_BVC),
|
||||||
.out_state_mask = S(BSSGP_BVCFSM_S_BLOCKED) |
|
.out_state_mask = S(BSSGP_BVCFSM_S_BLOCKED) |
|
||||||
S(BSSGP_BVCFSM_S_WAIT_RESET_ACK) |
|
S(BSSGP_BVCFSM_S_WAIT_RESET_ACK) |
|
||||||
S(BSSGP_BVCFSM_S_UNBLOCKED),
|
S(BSSGP_BVCFSM_S_UNBLOCKED),
|
||||||
|
|
|
@ -437,7 +437,7 @@ struct msgb *bssgp2_enc_fc_ms_ack(uint32_t tlli, uint8_t tag)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
bgph = (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
|
bgph = (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
|
||||||
bgph->pdu_type = BSSGP_PDUT_FLOW_CONTROL_BVC_ACK;
|
bgph->pdu_type = BSSGP_PDUT_FLOW_CONTROL_MS_ACK;
|
||||||
|
|
||||||
msgb_tvlv_put_32be(msg, BSSGP_IE_TLLI, tlli);
|
msgb_tvlv_put_32be(msg, BSSGP_IE_TLLI, tlli);
|
||||||
msgb_tvlv_put(msg, BSSGP_IE_TAG, 1, &tag);
|
msgb_tvlv_put(msg, BSSGP_IE_TAG, 1, &tag);
|
||||||
|
|
Loading…
Reference in New Issue