diff --git a/lib/fd/rx/rx_message.h b/lib/fd/rx/rx_message.h index 83ca2d2b71..522652782e 100644 --- a/lib/fd/rx/rx_message.h +++ b/lib/fd/rx/rx_message.h @@ -12,19 +12,17 @@ typedef struct _rx_message_t { c_uint16_t cmd_code; /* Result-Code AVP */ -#define RX_DIAMETER_ERROR_USER_UNKNOWN 5030 +#define RX_DIAMETER_REQUESTED_SERVICE_TEMPORARILY_NOT_AUTHORIZED 4261 /* Experimental-Result-Codes */ -#define RX_DIAMETER_ERROR_LATE_OVERLAPPING_REQUEST 5453 -#define RX_DIAMETER_ERROR_TIMED_OUT_REQUEST 5454 -#define RX_DIAMETER_ERROR_INITIAL_PARAMETERS 5140 -#define RX_DIAMETER_ERROR_TRIGGER_EVENT 5141 -#define RX_DIAMETER_PCC_RULE_EVENT 5142 -#define RX_DIAMETER_ERROR_BEARER_NOT_AUTHORIZED 5143 -#define RX_DIAMETER_ERROR_TRAFFIC_MAPPING_INFO_REJECTED 5144 -#define RX_DIAMETER_ERROR_CONFLICTING_REQUEST 5147 -#define RX_DIAMETER_ADC_RULE_EVENT 5148 -#define RX_DIAMETER_ERROR_NBIFOM_NOT_AUTHORIZED 5149 +#define RX_DIAMETER_INVALID_SERVICE_INFORMATION 5061 +#define RX_DIAMETER_FILTER_RESTRICTIONS 5062 +#define RX_DIAMETER_REQUESTED_SERVICE_NOT_AUTHORIZED 5063 +#define RX_DIAMETER_DUPLICATED_AF_SESSION 5064 +#define RX_DIAMETER_IP_CAN_SESSION_NOT_AVAILABLE 5065 +#define RX_DIAMETER_UNAUTHORIZED_NON_EMERGENCY_SESSION 5066 +#define RX_DIAMETER_UNAUTHORIZED_SPONSORED_DATA_CONNECTIVITY 5067 +#define RX_DIAMETER_TEMPORARY_NETWORK_FAILURE 5068 c_uint32_t result_code; } rx_message_t; diff --git a/lib/gtp/gtp_node.c b/lib/gtp/gtp_node.c index ff4db4d709..f3ae9c100b 100644 --- a/lib/gtp/gtp_node.c +++ b/lib/gtp/gtp_node.c @@ -82,6 +82,35 @@ status_t gtp_add_node(list_t *list, gtp_node_t **node, return CORE_OK; } +gtp_node_t *gtp_add_node_with_teid(list_t *list, gtp_f_teid_t *f_teid, + c_uint16_t port, int no_ipv4, int no_ipv6, int prefer_ipv4) +{ + status_t rv; + gtp_node_t *node = NULL; + c_sockaddr_t *sa_list = NULL; + + d_assert(list, return NULL,); + d_assert(f_teid, return NULL,); + d_assert(port, return NULL,); + + rv = gtp_f_teid_to_sockaddr(f_teid, port, &sa_list); + d_assert(rv == CORE_OK, return NULL,); + + rv = gtp_add_node(list, &node, sa_list, no_ipv4, no_ipv6, prefer_ipv4); + d_assert(rv == CORE_OK, return NULL,); + d_assert(node, return NULL,); + + rv = gtp_f_teid_to_ip(f_teid, &node->ip); + d_assert(rv == CORE_OK, return NULL,); + + rv = sock_fill_scope_id_in_local(node->sa_list); + d_assert(rv == CORE_OK, return NULL,); + + core_freeaddrinfo(sa_list); + + return node; +} + status_t gtp_remove_node(list_t *list, gtp_node_t *node) { d_assert(node, return CORE_ERROR,); diff --git a/lib/gtp/gtp_node.h b/lib/gtp/gtp_node.h index 0fcee87ff5..b24c3b6e7a 100644 --- a/lib/gtp/gtp_node.h +++ b/lib/gtp/gtp_node.h @@ -37,6 +37,9 @@ CORE_DECLARE(status_t) gtp_node_final(void); CORE_DECLARE(status_t) gtp_add_node(list_t *list, gtp_node_t **node, c_sockaddr_t *sa_list, int no_ipv4, int no_ipv6, int prefer_ipv4); +CORE_DECLARE(gtp_node_t *) gtp_add_node_with_teid( + list_t *list, gtp_f_teid_t *f_teid, + c_uint16_t port, int no_ipv4, int no_ipv6, int prefer_ipv4); CORE_DECLARE(status_t) gtp_remove_node(list_t *list, gtp_node_t *node); CORE_DECLARE(status_t) gtp_remove_all_nodes(list_t *list); diff --git a/lib/gtp/gtp_path.c b/lib/gtp/gtp_path.c index 2e0dd6875f..9a9515166b 100644 --- a/lib/gtp/gtp_path.c +++ b/lib/gtp/gtp_path.c @@ -45,36 +45,49 @@ status_t gtp_client(gtp_node_t *gnode) return CORE_OK; } -gtp_node_t *gtp_connect_to_node(list_t *list, gtp_f_teid_t *f_teid, - c_uint16_t port, int no_ipv4, int no_ipv6, int prefer_ipv4) +status_t gtp_connect(sock_id ipv4, sock_id ipv6, gtp_node_t *gnode) { - status_t rv; - gtp_node_t *node = NULL; - c_sockaddr_t *sa_list = NULL; + c_sockaddr_t *addr; + char buf[CORE_ADDRSTRLEN]; - d_assert(list, return NULL,); - d_assert(f_teid, return NULL,); - d_assert(port, return NULL,); + d_assert(ipv4 || ipv6, return CORE_ERROR,); + d_assert(gnode, return CORE_ERROR,); + d_assert(gnode->sa_list, return CORE_ERROR,); - rv = gtp_f_teid_to_sockaddr(f_teid, port, &sa_list); - d_assert(rv == CORE_OK, return NULL,); + addr = gnode->sa_list; + while(addr) + { + sock_id id; - rv = gtp_add_node(list, &node, sa_list, no_ipv4, no_ipv6, prefer_ipv4); - d_assert(rv == CORE_OK, return NULL,); - d_assert(node, return NULL,); + if (addr->c_sa_family == AF_INET) id = ipv4; + else if (addr->c_sa_family == AF_INET6) id = ipv6; + else + d_assert(0, return CORE_ERROR,); - rv = gtp_f_teid_to_ip(f_teid, &node->ip); - d_assert(rv == CORE_OK, return NULL,); + if (id) + { + if (sock_connect(id, addr) == CORE_OK) + { + d_trace(1, "gtp_connect() [%s]:%d\n", + CORE_ADDR(addr, buf), CORE_PORT(addr)); - rv = sock_fill_scope_id_in_local(node->sa_list); - d_assert(rv == CORE_OK, return NULL,); + gnode->sock = id; + break; + } + } - rv = gtp_client(node); - d_assert(rv == CORE_OK, return NULL,); + addr = addr->next; + } - core_freeaddrinfo(sa_list); + if (addr == NULL) + { + d_warn("gtp_connect() [%s]:%d failed(%d:%s)", + CORE_ADDR(gnode->sa_list, buf), CORE_PORT(gnode->sa_list), + errno, strerror(errno)); + return CORE_ERROR; + } - return node; + return CORE_OK; } status_t gtp_server_list(list_t *list, sock_handler handler) @@ -94,6 +107,22 @@ status_t gtp_server_list(list_t *list, sock_handler handler) return CORE_OK; } +sock_id gtp_local_sock_first(list_t *list) +{ + sock_node_t *snode = NULL; + sock_id sock = 0; + + d_assert(list, return 0,); + + for (snode = list_first(list); snode; snode = list_next(snode)) + { + sock = snode->sock; + if (sock) return sock; + } + + return 0; +} + c_sockaddr_t *gtp_local_addr_first(list_t *list) { sock_node_t *snode = NULL; diff --git a/lib/gtp/gtp_path.h b/lib/gtp/gtp_path.h index 64f25756d2..95a69f2dd9 100644 --- a/lib/gtp/gtp_path.h +++ b/lib/gtp/gtp_path.h @@ -12,12 +12,12 @@ extern "C" { CORE_DECLARE(status_t) gtp_server(sock_node_t *snode, sock_handler handler); CORE_DECLARE(status_t) gtp_client(gtp_node_t *gnode); - -CORE_DECLARE(gtp_node_t *) gtp_connect_to_node( - list_t *list, gtp_f_teid_t *f_teid, - c_uint16_t port, int no_ipv4, int no_ipv6, int prefer_ipv4); +CORE_DECLARE(status_t) gtp_connect( + sock_id ipv4, sock_id ipv6, gtp_node_t *gnode); CORE_DECLARE(status_t) gtp_server_list(list_t *list, sock_handler handler); + +CORE_DECLARE(sock_id) gtp_local_sock_first(list_t *list); CORE_DECLARE(c_sockaddr_t *) gtp_local_addr_first(list_t *list); CORE_DECLARE(status_t) gtp_recv(sock_id sock, pkbuf_t **pkbuf); diff --git a/src/mme/mme_context.c b/src/mme/mme_context.c index c29e137285..b87d962d70 100644 --- a/src/mme/mme_context.c +++ b/src/mme/mme_context.c @@ -1311,9 +1311,6 @@ status_t mme_context_parse_config() context_self()->parameter.prefer_ipv4); d_assert(rv == CORE_OK, return CORE_ERROR,); - rv = gtp_client(sgw); - d_assert(rv == CORE_OK, return CORE_ERROR,); - core_freeaddrinfo(list); } while(yaml_iter_type(>pc_array) == YAML_SEQUENCE_NODE); diff --git a/src/mme/mme_context.h b/src/mme/mme_context.h index b586b88a26..5b3ca19c81 100644 --- a/src/mme/mme_context.h +++ b/src/mme/mme_context.h @@ -63,8 +63,10 @@ typedef struct _mme_context_t { list_t s1ap_list6; /* MME S1AP IPv6 Server List */ list_t gtpc_list; /* MME GTPC IPv4 Server List */ - c_sockaddr_t *gtpc_addr; /* MME GTPC IPv4 Address */ list_t gtpc_list6; /* MME GTPC IPv6 Server List */ + sock_id gtpc_sock; /* MME GTPC IPv4 Socket */ + sock_id gtpc_sock6; /* MME GTPC IPv6 Socket */ + c_sockaddr_t *gtpc_addr; /* MME GTPC IPv4 Address */ c_sockaddr_t *gtpc_addr6; /* MME GTPC IPv6 Address */ list_t sgw_list; /* SGW GTPC Client List */ diff --git a/src/mme/mme_gtp_path.c b/src/mme/mme_gtp_path.c index b725b268a8..ec49b34e70 100644 --- a/src/mme/mme_gtp_path.c +++ b/src/mme/mme_gtp_path.c @@ -66,12 +66,15 @@ static c_sockaddr_t *gtp_addr_find_by_family(list_t *list, int family) status_t mme_gtp_open() { status_t rv; + gtp_node_t *gnode = NULL; rv = gtp_server_list(&mme_self()->gtpc_list, _gtpv2_c_recv_cb); d_assert(rv == CORE_OK, return CORE_ERROR,); rv = gtp_server_list(&mme_self()->gtpc_list6, _gtpv2_c_recv_cb); d_assert(rv == CORE_OK, return CORE_ERROR,); + mme_self()->gtpc_sock = gtp_local_sock_first(&mme_self()->gtpc_list); + mme_self()->gtpc_sock6 = gtp_local_sock_first(&mme_self()->gtpc_list6); mme_self()->gtpc_addr = gtp_local_addr_first(&mme_self()->gtpc_list); mme_self()->gtpc_addr6 = gtp_local_addr_first(&mme_self()->gtpc_list6); @@ -85,6 +88,13 @@ status_t mme_gtp_open() d_assert(mme_self()->pgw_addr || mme_self()->pgw_addr6, return CORE_ERROR,); + for (gnode = list_first(&mme_self()->sgw_list); + gnode; gnode = list_next(gnode)) + { + rv = gtp_client(gnode); + d_assert(rv == CORE_OK, return CORE_ERROR,); + } + return CORE_OK; } diff --git a/src/mme/s1ap_handler.c b/src/mme/s1ap_handler.c index 3c9543720d..17b62458c0 100644 --- a/src/mme/s1ap_handler.c +++ b/src/mme/s1ap_handler.c @@ -132,8 +132,8 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, s1ap_message_t *message) mme_ue = mme_ue_find_by_guti(&guti); if (!mme_ue) { - d_error("Can not find mme_ue with mme_code = %d, m_tmsi = %d", - guti.mme_code, guti.m_tmsi); + d_warn("Unknown UE by S_TMSI[G:%d,C:%d,M_TMSI:0x%x]", + guti.mme_gid, guti.mme_code, guti.m_tmsi); } else { @@ -410,7 +410,6 @@ void s1ap_handle_ue_context_release_request( enb_ue_t *enb_ue = NULL; S1ap_UEContextReleaseRequest_IEs_t *ies = NULL; - long cause; ies = &message->s1ap_UEContextReleaseRequest_IEs; d_assert(ies, return, "Null param"); @@ -426,8 +425,9 @@ void s1ap_handle_ue_context_release_request( switch(ies->cause.present) { case S1ap_Cause_PR_radioNetwork: - cause = ies->cause.choice.radioNetwork; - if (cause == S1ap_CauseRadioNetwork_user_inactivity) + { + if (ies->cause.choice.radioNetwork + == S1ap_CauseRadioNetwork_user_inactivity) { mme_ue_t *mme_ue = enb_ue->mme_ue; d_assert(mme_ue, return,); @@ -450,24 +450,48 @@ void s1ap_handle_ue_context_release_request( } else { - d_warn("Not implmented (radioNetwork cause : %d)", cause); + d_warn("Not implmented (radioNetwork cause : %d)", + ies->cause.choice.radioNetwork); } break; + } case S1ap_Cause_PR_transport: - cause = ies->cause.choice.transport; - d_warn("Not implmented (transport cause : %d)", cause); + { + S1ap_Cause_t cause; + const char *cause_string = NULL; + + if (ies->cause.choice.transport == + S1ap_CauseTransport_transport_resource_unavailable) + cause_string = "Transport Resource Unavailable"; + else if (ies->cause.choice.transport == + S1ap_CauseTransport_unspecified) + cause_string = "Unspecified"; + else + cause_string = "Unknown"; + + + d_warn("[S1AP] UE Context Release Request(Transport Cause: %s[%d])", + cause_string, ies->cause.choice.transport, + enb_ue->enb_ue_s1ap_id, + CORE_ADDR(enb->addr, buf), enb->enb_id); + + cause.present = S1ap_Cause_PR_nas; + cause.choice.nas = S1ap_CauseNas_normal_release; + rv = s1ap_send_ue_context_release_commmand( + enb_ue, &cause, 0); + d_assert(rv == CORE_OK, return, "s1ap send error"); + break; + } case S1ap_Cause_PR_nas: - cause = ies->cause.choice.nas; - d_warn("Not implmented (nas cause : %d)", cause); + d_warn("Not implmented (nas cause : %d)", ies->cause.choice.nas); break; case S1ap_Cause_PR_protocol: - cause = ies->cause.choice.protocol; - d_warn("Not implmented (protocol cause : %d)", cause); + d_warn("Not implmented (protocol cause : %d)", + ies->cause.choice.protocol); break; case S1ap_Cause_PR_misc: - cause = ies->cause.choice.misc; - d_warn("Not implmented (misc cause : %d)", cause); + d_warn("Not implmented (misc cause : %d)", ies->cause.choice.misc); break; default: d_warn("Invalid cause type : %d", ies->cause.present); @@ -493,8 +517,6 @@ void s1ap_handle_ue_context_release_complete( enb_ue = enb_ue_find_by_mme_ue_s1ap_id(ies->mme_ue_s1ap_id); d_assert(enb_ue, return, "No UE Context[%d]", ies->mme_ue_s1ap_id); - mme_ue = enb_ue->mme_ue; - d_assert(mme_ue, return,); d_trace(3, "[S1AP] UE Context Release Complete : " "UE[mME-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n", @@ -503,35 +525,39 @@ void s1ap_handle_ue_context_release_complete( enb_ue_remove(enb_ue); - sess = mme_sess_first(mme_ue); - while(sess) + mme_ue = enb_ue->mme_ue; + if (mme_ue) { - bearer = mme_bearer_first(sess); - while(bearer) + sess = mme_sess_first(mme_ue); + while(sess) { - if (MME_HAVE_SGW_DL_INDIRECT_TUNNEL(bearer) || - MME_HAVE_SGW_UL_INDIRECT_TUNNEL(bearer)) + bearer = mme_bearer_first(sess); + while(bearer) { - need_to_delete_indirect_tunnel = 1; + if (MME_HAVE_SGW_DL_INDIRECT_TUNNEL(bearer) || + MME_HAVE_SGW_UL_INDIRECT_TUNNEL(bearer)) + { + need_to_delete_indirect_tunnel = 1; + } + + bearer = mme_bearer_next(bearer); } - - bearer = mme_bearer_next(bearer); + sess = mme_sess_next(sess); } - sess = mme_sess_next(sess); - } - if (need_to_delete_indirect_tunnel) - { - rv = mme_gtp_send_delete_indirect_data_forwarding_tunnel_request( - mme_ue); - d_assert(rv == CORE_OK, return, "gtp send error"); - } - else - { - if (!FSM_CHECK(&mme_ue->sm, emm_state_detached) && - !FSM_CHECK(&mme_ue->sm, emm_state_attached)) + if (need_to_delete_indirect_tunnel) { - mme_ue_remove(mme_ue); + rv = mme_gtp_send_delete_indirect_data_forwarding_tunnel_request( + mme_ue); + d_assert(rv == CORE_OK, return, "gtp send error"); + } + else + { + if (!FSM_CHECK(&mme_ue->sm, emm_state_detached) && + !FSM_CHECK(&mme_ue->sm, emm_state_attached)) + { + mme_ue_remove(mme_ue); + } } } } diff --git a/src/pcrf/pcrf_context.c b/src/pcrf/pcrf_context.c index ed8bb5e749..e07a44981b 100644 --- a/src/pcrf/pcrf_context.c +++ b/src/pcrf/pcrf_context.c @@ -765,7 +765,7 @@ out: return rv; } -status_t pcrf_sess_set_ipv4(const void *key, c_int8_t *sid) +status_t pcrf_sess_set_ipv4(const void *key, c_uint8_t *sid) { d_assert(self.ip_hash, return CORE_ERROR,); @@ -777,7 +777,7 @@ status_t pcrf_sess_set_ipv4(const void *key, c_int8_t *sid) return CORE_OK; } -status_t pcrf_sess_set_ipv6(const void *key, c_int8_t *sid) +status_t pcrf_sess_set_ipv6(const void *key, c_uint8_t *sid) { d_assert(self.ip_hash, return CORE_ERROR,); @@ -790,30 +790,31 @@ status_t pcrf_sess_set_ipv6(const void *key, c_int8_t *sid) return CORE_OK; } -c_int8_t *pcrf_sess_find_by_ipv4(const void *key) +c_uint8_t *pcrf_sess_find_by_ipv4(const void *key) { - c_int8_t *sid = NULL; + c_uint8_t *sid = NULL; d_assert(key, return NULL,); mutex_lock(self.hash_lock); - sid = (c_int8_t *)hash_get(self.ip_hash, key, IPV4_LEN); + sid = (c_uint8_t *)hash_get(self.ip_hash, key, IPV4_LEN); mutex_unlock(self.hash_lock); return sid; } -c_int8_t *pcrf_sess_find_by_ipv6(const void *key) +c_uint8_t *pcrf_sess_find_by_ipv6(const void *key) { - c_int8_t *sid = NULL; + c_uint8_t *sid = NULL; d_assert(key, return NULL,); mutex_lock(self.hash_lock); - sid = (c_int8_t *)hash_get(self.ip_hash, key, IPV6_LEN); + sid = (c_uint8_t *)hash_get(self.ip_hash, key, IPV6_LEN); mutex_unlock(self.hash_lock); return sid; } + diff --git a/src/pcrf/pcrf_context.h b/src/pcrf/pcrf_context.h index 9656ec9fa6..2667c33693 100644 --- a/src/pcrf/pcrf_context.h +++ b/src/pcrf/pcrf_context.h @@ -13,6 +13,8 @@ extern "C" { #endif /* __cplusplus */ typedef struct _fd_config_t fd_config_t; +struct session; + typedef struct _pcrf_context_t { const char *fd_conf_path; /* PCRF freeDiameter conf path */ fd_config_t *fd_config; /* PCRF freeDiameter config */ @@ -37,10 +39,10 @@ CORE_DECLARE(status_t) pcrf_db_final(void); CORE_DECLARE(status_t) pcrf_db_pdn_data( c_int8_t *imsi_bcd, c_int8_t *apn, gx_cca_message_t *cca_message); -CORE_DECLARE(status_t) pcrf_sess_set_ipv4(const void *key, c_int8_t *sid); -CORE_DECLARE(status_t) pcrf_sess_set_ipv6(const void *key, c_int8_t *sid); -CORE_DECLARE(c_int8_t *) pcrf_sess_find_by_ipv4(const void *key); -CORE_DECLARE(c_int8_t *) pcrf_sess_find_by_ipv6(const void *key); +CORE_DECLARE(status_t) pcrf_sess_set_ipv4(const void *key, c_uint8_t *sid); +CORE_DECLARE(status_t) pcrf_sess_set_ipv6(const void *key, c_uint8_t *sid); +CORE_DECLARE(c_uint8_t *) pcrf_sess_find_by_ipv4(const void *key); +CORE_DECLARE(c_uint8_t *) pcrf_sess_find_by_ipv6(const void *key); #ifdef __cplusplus } diff --git a/src/pcrf/pcrf_fd_path.h b/src/pcrf/pcrf_fd_path.h index 697182730f..a2cf63ae73 100644 --- a/src/pcrf/pcrf_fd_path.h +++ b/src/pcrf/pcrf_fd_path.h @@ -7,6 +7,8 @@ extern "C" { #endif /* __cplusplus */ +struct sess_state; + CORE_DECLARE(int) pcrf_fd_init(void); CORE_DECLARE(void) pcrf_fd_final(void); @@ -15,6 +17,9 @@ CORE_DECLARE(void) pcrf_gx_final(void); CORE_DECLARE(int) pcrf_rx_init(void); CORE_DECLARE(void) pcrf_rx_final(void); +CORE_DECLARE(status_t) pcrf_sess_gx_associate_rx( + c_uint8_t *gx_sid, c_uint8_t *rx_sid); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/pcrf/pcrf_gx_path.c b/src/pcrf/pcrf_gx_path.c index 48de984063..52ee355b32 100644 --- a/src/pcrf/pcrf_gx_path.c +++ b/src/pcrf/pcrf_gx_path.c @@ -10,16 +10,18 @@ #include "fd/gx/gx_message.h" #include "pcrf_context.h" +#include "pcrf_fd_path.h" struct sess_state { c_uint32_t cc_request_type; /* CC-Request-Type */ - c_int8_t *sid; /* Session-Id */ + os0_t gx_sid; /* Gx Session-Id */ + os0_t rx_sid; /* Rx Session-Id */ ED3(c_uint8_t ipv4:1;, c_uint8_t ipv6:1;, c_uint8_t reserved:6;) c_uint32_t addr; /* Framed-IPv4-Address */ - c_uint8_t addr6[IPV6_LEN]; /* Framed-IPv6-Prefix */ + c_uint8_t addr6[IPV6_LEN]; /* Framed-IPv6-Prefix */ }; static struct session_handler *pcrf_gx_reg = NULL; @@ -35,8 +37,8 @@ static __inline__ struct sess_state *new_state(os0_t sid) d_assert(new, return NULL,); memset(new, 0, sizeof *new); - new->sid = core_strdup((char *)sid); - d_assert(new->sid, return NULL,); + new->gx_sid = (os0_t)core_strdup((char *)sid); + d_assert(new->gx_sid, return NULL,); return new; } @@ -51,8 +53,10 @@ static void state_cleanup( if (sess_data->ipv6) pcrf_sess_set_ipv6(sess_data->addr6, NULL); - if (sess_data->sid) - core_free(sess_data->sid); + if (sess_data->gx_sid) + core_free(sess_data->gx_sid); + if (sess_data->rx_sid) + core_free(sess_data->rx_sid); pool_free_node(&pcrf_gx_sess_pool, sess_data); } @@ -135,7 +139,7 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp, CHECK_FCT( fd_msg_avp_hdr(avp, &hdr) ); memcpy(&sess_data->addr, hdr->avp_value->os.data, sizeof sess_data->addr); - pcrf_sess_set_ipv4(&sess_data->addr, sess_data->sid); + pcrf_sess_set_ipv4(&sess_data->addr, sess_data->gx_sid); sess_data->ipv4 = 1; } @@ -151,7 +155,7 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp, d_assert(paa->len == IPV6_LEN * 8 /* 128bit */, goto out, "Invalid Framed-IPv6-Prefix Length:%d", paa->len); memcpy(sess_data->addr6, paa->addr6, sizeof sess_data->addr6); - pcrf_sess_set_ipv6(sess_data->addr6, sess_data->sid); + pcrf_sess_set_ipv6(sess_data->addr6, sess_data->gx_sid); sess_data->ipv6 = 1; } @@ -403,7 +407,7 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp, /* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */ CHECK_FCT( fd_msg_rescode_set(ans, "DIAMETER_SUCCESS", NULL, NULL, 1) ); - if (sess_data->cc_request_type == GX_CC_REQUEST_TYPE_TERMINATION_REQUEST) + if (sess_data->cc_request_type != GX_CC_REQUEST_TYPE_TERMINATION_REQUEST) { /* Store this value in the session */ CHECK_FCT_DO( fd_sess_state_store(pcrf_gx_reg, sess, &sess_data), @@ -440,6 +444,7 @@ out: CHECK_FCT( fd_msg_send(msg, NULL, NULL) ); + state_cleanup(sess_data, NULL, NULL); gx_cca_message_free(&cca_message); return 0; @@ -490,3 +495,35 @@ void pcrf_gx_final(void) pool_final(&pcrf_gx_sess_pool); } + +status_t pcrf_sess_gx_associate_rx(c_uint8_t *gx_sid, c_uint8_t *rx_sid) +{ + struct session *sess = NULL; + struct sess_state *sess_data = NULL; + int ret; + size_t sidlen = 0; + int new; + + d_assert(gx_sid, return CORE_ERROR,); + d_assert(rx_sid, return CORE_ERROR,); + + sidlen = strlen((char *)gx_sid); + ret = fd_sess_fromsid((os0_t)gx_sid, sidlen, &sess, &new); + d_assert(ret == 0, return CORE_ERROR,); + d_assert(new == 0, return CORE_ERROR,); + + ret = fd_sess_state_retrieve(pcrf_gx_reg, sess, &sess_data); + d_assert(ret == 0, return CORE_ERROR,); + d_assert(sess_data, return CORE_ERROR,); + + if (sess_data->rx_sid) + core_free(sess_data->rx_sid); + sess_data->rx_sid = (os0_t)core_strdup((char *)rx_sid); + d_assert(sess_data->rx_sid, return CORE_ERROR,); + + ret = fd_sess_state_store(pcrf_gx_reg, sess, &sess_data); + d_assert(ret == 0, return CORE_ERROR,); + d_assert(sess_data == NULL, return CORE_ERROR,); + + return CORE_OK; +} diff --git a/src/pcrf/pcrf_rx_path.c b/src/pcrf/pcrf_rx_path.c index a4d048672c..73f3433e58 100644 --- a/src/pcrf/pcrf_rx_path.c +++ b/src/pcrf/pcrf_rx_path.c @@ -1,21 +1,52 @@ #define TRACE_MODULE _pcrf_rx_path #include "core_debug.h" +#include "core_pool.h" +#include "core_pkbuf.h" +#include "core_network.h" #include "fd/fd_lib.h" #include "fd/rx/rx_dict.h" #include "fd/rx/rx_message.h" #include "pcrf_context.h" +#include "pcrf_fd_path.h" + +struct sess_state { + os0_t rx_sid; /* Rx Session-Id */ + os0_t gx_sid; /* Gx Session-Id */ +}; static struct session_handler *pcrf_rx_reg = NULL; static struct disp_hdl *hdl_rx_fb = NULL; static struct disp_hdl *hdl_rx_aar = NULL; -void pcrf_rx_sess_cleanup( +pool_declare(pcrf_rx_sess_pool, struct sess_state, MAX_POOL_OF_DIAMETER_SESS); + +static __inline__ struct sess_state *new_state(os0_t sid) +{ + struct sess_state *new = NULL; + pool_alloc_node(&pcrf_rx_sess_pool, &new); + d_assert(new, return NULL,); + memset(new, 0, sizeof *new); + + new->rx_sid = (os0_t)core_strdup((char *)sid); + d_assert(new->rx_sid, return NULL,); + + return new; +} + +static void state_cleanup( struct sess_state *sess_data, os0_t sid, void *opaque) { -// pool_free_node(&pgw_gx_sess_pool, sess_data); + d_assert(sess_data, return,); + + if (sess_data->rx_sid) + core_free((char *)sess_data->rx_sid); + if (sess_data->gx_sid) + core_free((char *)sess_data->gx_sid); + + pool_free_node(&pcrf_rx_sess_pool, sess_data); } static int pcrf_rx_fb_cb(struct msg **msg, struct avp *avp, @@ -30,26 +61,42 @@ static int pcrf_rx_fb_cb(struct msg **msg, struct avp *avp, static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp, struct session *sess, void *opaque, enum disp_action *act) { - struct msg *ans; -#if 0 + status_t rv; + struct msg *ans, *qry; +#if 0 struct avp *avpch1, *avpch2, *avpch3, *avpch4; - struct avp_hdr *hdr; #endif + struct avp_hdr *hdr; union avp_value val; + struct sess_state *sess_data = NULL; #if 0 - status_t rv; gx_cca_message_t cca_message; c_int8_t imsi_bcd[MAX_IMSI_BCD_LEN+1]; c_int8_t apn[MAX_APN_LEN+1]; int i, j; c_uint32_t cc_request_type = 0; - c_uint32_t result_code = RX_DIAMETER_ERROR_USER_UNKNOWN; #endif + char buf[CORE_ADDRSTRLEN]; + os0_t rx_sid = NULL; + os0_t gx_sid = NULL; + size_t sidlen; + c_uint32_t result_code = RX_DIAMETER_IP_CAN_SESSION_NOT_AVAILABLE; d_assert(msg, return EINVAL,); + d_assert(sess, return EINVAL,); + + d_assert( fd_sess_state_retrieve(pcrf_rx_reg, sess, &sess_data) == 0, + return EINVAL,); + if (!sess_data) + { + d_assert( fd_sess_getsid(sess, &rx_sid, &sidlen) == 0, return EINVAL,); + + sess_data = new_state(rx_sid); + d_assert(sess_data, return EINVAL,); + } #if 0 /* Initialize Message */ @@ -57,9 +104,7 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp, #endif /* Create answer header */ -#if 0 qry = *msg; -#endif CHECK_FCT( fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0) ); ans = *msg; @@ -75,9 +120,61 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp, CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out ); CHECK_FCT_DO( fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp), goto out ); + /* Get Framed-IP-Address */ + CHECK_FCT( fd_msg_search_avp(qry, rx_framed_ip_address, &avp) ); + if (avp) + { + CHECK_FCT( fd_msg_avp_hdr(avp, &hdr) ); + gx_sid = (os0_t)pcrf_sess_find_by_ipv4(hdr->avp_value->os.data); + if (!gx_sid) + { + d_warn("Cannot find Gx Sesson for IPv4:%s\n", + INET_NTOP(hdr->avp_value->os.data, buf)); + } + } + + if (!gx_sid) + { + /* Get Framed-IPv6-Prefix */ + CHECK_FCT( fd_msg_search_avp(qry, rx_framed_ipv6_prefix, &avp) ); + if (avp) + { + paa_t *paa = NULL; + + CHECK_FCT( fd_msg_avp_hdr(avp, &hdr) ); + paa = (paa_t *)hdr->avp_value->os.data; + d_assert(paa, goto out,); + d_assert(paa->len == IPV6_LEN * 8 /* 128bit */, goto out, + "Invalid Framed-IPv6-Prefix Length:%d", paa->len); + gx_sid = (os0_t)pcrf_sess_find_by_ipv6(paa->addr6); + if (!gx_sid) + { + d_warn("Cannot find Gx Sesson for IPv6:%s\n", + INET6_NTOP(hdr->avp_value->os.data, buf)); + } + } + } + + if (!gx_sid) goto out; + + /* Associate Gx-session with Rx-session */ + rv = pcrf_sess_gx_associate_rx(gx_sid, rx_sid); + d_assert(rv == CORE_OK, goto out,); + + /* Store Gx Session-Id in this session */ + if (sess_data->gx_sid) + core_free(sess_data->gx_sid); + sess_data->gx_sid = (os0_t)core_strdup((char *)gx_sid); + d_assert(sess_data->gx_sid, goto out,); + /* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */ CHECK_FCT( fd_msg_rescode_set(ans, "DIAMETER_SUCCESS", NULL, NULL, 1) ); + /* Store this value in the session */ + CHECK_FCT_DO( fd_sess_state_store(pcrf_rx_reg, sess, &sess_data), + goto out ); + d_assert(sess_data == NULL,,); + /* Send the answer */ CHECK_FCT( fd_msg_send(msg, NULL, NULL) ); @@ -93,20 +190,20 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp, return 0; out: -#if 0 - if (result_code == RX_DIAMETER_ERROR_USER_UNKNOWN) + if (result_code == RX_DIAMETER_REQUESTED_SERVICE_TEMPORARILY_NOT_AUTHORIZED) { CHECK_FCT( fd_msg_rescode_set(ans, - "DIAMETER_ERROR_USER_UNKNOWN", NULL, NULL, 1) ); + "RX_DIAMETER_REQUESTED_SERVICE_TEMPORARILY_NOT_AUTHORIZED", + NULL, NULL, 1) ); } else { CHECK_FCT( fd_message_experimental_rescode_set(ans, result_code) ); } -#endif CHECK_FCT( fd_msg_send(msg, NULL, NULL) ); + state_cleanup(sess_data, NULL, NULL); #if 0 gx_cca_message_free(&cca_message); #endif @@ -118,10 +215,13 @@ int pcrf_rx_init(void) { struct disp_when data; - /* RX Interface */ + pool_init(&pcrf_rx_sess_pool, MAX_POOL_OF_DIAMETER_SESS); + + /* Install objects definitions for this application */ CHECK_FCT( rx_dict_init() ); - CHECK_FCT( fd_sess_handler_create(&pcrf_rx_reg, pcrf_rx_sess_cleanup, + /* Create handler for sessions */ + CHECK_FCT( fd_sess_handler_create(&pcrf_rx_reg, state_cleanup, NULL, NULL) ); memset(&data, 0, sizeof(data)); @@ -134,6 +234,7 @@ int pcrf_rx_init(void) CHECK_FCT( fd_disp_register(pcrf_rx_aar_cb, DISP_HOW_CC, &data, NULL, &hdl_rx_aar) ); + /* Advertise the support for the application in the peer */ CHECK_FCT( fd_disp_app_support(rx_application, fd_vendor, 1, 0) ); return 0; @@ -146,4 +247,12 @@ void pcrf_rx_final(void) (void) fd_disp_unregister(&hdl_rx_fb, NULL); if (hdl_rx_aar) (void) fd_disp_unregister(&hdl_rx_aar, NULL); + + if (pool_used(&pcrf_rx_sess_pool)) + d_error("%d not freed in pcrf_rx_sess_pool[%d] of GX-SM", + pool_used(&pcrf_rx_sess_pool), pool_size(&pcrf_rx_sess_pool)); + d_trace(3, "%d not freed in pcrf_rx_sess_pool[%d] of GX-SM\n", + pool_used(&pcrf_rx_sess_pool), pool_size(&pcrf_rx_sess_pool)); + + pool_final(&pcrf_rx_sess_pool); } diff --git a/src/pgw/pgw_context.c b/src/pgw/pgw_context.c index 13e548ba32..db2937488c 100644 --- a/src/pgw/pgw_context.c +++ b/src/pgw/pgw_context.c @@ -1051,6 +1051,7 @@ pgw_sess_t* pgw_sess_find_by_imsi_apn( gtp_node_t *pgw_sgw_add_by_message(gtp_message_t *message) { + status_t rv; gtp_node_t *sgw = NULL; gtp_f_teid_t *sgw_s5c_teid = NULL; @@ -1067,12 +1068,15 @@ gtp_node_t *pgw_sgw_add_by_message(gtp_message_t *message) sgw = gtp_find_node(&pgw_self()->sgw_s5c_list, sgw_s5c_teid); if (!sgw) { - sgw = gtp_connect_to_node(&pgw_self()->sgw_s5c_list, sgw_s5c_teid, + sgw = gtp_add_node_with_teid(&pgw_self()->sgw_s5c_list, sgw_s5c_teid, pgw_self()->gtpc_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, context_self()->parameter.prefer_ipv4); d_assert(sgw, return NULL,); + + rv = gtp_client(sgw); + d_assert(rv == CORE_OK, return NULL,); } return sgw; diff --git a/src/pgw/pgw_context.h b/src/pgw/pgw_context.h index 6eccc8ae57..bdb118173f 100644 --- a/src/pgw/pgw_context.h +++ b/src/pgw/pgw_context.h @@ -31,13 +31,17 @@ typedef struct _pgw_context_t { const char *tun_ifname; /* Default:: pgwtun */ list_t gtpc_list; /* PGW GTPC IPv4 Server List */ - c_sockaddr_t *gtpc_addr; /* PGW GTPC IPv4 Address */ list_t gtpc_list6; /* PGW GTPC IPv6 Server List */ + sock_id gtpc_sock; /* PGW GTPC IPv4 Socket */ + sock_id gtpc_sock6; /* PGW GTPC IPv6 Socket */ + c_sockaddr_t *gtpc_addr; /* PGW GTPC IPv4 Address */ c_sockaddr_t *gtpc_addr6; /* PGW GTPC IPv6 Address */ list_t gtpu_list; /* PGW GTPU IPv4 Server List */ - c_sockaddr_t *gtpu_addr; /* PGW GTPU IPv4 Address */ list_t gtpu_list6; /* PGW GTPU IPv6 Server List */ + sock_id gtpu_sock; /* PGW GTPU IPv4 Socket */ + sock_id gtpu_sock6; /* PGW GTPU IPv6 Socket */ + c_sockaddr_t *gtpu_addr; /* PGW GTPU IPv4 Address */ c_sockaddr_t *gtpu_addr6; /* PGW GTPU IPv6 Address */ list_t dev_list; /* PGW Tun Device List */ diff --git a/src/pgw/pgw_fd_path.c b/src/pgw/pgw_fd_path.c index 17450987ae..e308ab530a 100644 --- a/src/pgw/pgw_fd_path.c +++ b/src/pgw/pgw_fd_path.c @@ -14,6 +14,8 @@ #include "pgw_fd_path.h" static struct session_handler *pgw_gx_reg = NULL; +static struct disp_hdl *hdl_gx_fb = NULL; +static struct disp_hdl *hdl_gx_rar = NULL; struct sess_state { gtp_xact_t *xact; @@ -28,7 +30,7 @@ pool_declare(pgw_gx_sess_pool, struct sess_state, MAX_POOL_OF_DIAMETER_SESS); static void pgw_gx_cca_cb(void *data, struct msg **msg); -void pgw_gx_sess_cleanup( +void state_cleanup( struct sess_state *sess_data, os0_t sid, void * opaque) { pool_free_node(&pgw_gx_sess_pool, sess_data); @@ -191,7 +193,7 @@ void pgw_gx_send_ccr(gtp_xact_t *xact, pgw_sess_t *sess, CHECK_FCT_DO( fd_msg_avp_new(gx_framed_ip_address, 0, &avp), goto out ); val.os.data = (c_uint8_t*)&sess->ipv4->addr; - val.os.len = 4; + val.os.len = IPV4_LEN; CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out ); CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out ); @@ -808,7 +810,7 @@ out: } else { - pgw_gx_sess_cleanup(mi, NULL, NULL); + state_cleanup(mi, NULL, NULL); } CHECK_FCT_DO( fd_msg_free(*msg), return ); @@ -817,8 +819,94 @@ out: return; } +static int pgw_gx_fb_cb(struct msg **msg, struct avp *avp, + struct session *sess, void *opaque, enum disp_action *act) +{ + /* This CB should never be called */ + d_warn("Unexpected message received!"); + + return ENOTSUP; +} + +static int pgw_gx_rar_cb( struct msg **msg, struct avp *avp, + struct session *sess, void *opaque, enum disp_action *act) +{ +#if 0 + status_t rv; +#endif + + struct msg *ans; +#if 0 + struct msg *ans, *qry; + struct avp *avpch1, *avpch2, *avpch3, *avpch4; + struct avp_hdr *hdr; +#endif + union avp_value val; + struct sess_state *mi = NULL; + + c_uint32_t result_code = GX_DIAMETER_ERROR_USER_UNKNOWN; + + d_assert(msg, return EINVAL,); + + d_assert( fd_sess_state_retrieve(pgw_gx_reg, sess, &mi) == 0, + return EINVAL,); + if (mi) + { + } + + /* Create answer header */ +#if 0 + qry = *msg; +#endif + CHECK_FCT( fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0) ); + ans = *msg; + + /* Set the Auth-Application-Id AVP */ + CHECK_FCT_DO( fd_msg_avp_new(fd_auth_application_id, 0, &avp), goto out ); + val.i32 = GX_APPLICATION_ID; + CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out ); + CHECK_FCT_DO( fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp), goto out ); + + /* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */ + CHECK_FCT( fd_msg_rescode_set(ans, "DIAMETER_SUCCESS", NULL, NULL, 1) ); + + /* Store this value in the session */ + CHECK_FCT_DO( fd_sess_state_store(pgw_gx_reg, sess, &mi), + goto out ); + d_assert(mi == NULL,,); + + /* Send the answer */ + CHECK_FCT( fd_msg_send(msg, NULL, NULL) ); + + /* Add this value to the stats */ + CHECK_POSIX_DO( pthread_mutex_lock(&fd_logger_self()->stats_lock), ); + fd_logger_self()->stats.nb_echoed++; + CHECK_POSIX_DO( pthread_mutex_unlock(&fd_logger_self()->stats_lock), ); + + return 0; + +out: + if (result_code == GX_DIAMETER_ERROR_USER_UNKNOWN) + { + CHECK_FCT( fd_msg_rescode_set(ans, + "DIAMETER_ERROR_USER_UNKNOWN", NULL, NULL, 1) ); + } + else + { + CHECK_FCT( fd_message_experimental_rescode_set(ans, result_code) ); + } + + CHECK_FCT( fd_msg_send(msg, NULL, NULL) ); + + state_cleanup(mi, NULL, NULL); + + return 0; +} + int pgw_fd_init(void) { + struct disp_when data; + pool_init(&pgw_gx_sess_pool, MAX_POOL_OF_DIAMETER_SESS); CHECK_FCT( fd_init(FD_MODE_CLIENT|FD_MODE_SERVER, @@ -828,9 +916,19 @@ int pgw_fd_init(void) CHECK_FCT( gx_dict_init() ); /* Create handler for sessions */ - CHECK_FCT( fd_sess_handler_create(&pgw_gx_reg, pgw_gx_sess_cleanup, + CHECK_FCT( fd_sess_handler_create(&pgw_gx_reg, state_cleanup, NULL, NULL) ); + memset(&data, 0, sizeof(data)); + data.app = gx_application; + + CHECK_FCT( fd_disp_register(pgw_gx_fb_cb, DISP_HOW_APPID, &data, NULL, + &hdl_gx_fb) ); + + data.command = gx_cmd_rar; + CHECK_FCT( fd_disp_register(pgw_gx_rar_cb, DISP_HOW_CC, &data, NULL, + &hdl_gx_rar) ); + /* Advertise the support for the application in the peer */ CHECK_FCT( fd_disp_app_support(gx_application, fd_vendor, 1, 0) ); @@ -840,6 +938,10 @@ int pgw_fd_init(void) void pgw_fd_final(void) { CHECK_FCT_DO( fd_sess_handler_destroy(&pgw_gx_reg, NULL), ); + if (hdl_gx_fb) + (void) fd_disp_unregister(&hdl_gx_fb, NULL); + if (hdl_gx_rar) + (void) fd_disp_unregister(&hdl_gx_rar, NULL); fd_final(); diff --git a/src/pgw/pgw_gtp_path.c b/src/pgw/pgw_gtp_path.c index 68d4005b3b..8350b9422c 100644 --- a/src/pgw/pgw_gtp_path.c +++ b/src/pgw/pgw_gtp_path.c @@ -150,8 +150,9 @@ static int _gtpv1_u_recv_cb(sock_id sock, void *data) if (!subnet) { d_print_hex(pkbuf->payload, pkbuf->len); - d_assert(0, goto cleanup, - "V:%d, IPv4:%p, IPv6:%p", ip_h->ip_v, sess->ipv4, sess->ipv6); + d_warn(0, "[DROP] Cannot find subnet V:%d, IPv4:%p, IPv6:%p", + ip_h->ip_v, sess->ipv4, sess->ipv6); + goto cleanup; } /* Check IPv6 */ @@ -188,6 +189,8 @@ status_t pgw_gtp_open() rv = gtp_server_list(&pgw_self()->gtpc_list6, _gtpv2_c_recv_cb); d_assert(rv == CORE_OK, return CORE_ERROR,); + pgw_self()->gtpc_sock = gtp_local_sock_first(&pgw_self()->gtpc_list); + pgw_self()->gtpc_sock6 = gtp_local_sock_first(&pgw_self()->gtpc_list6); pgw_self()->gtpc_addr = gtp_local_addr_first(&pgw_self()->gtpc_list); pgw_self()->gtpc_addr6 = gtp_local_addr_first(&pgw_self()->gtpc_list6); @@ -199,6 +202,8 @@ status_t pgw_gtp_open() rv = gtp_server_list(&pgw_self()->gtpu_list6, _gtpv1_u_recv_cb); d_assert(rv == CORE_OK, return CORE_ERROR,); + pgw_self()->gtpu_sock = gtp_local_sock_first(&pgw_self()->gtpu_list); + pgw_self()->gtpu_sock6 = gtp_local_sock_first(&pgw_self()->gtpu_list6); pgw_self()->gtpu_addr = gtp_local_addr_first(&pgw_self()->gtpu_list); pgw_self()->gtpu_addr6 = gtp_local_addr_first(&pgw_self()->gtpu_list6); diff --git a/src/pgw/pgw_s5c_handler.c b/src/pgw/pgw_s5c_handler.c index bd06ed32d4..c812ebc843 100644 --- a/src/pgw/pgw_s5c_handler.c +++ b/src/pgw/pgw_s5c_handler.c @@ -16,6 +16,7 @@ void pgw_s5c_handle_create_session_request( gtp_xact_t *xact, pgw_sess_t *sess, gtp_create_session_request_t *req) { + status_t rv; gtp_f_teid_t *sgw_s5c_teid, *sgw_s5u_teid; gtp_node_t *sgw = NULL; pgw_bearer_t *bearer = NULL; @@ -78,12 +79,15 @@ void pgw_s5c_handle_create_session_request( sgw = gtp_find_node(&pgw_self()->sgw_s5u_list, sgw_s5u_teid); if (!sgw) { - sgw = gtp_connect_to_node(&pgw_self()->sgw_s5u_list, sgw_s5u_teid, + sgw = gtp_add_node_with_teid(&pgw_self()->sgw_s5u_list, sgw_s5u_teid, pgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, context_self()->parameter.prefer_ipv4); d_assert(sgw, return,); + + rv = gtp_client(sgw); + d_assert(rv == CORE_OK, return,); } /* Setup GTP Node */ SETUP_GTP_NODE(bearer, sgw); @@ -174,12 +178,15 @@ void pgw_s5c_handle_create_bearer_response( sgw = gtp_find_node(&pgw_self()->sgw_s5u_list, sgw_s5u_teid); if (!sgw) { - sgw = gtp_connect_to_node(&pgw_self()->sgw_s5u_list, sgw_s5u_teid, + sgw = gtp_add_node_with_teid(&pgw_self()->sgw_s5u_list, sgw_s5u_teid, pgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, context_self()->parameter.prefer_ipv4); d_assert(sgw, return,); + + rv = gtp_client(sgw); + d_assert(rv == CORE_OK, return,); } /* Setup GTP Node */ SETUP_GTP_NODE(bearer, sgw); diff --git a/src/sgw/sgw_context.c b/src/sgw/sgw_context.c index 0d97cdc5da..e0d0176c0f 100644 --- a/src/sgw/sgw_context.c +++ b/src/sgw/sgw_context.c @@ -496,6 +496,7 @@ status_t sgw_context_setup_trace_module() gtp_node_t *sgw_mme_add_by_message(gtp_message_t *message) { + status_t rv; gtp_node_t *mme = NULL; gtp_f_teid_t *mme_s11_teid = NULL; gtp_create_session_request_t *req = &message->create_session_request; @@ -511,12 +512,15 @@ gtp_node_t *sgw_mme_add_by_message(gtp_message_t *message) mme = gtp_find_node(&sgw_self()->mme_s11_list, mme_s11_teid); if (!mme) { - mme = gtp_connect_to_node(&sgw_self()->mme_s11_list, mme_s11_teid, + mme = gtp_add_node_with_teid(&sgw_self()->mme_s11_list, mme_s11_teid, sgw_self()->gtpc_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, context_self()->parameter.prefer_ipv4); d_assert(mme, return NULL,); + + rv = gtp_client(mme); + d_assert(rv == CORE_OK, return NULL,); } return mme; diff --git a/src/sgw/sgw_context.h b/src/sgw/sgw_context.h index 157f7d8939..4275073a4d 100644 --- a/src/sgw/sgw_context.h +++ b/src/sgw/sgw_context.h @@ -24,13 +24,17 @@ typedef struct _sgw_context_t { c_uint32_t gtpu_port; /* Default GTPU port */ list_t gtpc_list; /* SGW GTPC IPv4 Server List */ - c_sockaddr_t *gtpc_addr; /* SGW GTPC IPv4 Address */ list_t gtpc_list6; /* SGW GTPC IPv6 Server List */ + sock_id gtpc_sock; /* SGW GTPC IPv4 Socket */ + sock_id gtpc_sock6; /* SGW GTPC IPv6 Socket */ + c_sockaddr_t *gtpc_addr; /* SGW GTPC IPv4 Address */ c_sockaddr_t *gtpc_addr6; /* SGW GTPC IPv6 Address */ list_t gtpu_list; /* SGW GTPU IPv4 Server List */ - c_sockaddr_t *gtpu_addr; /* SGW GTPU IPv4 Address */ list_t gtpu_list6; /* SGW GTPU IPv6 Server List */ + sock_id gtpu_sock; /* SGW GTPU IPv4 Socket */ + sock_id gtpu_sock6; /* SGW GTPU IPv6 Socket */ + c_sockaddr_t *gtpu_addr; /* SGW GTPU IPv4 Address */ c_sockaddr_t *gtpu_addr6; /* SGW GTPU IPv6 Address */ msgq_id queue_id; /* Queue for processing SGW control plane */ diff --git a/src/sgw/sgw_gtp_path.c b/src/sgw/sgw_gtp_path.c index 3b072d7c8c..6664aa23bc 100644 --- a/src/sgw/sgw_gtp_path.c +++ b/src/sgw/sgw_gtp_path.c @@ -226,6 +226,8 @@ status_t sgw_gtp_open() rv = gtp_server_list(&sgw_self()->gtpc_list6, _gtpv2_c_recv_cb); d_assert(rv == CORE_OK, return CORE_ERROR,); + sgw_self()->gtpc_sock = gtp_local_sock_first(&sgw_self()->gtpc_list); + sgw_self()->gtpc_sock6 = gtp_local_sock_first(&sgw_self()->gtpc_list6); sgw_self()->gtpc_addr = gtp_local_addr_first(&sgw_self()->gtpc_list); sgw_self()->gtpc_addr6 = gtp_local_addr_first(&sgw_self()->gtpc_list6); @@ -237,6 +239,8 @@ status_t sgw_gtp_open() rv = gtp_server_list(&sgw_self()->gtpu_list6, _gtpv1_u_recv_cb); d_assert(rv == CORE_OK, return CORE_ERROR,); + sgw_self()->gtpu_sock = gtp_local_sock_first(&sgw_self()->gtpu_list); + sgw_self()->gtpu_sock6 = gtp_local_sock_first(&sgw_self()->gtpu_list6); sgw_self()->gtpu_addr = gtp_local_addr_first(&sgw_self()->gtpu_list); sgw_self()->gtpu_addr6 = gtp_local_addr_first(&sgw_self()->gtpu_list6); diff --git a/src/sgw/sgw_s11_handler.c b/src/sgw/sgw_s11_handler.c index 2c1b023868..aa199363eb 100644 --- a/src/sgw/sgw_s11_handler.c +++ b/src/sgw/sgw_s11_handler.c @@ -112,12 +112,15 @@ void sgw_s11_handle_create_session_request( pgw = gtp_find_node(&sgw_self()->pgw_s5c_list, pgw_s5c_teid); if (!pgw) { - pgw = gtp_connect_to_node(&sgw_self()->pgw_s5c_list, pgw_s5c_teid, + pgw = gtp_add_node_with_teid(&sgw_self()->pgw_s5c_list, pgw_s5c_teid, sgw_self()->gtpc_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, context_self()->parameter.prefer_ipv4); d_assert(pgw, return,); + + rv = gtp_client(pgw); + d_assert(rv == CORE_OK, return,); } /* Setup GTP Node */ SETUP_GTP_NODE(sess, pgw); @@ -228,12 +231,19 @@ CORE_DECLARE(void) sgw_s11_handle_modify_bearer_request(gtp_xact_t *s11_xact, enb = gtp_find_node(&sgw_self()->enb_s1u_list, enb_s1u_teid); if (!enb) { - enb = gtp_connect_to_node(&sgw_self()->enb_s1u_list, enb_s1u_teid, + enb = gtp_add_node_with_teid(&sgw_self()->enb_s1u_list, enb_s1u_teid, sgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, context_self()->parameter.prefer_ipv4); d_assert(enb, return,); + +#if 1 + rv = gtp_client(enb); +#else /* Exmaple code for GTP code */ + rv = gtp_connect(sgw_self()->gtpu_sock, sgw_self()->gtpu_sock6, enb); +#endif + d_assert(rv == CORE_OK, return,); } /* Setup GTP Node */ SETUP_GTP_NODE(s1u_tunnel, enb); @@ -387,12 +397,15 @@ void sgw_s11_handle_create_bearer_response(gtp_xact_t *s11_xact, enb = gtp_find_node(&sgw_self()->enb_s1u_list, enb_s1u_teid); if (!enb) { - enb = gtp_connect_to_node(&sgw_self()->enb_s1u_list, enb_s1u_teid, + enb = gtp_add_node_with_teid(&sgw_self()->enb_s1u_list, enb_s1u_teid, sgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, context_self()->parameter.prefer_ipv4); d_assert(enb, return,); + + rv = gtp_client(enb); + d_assert(rv == CORE_OK, return,); } /* Setup GTP Node */ SETUP_GTP_NODE(s1u_tunnel, enb); @@ -629,12 +642,15 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request( enb = gtp_find_node(&sgw_self()->enb_s1u_list, req_teid); if (!enb) { - enb = gtp_connect_to_node(&sgw_self()->enb_s1u_list, req_teid, + enb = gtp_add_node_with_teid(&sgw_self()->enb_s1u_list, req_teid, sgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, context_self()->parameter.prefer_ipv4); d_assert(enb, return,); + + rv = gtp_client(enb); + d_assert(rv == CORE_OK, return,); } /* Setup GTP Node */ SETUP_GTP_NODE(tunnel, enb); @@ -663,12 +679,16 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request( enb = gtp_find_node(&sgw_self()->enb_s1u_list, req_teid); if (!enb) { - enb = gtp_connect_to_node(&sgw_self()->enb_s1u_list, req_teid, + enb = gtp_add_node_with_teid( + &sgw_self()->enb_s1u_list, req_teid, sgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, context_self()->parameter.prefer_ipv4); d_assert(enb, return,); + + rv = gtp_client(enb); + d_assert(rv == CORE_OK, return,); } /* Setup GTP Node */ SETUP_GTP_NODE(tunnel, enb); diff --git a/src/sgw/sgw_s5c_handler.c b/src/sgw/sgw_s5c_handler.c index 0ded877e05..e870c2eb3d 100644 --- a/src/sgw/sgw_s5c_handler.c +++ b/src/sgw/sgw_s5c_handler.c @@ -87,12 +87,15 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact, pgw = gtp_find_node(&sgw_self()->pgw_s5u_list, pgw_s5u_teid); if (!pgw) { - pgw = gtp_connect_to_node(&sgw_self()->pgw_s5u_list, pgw_s5u_teid, + pgw = gtp_add_node_with_teid(&sgw_self()->pgw_s5u_list, pgw_s5u_teid, sgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, context_self()->parameter.prefer_ipv4); d_assert(pgw, return,); + + rv = gtp_client(pgw); + d_assert(rv == CORE_OK, return,); } /* Setup GTP Node */ SETUP_GTP_NODE(s5u_tunnel, pgw); @@ -265,12 +268,15 @@ void sgw_s5c_handle_create_bearer_request(gtp_xact_t *s5c_xact, pgw = gtp_find_node(&sgw_self()->pgw_s5u_list, pgw_s5u_teid); if (!pgw) { - pgw = gtp_connect_to_node(&sgw_self()->pgw_s5u_list, pgw_s5u_teid, + pgw = gtp_add_node_with_teid(&sgw_self()->pgw_s5u_list, pgw_s5u_teid, sgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, context_self()->parameter.prefer_ipv4); d_assert(pgw, return,); + + rv = gtp_client(pgw); + d_assert(rv == CORE_OK, return,); } /* Setup GTP Node */ SETUP_GTP_NODE(s5u_tunnel, pgw); diff --git a/test/rx/pcscf_fd_path.c b/test/rx/pcscf_fd_path.c index fafff531eb..6a632186a9 100644 --- a/test/rx/pcscf_fd_path.c +++ b/test/rx/pcscf_fd_path.c @@ -3,6 +3,8 @@ #include "core_debug.h" #include "core_pool.h" #include "core_lib.h" +#include "core_network.h" +#include "3gpp_types.h" #include "gtp/gtp_xact.h" @@ -30,8 +32,10 @@ void pcscf_rx_sess_cleanup( pool_free_node(&pcscf_rx_sess_pool, sess_data); } -void pcscf_rx_send_aar() +void pcscf_rx_send_aar(const char *ip) { + status_t rv; + struct msg *req = NULL; struct avp *avp; #if 0 @@ -43,7 +47,12 @@ void pcscf_rx_send_aar() struct sess_state *mi = NULL, *svg; struct session *session = NULL; - c_uint32_t addr = 0x0100007f; + paa_t paa; + ipsubnet_t ipsub; + + d_assert(ip, return,); + rv = core_ipsubnet(&ipsub, ip, NULL); + d_assert(rv == CORE_OK, return,); /* Create the random value to store with the session */ pool_alloc_node(&pcscf_rx_sess_pool, &mi); @@ -100,14 +109,34 @@ void pcscf_rx_send_aar() CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out ); - /* Set Framed-IP-Address */ - CHECK_FCT_DO( fd_msg_avp_new(rx_framed_ip_address, 0, &avp), - goto out ); - val.os.data = (c_uint8_t*)&addr; - val.os.len = 4; - CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out ); - CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), - goto out ); + if (ipsub.family == AF_INET) + { + /* Set Framed-IP-Address */ + CHECK_FCT_DO( fd_msg_avp_new(rx_framed_ip_address, 0, &avp), + goto out ); + val.os.data = (c_uint8_t*)ipsub.sub; + val.os.len = IPV4_LEN; + CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out ); + CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), + goto out ); + } + else if (ipsub.family == AF_INET6) + { + /* Set Framed-IPv6-Prefix */ + CHECK_FCT_DO( fd_msg_avp_new(rx_framed_ipv6_prefix, 0, &avp), + goto out ); + memset(&paa, 0, sizeof(paa_t)); + + memcpy(paa.addr6, ipsub.sub, IPV6_LEN); + paa.pdn_type = 0x03; +#define FRAMED_IPV6_PREFIX_LENGTH 128 /* from spec document */ + paa.len = FRAMED_IPV6_PREFIX_LENGTH; + val.os.data = (c_uint8_t*)&paa; + val.os.len = PAA_IPV6_LEN; + CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out ); + CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), + goto out ); + } CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &mi->ts), goto out ); diff --git a/test/rx/pcscf_fd_path.h b/test/rx/pcscf_fd_path.h index cafd1f1ccd..e12c747ab6 100644 --- a/test/rx/pcscf_fd_path.h +++ b/test/rx/pcscf_fd_path.h @@ -10,7 +10,7 @@ extern "C" { CORE_DECLARE(int) pcscf_fd_init(void); CORE_DECLARE(void) pcscf_fd_final(void); -CORE_DECLARE(void) pcscf_rx_send_aar(); +CORE_DECLARE(void) pcscf_rx_send_aar(const char *ip); #ifdef __cplusplus } diff --git a/test/rx/volte_test.c b/test/rx/volte_test.c index 6e38330402..247950fb90 100644 --- a/test/rx/volte_test.c +++ b/test/rx/volte_test.c @@ -271,7 +271,7 @@ static void volte_test1(abts_case *tc, void *data) core_sleep(time_from_msec(300)); /* Send AA-Request */ - pcscf_rx_send_aar(); + pcscf_rx_send_aar("45.45.0.2"); /* Send PDN disconnectivity request */ rv = tests1ap_build_pdn_disconnectivity_request(&sendbuf, msgindex); @@ -312,6 +312,8 @@ static void volte_test1(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, CORE_OK, rv); pkbuf_free(recvbuf); + core_sleep(time_from_msec(1000)); + /********** Remove Subscriber in Database */ doc = BCON_NEW("imsi", BCON_UTF8("001010123456819")); ABTS_PTR_NOTNULL(tc, doc);