forked from acouzens/open5gs
Implement downlink data notfication(Not tested yet)
This commit is contained in:
parent
faa05ed5e1
commit
55c3d5e92e
|
@ -785,3 +785,27 @@ void emm_handle_service_request(
|
|||
d_assert(emm_send_to_enb(enb_ue, s1apbuf) == CORE_OK,, "s1ap send error");
|
||||
}
|
||||
|
||||
void emm_handle_downlink_data_notification(mme_bearer_t *bearer)
|
||||
{
|
||||
status_t rv;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
mme_sess_t *sess;
|
||||
pkbuf_t *s11buf = NULL;
|
||||
|
||||
d_assert(bearer, return, "Null param");
|
||||
mme_ue = bearer->mme_ue;
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
|
||||
sess = mme_sess_find_by_ebi(mme_ue, bearer->ebi);
|
||||
d_assert(sess, return, "Null param");
|
||||
|
||||
/* Build Downlink data notification ack */
|
||||
rv = mme_s11_build_downlink_data_notification_ack(&s11buf, sess);
|
||||
d_assert(rv == CORE_OK, return, "S11 build error");
|
||||
|
||||
rv = mme_s11_send_to_sgw(bearer->sgw,
|
||||
GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE, sess->sgw_s11_teid,
|
||||
s11buf);
|
||||
|
||||
/* FIXME : Send s1 paging */
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ CORE_DECLARE(void) emm_handle_delete_session_request(mme_ue_t *mme_ue);
|
|||
CORE_DECLARE(void) emm_handle_delete_session_response(mme_bearer_t *bearer);
|
||||
CORE_DECLARE(void) emm_handle_service_request(
|
||||
mme_ue_t *mme_ue, nas_service_request_t *service_request);
|
||||
CORE_DECLARE(void) emm_handle_downlink_data_notification(mme_bearer_t *bearer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -59,6 +59,8 @@ void emm_state_operational(fsm_t *s, event_t *e)
|
|||
break;
|
||||
case GTP_DELETE_SESSION_RESPONSE_TYPE:
|
||||
emm_handle_delete_session_response(bearer);
|
||||
case GTP_DOWNLINK_DATA_NOTIFICATION_TYPE:
|
||||
emm_handle_downlink_data_notification(bearer);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -250,3 +250,34 @@ status_t mme_s11_build_release_access_bearers_request(pkbuf_t **pkbuf)
|
|||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t mme_s11_build_downlink_data_notification_ack(pkbuf_t **pkbuf,
|
||||
mme_sess_t *sess)
|
||||
{
|
||||
status_t rv;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
gtp_message_t gtp_message;
|
||||
gtp_downlink_data_notification_acknowledge_t *ack =
|
||||
>p_message.downlink_data_notification_acknowledge;
|
||||
|
||||
gtp_cause_t cause;
|
||||
|
||||
d_assert(sess, return CORE_ERROR, "Null param");
|
||||
mme_ue = sess->mme_ue;
|
||||
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
||||
|
||||
memset(>p_message, 0, sizeof(gtp_message_t));
|
||||
|
||||
memset(&cause, 0, sizeof(cause));
|
||||
cause.value = GTP_CAUSE_REQUEST_ACCEPTED;
|
||||
|
||||
ack->cause.presence = 1;
|
||||
ack->cause.data = &cause;
|
||||
ack->cause.len = sizeof(cause);
|
||||
|
||||
rv = gtp_build_msg(pkbuf, GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE,
|
||||
>p_message);
|
||||
d_assert(rv == CORE_OK, return CORE_ERROR, "gtp build failed");
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@ CORE_DECLARE(status_t) mme_s11_build_delete_session_request(
|
|||
pkbuf_t **pkbuf, mme_sess_t *sess);
|
||||
CORE_DECLARE(status_t) mme_s11_build_release_access_bearers_request(
|
||||
pkbuf_t **pkbuf);
|
||||
|
||||
CORE_DECLARE(status_t) mme_s11_build_downlink_data_notification_ack(
|
||||
pkbuf_t **pkbuf, mme_sess_t *sess);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -158,3 +158,24 @@ void mme_s11_handle_release_access_bearers_response(
|
|||
event_set_param3(&e, (c_uintptr_t)GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE);
|
||||
mme_event_send(&e);
|
||||
}
|
||||
|
||||
void mme_s11_handle_downlink_data_notification(
|
||||
mme_sess_t *sess, gtp_downlink_data_notification_t *noti)
|
||||
{
|
||||
event_t e;
|
||||
mme_bearer_t *bearer = NULL;
|
||||
|
||||
d_assert(sess, return, "Null param");
|
||||
d_assert(noti, return, "Null param");
|
||||
|
||||
d_trace(3, "[GTP] Downlink Data Notification : "
|
||||
"MME[%d] <-- SGW[%d]\n", sess->mme_s11_teid, sess->sgw_s11_teid);
|
||||
|
||||
bearer = mme_bearer_find_by_sess_ebi(sess, noti->eps_bearer_id.u8);
|
||||
d_assert(bearer, return, "No ESM Context");
|
||||
|
||||
event_set(&e, MME_EVT_EMM_BEARER_FROM_S11);
|
||||
event_set_param1(&e, (c_uintptr_t)bearer->index);
|
||||
event_set_param2(&e, (c_uintptr_t)GTP_DOWNLINK_DATA_NOTIFICATION_TYPE);
|
||||
mme_event_send(&e);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ CORE_DECLARE(void) mme_s11_handle_delete_session_response(
|
|||
mme_sess_t *sess, gtp_delete_session_response_t *rsp);
|
||||
CORE_DECLARE(void) mme_s11_handle_release_access_bearers_response(
|
||||
mme_sess_t *sess, gtp_release_access_bearers_response_t *rsp);
|
||||
CORE_DECLARE(void) mme_s11_handle_downlink_data_notification(
|
||||
mme_sess_t *sess, gtp_downlink_data_notification_t *noti);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -326,6 +326,11 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||
mme_s11_handle_release_access_bearers_response(
|
||||
sess, >p_message.release_access_bearers_response);
|
||||
break;
|
||||
|
||||
case GTP_DOWNLINK_DATA_NOTIFICATION_TYPE:
|
||||
mme_s11_handle_downlink_data_notification(
|
||||
sess, >p_message.downlink_data_notification);
|
||||
break;
|
||||
default:
|
||||
d_warn("Not implmeneted(type:%d)", type);
|
||||
break;
|
||||
|
|
|
@ -86,9 +86,19 @@ typedef struct _sgw_bearer_t {
|
|||
c_uint32_t pgw_s5u_teid;
|
||||
c_uint32_t pgw_s5u_addr;
|
||||
|
||||
c_uint32_t state;
|
||||
|
||||
sgw_sess_t *sess;
|
||||
} sgw_bearer_t;
|
||||
|
||||
#define SGW_DL_NOTI_SENT 0x0001
|
||||
|
||||
#define CHECK_DL_NOTI_SENT(bearer) ((bearer)->state & SGW_DL_NOTI_SENT)
|
||||
#define SET_DL_NOTI_SETNT(bearer) \
|
||||
do { \
|
||||
(bearer)->state |= SGW_DL_NOTI_SENT;\
|
||||
} while (0)
|
||||
|
||||
CORE_DECLARE(status_t) sgw_context_init(void);
|
||||
CORE_DECLARE(status_t) sgw_context_final(void);
|
||||
CORE_DECLARE(sgw_context_t*) sgw_self(void);
|
||||
|
@ -116,6 +126,7 @@ CORE_DECLARE(sgw_bearer_t*) sgw_bearer_find_by_id(
|
|||
CORE_DECLARE(sgw_bearer_t*) sgw_default_bearer_in_sess(sgw_sess_t *sess);
|
||||
CORE_DECLARE(sgw_bearer_t*) sgw_bearer_first(sgw_sess_t *sess);
|
||||
CORE_DECLARE(sgw_bearer_t*) sgw_bearer_next(sgw_bearer_t *bearer);
|
||||
CORE_DECLARE(sgw_bearer_t*) sgw_bearer_find(index_t index);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -15,6 +15,8 @@ typedef enum {
|
|||
|
||||
SGW_EVT_TRANSACTION_T3,
|
||||
|
||||
SGW_EVT_LO_DLDATA_NOTI,
|
||||
|
||||
SGW_EVT_TOP,
|
||||
|
||||
} event_e;
|
||||
|
|
|
@ -319,12 +319,25 @@ void sgw_handle_release_access_bearers_request(gtp_xact_t *xact,
|
|||
gtp_release_access_bearers_response_t *rsp = NULL;
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
gtp_message_t gtp_message;
|
||||
sgw_bearer_t *bearer = NULL, *next_bearer = NULL;
|
||||
|
||||
gtp_cause_t cause;
|
||||
|
||||
d_assert(sess, return, "Null param");
|
||||
d_assert(xact, return, "Null param");
|
||||
|
||||
/* Release S1U(DL) path */
|
||||
bearer = list_first(&sess->bearer_list);
|
||||
while (bearer)
|
||||
{
|
||||
next_bearer = list_next(bearer);
|
||||
|
||||
bearer->enb_s1u_teid = 0;
|
||||
bearer->enb_s1u_addr = 0;
|
||||
|
||||
bearer = next_bearer;
|
||||
}
|
||||
|
||||
rsp = >p_message.release_access_bearers_response;
|
||||
memset(>p_message, 0, sizeof(gtp_message_t));
|
||||
|
||||
|
@ -347,3 +360,50 @@ void sgw_handle_release_access_bearers_request(gtp_xact_t *xact,
|
|||
d_trace(3, "[GTP] Release Access Bearers Reqeust : "
|
||||
"MME[%d] --> SGW[%d]\n", sess->mme_s11_teid, sess->sgw_s11_teid);
|
||||
}
|
||||
|
||||
void sgw_handle_lo_dldata_notification(sgw_bearer_t *bearer)
|
||||
{
|
||||
status_t rv;
|
||||
gtp_downlink_data_notification_t *noti = NULL;
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
gtp_message_t gtp_message;
|
||||
sgw_sess_t *sess = NULL;
|
||||
gtp_xact_t *xact = NULL;
|
||||
/* FIXME : ARP should be retrieved from ? */
|
||||
c_uint8_t arp = 0x61;
|
||||
|
||||
d_assert(bearer, return, "Null param");
|
||||
|
||||
sess = bearer->sess;
|
||||
d_assert(sess, return, "Null param");
|
||||
|
||||
|
||||
/* Build downlink notification message */
|
||||
noti = >p_message.downlink_data_notification;
|
||||
memset(>p_message, 0, sizeof(gtp_message_t));
|
||||
|
||||
noti->eps_bearer_id.presence = 1;
|
||||
noti->eps_bearer_id.u8 = bearer->id;
|
||||
|
||||
/* FIXME : ARP should be retrieved from ? */
|
||||
noti->allocation_retention_priority.presence = 1;
|
||||
noti->allocation_retention_priority.data = &arp;
|
||||
noti->allocation_retention_priority.len = sizeof(arp);
|
||||
|
||||
|
||||
rv = gtp_build_msg(&pkbuf,
|
||||
GTP_DOWNLINK_DATA_NOTIFICATION_TYPE, >p_message);
|
||||
d_assert(rv == CORE_OK, return, "gtp build failed");
|
||||
|
||||
xact = gtp_xact_local_create(&sgw_self()->gtp_xact_ctx,
|
||||
sgw_self()->s11_sock, &sgw_self()->s11_node);
|
||||
d_assert(xact, return , "Null param");
|
||||
|
||||
d_assert(sgw_s11_send_to_mme(xact,
|
||||
GTP_DOWNLINK_DATA_NOTIFICATION_TYPE,
|
||||
sess->mme_s11_teid, pkbuf) == CORE_OK, return,
|
||||
"failed to send message");
|
||||
|
||||
d_trace(3, "[GTP] Downlink Data Notification : "
|
||||
"SGW[%d] --> MME[%d]\n", sess->sgw_s11_teid, sess->mme_s11_teid);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ CORE_DECLARE(void) sgw_handle_delete_session_response(gtp_xact_t *xact,
|
|||
CORE_DECLARE(void) sgw_handle_release_access_bearers_request(gtp_xact_t *xact,
|
||||
sgw_sess_t *sess, gtp_release_access_bearers_request_t *req);
|
||||
|
||||
CORE_DECLARE(void) sgw_handle_lo_dldata_notification(sgw_bearer_t *bearer);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -108,13 +108,41 @@ static int _gtpv1_s5u_recv_cb(net_sock_t *sock, void *data)
|
|||
bearer = sgw_bearer_find_by_sgw_s5u_teid(teid);
|
||||
if (bearer)
|
||||
{
|
||||
/* Convert Teid and send to enodeB via s1u */
|
||||
gtp_h->teid = htonl(bearer->enb_s1u_teid);
|
||||
|
||||
gnode.addr = bearer->enb_s1u_addr;
|
||||
gnode.port = GTPV1_U_UDP_PORT;
|
||||
if (bearer->enb_s1u_teid)
|
||||
{
|
||||
/* Convert Teid and send to enodeB via s1u */
|
||||
gtp_h->teid = htonl(bearer->enb_s1u_teid);
|
||||
|
||||
gnode.addr = bearer->enb_s1u_addr;
|
||||
gnode.port = GTPV1_U_UDP_PORT;
|
||||
|
||||
gtp_send(sgw_self()->s1u_sock, &gnode, pkbuf);
|
||||
gtp_send(sgw_self()->s1u_sock, &gnode, pkbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* S1U path is deactivated.
|
||||
* Send downlink_data_notification to MME.
|
||||
* FIXME : Data buffering required
|
||||
*
|
||||
*/
|
||||
if (CHECK_DL_NOTI_SENT(bearer))
|
||||
{
|
||||
event_t e;
|
||||
status_t rv;
|
||||
|
||||
event_set(&e, SGW_EVT_S5C_SESSION_MSG);
|
||||
event_set_param1(&e, (c_uintptr_t)bearer->index);
|
||||
rv = sgw_event_send(&e);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("sgw_event_send error");
|
||||
pkbuf_free(pkbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SET_DL_NOTI_SETNT(bearer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -122,6 +122,21 @@ void sgw_state_operational(fsm_t *s, event_t *e)
|
|||
gtp_xact_timeout(event_get_param1(e));
|
||||
break;
|
||||
}
|
||||
case SGW_EVT_LO_DLDATA_NOTI:
|
||||
{
|
||||
index_t index = (index_t)event_get_param1(e);
|
||||
sgw_bearer_t* bearer = sgw_bearer_find(index);
|
||||
|
||||
if (!bearer)
|
||||
{
|
||||
d_error("Can not find bearer with index(%d)",index);
|
||||
break;
|
||||
}
|
||||
|
||||
sgw_handle_lo_dldata_notification(bearer);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_error("No handler for event %s", sgw_event_get_name(e));
|
||||
|
|
Loading…
Reference in New Issue