neels has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-upf/+/30831 )


Change subject: tunend: choose local GTP addr by Network Instance IEs
......................................................................

tunend: choose local GTP addr by Network Instance IEs

Implement handling of the Network Instance IEs from PFCP for tunend,
like already done for tunmap.

In 'tunend' cfg, allow indicating a local GTP address for both 'dev
create' and 'dev use'. Select a GTP device by the local address the
Network Instance IE in PFCP PDR indicates.

Change-Id: I376c09bfc1844df1e61d2efac17561fac614858b
---
M include/osmocom/upf/upf_gtp.h
M src/osmo-upf/up_gtp_action.c
M src/osmo-upf/upf_gtp.c
M src/osmo-upf/upf_vty.c
M tests/upf.vty
5 files changed, 64 insertions(+), 27 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-upf refs/changes/31/30831/1

diff --git a/include/osmocom/upf/upf_gtp.h b/include/osmocom/upf/upf_gtp.h
index 1a358ba..e3db918 100644
--- a/include/osmocom/upf/upf_gtp.h
+++ b/include/osmocom/upf/upf_gtp.h
@@ -83,6 +83,7 @@
 int upf_gtp_dev_open(const char *name, bool create_gtp_dev, const char 
*local_addr, bool listen_for_gtpv0,
                     bool sgsn_mode);
 struct upf_gtp_dev *upf_gtp_dev_find_by_name(const char *name);
+struct upf_gtp_dev *upf_gtp_dev_find_by_local_addr(const struct osmo_sockaddr 
*local_addr);
 struct upf_gtp_dev *upf_gtp_dev_first();

 int upf_gtp_dev_tunend_add(struct upf_gtp_dev *dev, const struct 
upf_gtp_tunend_desc *t);
diff --git a/src/osmo-upf/up_gtp_action.c b/src/osmo-upf/up_gtp_action.c
index 8ce8a6f..3b3da86 100644
--- a/src/osmo-upf/up_gtp_action.c
+++ b/src/osmo-upf/up_gtp_action.c
@@ -79,6 +79,7 @@
 static int up_gtp_action_enable_disable(struct up_gtp_action *a, bool enable)
 {
        struct upf_gtp_dev *gtp_dev;
+       const struct osmo_sockaddr *gtp_addr;
        int rc;

        switch (a->kind) {
@@ -89,12 +90,15 @@
                        return 0;
                }

-               /* use the first available GTP device.
-                * TODO: select by interface name?
-                */
-               gtp_dev = upf_gtp_dev_first();
+               /* Pick GTP device matching the local F-TEID set up for the GTP 
tunnel (it is on the Access side) */
+               gtp_addr = &a->tunend.access.gtp_local_addr;
+               gtp_dev = upf_gtp_dev_find_by_local_addr(gtp_addr);
                if (!gtp_dev) {
-                       LOG_UP_GTP_ACTION(a, LOGL_ERROR, "No GTP device open, 
cannot %s\n", enable ? "enable" : "disable");
+                       LOG_UP_GTP_ACTION(a, LOGL_ERROR, "No GTP device open 
for local address %s, cannot %s"
+                                         " -- consider configuring 'tunend' / 
'dev (create|use) foo %s'\n",
+                                         osmo_sockaddr_to_str_c(OTC_SELECT, 
gtp_addr),
+                                         enable ? "enable" : "disable",
+                                         osmo_sockaddr_to_str_c(OTC_SELECT, 
gtp_addr));
                        return -EIO;
                }

@@ -107,7 +111,8 @@
                                          enable ? "enable" : "disable", rc, 
strerror(-rc));
                        return rc;
                }
-               LOG_UP_GTP_ACTION(a, LOGL_NOTICE, "%s GTP tunnel\n", enable ? 
"Enabled" : "Disabled");
+               LOG_UP_GTP_ACTION(a, LOGL_NOTICE, "%s GTP tunnel on dev %s\n", 
enable ? "Enabled" : "Disabled",
+                                 gtp_dev->name);
                return 0;

        case UP_GTP_U_TUNMAP:
diff --git a/src/osmo-upf/upf_gtp.c b/src/osmo-upf/upf_gtp.c
index adac836..2c37bc4 100644
--- a/src/osmo-upf/upf_gtp.c
+++ b/src/osmo-upf/upf_gtp.c
@@ -73,6 +73,26 @@
        return NULL;
 }

