Merge branch 'master' of https://github.com/acetcom/cellwire
This commit is contained in:
commit
81a957172b
|
@ -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;
|
||||
|
|
|
@ -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,);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue