neels has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-upf/+/28309 )


Change subject: add nft
......................................................................

add nft

Related: SYS#5599
Change-Id: Ic0d319eb4f98cd51a5999c804c4203ab0bdda650
---
M configure.ac
M include/osmocom/upf/upf.h
M include/osmocom/upf/upf_nft.h
M src/osmo-upf/Makefile.am
M src/osmo-upf/osmo_upf_main.c
M src/osmo-upf/up_gtp_action.c
M src/osmo-upf/up_session.c
M src/osmo-upf/upf.c
A src/osmo-upf/upf_nft.c
M src/osmo-upf/upf_vty.c
10 files changed, 419 insertions(+), 6 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-upf refs/changes/09/28309/1

diff --git a/configure.ac b/configure.ac
index 119aa6c..fea27c6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -45,6 +45,8 @@
 PKG_CHECK_MODULES(LIBOSMOGTLV, libosmo-gtlv >= 0.1.0)
 PKG_CHECK_MODULES(LIBOSMOPFCP, libosmo-pfcp >= 0.1.0)
 PKG_CHECK_MODULES(LIBGTPNL, libgtpnl >= 1.2.0)
+PKG_CHECK_MODULES(LIBNFTNL, libnftnl >= 1.2.1)
+PKG_CHECK_MODULES(LIBNFTABLES, libnftables >= 1.0.2)

 dnl checks for header files
 AC_HEADER_STDC
diff --git a/include/osmocom/upf/upf.h b/include/osmocom/upf/upf.h
index b8065dd..49217c6 100644
--- a/include/osmocom/upf/upf.h
+++ b/include/osmocom/upf/upf.h
@@ -33,6 +33,7 @@
 struct ctrl_handle;

 struct upf_gtp_dev;
+struct nft_ctx;

 #define UPF_PFCP_LISTEN_DEFAULT "0.0.0.0"

@@ -72,6 +73,8 @@
                struct pfcp_vty_cfg vty_cfg;
                struct up_endpoint *ep;
        } pfcp;
+
+       /* Tunnel encaps decaps via GTP kernel module */
        struct {
                /* GTP devices as in osmo-upf.cfg */
                struct gtp_vty_cfg vty_cfg;
@@ -82,6 +85,14 @@
                struct mnl_socket *nl;
                int32_t genl_id;
        } gtp;
+
+       /* Tunnel forwarding via linux netfilter */
+       struct {
+               struct nft_ctx *nft_ctx;
+               char *table_name;
+               int priority;
+               uint32_t next_id_state;
+       } nft;
 };

 extern struct g_upf *g_upf;
@@ -91,6 +102,7 @@
        DPEER,
        DSESSION,
        DGTP,
+       DNFT,
 };

 void g_upf_alloc(void *ctx);
diff --git a/include/osmocom/upf/upf_nft.h b/include/osmocom/upf/upf_nft.h
index 569eadb..113bfd8 100644
--- a/include/osmocom/upf/upf_nft.h
+++ b/include/osmocom/upf/upf_nft.h
@@ -27,6 +27,8 @@

 #include <osmocom/core/socket.h>