+struct upf_gtp_dev *upf_gtp_dev_find_by_local_addr(const struct osmo_sockaddr 
*local_addr)
+{
+       struct upf_gtp_dev *dev;
+       struct upf_gtp_dev *dev_any = NULL;
+       struct osmo_sockaddr needle = *local_addr;
+
+       llist_for_each_entry(dev, &g_upf->gtp.devs, entry) {
+               /* To leave the port number out of the cmp, set the needle's 
port to match */
+               osmo_sockaddr_set_port(&needle.u.sa, 
osmo_sockaddr_port(&dev->gtpv1.local_addr.u.sa));
+
+               if (!osmo_sockaddr_cmp(&needle, &dev->gtpv1.local_addr))
+                       return dev;
+               if (osmo_sockaddr_is_any(&dev->gtpv1.local_addr) == 1)
+                       dev_any = dev;
+       }
+       /* No 1:1 match found, but there is a dev listening on ANY? Return that.
+        * If there is no such dev, return NULL. */
+       return dev_any;
+}
+
 struct upf_gtp_dev *upf_gtp_dev_first()
 {
        return llist_first_entry_or_null(&g_upf->gtp.devs, struct upf_gtp_dev, 
entry);
diff --git a/src/osmo-upf/upf_vty.c b/src/osmo-upf/upf_vty.c
index 4c683c8..4332902 100644
--- a/src/osmo-upf/upf_vty.c
+++ b/src/osmo-upf/upf_vty.c
@@ -137,37 +137,44 @@
        return CMD_SUCCESS;
 }

+static struct tunend_vty_cfg_dev *tunend_dev_add(int argc, const char **argv, 
bool create)
+{
+       struct tunend_vty_cfg_dev *d = talloc_zero(g_upf, struct 
tunend_vty_cfg_dev);
+       d->create = create;
+       d->dev_name = talloc_strdup(d, argv[0]);
+       if (argc > 1)
+               d->local_addr = talloc_strdup(d, argv[1]);
+       llist_add(&d->entry, &tunend_vty.devs);
+       return d;
+}
+
 DEFUN(cfg_tunend_dev_create, cfg_tunend_dev_create_cmd,
       "dev create DEVNAME [LISTEN_ADDR]",
       DEV_STR
       "Add GTP device, creating a new Linux kernel GTP device. Will listen on 
GTPv1 port "
       OSMO_STRINGIFY_VAL(PORT_GTP1_U)
-      " and GTPv0 port " OSMO_STRINGIFY_VAL(PORT_GTP0_U) " on the specified 
interface, or on ANY if LISTEN_ADDR is"
-      " omitted.\n"
+      " and GTPv0 port " OSMO_STRINGIFY_VAL(PORT_GTP0_U) " on the specified 
LISTEN_ADDR\n"
       "device name, e.g. 'apn0'\n"
-      "IPv4 or IPv6 address to listen on, omit for ANY\n")
+      "IPv4 or IPv6 address to listen on, omit for ANY. LISTEN_ADDR is used to 
pick a GTP device matching the local"
+      " address for a PFCP Network Instance," " which are configured in the 
'netinst' node.\n")
 {
-       struct tunend_vty_cfg_dev *d = talloc_zero(g_upf, struct 
tunend_vty_cfg_dev);
-       d->create = true;
-       d->dev_name = talloc_strdup(d, argv[0]);
-       if (argc > 1)
-               d->local_addr = talloc_strdup(d, argv[1]);
-       llist_add(&d->entry, &tunend_vty.devs);
-       vty_out(vty, "Added GTP device %s (create new)%s", d->dev_name, 
VTY_NEWLINE);
+       struct tunend_vty_cfg_dev *d = tunend_dev_add(argc, argv, true);
+       vty_out(vty, "Added GTP device %s on %s (create new)%s", d->dev_name, 
d->local_addr ? : "0.0.0.0", VTY_NEWLINE);
        return CMD_SUCCESS;
 }

 DEFUN(cfg_tunend_dev_use, cfg_tunend_dev_use_cmd,
-      "dev use DEVNAME",
+      "dev use DEVNAME [LOCAL_ADDR]",
       DEV_STR
       "Add GTP device, using an existing Linux kernel GTP device, e.g. created 
by 'gtp-link'\n"
-      "device name, e.g. 'apn0'\n")
+      "device name, e.g. 'apn0'\n"
+      "The local GTP address this device listens on. It is assumed to be ANY 
when omitted."
+      " LOCAL_ADDR is used to pick a GTP device matching the local address for 
a PFCP Network Instance,"
+      " which are configured in the 'netinst' node.\n")
 {
-       struct tunend_vty_cfg_dev *d = talloc_zero(g_upf, struct 
tunend_vty_cfg_dev);
-       d->create = false;
-       d->dev_name = talloc_strdup(d, argv[0]);
-       llist_add(&d->entry, &tunend_vty.devs);
-       vty_out(vty, "Added GTP device %s (use existing)%s", d->dev_name, 
VTY_NEWLINE);
+       struct tunend_vty_cfg_dev *d = tunend_dev_add(argc, argv, false);
+       vty_out(vty, "Added GTP device %s on %s (use existing)%s", d->dev_name, 
d->local_addr ? : "0.0.0.0",
+               VTY_NEWLINE);
        return CMD_SUCCESS;
 }

