This commit is contained in:
James Park 2018-01-09 18:09:08 -08:00
commit 81a957172b
27 changed files with 586 additions and 147 deletions

View File

@ -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;

View File

@ -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,);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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(&gtpc_array) == YAML_SEQUENCE_NODE);

View File

@ -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 */

View File

@ -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;
}

View File

@ -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);
}
}
}
}

View File

@ -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;
}

View File

@ -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
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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 */

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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 );

View File

@ -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
}

View File

@ -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);