pespin has uploaded this change for review.

View Change

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

To view, visit change 30992. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Change-Id: I7b4eaa0de428b418bb1d89bd544694e89beb3e6e
Gerrit-Change-Number: 30992
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin@sysmocom.de>
Gerrit-MessageType: newchange