esm_ebr_context.c 28.9 KB
Newer Older
Lionel Gauthier's avatar
GPLv3  
Lionel Gauthier committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*******************************************************************************
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom

    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.


    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
Cedric Roux's avatar
 
Cedric Roux committed
15

Lionel Gauthier's avatar
GPLv3  
Lionel Gauthier committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.

  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

  Address      : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.

 *******************************************************************************/
/*****************************************************************************
30
Source      esm_ebr_context.h
Cedric Roux's avatar
 
Cedric Roux committed
31

32
Version     0.1
Cedric Roux's avatar
 
Cedric Roux committed
33

34
Date        2013/05/28
Cedric Roux's avatar
 
Cedric Roux committed
35

36
Product     NAS stack
Cedric Roux's avatar
 
Cedric Roux committed
37

38
Subsystem   EPS Session Management
Cedric Roux's avatar
 
Cedric Roux committed
39

40
Author      Frederic Maurel
Cedric Roux's avatar
 
Cedric Roux committed
41

42
Description Defines functions used to handle EPS bearer contexts.
Cedric Roux's avatar
 
Cedric Roux committed
43 44

*****************************************************************************/
45 46
#include <stdlib.h> // malloc, free
#include <string.h> // memset
Cedric Roux's avatar
 
Cedric Roux committed
47 48 49 50

#include "commonDef.h"
#include "nas_log.h"

51
#include "emmData.h"
Cedric Roux's avatar
 
Cedric Roux committed
52 53
#include "esm_ebr.h"

54 55
#include "esm_ebr_context.h"

Cedric Roux's avatar
 
Cedric Roux committed
56 57
#include "emm_sap.h"

58 59 60
#if defined(ENABLE_ITTI)
# include "assertions.h"
#endif
Cedric Roux's avatar
 
Cedric Roux committed
61

62 63

#ifdef NAS_UE
64 65 66
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
67 68 69
#endif


Cedric Roux's avatar
 
Cedric Roux committed
70 71 72 73 74 75 76 77 78
/****************************************************************************/
/****************  E X T E R N A L    D E F I N I T I O N S  ****************/
/****************************************************************************/

/****************************************************************************/
/*******************  L O C A L    D E F I N I T I O N S  *******************/
/****************************************************************************/

#ifdef NAS_UE
79
static int _esm_ebr_context_check_identifiers(const network_tft_t *,
80
    const network_tft_t *);
81
static int _esm_ebr_context_check_precedence(const network_tft_t *,
82
    const network_tft_t *);
Cedric Roux's avatar
 
Cedric Roux committed
83 84 85 86 87 88 89 90
#endif

/****************************************************************************/
/******************  E X P O R T E D    F U N C T I O N S  ******************/
/****************************************************************************/

/****************************************************************************
 **                                                                        **
91
 ** Name:    esm_ebr_context_create()                                  **
Cedric Roux's avatar
 
Cedric Roux committed
92 93
 **                                                                        **
 ** Description: Creates a new EPS bearer context to the PDN with the spe- **
94
 **      cified PDN connection identifier                          **
Cedric Roux's avatar
 
Cedric Roux committed
95
 **                                                                        **
96 97 98 99 100 101 102 103
 ** Inputs:  ueid:      UE identifier                              **
 **      pid:       PDN connection identifier                  **
 **      ebi:       EPS bearer identity                        **
 **      is_default:    TRUE if the new bearer is a default EPS    **
 **             bearer context                             **
 **      esm_qos:   EPS bearer level QoS parameters            **
 **      tft:       Traffic flow template parameters           **
 **      Others:    _esm_data                                  **
Cedric Roux's avatar
 
Cedric Roux committed
104
 **                                                                        **
105 106 107 108 109 110
 ** Outputs:     None                                                      **
 **      Return:    The EPS bearer identity of the default EPS **
 **             bearer associated to the new EPS bearer    **
 **             context if successfully created;           **
 **             UNASSIGN EPS bearer value otherwise.       **
 **      Others:    _esm_data                                  **
Cedric Roux's avatar
 
Cedric Roux committed
111 112 113 114
 **                                                                        **
 ***************************************************************************/
int esm_ebr_context_create(
#ifdef NAS_MME
115
  emm_data_context_t *ctx,
Cedric Roux's avatar
 
Cedric Roux committed
116
#endif
117 118
  int pid, int ebi, int is_default,
  const network_qos_t *qos, const network_tft_t *tft)
