diff --git a/lib/core/include/core_network.h b/lib/core/include/core_network.h index 185e81e74..4a1960473 100644 --- a/lib/core/include/core_network.h +++ b/lib/core/include/core_network.h @@ -207,8 +207,7 @@ CORE_DECLARE(int) core_sctp_recvmsg(sock_id id, void *msg, size_t len, */ CORE_DECLARE(status_t) tun_open(sock_id *new, char *ifname, int is_tap); -CORE_DECLARE(status_t) tun_set_ip(sock_id id, - const char *ipstr, const char *mask_or_numbits); +CORE_DECLARE(status_t) tun_set_ip(sock_id id, ipsubnet_t *gw, ipsubnet_t *sub); /* * Send/Recv diff --git a/lib/core/src/unix/tun.c b/lib/core/src/unix/tun.c index 9211af03c..fd0fcfc9d 100644 --- a/lib/core/src/unix/tun.c +++ b/lib/core/src/unix/tun.c @@ -342,29 +342,20 @@ status_t tun_set_ipv6(sock_id id, ipsubnet_t *ipaddr, ipsubnet_t *ipsub) return CORE_OK; } -status_t tun_set_ip(sock_id id, const char *ipstr, const char *mask_or_numbits) +status_t tun_set_ip(sock_id id, ipsubnet_t *gw, ipsubnet_t *sub) { - ipsubnet_t ipaddr, ipsub; status_t rv; d_assert(id, return CORE_ERROR,); - d_assert(ipstr, return CORE_ERROR,); - d_assert(mask_or_numbits, return CORE_ERROR,); + d_assert(gw, return CORE_ERROR,); + d_assert(sub, return CORE_ERROR,); - rv = core_ipsubnet(&ipaddr, ipstr, NULL); - d_assert(rv == CORE_OK, return CORE_ERROR,); - - rv = core_ipsubnet(&ipsub, ipstr, mask_or_numbits); - d_assert(rv == CORE_OK, return CORE_ERROR,); - - if (ipsub.family == AF_INET) - { - rv = tun_set_ipv4(id, &ipaddr, &ipsub); - } + if (gw->family == AF_INET) + rv = tun_set_ipv4(id, gw, sub); + else if (gw->family == AF_INET6) + rv = tun_set_ipv6(id, gw, sub); else - { - rv = tun_set_ipv6(id, &ipaddr, &ipsub); - } + d_assert(0, return CORE_ERROR,); return rv; } diff --git a/src/pgw/pgw_context.c b/src/pgw/pgw_context.c index 34f7cb451..4f5a23794 100644 --- a/src/pgw/pgw_context.c +++ b/src/pgw/pgw_context.c @@ -1365,6 +1365,8 @@ pgw_subnet_t *pgw_subnet_add( d_assert(subnet, return NULL,); memset(subnet, 0, sizeof *subnet); + subnet->dev = dev; + rv = core_ipsubnet(&subnet->gw, ipstr, NULL); d_assert(rv == CORE_OK, return NULL,); diff --git a/src/pgw/pgw_context.h b/src/pgw/pgw_context.h index 2f8b8518c..7d88b2440 100644 --- a/src/pgw/pgw_context.h +++ b/src/pgw/pgw_context.h @@ -22,8 +22,9 @@ extern "C" { typedef struct _gtp_node_t gtp_node_t; typedef struct _pgw_context_t { - c_uint32_t gtpc_port; /* PGW GTP-C local port */ - c_uint32_t gtpu_port; /* PGW GTP-U local port */ + c_uint32_t gtpc_port; /* Default: PGW GTP-C local port */ + c_uint32_t gtpu_port; /* Default: PGW GTP-U local port */ + const char *tun_ifname; /* Default:: pgwtun */ list_t gtpc_list; /* PGW GTPC IPv4 Server List */ c_sockaddr_t *gtpc_addr; /* PGW GTPC IPv4 Address */ @@ -43,9 +44,6 @@ typedef struct _pgw_context_t { msgq_id queue_id; /* Qsesssess for processing PGW control plane */ tm_service_t tm_service; /* Timer Service */ - sock_id tun_sock; /* PGW Tun Interace for UE */ - const char *tun_ifname; /* default : pgwtun */ - #define MAX_NUM_OF_DNS 2 const char *dns[MAX_NUM_OF_DNS]; /* Primary/Secondanry */ const char *dns6[MAX_NUM_OF_DNS]; /* Primary/Secondanry */ diff --git a/src/pgw/pgw_gtp_path.c b/src/pgw/pgw_gtp_path.c index 8a8502867..756aac53f 100644 --- a/src/pgw/pgw_gtp_path.c +++ b/src/pgw/pgw_gtp_path.c @@ -15,7 +15,7 @@ c_uint16_t in_cksum(c_uint16_t *addr, int len); static status_t pgw_gtp_handle_multicast(pkbuf_t *recvbuf); -static status_t pgw_gtp_handle_slacc(c_uint32_t teid, pkbuf_t *recvbuf); +static status_t pgw_gtp_handle_slacc(pgw_sess_t *sess, pkbuf_t *recvbuf); static status_t pgw_gtp_send_to_bearer(pgw_bearer_t *bearer, pkbuf_t *sendbuf); static status_t pgw_gtp_send_router_advertisement(pgw_sess_t *sess); @@ -102,6 +102,13 @@ static int _gtpv1_u_recv_cb(sock_id sock, void *data) pkbuf_t *pkbuf = NULL; c_uint32_t size = GTPV1U_HEADER_LEN; gtp_header_t *gtp_h = NULL; + struct ip *ip_h = NULL; + + c_uint32_t teid; + pgw_bearer_t *bearer = NULL; + pgw_sess_t *sess = NULL; + pgw_subnet_t *subnet = NULL; + pgw_dev_t *dev = NULL; d_assert(sock, return -1, "Null param"); @@ -119,23 +126,32 @@ static int _gtpv1_u_recv_cb(sock_id sock, void *data) d_trace_hex(50, pkbuf->payload, pkbuf->len); - d_assert(pkbuf->payload, return 0,); + d_assert(pkbuf->payload, goto cleanup,); gtp_h = pkbuf->payload; if (gtp_h->flags & GTPU_FLAGS_S) size += 4; + teid = ntohl(gtp_h->teid); /* Remove GTP header and send packets to TUN interface */ - if (pkbuf_header(pkbuf, -size) != CORE_OK) - { - d_error("pkbuf_header error"); + d_assert(pkbuf_header(pkbuf, -size) == CORE_OK, goto cleanup,); - pkbuf_free(pkbuf); - return -1; - } + ip_h = pkbuf->payload; + d_assert(ip_h, goto cleanup,); + + bearer = pgw_bearer_find_by_pgw_s5u_teid(teid); + d_assert(bearer, goto cleanup,); + sess = bearer->sess; + d_assert(sess, goto cleanup,); + + if (ip_h->ip_v == 4 && sess->ipv4) + subnet = sess->ipv4->subnet; + else if (ip_h->ip_v == 6 && sess->ipv6) + subnet = sess->ipv6->subnet; + d_assert(subnet, goto cleanup,); /* Check IPv6 */ - if (context_self()->parameter.no_slaac == 0) + if (context_self()->parameter.no_slaac == 0 && ip_h->ip_v == 6) { - rv = pgw_gtp_handle_slacc(ntohl(gtp_h->teid), pkbuf); + rv = pgw_gtp_handle_slacc(sess, pkbuf); if (rv == PGW_GTP_HANDLED) { pkbuf_free(pkbuf); @@ -144,11 +160,12 @@ static int _gtpv1_u_recv_cb(sock_id sock, void *data) d_assert(rv == CORE_OK,, "pgw_gtp_handle_slacc() failed"); } - if (sock_write(pgw_self()->tun_sock, pkbuf->payload, pkbuf->len) <= 0) - { - d_error("Can not send packets to tuntap"); - } + dev = subnet->dev; + d_assert(dev, goto cleanup,); + if (sock_write(dev->sock, pkbuf->payload, pkbuf->len) <= 0) + d_error("sock_write() failed"); +cleanup: pkbuf_free(pkbuf); return 0; } @@ -156,9 +173,8 @@ static int _gtpv1_u_recv_cb(sock_id sock, void *data) status_t pgw_gtp_open() { status_t rv; -#if 0 - int i; -#endif + pgw_dev_t *dev = NULL; + pgw_subnet_t *subnet = NULL; int rc; rv = gtp_server_list(&pgw_self()->gtpc_list, _gtpv2_c_recv_cb); @@ -195,11 +211,22 @@ status_t pgw_gtp_open() */ /* Open Tun interface */ - rc = tun_open(&pgw_self()->tun_sock, (char *)pgw_self()->tun_ifname, 0); - if (rc != 0) + for (dev = pgw_dev_first(); dev; dev = pgw_dev_next(dev)) { - d_error("Can not open tun(dev : %s)", pgw_self()->tun_ifname); - return CORE_ERROR; + rc = tun_open(&dev->sock, (char *)dev->ifname, 0); + if (rc != 0) + { + d_error("tun_open(dev:%s) failed", dev->ifname); + return CORE_ERROR; + } + + rc = sock_register(dev->sock, _gtpv1_tun_recv_cb, NULL); + if (rc != 0) + { + d_error("sock_register(dev:%s) failed", dev->ifname); + sock_delete(dev->sock); + return CORE_ERROR; + } } /* @@ -213,45 +240,32 @@ status_t pgw_gtp_open() /* Set P-to-P IP address with Netmask * Note that Linux will skip this configuration */ -#if 0 - for (i = 0; i < pgw_self()->num_of_ue_pool; i++) + for (subnet = pgw_subnet_first(); subnet; subnet = pgw_subnet_next(subnet)) { - rc = tun_set_ip(pgw_self()->tun_sock, - pgw_self()->ue_pool[i].ipstr, - pgw_self()->ue_pool[i].mask_or_numbits); + d_assert(subnet->dev, return CORE_ERROR,); + rc = tun_set_ip(subnet->dev->sock, &subnet->gw, &subnet->sub); if (rc != 0) { - d_error("Can not configure tun(dev : %s for %s/%s)", - pgw_self()->tun_ifname, - pgw_self()->ue_pool[i].ipstr, - pgw_self()->ue_pool[i].mask_or_numbits); - + d_error("tun_set_ip(dev:%s) failed", subnet->dev->ifname); return CORE_ERROR; } } -#endif - - rc = sock_register(pgw_self()->tun_sock, _gtpv1_tun_recv_cb, NULL); - if (rc != 0) - { - d_error("Can not register tun(dev : %s)", - pgw_self()->tun_ifname); - sock_delete(pgw_self()->tun_sock); - return CORE_ERROR; - } return CORE_OK; } status_t pgw_gtp_close() { + pgw_dev_t *dev = NULL; + sock_delete_list(&pgw_self()->gtpc_list); sock_delete_list(&pgw_self()->gtpc_list6); sock_delete_list(&pgw_self()->gtpu_list); sock_delete_list(&pgw_self()->gtpu_list6); - sock_delete(pgw_self()->tun_sock); + for (dev = pgw_dev_first(); dev; dev = pgw_dev_next(dev)) + sock_delete(dev->sock); return CORE_OK; } @@ -294,11 +308,12 @@ static status_t pgw_gtp_handle_multicast(pkbuf_t *recvbuf) return CORE_OK; } -static status_t pgw_gtp_handle_slacc(c_uint32_t teid, pkbuf_t *recvbuf) +static status_t pgw_gtp_handle_slacc(pgw_sess_t *sess, pkbuf_t *recvbuf) { status_t rv; struct ip *ip_h = NULL; + d_assert(sess, return CORE_ERROR,); d_assert(recvbuf, return CORE_ERROR,); d_assert(recvbuf->payload, return CORE_ERROR,); ip_h = (struct ip *)recvbuf->payload; @@ -311,15 +326,6 @@ static status_t pgw_gtp_handle_slacc(c_uint32_t teid, pkbuf_t *recvbuf) (struct icmp6_hdr *)(recvbuf->payload + sizeof(struct ip6_hdr)); if (icmp_h->icmp6_type == ND_ROUTER_SOLICIT) { - pgw_bearer_t *bearer = NULL; - pgw_sess_t *sess = NULL; - - bearer = pgw_bearer_find_by_pgw_s5u_teid(teid); - d_assert(teid, return CORE_ERROR, - "cannot find teid = %d", teid); - sess = bearer->sess; - d_assert(sess, return CORE_ERROR,); - if (sess->ipv6) { rv = pgw_gtp_send_router_advertisement(sess);