+#define NFT_CHAIN_NAME_PREFIX_TUNMAP "tunmap"
+
 struct upf_nft_tunmap_desc {
        struct {
                struct osmo_sockaddr gtp_remote_addr;
diff --git a/src/osmo-upf/Makefile.am b/src/osmo-upf/Makefile.am
index d8aa5a0..1265051 100644
--- a/src/osmo-upf/Makefile.am
+++ b/src/osmo-upf/Makefile.am
@@ -13,11 +13,15 @@
        $(LIBOSMOGTLV_CFLAGS) \
        $(LIBOSMOPFCP_CFLAGS) \
        $(LIBGTPNL_CFLAGS) \
+       $(LIBNFTNL_CFLAGS) \
+       $(LIBNFTABLES_CFLAGS) \
        $(COVERAGE_CFLAGS) \
        $(NULL)

 AM_LDFLAGS = \
        $(LIBGTPNL_LDFLAGS) \
+       $(LIBNFTNL_LDFLAGS) \
+       $(LIBNFTABLES_LDFLAGS) \
        $(COVERAGE_LDFLAGS) \
        $(NULL)

@@ -33,6 +37,7 @@
        up_session.c \
        upf.c \
        upf_gtp.c \
+       upf_nft.c \
        upf_vty.c \
        $(NULL)

@@ -43,5 +48,7 @@
        $(LIBOSMOGTLV_LIBS) \
        $(LIBOSMOPFCP_LIBS) \
        $(LIBGTPNL_LIBS) \
+       $(LIBNFTNL_LIBS) \
+       $(LIBNFTABLES_LIBS) \
        $(COVERAGE_LDFLAGS) \
        $(NULL)
diff --git a/src/osmo-upf/osmo_upf_main.c b/src/osmo-upf/osmo_upf_main.c
index 302d957..81102dd 100644
--- a/src/osmo-upf/osmo_upf_main.c
+++ b/src/osmo-upf/osmo_upf_main.c
@@ -44,6 +44,7 @@
 #include <osmocom/upf/upf.h>
 #include <osmocom/upf/up_endpoint.h>
 #include <osmocom/upf/upf_gtp.h>
+#include <osmocom/upf/upf_nft.h>

 #define _GNU_SOURCE
 #include <getopt.h>
@@ -237,6 +238,12 @@
                .enabled = 0, .loglevel = LOGL_NOTICE,
                .color = OSMO_LOGCOLOR_PURPLE,
        },
+       [DNFT] = {
+               .name = "DNFT",
+               .description = "GTP forwarding rules via linux netfilter",
+               .enabled = 0, .loglevel = LOGL_NOTICE,
+               .color = OSMO_LOGCOLOR_PURPLE,
+       },
 };

 const struct log_info log_info = {
@@ -330,6 +337,9 @@
        if (upf_gtp_devs_open())
                return -1;

+       if (upf_nft_init())
+               return -1;
+
        if (upf_pfcp_listen())
                return -1;

@@ -356,6 +366,8 @@

        upf_gtp_genl_close();

+       upf_nft_free();
+
        /* Report the heap state of talloc contexts, then free, so both ASAN 
and Valgrind are happy... */
        talloc_report_full(tall_upf_ctx, stderr);
        talloc_free(tall_upf_ctx);
diff --git a/src/osmo-upf/up_gtp_action.c b/src/osmo-upf/up_gtp_action.c
index 840944e..cf5981e 100644
--- a/src/osmo-upf/up_gtp_action.c
+++ b/src/osmo-upf/up_gtp_action.c
@@ -100,9 +100,36 @@
                }
                LOG_UP_GTP_ACTION(a, LOGL_NOTICE, "%s GTP tunnel\n", enable ? 
"Enabled" : "Disabled");
                return 0;
+
        case UP_GTP_U_TUNMAP:
