<p>neels has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-bsc/+/18496">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">drop CC 'local-prefix' feature<br><br>It is not entirely clear to me what this used to do once, but I've stumbled<br>upon this before. By now I am certain that this is a non-standard legacy<br>feature. The BSC does *not* redirect connections during CC transactions.<br><br>Along with this, a bunch of legacy utility functions can be dropped. All of<br>this is unused code.<br><br>(Preparing for MSC pooling.)<br><br>Change-Id: Id54afe8ccf0e11b9121a733224054c9565eafb58<br>---<br>M include/osmocom/bsc/bsc_msc_data.h<br>M include/osmocom/bsc/gsm_data.h<br>M src/osmo-bsc/gsm_08_08.c<br>M src/osmo-bsc/gsm_data.c<br>M src/osmo-bsc/osmo_bsc_vty.c<br>5 files changed, 0 insertions(+), 180 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/96/18496/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/bsc/bsc_msc_data.h b/include/osmocom/bsc/bsc_msc_data.h</span><br><span>index c77c562..27eb75d 100644</span><br><span>--- a/include/osmocom/bsc/bsc_msc_data.h</span><br><span>+++ b/include/osmocom/bsc/bsc_msc_data.h</span><br><span>@@ -45,7 +45,6 @@</span><br><span> #include <osmocom/core/fsm.h></span><br><span> #include <osmocom/gsm/gsm23003.h></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#include <regex.h></span><br><span> #include <errno.h></span><br><span> </span><br><span> struct osmo_bsc_rf;</span><br><span>@@ -121,11 +120,6 @@</span><br><span>      int allow_emerg;</span><br><span>     int type;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* local call routing */</span><br><span style="color: hsl(0, 100%, 40%);">-        char *local_pref;</span><br><span style="color: hsl(0, 100%, 40%);">-       regex_t local_pref_reg;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>      /* Connection data */</span><br><span>        struct osmo_plmn_id core_plmn;</span><br><span>       int core_lac;</span><br><span>diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h</span><br><span>index e6a7708..73c0eb3 100644</span><br><span>--- a/include/osmocom/bsc/gsm_data.h</span><br><span>+++ b/include/osmocom/bsc/gsm_data.h</span><br><span>@@ -2,7 +2,6 @@</span><br><span> #define _GSM_DATA_H</span><br><span> </span><br><span> #include <stdint.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <regex.h></span><br><span> #include <sys/types.h></span><br><span> #include <stdbool.h></span><br><span> #include <stdint.h></span><br><span>@@ -1362,12 +1361,6 @@</span><br><span> /* return the gsm_lchan for the CBCH (if it exists at all) */</span><br><span> struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*</span><br><span style="color: hsl(0, 100%, 40%);">- * help with parsing regexps</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm_parse_reg(void *ctx, regex_t *reg, char **str,</span><br><span style="color: hsl(0, 100%, 40%);">-                int argc, const char **argv) __attribute__ ((warn_unused_result));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static inline uint8_t gsm_ts_tsc(const struct gsm_bts_trx_ts *ts)</span><br><span> {</span><br><span>         if (ts->tsc != -1)</span><br><span>diff --git a/src/osmo-bsc/gsm_08_08.c b/src/osmo-bsc/gsm_08_08.c</span><br><span>index 030808b..e9918ac 100644</span><br><span>--- a/src/osmo-bsc/gsm_08_08.c</span><br><span>+++ b/src/osmo-bsc/gsm_08_08.c</span><br><span>@@ -475,96 +475,6 @@</span><br><span>    return false;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause);</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%);">- * Plastic surgery... we want to give up the current connection</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static int move_to_msc(struct gsm_subscriber_connection *_conn,</span><br><span style="color: hsl(0, 100%, 40%);">-                 struct msgb *msg, struct bsc_msc_data *msc)</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%);">-       * 1. Give up the old connection.</span><br><span style="color: hsl(0, 100%, 40%);">-        * This happens by sending a clear request to the MSC,</span><br><span style="color: hsl(0, 100%, 40%);">-   * it should end with the MSC releasing the connection.</span><br><span style="color: hsl(0, 100%, 40%);">-  */</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc_clear_request(_conn, 0);</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%);">-       * 2. Attempt to create a new connection to the local</span><br><span style="color: hsl(0, 100%, 40%);">-    * MSC. If it fails the caller will need to handle this</span><br><span style="color: hsl(0, 100%, 40%);">-  * properly.</span><br><span style="color: hsl(0, 100%, 40%);">-     */</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!complete_layer3(_conn, msg, msc)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                /* FIXME: I have not the slightest idea what move_to_msc() intends to do; during lchan</span><br><span style="color: hsl(0, 100%, 40%);">-           * FSM introduction, I changed this and hope it is the appropriate action. I actually</span><br><span style="color: hsl(0, 100%, 40%);">-            * assume this is unused legacy code for osmo-bsc_nat?? */</span><br><span style="color: hsl(0, 100%, 40%);">-              gscon_release_lchans(_conn, false);</span><br><span style="color: hsl(0, 100%, 40%);">-             return 1;</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%);">-       return 2;</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%);">-static int handle_cc_setup(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(0, 100%, 40%);">-                       struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-    uint8_t pdisc = gsm48_hdr_pdisc(gh);</span><br><span style="color: hsl(0, 100%, 40%);">-    uint8_t mtype = gsm48_hdr_msg_type(gh);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- struct bsc_msc_data *msc;</span><br><span style="color: hsl(0, 100%, 40%);">-       struct gsm_mncc_number called;</span><br><span style="color: hsl(0, 100%, 40%);">-  struct tlv_parsed tp;</span><br><span style="color: hsl(0, 100%, 40%);">-   unsigned payload_len;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   char _dest_nr[35];</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%);">-       * Do we have a setup message here? if not return fast.</span><br><span style="color: hsl(0, 100%, 40%);">-  */</span><br><span style="color: hsl(0, 100%, 40%);">-     if (pdisc != GSM48_PDISC_CC || mtype != GSM48_MT_CC_SETUP)</span><br><span style="color: hsl(0, 100%, 40%);">-              return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       payload_len = msgb_l3len(msg) - sizeof(*gh);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {</span><br><span style="color: hsl(0, 100%, 40%);">-              LOGP(DMSC, LOGL_ERROR, "Called BCD not present in setup.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-         return -1;</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%);">-       memset(&called, 0, sizeof(called));</span><br><span style="color: hsl(0, 100%, 40%);">- gsm48_decode_called(&called,</span><br><span style="color: hsl(0, 100%, 40%);">-                            TLVP_VAL(&tp, GSM48_IE_CALLED_BCD) - 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        if (called.plan != 1 && called.plan != 0)</span><br><span style="color: hsl(0, 100%, 40%);">-               return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (called.plan == 1 && called.type == 1) {</span><br><span style="color: hsl(0, 100%, 40%);">-             _dest_nr[0] = _dest_nr[1] = '0';</span><br><span style="color: hsl(0, 100%, 40%);">-                memcpy(_dest_nr + 2, called.number, sizeof(called.number));</span><br><span style="color: hsl(0, 100%, 40%);">-     } else</span><br><span style="color: hsl(0, 100%, 40%);">-          memcpy(_dest_nr, called.number, sizeof(called.number));</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%);">-       * Check if the connection should be moved...</span><br><span style="color: hsl(0, 100%, 40%);">-    */</span><br><span style="color: hsl(0, 100%, 40%);">-     llist_for_each_entry(msc, &conn_get_bts(conn)->network->bsc_data->mscs, entry) {</span><br><span style="color: hsl(0, 100%, 40%);">-           if (msc->type != MSC_CON_TYPE_LOCAL)</span><br><span style="color: hsl(0, 100%, 40%);">-                 continue;</span><br><span style="color: hsl(0, 100%, 40%);">-               if (!msc->local_pref)</span><br><span style="color: hsl(0, 100%, 40%);">-                        continue;</span><br><span style="color: hsl(0, 100%, 40%);">-               if (regexec(&msc->local_pref_reg, _dest_nr, 0, NULL, 0) != 0)</span><br><span style="color: hsl(0, 100%, 40%);">-                    continue;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               return move_to_msc(conn, msg, msc);</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%);">-       return 0;</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%);">-</span><br><span> /*! MS->BSC/MSC: Um L3 message. */</span><br><span> void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg)</span><br><span> {</span><br><span>@@ -575,13 +485,6 @@</span><br><span> </span><br><span>      LOGP(DMSC, LOGL_INFO, "Tx MSC DTAP LINK_ID=0x%02x\n", link_id);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /*</span><br><span style="color: hsl(0, 100%, 40%);">-       * We might want to move this connection to a new MSC. Ask someone</span><br><span style="color: hsl(0, 100%, 40%);">-       * to handle it. If it was handled we will return.</span><br><span style="color: hsl(0, 100%, 40%);">-       */</span><br><span style="color: hsl(0, 100%, 40%);">-     if (handle_cc_setup(conn, msg) >= 1)</span><br><span style="color: hsl(0, 100%, 40%);">-         goto done;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>   bsc_scan_bts_msg(conn, msg);</span><br><span> </span><br><span>     /* Store link_id in msg->cb */</span><br><span>@@ -592,31 +495,6 @@</span><br><span>     return;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! BSSMAP Clear Request for legacy code paths, instead see gscon_bssmap_clear(). */</span><br><span style="color: hsl(0, 100%, 40%);">-static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       int rc;</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *resp;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!msc_connected(conn))</span><br><span style="color: hsl(0, 100%, 40%);">-               return 1;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       LOGP(DMSC, LOGL_INFO, "Tx MSC CLEAR REQUEST\n");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      resp = gsm0808_create_clear_rqst(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE);</span><br><span style="color: hsl(0, 100%, 40%);">-        if (!resp) {</span><br><span style="color: hsl(0, 100%, 40%);">-            LOGP(DMSC, LOGL_ERROR, "Failed to allocate response.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-             return 1;</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%);">-       rate_ctr_inc(&conn->sccp.msc->msc_ctrs->ctr[MSC_CTR_BSSMAP_TX_DT1_CLEAR_RQST]);</span><br><span style="color: hsl(0, 100%, 40%);">-    rc = osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_TX_SCCP, resp);</span><br><span style="color: hsl(0, 100%, 40%);">-       if (rc != 0)</span><br><span style="color: hsl(0, 100%, 40%);">-            msgb_free(resp);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        return 1;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /*! BSC->MSC: Classmark Update. */</span><br><span> void bsc_cm_update(struct gsm_subscriber_connection *conn,</span><br><span>               const uint8_t *cm2, uint8_t cm2_len,</span><br><span>diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c</span><br><span>index c34f06c..46e26ac 100644</span><br><span>--- a/src/osmo-bsc/gsm_data.c</span><br><span>+++ b/src/osmo-bsc/gsm_data.c</span><br><span>@@ -248,31 +248,6 @@</span><br><span>      gsm48_encode_ra(buf, &raid);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-int gsm_parse_reg(void *ctx, regex_t *reg, char **str, int argc, const char **argv)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   int ret;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        ret = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-        if (*str) {</span><br><span style="color: hsl(0, 100%, 40%);">-             talloc_free(*str);</span><br><span style="color: hsl(0, 100%, 40%);">-              *str = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-       regfree(reg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   if (argc > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-              *str = talloc_strdup(ctx, argv[0]);</span><br><span style="color: hsl(0, 100%, 40%);">-             ret = regcomp(reg, argv[0], REG_NOSUB);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-         /* handle compilation failures */</span><br><span style="color: hsl(0, 100%, 40%);">-               if (ret != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                 talloc_free(*str);</span><br><span style="color: hsl(0, 100%, 40%);">-                      *str = NULL;</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return ret;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /* Assume there are only 256 possible bts */</span><br><span> osmo_static_assert(sizeof(((struct gsm_bts *) 0)->nr) == 1, _bts_nr_is_256);</span><br><span> static void depends_calc_index_bit(int bts_nr, int *idx, int *bit)</span><br><span>diff --git a/src/osmo-bsc/osmo_bsc_vty.c b/src/osmo-bsc/osmo_bsc_vty.c</span><br><span>index cf995cc..7791212 100644</span><br><span>--- a/src/osmo-bsc/osmo_bsc_vty.c</span><br><span>+++ b/src/osmo-bsc/osmo_bsc_vty.c</span><br><span>@@ -157,9 +157,6 @@</span><br><span>         vty_out(vty, " allow-emergency %s%s", msc->allow_emerg ?</span><br><span>                                        "allow" : "deny", VTY_NEWLINE);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (msc->local_pref)</span><br><span style="color: hsl(0, 100%, 40%);">-         vty_out(vty, " local-prefix %s%s", msc->local_pref, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>       /* write amr options */</span><br><span>      write_msc_amr_options(vty, msc);</span><br><span> </span><br><span>@@ -482,22 +479,6 @@</span><br><span>  return CMD_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-DEFUN(cfg_net_msc_local_prefix,</span><br><span style="color: hsl(0, 100%, 40%);">-      cfg_net_msc_local_prefix_cmd,</span><br><span style="color: hsl(0, 100%, 40%);">-      "local-prefix REGEXP",</span><br><span style="color: hsl(0, 100%, 40%);">-      "Prefix for local numbers\n" "REGEXP used\n")</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    struct bsc_msc_data *msc = bsc_msc_data(vty);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   if (gsm_parse_reg(msc, &msc->local_pref_reg, &msc->local_pref, argc, argv) != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                vty_out(vty, "%%Failed to parse the regexp: '%s'%s",</span><br><span style="color: hsl(0, 100%, 40%);">-                  argv[0], VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">-          return CMD_WARNING;</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%);">-       return CMD_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> #define AMR_CONF_STR "AMR Multirate Configuration\n"</span><br><span> #define AMR_COMMAND(name) \</span><br><span>        DEFUN(cfg_net_msc_amr_##name,                                   \</span><br><span>@@ -961,7 +942,6 @@</span><br><span>      install_element(MSC_NODE, &cfg_net_msc_no_grace_ussd_cmd);</span><br><span>       install_element(MSC_NODE, &cfg_net_msc_type_cmd);</span><br><span>        install_element(MSC_NODE, &cfg_net_msc_emerg_cmd);</span><br><span style="color: hsl(0, 100%, 40%);">-  install_element(MSC_NODE, &cfg_net_msc_local_prefix_cmd);</span><br><span>        install_element(MSC_NODE, &cfg_net_msc_amr_12_2_cmd);</span><br><span>    install_element(MSC_NODE, &cfg_net_msc_amr_10_2_cmd);</span><br><span>    install_element(MSC_NODE, &cfg_net_msc_amr_7_95_cmd);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-bsc/+/18496">change 18496</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/c/osmo-bsc/+/18496"/><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-Change-Id: Id54afe8ccf0e11b9121a733224054c9565eafb58 </div>
<div style="display:none"> Gerrit-Change-Number: 18496 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>