Cedric Roux's avatar
 
Cedric Roux committed
119
{
120 121 122 123
  int                 bid     = 0;
  esm_data_context_t *esm_ctx = NULL;
  esm_pdn_t          *pdn     = NULL;
  unsigned int        ueid    = 0;
winckel's avatar
winckel committed
124

125
  LOG_FUNC_IN;
Cedric Roux's avatar
 
Cedric Roux committed
126 127

#ifdef NAS_UE
128
  esm_ctx = &_esm_data;
Cedric Roux's avatar
 
Cedric Roux committed
129 130
#endif
#ifdef NAS_MME
131
# if defined(NAS_BUILT_IN_EPC)
132
  esm_ctx = &ctx->esm_data_ctx;
133
# else
134 135 136 137 138 139 140

  if (ueid < ESM_DATA_NB_UE_MAX) {
    ctx = _esm_data.ctx[ueid];
  } else {
    LOG_FUNC_RETURN (ESM_EBI_UNASSIGNED);
  }

141
# endif
Cedric Roux's avatar
 
Cedric Roux committed
142 143
#endif

144 145 146 147 148
  bid = ESM_DATA_EPS_BEARER_MAX;

  LOG_TRACE(INFO, "ESM-PROC  - Create new %s EPS bearer context (ebi=%d) "
            "for PDN connection (pid=%d)",
            (is_default)? "default" : "dedicated", ebi, pid);
Cedric Roux's avatar
 
Cedric Roux committed
149

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
  if (pid < ESM_DATA_PDN_MAX) {
    if (pid != esm_ctx->pdn[pid].pid) {
      LOG_TRACE(ERROR, "ESM-PROC  - PDN connection identifier %d is "
                "not valid", pid);
    } else if (esm_ctx->pdn[pid].data == NULL) {
      LOG_TRACE(ERROR, "ESM-PROC  - PDN connection %d has not been "
                "allocated", pid);
    }
    /* Check the total number of active EPS bearers */
    else if (esm_ctx->n_ebrs > ESM_DATA_EPS_BEARER_TOTAL) {
      LOG_TRACE(WARNING, "ESM-PROC  - The total number of active EPS"
                "bearers is exceeded");
    } else {
      /* Get the PDN connection entry */
      pdn = esm_ctx->pdn[pid].data;

      if (is_default) {
        /* Default EPS bearer entry is defined at index 0 */
        bid = 0;
Cedric Roux's avatar
 
Cedric Roux committed
169

170 171 172 173
        if (pdn->bearer[bid] != NULL) {
          LOG_TRACE(ERROR, "ESM-PROC  - A default EPS bearer context "
                    "is already allocated");
          LOG_FUNC_RETURN (ESM_EBI_UNASSIGNED);
174
        }
175 176 177 178 179 180 181 182
      } else {
        /* Search for an available EPS bearer context entry */
        for (bid = 1; bid < ESM_DATA_EPS_BEARER_MAX; bid++) {
          if (pdn->bearer[bid] != NULL) {
            continue;
          }

          break;
183
        }
184
      }
Cedric Roux's avatar
 
Cedric Roux committed
185
    }
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
  }

  if (bid < ESM_DATA_EPS_BEARER_MAX) {
    /* Create new EPS bearer context */
    esm_bearer_t *ebr = (esm_bearer_t *)malloc(sizeof(esm_bearer_t));

    if (ebr != NULL) {
      memset(ebr, 0 , sizeof(esm_bearer_t));
      /* Increment the total number of active EPS bearers */
      esm_ctx->n_ebrs += 1;
      /* Increment the number of EPS bearer for this PDN connection */
      pdn->n_bearers += 1;
      /* Setup the EPS bearer data */
      pdn->bearer[bid] = ebr;
      ebr->bid = bid;
      ebr->ebi = ebi;

      if (qos != NULL) {
        /* EPS bearer level QoS parameters */
        ebr->qos = *qos;
      }

      if ( (tft != NULL) && (tft->n_pkfs < NET_PACKET_FILTER_MAX) ) {
        int i;

        /* Traffic flow template parameters */
        for (i = 0; i < tft->n_pkfs; i++) {
          ebr->tft.pkf[i] =
            (network_pkf_t *)malloc(sizeof(network_pkf_t));

          if (ebr->tft.pkf[i] != NULL) {
            *(ebr->tft.pkf[i]) = *(tft->pkf[i]);
            ebr->tft.n_pkfs += 1;
          }
        }
      }
Cedric Roux's avatar
 
Cedric Roux committed
222

223 224 225 226 227 228 229 230
      if (is_default) {
        /* Set the PDN connection activation indicator */
        esm_ctx->pdn[pid].is_active = TRUE;

        /* Update the emergency bearer services indicator */
        if (pdn->is_emergency) {
          esm_ctx->emergency = TRUE;
        }
231

232
#ifdef NAS_UE
233 234
        // LG ADD TEMP
        {
Lionel Gauthier's avatar
Lionel Gauthier committed
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
           char          *tmp          = NULL;
           char           ipv4_addr[INET_ADDRSTRLEN];
           char           ipv6_addr[INET6_ADDRSTRLEN];
           char          *netmask      = NULL;
           char           broadcast[INET_ADDRSTRLEN];
           struct in_addr in_addr;
           char           command_line[128];
           int            res;

           switch (pdn->type) {
           case NET_PDN_TYPE_IPV4V6:
             ipv6_addr[0] = pdn->ip_addr[4];

             // etc
           case NET_PDN_TYPE_IPV4:
             // in_addr is in network byte order
             in_addr.s_addr  = pdn->ip_addr[0] << 24                 |
                               ((pdn->ip_addr[1] << 16) & 0x00FF0000) |
                               ((pdn->ip_addr[2] <<  8) & 0x0000FF00) |
                               ( pdn->ip_addr[3]        & 0x000000FF);

             in_addr.s_addr = htonl(in_addr.s_addr);

             tmp = inet_ntoa(in_addr);
             //AssertFatal(tmp ,
             //            "error in PDN IPv4 address %x",
             //            in_addr.s_addr);
             strcpy(ipv4_addr, tmp);

264
             if (IN_CLASSA(ntohl(in_addr.s_addr))) {
Lionel Gauthier's avatar
Lionel Gauthier committed
265 266 267 268 269 270 271 272 273 274 275
               netmask = "255.0.0.0";
               in_addr.s_addr = pdn->ip_addr[0] << 24 |
                                ((255  << 16) & 0x00FF0000) |
                                ((255 <<  8)  & 0x0000FF00) |
                                ( 255         & 0x000000FF);
               in_addr.s_addr = htonl(in_addr.s_addr);
               tmp = inet_ntoa(in_addr);
               //                                AssertFatal(tmp ,
               //                                        "error in PDN IPv4 address %x",
               //                                        in_addr.s_addr);
               strcpy(broadcast, tmp);
276
             } else if (IN_CLASSB(ntohl(in_addr.s_addr))) {
Lionel Gauthier's avatar
Lionel Gauthier committed
277 278 279 280 281 282 283 284 285 286 287
               netmask = "255.255.0.0";
               in_addr.s_addr =  pdn->ip_addr[0] << 24 |
                                 ((pdn->ip_addr[1] << 16) & 0x00FF0000) |
                                 ((255 <<  8)  & 0x0000FF00) |
                                 ( 255         & 0x000000FF);
               in_addr.s_addr = htonl(in_addr.s_addr);
               tmp = inet_ntoa(in_addr);
               //                                AssertFatal(tmp ,
               //                                        "error in PDN IPv4 address %x",
               //                                        in_addr.s_addr);
               strcpy(broadcast, tmp);
288
             } else if (IN_CLASSC(ntohl(in_addr.s_addr))) {
Lionel Gauthier's avatar
Lionel Gauthier committed
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
               netmask = "255.255.255.0";
               in_addr.s_addr = pdn->ip_addr[0] << 24 |
                                ((pdn->ip_addr[1] << 16) & 0x00FF0000) |
                                ((pdn->ip_addr[2] <<  8) & 0x0000FF00) |
                                ( 255         & 0x000000FF);
               in_addr.s_addr = htonl(in_addr.s_addr);
               tmp = inet_ntoa(in_addr);
               //                                AssertFatal(tmp ,
               //                                        "error in PDN IPv4 address %x",
               //                                        in_addr.s_addr);
               strcpy(broadcast, tmp);
             } else {
               netmask = "255.255.255.255";
               strcpy(broadcast, ipv4_addr);
             }

             res = sprintf(command_line,
                           "ifconfig oip1 %s netmask %s broadcast %s up",
                           ipv4_addr, netmask, broadcast);
             //                            AssertFatal((res > 0) && (res < 128),
             //                                    "error in system command line");
             LOG_TRACE(INFO, "ESM-PROC  - executing %s ",
                       command_line);
             system(command_line);
             break;

           case NET_PDN_TYPE_IPV6:
             break;

           default:
             break;
           }
         }
         //                AssertFatal(0, "Forced stop in NAS UE");
323 324 325 326 327 328
#endif
      }

      /* Return the EPS bearer identity of the default EPS bearer
       * associated to the new EPS bearer context */
      LOG_FUNC_RETURN (pdn->bearer[0]->ebi);
Cedric Roux's avatar
 
Cedric Roux committed
329 330
    }

331 332 333 334 335
    LOG_TRACE(WARNING, "ESM-PROC  - Failed to create new EPS bearer "
              "context (ebi=%d)", ebi);
  }

  LOG_FUNC_RETURN (ESM_EBI_UNASSIGNED);
Cedric Roux's avatar
 
Cedric Roux committed
336 337 338 339
}

