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:
Sukchan Lee 2020-12-03 01:16:57 -05:00
parent b2d012c253
commit 33edd12335
33 changed files with 810 additions and 472 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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,30 +450,40 @@ void ogs_pfcp_build_create_far(
message->apply_action.presence = 1;
message->apply_action.u8 = far->apply_action;
message->forwarding_parameters.presence = 1;
message->forwarding_parameters.destination_interface.presence = 1;
message->forwarding_parameters.destination_interface.u8 =
far->dst_if;
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 =
far->dst_if;
if (far->outer_header_creation_len) {
memcpy(&farbuf[i].outer_header_creation,
&far->outer_header_creation, far->outer_header_creation_len);
farbuf[i].outer_header_creation.teid =
htobe32(far->outer_header_creation.teid);
if (far->outer_header_creation_len) {
memcpy(&farbuf[i].outer_header_creation,
&far->outer_header_creation, far->outer_header_creation_len);
farbuf[i].outer_header_creation.teid =
htobe32(far->outer_header_creation.teid);
message->forwarding_parameters.outer_header_creation.presence = 1;
message->forwarding_parameters.outer_header_creation.data =
&farbuf[i].outer_header_creation;
message->forwarding_parameters.outer_header_creation.len =
far->outer_header_creation_len;
message->forwarding_parameters.outer_header_creation.presence = 1;
message->forwarding_parameters.outer_header_creation.data =
&farbuf[i].outer_header_creation;
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->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)
{

View File

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

View File

@ -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)
{
@ -926,7 +943,7 @@ void ogs_pfcp_pdr_associate_far(ogs_pfcp_pdr_t *pdr, ogs_pfcp_far_t *far)
{
ogs_assert(pdr);
ogs_assert(far);
pdr->far = far;
}
void ogs_pfcp_pdr_associate_urr(ogs_pfcp_pdr_t *pdr, ogs_pfcp_urr_t *urr)
@ -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;
}

View File

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

View File

@ -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;
/* 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_in_message.flow_description_len+1);
sdf_filter.flow_description_len+1);
ogs_cpystrn(flow_description,
sdf_filter_in_message.flow_description,
sdf_filter_in_message.flow_description_len+1);
rule = ogs_pfcp_rule_add(pdr);
ogs_assert(rule);
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,67 +508,99 @@ 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;
/* 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_in_message.flow_description_len+1);
sdf_filter.flow_description_len+1);
ogs_cpystrn(flow_description,
sdf_filter_in_message.flow_description,
sdf_filter_in_message.flow_description_len+1);
sdf_filter.flow_description,
sdf_filter.flow_description_len+1);
rule = ogs_pfcp_rule_add(pdr);
ogs_assert(rule);
rv = ogs_ipfw_compile_rule(&rule->ipfw, flow_description);
ogs_assert(rv == OGS_OK);
/*
*
* TS29.244 Ch 5.2.1A.2A
*
* The UP function shall apply the SDF filter based on the Source Interface
* of the PDR as follows (see also clause 8.2.5):
*
* - when the Source Interface is CORE, this indicates that the filter is
* for downlink data flow, so the UP function shall apply
* the Flow Description as is;
*
* - when the Source Interface is ACCESS, this indicates that the filter is
* for uplink data flow, so the UP function shall swap the source and
* destination address/port in the Flow Description;
*
* - when the Source Interface is CP-function or SGi-LAN,
* the UP function shall use the Flow Description as is.
*
*
* Refer to lib/ipfw/ogs-ipfw.h
* Issue #338
*
* <DOWNLINK>
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
*
* <UPLINK>
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
*/
ogs_free(flow_description);
/*
*
* TS29.244 Ch 5.2.1A.2A
*
* The UP function shall apply the SDF filter based on the Source Interface
* of the PDR as follows (see also clause 8.2.5):
*
* - when the Source Interface is CORE, this indicates that the filter is
* for downlink data flow, so the UP function shall apply
* the Flow Description as is;
*
* - when the Source Interface is ACCESS, this indicates that the filter is
* for uplink data flow, so the UP function shall swap the source and
* destination address/port in the Flow Description;
*
* - when the Source Interface is CP-function or SGi-LAN,
* the UP function shall use the Flow Description as is.
*
*
* Refer to lib/ipfw/ogs-ipfw.h
* Issue #338
*
* <DOWNLINK>
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
*
* <UPLINK>
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
*/
/* 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,25 +694,28 @@ 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.outer_header_creation.presence) {
ogs_pfcp_tlv_outer_header_creation_t *outer_header_creation =
&message->forwarding_parameters.outer_header_creation;
if (message->forwarding_parameters.presence) {
if (message->forwarding_parameters.destination_interface.presence) {
far->dst_if =
message->forwarding_parameters.destination_interface.u8;
}
ogs_assert(outer_header_creation->data);
ogs_assert(outer_header_creation->len);
if (message->forwarding_parameters.outer_header_creation.presence) {
ogs_pfcp_tlv_outer_header_creation_t *outer_header_creation =
&message->forwarding_parameters.outer_header_creation;
ogs_assert(outer_header_creation->data);
ogs_assert(outer_header_creation->len);
memcpy(&far->outer_header_creation,
outer_header_creation->data, outer_header_creation->len);
far->outer_header_creation.teid =
be32toh(far->outer_header_creation.teid);
}
memcpy(&far->outer_header_creation,
outer_header_creation->data, outer_header_creation->len);
far->outer_header_creation.teid =
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;
}

View File

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

View File

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

View File

@ -480,23 +480,28 @@ 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;
};
union {
union {
uint32_t addr;
uint8_t addr6[OGS_IPV6_LEN];
struct {
struct {
ED4(uint8_t choose_id;,
uint8_t spare2;,
uint8_t spare3;,
uint8_t spare4;)
};
struct {
uint32_t teid;
union {
uint32_t addr;
uint8_t addr6[OGS_IPV6_LEN];
} both;
struct {
uint32_t addr;
uint8_t addr6[OGS_IPV6_LEN];
} 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 {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,32 +123,50 @@ 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_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_gtpu_resource_find(
&ogs_pfcp_self()->gtpu_resource_list,
sess->pdn.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);
if (resource->info.teidri)
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
resource->info.teid_range);
else
pdr->f_teid.teid = pdr->index;
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_sockaddr_t *addr = NULL, *addr6 = NULL;
ogs_pfcp_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_gtpu_resource_find(
&ogs_pfcp_self()->gtpu_resource_list,
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);
if (resource->info.teidri)
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
resource->info.teid_range);
else
pdr->f_teid.teid = pdr->index;
} else {
ogs_sockaddr_t *addr = NULL, *addr6 = NULL;
if (sgwu_self()->gtpu_sock)
addr = &sgwu_self()->gtpu_sock->local_addr;
if (sgwu_self()->gtpu_sock6)
addr6 = &sgwu_self()->gtpu_sock6->local_addr;
if (sgwu_self()->gtpu_sock)
addr = &sgwu_self()->gtpu_sock->local_addr;
if (sgwu_self()->gtpu_sock6)
addr6 = &sgwu_self()->gtpu_sock6->local_addr;
ogs_assert(addr || addr6);
ogs_pfcp_sockaddr_to_f_teid(
addr, addr6, &pdr->f_teid, &pdr->f_teid_len);
ogs_assert(addr || addr6);
ogs_pfcp_sockaddr_to_f_teid(
addr, addr6, &pdr->f_teid, &pdr->f_teid_len);
pdr->f_teid.teid = pdr->index;
pdr->f_teid.teid = pdr->index;
}
}
}
@ -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,32 +325,50 @@ 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_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_gtpu_resource_find(
&ogs_pfcp_self()->gtpu_resource_list,
sess->pdn.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);
if (resource->info.teidri)
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
resource->info.teid_range);
else
pdr->f_teid.teid = pdr->index;
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_sockaddr_t *addr = NULL, *addr6 = NULL;
ogs_pfcp_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_gtpu_resource_find(
&ogs_pfcp_self()->gtpu_resource_list,
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);
if (resource->info.teidri)
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
resource->info.teid_range);
else
pdr->f_teid.teid = pdr->index;
} else {
ogs_sockaddr_t *addr = NULL, *addr6 = NULL;
if (sgwu_self()->gtpu_sock)
addr = &sgwu_self()->gtpu_sock->local_addr;
if (sgwu_self()->gtpu_sock6)
addr6 = &sgwu_self()->gtpu_sock6->local_addr;
if (sgwu_self()->gtpu_sock)
addr = &sgwu_self()->gtpu_sock->local_addr;
if (sgwu_self()->gtpu_sock6)
addr6 = &sgwu_self()->gtpu_sock6->local_addr;
ogs_assert(addr || addr6);
ogs_pfcp_sockaddr_to_f_teid(
addr, addr6, &pdr->f_teid, &pdr->f_teid_len);
ogs_assert(addr || addr6);
ogs_pfcp_sockaddr_to_f_teid(
addr, addr6, &pdr->f_teid, &pdr->f_teid_len);
pdr->f_teid.teid = pdr->index;
pdr->f_teid.teid = pdr->index;
}
}
}

View File

@ -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(&gtpc_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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 */
if (pdr->f_teid_len) {
if (ogs_pfcp_self()->up_function_features.ftup &&
pdr->f_teid.ch) {
/* 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,9 +174,9 @@ void upf_n4_handle_session_establishment_request(
pdr->f_teid.teid = pdr->index;
}
}
ogs_pfcp_pdr_hash_set(pdr);
}
ogs_pfcp_pdr_hash_set(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,17 +336,33 @@ 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) {
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);
&resource->info, &pdr->f_teid, &pdr->f_teid_len);
if (resource->info.teidri)
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
@ -332,9 +384,9 @@ void upf_n4_handle_session_modification_request(
pdr->f_teid.teid = pdr->index;
}
}
ogs_pfcp_pdr_hash_set(pdr);
}
ogs_pfcp_pdr_hash_set(pdr);
}
}

View File

@ -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);
ogs_debug("Found Session : Fallback PDR-ID[%d]", fallback_pdr->id);
return 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");
}

View File

@ -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\" } }"
"]"
"}"

View File

@ -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\" } }"
"]"
"}"

View File

@ -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\" } }"
"]"
"}"