9
0
Fork 0

mgcp: Introduce multiple virtual trunks

A virtual trunk is identified by a virtual domain name.
This commit is contained in:
Holger Hans Peter Freyther 2011-09-14 19:14:54 +02:00
parent 96cc57af80
commit f574cec745
7 changed files with 236 additions and 283 deletions

View File

@ -122,6 +122,7 @@ struct mgcp_trunk_config {
struct mgcp_endpoint *endpoints; struct mgcp_endpoint *endpoints;
/* Special MGW handling */ /* Special MGW handling */
char *virtual_domain;
int target_trunk_start; int target_trunk_start;
int vad_enabled; int vad_enabled;
@ -165,7 +166,7 @@ struct mgcp_config {
void *data; void *data;
/* trunk handling */ /* trunk handling */
struct mgcp_trunk_config trunk; struct llist_head vtrunks;
struct llist_head trunks; struct llist_head trunks;
/* only used for start with a static configuration */ /* only used for start with a static configuration */

View File

@ -154,7 +154,9 @@ static inline int endp_back_channel(int endpoint)
} }
struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index); struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
struct mgcp_trunk_config *mgcp_vtrunk_alloc(struct mgcp_config *cfg, const char *);
struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index); struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
struct mgcp_trunk_config *mgcp_trunk_domain(struct mgcp_config *cfg, const char *);
void mgcp_trunk_free(struct mgcp_trunk_config *cfg); void mgcp_trunk_free(struct mgcp_trunk_config *cfg);

View File