/****************************************************************************
 **                                                                        **
340
 ** Name:    esm_ebr_context_release()                                 **
Cedric Roux's avatar
 
Cedric Roux committed
341 342
 **                                                                        **
 ** Description: Releases EPS bearer context entry previously allocated    **
343
 **      to the EPS bearer with the specified EPS bearer identity  **
Cedric Roux's avatar
 
Cedric Roux committed
344
 **                                                                        **
345 346 347
 ** Inputs:  ueid:      UE identifier                              **
 **      ebi:       EPS bearer identity                        **
 **      Others:    _esm_data                                  **
Cedric Roux's avatar
 
Cedric Roux committed
348
 **                                                                        **
349 350 351 352 353 354 355 356
 ** Outputs:     pid:       Identifier of the PDN connection entry the **
 **             EPS bearer context belongs to              **
 **      bid:       Identifier of the released EPS bearer con- **
 **             text entry                                 **
 **      Return:    The EPS bearer identity associated to the  **
 **             EPS bearer context if successfully relea-  **
 **             sed; UNASSIGN EPS bearer value otherwise.  **
 **      Others:    _esm_data                                  **
Cedric Roux's avatar
 
Cedric Roux committed
357 358 359 360
 **                                                                        **
 ***************************************************************************/
int esm_ebr_context_release(
#ifdef NAS_MME
361
  emm_data_context_t *ctx,
Cedric Roux's avatar
 
Cedric Roux committed
362
#endif
363
  int ebi, int *pid, int *bid)
Cedric Roux's avatar
 
Cedric Roux committed
364
{
365 366 367
  int found = FALSE;
  esm_pdn_t *pdn = NULL;
  esm_data_context_t *esm_ctx;
Cedric Roux's avatar
 
Cedric Roux committed
368

369
  unsigned int ueid = 0;
winckel's avatar
winckel committed
370

371
  LOG_FUNC_IN;
Cedric Roux's avatar
 
Cedric Roux committed
372 373

#ifdef NAS_UE
374
  esm_ctx = &_esm_data;
Cedric Roux's avatar
 
Cedric Roux committed
375
#endif
376

Cedric Roux's avatar
 
Cedric Roux committed
377
#ifdef NAS_MME
378
# if defined(NAS_BUILT_IN_EPC)
379
  esm_ctx = &ctx->esm_data_ctx;
380
# else
381 382 383 384 385 386 387

  if (ueid < ESM_DATA_NB_UE_MAX) {
    ctx = &_esm_data.ctx[ueid];
  } else {
    LOG_FUNC_RETURN (ESM_EBI_UNASSIGNED);
  }

388
# endif
Cedric Roux's avatar
 
Cedric Roux committed
389 390
#endif

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
  if (ebi != ESM_EBI_UNASSIGNED) {
    /*
     * The identity of the EPS bearer to released is given;
     * Release the EPS bearer context entry that match the specified EPS
     * bearer identity
     */

    /* Search for active PDN connection */
    for (*pid = 0; *pid < ESM_DATA_PDN_MAX; (*pid)++) {
      if ( !esm_ctx->pdn[*pid].is_active ) {
        continue;
      }

      /* An active PDN connection is found */
      if (esm_ctx->pdn[*pid].data != NULL) {
        pdn = esm_ctx->pdn[*pid].data;

        /* Search for the specified EPS bearer context entry */
        for (*bid = 0; *bid < pdn->n_bearers; (*bid)++) {
          if (pdn->bearer[*bid] != NULL) {
            if (pdn->bearer[*bid]->ebi != ebi) {
              continue;
413
            }
414 415 416 417 418

            /* The EPS bearer context entry is found */
            found = TRUE;
            break;
          }
419
        }
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
      }

      if (found) {
        break;
      }
    }
  } else {
    /*
     * The identity of the EPS bearer to released is not given;
     * Release the EPS bearer context entry allocated with the EPS
     * bearer context identifier (bid) to establish connectivity to
     * the PDN identified by the PDN connection identifier (pid).
     * Default EPS bearer to a given PDN is always identified by the
     * first EPS bearer context entry at index bid = 0
     */
    if (*pid < ESM_DATA_PDN_MAX) {
      if (*pid != esm_ctx->pdn[*pid].pid) {
        LOG_TRACE(ERROR, "ESM-PROC  - PDN connection identifier %d "
                  "is not valid", *pid);
      } else if (!esm_ctx->pdn[*pid].is_active) {
        LOG_TRACE(WARNING,"ESM-PROC  - PDN connection %d is not active",
                  *pid);
      } else if (esm_ctx->pdn[*pid].data == NULL) {
        LOG_TRACE(ERROR, "ESM-PROC  - PDN connection %d has not been "
                  "allocated", *pid);
      } else {
        pdn = esm_ctx->pdn[*pid].data;

        if (pdn->bearer[*bid] != NULL) {
          ebi = pdn->bearer[*bid]->ebi;
          found = TRUE;
451
        }
452 453 454 455 456 457 458 459 460 461 462 463 464 465
      }
    }
  }

  if (found) {
    int i, j;

    /*
     * Delete the specified EPS bearer context entry
     */
    if (pdn->bearer[*bid]->bid != *bid) {
      LOG_TRACE(ERROR, "ESM-PROC  - EPS bearer identifier %d is "
                "not valid", *bid);
      LOG_FUNC_RETURN (ESM_EBI_UNASSIGNED);
Cedric Roux's avatar
 
Cedric Roux committed
466 467
    }

468 469
    LOG_TRACE(WARNING, "ESM-PROC  - Release EPS bearer context "
              "(ebi=%d)", ebi);
470

471 472 473 474
    /* Delete the TFT */
    for (i = 0; i < pdn->bearer[*bid]->tft.n_pkfs; i++) {
      free(pdn->bearer[*bid]->tft.pkf[i]);
    }
475

476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
    /* Release the specified EPS bearer data */
    free(pdn->bearer[*bid]);
    pdn->bearer[*bid] = NULL;
    /* Decrement the number of EPS bearer context allocated
     * to the PDN connection */
    pdn->n_bearers -= 1;
    /* Decrement the total number of active EPS bearers */
    esm_ctx->n_ebrs -= 1;

    if (*bid == 0) {
      /* 3GPP TS 24.301, section 6.4.4.3, 6.4.4.6
       * If the EPS bearer identity is that of the default bearer to a
       * PDN, the UE shall delete all EPS bearer contexts associated to
       * that PDN connection.
       */
      for (i = 1; pdn->n_bearers > 0; i++) {
        if (pdn->bearer[i]) {

          LOG_TRACE(WARNING, "ESM-PROC  - Release EPS bearer context "
                    "(ebi=%d)", pdn->bearer[i]->ebi);

          /* Delete the TFT */
          for (j = 0; j < pdn->bearer[i]->tft.n_pkfs; j++) {
            free(pdn->bearer[i]->tft.pkf[j]);
          }

          /* Set the EPS bearer context state to INACTIVE */
Cedric Roux's avatar
 
Cedric Roux committed
503
#ifdef NAS_UE
504 505
          (void) esm_ebr_set_status(pdn->bearer[i]->ebi,
                                    ESM_EBR_INACTIVE, TRUE);
Cedric Roux's avatar
 
Cedric Roux committed
506 507
#endif
#ifdef NAS_MME
508 509
          (void) esm_ebr_set_status(ctx, pdn->bearer[i]->ebi,
                                    ESM_EBR_INACTIVE, TRUE);
Cedric Roux's avatar
 
Cedric Roux committed
510
#endif
511
          /* Release EPS bearer data */
Cedric Roux's avatar
 
Cedric Roux committed
512
#ifdef NAS_UE
513
          (void) esm_ebr_release(pdn->bearer[i]->ebi);
Cedric Roux's avatar
 
Cedric Roux committed
514 515
#endif
#ifdef NAS_MME
516
          (void) esm_ebr_release(ctx, pdn->bearer[i]->ebi);
Cedric Roux's avatar
 
Cedric Roux committed
517
#endif
518 519 520 521 522 523 524 525 526
          // esm_ebr_release()
          /* Release dedicated EPS bearer data */
          free(pdn->bearer[i]);
          pdn->bearer[i] = NULL;
          /* Decrement the number of EPS bearer context allocated
           * to the PDN connection */
          pdn->n_bearers -= 1;
          /* Decrement the total number of active EPS bearers */
          esm_ctx->n_ebrs -= 1;
527
        }
528 529 530 531 532 533 534 535 536 537
      }

      /* Reset the PDN connection activation indicator */
      esm_ctx->pdn[*pid].is_active = FALSE;

      /* Update the emergency bearer services indicator */
      if (pdn->is_emergency) {
        esm_ctx->emergency = FALSE;
      }
    }
Cedric Roux's avatar
 
Cedric Roux committed
538 539

#ifdef NAS_UE
540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564

    /* 3GPP TS 24.301, section 6.4.4.6
     * If the UE locally deactivated all EPS bearer contexts, the UE
     * shall perform a local detach and enter state EMM-DEREGISTERED.
     */
    if (esm_ctx->n_ebrs == 0) {
      emm_sap_t emm_sap;
      emm_sap.primitive = EMMESM_ESTABLISH_CNF;
      emm_sap.u.emm_esm.u.establish.is_attached = FALSE;
      (void) emm_sap_send(&emm_sap);
    }
    /* 3GPP TS 24.301, section 6.4.4.3, 6.4.4.6
     * If due to the EPS bearer context deactivation only the PDN
     * connection for emergency bearer services remains established,
     * the UE shall consider itself attached for emergency bearer
     * services only.
     */
    else if (esm_ctx->emergency && (esm_ctx->n_ebrs == 1) ) {
      emm_sap_t emm_sap;
      emm_sap.primitive = EMMESM_ESTABLISH_CNF;
      emm_sap.u.emm_esm.u.establish.is_attached = TRUE;
      emm_sap.u.emm_esm.u.establish.is_emergency = TRUE;
      (void) emm_sap_send(&emm_sap);
    }

Cedric Roux's avatar
 
Cedric Roux committed
565 566 567
#endif // NAS_UE
#ifdef NAS_MME

568 569 570
    if (esm_ctx->n_ebrs == 0) {
      /* TODO: Release the PDN connection and marked the UE as inactive
       * in the network for EPS services (is_attached = FALSE) */
Cedric Roux's avatar
 
Cedric Roux committed
571 572
    }

573 574 575 576 577 578
#endif

    LOG_FUNC_RETURN (ebi);
  }

  LOG_FUNC_RETURN (ESM_EBI_UNASSIGNED);
Cedric Roux's avatar
 
Cedric Roux committed
579 580 581 582 583
}

