Completed implementation of V52_le_lcp_fsm.c

This commit is contained in:
Andreas Eversberg 2022-12-23 21:49:52 +01:00
parent 6a4a58d4b1
commit 852990f2e3
4 changed files with 948 additions and 612 deletions

View File

@ -15,6 +15,7 @@ osmo_v5_le_SOURCES = logging.c \
v5x_le_ctrl_fsm.c \
v5x_le_port_fsm.c \
v5x_le_pstn_fsm.c \
v52_le_lcp_fsm.c \
v5x_le_provisioning.c \
v5x_le_management.c \
main.c

View File

@ -1,612 +0,0 @@
/* ITu-T G.965 Section 16.2 V5.2-interface Link control FSM - LE side */
#include "v5x_internal.h"
/* 16.2.4.2.2 */
enum v52_lcp_fsm_state {
V52_LCPFSM_S_LE01_NOP_LINK_FAILURE,
V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED,
V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED,
V52_LCPFSM_S_LE11_NOP_LOCAL_LINK_UNBLOCK,
V52_LCPFSM_S_LE12_NOP_REMOTE_LINK_UNBLOCK,
V52_LCPFSM_S_LE20_OP_OPERATIONAL,
V52_LCPFSM_S_LE21_OP_REMOTE_LINK_ID,
V52_LCPFSM_S_LE22_OP_LOCAL_LINK_ID,
};
enum v52_lcp_event {
V52_LCPFSM_E_MPH_AI, /* Activate Indication (L1 link operational) */
V52_LCPFSM_E_MPH_DI, /* Deactivate Indication (L1 link not operational) */
V52_LCPFSM_E_MDU_IDReq, /* Identification Request */
V52_LCPFSM_E_FE_IDAck,
V52_LCPFSM_E_MPH_IDI, /* Identification Indication */
V52_LCPFSM_E_MPH_EIg, /* Identification Failure */
V52_LCPFSM_E_FE_IDReq,
V52_LCPFSM_E_MDU_IDAck, /* Send Link ID ACK */
V52_LCPFSM_E_FE_IDRel,
V52_LCPFSM_E_MDU_IDRej, /* Link ID Reject */
V52_LCPFSM_E_FE_IDRej,
V52_LCPFSM_E_MDU_LUBR, /* Link Unblock Request */
V52_LCPFSM_E_MDU_LBI, /* Link Block Indication */
V52_LCPFSM_E_FE302, /* AN Initiated unblocking */
V52_LCPFSM_E_FE304, /* AN initiated link block */
V52_LCPFSM_E_FE305, /* deferred link block request */
V52_LCPFSM_E_FE306, /* non-deferred link block request */
};
static struct msgb *v52_enc_link_control(uint8_t link_id, enum v52_link_ctrl_func lcf)
{
struct v51_l3_hdr *l3h;
uint8_t lcf_enc = lcf;
struct msgb *msg = msgb_alloc_v5x();
if (!msg)
return NULL;
l3h = (struct v51_l3_hdr *) msgb_put(msg, sizeof(*l3h));
l3h->pdisc = V51_LCP_PDISC;
l3h->l3_addr = link_id
l3h->msg_type = V52_CTRL_MSGT_LCP_LINK_CTRL;
msgb_tlv_put(msg, V52_CTRL_IEI_LCP_LINK_CTRL_FUNCTION, 1, &lcf_enc);
return msg;
}
static struct msgb *v52_enc_link_control_ack(uint8_t link_id, enum v52_link_ctrl_func lcf)
{
struct v51_l3_hdr *l3h;
uint8_t lcf_enc = lcf;
struct msgb *msg = msgb_alloc_v5x();
if (!msg)
return NULL;
l3h = (struct v51_l3_hdr *) msgb_put(msg, sizeof(*l3h));
l3h->pdisc = V51_LCP_PDISC;
l3h->l3_addr = link_id;
l3h->msg_type = V52_CTRL_MSGT_LCP_LINK_CTRL_ACK;
msgb_tlv_put(msg, V52_CTRL_IEI_LCP_LINK_CTRL_FUNCTION, 1, &lcf_enc);
return msg;
}
static void lcp_fsm_le01_link_failure(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
/* TODO: Send MDU-LAI */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
break;
case V52_LCPFSM_E_MPH_DI:
/* ignore */
break;
case V52_LCPFSM_E_MDU_IDReq:
/* TODO: Send MDU-DI */
break;
case V52_LCPFSM_E_FE_IDReq:
/* TODO: Send FE303 */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_FE_IDRel:
case V52_LCPFSM_E_FE_IDRej:
/* ignore */
break;
case V52_LCPFSM_E_MDU_LUBR:
/* TODO: Send MDU-DI */
/* TODO: Send FE303 */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_MDU_LBI:
case V52_LCPFSM_E_FE302:
case V52_LCPFSM_E_FE305:
case V52_LCPFSM_E_FE306:
/* TODO: Send FE303 */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_FE304:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
break;
default:
OSMO_ASSERT(0);
}
}
static void lcp_fsm_le02_link_failure_blocked(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
/* TODO: Send MDU-LAI */
/* TODO: Send MDU-LBl */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_MPH_DI:
/* ignore */
break;
case V52_LCPFSM_E_MDU_IDReq:
/* TODO: Send MDU-DI */
break;
case V52_LCPFSM_E_FE_IDReq:
/* TODO: Send FE303 */
break;
case V52_LCPFSM_E_MDU_LUBR:
/* TODO: Send MDU-DI */
/* TODO: Send FE303 */
break;
case V52_LCPFSM_E_MDU_LBI:
case V52_LCPFSM_E_FE302:
case V52_LCPFSM_E_FE305:
case V52_LCPFSM_E_FE306:
/* TODO: Send FE303 */
break;
case V52_LCPFSM_E_FE304:
/* ignore */
break;
default:
OSMO_ASSERT(0);
}
}
static void lcp_fsm_le10_link_blocked(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
/* TODO: Send MDU-LAI */
break;
case V52_LCPFSM_E_MPH_DI:
/* TODO: Send MDU-DI */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_MDU_IDReq:
/* TODO: Send MDU-LBl */
break;
case V52_LCPFSM_E_FE_IDReq:
/* TODO: Send FE303 */
break;
case V52_LCPFSM_E_FE_IDRel:
case V52_LCPFSM_E_FE_IDRej:
/* ignore */
break;
case V52_LCPFSM_E_MDU_LUBR:
/* TODO: Send FE303 */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE11_NOP_LOCAL_LINK_UNBLOCK, 0, 0);
break;
case V52_LCPFSM_E_FE302:
/* TODO: Send MDL-LUBR */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE12_NOP_REMOTE_LINK_UNBLOCK, 0, 0);
break;
case V52_LCPFSM_E_MDU_LBI:
case V52_LCPFSM_E_FE305:
case V52_LCPFSM_E_FE306:
/* TODO: Send FE303 */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_FE304:
break;
default:
OSMO_ASSERT(0);
}
}
static void lcp_fsm_le11_local_link_unblock(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
/* ignore */
break;
case V52_LCPFSM_E_MPH_DI:
/* TODO: Send MDU-DI */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_MDU_IDReq:
/* TODO: Send MDU-LBl */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_FE_IDReq:
/* TODO: Send FE-IDRej */
break;
case V52_LCPFSM_E_FE_IDRel:
case V52_LCPFSM_E_FE_IDRej:
/* ignore */
break;
case V52_LCPFSM_E_MDU_LUBR:
/* TODO: Send FE301 */
break;
case V52_LCPFSM_E_MDU_LBI:
/* TODO: Send FE303 */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_FE302:
/* TODO: Send MDU-LUBl */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
break;
case V52_LCPFSM_E_FE304:
/* TODO: Send MDU-LBl */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_FE305:
case V52_LCPFSM_E_FE306:
/* TODO: Send FE303 */
/* TODO: Send MDU-LBl */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
break;
default:
OSMO_ASSERT(0);
}
}
static void lcp_fsm_le12_remote_link_unblock(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
/* ignore */
break;
case V52_LCPFSM_E_MPH_DI:
/* TODO: Send MDU-Dl */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_MDU_IDReq:
/* TODO: Send MDU-LUBR */
/* TODO: Send MDU-IDRej */
break;
case V52_LCPFSM_E_FE_IDReq:
/* TODO: Send FE-IDRej */
break;
case V52_LCPFSM_E_MDU_LUBR:
/* TODO: Send FE301 */
/* TODO: Send MDU-LUBl */
break;
case V52_LCPFSM_E_MDU_LBI:
/* TODO: Send FE303 */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
break;
case V52_LCPFSM_E_FE302:
/* TODO: Send MDU-LUBR */
break;
case V52_LCPFSM_E_FE304:
/* TODO: Send MDU-LBl */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_FE305:
case V52_LCPFSM_E_FE306:
/* TODO: Send FE303 */
/* TODO: Send MDU-LBl */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
break;
default:
OSMO_ASSERT(0);
}
}
static void lcp_fsm_le20_operational(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
/* ignore */
break;
case V52_LCPFSM_E_MPH_DI:
/* TODO: Send MDU-DI */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE01_NOP_LINK_FAILURE, 0, 0);
break;
case V52_LCPFSM_E_MDU_IDReq:
/* TODO: Send FE-IDReq */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE22_OP_LOCAL_LINK_ID, 0, 0);
break;
case V52_LCPFSM_E_FE_IDReq:
/* TODO: Send MDU-IDReq */
break;
case V52_LCPFSM_E_MDU_IDAck:
/* TODO: Send MPH-ID */
/* TODO: Send FE-IDAck */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE21_OP_REMOTE_LINK_ID, 0, 0);
break;
case V52_LCPFSM_E_MDU_IDRej:
/* TODO: Send FE-IDRej */
break;
case V52_LCPFSM_E_MDU_LUBR:
/* TODO: Send FE301 */
break;
case V52_LCPFSM_E_MDU_LBI:
/* TODO: Send FE303 */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_FE302:
/* TODO: Send MDU-LUBI */
break;
case V52_LCPFSM_E_FE304:
/* TODO: Send MDU-LBI */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_FE305:
/* TODO: Send MDU-LBR */
break;
case V52_LCPFSM_E_FE306:
/* TODO: Send MDU-LBRN */
break;
default:
OSMO_ASSERT(0);
}
}
static void lcp_fsm_le21_op_remote_link_id(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
/* ignore */
break;
case V52_LCPFSM_E_MPH_DI:
/* TODO: Send MDU-DI */
/* TODO: Send MPH-NOR */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE01_NOP_LINK_FAILURE, 0, 0);
break;
case V52_LCPFSM_E_MDU_IDReq:
/* TODO: Send MDU-IDRej */
break;
case V52_LCPFSM_E_MDU_IDAck:
/* ignore */
break;
case V52_LCPFSM_E_FE_IDRel:
/* TODO: Send MDU-IDRel */
/* TODO: Sen MPH-NOR */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
break;
case V52_LCPFSM_E_MDU_IDRej:
/* TODO: Send FE-IDRej */
/* TODO: Sen MPH-NOR */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
break;
case V52_LCPFSM_E_MDU_LUBR:
/* TODO: Send FE301 */
/* TODO: Sen MPH-NOR */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
break;
case V52_LCPFSM_E_MDU_LBI:
/* TODO: Send FE303 */
/* TODO: Sen MPH-NOR */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_FE302:
/* TODO: Send MDU-IDRel */
/* TODO: Send MDU-LUBI */
/* TODO: Sen MPH-NOR */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
break;
case V52_LCPFSM_E_FE304:
/* TODO: Send MDU-LBI */
/* TODO: Sen MPH-NOR */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_FE305:
/* TODO: Send MDU-LBR */
break;
case V52_LCPFSM_E_FE306:
/* TODO: Send MDU-LBRN */
break;
default:
OSMO_ASSERT(0);
}
}
static void lcp_fsm_le22_op_local_link_id(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
/* ignore */
break;
case V52_LCPFSM_E_MPH_DI:
/* TODO: Send MDU-DI */
/* TODO: Send FE-IdRel */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE01_NOP_LINK_FAILURE, 0, 0);
break;
case V52_LCPFSM_E_MDU_IDReq:
/* ignore */
break;
case V52_LCPFSM_E_MDU_IDAck:
/* TODO: Send MPH-IDR */
break;
case V52_LCPFSM_E_MPH_IDI:
/* TODO: Send MDU-AI */
/* TODO: Send FE-IDRel */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
break;
case V52_LCPFSM_E_MPH_EIg:
/* TODO: Send FE-IDRel */
/* TODO: Send MDU-ELg */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
break;
case V52_LCPFSM_E_FE_IDRej:
/* TODO: Send MDU-IDRej */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
break;
case V52_LCPFSM_E_MDU_LUBR:
/* TODO: Send FE301 */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
break;
case V52_LCPFSM_E_MDU_LBI:
/* TODO: Send FE303 */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_FE302:
/* TODO: Send MDU-IDRej */
/* TODO: Send MDU-LUBI */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
break;
case V52_LCPFSM_E_FE304:
/* TODO: Send MDU-LBI */
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
break;
case V52_LCPFSM_E_FE305:
/* TODO: Send MDU-LBR */
break;
case V52_LCPFSM_E_FE306:
/* TODO: Send MDU-LBRN */
break;
default:
OSMO_ASSERT(0);
}
}
/* Table 17G.965 */
static const struct osmo_fsm_state v52_lcp_le_fsm_states[] = {
[V52_LCPFSM_S_LE01_NOP_LINK_FAILURE] = {
.name = "LE0.1_LINK_FAILURE",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_FE_IDRel) |
S(V52_LCPFSM_E_FE_IDRej) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE20_OP_OPERATIONAL) |
S(V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED),
.action = lcp_fsm_le01_link_failure,
},
[V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED] = {
.name = "LE0.2_LINK_FAILURE_AND_BLOCKED",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED),
.action = lcp_fsm_le02_link_failure_blocked,
},
[V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED] = {
.name = "LE1.0_NOP_LINK_BLOCKED",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_FE_IDRel) |
S(V52_LCPFSM_E_FE_IDRej) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED) |
S(V52_LCPFSM_S_LE11_NOP_LOCAL_LINK_UNBLOCK) |
S(V52_LCPFSM_S_LE21_OP_REMOTE_LINK_ID),
.action = lcp_fsm_le10_link_blocked,
},
[V52_LCPFSM_S_LE11_NOP_LOCAL_LINK_UNBLOCK] = {
.name = "LE1.1_NOP_LOCAL_LINK_UNBLOCK",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_FE_IDRel) |
S(V52_LCPFSM_E_FE_IDRej) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED) |
S(V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED) |
S(V52_LCPFSM_S_LE20_OP_OPERATIONAL),
.action = lcp_fsm_le11_local_link_unblock,
},
[V52_LCPFSM_S_LE12_NOP_REMOTE_LINK_UNBLOCK] = {
.name = "LE1.2_NOP_REMOTE_LINK_UNBLOCK",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED) |
S(V52_LCPFSM_S_LE20_OP_OPERATIONAL) |
S(V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED),
.action = lcp_fsm_le12_remote_link_unblock,
},
[V52_LCPFSM_S_LE20_OP_OPERATIONAL] = {
.name = "LE2.0_OP_OPERATIONAL",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_MDU_IDAck) |
S(V52_LCPFSM_E_MDU_IDRej) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE01_NOP_LINK_FAILURE) |
S(V52_LCPFSM_S_LE22_OP_LOCAL_LINK_ID) |
S(V52_LCPFSM_S_LE21_OP_REMOTE_LINK_ID) |
S(V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED),
.action = lcp_fsm_le20_operational,
},
[V52_LCPFSM_S_LE21_OP_REMOTE_LINK_ID] = {
.name = "LE2.1_OP_REMOTE_LINK_ID",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_MDU_IDAck) |
S(V52_LCPFSM_E_MDU_IDRel) |
S(V52_LCPFSM_E_MDU_IDRej) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE01_NOP_LINK_FAILURE) |
S(V52_LCPFSM_S_LE20_OP_OPERATIONAL) |
S(V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED),
.action = lcp_fsm_le21_op_remote_link_id,
},
[V52_LCPFSM_S_LE22_OP_LOCAL_LINK_ID] = {
.name = "LE2.2_OP_LOCAL_LINK_ID",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_MDU_IDAck) |
S(V52_LCPFSM_E_MPH_IDI) |
S(V52_LCPFSM_E_MPH_EIg) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE01_NOP_LINK_FAILURE) |
S(V52_LCPFSM_S_LE20_OP_OPERATIONAL) |
S(V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED),
.action =lcp_fsm_le22_op_local_link_id,
},
};
struct osmo_fsm v52_lcp_le_fsm = {
.name = "V52_LCP_LE",
.states = v52_lcp_le_fsm_states,
.num_states = ARRAY_SIZE(v52_lcp_le_fsm_states),
.timer_cb = NULL,
.log_subsys = 0,
.event_names = v52_lcp_le_fsm_event_names,
};

