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. Related: SYS#6192 Change-Id: I376c09bfc1844df1e61d2efac17561fac614858b
This commit is contained in:
parent
c4eb92d211
commit
2a2884fbbe
|
@ -83,6 +83,7 @@ void upf_gtp_genl_close();
|
|||
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);
|
||||
|
|
|
@ -79,6 +79,7 @@ int up_gtp_action_cmp(const struct up_gtp_action *a, const struct up_gtp_action
|
|||
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 @@ static int up_gtp_action_enable_disable(struct up_gtp_action *a, bool enable)
|
|||
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 @@ static int up_gtp_action_enable_disable(struct up_gtp_action *a, bool enable)
|
|||
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:
|
||||
|
|
|
@ -73,6 +73,26 @@ struct upf_gtp_dev *upf_gtp_dev_find_by_name(const char *name)
|
|||
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);
|
||||
|
|
|
@ -137,37 +137,44 @@ DEFUN(cfg_tunend_no_mockup, cfg_tunend_no_mockup_cmd,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ OsmoUPF(config-tunend)# list
|
|||
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
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue