osmith has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-ggsn/+/33797?usp=email )

Change subject: kernel-gtp: support IPv6 on inner layer
......................................................................

kernel-gtp: support IPv6 on inner layer

Related: OS#6096
Change-Id: I3df47b6c209f1e2f8254ba139581d6e622c6b35f
---
M TODO-RELEASE
M ggsn/ggsn.c
M lib/gtp-kernel.c
3 files changed, 78 insertions(+), 41 deletions(-)

Approvals:
  pespin: Looks good to me, but someone else must approve
  osmith: Looks good to me, approved
  Jenkins Builder: Verified
  laforge: Looks good to me, but someone else must approve




diff --git a/TODO-RELEASE b/TODO-RELEASE
index d8cc3af..22cfd1d 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -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()
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index cec043d..db906ea 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -202,11 +202,6 @@
                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 @@

        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);
diff --git a/lib/gtp-kernel.c b/lib/gtp-kernel.c
index 2a731e6..9bfb380 100644
--- a/lib/gtp-kernel.c
+++ b/lib/gtp-kernel.c
@@ -104,61 +104,93 @@

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

--
To view, visit https://gerrit.osmocom.org/c/osmo-ggsn/+/33797?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ggsn
Gerrit-Branch: master
Gerrit-Change-Id: I3df47b6c209f1e2f8254ba139581d6e622c6b35f
Gerrit-Change-Number: 33797
Gerrit-PatchSet: 5
Gerrit-Owner: osmith <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: osmith <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>
Gerrit-MessageType: merged

Reply via email to