#ifdef NAS_UE
/****************************************************************************
 **                                                                        **
584
 ** Name:    esm_ebr_context_get_pid()                                 **
Cedric Roux's avatar
 
Cedric Roux committed
585 586
 **                                                                        **
 ** Description: Returns the identifier of the PDN connection entry the    **
587 588
 **      default EPS bearer context with the specified EPS bearer  **
 **      identity belongs to                                       **
Cedric Roux's avatar
 
Cedric Roux committed
589
 **                                                                        **
590 591 592
 ** Inputs:  ebi:       The EPS bearer identity of the default EPS **
 **             bearer context                             **
 **      Others:    _esm_data                                  **
Cedric Roux's avatar
 
Cedric Roux committed
593
 **                                                                        **
594 595 596 597 598
 ** Outputs:     None                                                      **
 **      Return:    The identifier of the PDN connection entry **
 **             associated to the specified default EPS    **
 **             bearer context if it exists; -1 otherwise. **
 **      Others:    None                                       **
Cedric Roux's avatar
 
Cedric Roux committed
599 600 601 602
 **                                                                        **
 ***************************************************************************/
int esm_ebr_context_get_pid(int ebi)
{
603
  LOG_FUNC_IN;
Cedric Roux's avatar
 
Cedric Roux committed
604

605
  int pid;
Cedric Roux's avatar
 
Cedric Roux committed
606

607 608 609
  for (pid = 0; pid < ESM_DATA_PDN_MAX; pid++) {
    if (_esm_data.pdn[pid].data == NULL) {
      continue;
Cedric Roux's avatar
 
Cedric Roux committed
610 611
    }

612 613
    if (_esm_data.pdn[pid].data->bearer[0] == NULL) {
      continue;
Cedric Roux's avatar
 
Cedric Roux committed
614
    }
615 616 617 618 619 620 621 622 623 624 625

    if (_esm_data.pdn[pid].data->bearer[0]->ebi == ebi) {
      break;
    }
  }

  if (pid < ESM_DATA_PDN_MAX) {
    LOG_FUNC_RETURN (pid);
  }

  LOG_FUNC_RETURN (-1);
Cedric Roux's avatar
 
Cedric Roux committed
626 627 628 629
}

