pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmocom-bb/+/30992 )
Change subject: layer23: Introduce APN VTY node ......................................................................
layer23: Introduce APN VTY node
Change-Id: I7b4eaa0de428b418bb1d89bd544694e89beb3e6e --- M doc/examples/modem/modem.cfg M src/host/layer23/include/osmocom/bb/common/Makefile.am A src/host/layer23/include/osmocom/bb/common/apn.h M src/host/layer23/include/osmocom/bb/common/ms.h M src/host/layer23/include/osmocom/bb/common/settings.h M src/host/layer23/include/osmocom/bb/modem/vty.h M src/host/layer23/src/common/Makefile.am A src/host/layer23/src/common/apn.c M src/host/layer23/src/common/ms.c M src/host/layer23/src/common/settings.c M src/host/layer23/src/modem/app_modem.c M src/host/layer23/src/modem/vty.c 12 files changed, 369 insertions(+), 3 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/92/30992/1
diff --git a/doc/examples/modem/modem.cfg b/doc/examples/modem/modem.cfg index d2cb81f..fd56b06 100644 --- a/doc/examples/modem/modem.cfg +++ b/doc/examples/modem/modem.cfg @@ -6,4 +6,8 @@ no login ! ms 1 + apn internet + tun-device modem4 + type-support v4 + no shutdown no shutdown diff --git a/src/host/layer23/include/osmocom/bb/common/Makefile.am b/src/host/layer23/include/osmocom/bb/common/Makefile.am index 270f079..28caf78 100644 --- a/src/host/layer23/include/osmocom/bb/common/Makefile.am +++ b/src/host/layer23/include/osmocom/bb/common/Makefile.am @@ -1,4 +1,5 @@ noinst_HEADERS = \ + apn.h \ l1ctl.h \ l1l2_interface.h \ l23_app.h \ diff --git a/src/host/layer23/include/osmocom/bb/common/apn.h b/src/host/layer23/include/osmocom/bb/common/apn.h new file mode 100644 index 0000000..18dc16f --- /dev/null +++ b/src/host/layer23/include/osmocom/bb/common/apn.h @@ -0,0 +1,68 @@ +/* APN Context + * (C) 2023 by sysmocom - s.m.f.c. GmbH info@sysmocom.de + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#pragma once + +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/select.h> + +struct osmocom_ms; + +#define APN_TYPE_IPv4 0x01 /* v4-only */ +#define APN_TYPE_IPv6 0x02 /* v6-only */ +#define APN_TYPE_IPv4v6 0x04 /* v4v6 dual-stack */ + +struct apn_name { + struct llist_head list; + char *name; +}; + +struct osmobb_apn { + /* list of APNs inside MS */ + struct llist_head list; + /* back-pointer to MS */ + struct osmocom_ms *ms; + + bool started; + + struct { + /* Primary name */ + char *name; + /* name of the network device */ + char *dev_name; + /* types supported address types on this APN */ + uint32_t apn_type_mask; + /* administratively shut-down (true) or not (false) */ + bool shutdown; + /* transmit G-PDU sequeence numbers (true) or not (false) */ + bool tx_gpdu_seq; + } cfg; + + /* corresponding tun device */ + struct { + //struct tun_t *tun; + struct osmo_fd fd; + } tun; + + /* ipv6 link-local address */ + //struct in6_addr v6_lladdr; +}; + +struct osmobb_apn *apn_alloc(struct osmocom_ms *ms, const char *name); +void apn_free(struct osmobb_apn *apn); +int apn_start(struct osmobb_apn *apn); +int apn_stop(struct osmobb_apn *apn); diff --git a/src/host/layer23/include/osmocom/bb/common/ms.h b/src/host/layer23/include/osmocom/bb/common/ms.h index a706a4c..30bb514 100644 --- a/src/host/layer23/include/osmocom/bb/common/ms.h +++ b/src/host/layer23/include/osmocom/bb/common/ms.h @@ -90,6 +90,9 @@ struct osmomncc_entity mncc_entity; struct llist_head trans_list;
+ /* GPRS */ + struct gprs_settings gprs; + /* Audio I/O */ struct gapk_io_state *gapk_io;
diff --git a/src/host/layer23/include/osmocom/bb/common/settings.h b/src/host/layer23/include/osmocom/bb/common/settings.h index 8ebf049..845292f 100644 --- a/src/host/layer23/include/osmocom/bb/common/settings.h +++ b/src/host/layer23/include/osmocom/bb/common/settings.h @@ -5,6 +5,7 @@ #include <osmocom/core/linuxlist.h>
struct osmocom_ms; +struct osmobb_apn;
#define MOB_C7_DEFLT_ANY_TIMEOUT 30
@@ -180,6 +181,14 @@ char *gsm_check_imei(const char *imei, const char *sv); int gsm_random_imei(struct gsm_settings *set);
+struct gprs_settings { + struct llist_head apn_list; +}; + +int gprs_settings_init(struct osmocom_ms *ms); +int gprs_settings_fi(struct osmocom_ms *ms); +struct osmobb_apn *ms_find_apn_by_name(struct osmocom_ms *ms, const char* apn_name); + extern char *layer2_socket_path;
#endif /* _settings_h */ diff --git a/src/host/layer23/include/osmocom/bb/modem/vty.h b/src/host/layer23/include/osmocom/bb/modem/vty.h index 14ec624..5b69af6 100644 --- a/src/host/layer23/include/osmocom/bb/modem/vty.h +++ b/src/host/layer23/include/osmocom/bb/modem/vty.h @@ -1,3 +1,10 @@ #pragma once
+#include <osmocom/bb/common/vty.h> + +enum modem_vty_node { + APN_NODE = _LAST_L23VTY_NODE + 1, +}; + int modem_vty_init(void); +int modem_vty_go_parent(struct vty *vty); diff --git a/src/host/layer23/src/common/Makefile.am b/src/host/layer23/src/common/Makefile.am index 9abc802..94eeec8 100644 --- a/src/host/layer23/src/common/Makefile.am +++ b/src/host/layer23/src/common/Makefile.am @@ -13,6 +13,7 @@
noinst_LIBRARIES = liblayer23.a liblayer23_a_SOURCES = \ + apn.c \ gps.c \ l1ctl.c \ l1l2_interface.c \ diff --git a/src/host/layer23/src/common/apn.c b/src/host/layer23/src/common/apn.c new file mode 100644 index 0000000..bd0eb25 --- /dev/null +++ b/src/host/layer23/src/common/apn.c @@ -0,0 +1,60 @@ +/* + * (C) 2023 by sysmocom - s.m.f.c. GmbH info@sysmocom.de + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <stdint.h> +#include <errno.h> +#include <string.h> +#include <arpa/inet.h> + +#include <talloc.h> + +#include <osmocom/bb/common/logging.h> +#include <osmocom/bb/common/apn.h> +#include <osmocom/bb/common/ms.h> + +struct osmobb_apn *apn_alloc(struct osmocom_ms *ms, const char *name) +{ + struct osmobb_apn *apn; + apn = talloc_zero(ms, struct osmobb_apn); + if (!apn) + return NULL; + + talloc_set_name(apn, "apn_%s", name); + apn->cfg.name = talloc_strdup(apn, name); + apn->cfg.shutdown = true; + apn->cfg.tx_gpdu_seq = true; + + apn->ms = ms; + llist_add_tail(&apn->list, &ms->gprs.apn_list); + return apn; +} + +void apn_free(struct osmobb_apn *apn) +{ + llist_del(&apn->list); + talloc_free(apn); +} + +int apn_start(struct osmobb_apn *apn) +{ + return 0; +} + +int apn_stop(struct osmobb_apn *apn) +{ + return 0; +} \ No newline at end of file diff --git a/src/host/layer23/src/common/ms.c b/src/host/layer23/src/common/ms.c index 558505a..ee27096 100644 --- a/src/host/layer23/src/common/ms.c +++ b/src/host/layer23/src/common/ms.c @@ -24,6 +24,12 @@ /* Default value be configured by cmdline arg: */ uint16_t cfg_test_arfcn = 871;
+static int osmocom_ms_talloc_destructor(struct osmocom_ms *ms) +{ + gprs_settings_fi(ms); + return 0; +} + struct osmocom_ms *osmocom_ms_alloc(void *ctx, const char *name) { struct osmocom_ms *ms; @@ -32,6 +38,7 @@ if (!ms) return NULL; talloc_set_name(ms, "ms_%s", name); + talloc_set_destructor(ms, osmocom_ms_talloc_destructor);
ms->name = talloc_strdup(ms, name); ms->test_arfcn = cfg_test_arfcn; @@ -50,6 +57,7 @@
gsm_support_init(ms); gsm_settings_init(ms); + gprs_settings_init(ms);
return ms; } diff --git a/src/host/layer23/src/common/settings.c b/src/host/layer23/src/common/settings.c index fd7177d..287dcda 100644 --- a/src/host/layer23/src/common/settings.c +++ b/src/host/layer23/src/common/settings.c @@ -20,13 +20,12 @@ #include <string.h> #include <osmocom/core/talloc.h>
-#include <osmocom/bb/mobile/app_mobile.h> #include <osmocom/bb/common/settings.h> #include <osmocom/bb/common/utils.h> #include <osmocom/bb/common/logging.h> #include <osmocom/bb/common/osmocom_data.h> +#include <osmocom/bb/common/apn.h> #include <osmocom/bb/common/ms.h> -#include <osmocom/bb/common/networks.h> #include <osmocom/bb/common/l1l2_interface.h>
/* Used to set default path globally through cmdline */ @@ -220,3 +219,35 @@ { AUDIO_IOF_TI, "ti" }, { 0x00, NULL} }; + + +int gprs_settings_init(struct osmocom_ms *ms) +{ + struct gprs_settings *set = &ms->gprs; + INIT_LLIST_HEAD(&set->apn_list); + + return 0; +} + +int gprs_settings_fi(struct osmocom_ms *ms) +{ + struct gprs_settings *set = &ms->gprs; + struct osmobb_apn *apn; + while((apn = llist_first_entry_or_null(&set->apn_list, struct osmobb_apn, list))) { + /* free calls llist_del(): */ + apn_free(apn); + } + return 0; +} + +struct osmobb_apn *ms_find_apn_by_name(struct osmocom_ms *ms, const char* apn_name) +{ + struct gprs_settings *set = &ms->gprs; + struct osmobb_apn *apn; + + llist_for_each_entry(apn, &set->apn_list, list) { + if (strcmp(apn->cfg.name, apn_name) == 0) + return apn; + } + return NULL; +} \ No newline at end of file diff --git a/src/host/layer23/src/modem/app_modem.c b/src/host/layer23/src/modem/app_modem.c index 7dcda17..d7c9a29 100644 --- a/src/host/layer23/src/modem/app_modem.c +++ b/src/host/layer23/src/modem/app_modem.c @@ -509,6 +509,7 @@ static struct vty_app_info _modem_vty_info = { .name = "modem", .version = PACKAGE_VERSION, + .go_parent_cb = modem_vty_go_parent, };
static struct l23_app_info info = { diff --git a/src/host/layer23/src/modem/vty.c b/src/host/layer23/src/modem/vty.c index 4304876..12107ec 100644 --- a/src/host/layer23/src/modem/vty.c +++ b/src/host/layer23/src/modem/vty.c @@ -25,14 +25,179 @@ #include <osmocom/vty/command.h>
#include <osmocom/bb/common/vty.h> +#include <osmocom/bb/common/apn.h> #include <osmocom/bb/common/ms.h> +#include <osmocom/bb/modem/vty.h>
+static struct cmd_node apn_node = { + APN_NODE, + "%s(apn)# ", + 1 +}; + +int modem_vty_go_parent(struct vty *vty) +{ + struct osmobb_apn *apn; + + switch (vty->node) { + case APN_NODE: + apn = vty->index; + vty->index = apn->ms; + vty->node = MS_NODE; + break; + } + return vty->node; +} + +/* per APN config */ +DEFUN(cfg_ms_apn, cfg_ms_apn_cmd, "apn APN_NAME", + "Configure an APN\n" + "Name of APN\n") +{ + struct osmocom_ms *ms = vty->index; + struct osmobb_apn *apn; + + apn = ms_find_apn_by_name(ms, argv[0]); + if (!apn) + apn = apn_alloc(ms, argv[0]); + if (!apn) { + vty_out(vty, "Unable to create APN '%s'%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + vty->index = apn; + vty->node = APN_NODE; + return CMD_SUCCESS; +} + +DEFUN(cfg_ms_no_apn, cfg_ms_no_apn_cmd, "no apn APN_NAME", + NO_STR "Configure an APN\n" + "Name of APN\n") +{ + struct osmocom_ms *ms = vty->index; + struct osmobb_apn *apn; + + apn = ms_find_apn_by_name(ms, argv[0]); + if (!apn) { + vty_out(vty, "Unable to find APN '%s'%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + apn_free(apn); + + return CMD_SUCCESS; +} + +DEFUN(cfg_apn_tun_dev_name, cfg_apn_tun_dev_name_cmd, + "tun-device NAME", + "Configure tun device name\n" + "TUN device name") +{ + struct osmobb_apn *apn = (struct osmobb_apn *) vty->index; + osmo_talloc_replace_string(apn, &apn->cfg.dev_name, argv[0]); + return CMD_SUCCESS; +} + +static const struct value_string pdp_type_names[] = { + { APN_TYPE_IPv4, "v4" }, + { APN_TYPE_IPv6, "v6" }, + { APN_TYPE_IPv4v6, "v4v6" }, + { 0, NULL } +}; + +#define V4V6V46_STRING "IPv4(-only) PDP Type\n" \ + "IPv6(-only) PDP Type\n" \ + "IPv4v6 (dual-stack) PDP Type\n" + +DEFUN(cfg_apn_type_support, cfg_apn_type_support_cmd, + "type-support (v4|v6|v4v6)", + "Enable support for PDP Type\n" + V4V6V46_STRING) +{ + struct osmobb_apn *apn = (struct osmobb_apn *) vty->index; + uint32_t type = get_string_value(pdp_type_names, argv[0]); + + apn->cfg.apn_type_mask |= type; + return CMD_SUCCESS; +} + +DEFUN(cfg_apn_shutdown, cfg_apn_shutdown_cmd, + "shutdown", + "Put the APN in administrative shut-down\n") +{ + struct osmobb_apn *apn = (struct osmobb_apn *) vty->index; + + if (!apn->cfg.shutdown) { + if (apn_stop(apn)) { + vty_out(vty, "%% Failed to Stop APN%s", VTY_NEWLINE); + return CMD_WARNING; + } + apn->cfg.shutdown = true; + } + + return CMD_SUCCESS; +} + +DEFUN(cfg_apn_no_shutdown, cfg_apn_no_shutdown_cmd, + "no shutdown", + NO_STR "Remove the APN from administrative shut-down\n") +{ + struct osmobb_apn *apn = (struct osmobb_apn *) vty->index; + + if (apn->cfg.shutdown) { + if (!apn->cfg.dev_name) { + vty_out(vty, "%% Failed to start APN, tun-device is not configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + if (apn_start(apn) < 0) { + vty_out(vty, "%% Failed to start APN, check log for details%s", VTY_NEWLINE); + return CMD_WARNING; + } + apn->cfg.shutdown = false; + } + + return CMD_SUCCESS; +} + +static void config_write_apn(struct vty *vty, const struct osmobb_apn *apn) +{ + unsigned int i; + + vty_out(vty, " apn %s%s", apn->cfg.name, VTY_NEWLINE); + + if (apn->cfg.dev_name) + vty_out(vty, " tun-device %s%s", apn->cfg.dev_name, VTY_NEWLINE); + + for (i = 0; i < 32; i++) { + if (!(apn->cfg.apn_type_mask & (UINT32_C(1) << i))) + continue; + vty_out(vty, " type-support %s%s", get_value_string(pdp_type_names, (UINT32_C(1) << i)), + VTY_NEWLINE); + } + + /* must be last */ + vty_out(vty, " %sshutdown%s", apn->cfg.shutdown ? "" : "no ", VTY_NEWLINE); +} + +static void config_write_ms(struct vty *vty, const struct osmocom_ms *ms) +{ + struct osmobb_apn *apn; + + vty_out(vty, "ms %s%s", ms->name, VTY_NEWLINE); + + l23_vty_config_write_ms_node_contents(vty, ms, " "); + + llist_for_each_entry(apn, &ms->gprs.apn_list, list) + config_write_apn(vty, apn); + + l23_vty_config_write_ms_node_contents_final(vty, ms, " "); +}
static int config_write(struct vty *vty) { struct osmocom_ms *ms; llist_for_each_entry(ms, &ms_list, entity) - l23_vty_config_write_ms_node(vty, ms, ""); + config_write_ms(vty, ms); return CMD_SUCCESS; }
@@ -45,5 +210,13 @@ install_element_ve(&l23_show_ms_cmd); install_element(CONFIG_NODE, &l23_cfg_ms_cmd);
+ install_element(MS_NODE, &cfg_ms_apn_cmd); + install_element(MS_NODE, &cfg_ms_no_apn_cmd); + install_node(&apn_node, NULL); + install_element(APN_NODE, &cfg_apn_tun_dev_name_cmd); + install_element(APN_NODE, &cfg_apn_type_support_cmd); + install_element(APN_NODE, &cfg_apn_shutdown_cmd); + install_element(APN_NODE, &cfg_apn_no_shutdown_cmd); + return 0; }