forked from acouzens/open5gs
fix: UPF is not working with Landslide (#685)
* Flow-Description use 'to assigned' in Gx Interface * Support SDF Filter ID * Support F-TEID's Choose * BAR(Buffering) is added in PFCP session * Default Apply Action uses NOCP|BUFF
This commit is contained in:
parent
b2d012c253
commit
33edd12335
|
@ -98,26 +98,26 @@ logger:
|
|||
# o Specific DNN/APN(e.g 'ims') uses 10.46.0.1/16, cafe:2::1/64
|
||||
# pdn:
|
||||
# - addr: 10.45.0.1/16
|
||||
# apn: internet
|
||||
# dnn: internet
|
||||
# - addr: cafe:1::1/64
|
||||
# apn: internet
|
||||
# dnn: internet
|
||||
# - addr: 10.46.0.1/16
|
||||
# apn: ims
|
||||
# dnn: ims
|
||||
# - addr: cafe:2::1/64
|
||||
# apn: ims
|
||||
# dnn: ims
|
||||
#
|
||||
# o Multiple Devices (default: ogstun)
|
||||
# pdn:
|
||||
# - addr: 10.45.0.1/16
|
||||
# apn: internet
|
||||
# dnn: internet
|
||||
# - addr: cafe:1::1/64
|
||||
# apn: internet
|
||||
# dnn: internet
|
||||
# dev: ogstun2
|
||||
# - addr: 10.46.0.1/16
|
||||
# apn: ims
|
||||
# dnn: ims
|
||||
# dev: ogstun3
|
||||
# - addr: cafe:2::1/64
|
||||
# apn: ims
|
||||
# dnn: ims
|
||||
# dev: ogstun3
|
||||
#
|
||||
# o Pool Range Sample
|
||||
|
@ -261,7 +261,7 @@ nrf:
|
|||
# - addr: 127.0.0.7
|
||||
# dnn: ims
|
||||
# - addr: 127.0.0.12
|
||||
# apn: [internet, web]
|
||||
# dnn: [internet, web]
|
||||
#
|
||||
# o UPF selection by CellID(e_cell_id: 28bit, nr_cell_id: 36bit)
|
||||
# (either single enb_id or multiple enb_ids, HEX representation)
|
||||
|
|
|
@ -107,13 +107,13 @@ logger:
|
|||
#
|
||||
# pdn:
|
||||
# - addr: 10.45.0.1/16
|
||||
# apn: internet
|
||||
# dnn: internet
|
||||
# - addr: cafe:1::1/64
|
||||
# apn: internet
|
||||
# dnn: internet
|
||||
# - addr: 10.46.0.1/16
|
||||
# apn: ims
|
||||
# dnn: ims
|
||||
# - addr: cafe:2::1/64
|
||||
# apn: ims
|
||||
# dnn: ims
|
||||
#
|
||||
# o Multiple Devices (default: ogstun)
|
||||
# $ sudo ip addr add 10.45.0.1/16 dev ogstun
|
||||
|
@ -123,15 +123,15 @@ logger:
|
|||
#
|
||||
# pdn:
|
||||
# - addr: 10.45.0.1/16
|
||||
# apn: internet
|
||||
# dnn: internet
|
||||
# - addr: cafe:1::1/64
|
||||
# apn: internet
|
||||
# dnn: internet
|
||||
# dev: ogstun2
|
||||
# - addr: 10.46.0.1/16
|
||||
# apn: ims
|
||||
# dnn: ims
|
||||
# dev: ogstun3
|
||||
# - addr: cafe:2::1/64
|
||||
# apn: ims
|
||||
# dnn: ims
|
||||
# dev: ogstun3
|
||||
#
|
||||
# o Pool Range Sample
|
||||
|
|
|
@ -57,7 +57,8 @@ extern "C" {
|
|||
|
||||
#define OGS_MAX_NUM_OF_CELL_ID 16
|
||||
#define OGS_MAX_NUM_OF_ENB_ID 16
|
||||
#define OGS_MAX_NUM_OF_APN 16
|
||||
#define OGS_MAX_NUM_OF_DNN 16
|
||||
#define OGS_MAX_NUM_OF_APN OGS_MAX_NUM_OF_DNN
|
||||
#define OGS_MAX_NUM_OF_HOSTNAME 16
|
||||
#define OGS_MAX_DNN_LEN 100
|
||||
#define OGS_MAX_APN_LEN OGS_MAX_DNN_LEN
|
||||
|
|
|
@ -36,10 +36,9 @@ void compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, void *tstate);
|
|||
|
||||
int ogs_ipfw_compile_rule(ogs_ipfw_rule_t *ipfw_rule, char *flow_description)
|
||||
{
|
||||
ogs_ipfw_rule_t zero_rule;
|
||||
char *token, *dir;
|
||||
char *saveptr;
|
||||
int i = 2;
|
||||
int i;
|
||||
|
||||
char *av[MAX_NUM_OF_TOKEN];
|
||||
uint32_t rulebuf[MAX_NUM_OF_RULE_BUFFER];
|
||||
|
@ -60,7 +59,6 @@ int ogs_ipfw_compile_rule(ogs_ipfw_rule_t *ipfw_rule, char *flow_description)
|
|||
av[0] = NULL;
|
||||
|
||||
/* ACTION */
|
||||
|
||||
description = ogs_strdup(flow_description);
|
||||
ogs_assert(description);
|
||||
|
||||
|
@ -81,6 +79,7 @@ int ogs_ipfw_compile_rule(ogs_ipfw_rule_t *ipfw_rule, char *flow_description)
|
|||
}
|
||||
|
||||
/* ADDR */
|
||||
i = 2;
|
||||
token = ogs_strtok_r(NULL, " ", &saveptr);
|
||||
while (token != NULL) {
|
||||
av[i++] = token;
|
||||
|
@ -92,6 +91,14 @@ int ogs_ipfw_compile_rule(ogs_ipfw_rule_t *ipfw_rule, char *flow_description)
|
|||
|
||||
av[i] = NULL;
|
||||
|
||||
/* "to assigned" --> "to any" */
|
||||
for (i = 2; av[i] != NULL; i++) {
|
||||
if (strcmp(av[i], "assigned") == 0 && strcmp(av[i-1], "to") == 0) {
|
||||
av[i] = "any";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
compile_rule(av, (uint32_t *)rule, &rbufsize, NULL);
|
||||
|
||||
memset(ipfw_rule, 0, sizeof(ogs_ipfw_rule_t));
|
||||
|
@ -156,13 +163,6 @@ int ogs_ipfw_compile_rule(ogs_ipfw_rule_t *ipfw_rule, char *flow_description)
|
|||
}
|
||||
}
|
||||
|
||||
memset(&zero_rule, 0, sizeof(ogs_ipfw_rule_t));
|
||||
if (memcmp(ipfw_rule, &zero_rule, sizeof(ogs_ipfw_rule_t)) == 0) {
|
||||
ogs_error("Cannot find Flow-Description");
|
||||
ogs_free(description);
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
ogs_free(description);
|
||||
return OGS_OK;
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ char *ogs_ipfw_encode_flow_description(ogs_ipfw_rule_t *ipfw_rule)
|
|||
ipfw_rule->ip.dst.mask[3]);
|
||||
return NULL;
|
||||
} else if (prefixlen == 0) {
|
||||
p = ogs_slprintf(p, last, " any");
|
||||
p = ogs_slprintf(p, last, " assigned");
|
||||
} else if (prefixlen > 0 && prefixlen < IPV4_BITLEN) {
|
||||
p = ogs_slprintf(p, last, " %s/%d", buf, prefixlen);
|
||||
} else if (prefixlen == IPV4_BITLEN) {
|
||||
|
@ -308,7 +308,7 @@ char *ogs_ipfw_encode_flow_description(ogs_ipfw_rule_t *ipfw_rule)
|
|||
ipfw_rule->ip.dst.mask[3]);
|
||||
return NULL;
|
||||
} else if (prefixlen == 0) {
|
||||
p = ogs_slprintf(p, last, " any");
|
||||
p = ogs_slprintf(p, last, " assigned");
|
||||
} else if (prefixlen > 0 && prefixlen < IPV6_BITLEN) {
|
||||
p = ogs_slprintf(p, last, " %s/%d", buf, prefixlen);
|
||||
} else if (prefixlen == IPV6_BITLEN) {
|
||||
|
@ -318,7 +318,7 @@ char *ogs_ipfw_encode_flow_description(ogs_ipfw_rule_t *ipfw_rule)
|
|||
ogs_assert_if_reached();
|
||||
}
|
||||
} else
|
||||
p = ogs_slprintf(p, last, " any");
|
||||
p = ogs_slprintf(p, last, " assigned");
|
||||
|
||||
if (ipfw_rule->port.dst.low == ipfw_rule->port.dst.high) {
|
||||
if (ipfw_rule->port.dst.low == 0) {
|
||||
|
|
|
@ -281,10 +281,10 @@ void ogs_pfcp_build_create_pdr(
|
|||
message->pdi.source_interface.presence = 1;
|
||||
message->pdi.source_interface.u8 = pdr->src_if;
|
||||
|
||||
if (pdr->apn) {
|
||||
if (pdr->dnn) {
|
||||
message->pdi.network_instance.presence = 1;
|
||||
message->pdi.network_instance.len = ogs_fqdn_build(
|
||||
pdrbuf[i].dnn, pdr->apn, strlen(pdr->apn));
|
||||
pdrbuf[i].dnn, pdr->dnn, strlen(pdr->dnn));
|
||||
message->pdi.network_instance.data = pdrbuf[i].dnn;
|
||||
}
|
||||
|
||||
|
@ -386,10 +386,10 @@ void ogs_pfcp_build_update_pdr(
|
|||
message->pdi.source_interface.presence = 1;
|
||||
message->pdi.source_interface.u8 = pdr->src_if;
|
||||
|
||||
if (pdr->apn) {
|
||||
if (pdr->dnn) {
|
||||
message->pdi.network_instance.presence = 1;
|
||||
message->pdi.network_instance.len = ogs_fqdn_build(
|
||||
pdrbuf[i].dnn, pdr->apn, strlen(pdr->apn));
|
||||
pdrbuf[i].dnn, pdr->dnn, strlen(pdr->dnn));
|
||||
message->pdi.network_instance.data = pdrbuf[i].dnn;
|
||||
}
|
||||
|
||||
|
@ -436,8 +436,12 @@ static struct {
|
|||
void ogs_pfcp_build_create_far(
|
||||
ogs_pfcp_tlv_create_far_t *message, int i, ogs_pfcp_far_t *far)
|
||||
{
|
||||
ogs_pfcp_sess_t *sess = NULL;
|
||||
|
||||
ogs_assert(message);
|
||||
ogs_assert(far);
|
||||
sess = far->sess;
|
||||
ogs_assert(sess);
|
||||
|
||||
message->presence = 1;
|
||||
message->far_id.presence = 1;
|
||||
|
@ -446,6 +450,7 @@ void ogs_pfcp_build_create_far(
|
|||
message->apply_action.presence = 1;
|
||||
message->apply_action.u8 = far->apply_action;
|
||||
|
||||
if (far->apply_action & OGS_PFCP_APPLY_ACTION_FORW) {
|
||||
message->forwarding_parameters.presence = 1;
|
||||
message->forwarding_parameters.destination_interface.presence = 1;
|
||||
message->forwarding_parameters.destination_interface.u8 =
|
||||
|
@ -463,13 +468,22 @@ void ogs_pfcp_build_create_far(
|
|||
message->forwarding_parameters.outer_header_creation.len =
|
||||
far->outer_header_creation_len;
|
||||
}
|
||||
} else if (far->apply_action & OGS_PFCP_APPLY_ACTION_BUFF) {
|
||||
ogs_assert(sess->bar);
|
||||
message->bar_id.presence = 1;
|
||||
message->bar_id.u8 = sess->bar->id;
|
||||
}
|
||||
}
|
||||
|
||||
void ogs_pfcp_build_update_far_deactivate(
|
||||
ogs_pfcp_tlv_update_far_t *message, int i, ogs_pfcp_far_t *far)
|
||||
{
|
||||
ogs_pfcp_sess_t *sess = NULL;
|
||||
|
||||
ogs_assert(message);
|
||||
ogs_assert(far);
|
||||
sess = far->sess;
|
||||
ogs_assert(sess);
|
||||
|
||||
message->presence = 1;
|
||||
message->far_id.presence = 1;
|
||||
|
@ -479,6 +493,10 @@ void ogs_pfcp_build_update_far_deactivate(
|
|||
OGS_PFCP_APPLY_ACTION_BUFF | OGS_PFCP_APPLY_ACTION_NOCP;
|
||||
message->apply_action.presence = 1;
|
||||
message->apply_action.u8 = far->apply_action;
|
||||
|
||||
ogs_assert(sess->bar);
|
||||
message->bar_id.presence = 1;
|
||||
message->bar_id.u8 = sess->bar->id;
|
||||
}
|
||||
|
||||
void ogs_pfcp_build_update_far_activate(
|
||||
|
@ -491,15 +509,17 @@ void ogs_pfcp_build_update_far_activate(
|
|||
message->far_id.presence = 1;
|
||||
message->far_id.u32 = far->id;
|
||||
|
||||
if (far->apply_action != OGS_PFCP_APPLY_ACTION_FORW) {
|
||||
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||
ogs_assert(far->apply_action == OGS_PFCP_APPLY_ACTION_FORW);
|
||||
|
||||
message->apply_action.presence = 1;
|
||||
message->apply_action.u8 = far->apply_action;
|
||||
}
|
||||
|
||||
message->update_forwarding_parameters.presence = 1;
|
||||
message->update_forwarding_parameters.destination_interface.presence = 1;
|
||||
message->update_forwarding_parameters.
|
||||
destination_interface.u8 = far->dst_if;
|
||||
|
||||
if (far->outer_header_creation_len || far->smreq_flags.value) {
|
||||
message->update_forwarding_parameters.presence = 1;
|
||||
|
||||
if (far->outer_header_creation_len) {
|
||||
memcpy(&farbuf[i].outer_header_creation,
|
||||
|
@ -596,6 +616,17 @@ void ogs_pfcp_build_create_urr(
|
|||
message->urr_id.u32 = urr->id;
|
||||
}
|
||||
|
||||
void ogs_pfcp_build_create_bar(
|
||||
ogs_pfcp_tlv_create_bar_t *message, ogs_pfcp_bar_t *bar)
|
||||
{
|
||||
ogs_assert(message);
|
||||
ogs_assert(bar);
|
||||
|
||||
message->presence = 1;
|
||||
message->bar_id.presence = 1;
|
||||
message->bar_id.u8 = bar->id;
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *ogs_pfcp_build_session_report_request(
|
||||
uint8_t type, ogs_pfcp_user_plane_report_t *report)
|
||||
{
|
||||
|
|
|
@ -60,6 +60,9 @@ void ogs_pfcp_build_update_qer(
|
|||
void ogs_pfcp_build_create_urr(
|
||||
ogs_pfcp_tlv_create_urr_t *message, int i, ogs_pfcp_urr_t *urr);
|
||||
|
||||
void ogs_pfcp_build_create_bar(
|
||||
ogs_pfcp_tlv_create_bar_t *message, ogs_pfcp_bar_t *bar);
|
||||
|
||||
ogs_pkbuf_t *ogs_pfcp_build_session_report_request(
|
||||
uint8_t type, ogs_pfcp_user_plane_report_t *report);
|
||||
ogs_pkbuf_t *ogs_pfcp_build_session_report_response(
|
||||
|
|
|
@ -245,7 +245,8 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote)
|
|||
}
|
||||
} else if (!strcmp(pfcp_key, "dev")) {
|
||||
dev = ogs_yaml_iter_value(&pfcp_iter);
|
||||
} else if (!strcmp(pfcp_key, "apn")) {
|
||||
} else if (!strcmp(pfcp_key, "apn") ||
|
||||
!strcmp(pfcp_key, "dnn")) {
|
||||
/* Skip */
|
||||
} else
|
||||
ogs_warn("unknown key `%s`", pfcp_key);
|
||||
|
@ -299,7 +300,7 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote)
|
|||
ogs_pfcp_subnet_t *subnet = NULL;
|
||||
const char *ipstr = NULL;
|
||||
const char *mask_or_numbits = NULL;
|
||||
const char *apn = NULL;
|
||||
const char *dnn = NULL;
|
||||
const char *dev = self.tun_ifname;
|
||||
const char *low[MAX_NUM_OF_SUBNET_RANGE];
|
||||
const char *high[MAX_NUM_OF_SUBNET_RANGE];
|
||||
|
@ -334,7 +335,7 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote)
|
|||
}
|
||||
} else if (!strcmp(pdn_key, "apn") ||
|
||||
!strcmp(pdn_key, "dnn")) {
|
||||
apn = ogs_yaml_iter_value(&pdn_iter);
|
||||
dnn = ogs_yaml_iter_value(&pdn_iter);
|
||||
} else if (!strcmp(pdn_key, "dev")) {
|
||||
dev = ogs_yaml_iter_value(&pdn_iter);
|
||||
} else if (!strcmp(pdn_key, "range")) {
|
||||
|
@ -375,7 +376,7 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote)
|
|||
}
|
||||
|
||||
subnet = ogs_pfcp_subnet_add(
|
||||
ipstr, mask_or_numbits, apn, dev);
|
||||
ipstr, mask_or_numbits, dnn, dev);
|
||||
ogs_assert(subnet);
|
||||
|
||||
subnet->num_of_range = num;
|
||||
|
@ -406,8 +407,8 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote)
|
|||
uint16_t port = self.pfcp_port;
|
||||
uint16_t tac[OGS_MAX_NUM_OF_TAI] = {0,};
|
||||
uint8_t num_of_tac = 0;
|
||||
const char *apn[OGS_MAX_NUM_OF_APN];
|
||||
uint8_t num_of_apn = 0;
|
||||
const char *dnn[OGS_MAX_NUM_OF_DNN];
|
||||
uint8_t num_of_dnn = 0;
|
||||
uint32_t e_cell_id[OGS_MAX_NUM_OF_CELL_ID] = {0,};
|
||||
uint8_t num_of_e_cell_id = 0;
|
||||
uint64_t nr_cell_id[OGS_MAX_NUM_OF_CELL_ID] = {0,};
|
||||
|
@ -497,29 +498,29 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote)
|
|||
YAML_SEQUENCE_NODE);
|
||||
} else if (!strcmp(pfcp_key, "apn") ||
|
||||
!strcmp(pfcp_key, "dnn")) {
|
||||
ogs_yaml_iter_t apn_iter;
|
||||
ogs_yaml_iter_recurse(&pfcp_iter, &apn_iter);
|
||||
ogs_assert(ogs_yaml_iter_type(&apn_iter) !=
|
||||
ogs_yaml_iter_t dnn_iter;
|
||||
ogs_yaml_iter_recurse(&pfcp_iter, &dnn_iter);
|
||||
ogs_assert(ogs_yaml_iter_type(&dnn_iter) !=
|
||||
YAML_MAPPING_NODE);
|
||||
|
||||
do {
|
||||
const char *v = NULL;
|
||||
|
||||
ogs_assert(num_of_apn <=
|
||||
OGS_MAX_NUM_OF_APN);
|
||||
if (ogs_yaml_iter_type(&apn_iter) ==
|
||||
ogs_assert(num_of_dnn <=
|
||||
OGS_MAX_NUM_OF_DNN);
|
||||
if (ogs_yaml_iter_type(&dnn_iter) ==
|
||||
YAML_SEQUENCE_NODE) {
|
||||
if (!ogs_yaml_iter_next(&apn_iter))
|
||||
if (!ogs_yaml_iter_next(&dnn_iter))
|
||||
break;
|
||||
}
|
||||
|
||||
v = ogs_yaml_iter_value(&apn_iter);
|
||||
v = ogs_yaml_iter_value(&dnn_iter);
|
||||
if (v) {
|
||||
apn[num_of_apn] = v;
|
||||
num_of_apn++;
|
||||
dnn[num_of_dnn] = v;
|
||||
num_of_dnn++;
|
||||
}
|
||||
} while (
|
||||
ogs_yaml_iter_type(&apn_iter) ==
|
||||
ogs_yaml_iter_type(&dnn_iter) ==
|
||||
YAML_SEQUENCE_NODE);
|
||||
} else if (!strcmp(pfcp_key, "e_cell_id")) {
|
||||
ogs_yaml_iter_t e_cell_id_iter;
|
||||
|
@ -606,9 +607,9 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote)
|
|||
if (num_of_tac != 0)
|
||||
memcpy(node->tac, tac, sizeof(node->tac));
|
||||
|
||||
node->num_of_apn = num_of_apn;
|
||||
if (num_of_apn != 0)
|
||||
memcpy(node->apn, apn, sizeof(node->apn));
|
||||
node->num_of_dnn = num_of_dnn;
|
||||
if (num_of_dnn != 0)
|
||||
memcpy(node->dnn, dnn, sizeof(node->dnn));
|
||||
|
||||
node->num_of_e_cell_id = num_of_e_cell_id;
|
||||
if (num_of_e_cell_id != 0)
|
||||
|
@ -743,7 +744,7 @@ ogs_pfcp_gtpu_resource_t *ogs_pfcp_gtpu_resource_add(ogs_list_t *list,
|
|||
}
|
||||
|
||||
ogs_pfcp_gtpu_resource_t *ogs_pfcp_gtpu_resource_find(ogs_list_t *list,
|
||||
char *apn, ogs_pfcp_interface_t source_interface)
|
||||
char *dnn, ogs_pfcp_interface_t source_interface)
|
||||
{
|
||||
ogs_pfcp_gtpu_resource_t *resource = NULL;
|
||||
|
||||
|
@ -754,8 +755,8 @@ ogs_pfcp_gtpu_resource_t *ogs_pfcp_gtpu_resource_find(ogs_list_t *list,
|
|||
|
||||
if (resource->info.assoni &&
|
||||
strlen(resource->info.network_instance) &&
|
||||
apn && strlen(apn) &&
|
||||
ogs_strcasecmp(apn, resource->info.network_instance) != 0) {
|
||||
dnn && strlen(dnn) &&
|
||||
ogs_strcasecmp(dnn, resource->info.network_instance) != 0) {
|
||||
match = false;
|
||||
}
|
||||
|
||||
|
@ -845,6 +846,8 @@ ogs_pfcp_pdr_t *ogs_pfcp_pdr_add(ogs_pfcp_sess_t *sess)
|
|||
pdr->id = *(pdr->id_node);
|
||||
ogs_assert(pdr->id > 0 && pdr->id <= OGS_MAX_NUM_OF_PDR);
|
||||
|
||||
pdr->src_if = OGS_PFCP_INTERFACE_UNKNOWN;
|
||||
|
||||
pdr->sess = sess;
|
||||
ogs_list_add(&sess->pdr_list, pdr);
|
||||
|
||||
|
@ -907,6 +910,20 @@ ogs_pfcp_pdr_t *ogs_pfcp_pdr_find_by_teid_and_qfi(uint32_t teid, uint8_t qfi)
|
|||
&hashkey, sizeof(hashkey));
|
||||
}
|
||||
|
||||
ogs_pfcp_pdr_t *ogs_pfcp_pdr_find_by_choose_id(
|
||||
ogs_pfcp_sess_t *sess, uint8_t choose_id)
|
||||
{
|
||||
ogs_pfcp_pdr_t *pdr = NULL;
|
||||
|
||||
ogs_assert(sess);
|
||||
|
||||
ogs_list_for_each(&sess->pdr_list, pdr)
|
||||
if (pdr->chid == true && pdr->choose_id == choose_id)
|
||||
return pdr;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ogs_pfcp_pdr_reorder_by_precedence(
|
||||
ogs_pfcp_pdr_t *pdr, ogs_pfcp_precedence_t precedence)
|
||||
{
|
||||
|
@ -990,7 +1007,7 @@ ogs_pfcp_far_t *ogs_pfcp_far_add(ogs_pfcp_sess_t *sess)
|
|||
far->id = *(far->id_node);
|
||||
ogs_assert(far->id > 0 && far->id <= OGS_MAX_NUM_OF_FAR);
|
||||
|
||||
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||
far->dst_if = OGS_PFCP_INTERFACE_UNKNOWN;
|
||||
|
||||
far->sess = sess;
|
||||
ogs_list_add(&sess->far_list, far);
|
||||
|
@ -1333,6 +1350,9 @@ ogs_pfcp_bar_t *ogs_pfcp_bar_new(ogs_pfcp_sess_t *sess)
|
|||
ogs_pool_alloc(&sess->bar_id_pool, &bar->id_node);
|
||||
ogs_assert(bar->id_node);
|
||||
|
||||
bar->id = *(bar->id_node);
|
||||
ogs_assert(bar->id > 0 && bar->id <= OGS_MAX_NUM_OF_BAR);
|
||||
|
||||
bar->sess = sess;
|
||||
sess->bar = bar;
|
||||
|
||||
|
@ -1347,13 +1367,13 @@ void ogs_pfcp_bar_delete(ogs_pfcp_bar_t *bar)
|
|||
sess = bar->sess;
|
||||
ogs_assert(sess);
|
||||
|
||||
bar->sess = NULL;
|
||||
sess->bar = NULL;
|
||||
|
||||
if (bar->id_node)
|
||||
ogs_pool_free(&bar->sess->bar_id_pool, bar->id_node);
|
||||
|
||||
ogs_pool_free(&ogs_pfcp_bar_pool, bar);
|
||||
|
||||
bar->sess = NULL;
|
||||
sess->bar = NULL;
|
||||
}
|
||||
|
||||
ogs_pfcp_rule_t *ogs_pfcp_rule_add(ogs_pfcp_pdr_t *pdr)
|
||||
|
@ -1372,6 +1392,24 @@ ogs_pfcp_rule_t *ogs_pfcp_rule_add(ogs_pfcp_pdr_t *pdr)
|
|||
return rule;
|
||||
}
|
||||
|
||||
ogs_pfcp_rule_t *ogs_pfcp_rule_find_by_sdf_filter_id(
|
||||
ogs_pfcp_sess_t *sess, uint32_t sdf_filter_id)
|
||||
{
|
||||
ogs_pfcp_pdr_t *pdr = NULL;
|
||||
ogs_pfcp_rule_t *rule = NULL;
|
||||
|
||||
ogs_assert(sess);
|
||||
|
||||
ogs_list_for_each(&sess->pdr_list, pdr) {
|
||||
ogs_list_for_each(&pdr->rule_list, rule) {
|
||||
if (rule->bid && rule->sdf_filter_id == sdf_filter_id)
|
||||
return rule;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ogs_pfcp_rule_remove(ogs_pfcp_rule_t *rule)
|
||||
{
|
||||
ogs_pfcp_pdr_t *pdr = NULL;
|
||||
|
@ -1490,7 +1528,7 @@ int ogs_pfcp_ue_pool_generate(void)
|
|||
}
|
||||
|
||||
ogs_pfcp_ue_ip_t *ogs_pfcp_ue_ip_alloc(
|
||||
int family, const char *apn, uint8_t *addr)
|
||||
int family, const char *dnn, uint8_t *addr)
|
||||
{
|
||||
ogs_pfcp_subnet_t *subnet = NULL;
|
||||
ogs_pfcp_ue_ip_t *ue_ip = NULL;
|
||||
|
@ -1498,22 +1536,6 @@ ogs_pfcp_ue_ip_t *ogs_pfcp_ue_ip_alloc(
|
|||
uint8_t zero[16];
|
||||
size_t maxbytes = 0;
|
||||
|
||||
ogs_assert(apn);
|
||||
subnet = ogs_pfcp_find_subnet(family, apn);
|
||||
if (subnet == NULL) {
|
||||
ogs_error("CHECK CONFIGURATION: Cannot find subnet [family:%d, apn:%s]",
|
||||
family, apn);
|
||||
ogs_error("smf");
|
||||
ogs_error(" pdn:");
|
||||
if (family == AF_INET)
|
||||
ogs_error(" - addr: 10.45.0.1/16");
|
||||
else if (family == AF_INET6)
|
||||
ogs_error(" - addr: cafe::1/64");
|
||||
|
||||
ogs_assert_if_reached();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(zero, 0, sizeof zero);
|
||||
if (family == AF_INET) {
|
||||
maxbytes = 4;
|
||||
|
@ -1524,7 +1546,26 @@ ogs_pfcp_ue_ip_t *ogs_pfcp_ue_ip_alloc(
|
|||
ogs_assert_if_reached();
|
||||
}
|
||||
|
||||
// if assigning a static IP, do so. If not, assign dynamically!
|
||||
if (dnn)
|
||||
subnet = ogs_pfcp_find_subnet_by_dnn(family, dnn);
|
||||
else
|
||||
subnet = ogs_pfcp_find_subnet(family);
|
||||
|
||||
if (subnet == NULL) {
|
||||
ogs_error("CHECK CONFIGURATION: Cannot find subnet [family:%d, dnn:%s]",
|
||||
family, dnn ? dnn : "No DNN");
|
||||
ogs_error("smf");
|
||||
ogs_error(" pdn:");
|
||||
if (family == AF_INET)
|
||||
ogs_error(" - addr: 10.45.0.1/16");
|
||||
else if (family == AF_INET6)
|
||||
ogs_error(" - addr: cafe::1/64");
|
||||
|
||||
ogs_assert_if_reached();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* if assigning a static IP, do so. If not, assign dynamically! */
|
||||
if (memcmp(addr, zero, maxbytes) != 0) {
|
||||
ue_ip = ogs_calloc(1, sizeof(ogs_pfcp_ue_ip_t));
|
||||
|
||||
|
@ -1608,7 +1649,7 @@ ogs_pfcp_dev_t *ogs_pfcp_dev_find_by_ifname(const char *ifname)
|
|||
|
||||
ogs_pfcp_subnet_t *ogs_pfcp_subnet_add(
|
||||
const char *ipstr, const char *mask_or_numbits,
|
||||
const char *apn, const char *ifname)
|
||||
const char *dnn, const char *ifname)
|
||||
{
|
||||
int rv;
|
||||
ogs_pfcp_dev_t *dev = NULL;
|
||||
|
@ -1639,8 +1680,8 @@ ogs_pfcp_subnet_t *ogs_pfcp_subnet_add(
|
|||
subnet->prefixlen = atoi(mask_or_numbits);
|
||||
}
|
||||
|
||||
if (apn)
|
||||
strcpy(subnet->apn, apn);
|
||||
if (dnn)
|
||||
strcpy(subnet->dnn, dnn);
|
||||
|
||||
ogs_pool_init(&subnet->pool, ogs_app()->pool.sess);
|
||||
|
||||
|
@ -1668,17 +1709,32 @@ void ogs_pfcp_subnet_remove_all(void)
|
|||
ogs_pfcp_subnet_remove(subnet);
|
||||
}
|
||||
|
||||
ogs_pfcp_subnet_t *ogs_pfcp_find_subnet(int family, const char *apn)
|
||||
ogs_pfcp_subnet_t *ogs_pfcp_find_subnet(int family)
|
||||
{
|
||||
ogs_pfcp_subnet_t *subnet = NULL;
|
||||
|
||||
ogs_assert(apn);
|
||||
ogs_assert(family == AF_INET || family == AF_INET6);
|
||||
|
||||
ogs_list_for_each(&self.subnet_list, subnet) {
|
||||
if ((subnet->family == AF_UNSPEC || subnet->family == family) &&
|
||||
(strlen(subnet->apn) == 0 ||
|
||||
(strlen(subnet->apn) && ogs_strcasecmp(subnet->apn, apn) == 0)))
|
||||
(strlen(subnet->dnn) == 0))
|
||||
break;
|
||||
}
|
||||
|
||||
return subnet;
|
||||
}
|
||||
|
||||
ogs_pfcp_subnet_t *ogs_pfcp_find_subnet_by_dnn(int family, const char *dnn)
|
||||
{
|
||||
ogs_pfcp_subnet_t *subnet = NULL;
|
||||
|
||||
ogs_assert(dnn);
|
||||
ogs_assert(family == AF_INET || family == AF_INET6);
|
||||
|
||||
ogs_list_for_each(&self.subnet_list, subnet) {
|
||||
if ((subnet->family == AF_UNSPEC || subnet->family == family) &&
|
||||
(strlen(subnet->dnn) == 0 ||
|
||||
(strlen(subnet->dnn) && ogs_strcasecmp(subnet->dnn, dnn) == 0)))
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,8 +88,8 @@ typedef struct ogs_pfcp_node_s {
|
|||
|
||||
uint16_t tac[OGS_MAX_NUM_OF_TAI];
|
||||
uint8_t num_of_tac;
|
||||
const char* apn[OGS_MAX_APN_LEN];
|
||||
uint8_t num_of_apn;
|
||||
const char* dnn[OGS_MAX_DNN_LEN];
|
||||
uint8_t num_of_dnn;
|
||||
uint32_t e_cell_id[OGS_MAX_NUM_OF_CELL_ID];
|
||||
uint8_t num_of_e_cell_id;
|
||||
uint64_t nr_cell_id[OGS_MAX_NUM_OF_CELL_ID];
|
||||
|
@ -138,6 +138,10 @@ typedef struct ogs_pfcp_pdr_s {
|
|||
|
||||
ogs_pfcp_f_teid_t f_teid;
|
||||
int f_teid_len;
|
||||
|
||||
bool chid;
|
||||
uint8_t choose_id;
|
||||
|
||||
ogs_pfcp_outer_header_removal_t outer_header_removal;
|
||||
int outer_header_removal_len;
|
||||
|
||||
|
@ -255,7 +259,7 @@ typedef struct ogs_pfcp_subnet_s {
|
|||
|
||||
ogs_ipsubnet_t sub; /* Subnet : cafe::0/64 */
|
||||
ogs_ipsubnet_t gw; /* Gateway : cafe::1 */
|
||||
char apn[OGS_MAX_APN_LEN]; /* APN : "internet", "volte", .. */
|
||||
char dnn[OGS_MAX_DNN_LEN]; /* DNN : "internet", "volte", .. */
|
||||
|
||||
#define MAX_NUM_OF_SUBNET_RANGE 16
|
||||
struct {
|
||||
|
@ -274,7 +278,20 @@ typedef struct ogs_pfcp_subnet_s {
|
|||
typedef struct ogs_pfcp_rule_s {
|
||||
ogs_lnode_t lnode;
|
||||
|
||||
union {
|
||||
struct {
|
||||
ED6(uint8_t spare1:3;,
|
||||
uint8_t bid:1;,
|
||||
uint8_t fl:1;,
|
||||
uint8_t spi:1;,
|
||||
uint8_t ttc:1;,
|
||||
uint8_t fd:1;)
|
||||
};
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
ogs_ipfw_rule_t ipfw;
|
||||
uint32_t sdf_filter_id;
|
||||
|
||||
/* Related Context */
|
||||
ogs_pfcp_pdr_t *pdr;
|
||||
|
@ -298,7 +315,7 @@ void ogs_pfcp_node_remove_all(ogs_list_t *list);
|
|||
ogs_pfcp_gtpu_resource_t *ogs_pfcp_gtpu_resource_add(ogs_list_t *list,
|
||||
ogs_pfcp_user_plane_ip_resource_info_t *info);
|
||||
ogs_pfcp_gtpu_resource_t *ogs_pfcp_gtpu_resource_find(ogs_list_t *list,
|
||||
char *apn, ogs_pfcp_interface_t source_interface);
|
||||
char *dnn, ogs_pfcp_interface_t source_interface);
|
||||
void ogs_pfcp_gtpu_resource_remove(ogs_list_t *list,
|
||||
ogs_pfcp_gtpu_resource_t *resource);
|
||||
void ogs_pfcp_gtpu_resource_remove_all(ogs_list_t *list);
|
||||
|
@ -320,6 +337,9 @@ ogs_pfcp_pdr_t *ogs_pfcp_pdr_find_or_add(
|
|||
void ogs_pfcp_pdr_hash_set(ogs_pfcp_pdr_t *pdr);
|
||||
ogs_pfcp_pdr_t *ogs_pfcp_pdr_find_by_teid_and_qfi(uint32_t teid, uint8_t qfi);
|
||||
|
||||
ogs_pfcp_pdr_t *ogs_pfcp_pdr_find_by_choose_id(
|
||||
ogs_pfcp_sess_t *sess, uint8_t choose_id);
|
||||
|
||||
void ogs_pfcp_pdr_reorder_by_precedence(
|
||||
ogs_pfcp_pdr_t *pdr, ogs_pfcp_precedence_t precedence);
|
||||
void ogs_pfcp_pdr_associate_far(ogs_pfcp_pdr_t *pdr, ogs_pfcp_far_t *far);
|
||||
|
@ -360,12 +380,14 @@ ogs_pfcp_bar_t *ogs_pfcp_bar_new(ogs_pfcp_sess_t *sess);
|
|||
void ogs_pfcp_bar_delete(ogs_pfcp_bar_t *bar);
|
||||
|
||||
ogs_pfcp_rule_t *ogs_pfcp_rule_add(ogs_pfcp_pdr_t *pdr);
|
||||
ogs_pfcp_rule_t *ogs_pfcp_rule_find_by_sdf_filter_id(
|
||||
ogs_pfcp_sess_t *sess, uint32_t sdf_filter_id);
|
||||
void ogs_pfcp_rule_remove(ogs_pfcp_rule_t *rule);
|
||||
void ogs_pfcp_rule_remove_all(ogs_pfcp_pdr_t *pdr);
|
||||
|
||||
int ogs_pfcp_ue_pool_generate(void);
|
||||
ogs_pfcp_ue_ip_t *ogs_pfcp_ue_ip_alloc(
|
||||
int family, const char *apn, uint8_t *addr);
|
||||
int family, const char *dnn, uint8_t *addr);
|
||||
void ogs_pfcp_ue_ip_free(ogs_pfcp_ue_ip_t *ip);
|
||||
|
||||
ogs_pfcp_dev_t *ogs_pfcp_dev_add(const char *ifname);
|
||||
|
@ -375,11 +397,12 @@ ogs_pfcp_dev_t *ogs_pfcp_dev_find_by_ifname(const char *ifname);
|
|||
|
||||
ogs_pfcp_subnet_t *ogs_pfcp_subnet_add(
|
||||
const char *ipstr, const char *mask_or_numbits,
|
||||
const char *apn, const char *ifname);
|
||||
const char *dnn, const char *ifname);
|
||||
ogs_pfcp_subnet_t *ogs_pfcp_subnet_next(ogs_pfcp_subnet_t *subnet);
|
||||
void ogs_pfcp_subnet_remove(ogs_pfcp_subnet_t *subnet);
|
||||
void ogs_pfcp_subnet_remove_all(void);
|
||||
ogs_pfcp_subnet_t *ogs_pfcp_find_subnet(int family, const char *apn);
|
||||
ogs_pfcp_subnet_t *ogs_pfcp_find_subnet(int family);
|
||||
ogs_pfcp_subnet_t *ogs_pfcp_find_subnet_by_dnn(int family, const char *dnn);
|
||||
|
||||
void ogs_pfcp_pool_init(ogs_pfcp_sess_t *sess);
|
||||
void ogs_pfcp_pool_final(ogs_pfcp_sess_t *sess);
|
||||
|
|
|
@ -177,7 +177,7 @@ void ogs_pfcp_up_handle_pdr(
|
|||
buffering = true;
|
||||
|
||||
} else {
|
||||
ogs_error("Not implemented");
|
||||
ogs_error("Not implemented = %d", far->apply_action);
|
||||
ogs_pkbuf_free(sendbuf);
|
||||
}
|
||||
}
|
||||
|
@ -280,29 +280,64 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_create_pdr(ogs_pfcp_sess_t *sess,
|
|||
ogs_pfcp_rule_remove_all(pdr);
|
||||
|
||||
for (i = 0; i < OGS_MAX_NUM_OF_RULE; i++) {
|
||||
ogs_pfcp_sdf_filter_t sdf_filter_in_message;
|
||||
ogs_pfcp_sdf_filter_t sdf_filter;
|
||||
ogs_pfcp_rule_t *rule = NULL;
|
||||
ogs_pfcp_rule_t *oppsite_direction_rule = NULL;
|
||||
|
||||
if (message->pdi.sdf_filter[i].presence == 0)
|
||||
break;
|
||||
|
||||
len = ogs_pfcp_parse_sdf_filter(
|
||||
&sdf_filter_in_message, &message->pdi.sdf_filter[i]);
|
||||
&sdf_filter, &message->pdi.sdf_filter[i]);
|
||||
ogs_assert(message->pdi.sdf_filter[i].len == len);
|
||||
if (sdf_filter_in_message.fd) {
|
||||
ogs_pfcp_rule_t *rule = NULL;
|
||||
char *flow_description = NULL;
|
||||
|
||||
flow_description = ogs_malloc(
|
||||
sdf_filter_in_message.flow_description_len+1);
|
||||
ogs_cpystrn(flow_description,
|
||||
sdf_filter_in_message.flow_description,
|
||||
sdf_filter_in_message.flow_description_len+1);
|
||||
/* Check Previous SDF Filter ID */
|
||||
if (sdf_filter.bid) {
|
||||
oppsite_direction_rule = ogs_pfcp_rule_find_by_sdf_filter_id(
|
||||
sess, sdf_filter.sdf_filter_id);
|
||||
|
||||
}
|
||||
|
||||
if (!oppsite_direction_rule && !sdf_filter.fd) {
|
||||
ogs_error("Not Supported SDF Filter [Flags:0x%x, Len:%d]",
|
||||
sdf_filter.flags, message->pdi.sdf_filter[i].len);
|
||||
ogs_log_hexdump(OGS_LOG_ERROR,
|
||||
message->pdi.sdf_filter[i].data,
|
||||
message->pdi.sdf_filter[i].len);
|
||||
continue;
|
||||
}
|
||||
|
||||
rule = ogs_pfcp_rule_add(pdr);
|
||||
ogs_assert(rule);
|
||||
|
||||
/* Set All Flags (BID, FL, SPI, TTC, FD) */
|
||||
rule->flags = sdf_filter.flags;
|
||||
|
||||
if (oppsite_direction_rule) {
|
||||
/* Copy oppsite direction rule and Swap */
|
||||
memcpy(&rule->ipfw,
|
||||
&oppsite_direction_rule->ipfw, sizeof(rule->ipfw));
|
||||
ogs_ipfw_rule_swap(&rule->ipfw);
|
||||
}
|
||||
|
||||
/* If BID, Store SDF Filter ID */
|
||||
if (rule->bid)
|
||||
rule->sdf_filter_id = sdf_filter.sdf_filter_id;
|
||||
|
||||
/* If FD, Apply Flow-Description to the RULE */
|
||||
if (rule->fd) {
|
||||
char *flow_description = NULL;
|
||||
|
||||
flow_description = ogs_malloc(
|
||||
sdf_filter.flow_description_len+1);
|
||||
ogs_cpystrn(flow_description,
|
||||
sdf_filter.flow_description,
|
||||
sdf_filter.flow_description_len+1);
|
||||
|
||||
rv = ogs_ipfw_compile_rule(&rule->ipfw, flow_description);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
ogs_free(flow_description);
|
||||
/*
|
||||
*
|
||||
* TS29.244 Ch 5.2.1A.2A
|
||||
|
@ -337,8 +372,6 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_create_pdr(ogs_pfcp_sess_t *sess,
|
|||
/* Uplink data flow */
|
||||
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS)
|
||||
ogs_ipfw_rule_swap(&rule->ipfw);
|
||||
|
||||
ogs_free(flow_description);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,6 +397,12 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_create_pdr(ogs_pfcp_sess_t *sess,
|
|||
pdr->qfi = message->pdi.qfi.u8;
|
||||
}
|
||||
|
||||
if (message->pdi.ue_ip_address.presence) {
|
||||
pdr->ue_ip_addr_len = message->pdi.ue_ip_address.len;
|
||||
memcpy(&pdr->ue_ip_addr,
|
||||
message->pdi.ue_ip_address.data, pdr->ue_ip_addr_len);
|
||||
}
|
||||
|
||||
if (message->outer_header_removal.presence) {
|
||||
pdr->outer_header_removal_len = message->outer_header_removal.len;
|
||||
memcpy(&pdr->outer_header_removal, message->outer_header_removal.data,
|
||||
|
@ -382,12 +421,6 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_create_pdr(ogs_pfcp_sess_t *sess,
|
|||
ogs_pfcp_pdr_associate_qer(pdr, qer);
|
||||
}
|
||||
|
||||
if (message->far_id.presence) {
|
||||
far = ogs_pfcp_far_find_or_add(sess, message->far_id.u32);
|
||||
ogs_assert(far);
|
||||
ogs_pfcp_pdr_associate_far(pdr, far);
|
||||
}
|
||||
|
||||
if (message->qer_id.presence) {
|
||||
qer = ogs_pfcp_qer_find_or_add(sess, message->qer_id.u32);
|
||||
ogs_assert(qer);
|
||||
|
@ -475,30 +508,65 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_update_pdr(ogs_pfcp_sess_t *sess,
|
|||
ogs_pfcp_rule_remove_all(pdr);
|
||||
|
||||
for (i = 0; i < OGS_MAX_NUM_OF_RULE; i++) {
|
||||
ogs_pfcp_sdf_filter_t sdf_filter_in_message;
|
||||
ogs_pfcp_sdf_filter_t sdf_filter;
|
||||
ogs_pfcp_rule_t *rule = NULL;
|
||||
ogs_pfcp_rule_t *oppsite_direction_rule = NULL;
|
||||
|
||||
if (message->pdi.sdf_filter[i].presence == 0)
|
||||
break;
|
||||
|
||||
len = ogs_pfcp_parse_sdf_filter(
|
||||
&sdf_filter_in_message, &message->pdi.sdf_filter[i]);
|
||||
&sdf_filter, &message->pdi.sdf_filter[i]);
|
||||
ogs_assert(message->pdi.sdf_filter[i].len == len);
|
||||
if (sdf_filter_in_message.fd) {
|
||||
ogs_pfcp_rule_t *rule = NULL;
|
||||
char *flow_description = NULL;
|
||||
|
||||
flow_description = ogs_malloc(
|
||||
sdf_filter_in_message.flow_description_len+1);
|
||||
ogs_cpystrn(flow_description,
|
||||
sdf_filter_in_message.flow_description,
|
||||
sdf_filter_in_message.flow_description_len+1);
|
||||
/* Check Previous SDF Filter ID */
|
||||
if (sdf_filter.bid) {
|
||||
oppsite_direction_rule = ogs_pfcp_rule_find_by_sdf_filter_id(
|
||||
sess, sdf_filter.sdf_filter_id);
|
||||
|
||||
}
|
||||
|
||||
if (!oppsite_direction_rule && !sdf_filter.fd) {
|
||||
ogs_error("Not Supported SDF Filter [Flags:0x%x, Len:%d]",
|
||||
sdf_filter.flags, message->pdi.sdf_filter[i].len);
|
||||
ogs_log_hexdump(OGS_LOG_ERROR,
|
||||
message->pdi.sdf_filter[i].data,
|
||||
message->pdi.sdf_filter[i].len);
|
||||
continue;
|
||||
}
|
||||
|
||||
rule = ogs_pfcp_rule_add(pdr);
|
||||
ogs_assert(rule);
|
||||
|
||||
/* Set All Flags (BID, FL, SPI, TTC, FD) */
|
||||
rule->flags = sdf_filter.flags;
|
||||
|
||||
if (oppsite_direction_rule) {
|
||||
/* Copy oppsite direction rule and Swap */
|
||||
memcpy(&rule->ipfw,
|
||||
&oppsite_direction_rule->ipfw, sizeof(rule->ipfw));
|
||||
ogs_ipfw_rule_swap(&rule->ipfw);
|
||||
}
|
||||
|
||||
/* If BID, Store SDF Filter ID */
|
||||
if (rule->bid)
|
||||
rule->sdf_filter_id = sdf_filter.sdf_filter_id;
|
||||
|
||||
/* If FD, Apply Flow-Description to the RULE */
|
||||
if (rule->fd) {
|
||||
char *flow_description = NULL;
|
||||
|
||||
flow_description = ogs_malloc(
|
||||
sdf_filter.flow_description_len+1);
|
||||
ogs_cpystrn(flow_description,
|
||||
sdf_filter.flow_description,
|
||||
sdf_filter.flow_description_len+1);
|
||||
|
||||
rv = ogs_ipfw_compile_rule(&rule->ipfw, flow_description);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
/*
|
||||
ogs_free(flow_description);
|
||||
/*
|
||||
*
|
||||
* TS29.244 Ch 5.2.1A.2A
|
||||
*
|
||||
|
@ -532,10 +600,7 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_update_pdr(ogs_pfcp_sess_t *sess,
|
|||
/* Uplink data flow */
|
||||
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS)
|
||||
ogs_ipfw_rule_swap(&rule->ipfw);
|
||||
|
||||
ogs_free(flow_description);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (message->pdi.network_instance.presence) {
|
||||
|
@ -629,13 +694,14 @@ ogs_pfcp_far_t *ogs_pfcp_handle_create_far(ogs_pfcp_sess_t *sess,
|
|||
*offending_ie_value = OGS_PFCP_APPLY_ACTION_TYPE;
|
||||
return NULL;
|
||||
}
|
||||
if (message->forwarding_parameters.
|
||||
destination_interface.presence == 0) {
|
||||
return far;
|
||||
}
|
||||
|
||||
far->apply_action = message->apply_action.u8;
|
||||
far->dst_if = message->forwarding_parameters.destination_interface.u8;
|
||||
|
||||
if (message->forwarding_parameters.presence) {
|
||||
if (message->forwarding_parameters.destination_interface.presence) {
|
||||
far->dst_if =
|
||||
message->forwarding_parameters.destination_interface.u8;
|
||||
}
|
||||
|
||||
if (message->forwarding_parameters.outer_header_creation.presence) {
|
||||
ogs_pfcp_tlv_outer_header_creation_t *outer_header_creation =
|
||||
|
@ -650,6 +716,8 @@ ogs_pfcp_far_t *ogs_pfcp_handle_create_far(ogs_pfcp_sess_t *sess,
|
|||
be32toh(far->outer_header_creation.teid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return far;
|
||||
}
|
||||
|
||||
|
@ -724,8 +792,8 @@ ogs_pfcp_far_t *ogs_pfcp_handle_update_far(ogs_pfcp_sess_t *sess,
|
|||
if (message->update_forwarding_parameters.presence) {
|
||||
if (message->update_forwarding_parameters.
|
||||
destination_interface.presence) {
|
||||
far->dst_if = message->update_forwarding_parameters.
|
||||
destination_interface.u8;
|
||||
far->dst_if =
|
||||
message->update_forwarding_parameters.destination_interface.u8;
|
||||
}
|
||||
|
||||
if (message->update_forwarding_parameters.
|
||||
|
@ -889,3 +957,58 @@ bool ogs_pfcp_handle_remove_qer(ogs_pfcp_sess_t *sess,
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
ogs_pfcp_bar_t *ogs_pfcp_handle_create_bar(ogs_pfcp_sess_t *sess,
|
||||
ogs_pfcp_tlv_create_bar_t *message,
|
||||
uint8_t *cause_value, uint8_t *offending_ie_value)
|
||||
{
|
||||
ogs_assert(message);
|
||||
ogs_assert(sess);
|
||||
|
||||
if (message->presence == 0)
|
||||
return NULL;
|
||||
|
||||
if (message->bar_id.presence == 0) {
|
||||
ogs_error("No BAR-ID");
|
||||
*cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_MISSING;
|
||||
*offending_ie_value = OGS_PFCP_BAR_ID_TYPE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sess->bar)
|
||||
ogs_pfcp_bar_delete(sess->bar);
|
||||
|
||||
ogs_pfcp_bar_new(sess);
|
||||
ogs_assert(sess->bar);
|
||||
|
||||
sess->bar->id = message->bar_id.u8;
|
||||
|
||||
return sess->bar;
|
||||
}
|
||||
|
||||
bool ogs_pfcp_handle_remove_bar(ogs_pfcp_sess_t *sess,
|
||||
ogs_pfcp_tlv_remove_bar_t *message,
|
||||
uint8_t *cause_value, uint8_t *offending_ie_value)
|
||||
{
|
||||
ogs_assert(sess);
|
||||
ogs_assert(message);
|
||||
|
||||
if (message->presence == 0)
|
||||
return false;
|
||||
|
||||
if (message->bar_id.presence == 0) {
|
||||
ogs_error("No BAR-ID");
|
||||
*cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_MISSING;
|
||||
*offending_ie_value = OGS_PFCP_BAR_ID_TYPE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sess->bar && sess->bar->id == message->bar_id.u8) {
|
||||
ogs_pfcp_bar_delete(sess->bar);
|
||||
return true;
|
||||
}
|
||||
|
||||
ogs_error("[%p] Unknown BAR-ID[%d]", sess->bar, message->bar_id.u8);
|
||||
*cause_value = OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -87,6 +87,13 @@ bool ogs_pfcp_handle_remove_qer(ogs_pfcp_sess_t *sess,
|
|||
ogs_pfcp_tlv_remove_qer_t *message,
|
||||
uint8_t *cause_value, uint8_t *offending_ie_value);
|
||||
|
||||
ogs_pfcp_bar_t *ogs_pfcp_handle_create_bar(ogs_pfcp_sess_t *sess,
|
||||
ogs_pfcp_tlv_create_bar_t *message,
|
||||
uint8_t *cause_value, uint8_t *offending_ie_value);
|
||||
bool ogs_pfcp_handle_remove_bar(ogs_pfcp_sess_t *sess,
|
||||
ogs_pfcp_tlv_remove_bar_t *message,
|
||||
uint8_t *cause_value, uint8_t *offending_ie_value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -278,6 +278,12 @@ void ogs_pfcp_send_g_pdu(ogs_pfcp_pdr_t *pdr, ogs_pkbuf_t *sendbuf)
|
|||
return;
|
||||
}
|
||||
|
||||
if (far->dst_if == OGS_PFCP_INTERFACE_UNKNOWN) {
|
||||
ogs_error("No Destination Interface");
|
||||
ogs_pkbuf_free(sendbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
gnode = far->gnode;
|
||||
ogs_assert(gnode);
|
||||
ogs_assert(gnode->sock);
|
||||
|
|
|
@ -480,16 +480,20 @@ ED3(uint8_t spare:6;,
|
|||
* if the CHID bit in octet 5 is set to "1".
|
||||
*/
|
||||
typedef struct ogs_pfcp_f_teid_s {
|
||||
ED5(uint8_t spare:4;,
|
||||
ED5(uint8_t spare1:4;,
|
||||
uint8_t chid:1;,
|
||||
uint8_t ch:1;,
|
||||
uint8_t ipv6:1;,
|
||||
uint8_t ipv4:1;)
|
||||
union {
|
||||
uint32_t teid;
|
||||
uint8_t choose_id;
|
||||
struct {
|
||||
ED4(uint8_t choose_id;,
|
||||
uint8_t spare2;,
|
||||
uint8_t spare3;,
|
||||
uint8_t spare4;)
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
uint32_t teid;
|
||||
union {
|
||||
uint32_t addr;
|
||||
uint8_t addr6[OGS_IPV6_LEN];
|
||||
|
@ -499,6 +503,7 @@ ED5(uint8_t spare:4;,
|
|||
} both;
|
||||
};
|
||||
};
|
||||
};
|
||||
} __attribute__ ((packed)) ogs_pfcp_f_teid_t;
|
||||
|
||||
/*
|
||||
|
@ -797,7 +802,6 @@ int16_t ogs_pfcp_parse_user_plane_ip_resource_info(
|
|||
* the UP function shall apply the SDF filter as specified in clause 5.2.1A.2A.
|
||||
*/
|
||||
|
||||
#define OGS_PFCP_MAX_SDF_FILTER_LEN 256
|
||||
typedef struct ogs_pfcp_sdf_filter_s {
|
||||
union {
|
||||
struct {
|
||||
|
|
|
@ -1348,10 +1348,8 @@ static int flow_rx_to_gx(ogs_flow_t *rx_flow, ogs_flow_t *gx_flow)
|
|||
if (!strncmp(rx_flow->description,
|
||||
"permit out", strlen("permit out"))) {
|
||||
gx_flow->direction = OGS_FLOW_DOWNLINK_ONLY;
|
||||
gx_flow->description = ogs_strdup(rx_flow->description);
|
||||
|
||||
len = strlen(rx_flow->description)+1;
|
||||
gx_flow->description = ogs_malloc(len);
|
||||
ogs_cpystrn(gx_flow->description, rx_flow->description, len);
|
||||
} else if (!strncmp(rx_flow->description,
|
||||
"permit in", strlen("permit in"))) {
|
||||
gx_flow->direction = OGS_FLOW_UPLINK_ONLY;
|
||||
|
|
|
@ -409,6 +409,9 @@ sgwc_sess_t *sgwc_sess_add(sgwc_ue_t *sgwc_ue, char *apn)
|
|||
sess->sgw_s5c_teid = sess->index;
|
||||
sess->sgwc_sxa_seid = sess->index;
|
||||
|
||||
/* Create BAR in PFCP Session */
|
||||
ogs_pfcp_bar_new(&sess->pfcp);
|
||||
|
||||
/* Set APN */
|
||||
ogs_cpystrn(sess->pdn.apn, apn, OGS_MAX_APN_LEN+1);
|
||||
|
||||
|
@ -431,8 +434,8 @@ static bool compare_ue_info(ogs_pfcp_node_t *node, sgwc_sess_t *sess)
|
|||
sgwc_ue = sess->sgwc_ue;
|
||||
ogs_assert(sgwc_ue);
|
||||
|
||||
for (i = 0; i < node->num_of_apn; i++)
|
||||
if (ogs_strcasecmp(node->apn[i], sess->pdn.apn) == 0) return true;
|
||||
for (i = 0; i < node->num_of_dnn; i++)
|
||||
if (ogs_strcasecmp(node->dnn[i], sess->pdn.apn) == 0) return true;
|
||||
|
||||
for (i = 0; i < node->num_of_e_cell_id; i++)
|
||||
if (node->e_cell_id[i] == sgwc_ue->e_cgi.cell_id) return true;
|
||||
|
@ -532,6 +535,9 @@ int sgwc_sess_remove(sgwc_sess_t *sess)
|
|||
|
||||
sgwc_bearer_remove_all(sess);
|
||||
|
||||
ogs_assert(sess->pfcp.bar);
|
||||
ogs_pfcp_bar_delete(sess->pfcp.bar);
|
||||
|
||||
ogs_pfcp_pool_final(&sess->pfcp);
|
||||
|
||||
ogs_pool_free(&sgwc_sess_pool, sess);
|
||||
|
@ -812,9 +818,14 @@ sgwc_tunnel_t *sgwc_tunnel_add(
|
|||
|
||||
far = ogs_pfcp_far_add(&sess->pfcp);
|
||||
ogs_assert(far);
|
||||
|
||||
far->dst_if = dst_if;
|
||||
ogs_pfcp_pdr_associate_far(pdr, far);
|
||||
|
||||
far->apply_action =
|
||||
OGS_PFCP_APPLY_ACTION_BUFF| OGS_PFCP_APPLY_ACTION_NOCP;
|
||||
ogs_assert(sess->pfcp.bar);
|
||||
|
||||
ogs_assert(sess->pfcp_node);
|
||||
if (sess->pfcp_node->up_function_features.ftup) {
|
||||
pdr->f_teid.ch = 1;
|
||||
|
|
|
@ -383,6 +383,8 @@ void sgwc_s11_handle_modify_bearer_request(
|
|||
far = dl_tunnel->far;
|
||||
ogs_assert(far);
|
||||
|
||||
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||
|
||||
ogs_pfcp_ip_to_outer_header_creation(&dl_tunnel->remote_ip,
|
||||
&far->outer_header_creation, &far->outer_header_creation_len);
|
||||
far->outer_header_creation.teid = dl_tunnel->remote_teid;
|
||||
|
@ -605,6 +607,8 @@ void sgwc_s11_handle_create_bearer_response(
|
|||
far = dl_tunnel->far;
|
||||
ogs_assert(far);
|
||||
|
||||
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||
|
||||
ogs_pfcp_ip_to_outer_header_creation(&dl_tunnel->remote_ip,
|
||||
&far->outer_header_creation, &far->outer_header_creation_len);
|
||||
far->outer_header_creation.teid = dl_tunnel->remote_teid;
|
||||
|
@ -984,6 +988,8 @@ void sgwc_s11_handle_create_indirect_data_forwarding_tunnel_request(
|
|||
far = tunnel->far;
|
||||
ogs_assert(far);
|
||||
|
||||
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||
|
||||
ogs_pfcp_ip_to_outer_header_creation(&tunnel->remote_ip,
|
||||
&far->outer_header_creation, &far->outer_header_creation_len);
|
||||
far->outer_header_creation.teid = tunnel->remote_teid;
|
||||
|
@ -1014,6 +1020,8 @@ void sgwc_s11_handle_create_indirect_data_forwarding_tunnel_request(
|
|||
far = tunnel->far;
|
||||
ogs_assert(far);
|
||||
|
||||
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||
|
||||
ogs_pfcp_ip_to_outer_header_creation(&tunnel->remote_ip,
|
||||
&far->outer_header_creation, &far->outer_header_creation_len);
|
||||
far->outer_header_creation.teid = tunnel->remote_teid;
|
||||
|
|
|
@ -203,6 +203,8 @@ void sgwc_s5c_handle_create_session_response(
|
|||
far = ul_tunnel->far;
|
||||
ogs_assert(far);
|
||||
|
||||
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||
|
||||
ogs_pfcp_ip_to_outer_header_creation(&ul_tunnel->remote_ip,
|
||||
&far->outer_header_creation, &far->outer_header_creation_len);
|
||||
far->outer_header_creation.teid = ul_tunnel->remote_teid;
|
||||
|
@ -369,6 +371,8 @@ void sgwc_s5c_handle_create_bearer_request(
|
|||
far = ul_tunnel->far;
|
||||
ogs_assert(far);
|
||||
|
||||
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||
|
||||
ogs_pfcp_ip_to_outer_header_creation(&ul_tunnel->remote_ip,
|
||||
&far->outer_header_creation, &far->outer_header_creation_len);
|
||||
far->outer_header_creation.teid = ul_tunnel->remote_teid;
|
||||
|
|
|
@ -90,6 +90,11 @@ ogs_pkbuf_t *sgwc_sxa_build_session_establishment_request(
|
|||
i++;
|
||||
}
|
||||
|
||||
/* Create BAR */
|
||||
if (sess->pfcp.bar) {
|
||||
ogs_pfcp_build_create_bar(&req->create_bar, sess->pfcp.bar);
|
||||
}
|
||||
|
||||
/* PDN Type */
|
||||
req->pdn_type.presence = 1;
|
||||
req->pdn_type.u8 = sess->pdn.paa.pdn_type;
|
||||
|
|
|
@ -410,13 +410,11 @@ int sgwu_context_parse_config(void)
|
|||
return OGS_OK;
|
||||
}
|
||||
|
||||
sgwu_sess_t *sgwu_sess_add(
|
||||
ogs_pfcp_f_seid_t *cp_f_seid, const char *apn, uint8_t pdn_type)
|
||||
sgwu_sess_t *sgwu_sess_add(ogs_pfcp_f_seid_t *cp_f_seid)
|
||||
{
|
||||
sgwu_sess_t *sess = NULL;
|
||||
|
||||
ogs_assert(cp_f_seid);
|
||||
ogs_assert(apn);
|
||||
|
||||
ogs_pool_alloc(&sgwu_sess_pool, &sess);
|
||||
ogs_assert(sess);
|
||||
|
@ -432,11 +430,8 @@ sgwu_sess_t *sgwu_sess_add(
|
|||
ogs_hash_set(self.sess_hash, &sess->sgwc_sxa_seid,
|
||||
sizeof(sess->sgwc_sxa_seid), sess);
|
||||
|
||||
/* Set APN */
|
||||
ogs_cpystrn(sess->pdn.apn, apn, OGS_MAX_APN_LEN+1);
|
||||
|
||||
ogs_info("UE F-SEID[CP:0x%lx,UP:0x%lx] APN[%s] PDN-Type[%d]",
|
||||
(long)sess->sgwu_sxa_seid, (long)sess->sgwc_sxa_seid, apn, pdn_type);
|
||||
ogs_info("UE F-SEID[CP:0x%lx,UP:0x%lx]",
|
||||
(long)sess->sgwu_sxa_seid, (long)sess->sgwc_sxa_seid);
|
||||
|
||||
ogs_list_add(&self.sess_list, sess);
|
||||
|
||||
|
@ -496,11 +491,9 @@ sgwu_sess_t *sgwu_sess_add_by_message(ogs_pfcp_message_t *message)
|
|||
sgwu_sess_t *sess = NULL;
|
||||
|
||||
ogs_pfcp_f_seid_t *f_seid = NULL;
|
||||
char apn[OGS_MAX_APN_LEN];
|
||||
|
||||
ogs_pfcp_session_establishment_request_t *req =
|
||||
&message->pfcp_session_establishment_request;;
|
||||
int i;
|
||||
|
||||
f_seid = req->cp_f_seid.data;
|
||||
if (req->cp_f_seid.presence == 0 || f_seid == NULL) {
|
||||
|
@ -509,42 +502,9 @@ sgwu_sess_t *sgwu_sess_add_by_message(ogs_pfcp_message_t *message)
|
|||
}
|
||||
f_seid->seid = be64toh(f_seid->seid);
|
||||
|
||||
if (req->pdn_type.presence == 0) {
|
||||
ogs_error("No PDN Type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find APN
|
||||
* - PDR ID is existed
|
||||
* - APN(Network Instance) is existed
|
||||
*/
|
||||
memset(apn, 0, sizeof(apn));
|
||||
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
|
||||
ogs_pfcp_tlv_create_pdr_t *message = &req->create_pdr[i];
|
||||
ogs_assert(message);
|
||||
if (message->presence == 0)
|
||||
continue;
|
||||
if (message->pdr_id.presence == 0)
|
||||
continue;
|
||||
if (message->pdi.presence == 0)
|
||||
continue;
|
||||
if (message->pdi.network_instance.presence == 0)
|
||||
continue;
|
||||
|
||||
ogs_fqdn_parse(apn,
|
||||
message->pdi.network_instance.data,
|
||||
message->pdi.network_instance.len);
|
||||
break;
|
||||
}
|
||||
|
||||
if (strlen(apn) == 0) {
|
||||
ogs_error("No APN in PDR");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sess = sgwu_sess_find_by_cp_seid(f_seid->seid);
|
||||
if (!sess) {
|
||||
sess = sgwu_sess_add(f_seid, apn, req->pdn_type.u8);
|
||||
sess = sgwu_sess_add(f_seid);
|
||||
if (!sess) return NULL;
|
||||
}
|
||||
ogs_assert(sess);
|
||||
|
|
|
@ -72,8 +72,7 @@ int sgwu_context_parse_config(void);
|
|||
|
||||
sgwu_sess_t *sgwu_sess_add_by_message(ogs_pfcp_message_t *message);
|
||||
|
||||
sgwu_sess_t *sgwu_sess_add(
|
||||
ogs_pfcp_f_seid_t *f_seid, const char *apn, uint8_t pdn_type);
|
||||
sgwu_sess_t *sgwu_sess_add(ogs_pfcp_f_seid_t *f_seid);
|
||||
int sgwu_sess_remove(sgwu_sess_t *sess);
|
||||
void sgwu_sess_remove_all(void);
|
||||
sgwu_sess_t *sgwu_sess_find(uint32_t index);
|
||||
|
|
|
@ -76,7 +76,7 @@ void sgwu_sxa_handle_session_establishment_request(
|
|||
ogs_error("No Context");
|
||||
ogs_pfcp_send_error_message(xact, 0,
|
||||
OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE,
|
||||
OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND, 0);
|
||||
OGS_PFCP_CAUSE_MANDATORY_IE_MISSING, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -106,6 +106,11 @@ void sgwu_sxa_handle_session_establishment_request(
|
|||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||
goto cleanup;
|
||||
|
||||
ogs_pfcp_handle_create_bar(&sess->pfcp, &req->create_bar,
|
||||
&cause_value, &offending_ie_value);
|
||||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||
goto cleanup;
|
||||
|
||||
/* Setup GTP Node */
|
||||
ogs_list_for_each(&sess->pfcp.far_list, far)
|
||||
setup_gtp_node(far);
|
||||
|
@ -118,10 +123,27 @@ void sgwu_sxa_handle_session_establishment_request(
|
|||
if (pdr->f_teid_len) {
|
||||
if (ogs_pfcp_self()->up_function_features.ftup &&
|
||||
pdr->f_teid.ch) {
|
||||
|
||||
ogs_pfcp_pdr_t *choosed_pdr = NULL;
|
||||
|
||||
if (pdr->f_teid.chid) {
|
||||
choosed_pdr = ogs_pfcp_pdr_find_by_choose_id(
|
||||
&sess->pfcp, pdr->f_teid.choose_id);
|
||||
if (!choosed_pdr) {
|
||||
pdr->chid = true;
|
||||
pdr->choose_id = pdr->f_teid.choose_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (choosed_pdr) {
|
||||
pdr->f_teid_len = choosed_pdr->f_teid_len;
|
||||
memcpy(&pdr->f_teid, &choosed_pdr->f_teid, pdr->f_teid_len);
|
||||
|
||||
} else {
|
||||
ogs_pfcp_gtpu_resource_t *resource = NULL;
|
||||
resource = ogs_pfcp_gtpu_resource_find(
|
||||
&ogs_pfcp_self()->gtpu_resource_list,
|
||||
sess->pdn.apn, OGS_PFCP_INTERFACE_ACCESS);
|
||||
pdr->apn, OGS_PFCP_INTERFACE_ACCESS);
|
||||
if (resource) {
|
||||
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
|
||||
&resource->info, &pdr->f_teid, &pdr->f_teid_len);
|
||||
|
@ -146,6 +168,7 @@ void sgwu_sxa_handle_session_establishment_request(
|
|||
pdr->f_teid.teid = pdr->index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ogs_pfcp_pdr_hash_set(pdr);
|
||||
}
|
||||
|
@ -280,6 +303,16 @@ void sgwu_sxa_handle_session_modification_request(
|
|||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||
goto cleanup;
|
||||
|
||||
ogs_pfcp_handle_create_bar(&sess->pfcp, &req->create_bar,
|
||||
&cause_value, &offending_ie_value);
|
||||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||
goto cleanup;
|
||||
|
||||
ogs_pfcp_handle_remove_bar(&sess->pfcp, &req->remove_bar,
|
||||
&cause_value, &offending_ie_value);
|
||||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||
goto cleanup;
|
||||
|
||||
/* Setup GTP Node */
|
||||
ogs_list_for_each(&sess->pfcp.far_list, far)
|
||||
setup_gtp_node(far);
|
||||
|
@ -292,10 +325,27 @@ void sgwu_sxa_handle_session_modification_request(
|
|||
if (pdr->f_teid_len) {
|
||||
if (ogs_pfcp_self()->up_function_features.ftup &&
|
||||
pdr->f_teid.ch) {
|
||||
|
||||
ogs_pfcp_pdr_t *choosed_pdr = NULL;
|
||||
|
||||
if (pdr->f_teid.chid) {
|
||||
choosed_pdr = ogs_pfcp_pdr_find_by_choose_id(
|
||||
&sess->pfcp, pdr->f_teid.choose_id);
|
||||
if (!choosed_pdr) {
|
||||
pdr->chid = true;
|
||||
pdr->choose_id = pdr->f_teid.choose_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (choosed_pdr) {
|
||||
pdr->f_teid_len = choosed_pdr->f_teid_len;
|
||||
memcpy(&pdr->f_teid, &choosed_pdr->f_teid, pdr->f_teid_len);
|
||||
|
||||
} else {
|
||||
ogs_pfcp_gtpu_resource_t *resource = NULL;
|
||||
resource = ogs_pfcp_gtpu_resource_find(
|
||||
&ogs_pfcp_self()->gtpu_resource_list,
|
||||
sess->pdn.apn, OGS_PFCP_INTERFACE_ACCESS);
|
||||
pdr->apn, OGS_PFCP_INTERFACE_ACCESS);
|
||||
if (resource) {
|
||||
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
|
||||
&resource->info, &pdr->f_teid, &pdr->f_teid_len);
|
||||
|
@ -320,6 +370,7 @@ void sgwu_sxa_handle_session_modification_request(
|
|||
pdr->f_teid.teid = pdr->index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ogs_pfcp_pdr_hash_set(pdr);
|
||||
}
|
||||
|
|
|
@ -363,7 +363,8 @@ int smf_context_parse_config(void)
|
|||
if (v) port = atoi(v);
|
||||
} else if (!strcmp(gtpc_key, "dev")) {
|
||||
dev = ogs_yaml_iter_value(>pc_iter);
|
||||
} else if (!strcmp(gtpc_key, "apn")) {
|
||||
} else if (!strcmp(gtpc_key, "apn") ||
|
||||
!strcmp(gtpc_key, "dnn")) {
|
||||
/* Skip */
|
||||
} else
|
||||
ogs_warn("unknown key `%s`", gtpc_key);
|
||||
|
@ -611,8 +612,8 @@ static bool compare_ue_info(ogs_pfcp_node_t *node, smf_sess_t *sess)
|
|||
ogs_assert(node);
|
||||
ogs_assert(sess);
|
||||
|
||||
for (i = 0; i < node->num_of_apn; i++)
|
||||
if (ogs_strcasecmp(node->apn[i], sess->pdn.apn) == 0) return true;
|
||||
for (i = 0; i < node->num_of_dnn; i++)
|
||||
if (ogs_strcasecmp(node->dnn[i], sess->pdn.dnn) == 0) return true;
|
||||
|
||||
for (i = 0; i < node->num_of_e_cell_id; i++)
|
||||
if (node->e_cell_id[i] == sess->e_cgi.cell_id) return true;
|
||||
|
@ -731,6 +732,9 @@ smf_sess_t *smf_sess_add_by_apn(smf_ue_t *smf_ue, char *apn)
|
|||
sess->smf_n4_teid = sess->index;
|
||||
sess->smf_n4_seid = sess->index;
|
||||
|
||||
/* Create BAR in PFCP Session */
|
||||
ogs_pfcp_bar_new(&sess->pfcp);
|
||||
|
||||
/* Set APN */
|
||||
ogs_cpystrn(sess->pdn.apn, apn, OGS_MAX_APN_LEN+1);
|
||||
|
||||
|
@ -837,6 +841,9 @@ smf_sess_t *smf_sess_add_by_psi(smf_ue_t *smf_ue, uint8_t psi)
|
|||
(int)ogs_pool_index(&smf_sess_pool, sess));
|
||||
ogs_assert(sess->sm_context_ref);
|
||||
|
||||
/* Create BAR in PFCP Session */
|
||||
ogs_pfcp_bar_new(&sess->pfcp);
|
||||
|
||||
/* Set PSI */
|
||||
sess->psi = psi;
|
||||
|
||||
|
@ -934,8 +941,8 @@ void smf_sess_set_ue_ip(smf_sess_t *sess)
|
|||
ogs_pfcp_subnet_t *subnet = NULL;
|
||||
ogs_pfcp_subnet_t *subnet6 = NULL;
|
||||
|
||||
subnet = ogs_pfcp_find_subnet(AF_INET, sess->pdn.apn);
|
||||
subnet6 = ogs_pfcp_find_subnet(AF_INET6, sess->pdn.apn);
|
||||
subnet = ogs_pfcp_find_subnet_by_dnn(AF_INET, sess->pdn.dnn);
|
||||
subnet6 = ogs_pfcp_find_subnet_by_dnn(AF_INET6, sess->pdn.dnn);
|
||||
|
||||
if (subnet != NULL && subnet6 == NULL)
|
||||
sess->pdn.pdn_type = OGS_PDU_SESSION_TYPE_IPV4;
|
||||
|
@ -959,14 +966,14 @@ void smf_sess_set_ue_ip(smf_sess_t *sess)
|
|||
|
||||
if (sess->pdn.pdn_type == OGS_PDU_SESSION_TYPE_IPV4) {
|
||||
sess->ipv4 = ogs_pfcp_ue_ip_alloc(
|
||||
AF_INET, sess->pdn.apn, (uint8_t *)&sess->pdn.ue_ip.addr);
|
||||
AF_INET, sess->pdn.dnn, (uint8_t *)&sess->pdn.ue_ip.addr);
|
||||
ogs_assert(sess->ipv4);
|
||||
sess->pdn.paa.addr = sess->ipv4->addr[0];
|
||||
ogs_hash_set(smf_self()->ipv4_hash,
|
||||
sess->ipv4->addr, OGS_IPV4_LEN, sess);
|
||||
} else if (sess->pdn.pdn_type == OGS_PDU_SESSION_TYPE_IPV6) {
|
||||
sess->ipv6 = ogs_pfcp_ue_ip_alloc(
|
||||
AF_INET6, sess->pdn.apn, sess->pdn.ue_ip.addr6);
|
||||
AF_INET6, sess->pdn.dnn, sess->pdn.ue_ip.addr6);
|
||||
ogs_assert(sess->ipv6);
|
||||
|
||||
subnet6 = sess->ipv6->subnet;
|
||||
|
@ -978,10 +985,10 @@ void smf_sess_set_ue_ip(smf_sess_t *sess)
|
|||
sess->ipv6->addr, OGS_IPV6_LEN, sess);
|
||||
} else if (sess->pdn.pdn_type == OGS_PDU_SESSION_TYPE_IPV4V6) {
|
||||
sess->ipv4 = ogs_pfcp_ue_ip_alloc(
|
||||
AF_INET, sess->pdn.apn, (uint8_t *)&sess->pdn.ue_ip.addr);
|
||||
AF_INET, sess->pdn.dnn, (uint8_t *)&sess->pdn.ue_ip.addr);
|
||||
ogs_assert(sess->ipv4);
|
||||
sess->ipv6 = ogs_pfcp_ue_ip_alloc(
|
||||
AF_INET6, sess->pdn.apn, sess->pdn.ue_ip.addr6);
|
||||
AF_INET6, sess->pdn.dnn, sess->pdn.ue_ip.addr6);
|
||||
ogs_assert(sess->ipv6);
|
||||
|
||||
subnet6 = sess->ipv6->subnet;
|
||||
|
@ -1013,9 +1020,9 @@ void smf_sess_remove(smf_sess_t *sess)
|
|||
smf_ue = sess->smf_ue;
|
||||
ogs_assert(smf_ue);
|
||||
|
||||
ogs_info("Removed Session: UE IMSI:[%s] APN:[%s] IPv4:[%s] IPv6:[%s]",
|
||||
ogs_info("Removed Session: UE IMSI:[%s] DNN:[%s] IPv4:[%s] IPv6:[%s]",
|
||||
smf_ue->imsi_bcd,
|
||||
sess->pdn.apn,
|
||||
sess->pdn.dnn,
|
||||
sess->ipv4 ? OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "",
|
||||
sess->ipv6 ? OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : "");
|
||||
|
||||
|
@ -1068,6 +1075,9 @@ void smf_sess_remove(smf_sess_t *sess)
|
|||
|
||||
smf_bearer_remove_all(sess);
|
||||
|
||||
ogs_assert(sess->pfcp.bar);
|
||||
ogs_pfcp_bar_delete(sess->pfcp.bar);
|
||||
|
||||
ogs_pfcp_pool_final(&sess->pfcp);
|
||||
smf_qfi_pool_final(sess);
|
||||
|
||||
|
@ -1221,6 +1231,10 @@ smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess)
|
|||
dl_far->dst_if = OGS_PFCP_INTERFACE_ACCESS;
|
||||
ogs_pfcp_pdr_associate_far(dl_pdr, dl_far);
|
||||
|
||||
dl_far->apply_action =
|
||||
OGS_PFCP_APPLY_ACTION_BUFF| OGS_PFCP_APPLY_ACTION_NOCP;
|
||||
ogs_assert(sess->pfcp.bar);
|
||||
|
||||
ul_far = ogs_pfcp_far_add(&sess->pfcp);
|
||||
ogs_assert(ul_far);
|
||||
qos_flow->ul_far = ul_far;
|
||||
|
@ -1228,6 +1242,8 @@ smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess)
|
|||
ul_far->dst_if = OGS_PFCP_INTERFACE_CORE;
|
||||
ogs_pfcp_pdr_associate_far(ul_pdr, ul_far);
|
||||
|
||||
ul_far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||
|
||||
qer = ogs_pfcp_qer_add(&sess->pfcp);
|
||||
ogs_assert(qer);
|
||||
qos_flow->qer = qer;
|
||||
|
@ -1323,6 +1339,10 @@ smf_bearer_t *smf_bearer_add(smf_sess_t *sess)
|
|||
dl_far->dst_if = OGS_PFCP_INTERFACE_ACCESS;
|
||||
ogs_pfcp_pdr_associate_far(dl_pdr, dl_far);
|
||||
|
||||
dl_far->apply_action =
|
||||
OGS_PFCP_APPLY_ACTION_BUFF| OGS_PFCP_APPLY_ACTION_NOCP;
|
||||
ogs_assert(sess->pfcp.bar);
|
||||
|
||||
ul_far = ogs_pfcp_far_add(&sess->pfcp);
|
||||
ogs_assert(ul_far);
|
||||
bearer->ul_far = ul_far;
|
||||
|
@ -1330,6 +1350,8 @@ smf_bearer_t *smf_bearer_add(smf_sess_t *sess)
|
|||
ul_far->dst_if = OGS_PFCP_INTERFACE_CORE;
|
||||
ogs_pfcp_pdr_associate_far(ul_pdr, ul_far);
|
||||
|
||||
ul_far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||
|
||||
ogs_assert(sess->pfcp_node);
|
||||
if (sess->pfcp_node->up_function_features.ftup) {
|
||||
ul_pdr->f_teid.ch = 1;
|
||||
|
|
|
@ -135,6 +135,8 @@ void smf_gx_handle_cca_initial_request(
|
|||
dl_far = bearer->dl_far;
|
||||
ogs_assert(dl_far);
|
||||
|
||||
dl_far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||
|
||||
/* Set Outer Header Creation to the Default DL FAR */
|
||||
ogs_pfcp_ip_to_outer_header_creation(&bearer->sgw_s5u_ip,
|
||||
&dl_far->outer_header_creation, &dl_far->outer_header_creation_len);
|
||||
|
|
|
@ -91,6 +91,11 @@ ogs_pkbuf_t *smf_n4_build_session_establishment_request(
|
|||
i++;
|
||||
}
|
||||
|
||||
/* Create BAR */
|
||||
if (sess->pfcp.bar) {
|
||||
ogs_pfcp_build_create_bar(&req->create_bar, sess->pfcp.bar);
|
||||
}
|
||||
|
||||
/* PDN Type */
|
||||
req->pdn_type.presence = 1;
|
||||
req->pdn_type.u8 = sess->pdn.paa.pdn_type;
|
||||
|
@ -171,6 +176,7 @@ ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request(
|
|||
message->qer_id.u32 = qos_flow->qer->id;
|
||||
i++;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (modify_flags & OGS_PFCP_MODIFY_CREATE) {
|
||||
ogs_pfcp_pdrbuf_init();
|
||||
|
|
|
@ -154,6 +154,9 @@ void smf_5gc_n4_handle_session_establishment_response(
|
|||
if (!pdr)
|
||||
break;
|
||||
|
||||
if (pdr->src_if != OGS_PFCP_INTERFACE_ACCESS)
|
||||
continue;
|
||||
|
||||
ogs_assert(sess->pfcp_node);
|
||||
if (sess->pfcp_node->up_function_features.ftup &&
|
||||
pdr->f_teid_len) {
|
||||
|
@ -244,6 +247,9 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||
if (!pdr)
|
||||
break;
|
||||
|
||||
if (pdr->src_if != OGS_PFCP_INTERFACE_ACCESS)
|
||||
continue;
|
||||
|
||||
ogs_assert(sess->pfcp_node);
|
||||
if (sess->pfcp_node->up_function_features.ftup &&
|
||||
pdr->f_teid_len) {
|
||||
|
@ -419,6 +425,9 @@ void smf_epc_n4_handle_session_establishment_response(
|
|||
if (!pdr)
|
||||
break;
|
||||
|
||||
if (pdr->src_if != OGS_PFCP_INTERFACE_ACCESS)
|
||||
continue;
|
||||
|
||||
bearer = smf_bearer_find_by_pdr_id(sess, pdr->id);
|
||||
if (!bearer) {
|
||||
pfcp_cause_value = OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND;
|
||||
|
@ -521,6 +530,9 @@ void smf_epc_n4_handle_session_modification_response(
|
|||
if (!pdr)
|
||||
break;
|
||||
|
||||
if (pdr->src_if != OGS_PFCP_INTERFACE_ACCESS)
|
||||
continue;
|
||||
|
||||
ogs_assert(sess->pfcp_node);
|
||||
if (sess->pfcp_node->up_function_features.ftup &&
|
||||
pdr->f_teid_len) {
|
||||
|
|
|
@ -128,6 +128,8 @@ int ngap_handle_pdu_session_resource_setup_response_transfer(
|
|||
memcpy(&sess->gnb_n3_ip, &upf_n3_ip, sizeof(sess->gnb_n3_ip));
|
||||
sess->gnb_n3_teid = upf_n3_teid;
|
||||
|
||||
dl_far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||
|
||||
ogs_pfcp_ip_to_outer_header_creation(&sess->gnb_n3_ip,
|
||||
&dl_far->outer_header_creation, &dl_far->outer_header_creation_len);
|
||||
dl_far->outer_header_creation.teid = sess->gnb_n3_teid;
|
||||
|
|
|
@ -373,6 +373,8 @@ void smf_s5c_handle_create_bearer_response(
|
|||
dl_far = bearer->dl_far;
|
||||
ogs_assert(dl_far);
|
||||
|
||||
dl_far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||
|
||||
ogs_pfcp_ip_to_outer_header_creation(&bearer->sgw_s5u_ip,
|
||||
&dl_far->outer_header_creation, &dl_far->outer_header_creation_len);
|
||||
dl_far->outer_header_creation.teid = bearer->sgw_s5u_teid;
|
||||
|
|
|
@ -420,16 +420,11 @@ int upf_context_parse_config(void)
|
|||
return OGS_OK;
|
||||
}
|
||||
|
||||
upf_sess_t *upf_sess_add(ogs_pfcp_f_seid_t *cp_f_seid,
|
||||
const char *apn, uint8_t pdn_type, ogs_pfcp_ue_ip_addr_t *ue_ip)
|
||||
upf_sess_t *upf_sess_add(ogs_pfcp_f_seid_t *cp_f_seid)
|
||||
{
|
||||
char buf1[OGS_ADDRSTRLEN];
|
||||
char buf2[OGS_ADDRSTRLEN];
|
||||
upf_sess_t *sess = NULL;
|
||||
|
||||
ogs_assert(cp_f_seid);
|
||||
ogs_assert(apn);
|
||||
ogs_assert(ue_ip);
|
||||
|
||||
ogs_pool_alloc(&upf_sess_pool, &sess);
|
||||
ogs_assert(sess);
|
||||
|
@ -445,67 +440,12 @@ upf_sess_t *upf_sess_add(ogs_pfcp_f_seid_t *cp_f_seid,
|
|||
ogs_hash_set(self.sess_hash, &sess->smf_n4_seid,
|
||||
sizeof(sess->smf_n4_seid), sess);
|
||||
|
||||
/* Set APN */
|
||||
ogs_cpystrn(sess->pdn.apn, apn, OGS_MAX_APN_LEN+1);
|
||||
|
||||
/* Set PDN-Type and UE IP Address */
|
||||
sess->pdn.pdn_type = pdn_type;
|
||||
if (pdn_type == OGS_GTP_PDN_TYPE_IPV4) {
|
||||
if (ue_ip->ipv4 == 0) {
|
||||
ogs_error("Cannot support PDN-Type[%d] != [IPv4:%d, IPv6:%d]",
|
||||
pdn_type, ue_ip->ipv4, ue_ip->ipv6);
|
||||
goto cleanup;
|
||||
}
|
||||
sess->ipv4 = ogs_pfcp_ue_ip_alloc(
|
||||
AF_INET, apn, (uint8_t *)&(ue_ip->addr));
|
||||
ogs_assert(sess->ipv4);
|
||||
ogs_hash_set(self.ipv4_hash, sess->ipv4->addr, OGS_IPV4_LEN, sess);
|
||||
} else if (pdn_type == OGS_GTP_PDN_TYPE_IPV6) {
|
||||
if (ue_ip->ipv6 == 0) {
|
||||
ogs_error("Cannot support PDN-Type[%d] != [IPv4:%d, IPv6:%d]",
|
||||
pdn_type, ue_ip->ipv4, ue_ip->ipv6);
|
||||
goto cleanup;
|
||||
}
|
||||
sess->ipv6 = ogs_pfcp_ue_ip_alloc(AF_INET6, apn, ue_ip->addr6);
|
||||
ogs_assert(sess->ipv6);
|
||||
ogs_hash_set(self.ipv6_hash, sess->ipv6->addr, OGS_IPV6_LEN, sess);
|
||||
} else if (pdn_type == OGS_GTP_PDN_TYPE_IPV4V6) {
|
||||
if (ue_ip->ipv4 == 0 || ue_ip->ipv6 == 0) {
|
||||
ogs_error("Cannot support PDN-Type[%d] != [IPv4:%d, IPv6:%d]",
|
||||
pdn_type, ue_ip->ipv4, ue_ip->ipv6);
|
||||
goto cleanup;
|
||||
}
|
||||
sess->ipv4 = ogs_pfcp_ue_ip_alloc(
|
||||
AF_INET, apn, (uint8_t *)&(ue_ip->both.addr));
|
||||
ogs_assert(sess->ipv4);
|
||||
ogs_hash_set(self.ipv4_hash, sess->ipv4->addr, OGS_IPV4_LEN, sess);
|
||||
|
||||
sess->ipv6 = ogs_pfcp_ue_ip_alloc(AF_INET6, apn, ue_ip->both.addr6);
|
||||
ogs_assert(sess->ipv6);
|
||||
ogs_hash_set(self.ipv6_hash, sess->ipv6->addr, OGS_IPV6_LEN, sess);
|
||||
} else {
|
||||
ogs_error("Cannot support PDN-Type[%d] != [IPv4:%d, IPv6:%d]",
|
||||
pdn_type, ue_ip->ipv4, ue_ip->ipv6);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ogs_info("UE F-SEID[CP:0x%lx,UP:0x%lx] "
|
||||
"APN[%s] PDN-Type[%d] IPv4[%s] IPv6[%s]",
|
||||
(long)sess->upf_n4_seid, (long)sess->smf_n4_seid,
|
||||
apn, pdn_type,
|
||||
sess->ipv4 ? OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "",
|
||||
sess->ipv6 ? OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : "");
|
||||
|
||||
ogs_list_add(&self.sess_list, sess);
|
||||
|
||||
ogs_info("[Added] Number of UPF-Sessions is now %d",
|
||||
ogs_list_count(&self.sess_list));
|
||||
|
||||
return sess;
|
||||
|
||||
cleanup:
|
||||
ogs_pool_free(&upf_sess_pool, sess);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int upf_sess_remove(upf_sess_t *sess)
|
||||
|
@ -578,15 +518,10 @@ upf_sess_t *upf_sess_find_by_ipv6(uint32_t *addr6)
|
|||
upf_sess_t *upf_sess_add_by_message(ogs_pfcp_message_t *message)
|
||||
{
|
||||
upf_sess_t *sess = NULL;
|
||||
|
||||
ogs_pfcp_f_seid_t *f_seid = NULL;
|
||||
char apn[OGS_MAX_APN_LEN];
|
||||
ogs_pfcp_ue_ip_addr_t *addr = NULL;
|
||||
bool default_pdr_found = false;
|
||||
|
||||
ogs_pfcp_session_establishment_request_t *req =
|
||||
&message->pfcp_session_establishment_request;;
|
||||
int i;
|
||||
|
||||
f_seid = req->cp_f_seid.data;
|
||||
if (req->cp_f_seid.presence == 0 || f_seid == NULL) {
|
||||
|
@ -595,69 +530,80 @@ upf_sess_t *upf_sess_add_by_message(ogs_pfcp_message_t *message)
|
|||
}
|
||||
f_seid->seid = be64toh(f_seid->seid);
|
||||
|
||||
if (req->pdn_type.presence == 0) {
|
||||
ogs_error("No PDN Type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find the Default PDR :
|
||||
* - PDR ID is existed
|
||||
* - SDF Filter is NOT existed
|
||||
* - APN(Network Instance) is existed
|
||||
* - UE IP Address is existed
|
||||
* - Downlink PDR
|
||||
*/
|
||||
memset(apn, 0, sizeof(apn));
|
||||
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
|
||||
ogs_pfcp_tlv_create_pdr_t *message = &req->create_pdr[i];
|
||||
ogs_assert(message);
|
||||
if (message->presence == 0)
|
||||
continue;
|
||||
if (message->pdr_id.presence == 0)
|
||||
continue;
|
||||
if (message->pdi.presence == 0)
|
||||
continue;
|
||||
if (message->pdi.sdf_filter[0].presence) /* No SDF Filter */
|
||||
continue;
|
||||
if (message->pdi.network_instance.presence == 0)
|
||||
continue;
|
||||
if (message->pdi.ue_ip_address.presence == 0)
|
||||
continue;
|
||||
if (message->pdi.source_interface.presence == 0)
|
||||
continue;
|
||||
if (message->pdi.source_interface.u8 != OGS_PFCP_INTERFACE_CORE)
|
||||
continue;
|
||||
|
||||
ogs_fqdn_parse(apn,
|
||||
message->pdi.network_instance.data,
|
||||
message->pdi.network_instance.len);
|
||||
addr = message->pdi.ue_ip_address.data;
|
||||
|
||||
default_pdr_found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!default_pdr_found) {
|
||||
ogs_error("Cannot find Default PDR");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strlen(apn) == 0) {
|
||||
ogs_error("No APN in PDR");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!addr) {
|
||||
ogs_error("No UE IP Address in PDR");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sess = upf_sess_find_by_cp_seid(f_seid->seid);
|
||||
if (!sess) {
|
||||
sess = upf_sess_add(f_seid, apn, req->pdn_type.u8, addr);
|
||||
sess = upf_sess_add(f_seid);
|
||||
if (!sess) return NULL;
|
||||
}
|
||||
ogs_assert(sess);
|
||||
|
||||
return sess;
|
||||
}
|
||||
|
||||
void upf_sess_set_ue_ip(upf_sess_t *sess,
|
||||
uint8_t pdn_type, ogs_pfcp_pdr_t *pdr)
|
||||
{
|
||||
ogs_pfcp_ue_ip_addr_t *ue_ip = NULL;
|
||||
char buf1[OGS_ADDRSTRLEN];
|
||||
char buf2[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_assert(sess);
|
||||
ogs_assert(pdn_type);
|
||||
ogs_assert(pdr);
|
||||
ogs_assert(pdr->ue_ip_addr_len);
|
||||
ue_ip = &pdr->ue_ip_addr;
|
||||
ogs_assert(ue_ip);
|
||||
|
||||
/* Set PDN-Type and UE IP Address */
|
||||
sess->pdn.pdn_type = pdn_type;
|
||||
if (pdn_type == OGS_GTP_PDN_TYPE_IPV4) {
|
||||
if (ue_ip->ipv4 || pdr->dnn) {
|
||||
sess->ipv4 = ogs_pfcp_ue_ip_alloc(
|
||||
AF_INET, pdr->dnn, (uint8_t *)&(ue_ip->addr));
|
||||
ogs_assert(sess->ipv4);
|
||||
ogs_hash_set(self.ipv4_hash, sess->ipv4->addr, OGS_IPV4_LEN, sess);
|
||||
} else {
|
||||
ogs_warn("Cannot support PDN-Type[%d], [IPv4:%d IPv6:%d DNN:%s]",
|
||||
pdn_type, ue_ip->ipv4, ue_ip->ipv6, pdr->dnn ? pdr->dnn : "");
|
||||
}
|
||||
} else if (pdn_type == OGS_GTP_PDN_TYPE_IPV6) {
|
||||
if (ue_ip->ipv6 || pdr->dnn) {
|
||||
sess->ipv6 = ogs_pfcp_ue_ip_alloc(AF_INET6, pdr->dnn, ue_ip->addr6);
|
||||
ogs_assert(sess->ipv6);
|
||||
ogs_hash_set(self.ipv6_hash, sess->ipv6->addr, OGS_IPV6_LEN, sess);
|
||||
} else {
|
||||
ogs_warn("Cannot support PDN-Type[%d], [IPv4:%d IPv6:%d DNN:%s]",
|
||||
pdn_type, ue_ip->ipv4, ue_ip->ipv6, pdr->dnn ? pdr->dnn : "");
|
||||
}
|
||||
} else if (pdn_type == OGS_GTP_PDN_TYPE_IPV4V6) {
|
||||
if (ue_ip->ipv4 || pdr->dnn) {
|
||||
sess->ipv4 = ogs_pfcp_ue_ip_alloc(
|
||||
AF_INET, pdr->dnn, (uint8_t *)&(ue_ip->both.addr));
|
||||
ogs_assert(sess->ipv4);
|
||||
ogs_hash_set(self.ipv4_hash, sess->ipv4->addr, OGS_IPV4_LEN, sess);
|
||||
} else {
|
||||
ogs_warn("Cannot support PDN-Type[%d], [IPv4:%d IPv6:%d DNN:%s]",
|
||||
pdn_type, ue_ip->ipv4, ue_ip->ipv6, pdr->dnn ? pdr->dnn : "");
|
||||
}
|
||||
|
||||
if (ue_ip->ipv6 || pdr->dnn) {
|
||||
sess->ipv6 = ogs_pfcp_ue_ip_alloc(
|
||||
AF_INET6, pdr->dnn, ue_ip->both.addr6);
|
||||
ogs_assert(sess->ipv6);
|
||||
ogs_hash_set(self.ipv6_hash, sess->ipv6->addr, OGS_IPV6_LEN, sess);
|
||||
} else {
|
||||
ogs_warn("Cannot support PDN-Type[%d], [IPv4:%d IPv6:%d DNN:%s]",
|
||||
pdn_type, ue_ip->ipv4, ue_ip->ipv6, pdr->dnn ? pdr->dnn : "");
|
||||
}
|
||||
} else {
|
||||
ogs_warn("Cannot support PDN-Type[%d], [IPv4:%d IPv6:%d DNN:%s]",
|
||||
pdn_type, ue_ip->ipv4, ue_ip->ipv6, pdr->dnn ? pdr->dnn : "");
|
||||
}
|
||||
|
||||
ogs_info("UE F-SEID[CP:0x%lx,UP:0x%lx] "
|
||||
"APN[%s] PDN-Type[%d] IPv4[%s] IPv6[%s]",
|
||||
(long)sess->upf_n4_seid, (long)sess->smf_n4_seid,
|
||||
pdr->dnn, pdn_type,
|
||||
sess->ipv4 ? OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "",
|
||||
sess->ipv6 ? OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : "");
|
||||
}
|
||||
|
|
|
@ -88,8 +88,7 @@ int upf_context_parse_config(void);
|
|||
|
||||
upf_sess_t *upf_sess_add_by_message(ogs_pfcp_message_t *message);
|
||||
|
||||
upf_sess_t *upf_sess_add(ogs_pfcp_f_seid_t *f_seid,
|
||||
const char *apn, uint8_t pdn_type, ogs_pfcp_ue_ip_addr_t *ue_ip);
|
||||
upf_sess_t *upf_sess_add(ogs_pfcp_f_seid_t *f_seid);
|
||||
int upf_sess_remove(upf_sess_t *sess);
|
||||
void upf_sess_remove_all(void);
|
||||
upf_sess_t *upf_sess_find(uint32_t index);
|
||||
|
@ -98,6 +97,9 @@ upf_sess_t *upf_sess_find_by_up_seid(uint64_t seid);
|
|||
upf_sess_t *upf_sess_find_by_ipv4(uint32_t addr);
|
||||
upf_sess_t *upf_sess_find_by_ipv6(uint32_t *addr6);
|
||||
|
||||
void upf_sess_set_ue_ip(upf_sess_t *sess,
|
||||
uint8_t pdn_type, ogs_pfcp_pdr_t *pdr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -74,10 +74,10 @@ void upf_n4_handle_session_establishment_request(
|
|||
cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
|
||||
|
||||
if (!sess) {
|
||||
ogs_error("Invalid Message Format");
|
||||
ogs_error("No Context");
|
||||
ogs_pfcp_send_error_message(xact, 0,
|
||||
OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE,
|
||||
OGS_GTP_CAUSE_INVALID_MESSAGE_FORMAT, 0);
|
||||
OGS_PFCP_CAUSE_MANDATORY_IE_MISSING, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -107,23 +107,49 @@ void upf_n4_handle_session_establishment_request(
|
|||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||
goto cleanup;
|
||||
|
||||
ogs_pfcp_handle_create_bar(&sess->pfcp, &req->create_bar,
|
||||
&cause_value, &offending_ie_value);
|
||||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||
goto cleanup;
|
||||
|
||||
/* Setup GTP Node */
|
||||
ogs_list_for_each(&sess->pfcp.far_list, far)
|
||||
setup_gtp_node(far);
|
||||
|
||||
/* Setup UPF-N3-TEID & QFI Hash */
|
||||
for (i = 0; i < num_of_created_pdr; i++) {
|
||||
pdr = created_pdr[i];
|
||||
ogs_assert(pdr);
|
||||
|
||||
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) { /* Uplink */
|
||||
/* Setup UE IP address */
|
||||
if (req->pdn_type.presence && pdr->ue_ip_addr_len) {
|
||||
upf_sess_set_ue_ip(sess, req->pdn_type.u8, pdr);
|
||||
}
|
||||
|
||||
/* Setup UPF-N3-TEID & QFI Hash */
|
||||
if (pdr->f_teid_len) {
|
||||
if (ogs_pfcp_self()->up_function_features.ftup &&
|
||||
pdr->f_teid.ch) {
|
||||
|
||||
ogs_pfcp_pdr_t *choosed_pdr = NULL;
|
||||
|
||||
if (pdr->f_teid.chid) {
|
||||
choosed_pdr = ogs_pfcp_pdr_find_by_choose_id(
|
||||
&sess->pfcp, pdr->f_teid.choose_id);
|
||||
if (!choosed_pdr) {
|
||||
pdr->chid = true;
|
||||
pdr->choose_id = pdr->f_teid.choose_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (choosed_pdr) {
|
||||
pdr->f_teid_len = choosed_pdr->f_teid_len;
|
||||
memcpy(&pdr->f_teid, &choosed_pdr->f_teid, pdr->f_teid_len);
|
||||
|
||||
} else {
|
||||
ogs_pfcp_gtpu_resource_t *resource = NULL;
|
||||
resource = ogs_pfcp_gtpu_resource_find(
|
||||
&ogs_pfcp_self()->gtpu_resource_list,
|
||||
sess->pdn.apn, OGS_PFCP_INTERFACE_ACCESS);
|
||||
pdr->dnn, OGS_PFCP_INTERFACE_ACCESS);
|
||||
if (resource) {
|
||||
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
|
||||
&resource->info, &pdr->f_teid, &pdr->f_teid_len);
|
||||
|
@ -148,11 +174,11 @@ void upf_n4_handle_session_establishment_request(
|
|||
pdr->f_teid.teid = pdr->index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ogs_pfcp_pdr_hash_set(pdr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Send Buffered Packet to gNB/SGW */
|
||||
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
|
||||
|
@ -291,6 +317,16 @@ void upf_n4_handle_session_modification_request(
|
|||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||
goto cleanup;
|
||||
|
||||
ogs_pfcp_handle_create_bar(&sess->pfcp, &req->create_bar,
|
||||
&cause_value, &offending_ie_value);
|
||||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||
goto cleanup;
|
||||
|
||||
ogs_pfcp_handle_remove_bar(&sess->pfcp, &req->remove_bar,
|
||||
&cause_value, &offending_ie_value);
|
||||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||
goto cleanup;
|
||||
|
||||
/* Setup GTP Node */
|
||||
ogs_list_for_each(&sess->pfcp.far_list, far)
|
||||
setup_gtp_node(far);
|
||||
|
@ -300,14 +336,30 @@ void upf_n4_handle_session_modification_request(
|
|||
pdr = created_pdr[i];
|
||||
ogs_assert(pdr);
|
||||
|
||||
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) { /* Uplink */
|
||||
if (pdr->f_teid_len) {
|
||||
if (ogs_pfcp_self()->up_function_features.ftup &&
|
||||
pdr->f_teid.ch) {
|
||||
|
||||
ogs_pfcp_pdr_t *choosed_pdr = NULL;
|
||||
|
||||
if (pdr->f_teid.chid) {
|
||||
choosed_pdr = ogs_pfcp_pdr_find_by_choose_id(
|
||||
&sess->pfcp, pdr->f_teid.choose_id);
|
||||
if (!choosed_pdr) {
|
||||
pdr->chid = true;
|
||||
pdr->choose_id = pdr->f_teid.choose_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (choosed_pdr) {
|
||||
pdr->f_teid_len = choosed_pdr->f_teid_len;
|
||||
memcpy(&pdr->f_teid, &choosed_pdr->f_teid, pdr->f_teid_len);
|
||||
|
||||
} else {
|
||||
ogs_pfcp_gtpu_resource_t *resource = NULL;
|
||||
resource = ogs_pfcp_gtpu_resource_find(
|
||||
&ogs_pfcp_self()->gtpu_resource_list,
|
||||
sess->pdn.apn, OGS_PFCP_INTERFACE_ACCESS);
|
||||
pdr->dnn, OGS_PFCP_INTERFACE_ACCESS);
|
||||
if (resource) {
|
||||
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
|
||||
&resource->info, &pdr->f_teid, &pdr->f_teid_len);
|
||||
|
@ -332,11 +384,11 @@ void upf_n4_handle_session_modification_request(
|
|||
pdr->f_teid.teid = pdr->index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ogs_pfcp_pdr_hash_set(pdr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Send Buffered Packet to gNB/SGW */
|
||||
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
|
||||
|
|
|
@ -172,13 +172,13 @@ ogs_pfcp_pdr_t *upf_pdr_find_by_packet(ogs_pkbuf_t *pkt)
|
|||
if (pdr->src_if != OGS_PFCP_INTERFACE_CORE)
|
||||
continue;
|
||||
|
||||
/* Save the Fallback PDR : Lowest precedence downlink PDR */
|
||||
fallback_pdr = pdr;
|
||||
|
||||
/* Check if FAR is Downlink */
|
||||
if (far->dst_if != OGS_PFCP_INTERFACE_ACCESS)
|
||||
continue;
|
||||
|
||||
/* Save the Fallback PDR : Lowest precedence downlink PDR */
|
||||
fallback_pdr = pdr;
|
||||
|
||||
/* Check if Outer header creation */
|
||||
if (far->outer_header_creation.teid == 0)
|
||||
continue;
|
||||
|
@ -310,10 +310,12 @@ found:
|
|||
return pdr;
|
||||
}
|
||||
|
||||
ogs_assert(fallback_pdr);
|
||||
if (fallback_pdr) {
|
||||
ogs_debug("Found Session : Fallback PDR-ID[%d]", fallback_pdr->id);
|
||||
return fallback_pdr;
|
||||
}
|
||||
|
||||
ogs_error("No PDR in Session");
|
||||
} else {
|
||||
ogs_debug("No Session");
|
||||
}
|
||||
|
|
|
@ -72,16 +72,16 @@ static void test1_func(abts_case *tc, void *data)
|
|||
"},"
|
||||
"\"flow\" : ["
|
||||
"{ \"direction\" : 2,"
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 23454 to any 1-65535\","
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 23454 to assigned 1-65535\","
|
||||
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd31\" } },"
|
||||
"{ \"direction\" : 1,"
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to any 50020\","
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to assigned 50020\","
|
||||
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd30\" } },"
|
||||
"{ \"direction\" : 2,"
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 23455 to any 1-65535\","
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 23455 to assigned 1-65535\","
|
||||
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2f\" } },"
|
||||
"{ \"direction\" : 1,"
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to any 50021\","
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to assigned 50021\","
|
||||
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2e\" } }"
|
||||
"]"
|
||||
"}"
|
||||
|
|
|
@ -698,16 +698,16 @@ static void test2_func(abts_case *tc, void *data)
|
|||
"},"
|
||||
"\"flow\" : ["
|
||||
"{ \"direction\" : 2,"
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 23454 to any 1-65535\","
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 23454 to assigned 1-65535\","
|
||||
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd31\" } },"
|
||||
"{ \"direction\" : 1,"
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to any 50020\","
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to assigned 50020\","
|
||||
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd30\" } },"
|
||||
"{ \"direction\" : 2,"
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 23455 to any 1-65535\","
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 23455 to assigned 1-65535\","
|
||||
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2f\" } },"
|
||||
"{ \"direction\" : 1,"
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to any 50021\","
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to assigned 50021\","
|
||||
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2e\" } }"
|
||||
"]"
|
||||
"}"
|
||||
|
|
|
@ -85,16 +85,16 @@ static void test1_func(abts_case *tc, void *data)
|
|||
"},"
|
||||
"\"flow\" : ["
|
||||
"{ \"direction\" : 2,"
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 23454 to any 1-65535\","
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 23454 to assigned 1-65535\","
|
||||
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd31\" } },"
|
||||
"{ \"direction\" : 1,"
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to any 50020\","
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to assigned 50020\","
|
||||
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd30\" } },"
|
||||
"{ \"direction\" : 2,"
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 23455 to any 1-65535\","
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 23455 to assigned 1-65535\","
|
||||
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2f\" } },"
|
||||
"{ \"direction\" : 1,"
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to any 50021\","
|
||||
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to assigned 50021\","
|
||||
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2e\" } }"
|
||||
"]"
|
||||
"}"
|
||||
|
|
Loading…
Reference in New Issue