summaryrefslogtreecommitdiffstats
path: root/src/gsm/gsm0808_utils.c
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2018-03-23 01:46:42 +0100
committerNeels Hofmeyr <neels@hofmeyr.de>2018-04-13 05:28:09 +0200
commit74663d97c6677d92ba9ed4338c190b8dc42b537e (patch)
treefe2d218c2f0040172d9700854371063cd9b35243 /src/gsm/gsm0808_utils.c
parent43496206c18b783a0c82faacd964819f8ee2e837 (diff)
add gsm0808_cell_id_list_add() to combine two cell identifier lists
This will be used by the upcoming neighbor_ident API in osmo-bsc, where the vty interface allows composing neihbor BSS cell identifier lists, and we want to allow adding individual items from individual user commands. It will also be useful to accumulate cell identifiers in case a subscriber sees multiple alternative cells from a neighboring BSS, and we want to pass these on to the MSC in a Handover Required. Related: OS#2283 (inter-BSC HO, BSC side) Change-Id: I5781f5fa5339c92ab2e2620489b002829d206925
Diffstat (limited to 'src/gsm/gsm0808_utils.c')
-rw-r--r--src/gsm/gsm0808_utils.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c
index e4872b87..996456e1 100644
--- a/src/gsm/gsm0808_utils.c
+++ b/src/gsm/gsm0808_utils.c
@@ -909,6 +909,85 @@ int gsm0808_dec_cell_id_list(struct gsm0808_cell_id_list *cil,
return (int)(elem - old_elem);
}
+static bool same_cell_id_list_entries(const struct gsm0808_cell_id_list2 *a, int ai,
+ const struct gsm0808_cell_id_list2 *b, int bi)
+{
+ struct gsm0808_cell_id_list2 tmp = {
+ .id_discr = a->id_discr,
+ .id_list_len = 1,
+ };
+ uint8_t buf_a[32 + sizeof(struct msgb)];
+ uint8_t buf_b[32 + sizeof(struct msgb)];
+ struct msgb *msg_a = (void*)buf_a;
+ struct msgb *msg_b = (void*)buf_b;
+
+ msg_a->data_len = 32;
+ msg_b->data_len = 32;
+ msgb_reset(msg_a);
+ msgb_reset(msg_b);
+
+ if (a->id_discr != b->id_discr)
+ return false;
+ if (ai >= a->id_list_len
+ || bi >= b->id_list_len)
+ return false;
+
+ tmp.id_list[0] = a->id_list[ai];
+ gsm0808_enc_cell_id_list2(msg_a, &tmp);
+
+ tmp.id_list[0] = b->id_list[bi];
+ gsm0808_enc_cell_id_list2(msg_b, &tmp);
+
+ if (msg_a->len != msg_b->len)
+ return false;
+ if (memcmp(msg_a->data, msg_b->data, msg_a->len))
+ return false;
+
+ return true;
+}
+
+/*! Append entries from one Cell Identifier List to another.
+ * The cell identifier types must be identical between the two lists.
+ * \param dst[out] Append entries to this list.
+ * \param src[in] Append these entries to \a dst.
+ * \returns the nr of items added, or negative on error: -EINVAL if the id_discr mismatch
+ * between the lists, -ENOSPC if the destination list does not have enough space. If an error is
+ * returned, \a dst may have already been changed (particularly on -ENOSPC). Note that a return value
+ * of zero may occur when the src->id_list_len is zero, or when all entries from \a src already exist
+ * in \a dst, and does not indicate error per se. */
+int gsm0808_cell_id_list_add(struct gsm0808_cell_id_list2 *dst, const struct gsm0808_cell_id_list2 *src)
+{
+ int i, j;
+ int added = 0;
+
+ if (dst->id_list_len == 0
+ && dst->id_discr != CELL_IDENT_BSS)
+ dst->id_discr = src->id_discr;
+ else if (dst->id_discr != src->id_discr)
+ return -EINVAL;
+
+ for (i = 0; i < src->id_list_len; i++) {
+ /* don't add duplicate entries */
+ bool skip = false;
+ for (j = 0; j < dst->id_list_len; j++) {
+ if (same_cell_id_list_entries(dst, j, src, i)) {
+ skip = true;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+
+ if (dst->id_list_len >= ARRAY_SIZE(dst->id_list))
+ return -ENOSPC;
+
+ dst->id_list[dst->id_list_len++] = src->id_list[i];
+ added ++;
+ }
+
+ return added;
+}
+
/*! Convert the representation of the permitted speech codec identifier
* that is used in struct gsm0808_channel_type to the speech codec
* representation we use in struct gsm0808_speech_codec.