-               LOG_UP_GTP_ACTION(a, LOGL_ERROR, "TEID translation not yet 
implemented\n");
-               return -ENOTSUP;
+               if (enable && a->tunmap.id != 0) {
+                       LOG_UP_GTP_ACTION(a, LOGL_ERROR,
+                                         "Cannot enable: nft GTP tunnel 
mapping rule has been enabled before"
+                                         " as " NFT_CHAIN_NAME_PREFIX_TUNMAP 
"%u\n", a->tunmap.id);
+                       return -EALREADY;
+               }
+               if (!enable && a->tunmap.id == 0) {
+                       LOG_UP_GTP_ACTION(a, LOGL_ERROR,
+                                         "Cannot disable: nft GTP tunnel 
mapping rule has not been enabled"
+                                         " (no " NFT_CHAIN_NAME_PREFIX_TUNMAP 
" id)\n");
+                       return -ENOENT;
+               }
+               if (enable)
+                       rc = upf_nft_tunmap_create(&a->tunmap);
+               else
+                       rc = upf_nft_tunmap_delete(&a->tunmap);
+               if (rc) {
+                       LOG_UP_GTP_ACTION(a, LOGL_ERROR,
+                                         "Failed to %s nft GTP tunnel mapping 
" NFT_CHAIN_NAME_PREFIX_TUNMAP "%u:"
+                                         " %d %s\n", enable ? "enable" : 
"disable", a->tunmap.id, rc, strerror(-rc));
+                       return rc;
+               }
+               LOG_UP_GTP_ACTION(a, LOGL_NOTICE, "%s nft GTP tunnel mapping " 
NFT_CHAIN_NAME_PREFIX_TUNMAP "%u\n",
+                                 enable ? "Enabled" : "Disabled", 
a->tunmap.id);
+               if (!enable)
+                       a->tunmap.id = 0;
+               return 0;
+
        default:
                LOG_UP_GTP_ACTION(a, LOGL_ERROR, "Invalid action\n");
                return -ENOTSUP;
diff --git a/src/osmo-upf/up_session.c b/src/osmo-upf/up_session.c
index d1479b1..00299d3 100644
--- a/src/osmo-upf/up_session.c
+++ b/src/osmo-upf/up_session.c
@@ -1141,7 +1141,107 @@

 static void add_gtp_action_forw(void *ctx, struct llist_head *dst, struct pdr 
*pdr)
 {
-       /* TODO implement GTP forwarding with TEID translation */
+       struct up_session *session = pdr->session;
+       struct up_gtp_action *a;
+       struct pdr *rpdr;
+       struct far *far;
+       struct osmo_pfcp_ie_forw_params *far_forw;
+       struct far *rfar;
+       struct osmo_pfcp_ie_forw_params *rfar_forw;
+
+       OSMO_ASSERT(pdr->far);
+       OSMO_ASSERT(pdr->reverse_pdr);
+       OSMO_ASSERT(pdr->reverse_pdr->far);
+
+       far = pdr->far;
+       far_forw = &far->desc.forw_params;
+       rpdr = pdr->reverse_pdr;
+       rfar = rpdr->far;
+       rfar_forw = &rfar->desc.forw_params;
+
+       /* To decaps, we need to have a local TEID assigned for which to 
receive GTP packets. */
+       /* decaps from CORE */
+       if (!pdr->local_f_teid || pdr->local_f_teid->choose_flag) {
+               log_inactive_pdr_set(pdr, "missing local TEID (CORE side)", 
pdr);
+               return;
+       }
+       /* decaps from ACCESS */
+       if (!rpdr->local_f_teid || rpdr->local_f_teid->choose_flag) {
+               log_inactive_pdr_set(pdr, "missing local TEID (ACCESS side)", 
pdr);
+               return;
+       }
+
+       /* To encaps, we need to have a remote TEID assigned to send out in GTP 
packets, and we need to know where to
+        * send GTP to. */
+       /* encaps towards ACCESS */
+       if (!far->desc.forw_params_present) {
+               log_inactive_pdr_set(pdr, "missing FAR Forwarding Parameters", 
pdr);
+               return;
+       }
+       if (!far_forw->outer_header_creation_present) {
+               log_inactive_pdr_set(pdr, "missing FAR Outer Header Creation", 
pdr);
+               return;
+       }
+       if (!far_forw->outer_header_creation.teid_present) {
+               log_inactive_pdr_set(pdr, "missing TEID in FAR Outer Header 
Creation", pdr);
+               return;
+       }
+       if (!far_forw->outer_header_creation.ip_addr.v4_present) {
+               log_inactive_pdr_set(pdr, "missing IPv4 in FAR Outer Header 
Creation", pdr);
+               return;
+       }
+       /* encaps towards CORE */
+       if (!rfar->desc.forw_params_present) {
+               log_inactive_pdr_set(pdr, "missing FAR Forwarding Parameters", 
rpdr);
+               return;
+       }
+       if (!rfar_forw->outer_header_creation_present) {
+               log_inactive_pdr_set(pdr, "missing FAR Outer Header Creation", 
rpdr);
+               return;
+       }
+       if (!rfar_forw->outer_header_creation.teid_present) {
+               log_inactive_pdr_set(pdr, "missing TEID in FAR Outer Header 
Creation", rpdr);
+               return;
+       }
+       if (!rfar_forw->outer_header_creation.ip_addr.v4_present) {
+               log_inactive_pdr_set(pdr, "missing IPv4 in FAR Outer Header 
Creation", rpdr);
+               return;
+       }
+
+       pdr->active = true;
+       far->active = true;
+       rpdr->active = true;
+       rfar->active = true;
+       LOGPFSML(session->fi, LOGL_DEBUG, "Active PDR set:   %s\n", 
pdr_to_str_c(OTC_SELECT, pdr));
+       LOGPFSML(session->fi, LOGL_DEBUG, "Active PDR set: + %s\n", 
pdr_to_str_c(OTC_SELECT, rpdr));
+
+       talloc_free(pdr->inactive_reason);
+       pdr->inactive_reason = NULL;
+       talloc_free(rpdr->inactive_reason);
+       rpdr->inactive_reason = NULL;
+
+       a = talloc(ctx, struct up_gtp_action);
+       OSMO_ASSERT(a);
+       *a = (struct up_gtp_action){
+               .session = session,
+               .pdr_core = pdr->desc.pdr_id,
+               .pdr_access = rpdr->desc.pdr_id,
+               .kind = UP_GTP_U_TUNMAP,
+               .tunmap = {
+                       .core = {
+                               .local_teid = pdr->local_f_teid->fixed.teid,
+                               .remote_teid = 
rfar_forw->outer_header_creation.teid,
+                               .gtp_remote_addr = 
rfar_forw->outer_header_creation.ip_addr.v4,
+                       },
+                       .access = {
+                               .local_teid = rpdr->local_f_teid->fixed.teid,
+                               .remote_teid = 
far_forw->outer_header_creation.teid,
+                               .gtp_remote_addr = 
far_forw->outer_header_creation.ip_addr.v4,
+                       },
+               },
+       };
+
+       llist_add_tail(&a->entry, dst);
 }

 /* Analyse all PDRs and FARs and find configurations that match either a GTP 
encaps/decaps or a GTP forward rule. Add to
@@ -1294,11 +1394,12 @@
 {
        struct llist_head empty;
        INIT_LLIST_HEAD(&empty);
+       /* Call setup_gtp_actions() with an empty list, to clean up all active 
GTP actions */
        setup_gtp_actions(session, &empty);
 }

-/* Check whether the Packet Detection and Forwarding Action Rules amount to an 
encaps/decaps of GTP or a GTP forwarding,
- * or none of the two. */
+/* Check whether the Packet Detection and Forwarding Action Rules amount to an 
encaps/decaps of GTP or a GTP tunnel
+ * mapping, or none of the two. */
 static enum osmo_pfcp_cause up_session_setup_gtp(struct up_session *session)
 {
        enum osmo_pfcp_cause cause;
diff --git a/src/osmo-upf/upf.c b/src/osmo-upf/upf.c
index 234368a..9677147 100644
--- a/src/osmo-upf/upf.c
+++ b/src/osmo-upf/upf.c
@@ -50,6 +50,9 @@
                                .local_port = OSMO_PFCP_PORT,
                        },
                },
+               .nft = {
+                       .priority = -300,
+               },
        };

        INIT_LLIST_HEAD(&g_upf->gtp.vty_cfg.devs);
diff --git a/src/osmo-upf/upf_nft.c b/src/osmo-upf/upf_nft.c
new file mode 100644
index 0000000..d93dc39
--- /dev/null
+++ b/src/osmo-upf/upf_nft.c
@@ -0,0 +1,207 @@
+/*
+ * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH <[email protected]>
+ * All Rights Reserved.
+ *
+ * Author: Neels Janosch Hofmeyr <[email protected]>
+ *
+ * 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 <errno.h>
+#include <nftables/libnftables.h>
+
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/logging.h>
+
+#include <osmocom/upf/upf.h>
+#include <osmocom/upf/upf_nft.h>
+
+static char *upf_nft_ruleset_table_create(void *ctx, const char *table_name)
+{
+       return talloc_asprintf(ctx, "add table inet %s\n", table_name);
+}
+
+static int upf_nft_run(const char *ruleset)
+{
+       int rc;
+       if (!g_upf->nft.nft_ctx) {
+               rc = upf_nft_init();
+               if (rc)
+                       return rc;
+       }
+
+       rc = nft_run_cmd_from_buffer(g_upf->nft.nft_ctx, ruleset);
+       if (rc < 0) {
+               LOGP(DNFT, LOGL_ERROR, "error running nft ruleset: rc=%d 
ruleset=%s\n",
+                    rc, osmo_quote_str_c(OTC_SELECT, ruleset, -1));
+               return -EIO;
+       }
+       return 0;
+}
+
+int upf_nft_init()
+{
+       int rc;
+       g_upf->nft.nft_ctx = nft_ctx_new(NFT_CTX_DEFAULT);
+       if (!g_upf->nft.nft_ctx) {
+               LOGP(DNFT, LOGL_ERROR, "cannot allocate libnftables nft_ctx\n");
+               return -EIO;
+       }
+
+       if (!g_upf->nft.table_name)
+               g_upf->nft.table_name = talloc_strdup(g_upf, "osmo-upf");
+
+       rc = upf_nft_run(upf_nft_ruleset_table_create(OTC_SELECT, 
g_upf->nft.table_name));
+       if (rc) {
+               LOGP(DNFT, LOGL_ERROR, "Failed to create nft table %s\n",
+                    osmo_quote_str_c(OTC_SELECT, g_upf->nft.table_name, -1));
+               return rc;
+       }
+       LOGP(DNFT, LOGL_NOTICE, "Created nft table %s\n", 
osmo_quote_str_c(OTC_SELECT, g_upf->nft.table_name, -1));
+       return 0;
+}
+
+int upf_nft_free()
+{
+       if (!g_upf->nft.nft_ctx)
+               return 0;
+       nft_ctx_free(g_upf->nft.nft_ctx);
+       g_upf->nft.nft_ctx = NULL;
+       return 0;
+}
+
+struct upf_nft_args_peer {
+       /* The source IP address in packets received from this peer */
+       const struct osmo_sockaddr *addr;
+       /* The TEID that we send to the peer in GTP packets. */
+       uint32_t teid_remote;
+       /* The TEID that the peer sends to us in GTP packets. */
+       uint32_t teid_local;
+};
+
+struct upf_nft_args {
+       /* global table name */
+       const char *table_name;
+       /* chain name for this specific tunnel mapping */
+       uint32_t chain_id;
+       int priority;
+
+       struct upf_nft_args_peer peer_a;
+       struct upf_nft_args_peer peer_b;
+};
+
+static int tunmap_single_direction(char *buf, size_t buflen,
+                                  const struct upf_nft_args *args,
+                                  const struct upf_nft_args_peer *from_peer,
+                                  const struct upf_nft_args_peer *to_peer)
+{
+       struct osmo_strbuf sb = { .buf = buf, .len = buflen };
+       OSMO_STRBUF_PRINTF(sb, "add rule inet %s " NFT_CHAIN_NAME_PREFIX_TUNMAP 
"%u", args->table_name, args->chain_id);
+
+       /* Match only UDP packets */
+       OSMO_STRBUF_PRINTF(sb, " meta l4proto udp");
+
+       /* Match on packets coming in from from_peer */
+       OSMO_STRBUF_PRINTF(sb, " ip saddr ");
+       OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, from_peer->addr);
+
+       /* Match on the TEID in the header */
+       OSMO_STRBUF_PRINTF(sb, " @ih,32,32 0x%08x", from_peer->teid_local);
+
+       /* Change destination address to to_peer */
+       OSMO_STRBUF_PRINTF(sb, " ip daddr set ");
+       OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, to_peer->addr);
+
+       /* Change the TEID in the header to the one to_peer expects */
+       OSMO_STRBUF_PRINTF(sb, " @ih,32,32 set 0x%08x", to_peer->teid_remote);
+
+       OSMO_STRBUF_PRINTF(sb, " counter\n");
+
+       return sb.chars_needed;
+}
+
+static int upf_nft_ruleset_tunmap_create_buf(char *buf, size_t buflen, const 
struct upf_nft_args *args)
+{
+       struct osmo_strbuf sb = { .buf = buf, .len = buflen };
+
+       /* Add a chain for this tunnel mapping */
+       OSMO_STRBUF_PRINTF(sb, "add chain inet %s " 
NFT_CHAIN_NAME_PREFIX_TUNMAP "%u { type filter hook prerouting priority %d; 
}\n",
+                          args->table_name, args->chain_id, args->priority);
+
+       /* Forwarding from peer_a to peer_b */
+       OSMO_STRBUF_APPEND(sb, tunmap_single_direction, args, &args->peer_a, 
&args->peer_b);
+       /* And from peer_b to peer_a */
+       OSMO_STRBUF_APPEND(sb, tunmap_single_direction, args, &args->peer_b, 
&args->peer_a);
+
+       return sb.chars_needed;
+}
+
+static char *upf_nft_ruleset_tunmap_create_c(void *ctx, const struct 
upf_nft_args *args)
+{
+       OSMO_NAME_C_IMPL(ctx, 512, "ERROR", upf_nft_ruleset_tunmap_create_buf, 
args)
+}
+
+static int upf_nft_ruleset_tunmap_delete_buf(char *buf, size_t buflen, const 
struct upf_nft_args *args)
+{
+       struct osmo_strbuf sb = { .buf = buf, .len = buflen };
+       OSMO_STRBUF_PRINTF(sb, "delete chain inet %s " 
NFT_CHAIN_NAME_PREFIX_TUNMAP "%u\n",
+                          args->table_name, args->chain_id);
+       return sb.chars_needed;
+}
+
+static char *upf_nft_ruleset_tunmap_delete_c(void *ctx, const struct 
upf_nft_args *args)
+{
+       OSMO_NAME_C_IMPL(ctx, 64, "ERROR", upf_nft_ruleset_tunmap_delete_buf, 
args)
+}
+
+static void upf_nft_args_from_tunmap_desc(struct upf_nft_args *args, const 
struct upf_nft_tunmap_desc *tunmap)
+{
+       *args = (struct upf_nft_args){
+               .table_name = g_upf->nft.table_name,
+               .chain_id = tunmap->id,
+               .priority = g_upf->nft.priority,
+               .peer_a = {
+                       .addr = &tunmap->access.gtp_remote_addr,
+                       .teid_remote = tunmap->access.remote_teid,
+                       .teid_local = tunmap->access.local_teid,
+               },
+               .peer_b = {
+                       .addr = &tunmap->core.gtp_remote_addr,
+                       .teid_remote = tunmap->core.remote_teid,
+                       .teid_local = tunmap->core.local_teid,
+               },
+       };
+}
+
+int upf_nft_tunmap_create(struct upf_nft_tunmap_desc *tunmap)
+{
+       struct upf_nft_args args;
+
+       /* Give this tunnel mapping a new id, returned to the caller so that 
the tunnel mapping can be deleted later */
+       g_upf->nft.next_id_state++;
+       tunmap->id = g_upf->nft.next_id_state;
+
+       upf_nft_args_from_tunmap_desc(&args, tunmap);
+       return upf_nft_run(upf_nft_ruleset_tunmap_create_c(OTC_SELECT, &args));
+}
+
+int upf_nft_tunmap_delete(struct upf_nft_tunmap_desc *tunmap)
+{
+       struct upf_nft_args args;
+       upf_nft_args_from_tunmap_desc(&args, tunmap);
+       return upf_nft_run(upf_nft_ruleset_tunmap_delete_c(OTC_SELECT, &args));
+}
diff --git a/src/osmo-upf/upf_vty.c b/src/osmo-upf/upf_vty.c
index 73d86d1..0e51cd4 100644
--- a/src/osmo-upf/upf_vty.c
+++ b/src/osmo-upf/upf_vty.c
@@ -41,6 +41,7 @@
 enum upf_vty_node {
        PFCP_NODE = _LAST_OSMOVTY_NODE + 1,
        GTP_NODE,
+       NFT_NODE,
 };

 static struct cmd_node cfg_pfcp_node = {
@@ -85,7 +86,7 @@

 DEFUN(cfg_gtp, cfg_gtp_cmd,
       "gtp",
-      "Enter the GTP configuration node\n")
+      "Enter the 'gtp' node to configure GTP kernel module usage\n")
 {
        vty->node = GTP_NODE;
        return CMD_SUCCESS;
@@ -169,6 +170,40 @@
        return CMD_SUCCESS;
 }

