Adding support for static IP assignment in HSS (#306)

This commit is contained in:
Spencer Sevilla 2019-11-13 19:30:19 -10:00 committed by Sukchan Lee
parent cdbbbc500b
commit b994a8efbf
11 changed files with 245 additions and 29 deletions

View File

@ -261,7 +261,7 @@ int ogs_dict_s6a_entry(char *conffile)
struct local_rules_definition rules[] =
{
{ { .avp_vendor = 10415, .avp_name = "Context-Identifier" }, RULE_REQUIRED, -1, 1 },
{ { .avp_vendor = 10415, .avp_name = "Served-Party-IP-Address" }, RULE_OPTIONAL, -1, 1 },
{ { .avp_vendor = 10415, .avp_name = "Served-Party-IP-Address" }, RULE_OPTIONAL, -1, 2 },
{ { .avp_vendor = 10415, .avp_name = "PDN-Type" }, RULE_REQUIRED, -1, 1 },
{ { .avp_name = "Service-Selection" }, RULE_REQUIRED, -1, 1 },
{ { .avp_vendor = 10415, .avp_name = "EPS-Subscribed-QoS-Profile" }, RULE_OPTIONAL, -1, 1 },

View File

@ -60,6 +60,7 @@ struct dict_object *ogs_diam_s6a_apn_configuration = NULL;
struct dict_object *ogs_diam_s6a_max_bandwidth_ul = NULL;
struct dict_object *ogs_diam_s6a_max_bandwidth_dl = NULL;
struct dict_object *ogs_diam_s6a_pdn_type = NULL;
struct dict_object *ogs_diam_s6a_served_party_ip_address = NULL;
struct dict_object *ogs_diam_s6a_eps_subscribed_qos_profile = NULL;
struct dict_object *ogs_diam_s6a_qos_class_identifier = NULL;
struct dict_object *ogs_diam_s6a_allocation_retention_priority = NULL;
@ -119,6 +120,7 @@ int ogs_diam_s6a_init(void)
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "APN-Configuration", &ogs_diam_s6a_apn_configuration);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Service-Selection", &ogs_diam_s6a_service_selection);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "PDN-Type", &ogs_diam_s6a_pdn_type);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Served-Party-IP-Address", &ogs_diam_s6a_served_party_ip_address);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Subscription-Data", &ogs_diam_s6a_subscription_data);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Subscriber-Status", &ogs_diam_s6a_subscriber_status);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Network-Access-Mode", &ogs_diam_s6a_network_access_mode);

View File

@ -36,6 +36,7 @@ extern "C" {
#define OGS_DIAM_S6A_AVP_CODE_ALL_APN_CONFIG_INC_IND (1428)
#define OGS_DIAM_S6A_AVP_CODE_APN_CONFIGURATION (1430)
#define OGS_DIAM_S6A_AVP_CODE_MIP_HOME_AGENT_ADDRESS (334)
#define OGS_DIAM_S6A_AVP_CODE_SERVED_PARTY_IP_ADDRESS (848)
#define OGS_DIAM_S6A_RAT_TYPE_WLAN 0
#define OGS_DIAM_S6A_RAT_TYPE_VIRTUAL 1
@ -99,6 +100,7 @@ extern struct dict_object *ogs_diam_s6a_apn_configuration;
extern struct dict_object *ogs_diam_s6a_max_bandwidth_ul;
extern struct dict_object *ogs_diam_s6a_max_bandwidth_dl;
extern struct dict_object *ogs_diam_s6a_pdn_type;
extern struct dict_object *ogs_diam_s6a_served_party_ip_address;
extern struct dict_object *ogs_diam_s6a_eps_subscribed_qos_profile;
extern struct dict_object *ogs_diam_s6a_qos_class_identifier;
extern struct dict_object *ogs_diam_s6a_allocation_retention_priority;

View File

@ -8,6 +8,9 @@ display_help() {
echo " add {imsi key opc}: adds a user to the database with default values"
echo " remove {imsi}: removes a user from the database"
echo " reset: WIPES OUT the database and restores it to an empty default"
echo " static_ip {imsi ip4}: adds a static IP assignment to an already-existing user"
echo " static_ip6 {imsi ip6}: adds a static IPv6 assignment to an already-existing user"
echo " type {imsi type}: changes the PDN-Type of the first PDN: 0 = IPv4, 1 = IPv6, 2 = IPv4v6, 3 = v4 OR v6"
echo " help: displays this message and exits"
echo " default values are as follows: APN \"internet\", dl_bw/ul_bw 1 Gbps, PGW address is 127.0.0.3, IPv4 only"
}
@ -24,16 +27,27 @@ if [ "$1" = "help" ]; then
fi
if [ "$1" = "add" ]; then
if [ "$#" -ne 4 ]; then
echo "dbconf.sh: incorrect number of args, format is \"dbconf.sh add imsi key opc\""
exit 1
fi
IMSI=$2
KI=$3
OPC=$4
if [ "$#" -eq 4 ]; then
IMSI=$2
KI=$3
OPC=$4
mongo --eval "db.subscribers.update({\"imsi\" : \"$IMSI\"}, { \$setOnInsert: { \"imsi\" : \"$IMSI\", \"pdn\" : [ { \"apn\" : \"internet\", \"_id\" : new ObjectId(), \"pcc_rule\" : [ ], \"pgw\" : { \"addr\" : \"127.0.0.3\" }, \"ambr\" : { \"downlink\" : NumberLong(1024000), \"uplink\" : NumberLong(1024000) }, \"qos\" : { \"qci\" : NumberInt(9), \"arp\" : { \"priority_level\" : NumberInt(8), \"pre_emption_vulnerability\" : NumberInt(1), \"pre_emption_capability\" : NumberInt(0) } }, \"type\" : NumberInt(0) } ], \"ambr\" : { \"downlink\" : NumberLong(1024000), \"uplink\" : NumberLong(1024000) }, \"subscribed_rau_tau_timer\" : NumberInt(12), \"network_access_mode\" : NumberInt(2), \"subscriber_status\" : NumberInt(0), \"access_restriction_data\" : NumberInt(32), \"security\" : { \"k\" : \"$KI\", \"amf\" : \"8000\", \"op\" : null, \"opc\" : \"$OPC\" }, \"__v\" : 0 } }, upsert=true);" open5gs
exit 0
mongo --eval "db.subscribers.update({\"imsi\" : \"$IMSI\"}, { \$setOnInsert: { \"imsi\" : \"$IMSI\", \"pdn\" : [ { \"apn\" : \"internet\", \"_id\" : new ObjectId(), \"pcc_rule\" : [ ], \"pgw\" : { \"addr\" : \"127.0.0.3\" }, \"ambr\" : { \"downlink\" : NumberLong(1024000), \"uplink\" : NumberLong(1024000) }, \"qos\" : { \"qci\" : NumberInt(9), \"arp\" : { \"priority_level\" : NumberInt(8), \"pre_emption_vulnerability\" : NumberInt(1), \"pre_emption_capability\" : NumberInt(0) } }, \"type\" : NumberInt(0) } ], \"ambr\" : { \"downlink\" : NumberLong(1024000), \"uplink\" : NumberLong(1024000) }, \"subscribed_rau_tau_timer\" : NumberInt(12), \"network_access_mode\" : NumberInt(2), \"subscriber_status\" : NumberInt(0), \"access_restriction_data\" : NumberInt(32), \"security\" : { \"k\" : \"$KI\", \"amf\" : \"8000\", \"op\" : null, \"opc\" : \"$OPC\" }, \"__v\" : 0 } }, upsert=true);" open5gs
exit 0
fi
if [ "$#" -eq 5 ]; then
IMSI=$2
IP=$3
KI=$4
OPC=$5
mongo --eval "db.subscribers.update({\"imsi\" : \"$IMSI\"}, { \$setOnInsert: { \"imsi\" : \"$IMSI\", \"pdn\" : [ { \"apn\" : \"internet\", \"_id\" : new ObjectId(), \"pcc_rule\" : [ ], \"pgw\" : { \"addr\" : \"127.0.0.3\" }, \"ambr\" : { \"downlink\" : NumberLong(1024000), \"uplink\" : NumberLong(1024000) }, \"qos\" : { \"qci\" : NumberInt(9), \"arp\" : { \"priority_level\" : NumberInt(8), \"pre_emption_vulnerability\" : NumberInt(1), \"pre_emption_capability\" : NumberInt(0) } }, \"type\" : NumberInt(0), \"addr\" : \"$IP\" } ], \"ambr\" : { \"downlink\" : NumberLong(1024000), \"uplink\" : NumberLong(1024000) }, \"subscribed_rau_tau_timer\" : NumberInt(12), \"network_access_mode\" : NumberInt(2), \"subscriber_status\" : NumberInt(0), \"access_restriction_data\" : NumberInt(32), \"security\" : { \"k\" : \"$KI\", \"amf\" : \"8000\", \"op\" : null, \"opc\" : \"$OPC\" }, \"__v\" : 0 } }, upsert=true);" open5gs
exit 0
fi
echo "dbconf.sh: incorrect number of args, format is \"dbconf.sh add imsi key opc\""
exit 1
fi
if [ "$1" = "remove" ]; then
@ -57,4 +71,40 @@ if [ "$1" = "reset" ]; then
exit 0
fi
if [ "$1" = "static_ip" ]; then
if [ "$#" -ne 3 ]; then
echo "dbconf.sh: incorrect number of args, format is \"dbconf.sh static_ip imsi ip\""
exit 1
fi
IMSI=$2
IP=$3
mongo --eval "db.subscribers.update({\"imsi\": \"$IMSI\"},{\$set: { \"pdn.0.addr\": \"$IP\" }});" open5gs
exit 0
fi
if [ "$1" = "static_ip6" ]; then
if [ "$#" -ne 3 ]; then
echo "dbconf.sh: incorrect number of args, format is \"dbconf.sh static_ip6 imsi ip\""
exit 1
fi
IMSI=$2
IP=$3
mongo --eval "db.subscribers.update({\"imsi\": \"$IMSI\"},{\$set: { \"pdn.0.addr6\": \"$IP\" }});" open5gs
exit 0
fi
if [ "$1" = "type" ]; then
if [ "$#" -ne 3 ]; then
echo "dbconf.sh: incorrect number of args, format is \"dbconf.sh type imsi type\""
exit 1
fi
IMSI=$2
TYPE=$3
mongo --eval "db.subscribers.update({\"imsi\": \"$IMSI\"},{\$set: { \"pdn.0.type\": NumberInt($TYPE) }});" open5gs
exit 0
fi
display_help

View File

@ -630,6 +630,30 @@ int hss_db_subscription_data(
}
}
}
} else if (!strcmp(child2_key, "addr") && BSON_ITER_HOLDS_UTF8(&child2_iter)) {
ogs_ipsubnet_t ipsub;
const char *v = bson_iter_utf8(&child2_iter, &length);
rv = ogs_ipsubnet(&ipsub, v, NULL);
if (rv == OGS_OK) {
if (pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV6) {
pdn->paa.pdn_type = OGS_HSS_PDN_TYPE_IPV4V6;
} else {
pdn->paa.pdn_type = OGS_HSS_PDN_TYPE_IPV4;
}
pdn->paa.both.addr = ipsub.sub[0];
}
} else if (!strcmp(child2_key, "addr6") && BSON_ITER_HOLDS_UTF8(&child2_iter)) {
ogs_ipsubnet_t ipsub;
const char *v = bson_iter_utf8(&child2_iter, &length);
rv = ogs_ipsubnet(&ipsub, v, NULL);
if (rv == OGS_OK) {
if (pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4) {
pdn->paa.pdn_type = OGS_HSS_PDN_TYPE_IPV4V6;
} else {
pdn->paa.pdn_type = OGS_HSS_PDN_TYPE_IPV6;
}
memcpy(&(pdn->paa.both.addr6), ipsub.sub, OGS_IPV6_LEN);
}
}
}
pdn_index++;

