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 <nhofmeyr(a)sysmocom.de>
Gerrit-MessageType: newchange