Adding the ability to set the interface local link IPv6 address.
This commit is contained in:
parent
25108e2e2b
commit
ac1c300126
|
@ -105,6 +105,7 @@ class gw_interface_nas
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual srslte::error_t setup_if_addr(uint32_t ip_addr, char *err_str) = 0;
|
virtual srslte::error_t setup_if_addr(uint32_t ip_addr, char *err_str) = 0;
|
||||||
|
virtual srslte::error_t setup_if_addr6(uint8_t *ipv6_if_id, char *err_str) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// GW interface for RRC
|
// GW interface for RRC
|
||||||
|
|
|
@ -60,6 +60,7 @@ public:
|
||||||
|
|
||||||
// NAS interface
|
// NAS interface
|
||||||
srslte::error_t setup_if_addr(uint32_t ip_addr, char *err_str);
|
srslte::error_t setup_if_addr(uint32_t ip_addr, char *err_str);
|
||||||
|
srslte::error_t setup_if_addr6(uint8_t *ipv6_if_id, char *err_str);
|
||||||
|
|
||||||
// RRC interface
|
// RRC interface
|
||||||
void add_mch_port(uint32_t lcid, uint32_t port);
|
void add_mch_port(uint32_t lcid, uint32_t port);
|
||||||
|
@ -88,6 +89,7 @@ private:
|
||||||
bool if_up;
|
bool if_up;
|
||||||
|
|
||||||
uint32_t current_ip_addr;
|
uint32_t current_ip_addr;
|
||||||
|
uint8_t current_if_id[8];
|
||||||
|
|
||||||
long ul_tput_bytes;
|
long ul_tput_bytes;
|
||||||
long dl_tput_bytes;
|
long dl_tput_bytes;
|
||||||
|
|
|
@ -134,6 +134,7 @@ private:
|
||||||
bool auth_request;
|
bool auth_request;
|
||||||
|
|
||||||
uint32_t ip_addr;
|
uint32_t ip_addr;
|
||||||
|
uint8_t ipv6_if_id[8];
|
||||||
uint8_t eps_bearer_id;
|
uint8_t eps_bearer_id;
|
||||||
|
|
||||||
uint8_t chap_id;
|
uint8_t chap_id;
|
||||||
|
|
|
@ -86,7 +86,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
|
||||||
("rrc.ue_category", bpo::value<string>(&args->ue_category_str)->default_value("4"), "UE Category (1 to 5)")
|
("rrc.ue_category", bpo::value<string>(&args->ue_category_str)->default_value("4"), "UE Category (1 to 5)")
|
||||||
|
|
||||||
("nas.apn", bpo::value<string>(&args->nas.apn_name)->default_value(""), "Set Access Point Name (APN) for data services")
|
("nas.apn", bpo::value<string>(&args->nas.apn_name)->default_value(""), "Set Access Point Name (APN) for data services")
|
||||||
("nas.apn_protocol", bpo::value<string>(&args->nas.apn_protocol)->default_value("ipv4"), "Set Access Point Name (APN) protocol for data services")
|
("nas.apn_protocol", bpo::value<string>(&args->nas.apn_protocol)->default_value(""), "Set Access Point Name (APN) protocol for data services")
|
||||||
("nas.user", bpo::value<string>(&args->nas.apn_user)->default_value(""), "Username for CHAP authentication")
|
("nas.user", bpo::value<string>(&args->nas.apn_user)->default_value(""), "Username for CHAP authentication")
|
||||||
("nas.pass", bpo::value<string>(&args->nas.apn_pass)->default_value(""), "Password for CHAP authentication")
|
("nas.pass", bpo::value<string>(&args->nas.apn_pass)->default_value(""), "Password for CHAP authentication")
|
||||||
("nas.force_imsi_attach", bpo::value<bool>(&args->nas.force_imsi_attach)->default_value(false), "Whether to always perform an IMSI attach")
|
("nas.force_imsi_attach", bpo::value<bool>(&args->nas.force_imsi_attach)->default_value(false), "Whether to always perform an IMSI attach")
|
||||||
|
|
|
@ -37,6 +37,11 @@
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
struct in6_ifreq {
|
||||||
|
struct in6_addr ifr6_addr;
|
||||||
|
__u32 ifr6_prefixlen;
|
||||||
|
unsigned int ifr6_ifindex;
|
||||||
|
};
|
||||||
|
|
||||||
namespace srsue {
|
namespace srsue {
|
||||||
|
|
||||||
|
@ -165,29 +170,14 @@ void gw::write_pdu_mch(uint32_t lcid, srslte::byte_buffer_t *pdu)
|
||||||
struct in_addr dst_addr;
|
struct in_addr dst_addr;
|
||||||
memcpy(&dst_addr.s_addr, &pdu->msg[16],4);
|
memcpy(&dst_addr.s_addr, &pdu->msg[16],4);
|
||||||
|
|
||||||
if(!if_up)
|
if (!if_up) {
|
||||||
{
|
|
||||||
gw_log->warning("TUN/TAP not up - dropping gw RX message\n");
|
gw_log->warning("TUN/TAP not up - dropping gw RX message\n");
|
||||||
}else{
|
} else {
|
||||||
int n = write(tun_fd, pdu->msg, pdu->N_bytes);
|
int n = write(tun_fd, pdu->msg, pdu->N_bytes);
|
||||||
if(n > 0 && (pdu->N_bytes != (uint32_t)n))
|
if(n > 0 && (pdu->N_bytes != (uint32_t) n) ) {
|
||||||
{
|
|
||||||
gw_log->warning("DL TUN/TAP write failure\n");
|
gw_log->warning("DL TUN/TAP write failure\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
// Strip IP/UDP header
|
|
||||||
pdu->msg += 28;
|
|
||||||
pdu->N_bytes -= 28;
|
|
||||||
|
|
||||||
if(mbsfn_sock_fd) {
|
|
||||||
if(lcid > 0 && lcid < SRSLTE_N_MCH_LCIDS) {
|
|
||||||
mbsfn_sock_addr.sin_port = htons(mbsfn_ports[lcid]);
|
|
||||||
if(sendto(mbsfn_sock_fd, pdu->msg, pdu->N_bytes, MSG_EOR, (struct sockaddr*)&mbsfn_sock_addr, sizeof(struct sockaddr_in))<0) {
|
|
||||||
gw_log->error("Failed to send MCH PDU to port %d\n", mbsfn_ports[lcid]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
pool->deallocate(pdu);
|
pool->deallocate(pdu);
|
||||||
}
|
}
|
||||||
|
@ -241,6 +231,63 @@ srslte::error_t gw::setup_if_addr(uint32_t ip_addr, char *err_str)
|
||||||
return(srslte::ERROR_NONE);
|
return(srslte::ERROR_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srslte::error_t gw::setup_if_addr6(uint8_t *ipv6_if_id, char *err_str)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 sai;
|
||||||
|
struct in6_ifreq ifr6;
|
||||||
|
bool match = true;
|
||||||
|
|
||||||
|
for (int i=0; i<8; i++){
|
||||||
|
if(ipv6_if_id[i] != current_if_id[i]){
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
if (!if_up) {
|
||||||
|
if( init_if(err_str) ) {
|
||||||
|
gw_log->error("init_if failed\n");
|
||||||
|
return(srslte::ERROR_CANT_START);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the IP address
|
||||||
|
sock = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||||
|
ifr.ifr_addr.sa_family = AF_INET6;
|
||||||
|
|
||||||
|
if(inet_pton(AF_INET6, "fe80::", (void *)&sai.sin6_addr) <= 0) {
|
||||||
|
gw_log->error("Bad address\n");
|
||||||
|
return srslte::ERROR_CANT_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&sai.sin6_addr.s6_addr[8], ipv6_if_id, 8);
|
||||||
|
if (ioctl(sock, SIOGIFINDEX, &ifr) < 0) {
|
||||||
|
perror("SIOGIFINDEX");
|
||||||
|
return srslte::ERROR_CANT_START;
|
||||||
|
}
|
||||||
|
ifr6.ifr6_ifindex = ifr.ifr_ifindex;
|
||||||
|
ifr6.ifr6_prefixlen = 64;
|
||||||
|
memcpy((char *) &ifr6.ifr6_addr, (char *) &sai.sin6_addr,
|
||||||
|
sizeof(struct in6_addr));
|
||||||
|
|
||||||
|
if (ioctl(sock, SIOCSIFADDR, &ifr6) < 0) {
|
||||||
|
err_str = strerror(errno);
|
||||||
|
gw_log->error("Could not set IPv6 Link local address. Error %s\n", err_str);
|
||||||
|
return srslte::ERROR_CANT_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<8; i++){
|
||||||
|
current_if_id[i] = ipv6_if_id[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup a thread to receive packets from the TUN device
|
||||||
|
start(GW_THREAD_PRIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(srslte::ERROR_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
srslte::error_t gw::init_if(char *err_str)
|
srslte::error_t gw::init_if(char *err_str)
|
||||||
{
|
{
|
||||||
if(if_up)
|
if(if_up)
|
||||||
|
|
|
@ -653,6 +653,35 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) {
|
||||||
if (gw->setup_if_addr(ip_addr, err_str)) {
|
if (gw->setup_if_addr(ip_addr, err_str)) {
|
||||||
nas_log->error("Failed to set gateway address - %s\n", err_str);
|
nas_log->error("Failed to set gateway address - %s\n", err_str);
|
||||||
}
|
}
|
||||||
|
} else if (LIBLTE_MME_PDN_TYPE_IPV6 == act_def_eps_bearer_context_req.pdn_addr.pdn_type){
|
||||||
|
memcpy(ipv6_if_id, act_def_eps_bearer_context_req.pdn_addr.addr, 8);
|
||||||
|
nas_log->info("Network attach successful. APN: %s, IPv6 interface id: %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
|
||||||
|
act_def_eps_bearer_context_req.apn.apn,
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[0],
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[1],
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[2],
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[3],
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[4],
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[5],
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[6],
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[7]);
|
||||||
|
|
||||||
|
nas_log->console("Network attach successful. IPv6 interface Id: %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[0],
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[1],
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[2],
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[3],
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[4],
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[5],
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[6],
|
||||||
|
act_def_eps_bearer_context_req.pdn_addr.addr[7]);
|
||||||
|
// Setup GW
|
||||||
|
char *err_str = NULL;
|
||||||
|
if (gw->setup_if_addr6(ipv6_if_id, err_str)) {
|
||||||
|
nas_log->error("Failed to set gateway address - %s\n", err_str);
|
||||||
|
}
|
||||||
|
pool->deallocate(pdu);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
nas_log->error("Not handling IPV6 or IPV4V6\n");
|
nas_log->error("Not handling IPV6 or IPV4V6\n");
|
||||||
pool->deallocate(pdu);
|
pool->deallocate(pdu);
|
||||||
|
@ -1128,7 +1157,7 @@ void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg) {
|
||||||
pdn_con_req.apn_present = false;
|
pdn_con_req.apn_present = false;
|
||||||
|
|
||||||
//Set PDN protocol type
|
//Set PDN protocol type
|
||||||
if (cfg.apn_protocol == "ipv4"){
|
if (cfg.apn_protocol == "ipv4" || cfg.apn_protocol == ""){
|
||||||
nas_log->console("Setting PDN protocol to IPv4\n");
|
nas_log->console("Setting PDN protocol to IPv4\n");
|
||||||
pdn_con_req.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4;
|
pdn_con_req.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4;
|
||||||
} else if (cfg.apn_protocol == "ipv6") {
|
} else if (cfg.apn_protocol == "ipv6") {
|
||||||
|
|
|
@ -127,6 +127,7 @@ private:
|
||||||
class gw_dummy : public gw_interface_nas, public gw_interface_pdcp
|
class gw_dummy : public gw_interface_nas, public gw_interface_pdcp
|
||||||
{
|
{
|
||||||
error_t setup_if_addr(uint32_t ip_addr, char *err_str) { return ERROR_NONE; }
|
error_t setup_if_addr(uint32_t ip_addr, char *err_str) { return ERROR_NONE; }
|
||||||
|
error_t setup_if_addr6(uint8_t *ipv6_if_id, char *err_str) { return ERROR_NONE; }
|
||||||
void write_pdu(uint32_t lcid, byte_buffer_t *pdu) {}
|
void write_pdu(uint32_t lcid, byte_buffer_t *pdu) {}
|
||||||
void write_pdu_mch(uint32_t lcid, srslte::byte_buffer_t *sdu) {}
|
void write_pdu_mch(uint32_t lcid, srslte::byte_buffer_t *sdu) {}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue