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/libosmocore/+/21244 ) Change subject: ns2: implement link sharing selector ...................................................................... ns2: implement link sharing selector Change-Id: I212fa1a65e8c16cf1e525d1962d5689446c7e49e --- M include/osmocom/gprs/gprs_ns2.h M src/gb/gprs_ns2.c M src/gb/gprs_ns2_internal.h 3 files changed, 138 insertions(+), 15 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/44/21244/1 diff --git a/include/osmocom/gprs/gprs_ns2.h b/include/osmocom/gprs/gprs_ns2.h index 2a805c2..c13d315 100644 --- a/include/osmocom/gprs/gprs_ns2.h +++ b/include/osmocom/gprs/gprs_ns2.h @@ -92,6 +92,7 @@ union { struct { enum gprs_ns2_change_ip_endpoint change; + uint32_t link_selector; /* TODO: implement resource distribution * add place holder for the link selector */ long long _resource_distribution_placeholder1; diff --git a/src/gb/gprs_ns2.c b/src/gb/gprs_ns2.c index 4b32ddf..602bca7 100644 --- a/src/gb/gprs_ns2.c +++ b/src/gb/gprs_ns2.c @@ -57,9 +57,7 @@ * Those mappings are administratively configured. * * This implementation has the following limitations: - * - Only one NS-VC for each NSE: No load-sharing function * - NSVCI 65535 and 65534 are reserved for internal use - * - Only UDP is supported as of now, no frame relay support * - There are no BLOCK and UNBLOCK timers (yet?) * * \file gprs_ns2.c */ @@ -303,19 +301,130 @@ return osmo_fsm_inst_state_name(nsvc->fi); } +/* select a signalling NSVC and respect sig_counter + * param[out] reset_counter - all counter has to be resetted to their signal weight + * return the chosen nsvc or NULL + */ +static struct gprs_ns2_vc *ns2_load_sharing_signal( + struct gprs_ns2_nse *nse) +{ + struct gprs_ns2_vc *nsvc = NULL, *last = NULL, *tmp; + + llist_for_each_entry(tmp, &nse->nsvc, list) { + if (tmp->sig_weight == 0) + continue; + if (!gprs_ns2_vc_is_unblocked(tmp)) + continue; + if (tmp->sig_counter == 0) { + last = tmp; + continue; + } + + tmp->sig_counter--; + nsvc = tmp; + break; + } + + /* all counter were zero, but there are valid nsvc */ + if (!nsvc && last) { + llist_for_each_entry(tmp, &nse->nsvc, list) { + tmp->sig_counter = tmp->sig_weight; + } + + last->sig_counter--; + return last; + } else { + return nsvc; + } +} + +/* 4.4.1 Load Sharing function for the Frame Relay Sub-Network */ +static struct gprs_ns2_vc *ns2_load_sharing_modulor( + struct gprs_ns2_nse *nse, + uint16_t bvci, + uint32_t load_selector) +{ + struct gprs_ns2_vc *tmp; + uint32_t mod = (bvci + load_selector) % nse->nsvc_data_count; + uint32_t i = 0; + + llist_for_each_entry(tmp, &nse->nsvc, list) { + if (!gprs_ns2_vc_is_unblocked(tmp)) + continue; + if (tmp->data_weight == 0) + continue; + + if (i == mod) + return tmp; + i++; + } + + return NULL; +} + +/* pick the first available data NSVC - no load sharing */ +struct gprs_ns2_vc *ns2_load_sharing_first(struct gprs_ns2_nse *nse) +{ + struct gprs_ns2_vc *nsvc = NULL, *tmp; + + llist_for_each_entry(tmp, &nse->nsvc, list) { + if (!gprs_ns2_vc_is_unblocked(tmp)) + continue; + if (tmp->data_weight == 0) + continue; + + nsvc = tmp; + break; + } + + return nsvc; +} + + +static struct gprs_ns2_vc *ns2_load_sharing( + struct gprs_ns2_nse *nse, + uint16_t bvci, + uint32_t link_selector) +{ + struct gprs_ns2_vc *nsvc = NULL; + + if (bvci == 0) { + /* signalling */ + nsvc = ns2_load_sharing_signal(nse); + } else { + enum gprs_ns_ll ll; + + /* data with load sharing parameter */ + if (llist_empty(&nse->nsvc)) + return NULL; + nsvc = llist_first_entry(&nse->nsvc, struct gprs_ns2_vc, list); + ll = nsvc->ll; + + switch (ll) { + case GPRS_NS_LL_FR: + nsvc = ns2_load_sharing_modulor(nse, bvci, link_selector); + break; + default: + nsvc = ns2_load_sharing_first(nse); + break; + } + } + + return nsvc; +} + /*! Receive a primitive from the NS User (Gb). * \param[in] nsi NS instance to which the primitive is issued * \param[in] oph The primitive * \return 0 on success; negative on error */ int gprs_ns2_recv_prim(struct gprs_ns2_inst *nsi, struct osmo_prim_hdr *oph) { - /* TODO: implement load distribution function */ /* TODO: implement resource distribution */ /* TODO: check for empty PDUs which can be sent to Request/Confirm * the IP endpoint */ struct osmo_gprs_ns2_prim *nsp; struct gprs_ns2_nse *nse = NULL; - struct gprs_ns2_vc *nsvc = NULL, *tmp; + struct gprs_ns2_vc *nsvc = NULL; uint16_t bvci, nsei; uint8_t sducontrol = 0; @@ -337,16 +446,7 @@ if (!nse) return -EINVAL; - llist_for_each_entry(tmp, &nse->nsvc, list) { - if (!gprs_ns2_vc_is_unblocked(tmp)) - continue; - if (bvci == 0 && tmp->sig_weight == 0) - continue; - if (bvci != 0 && tmp->data_weight == 0) - continue; - - nsvc = tmp; - } + nsvc = ns2_load_sharing(nse, bvci, nsp->u.unitdata.link_selector); /* TODO: send a status primitive back */ if (!nsvc) @@ -980,6 +1080,20 @@ return rc; } +/* summarize all active data nsvcs */ +void ns2_nse_data_sum(struct gprs_ns2_nse *nse) +{ + struct gprs_ns2_vc *nsvc; + nse->nsvc_data_count = 0; + + llist_for_each_entry(nsvc, &nse->nsvc, list) { + if (!gprs_ns2_vc_is_unblocked(nsvc)) + continue; + if (nsvc->data_weight > 0) + nse->nsvc_data_count++; + } +} + /*! Notify a nse about the change of a NS-VC. * \param[in] nsvc NS-VC which has detected the change (and shall not be notified). * \param[in] unblocked whether the NSE should be marked as unblocked (true) or blocked (false) */ @@ -988,6 +1102,8 @@ struct gprs_ns2_nse *nse = nsvc->nse; struct gprs_ns2_vc *tmp; + ns2_nse_data_sum(nse); + if (unblocked == nse->alive) return; diff --git a/src/gb/gprs_ns2_internal.h b/src/gb/gprs_ns2_internal.h index e4d2d8a..78b6d82 100644 --- a/src/gb/gprs_ns2_internal.h +++ b/src/gb/gprs_ns2_internal.h @@ -118,6 +118,9 @@ /*! llist head to hold all nsvc */ struct llist_head nsvc; + /*! count all active NSVCs with data capabilities */ + int nsvc_data_count; + /*! true if this NSE was created by VTY or pcu socket) */ bool persistent; @@ -154,7 +157,10 @@ /*! signalling weight. 0 = don't use for signalling (BVCI == 0)*/ uint8_t sig_weight; - /*! signaling weight. 0 = don't use for user data (BVCI != 0) */ + /*! signalling packet counter for the load sharing function */ + uint8_t sig_counter; + + /*! data weight. 0 = don't use for user data (BVCI != 0) */ uint8_t data_weight; /*! can be used by the bind/driver of the virtual circuit. e.g. ipv4/ipv6/frgre/e1 */ -- To view, visit https://gerrit.osmocom.org/c/libosmocore/+/21244 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Change-Id: I212fa1a65e8c16cf1e525d1962d5689446c7e49e Gerrit-Change-Number: 21244 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/20201119/4a127426/attachment.htm>