938
src/v52_le_lcp_fsm.c Normal file
View File

@ -0,0 +1,938 @@
/* ITu-T G.965 Section 16.2 V5.2-interface Link control FSM - LE side */
/* (C) 2021 by Harald Welte <laforge@gnumonks.org>
* (C) 2022 by Andreas Eversberg <jolly@eversberg.eu>
*
* All Rights Reserved
*
* SPDX-License-Identifier: GPL-2.0+
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
/***********************************************************************/
/* internal data structures */
/***********************************************************************/
#include <unistd.h>
#include <stdint.h>
#include <errno.h>
#include <osmocom/core/utils.h>
#include "v5x_internal.h"
#include "v5x_protocol.h"
#include "layer1.h"
#include "v5x_l1_fsm.h"
#include "v5x_le_ctrl_fsm.h"
#include "v5x_le_management.h"
#include "v52_le_lcp_fsm.h"
#include "logging.h"
#define S(x) (1 << (x))
/***********************************************************************/
/* state names, event names, primitives, ... */
/***********************************************************************/
/* 16.2.4.2.2 */
enum v52_lcp_fsm_state {
V52_LCPFSM_S_LE01_NOP_LINK_FAILURE,
V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED,
V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED,
V52_LCPFSM_S_LE11_NOP_LOCAL_LINK_UNBLOCK,
V52_LCPFSM_S_LE12_NOP_REMOTE_LINK_UNBLOCK,
V52_LCPFSM_S_LE20_OP_OPERATIONAL,
V52_LCPFSM_S_LE21_OP_REMOTE_LINK_ID,
V52_LCPFSM_S_LE22_OP_LOCAL_LINK_ID,
};
enum v52_lcp_fsm_event {
V52_LCPFSM_E_MPH_AI, /* Activate Indication (L1 link operational) */
V52_LCPFSM_E_MPH_DI, /* Deactivate Indication (L1 link not operational) */
V52_LCPFSM_E_MDU_IDReq, /* Identification Request */
V52_LCPFSM_E_FE_IDAck,
V52_LCPFSM_E_MPH_IDI, /* Identification Indication */
V52_LCPFSM_E_MPH_EIg, /* Identification Failure */
V52_LCPFSM_E_FE_IDReq,
V52_LCPFSM_E_MDU_IDAck, /* Send Link ID ACK */
V52_LCPFSM_E_FE_IDRel,
V52_LCPFSM_E_MDU_IDRej, /* Link ID Reject */
V52_LCPFSM_E_FE_IDRej,
V52_LCPFSM_E_MDU_LUBR, /* Link Unblock Request */
V52_LCPFSM_E_MDU_LBI, /* Link Block Indication */
V52_LCPFSM_E_FE302, /* AN Initiated unblocking */
V52_LCPFSM_E_FE304, /* AN initiated link block */
V52_LCPFSM_E_FE305, /* deferred link block request */
V52_LCPFSM_E_FE306, /* non-deferred link block request */
};
static const struct value_string v52_lcp_fsm_event_names[] = {
{ V52_LCPFSM_E_MPH_AI, "MPH-AI" },
{ V52_LCPFSM_E_MPH_DI, "MPH-DI" },
{ V52_LCPFSM_E_MDU_IDReq, "MDU-IDReq" },
{ V52_LCPFSM_E_FE_IDAck, "FE-IDAck" },
{ V52_LCPFSM_E_MPH_IDI, "MPH-IDI" },
{ V52_LCPFSM_E_MPH_EIg, "MPH-EIg" },
{ V52_LCPFSM_E_FE_IDReq, "FE-IDReq" },
{ V52_LCPFSM_E_MDU_IDAck, "MDU-IDack" },
{ V52_LCPFSM_E_FE_IDRel, "FE-IDRel" },
{ V52_LCPFSM_E_MDU_IDRej, "MDU-IDRej" },
{ V52_LCPFSM_E_FE_IDRej, "FE-IDRej" },
{ V52_LCPFSM_E_MDU_LUBR, "MDU-LUBR" },
{ V52_LCPFSM_E_MDU_LBI, "MDU-LBI" },
{ V52_LCPFSM_E_FE302, "FE302" },
{ V52_LCPFSM_E_FE304, "FE304" },
{ V52_LCPFSM_E_FE305, "FE305" },
{ V52_LCPFSM_E_FE306, "FE306" },
{ 0, NULL }
};
/***********************************************************************/
/* Messages to other layers */
/***********************************************************************/
/* send message to upper (management) layer */
static void rcv_mdu(struct osmo_fsm_inst *fi, enum v5x_mgmt_prim prim)
{
struct v5x_link *v5l = fi->priv;
v52_le_lcp_mdu_rcv(v5l, prim);
}
/* send message to lower (L1 FSM) layer */
static void snd_mph(struct osmo_fsm_inst *fi, enum v5x_mph_prim prim)
{
struct v5x_link *v5l = fi->priv;
v5x_l1_mph_snd(v5l, prim);
}
/* send message to lower (CTRL) layer */
void snd_fe(struct osmo_fsm_inst *fi, enum v52_link_ctrl_func lcf)
{
struct v5x_link *v5l = fi->priv;
v52_le_ctrl_link_snd(v5l, lcf);
}
/***********************************************************************/
/* LCP state FSM */
/***********************************************************************/
static void lcp_fsm_le01_link_failure(struct osmo_fsm_inst *fi, uint32_t event, void __attribute__((unused)) *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
/* Send MDU-LAI */
rcv_mdu(fi, MDU_LAI);
break;
case V52_LCPFSM_E_MPH_DI:
/* ignore */
break;
case V52_LCPFSM_E_MDU_IDReq:
/* Send MDU-DI */
rcv_mdu(fi, MDU_DI);
break;
case V52_LCPFSM_E_FE_IDReq:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
break;
case V52_LCPFSM_E_FE_IDRel:
case V52_LCPFSM_E_FE_IDRej:
/* ignore */
break;
case V52_LCPFSM_E_MDU_LUBR:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
/* Send MDU-DI */
rcv_mdu(fi, MDU_DI);
break;
case V52_LCPFSM_E_MDU_LBI:
case V52_LCPFSM_E_FE302:
case V52_LCPFSM_E_FE305:
case V52_LCPFSM_E_FE306:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
break;
case V52_LCPFSM_E_FE304:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
break;
default:
OSMO_ASSERT(0);
}
}
static void lcp_fsm_le02_link_failure_blocked(struct osmo_fsm_inst *fi, uint32_t event,
void __attribute__((unused)) *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
/* Send MDU-LBI */
rcv_mdu(fi, MDU_LBI);
/* Send MDU-LAI */
rcv_mdu(fi, MDU_LAI);
break;
case V52_LCPFSM_E_MPH_DI:
/* ignore */
break;
case V52_LCPFSM_E_MDU_IDReq:
/* Send MDU-DI */
rcv_mdu(fi, MDU_DI);
break;
case V52_LCPFSM_E_FE_IDReq:
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
break;
case V52_LCPFSM_E_MDU_LUBR:
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
/* Send MDU-DI */
rcv_mdu(fi, MDU_DI);
break;
case V52_LCPFSM_E_MDU_LBI:
case V52_LCPFSM_E_FE302:
case V52_LCPFSM_E_FE305:
case V52_LCPFSM_E_FE306:
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
break;
case V52_LCPFSM_E_FE304:
/* ignore */
break;
default:
OSMO_ASSERT(0);
}
}
static void lcp_fsm_le10_link_blocked(struct osmo_fsm_inst *fi, uint32_t event, void __attribute__((unused)) *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
/* Send MDU-LAI */
rcv_mdu(fi, MDU_LAI);
break;
case V52_LCPFSM_E_MPH_DI:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
/* Send MDU-DI */
rcv_mdu(fi, MDU_DI);
break;
case V52_LCPFSM_E_MDU_IDReq:
/* Send MDU-LBI */
rcv_mdu(fi, MDU_LBI);
break;
case V52_LCPFSM_E_FE_IDReq:
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
break;
case V52_LCPFSM_E_FE_IDRel:
case V52_LCPFSM_E_FE_IDRej:
/* ignore */
break;
case V52_LCPFSM_E_MDU_LUBR:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE11_NOP_LOCAL_LINK_UNBLOCK, 0, 0);
/* Send FE301 */
snd_fe(fi, V52_LCP_FE_301_302_LINK_UNBLOCK);
break;
case V52_LCPFSM_E_MDU_LBI:
case V52_LCPFSM_E_FE305:
case V52_LCPFSM_E_FE306:
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
break;
case V52_LCPFSM_E_FE302:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE12_NOP_REMOTE_LINK_UNBLOCK, 0, 0);
/* Send MDL-LUBR */
rcv_mdu(fi, MDU_LUBR);
break;
case V52_LCPFSM_E_FE304:
/* ignore */
break;
default:
OSMO_ASSERT(0);
}
}
static void lcp_fsm_le11_local_link_unblock(struct osmo_fsm_inst *fi, uint32_t event,
__attribute__((unused)) void *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
/* ignore */
break;
case V52_LCPFSM_E_MPH_DI:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
/* Send MDU-DI */
rcv_mdu(fi, MDU_DI);
break;
case V52_LCPFSM_E_MDU_IDReq:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
/* Send MDU-LBI */
rcv_mdu(fi, MDU_LBI);
break;
case V52_LCPFSM_E_FE_IDReq:
/* Send FE-IDRej */
snd_fe(fi, V52_LCP_FE_IDRej);
break;
case V52_LCPFSM_E_FE_IDRel:
case V52_LCPFSM_E_FE_IDRej:
/* ignore */
break;
case V52_LCPFSM_E_MDU_LUBR:
/* Send FE301 */
snd_fe(fi, V52_LCP_FE_301_302_LINK_UNBLOCK);
break;
case V52_LCPFSM_E_MDU_LBI:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
break;
case V52_LCPFSM_E_FE302:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
/* Send MDU-LUBI */
rcv_mdu(fi, MDU_LUBI);
break;
case V52_LCPFSM_E_FE304:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
/* Send MDU-LBI */
rcv_mdu(fi, MDU_LBI);
break;
case V52_LCPFSM_E_FE305:
case V52_LCPFSM_E_FE306:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
/* Send MDU-LBI */
rcv_mdu(fi, MDU_LBI);
break;
default:
OSMO_ASSERT(0);
}
}
static void lcp_fsm_le12_remote_link_unblock(struct osmo_fsm_inst *fi, uint32_t event,
void __attribute__((unused)) *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
/* ignore */
break;
case V52_LCPFSM_E_MPH_DI:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED, 0, 0);
/* Send MDU-DI */
rcv_mdu(fi, MDU_DI);
break;
case V52_LCPFSM_E_MDU_IDReq:
/* Send MDU-IDRej */
rcv_mdu(fi, MDU_IDRej);
/* Send MDU-LUBR */
rcv_mdu(fi, MDU_LUBR);
break;
case V52_LCPFSM_E_FE_IDReq:
/* Send FE-IDRej */
snd_fe(fi, V52_LCP_FE_IDRej);
break;
case V52_LCPFSM_E_MDU_LUBR:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
/* Send FE301 */
snd_fe(fi, V52_LCP_FE_301_302_LINK_UNBLOCK);
/* Send MDU-LUBI */
rcv_mdu(fi, MDU_LUBI);
break;
case V52_LCPFSM_E_MDU_LBI:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
break;
case V52_LCPFSM_E_FE302:
/* Send MDU-LUBR */
rcv_mdu(fi, MDU_LUBR);
break;
case V52_LCPFSM_E_FE304:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
/* Send MDU-LBI */
rcv_mdu(fi, MDU_LBI);
break;
case V52_LCPFSM_E_FE305:
case V52_LCPFSM_E_FE306:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
/* Send MDU-LBI */
rcv_mdu(fi, MDU_LBI);
break;
default:
OSMO_ASSERT(0);
}
}
static void lcp_fsm_le20_operational(struct osmo_fsm_inst *fi, uint32_t event, void __attribute__((unused)) *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
/* ignore */
break;
case V52_LCPFSM_E_MPH_DI:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE01_NOP_LINK_FAILURE, 0, 0);
/* Send MDU-DI */
rcv_mdu(fi, MDU_DI);
break;
case V52_LCPFSM_E_MDU_IDReq:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE22_OP_LOCAL_LINK_ID, 0, 0);
/* Send FE-IDReq */
snd_fe(fi, V52_LCP_FE_IDReq);
break;
case V52_LCPFSM_E_FE_IDReq:
/* Send MDU-IDReq */
rcv_mdu(fi, MDU_IDReq);
break;
case V52_LCPFSM_E_MDU_IDAck:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE21_OP_REMOTE_LINK_ID, 0, 0);
/* Send FE-IDAck */
snd_fe(fi, V52_LCP_FE_IDAck);
/* Send MPH-ID */
snd_mph(fi, MPH_ID);
break;
case V52_LCPFSM_E_MDU_IDRej:
/* Send FE-IDRej */
snd_fe(fi, V52_LCP_FE_IDRej);
break;
case V52_LCPFSM_E_MDU_LUBR:
/* Send FE301 */
snd_fe(fi, V52_LCP_FE_301_302_LINK_UNBLOCK);
break;
case V52_LCPFSM_E_MDU_LBI:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
break;
case V52_LCPFSM_E_FE302:
/* Send MDU-LUBI */
rcv_mdu(fi, MDU_LUBI);
break;
case V52_LCPFSM_E_FE304:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
/* Send MDU-LBI */
rcv_mdu(fi, MDU_LBI);
break;
case V52_LCPFSM_E_FE305:
/* Send MDU-LBR */
rcv_mdu(fi, MDU_LBR);
break;
case V52_LCPFSM_E_FE306:
/* Send MDU-LBRN */
rcv_mdu(fi, MDU_LBRN);
break;
default:
OSMO_ASSERT(0);
}
}
static void lcp_fsm_le21_op_remote_link_id(struct osmo_fsm_inst *fi, uint32_t event, void __attribute__((unused)) *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
/* ignore */
break;
case V52_LCPFSM_E_MPH_DI:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE01_NOP_LINK_FAILURE, 0, 0);
/* Send MPH-NOR */
snd_mph(fi, MPH_NOR);
/* Send MDU-DI */
rcv_mdu(fi, MDU_DI);
break;
case V52_LCPFSM_E_MDU_IDReq:
/* Send MDU-IDRej */
rcv_mdu(fi, MDU_IDRej);
break;
case V52_LCPFSM_E_MDU_IDAck:
/* ignore */
break;
case V52_LCPFSM_E_FE_IDRel:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
/* Send MDU-IDRel */
rcv_mdu(fi, MDU_IDRel);
/* Send MPH-NOR */
snd_mph(fi, MPH_NOR);
break;
case V52_LCPFSM_E_MDU_IDRej:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
/* Send FE-IDRej */
rcv_mdu(fi, MDU_IDRej);
/* Send MPH-NOR */
snd_mph(fi, MPH_NOR);
break;
case V52_LCPFSM_E_MDU_LUBR:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
/* Send FE301 */
snd_fe(fi, V52_LCP_FE_301_302_LINK_UNBLOCK);
/* Send MPH-NOR */
snd_mph(fi, MPH_NOR);
break;
case V52_LCPFSM_E_MDU_LBI:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
/* Send MPH-NOR */
snd_mph(fi, MPH_NOR);
break;
case V52_LCPFSM_E_FE302:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
/* Send MPH-NOR */
snd_mph(fi, MPH_NOR);
/* Send MDU-IDRel */
rcv_mdu(fi, MDU_IDRel);
/* Send MDU-LUBI */
rcv_mdu(fi, MDU_LUBI);
break;
case V52_LCPFSM_E_FE304:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
/* Send MPH-NOR */
snd_mph(fi, MPH_NOR);
/* Send MDU-LBI */
rcv_mdu(fi, MDU_LBI);
break;
case V52_LCPFSM_E_FE305:
/* Send MDU-LBR */
rcv_mdu(fi, MDU_LBR);
break;
case V52_LCPFSM_E_FE306:
/* Send MDU-LBRN */
rcv_mdu(fi, MDU_LBRN);
break;
default:
OSMO_ASSERT(0);
}
}
static void lcp_fsm_le22_op_local_link_id(struct osmo_fsm_inst *fi, uint32_t event, void __attribute__((unused)) *data)
{
switch (event) {
case V52_LCPFSM_E_MPH_AI:
/* ignore */
break;
case V52_LCPFSM_E_MPH_DI:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE01_NOP_LINK_FAILURE, 0, 0);
/* Send FE-IDRel */
snd_fe(fi, V52_LCP_FE_IDRel);
/* Send MDU-DI */
rcv_mdu(fi, MDU_DI);
break;
case V52_LCPFSM_E_MDU_IDReq:
/* ignore */
break;
case V52_LCPFSM_E_FE_IDAck:
/* Send MPH-IDR */
snd_mph(fi, MPH_IDR);
break;
case V52_LCPFSM_E_MPH_IDI:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
/* Send FE-IDRel */
snd_fe(fi, V52_LCP_FE_IDRel);
/* Send MDU-AI */
rcv_mdu(fi, MDU_AI);
break;
case V52_LCPFSM_E_MPH_EIg:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
/* Send FE-IDRel */
snd_fe(fi, V52_LCP_FE_IDRel);
/* Send MDU-EIg */
rcv_mdu(fi, MDU_EIg);
break;
case V52_LCPFSM_E_FE_IDReq:
/* Send FE-IDRej */
snd_fe(fi, V52_LCP_FE_IDRej);
break;
case V52_LCPFSM_E_FE_IDRej:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
/* Send MDU-IDRej */
rcv_mdu(fi, MDU_IDRej);
break;
case V52_LCPFSM_E_MDU_LUBR:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
/* Send FE301 */
snd_fe(fi, V52_LCP_FE_301_302_LINK_UNBLOCK);
break;
case V52_LCPFSM_E_MDU_LBI:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
/* Send FE303 */
snd_fe(fi, V52_LCP_FE_303_304_LINK_BLOCK);
break;
case V52_LCPFSM_E_FE302:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE20_OP_OPERATIONAL, 0, 0);
/* Send MDU-IDRej */
rcv_mdu(fi, MDU_IDRej);
/* Send MDU-LUBI */
rcv_mdu(fi, MDU_LUBI);
break;
case V52_LCPFSM_E_FE304:
osmo_fsm_inst_state_chg(fi, V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED, 0, 0);
/* Send MDU-LBI */
rcv_mdu(fi, MDU_LBI);
break;
case V52_LCPFSM_E_FE305:
/* Send MDU-LBR */
rcv_mdu(fi, MDU_LBR);
break;
case V52_LCPFSM_E_FE306:
/* Send MDU-LBRN */
rcv_mdu(fi, MDU_LBRN);
break;
default:
OSMO_ASSERT(0);
}
}
/* Table 17G.965 */
static const struct osmo_fsm_state v52_le_lcp_fsm_states[] = {
[V52_LCPFSM_S_LE01_NOP_LINK_FAILURE] = {
.name = "Link failure (LE0.1)",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_FE_IDRel) |
S(V52_LCPFSM_E_FE_IDRej) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE20_OP_OPERATIONAL) |
S(V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED),
.action = lcp_fsm_le01_link_failure,
},
[V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED] = {
.name = "Link failure and blocked(LE0.2)",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED),
.action = lcp_fsm_le02_link_failure_blocked,
},
[V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED] = {
.name = "Link blocked (LE1.0)",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_FE_IDRel) |
S(V52_LCPFSM_E_FE_IDRej) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED) |
S(V52_LCPFSM_S_LE11_NOP_LOCAL_LINK_UNBLOCK) |
S(V52_LCPFSM_S_LE12_NOP_REMOTE_LINK_UNBLOCK),
.action = lcp_fsm_le10_link_blocked,
},
[V52_LCPFSM_S_LE11_NOP_LOCAL_LINK_UNBLOCK] = {
.name = "Local link unblock (LE1.1)",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_FE_IDRel) |
S(V52_LCPFSM_E_FE_IDRej) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED) |
S(V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED) |
S(V52_LCPFSM_S_LE20_OP_OPERATIONAL),
.action = lcp_fsm_le11_local_link_unblock,
},
[V52_LCPFSM_S_LE12_NOP_REMOTE_LINK_UNBLOCK] = {
.name = "Remote link unblocke (LE1.2)",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE02_NOP_LINK_FAILURE_AND_BLOCKED) |
S(V52_LCPFSM_S_LE20_OP_OPERATIONAL) |
S(V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED),
.action = lcp_fsm_le12_remote_link_unblock,
},
[V52_LCPFSM_S_LE20_OP_OPERATIONAL] = {
.name = "Link Operational (LE2.0)",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_MDU_IDAck) |
S(V52_LCPFSM_E_MDU_IDRej) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE01_NOP_LINK_FAILURE) |
S(V52_LCPFSM_S_LE22_OP_LOCAL_LINK_ID) |
S(V52_LCPFSM_S_LE21_OP_REMOTE_LINK_ID) |
S(V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED),
.action = lcp_fsm_le20_operational,
},
[V52_LCPFSM_S_LE21_OP_REMOTE_LINK_ID] = {
.name = "Remote link identification (LE2.1)",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_MDU_IDAck) |
S(V52_LCPFSM_E_FE_IDRel) |
S(V52_LCPFSM_E_MDU_IDRej) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE01_NOP_LINK_FAILURE) |
S(V52_LCPFSM_S_LE20_OP_OPERATIONAL) |
S(V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED),
.action = lcp_fsm_le21_op_remote_link_id,
},
[V52_LCPFSM_S_LE22_OP_LOCAL_LINK_ID] = {
.name = "Local link identification (LE2.2)",
.in_event_mask = S(V52_LCPFSM_E_MPH_AI) |
S(V52_LCPFSM_E_MPH_DI) |
S(V52_LCPFSM_E_MDU_IDReq) |
S(V52_LCPFSM_E_FE_IDAck) |
S(V52_LCPFSM_E_MPH_IDI) |
S(V52_LCPFSM_E_MPH_EIg) |
S(V52_LCPFSM_E_FE_IDReq) |
S(V52_LCPFSM_E_FE_IDRej) |
S(V52_LCPFSM_E_MDU_LUBR) |
S(V52_LCPFSM_E_MDU_LBI) |
S(V52_LCPFSM_E_FE302) |
S(V52_LCPFSM_E_FE304) |
S(V52_LCPFSM_E_FE305) |
S(V52_LCPFSM_E_FE306),
.out_state_mask = S(V52_LCPFSM_S_LE01_NOP_LINK_FAILURE) |
S(V52_LCPFSM_S_LE20_OP_OPERATIONAL) |
S(V52_LCPFSM_S_LE10_NOP_LINK_BLOCKED),
.action =lcp_fsm_le22_op_local_link_id,
},
};
struct osmo_fsm v52_le_lcp_fsm = {
.name = "V52_LE_LCP",
.states = v52_le_lcp_fsm_states,
.num_states = ARRAY_SIZE(v52_le_lcp_fsm_states),
.timer_cb = NULL,
.log_subsys = DV5LCP,
.event_names = v52_lcp_fsm_event_names,
};
struct osmo_fsm_inst *v52_le_lcp_create(void *ctx, struct v5x_link *v5l, uint8_t id)
{
struct osmo_fsm_inst *fi;
OSMO_ASSERT(v5l);
fi = osmo_fsm_inst_alloc(&v52_le_lcp_fsm, ctx, v5l, LOGL_DEBUG, NULL);
if (!fi)
return NULL;
osmo_fsm_inst_update_id_f(fi, "%d", id);
/* initial state for links that are not in failure state */
fi->state = V52_LCPFSM_S_LE20_OP_OPERATIONAL;
return fi;
}
void v52_le_lcp_destroy(struct osmo_fsm_inst *fi)
{
if (fi)
osmo_fsm_inst_free(fi);
}
bool v52_le_lcp_is_operational(struct osmo_fsm_inst *fi)
{
return (fi->state >= V52_LCPFSM_S_LE20_OP_OPERATIONAL);
}
const char *v52_le_lcp_state_name(struct osmo_fsm_inst *fi)
{
return v52_le_lcp_fsm_states[fi->state].name;
}
void v52_le_lcp_init(void)
{
int rc;
rc = osmo_fsm_register(&v52_le_lcp_fsm);
OSMO_ASSERT(!rc);
LOGP(DV5LCP, LOGL_NOTICE, "Using V52 link control protocol\n");
}
/***********************************************************************
* Messages from other layers
***********************************************************************/
/* receive message from lower (L1 FSM) layer */
int v52_le_lcp_mph_rcv(struct v5x_link *v5l, enum v5x_mph_prim prim)
{
enum v52_lcp_fsm_event event = 9999;
switch (prim) {
case MPH_AI:
LOGP(DV5LCP, LOGL_NOTICE, "Received link activation indication from L1 (link ID %d).\n", v5l->id);
event = V52_LCPFSM_E_MPH_AI;
break;
case MPH_DI:
LOGP(DV5LCP, LOGL_NOTICE, "Received link deactivation indication from L1 (link ID %d).\n", v5l->id);
event = V52_LCPFSM_E_MPH_DI;
break;
case MPH_EIa:
LOGP(DV5LCP, LOGL_DEBUG, "Received link error indication from L1 (link ID %d): LOS\n", v5l->id);
return 0;
case MPH_EIb:
LOGP(DV5LCP, LOGL_DEBUG, "Received link error indication from L1 (link ID %d): RAI\n", v5l->id);
return 0;
case MPH_EIc:
LOGP(DV5LCP, LOGL_DEBUG, "Received link error indication from L1 (link ID %d): AIS\n", v5l->id);
return 0;
case MPH_EId:
LOGP(DV5LCP, LOGL_DEBUG, "Received link error indication from L1 (link ID %d): Internal failure\n",
v5l->id);
return 0;
case MPH_EIe:
LOGP(DV5LCP, LOGL_DEBUG, "Received link error indication from L1 (link ID %d): CRC error\n", v5l->id);
return 0;
case MPH_EIf:
LOGP(DV5LCP, LOGL_DEBUG, "Received link error indication from L1 (link ID %d): "
"Remote CRC error indication\n", v5l->id);
return 0;
case MPH_IDI:
LOGP(DV5LCP, LOGL_NOTICE, "Received link identification indication from L1 (link ID %d).\n", v5l->id);
event = V52_LCPFSM_E_MPH_IDI;
break;
case MPH_EIg:
LOGP(DV5LCP, LOGL_NOTICE, "Received link identification failure from L1 (link ID %d).\n", v5l->id);
event = V52_LCPFSM_E_MPH_EIg;
break;
case MPH_EIdr:
return 0;
case MPH_EIbr:
return 0;
default:
LOGP(DV5LCP, LOGL_NOTICE, "Invalid LCP primitive %d receied from L1/AN (link ID %d).\n", prim, v5l->id);
return -EINVAL;
}
OSMO_ASSERT(event < 9999);
osmo_fsm_inst_dispatch(v5l->fi, event, NULL);
return 0;
}
/* receive message from lower (CTRL) layer */
int v52_le_lcp_fe_rcv(struct v5x_link *v5l, enum v52_link_ctrl_func lcf)
{
enum v52_lcp_fsm_event event;
switch (lcf) {
case V52_LCP_FE_IDReq:
event = V52_LCPFSM_E_FE_IDReq;
break;
case V52_LCP_FE_IDAck:
event = V52_LCPFSM_E_FE_IDAck;
break;
case V52_LCP_FE_IDRel:
event = V52_LCPFSM_E_FE_IDRel;
break;
case V52_LCP_FE_IDRej:
event = V52_LCPFSM_E_FE_IDRej;
break;
case V52_LCP_FE_301_302_LINK_UNBLOCK:
event = V52_LCPFSM_E_FE302;
break;
case V52_LCP_FE_303_304_LINK_BLOCK:
event = V52_LCPFSM_E_FE304;
break;
case V52_LCP_FE_305_DEF_LINK_BLOCK_REQ:
event = V52_LCPFSM_E_FE305;
break;
case V52_LCP_FE_306_NON_DEF_LINK_BLOCK_REQ:
event = V52_LCPFSM_E_FE306;
break;
default:
LOGP(DV5LCP, LOGL_NOTICE, "Invalid link control function primitive %d receied from AN.\n", lcf);
return -EINVAL;
}
osmo_fsm_inst_dispatch(v5l->fi, event, NULL);
return 0;
}
int v52_le_lcp_mdu_snd(struct v5x_link *v5l, enum v5x_mgmt_prim prim)
{
enum v52_lcp_fsm_event event;
switch (prim) {
case MDU_IDReq:
event = V52_LCPFSM_E_MDU_IDReq;
break;
case MDU_IDAck:
event = V52_LCPFSM_E_MDU_IDAck;
break;
case MDU_IDRej:
event = V52_LCPFSM_E_MDU_IDRej;
break;
case MDU_LUBR:
event = V52_LCPFSM_E_MDU_LUBR;
break;
case MDU_LBI:
event = V52_LCPFSM_E_MDU_LBI;
break;
default:
LOGP(DV5LCP, LOGL_NOTICE, "Invalid MDU primitive %d receied from management.\n", prim);
return -EINVAL;
}
osmo_fsm_inst_dispatch(v5l->fi, event, NULL);
return 0;
}

9
src/v52_le_lcp_fsm.h Normal file
View File

@ -0,0 +1,9 @@
struct osmo_fsm_inst *v52_le_lcp_create(void *ctx, struct v5x_link *v5l, uint8_t id);
void v52_le_lcp_destroy(struct osmo_fsm_inst *fi);
bool v52_le_lcp_is_operational(struct osmo_fsm_inst *fi);
const char *v52_le_lcp_state_name(struct osmo_fsm_inst *fi);
void v52_le_lcp_init(void);
int v52_le_lcp_mph_rcv(struct v5x_link *v5l, enum v5x_mph_prim prim);
int v52_le_lcp_fe_rcv(struct v5x_link *v5l, enum v52_link_ctrl_func lcf);
int v52_le_lcp_mdu_snd(struct v5x_link *v5l, enum v5x_mgmt_prim prim);