View File

@ -446,7 +446,7 @@ static int hss_ogs_diam_s6a_ulr_cb( struct msg **msg, struct avp *avp,
for (i = 0; i < subscription_data.num_of_pdn; i++) {
/* Set the APN Configuration */
struct avp *apn_configuration, *context_identifier;
struct avp *pdn_type, *service_selection;
struct avp *pdn_type, *served_party_ip_address, *service_selection;
struct avp *eps_subscribed_qos_profile, *qos_class_identifier;
struct avp *allocation_retention_priority, *priority_level;
struct avp *pre_emption_capability, *pre_emption_vulnerability;
@ -481,6 +481,31 @@ static int hss_ogs_diam_s6a_ulr_cb( struct msg **msg, struct avp *avp,
MSG_BRW_LAST_CHILD, pdn_type);
ogs_assert(ret == 0);
/* Set Served-Party-IP-Address */
if ((pdn->pdn_type == OGS_HSS_PDN_TYPE_IPV4 || pdn->pdn_type == OGS_HSS_PDN_TYPE_IPV4V6) &&
(pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4 || pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4V6)) {
ret = fd_msg_avp_new(ogs_diam_s6a_served_party_ip_address, 0, &served_party_ip_address);
ogs_assert(ret == 0);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = pdn->paa.both.addr;
ret = fd_msg_avp_value_encode (&sin, served_party_ip_address);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(apn_configuration, MSG_BRW_LAST_CHILD, served_party_ip_address);
ogs_assert(ret == 0);
}
if ((pdn->pdn_type == OGS_HSS_PDN_TYPE_IPV6 || pdn->pdn_type == OGS_HSS_PDN_TYPE_IPV4V6) &&
(pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV6 || pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4V6)) {
ret = fd_msg_avp_new(ogs_diam_s6a_served_party_ip_address, 0, &served_party_ip_address);
ogs_assert(ret == 0);
sin6.sin6_family = AF_INET6;
memcpy(sin6.sin6_addr.s6_addr, pdn->paa.both.addr6, OGS_IPV6_LEN);
ret = fd_msg_avp_value_encode (&sin6, served_party_ip_address);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(apn_configuration, MSG_BRW_LAST_CHILD, served_party_ip_address);
ogs_assert(ret == 0);
}
/* Set Service-Selection */
ret = fd_msg_avp_new(ogs_diam_s6a_service_selection, 0,
&service_selection);

View File

@ -567,6 +567,7 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
unsigned long dur;
int error = 0;
int new;
ogs_sockaddr_t addr;
mme_event_t *e = NULL;
mme_ue_t *mme_ue = NULL;
@ -767,11 +768,47 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
if (avpch3) {
ret = fd_msg_avp_hdr(avpch3, &hdr);
pdn->pdn_type = hdr->avp_value->i32;
pdn->paa.pdn_type = pdn->pdn_type;
} else {
ogs_error("no_PDN-Type");
error++;
}
/* Served-Party-IP-Address parsing for any static IPs */
ret = fd_msg_browse(avpch2, MSG_BRW_FIRST_CHILD, &avpch3, NULL);
ogs_assert(ret == 0);
while (avpch3) {
ret = fd_msg_avp_hdr(avpch3, &hdr);
ogs_assert(ret == 0);
switch(hdr->avp_code) {
case OGS_DIAM_S6A_AVP_CODE_SERVED_PARTY_IP_ADDRESS:
ret = fd_msg_avp_value_interpret(avpch3, &addr.sa);
ogs_assert(ret == 0);
if (addr.ogs_sa_family == AF_INET) {
if (pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4) {
pdn->paa.addr = addr.sin.sin_addr.s_addr;
} else if (pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4V6) {
pdn->paa.both.addr = addr.sin.sin_addr.s_addr;
} else {
ogs_error("Warning: Received a static IPv4 address but PDN-Type does not include IPv4. Ignoring...");
}
} else if (addr.ogs_sa_family == AF_INET6) {
if (pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV6) {
memcpy(pdn->paa.addr6, addr.sin6.sin6_addr.s6_addr, OGS_IPV6_LEN);
} else if (pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4V6) {
memcpy(pdn->paa.both.addr6, addr.sin6.sin6_addr.s6_addr, OGS_IPV6_LEN);
} else {
ogs_error("Warning: Received a static IPv6 address but PDN-Type does not include IPv6. Ignoring...");
}
}
break;
default:
break;
}
fd_msg_browse(avpch3, MSG_BRW_NEXT, &avpch3, NULL);
}
ret = fd_avp_search_avp(avpch2,
ogs_diam_s6a_eps_subscribed_qos_profile, &avpch3);
ogs_assert(ret == 0);

View File

@ -164,6 +164,21 @@ int mme_s11_build_create_session_request(
}
req->pdn_type.presence = 1;
/* If we started with both addrs (IPV4V6) but the above code
* (pdn_type & sess->request_type) truncates us down to just one,
* we need to change position of addresses in struct. */
if (req->pdn_type.u8 == OGS_GTP_PDN_TYPE_IPV4 &&
pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4V6) {
uint32_t addr = pdn->paa.both.addr;
pdn->paa.addr = addr;
}
if (req->pdn_type.u8 == OGS_GTP_PDN_TYPE_IPV6 &&
pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4V6) {
uint8_t addr[16];
memcpy(&addr, pdn->paa.both.addr6, OGS_IPV6_LEN);
memcpy(pdn->paa.addr6, &addr, OGS_IPV6_LEN);
}
pdn->paa.pdn_type = req->pdn_type.u8;
req->pdn_address_allocation.data = &pdn->paa;
if (req->pdn_type.u8 == OGS_GTP_PDN_TYPE_IPV4)

View File

@ -573,6 +573,7 @@ int pgw_context_parse_config(void)
const char *mask_or_numbits = NULL;
const char *apn = NULL;
const char *dev = self.tun_ifname;
bool static_pool = false;
if (ogs_yaml_iter_type(&ue_pool_array) ==
YAML_MAPPING_NODE) {
@ -607,13 +608,17 @@ int pgw_context_parse_config(void)
apn = ogs_yaml_iter_value(&ue_pool_iter);
} else if (!strcmp(ue_pool_key, "dev")) {
dev = ogs_yaml_iter_value(&ue_pool_iter);
} else if (!strcmp(ue_pool_key, "static")) {
char *str = (char *)ogs_yaml_iter_value(&ue_pool_iter);
if (!strcmp(str, "true")) {
static_pool = true;
}
} else
ogs_warn("unknown key `%s`", ue_pool_key);
}
if (ipstr && mask_or_numbits) {
subnet = pgw_subnet_add(
ipstr, mask_or_numbits, apn, dev);
subnet = pgw_subnet_add(ipstr, mask_or_numbits, apn, dev, static_pool);
ogs_assert(subnet);
} else {
ogs_warn("Ignore : addr(%s/%s), apn(%s)",
@ -724,7 +729,7 @@ static void *sess_hash_keygen(uint8_t *out, int *out_len,
pgw_sess_t *pgw_sess_add(
uint8_t *imsi, int imsi_len, char *apn,
uint8_t pdn_type, uint8_t ebi)
uint8_t pdn_type, uint8_t ebi, ogs_paa_t *paa)
{
char buf1[OGS_ADDRSTRLEN];
char buf2[OGS_ADDRSTRLEN];
@ -760,12 +765,14 @@ pgw_sess_t *pgw_sess_add(
bearer->ebi = ebi;
sess->pdn.paa.pdn_type = pdn_type;
ogs_assert(pdn_type == paa->pdn_type);
if (pdn_type == OGS_GTP_PDN_TYPE_IPV4) {
sess->ipv4 = pgw_ue_ip_alloc(AF_INET, apn);
sess->ipv4 = pgw_ue_ip_alloc(AF_INET, apn, (uint8_t *)&(paa->addr));
ogs_assert(sess->ipv4);
sess->pdn.paa.addr = sess->ipv4->addr[0];
} else if (pdn_type == OGS_GTP_PDN_TYPE_IPV6) {
sess->ipv6 = pgw_ue_ip_alloc(AF_INET6, apn);
sess->ipv6 = pgw_ue_ip_alloc(AF_INET6, apn, (paa->addr6));
ogs_assert(sess->ipv6);
subnet6 = sess->ipv6->subnet;
@ -774,9 +781,9 @@ pgw_sess_t *pgw_sess_add(
sess->pdn.paa.len = subnet6->prefixlen;
memcpy(sess->pdn.paa.addr6, sess->ipv6->addr, OGS_IPV6_LEN);
} else if (pdn_type == OGS_GTP_PDN_TYPE_IPV4V6) {
sess->ipv4 = pgw_ue_ip_alloc(AF_INET, apn);
sess->ipv4 = pgw_ue_ip_alloc(AF_INET, apn, (uint8_t *)&(paa->both.addr));
ogs_assert(sess->ipv4);
sess->ipv6 = pgw_ue_ip_alloc(AF_INET6, apn);
sess->ipv6 = pgw_ue_ip_alloc(AF_INET6, apn, (paa->both.addr6));
ogs_assert(sess->ipv6);
subnet6 = sess->ipv6->subnet;
@ -887,6 +894,11 @@ pgw_sess_t *pgw_sess_add_by_message(ogs_gtp_message_t *message)
return NULL;
}
if (req->pdn_address_allocation.presence == 0) {
ogs_error("No PAA Type");
return NULL;
}
ogs_fqdn_parse(apn,
req->access_point_name.data, req->access_point_name.len);
@ -894,6 +906,8 @@ pgw_sess_t *pgw_sess_add_by_message(ogs_gtp_message_t *message)
apn, req->pdn_type.u8,
req->bearer_contexts_to_be_created.eps_bearer_id.u8);
ogs_paa_t *paa = (ogs_paa_t *)req->pdn_address_allocation.data;
/*
* 7.2.1 in 3GPP TS 29.274 Release 15
*
@ -920,7 +934,7 @@ pgw_sess_t *pgw_sess_add_by_message(ogs_gtp_message_t *message)
}
sess = pgw_sess_add(req->imsi.data, req->imsi.len, apn,
req->pdn_type.u8,
req->bearer_contexts_to_be_created.eps_bearer_id.u8);
req->bearer_contexts_to_be_created.eps_bearer_id.u8, paa);
ogs_assert(sess);
return sess;
@ -1253,19 +1267,57 @@ static pgw_subnet_t *find_subnet(int family, const char *apn)
return subnet;
}
pgw_ue_ip_t *pgw_ue_ip_alloc(int family, const char *apn)
pgw_ue_ip_t *pgw_ue_ip_alloc(int family, const char *apn, uint8_t *addr)
{
pgw_subnet_t *subnet = NULL;
pgw_ue_ip_t *ue_ip = NULL;
ogs_assert(apn);
subnet = find_subnet(family, apn);
ogs_assert(subnet);
ogs_pool_alloc(&subnet->pool, &ue_ip);
ogs_assert(ue_ip);
bool static_ip = 0;
int address_size = 0;
if (family == AF_INET) {
address_size = 4;
} else if (family == AF_INET6) {
address_size = 16;
} else {
ogs_error("unknown address family!");
ogs_assert(0);
}
// if address is all zeros, we are allocating dynamically
int i = 0;
for(i = 0; i < address_size; i++) {
if (addr[i] != 0) {
static_ip = 1;
break;
}
}
// mismatch error cases
if (!subnet->static_pool && static_ip) {
ogs_warn("HSS assigning static IP but PGW subnet is dynamic (default). Ignoring HSS-assigned IP and proceeding with dynamic allocation...");
}
if (subnet->static_pool && !static_ip) {
ogs_error("PGW subnet is static but HSS did not assign the UE an IP. Cannot proceed with assignment.");
ogs_assert(ue_ip);
return ue_ip;
}
// if assigning a static IP, do so. If not, assign dynamically!
if (subnet->static_pool) {
ue_ip = calloc(1, sizeof(pgw_ue_ip_t));
ue_ip->subnet = subnet;
memcpy(ue_ip->addr, addr, address_size);
} else {
ogs_pool_alloc(&subnet->pool, &ue_ip);
}
ogs_assert(ue_ip);
return ue_ip;
}
@ -1277,7 +1329,12 @@ int pgw_ue_ip_free(pgw_ue_ip_t *ue_ip)
subnet = ue_ip->subnet;
ogs_assert(subnet);
ogs_pool_free(&subnet->pool, ue_ip);
if (subnet->static_pool) {
free(ue_ip);
} else {
ogs_pool_free(&subnet->pool, ue_ip);
}
return OGS_OK;
}
@ -1350,7 +1407,7 @@ pgw_dev_t *pgw_dev_next(pgw_dev_t *dev)
pgw_subnet_t *pgw_subnet_add(
const char *ipstr, const char *mask_or_numbits,
const char *apn, const char *ifname)
const char *apn, const char *ifname, bool static_pool)
{
int rv;
pgw_dev_t *dev = NULL;
@ -1385,6 +1442,8 @@ pgw_subnet_t *pgw_subnet_add(
ogs_pool_init(&subnet->pool, ogs_config()->pool.sess);
subnet->static_pool = static_pool;
ogs_list_add(&self.subnet_list, subnet);
return subnet;

View File

@ -117,6 +117,7 @@ typedef struct pgw_subnet_s {
ogs_ipsubnet_t gw; /* Gateway : cafe::1 */
char apn[OGS_MAX_APN_LEN]; /* APN : "internet", "volte", .. */
bool static_pool; /* Does the pool assign addresses dynamically or statically via HSS */
int family; /* AF_INET or AF_INET6 */
uint8_t prefixlen; /* prefixlen */
OGS_POOL(pool, pgw_ue_ip_t);
@ -228,7 +229,8 @@ pgw_sess_t *pgw_sess_add_by_message(ogs_gtp_message_t *message);
pgw_sess_t *pgw_sess_add(
uint8_t *imsi, int imsi_len, char *apn,
uint8_t pdn_type, uint8_t ebi);
uint8_t pdn_type, uint8_t ebi, ogs_paa_t *addr);
int pgw_sess_remove(pgw_sess_t *sess);
void pgw_sess_remove_all(void);
pgw_sess_t *pgw_sess_find(uint32_t index);
@ -259,7 +261,7 @@ pgw_pf_t *pgw_pf_first(pgw_bearer_t *bearer);
pgw_pf_t *pgw_pf_next(pgw_pf_t *pf);
int pgw_ue_pool_generate(void);
pgw_ue_ip_t *pgw_ue_ip_alloc(int family, const char *apn);
pgw_ue_ip_t *pgw_ue_ip_alloc(int family, const char *apn, uint8_t *addr);
int pgw_ue_ip_free(pgw_ue_ip_t *ip);
pgw_dev_t *pgw_dev_add(const char *ifname);
@ -271,7 +273,7 @@ pgw_dev_t *pgw_dev_next(pgw_dev_t *dev);
pgw_subnet_t *pgw_subnet_add(
const char *ipstr, const char *mask_or_numbits,
const char *apn, const char *ifname);
const char *apn, const char *ifname, bool static_pool);
pgw_subnet_t *pgw_subnet_next(pgw_subnet_t *subnet);
int pgw_subnet_remove(pgw_subnet_t *subnet);
void pgw_subnet_remove_all(void);

View File

@ -185,7 +185,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
if (!subnet) {
ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data, pkbuf->len);
ogs_trace("[DROP] Cannot find subnet V:%d, IPv4:%p, IPv6:%p",
ogs_error("[DROP] Cannot find subnet V:%d, IPv4:%p, IPv6:%p",
ip_h->ip_v, sess->ipv4, sess->ipv6);
goto cleanup;
}