diff --git a/src/lapv5.c b/src/lapv5.c index c67c815..a77d258 100644 --- a/src/lapv5.c +++ b/src/lapv5.c @@ -190,14 +190,7 @@ int lapv5_ph_data_ind(struct lapv5_instance *li, struct msgb *msg, int *error) /* write to PCAP file, if enabled. */ osmo_pcap_lapd_write(li->pcap_fd, OSMO_LAPD_PCAP_INPUT, msg); - if (!li->enabled) { - LOGLI(li, LOGL_DEBUG, "LAPV5 frame ignored, because DL is disabled.\n"); - msgb_free(msg); - return -EINVAL; - } - msgb_pull(msg, msg->l2h - msg->data); - LOGLI(li, LOGL_DEBUG, "RX: %s\n", osmo_hexdump(msg->data, msg->len)); if (msg->len < 2) { LOGLI(li, LOGL_ERROR, "LAPV5 frame receive len %d < 2, ignoring\n", msg->len); @@ -206,11 +199,20 @@ int lapv5_ph_data_ind(struct lapv5_instance *li, struct msgb *msg, int *error) return -EINVAL; }; + dladdr = ((msg->l2h[0] & 0xfe) << 5) | (msg->l2h[1] >> 1); + + if (!li->enabled) { + LOGLI(li, LOGL_NOTICE, "LAPV5 frame ignored, because DL is disabled.\n"); + if (dladdr == V5X_DLADDR_PSTN) + LOGLI(li, LOGL_NOTICE, "PLEASE ENABLE EARLY PSTN DATALINK ENABLE AT INTERFACE CONFIG!\n"); + msgb_free(msg); + return -EINVAL; + } + memset(&lctx, 0, sizeof(lctx)); i = 0; /* adress field */ - dladdr = ((msg->l2h[0] & 0xfe) << 5) | (msg->l2h[1] >> 1); lctx.lpd = 0; lctx.sapi = dladdr >> 7; lctx.tei = dladdr & 0x7f; @@ -591,6 +593,9 @@ void lapv5_set_enabled(struct lapv5_instance *li, bool enabled) { struct lapv5_sap *sap; + if (li->enabled == enabled) + return; + li->enabled = enabled; /* reset DL instances */ diff --git a/src/v5le_vty.c b/src/v5le_vty.c index c5b33df..74293b7 100644 --- a/src/v5le_vty.c +++ b/src/v5le_vty.c @@ -188,6 +188,7 @@ DEFUN(show_interface, show_interface_cmd, vty_out(vty, "Interface %d %s:%s", v5if->id, (v5if->dialect == V5X_DIALECT_V51) ? "V5.1" : "V5.2", VTY_NEWLINE); vty_out(vty, " Trigger system restart: %s%s", (v5if->mgmt->auto_restart) ? "automatic" : "manual", VTY_NEWLINE); vty_out(vty, " Trigger data links: %s%s", (v5if->mgmt->do_est) ? "yes" : "no", VTY_NEWLINE); + vty_out(vty, " Enable PSTN datalink: %s statup)%s", (v5if->mgmt->pstn_enable_early) ? "early (before" : "late (after", VTY_NEWLINE); vty_out(vty, " Trigger user port alignment: %s%s", (v5if->mgmt->do_align) ? "yes" : "no", VTY_NEWLINE); if (v5if->dialect == V5X_DIALECT_V52) vty_out(vty, " Accelerated alignment: %s%s", (v5if->mgmt->acc_align) ? "yes" : "no", VTY_NEWLINE); @@ -733,6 +734,16 @@ DEFUN(cfg_no_establish, cfg_no_establish_cmd, return CMD_SUCCESS; } +DEFUN(cfg_pstn_enable, cfg_pstn_enable_cmd, + "pstn-enable (early|late)", + "Enable PSTN datalink before or after startup.\nEnable datalink before startup\nEnable datalink after startup") +{ + struct v5x_interface *v5if = vty->index; + + v5if->mgmt->pstn_enable_early = (argv[0][0] == 'e'); + return CMD_SUCCESS; +} + DEFUN(cfg_alignment, cfg_alignment_cmd, "alignment", "Actively trigger alignment of user ports on startup") @@ -1155,6 +1166,7 @@ static void config_write_interface_v51(struct vty *vty, struct v5x_interface *v5 vty_out(vty, "interface %d v5.1%s", v5if->id, VTY_NEWLINE); vty_out(vty, " %sauto-restart%s", (v5if->mgmt->auto_restart) ? "" : "no ", VTY_NEWLINE); vty_out(vty, " %sestablish%s", (v5if->mgmt->do_est) ? "" : "no ", VTY_NEWLINE); + vty_out(vty, " pstn-enable %s %s", (v5if->mgmt->pstn_enable_early) ? "early" : "late", VTY_NEWLINE); vty_out(vty, " %salignment%s", (v5if->mgmt->do_align) ? "" : "no ", VTY_NEWLINE); vty_out(vty, " variant %d%s", v5if->variant, VTY_NEWLINE); vty_out(vty, " link%s", VTY_NEWLINE); @@ -1173,6 +1185,7 @@ static void config_write_interface_v52(struct vty *vty, struct v5x_interface *v5 vty_out(vty, "interface %d v5.2%s", v5if->id, VTY_NEWLINE); vty_out(vty, " %sauto-restart%s", (v5if->mgmt->auto_restart) ? "" : "no ", VTY_NEWLINE); vty_out(vty, " %sestablish%s", (v5if->mgmt->do_est) ? "" : "no ", VTY_NEWLINE); + vty_out(vty, " pstn-enable %s %s", (v5if->mgmt->pstn_enable_early) ? "early" : "late", VTY_NEWLINE); vty_out(vty, " %salignment%s", (v5if->mgmt->do_align) ? "" : "no ", VTY_NEWLINE); vty_out(vty, " %saccelerated-alignment%s", (v5if->mgmt->acc_align) ? "" : "no ", VTY_NEWLINE); vty_out(vty, " variant %d%s", v5if->variant, VTY_NEWLINE); @@ -1240,6 +1253,7 @@ int v5le_vty_init(void) install_element(CONFIG_INTERFACE_NODE_V51, &cfg_no_auto_restart_cmd); install_element(CONFIG_INTERFACE_NODE_V51, &cfg_establish_cmd); install_element(CONFIG_INTERFACE_NODE_V51, &cfg_no_establish_cmd); + install_element(CONFIG_INTERFACE_NODE_V51, &cfg_pstn_enable_cmd); install_element(CONFIG_INTERFACE_NODE_V51, &cfg_alignment_cmd); install_element(CONFIG_INTERFACE_NODE_V51, &cfg_no_alignment_cmd); install_element(CONFIG_INTERFACE_NODE_V51, &cfg_interface_variant_cmd); @@ -1254,6 +1268,7 @@ int v5le_vty_init(void) install_element(CONFIG_INTERFACE_NODE_V52, &cfg_no_auto_restart_cmd); install_element(CONFIG_INTERFACE_NODE_V52, &cfg_establish_cmd); install_element(CONFIG_INTERFACE_NODE_V52, &cfg_no_establish_cmd); + install_element(CONFIG_INTERFACE_NODE_V52, &cfg_pstn_enable_cmd); install_element(CONFIG_INTERFACE_NODE_V52, &cfg_alignment_cmd); install_element(CONFIG_INTERFACE_NODE_V52, &cfg_no_alignment_cmd); install_element(CONFIG_INTERFACE_NODE_V52, &cfg_accelerated_cmd); diff --git a/src/v5x_internal.h b/src/v5x_internal.h index 15ea647..8c03a84 100644 --- a/src/v5x_internal.h +++ b/src/v5x_internal.h @@ -279,6 +279,7 @@ struct v5x_pstn_proto { struct v5x_mgmt_proto { struct v5x_interface *interface; /* back-pointer to instance we're part of */ bool auto_restart; /* restart automatically after TC8/TC9 timeout */ + bool pstn_enable_early; /* enable datalink before startup */ bool pstn_rs_pending; /* pending restart flag */ bool do_est; /* actively establish datalinks */ bool do_align; /* actively perform alignment */ diff --git a/src/v5x_le_management.c b/src/v5x_le_management.c index 6176764..b54d22a 100644 --- a/src/v5x_le_management.c +++ b/src/v5x_le_management.c @@ -551,7 +551,7 @@ static void system_startup(struct v5x_mgmt_proto *mgmt) /* enable LAPV5 DLs except PSTN */ lapv5_set_enabled(v5if->control.li, true); if (v5if->pstn.li) - lapv5_set_enabled(v5if->pstn.li, false); + lapv5_set_enabled(v5if->pstn.li, mgmt->pstn_enable_early); if (v5if->lcp.li) lapv5_set_enabled(v5if->lcp.li, true); if (v5if->bcc.li) @@ -1014,6 +1014,11 @@ static void pstn_lepdl0_pstn_null(struct osmo_fsm_inst *fi, uint32_t event, void case V5X_LE_PSTN_DL_E_START: /* new state */ osmo_fsm_inst_state_chg(fi, V5X_LE_PSTN_DL_S_LEPDL1_ACTIVATE_PSTN, 0, 0); + /* if DL is already established */ + if (mgmt->pstn_enable_early && v5if->pstn.established) { + osmo_fsm_inst_dispatch(fi, V5X_LE_PSTN_DL_E_PSTN_DL_ESTABLISHED, NULL); + break; + } /* establish DL */ if (mgmt->do_est && !v5if->pstn.established) lapv5_dl_est_req(v5if->pstn.li, V5X_DLADDR_PSTN); @@ -1614,6 +1619,7 @@ struct v5x_mgmt_proto *v5x_le_mgmt_create(struct v5x_interface *v5if) return NULL; mgmt->interface = v5if; mgmt->auto_restart = true; + mgmt->pstn_enable_early = false; /* accellerated alignment when using V5.2 */ if (v5if->dialect == V5X_DIALECT_V52)