This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
lynxis lazus gerrit-no-reply at lists.osmocom.orglynxis lazus has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-pcu/+/20565 ) Change subject: Rework NS configuration over the info indication ...................................................................... Rework NS configuration over the info indication Add support of the second NSVC in the info indication. Add support to update a previous NS configuration. Allow to update of a NS-VC while the NSE is still available over the second. Depends-on: I917f25ebd1239eae5855d973ced15b93731e33a0 (libosmocore) Depends-on: I3a0cd305fd73b3cb9ec70246ec15ac70b83e57f2 (libosmocore) Depends-on: I5a2bb95d05d06d909347e2fb084a446ead888cb3 (libosmocore) Depends-on: I54f110acc3acccb362f6e554324d08cc42b7c328 (libosmocore) Depends-on: Ia00753a64b7622a0864341f51ea49b6963543755 (libosmocore) Depends-on: Ic8f6f8aca10da23a18fab8870be7806065a34b47 (libosmocore) Depends-on: I5f67e6a9bf4cb322bd169061fee0a528012ed54d (libosmocore) Change-Id: I589ebaa2a2b7de55b7e4e975d8fd6412dd5f214b --- M include/osmocom/pcu/pcuif_proto.h M src/gprs_bssgp_pcu.cpp M src/gprs_bssgp_pcu.h M src/pcu_l1_if.cpp M tests/emu/pcu_emu.cpp 5 files changed, 207 insertions(+), 78 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/65/20565/1 diff --git a/include/osmocom/pcu/pcuif_proto.h b/include/osmocom/pcu/pcuif_proto.h index 82d761d..cdd73d9 100644 --- a/include/osmocom/pcu/pcuif_proto.h +++ b/include/osmocom/pcu/pcuif_proto.h @@ -56,6 +56,8 @@ #define PCU_IF_ADDR_TYPE_IPV4 0x04 /* IPv4 address */ #define PCU_IF_ADDR_TYPE_IPV6 0x29 /* IPv6 address */ +#define PCU_IF_NUM_NSVC 2 + enum gsm_pcu_if_text_type { PCU_VERSION, PCU_OML_ALERT, @@ -167,14 +169,14 @@ uint8_t initial_cs; uint8_t initial_mcs; /* NSVC */ - uint16_t nsvci[2]; - uint16_t local_port[2]; - uint16_t remote_port[2]; - uint8_t address_type[2]; + uint16_t nsvci[PCU_IF_NUM_NSVC]; + uint16_t local_port[PCU_IF_NUM_NSVC]; + uint16_t remote_port[PCU_IF_NUM_NSVC]; + uint8_t address_type[PCU_IF_NUM_NSVC]; union { struct in_addr v4; struct in6_addr v6; - } remote_ip[2]; + } remote_ip[PCU_IF_NUM_NSVC]; } __attribute__ ((packed)); struct gsm_pcu_if_act_req { diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index e0cfc37..357df79 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -920,21 +920,37 @@ osmo_timer_schedule(&the_pcu.bvc_timer, the_pcu.bts->fc_interval, 0); } - -int gprs_nsvc_create_and_connect(struct gprs_rlcmac_bts *bts, - const struct osmo_sockaddr *local, - const struct osmo_sockaddr *sgsn, - uint16_t nsei, uint16_t nsvci) +static int ns_create_nsvc(struct gprs_rlcmac_bts *bts, + uint16_t nsei, + const struct osmo_sockaddr *local, + const struct osmo_sockaddr *remote, + const uint16_t *nsvci, + int valid) { + int i, rc; + int binds = 0, nsvcs = 0; struct gprs_ns2_vc *nsvc; - struct gprs_ns2_vc_bind *bind; - int rc; + struct gprs_ns2_vc_bind *bind[PCU_IF_NUM_NSVC] = { }; - rc = gprs_ns2_ip_bind(bts->nsi, local, 0, &bind); - if (rc < 0) { - LOGP(DBSSGP, LOGL_ERROR, "Failed to create socket\n"); - gprs_ns2_free(bts->nsi); - return 1; + if (!valid) + return -1; + + for (i=0; i < PCU_IF_NUM_NSVC; i++) { + if (!(valid & (1 << i))) + continue; + + rc = gprs_ns2_ip_bind(bts->nsi, &local[i], 0, &bind[i]); + if (rc < 0 && rc != -EBUSY) { + LOGP(DBSSGP, LOGL_ERROR, "Failed to bind to %s\n", osmo_sockaddr_to_str(&local[i])); + return 1; + } + + binds |= 1 << i; + } + + if (!binds) { + LOGP(DBSSGP, LOGL_ERROR, "Failed to bind to any NS-VC\n"); + return -1; } bts->nse = gprs_ns2_nse_by_nsei(bts->nsi, nsei); @@ -943,16 +959,119 @@ if (!bts->nse) { LOGP(DBSSGP, LOGL_ERROR, "Failed to create NSE\n"); - gprs_ns2_free_bind(bind); + gprs_ns2_free_binds(bts->nsi); return 1; } - if (bts->gb_dialect_sns) { - rc = gprs_ns2_ip_connect_sns(bind, sgsn, nsei); + for (i=0; i < PCU_IF_NUM_NSVC; i++) { + if (!(binds & (1 << i))) + continue; + + /* FIXME: for SNS we just use the first successful NS-VC instead of all for the initial connect */ + if (bts->gb_dialect_sns) { + rc = gprs_ns2_ip_connect_sns(bind[i], &remote[i], nsei); + if (!rc) + return rc; + else + LOGP(DBSSGP, LOGL_ERROR, "Failed to connect to (SNS) towards SGSN %s!\n", osmo_sockaddr_to_str(&remote[i])); + } else { + nsvc = gprs_ns2_ip_connect(bind[i], &remote[i], bts->nse, nsvci[i]); + if (nsvc) + nsvcs |= 1 << i; + else + LOGP(DBSSGP, LOGL_ERROR, "Failed to connect to towards SGSN %s!\n", osmo_sockaddr_to_str(&remote[i])); + } + } + + return nsvc ? 0 : -1; +} + +struct nsvc_cb { + const struct osmo_sockaddr *local; + const struct osmo_sockaddr *remote; + const uint16_t *nsvci; + /* [in] bitmask of valid nsvc in local/remote */ + int valid; + /* [out] bitmask of found nsvcs */ + int found; +}; + +static int ns_conf_vc_cb(struct gprs_ns2_vc *nsvc, void *ctx) +{ + struct nsvc_cb *data = (struct nsvc_cb *) ctx; + + for (unsigned int i = 0; i < PCU_IF_NUM_NSVC; i++) { + if (!(data->valid & (1 << i))) + continue; + if (data->found & (1 << i)) + continue; + + if (gprs_ns2_ip_vc_equal(nsvc, &data->local[i], + &data->remote[i], + data->nsvci[i])) { + data->found |= 1 << i; + return 0; + } + } + + /* Found an extra nsvc */ + LOGP(DBSSGP, LOGL_DEBUG, " Removing NSVC %s\n", gprs_ns2_ll_str(nsvc)); + gprs_ns2_free_nsvc(nsvc); + + return 0; +} + +int gprs_ns_config(struct gprs_rlcmac_bts *bts, uint16_t nsei, + const struct osmo_sockaddr *local, + const struct osmo_sockaddr *remote, + uint16_t *nsvci, int valid) +{ + int rc = 0; + if (!bts->nse) { + /* there shouldn't any previous state. */ + gprs_ns2_free_nses(bts->nsi); + gprs_ns2_free_binds(bts->nsi); + rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid); + } else if (nsei != gprs_ns2_nse_nsei(bts->nse)) { + /* the NSEI has changed */ + gprs_ns2_free_nses(bts->nsi); + gprs_ns2_free_binds(bts->nsi); + rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid); + } else if (bts->gb_dialect_sns) { + /* SNS: check if the initial nsvc is the same, if not recreate it */ + const struct osmo_sockaddr *initial = gprs_ns2_nse_sns_remote(bts->nse); + for (unsigned int i = 0; i < PCU_IF_NUM_NSVC; i++) { + if (!(valid & (1 << i))) + continue; + + /* found the initial - everything should be fine */ + if (!osmo_sockaddr_cmp(initial, &remote[i])) + return 0; + } + + gprs_ns2_free_nses(bts->nsi); + gprs_ns2_free_binds(bts->nsi); + rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid); } else { - nsvc = gprs_ns2_ip_connect2(bind, sgsn, nsei, nsvci); - if (!nsvc) - rc = -1; + /* check if all NSVC are still the same. */ + struct nsvc_cb data = { + .local = &local[0], + .remote = &remote[0], + .nsvci = &nsvci[0], + .valid = valid, + .found = 0, + }; + + /* search the current active nsvcs */ + gprs_ns2_nse_foreach_nsvc(bts->nse, &ns_conf_vc_cb, &data); + + /* we found all our valid nsvcs and might removed all other nsvcs */ + if (valid == data.found) + return 0; + + /* remove all found nsvcs from the valid field */ + valid &= ~data.found; + rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid); } if (rc) diff --git a/src/gprs_bssgp_pcu.h b/src/gprs_bssgp_pcu.h index 078f488..1bd0b43 100644 --- a/src/gprs_bssgp_pcu.h +++ b/src/gprs_bssgp_pcu.h @@ -81,10 +81,10 @@ uint16_t mcc, uint16_t mnc, bool mnc_3_digits, uint16_t lac, uint16_t rac, uint16_t cell_id); -int gprs_nsvc_create_and_connect(struct gprs_rlcmac_bts *bts, - const struct osmo_sockaddr *local, - const struct osmo_sockaddr *sgsn, - uint16_t nsei, uint16_t nsvci); +int gprs_ns_config(struct gprs_rlcmac_bts *bts, uint16_t nsei, + const struct osmo_sockaddr *local, + const struct osmo_sockaddr *remote, + uint16_t *nsvci, int valid); int gprs_ns_prim_cb(struct osmo_prim_hdr *oph, void *ctx); int gprs_gp_send_cb(void *ctx, struct msgb *msg); diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp index 99d4a58..2f379f5 100644 --- a/src/pcu_l1_if.cpp +++ b/src/pcu_l1_if.cpp @@ -39,6 +39,7 @@ #include <osmocom/core/sockaddr_str.h> #include <osmocom/core/logging.h> #include <osmocom/core/utils.h> +#include <osmocom/gprs/gprs_ns2.h> #include <osmocom/gsm/l1sap.h> #include <osmocom/gsm/protocol/gsm_04_08.h> } @@ -488,12 +489,64 @@ return rc; } +static int pcu_info_ind_ns(struct gprs_rlcmac_bts *bts, + const struct gsm_pcu_if_info_ind *info_ind) +{ + struct osmo_sockaddr remote[PCU_IF_NUM_NSVC] = { }; + struct osmo_sockaddr local[PCU_IF_NUM_NSVC] = { }; + uint16_t nsvci[PCU_IF_NUM_NSVC] = { }; + int valid = 0; + + for (unsigned int i = 0; i < PCU_IF_NUM_NSVC; i++) { + struct osmo_sockaddr_str sockstr; + + switch (info_ind->address_type[i]) { + case PCU_IF_ADDR_TYPE_IPV4: + local[i].u.sin.sin_family = AF_INET; + local[i].u.sin.sin_addr.s_addr = INADDR_ANY; + local[i].u.sin.sin_port = htons(info_ind->local_port[i]); + + remote[i].u.sin.sin_family = AF_INET; + remote[i].u.sin.sin_addr = info_ind->remote_ip[i].v4; + remote[i].u.sin.sin_port = htons(info_ind->remote_port[i]); + break; + case PCU_IF_ADDR_TYPE_IPV6: + local[i].u.sin6.sin6_family = AF_INET6; + local[i].u.sin6.sin6_addr = in6addr_any; + local[i].u.sin6.sin6_port = htons(info_ind->local_port[i]); + + remote[i].u.sin6.sin6_family = AF_INET6; + remote[i].u.sin6.sin6_addr = info_ind->remote_ip[i].v6; + remote[i].u.sin6.sin6_port = htons(info_ind->remote_port[i]); + break; + default: + continue; + } + nsvci[i] = info_ind->nsvci[i]; + + LOGP(DL1IF, LOGL_DEBUG, " NS%u nsvci=%u\n", i, nsvci[i]); + if (osmo_sockaddr_str_from_sockaddr(&sockstr, &remote[i].u.sas)) + strcpy(sockstr.ip, "invalid"); + + LOGP(DL1IF, LOGL_DEBUG, " NS%u address: r=%s:%u<->l=NULL:%u\n", + i, sockstr.ip, sockstr.port, info_ind->local_port[i]); + + valid |= 1 << i; + } + + if (valid == 0) { + LOGP(DL1IF, LOGL_ERROR, "No NSVC available to connect to the SGSN!\n"); + return -EINVAL; + } + + return gprs_ns_config(bts, info_ind->nsei, local, remote, nsvci, valid); +} + static int pcu_rx_info_ind(const struct gsm_pcu_if_info_ind *info_ind) { struct gprs_rlcmac_bts *bts = bts_main_data(); struct gprs_bssgp_pcu *pcu; int rc = 0; - int good_nsvc = 0; unsigned int trx_nr, ts_nr; int i; @@ -578,54 +631,8 @@ goto bssgp_failed; } - for (unsigned int i = 0; i < ARRAY_SIZE(info_ind->nsvci); i++) { - struct osmo_sockaddr remote_sockaddr = { }; - struct osmo_sockaddr local_sockaddr = { }; - struct osmo_sockaddr_str sockstr; - - switch (info_ind->address_type[i]) { - case PCU_IF_ADDR_TYPE_IPV4: - local_sockaddr.u.sin.sin_family = AF_INET; - local_sockaddr.u.sin.sin_addr.s_addr = INADDR_ANY; - local_sockaddr.u.sin.sin_port = htons(info_ind->local_port[i]); - - remote_sockaddr.u.sin.sin_family = AF_INET; - remote_sockaddr.u.sin.sin_addr = info_ind->remote_ip[i].v4; - remote_sockaddr.u.sin.sin_port = htons(info_ind->remote_port[i]); - break; - case PCU_IF_ADDR_TYPE_IPV6: - local_sockaddr.u.sin6.sin6_family = AF_INET6; - local_sockaddr.u.sin6.sin6_addr = in6addr_any; - local_sockaddr.u.sin6.sin6_port = htons(info_ind->local_port[i]); - - remote_sockaddr.u.sin6.sin6_family = AF_INET6; - remote_sockaddr.u.sin6.sin6_addr = info_ind->remote_ip[i].v6; - remote_sockaddr.u.sin6.sin6_port = htons(info_ind->remote_port[i]); - break; - default: - continue; - } - - LOGP(DL1IF, LOGL_DEBUG, " NS%u nsvci=%u\n", i, info_ind->nsvci[i]); - - if (osmo_sockaddr_str_from_sockaddr(&sockstr, &remote_sockaddr.u.sas)) - strcpy(sockstr.ip, "invalid"); - - LOGP(DL1IF, LOGL_DEBUG, " NS%u address: r=%s:%u<->l=NULL:%u\n", - i, sockstr.ip, sockstr.port, info_ind->local_port[i]); - rc = gprs_nsvc_create_and_connect(bts, - &local_sockaddr, &remote_sockaddr, - info_ind->nsei, info_ind->nsvci[i]); - if (rc) { - LOGP(DL1IF, LOGL_ERROR, "Failed to create NSVC connection to %s:%u!\n", - sockstr.ip, sockstr.port); - continue; - } - - good_nsvc++; - } - - if (good_nsvc == 0) { + rc = pcu_info_ind_ns(pcu->bts, info_ind); + if (rc < 0) { LOGP(DL1IF, LOGL_ERROR, "No NSVC available to connect to the SGSN!\n"); goto bssgp_failed; } diff --git a/tests/emu/pcu_emu.cpp b/tests/emu/pcu_emu.cpp index 98da13e..853fcb9 100644 --- a/tests/emu/pcu_emu.cpp +++ b/tests/emu/pcu_emu.cpp @@ -94,6 +94,8 @@ { struct gprs_bssgp_pcu *pcu; struct osmo_sockaddr local, remote; + uint16_t nsvci = 20; + uint16_t nsei = 20; local.u.sin.sin_family = AF_INET; local.u.sin.sin_addr.s_addr = 0; @@ -104,8 +106,7 @@ remote.u.sin.sin_port = htons(sgsn_port); pcu = gprs_bssgp_init(bts, 20, 20, 901, 99, false, 1, 0, 0); - gprs_nsvc_create_and_connect(bts, &local, &remote, - 20, 20); + gprs_ns_config(bts, nsei, &local, &remote, &nsvci, 1); pcu->on_unblock_ack = bvci_unblocked; pcu->on_dl_unit_data = bssgp_data; -- To view, visit https://gerrit.osmocom.org/c/osmo-pcu/+/20565 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-pcu Gerrit-Branch: master Gerrit-Change-Id: I589ebaa2a2b7de55b7e4e975d8fd6412dd5f214b Gerrit-Change-Number: 20565 Gerrit-PatchSet: 1 Gerrit-Owner: lynxis lazus <lynxis at fe80.eu> Gerrit-MessageType: newchange -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201012/e665f6ac/attachment.htm>