kernel-gtp: support IPv6 on inner layer
Related: OS#6096 Change-Id: I3df47b6c209f1e2f8254ba139581d6e622c6b35f
This commit is contained in:
parent
0917ce4e22
commit
b17fe7bfe9
|
@ -8,3 +8,4 @@
|
||||||
# If any interfaces have been removed or changed since the last public release: c:r:0.
|
# If any interfaces have been removed or changed since the last public release: c:r:0.
|
||||||
#library what description / commit summary line
|
#library what description / commit summary line
|
||||||
libgtp REMOVE remove GTP cause defines of reserved values
|
libgtp REMOVE remove GTP cause defines of reserved values
|
||||||
|
libgtpnl > 1.2.5 gtp_tunnel_set_family()
|
||||||
|
|
|
@ -202,11 +202,6 @@ int apn_start(struct apn_ctx *apn)
|
||||||
break;
|
break;
|
||||||
case APN_GTPU_MODE_KERNEL_GTP:
|
case APN_GTPU_MODE_KERNEL_GTP:
|
||||||
LOGPAPN(LOGL_INFO, apn, "Opening Kernel GTP device %s\n", apn->tun.cfg.dev_name);
|
LOGPAPN(LOGL_INFO, apn, "Opening Kernel GTP device %s\n", apn->tun.cfg.dev_name);
|
||||||
if (apn->cfg.apn_type_mask & (APN_TYPE_IPv6|APN_TYPE_IPv4v6)) {
|
|
||||||
LOGPAPN(LOGL_ERROR, apn, "Kernel GTP currently supports only IPv4\n");
|
|
||||||
apn_stop(apn);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (gsn == NULL) {
|
if (gsn == NULL) {
|
||||||
/* skip bringing up the APN now if the GSN is not initialized yet.
|
/* skip bringing up the APN now if the GSN is not initialized yet.
|
||||||
* This happens during initial load of the config file, as the
|
* This happens during initial load of the config file, as the
|
||||||
|
@ -536,8 +531,7 @@ int create_context_ind(struct pdp_t *pdp)
|
||||||
|
|
||||||
in46a_to_eua(addr, num_addr, &pdp->eua);
|
in46a_to_eua(addr, num_addr, &pdp->eua);
|
||||||
|
|
||||||
if (apn->cfg.gtpu_mode == APN_GTPU_MODE_KERNEL_GTP && apn_supports_ipv4(apn)) {
|
if (apn->cfg.gtpu_mode == APN_GTPU_MODE_KERNEL_GTP) {
|
||||||
/* TODO: In IPv6, EUA doesn't contain the actual IP addr/prefix! */
|
|
||||||
if (gtp_kernel_tunnel_add(pdp, apn->tun.cfg.dev_name) < 0) {
|
if (gtp_kernel_tunnel_add(pdp, apn->tun.cfg.dev_name) < 0) {
|
||||||
LOGPPDP(LOGL_ERROR, pdp, "Cannot add tunnel to kernel: %s\n", strerror(errno));
|
LOGPPDP(LOGL_ERROR, pdp, "Cannot add tunnel to kernel: %s\n", strerror(errno));
|
||||||
gtp_create_context_resp(gsn, pdp, GTPCAUSE_SYS_FAIL);
|
gtp_create_context_resp(gsn, pdp, GTPCAUSE_SYS_FAIL);
|
||||||
|
|
100
lib/gtp-kernel.c
100
lib/gtp-kernel.c
|
@ -104,61 +104,93 @@ void gtp_kernel_stop(const char *devname)
|
||||||
|
|
||||||
int gtp_kernel_tunnel_add(struct pdp_t *pdp, const char *devname)
|
int gtp_kernel_tunnel_add(struct pdp_t *pdp, const char *devname)
|
||||||
{
|
{
|
||||||
struct in_addr ms, sgsn;
|
int ms_addr_count;
|
||||||
|
struct in46_addr ms[2];
|
||||||
|
struct in46_addr sgsn;
|
||||||
struct gtp_tunnel *t;
|
struct gtp_tunnel *t;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
pdp_debug(__func__, devname, pdp);
|
pdp_debug(__func__, devname, pdp);
|
||||||
|
|
||||||
t = gtp_tunnel_alloc();
|
in46a_from_gsna(&pdp->gsnrc, &sgsn);
|
||||||
if (t == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
memcpy(&ms, &pdp->eua.v[2], sizeof(struct in_addr));
|
ms_addr_count = in46a_from_eua(&pdp->eua, ms);
|
||||||
memcpy(&sgsn, &pdp->gsnrc.v[0], sizeof(struct in_addr));
|
|
||||||
|
|
||||||
gtp_tunnel_set_ifidx(t, if_nametoindex(devname));
|
for (int i = 0; i < ms_addr_count; i++) {
|
||||||
gtp_tunnel_set_version(t, pdp->version);
|
t = gtp_tunnel_alloc();
|
||||||
gtp_tunnel_set_ms_ip4(t, &ms);
|
if (t == NULL)
|
||||||
gtp_tunnel_set_sgsn_ip4(t, &sgsn);
|
return -1;
|
||||||
if (pdp->version == 0) {
|
|
||||||
gtp_tunnel_set_tid(t, pdp_gettid(pdp->imsi, pdp->nsapi));
|
gtp_tunnel_set_ifidx(t, if_nametoindex(devname));
|
||||||
gtp_tunnel_set_flowid(t, pdp->flru);
|
gtp_tunnel_set_version(t, pdp->version);
|
||||||
} else {
|
|
||||||
gtp_tunnel_set_i_tei(t, pdp->teid_own);
|
if (in46a_to_af(&ms[i]) == AF_INET)
|
||||||
/* use the TEI advertised by SGSN when sending packets
|
gtp_tunnel_set_ms_ip4(t, &ms[i].v4);
|
||||||
* towards the SGSN */
|
else {
|
||||||
gtp_tunnel_set_o_tei(t, pdp->teid_gn);
|
/* In IPv6, EUA doesn't contain the actual IP
|
||||||
|
* addr/prefix. Set higher bits to 0 to get the 64 bit
|
||||||
|
* netmask. */
|
||||||
|
memset(((void *)&ms[i].v6) + 8, 0, 8);
|
||||||
|
gtp_tunnel_set_ms_ip6(t, &ms[i].v6);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in46a_to_af(&sgsn) == AF_INET)
|
||||||
|
gtp_tunnel_set_sgsn_ip4(t, &sgsn.v4);
|
||||||
|
else
|
||||||
|
gtp_tunnel_set_sgsn_ip6(t, &sgsn.v6);
|
||||||
|
|
||||||
|
if (pdp->version == 0) {
|
||||||
|
gtp_tunnel_set_tid(t, pdp_gettid(pdp->imsi, pdp->nsapi));
|
||||||
|
gtp_tunnel_set_flowid(t, pdp->flru);
|
||||||
|
} else {
|
||||||
|
gtp_tunnel_set_i_tei(t, pdp->teid_own);
|
||||||
|
/* use the TEI advertised by SGSN when sending packets
|
||||||
|
* towards the SGSN */
|
||||||
|
gtp_tunnel_set_o_tei(t, pdp->teid_gn);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gtp_add_tunnel(gtp_nl.genl_id, gtp_nl.nl, t);
|
||||||
|
gtp_tunnel_free(t);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gtp_add_tunnel(gtp_nl.genl_id, gtp_nl.nl, t);
|
|
||||||
gtp_tunnel_free(t);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gtp_kernel_tunnel_del(struct pdp_t *pdp, const char *devname)
|
int gtp_kernel_tunnel_del(struct pdp_t *pdp, const char *devname)
|
||||||
{
|
{
|
||||||
|
int ms_addr_count;
|
||||||
|
struct in46_addr ms[2];
|
||||||
struct gtp_tunnel *t;
|
struct gtp_tunnel *t;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
pdp_debug(__func__, devname, pdp);
|
pdp_debug(__func__, devname, pdp);
|
||||||
|
|
||||||
t = gtp_tunnel_alloc();
|
ms_addr_count = in46a_from_eua(&pdp->eua, ms);
|
||||||
if (t == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
gtp_tunnel_set_ifidx(t, if_nametoindex(devname));
|
for (int i = 0; i < ms_addr_count; i++) {
|
||||||
gtp_tunnel_set_version(t, pdp->version);
|
t = gtp_tunnel_alloc();
|
||||||
if (pdp->version == 0) {
|
if (t == NULL)
|
||||||
gtp_tunnel_set_tid(t, pdp_gettid(pdp->imsi, pdp->nsapi));
|
return -1;
|
||||||
gtp_tunnel_set_flowid(t, pdp->flru);
|
|
||||||
} else {
|
gtp_tunnel_set_ifidx(t, if_nametoindex(devname));
|
||||||
gtp_tunnel_set_i_tei(t, pdp->teid_own);
|
gtp_tunnel_set_family(t, in46a_to_af(&ms[i]));
|
||||||
|
gtp_tunnel_set_version(t, pdp->version);
|
||||||
|
if (pdp->version == 0) {
|
||||||
|
gtp_tunnel_set_tid(t, pdp_gettid(pdp->imsi, pdp->nsapi));
|
||||||
|
gtp_tunnel_set_flowid(t, pdp->flru);
|
||||||
|
} else {
|
||||||
|
gtp_tunnel_set_i_tei(t, pdp->teid_own);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gtp_del_tunnel(gtp_nl.genl_id, gtp_nl.nl, t);
|
||||||
|
gtp_tunnel_free(t);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gtp_del_tunnel(gtp_nl.genl_id, gtp_nl.nl, t);
|
|
||||||
gtp_tunnel_free(t);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue