From 5fe471bf433760eedcce9fef24920381e04c9199 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 26 Dec 2022 14:45:13 +0100 Subject: [PATCH] Work on management Also merged provisioning and management into one source file. --- src/v5x_le_management.c | 809 ++++++++++++++++++++++++++++++++++---- src/v5x_le_management.h | 23 +- src/v5x_le_provisioning.c | 90 ----- src/v5x_le_provisioning.h | 4 - 4 files changed, 744 insertions(+), 182 deletions(-) delete mode 100644 src/v5x_le_provisioning.c delete mode 100644 src/v5x_le_provisioning.h diff --git a/src/v5x_le_management.c b/src/v5x_le_management.c index 62c1d0b..2301508 100644 --- a/src/v5x_le_management.c +++ b/src/v5x_le_management.c @@ -22,13 +22,22 @@ * */ +#warning The blocking_enable state and timer is a hack to delay port blocking messages during startup. (AN may not like to get blocking messages too early.) This must be replaced by a more elegant algorithm. + +// FIXME: explain each process, especially the port blocking/unblocking states and process + #include -#include +#include #include "v5x_internal.h" #include "v5x_protocol.h" +#include "v5x_le_ctrl_fsm.h" #include "v5x_le_port_fsm.h" #include "v5x_le_pstn_fsm.h" +#include "v52_le_lcp_fsm.h" +#include "v52_le_bcc_fsm.h" +#include "v52_le_pp_fsm.h" +#include "v5x_le_management.h" #include "logging.h" void v5x_le_mgmt_init(void) @@ -36,47 +45,71 @@ void v5x_le_mgmt_init(void) LOGP(DV5MGMT, LOGL_NOTICE, "Using V5x management\n"); } -/* received management primitives from LE (NAT protocol via PH-socket) */ -void v5x_mph_rcv_le(struct v5x_user_port *v5up, uint8_t prim, uint8_t *data, int length) -{ - ph_socket_t *s = &v5up->ph_socket; +/* + * provisioning and port handling + */ - switch (prim) { - case PH_PRIM_CTRL_REQ: - if (length && *data == PH_CTRL_UNBLOCK) { - LOGP(DV5MGMT, LOGL_INFO, "Received unblocking from LE of port %d.\n", v5up->nr); - v5up->le_unblocked = true; - v5x_mph_snd(v5up, MPH_UBR); - if (v5up->pstn.proto && v5up->an_unblocked) +struct osmo_timer_list provisioning_timer; +struct osmo_timer_list blocking_enable_timer; + +static void provisioning_cb(void *data) +{ + struct v5x_interface *v5if = data; + /* ask for variant and interface ID */ + LOGP(DV5MGMT, LOGL_INFO, "Requesting variant and interface ID.\n"); + v5x_le_ctrl_common_snd(v5if, V5X_CTRL_ID_REQUEST_VARIANT_AND_INTERFACE_ID, NULL, NULL, NULL); +} + +static void blocking_enable_cb(void *data) +{ + struct v5x_interface *v5if = data; + struct v5x_link *v5l; + struct v5x_user_port *v5up; + + LOGP(DV5MGMT, LOGL_DEBUG, "Enable sending of port blocking/unblocking and sending all block states to AN.\n"); + + /* unblock all links */ + if (v5if->dialect == V5X_DIALECT_V52) { + llist_for_each_entry(v5l, &v5if->links, list) { + LOGP(DV5MGMT, LOGL_INFO, "Send unblocking request for link %d.\n", v5l->id); + v52_le_lcp_mdu_snd(v5l, MDU_LUBR); + } + } + /* unblock all ports */ + llist_for_each_entry(v5up, &v5if->user_ports, list) { + if (v5up->blocking_enabled) + continue; + v5up->blocking_enabled = true; + if (v5up->le_unblocked) { + LOGP(DV5MGMT, LOGL_INFO, "Send unblock request to %s port %d.\n", + (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + v5x_port_mph_snd(v5up, MPH_UBR); + if (v5up->pstn.proto && v5up->an_unblocked) { + LOGP(DV5MGMT, LOGL_INFO, "Send port unblocked control to PSTN port %d.\n", v5up->nr); v5x_le_pstn_mdu_snd(v5up, MDU_CTRL_port_unblocked); - if (!v5up->an_unblocked) { - LOGP(DV5MGMT, LOGL_INFO, "Reply with blocking, because AN is blocked.\n"); - uint8_t ctrl = PH_CTRL_BLOCK; - ph_socket_tx_msg(&v5up->ph_socket, v5up->type == V5X_USER_TYPE_ISDN ? 3 : 0, PH_PRIM_CTRL_IND, &ctrl, 1); + } + } else { + LOGP(DV5MGMT, LOGL_INFO, "Send block indication to %s port %d.\n", + (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + v5x_port_mph_snd(v5up, MPH_BI); + if (v5up->pstn.proto) { + LOGP(DV5MGMT, LOGL_INFO, "Send port blocked control to PSTN port %d.\n", v5up->nr); + v5x_le_pstn_mdu_snd(v5up, MDU_CTRL_port_blocked); } } - if (length && *data == PH_CTRL_BLOCK) { - LOGP(DV5MGMT, LOGL_INFO, "Received blocking from LE of port %d.\n", v5up->nr); - v5up->le_unblocked = false; - v5x_mph_snd(v5up, MPH_BI); - if (v5up->pstn.proto) - v5x_le_pstn_mdu_snd(v5up, MDU_CTRL_port_blocked); + } +} + +static void restart_all_pstn_ports(struct v5x_interface *v5if) +{ + struct v5x_user_port *v5up; + + llist_for_each_entry(v5up, &v5if->user_ports, list) { + if (v5up->pstn.proto) { + LOGP(DV5MGMT, LOGL_INFO, "Send restart request to PSTN port %d.\n", v5up->nr); + v5x_le_pstn_mdu_snd(v5up, MDU_CTRL_port_restart_req); + v5x_le_pstn_mdu_snd(v5up, MDU_CTRL_port_restart_compl); } - break; - case PH_PRIM_ACT_REQ: - LOGP(DV5MGMT, LOGL_INFO, "Received activation from LE of port %d.\n", v5up->nr); - if (!v5up->an_unblocked) { - ph_socket_tx_msg(s, 3, PH_PRIM_DACT_IND, NULL, 0); - break; - } - v5x_mph_snd(v5up, MPH_AR); - break; - case PH_PRIM_DACT_REQ: - LOGP(DV5MGMT, LOGL_INFO, "Received deactivation from LE of port %d.\n", v5up->nr); - v5x_mph_snd(v5up, MPH_DR); - break; - default: - LOGP(DV5MGMT, LOGL_INFO, "Received unknown prim %d from LE for port %d.\n", prim, v5up->nr); } } @@ -85,100 +118,710 @@ static void _block_unblock_socket(struct v5x_user_port *v5up, bool block) uint8_t ctrl; if (block && v5up->an_unblocked) { - v5up->an_unblocked = 0; + v5up->an_unblocked = false; ctrl = PH_CTRL_BLOCK; - ph_socket_tx_msg(&v5up->ph_socket, v5up->type == V5X_USER_TYPE_ISDN ? 3 : 0, PH_PRIM_CTRL_IND, &ctrl, 1); + ph_socket_tx_msg(&v5up->ph_socket, v5up->type == V5X_USER_TYPE_ISDN ? 3 : 0, PH_PRIM_CTRL_IND, &ctrl, + 1); return; } if (!block && !v5up->an_unblocked) { - v5up->an_unblocked = 1; + v5up->an_unblocked = true; ctrl = PH_CTRL_UNBLOCK; - ph_socket_tx_msg(&v5up->ph_socket, v5up->type == V5X_USER_TYPE_ISDN ? 3 : 0, PH_PRIM_CTRL_IND, &ctrl, 1); + ph_socket_tx_msg(&v5up->ph_socket, v5up->type == V5X_USER_TYPE_ISDN ? 3 : 0, PH_PRIM_CTRL_IND, &ctrl, + 1); return; } } +/* messages from common control layer */ +void v5x_le_common_ctrl_rcv(struct v5x_interface *v5if, uint8_t cfi, uint8_t variant, uint8_t rej_cause, + uint32_t interface_id) +{ + struct v5x_user_port *v5up; + + LOGP(DV5MGMT, LOGL_DEBUG, "Received common control message from control protocol. " + "(cfi = %d, variant = %d, rej_cause = %d, interface_id = %d)\n", cfi, variant, rej_cause, interface_id); + switch (cfi) { + case V5X_CTRL_ID_REQUEST_VARIANT_AND_INTERFACE_ID: + LOGP(DV5MGMT, LOGL_INFO, "AN requests variant and interface ID, replying.\n"); + v5x_le_ctrl_common_snd(v5if, V5X_CTRL_ID_VARIANT_AND_INTERFACE_ID, NULL, &v5if->variant_local, + &v5if->id_local); + break; + case V5X_CTRL_ID_RESTART_REQUEST: + LOGP(DV5MGMT, LOGL_INFO, "AN requests restart, sending restart to every PSTN port and replying.\n"); + /* all PSTN ports are restarted */ + restart_all_pstn_ports(v5if); + v5x_le_ctrl_common_snd(v5if, V5X_CTRL_ID_RESTART_COMPLETE, NULL, NULL, NULL); + break; + case V5X_CTRL_ID_VARIANT_AND_INTERFACE_ID: + LOGP(DV5MGMT, LOGL_INFO, "AN replies variant and interface ID. (variant = %d, interface_id = %d)\n", + variant, interface_id); + v5if->variant_remote = variant; + v5if->variant_remote_valid = true; + if (v5if->variant_remote != v5if->variant_local) { + LOGP(DV5MGMT, LOGL_ERROR, "Variant does not match: AN(%d) != LE(%d)\n", v5if->variant_remote, + v5if->variant_local); + } + v5if->id_remote = interface_id; + v5if->id_remote_valid = true; + if (v5if->id_remote != v5if->id_local) { + LOGP(DV5MGMT, LOGL_ERROR, "Interface ID does not match: AN(%d) != LE(%d)\n", v5if->id_remote, + v5if->id_local); + } + if (v5if->variant_remote != v5if->variant_local || v5if->id_remote != v5if->id_local) { + LOGP(DV5MGMT, LOGL_ERROR, "****************************************************************\n"); + LOGP(DV5MGMT, LOGL_ERROR, "You must set correct Variant and Interface ID on both AN and LE!\n"); + LOGP(DV5MGMT, LOGL_ERROR, "****************************************************************\n"); + break; + } + memset(&blocking_enable_timer, 0, sizeof(blocking_enable_timer)); + blocking_enable_timer.data = v5if; + blocking_enable_timer.cb = blocking_enable_cb; + osmo_timer_schedule(&blocking_enable_timer, 4, 0); // FIXME: make configurable + break; + case V5X_CTRL_ID_RESTART_COMPLETE: + LOGP(DV5MGMT, LOGL_INFO, "AN indicated complete restart.\n"); + break; + case V5X_CTRL_ID_UNBLK_ALL_REL_PSTN_ISDN_REQUEST: + case V5X_CTRL_ID_UNBLK_ALL_REL_PSTN_REQUEST: + case V5X_CTRL_ID_UNBLK_ALL_REL_ISDN_REQUEST: + LOGP(DV5MGMT, LOGL_INFO, "Multiple port unblocking received.\n"); + LOGP(DV5MGMT, LOGL_INFO, "Accepting multiple port unblocking, sending reply.\n"); + v5x_le_ctrl_common_snd(v5if, cfi + 1, NULL, NULL, NULL); + llist_for_each_entry(v5up, &v5if->user_ports, list) { + if (cfi == V5X_CTRL_ID_UNBLK_ALL_REL_PSTN_REQUEST && !v5up->pstn.proto) + continue; + if (cfi == V5X_CTRL_ID_UNBLK_ALL_REL_ISDN_REQUEST && v5up->pstn.proto) + continue; + v5up->blocking_enabled = true; + if (v5up->le_unblocked) { + LOGP(DV5MGMT, LOGL_INFO, " -> Set %s port %d into unblocked state.\n", + (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + _block_unblock_socket(v5up, false); + if (v5up->pstn.proto) { + v5x_le_port_pstn_unblock(v5up->port_fi); + LOGP(DV5MGMT, LOGL_INFO, " -> Send port unblocked control to PSTN port %d.\n", + v5up->nr); + v5x_le_pstn_mdu_snd(v5up, MDU_CTRL_port_unblocked); + } else + v5x_le_port_isdn_unblock(v5up->port_fi); + } + } + LOGP(DV5MGMT, LOGL_INFO, "Completed multiple port unblocking, sending info.\n"); + v5x_le_ctrl_common_snd(v5if, cfi + 3, NULL, NULL, NULL); + break; + case V5X_CTRL_ID_BLK_ALL_PSTN_REQUEST: + case V5X_CTRL_ID_BLK_ALL_ISDN_REQUEST: + LOGP(DV5MGMT, LOGL_INFO, "Multiple port blocking request from remote.\n"); + LOGP(DV5MGMT, LOGL_INFO, "Accepting multiple port blocking, sending reply.\n"); + v5x_le_ctrl_common_snd(v5if, cfi + 1, NULL, NULL, NULL); + llist_for_each_entry(v5up, &v5if->user_ports, list) { + if (cfi == V5X_CTRL_ID_BLK_ALL_PSTN_REQUEST && !v5up->pstn.proto) + continue; + if (cfi == V5X_CTRL_ID_BLK_ALL_ISDN_REQUEST && v5up->pstn.proto) + continue; + v5up->blocking_enabled = true; + LOGP(DV5MGMT, LOGL_INFO, " -> Set %s port %d into blocked state.\n", + (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + _block_unblock_socket(v5up, true); + if (v5up->pstn.proto) { + v5x_le_port_pstn_block(v5up->port_fi); + LOGP(DV5MGMT, LOGL_INFO, " -> Send port blocked control to PSTN port %d.\n", v5up->nr); + v5x_le_pstn_mdu_snd(v5up, MDU_CTRL_port_blocked); + } else + v5x_le_port_isdn_block(v5up->port_fi); + } + LOGP(DV5MGMT, LOGL_INFO, "Completed multiple port blocking, sending info.\n"); + v5x_le_ctrl_common_snd(v5if, cfi + 3, NULL, NULL, NULL); + break; + case V5X_CTRL_ID_UNBLK_ALL_REL_PSTN_ISDN_COMPLETED: + case V5X_CTRL_ID_UNBLK_ALL_REL_PSTN_COMPLETED: + case V5X_CTRL_ID_UNBLK_ALL_REL_ISDN_COMPLETED: + LOGP(DV5MGMT, LOGL_INFO, "Completed multiple port blocking by remote. Updating blocked ports.\n"); + llist_for_each_entry(v5up, &v5if->user_ports, list) { + if (cfi == V5X_CTRL_ID_UNBLK_ALL_REL_PSTN_COMPLETED && !v5up->pstn.proto) + continue; + if (cfi == V5X_CTRL_ID_UNBLK_ALL_REL_ISDN_COMPLETED && v5up->pstn.proto) + continue; + if (!v5up->le_unblocked) { + LOGP(DV5MGMT, LOGL_INFO, " -> Send block indication to %s port %d.\n", + (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + v5x_port_mph_snd(v5up, MPH_BI); + } + } + case V5X_CTRL_ID_BLK_ALL_PSTN_COMPLETED: + case V5X_CTRL_ID_BLK_ALL_ISDN_COMPLETED: + break; + default: + LOGP(DV5MGMT, LOGL_NOTICE, "Ignoring common control message with cfi = %d\n", cfi); + } +} + +/* perform provisioning */ +void v5x_le_provisioning_start(struct v5x_interface *v5if) +{ + memset(&provisioning_timer, 0, sizeof(provisioning_timer)); + provisioning_timer.data = v5if; + provisioning_timer.cb = provisioning_cb; + osmo_timer_schedule(&provisioning_timer, 1, 0); // FIXME: make configurable +} + +void v5x_le_pstn_restart(struct v5x_interface *v5if) +{ + /* request a restart */ + LOGP(DV5MGMT, LOGL_NOTICE, "Perform PSTN restart.\n"); + v5x_le_ctrl_common_snd(v5if, V5X_CTRL_ID_RESTART_REQUEST, NULL, NULL, NULL); + /* all PSTN ports are restarted */ + restart_all_pstn_ports(v5if); + v5x_le_ctrl_common_snd(v5if, V5X_CTRL_ID_RESTART_COMPLETE, NULL, NULL, NULL); +} + +/* received management primitives from LE (NAT protocol via PH-socket) */ +void v5x_le_nat_ph_rcv(struct v5x_user_port *v5up, uint8_t prim, uint8_t *data, int length) +{ + ph_socket_t *s = &v5up->ph_socket; + + switch (prim) { + case PH_PRIM_CTRL_REQ: + if (length && *data == PH_CTRL_UNBLOCK) { + LOGP(DV5MGMT, LOGL_INFO, "Received unblocking from LE of %s port %d.\n", + (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + v5up->le_unblocked = true; + if (v5up->blocking_enabled) { + v5x_port_mph_snd(v5up, MPH_UBR); + if (v5up->pstn.proto && v5up->an_unblocked) { + LOGP(DV5MGMT, LOGL_INFO, "Send port unblocked control to PSTN port %d.\n", + v5up->nr); + v5x_le_pstn_mdu_snd(v5up, MDU_CTRL_port_unblocked); + } + } + if (!v5up->an_unblocked) { + LOGP(DV5MGMT, LOGL_INFO, "Reply with blocking, because AN is blocked.\n"); + uint8_t ctrl = PH_CTRL_BLOCK; + ph_socket_tx_msg(&v5up->ph_socket, v5up->type == V5X_USER_TYPE_ISDN ? 3 : 0, + PH_PRIM_CTRL_IND, &ctrl, 1); + } + } + if (length && *data == PH_CTRL_BLOCK) { + LOGP(DV5MGMT, LOGL_INFO, "Received blocking from LE of %s port %d.\n", + (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + v5up->le_unblocked = false; + if (v5up->blocking_enabled) { + v5x_port_mph_snd(v5up, MPH_BI); + if (v5up->pstn.proto) { + LOGP(DV5MGMT, LOGL_INFO, "Send port blocked control to PSTN port %d.\n", + v5up->nr); + v5x_le_pstn_mdu_snd(v5up, MDU_CTRL_port_blocked); + } + } + } + break; + case PH_PRIM_ACT_REQ: + LOGP(DV5MGMT, LOGL_INFO, "Received activation from LE of %s port %d.\n", + (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + if (!v5up->an_unblocked) { + ph_socket_tx_msg(s, 3, PH_PRIM_DACT_IND, NULL, 0); + break; + } + v5x_port_mph_snd(v5up, MPH_AR); + break; + case PH_PRIM_DACT_REQ: + LOGP(DV5MGMT, LOGL_INFO, "Received deactivation from LE of %s port %d.\n", + (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + v5x_port_mph_snd(v5up, MPH_DR); + break; + default: + LOGP(DV5MGMT, LOGL_INFO, "Received unknown prim %d from LE for %s port %d.\n", prim, + (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + } +} + /* received management primitives from AN (via port control protocol) */ -void v5x_mph_rcv_an(struct v5x_user_port *v5up, enum v5x_mph_prim prim, uint8_t perf_grading) +void v5x_le_port_mph_rcv(struct v5x_user_port *v5up, enum v5x_mph_prim prim, uint8_t perf_grading) { switch (prim) { case MPH_UBR: - LOGP(DV5MGMT, LOGL_INFO, "Received unblocking request from AN of port %d.\n", v5up->nr); + LOGP(DV5MGMT, LOGL_INFO, "Received unblocking request from AN of %s port %d.\n", + (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + v5up->blocking_enabled = true; if (v5up->le_unblocked) { - LOGP(DV5MGMT, LOGL_INFO, "Reply with unblocking request.\n"); - v5x_mph_snd(v5up, MPH_UBR); + LOGP(DV5MGMT, LOGL_INFO, "Reply with unblocking request, because port available at LE.\n"); + v5x_port_mph_snd(v5up, MPH_UBR); _block_unblock_socket(v5up, false); - if (v5up->pstn.proto) + if (v5up->pstn.proto) { + LOGP(DV5MGMT, LOGL_INFO, "Send port unblocked control to PSTN port %d.\n", v5up->nr); v5x_le_pstn_mdu_snd(v5up, MDU_CTRL_port_unblocked); - } else - LOGP(DV5MGMT, LOGL_INFO, "Ignore unblocking request from AN, because LE is blocked.\n"); + } + } else { + LOGP(DV5MGMT, LOGL_INFO, "Reply with blocking indication, because port unavailable at LE.\n"); + v5up->an_unblocked = false; + v5x_port_mph_snd(v5up, MPH_BI); + } break; case MPH_UBI: - LOGP(DV5MGMT, LOGL_INFO, "Received unblocking indication from AN of port %d.\n", v5up->nr); + LOGP(DV5MGMT, LOGL_INFO, "Received unblocking indication from AN of %s port %d.\n", + (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + v5up->blocking_enabled = true; _block_unblock_socket(v5up, false); - if (v5up->pstn.proto) + if (v5up->pstn.proto) { + LOGP(DV5MGMT, LOGL_INFO, "Send port unblocked control to PSTN port %d.\n", v5up->nr); v5x_le_pstn_mdu_snd(v5up, MDU_CTRL_port_unblocked); + } break; case MPH_BR: - LOGP(DV5MGMT, LOGL_INFO, "Received blocking request from AN of port %d.\n", v5up->nr); - v5x_mph_snd(v5up, MPH_BI); + LOGP(DV5MGMT, LOGL_INFO, "Received blocking request from AN of %s port %d.\n", + (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + v5up->blocking_enabled = true; + LOGP(DV5MGMT, LOGL_INFO, "Reply with blocking indication.\n"); + v5x_port_mph_snd(v5up, MPH_BI); _block_unblock_socket(v5up, true); - if (v5up->pstn.proto) + if (v5up->pstn.proto) { + LOGP(DV5MGMT, LOGL_INFO, "Send port blocked control to PSTN port %d.\n", v5up->nr); v5x_le_pstn_mdu_snd(v5up, MDU_CTRL_port_blocked); + } break; case MPH_BI: - LOGP(DV5MGMT, LOGL_INFO, "Received blocking indication from AN of port %d.\n", v5up->nr); + LOGP(DV5MGMT, LOGL_INFO, "Received blocking indication from AN of %s port %d.\n", + (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + v5up->blocking_enabled = true; _block_unblock_socket(v5up, true); - if (v5up->pstn.proto) + if (v5up->pstn.proto) { + LOGP(DV5MGMT, LOGL_INFO, "Send port blocked control to PSTN port %d.\n", v5up->nr); v5x_le_pstn_mdu_snd(v5up, MDU_CTRL_port_blocked); + } break; case MPH_AI: - LOGP(DV5MGMT, LOGL_INFO, "Received activation indication from AN of port %d.\n", v5up->nr); + LOGP(DV5MGMT, LOGL_INFO, "Received activation indication from AN of ISDN port %d.\n", v5up->nr); ph_socket_tx_msg(&v5up->ph_socket, 3, PH_PRIM_ACT_IND, NULL, 0); break; + case MPH_AWI: + break; + case MPH_DSAI: + break; case MPH_DI: - LOGP(DV5MGMT, LOGL_INFO, "Received deactivation indication from AN of port %d.\n", v5up->nr); + LOGP(DV5MGMT, LOGL_INFO, "Received deactivation indication from AN of ISDN port %d.\n", v5up->nr); ph_socket_tx_msg(&v5up->ph_socket, 3, PH_PRIM_DACT_IND, NULL, 0); break; + case MPH_GI: + LOGP(DV5MGMT, LOGL_INFO, "Received performance grading from AN for ISDN port %d: %s\n", v5up->nr, + (perf_grading) ? "Degraded" : "Normal grade"); + break; default: - LOGP(DV5MGMT, LOGL_INFO, "Received unknown prim %d from AN for port %d.\n", prim, v5up->nr); + LOGP(DV5MGMT, LOGL_INFO, "Received unknown prim %d from AN for %s port %d.\n", prim, (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); } } -/* receive FE-message from NAT (PH-socket) and forward it to the PSTN protocol */ -void v5x_nat_rcv_fe(struct v5x_user_port *v5up, struct msgb *msg) -{ - enum v5x_fe_prim prim; - - prim = *msg->data; - msgb_pull(msg, 1); - - LOGP(DV5MGMT, LOGL_INFO, "FE message: NAT -> PSTN_LE of port %d.\n", v5up->nr); - v5x_le_pstn_fe_snd(v5up, prim, msg); -} - -/* receive FE-message from PSTN protocol and forward it to NAT (PH-socket) */ -void v5x_pstn_rcv_fe(struct v5x_user_port *v5up, enum v5x_fe_prim prim, struct msgb *msg) -{ - *msgb_push(msg, 1) = prim; - - LOGP(DV5MGMT, LOGL_INFO, "FE message: PSTN_LE -> NAT of port %d.\n", v5up->nr); - ph_socket_tx_msg(&v5up->ph_socket, 0, PH_PRIM_DATA_IND, msg->data, msg->len); - - msgb_free(msg); -} - /* receive MDU primitives from PSTN protocol */ -void v5x_pstn_rcv_mdu(struct v5x_user_port *v5up, enum v5x_mgmt_prim prim) +void v5x_le_pstn_mdu_rcv(struct v5x_user_port *v5up, enum v5x_mgmt_prim prim) { switch (prim) { case MDU_error_ind: LOGP(DV5MGMT, LOGL_NOTICE, "Received MDU-error_indication from PSTN protocol of port %d.\n", v5up->nr); break; case MDU_CTRL_port_restart_ack: - //FIXME: handle restart procedure + LOGP(DV5MGMT, LOGL_INFO, "Received restart acknowledge from PSTN protocol of port %d.\n", v5up->nr); break; default: LOGP(DV5MGMT, LOGL_INFO, "Received unknown prim %d from PSTN protocol for port %d.\n", prim, v5up->nr); } } + +/* flush all channels from non-operational link */ +static void flush_link(struct v5x_link *v5l) +{ + struct v5x_user_port *v5up; + int t; + + for (t = 1; t <= 31; t++) { + if (!v5l->ts[t].b_channel) + continue; + if ((v5up = v5l->ts[t].v5up)) { + if (v5up->ts[0] == &v5l->ts[t]) { + v5up->ts[0] = NULL; + v5up->ts_activated[0] = 0; + } + if (v5up->ts[1] == &v5l->ts[t]) { + v5up->ts[1] = NULL; + v5up->ts_activated[1] = 0; + } + v5l->ts[t].v5up = NULL; + } + } +} + +/* + * LCP handling + */ + +/* receive MDU primitives from LCP protocol */ +void v52_le_lcp_mdu_rcv(struct v5x_link *v5l, enum v5x_mgmt_prim prim) +{ + switch (prim) { + case MDU_AI: + LOGP(DV5MGMT, LOGL_INFO, "Link %d is active.\n", v5l->id); + break; + case MDU_DI: + LOGP(DV5MGMT, LOGL_INFO, "Link %d is inactive.\n", v5l->id); + break; + case MDU_LAI: + LOGP(DV5MGMT, LOGL_INFO, "Link %d becomes active in blocked state, try unblocking.\n", v5l->id); + v52_le_lcp_mdu_snd(v5l, MDU_LUBR); + break; + case MDU_IDReq: + LOGP(DV5MGMT, LOGL_INFO, "Remote side perform link ID check of link %d, replying.\n", v5l->id); + v52_le_lcp_mdu_snd(v5l, MDU_IDAck); + break; + case MDU_IDAck: + break; + case MDU_IDRel: + LOGP(DV5MGMT, LOGL_INFO, "Remote side ID check done.\n"); + break; + case MDU_IDRej: + break; + case MDU_EIg: + break; + case MDU_LUBR: + LOGP(DV5MGMT, LOGL_INFO, "Remote side unblocks link ID %d, replying.\n", v5l->id); + v52_le_lcp_mdu_snd(v5l, MDU_LUBR); + break; + case MDU_LUBI: + LOGP(DV5MGMT, LOGL_INFO, "Remote side link ID %d is now unblocked.\n", v5l->id); + break; + case MDU_LBI: + LOGP(DV5MGMT, LOGL_INFO, "LCP indicated blocked link ID %d.\n", v5l->id); + flush_link(v5l); + break; + case MDU_LBR: + case MDU_LBRN: + LOGP(DV5MGMT, LOGL_INFO, "Remote request blocking of link link ID %d, replying.\n", v5l->id); + flush_link(v5l); + v52_le_lcp_mdu_snd(v5l, MDU_LBI); + break; + default: + LOGP(DV5MGMT, LOGL_INFO, "Received unknown prim %d from LCP protocol for link ID %d.\n", prim, v5l->id); + } +} + +/* + * forwarding messages between PSTN and gateway application + */ + +/* receive FE-message from NAT (PH-socket) and forward it to the PSTN protocol */ +void v5x_le_nat_fe_rcv(struct v5x_user_port *v5up, struct msgb *msg) +{ + enum v5x_fe_prim prim; + + prim = *msg->data; + msgb_pull(msg, 1); + + if (!v5x_le_port_isdn_is_operational(v5up->port_fi)) { + LOGP(DV5MGMT, LOGL_NOTICE, "Dropping (NAT->LE) message of non-operational PSTN port for L3Addr %d.\n", + v5up->nr); + msgb_free(msg); + return; + } + LOGP(DV5MGMT, LOGL_INFO, "FE message: NAT -> PSTN_LE of PSTN port %d.\n", v5up->nr); + v5x_le_pstn_fe_snd(v5up, prim, msg); +} + +/* receive FE-message from PSTN protocol and forward it to NAT (PH-socket) */ +void v5x_le_pstn_fe_rcv(struct v5x_user_port *v5up, enum v5x_fe_prim prim, struct msgb *msg) +{ + *msgb_push(msg, 1) = prim; + + if (!v5x_le_port_isdn_is_operational(v5up->port_fi)) { + LOGP(DV5MGMT, LOGL_NOTICE, "Dropping (AN->NAT) message of non-operational PSTN port for L3Addr %d.\n", + v5up->nr); + msgb_free(msg); + return; + } + LOGP(DV5MGMT, LOGL_INFO, "FE message: PSTN_LE -> NAT of PSTN port %d.\n", v5up->nr); + ph_socket_tx_msg(&v5up->ph_socket, 0, PH_PRIM_DATA_IND, msg->data, msg->len); + + msgb_free(msg); +} + +/* + * BCC channel handling + */ + +/* assign channel */ +void v5x_le_channel_assign(struct v5x_user_port *v5up, int channel) +{ + struct v5x_interface *v5if = v5up->interface; + struct v5x_link *v5l = NULL; + int found, t; + + OSMO_ASSERT(channel >= 1 && channel <= 2); + + /* the channels are pre-assigned with V5.1, so only activation state is set */ + if (v5if->dialect == V5X_DIALECT_V51) { + if (!v5up->ts[channel - 1]) { + LOGP(DV5MGMT, LOGL_ERROR, "Cannot activate channel, because no TS is assigned for %s port " + "%d.\n", (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5l->id); + return; + } + if (v5up->ts_activated[channel - 1]) + return; + LOGP(DV5MGMT, LOGL_DEBUG, "Activating channel %d for %s port %d at TS %d of link %d.\n", + channel, (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr, + v5up->ts[channel - 1]->nr, v5up->ts[channel - 1]->link->id); + v5up->ts_activated[channel - 1] = 1; + return; + } + + /* channel already assigned, just activate it, if not already */ + if (v5up->ts[channel - 1]) { + v5up->ts_activated[channel - 1] = 1; + return; + } + + /* hunt for a channel */ + found = 0; + llist_for_each_entry(v5l, &v5if->links, list) { + if (!v52_le_lcp_is_operational(v5l->fi)) { + LOGP(DV5MGMT, LOGL_NOTICE, "While searching for a bearer channel: Skipping link with ID %d, " + "because it is not operational.\n", v5l->id); + continue; + } + for (t = 1; t <= 31; t++) { + if (!v5l->ts[t].b_channel) + continue; + if (!v5l->ts[t].v5up) { + found = 1; + break; + } + } + if (found) + break; + } + if (!found) { + LOGP(DV5MGMT, LOGL_NOTICE, "No free channel found.\n"); + return; + } + + /* assign channel */ + v5l->ts[t].v5up = v5up; + v5up->ts[channel - 1] = &v5l->ts[t]; + + /* request BCC to allocate channel on AN */ + v52_le_bcc_mdu_snd(v5if, v5up->nr, (v5up->type == V5X_USER_TYPE_ISDN), v5up->ts[channel - 1]->link->id, + v5up->ts[channel - 1]->nr, 1, channel, NULL, (v5if->use_capability) ? &v5if->capability : NULL, + MDU_BCC_allocation_req); +} + +/* unassign channel */ +void v5x_le_channel_unassign(struct v5x_user_port *v5up, int channel) +{ + struct v5x_interface *v5if = v5up->interface; + + /* the channels are pre-assigned with V5.1, so only activation state is set */ + if (v5if->dialect == V5X_DIALECT_V51) { + if (!v5up->ts_activated[channel - 1]) + return; + if (!v5up->ts[channel - 1]) { + LOGP(DV5MGMT, LOGL_ERROR, "Cannot deactivate channel, because no TS is assigned for %s port " + "%d.\n", (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); + return; + } + LOGP(DV5MGMT, LOGL_DEBUG, "Deactivating channel %d for %s port %d at TS %d of link %d.\n", + channel, (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr, + v5up->ts[channel - 1]->nr, v5up->ts[channel - 1]->link->id); + v5up->ts_activated[channel - 1] = 0; + return; + } + + /* deactivate */ + v5up->ts_activated[channel - 1] = 0; + + /* if not assigned */ + if (!v5up->ts[channel - 1]) + return; + + /* unassign or abort ongoing BCC allocation */ + v52_le_bcc_mdu_snd(v5if, v5up->nr, v5up->type == V5X_USER_TYPE_ISDN, v5up->ts[channel - 1]->link->id, + v5up->ts[channel - 1]->nr, 1, channel, NULL, 0, MDU_BCC_deallocation_req); +} + +int v52_le_bcc_mdu_rcv(struct v5x_interface *v5if, uint8_t link_id, uint8_t ts, + uint8_t __attribute__((unused)) *isdn_multislot, enum v5x_mgmt_prim prim, const uint8_t *cause, + uint8_t cause_len) +{ + struct v5x_link *v5l; + struct v5x_user_port *v5up; + int channel = 0; + + if (ts > 31) { + LOGP(DV5MGMT, LOGL_ERROR, "TS %d out of range.\n", ts); + return -EINVAL; + } + + v5l = v5x_link_find_id(v5if, link_id); + if (!v5l) { + LOGP(DV5MGMT, LOGL_ERROR, "Invalid link ID %d.\n", link_id); + return -EINVAL; + } + v5up = v5l->ts[ts].v5up; + if (!v5up) { + LOGP(DV5MGMT, LOGL_NOTICE, "TS %d of link ID %d is not assigned.\n", ts, link_id); + return 0; + } + if (v5up->ts[0] == &v5l->ts[ts]) + channel = 1; + if (v5up->ts[1] == &v5l->ts[ts]) + channel = 2; + OSMO_ASSERT(channel); + + switch (prim) { + case MDU_BCC_allocation_conf: + LOGP(DV5MGMT, LOGL_INFO, "Assigned channel %d for %s port %d at TS %d of link %d.\n", + channel, (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr, ts, link_id); + v5up->ts_activated[channel - 1] = 1; + break; + case MDU_BCC_deallocation_conf: + LOGP(DV5MGMT, LOGL_INFO, "Unassigned channel %d for %s port %d at TS %d of link %d.\n", + channel, (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr, ts, link_id); + v5l->ts[ts].v5up = NULL; + v5up->ts[0] = NULL; + break; + case MDU_BCC_allocation_reject_ind: + case MDU_BCC_deallocation_reject_ind: + if (cause_len < 1) + break; + LOGP(DV5MGMT, LOGL_ERROR, "Failed to (un)assign channel %d for %s port %d at TS %d of link %d: %s.\n", + channel, (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr, ts, link_id, + get_value_string(v52_bcc_reject_cause_type_str, + cause[0] & 0x7f)); + if (cause_len > 1) + LOGP(DV5MGMT, LOGL_ERROR, " -> Diagnostic: %s\n", osmo_hexdump(cause + 1, cause_len - 1)); + break; + case MDU_BCC_protocol_error_ind: + if (cause_len < 1) + break; + LOGP(DV5MGMT, LOGL_ERROR, "Failed to (un)assign channel %d for %s port %d at TS %d of link %d: %s.\n", + channel, (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr, ts, link_id, + get_value_string(v5x_cause_type_str, cause[0] & 0x7f)); + if (cause_len > 1) + LOGP(DV5MGMT, LOGL_ERROR, " -> Diagnostic: %s\n", osmo_hexdump(cause + 1, cause_len - 1)); + if (cause_len >= 3 && cause[1] == 0x20 && cause[2] == 0x47) { + LOGP(DV5MGMT, LOGL_ERROR, "AN rejects information-transfer-capability information element, " + "please disable via VTY!\n"); + } + break; + default: + LOGP(DV5MGMT, LOGL_ERROR, "Failed to (un)assign channel %d for %s port %d at TS %d of link %d.\n", + channel, (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr, ts, link_id); + } + + return 0; +} + +/* + * Protection protocol handling + */ + +static void switchover_request_link(struct v5x_link *v5l, uint8_t link_id, uint8_t ts) +{ + LOGP(DV5MGMT, LOGL_NOTICE, "Switch over request from AN to link %d and TS %d.\n", link_id, ts); + if (!v5l) { + LOGP(DV5MGMT, LOGL_ERROR, " -> Rejecting, because requested link is not primary, nor secondary.\n"); + v52_le_pp_mdu_snd(v5l->interface, MDU_Protection_switch_over_rej, link_id, ts, + V52_PP_REJECT_CAUSE_T_TARGET_CC_NOT_PROV); + return; + } + if (ts != v5l->c_channel[0].ts->nr) { + LOGP(DV5MGMT, LOGL_ERROR, " -> Rejecting, because requested TS is not a C-channel.\n"); + v52_le_pp_mdu_snd(v5l->interface, MDU_Protection_switch_over_rej, link_id, ts, + V52_PP_REJECT_CAUSE_T_TARGET_CC_NOT_PROV); + return; + } + if (!v52_le_lcp_is_operational(v5l->fi)) { + LOGP(DV5MGMT, LOGL_ERROR, " -> Rejecting, because requested link is not operational.\n"); + v52_le_pp_mdu_snd(v5l->interface, MDU_Protection_switch_over_rej, link_id, ts, + V52_PP_REJECT_CAUSE_T_TARGET_CC_NOT_OPER); + return; + } + if (v5l == v5l->interface->cc_link) { + LOGP(DV5MGMT, LOGL_ERROR, " -> Rejecting, because requested allocation exists already.\n"); + v52_le_pp_mdu_snd(v5l->interface, MDU_Protection_switch_over_rej, link_id, ts, + V52_PP_REJECT_CAUSE_T_ALLOC_EXISTS_ALREADY); + return; + } + LOGP(DV5MGMT, LOGL_NOTICE, "Sending switch over command to AN.\n"); + v52_le_pp_mdu_snd(v5l->interface, MDU_Protection_switch_over_com, link_id, ts, 0); +} + +static void switchover_request(struct v5x_interface *v5if) +{ + LOGP(DV5MGMT, LOGL_NOTICE, "Switch over request from AN, due to link failure.\n"); + if (v5if->primary_link == v5if->cc_link) { + LOGP(DV5MGMT, LOGL_NOTICE, "Sending switch over command to AN. (go to secondary link)\n"); + v52_le_pp_mdu_snd(v5if, MDU_Protection_switch_over_com, v5if->secondary_link->id, 16, 0); + } + if (v5if->secondary_link == v5if->cc_link) { + LOGP(DV5MGMT, LOGL_NOTICE, "Sending switch over command to AN. (go to primary link)\n"); + v52_le_pp_mdu_snd(v5if, MDU_Protection_switch_over_com, v5if->primary_link->id, 16, 0); + } +} + +int v52_le_pp_mdu_rcv(struct v5x_interface *v5if, enum v5x_mgmt_prim prim, uint8_t link_id, uint8_t ts, + const uint8_t *cause, uint8_t cause_len) +{ + struct v5x_link *v5l = NULL; + + /* get link from what the AN is talking about */ + if (link_id == v5if->primary_link->id) + v5l = v5if->primary_link; + if (link_id == v5if->secondary_link->id) + v5l = v5if->secondary_link; + + switch (prim) { + case MDU_Protection_switch_over_ack: + LOGP(DV5MGMT, LOGL_NOTICE, "Switch over request from LE to link %d and TS %d was acked.\n", link_id, + ts); + LOGP(DV5MGMT, LOGL_NOTICE, "Performing switch over.\n"); + if (v5l) + v5if->cc_link = v5l; + break; + case MDU_Protection_switch_over_req: + if (ts) + switchover_request_link(v5l, link_id, ts); + else + switchover_request(v5if); + break; + case MDU_Protection_switch_over_reject_ind: + if (cause_len < 1) + break; + LOGP(DV5MGMT, LOGL_ERROR, "Switch over to link %d and TS %d was rejected by AN: %s.\n", link_id, ts, + get_value_string(v52_pp_reject_cause_type_str, cause[0] & 0x7f)); + break; + case MDU_Protection_switch_over_error_ind: + LOGP(DV5MGMT, LOGL_NOTICE, "Switch over request from LE to link %d and TS %d failed.\n", link_id, ts); + break; + case MDU_Protection_reset_SN_ind: + LOGP(DV5MGMT, LOGL_NOTICE, "AN resets serial numbers at Protection protocol.\n"); + break; + case MDU_Protection_reset_SN_com: + LOGP(DV5MGMT, LOGL_NOTICE, "LE resets serial numbers at Protection protocol.\n"); + break; + case MDU_Protection_reset_SN_ack: + LOGP(DV5MGMT, LOGL_NOTICE, "AN acknowledges reset serial numbers at Protection protocol.\n"); + break; + case MDU_Protection_reset_SN_error_ind: + LOGP(DV5MGMT, LOGL_NOTICE, "Switch over request failed, due to serial numbers reset at Protection " + "protocol.\n"); + break; + case MDU_Protection_protocol_error_ind: + if (cause_len < 1) + break; + LOGP(DV5MGMT, LOGL_ERROR, "Protocol error: %s.\n", + get_value_string(v5x_cause_type_str, cause[0] & 0x7f)); + if (cause_len > 1) + LOGP(DV5MGMT, LOGL_ERROR, " -> Diagnostic: %s\n", osmo_hexdump(cause + 1, cause_len - 1)); + break; + default: + LOGP(DV5MGMT, LOGL_ERROR, "Unknown message primitive %d.\n", prim); + } + + return 0; +} diff --git a/src/v5x_le_management.h b/src/v5x_le_management.h index 50d8f88..b10f7a6 100644 --- a/src/v5x_le_management.h +++ b/src/v5x_le_management.h @@ -1,7 +1,20 @@ void v5x_le_mgmt_init(void); -void v5x_mph_rcv_le(struct v5x_user_port *v5up, uint8_t prim, uint8_t *data, int length); -void v5x_mph_rcv_an(struct v5x_user_port *v5up, enum v5x_mph_prim prim, uint8_t perf_grading); -void v5x_nat_rcv_fe(struct v5x_user_port *v5up, struct msgb *msg); -void v5x_pstn_rcv_fe(struct v5x_user_port *v5up, enum v5x_fe_prim prim, struct msgb *msg); -void v5x_pstn_rcv_mdu(struct v5x_user_port *v5up, enum v5x_mgmt_prim prim); + +void v5x_le_common_ctrl_rcv(struct v5x_interface *v5if, uint8_t cfi, uint8_t variant, uint8_t rej_cause, + uint32_t interface_id); +void v5x_le_provisioning_start(struct v5x_interface *v5if); +void v5x_le_pstn_restart(struct v5x_interface *v5if); +void v5x_le_nat_ph_rcv(struct v5x_user_port *v5up, uint8_t prim, uint8_t *data, int length); +void v5x_le_port_mph_rcv(struct v5x_user_port *v5up, enum v5x_mph_prim prim, uint8_t perf_grading); +void v5x_le_nat_fe_rcv(struct v5x_user_port *v5up, struct msgb *msg); +void v5x_le_pstn_fe_rcv(struct v5x_user_port *v5up, enum v5x_fe_prim prim, struct msgb *msg); +void v5x_le_pstn_mdu_rcv(struct v5x_user_port *v5up, enum v5x_mgmt_prim prim); +void v52_le_lcp_mdu_rcv(struct v5x_link *v5l, enum v5x_mgmt_prim prim); +int v52_le_pp_mdu_rcv(struct v5x_interface *v5if, enum v5x_mgmt_prim prim, uint8_t link_id, uint8_t ts, + const uint8_t *cause, uint8_t cause_len); +void v5x_le_channel_assign(struct v5x_user_port *v5up, int channel); +void v5x_le_channel_unassign(struct v5x_user_port *v5up, int channel); +int v52_le_bcc_mdu_rcv(struct v5x_interface *v5if, uint8_t link_id, uint8_t ts, + uint8_t __attribute__((unused)) *isdn_multislot, enum v5x_mgmt_prim prim, const uint8_t *cause, + uint8_t cause_len); diff --git a/src/v5x_le_provisioning.c b/src/v5x_le_provisioning.c deleted file mode 100644 index f40cd74..0000000 --- a/src/v5x_le_provisioning.c +++ /dev/null @@ -1,90 +0,0 @@ -/* (C) 2022 by Andreas Eversberg - * - * 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. - * - */ - -#include -#include -#include - -#include "v5x_internal.h" -#include "v5x_protocol.h" -#include "v5x_le_ctrl_fsm.h" -#include "v5x_le_provisioning.h" -#include "logging.h" - -/* ITU-T G.964 Section 14.5 V5.1-re-provisioning procedures */ - -/* This is incomplete and very minimal */ - -void v5x_le_provisioning_init(void) -{ - LOGP(DV5PROV, LOGL_NOTICE, "Using V5x provisioning\n"); -} - - -/* messages from common control layer */ -void v5x_le_provisioning_rcv(struct v5x_interface *v5if, uint8_t cfi, uint8_t variant, uint8_t rej_cause, - uint32_t interface_id) -{ - LOGP(DV5PROV, LOGL_DEBUG, "Received common control message from control protocol. " - "(cfi = %d, variant = %d, rej_cause = %d, interface_id = %d)\n", cfi, variant, rej_cause, interface_id); - switch (cfi) { - case V5X_CTRL_ID_REQUEST_VARIANT_AND_INTERFACE_ID: - LOGP(DV5PROV, LOGL_INFO, "AN requests variant and interface ID, replying.\n"); - v5x_le_ctrl_common_snd(v5if, V5X_CTRL_ID_VARIANT_AND_INTERFACE_ID, NULL, &v5if->variant, &v5if->id); - break; - case V5X_CTRL_ID_RESTART_REQUEST: - LOGP(DV5PROV, LOGL_INFO, "AN requests restart, replying.\n"); - v5x_le_ctrl_common_snd(v5if, V5X_CTRL_ID_RESTART_COMPLETE, NULL, NULL, NULL); - break; - case V5X_CTRL_ID_VARIANT_AND_INTERFACE_ID: - LOGP(DV5PROV, LOGL_INFO, "AN replies variant and interface ID. (variant = %d, interface_id = %d)\n", - variant, interface_id); - if (variant != v5if->variant) - LOGP(DV5PROV, LOGL_ERROR, "Variant does not match: AN(%d) != LE(%d)\n", variant, v5if->variant); - if (interface_id != v5if->id) { - LOGP(DV5PROV, LOGL_ERROR, "Interface ID does not match: AN(%d) != LE(%d)\n", variant, - v5if->variant); - } - break; - case V5X_CTRL_ID_RESTART_COMPLETE: - LOGP(DV5PROV, LOGL_INFO, "AN replies restart.\n"); - break; - default: - LOGP(DV5PROV, LOGL_NOTICE, "Ignoring common control message with cfi = %d\n", cfi); - } -} - -/* perform provisioning */ -void v5x_le_provisioning_start(struct v5x_interface *v5if) -{ - /* ask for variant and interface ID */ - LOGP(DV5PROV, LOGL_INFO, "Requesting variant and interface ID.\n"); - v5x_le_ctrl_common_snd(v5if, V5X_CTRL_ID_REQUEST_VARIANT_AND_INTERFACE_ID, NULL, NULL, NULL); - -#if 0 - Do not send a restart, because it will make Fastlink reset the link after two minutes. - Also port states will not be indicted. (blocked/unblocked) - /* request a restart */ - LOGP(DV5PROV, LOGL_INFO, "Requesting restart.\n"); - v51_snd_ctrl_common(v5if, V51_CTRL_ID_RESTART_REQUEST, NULL, NULL, NULL); -#endif -} diff --git a/src/v5x_le_provisioning.h b/src/v5x_le_provisioning.h deleted file mode 100644 index 701e6c1..0000000 --- a/src/v5x_le_provisioning.h +++ /dev/null @@ -1,4 +0,0 @@ - -void v5x_le_provisioning_init(void); -void v5x_le_provisioning_rcv(struct v5x_interface *v5if, uint8_t cfi, uint8_t variant, uint8_t rej_cause, uint32_t interface_id); -void v5x_le_provisioning_start(struct v5x_interface *v5if);