/****************************************************************************
 **                                                                        **
630
 ** Name:    esm_ebr_context_check_tft()                               **
Cedric Roux's avatar
 
Cedric Roux committed
631 632
 **                                                                        **
 ** Description: Checks syntactical errors in packet filters associated to **
633 634 635
 **      the EPS bearer context with the specified EPS bearer      **
 **      identity for the PDN connection entry with the given      **
 **      identifier                                                **
Cedric Roux's avatar
 
Cedric Roux committed
636
 **                                                                        **
637 638 639 640 641 642 643 644
 ** Inputs:  pid:       Identifier of the PDN connection entry the **
 **             EPS bearer context belongs to              **
 **      ebi:       The EPS bearer identity of the EPS bearer  **
 **             context with associated packet filter list **
 **      tft:       The traffic flow template (set of packet   **
 **             filters) to be checked                     **
 **      operation: Traffic flow template operation            **
 **      Others:    _esm_data                                  **
Cedric Roux's avatar
 
Cedric Roux committed
645
 **                                                                        **
646 647 648
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
Cedric Roux's avatar
 
Cedric Roux committed
649 650 651
 **                                                                        **
 ***************************************************************************/
int esm_ebr_context_check_tft(int pid, int ebi,
652 653
                              const network_tft_t *tft,
                              esm_ebr_context_tft_t operation)
