From ae1a7de2b84ed3e6331242c82b5d43ec093750f4 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sat, 3 Dec 2022 12:47:03 +0100 Subject: [PATCH] Serveral fixes to v51_le_ctrl.c --- v51_le_ctrl.c | 218 +++++++++++++++++++++++++++++--------------------- v51_le_ctrl.h | 6 +- 2 files changed, 131 insertions(+), 93 deletions(-) diff --git a/v51_le_ctrl.c b/v51_le_ctrl.c index c1bddb8..6322e99 100644 --- a/v51_le_ctrl.c +++ b/v51_le_ctrl.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -33,6 +32,8 @@ #include "v5x_internal.h" #include "v5x_protocol.h" #include "v51_le_ctrl.h" +#include "v51_le_provisioning.h" +#include "v52_le_user_port_fsm.h" #include "logging.h" #define S(x) (1 << (x)) @@ -40,7 +41,6 @@ #define TIMEOUT 1 /* uncomment to test lost TX messages at the first transmission */ -#warning fixme //#define TEST_TX_FAILURE /* PSTN Protocol FSM */ @@ -81,43 +81,41 @@ static const struct value_string v51_ctrl_fsm_event_names[] = { { 0, NULL } }; -static int blocked = 1; static void v51_mdu_ctrl(struct osmo_fsm_inst *fi, const struct tlv_parsed *tp) { struct v5x_ctrl_proto *ctrl = fi->priv; - LOGP(DV5CTRL, LOGL_NOTICE, "MDU-CTRL\n"); - if (ctrl->v5if) { - puts("common control"); enum v51_ctrl_func_id cfi = *TLVP_VAL(tp, V51_CTRL_IEI_CTRL_F_ID) & 0x7f; - printf("cfi=%d\n", cfi); - if (cfi == V51_CTRL_ID_REQUEST_VARIANT_AND_INTERFACE_ID) { - puts("request variant+id"); - v51_snd_ctrl_common(ctrl->v5if, V51_CTRL_ID_VARIANT_AND_INTERFACE_ID, NULL, &ctrl->v5if->variant, &ctrl->v5if->id); - } - if (cfi == V51_CTRL_ID_RESTART_REQUEST) { - puts("request restart"); - v51_snd_ctrl_common(ctrl->v5if, V51_CTRL_ID_RESTART_COMPLETE, NULL, NULL, NULL); - } + uint8_t variant = 0; + uint8_t rej_cause = 0; + uint32_t interface_id = 0; + + LOGP(DV5CTRL, LOGL_DEBUG, "MDU-CTRL received.\n"); + + if (TLVP_PRESENT(tp, V51_CTRL_IEI_VARIANT)) + variant = *TLVP_VAL(tp, V51_CTRL_IEI_VARIANT) & 0x7f; + if (TLVP_PRESENT(tp, V51_CTRL_IEI_REJECTION_CAUSE)) + rej_cause = *TLVP_VAL(tp, V51_CTRL_IEI_REJECTION_CAUSE) & 0x0f; + if (TLVP_PRESENT(tp, V51_CTRL_IEI_INTERFACE_ID)) + interface_id = osmo_load32be_ext_2(TLVP_VAL(tp, V51_CTRL_IEI_INTERFACE_ID), 3); + v51_rcv_provisioning(ctrl->v5if, cfi, variant, rej_cause, interface_id); } if (ctrl->v5up) { - puts("port control"); - enum v51_ctrl_func_el cfe = *TLVP_VAL(tp, V51_CTRL_IEI_CTRL_F_ELEMENT) & 0x7f; - printf("cfe=%d\n", cfe); - if (cfe == V51_CTRL_FE201_UNBLOCK) { - puts("request unblock"); - if (blocked) { - blocked = 0; - v51_snd_ctrl_port(ctrl->v5up, V51_CTRL_FE201_UNBLOCK); - } - } - if (cfe == V51_CTRL_FE203_BLOCK) { - puts("request block"); - if (!blocked) { - blocked = 1; - v51_snd_ctrl_port(ctrl->v5up, V51_CTRL_FE203_BLOCK); - } + enum v51_ctrl_func_id cfe = *TLVP_VAL(tp, V51_CTRL_IEI_CTRL_F_ELEMENT) & 0x7f; + uint8_t perf_grading = 0; + + LOGP(DV5CTRL, LOGL_DEBUG, "FE received for address %d.\n", ctrl->v5up->nr); + + if (TLVP_PRESENT(tp, V51_CTRL_IEI_PERFORMANCE_GRADING)) + perf_grading = *TLVP_VAL(tp, V51_CTRL_IEI_PERFORMANCE_GRADING) & 0x0f; + switch (ctrl->v5up->type) { + case V5X_USER_TYPE_ISDN: + v51_ctrl_le_i_port_rcv(ctrl->v5up, cfe, perf_grading); + break; + case V5X_USER_TYPE_PSTN: + v51_ctrl_le_p_port_rcv(ctrl->v5up, cfe); + break; } } } @@ -228,23 +226,23 @@ static int v51_ctrl_fsm_timer_cb(struct osmo_fsm_inst *fi) static void v51_ctrl_fsm_oos(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { - case V51_CTRL_EV_MDU_START_TRAFFIC: - /* go to IN_SERVICE */ - osmo_fsm_inst_state_chg(fi, V51_CTRL_ST_IN_SERVICE, 0, 0); - break; - case V51_CTRL_EV_MDU_STOP_TRAFFIC: - v51_mdu_error(fi, "Got MDU-stop, but traffic not started."); - break; - case V51_CTRL_EV_MDU_CTRL: - msgb_free(data); - v51_mdu_error(fi, "Got MDU-CTRL, but traffic not started."); - break; - case V51_CTRL_EV_RX_CONTROL: - v51_mdu_error(fi, "Received CONTROL, but traffic not started."); - break; - case V51_CTRL_EV_RX_CONTROL_ACK: - v51_mdu_error(fi, "Received CONTROL ACK, but traffic not started."); - break; + case V51_CTRL_EV_MDU_START_TRAFFIC: + /* go to IN_SERVICE */ + osmo_fsm_inst_state_chg(fi, V51_CTRL_ST_IN_SERVICE, 0, 0); + break; + case V51_CTRL_EV_MDU_STOP_TRAFFIC: + v51_mdu_error(fi, "Got MDU-stop, but traffic not started."); + break; + case V51_CTRL_EV_MDU_CTRL: + msgb_free(data); + v51_mdu_error(fi, "Got MDU-CTRL, but traffic not started."); + break; + case V51_CTRL_EV_RX_CONTROL: + v51_mdu_error(fi, "Received CONTROL, but traffic not started."); + break; + case V51_CTRL_EV_RX_CONTROL_ACK: + v51_mdu_error(fi, "Received CONTROL ACK, but traffic not started."); + break; } } @@ -252,17 +250,17 @@ static void v51_ctrl_fsm_oos(struct osmo_fsm_inst *fi, uint32_t event, void *dat static void v51_ctrl_fsm_ins(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { - case V51_CTRL_EV_MDU_START_TRAFFIC: - break; - case V51_CTRL_EV_MDU_STOP_TRAFFIC: - v51_ctrl_stop(fi); - break; - case V51_CTRL_EV_MDU_CTRL: - v51_ctrl_send(fi->priv, data); - break; - case V51_CTRL_EV_RX_CONTROL: - v51_mdu_ctrl(fi, data); - break; + case V51_CTRL_EV_MDU_START_TRAFFIC: + break; + case V51_CTRL_EV_MDU_STOP_TRAFFIC: + v51_ctrl_stop(fi); + break; + case V51_CTRL_EV_MDU_CTRL: + v51_ctrl_send(fi->priv, data); + break; + case V51_CTRL_EV_RX_CONTROL: + v51_mdu_ctrl(fi, data); + break; } } @@ -270,20 +268,20 @@ static void v51_ctrl_fsm_ins(struct osmo_fsm_inst *fi, uint32_t event, void *dat static void v51_ctrl_fsm_aa(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { - case V51_CTRL_EV_MDU_START_TRAFFIC: - break; - case V51_CTRL_EV_MDU_STOP_TRAFFIC: - v51_ctrl_stop(fi); - break; - case V51_CTRL_EV_MDU_CTRL: - v51_ctrl_send(fi->priv, data); - break; - case V51_CTRL_EV_RX_CONTROL: - v51_mdu_ctrl(fi, data); - break; - case V51_CTRL_EV_RX_CONTROL_ACK: - v51_ctrl_ack(fi, data); - break; + case V51_CTRL_EV_MDU_START_TRAFFIC: + break; + case V51_CTRL_EV_MDU_STOP_TRAFFIC: + v51_ctrl_stop(fi); + break; + case V51_CTRL_EV_MDU_CTRL: + v51_ctrl_send(fi->priv, data); + break; + case V51_CTRL_EV_RX_CONTROL: + v51_mdu_ctrl(fi, data); + break; + case V51_CTRL_EV_RX_CONTROL_ACK: + v51_ctrl_ack(fi, data); + break; } } @@ -334,11 +332,20 @@ struct osmo_fsm v51_ctrl_fsm = { .event_names = v51_ctrl_fsm_event_names, }; +void v51_ctrl_init(void) +{ + int rc; + + rc = osmo_fsm_register(&v51_ctrl_fsm); + OSMO_ASSERT(!rc); + LOGP(DV5CTRL, LOGL_NOTICE, "Using V5x control protocol\n"); +} + struct v5x_ctrl_proto *v51_ctrl_create(struct v5x_interface *v5if, struct v5x_user_port *v5up, uint16_t nr) { struct v5x_ctrl_proto *ctrl; - assert((v5if && !v5up) || (!v5if && v5up)); + OSMO_ASSERT((v5if && !v5up) || (!v5if && v5up)); ctrl = talloc_zero((v5if) ? : v5up->inst, struct v5x_ctrl_proto); if (!ctrl) @@ -348,20 +355,34 @@ struct v5x_ctrl_proto *v51_ctrl_create(struct v5x_interface *v5if, struct v5x_us INIT_LLIST_HEAD(&ctrl->tx_queue); ctrl->fi = osmo_fsm_inst_alloc(&v51_ctrl_fsm, ctrl, ctrl, LOGL_DEBUG, NULL); - if (!ctrl->fi) + if (!ctrl->fi) { + v51_ctrl_destroy(ctrl); return NULL; + } osmo_fsm_inst_update_id_f(ctrl->fi, "%d", nr); return ctrl; } +void v51_ctrl_destroy(struct v5x_ctrl_proto *ctrl) +{ + /* get rid of pending messages */ + msgb_queue_free(&ctrl->tx_queue); + if (ctrl->tx_msg) + msgb_free(ctrl->tx_msg); + + if (ctrl->fi) + osmo_fsm_inst_free(ctrl->fi); + + free(ctrl); +} /*********************************************************************** * V5 Message encoding / sending ***********************************************************************/ /* G.964 Section 14.4.1.1 / Table 48 */ -struct msgb *v51_enc_ctrl_port(struct v5x_user_port *v5up, enum v51_ctrl_func_el cfe) +struct msgb *v51_enc_ctrl_port(struct v5x_user_port *v5up, enum v51_ctrl_func_el cfe, bool is_isdn) { uint8_t cfe_ie = cfe | 0x80; struct v51_l3_hdr *l3h; @@ -371,7 +392,7 @@ struct msgb *v51_enc_ctrl_port(struct v5x_user_port *v5up, enum v51_ctrl_func_el l3h = (struct v51_l3_hdr *) msgb_put(msg, sizeof(*l3h)); l3h->pdisc = V51_CTRL_PDISC; - l3h->l3_addr = ntohs(v51_l3_addr_enc(v5up->nr, true)); + l3h->l3_addr = ntohs(v51_l3_addr_enc(v5up->nr, is_isdn)); l3h->msg_type = V51_CTRL_MSGT_PORT_CTRL; msgb_tlv_put(msg, V51_CTRL_IEI_CTRL_F_ELEMENT, 1, &cfe_ie); @@ -380,7 +401,7 @@ struct msgb *v51_enc_ctrl_port(struct v5x_user_port *v5up, enum v51_ctrl_func_el } /* G.964 Section 14.4.1.2 / Table 49 */ -static struct msgb *v51_enc_ctrl_port_ack(struct v5x_user_port *v5up, enum v51_ctrl_func_el cfe) +static struct msgb *v51_enc_ctrl_port_ack(struct v5x_user_port *v5up, enum v51_ctrl_func_el cfe, bool is_isdn) { uint8_t cfe_ie = cfe | 0x80; struct v51_l3_hdr *l3h; @@ -390,7 +411,7 @@ static struct msgb *v51_enc_ctrl_port_ack(struct v5x_user_port *v5up, enum v51_c l3h = (struct v51_l3_hdr *) msgb_put(msg, sizeof(*l3h)); l3h->pdisc = V51_CTRL_PDISC; - l3h->l3_addr = ntohs(v51_l3_addr_enc(v5up->nr, true)); + l3h->l3_addr = ntohs(v51_l3_addr_enc(v5up->nr, is_isdn)); l3h->msg_type = V51_CTRL_MSGT_PORT_CTRL_ACK; msgb_tlv_put(msg, V51_CTRL_IEI_CTRL_F_ELEMENT, 1, &cfe_ie); @@ -400,7 +421,7 @@ static struct msgb *v51_enc_ctrl_port_ack(struct v5x_user_port *v5up, enum v51_c /* G.964 Section 14.4.1.3 / Table 50 */ static struct msgb *v51_enc_ctrl_common(struct v5x_interface *v5if, enum v51_ctrl_func_id cfi, - uint8_t *rej_cause, uint8_t *variant, uint32_t *interface_id) + uint8_t *variant, uint8_t *rej_cause, uint32_t *interface_id) { uint8_t cfi_ie = cfi | 0x80; struct v51_l3_hdr *l3h; @@ -462,10 +483,11 @@ static int v51_rcv_ctrl_port(struct v5x_user_port *v5up, uint8_t msg_type, const switch (msg_type) { case V51_CTRL_MSGT_PORT_CTRL: + /* send ACK to AN */ + v5x_snd(v5up->inst, V51_DLADDR_CTRL, v51_enc_ctrl_port_ack(v5up, cfe, v5up->type == V5X_USER_TYPE_ISDN)); /* FIXME: send event to FSM */ osmo_fsm_inst_dispatch(v5up->ctrl->fi, V51_CTRL_EV_RX_CONTROL, (void *)tp); - /* send ACK to AN */ - return v5x_snd(v5up->inst, V51_DLADDR_CTRL, v51_enc_ctrl_port_ack(v5up, cfe)); + return 0; case V51_CTRL_MSGT_PORT_CTRL_ACK: osmo_fsm_inst_dispatch(v5up->ctrl->fi, V51_CTRL_EV_RX_CONTROL_ACK, (void *)tp); default: @@ -479,11 +501,11 @@ static int v51_rcv_ctrl_common(struct v5x_interface *v5if, uint8_t msg_type, con switch (msg_type) { case V51_CTRL_MSGT_COMMON_CTRL: + v5x_snd(v5if, V51_DLADDR_CTRL, v51_enc_ctrl_common_ack(v5if, cfi)); /* send event to FSM */ osmo_fsm_inst_dispatch(v5if->control.ctrl->fi, V51_CTRL_EV_RX_CONTROL, (void *)tp); /* send ACK to AN */ - printf("sending ack\n"); - return v5x_snd(v5if, V51_DLADDR_CTRL, v51_enc_ctrl_common_ack(v5if, cfi)); + return 0; case V51_CTRL_MSGT_COMMON_CTRL_ACK: /* send event to FSM */ osmo_fsm_inst_dispatch(v5if->control.ctrl->fi, V51_CTRL_EV_RX_CONTROL_ACK, (void *)tp); @@ -494,16 +516,26 @@ static int v51_rcv_ctrl_common(struct v5x_interface *v5if, uint8_t msg_type, con } /* receive message from lower (DL) layer */ -int v51_rcv_ctrl(struct v5x_interface *v5if, uint16_t l3_addr, uint8_t msg_type, const struct tlv_parsed *tp) +int v51_rcv_ctrl(struct v5x_interface *v5if, uint16_t l3_addr, bool is_isdn, uint8_t msg_type, const struct tlv_parsed *tp) { struct v5x_user_port *v5up; switch (msg_type) { case V51_CTRL_MSGT_PORT_CTRL: case V51_CTRL_MSGT_PORT_CTRL_ACK: - v5up = v5x_user_port_find(v5if, l3_addr); - if (!v5up) + v5up = v5x_user_port_find(v5if, l3_addr, is_isdn); + if (!v5up) { + LOGP(DV5CTRL, LOGL_ERROR, "Received port control message from unknown layer 3 address %d. Please check provisioning!\n", l3_addr); return -ENODEV; + } + if (v5up->type == V5X_USER_TYPE_ISDN && !is_isdn) { + LOGP(DV5CTRL, LOGL_ERROR, "Received port control message from layer 3 address %d. AN is set to PSTN, LE to ISDN, please check provisioning!", l3_addr); + return -EIO; + } + if (v5up->type == V5X_USER_TYPE_PSTN && is_isdn) { + LOGP(DV5CTRL, LOGL_ERROR, "Received port control message from layer 3 address %d. AN is set to ISDN, LE to PSTN, please check provisioning!", l3_addr); + return -EIO; + } return v51_rcv_ctrl_port(v5up, msg_type, tp); case V51_CTRL_MSGT_COMMON_CTRL: case V51_CTRL_MSGT_COMMON_CTRL_ACK: @@ -523,14 +555,20 @@ int v51_rcv_ctrl(struct v5x_interface *v5if, uint16_t l3_addr, uint8_t msg_type, int v51_snd_ctrl_common(struct v5x_interface *v5if, enum v51_ctrl_func_id cfi, uint8_t *rej_cause, uint8_t *variant, uint32_t *interface_id) { - osmo_fsm_inst_dispatch(v5if->control.ctrl->fi, V51_CTRL_EV_MDU_CTRL, v51_enc_ctrl_common(v5if, cfi, rej_cause, variant, interface_id)); + LOGP(DV5CTRL, LOGL_DEBUG, "Sending MDU-CTRL.\n"); + + osmo_fsm_inst_dispatch(v5if->control.ctrl->fi, V51_CTRL_EV_MDU_CTRL, + v51_enc_ctrl_common(v5if, cfi, variant, rej_cause, interface_id)); return 0; } /* send port message from upper layer */ int v51_snd_ctrl_port(struct v5x_user_port *v5up, enum v51_ctrl_func_el cfe) { - osmo_fsm_inst_dispatch(v5up->ctrl->fi, V51_CTRL_EV_MDU_CTRL, v51_enc_ctrl_port(v5up, cfe)); + LOGP(DV5CTRL, LOGL_DEBUG, "Sending FE.\n"); + + osmo_fsm_inst_dispatch(v5up->ctrl->fi, V51_CTRL_EV_MDU_CTRL, + v51_enc_ctrl_port(v5up, cfe, v5up->type == V5X_USER_TYPE_ISDN)); return 0; } @@ -540,5 +578,5 @@ void v51_start_ctrl(struct v5x_ctrl_proto *ctrl) } void v51_stop_ctrl(struct v5x_ctrl_proto *ctrl) { - osmo_fsm_inst_dispatch(ctrl->fi, V51_CTRL_EV_MDU_START_TRAFFIC, NULL); + osmo_fsm_inst_dispatch(ctrl->fi, V51_CTRL_EV_MDU_STOP_TRAFFIC, NULL); } diff --git a/v51_le_ctrl.h b/v51_le_ctrl.h index 205ae78..63176d7 100644 --- a/v51_le_ctrl.h +++ b/v51_le_ctrl.h @@ -1,8 +1,8 @@ -extern struct osmo_fsm v51_ctrl_fsm; - +void v51_ctrl_init(void); struct v5x_ctrl_proto *v51_ctrl_create(struct v5x_interface *v5if, struct v5x_user_port *v5up, uint16_t nr); -int v51_rcv_ctrl(struct v5x_interface *v5if, uint16_t l3_addr, uint8_t msg_type, const struct tlv_parsed *tp); +void v51_ctrl_destroy(struct v5x_ctrl_proto *ctrl); +int v51_rcv_ctrl(struct v5x_interface *v5if, uint16_t l3_addr, bool is_isdn, uint8_t msg_type, const struct tlv_parsed *tp); int v51_snd_ctrl_common(struct v5x_interface *v5if, enum v51_ctrl_func_id cfi, uint8_t *rej_cause, uint8_t *variant, uint32_t *interface_id); int v51_snd_ctrl_port(struct v5x_user_port *v5up, enum v51_ctrl_func_el cfe);