@ -28,6 +28,7 @@
enum ss7_vty_node { enum ss7_vty_node {
MGCP_NODE = _LAST_OSMOVTY_NODE + 1, MGCP_NODE = _LAST_OSMOVTY_NODE + 1,
TRUNK_NODE, TRUNK_NODE,
VTRUNK_NODE,
CELLMGR_NODE, CELLMGR_NODE,
SS7_NODE, SS7_NODE,
LINKSETS_NODE, LINKSETS_NODE,

View File

@ -308,6 +308,27 @@ static struct mgcp_endpoint *find_e1_endpoint(struct mgcp_config *cfg,
return &tcfg->endpoints[endp]; return &tcfg->endpoints[endp];
} }
struct mgcp_endpoint *find_virtual_endpoint(struct mgcp_config *cfg,
const char *endptr, int gw)
{
struct mgcp_trunk_config *tcfg;
if (gw <= 0)
return NULL;
llist_for_each_entry(tcfg, &cfg->vtrunks, entry) {
if (strcmp(&endptr[1], tcfg->virtual_domain) != 0)
continue;
if (gw >= tcfg->number_endpoints)
return NULL;
return &tcfg->endpoints[gw];
}
return NULL;
}
static struct mgcp_endpoint *find_endpoint(struct mgcp_config *cfg, const char *mgcp) static struct mgcp_endpoint *find_endpoint(struct mgcp_config *cfg, const char *mgcp)
{ {
struct mgcp_endpoint *endp = NULL; struct mgcp_endpoint *endp = NULL;
@ -318,8 +339,7 @@ static struct mgcp_endpoint *find_endpoint(struct mgcp_config *cfg, const char *
endp = find_e1_endpoint(cfg, mgcp); endp = find_e1_endpoint(cfg, mgcp);
} else { } else {
gw = strtoul(mgcp, &endptr, 16); gw = strtoul(mgcp, &endptr, 16);
if (gw > 0 && gw < cfg->trunk.number_endpoints && strcmp(endptr, "@mgw") == 0) endp = find_virtual_endpoint(cfg, endptr, gw);
endp = &cfg->trunk.endpoints[gw];
} }
if (!endp) { if (!endp) {
@ -908,11 +928,7 @@ struct mgcp_config *mgcp_config_alloc(void)
cfg->net_ports.base_port = RTP_PORT_NET_DEFAULT; cfg->net_ports.base_port = RTP_PORT_NET_DEFAULT;
/* default trunk handling */ /* default trunk handling */
cfg->trunk.cfg = cfg; INIT_LLIST_HEAD(&cfg->vtrunks);
cfg->trunk.trunk_nr = 0;
cfg->trunk.trunk_type = MGCP_TRUNK_VIRTUAL;
trunk_init(&cfg->trunk);
INIT_LLIST_HEAD(&cfg->trunks); INIT_LLIST_HEAD(&cfg->trunks);
return cfg; return cfg;
@ -937,6 +953,32 @@ struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int nr)
return trunk; return trunk;
} }
struct mgcp_trunk_config *mgcp_vtrunk_alloc(struct mgcp_config *cfg,
const char *domain)
{
struct mgcp_trunk_config *trunk;
trunk = talloc_zero(cfg, struct mgcp_trunk_config);
if (!trunk) {
LOGP(DMGCP, LOGL_ERROR, "Failed to allocate.\n");
return NULL;
}
trunk->virtual_domain = talloc_strdup(trunk, domain);
if (!trunk->virtual_domain) {
LOGP(DMGCP, LOGL_ERROR, "Failed to allocate.\n");
talloc_free(trunk);
return NULL;
}
trunk->cfg = cfg;
trunk->trunk_type = MGCP_TRUNK_VIRTUAL;
trunk->trunk_nr = 0;
trunk_init(trunk);
llist_add_tail(&trunk->entry, &cfg->vtrunks);
return trunk;
}
void mgcp_trunk_free(struct mgcp_trunk_config *cfg) void mgcp_trunk_free(struct mgcp_trunk_config *cfg)
{ {
llist_del(&cfg->entry); llist_del(&cfg->entry);
@ -954,6 +996,18 @@ struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index)
return NULL; return NULL;
} }
struct mgcp_trunk_config *mgcp_trunk_domain(struct mgcp_config *cfg,
const char *domain)
{
struct mgcp_trunk_config *trunk;
llist_for_each_entry(trunk, &cfg->vtrunks, entry)
if (strcmp(trunk->virtual_domain, domain) == 0)
return trunk;
return NULL;
}
static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end) static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end)
{ {
if (end->local_alloc == PORT_ALLOC_DYNAMIC) { if (end->local_alloc == PORT_ALLOC_DYNAMIC) {

View File

@ -36,6 +36,7 @@
/* MGW changes */ /* MGW changes */
extern void mgcp_write_extra(struct vty *vty, struct mgcp_config *cfg); extern void mgcp_write_extra(struct vty *vty, struct mgcp_config *cfg);
extern void mgcp_write_trunk_extra(struct vty *vty, struct mgcp_trunk_config *cfg); extern void mgcp_write_trunk_extra(struct vty *vty, struct mgcp_trunk_config *cfg);
extern void mgcp_write_vtrunk_extra(struct vty *vty, struct mgcp_trunk_config *cfg);
static int allocate_endpoints(struct mgcp_trunk_config *tcfg); static int allocate_endpoints(struct mgcp_trunk_config *tcfg);
@ -43,6 +44,7 @@ enum node_type mgcp_go_parent(struct vty *vty)
{ {
switch (vty->node) { switch (vty->node) {
case TRUNK_NODE: case TRUNK_NODE:
case VTRUNK_NODE:
vty->node = MGCP_NODE; vty->node = MGCP_NODE;
break; break;
default: default:
@ -88,14 +90,15 @@ static void bsc_replace_string(void *ctx, char **dst, const char *newstr)
struct mgcp_config *g_cfg = NULL; struct mgcp_config *g_cfg = NULL;
static struct mgcp_trunk_config *find_trunk(struct mgcp_config *cfg, int nr) static struct mgcp_trunk_config *find_trunk(struct mgcp_config *cfg,
const char *type, const char *name)
{ {
struct mgcp_trunk_config *trunk; struct mgcp_trunk_config *trunk;
if (nr == 0) if (strcmp(type, "virtual") == 0)
trunk = &cfg->trunk; trunk = mgcp_trunk_domain(cfg, name);
else else
trunk = mgcp_trunk_num(cfg, nr); trunk = mgcp_trunk_num(cfg, atoi(name));
return trunk; return trunk;
} }
@ -109,6 +112,12 @@ struct cmd_node mgcp_node = {
1, 1,
}; };
struct cmd_node vtrunk_node = {
VTRUNK_NODE,
"%s(vtrunk)#",
1,
};
struct cmd_node trunk_node = { struct cmd_node trunk_node = {
TRUNK_NODE, TRUNK_NODE,
"%s(trunk)#", "%s(trunk)#",
@ -138,14 +147,6 @@ static int config_write_mgcp(struct vty *vty)
g_cfg->net_ports.range_start, g_cfg->net_ports.range_end, VTY_NEWLINE); g_cfg->net_ports.range_start, g_cfg->net_ports.range_end, VTY_NEWLINE);
vty_out(vty, " rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE); vty_out(vty, " rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE);
if (g_cfg->trunk.audio_payload != -1)
vty_out(vty, " sdp audio payload number %d%s",
g_cfg->trunk.audio_payload, VTY_NEWLINE);
if (g_cfg->trunk.audio_name)
vty_out(vty, " sdp audio payload name %s%s",
g_cfg->trunk.audio_name, VTY_NEWLINE);
vty_out(vty, " loop %u%s", !!g_cfg->trunk.audio_loop, VTY_NEWLINE);
vty_out(vty, " number endpoints %u%s", g_cfg->trunk.number_endpoints - 1, VTY_NEWLINE);
if (g_cfg->call_agent_addr) if (g_cfg->call_agent_addr)
vty_out(vty, " call agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE); vty_out(vty, " call agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
if (g_cfg->transcoder_ip) if (g_cfg->transcoder_ip)
@ -159,7 +160,6 @@ static int config_write_mgcp(struct vty *vty)
vty_out(vty, " transcoder-remote-base %u%s", g_cfg->transcoder_remote_base, VTY_NEWLINE); vty_out(vty, " transcoder-remote-base %u%s", g_cfg->transcoder_remote_base, VTY_NEWLINE);
mgcp_write_extra(vty, g_cfg); mgcp_write_extra(vty, g_cfg);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -197,7 +197,8 @@ DEFUN(show_mcgp, show_mgcp_cmd, "show mgcp",
{ {
struct mgcp_trunk_config *trunk; struct mgcp_trunk_config *trunk;
dump_trunk(vty, &g_cfg->trunk); llist_for_each_entry(trunk, &g_cfg->vtrunks, entry)
dump_trunk(vty, trunk);
llist_for_each_entry(trunk, &g_cfg->trunks, entry) llist_for_each_entry(trunk, &g_cfg->trunks, entry)
dump_trunk(vty, trunk); dump_trunk(vty, trunk);
@ -372,47 +373,21 @@ ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
"Set the IP_TOS socket attribute on the RTP/RTCP sockets.\n" "The DSCP value.") "Set the IP_TOS socket attribute on the RTP/RTCP sockets.\n" "The DSCP value.")
DEFUN(cfg_mgcp_sdp_payload_number, DEFUN(cfg_vtrunk_number_endp,
cfg_mgcp_sdp_payload_number_cmd, cfg_vtrunk_number_endp_cmd,
"sdp audio payload number <1-255>",
"Set the audio codec to use")
{
unsigned int payload = atoi(argv[0]);
g_cfg->trunk.audio_payload = payload;
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_sdp_payload_name,
cfg_mgcp_sdp_payload_name_cmd,
"sdp audio payload name NAME",
"Set the audio name to use")
{
bsc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_loop,
cfg_mgcp_loop_cmd,
"loop (0|1)",
"Loop the audio")
{
g_cfg->trunk.audio_loop = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_number_endp,
cfg_mgcp_number_endp_cmd,
"number endpoints <0-65534>", "number endpoints <0-65534>",
"The number of endpoints to allocate. This is not dynamic.") "The number of endpoints to allocate. This is not dynamic.")
{ {
if (g_cfg->trunk.endpoints) { struct mgcp_trunk_config *trunk = vty->index;
if (trunk->endpoints) {
vty_out(vty, "Can not change size.%s", VTY_NEWLINE); vty_out(vty, "Can not change size.%s", VTY_NEWLINE);
return CMD_WARNING; return CMD_WARNING;
} }
/* + 1 as we start counting at one */ /* + 1 as we start counting at one */
g_cfg->trunk.number_endpoints = atoi(argv[0]) + 1; trunk->number_endpoints = atoi(argv[0]) + 1;
if (allocate_endpoints(&g_cfg->trunk) != 0) { if (allocate_endpoints(trunk) != 0) {
vty_out(vty, "Can not allocate endpoints.%s", VTY_NEWLINE); vty_out(vty, "Can not allocate endpoints.%s", VTY_NEWLINE);
return CMD_WARNING; return CMD_WARNING;
} }
@ -464,6 +439,27 @@ DEFUN(cfg_mgcp_transcoder_remote_base,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(cfg_mgcp_vtrunk, cfg_mgcp_vtrunk_cmd,
"vtrunk NAME",
"Configure a Virtual Trunk\n" "Domain Name\n")
{
struct mgcp_trunk_config *trunk;
trunk = mgcp_trunk_domain(g_cfg, argv[0]);
if (!trunk)
trunk = mgcp_vtrunk_alloc(g_cfg, argv[0]);
if (!trunk) {
vty_out(vty, "%%Unable to allocate trunk %s.%s",
argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
vty->node = VTRUNK_NODE;
vty->index = trunk;
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd, DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
"trunk <1-64>", "trunk <1-64>",
"Configure a SS7 trunk\n" "Trunk Nr\n") "Configure a SS7 trunk\n" "Trunk Nr\n")
@ -493,19 +489,39 @@ DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
static void config_write_trunk_common(struct vty *vty,
struct mgcp_trunk_config *tcfg)
{
vty_out(vty, " sdp audio payload number %d%s",
tcfg->audio_payload, VTY_NEWLINE);
vty_out(vty, " sdp audio payload name %s%s",
tcfg->audio_name, VTY_NEWLINE);
vty_out(vty, " loop %d%s",
tcfg->audio_loop, VTY_NEWLINE);
}
static int config_write_trunk(struct vty *vty) static int config_write_trunk(struct vty *vty)
{ {
struct mgcp_trunk_config *trunk; struct mgcp_trunk_config *trunk;
llist_for_each_entry(trunk, &g_cfg->trunks, entry) { llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE); vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
vty_out(vty, " sdp audio payload number %d%s", config_write_trunk_common(vty, trunk);
trunk->audio_payload, VTY_NEWLINE); mgcp_write_trunk_extra(vty, trunk);
vty_out(vty, " sdp audio payload name %s%s", }
trunk->audio_name, VTY_NEWLINE);
vty_out(vty, " loop %d%s",
trunk->audio_loop, VTY_NEWLINE);
return CMD_SUCCESS;
}
static int config_write_vtrunk(struct vty *vty)
{
struct mgcp_trunk_config *trunk;
llist_for_each_entry(trunk, &g_cfg->vtrunks, entry) {
vty_out(vty, " vtrunk %s%s", trunk->virtual_domain, VTY_NEWLINE);
vty_out(vty, " number endpoints %d%s",
trunk->number_endpoints - 1, VTY_NEWLINE);
config_write_trunk_common(vty, trunk);
mgcp_write_trunk_extra(vty, trunk); mgcp_write_trunk_extra(vty, trunk);
} }
@ -546,16 +562,21 @@ DEFUN(cfg_trunk_loop,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
#define TRUNK_TYPE_STR "Virtual trunk\nE1 trunk\n"
#define TRUNK_IDENT_STR "Trunk identifier depending on the type\n"
DEFUN(loop_endp, DEFUN(loop_endp,
loop_endp_cmd, loop_endp_cmd,
"loop-endpoint <0-64> NAME (0|1)", "loop-endpoint (virtual|e1) IDENT NAME (0|1)",
"Loop a given endpoint\n" "Trunk number\n" "Loop a given endpoint\n"
TRUNK_TYPE_STR
TRUNK_IDENT_STR
"The name in hex of the endpoint\n" "Disable the loop\n" "Enable the loop\n") "The name in hex of the endpoint\n" "Disable the loop\n" "Enable the loop\n")
{ {
struct mgcp_trunk_config *trunk; struct mgcp_trunk_config *trunk;
struct mgcp_endpoint *endp; struct mgcp_endpoint *endp;
trunk = find_trunk(g_cfg, atoi(argv[0])); trunk = find_trunk(g_cfg, argv[0], argv[1]);
if (!trunk) { if (!trunk) {
vty_out(vty, "%%Trunk %d not found in the config.%s", vty_out(vty, "%%Trunk %d not found in the config.%s",
atoi(argv[0]), VTY_NEWLINE); atoi(argv[0]), VTY_NEWLINE);
@ -568,7 +589,7 @@ DEFUN(loop_endp,
return CMD_WARNING; return CMD_WARNING;
} }
int endp_no = strtoul(argv[1], NULL, 16); int endp_no = strtoul(argv[2], NULL, 16);
if (endp_no < 1 || endp_no >= trunk->number_endpoints) { if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
vty_out(vty, "Loopback number %s/%d is invalid.%s", vty_out(vty, "Loopback number %s/%d is invalid.%s",
argv[1], endp_no, VTY_NEWLINE); argv[1], endp_no, VTY_NEWLINE);
@ -577,7 +598,7 @@ DEFUN(loop_endp,
endp = &trunk->endpoints[endp_no]; endp = &trunk->endpoints[endp_no];
int loop = atoi(argv[2]); int loop = atoi(argv[3]);
if (loop) if (loop)
endp->conn_mode = MGCP_CONN_LOOPBACK; endp->conn_mode = MGCP_CONN_LOOPBACK;
@ -590,8 +611,10 @@ DEFUN(loop_endp,
DEFUN(tap_call, DEFUN(tap_call,
tap_call_cmd, tap_call_cmd,
"tap-call <0-64> ENDPOINT (bts-in|bts-out|net-in|net-out) A.B.C.D <0-65534>", "tap-call (virtual|e1) IDENT ENDPOINT (bts-in|bts-out|net-in|net-out) A.B.C.D <0-65534>",
"Forward data on endpoint to a different system\n" "Trunk number\n" "Forward data on endpoint to a different system\n"
TRUNK_TYPE_STR
TRUNK_IDENT_STR
"The endpoint in hex\n" "The endpoint in hex\n"
"Forward the data coming from the bts\n" "Forward the data coming from the bts\n"
"Forward the data coming from the bts leaving to the network\n" "Forward the data coming from the bts leaving to the network\n"
@ -604,10 +627,10 @@ DEFUN(tap_call,
struct mgcp_endpoint *endp; struct mgcp_endpoint *endp;
int port = 0; int port = 0;
trunk = find_trunk(g_cfg, atoi(argv[0])); trunk = find_trunk(g_cfg, argv[0], argv[1]);
if (!trunk) { if (!trunk) {
vty_out(vty, "%%Trunk %d not found in the config.%s", vty_out(vty, "%%Trunk %d not found in the config.%s",
atoi(argv[0]), VTY_NEWLINE); atoi(argv[1]), VTY_NEWLINE);
return CMD_WARNING; return CMD_WARNING;
} }
@ -617,7 +640,7 @@ DEFUN(tap_call,
return CMD_WARNING; return CMD_WARNING;
} }
int endp_no = strtoul(argv[1], NULL, 16); int endp_no = strtoul(argv[2], NULL, 16);
if (endp_no < 1 || endp_no >= trunk->number_endpoints) { if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
vty_out(vty, "Endpoint number %s/%d is invalid.%s", vty_out(vty, "Endpoint number %s/%d is invalid.%s",
argv[1], endp_no, VTY_NEWLINE); argv[1], endp_no, VTY_NEWLINE);
@ -626,13 +649,13 @@ DEFUN(tap_call,
endp = &trunk->endpoints[endp_no]; endp = &trunk->endpoints[endp_no];
if (strcmp(argv[2], "bts-in") == 0) { if (strcmp(argv[3], "bts-in") == 0) {
port = MGCP_TAP_BTS_IN; port = MGCP_TAP_BTS_IN;
} else if (strcmp(argv[2], "bts-out") == 0) { } else if (strcmp(argv[3], "bts-out") == 0) {
port = MGCP_TAP_BTS_OUT; port = MGCP_TAP_BTS_OUT;
} else if (strcmp(argv[2], "net-in") == 0) { } else if (strcmp(argv[3], "net-in") == 0) {
port = MGCP_TAP_NET_IN; port = MGCP_TAP_NET_IN;
} else if (strcmp(argv[2], "net-out") == 0) { } else if (strcmp(argv[3], "net-out") == 0) {
port = MGCP_TAP_NET_OUT; port = MGCP_TAP_NET_OUT;
} else { } else {
vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE); vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
@ -641,24 +664,26 @@ DEFUN(tap_call,
tap = &endp->taps[port]; tap = &endp->taps[port];
memset(&tap->forward, 0, sizeof(tap->forward)); memset(&tap->forward, 0, sizeof(tap->forward));
inet_aton(argv[3], &tap->forward.sin_addr); inet_aton(argv[4], &tap->forward.sin_addr);
tap->forward.sin_port = htons(atoi(argv[4])); tap->forward.sin_port = htons(atoi(argv[5]));
tap->enabled = 1; tap->enabled = 1;
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(free_endp, free_endp_cmd, DEFUN(free_endp, free_endp_cmd,
"free-endpoint <0-64> NUMBER", "free-endpoint (virtual|e1) IDENT NUMBER",
"Free the given endpoint\n" "Trunk number\n" "Free the given endpoint\n"
TRUNK_TYPE_STR
TRUNK_IDENT_STR
"Endpoint number in hex.\n") "Endpoint number in hex.\n")
{ {
struct mgcp_trunk_config *trunk; struct mgcp_trunk_config *trunk;
struct mgcp_endpoint *endp; struct mgcp_endpoint *endp;
trunk = find_trunk(g_cfg, atoi(argv[0])); trunk = find_trunk(g_cfg, argv[0], argv[1]);
if (!trunk) { if (!trunk) {
vty_out(vty, "%%Trunk %d not found in the config.%s", vty_out(vty, "%%Trunk %d not found in the config.%s",
atoi(argv[0]), VTY_NEWLINE); atoi(argv[1]), VTY_NEWLINE);
return CMD_WARNING; return CMD_WARNING;
} }
@ -668,7 +693,7 @@ DEFUN(free_endp, free_endp_cmd,
return CMD_WARNING; return CMD_WARNING;
} }
int endp_no = strtoul(argv[1], NULL, 16); int endp_no = strtoul(argv[2], NULL, 16);
if (endp_no < 1 || endp_no >= trunk->number_endpoints) { if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
vty_out(vty, "Endpoint number %s/%d is invalid.%s", vty_out(vty, "Endpoint number %s/%d is invalid.%s",
argv[1], endp_no, VTY_NEWLINE); argv[1], endp_no, VTY_NEWLINE);
@ -711,10 +736,16 @@ int mgcp_vty_init(void)
install_element(MGCP_NODE, &cfg_mgcp_transcoder_cmd); install_element(MGCP_NODE, &cfg_mgcp_transcoder_cmd);
install_element(MGCP_NODE, &cfg_mgcp_no_transcoder_cmd); install_element(MGCP_NODE, &cfg_mgcp_no_transcoder_cmd);
install_element(MGCP_NODE, &cfg_mgcp_transcoder_remote_base_cmd); install_element(MGCP_NODE, &cfg_mgcp_transcoder_remote_base_cmd);
install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd);
install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd); install_element(MGCP_NODE, &cfg_mgcp_vtrunk_cmd);
install_element(MGCP_NODE, &cfg_mgcp_loop_cmd); install_node(&vtrunk_node, config_write_vtrunk);
install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd); install_default(VTRUNK_NODE);
install_element(VTRUNK_NODE, &ournode_exit_cmd);
install_element(VTRUNK_NODE, &ournode_end_cmd);
install_element(VTRUNK_NODE, &cfg_vtrunk_number_endp_cmd);
install_element(VTRUNK_NODE, &cfg_trunk_payload_number_cmd);
install_element(VTRUNK_NODE, &cfg_trunk_payload_name_cmd);
install_element(VTRUNK_NODE, &cfg_trunk_loop_cmd);
install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd); install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
install_node(&trunk_node, config_write_trunk); install_node(&trunk_node, config_write_trunk);
@ -821,9 +852,12 @@ int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg)
g_cfg->last_bts_port = rtp_calculate_port(0, g_cfg->bts_ports.base_port); g_cfg->last_bts_port = rtp_calculate_port(0, g_cfg->bts_ports.base_port);
g_cfg->last_net_port = rtp_calculate_port(0, g_cfg->net_ports.base_port); g_cfg->last_net_port = rtp_calculate_port(0, g_cfg->net_ports.base_port);
if (configure_endpoints(&g_cfg->trunk) != 0) { llist_for_each_entry(trunk, &g_cfg->vtrunks, entry) {
LOGP(DMGCP, LOGL_ERROR, "Failed to initialize the virtual trunk.\n"); if (configure_endpoints(trunk) != 0) {
return -1; LOGP(DMGCP, LOGL_ERROR,
"Failed to initialize virtual trunk %s.\n", trunk->virtual_domain);
return -1;
}
} }
llist_for_each_entry(trunk, &g_cfg->trunks, entry) { llist_for_each_entry(trunk, &g_cfg->trunks, entry) {

View File

@ -700,7 +700,7 @@ static int configure_trunk(struct mgcp_trunk_config *tcfg, int *dsp_resource)
static struct mgcp_ss7 *mgcp_ss7_init(struct mgcp_config *cfg) static struct mgcp_ss7 *mgcp_ss7_init(struct mgcp_config *cfg)
{ {
struct mgcp_trunk_config *trunk; struct mgcp_trunk_config *trunk;
int dsp_resource, i; int dsp_resource;
struct mgcp_ss7 *conf = talloc_zero(NULL, struct mgcp_ss7); struct mgcp_ss7 *conf = talloc_zero(NULL, struct mgcp_ss7);
if (!conf) if (!conf)
@ -731,8 +731,8 @@ static struct mgcp_ss7 *mgcp_ss7_init(struct mgcp_config *cfg)
/* Now do the init of the trunks */ /* Now do the init of the trunks */
dsp_resource = 0; dsp_resource = 0;
for (i = 1; i < cfg->trunk.number_endpoints; ++i) { llist_for_each_entry(trunk, &cfg->vtrunks, entry) {
if (configure_trunk(&cfg->trunk, &dsp_resource) != 0) { if (configure_trunk(trunk, &dsp_resource) != 0) {
talloc_free(conf); talloc_free(conf);
return NULL; return NULL;
} }
@ -780,8 +780,9 @@ void mgcp_ss7_reset(struct mgcp_ss7 *mgcp)
LOGP(DMGCP, LOGL_INFO, "Resetting all endpoints.\n"); LOGP(DMGCP, LOGL_INFO, "Resetting all endpoints.\n");
/* free UniPorte and MGCP data */ /* free UniPorte and MGCP data */
free_trunk(&mgcp->cfg->trunk);
llist_for_each_entry(trunk, &mgcp->cfg->vtrunks, entry)
free_trunk(trunk);
llist_for_each_entry(trunk, &mgcp->cfg->trunks, entry) llist_for_each_entry(trunk, &mgcp->cfg->trunks, entry)
free_trunk(trunk); free_trunk(trunk);
} }

View File

@ -46,160 +46,27 @@ DEFUN(cfg_mgcp_configure, cfg_mgcp_configure_cmd,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(cfg_mgcp_vad, cfg_mgcp_vad_cmd, DEFUN(cfg_vtrunk_target_trunk, cfg_vtrunk_target_trunk_cmd,
"vad (enabled|disabled)",
"Enable the Voice Activity Detection\n"
"Enable\n" "Disable\n")
{
if (argv[0][0] == 'e')
g_cfg->trunk.vad_enabled = 1;
else
g_cfg->trunk.vad_enabled = 0;
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_realloc, cfg_mgcp_realloc_cmd,
"force-realloc (0|1)",
"Force the reallocation of an endpoint\n"
"Disable\n" "Enable\n")
{
g_cfg->trunk.force_realloc = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_inp_dig_gain, cfg_mgcp_inp_dig_gain_cmd,
"input-digital-gain <0-62>",
"Static Digital Input Gain\n"
"Gain value")
{
g_cfg->trunk.digital_inp_gain = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_out_dig_gain, cfg_mgcp_out_dig_gain_cmd,
"outut-digital-gain <0-62>",
"Static Digital Output Gain\n"
"Gain value")
{
g_cfg->trunk.digital_out_gain = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_upstr_agc, cfg_mgcp_upstr_agc_cmd,
"upstream-automatic-gain (0|1)",
"Enable automatic gain control on upstream\n"
"Disable\n" "Enabled\n")
{
g_cfg->trunk.upstr_agc_enbl = argv[0][0] == '1';
return CMD_SUCCESS;
}
DEFUN(cfg_mgc_upstr_adp, cfg_mgcp_upstr_adp_cmd,
"upstream-adaptiton-rate <1-128>",
"Set the adaption rate in (dB/sec) * 10\n"
"Range\n")
{
g_cfg->trunk.upstr_adp_rate = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_upstr_max_gain, cfg_mgcp_upstr_max_gain_cmd,
"upstream-max-applied-gain <0-49>",
"Maximum applied gain from -31db to 18db\n"
"Gain level\n")
{
g_cfg->trunk.upstr_max_gain = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_upstr_target, cfg_mgcp_upstr_target_cmd,
"upstream-target-level <6-37>",
"Set the desired level in db\n"
"Desired lievel\n")
{
g_cfg->trunk.upstr_target_lvl = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_dwnstr_agc, cfg_mgcp_dwnstr_agc_cmd,
"downstream-automatic-gain (0|1)",
"Enable automatic gain control on downstream\n"
"Disable\n" "Enabled\n")
{
g_cfg->trunk.dwnstr_agc_enbl = argv[0][0] == '1';
return CMD_SUCCESS;
}
DEFUN(cfg_mgc_dwnstr_adp, cfg_mgcp_dwnstr_adp_cmd,
"downstream-adaptation-rate <1-128>",
"Set the adaption rate in (dB/sec) * 10\n"
"Range\n")
{
g_cfg->trunk.dwnstr_adp_rate = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_dwnstr_max_gain, cfg_mgcp_dwnstr_max_gain_cmd,
"downstream-max-applied-gain <0-49>",
"Maximum applied gain from -31db to 18db\n"
"Gain level\n")
{
g_cfg->trunk.dwnstr_max_gain = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_dwnstr_target, cfg_mgcp_dwnstr_target_cmd,
"downstream-target-level <6-37>",
"Set the desired level in db\n"
"Desired lievel\n")
{
g_cfg->trunk.dwnstr_target_lvl = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN_DEPRECATED(cfg_mgcp_endp_offset, cfg_mgcp_endp_offset_cmd,
"endpoint-offset <-60-60>",
"Offset to the CIC map\n" "Value to set\n")
{
vty_out(vty, "%%endpoint-offset is not used anymore.%s", VTY_NEWLINE);
return CMD_WARNING;
}
DEFUN(cfg_mgcp_target_trunk, cfg_mgcp_target_trunk_cmd,
"target-trunk-start <1-24>", "target-trunk-start <1-24>",
"Map the virtual trunk to start here\n" "Trunk Nr\n") "Map the virtual trunk to start here\n" "Trunk Nr\n")
{ {
g_cfg->trunk.target_trunk_start = atoi(argv[0]); struct mgcp_trunk_config *trunk = vty->index;
trunk->target_trunk_start = atoi(argv[0]);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
#define ENDP_BLOCK_STR "Block the Endpoint/Timeslot for Audio\n" #define ENDP_BLOCK_STR "Block the Endpoint/Timeslot for Audio\n"
DEFUN(cfg_mgcp_timeslot_block, cfg_mgcp_timeslot_block_cmd, DEFUN(cfg_vtrunk_block_defaults, cfg_vtrunk_block_defaults_cmd,
"block-endpoint <1-65534>",
ENDP_BLOCK_STR "Endpoint number\n")
{
int nr = atoi(argv[0]);
if (g_cfg->trunk.number_endpoints <= nr) {
vty_out(vty, "%%Endpoint %d too big. Current size: %d%s",
nr, g_cfg->trunk.number_endpoints, VTY_NEWLINE);
return CMD_WARNING;
}
g_cfg->trunk.endpoints[nr].blocked = 1;
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_block_defaults, cfg_mgcp_block_defaults_cmd,
"block-defaults", "block-defaults",
"Block the default endpoints 0x0 and 0x1F\n") "Block the default endpoints 0x0 and 0x1F\n")
{ {
int i; int i;
struct mgcp_trunk_config *trunk = vty->index;
for (i = 1; i < g_cfg->trunk.number_endpoints; ++i) { for (i = 1; i < trunk->number_endpoints; ++i) {
int multiplex, timeslot; int multiplex, timeslot;
struct mgcp_endpoint *endp = &g_cfg->trunk.endpoints[i]; struct mgcp_endpoint *endp = &trunk->endpoints[i];
mgcp_endpoint_to_timeslot(ENDPOINT_NUMBER(endp), &multiplex, &timeslot); mgcp_endpoint_to_timeslot(ENDPOINT_NUMBER(endp), &multiplex, &timeslot);
if (timeslot == 0x0 || timeslot == 0x1F) if (timeslot == 0x0 || timeslot == 0x1F)
@ -357,10 +224,23 @@ DEFUN(cfg_trunk_timeslot_block, cfg_trunk_timeslot_block_cmd,
ENDP_BLOCK_STR "Endpoint number\n") ENDP_BLOCK_STR "Endpoint number\n")
{ {
struct mgcp_trunk_config *trunk = vty->index; struct mgcp_trunk_config *trunk = vty->index;
int no = atoi(argv[0]);
if (no <= 0 || no >= trunk->number_endpoints) {
vty_out(vty, "%%Endpoint does not fit: %d.%s", no, VTY_NEWLINE);
return CMD_WARNING;
}
trunk->endpoints[atoi(argv[0])].blocked = 1; trunk->endpoints[atoi(argv[0])].blocked = 1;
return CMD_SUCCESS; return CMD_SUCCESS;
} }
void mgcp_write_extra(struct vty *vty, struct mgcp_config *cfg)
{
vty_out(vty, " configure-trunks %d%s",
cfg->configure_trunks, VTY_NEWLINE);
}
static void write_blocked_endpoints(struct vty *vty, static void write_blocked_endpoints(struct vty *vty,
struct mgcp_trunk_config *tcfg) struct mgcp_trunk_config *tcfg)
{ {
@ -374,40 +254,7 @@ static void write_blocked_endpoints(struct vty *vty,
} }
} }
void mgcp_write_extra(struct vty *vty, struct mgcp_config *cfg) void write_trunk_extra(struct vty *vty, struct mgcp_trunk_config *trunk)
{
vty_out(vty, " configure-trunks %d%s",
cfg->configure_trunks, VTY_NEWLINE);
vty_out(vty, " force-realloc %d%s",
cfg->trunk.force_realloc, VTY_NEWLINE);
vty_out(vty, " vad %s%s",
cfg->trunk.vad_enabled ? "enabled" : "disabled", VTY_NEWLINE);
vty_out(vty, " input-digital-gain %d%s",
cfg->trunk.digital_inp_gain, VTY_NEWLINE);
vty_out(vty, " output-digital-gain %d%s",
cfg->trunk.digital_out_gain, VTY_NEWLINE);
vty_out(vty, " upstream-automatic-gain %d%s",
cfg->trunk.upstr_agc_enbl, VTY_NEWLINE);
vty_out(vty, " upstream-adaptation-rate %d%s",
cfg->trunk.upstr_adp_rate, VTY_NEWLINE);
vty_out(vty, " upstream-max-applied-gain %d%s",
cfg->trunk.upstr_max_gain, VTY_NEWLINE);
vty_out(vty, " upstream-target-level %d%s",
cfg->trunk.upstr_target_lvl, VTY_NEWLINE);
vty_out(vty, " downstream-automatic-gain %d%s",
cfg->trunk.dwnstr_agc_enbl, VTY_NEWLINE);
vty_out(vty, " downstream-adaptation-rate %d%s",
cfg->trunk.dwnstr_adp_rate, VTY_NEWLINE);
vty_out(vty, " downstream-max-applied-gain %d%s",
cfg->trunk.dwnstr_max_gain, VTY_NEWLINE);
vty_out(vty, " downstream-target-level %d%s",
cfg->trunk.dwnstr_target_lvl, VTY_NEWLINE);
vty_out(vty, " target-trunk-start %d%s",
cfg->trunk.target_trunk_start, VTY_NEWLINE);
write_blocked_endpoints(vty, &cfg->trunk);
}
void mgcp_write_trunk_extra(struct vty *vty, struct mgcp_trunk_config *trunk)
{ {
vty_out(vty, " force-realloc %d%s", vty_out(vty, " force-realloc %d%s",
trunk->force_realloc, VTY_NEWLINE); trunk->force_realloc, VTY_NEWLINE);
@ -436,6 +283,18 @@ void mgcp_write_trunk_extra(struct vty *vty, struct mgcp_trunk_config *trunk)
write_blocked_endpoints(vty, trunk); write_blocked_endpoints(vty, trunk);
} }
void mgcp_write_trunk_extra(struct vty *vty, struct mgcp_trunk_config *trunk)
{
write_trunk_extra(vty, trunk);
}
void mgcp_write_vtrunk_extra(struct vty *vty, struct mgcp_trunk_config *trunk)
{
vty_out(vty, " target-trunk-start %d%s",
trunk->target_trunk_start, VTY_NEWLINE);
write_trunk_extra(vty, trunk);
}
void mgcp_mgw_vty_init(void) void mgcp_mgw_vty_init(void)
{ {
@ -445,22 +304,23 @@ void mgcp_mgw_vty_init(void)
mgcp_vty_init(); mgcp_vty_init();
install_element(MGCP_NODE, &cfg_mgcp_configure_cmd); install_element(MGCP_NODE, &cfg_mgcp_configure_cmd);
install_element(MGCP_NODE, &cfg_mgcp_vad_cmd);
install_element(MGCP_NODE, &cfg_mgcp_realloc_cmd); install_element(VTRUNK_NODE, &cfg_vtrunk_target_trunk_cmd);
install_element(MGCP_NODE, &cfg_mgcp_inp_dig_gain_cmd); install_element(VTRUNK_NODE, &cfg_vtrunk_block_defaults_cmd);
install_element(MGCP_NODE, &cfg_mgcp_out_dig_gain_cmd); install_element(VTRUNK_NODE, &cfg_trunk_vad_cmd);
install_element(MGCP_NODE, &cfg_mgcp_upstr_agc_cmd); install_element(VTRUNK_NODE, &cfg_trunk_realloc_cmd);
install_element(MGCP_NODE, &cfg_mgcp_upstr_adp_cmd); install_element(VTRUNK_NODE, &cfg_trunk_inp_dig_gain_cmd);
install_element(MGCP_NODE, &cfg_mgcp_upstr_max_gain_cmd); install_element(VTRUNK_NODE, &cfg_trunk_out_dig_gain_cmd);
install_element(MGCP_NODE, &cfg_mgcp_upstr_target_cmd); install_element(VTRUNK_NODE, &cfg_trunk_upstr_agc_cmd);
install_element(MGCP_NODE, &cfg_mgcp_dwnstr_agc_cmd); install_element(VTRUNK_NODE, &cfg_trunk_upstr_adp_cmd);
install_element(MGCP_NODE, &cfg_mgcp_dwnstr_adp_cmd); install_element(VTRUNK_NODE, &cfg_trunk_upstr_max_gain_cmd);
install_element(MGCP_NODE, &cfg_mgcp_dwnstr_max_gain_cmd); install_element(VTRUNK_NODE, &cfg_trunk_upstr_target_cmd);
install_element(MGCP_NODE, &cfg_mgcp_dwnstr_target_cmd); install_element(VTRUNK_NODE, &cfg_trunk_dwnstr_agc_cmd);
install_element(MGCP_NODE, &cfg_mgcp_endp_offset_cmd); install_element(VTRUNK_NODE, &cfg_trunk_dwnstr_adp_cmd);
install_element(MGCP_NODE, &cfg_mgcp_target_trunk_cmd); install_element(VTRUNK_NODE, &cfg_trunk_dwnstr_max_gain_cmd);
install_element(MGCP_NODE, &cfg_mgcp_timeslot_block_cmd); install_element(VTRUNK_NODE, &cfg_trunk_dwnstr_target_cmd);
install_element(MGCP_NODE, &cfg_mgcp_block_defaults_cmd); install_element(VTRUNK_NODE, &cfg_trunk_endp_offset_cmd);
install_element(VTRUNK_NODE, &cfg_trunk_timeslot_block_cmd);
install_element(TRUNK_NODE, &cfg_trunk_vad_cmd); install_element(TRUNK_NODE, &cfg_trunk_vad_cmd);
install_element(TRUNK_NODE, &cfg_trunk_realloc_cmd); install_element(TRUNK_NODE, &cfg_trunk_realloc_cmd);