neels has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmo-upf/+/30461
)
Change subject: tunmap: choose local GTP addr by Network Instance IEs
......................................................................
tunmap: choose local GTP addr by Network Instance IEs
Add 'netinst' config section to osmo-upf.cfg, to define Network Instance
name to local IP address mappings.
For the tunmap use case (forwarding GTP tunnels), heed the Network
Instance IEs in PFCP session creation and return IP addresses in F-TEIDs
accordingly.
Related: SYS#6192
Related: I37bebc7d6ef75c3e6ae05e81b83a1b5895839a64 (osmo-ttcn3-hacks)
Change-Id: I15ee046a1c37b83b8a83527a67a6215a30106d81
---
M include/osmocom/upf/Makefile.am
A include/osmocom/upf/netinst.h
M include/osmocom/upf/upf.h
M src/osmo-upf/Makefile.am
A src/osmo-upf/netinst.c
M src/osmo-upf/up_session.c
M src/osmo-upf/upf.c
M src/osmo-upf/upf_vty.c
A tests/netinst.vty
9 files changed, 409 insertions(+), 12 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-upf refs/changes/61/30461/1
diff --git a/include/osmocom/upf/Makefile.am b/include/osmocom/upf/Makefile.am
index 127e03e..f418cb1 100644
--- a/include/osmocom/upf/Makefile.am
+++ b/include/osmocom/upf/Makefile.am
@@ -1,4 +1,5 @@
noinst_HEADERS = \
+ netinst.h \
up_endpoint.h \
up_peer.h \
up_session.h \
diff --git a/include/osmocom/upf/netinst.h b/include/osmocom/upf/netinst.h
new file mode 100644
index 0000000..fb659b6
--- /dev/null
+++ b/include/osmocom/upf/netinst.h
@@ -0,0 +1,44 @@
+/*
+ * (C) 2022 by sysmocom - s.f.m.c. GmbH <info(a)sysmocom.de>
+ * All Rights Reserved.
+ *
+ * Author: Neels Janosch Hofmeyr <nhofmeyr(a)sysmocom.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/sockaddr_str.h>
+
+struct vty;
+
+struct network_instance {
+ struct llist_head entry;
+
+ char *name;
+ struct osmo_sockaddr_str addr;
+};
+
+const struct network_instance *netinst_add(void *ctx, struct llist_head *list, const char
*name, const char *addr,
+ const char **errmsg);
+const struct network_instance *netinst_find(struct llist_head *list, const char *name);
+const struct network_instance *netinst_first(struct llist_head *list);
+int netinst_clear(struct llist_head *list);
+
+int netinst_vty_write(struct vty *vty, struct llist_head *list, const char *indent, const
char *name_or_null);
diff --git a/include/osmocom/upf/upf.h b/include/osmocom/upf/upf.h
index 1597e2c..735a724 100644
--- a/include/osmocom/upf/upf.h
+++ b/include/osmocom/upf/upf.h
@@ -101,6 +101,8 @@
int priority;
uint32_t next_id_state;
} nft;
+
+ struct llist_head netinst;
};
extern struct g_upf *g_upf;
diff --git a/src/osmo-upf/Makefile.am b/src/osmo-upf/Makefile.am
index 1d43ee8..403fb06 100644
--- a/src/osmo-upf/Makefile.am
+++ b/src/osmo-upf/Makefile.am
@@ -30,6 +30,7 @@
$(NULL)
osmo_upf_SOURCES = \
+ netinst.c \
osmo_upf_main.c \
up_endpoint.c \
up_gtp_action.c \
diff --git a/src/osmo-upf/netinst.c b/src/osmo-upf/netinst.c
new file mode 100644
index 0000000..039fd5c
--- /dev/null
+++ b/src/osmo-upf/netinst.c
@@ -0,0 +1,124 @@
+/*
+ * (C) 2022 by sysmocom - s.f.m.c. GmbH <info(a)sysmocom.de>
+ * All Rights Reserved.
+ *
+ * Author: Neels Janosch Hofmeyr <nhofmeyr(a)sysmocom.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <string.h>
+
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/vty/vty.h>
+
+#include <osmocom/upf/netinst.h>
+
+/* Add a new netinst entry to the given list.
+ * \param ctx talloc allocate new entry from ctx.
+ * \param list append to this list.
+ * \param name The Network Instance name as given in PFCP Network Instance IEs.
+ * \param addr IP address string of local interface to associate with the Network
Instance.
+ * \param errmsg On error, an error description is returned in this out-argument.
+ * \return new network_instance entry, or NULL on error.
+ */
+const struct network_instance *netinst_add(void *ctx, struct llist_head *list, const char
*name, const char *addr,
+ const char **errmsg)
+{
+ struct network_instance *netinst;
+ if (errmsg)
+ *errmsg = NULL;
+
+ if (!name || !*name) {
+ if (errmsg)
+ *errmsg = "Network Instance name must not be empty";
+ return NULL;
+ }
+
+ if (netinst_find(list, name)) {
+ if (errmsg)
+ *errmsg = "Network Instance entry with this name already exists";
+ return NULL;
+ }
+
+ netinst = talloc(ctx, struct network_instance);
+ *netinst = (struct network_instance){
+ .name = talloc_strdup(ctx, name),
+ };
+ if (osmo_sockaddr_str_from_str(&netinst->addr, addr, 0)) {
+ if (errmsg)
+ *errmsg = "Network Instance address is not a valid IP address string";
+ talloc_free(netinst);
+ return NULL;
+ }
+
+ llist_add_tail(&netinst->entry, list);
+
+ return netinst;
+}
+
+const struct network_instance *netinst_find(struct llist_head *list, const char *name)
+{
+ const struct network_instance *netinst;
+
+ if (!name)
+ return NULL;
+
+ llist_for_each_entry(netinst, list, entry)
+ if (!strcmp(netinst->name, name))
+ return netinst;
+
+ return NULL;
+}
+
+const struct network_instance *netinst_first(struct llist_head *list)
+{
+ return llist_first_entry_or_null(list, struct network_instance, entry);
+}
+
+/* Clear the list of Network Instance entries, return the nr of entries that were
removed. */
+int netinst_clear(struct llist_head *list)
+{
+ int count = 0;
+ while (1) {
+ struct network_instance *netinst = llist_first_entry_or_null(list, struct
network_instance, entry);
+ if (!netinst)
+ break;
+ llist_del(&netinst->entry);
+ talloc_free(netinst);
+ count++;
+ }
+ return count;
+}
+
+/* Write one or all netinst entries to the VTY output.
+ * If name_or_null is NULL, print all entries. Else, print only the entry matching that
name.
+ * Return number of printed entries. */
+int netinst_vty_write(struct vty *vty, struct llist_head *list, const char *indent, const
char *name_or_null)
+{
+ const struct network_instance *netinst;
+ int count = 0;
+
+ llist_for_each_entry(netinst, list, entry) {
+ if (name_or_null && strcmp(netinst->name, name_or_null))
+ continue;
+ vty_out(vty, "%sadd %s %s%s", indent, netinst->name, netinst->addr.ip,
VTY_NEWLINE);
+ count++;
+ }
+ return count;
+}
diff --git a/src/osmo-upf/up_session.c b/src/osmo-upf/up_session.c
index 195bd13..e17b319 100644
--- a/src/osmo-upf/up_session.c
+++ b/src/osmo-upf/up_session.c
@@ -34,6 +34,7 @@
#include <osmocom/upf/up_peer.h>
#include <osmocom/upf/up_session.h>
#include <osmocom/upf/up_gtp_action.h>
+#include <osmocom/upf/netinst.h>
static enum osmo_pfcp_cause up_session_setup_gtp(struct up_session *session);
@@ -114,12 +115,73 @@
return NULL;
}
+/* Find local interface's IP address by Network Instance name. Return 0 on success,
or an OSMO_PFCP_CAUSE_* value on
+ * failure. */
+static int up_session_choose_local_ip(struct up_session *session, struct
osmo_pfcp_ip_addrs *local_addr,
+ const char *netinst_name)
+{
+ const struct network_instance *netinst;
+ struct osmo_sockaddr osa = {};
+
+ if (llist_empty(&g_upf->netinst)) {
+ /* No network instances are configured in osmo-upf.cfg. Instead use the local address
configured for
+ * PFCP, assuming that in a simplistic setup the host has only one interface. It is
unlikely to be
+ * useful for a production environment where the entire point is to hand packet data
from one interface
+ * to another, and where PFCP most probably happens on an entirely different interface,
but may make
+ * things simpler for lab testing. */
+ if (osmo_pfcp_ip_addrs_set(local_addr,
+
osmo_pfcp_endpoint_get_local_addr(session->up_peer->up_endpoint->pfcp_ep))) {
+ LOGPFSML(session->fi, LOGL_ERROR, "Invalid local address in pfcp_endpoint
cfg\n");
+ return OSMO_PFCP_CAUSE_SYSTEM_FAILURE;
+ }
+ LOGPFSML(session->fi, LOGL_NOTICE,
+ "Cannot look up Network Instance %s: No 'netinst' is configured, setting
up GTP on same local"
+ " interface as PFCP: %s (makes sense only for lab testing)\n",
+ osmo_quote_str_c(OTC_SELECT, netinst_name, -1),
+ osmo_pfcp_ip_addrs_to_str_c(OTC_SELECT, local_addr));
+ return 0;
+ }
+
+ if (!netinst_name || !*netinst_name) {
+ /* Empty or no Network Instance IE in incoming PFCP request. Pick the first network
instance; makes
+ * sense only in a simplistic lab setup where packet data is forwarded to the same
interface that it is
+ * received on, and where no Network Instance is indicated by the CPF. Warn if more
than one network
+ * instance is configured to choose from. */
+ if (llist_count(&g_upf->netinst) > 1)
+ LOGPFSML(session->fi, LOGL_NOTICE,
+ "Missing Network Instance in incoming request, using the first
'netinst' from cfg\n");
+ netinst = netinst_first(&g_upf->netinst);
+ /* there has to be a first entry, because we handled the empty list above. */
+ OSMO_ASSERT(netinst);
+ } else {
+ netinst = netinst_find(&g_upf->netinst, netinst_name);
+ if (!netinst) {
+ LOGPFSML(session->fi, LOGL_ERROR, "Network Instance from PFCP request not
found: %s\n",
+ osmo_quote_str_c(OTC_SELECT, netinst_name, -1));
+ return OSMO_PFCP_CAUSE_RULE_CREATION_MOD_FAILURE;
+ }
+ }
+
+ /* Convert netinst IP address string first to osmo_sockaddr and then to
osmo_pfcp_ip_addrs. */
+ if (osmo_sockaddr_str_to_sockaddr(&netinst->addr, &osa.u.sas)
+ || osmo_pfcp_ip_addrs_set(local_addr, &osa)) {
+ LOGPFSML(session->fi, LOGL_ERROR,
+ "Network Instance %s from PFCP request yields no valid IP address: "
+ OSMO_SOCKADDR_STR_FMT "\n",
+ osmo_quote_str_c(OTC_SELECT, netinst_name, -1),
+ OSMO_SOCKADDR_STR_FMT_ARGS(&netinst->addr));
+ return OSMO_PFCP_CAUSE_RULE_CREATION_MOD_FAILURE;
+ }
+ return 0;
+}
+
/* Choose an F-TEID (when the peer has sent CHOOSE = 1).
* If the peer also sent a CHOOSE_ID, then remember this F-TEID choice under the given
ID, and re-use that choice when
* the same ID re-appears. The chosen IDs are saved in session->chosen_f_teids.
* Return 0 on success, or an OSMO_PFCP_CAUSE_* value on failure. */
static enum osmo_pfcp_cause up_session_choose_f_teid(struct up_session *session, struct
osmo_pfcp_ie_f_teid *dst,
- bool choose_id_present, uint8_t choose_id)
+ bool choose_id_present, uint8_t choose_id,
+ const char *netinst_name)
{
struct up_endpoint *up_ep = session->up_peer->up_endpoint;
struct chosen_f_teid *chosen = NULL;
@@ -130,23 +192,26 @@
/* Re-use a previous F-TEID */
*dst = chosen->f_teid;
} else {
- /* Choose a new F-TEID */
+ int rc;
+
*dst = (struct osmo_pfcp_ie_f_teid){
- .fixed = {
- .teid = up_endpoint_next_teid(up_ep),
- },
+ .choose_flag = false,
};
+
+ /* Determine local IP address from Network Instance value received in PFCP request */
+ rc = up_session_choose_local_ip(session, &dst->fixed.ip_addr, netinst_name);
+ if (rc)
+ return rc;
+
+ /* Choose a new TEID */
+ dst->fixed.teid = up_endpoint_next_teid(up_ep);
if (dst->fixed.teid == 0) {
LOGPFSML(session->fi, LOGL_ERROR, "Failed to allocate an unused
TEID\n");
return OSMO_PFCP_CAUSE_PFCP_ENTITY_IN_CONGESTION;
}
- LOGPFSML(session->fi, LOGL_INFO, "Allocated new local TEID 0x%x\n",
dst->fixed.teid);
+ LOGPFSML(session->fi, LOGL_INFO, "Allocated new local F-TEID %s\n",
+ osmo_pfcp_ie_f_teid_to_str_c(OTC_SELECT, dst));
- if (osmo_pfcp_ip_addrs_set(&dst->fixed.ip_addr,
- osmo_pfcp_endpoint_get_local_addr(up_ep->pfcp_ep))) {
- LOGPFSML(session->fi, LOGL_ERROR, "Invalid local address in pfcp_endpoint
cfg\n");
- return OSMO_PFCP_CAUSE_PFCP_ENTITY_IN_CONGESTION;
- }
/* Save this choice */
if (choose_id_present) {
chosen = talloc(session, struct chosen_f_teid);
@@ -270,6 +335,10 @@
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2,
&pdr->desc.pdi.ue_ip_address.ip_addr.v6);
}
}
+ if (pdr->desc.pdi.network_inst_present) {
+ OSMO_STRBUF_PRINTF(sb, " netinst:");
+ OSMO_STRBUF_APPEND(sb, osmo_quote_str_buf3, pdr->desc.pdi.network_inst.str, -1);
+ }
if (pdr->local_f_teid) {
OSMO_STRBUF_PRINTF(sb, " ");
OSMO_STRBUF_APPEND(sb, osmo_pfcp_ie_f_teid_to_str_buf, pdr->local_f_teid);
@@ -370,9 +439,13 @@
if (pdr->desc.pdi.local_f_teid.choose_flag) {
/* CHOOSE = 1: we need to pick our own local F-TEID */
struct osmo_pfcp_ie_f_teid local_f_teid;
+ const char *netinst_name = NULL;
+ if (pdr->desc.pdi.network_inst_present)
+ netinst_name = pdr->desc.pdi.network_inst.str;
*cause = up_session_choose_f_teid(session, &local_f_teid,
pdr->desc.pdi.local_f_teid.choose.choose_id_present,
- pdr->desc.pdi.local_f_teid.choose.choose_id);
+ pdr->desc.pdi.local_f_teid.choose.choose_id,
+ netinst_name);
if (*cause != OSMO_PFCP_CAUSE_REQUEST_ACCEPTED) {
*offending_ie = OSMO_PFCP_IEI_F_TEID;
*offending_ie_present = true;
diff --git a/src/osmo-upf/upf.c b/src/osmo-upf/upf.c
index 3b8bfeb..0a84799 100644
--- a/src/osmo-upf/upf.c
+++ b/src/osmo-upf/upf.c
@@ -61,6 +61,7 @@
INIT_LLIST_HEAD(&g_upf->gtp.vty_cfg.devs);
INIT_LLIST_HEAD(&g_upf->gtp.devs);
+ INIT_LLIST_HEAD(&g_upf->netinst);
}
int upf_pfcp_listen()
diff --git a/src/osmo-upf/upf_vty.c b/src/osmo-upf/upf_vty.c
index 45f6dec..aff7590 100644
--- a/src/osmo-upf/upf_vty.c
+++ b/src/osmo-upf/upf_vty.c
@@ -37,11 +37,13 @@
#include <osmocom/upf/up_peer.h>
#include <osmocom/upf/up_session.h>
#include <osmocom/upf/up_gtp_action.h>
+#include <osmocom/upf/netinst.h>
enum upf_vty_node {
PFCP_NODE = _LAST_OSMOVTY_NODE + 1,
TUNEND_NODE,
TUNMAP_NODE,
+ NETINST_NODE,
};
static struct cmd_node cfg_pfcp_node = {
@@ -252,6 +254,67 @@
return CMD_SUCCESS;
}
+static struct cmd_node cfg_netinst_node = {
+ NETINST_NODE,
+ "%s(config-netinst)# ",
+ 1,
+};
+
+DEFUN(cfg_netinst, cfg_netinst_cmd,
+ "netinst",
+ "Enter the Network Instance configuration node\n")
+{
+ vty->node = NETINST_NODE;
+ return CMD_SUCCESS;
+}
+
+static int config_write_netinst(struct vty *vty)
+{
+ vty_out(vty, "netinst%s", VTY_NEWLINE);
+ netinst_vty_write(vty, &g_upf->netinst, " ", NULL);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_netinst_add, cfg_netinst_add_cmd,
+ "add NAME ADDR",
+ "add Network Instance: associate a PFCP Network Instance name with a local IP
address\n"
+ "Network Instance name as received in PFCP Network Instance IE\n"
+ "IP address of a local interface\n")
+{
+ const char *errmsg;
+ if (!netinst_add(g_upf, &g_upf->netinst, argv[0], argv[1], &errmsg)) {
+ vty_out(vty, "%% Error: netinst: cannot add %s %s: %s%s", argv[0], argv[1],
+ errmsg ? : "(unknown error)", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_netinst, show_netinst_cmd,
+ "show netinst [NAME]",
+ SHOW_STR "List configured Network Instance entries\n"
+ "Show the Network Instance with this name (show all when omitted)\n")
+{
+ const char *name_or_null = argc > 0 ? argv[0] : NULL;
+
+ if (!netinst_vty_write(vty, &g_upf->netinst, " ", name_or_null)) {
+ if (name_or_null)
+ vty_out(vty, "%% No such Network Instance entry%s", VTY_NEWLINE);
+ else
+ vty_out(vty, "%% No Network Instance entries configured%s", VTY_NEWLINE);
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_netinst_clear, cfg_netinst_clear_cmd,
+ "clear",
+ "Remove all Network Instance entries\n")
+{
+ int count = netinst_clear(&g_upf->netinst);
+ vty_out(vty, "netinst entries removed: %d%s", count, VTY_NEWLINE);
+ return CMD_SUCCESS;
+}
+
DEFUN(show_pdr, show_pdr_cmd,
"show pdr",
SHOW_STR
@@ -348,6 +411,7 @@
install_element_ve(&show_pdr_cmd);
install_element_ve(&show_gtp_cmd);
install_element_ve(&show_session_cmd);
+ install_element_ve(&show_netinst_cmd);
install_node(&cfg_pfcp_node, config_write_pfcp);
install_element(CONFIG_NODE, &cfg_pfcp_cmd);
@@ -371,4 +435,11 @@
install_element(TUNMAP_NODE, &cfg_tunmap_mockup_cmd);
install_element(TUNMAP_NODE, &cfg_tunmap_no_mockup_cmd);
install_element(TUNMAP_NODE, &cfg_tunmap_table_name_cmd);
+
+ install_node(&cfg_netinst_node, config_write_netinst);
+ install_element(CONFIG_NODE, &cfg_netinst_cmd);
+
+ install_element(NETINST_NODE, &cfg_netinst_clear_cmd);
+ install_element(NETINST_NODE, &cfg_netinst_add_cmd);
+ install_element(NETINST_NODE, &show_netinst_cmd);
}
diff --git a/tests/netinst.vty b/tests/netinst.vty
new file mode 100644
index 0000000..7b3c726
--- /dev/null
+++ b/tests/netinst.vty
@@ -0,0 +1,80 @@
+OsmoUPF> show ?
+...
+ netinst List configured Network Instance entries
+...
+OsmoUPF> show netinst?
+ netinst List configured Network Instance entries
+OsmoUPF> show netinst ?
+ [NAME] Show the Network Instance with this name (show all when omitted)
+
+OsmoUPF> show netinst
+% No Network Instance entries configured
+OsmoUPF> show netinst foo
+% No such Network Instance entry
+
+OsmoUPF> enable
+
+OsmoUPF# show netinst
+% No Network Instance entries configured
+
+OsmoUPF# configure terminal
+OsmoUPF(config)# netinst
+
+OsmoUPF(config-netinst)# list
+...
+ clear
+ add NAME ADDR
+ show netinst [NAME]
+
+OsmoUPF(config-netinst)# clear?
+ clear Remove all Network Instance entries
+OsmoUPF(config-netinst)# clear ?
+ <cr>
+
+OsmoUPF(config-netinst)# add?
+ add add Network Instance: associate a PFCP Network Instance name with a local IP
address
+OsmoUPF(config-netinst)# add ?
+ NAME Network Instance name as received in PFCP Network Instance IE
+OsmoUPF(config-netinst)# add foo ?
+ ADDR IP address of a local interface
+
+OsmoUPF(config-netinst)# add foo bar
+% Error: netinst: cannot add foo bar: Network Instance address is not a valid IP address
string
+OsmoUPF(config-netinst)# add foo 1.2.3.4
+OsmoUPF(config-netinst)# add foo 2.3.4.5
+% Error: netinst: cannot add foo 2.3.4.5: Network Instance entry with this name already
exists
+OsmoUPF(config-netinst)# add bar 2.3.4.5
+OsmoUPF(config-netinst)# show netinst
+ add foo 1.2.3.4
+ add bar 2.3.4.5
+OsmoUPF(config-netinst)# add baz 1:2:3:4::0
+OsmoUPF(config-netinst)# show netinst
+ add foo 1.2.3.4
+ add bar 2.3.4.5
+ add baz 1:2:3:4::0
+OsmoUPF(config-netinst)# show netinst foo
+ add foo 1.2.3.4
+OsmoUPF(config-netinst)# show netinst bar
+ add bar 2.3.4.5
+OsmoUPF(config-netinst)# show netinst baz
+ add baz 1:2:3:4::0
+
+OsmoUPF(config-netinst)# show running-config
+...
+netinst
+ add foo 1.2.3.4
+ add bar 2.3.4.5
+ add baz 1:2:3:4::0
+...
+
+OsmoUPF(config-netinst)# clear
+netinst entries removed: 3
+OsmoUPF(config-netinst)# show netinst
+% No Network Instance entries configured
+OsmoUPF(config-netinst)# clear
+netinst entries removed: 0
+
+OsmoUPF(config-netinst)# show netinst?
+ netinst List configured Network Instance entries
+OsmoUPF(config-netinst)# show netinst ?
+ [NAME] Show the Network Instance with this name (show all when omitted)
--
To view, visit
https://gerrit.osmocom.org/c/osmo-upf/+/30461
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-upf
Gerrit-Branch: master
Gerrit-Change-Id: I15ee046a1c37b83b8a83527a67a6215a30106d81
Gerrit-Change-Number: 30461
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
Gerrit-MessageType: newchange