static int gtpv1u_create_s1u_tunnel(Gtpv1uCreateTunnelReq *create_tunnel_reqP) { /* Create a new nw-gtpv1-u stack req using API */ NwGtpv1uUlpApiT stack_req; NwGtpv1uRcT rc; /* Local tunnel end-point identifier */ uint32_t s1u_teid = 0; gtpv1u_teid2enb_info_t *gtpv1u_teid2enb_info = NULL; MessageDef *message_p = NULL; hashtable_rc_t hash_rc; GTPU_DEBUG("Rx GTPV1U_CREATE_TUNNEL_REQ Context %d\n", create_tunnel_reqP->context_teid); memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT)); stack_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT; do { s1u_teid = gtpv1u_new_teid(); GTPU_DEBUG("gtpv1u_create_s1u_tunnel() %u\n", s1u_teid); stack_req.apiInfo.createTunnelEndPointInfo.teid = s1u_teid; stack_req.apiInfo.createTunnelEndPointInfo.hUlpSession = 0; stack_req.apiInfo.createTunnelEndPointInfo.hStackSession = 0; rc = nwGtpv1uProcessUlpReq(gtpv1u_sgw_data.gtpv1u_stack, &stack_req); GTPU_DEBUG(".\n"); } while (rc != NW_GTPV1U_OK); gtpv1u_teid2enb_info = malloc (sizeof(gtpv1u_teid2enb_info_t)); memset(gtpv1u_teid2enb_info, 0, sizeof(gtpv1u_teid2enb_info_t)); gtpv1u_teid2enb_info->state = BEARER_IN_CONFIG; //#warning !!! hack because missing modify session request, so force enb address // gtpv1u_teid2enb_info->enb_ip_addr.pdn_type = IPv4; // gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address[0] = 192; // gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address[1] = 168; // gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address[2] = 1; // gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address[3] = 2; message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_CREATE_TUNNEL_RESP); message_p->ittiMsg.gtpv1uCreateTunnelResp.S1u_teid = s1u_teid; message_p->ittiMsg.gtpv1uCreateTunnelResp.context_teid = create_tunnel_reqP->context_teid; message_p->ittiMsg.gtpv1uCreateTunnelResp.eps_bearer_id = create_tunnel_reqP->eps_bearer_id; hash_rc = hashtable_is_key_exists(gtpv1u_sgw_data.S1U_mapping, s1u_teid); if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) { hash_rc = hashtable_insert(gtpv1u_sgw_data.S1U_mapping, s1u_teid, gtpv1u_teid2enb_info); message_p->ittiMsg.gtpv1uCreateTunnelResp.status = 0; } else { message_p->ittiMsg.gtpv1uCreateTunnelResp.status = 0xFF; } GTPU_DEBUG("Tx GTPV1U_CREATE_TUNNEL_RESP Context %u teid %u eps bearer id %u status %d\n", message_p->ittiMsg.gtpv1uCreateTunnelResp.context_teid, message_p->ittiMsg.gtpv1uCreateTunnelResp.S1u_teid, message_p->ittiMsg.gtpv1uCreateTunnelResp.eps_bearer_id, message_p->ittiMsg.gtpv1uCreateTunnelResp.status); return itti_send_msg_to_task(TASK_SPGW_APP, INSTANCE_DEFAULT, message_p); }
//----------------------------------------------------------------------------- int gtpv1u_create_s1u_tunnel( const instance_t instanceP, const gtpv1u_enb_create_tunnel_req_t * const create_tunnel_req_pP, gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP ) { /* Create a new nw-gtpv1-u stack req using API */ NwGtpv1uUlpApiT stack_req; NwGtpv1uRcT rc = NW_GTPV1U_FAILURE; /* Local tunnel end-point identifier */ teid_t s1u_teid = 0; gtpv1u_teid_data_t *gtpv1u_teid_data_p = NULL; gtpv1u_ue_data_t *gtpv1u_ue_data_p = NULL; //MessageDef *message_p = NULL; hashtable_rc_t hash_rc = HASH_TABLE_KEY_NOT_EXISTS; int i; ebi_t eps_bearer_id = 0; // int ipv4_addr = 0; int ip_offset = 0; in_addr_t in_addr; int addrs_length_in_bytes= 0; MSC_LOG_RX_MESSAGE( MSC_GTPU_ENB, MSC_RRC_ENB, NULL,0, MSC_AS_TIME_FMT" CREATE_TUNNEL_REQ RNTI %"PRIx16" inst %u ntuns %u ebid %u sgw-s1u teid %u", 0,0,create_tunnel_req_pP->rnti, instanceP, create_tunnel_req_pP->num_tunnels, create_tunnel_req_pP->eps_bearer_id[0], create_tunnel_req_pP->sgw_S1u_teid[0]); create_tunnel_resp_pP->rnti = create_tunnel_req_pP->rnti; create_tunnel_resp_pP->status = 0; create_tunnel_resp_pP->num_tunnels = 0; for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) { ip_offset = 0; eps_bearer_id = create_tunnel_req_pP->eps_bearer_id[i]; LOG_D(GTPU, "Rx GTPV1U_ENB_CREATE_TUNNEL_REQ ue rnti %x eps bearer id %u\n", create_tunnel_req_pP->rnti, eps_bearer_id); memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT)); stack_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT; do { s1u_teid = gtpv1u_new_teid(); LOG_D(GTPU, "gtpv1u_create_s1u_tunnel() 0x%x %u(dec)\n", s1u_teid, s1u_teid); stack_req.apiInfo.createTunnelEndPointInfo.teid = s1u_teid; stack_req.apiInfo.createTunnelEndPointInfo.hUlpSession = 0; stack_req.apiInfo.createTunnelEndPointInfo.hStackSession = 0; rc = nwGtpv1uProcessUlpReq(gtpv1u_data_g.gtpv1u_stack, &stack_req); LOG_D(GTPU, ".\n"); } while (rc != NW_GTPV1U_OK); //----------------------- // PDCP->GTPV1U mapping //----------------------- hash_rc = hashtable_get(gtpv1u_data_g.ue_mapping, create_tunnel_req_pP->rnti, (void **)>pv1u_ue_data_p); if ((hash_rc == HASH_TABLE_KEY_NOT_EXISTS) || (hash_rc == HASH_TABLE_OK)) { if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) { gtpv1u_ue_data_p = calloc (1, sizeof(gtpv1u_ue_data_t)); hash_rc = hashtable_insert(gtpv1u_data_g.ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_p); AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable"); } gtpv1u_ue_data_p->ue_id = create_tunnel_req_pP->rnti; gtpv1u_ue_data_p->instance_id = 0; // TO DO memcpy(&create_tunnel_resp_pP->enb_addr.buffer, >pv1u_data_g.enb_ip_address_for_S1u_S12_S4_up, sizeof (in_addr_t)); create_tunnel_resp_pP->enb_addr.length = sizeof (in_addr_t); addrs_length_in_bytes = create_tunnel_req_pP->sgw_addr[i].length / 8; AssertFatal((addrs_length_in_bytes == 4) || (addrs_length_in_bytes == 16) || (addrs_length_in_bytes == 20), "Bad transport layer address length %d (bits) %d (bytes)", create_tunnel_req_pP->sgw_addr[i].length, addrs_length_in_bytes); if ((addrs_length_in_bytes == 4) || (addrs_length_in_bytes == 20)) { in_addr = *((in_addr_t*)create_tunnel_req_pP->sgw_addr[i].buffer); ip_offset = 4; gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].sgw_ip_addr = in_addr; } if ((addrs_length_in_bytes == 16) || (addrs_length_in_bytes == 20)) { memcpy(gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].sgw_ip6_addr.s6_addr, &create_tunnel_req_pP->sgw_addr[i].buffer[ip_offset], 16); } gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].state = BEARER_IN_CONFIG; gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_eNB = s1u_teid; gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_eNB_stack_session = stack_req.apiInfo.createTunnelEndPointInfo.hStackSession; gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_sgw = create_tunnel_req_pP->sgw_S1u_teid[i]; create_tunnel_resp_pP->enb_S1u_teid[i] = s1u_teid; } else { create_tunnel_resp_pP->enb_S1u_teid[i] = 0; create_tunnel_resp_pP->status = 0xFF; } create_tunnel_resp_pP->eps_bearer_id[i] = eps_bearer_id; create_tunnel_resp_pP->num_tunnels += 1; //----------------------- // GTPV1U->PDCP mapping //----------------------- hash_rc = hashtable_get(gtpv1u_data_g.teid_mapping, s1u_teid, (void**)>pv1u_teid_data_p); if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) { gtpv1u_teid_data_p = calloc (1, sizeof(gtpv1u_teid_data_t)); gtpv1u_teid_data_p->enb_id = 0; // TO DO gtpv1u_teid_data_p->ue_id = create_tunnel_req_pP->rnti; gtpv1u_teid_data_p->eps_bearer_id = eps_bearer_id; hash_rc = hashtable_insert(gtpv1u_data_g.teid_mapping, s1u_teid, gtpv1u_teid_data_p); AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting teid mapping in GTPV1U hashtable"); } else { create_tunnel_resp_pP->enb_S1u_teid[i] = 0; create_tunnel_resp_pP->status = 0xFF; } } MSC_LOG_TX_MESSAGE( MSC_GTPU_ENB, MSC_RRC_ENB, NULL,0, "0 GTPV1U_ENB_CREATE_TUNNEL_RESP rnti %x teid %x", create_tunnel_resp_pP->rnti, s1u_teid); LOG_D(GTPU, "Tx GTPV1U_ENB_CREATE_TUNNEL_RESP ue rnti %x status %d\n", create_tunnel_req_pP->rnti, create_tunnel_resp_pP->status); return 0; }