GTP Loopback Test Module is Added.

1. ping(src:45.45.0.1, dst:45.45.0.1)
2. MME emulates GTP-U instead of eNB, and send GTP-U to the SGW
3. SGW relay to PGW using GTP-U
4. PGW TUN reponse ping reply
5. PGW sends GTP-U to the SGW
6. SGW sends GTP-U to the MME
7. GTP-U decapsulates and sends ping packet to the kernel
This commit is contained in:
Sukchan Lee 2017-10-15 00:45:49 +09:00
parent 1f14b132c2
commit 172266b0c5
8 changed files with 237 additions and 5 deletions

View File

@ -32,7 +32,7 @@ case $host in
;;
*-apple-darwin*)
OSDIR="unix"
OSPPCFLAGS="-DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK"
OSCPPFLAGS="-DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK"
;;
*)
OSDIR="unix"

View File

@ -266,6 +266,8 @@ CORE_DECLARE(int) net_fds_read_run(long timeout);
CORE_DECLARE(int) net_tuntap_open(net_link_t **net_link, char *tuntap_dev_name,
int is_tap);
CORE_DECLARE(int) net_tuntap_set_ipv4(c_uint32_t ip_addr, c_uint8_t bits);
CORE_DECLARE(int) net_tuntap_close(net_link_t *net_link);
#ifdef __cplusplus

View File

@ -1225,6 +1225,66 @@ cleanup:
#endif
}
int net_tuntap_set_ipv4(c_uint32_t ip_addr, c_uint8_t bits)
{
#if LINUX == 1
/* No root priviledge */
return 0;
#elif defined(DARWIN)
c_uint32_t mask_addr = htonl(0xffffffff << (32 - bits));
int sock = socket(AF_INET, SOCK_DGRAM, 0);
char *dev = "tun0";
struct ifaliasreq ifa;
struct ifreq ifr;
struct sockaddr_in addr;
struct sockaddr_in mask;
(void)memset(&ifa, '\0', sizeof ifa);
(void)strlcpy(ifa.ifra_name, dev, sizeof ifa.ifra_name);
(void)memset(&ifr, '\0', sizeof ifr);
(void)strlcpy(ifr.ifr_name, dev, sizeof ifr.ifr_name);
/* Delete previously assigned address */
(void)ioctl(sock, SIOCDIFADDR, &ifr);
/*
* Fill-in the destination address and netmask,
* but don't care of the broadcast address
*/
(void)memset(&addr, '\0', sizeof addr);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = ip_addr;
addr.sin_len = sizeof addr;
(void)memcpy(&ifa.ifra_addr, &addr, sizeof addr);
(void)memset(&mask, '\0', sizeof mask);
mask.sin_family = AF_INET;
mask.sin_addr.s_addr = mask_addr;
mask.sin_len = sizeof mask;
(void)memcpy(&ifa.ifra_mask, &mask, sizeof ifa.ifra_mask);
/* Simpler than calling SIOCSIFADDR and/or SIOCSIFBRDADDR */
if (ioctl(sock, SIOCSIFADDR, &ifa) == -1) {
d_error("Can't set IP/netmask");
return -1;
}
(void)memcpy(&ifr.ifr_addr, &addr, sizeof addr);
if (ioctl(sock, SIOCSIFDSTADDR, &ifr) == -1) {
d_error("Can't set IP/netmask");
return -1;
}
close(sock);
return 0;
#else
/* TODO */
return 0;
#endif /* LINUX != 1 */
}
#if LINUX == 1
int net_link_open(net_link_t **net_link, char *device, int proto)

View File

@ -192,6 +192,8 @@ status_t pgw_gtp_open()
{
int rc;
int i;
char buf[INET_ADDRSTRLEN];
/* NOTE : tun device can be created via following command.
*
@ -212,6 +214,20 @@ status_t pgw_gtp_open()
return CORE_ERROR;
}
for (i = 0; i < pgw_self()->num_of_ip_pool; i++)
{
rc = net_tuntap_set_ipv4(
pgw_self()->ip_pool[i].prefix, pgw_self()->ip_pool[i].mask);
if (rc != 0)
{
d_error("Can not configure tun(dev : %s for %s/%d)",
pgw_self()->tun_dev_name,
INET_NTOP(&pgw_self()->ip_pool[i].prefix, buf),
pgw_self()->ip_pool[i].mask);
return CORE_ERROR;
}
}
rc = net_register_link(pgw_self()->tun_link, _gtpv1_tun_recv_cb, NULL);
if (rc != 0)
{

View File

@ -81,7 +81,7 @@
IP_POOL :
{
CIDR: 45.45.45.0/24
CIDR: 45.45.0.1/24
}
DNS :

View File

@ -19,6 +19,7 @@ static void attach_test1(abts_case *tc, void *data)
{
status_t rv;
net_sock_t *sock;
net_sock_t *gtpu;
pkbuf_t *sendbuf;
pkbuf_t *recvbuf;
s1ap_message_t message;
@ -39,8 +40,8 @@ static void attach_test1(abts_case *tc, void *data)
char *_initial_context_setup_request =
"00090080d8000006 00000005c0010000 9d00080002000100 42000a183e800000"
"603e800000001800 8086000034008080 450009200f800a01 23d8000000017127"
"fcf13a9702074202 49064000f1105ba0 00485221c1010909 08696e7465726e65"
"7405012d2d2d015e 06fefeeeee030327 2980c22304030000 0480211002000010"
"a21f172602074202 49064000f1105ba0 00485221c1010909 08696e7465726e65"
"7405012d2d00015e 06fefeeeee030327 2980c22304030000 0480211002000010"
"8106080808088306 04040404000d0408 080808000d040404 0404500bf600f110"
"0002010000000153 12172c5949640125 006b000518000c00 00004900203311c6"
"03c6a6d67f695e5a c02bb75b381b693c 3893a6d932fd9182 3544e3e79b000000"
@ -138,6 +139,10 @@ static void attach_test1(abts_case *tc, void *data)
sock = tests1ap_enb_connect();
ABTS_PTR_NOTNULL(tc, sock);
/* eNB connects to SGW */
gtpu = testgtpu_enb_connect();
ABTS_PTR_NOTNULL(tc, gtpu);
/* Send S1-Setup Reqeust */
rv = tests1ap_build_setup_req(
&sendbuf, S1ap_ENB_ID_PR_macroENB_ID, 0x54f64);
@ -287,6 +292,19 @@ static void attach_test1(abts_case *tc, void *data)
ABTS_TRUE(tc, memcmp(recvbuf->payload+43, tmp+43, 3) == 0);
pkbuf_free(recvbuf);
core_sleep(time_from_msec(300));
/* Send GTP-U ICMP Packet */
rv = testgtpu_enb_send(gtpu);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
#if 0
/* Receive GTP-U ICMP Packet */
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
rc = testgtpu_enb_read(gtpu, recvbuf);
pkbuf_free(recvbuf);
#endif
/*****************************************************************
* Attach Request : Known GUTI, Integrity Protected, MAC Matched
* Send Initial-UE Message + Attach Request + PDN Connectivity */
@ -408,6 +426,10 @@ static void attach_test1(abts_case *tc, void *data)
rv = tests1ap_enb_close(sock);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
/* eNB disonncect from SGW */
rv = testgtpu_enb_close(gtpu);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
core_sleep(time_from_msec(300));
}

View File

@ -64,6 +64,133 @@ int tests1ap_enb_read(net_sock_t *sock, pkbuf_t *recvbuf)
return rc;
}
net_sock_t *testgtpu_enb_connect(void)
{
char buf[INET_ADDRSTRLEN];
int rc;
mme_context_t *mme = mme_self();
net_sock_t *sock = NULL;
if (!mme) return NULL;
rc = net_listen_ext(&sock, SOCK_DGRAM, IPPROTO_UDP,
0, mme->s1ap_addr, GTPV1_U_UDP_PORT);
if (rc != 0) return NULL;
return sock;
}
status_t testgtpu_enb_close(net_sock_t *sock)
{
return net_close(sock);
}
static uint16_t in_cksum(uint16_t *addr, int len)
{
int nleft = len;
uint32_t sum = 0;
uint16_t *w = addr;
uint16_t answer = 0;
// Adding 16 bits sequentially in sum
while (nleft > 1) {
sum += *w;
nleft -= 2;
w++;
}
// If an odd byte is left
if (nleft == 1) {
*(unsigned char *) (&answer) = *(unsigned char *) w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return answer;
}
int testgtpu_enb_send(net_sock_t *sock)
{
mme_sgw_t *sgw = mme_sgw_first();
if (!sgw) return -1;
status_t rv;
pkbuf_t *pkbuf = NULL;
gtp_header_t *gtp_h = NULL;
gtp_node_t gnode;
struct ip *ip_h = NULL;
struct icmp_header_t {
c_int8_t type;
c_int8_t code;
c_int16_t checksum;
union
{
struct
{
c_int16_t id;
c_int16_t sequence;
} echo; /* echo datagram */
u_int32_t gateway; /* gateway address */
struct
{
c_int16_t __glibc_reserved;
c_int16_t mtu;
} frag; /* path mtu discovery */
} un;
} *icmp_h = NULL;
pkbuf = pkbuf_alloc(0, 100 /* enough for ICMP; use smaller buffer */);
d_assert(pkbuf, return CORE_ERROR,);
memset(pkbuf->payload, 0, pkbuf->len);
gtp_h = (gtp_header_t *)pkbuf->payload;
ip_h = (struct ip *)(pkbuf->payload + GTPV1U_HEADER_LEN);
icmp_h = (struct icmp_header_t *)
(pkbuf->payload + GTPV1U_HEADER_LEN + sizeof(struct ip));
gtp_h->flags = 0x30;
gtp_h->type = GTPU_MSGTYPE_GPDU;
gtp_h->teid = htonl(1);
gtp_h->length = htons(sizeof(struct ip) + sizeof(struct icmp_header_t));
ip_h->ip_v = 4;
ip_h->ip_hl = 5;
ip_h->ip_tos = 0;
ip_h->ip_id = rand();
ip_h->ip_off = 0;
ip_h->ip_ttl = 255;
ip_h->ip_p = IPPROTO_ICMP;
ip_h->ip_len = gtp_h->length;
ip_h->ip_src.s_addr = inet_addr("45.45.0.1");
ip_h->ip_dst.s_addr = inet_addr("45.45.0.1");
ip_h->ip_sum = in_cksum(
(unsigned short *)ip_h, sizeof(struct ip));
icmp_h->type = 8;
icmp_h->un.echo.sequence = rand();
icmp_h->un.echo.id = rand();
icmp_h->checksum = in_cksum(
(unsigned short *)icmp_h, sizeof(struct icmp_header_t));
gnode.addr = sgw->addr;
gnode.port = GTPV1_U_UDP_PORT;
gnode.sock = sock;
rv = gtp_send(&gnode, pkbuf);
pkbuf_free(pkbuf);
if (rv != CORE_OK) return -1;
return 0;
}
int testgtpu_enb_read(net_sock_t *sock, pkbuf_t *recvbuf)
{
return tests1ap_enb_read(sock, recvbuf);
}
status_t tests1ap_build_setup_req(
pkbuf_t **pkbuf, S1ap_ENB_ID_PR present, c_uint32_t enb_id)
@ -507,7 +634,7 @@ status_t tests1ap_build_initial_context_setup_response(pkbuf_t **pkbuf, int i)
char *payload[TESTS1AP_MAX_MESSAGE] = {
"2009"
"0025000003000040 05c00100009d0008 400200010033400f 000032400a0a1f0a"
"012d2801000008",
"0123d700000001",
"",
"",

View File

@ -12,6 +12,11 @@ CORE_DECLARE(status_t) tests1ap_enb_close(net_sock_t *sock);
CORE_DECLARE(int) tests1ap_enb_send(net_sock_t *sock, pkbuf_t *sendbuf);
CORE_DECLARE(int) tests1ap_enb_read(net_sock_t *sock, pkbuf_t *recvbuf);
CORE_DECLARE(net_sock_t) *testgtpu_enb_connect(void);
CORE_DECLARE(status_t) testgtpu_enb_close(net_sock_t *sock);
CORE_DECLARE(int) testgtpu_enb_send(net_sock_t *sock);
CORE_DECLARE(int) testgtpu_enb_read(net_sock_t *sock, pkbuf_t *recvbuf);
CORE_DECLARE(status_t) tests1ap_build_setup_req(
pkbuf_t **pkbuf, S1ap_ENB_ID_PR present, c_uint32_t enb_id);
CORE_DECLARE(status_t) tests1ap_build_initial_ue_msg(pkbuf_t **pkbuf, int i);