multiple device is added

This commit is contained in:
Sukchan Lee 2017-12-17 06:36:50 +00:00
parent 60804c79d6
commit 8d3330cb79
5 changed files with 72 additions and 76 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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,);

View File

@ -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 */

View File

@ -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);