osmo-v5/src/v5le_vty.c

1261 lines
36 KiB
C

#include <osmocom/vty/command.h>
#include "v5x_internal.h"
#include "v5x_protocol.h"
#include "v5le_vty.h"
#include "v52_le_lcp_fsm.h"
#include "v52_le_pp_fsm.h"
#include "v5x_le_port_fsm.h"
#include "v5x_le_pstn_fsm.h"
#include "v5x_le_management.h"
#include "layer1.h"
#include "lapv5.h"
#include "../config.h"
extern struct v5x_instance *v5i;
enum v5_vty_node {
INTERFACE_NODE = _LAST_OSMOVTY_NODE + 1,
CONFIG_INTERFACE_NODE_V51,
CONFIG_INTERFACE_NODE_V52,
CONFIG_LINK_NODE,
CONFIG_PORT_NODE,
};
char if_prompt[64];
char conf_if_prompt[64];
char conf_link_prompt[64];
char conf_port_prompt[64];
static struct cmd_node interface_node = {
.node = INTERFACE_NODE,
.prompt = if_prompt,
.vtysh = 1,
};
static struct cmd_node config_interface_node_v51 = {
.node = CONFIG_INTERFACE_NODE_V51,
.prompt = conf_if_prompt,
.vtysh = 1,
};
static struct cmd_node config_interface_node_v52 = {
.node = CONFIG_INTERFACE_NODE_V52,
.prompt = conf_if_prompt,
.vtysh = 1,
};
static struct cmd_node config_link_node = {
.node = CONFIG_LINK_NODE,
.prompt = conf_link_prompt,
.vtysh = 1,
};
static struct cmd_node config_port_node = {
.node = CONFIG_PORT_NODE,
.prompt = conf_port_prompt,
.vtysh = 1,
};
static int v5le_vty_is_config_node(struct vty __attribute__((unused)) *vty, int node)
{
switch (node) {
case INTERFACE_NODE:
case CONFIG_NODE:
return 0;
default:
return 1;
}
}
static int v5le_vty_go_parent(struct vty *vty)
{
struct v5x_interface *v5if;
struct v5x_link *v5l;
struct v5x_user_port *v5up;
switch (vty->node) {
case CONFIG_PORT_NODE:
v5up = vty->index;
v5if = v5up->interface;
vty->node = (v5if->dialect == V5X_DIALECT_V51) ? CONFIG_INTERFACE_NODE_V51 : CONFIG_INTERFACE_NODE_V52;
vty->index = v5if;
break;
case CONFIG_LINK_NODE:
v5l = vty->index;
v5if = v5l->interface;
vty->node = (v5if->dialect == V5X_DIALECT_V51) ? CONFIG_INTERFACE_NODE_V51 : CONFIG_INTERFACE_NODE_V52;
vty->index = v5if;
break;
case CONFIG_INTERFACE_NODE_V51:
case CONFIG_INTERFACE_NODE_V52:
vty->node = CONFIG_NODE;
vty->index = NULL;
break;
default:
vty->node = ENABLE_NODE;
vty->index = NULL;
}
return vty->node;
}
struct vty_app_info vty_info = {
.name = "OsmoV5LE",
.version = PACKAGE_VERSION,
.go_parent_cb = v5le_vty_go_parent,
.is_config_node = v5le_vty_is_config_node,
};
/*
* show
*/
static const char *link_status(bool established, struct lapv5_instance *li)
{
if (!li->enabled)
return "disabled";
if (!established)
return "down";
return "up";
}
DEFUN(interface, interface_cmd,
"interface <0-16777215>",
"Select given interface\n" "Interface ID")
{
struct v5x_interface *v5if, *found = NULL;
uint32_t id = atoi(argv[0]);
if (llist_empty(&v5i->interfaces)) {
vty_out(vty, "%%No interface created!%s", VTY_NEWLINE);
return CMD_WARNING;
}
llist_for_each_entry(v5if, &v5i->interfaces, list) {
if (v5if->id == id)
found = v5if;
}
v5if = found;
if (!v5if) {
vty_out(vty, "Interface does not exist.%s", VTY_NEWLINE);
return CMD_WARNING;
}
sprintf(if_prompt, "%%s(interface-%d)# ", v5if->id);
vty->node = INTERFACE_NODE;
vty->index = v5if;
return CMD_SUCCESS;
}
DEFUN(show_interface, show_interface_cmd,
"show interface",
SHOW_STR "Show interface and states")
{
struct v5x_interface *v5if = vty->index;
struct v5x_link *v5l;
struct v5x_user_port *v5up;
int calls;
if (!v5if) {
vty_out(vty, "No interface exists.%s", VTY_NEWLINE);
return CMD_WARNING;
}
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, " 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);
if (v5if->control.li)
vty_out(vty, " Control data link: %s%s", link_status(v5if->control.established, v5if->control.li),
VTY_NEWLINE);
if (v5if->pstn.li)
vty_out(vty, " PSTN data link: %s%s", link_status(v5if->pstn.established, v5if->pstn.li), VTY_NEWLINE);
if (v5if->lcp.li)
vty_out(vty, " LCP data link: %s%s", link_status(v5if->lcp.established, v5if->lcp.li), VTY_NEWLINE);
if (v5if->bcc.li)
vty_out(vty, " BCC data link: %s%s", link_status(v5if->bcc.established, v5if->bcc.li), VTY_NEWLINE);
if (v5if->protection.li[0])
vty_out(vty, " Protection data link (primary): %s%s",
link_status(v5if->protection.established[0], v5if->protection.li[0]), VTY_NEWLINE);
if (v5if->protection.li[1])
vty_out(vty, " Protection data link (secondary): %s%s",
link_status(v5if->protection.established[1], v5if->protection.li[1]), VTY_NEWLINE);
vty_out(vty, " System startup state: %s%s", v5x_le_system_fsm_state_name(v5if->mgmt->system_fi), VTY_NEWLINE);
vty_out(vty, " PSTN data link startup state: %s%s", v5x_le_pstn_dl_fsm_state_name(v5if->mgmt->pstn_dl_fi),
VTY_NEWLINE);
vty_out(vty, " PSTN restart state: %s%s", v5x_le_pstn_rs_fsm_state_name(v5if->mgmt->pstn_rs_fi), VTY_NEWLINE);
if (v5if->dialect == V5X_DIALECT_V52) {
vty_out(vty, " Unblock all PSTN/ISDN state: %s%s",
v5x_le_unblk_all_fsm_state_name(v5if->mgmt->unblk_all_fi[UNBLK_ALL_PSTN_ISDN]), VTY_NEWLINE);
vty_out(vty, " Unblock all PSTN state: %s%s",
v5x_le_unblk_all_fsm_state_name(v5if->mgmt->unblk_all_fi[UNBLK_ALL_PSTN]), VTY_NEWLINE);
vty_out(vty, " Unblock all ISDN state: %s%s",
v5x_le_unblk_all_fsm_state_name(v5if->mgmt->unblk_all_fi[UNBLK_ALL_ISDN]), VTY_NEWLINE);
vty_out(vty, " Block all PSTN state: %s%s",
v5x_le_unblk_all_fsm_state_name(v5if->mgmt->unblk_all_fi[BLK_ALL_PSTN]), VTY_NEWLINE);
vty_out(vty, " Block all ISDN state: %s%s",
v5x_le_unblk_all_fsm_state_name(v5if->mgmt->unblk_all_fi[BLK_ALL_ISDN]), VTY_NEWLINE);
}
if (!v5if->id_remote_valid)
vty_out(vty, " ID: local: %d remote: unknown%s", v5if->id, VTY_NEWLINE);
else
vty_out(vty, " ID: local: %d remote: %d%s%s", v5if->id, v5if->id_remote,
(v5if->id != v5if->id_remote) ? " (mismatching)" : "", VTY_NEWLINE);
if (!v5if->variant_remote_valid)
vty_out(vty, " Variant: local: %d remote: unknown%s", v5if->variant, VTY_NEWLINE);
else
vty_out(vty, " Variant: local: %d remote: %d%s%s", v5if->variant, v5if->variant_remote,
(v5if->variant != v5if->variant_remote) ? " (mismatching)" : "", VTY_NEWLINE);
if (v5if->dialect == V5X_DIALECT_V52) {
vty_out(vty, " Link IDs:");
llist_for_each_entry(v5l, &v5if->links, list)
vty_out(vty, " %d", v5l->id);
vty_out(vty, VTY_NEWLINE);
if (v5if->primary_link)
vty_out(vty, " Primary link ID: %d%s", v5if->primary_link->id, VTY_NEWLINE);
if (v5if->secondary_link)
vty_out(vty, " Secondary link ID: %d%s", v5if->secondary_link->id, VTY_NEWLINE);
if (v5if->cc_link)
vty_out(vty, " Current C-Channel data link ID: %d%s", v5if->cc_link->id, VTY_NEWLINE);
}
calls = 0;
llist_for_each_entry(v5up, &v5if->user_ports, list) {
if (v5up->ts[0] && v5up->ts[0]->b_activated)
calls++;
if (v5up->ts[1] && v5up->ts[1]->b_activated)
calls++;
}
vty_out(vty, " Active calls (B-channels): %d%s", calls, VTY_NEWLINE);
return CMD_SUCCESS;
}
DEFUN(show_link, show_link_cmd,
"show link",
SHOW_STR "Show links and states")
{
struct v5x_interface *v5if = vty->index;
struct v5x_link *v5l;
struct v5x_user_port *v5up;
int t;
if (!v5if)
return CMD_WARNING;
if (llist_empty(&v5if->links)) {
vty_out(vty, "%%No link created!%s", VTY_NEWLINE);
return CMD_WARNING;
}
llist_for_each_entry(v5l, &v5if->links, list) {
if (v5if->dialect == V5X_DIALECT_V51)
vty_out(vty, "Link:%s", VTY_NEWLINE);
else
vty_out(vty, "Link ID %d:", v5l->id);
if (v5if->dialect == V5X_DIALECT_V52) {
vty_out(vty, " State=%s", v52_le_lcp_state_name(v5l->fi));
vty_out(vty, " L1=%s%s", v5x_l1_fsm_state_name(v5l->l1), VTY_NEWLINE);
}
for (t = 0; t < 32; t++) {
if (v5l->c_channel[0].ts && v5l->c_channel[0].ts->nr == t) {
vty_out(vty, " TS %2d: signaling channel 1%s", t, VTY_NEWLINE);
continue;
}
if (v5l->c_channel[1].ts && v5l->c_channel[1].ts->nr == t) {
vty_out(vty, " TS %2d: signaling channel 2%s", t, VTY_NEWLINE);
continue;
}
if (v5l->c_channel[2].ts && v5l->c_channel[2].ts->nr == t) {
vty_out(vty, " TS %2d: signaling channel 3%s", t, VTY_NEWLINE);
continue;
}
if (v5l->ts[t].b_channel) {
if ((v5up = v5l->ts[t].v5up))
vty_out(vty, " TS %2d: %s-%d %s%s", t,
(v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr,
(v5l->ts[t].b_activated) ? "(active)": "", VTY_NEWLINE);
}
}
}
return CMD_SUCCESS;
}
static void print_port_channel(struct vty *vty, enum v5x_dialect dialect, const char *bchan, struct v5x_timeslot *ts)
{
if (dialect == V5X_DIALECT_V51)
vty_out(vty, " Channel%s: TS %d %s%s", bchan, ts->nr,
(ts->b_activated) ? "(active)": "", VTY_NEWLINE);
else
vty_out(vty, " Channel%s: link %d TS %d %s%s", bchan, ts->link->id, ts->nr,
(ts->b_activated) ? "(active)": "", VTY_NEWLINE);
}
static void print_port(struct vty *vty, struct v5x_user_port *v5up)
{
if (v5up->type == V5X_USER_TYPE_PSTN) {
vty_out(vty, "PSTN port nr %d:", v5up->nr);
vty_out(vty, " Port state=%s;", v5x_le_port_pstn_state_name(v5up->port_fi));
vty_out(vty, " PSTN state=%s%s", v5x_le_pstn_state_name(v5up->pstn.proto), VTY_NEWLINE);
if (v5up->ts[0])
print_port_channel(vty, v5up->interface->dialect, "", v5up->ts[0]);
} else {
vty_out(vty, "ISDN port nr %d:", v5up->nr);
vty_out(vty, " Port state=%s%s", v5x_le_port_isdn_state_name(v5up->port_fi), VTY_NEWLINE);
if (v5up->ts[0])
print_port_channel(vty, v5up->interface->dialect, " B1", v5up->ts[0]);
if (v5up->ts[1])
print_port_channel(vty, v5up->interface->dialect, " B2", v5up->ts[1]);
}
}
#define SHOW_PORT "Show given user port and states\n"
DEFUN(show_port_pstn, show_port_pstn_cmd,
"show port pstn <0-32767>",
SHOW_STR SHOW_PORT "Show given PSTN user port and states\n" "L3 address")
{
struct v5x_interface *v5if = vty->index;
struct v5x_user_port *v5up;
if (!v5if)
return CMD_WARNING;
v5up = v5x_user_port_find(v5if, atoi(argv[0]), false);
if (!v5up) {
vty_out(vty, "%%Given PSTN user port does not exist.%s", VTY_NEWLINE);
return CMD_WARNING;
}
print_port(vty, v5up);
return CMD_SUCCESS;
}
DEFUN(show_port_isdn, show_port_isdn_cmd,
"show port isdn <0-8175>",
SHOW_STR SHOW_PORT "Show given ISDN user port and states\n" "L3 address")
{
struct v5x_interface *v5if = vty->index;
struct v5x_user_port *v5up;
if (!v5if)
return CMD_WARNING;
v5up = v5x_user_port_find(v5if, atoi(argv[0]), true);
if (!v5up) {
vty_out(vty, "%%Given ISDN user port does not exist.%s", VTY_NEWLINE);
return CMD_WARNING;
}
print_port(vty, v5up);
return CMD_SUCCESS;
}
DEFUN(show_port, show_port_cmd,
"show port",
SHOW_STR "Show all user ports and states")
{
struct v5x_interface *v5if = vty->index;
struct v5x_user_port *v5up;
if (!v5if)
return CMD_WARNING;
if (llist_empty(&v5if->user_ports)) {
vty_out(vty, "%%No user port created!%s", VTY_NEWLINE);
return CMD_WARNING;
}
llist_for_each_entry(v5up, &v5if->user_ports, list)
print_port(vty, v5up);
return CMD_SUCCESS;
}
/*
* operate
*/
DEFUN(system_restart, system_restart_cmd,
"system-restart",
"Perform system startup/restart")
{
struct v5x_interface *v5if = vty->index;
int rc;
if (!v5if)
return CMD_WARNING;
rc = v5x_le_mgmt_start(v5if);
if (rc < 0) {
vty_out(vty, "%%System is not in right state.%s", VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(pstn_restart, pstn_restart_cmd,
"pstn-restart",
"Perform PSTN protocol restart")
{
struct v5x_interface *v5if = vty->index;
int rc;
if (!v5if)
return CMD_WARNING;
rc = v5x_le_pstn_restart(v5if);
if (rc < 0) {
vty_out(vty, "%%System is not in right state.%s", VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(align_ports, align_ports_cmd,
"align-ports [accelerated]",
"Perform alignment of all ports (sync (un)blocked state)")
{
struct v5x_interface *v5if = vty->index;
int accelerated = 0;
int rc;
if (!v5if)
return CMD_WARNING;
if (argc >= 1)
accelerated = 1;
rc = v5x_le_align_ports(v5if, accelerated);
if (rc < 0) {
vty_out(vty, "%%System is not in right state.%s", VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(switchover, switchover_cmd,
"switch-over <0-255>",
"Perform switch-over to given link\n" "Link ID")
{
struct v5x_interface *v5if = vty->index;
struct v5x_link *v5l;
if (!v5if)
return CMD_WARNING;
if (v5if->dialect != V5X_DIALECT_V52) {
vty_out(vty, "%%This command is only applicable to V5.2 interface.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v5l = v5x_link_find_id(v5if, atoi(argv[0]));
if (!v5l) {
vty_out(vty, "%%Given link does not exist.%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (v5l != v5if->primary_link && v5l != v5if->secondary_link) {
vty_out(vty, "%%Given link is not primary, nor secondary.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v52_le_pp_mdu_snd(v5if, MDU_Protection_switch_over_com, atoi(argv[0]), v5l->c_channel[0].ts->nr, 0);
return CMD_SUCCESS;
}
#define PERF_UBLK "Perform unblocking\n"
#define PERF_BLK "Perform blocking\n"
DEFUN(unblock_link, unblock_link_cmd,
"unblock link <0-255>",
PERF_UBLK "Perform unblocking of link\n" "Link ID")
{
struct v5x_interface *v5if = vty->index;
struct v5x_link *v5l;
if (!v5if)
return CMD_WARNING;
if (v5if->dialect != V5X_DIALECT_V52) {
vty_out(vty, "%%This command is only applicable to V5.2 interface.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v5l = v5x_link_find_id(v5if, atoi(argv[0]));
if (!v5l) {
vty_out(vty, "%%Given link does not exist.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v52_le_lcp_mdu_snd(v5l, MDU_LUBR);
return CMD_SUCCESS;
}
DEFUN(block_link, block_link_cmd,
"block link <0-255>",
PERF_BLK "Perform blocking of link\n" "Link ID")
{
struct v5x_interface *v5if = vty->index;
struct v5x_link *v5l;
if (!v5if)
return CMD_WARNING;
if (v5if->dialect != V5X_DIALECT_V52) {
vty_out(vty, "%%This command is only applicable to V5.2 interface.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v5l = v5x_link_find_id(v5if, atoi(argv[0]));
if (!v5l) {
vty_out(vty, "%%Given link does not exist.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v52_le_lcp_mdu_snd(v5l, MDU_LBI);
return CMD_SUCCESS;
}
DEFUN(unblock_pstn_port, unblock_pstn_port_cmd,
"unblock pstn <0-32767>",
PERF_UBLK "Perform unblocking of PSTN port\n" "L3 address")
{
struct v5x_interface *v5if = vty->index;
struct v5x_user_port *v5up;
if (!v5if)
return CMD_WARNING;
v5up = v5x_user_port_find(v5if, atoi(argv[0]), false);
if (!v5up) {
vty_out(vty, "%%Given PSTN user port does not exist.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v5x_le_mgmt_port_unblock(v5up);
return CMD_SUCCESS;
}
DEFUN(block_pstn_port, block_pstn_port_cmd,
"block pstn <0-32767>",
PERF_BLK "Perform blocking of PSTN port\n" "L3 address")
{
struct v5x_interface *v5if = vty->index;
struct v5x_user_port *v5up;
if (!v5if)
return CMD_WARNING;
v5up = v5x_user_port_find(v5if, atoi(argv[0]), false);
if (!v5up) {
vty_out(vty, "%%Given PSTN user port does not exist.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v5x_le_mgmt_port_block(v5up);
return CMD_SUCCESS;
}
DEFUN(unblock_isdn_port, unblock_isdn_port_cmd,
"unblock isdn <0-8175>",
PERF_UBLK "Perform unblocking of ISDN port\n" "L3 address")
{
struct v5x_interface *v5if = vty->index;
struct v5x_user_port *v5up;
if (!v5if)
return CMD_WARNING;
v5up = v5x_user_port_find(v5if, atoi(argv[0]), true);
if (!v5up) {
vty_out(vty, "%%Given ISDN user port does not exist.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v5x_le_mgmt_port_unblock(v5up);
return CMD_SUCCESS;
}
DEFUN(block_isdn_port, block_isdn_port_cmd,
"block isdn <0-8175>",
PERF_BLK "Perform blocking of ISDN port\n" "L3 address")
{
struct v5x_interface *v5if = vty->index;
struct v5x_user_port *v5up;
if (!v5if)
return CMD_WARNING;
v5up = v5x_user_port_find(v5if, atoi(argv[0]), true);
if (!v5up) {
vty_out(vty, "%%Given ISDN user port does not exist.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v5x_le_mgmt_port_block(v5up);
return CMD_SUCCESS;
}
/*
* configure
*/
DEFUN(cfg_interface, cfg_interface_cmd,
"interface <0-16777215> [(v5.1|v5.2)]",
"Configure V5 interface\n" "Interface ID\n" "Configure as V5.1 interface\n" "Configure as V5.2 interface")
{
struct v5x_interface *v5if, *found = NULL;
enum v5x_dialect dialect = V5X_DIALECT_V51;
uint32_t id = atoi(argv[0]);
llist_for_each_entry(v5if, &v5i->interfaces, list) {
if (v5if->id == id)
found = v5if;
}
v5if = found;
if (argc < 2) {
if (!v5if) {
vty_out(vty, "%%Interface not created, Add v5.1 or v5.2 after this command.%s", VTY_NEWLINE);
return CMD_WARNING;
}
dialect = v5if->dialect;
} else {
if (!strcasecmp(argv[1], "v5.2"))
dialect = V5X_DIALECT_V52;
}
if (!v5if) {
v5if = v5x_interface_alloc(v5i, id, dialect);
if (!v5if) {
vty_out(vty, "%%Failed to create interface. See logging output.%s", VTY_NEWLINE);
return CMD_WARNING;
}
} else if (dialect != v5if->dialect) {
vty_out(vty, "%%Different interface type already created. To change, remove first.%s", VTY_NEWLINE);
}
sprintf(conf_if_prompt, "%%s(config-interface-%d)# ", v5if->id);
vty->node = (v5if->dialect == V5X_DIALECT_V51) ? CONFIG_INTERFACE_NODE_V51 : CONFIG_INTERFACE_NODE_V52;
vty->index = v5if;
return CMD_SUCCESS;
}
DEFUN(cfg_no_interface, cfg_no_interface_cmd,
"no interface <0-16777215>",
NO_STR "Remove V5 interface\n" "Interface ID")
{
struct v5x_interface *v5if, *found = NULL;
uint32_t id = atoi(argv[0]);
llist_for_each_entry(v5if, &v5i->interfaces, list) {
if (v5if->id == id)
found = v5if;
}
v5if = found;
if (!v5if) {
vty_out(vty, "%%Interface does not exist.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v5x_interface_free(v5if);
return CMD_SUCCESS;
}
DEFUN(cfg_auto_restart, cfg_auto_restart_cmd,
"auto-restart",
"Automatically restart interface in case of failure")
{
struct v5x_interface *v5if = vty->index;
v5if->mgmt->auto_restart = true;
return CMD_SUCCESS;
}
DEFUN(cfg_no_auto_restart, cfg_no_auto_restart_cmd,
"no auto-restart",
NO_STR "Automatically restart interface in case of failure")
{
struct v5x_interface *v5if = vty->index;
v5if->mgmt->auto_restart = false;
return CMD_SUCCESS;
}
DEFUN(cfg_establish, cfg_establish_cmd,
"establish",
"Actively establish and re-establish data link layer")
{
struct v5x_interface *v5if = vty->index;
v5if->mgmt->do_est = true;
return CMD_SUCCESS;
}
DEFUN(cfg_no_establish, cfg_no_establish_cmd,
"no establish",
NO_STR "Let the remote side establish and re-establish data link layer")
{
struct v5x_interface *v5if = vty->index;
v5if->mgmt->do_est = false;
return CMD_SUCCESS;
}
DEFUN(cfg_alignment, cfg_alignment_cmd,
"alignment",
"Actively trigger alignment of user ports on startup")
{
struct v5x_interface *v5if = vty->index;
v5if->mgmt->do_align = true;
return CMD_SUCCESS;
}
DEFUN(cfg_no_alignment, cfg_no_alignment_cmd,
"no alignment",
NO_STR "Let the remote side do the alignment of user ports on startup")
{
struct v5x_interface *v5if = vty->index;
v5if->mgmt->do_align = false;
return CMD_SUCCESS;
}
DEFUN(cfg_accelerated, cfg_accelerated_cmd,
"accelerated-alignment",
"Use accelerated alignment to block/unblock user ports")
{
struct v5x_interface *v5if = vty->index;
v5if->mgmt->acc_align = true;
return CMD_SUCCESS;
}
DEFUN(cfg_no_accelerated, cfg_no_accelerated_cmd,
"no accelerated-alignment",
NO_STR "Use individual alignment to block/unblock user ports")
{
struct v5x_interface *v5if = vty->index;
v5if->mgmt->acc_align = false;
return CMD_SUCCESS;
}
DEFUN(cfg_interface_variant, cfg_interface_variant_cmd,
"variant <0-127>",
"Set interface provisioning variant\n" "Variant value")
{
struct v5x_interface *v5if = vty->index;
v5if->variant = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_interface_cc_id, cfg_interface_cc_id_cmd,
"cc-id <0-65535>",
"Set protection CC-ID\n" "CC-ID value")
{
struct v5x_interface *v5if = vty->index;
v5if->protection.cc_id = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_interface_capability, cfg_interface_capability_cmd,
"information-transfer-capability <0-31>",
"Enable information transfer capability with ISDN port allocation\n" "Information transfer capability")
{
struct v5x_interface *v5if = vty->index;
v5if->use_capability = true;
v5if->capability = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_interface_no_capability, cfg_interface_no_capability_cmd,
"no information-transfer-capability",
NO_STR "Disable information transfer capability with ISDN port allocation")
{
struct v5x_interface *v5if = vty->index;
v5if->use_capability = false;
return CMD_SUCCESS;
}
DEFUN(cfg_link_v51, cfg_link_cmd_v51,
"link",
"Modify link")
{
struct v5x_interface *v5if = vty->index;
struct v5x_link *v5l;
v5l = llist_first_entry(&v5if->links, struct v5x_link, list);
sprintf(conf_link_prompt, "%%s(config-link-%d)# ", v5l->id);
vty->node = CONFIG_LINK_NODE;
vty->index = v5l;
return CMD_SUCCESS;
}
DEFUN(cfg_link_v52, cfg_link_cmd_v52,
"link <0-255>",
"Add or modify link\n" "Link ID to create or modify")
{
struct v5x_interface *v5if = vty->index;
struct v5x_link *v5l;
v5l = v5x_link_find_id(v5if, atoi(argv[0]));
if (!v5l) {
v5l = v5x_link_create(v5if, atoi(argv[0]));
if (!v5l) {
vty_out(vty, "%%Failed to create link. See logging output.%s", VTY_NEWLINE);
return CMD_WARNING;
}
}
sprintf(conf_link_prompt, "%%s(config-link-%d)# ", v5l->id);
vty->node = CONFIG_LINK_NODE;
vty->index = v5l;
return CMD_SUCCESS;
}
DEFUN(cfg_no_link_v52, cfg_no_link_cmd_v52,
"no link <0-255>",
NO_STR "Remove link from interface\n" "Link ID to remove")
{
struct v5x_interface *v5if = vty->index;
struct v5x_link *v5l;
int rc;
v5l = v5x_link_find_id(v5if, atoi(argv[0]));
if (!v5l) {
vty_out(vty, "%%Given link with ID %d is not created.%s", atoi(argv[0]), VTY_NEWLINE);
return CMD_WARNING;
}
rc = v5x_link_destroy(v5l);
if (rc < 0) {
vty_out(vty, "%%Given link with ID %d cannot be deleted, see debug output.%s", atoi(argv[0]),
VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(cfg_e1_line, cfg_e1_line_cmd,
"e1 line <0-255>",
"E1 configuration\n" "E1 line configuration\n" "E1 line number to use for link")
{
struct v5x_interface *search_v5if;
struct v5x_link *v5l = vty->index, *search_v5l;
struct e1inp_line *e1_line;
unsigned int num = atoi(argv[0]);
/* nothing has changed, same line number */
if (v5l->e1_line && v5l->e1_line->num == num)
return CMD_SUCCESS;
/* is there someone using this line already? */
llist_for_each_entry(search_v5if, &v5i->interfaces, list) {
llist_for_each_entry(search_v5l, &search_v5if->links, list) {
if (!search_v5l->e1_line)
continue;
if (search_v5l->e1_line->num == num) {
vty_out(vty, "%%E1 line %d already used by interface %d / link ID %d.%s", num,
search_v5if->id, search_v5l->id, VTY_NEWLINE);
return CMD_WARNING;
}
}
}
/* remove line, if attached */
if (v5l->e1_line)
e1_line_exit(v5l);
/* add line, if created */
e1_line = e1_line_init(v5l, num);
if (!e1_line) {
vty_out(vty, "%%E1 line %d is not created. Please create it first.%s", num, VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(cfg_no_e1_line, cfg_no_e1_line_cmd,
"no e1 line",
NO_STR "E1 configuration\n" "Remove E1 line from link")
{
struct v5x_link *v5l = vty->index;
/* remove line, if attached */
if (v5l->e1_line)
e1_line_exit(v5l);
return CMD_SUCCESS;
}
DEFUN(cfg_port_pstn_v51, cfg_port_pstn_cmd_v51,
"port pstn <0-32767> <1-31>",
"Create/modify V5 user port\n" "PSTN user port\n" "L3 address\n" "Time slot")
{
struct v5x_interface *v5if = vty->index;
struct v5x_user_port *v5up;
v5up = v5x_user_port_find(v5if, atoi(argv[0]), false);
if (v5up) {
vty_out(vty, "%%Given PSTN user port already exists.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v5up = v5x_user_port_create(v5if, atoi(argv[0]), V5X_USER_TYPE_PSTN, atoi(argv[1]), 0);
if (!v5up) {
vty_out(vty, "%%Failed to create PSTN user port. See logging output.%s", VTY_NEWLINE);
return CMD_WARNING;
}
sprintf(conf_port_prompt, "%%s(config-port-pstn-%d)# ", v5up->nr);
vty->node = CONFIG_PORT_NODE;
vty->index = v5up;
return CMD_SUCCESS;
}
DEFUN(cfg_port_pstn, cfg_port_pstn_cmd,
"port pstn <0-32767>",
"Create/modify V5 user port\n" "PSTN user port\n" "L3 address")
{
struct v5x_interface *v5if = vty->index;
struct v5x_user_port *v5up;
v5up = v5x_user_port_find(v5if, atoi(argv[0]), false);
if (!v5up) {
if (v5if->dialect == V5X_DIALECT_V51) {
vty_out(vty, "%%Given PSTN user port does not exist, give time slot.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v5up = v5x_user_port_create(v5if, atoi(argv[0]), V5X_USER_TYPE_PSTN, 0, 0);
}
if (!v5up) {
vty_out(vty, "%%Failed to create PSTN user port. See logging output.%s", VTY_NEWLINE);
return CMD_WARNING;
}
sprintf(conf_port_prompt, "%%s(config-port-pstn-%d)# ", v5up->nr);
vty->node = CONFIG_PORT_NODE;
vty->index = v5up;
return CMD_SUCCESS;
}
DEFUN(cfg_no_port_pstn, cfg_no_port_pstn_cmd,
"no port pstn <0-32767>",
NO_STR "Delete V5 user port\n" "PSTN user port\n" "L3 address")
{
struct v5x_interface *v5if = vty->index;
struct v5x_user_port *v5up;
v5up = v5x_user_port_find(v5if, atoi(argv[0]), false);
if (!v5up) {
vty_out(vty, "%%Given PSTN user port does not exist.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v5x_user_port_destroy(v5up);
return CMD_SUCCESS;
}
DEFUN(cfg_port_isdn_v51, cfg_port_isdn_cmd_v51,
"port isdn <0-8175> <1-31> <1-31>",
"Create/modify V5 user port\n" "ISDN user port\n" "L3 address\n" "Time slot 1\n" "Time slot 2")
{
struct v5x_interface *v5if = vty->index;
struct v5x_user_port *v5up;
v5up = v5x_user_port_find(v5if, atoi(argv[0]), true);
if (v5up) {
vty_out(vty, "%%Given ISDN user port already exists.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v5up = v5x_user_port_create(v5if, atoi(argv[0]), V5X_USER_TYPE_ISDN, atoi(argv[1]), atoi(argv[2]));
if (!v5up) {
vty_out(vty, "%%Failed to create ISDN user port. See logging output.%s", VTY_NEWLINE);
return CMD_WARNING;
}
sprintf(conf_port_prompt, "%%s(config-port-isdn-%d)# ", v5up->nr);
vty->node = CONFIG_PORT_NODE;
vty->index = v5up;
return CMD_SUCCESS;
}
DEFUN(cfg_port_isdn, cfg_port_isdn_cmd,
"port isdn <0-8175>",
"Create/modify V5 user port\n" "ISDN user port\n" "L3 address")
{
struct v5x_interface *v5if = vty->index;
struct v5x_user_port *v5up;
v5up = v5x_user_port_find(v5if, atoi(argv[0]), true);
if (!v5up) {
if (v5if->dialect == V5X_DIALECT_V51) {
vty_out(vty, "%%Given ISDN user port does not exist, give time slots.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v5up = v5x_user_port_create(v5if, atoi(argv[0]), V5X_USER_TYPE_ISDN, 0, 0);
}
if (!v5up) {
vty_out(vty, "%%Failed to create ISDN user port. See logging output.%s", VTY_NEWLINE);
return CMD_WARNING;
}
sprintf(conf_port_prompt, "%%s(config-port-isdn-%d)# ", v5up->nr);
vty->node = CONFIG_PORT_NODE;
vty->index = v5up;
return CMD_SUCCESS;
}
DEFUN(cfg_no_port_isdn, cfg_no_port_isdn_cmd,
"no port isdn <0-8175>",
NO_STR "Delete V5 user port\n" "ISDN user port\n" "L3 address")
{
struct v5x_interface *v5if = vty->index;
struct v5x_user_port *v5up;
v5up = v5x_user_port_find(v5if, atoi(argv[0]), true);
if (!v5up) {
vty_out(vty, "%%Given ISDN user port does not exist.%s", VTY_NEWLINE);
return CMD_WARNING;
}
v5x_user_port_destroy(v5up);
return CMD_SUCCESS;
}
DEFUN(cfg_echo_can, cfg_echo_can_cmd,
"line-echo-canceler",
"Enable line echo canceler for all calls")
{
struct v5x_user_port *v5up = vty->index;
v5up->use_line_echo = USE_ECHO_CANCELER;
if (v5up->ts[0] && v5up->ts[0]->b_activated)
v5x_echo_reset(&v5up->ep[0], v5up->use_line_echo);
if (v5up->ts[1] && v5up->ts[1]->b_activated)
v5x_echo_reset(&v5up->ep[1], v5up->use_line_echo);
return CMD_SUCCESS;
}
DEFUN(cfg_no_echo_can, cfg_no_echo_can_cmd,
"no line-echo-canceler",
NO_STR "Disable line echo canceler for all calls")
{
struct v5x_user_port *v5up = vty->index;
v5up->use_line_echo = 0;
if (v5up->ts[0] && v5up->ts[0]->b_activated)
v5x_echo_reset(&v5up->ep[0], v5up->use_line_echo);
if (v5up->ts[1] && v5up->ts[1]->b_activated)
v5x_echo_reset(&v5up->ep[1], v5up->use_line_echo);
return CMD_SUCCESS;
}
DEFUN(cfg_echo_sup, cfg_echo_sup_cmd,
"line-echo-suppressor",
"Enable line echo suppressor for all calls")
{
struct v5x_user_port *v5up = vty->index;
v5up->use_line_echo = USE_ECHO_SUPPRESSOR;
if (v5up->ts[0] && v5up->ts[0]->b_activated)
v5x_echo_reset(&v5up->ep[0], v5up->use_line_echo);
if (v5up->ts[1] && v5up->ts[1]->b_activated)
v5x_echo_reset(&v5up->ep[1], v5up->use_line_echo);
return CMD_SUCCESS;
}
DEFUN(cfg_no_echo_sup, cfg_no_echo_sup_cmd,
"no line-echo-suppressor",
NO_STR "Disable line echo suppressor for all calls")
{
struct v5x_user_port *v5up = vty->index;
v5up->use_line_echo = 0;
if (v5up->ts[0] && v5up->ts[0]->b_activated)
v5x_echo_reset(&v5up->ep[0], v5up->use_line_echo);
if (v5up->ts[1] && v5up->ts[1]->b_activated)
v5x_echo_reset(&v5up->ep[1], v5up->use_line_echo);
return CMD_SUCCESS;
}
/*
* write
*/
static void config_write_user_port(struct vty *vty, struct v5x_interface *v5if)
{
struct v5x_user_port *v5up;
llist_for_each_entry(v5up, &v5if->user_ports, list) {
switch (v5up->type) {
case V5X_USER_TYPE_PSTN:
if (v5if->dialect == V5X_DIALECT_V51)
vty_out(vty, " port pstn %d %d%s", v5up->nr, v5up->ts[0]->nr, VTY_NEWLINE);
else
vty_out(vty, " port pstn %d%s", v5up->nr, VTY_NEWLINE);
break;
case V5X_USER_TYPE_ISDN:
if (v5if->dialect == V5X_DIALECT_V51)
vty_out(vty, " port isdn %d %d %d%s", v5up->nr, v5up->ts[0]->nr, v5up->ts[1]->nr,
VTY_NEWLINE);
else
vty_out(vty, " port isdn %d%s", v5up->nr, VTY_NEWLINE);
break;
}
if (v5up->use_line_echo == USE_ECHO_CANCELER)
vty_out(vty, " line-echo-canceler%s", VTY_NEWLINE);
if (v5up->use_line_echo == USE_ECHO_SUPPRESSOR)
vty_out(vty, " line-echo-suppressor%s", VTY_NEWLINE);
}
}
static void config_write_interface_v51(struct vty *vty, struct v5x_interface *v5if)
{
struct v5x_link *v5l;
vty_out(vty, "!%s", VTY_NEWLINE);
v5l = llist_first_entry(&v5if->links, struct v5x_link, list);
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, " %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);
if (!v5l->e1_line)
vty_out(vty, " no e1 line%s", VTY_NEWLINE);
else
vty_out(vty, " e1 line %d%s", v5l->e1_line->num, VTY_NEWLINE);
config_write_user_port(vty, v5if);
}
static void config_write_interface_v52(struct vty *vty, struct v5x_interface *v5if)
{
struct v5x_link *v5l;
vty_out(vty, "!%s", VTY_NEWLINE);
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, " %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);
vty_out(vty, " cc-id %d%s", v5if->protection.cc_id, VTY_NEWLINE);
if (v5if->use_capability)
vty_out(vty, " information-transfer-capability %d%s", v5if->capability, VTY_NEWLINE);
else
vty_out(vty, " no information-transfer-capability%s", VTY_NEWLINE);
llist_for_each_entry(v5l, &v5if->links, list) {
vty_out(vty, " link %d%s", v5l->id, VTY_NEWLINE);
if (v5l == v5if->primary_link)
vty_out(vty, " # primary%s", VTY_NEWLINE);
if (v5l == v5if->secondary_link)
vty_out(vty, " # secondary%s", VTY_NEWLINE);
if (!v5l->e1_line)
vty_out(vty, " no e1 line%s", VTY_NEWLINE);
else
vty_out(vty, " e1 line %d%s", v5l->e1_line->num, VTY_NEWLINE);
}
config_write_user_port(vty, v5if);
}
static int config_write_interfaces(struct vty *vty)
{
struct v5x_interface *v5if = NULL;
llist_for_each_entry(v5if, &v5i->interfaces, list) {
if (v5if->dialect == V5X_DIALECT_V51)
config_write_interface_v51(vty, v5if);
else
config_write_interface_v52(vty, v5if);
}
return CMD_SUCCESS;
}
/*
* init
*/
int v5le_vty_init(void)
{
install_element(ENABLE_NODE, &interface_cmd);
install_node(&interface_node, NULL);
install_element(INTERFACE_NODE, &show_interface_cmd);
install_element(INTERFACE_NODE, &show_link_cmd);
install_element(INTERFACE_NODE, &show_port_cmd);
install_element(INTERFACE_NODE, &show_port_pstn_cmd);
install_element(INTERFACE_NODE, &show_port_isdn_cmd);
install_element(INTERFACE_NODE, &system_restart_cmd);
install_element(INTERFACE_NODE, &pstn_restart_cmd);
install_element(INTERFACE_NODE, &align_ports_cmd);
install_element(INTERFACE_NODE, &switchover_cmd);
install_element(INTERFACE_NODE, &unblock_link_cmd);
install_element(INTERFACE_NODE, &block_link_cmd);
install_element(INTERFACE_NODE, &unblock_pstn_port_cmd);
install_element(INTERFACE_NODE, &block_pstn_port_cmd);
install_element(INTERFACE_NODE, &unblock_isdn_port_cmd);
install_element(INTERFACE_NODE, &block_isdn_port_cmd);
install_element(CONFIG_NODE, &cfg_interface_cmd);
install_element(CONFIG_NODE, &cfg_no_interface_cmd);
install_node(&config_interface_node_v51, config_write_interfaces);
install_node(&config_interface_node_v52, NULL);
install_element(CONFIG_INTERFACE_NODE_V51, &cfg_auto_restart_cmd);
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_alignment_cmd);
install_element(CONFIG_INTERFACE_NODE_V51, &cfg_no_alignment_cmd);
install_element(CONFIG_INTERFACE_NODE_V51, &cfg_interface_variant_cmd);
install_element(CONFIG_INTERFACE_NODE_V51, &cfg_link_cmd_v51);
install_element(CONFIG_INTERFACE_NODE_V51, &cfg_port_pstn_cmd_v51);
install_element(CONFIG_INTERFACE_NODE_V51, &cfg_port_pstn_cmd);
install_element(CONFIG_INTERFACE_NODE_V51, &cfg_no_port_pstn_cmd);
install_element(CONFIG_INTERFACE_NODE_V51, &cfg_port_isdn_cmd_v51);
install_element(CONFIG_INTERFACE_NODE_V51, &cfg_port_isdn_cmd);
install_element(CONFIG_INTERFACE_NODE_V51, &cfg_no_port_isdn_cmd);
install_element(CONFIG_INTERFACE_NODE_V52, &cfg_auto_restart_cmd);
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_alignment_cmd);
install_element(CONFIG_INTERFACE_NODE_V52, &cfg_no_alignment_cmd);
install_element(CONFIG_INTERFACE_NODE_V52, &cfg_accelerated_cmd);
install_element(CONFIG_INTERFACE_NODE_V52, &cfg_no_accelerated_cmd);
install_element(CONFIG_INTERFACE_NODE_V52, &cfg_interface_variant_cmd);
install_element(CONFIG_INTERFACE_NODE_V52, &cfg_interface_cc_id_cmd);
install_element(CONFIG_INTERFACE_NODE_V52, &cfg_interface_capability_cmd);
install_element(CONFIG_INTERFACE_NODE_V52, &cfg_interface_no_capability_cmd);
install_element(CONFIG_INTERFACE_NODE_V52, &cfg_link_cmd_v52);
install_element(CONFIG_INTERFACE_NODE_V52, &cfg_no_link_cmd_v52);
install_element(CONFIG_INTERFACE_NODE_V52, &cfg_port_pstn_cmd);
install_element(CONFIG_INTERFACE_NODE_V52, &cfg_no_port_pstn_cmd);
install_element(CONFIG_INTERFACE_NODE_V52, &cfg_port_isdn_cmd);
install_element(CONFIG_INTERFACE_NODE_V52, &cfg_no_port_isdn_cmd);
install_node(&config_link_node, NULL);
install_element(CONFIG_LINK_NODE, &cfg_e1_line_cmd);
install_element(CONFIG_LINK_NODE, &cfg_no_e1_line_cmd);
install_node(&config_port_node, NULL);
install_element(CONFIG_PORT_NODE, &cfg_echo_can_cmd);
install_element(CONFIG_PORT_NODE, &cfg_no_echo_can_cmd);
install_element(CONFIG_PORT_NODE, &cfg_echo_sup_cmd);
install_element(CONFIG_PORT_NODE, &cfg_no_echo_sup_cmd);
return 0;
}