diff --git a/tests/upf.vty b/tests/upf.vty
index 51ebeb3..bfaa0cc 100644
--- a/tests/upf.vty
+++ b/tests/upf.vty
@@ -20,7 +20,7 @@
   mockup
   no mockup
   dev create DEVNAME [LISTEN_ADDR]
-  dev use DEVNAME
+  dev use DEVNAME [LOCAL_ADDR]
   dev delete DEVNAME

 OsmoUPF(config-tunend)# exit
@@ -28,19 +28,23 @@
 OsmoUPF(config-tunend)# list
 ...
   dev create DEVNAME [LISTEN_ADDR]
-  dev use DEVNAME
+  dev use DEVNAME [LOCAL_ADDR]
   dev delete DEVNAME

 OsmoUPF(config-tunend)# dev?
   dev  Configure the GTP device to use for encaps/decaps.
 OsmoUPF(config-tunend)# dev ?
-  create  Add GTP device, creating a new Linux kernel GTP device. Will listen 
on GTPv1 port 2152 and GTPv0 port 3386 on the specified interface, or on ANY if 
LISTEN_ADDR is omitted.
+  create  Add GTP device, creating a new Linux kernel GTP device. Will listen 
on GTPv1 port 2152 and GTPv0 port 3386 on the specified LISTEN_ADDR
   use     Add GTP device, using an existing Linux kernel GTP device, e.g. 
created by 'gtp-link'
   delete  Remove a GTP device from the configuration, and delete the Linux 
kernel GTP device if it was created here.
 OsmoUPF(config-tunend)# dev create ?
   DEVNAME  device name, e.g. 'apn0'
 OsmoUPF(config-tunend)# dev create foo ?
-  [LISTEN_ADDR]  IPv4 or IPv6 address to listen on, omit for ANY
+  [LISTEN_ADDR]  IPv4 or IPv6 address to listen on, omit for ANY. LISTEN_ADDR 
is used to pick a GTP device matching the local address for a PFCP Network 
Instance, which are configured in the 'netinst' node.
+OsmoUPF(config-tunend)# dev use ?
+  DEVNAME  device name, e.g. 'apn0'
+OsmoUPF(config-tunend)# dev use foo ?
+  [LOCAL_ADDR]  The local GTP address this device listens on. It is assumed to 
be ANY when omitted. LOCAL_ADDR is used to pick a GTP device matching the local 
address for a PFCP Network Instance, which are configured in the 'netinst' node.
 OsmoUPF(config-tunend)# dev delete ?
   DEVNAME  device name, e.g. 'apn0'
 OsmoUPF(config-tunend)# exit

--
To view, visit https://gerrit.osmocom.org/c/osmo-upf/+/30831
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-upf
Gerrit-Branch: master
Gerrit-Change-Id: I376c09bfc1844df1e61d2efac17561fac614858b
Gerrit-Change-Number: 30831
Gerrit-PatchSet: 1
Gerrit-Owner: neels <[email protected]>
Gerrit-MessageType: newchange

Reply via email to