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.
|
||||
#library what description / commit summary line
|
||||
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;
|
||||
case APN_GTPU_MODE_KERNEL_GTP:
|
||||
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) {
|
||||
/* skip bringing up the APN now if the GSN is not initialized yet.
|
||||
* 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);
|
||||
|
||||
if (apn->cfg.gtpu_mode == APN_GTPU_MODE_KERNEL_GTP && apn_supports_ipv4(apn)) {
|
||||
/* TODO: In IPv6, EUA doesn't contain the actual IP addr/prefix! */
|
||||
if (apn->cfg.gtpu_mode == APN_GTPU_MODE_KERNEL_GTP) {
|
||||
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));
|
||||
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)
|
||||
{
|
||||
struct in_addr ms, sgsn;
|
||||
int ms_addr_count;
|
||||
struct in46_addr ms[2];
|
||||
struct in46_addr sgsn;
|
||||
struct gtp_tunnel *t;
|
||||
int ret;
|
||||
|
||||
pdp_debug(__func__, devname, pdp);
|
||||
|
||||
t = gtp_tunnel_alloc();
|
||||
if (t == NULL)
|
||||
return -1;
|
||||
in46a_from_gsna(&pdp->gsnrc, &sgsn);
|
||||
|
||||
memcpy(&ms, &pdp->eua.v[2], sizeof(struct in_addr));
|
||||
memcpy(&sgsn, &pdp->gsnrc.v[0], sizeof(struct in_addr));
|
||||
ms_addr_count = in46a_from_eua(&pdp->eua, ms);
|
||||
|
||||
gtp_tunnel_set_ifidx(t, if_nametoindex(devname));
|
||||
gtp_tunnel_set_version(t, pdp->version);
|
||||
gtp_tunnel_set_ms_ip4(t, &ms);
|
||||
gtp_tunnel_set_sgsn_ip4(t, &sgsn);
|
||||
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);
|
||||
for (int i = 0; i < ms_addr_count; i++) {
|
||||
t = gtp_tunnel_alloc();
|
||||
if (t == NULL)
|
||||
return -1;
|
||||
|
||||
gtp_tunnel_set_ifidx(t, if_nametoindex(devname));
|
||||
gtp_tunnel_set_version(t, pdp->version);
|
||||
|
||||
if (in46a_to_af(&ms[i]) == AF_INET)
|
||||
gtp_tunnel_set_ms_ip4(t, &ms[i].v4);
|
||||
else {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
int ret;
|
||||
|
||||
pdp_debug(__func__, devname, pdp);
|
||||
|
||||
t = gtp_tunnel_alloc();
|
||||
if (t == NULL)
|
||||
return -1;
|
||||
ms_addr_count = in46a_from_eua(&pdp->eua, ms);
|
||||
|
||||
gtp_tunnel_set_ifidx(t, if_nametoindex(devname));
|
||||
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);
|
||||
for (int i = 0; i < ms_addr_count; i++) {
|
||||
t = gtp_tunnel_alloc();
|
||||
if (t == NULL)
|
||||
return -1;
|
||||
|
||||
gtp_tunnel_set_ifidx(t, if_nametoindex(devname));
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue