lynxis lazus has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmocore/+/24591 )
Change subject: gprs_ns2_sns: implement outbound DEL SNS procedures ...................................................................... gprs_ns2_sns: implement outbound DEL SNS procedures When removing a bind the remote side needs to be informed via the SNS-DELETE procedure. Related: OS#5036 Change-Id: I53cd54dfd262c70c425c3f13dad3b29526daa523 --- M src/gb/gprs_ns2_sns.c 1 file changed, 76 insertions(+), 7 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/91/24591/1 diff --git a/src/gb/gprs_ns2_sns.c b/src/gb/gprs_ns2_sns.c index 656e06f..091a62b 100644 --- a/src/gb/gprs_ns2_sns.c +++ b/src/gb/gprs_ns2_sns.c @@ -592,6 +592,32 @@ return -1; } +static int remove_bind_elem(struct ns2_sns_state *gss, struct ns2_sns_elems *elems, struct ns2_sns_bind *sbind) +{ + struct gprs_ns_ie_ip4_elem ip4; + struct gprs_ns_ie_ip6_elem ip6; + const struct osmo_sockaddr *saddr = gprs_ns2_ip_bind_sockaddr(sbind->bind); + + switch (saddr->u.sa.sa_family) { + case AF_INET: + ip4.ip_addr = saddr->u.sin.sin_addr.s_addr; + ip4.udp_port = saddr->u.sin.sin_port; + ip4.sig_weight = sbind->bind->sns_sig_weight; + ip4.data_weight = sbind->bind->sns_data_weight; + return remove_ip4_elem(gss, elems, &ip4); + case AF_INET6: + memcpy(&ip6.ip_addr, &saddr->u.sin6.sin6_addr, sizeof(struct in6_addr)); + ip6.udp_port = saddr->u.sin.sin_port; + ip6.sig_weight = sbind->bind->sns_sig_weight; + ip6.data_weight = sbind->bind->sns_data_weight; + return remove_ip6_elem(gss, elems, &ip6); + default: + return -1; + } + + return -1; +} + static int do_sns_change_weight(struct osmo_fsm_inst *fi, const struct gprs_ns_ie_ip4_elem *ip4, const struct gprs_ns_ie_ip6_elem *ip6) { struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv; @@ -1484,6 +1510,12 @@ else ns2_tx_sns_change_weight(gss->sns_nsvc, gss->current_procedure->trans_id, NULL, 0, &gss->current_procedure->ip6, 1); break; + case SNS_DEL: + if (gss->family == AF_INET) + ns2_tx_sns_del(gss->sns_nsvc, gss->current_procedure->trans_id, &gss->current_procedure->ip4, 1, NULL, 0); + else + ns2_tx_sns_del(gss->sns_nsvc, gss->current_procedure->trans_id, NULL, 0, &gss->current_procedure->ip6, 1); + break; default: break; } @@ -1596,8 +1628,11 @@ add_ip6_elem(gss, &gss->local, &gss->current_procedure->ip6); break; } - create_nsvc_for_new_sbind(gss, gss->current_procedure->sbind); - gprs_ns2_start_alive_all_nsvcs(nse); + /* the sbind can be NULL if the bind has been released by del_bind */ + if (gss->current_procedure->sbind) { + create_nsvc_for_new_sbind(gss, gss->current_procedure->sbind); + gprs_ns2_start_alive_all_nsvcs(nse); + } break; case SNS_CHANGE_WEIGHT: switch (gss->family) { @@ -1630,6 +1665,16 @@ OSMO_ASSERT(0); } break; + case SNS_DEL: + switch (gss->family) { + case AF_INET: + remove_ip4_elem(gss, &gss->local, &gss->current_procedure->ip4); + break; + case AF_INET6: + remove_ip6_elem(gss, &gss->local, &gss->current_procedure->ip6); + break; + } + break; default: break; } @@ -1851,6 +1896,8 @@ switch (procedure_type) { case SNS_ADD: break; + case SNS_DEL: + break; case SNS_CHANGE_WEIGHT: llist_for_each_entry(procedure, &gss->procedures, list) { if (procedure->sbind == sbind && procedure->procedure == procedure_type && @@ -1881,8 +1928,16 @@ if (!procedure) return; + switch (procedure_type) { + case SNS_ADD: + case SNS_CHANGE_WEIGHT: + procedure->sbind = sbind; + break; + default: + break; + } + llist_add_tail(&procedure->list, &gss->procedures); - procedure->sbind = sbind; procedure->procedure = procedure_type; procedure->sig_weight = sbind->bind->sns_sig_weight; procedure->data_weight = sbind->bind->sns_data_weight; @@ -1895,7 +1950,6 @@ procedure->ip4.data_weight = sbind->bind->sns_data_weight; break; case AF_INET6: - memcpy(&procedure->ip6.ip_addr, &saddr->u.sin6.sin6_addr, sizeof(struct in6_addr)); procedure->ip6.udp_port = saddr->u.sin.sin_port; procedure->ip6.sig_weight = sbind->bind->sns_sig_weight; @@ -1950,6 +2004,7 @@ struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv; struct ns2_sns_bind *sbind; struct gprs_ns2_vc *nsvc, *nsvc2; + struct ns2_sns_procedure *procedure; switch (event) { case GPRS_SNS_EV_REQ_ADD_BIND: @@ -2022,25 +2077,39 @@ case GPRS_SNS_ST_UNCONFIGURED: break; case GPRS_SNS_ST_BSS_SIZE: - /* TODO: remove the ip4 element from the list */ llist_for_each_entry_safe(nsvc, nsvc2, &nse->nsvc, list) { if (nsvc->bind == sbind->bind) { gprs_ns2_free_nsvc(nsvc); } } + osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_REQ_SELECT_ENDPOINT, NULL); break; case GPRS_SNS_ST_BSS_CONFIG_BSS: case GPRS_SNS_ST_BSS_CONFIG_SGSN: case GPRS_SNS_ST_CONFIGURED: - /* TODO: do an delete SNS-IP procedure */ - /* TODO: remove the ip4 element to the list */ + case GPRS_SNS_ST_LOCAL_PROCEDURE: + remove_bind_elem(gss, &gss->local_procedure, sbind); + if (ip46_weight_sum(&gss->local_procedure, true) == 0 || + ip46_weight_sum(&gss->local_procedure, false) == 0) { + LOGPFSML(fi, LOGL_ERROR, "NSE %d: weight become invalid because of removing bind %s. Resetting the configuration\n", + nse->nsei, sbind->bind->name); + osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_REQ_SELECT_ENDPOINT, NULL); + break; + } llist_for_each_entry_safe(nsvc, nsvc2, &nse->nsvc, list) { if (nsvc->bind == sbind->bind) { gprs_ns2_free_nsvc(nsvc); } } + /* ensure other procedures doesn't use the sbind */ + llist_for_each_entry(procedure, &gss->procedures, list) { + if (procedure->sbind == sbind) + procedure->sbind = NULL; + } + ns2_add_procedure(gss, sbind, SNS_DEL); break; } + /* if this is the last bind, the free_nsvc() will trigger a reselection */ talloc_free(sbind); break; -- To view, visit https://gerrit.osmocom.org/c/libosmocore/+/24591 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Change-Id: I53cd54dfd262c70c425c3f13dad3b29526daa523 Gerrit-Change-Number: 24591 Gerrit-PatchSet: 1 Gerrit-Owner: lynxis lazus <lyn...@fe80.eu> Gerrit-MessageType: newchange