Cedric Roux's avatar
 
Cedric Roux committed
654
{
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
  LOG_FUNC_IN;

  int rc = RETURNerror;
  int i;

  if (pid < ESM_DATA_PDN_MAX) {
    if (pid != _esm_data.pdn[pid].pid) {
      LOG_TRACE(ERROR, "ESM-PROC  - PDN connection identifier %d "
                "is not valid", pid);
    } else if (_esm_data.pdn[pid].data == NULL) {
      LOG_TRACE(ERROR, "ESM-PROC  - PDN connection %d has not been "
                "allocated", pid);
    } else if (operation == ESM_EBR_CONTEXT_TFT_CREATE) {
      esm_pdn_t *pdn = _esm_data.pdn[pid].data;

      /* For each EPS bearer context associated to the PDN connection */
      for (i = 0; i < pdn->n_bearers; i++) {
        if (pdn->bearer[i]) {
          if (pdn->bearer[i]->ebi == ebi) {
            /* Check the packet filter identifiers */
            rc = _esm_ebr_context_check_identifiers(tft,
                                                    &pdn->bearer[i]->tft);

            if (rc != RETURNok) {
              break;
680
            }
681 682 683 684 685 686 687 688 689
          }

          /* Check the packet filter precedence values */
          rc = _esm_ebr_context_check_precedence(tft,
                                                 &pdn->bearer[i]->tft);

          if (rc != RETURNok) {
            break;
          }
690
        }
691
      }
Cedric Roux's avatar
 
Cedric Roux committed
692
    }
693
  }
Cedric Roux's avatar
 
Cedric Roux committed
694

695
  LOG_FUNC_RETURN (rc);
Cedric Roux's avatar
 
Cedric Roux committed
696 697 698 699 700 701 702 703 704 705
}
#endif // NAS_UE

/****************************************************************************/
/*********************  L O C A L    F U N C T I O N S  *********************/
/****************************************************************************/

