aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2023-08-03 17:09:45 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2023-08-21 12:23:52 +0200
commit8b8458d15342455a157c48bf02d53cad6076633b (patch)
treef64a7b54abeb90d2a40e93dfef60053aba92e676
parent58fd289443f358b7450246d3df67fdc40a74ffb0 (diff)
asp: Allow setting IP address as SCTP primary upon conn establishment
This is an initial implementation to set the local SCTP Primary address as well as the peer's Primary Address (through SCTP ASCONF messages). The Primary address is only set upon conn establishment (after connect() for clients, or accept() for severs), which means no logic is introduced to make sure that primary address is kept during the entire operation of the SCTP association (for instance if the Primary address becomes unavailable and the stack changes the primary, and later on that address becomes available again, the primary addres won't be set back to the initially configured one). Related: OS#6076 Change-Id: I4a9fc1a4ad82ed20ece328bc53fca58299d744ca
-rw-r--r--TODO-RELEASE1
-rw-r--r--include/osmocom/sigtran/osmo_ss7.h6
-rw-r--r--src/osmo_ss7.c257
-rw-r--r--src/osmo_ss7_vty.c24
-rw-r--r--tests/vty/ss7_asp_test.vty38
5 files changed, 296 insertions, 30 deletions
diff --git a/TODO-RELEASE b/TODO-RELEASE
index 753e24a..306eed9 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -12,3 +12,4 @@ libosmo-netif > 1.3.0 uses osmo_stream_*_set_name()
libosmo-sccp add API osmo_ss7_asp_get_name(), osmo_ss7_asp_get_proto()
osmo_sccp_simple_client_on_ss7_id() behavior change: ASPs asp-clnt-* defined through VTY must explicitly configure "role" and "sctp-role"
libosmo-netif > 1.3.0 flag OSMO_STREAM_SCTP_MSG_FLAGS_NOTIFICATION set by osmo_stream_cli_recv()
+libosmo-sccp add API osmo_ss7_asp_peer_init(), osmo_ss7_asp_peer_set_hosts2(), osmo_ss7_asp_peer_add_host2()
diff --git a/include/osmocom/sigtran/osmo_ss7.h b/include/osmocom/sigtran/osmo_ss7.h
index 1197ddf..ed3d409 100644
--- a/include/osmocom/sigtran/osmo_ss7.h
+++ b/include/osmocom/sigtran/osmo_ss7.h
@@ -366,6 +366,8 @@ struct osmo_ss7_asp_peer {
char *host[OSMO_SOCK_MAX_ADDRS];
size_t host_cnt;
uint16_t port;
+ /* index in "hosts" array marking the SCTP Primary Address, -1 if no explicit Primary Address set */
+ int idx_primary;
};
enum osmo_ss7_asp_admin_state {
@@ -451,9 +453,13 @@ struct osmo_ss7_asp {
#define OSMO_SS7_ASP_QUIRK_SNM_INACTIVE 0x00000004
int osmo_ss7_asp_peer_snprintf(char* buf, size_t buf_len, struct osmo_ss7_asp_peer *peer);
+void osmo_ss7_asp_peer_init(struct osmo_ss7_asp_peer *peer);
int osmo_ss7_asp_peer_set_hosts(struct osmo_ss7_asp_peer *peer, void *talloc_ctx,
const char *const*hosts, size_t host_cnt);
+int osmo_ss7_asp_peer_set_hosts2(struct osmo_ss7_asp_peer *peer, void *talloc_ctx,
+ const char *const*hosts, size_t host_cnt, int idx_primary);
int osmo_ss7_asp_peer_add_host(struct osmo_ss7_asp_peer *peer, void *talloc_ctx, const char *host);
+int osmo_ss7_asp_peer_add_host2(struct osmo_ss7_asp_peer *peer, void *talloc_ctx, const char *host, bool is_primary_addr);
struct osmo_ss7_asp *
osmo_ss7_asp_find_by_name(struct osmo_ss7_instance *inst, const char *name);
diff --git a/src/osmo_ss7.c b/src/osmo_ss7.c
index 5befdee..7882bc2 100644
--- a/src/osmo_ss7.c
+++ b/src/osmo_ss7.c
@@ -125,6 +125,59 @@ static uint32_t find_free_l_rk_id(struct osmo_ss7_instance *inst)
return -1;
}
+static int _setsockopt_peer_primary_addr(int fd, const struct osmo_sockaddr *saddr)
+{
+ int rc;
+
+ struct sctp_setpeerprim so_sctp_setpeerprim = {0};
+
+ /* rfc6458 sec 8: "For the one-to-one style sockets and branched-off one-to-many
+ * style sockets (see Section 9.2), this association ID parameter is ignored"
+ */
+
+ /* NOTE: Requires setting:
+ * - sysctl net.sctp.addip_enable = 1, otherwise EPERM is returned
+ * - sysctl net.sctp.auth_enable = 1, RFC 5061 4.2.7 "An implementation supporting this
+ * extension MUST list the ASCONF,the ASCONF-ACK, and the AUTH chunks in
+ * its INIT and INIT-ACK parameters."
+ */
+
+ so_sctp_setpeerprim.sspp_addr = saddr->u.sas;
+ rc = setsockopt(fd, IPPROTO_SCTP, SCTP_SET_PEER_PRIMARY_ADDR,
+ &so_sctp_setpeerprim, sizeof(so_sctp_setpeerprim));
+ if (rc < 0) {
+ char buf[128];
+ int err = errno;
+ strerror_r(err, (char *)buf, sizeof(buf));
+ LOGP(DLSS7, LOGL_ERROR, "setsockopt(SCTP_SET_PEER_PRIMARY_ADDR, %s) failed: %s%s\n",
+ osmo_sockaddr_to_str(saddr), buf,
+ err == EPERM ? " (EPERM: Make sure you have sysctl 'net.sctp.auth_enable' "
+ "and 'net.sctp.addip_enable' set to 1)" : "");
+ }
+ return rc;
+}
+
+static int _setsockopt_primary_addr(int fd, const struct osmo_sockaddr *saddr)
+{
+ int rc;
+
+ struct sctp_prim so_sctp_prim = {0};
+
+ /* rfc6458 sec 8: "For the one-to-one style sockets and branched-off one-to-many
+ * style sockets (see Section 9.2), this association ID parameter is ignored"
+ */
+
+ so_sctp_prim.ssp_addr = saddr->u.sas;
+ rc = setsockopt(fd, IPPROTO_SCTP, SCTP_PRIMARY_ADDR,
+ &so_sctp_prim, sizeof(so_sctp_prim));
+ if (rc < 0) {
+ char buf[128];
+ strerror_r(errno, (char *)buf, sizeof(buf));
+ LOGP(DLSS7, LOGL_ERROR, "setsockopt(SCTP_PRIMARY_ADDR, %s) failed: %s\n",
+ osmo_sockaddr_to_str(saddr), buf);
+ }
+ return rc;
+}
/***********************************************************************
* SS7 Point Code Parsing / Printing
@@ -1179,11 +1232,18 @@ static const struct rate_ctr_group_desc ss7_asp_rcgd = {
};
static unsigned int g_ss7_asp_rcg_idx;
+void osmo_ss7_asp_peer_init(struct osmo_ss7_asp_peer *peer)
+{
+ memset(peer, 0, sizeof(*peer));
+ peer->idx_primary = -1;
+}
+
int osmo_ss7_asp_peer_snprintf(char* buf, size_t buf_len, struct osmo_ss7_asp_peer *peer)
{
int len = 0, offset = 0, rem = buf_len;
int ret, i;
char *after;
+ char *primary;
if (buf_len < 3)
return -EINVAL;
@@ -1195,11 +1255,12 @@ int osmo_ss7_asp_peer_snprintf(char* buf, size_t buf_len, struct osmo_ss7_asp_pe
OSMO_SNPRINTF_RET(ret, rem, offset, len);
}
for (i = 0; i < peer->host_cnt; i++) {
+ primary = (peer->idx_primary == i) ? "*" : "";
if (peer->host_cnt == 1)
after = "";
else
after = (i == (peer->host_cnt - 1)) ? ")" : "|";
- ret = snprintf(buf + offset, rem, "%s%s", peer->host[i] ? : "0.0.0.0", after);
+ ret = snprintf(buf + offset, rem, "%s%s%s", peer->host[i] ? : "0.0.0.0", primary, after);
OSMO_SNPRINTF_RET(ret, rem, offset, len);
}
ret = snprintf(buf + offset, rem, ":%u", peer->port);
@@ -1215,11 +1276,15 @@ int osmo_ss7_asp_peer_snprintf(char* buf, size_t buf_len, struct osmo_ss7_asp_pe
* \param[in] talloc_ctx talloc context used to allocate new addresses.
* \param[in] hosts Array of strings containing IP addresses.
* \param[in] host_cnt Number of strings in hosts
+ * \param[in] idx_primary Index in "hosts" array marking the SCTP Primary Address, -1 if no explicit Primary Address set
* \returns 0 on success; negative otherwise */
-int osmo_ss7_asp_peer_set_hosts(struct osmo_ss7_asp_peer *peer, void *talloc_ctx, const char *const*hosts, size_t host_cnt)
+int osmo_ss7_asp_peer_set_hosts2(struct osmo_ss7_asp_peer *peer, void *talloc_ctx, const char *const*hosts, size_t host_cnt, int idx_primary)
{
int i = 0;
+ if (idx_primary >= (int)host_cnt || idx_primary < -1)
+ return -EINVAL;
+
if (host_cnt > ARRAY_SIZE(peer->host))
return -EINVAL;
@@ -1231,9 +1296,21 @@ int osmo_ss7_asp_peer_set_hosts(struct osmo_ss7_asp_peer *peer, void *talloc_ctx
}
peer->host_cnt = host_cnt;
+ peer->idx_primary = idx_primary;
return 0;
}
+/*! \brief Set (copy) addresses for a given ASP peer. Previous addresses are freed.
+ * \param[in] peer Application Server Process peer whose addresses are to be set.
+ * \param[in] talloc_ctx talloc context used to allocate new addresses.
+ * \param[in] hosts Array of strings containing IP addresses.
+ * \param[in] host_cnt Number of strings in hosts
+ * \returns 0 on success; negative otherwise */
+int osmo_ss7_asp_peer_set_hosts(struct osmo_ss7_asp_peer *peer, void *talloc_ctx, const char *const*hosts, size_t host_cnt)
+{
+ return osmo_ss7_asp_peer_set_hosts2(peer, talloc_ctx, hosts, host_cnt, -1);
+}
+
/* Is string formatted IPv4/v6 addr considered IN(6)ADDR_ANY? */
static inline bool host_is_ip_anyaddr(const char *host, bool is_v6)
{
@@ -1247,38 +1324,160 @@ static inline bool host_is_ip_anyaddr(const char *host, bool is_v6)
/*! \brief Append (copy) address to a given ASP peer. Previous addresses are kept.
* \param[in] peer Application Server Process peer the address is appended to.
* \param[in] talloc_ctx talloc context used to allocate new address.
- * \param[in] host string containing an IP addresses.
+ * \param[in] host string containing an IP address.
+ * \param[in] is_primary_addr whether this IP address is to be added as SCTP Primary Address
* \returns 0 on success; negative otherwise */
-int osmo_ss7_asp_peer_add_host(struct osmo_ss7_asp_peer *peer, void *talloc_ctx, const char *host)
+int osmo_ss7_asp_peer_add_host2(struct osmo_ss7_asp_peer *peer, void *talloc_ctx,
+ const char *host, bool is_primary_addr)
{
int i;
bool new_is_v6 = osmo_ip_str_type(host) == AF_INET6;
bool new_is_any = host_is_ip_anyaddr(host, new_is_v6);
- bool iter_is_v6;
+ struct osmo_sockaddr_str addr_str;
- if (peer->host_cnt >= ARRAY_SIZE(peer->host))
+ if (osmo_sockaddr_str_from_str(&addr_str, host, 0) < 0)
return -EINVAL;
- /* Makes no sense to have INET(6)_ANY many times, or INET(6)_ANY
- together with specific addresses, be it of same or different
- IP version:*/
- if (new_is_any && peer->host_cnt != 0)
- return -EINVAL;
+ if (new_is_any) {
+ /* Makes no sense to have INET(6)_ANY many times, or INET(6)_ANY
+ * together with specific addresses, be it of same or different
+ * IP version: */
+ if (peer->host_cnt != 0)
+ return -EINVAL;
+
+ /* Makes no sense to have INET(6)_ANY as primary: */
+ if (is_primary_addr)
+ return -EINVAL;
+
+ if (peer->host_cnt >= ARRAY_SIZE(peer->host))
+ return -EINVAL;
+ osmo_talloc_replace_string(talloc_ctx, &peer->host[peer->host_cnt], host);
+ peer->host_cnt++;
+ return 0;
+ }
+
+ /* Makes no sense to add specific address to set if INET(6)_ANY
+ * is already set, be it from same or different IP version: */
+ for (i = 0; i < peer->host_cnt; i++) {
+ bool iter_is_v6 = osmo_ip_str_type(peer->host[i]) == AF_INET6;
+ if (host_is_ip_anyaddr(peer->host[i], iter_is_v6))
+ return -EINVAL;
+ }
+ /* Reached this point, no INET(6)_ANY address is set nor we are adding an INET(6)_ANY address. */
+
+ /* Check if address already exists, and then if primary flags need to be changed: */
+ for (i = 0; i < peer->host_cnt; i++) {
+ struct osmo_sockaddr_str it_addr_str;
+ bool it_is_primary;
+ osmo_sockaddr_str_from_str(&it_addr_str, peer->host[i], 0);
- if (!new_is_any) {
- /* Makes no sense to add specific address to set if INET(6)_ANY
- is already set, be it from same or different IP version: */
- for (i = 0; i < peer->host_cnt; i++) {
- iter_is_v6 = osmo_ip_str_type(peer->host[i]) == AF_INET6;
- if (host_is_ip_anyaddr(peer->host[i], iter_is_v6))
- return -EINVAL;
+ if (osmo_sockaddr_str_cmp(&addr_str, &it_addr_str) != 0)
+ continue;
+ it_is_primary = (peer->idx_primary == i);
+ if (is_primary_addr == it_is_primary) {
+ /* Nothing to do, return below */
+ } else if (is_primary_addr && !it_is_primary) {
+ /* Mark it as primary: */
+ peer->idx_primary = i;
+ } else { /* if (!is_primary_addr && it_is_primary) { */
+ /* mark it as non-primary: */
+ peer->idx_primary = -1;
}
+ return 0;
}
+
+ if (peer->host_cnt >= ARRAY_SIZE(peer->host))
+ return -EINVAL;
+
osmo_talloc_replace_string(talloc_ctx, &peer->host[peer->host_cnt], host);
+ if (is_primary_addr)
+ peer->idx_primary = peer->host_cnt;
peer->host_cnt++;
return 0;
}
+/*! \brief Append (copy) address to a given ASP peer. Previous addresses are kept.
+ * \param[in] peer Application Server Process peer the address is appended to.
+ * \param[in] talloc_ctx talloc context used to allocate new address.
+ * \param[in] host string containing an IP address.
+ * \returns 0 on success; negative otherwise */
+int osmo_ss7_asp_peer_add_host(struct osmo_ss7_asp_peer *peer, void *talloc_ctx,
+ const char *host)
+{
+ return osmo_ss7_asp_peer_add_host2(peer, talloc_ctx, host, false);
+}
+
+static int asp_apply_peer_primary_address(const struct osmo_ss7_asp *asp)
+{
+ struct osmo_fd *ofd;
+ struct osmo_sockaddr_str addr_str;
+ struct osmo_sockaddr addr;
+ uint16_t local_port;
+ int rc;
+
+ /* No SCTP Peer Primary Address explicitly configured, do nothing. */
+ if (asp->cfg.local.idx_primary == -1)
+ return 0;
+ OSMO_ASSERT(asp->cfg.local.idx_primary < asp->cfg.local.host_cnt);
+
+ if (asp->cfg.is_server)
+ ofd = osmo_stream_srv_get_ofd(asp->server);
+ else
+ ofd = osmo_stream_cli_get_ofd(asp->client);
+
+ if (asp->cfg.local.port == 0) {
+ char port_buf[16];
+ osmo_sock_get_local_ip_port(ofd->fd, port_buf, sizeof(port_buf));
+ local_port = atoi(port_buf);
+ } else {
+ local_port = asp->cfg.local.port;
+ }
+ rc = osmo_sockaddr_str_from_str(&addr_str,
+ asp->cfg.local.host[asp->cfg.local.idx_primary],
+ local_port);
+ if (rc < 0)
+ return rc;
+ rc = osmo_sockaddr_str_to_sockaddr(&addr_str, &addr.u.sas);
+ if (rc < 0)
+ return rc;
+ LOGPASP(asp, DLSS7, LOGL_INFO, "Set Peer's Primary Address %s\n",
+ osmo_sockaddr_to_str(&addr));
+ rc = _setsockopt_peer_primary_addr(ofd->fd, &addr);
+
+ return rc;
+}
+
+static int asp_apply_primary_address(const struct osmo_ss7_asp *asp)
+{
+ struct osmo_fd *ofd;
+ struct osmo_sockaddr_str addr_str;
+ struct osmo_sockaddr addr;
+ int rc;
+
+ /* No SCTP Primary Address explicitly configured, do nothing. */
+ if (asp->cfg.remote.idx_primary == -1)
+ return 0;
+ OSMO_ASSERT(asp->cfg.remote.idx_primary < asp->cfg.remote.host_cnt);
+
+ if (asp->cfg.is_server)
+ ofd = osmo_stream_srv_get_ofd(asp->server);
+ else
+ ofd = osmo_stream_cli_get_ofd(asp->client);
+
+ rc = osmo_sockaddr_str_from_str(&addr_str,
+ asp->cfg.remote.host[asp->cfg.remote.idx_primary],
+ asp->cfg.remote.port);
+ if (rc < 0)
+ return rc;
+ rc = osmo_sockaddr_str_to_sockaddr(&addr_str, &addr.u.sas);
+ if (rc < 0)
+ return rc;
+ LOGPASP(asp, DLSS7, LOGL_INFO, "Set Primary Address %s\n",
+ osmo_sockaddr_to_str(&addr));
+ rc = _setsockopt_primary_addr(ofd->fd, &addr);
+ return rc;
+}
+
static bool ipv6_sctp_supported(const char *host, bool bind)
{
int rc;
@@ -1534,7 +1733,9 @@ osmo_ss7_asp_alloc(struct osmo_ss7_instance *inst, const char *name,
}
rate_ctr_group_set_name(asp->ctrg, name);
asp->inst = inst;
+ osmo_ss7_asp_peer_init(&asp->cfg.remote);
asp->cfg.remote.port = remote_port;
+ osmo_ss7_asp_peer_init(&asp->cfg.local);
asp->cfg.local.port = local_port;
asp->cfg.proto = proto;
asp->cfg.name = talloc_strdup(asp, name);
@@ -1849,6 +2050,7 @@ static int xua_cli_connect_cb(struct osmo_stream_cli *cli)
{
struct osmo_fd *ofd = osmo_stream_cli_get_ofd(cli);
struct osmo_ss7_asp *asp = osmo_stream_cli_get_data(cli);
+ int rc = 0;
/* update the socket name */
talloc_free(asp->sock_name);
@@ -1856,6 +2058,15 @@ static int xua_cli_connect_cb(struct osmo_stream_cli *cli)
LOGPASP(asp, DLSS7, LOGL_INFO, "Client connected %s\n", asp->sock_name);
+ /* Now that we have the conn in place, the local/remote addresses are
+ * fed and the local port is known for sure. Apply SCTP Primary addresses
+ * if needed:
+ */
+ if (asp->cfg.proto != OSMO_SS7_ASP_PROT_IPA) {
+ rc = asp_apply_peer_primary_address(asp);
+ rc = asp_apply_primary_address(asp);
+ }
+
if (asp->lm && asp->lm->prim_cb) {
/* Notify layer manager that a connection has been
* established */
@@ -1865,7 +2076,7 @@ static int xua_cli_connect_cb(struct osmo_stream_cli *cli)
osmo_fsm_inst_dispatch(asp->fi, XUA_ASP_E_M_ASP_UP_REQ, NULL);
}
- return 0;
+ return rc;
}
static void xua_cli_close(struct osmo_stream_cli *cli)
@@ -2016,6 +2227,7 @@ static int xua_accept_cb(struct osmo_stream_srv_link *link, int fd)
struct osmo_ss7_asp *asp;
char *sock_name = osmo_sock_get_name(link, fd);
const char *proto_name = get_value_string(osmo_ss7_asp_protocol_vals, oxs->cfg.proto);
+ int rc = 0;
LOGP(DLSS7, LOGL_INFO, "%s: New %s connection accepted\n", sock_name, proto_name);
@@ -2105,11 +2317,16 @@ static int xua_accept_cb(struct osmo_stream_srv_link *link, int fd)
* data */
osmo_stream_srv_set_data(srv, asp);
+ if (oxs->cfg.proto != OSMO_SS7_ASP_PROT_IPA) {
+ rc = asp_apply_peer_primary_address(asp);
+ rc = asp_apply_primary_address(asp);
+ }
+
/* send M-SCTP_ESTABLISH.ind to Layer Manager */
osmo_fsm_inst_dispatch(asp->fi, XUA_ASP_E_SCTP_EST_IND, 0);
xua_asp_send_xlm_prim_simple(asp, OSMO_XLM_PRIM_M_SCTP_ESTABLISH, PRIM_OP_INDICATION);
- return 0;
+ return rc;
}
/*! \brief send a fully encoded msgb via a given ASP
diff --git a/src/osmo_ss7_vty.c b/src/osmo_ss7_vty.c
index 61f14cd..44ba780 100644
--- a/src/osmo_ss7_vty.c
+++ b/src/osmo_ss7_vty.c
@@ -656,14 +656,17 @@ DEFUN_ATTR(no_cs7_asp, no_cs7_asp_cmd,
}
DEFUN_ATTR(asp_local_ip, asp_local_ip_cmd,
- "local-ip " VTY_IPV46_CMD,
+ "local-ip " VTY_IPV46_CMD " [primary]",
"Specify Local IP Address from which to contact ASP\n"
"Local IPv4 Address from which to contact of ASP\n"
- "Local IPv6 Address from which to contact of ASP\n",
+ "Local IPv6 Address from which to contact of ASP\n"
+ "Signal the SCTP peer to use this address as Primary Address\n",
CMD_ATTR_NODE_EXIT)
{
struct osmo_ss7_asp *asp = vty->index;
- if (osmo_ss7_asp_peer_add_host(&asp->cfg.local, asp, argv[0]) != 0) {
+ bool is_primary = argc > 1;
+
+ if (osmo_ss7_asp_peer_add_host2(&asp->cfg.local, asp, argv[0], is_primary) != 0) {
vty_out(vty, "%% Failed adding host '%s' to set%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
@@ -671,14 +674,17 @@ DEFUN_ATTR(asp_local_ip, asp_local_ip_cmd,
}
DEFUN_ATTR(asp_remote_ip, asp_remote_ip_cmd,
- "remote-ip " VTY_IPV46_CMD,
+ "remote-ip " VTY_IPV46_CMD " [primary]",
"Specify Remote IP Address of ASP\n"
"Remote IPv4 Address of ASP\n"
- "Remote IPv6 Address of ASP\n",
+ "Remote IPv6 Address of ASP\n"
+ "Set remote address as SCTP Primary Address\n",
CMD_ATTR_NODE_EXIT)
{
struct osmo_ss7_asp *asp = vty->index;
- if (osmo_ss7_asp_peer_add_host(&asp->cfg.remote, asp, argv[0]) != 0) {
+ bool is_primary = argc > 1;
+
+ if (osmo_ss7_asp_peer_add_host2(&asp->cfg.remote, asp, argv[0], is_primary) != 0) {
vty_out(vty, "%% Failed adding host '%s' to set%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
@@ -937,11 +943,13 @@ static void write_one_asp(struct vty *vty, struct osmo_ss7_asp *asp, bool show_d
vty_out(vty, " description %s%s", asp->cfg.description, VTY_NEWLINE);
for (i = 0; i < asp->cfg.local.host_cnt; i++) {
if (asp->cfg.local.host[i])
- vty_out(vty, " local-ip %s%s", asp->cfg.local.host[i], VTY_NEWLINE);
+ vty_out(vty, " local-ip %s%s%s", asp->cfg.local.host[i],
+ asp->cfg.local.idx_primary == i ? " primary" : "", VTY_NEWLINE);
}
for (i = 0; i < asp->cfg.remote.host_cnt; i++) {
if (asp->cfg.remote.host[i])
- vty_out(vty, " remote-ip %s%s", asp->cfg.remote.host[i], VTY_NEWLINE);
+ 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.qos_class)
vty_out(vty, " qos-class %u%s", asp->cfg.qos_class, VTY_NEWLINE);
diff --git a/tests/vty/ss7_asp_test.vty b/tests/vty/ss7_asp_test.vty
index 3296c65..d23f9c0 100644
--- a/tests/vty/ss7_asp_test.vty
+++ b/tests/vty/ss7_asp_test.vty
@@ -220,8 +220,8 @@ ss7_asp_vty_test(config-cs7)# asp my-asp 12345 54321 m3ua
ss7_asp_vty_test(config-cs7-asp)# list
...
description .TEXT
- remote-ip (A.B.C.D|X:X::X:X)
- local-ip (A.B.C.D|X:X::X:X)
+ remote-ip (A.B.C.D|X:X::X:X) [primary]
+ local-ip (A.B.C.D|X:X::X:X) [primary]
qos-class <0-255>
role (sg|asp|ipsp)
sctp-role (client|server)
@@ -255,6 +255,40 @@ ss7_asp_vty_test(config-cs7-asp)# do show cs7 instance 0 asp
ASP Name AS Name State Type Role Remote IPaddr & Port SCTP Role
------------ ------------ ------------- ---- ---- ----------------------- ---------
my-asp ? uninitialized m3ua sg (127.0.0.200|127.0.0.201):12345 server
+ss7_asp_vty_test(config-cs7-asp)# ! Mark as primary:
+ss7_asp_vty_test(config-cs7-asp)# remote-ip 127.0.0.201 primary
+ss7_asp_vty_test(config-cs7-asp)# ! 'local-ip 127.0.0.101 primary' cannot be tested here since output may be different based on sysctl available
+ss7_asp_vty_test(config-cs7-asp)# local-ip 127.0.0.101
+...
+ss7_asp_vty_test(config-cs7-asp)# do show cs7 instance 0 asp
+ Current Primary Link
+ASP Name AS Name State Type Role Remote IPaddr & Port SCTP Role
+------------ ------------ ------------- ---- ---- ----------------------- ---------
+my-asp ? uninitialized m3ua sg (127.0.0.200|127.0.0.201*):12345 server
+ss7_asp_vty_test(config-cs7-asp)# show running-config
+...
+ local-ip 127.0.0.100
+ local-ip 127.0.0.101
+ remote-ip 127.0.0.200
+ remote-ip 127.0.0.201 primary
+...
+end
+ss7_asp_vty_test(config-cs7-asp)# ! Mark as non-primary:
+ss7_asp_vty_test(config-cs7-asp)# remote-ip 127.0.0.201
+ss7_asp_vty_test(config-cs7-asp)# local-ip 127.0.0.101
+ss7_asp_vty_test(config-cs7-asp)# do show cs7 instance 0 asp
+ Current Primary Link
+ASP Name AS Name State Type Role Remote IPaddr & Port SCTP Role
+------------ ------------ ------------- ---- ---- ----------------------- ---------
+my-asp ? uninitialized m3ua sg (127.0.0.200|127.0.0.201):12345 server
+ss7_asp_vty_test(config-cs7-asp)# show running-config
+...
+ local-ip 127.0.0.100
+ local-ip 127.0.0.101
+ remote-ip 127.0.0.200
+ remote-ip 127.0.0.201
+...
+end
ss7_asp_vty_test(config-cs7-asp)# exit
ss7_asp_vty_test(config-cs7)# as my-ass m3ua