+static struct cmd_node cfg_nft_node = {
+       NFT_NODE,
+       "%s(config-nft)# ",
+       1,
+};
+
+DEFUN(cfg_nft, cfg_nft_cmd,
+      "nft",
+      "Enter the 'nft' node to configure nftables usage\n")
+{
+       vty->node = NFT_NODE;
+       return CMD_SUCCESS;
+}
+
+static int config_write_nft(struct vty *vty)
+{
+       vty_out(vty, "nft%s", VTY_NEWLINE);
+
+       if (g_upf->nft.table_name && strcmp(g_upf->nft.table_name, "osmo-upf"))
+               vty_out(vty, " table-name %s%s", g_upf->nft.table_name, 
VTY_NEWLINE);
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nft_table_name, cfg_nft_table_name_cmd,
+      "table-name TABLE_NAME",
+      "Set the nft inet table name to create and place GTP tunnel forwarding 
chains in"
+      " (as in 'nft add table inet foo'). If multiple instances of osmo-upf 
are running on the same system, each"
+      " osmo-upf must have its own table name. Otherwise the names of created 
forwarding chains will collide.\n"
+      "nft inet table name\n")
+{
+       osmo_talloc_replace_string(g_upf, &g_upf->nft.table_name, argv[0]);
+       return CMD_SUCCESS;
+}
+
 DEFUN(show_pdr, show_pdr_cmd,
       "show pdr",
       SHOW_STR
@@ -282,5 +317,10 @@
        install_element(GTP_NODE, &cfg_gtp_dev_create_cmd);
        install_element(GTP_NODE, &cfg_gtp_dev_use_cmd);
        install_element(GTP_NODE, &cfg_gtp_dev_del_cmd);
+
+       install_node(&cfg_nft_node, config_write_nft);
+       install_element(CONFIG_NODE, &cfg_nft_cmd);
+
+       install_element(NFT_NODE, &cfg_nft_table_name_cmd);
 }


--
To view, visit https://gerrit.osmocom.org/c/osmo-upf/+/28309
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-upf
Gerrit-Branch: master
Gerrit-Change-Id: Ic0d319eb4f98cd51a5999c804c4203ab0bdda650
Gerrit-Change-Number: 28309
Gerrit-PatchSet: 1
Gerrit-Owner: neels <[email protected]>
Gerrit-MessageType: newchange

Reply via email to