#ifdef NAS_UE
/****************************************************************************
 **                                                                        **
706
 ** Name:    _esm_ebr_context_check_identifiers()                      **
Cedric Roux's avatar
 
Cedric Roux committed
707 708
 **                                                                        **
 ** Description: Compares traffic flow templates to check whether two or   **
709 710
 **      more packet filters have identical packet filter identi-  **
 **      fiers                                                     **
Cedric Roux's avatar
 
Cedric Roux committed
711
 **                                                                        **
712 713 714
 ** Inputs:  tft1:      The first set of packet filters            **
 **      tft2:      The second set of packet filters           **
 **      Others:    None                                       **
Cedric Roux's avatar
 
Cedric Roux committed
715
 **                                                                        **
716 717 718 719 720
 ** Outputs:     None                                                      **
 **      Return:    RETURNerror if at least one packet filter  **
 **             has same identifier in both traffic flow   **
 **             templates; RETURNok otherwise.             **
 **      Others:    None                                       **
Cedric Roux's avatar
 
Cedric Roux committed
721 722
 **                                                                        **
 ***************************************************************************/
723
static int _esm_ebr_context_check_identifiers(const network_tft_t *tft1,
724
    const network_tft_t *tft2)
Cedric Roux's avatar
 
Cedric Roux committed
725
{
726 727
  int i;
  int j;
728

729
  if ( (tft1 == NULL) || (tft2 == NULL) ) {
Cedric Roux's avatar
 
Cedric Roux committed
730
    return (RETURNok);
731 732 733 734 735 736 737 738 739 740 741 742 743 744
  }

  for (i = 0; i < tft1->n_pkfs; i++) {
    for (j = 0; j < tft2->n_pkfs; j++) {
      /* Packet filters should have been allocated */
      if (tft1->pkf[i]->id == tft2->pkf[i]->id) {
        /* 3GPP TS 24.301, section 6.4.2.5, abnormal cases d.1
         * Packet filters have same identifier */
        return (RETURNerror);
      }
    }
  }

  return (RETURNok);
Cedric Roux's avatar
 
Cedric Roux committed
745 746 747 748
}

/****************************************************************************
 **                                                                        **
749
 ** Name:    _esm_ebr_context_check_precedence()                       **
Cedric Roux's avatar
 
Cedric Roux committed
750 751
 **                                                                        **
 ** Description: Compares traffic flow templates to check whether two or   **
752
 **      more packet filters have identical precedence values      **
Cedric Roux's avatar
 
Cedric Roux committed
753
 **                                                                        **
754 755 756
 ** Inputs:  tft1:      The first set of packet filters            **
 **      tft2:      The second set of packet filters           **
 **      Others:    None                                       **
Cedric Roux's avatar
 
Cedric Roux committed
757
 **                                                                        **
758 759 760 761 762
 ** Outputs:     None                                                      **
 **      Return:    RETURNerror if at least one packet filter  **
 **             has same precedence value in both traffic  **
 **             flow templates; RETURNerror otherwise.     **
 **      Others:    None                                       **
Cedric Roux's avatar
 
Cedric Roux committed
763 764
 **                                                                        **
 ***************************************************************************/
765
static int _esm_ebr_context_check_precedence(const network_tft_t *tft1,
766
    const network_tft_t *tft2)
Cedric Roux's avatar
 
Cedric Roux committed
767
{
768 769
  int i;
  int j;
770

771
  if ( (tft1 == NULL) || (tft2 == NULL) ) {
Cedric Roux's avatar
 
Cedric Roux committed
772
    return (RETURNok);
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789
  }

  for (i = 0; i < tft1->n_pkfs; i++) {
    for (j = 0; j < tft2->n_pkfs; j++) {
      /* Packet filters should have been allocated */
      if (tft1->pkf[i]->precedence == tft2->pkf[i]->precedence) {
        /* 3GPP TS 24.301, section 6.4.2.5, abnormal cases d.2
         * Packet filters have same precedence value */
        /* TODO: Actually if the old packet filters do not belong
         * to the default EPS bearer context, the UE shall not
         * diagnose an error (see 6.4.2.5, abnormal cases d.2) */
        return (RETURNerror);
      }
    }
  }

  return (RETURNok);
Cedric Roux's avatar
 
Cedric Roux committed
790 791
}
#endif // NAS_UE