pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-sigtran/+/43667?usp=email )
Change subject: Add Cisco like DSCP configuration support ......................................................................
Add Cisco like DSCP configuration support
Add Cisco like VTY configuration support for DSCP. QoS classes can be defined and configured per SS7 instance and the classes can be assigned to listener and connections like this:
cs7 instance 0 qos class 3 qos-ip-dscp 36 ... asp myasp 2905 2905 m3ua qos-class 3 ... asp asp-srv-m3ua 2906 2905 m3ua qos-class 3 ... asp asp-clnt-m3ua 2905 2906 m3ua qos-class 3 ...
Ensure that the ongoing listener or connection socket is updated whenever the QoS class is changed or deleted or its DSCP value is changed.
Deprecated "ip-dscp" and "init-ip-dscp" configuration is still supported. When QoS class is assigned, the deprecated configuration is removed and vice versa.
Update vty tests to the new VTY command layout and test the new VTY commands.
Related: OS#6753 Depends-on: I06927855a173c5b6dbf5c93aa08ea75e1d9d5f37 (libosmocore) Change-Id: Ic346698fc63771d95e474aec53ffb6c776636b3b --- M TODO-RELEASE M src/Makefile.am M src/ss7_asp.c M src/ss7_asp.h M src/ss7_asp_vty.c M src/ss7_instance.c M src/ss7_instance.h A src/ss7_qos_class.c A src/ss7_qos_class.h A src/ss7_qos_class_vty.c M src/ss7_vty.c M src/ss7_vty.h M src/ss7_xua_srv.c M src/ss7_xua_srv.h M src/ss7_xua_srv_vty.c M tests/vty/osmo_stp_test.vty M tests/vty/ss7_asp_test.vty M tests/vty/vty_test_runner.py 18 files changed, 469 insertions(+), 52 deletions(-)
Approvals: fixeria: Looks good to me, approved Jenkins Builder: Verified
diff --git a/TODO-RELEASE b/TODO-RELEASE index 0ed7189..4597a71 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -7,3 +7,4 @@ # If any interfaces have been added since the last public release: c:r:a + 1. # If any interfaces have been removed or changed since the last public release: c:r:0. #library what description / commit summary line +libosmocore >1.14.2 new VTY node L_CS7_QOS_CLASS_NODE added diff --git a/src/Makefile.am b/src/Makefile.am index 506f07c..1e494bb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,6 +25,7 @@ ss7_user.h \ ss7_vty.h \ ss7_xua_srv.h \ + ss7_qos_class.h \ tcap_as_loadshare.h \ tcap_as_loadshare_vty.h \ tcap_trans_tracking.h \ @@ -89,6 +90,8 @@ ss7_route.c \ ss7_route_table.c \ ss7_user.c \ + ss7_qos_class.c \ + ss7_qos_class_vty.c \ sua.c \ xua_asp_fsm.c \ xua_as_fsm.c \ diff --git a/src/ss7_asp.c b/src/ss7_asp.c index 5a47248..63038d9 100644 --- a/src/ss7_asp.c +++ b/src/ss7_asp.c @@ -57,6 +57,7 @@ #include "ss7_asp.h" #include "ss7_internal.h" #include "ss7_xua_srv.h" +#include "ss7_qos_class.h" #include "xua_asp_fsm.h" #include "xua_as_fsm.h" #include "xua_lm_sap.h" @@ -375,11 +376,11 @@ return osmo_sock_multiaddr_del_local_addr(fd, &new_loc_addr, 1); }
-int ss7_asp_apply_ip_dscp(const struct osmo_ss7_asp *asp) +int ss7_asp_apply_qos_class(const struct osmo_ss7_asp *asp) { int fd = -1;
- LOGPASP(asp, DLSS7, LOGL_INFO, "Set IP DSCP %d\n", asp->cfg.ip_dscp); + LOGPASP(asp, DLSS7, LOGL_INFO, "Set IP DSCP %d\n", (asp->cfg.qos) ? asp->cfg.qos->ip_dscp : asp->cfg.ip_dscp);
if (asp->cfg.is_server && asp->server) fd = osmo_stream_srv_get_fd(asp->server); @@ -389,7 +390,7 @@ if (fd < 0) return fd;
- return osmo_sock_set_dscp(fd, asp->cfg.ip_dscp); + return osmo_sock_set_dscp(fd, (asp->cfg.qos) ? asp->cfg.qos->ip_dscp : asp->cfg.ip_dscp); }
int ss7_asp_apply_peer_primary_address(const struct osmo_ss7_asp *asp) @@ -834,7 +835,9 @@ osmo_stream_cli_set_local_addrs(asp->client, (const char **)asp->cfg.local.host, asp->cfg.local.host_cnt); osmo_stream_cli_set_local_port(asp->client, asp->cfg.local.port); osmo_stream_cli_set_proto(asp->client, asp->cfg.trans_proto); - if (asp->cfg.ip_dscp != 0) + if (asp->cfg.qos) + osmo_stream_cli_set_ip_dscp(asp->client, asp->cfg.qos->ip_dscp); + else if (asp->cfg.ip_dscp != 0) osmo_stream_cli_set_ip_dscp(asp->client, asp->cfg.ip_dscp); osmo_stream_cli_set_reconnect_timeout(asp->client, 5); osmo_stream_cli_set_connect_cb(asp->client, xua_cli_connect_cb); diff --git a/src/ss7_asp.h b/src/ss7_asp.h index a7e8978..b7f0058 100644 --- a/src/ss7_asp.h +++ b/src/ss7_asp.h @@ -138,8 +138,8 @@
struct osmo_ss7_asp_peer local; struct osmo_ss7_asp_peer remote; + const struct ss7_qos_class *qos; uint8_t ip_dscp; - uint8_t qos_class; uint32_t quirks;
/* Whether to Tx xUA DAUD during ASP activation when in ASP role. */ @@ -192,7 +192,7 @@ int ss7_asp_apply_primary_address(const struct osmo_ss7_asp *asp); int ss7_asp_apply_new_local_address(const struct osmo_ss7_asp *asp, unsigned int loc_idx); int ss7_asp_apply_drop_local_address(const struct osmo_ss7_asp *asp, unsigned int loc_idx); -int ss7_asp_apply_ip_dscp(const struct osmo_ss7_asp *asp); +int ss7_asp_apply_qos_class(const struct osmo_ss7_asp *asp);
void ss7_asp_set_blocked(struct osmo_ss7_asp *asp, bool blocked); void ss7_asp_restart_after_reconfigure(struct osmo_ss7_asp *asp); diff --git a/src/ss7_asp_vty.c b/src/ss7_asp_vty.c index 5136105..a0a3a6d 100644 --- a/src/ss7_asp_vty.c +++ b/src/ss7_asp_vty.c @@ -53,6 +53,7 @@ #include <ss7_linkset.h> #include "ss7_internal.h" #include "ss7_vty.h" +#include "ss7_qos_class.h"
#include <netinet/tcp.h>
@@ -414,33 +415,58 @@ "ip-dscp " IP_DSCP_RANGE_STR, "Specify IP DSCP of ASP\n" IP_DSCP_RANGE_HELP_STR, - CMD_ATTR_NODE_EXIT) + CMD_ATTR_IMMEDIATE | CMD_ATTR_DEPRECATED) { struct osmo_ss7_asp *asp = vty->index; + vty_out(vty, "%% 'ip-dscp' command is deprecated, use 'qos-class' instead%s", VTY_NEWLINE); asp->cfg.ip_dscp = atoi(argv[0]); - ss7_asp_apply_ip_dscp(asp); + asp->cfg.qos = NULL; + ss7_asp_apply_qos_class(asp); return CMD_SUCCESS; }
DEFUN_ATTR(asp_no_ip_dscps, asp_no_ip_dscp_cmd, "no ip-dscp", NO_STR "Reset IP DSCP of ASP to default\n", - CMD_ATTR_NODE_EXIT) + CMD_ATTR_IMMEDIATE | CMD_ATTR_DEPRECATED) { struct osmo_ss7_asp *asp = vty->index; asp->cfg.ip_dscp = 0; - ss7_asp_apply_ip_dscp(asp); + ss7_asp_apply_qos_class(asp); return CMD_SUCCESS; }
-DEFUN_ATTR(asp_qos_clas, asp_qos_class_cmd, - "qos-class " QOS_CLASS_RANGE_STR, - "Specify QoS Class of ASP\n" - QOS_CLASS_RANGE_HELP_STR, - CMD_ATTR_NODE_EXIT) +DEFUN_ATTR(asp_qos_class, asp_qos_class_cmd, + "qos-class " SS7_QOS_CLASS_RANGE_STR, + "Specify QoS class of ASP\n" + SS7_QOS_CLASS_RANGE_HELP_STR, + CMD_ATTR_IMMEDIATE) { struct osmo_ss7_asp *asp = vty->index; - asp->cfg.qos_class = atoi(argv[0]); + struct ss7_qos_class *qos = ss7_qos_class_find(asp->inst, atoi(argv[0])); + if (qos) { + asp->cfg.qos = qos; + if (asp->cfg.ip_dscp != 0) { + vty_out(vty, "%% Config updated: ip-dscp %d -> qos-class %d (ip-dscp %d)%s", + asp->cfg.ip_dscp, qos->qos_class, qos->ip_dscp, VTY_NEWLINE); + asp->cfg.ip_dscp = 0; + } + ss7_asp_apply_qos_class(asp); + } else { + vty_out(vty, "%% QoS class with ID '%s' does not exit%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + return CMD_SUCCESS; +} + +DEFUN_ATTR(asp_no_qos_class, asp_no_qos_class_cmd, + "no qos-class", + NO_STR "QoS class\n", + CMD_ATTR_IMMEDIATE) +{ + struct osmo_ss7_asp *asp = vty->index; + asp->cfg.qos = NULL; + ss7_asp_apply_qos_class(asp); return CMD_SUCCESS; }
@@ -1432,10 +1458,10 @@ vty_out(vty, " remote-ip %s%s%s", asp->cfg.remote.host[i], asp->cfg.remote.idx_primary == i ? " primary" : "", VTY_NEWLINE); } - if (asp->cfg.ip_dscp != 0) + if (asp->cfg.qos) + vty_out(vty, " qos-class %u%s", asp->cfg.qos->qos_class, VTY_NEWLINE); + else if (asp->cfg.ip_dscp != 0) vty_out(vty, " ip-dscp %u%s", asp->cfg.ip_dscp, VTY_NEWLINE); - if (asp->cfg.qos_class) - vty_out(vty, " qos-class %u%s", asp->cfg.qos_class, VTY_NEWLINE); vty_out(vty, " role %s%s", osmo_str_tolower(get_value_string(osmo_ss7_asp_role_names, asp->cfg.role)), VTY_NEWLINE); if (asp->cfg.trans_proto == IPPROTO_SCTP) @@ -1546,6 +1572,7 @@ install_lib_element(L_CS7_ASP_NODE, &asp_ip_dscp_cmd); install_lib_element(L_CS7_ASP_NODE, &asp_no_ip_dscp_cmd); install_lib_element(L_CS7_ASP_NODE, &asp_qos_class_cmd); + install_lib_element(L_CS7_ASP_NODE, &asp_no_qos_class_cmd); install_lib_element(L_CS7_ASP_NODE, &asp_role_cmd); install_lib_element(L_CS7_ASP_NODE, &asp_transport_role_cmd); install_lib_element(L_CS7_ASP_NODE, &asp_sctp_role_cmd); diff --git a/src/ss7_instance.c b/src/ss7_instance.c index 61b0a2c..a006fe5 100644 --- a/src/ss7_instance.c +++ b/src/ss7_instance.c @@ -37,8 +37,10 @@ #include "ss7_asp.h" #include "ss7_internal.h" #include "ss7_instance.h" +#include "ss7_xua_srv.h" #include "ss7_linkset.h" #include "ss7_route_table.h" +#include "ss7_qos_class.h" #include "sccp_internal.h"
static int32_t next_rctx = 1; @@ -108,6 +110,7 @@ INIT_LLIST_HEAD(&inst->rtable_list); INIT_LLIST_HEAD(&inst->xua_servers); INIT_LLIST_HEAD(&inst->t8_inaccessible_sp.list); + INIT_LLIST_HEAD(&inst->qos_class_list);
osmo_timer_setup(&inst->t8_inaccessible_sp.timer, t8_inaccessible_sp_timer_cb, inst);
@@ -141,6 +144,7 @@ struct osmo_ss7_linkset *lset, *lset2; struct osmo_ss7_as *as, *as2; struct osmo_ss7_asp *asp, *asp2; + struct ss7_qos_class *qos, *qos2;
OSMO_ASSERT(ss7_initialized); LOGSS7(inst, LOGL_INFO, "Destroying SS7 Instance\n"); @@ -154,6 +158,9 @@ llist_for_each_entry_safe(lset, lset2, &inst->linksets, list) ss7_linkset_destroy(lset);
+ llist_for_each_entry_safe(qos, qos2, &inst->qos_class_list, list) + ss7_qos_class_destroy(qos); + osmo_timer_del(&inst->t8_inaccessible_sp.timer); /* Talloc takes care of freeing inst->t8_inaccessible_sp.list and its entries */
diff --git a/src/ss7_instance.h b/src/ss7_instance.h index 6861d40..8a8e3aa 100644 --- a/src/ss7_instance.h +++ b/src/ss7_instance.h @@ -47,6 +47,8 @@ struct osmo_ss7_instance { /*! member of global list of instances */ struct llist_head list; + /*! list of \ref ss7_qos_class */ + struct llist_head qos_class_list; /*! list of \ref osmo_ss7_linkset */ struct llist_head linksets; /*! list of \ref osmo_ss7_as */ diff --git a/src/ss7_qos_class.c b/src/ss7_qos_class.c new file mode 100644 index 0000000..44af89d --- /dev/null +++ b/src/ss7_qos_class.c @@ -0,0 +1,126 @@ +/* (C) 2026 by sysmocom s.f.m.c. GmbH info@sysmocom.de + * 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, see http://www.gnu.org/licenses/. + * + */ + +#include "ss7_asp.h" +#include "ss7_xua_srv.h" +#include "ss7_qos_class.h" + +/*********************************************************************** + * SS7 QoS Class + ***********************************************************************/ + +/*! \brief Find QoS Class + * \param[in] inst SS7 Instance on which we operate + * \param[in] qos_class Id of QoS class + * \returns pointer to a QoS class instance on success; NULL otherwise */ +struct ss7_qos_class * +ss7_qos_class_find(struct osmo_ss7_instance *inst, uint8_t qos_class) +{ + struct ss7_qos_class *qos; + + llist_for_each_entry(qos, &inst->qos_class_list, list) { + if (qos->qos_class == qos_class) + return qos; + } + + return NULL; +} + +/*! \brief Create QoS Class + * \param[in] inst SS7 Instance on which we operate + * \param[in] qos_class Id of QoS class + * \param[in] ip_dscp IP DSCP + * \returns pointer to a QoS class instance on success; NULL otherwise */ +struct ss7_qos_class * +ss7_qos_class_create(struct osmo_ss7_instance *inst, uint8_t qos_class, uint8_t ip_dscp) +{ + struct ss7_qos_class *qos; + + qos = talloc_zero(inst, struct ss7_qos_class); + if (!qos) + return NULL; + qos->inst = inst; + qos->qos_class = qos_class; + qos->ip_dscp = ip_dscp; + llist_add_tail(&qos->list, &inst->qos_class_list); + + return qos; +} + +/*! \brief Delete QoS Class + * \param[in] QoS class instance to delete */ +void ss7_qos_class_destroy(struct ss7_qos_class *qos) +{ + struct osmo_ss7_instance *inst = qos->inst; + struct osmo_ss7_asp *asp; + struct osmo_xua_server *xua; + + /* Remove bindings, if any. */ + llist_for_each_entry(asp, &inst->asp_list, list) { + if (asp->cfg.qos == qos) { + asp->cfg.qos = NULL; + ss7_asp_apply_qos_class(asp); + } + } + llist_for_each_entry(xua, &inst->xua_servers, list) { + if (xua->cfg.qos == qos) { + xua->cfg.qos = NULL; + ss7_xua_server_set_ip_dscp(xua); + } + } + llist_del(&qos->list); + talloc_free(qos); +} + +/*! \brief Find or Create QoS Class + * \param[in] inst SS7 Instance on which we operate + * \param[in] qos_class Id of QoS class + * \param[in] ip_dscp IP DSCP + * \returns pointer to a QoS class instance on success; NULL otherwise */ +struct ss7_qos_class * +ss7_qos_class_find_or_create(struct osmo_ss7_instance *inst, uint8_t qos_class, uint8_t ip_dscp) +{ + struct ss7_qos_class *qos; + + qos = ss7_qos_class_find(inst, qos_class); + if (!qos) + qos = ss7_qos_class_create(inst, qos_class, ip_dscp); + + return qos; +} + +/*! \brief Update sockets of all ASPs and xUA Servers that use this QoS class + * \param[in] QoS class instance to update */ +void ss7_qos_class_update(struct ss7_qos_class *qos) +{ + struct osmo_ss7_instance *inst = qos->inst; + struct osmo_ss7_asp *asp; + struct osmo_xua_server *xua; + + llist_for_each_entry(asp, &inst->asp_list, list) { + if (asp->cfg.qos == qos) + ss7_asp_apply_qos_class(asp); + } + llist_for_each_entry(xua, &inst->xua_servers, list) { + if (xua->cfg.qos == qos) + ss7_xua_server_set_ip_dscp(xua); + } +} + diff --git a/src/ss7_qos_class.h b/src/ss7_qos_class.h new file mode 100644 index 0000000..d9b4e8f --- /dev/null +++ b/src/ss7_qos_class.h @@ -0,0 +1,24 @@ +#pragma once + +#include "ss7_instance.h" + +/*********************************************************************** + * QoS Class + ***********************************************************************/ + +struct ss7_qos_class { + struct llist_head list; + struct osmo_ss7_instance *inst; + + uint8_t qos_class; + uint8_t ip_dscp; +}; + +struct ss7_qos_class * +ss7_qos_class_find(struct osmo_ss7_instance *inst, uint8_t qos_class); +struct ss7_qos_class * +ss7_qos_class_create(struct osmo_ss7_instance *inst, uint8_t qos_class, uint8_t ip_dscp); +void ss7_qos_class_destroy(struct ss7_qos_class *qos); +struct ss7_qos_class * +ss7_qos_class_find_or_create(struct osmo_ss7_instance *inst, uint8_t qos_class, uint8_t ip_dscp); +void ss7_qos_class_update(struct ss7_qos_class *qos); diff --git a/src/ss7_qos_class_vty.c b/src/ss7_qos_class_vty.c new file mode 100644 index 0000000..c1c28b7 --- /dev/null +++ b/src/ss7_qos_class_vty.c @@ -0,0 +1,127 @@ +/* SS7 QoS Class VTY Interface */ + +/* (C) 2026 by sysmocom s.f.m.c. GmbH info@sysmocom.de + * 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, see http://www.gnu.org/licenses/. + * + */ + +#include <osmocom/vty/vty.h> +#include <osmocom/vty/command.h> + +#include "ss7_vty.h" +#include "ss7_qos_class.h" + +/*********************************************************************** + * QoS Class Definition + ***********************************************************************/ + +static struct cmd_node qos_class_node = { + L_CS7_QOS_CLASS_NODE, + "%s(config-cs7-qos-class)# ", + 1, +}; + +DEFUN_ATTR(cs7_qos_class, cs7_qos_class_cmd, + "qos class " SS7_QOS_CLASS_RANGE_STR, + "QoS definition\n" + "QoS class definition\n" + SS7_QOS_CLASS_RANGE_HELP_STR, + CMD_ATTR_IMMEDIATE) +{ + struct osmo_ss7_instance *inst = vty->index; + struct ss7_qos_class *qos; + + qos = ss7_qos_class_find_or_create(inst, atoi(argv[0]), 0); + if (!qos) { + vty_out(vty, "Failed to add new QoS class %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + vty->node = L_CS7_QOS_CLASS_NODE; + vty->index = qos; + + return CMD_SUCCESS; +} + +DEFUN_ATTR(cs7_no_qos_class, cs7_no_qos_class_cmd, + "no qos class " SS7_QOS_CLASS_RANGE_STR, + NO_STR + "QoS definition\n" + "QoS class definition\n" + SS7_QOS_CLASS_RANGE_HELP_STR, + CMD_ATTR_IMMEDIATE) +{ + struct osmo_ss7_instance *inst = vty->index; + struct ss7_qos_class *qos; + + qos = ss7_qos_class_find(inst, atoi(argv[0])); + if (!qos) { + vty_out(vty, "QoS class %s does not exists%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + ss7_qos_class_destroy(qos); + + return CMD_SUCCESS; +} + +DEFUN_ATTR(cs7_qos_ip_dscp, cs7_qos_ip_dscp_cmd, + "qos-ip-dscp " IP_DSCP_RANGE_STR, + "Specify IP DSCP of QoS class\n" + IP_DSCP_RANGE_HELP_STR, + CMD_ATTR_IMMEDIATE) +{ + struct ss7_qos_class *qos = vty->index; + + qos->ip_dscp = atoi(argv[0]); + ss7_qos_class_update(qos); + + return CMD_SUCCESS; +} + +DEFUN_ATTR(cs7_no_qos_ip_dscp, cs7_no_qos_ip_dscp_cmd, + "no qos-ip-dscp", + NO_STR "Reset IP DSCP of QoS class to default\n", + CMD_ATTR_IMMEDIATE) +{ + struct ss7_qos_class *qos = vty->index; + + qos->ip_dscp = 0; + ss7_qos_class_update(qos); + + return CMD_SUCCESS; +} + +void ss7_vty_write_one_qos_class(struct vty *vty, struct ss7_qos_class *qos) +{ + /* Only show class, if it has ip-dscp set. */ + vty_out(vty, " qos class %u%s", qos->qos_class, VTY_NEWLINE); + if (qos->ip_dscp) + vty_out(vty, " qos-ip-dscp %u%s", qos->ip_dscp, VTY_NEWLINE); + else + vty_out(vty, " no qos-ip-dscp%s", VTY_NEWLINE); +} + +void ss7_vty_init_node_qos_class(void) +{ + install_node(&qos_class_node, NULL); + install_lib_element(L_CS7_NODE, &cs7_qos_class_cmd); + install_lib_element(L_CS7_NODE, &cs7_no_qos_class_cmd); + install_lib_element(L_CS7_QOS_CLASS_NODE, &cs7_qos_ip_dscp_cmd); + install_lib_element(L_CS7_QOS_CLASS_NODE, &cs7_no_qos_ip_dscp_cmd); +} diff --git a/src/ss7_vty.c b/src/ss7_vty.c index 56633f3..eec4a80 100644 --- a/src/ss7_vty.c +++ b/src/ss7_vty.c @@ -50,6 +50,7 @@ #include "ss7_user.h" #include "ss7_vty.h" #include "ss7_xua_srv.h" +#include "ss7_qos_class.h" #ifdef WITH_TCAP_LOADSHARING #include "tcap_as_loadshare_vty.h" #endif /* WITH_TCAP_LOADSHARING */ @@ -1352,6 +1353,7 @@
static void write_one_cs7(struct vty *vty, struct osmo_ss7_instance *inst, bool show_dyn_config) { + struct ss7_qos_class *qos; struct osmo_ss7_asp *asp; struct osmo_ss7_as *as; struct osmo_ss7_route_table *rtable; @@ -1401,15 +1403,19 @@
write_cs7_timers_xua(vty, " ", inst);
- /* first dump ASPs, as ASs reference them */ + /* dump QoS classes */ + llist_for_each_entry(qos, &inst->qos_class_list, list) + ss7_vty_write_one_qos_class(vty, qos); + + /* dump ASPs, as ASs reference them */ llist_for_each_entry(asp, &inst->asp_list, list) ss7_vty_write_one_asp(vty, asp, show_dyn_config);
- /* then dump ASPs, as routes reference them */ + /* dump ASPs, as routes reference them */ llist_for_each_entry(as, &inst->as_list, list) ss7_vty_write_one_as(vty, as, show_dyn_config);
- /* now dump everything that is relevant for the SG role */ + /* dump everything that is relevant for the SG role */ if (cs7_role == CS7_ROLE_SG) {
/* dump routes, as their target ASs exist */ @@ -1429,10 +1435,16 @@
int osmo_ss7_vty_go_parent(struct vty *vty) { + struct ss7_qos_class *qos; struct osmo_ss7_route_table *rtbl; struct osmo_sccp_addr_entry *entry;
switch (vty->node) { + case L_CS7_QOS_CLASS_NODE: + qos = vty->index; + vty->node = L_CS7_NODE; + vty->index = qos->inst; + break; case L_CS7_ASP_NODE: return ss7_vty_node_asp_go_parent(vty); case L_CS7_RTABLE_NODE: @@ -1537,6 +1549,7 @@ install_lib_element(L_CS7_NODE, &cs7_opc_dpc_shift_cmd); install_lib_element(L_CS7_NODE, &cs7_sls_shift_cmd);
+ ss7_vty_init_node_qos_class(); ss7_vty_init_node_asp(); ss7_vty_init_node_as();
diff --git a/src/ss7_vty.h b/src/ss7_vty.h index 1d99cad..ac33945 100644 --- a/src/ss7_vty.h +++ b/src/ss7_vty.h @@ -40,6 +40,9 @@ #define IP_DSCP_RANGE_STR "<0-63>" #define IP_DSCP_RANGE_HELP_STR "IP Differentiated Service Code Point\n"
+#define SS7_QOS_CLASS_RANGE_STR "<1-255>" +#define SS7_QOS_CLASS_RANGE_HELP_STR "QoS Class\n" + #define QOS_CLASS_RANGE_STR "<0-7>" #define QOS_CLASS_RANGE_HELP_STR "QoS Class\n" #define QOS_CLASS_VAR_STR "(" QOS_CLASS_RANGE_STR "|default)" @@ -50,6 +53,11 @@ int parse_trans_proto(const char *protocol); enum osmo_ss7_asp_protocol parse_asp_proto(const char *protocol);
+/* ss7_qos_class_vty.c */ +struct ss7_qos_class; +void ss7_vty_init_node_qos_class(void); +void ss7_vty_write_one_qos_class(struct vty *vty, struct ss7_qos_class *qos); + /* ss7_asp_vty.c */ void ss7_vty_init_node_asp(void); void ss7_vty_write_one_asp(struct vty *vty, struct osmo_ss7_asp *asp, bool show_dyn_config); diff --git a/src/ss7_xua_srv.c b/src/ss7_xua_srv.c index 3d9332d..4fd1067 100644 --- a/src/ss7_xua_srv.c +++ b/src/ss7_xua_srv.c @@ -57,6 +57,7 @@ #include "xua_as_fsm.h" #include "xua_lm_sap.h" #include "ss7_xua_srv.h" +#include "ss7_qos_class.h"
/*********************************************************************** * SS7 xUA Server @@ -106,7 +107,9 @@ asp = ss7_asp_find_by_socket_addr(fd, oxs->cfg.trans_proto); } /* If ASP uses individual DSCP setting, override the setting from the listener socket. */ - if (asp->cfg.ip_dscp > 0) + if (asp->cfg.qos) + osmo_sock_set_dscp(fd, asp->cfg.qos->ip_dscp); + else if (asp->cfg.ip_dscp != 0) osmo_sock_set_dscp(fd, asp->cfg.ip_dscp); }
@@ -409,7 +412,9 @@ { if (!xs->server) return false; - if (xs->cfg.ip_dscp != 0) + if (xs->cfg.qos) + osmo_stream_srv_link_set_ip_dscp(xs->server, xs->cfg.qos->ip_dscp); + else if (xs->cfg.ip_dscp != 0) osmo_stream_srv_link_set_ip_dscp(xs->server, xs->cfg.ip_dscp); return true; } diff --git a/src/ss7_xua_srv.h b/src/ss7_xua_srv.h index 7eb00c2..7e93b4e 100644 --- a/src/ss7_xua_srv.h +++ b/src/ss7_xua_srv.h @@ -27,6 +27,7 @@ struct { bool accept_dyn_reg; struct osmo_ss7_asp_peer local; + const struct ss7_qos_class *qos; uint8_t ip_dscp; enum osmo_ss7_asp_protocol proto; struct { @@ -71,7 +72,7 @@ ss7_xua_server_set_local_hosts(struct osmo_xua_server *xs, const char **local_hosts, size_t local_host_cnt); int ss7_xua_server_add_local_host(struct osmo_xua_server *xs, const char *local_host); int ss7_xua_server_del_local_host(struct osmo_xua_server *xs, const char *local_host); -bool ss7_xua_server_set_ip_dscp(struct osmo_xua_server *oxs); +bool ss7_xua_server_set_ip_dscp(struct osmo_xua_server *xs); void ss7_xua_server_destroy(struct osmo_xua_server *xs);
bool ss7_xua_server_set_default_local_hosts(struct osmo_xua_server *oxs); diff --git a/src/ss7_xua_srv_vty.c b/src/ss7_xua_srv_vty.c index 5ee395b..37a9212 100644 --- a/src/ss7_xua_srv_vty.c +++ b/src/ss7_xua_srv_vty.c @@ -42,6 +42,7 @@ #include "ss7_internal.h" #include "ss7_vty.h" #include "ss7_xua_srv.h" +#include "ss7_qos_class.h"
/*********************************************************************** * xUA Listener Configuration (SG) @@ -152,11 +153,13 @@ "init-ip-dscp " IP_DSCP_RANGE_STR, "Specify IP DSCP of Listener\n" IP_DSCP_RANGE_HELP_STR, - CMD_ATTR_IMMEDIATE) + CMD_ATTR_IMMEDIATE | CMD_ATTR_DEPRECATED) { struct osmo_xua_server *xs = vty->index;
+ vty_out(vty, "%% 'init-ip-dscp' command is deprecated, use 'qos-class' instead%s", VTY_NEWLINE); xs->cfg.ip_dscp = atoi(argv[0]); + xs->cfg.qos = NULL; ss7_xua_server_set_ip_dscp(xs);
return CMD_SUCCESS; @@ -165,7 +168,7 @@ DEFUN_ATTR(xua_no_init_ip_dscp, xua_no_init_ip_dscp_cmd, "no init-ip-dscp", NO_STR "Specify IP DSCP of Listener\n", - CMD_ATTR_IMMEDIATE) + CMD_ATTR_IMMEDIATE | CMD_ATTR_DEPRECATED) { struct osmo_xua_server *xs = vty->index;
@@ -175,6 +178,40 @@ return CMD_SUCCESS; }
+DEFUN_ATTR(xua_qos_class, xua_qos_class_cmd, + "qos-class " SS7_QOS_CLASS_RANGE_STR, + "QoS class\n" + SS7_QOS_CLASS_RANGE_HELP_STR, + CMD_ATTR_IMMEDIATE) +{ + struct osmo_xua_server *xs = vty->index; + struct ss7_qos_class *qos = ss7_qos_class_find(xs->inst, atoi(argv[0])); + if (qos) { + xs->cfg.qos = qos; + if (xs->cfg.ip_dscp != 0) { + vty_out(vty, "%% Config updated: init-ip-dscp %d -> qos-class %d (ip-dscp %d)%s", + xs->cfg.ip_dscp, qos->qos_class, qos->ip_dscp, VTY_NEWLINE); + xs->cfg.ip_dscp = 0; + } + ss7_xua_server_set_ip_dscp(xs); + } else { + vty_out(vty, "%% QoS class with ID '%s' does not exit%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + return CMD_SUCCESS; +} + +DEFUN_ATTR(xua_no_qos_class, xua_no_qos_class_cmd, + "no qos-class", + NO_STR "QoS class\n", + CMD_ATTR_IMMEDIATE) +{ + struct osmo_xua_server *xs = vty->index; + xs->cfg.qos = NULL; + ss7_xua_server_set_ip_dscp(xs); + return CMD_SUCCESS; +} + DEFUN_ATTR(xua_accept_dyn_asp, xua_accept_dyn_asp_cmd, "accept-asp-connections (pre-configured|dynamic-permitted)", "Define what kind of ASP connections to accept\n" @@ -252,7 +289,9 @@ if (xs->cfg.local.host[i]) vty_out(vty, " local-ip %s%s", xs->cfg.local.host[i], VTY_NEWLINE); } - if (xs->cfg.ip_dscp) + if (xs->cfg.qos) + vty_out(vty, " qos-class %u%s", xs->cfg.qos->qos_class, VTY_NEWLINE); + else if (xs->cfg.ip_dscp != 0) vty_out(vty, " init-ip-dscp %u%s", xs->cfg.ip_dscp, VTY_NEWLINE); if (xs->cfg.accept_dyn_reg) vty_out(vty, " accept-asp-connections dynamic-permitted%s", VTY_NEWLINE); @@ -372,6 +411,8 @@ install_lib_element(L_CS7_XUA_NODE, &xua_no_local_ip_cmd); install_lib_element(L_CS7_XUA_NODE, &xua_init_ip_dscp_cmd); install_lib_element(L_CS7_XUA_NODE, &xua_no_init_ip_dscp_cmd); + install_lib_element(L_CS7_XUA_NODE, &xua_qos_class_cmd); + install_lib_element(L_CS7_XUA_NODE, &xua_no_qos_class_cmd); install_lib_element(L_CS7_XUA_NODE, &xua_accept_dyn_asp_cmd); install_lib_element(L_CS7_XUA_NODE, &xua_sctp_param_init_cmd); install_lib_element(L_CS7_XUA_NODE, &xua_no_sctp_param_init_cmd); diff --git a/tests/vty/osmo_stp_test.vty b/tests/vty/osmo_stp_test.vty index 01cad83..167a1a0 100644 --- a/tests/vty/osmo_stp_test.vty +++ b/tests/vty/osmo_stp_test.vty @@ -125,6 +125,8 @@ xua rkm routing-key-allocation (static-only|dynamic-permitted) sls-opc-dpc [opc-shift] [<0-8>] [dpc-shift] [<0-8>] sls-shift <0-6> + qos class <1-255> + no qos class <1-255> asp NAME <0-65535> <0-65535> (sua|m3ua|ipa) asp NAME <0-65535> <0-65535> (sua|m3ua|ipa) (sctp|tcp) no asp NAME @@ -148,8 +150,9 @@ xua SIGTRAN xxxUA related sls-opc-dpc Shift OPC and DPC bits used during routing decision sls-shift Shift SLS bits used during routing decision - asp Configure Application Server Process + qos QoS definition no Negate a command or set its defaults + asp Configure Application Server Process as Configure an Application Server sccp-address Create/Modify an SCCP addressbook entry timer Configure CS7 Instance default timer values @@ -218,6 +221,7 @@ NAME Name of the SCCP Address
OsmoSTP(config-cs7)# no ? + qos QoS definition asp Disable Application Server Process as Disable Application Server sccp-address Delete an SCCP addressbook entry @@ -285,9 +289,8 @@ no remote-ip (A.B.C.D|X:X::X:X) local-ip (A.B.C.D|X:X::X:X) [primary] no local-ip (A.B.C.D|X:X::X:X) - ip-dscp <0-63> - no ip-dscp - qos-class <0-7> + qos-class <1-255> + no qos-class role (sg|asp|ipsp) transport-role (client|server) sctp-param init (num-ostreams|max-instreams|max-attempts|timeout) <0-65535> @@ -317,8 +320,7 @@ no Negate a command or set its defaults remote-ip Specify Remote IP Address of ASP local-ip Specify Local IP Address from which to contact ASP - ip-dscp Specify IP DSCP of ASP - qos-class Specify QoS Class of ASP + qos-class Specify QoS class of ASP role Specify the xUA role for this ASP transport-role Specify the transport layer role for this ASP sctp-param Configure SCTP parameters @@ -332,7 +334,7 @@
OsmoSTP(config-cs7-asp)# no ? ... - ip-dscp Reset IP DSCP of ASP to default + qos-class QoS class sctp-param Configure SCTP parameters tcp-param Configure TCP parameters destination-audit Configure ASP Auditing (xUA DAUD) @@ -428,8 +430,8 @@ ... local-ip (A.B.C.D|X:X::X:X) no local-ip (A.B.C.D|X:X::X:X) - init-ip-dscp <0-63> - no init-ip-dscp + qos-class <1-255> + no qos-class accept-asp-connections (pre-configured|dynamic-permitted) sctp-param init (num-ostreams|max-instreams) <0-65535> no sctp-param init (num-ostreams|max-instreams) @@ -439,16 +441,16 @@ ... local-ip Configure the Local IP Address for xUA no Negate a command or set its defaults - init-ip-dscp Specify IP DSCP of Listener + qos-class QoS class accept-asp-connections Define what kind of ASP connections to accept sctp-param Configure SCTP parameters ...
OsmoSTP(config-cs7-listen)# no ? ... - local-ip Configure the Local IP Address for xUA - init-ip-dscp Specify IP DSCP of Listener - sctp-param Configure SCTP parameters + local-ip Configure the Local IP Address for xUA + qos-class QoS class + sctp-param Configure SCTP parameters ...
OsmoSTP(config-cs7-listen)# exit diff --git a/tests/vty/ss7_asp_test.vty b/tests/vty/ss7_asp_test.vty index 5ea965b..08d8ed6 100644 --- a/tests/vty/ss7_asp_test.vty +++ b/tests/vty/ss7_asp_test.vty @@ -123,6 +123,8 @@ xua rkm routing-key-allocation (static-only|dynamic-permitted) sls-opc-dpc [opc-shift] [<0-8>] [dpc-shift] [<0-8>] sls-shift <0-6> + qos class <1-255> + no qos class <1-255> asp NAME <0-65535> <0-65535> (sua|m3ua|ipa) asp NAME <0-65535> <0-65535> (sua|m3ua|ipa) (sctp|tcp) no asp NAME @@ -145,8 +147,9 @@ xua SIGTRAN xxxUA related sls-opc-dpc Shift OPC and DPC bits used during routing decision sls-shift Shift SLS bits used during routing decision - asp Configure Application Server Process + qos QoS definition no Negate a command or set its defaults + asp Configure Application Server Process as Configure an Application Server sccp-address Create/Modify an SCCP addressbook entry timer Configure CS7 Instance default timer values @@ -214,6 +217,7 @@ NAME Name of the SCCP Address
ss7_asp_vty_test(config-cs7)# no ? + qos QoS definition asp Disable Application Server Process as Disable Application Server sccp-address Delete an SCCP addressbook entry @@ -281,9 +285,8 @@ no remote-ip (A.B.C.D|X:X::X:X) local-ip (A.B.C.D|X:X::X:X) [primary] no local-ip (A.B.C.D|X:X::X:X) - ip-dscp <0-63> - no ip-dscp - qos-class <0-7> + qos-class <1-255> + no qos-class role (sg|asp|ipsp) transport-role (client|server) sctp-param init (num-ostreams|max-instreams|max-attempts|timeout) <0-65535> @@ -313,8 +316,7 @@ no Negate a command or set its defaults remote-ip Specify Remote IP Address of ASP local-ip Specify Local IP Address from which to contact ASP - ip-dscp Specify IP DSCP of ASP - qos-class Specify QoS Class of ASP + qos-class Specify QoS class of ASP role Specify the xUA role for this ASP transport-role Specify the transport layer role for this ASP sctp-param Configure SCTP parameters @@ -330,7 +332,7 @@ ... remote-ip Specify Remote IP Address of ASP local-ip Specify Local IP Address from which to contact ASP - ip-dscp Reset IP DSCP of ASP to default + qos-class QoS class sctp-param Configure SCTP parameters tcp-param Configure TCP parameters destination-audit Configure ASP Auditing (xUA DAUD) diff --git a/tests/vty/vty_test_runner.py b/tests/vty/vty_test_runner.py index a01f193..bad989e 100755 --- a/tests/vty/vty_test_runner.py +++ b/tests/vty/vty_test_runner.py @@ -235,20 +235,36 @@ def vty_app(self): return (4239, "./stp/osmo-stp", "OsmoSTP", "stp")
- def testDSCPSettings(self): + def _run_test_dscp_settings(self, qos_class): self.vty.enable() self.assertTrue(self.vty.verify("configure terminal",[''])) self.assertTrue(self.vty.verify("cs7 instance 0",[''])) + if qos_class: + self.assertTrue(self.vty.verify("qos class 5",[''])) + self.assertTrue(self.vty.verify("qos-ip-dscp 23",[''])) + self.assertTrue(self.vty.verify("exit",[''])) + self.assertTrue(self.vty.verify("qos class 6",[''])) + self.assertTrue(self.vty.verify("qos-ip-dscp 42",[''])) + self.assertTrue(self.vty.verify("exit",[''])) + self.assertTrue(self.vty.verify("qos class 7",[''])) + self.assertTrue(self.vty.verify("qos-ip-dscp 8",[''])) + self.assertTrue(self.vty.verify("exit",[''])) self.assertTrue(self.vty.verify("no listen m3ua 2905",[''])) self.assertTrue(self.vty.verify("listen m3ua 2905",[''])) self.assertTrue(self.vty.verify("accept-asp-connections dynamic-permitted",[''])) self.assertTrue(self.vty.verify("local-ip 127.0.0.1",[''])) - self.assertTrue(self.vty.verify("init-ip-dscp 23",[''])) + if qos_class: + self.assertTrue(self.vty.verify("qos-class 5",[''])) + else: + self.assertTrue(self.vty.verify("init-ip-dscp 23",["% 'init-ip-dscp' command is deprecated, use 'qos-class' instead"])) self.assertTrue(self.vty.verify("exit",[''])) self.assertTrue(self.vty.verify("asp asp-srv-m3ua 2906 2905 m3ua",[''])) self.assertTrue(self.vty.verify("local-ip 127.0.0.1",[''])) self.assertTrue(self.vty.verify("remote-ip 127.0.0.2",[''])) - self.assertTrue(self.vty.verify("ip-dscp 8",[''])) + if qos_class: + self.assertTrue(self.vty.verify("qos-class 7",[''])) + else: + self.assertTrue(self.vty.verify("ip-dscp 8",["% 'ip-dscp' command is deprecated, use 'qos-class' instead"])) self.assertTrue(self.vty.verify("role asp",[''])) self.assertTrue(self.vty.verify("sctp-role server",[''])) self.assertTrue(self.vty.verify("no shutdown",[''])) @@ -256,7 +272,10 @@ self.assertTrue(self.vty.verify("asp asp-clnt-m3ua 2905 2906 m3ua",[''])) self.assertTrue(self.vty.verify("local-ip 127.0.0.2",[''])) self.assertTrue(self.vty.verify("remote-ip 127.0.0.1",[''])) - self.assertTrue(self.vty.verify("ip-dscp 42",[''])) + if qos_class: + self.assertTrue(self.vty.verify("qos-class 6",[''])) + else: + self.assertTrue(self.vty.verify("ip-dscp 42",["% 'ip-dscp' command is deprecated, use 'qos-class' instead"])) self.assertTrue(self.vty.verify("role asp",[''])) self.assertTrue(self.vty.verify("sctp-role client",[''])) self.assertTrue(self.vty.verify("no shutdown",[''])) @@ -368,6 +387,12 @@ sorted_output = "\n".join(sorted(output.splitlines())) self.assertEqual(sorted_output, expected_output)
+ def testDSCPSettings_without_QoSClass(self): + self._run_test_dscp_settings(qos_class = False) + + def testDSCPSettings_with_QoSClass(self): + self._run_test_dscp_settings(qos_class = True) + if __name__ == '__main__': import argparse import sys