<p>Pau Espin Pedrol has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/11682">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">abis_nm: Unify Get Attribute Response parsing<br><br>After a bit more investgiation, it seems nanoBTS actually supports<br>regular formatting. There are a few differences with spec though:<br>* The attributes are directly in the message instead of being inside the<br>Get Attributes Response Info after the unsupported attribute ID list.<br>* The Get Attributes Response info can be at any position in the<br>attribute list, and it only contains the unsupported attribute ID list.<br><br>As a result, we can split parsing into 3 main parts or functions:<br>* Parsing regular (per spec) Get Attributes Response Info attr and get a<br>pointer to the list of attributes.<br>* A function that parses the list of attributes, called directly in case<br>of nanoBTS, and called by the former parser of Get Attributes Response<br>Info for regular (per spec) OML endpoints.<br>* A function to parse the unsupported attribute ID list, also used in the<br>first function to get a pointer to the list of attributes.<br><br>Related: OS#3624<br>Change-Id: I77574579a19f1988f82cdac81b257b8f6871b857<br>---<br>M src/osmo-bsc/abis_nm.c<br>1 file changed, 55 insertions(+), 68 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/82/11682/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/osmo-bsc/abis_nm.c b/src/osmo-bsc/abis_nm.c</span><br><span>index 61820b8..bb2b5e2 100644</span><br><span>--- a/src/osmo-bsc/abis_nm.c</span><br><span>+++ b/src/osmo-bsc/abis_nm.c</span><br><span>@@ -461,36 +461,41 @@</span><br><span>                bts_nr, get_value_string(abis_nm_att_names, ari[i + 1]));</span><br><span> </span><br><span>   /* the data starts right after the list of unreported attributes + space for length of that list */</span><br><span style="color: hsl(0, 100%, 40%);">-     *out_len = ari_len - (num_unreported + 2);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (out_len)</span><br><span style="color: hsl(120, 100%, 40%);">+          *out_len = ari_len - (num_unreported + 2);</span><br><span> </span><br><span>       return ari + num_unreported + 1; /* we have to account for 1st byte with number of unreported attributes */</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* Parse Attribute Response Info content for 3GPP TS 52.021 §9.4.30 Manufacturer Id */</span><br><span style="color: hsl(0, 100%, 40%);">-static inline const uint8_t *parse_attr_resp_info_manuf_id(struct gsm_bts *bts, const uint8_t *data, uint16_t *data_len)</span><br><span style="color: hsl(120, 100%, 40%);">+/* Handle 3GPP TS 52.021 §8.11.3 Get Attribute Response (with nanoBTS speecific attribute formatting) */</span><br><span style="color: hsl(120, 100%, 40%);">+static int parse_attr_resp_info_attr(struct gsm_bts *bts, const struct gsm_bts_trx *trx, struct abis_om_fom_hdr *foh, struct tlv_parsed *tp)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-       struct tlv_parsed tp;</span><br><span style="color: hsl(0, 100%, 40%);">-   uint16_t m_id_len = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-  uint8_t adjust = 0, i;</span><br><span style="color: hsl(120, 100%, 40%);">+        const uint8_t* data;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint16_t len;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t port;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct in_addr ia = {0};</span><br><span style="color: hsl(120, 100%, 40%);">+      char unit_id[40];</span><br><span style="color: hsl(120, 100%, 40%);">+     int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct abis_nm_sw_desc sw_descr[MAX_BTS_ATTR];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      abis_nm_tlv_parse(&tp, bts, data, *data_len);</span><br><span style="color: hsl(0, 100%, 40%);">-       if (TLVP_PRES_LEN(&tp, NM_ATT_MANUF_ID, 2)) {</span><br><span style="color: hsl(0, 100%, 40%);">-               m_id_len = TLVP_LEN(&tp, NM_ATT_MANUF_ID);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Parse Attribute Response Info content for 3GPP TS 52.021 §9.4.30 Manufacturer Id */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (TLVP_PRES_LEN(tp, NM_ATT_MANUF_ID, 2)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          len = TLVP_LEN(tp, NM_ATT_MANUF_ID);</span><br><span> </span><br><span>             /* log potential BTS feature vector overflow */</span><br><span style="color: hsl(0, 100%, 40%);">-         if (m_id_len > sizeof(bts->_features_data))</span><br><span style="color: hsl(120, 100%, 40%);">+             if (len > sizeof(bts->_features_data))</span><br><span>                         LOGP(DNM, LOGL_NOTICE, "BTS%u Get Attributes Response: feature vector is truncated to %u bytes\n",</span><br><span>                              bts->nr, MAX_BTS_FEATURES/8);</span><br><span> </span><br><span>            /* check that max. expected BTS attribute is above given feature vector length */</span><br><span style="color: hsl(0, 100%, 40%);">-               if (m_id_len > OSMO_BYTES_FOR_BITS(_NUM_BTS_FEAT))</span><br><span style="color: hsl(120, 100%, 40%);">+         if (len > OSMO_BYTES_FOR_BITS(_NUM_BTS_FEAT))</span><br><span>                     LOGP(DNM, LOGL_NOTICE, "BTS%u Get Attributes Response: reported unexpectedly long (%u bytes) "</span><br><span>                          "feature vector - most likely it was compiled against newer BSC headers. "</span><br><span>                         "Consider upgrading your BSC to later version.\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                            bts->nr, m_id_len);</span><br><span style="color: hsl(120, 100%, 40%);">+                        bts->nr, len);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-              memcpy(bts->_features_data, TLVP_VAL(&tp, NM_ATT_MANUF_ID), sizeof(bts->_features_data));</span><br><span style="color: hsl(0, 100%, 40%);">-             adjust = m_id_len + 3; /* adjust for parsed TL16V struct */</span><br><span style="color: hsl(120, 100%, 40%);">+           memcpy(bts->_features_data, TLVP_VAL(tp, NM_ATT_MANUF_ID), sizeof(bts->_features_data));</span><br><span> </span><br><span>           for (i = 0; i < _NUM_BTS_FEAT; i++)</span><br><span>                       if (osmo_bts_has_feature(&bts->features, i) != osmo_bts_has_feature(&bts->model->features, i))</span><br><span>@@ -500,42 +505,32 @@</span><br><span>                                   osmo_bts_has_feature(&bts->features, i), osmo_bts_has_feature(&bts->model->features, i));</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   *data_len -= adjust;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    return data + adjust;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Parse Attribute Response Info content for 3GPP TS 52.021 §9.4.28 Manufacturer Dependent State */</span><br><span style="color: hsl(0, 100%, 40%);">-static inline const uint8_t *parse_attr_resp_info_manuf_state(const struct gsm_bts_trx *trx, const uint8_t *data, uint16_t *data_len)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        struct tlv_parsed tp;</span><br><span style="color: hsl(0, 100%, 40%);">-   const uint8_t *power;</span><br><span style="color: hsl(0, 100%, 40%);">-   uint8_t adjust = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!trx) /* this attribute does not make sense on BTS level, only on TRX level */</span><br><span style="color: hsl(0, 100%, 40%);">-              return data;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    abis_nm_tlv_parse(&tp, trx->bts, data, *data_len);</span><br><span style="color: hsl(0, 100%, 40%);">-       if (TLVP_PRES_LEN(&tp, NM_ATT_MANUF_STATE, 1)) {</span><br><span style="color: hsl(0, 100%, 40%);">-            power = TLVP_VAL(&tp, NM_ATT_MANUF_STATE);</span><br><span style="color: hsl(0, 100%, 40%);">-          LOGP(DNM, LOGL_NOTICE, "%s Get Attributes Response: nominal power is %u\n", gsm_trx_name(trx), *power);</span><br><span style="color: hsl(0, 100%, 40%);">-               adjust = 2; /* adjust for parsed TV struct */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Parse Attribute Response Info content for 3GPP TS 52.021 §9.4.28 Manufacturer Dependent State */</span><br><span style="color: hsl(120, 100%, 40%);">+  /* this attribute does not make sense on BTS level, only on TRX level */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (trx && TLVP_PRES_LEN(tp, NM_ATT_MANUF_STATE, 1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                data = TLVP_VAL(tp, NM_ATT_MANUF_STATE);</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGPFOH(DNM, LOGL_INFO, foh, "%s Get Attributes Response: nominal power is %u\n", gsm_trx_name(trx), *data);</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   *data_len -= adjust;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    return data + adjust;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Handle 3GPP TS 52.021 §8.11.3 Get Attribute Response (with nanoBTS speecific attribute formatting) */</span><br><span style="color: hsl(0, 100%, 40%);">-static int parse_attr_resp_nanobts(struct gsm_bts *bts, struct abis_om_fom_hdr *foh, struct tlv_parsed *tp)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-     const uint8_t* data;</span><br><span style="color: hsl(0, 100%, 40%);">-    uint16_t len;</span><br><span style="color: hsl(0, 100%, 40%);">-   uint16_t port;</span><br><span style="color: hsl(0, 100%, 40%);">-  struct in_addr ia = {0};</span><br><span style="color: hsl(0, 100%, 40%);">-        char unit_id[40];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Parse Attribute Response Info content for 3GPP TS 52.021 §9.4.61 SW Configuration */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (TLVP_PRESENT(tp, NM_ATT_SW_CONFIG)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             data = TLVP_VAL(tp, NM_ATT_SW_CONFIG);</span><br><span style="color: hsl(120, 100%, 40%);">+                len = TLVP_LEN(tp, NM_ATT_SW_CONFIG);</span><br><span style="color: hsl(120, 100%, 40%);">+         /* after parsing manufacturer-specific attributes there's list of replies in form of sw-conf structure: */</span><br><span style="color: hsl(120, 100%, 40%);">+                rc = abis_nm_get_sw_conf(data, len, &sw_descr[0], ARRAY_SIZE(sw_descr));</span><br><span style="color: hsl(120, 100%, 40%);">+          if (rc > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      for (i = 0; i < rc; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         if (!handle_attr(bts, str2btsattr((const char *)sw_descr[i].file_id),</span><br><span style="color: hsl(120, 100%, 40%);">+                                          sw_descr[i].file_version, sw_descr[i].file_version_len))</span><br><span style="color: hsl(120, 100%, 40%);">+                                     LOGPFOH(DNM, LOGL_NOTICE, foh, "BTS%u: ARI reported sw[%d/%d]: %s "</span><br><span style="color: hsl(120, 100%, 40%);">+                                         "is %s\n", bts->nr, i, rc, sw_descr[i].file_id,</span><br><span style="color: hsl(120, 100%, 40%);">+                                          sw_descr[i].file_version);</span><br><span style="color: hsl(120, 100%, 40%);">+                    }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      LOGPFOH(DNM, LOGL_ERROR, foh, "BTS%u: failed to parse SW-Config part of "</span><br><span style="color: hsl(120, 100%, 40%);">+                           "Get Attribute Response Info: %s\n", bts->nr, strerror(-rc));</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span> </span><br><span>        if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_PRIM_OML_CFG_LIST, 7)) {</span><br><span>          data = TLVP_VAL(tp, NM_ATT_IPACC_PRIM_OML_CFG_LIST);</span><br><span>@@ -555,6 +550,14 @@</span><br><span>          osmo_strlcpy(unit_id, (char*)data, OSMO_MIN(len, sizeof(unit_id)));</span><br><span>          LOGPFOH(DNM, LOGL_ERROR, foh, "BTS%u Get Attributes Response: Unit ID is %s\n", bts->nr, unit_id);</span><br><span>      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* nanoBTS provides Get Attribute Response Info at random position and only the unreported part of it. */</span><br><span style="color: hsl(120, 100%, 40%);">+     if (TLVP_PRES_LEN(tp, NM_ATT_GET_ARI, 1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           data = TLVP_VAL(tp, NM_ATT_GET_ARI);</span><br><span style="color: hsl(120, 100%, 40%);">+          len = TLVP_LEN(tp, NM_ATT_GET_ARI);</span><br><span style="color: hsl(120, 100%, 40%);">+           parse_attr_resp_info_unreported(bts->nr, data, len, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  return 0;</span><br><span> }</span><br><span> </span><br><span>@@ -562,10 +565,7 @@</span><br><span> static int parse_attr_resp_info(struct gsm_bts *bts, const struct gsm_bts_trx *trx, struct abis_om_fom_hdr *foh, struct tlv_parsed *tp)</span><br><span> {</span><br><span>    const uint8_t *data;</span><br><span style="color: hsl(0, 100%, 40%);">-    int i;</span><br><span>       uint16_t data_len;</span><br><span style="color: hsl(0, 100%, 40%);">-      int rc;</span><br><span style="color: hsl(0, 100%, 40%);">- struct abis_nm_sw_desc sw_descr[MAX_BTS_ATTR];</span><br><span> </span><br><span>   if (!TLVP_PRES_LEN(tp, NM_ATT_GET_ARI, 1)) {</span><br><span>                 LOGPFOH(DNM, LOGL_ERROR, foh, "BTS%u: Get Attr Response without Response Info?!\n",</span><br><span>@@ -576,23 +576,10 @@</span><br><span>        data = parse_attr_resp_info_unreported(bts->nr, TLVP_VAL(tp, NM_ATT_GET_ARI), TLVP_LEN(tp, NM_ATT_GET_ARI),</span><br><span>                                              &data_len);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      data = parse_attr_resp_info_manuf_state(trx, data, &data_len);</span><br><span style="color: hsl(0, 100%, 40%);">-      data = parse_attr_resp_info_manuf_id(bts, data, &data_len);</span><br><span style="color: hsl(120, 100%, 40%);">+       /* After parsing unreported part of Response info, there's a TLV of attr, same as per nanoBTS */</span><br><span style="color: hsl(120, 100%, 40%);">+  abis_nm_tlv_parse(tp, bts, data, data_len);</span><br><span style="color: hsl(120, 100%, 40%);">+   parse_attr_resp_info_attr(bts, trx, foh, tp);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       /* after parsing manufacturer-specific attributes there's list of replies in form of sw-conf structure: */</span><br><span style="color: hsl(0, 100%, 40%);">-  rc = abis_nm_get_sw_conf(data, data_len, &sw_descr[0], ARRAY_SIZE(sw_descr));</span><br><span style="color: hsl(0, 100%, 40%);">-       if (rc > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                for (i = 0; i < rc; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   if (!handle_attr(bts, str2btsattr((const char *)sw_descr[i].file_id),</span><br><span style="color: hsl(0, 100%, 40%);">-                                    sw_descr[i].file_version, sw_descr[i].file_version_len))</span><br><span style="color: hsl(0, 100%, 40%);">-                               LOGPFOH(DNM, LOGL_NOTICE, foh, "BTS%u: ARI reported sw[%d/%d]: %s "</span><br><span style="color: hsl(0, 100%, 40%);">-                                   "is %s\n", bts->nr, i, rc, sw_descr[i].file_id,</span><br><span style="color: hsl(0, 100%, 40%);">-                                    sw_descr[i].file_version);</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-       } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                LOGPFOH(DNM, LOGL_ERROR, foh, "BTS%u: failed to parse SW-Config part of "</span><br><span style="color: hsl(0, 100%, 40%);">-                     "Get Attribute Response Info: %s\n", bts->nr, strerror(-rc));</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span>    return 0;</span><br><span> }</span><br><span> </span><br><span>@@ -613,7 +600,7 @@</span><br><span>     if (bts->type != GSM_BTS_TYPE_NANOBTS)</span><br><span>            parse_attr_resp_info(bts, trx, foh, &tp);</span><br><span>        else</span><br><span style="color: hsl(0, 100%, 40%);">-            parse_attr_resp_nanobts(bts, foh, &tp);</span><br><span style="color: hsl(120, 100%, 40%);">+           parse_attr_resp_info_attr(bts, trx, foh, &tp);</span><br><span> </span><br><span> </span><br><span>   return 0;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/11682">change 11682</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/11682"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bsc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I77574579a19f1988f82cdac81b257b8f6871b857 </div>
<div style="display:none"> Gerrit-Change-Number: 11682 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Pau Espin Pedrol <pespin@sysmocom.de> </div>