mirror of https://github.com/PentHertz/srsLTE.git
added support for optional ue static ip address (rebase #225)
This commit is contained in:
parent
185242d5f5
commit
fa99aa590e
|
@ -69,6 +69,7 @@ typedef struct {
|
||||||
uint8_t sqn[6];
|
uint8_t sqn[6];
|
||||||
uint16_t qci;
|
uint16_t qci;
|
||||||
uint8_t last_rand[16];
|
uint8_t last_rand[16];
|
||||||
|
std::string static_ip_addr;
|
||||||
} hss_ue_ctx_t;
|
} hss_ue_ctx_t;
|
||||||
|
|
||||||
class hss : public hss_interface_nas
|
class hss : public hss_interface_nas
|
||||||
|
@ -84,6 +85,8 @@ public:
|
||||||
|
|
||||||
virtual bool resync_sqn(uint64_t imsi, uint8_t* auts);
|
virtual bool resync_sqn(uint64_t imsi, uint8_t* auts);
|
||||||
|
|
||||||
|
std::map<std::string, uint64_t> get_ip_to_imsi() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
hss();
|
hss();
|
||||||
virtual ~hss();
|
virtual ~hss();
|
||||||
|
@ -125,6 +128,8 @@ private:
|
||||||
|
|
||||||
uint16_t mcc;
|
uint16_t mcc;
|
||||||
uint16_t mnc;
|
uint16_t mnc;
|
||||||
|
|
||||||
|
std::map<std::string, uint64_t> m_ip_to_imsi;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace srsepc
|
} // namespace srsepc
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "srsepc/hdr/spgw/spgw.h"
|
#include "srsepc/hdr/spgw/spgw.h"
|
||||||
#include "srslte/asn1/gtpc.h"
|
#include "srslte/asn1/gtpc.h"
|
||||||
#include "srslte/interfaces/epc_interfaces.h"
|
#include "srslte/interfaces/epc_interfaces.h"
|
||||||
|
#include <set>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
@ -39,16 +40,20 @@ class spgw::gtpc : public gtpc_interface_gtpu
|
||||||
public:
|
public:
|
||||||
gtpc();
|
gtpc();
|
||||||
virtual ~gtpc();
|
virtual ~gtpc();
|
||||||
int init(spgw_args_t* args, spgw* spgw, gtpu_interface_gtpc* gtpu, srslte::log_filter* gtpc_log);
|
int init(spgw_args_t* args,
|
||||||
|
spgw* spgw,
|
||||||
|
gtpu_interface_gtpc* gtpu,
|
||||||
|
srslte::log_filter* gtpc_log,
|
||||||
|
const std::map<std::string, uint64_t>& ip_to_imsi);
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
srslte::error_t init_s11(spgw_args_t *args);
|
srslte::error_t init_s11(spgw_args_t *args);
|
||||||
srslte::error_t init_ue_ip(spgw_args_t* args);
|
srslte::error_t init_ue_ip(spgw_args_t* args, const std::map<std::string, uint64_t>& ip_to_imsi);
|
||||||
|
|
||||||
int get_s11();
|
int get_s11();
|
||||||
uint64_t get_new_ctrl_teid();
|
uint64_t get_new_ctrl_teid();
|
||||||
uint64_t get_new_user_teid();
|
uint64_t get_new_user_teid();
|
||||||
in_addr_t get_new_ue_ipv4();
|
in_addr_t get_new_ue_ipv4(uint64_t imsi);
|
||||||
|
|
||||||
void handle_s11_pdu(srslte::byte_buffer_t* msg);
|
void handle_s11_pdu(srslte::byte_buffer_t* msg);
|
||||||
bool send_s11_pdu(const srslte::gtpc_pdu& pdu);
|
bool send_s11_pdu(const srslte::gtpc_pdu& pdu);
|
||||||
|
@ -90,6 +95,9 @@ public:
|
||||||
std::map<uint32_t, spgw_tunnel_ctx*> m_teid_to_tunnel_ctx; // Map control TEID to tunnel ctx. Usefull to get
|
std::map<uint32_t, spgw_tunnel_ctx*> m_teid_to_tunnel_ctx; // Map control TEID to tunnel ctx. Usefull to get
|
||||||
// reply ctrl TEID, UE IP, etc.
|
// reply ctrl TEID, UE IP, etc.
|
||||||
|
|
||||||
|
std::set<uint32_t> m_ue_ip_addr_pool;
|
||||||
|
std::map<uint64_t, struct in_addr> m_imsi_to_ip;
|
||||||
|
|
||||||
srslte::log_filter* m_gtpc_log;
|
srslte::log_filter* m_gtpc_log;
|
||||||
srslte::byte_buffer_pool* m_pool;
|
srslte::byte_buffer_pool* m_pool;
|
||||||
};
|
};
|
||||||
|
@ -109,17 +117,5 @@ inline uint64_t spgw::gtpc::get_new_user_teid()
|
||||||
return m_next_user_teid++;
|
return m_next_user_teid++;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline in_addr_t spgw::gtpc::get_new_ue_ipv4()
|
|
||||||
{
|
|
||||||
m_h_next_ue_ip++;
|
|
||||||
return ntohl(m_h_next_ue_ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline srslte::error_t spgw::gtpc::init_ue_ip(spgw_args_t* args)
|
|
||||||
{
|
|
||||||
m_h_next_ue_ip = ntohl(inet_addr(args->sgi_if_addr.c_str()));
|
|
||||||
return srslte::ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace srsepc
|
} // namespace srsepc
|
||||||
#endif // SRSEPC_SPGW_H
|
#endif // SRSEPC_SPGW_H
|
||||||
|
|
|
@ -75,7 +75,11 @@ class spgw : public thread
|
||||||
public:
|
public:
|
||||||
static spgw* get_instance(void);
|
static spgw* get_instance(void);
|
||||||
static void cleanup(void);
|
static void cleanup(void);
|
||||||
int init(spgw_args_t* args, srslte::log_filter* gtpu_log, srslte::log_filter* gtpc_log, srslte::log_filter* spgw_log);
|
int init(spgw_args_t* args,
|
||||||
|
srslte::log_filter* gtpu_log,
|
||||||
|
srslte::log_filter* gtpc_log,
|
||||||
|
srslte::log_filter* spgw_log,
|
||||||
|
const std::map<std::string, uint64_t>& ip_to_imsi);
|
||||||
void stop();
|
void stop();
|
||||||
void run_thread();
|
void run_thread();
|
||||||
|
|
||||||
|
@ -84,14 +88,6 @@ private:
|
||||||
virtual ~spgw();
|
virtual ~spgw();
|
||||||
static spgw* m_instance;
|
static spgw* m_instance;
|
||||||
|
|
||||||
srslte::error_t init_sgi_if(spgw_args_t* args);
|
|
||||||
srslte::error_t init_s1u(spgw_args_t* args);
|
|
||||||
srslte::error_t init_ue_ip(spgw_args_t* args);
|
|
||||||
|
|
||||||
uint64_t get_new_ctrl_teid();
|
|
||||||
uint64_t get_new_user_teid();
|
|
||||||
in_addr_t get_new_ue_ipv4();
|
|
||||||
|
|
||||||
spgw_tunnel_ctx_t* create_gtp_ctx(struct srslte::gtpc_create_session_request* cs_req);
|
spgw_tunnel_ctx_t* create_gtp_ctx(struct srslte::gtpc_create_session_request* cs_req);
|
||||||
bool delete_gtp_ctx(uint32_t ctrl_teid);
|
bool delete_gtp_ctx(uint32_t ctrl_teid);
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ bool hss::read_db_file(std::string db_filename)
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(m_db_file, line)) {
|
while (std::getline(m_db_file, line)) {
|
||||||
if (line[0] != '#') {
|
if (line[0] != '#') {
|
||||||
uint column_size = 9;
|
uint column_size = 10;
|
||||||
std::vector<std::string> split = split_string(line, ',');
|
std::vector<std::string> split = split_string(line, ',');
|
||||||
if (split.size() != column_size) {
|
if (split.size() != column_size) {
|
||||||
m_hss_log->error("Error parsing UE database. Wrong number of columns in .csv\n");
|
m_hss_log->error("Error parsing UE database. Wrong number of columns in .csv\n");
|
||||||
|
@ -166,6 +166,24 @@ bool hss::read_db_file(std::string db_filename)
|
||||||
m_hss_log->debug_hex(ue_ctx->sqn, 6, "SQN : ");
|
m_hss_log->debug_hex(ue_ctx->sqn, 6, "SQN : ");
|
||||||
ue_ctx->qci = atoi(split[8].c_str());
|
ue_ctx->qci = atoi(split[8].c_str());
|
||||||
m_hss_log->debug("Default Bearer QCI: %d\n", ue_ctx->qci);
|
m_hss_log->debug("Default Bearer QCI: %d\n", ue_ctx->qci);
|
||||||
|
|
||||||
|
if (split[9] == std::string("dynamic")) {
|
||||||
|
ue_ctx->static_ip_addr = "0.0.0.0";
|
||||||
|
} else {
|
||||||
|
char buf[128];
|
||||||
|
if (inet_ntop(AF_INET, split[9].c_str(), buf, sizeof(buf))) {
|
||||||
|
if (m_ip_to_imsi.insert(std::make_pair(split[8], ue_ctx->imsi)).second) {
|
||||||
|
ue_ctx->static_ip_addr = split[9];
|
||||||
|
m_hss_log->info("static ip addr %s\n", ue_ctx->static_ip_addr.c_str());
|
||||||
|
} else {
|
||||||
|
m_hss_log->info("duplicate static ip addr %s\n", split[9].c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_hss_log->info("invalid static ip addr %s, %s\n", split[9].c_str(), strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
m_imsi_to_ue_ctx.insert(std::pair<uint64_t, hss_ue_ctx_t*>(ue_ctx->imsi, ue_ctx));
|
m_imsi_to_ue_ctx.insert(std::pair<uint64_t, hss_ue_ctx_t*>(ue_ctx->imsi, ue_ctx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,6 +252,12 @@ bool hss::write_db_file(std::string db_filename)
|
||||||
m_db_file << hex_string(it->second->sqn, 6);
|
m_db_file << hex_string(it->second->sqn, 6);
|
||||||
m_db_file << ",";
|
m_db_file << ",";
|
||||||
m_db_file << it->second->qci;
|
m_db_file << it->second->qci;
|
||||||
|
if (it->second->static_ip_addr != "0.0.0.0") {
|
||||||
|
m_db_file << ",";
|
||||||
|
m_db_file << it->second->static_ip_addr;
|
||||||
|
} else {
|
||||||
|
m_db_file << ",dynamic";
|
||||||
|
}
|
||||||
m_db_file << std::endl;
|
m_db_file << std::endl;
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
|
@ -698,4 +722,10 @@ std::string hss::hex_string(uint8_t* hex, int size)
|
||||||
}
|
}
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<std::string, uint64_t> hss::get_ip_to_imsi(void) const
|
||||||
|
{
|
||||||
|
return m_ip_to_imsi;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace srsepc
|
} // namespace srsepc
|
||||||
|
|
|
@ -456,7 +456,7 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
spgw* spgw = spgw::get_instance();
|
spgw* spgw = spgw::get_instance();
|
||||||
if (spgw->init(&args.spgw_args, >pu_log, &spgw_gtpc_log, &spgw_log)) {
|
if (spgw->init(&args.spgw_args, >pu_log, &spgw_gtpc_log, &spgw_log, hss->get_ip_to_imsi())) {
|
||||||
cout << "Error initializing SP-GW" << endl;
|
cout << "Error initializing SP-GW" << endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,11 @@ spgw::gtpc::~gtpc()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int spgw::gtpc::init(spgw_args_t* args, spgw* spgw, gtpu_interface_gtpc* gtpu, srslte::log_filter* gtpc_log)
|
int spgw::gtpc::init(spgw_args_t* args,
|
||||||
|
spgw* spgw,
|
||||||
|
gtpu_interface_gtpc* gtpu,
|
||||||
|
srslte::log_filter* gtpc_log,
|
||||||
|
const std::map<std::string, uint64_t>& ip_to_imsi)
|
||||||
{
|
{
|
||||||
srslte::error_t err;
|
srslte::error_t err;
|
||||||
m_pool = srslte::byte_buffer_pool::get_instance();
|
m_pool = srslte::byte_buffer_pool::get_instance();
|
||||||
|
@ -74,7 +78,7 @@ int spgw::gtpc::init(spgw_args_t* args, spgw* spgw, gtpu_interface_gtpc* gtpu, s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init IP pool
|
// Init IP pool
|
||||||
err = init_ue_ip(args);
|
err = init_ue_ip(args, ip_to_imsi);
|
||||||
if (err != srslte::ERROR_NONE) {
|
if (err != srslte::ERROR_NONE) {
|
||||||
m_gtpc_log->console("Could not initialize the IP pool.\n");
|
m_gtpc_log->console("Could not initialize the IP pool.\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -442,7 +446,7 @@ spgw_tunnel_ctx_t* spgw::gtpc::create_gtpc_ctx(const struct srslte::gtpc_create_
|
||||||
// Setup uplink user TEID
|
// Setup uplink user TEID
|
||||||
uint64_t spgw_uplink_user_teid = get_new_user_teid();
|
uint64_t spgw_uplink_user_teid = get_new_user_teid();
|
||||||
// Allocate UE IP
|
// Allocate UE IP
|
||||||
in_addr_t ue_ip = get_new_ue_ipv4();
|
in_addr_t ue_ip = get_new_ue_ipv4(cs_req.imsi);
|
||||||
|
|
||||||
uint8_t default_bearer_id = 5;
|
uint8_t default_bearer_id = 5;
|
||||||
|
|
||||||
|
@ -535,4 +539,64 @@ bool spgw::gtpc::free_all_queued_packets(spgw_tunnel_ctx_t* tunnel_ctx)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srslte::error_t spgw::gtpc::init_ue_ip(spgw_args_t* args, const std::map<std::string, uint64_t>& ip_to_imsi)
|
||||||
|
{
|
||||||
|
std::map<std::string, uint64_t>::const_iterator iter = ip_to_imsi.find(args->sgi_if_addr);
|
||||||
|
|
||||||
|
// check for collision w/our ip address
|
||||||
|
if (iter != ip_to_imsi.end()) {
|
||||||
|
m_gtpc_log->error("SPGW: static ip addr %s for imsi %lu, is reserved for the epc tun interface\n",
|
||||||
|
iter->first.c_str(), iter->second);
|
||||||
|
return srslte::ERROR_OUT_OF_BOUNDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load our imsi to ip lookup table
|
||||||
|
for (std::map<std::string, uint64_t>::const_iterator iter = ip_to_imsi.begin(); iter != ip_to_imsi.end(); ++iter) {
|
||||||
|
struct in_addr in_addr;
|
||||||
|
in_addr.s_addr = inet_addr(iter->first.c_str());
|
||||||
|
if (!m_imsi_to_ip.insert(std::make_pair(iter->second, in_addr)).second) {
|
||||||
|
m_gtpc_log->error("SPGW: duplicate imsi %lu for static ip address %s.\n", iter->second, iter->first.c_str());
|
||||||
|
return srslte::ERROR_OUT_OF_BOUNDS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX TODO add an upper bound to ip addr range via config, use 254 for now
|
||||||
|
// first address is allocated to the epc tun interface, start w/next addr
|
||||||
|
for (uint32_t n = 1; n < 254; ++n) {
|
||||||
|
struct in_addr ue_addr;
|
||||||
|
ue_addr.s_addr = inet_addr(args->sgi_if_addr.c_str()) + htonl(n);
|
||||||
|
|
||||||
|
std::map<std::string, uint64_t>::const_iterator iter = ip_to_imsi.find(inet_ntoa(ue_addr));
|
||||||
|
if (iter != ip_to_imsi.end()) {
|
||||||
|
m_gtpc_log->debug("SPGW: init_ue_ip ue ip addr %s is reserved for imsi %lu, not adding to pool\n",
|
||||||
|
iter->first.c_str(), iter->second);
|
||||||
|
} else {
|
||||||
|
m_ue_ip_addr_pool.insert(ue_addr.s_addr);
|
||||||
|
m_gtpc_log->debug("SPGW: init_ue_ip ue ip addr %s is added to pool\n", inet_ntoa(ue_addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return srslte::ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_addr_t spgw::gtpc::get_new_ue_ipv4(uint64_t imsi)
|
||||||
|
{
|
||||||
|
struct in_addr ue_addr;
|
||||||
|
|
||||||
|
std::map<uint64_t, struct in_addr>::const_iterator iter = m_imsi_to_ip.find(imsi);
|
||||||
|
if (iter != m_imsi_to_ip.end()) {
|
||||||
|
ue_addr = iter->second;
|
||||||
|
m_gtpc_log->info("SPGW: get_new_ue_ipv4 static ip addr %s\n", inet_ntoa(ue_addr));
|
||||||
|
} else {
|
||||||
|
if (m_ue_ip_addr_pool.empty()) {
|
||||||
|
m_gtpc_log->error("SPGW: ue address pool is empty\n");
|
||||||
|
ue_addr.s_addr = 0;
|
||||||
|
} else {
|
||||||
|
ue_addr.s_addr = *m_ue_ip_addr_pool.begin();
|
||||||
|
m_ue_ip_addr_pool.erase(ue_addr.s_addr);
|
||||||
|
m_gtpc_log->info("SPGW: get_new_ue_ipv4 pool ip addr %s\n", inet_ntoa(ue_addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ue_addr.s_addr;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace srsepc
|
} // namespace srsepc
|
||||||
|
|
|
@ -70,10 +70,11 @@ void spgw::cleanup()
|
||||||
pthread_mutex_unlock(&spgw_instance_mutex);
|
pthread_mutex_unlock(&spgw_instance_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
int spgw::init(spgw_args_t* args,
|
int spgw::init(spgw_args_t* args,
|
||||||
srslte::log_filter* gtpu_log,
|
srslte::log_filter* gtpu_log,
|
||||||
srslte::log_filter* gtpc_log,
|
srslte::log_filter* gtpc_log,
|
||||||
srslte::log_filter* spgw_log)
|
srslte::log_filter* spgw_log,
|
||||||
|
const std::map<std::string, uint64_t>& ip_to_imsi)
|
||||||
{
|
{
|
||||||
srslte::error_t err;
|
srslte::error_t err;
|
||||||
m_pool = srslte::byte_buffer_pool::get_instance();
|
m_pool = srslte::byte_buffer_pool::get_instance();
|
||||||
|
@ -88,7 +89,7 @@ int spgw::init(spgw_args_t* args,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init GTP-C
|
// Init GTP-C
|
||||||
if (m_gtpc->init(args, this, m_gtpu, gtpc_log) != 0) {
|
if (m_gtpc->init(args, this, m_gtpu, gtpc_log, ip_to_imsi) != 0) {
|
||||||
m_spgw_log->console("Could not initialize the S1-U interface.\n");
|
m_spgw_log->console("Could not initialize the S1-U interface.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue