tunmap: refactor nft ruleset: fix "martians" and "1024"

Take care of two problems:
- limitation of <= 1024 base chains in nftables, so far meaning we can
  establish at most 1024 GTP tunnel mappings.
- mangling of source IP in prerouting so far meaning that the system
  needs to be configured to permit 'martian' packets

The new ruleset separates in pre- and post-routing, so that we set a new
destination IP address in pre-routing, and set a new source IP address
in post-routing. Hence no problem with martian packet rejection.

The new ruleset uses verdict maps, which are more efficient, and do not
hit a limit of 1024 as base chains do.

Before, the nft rule used one chain id. In the new ruleset, each tunmap
now needs two distinct chain ids. Refactor.

Related: SYS#6327 SYS#6264
Change-Id: Iccb975a1c0f8a2087f7b7dc4942a6b41f5675a13
This commit is contained in:
Neels Hofmeyr 2023-02-03 02:05:05 +01:00
parent fbe70076eb
commit 4e1c680e59
7 changed files with 245 additions and 82 deletions

View File

@ -110,8 +110,9 @@ struct g_upf {
struct nft_ctx *nft_ctx;
char *table_name;
int priority;
uint32_t next_id_state;
int priority_pre;
int priority_post;
uint32_t next_chain_id_state;
} nft;
struct llist_head netinst;

View File

@ -27,28 +27,32 @@
#include <osmocom/core/socket.h>
#define NFT_CHAIN_NAME_PREFIX_TUNMAP "tunmap"
struct upf_nft_tunmap_desc {
struct {
struct osmo_sockaddr gtp_local_addr;
uint32_t local_teid;
struct osmo_sockaddr gtp_remote_addr;
uint32_t remote_teid;
uint32_t chain_id;
} access;
struct {
struct osmo_sockaddr gtp_local_addr;
uint32_t local_teid;
struct osmo_sockaddr gtp_remote_addr;
uint32_t remote_teid;
uint32_t chain_id;
} core;
/* id as in ruleset name 'tunmap<id>'. If zero, no id has been assigned yet. */
uint32_t id;
};
int upf_nft_tunmap_to_str_buf(char *buf, size_t buflen, const struct upf_nft_tunmap_desc *tunmap);
char *upf_nft_tunmap_to_str_c(void *ctx, const struct upf_nft_tunmap_desc *tunmap);
int upf_nft_init();
int upf_nft_free();
char *upf_nft_tunmap_get_table_init_str(void *ctx);
char *upf_nft_tunmap_get_vmap_init_str(void *ctx);
char *upf_nft_tunmap_get_ruleset_str(void *ctx, struct upf_nft_tunmap_desc *tunmap);
char *upf_nft_tunmap_get_ruleset_del_str(void *ctx, struct upf_nft_tunmap_desc *tunmap);
int upf_nft_tunmap_create(struct upf_nft_tunmap_desc *tunmap);
int upf_nft_tunmap_delete(struct upf_nft_tunmap_desc *tunmap);

View File

@ -107,11 +107,11 @@ static int up_gtp_action_enable_disable(struct up_gtp_action *a, bool enable)
else
rc = upf_gtp_dev_tunend_del(gtp_dev, &a->tunend);
if (rc) {
LOG_UP_GTP_ACTION(a, LOGL_ERROR, "Failed to %s GTP tunnel: %d %s\n",
enable ? "enable" : "disable", rc, strerror(-rc));
LOG_UP_GTP_ACTION(a, LOGL_ERROR, "Failed to %s GTP tunnel (rc=%d)\n",
enable ? "enable" : "disable", rc);
return rc;
}
LOG_UP_GTP_ACTION(a, LOGL_NOTICE, "%s GTP tunnel on dev %s\n", enable ? "Enabled" : "Disabled",
LOG_UP_GTP_ACTION(a, LOGL_NOTICE, "%s tunend on dev %s\n", enable ? "Enabled" : "Disabled",
gtp_dev->name);
return 0;
@ -122,32 +122,18 @@ static int up_gtp_action_enable_disable(struct up_gtp_action *a, bool enable)
return 0;
}
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 rule id %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 rule 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 %u:"
" %d %s\n", enable ? "enable" : "disable", a->tunmap.id, rc, strerror(-rc));
LOG_UP_GTP_ACTION(a, LOGL_ERROR, "Failed to %s nft GTP tunnel mapping (rc=%d)\n",
enable ? "enable" : "disable", rc);
return rc;
}
LOG_UP_GTP_ACTION(a, LOGL_NOTICE, "%s nft GTP tunnel mapping %u\n",
enable ? "Enabled" : "Disabled", a->tunmap.id);
if (!enable)
a->tunmap.id = 0;
LOG_UP_GTP_ACTION(a, LOGL_NOTICE, "%s tunmap, nft chain IDs: access--%u-> <-%u--core\n",
enable ? "Enabled" : "Disabled",
a->tunmap.access.chain_id, a->tunmap.core.chain_id);
return 0;
default:

View File

@ -51,7 +51,8 @@ void g_upf_alloc(void *ctx)
},
},
.nft = {
.priority = -300,
.priority_pre = -300,
.priority_post = 400,
},
.gtp = {
/* TODO: recovery count state file; use lower byte of current time, poor person's random. */

View File

@ -35,6 +35,30 @@ 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 char *upf_nft_ruleset_vmap_init(void *ctx, const char *table_name, int priority_pre, int priority_post)
{
/* add chain inet osmo-upf pre { type filter hook prerouting priority -300; policy accept; }
* add chain inet osmo-upf post { type filter hook postrouting priority 400; policy accept; }
* add map inet osmo-upf tunmap-pre { typeof ip daddr . @ih,32,32 : verdict; }
* add map inet osmo-upf tunmap-post { typeof meta mark : verdict; }
* add rule inet osmo-upf pre udp dport 2152 ip daddr . @ih,32,32 vmap @tunmap-pre
* add rule inet osmo-upf post meta mark vmap @tunmap-post
*/
return talloc_asprintf(ctx,
"add chain inet %s pre { type filter hook prerouting priority %d; policy accept; };\n"
"add chain inet %s post { type filter hook postrouting priority %d; policy accept; };\n"
"add map inet %s tunmap-pre { typeof ip daddr . @ih,32,32 : verdict; };\n"
"add map inet %s tunmap-post { typeof meta mark : verdict; };\n"
"add rule inet %s pre udp dport %u ip daddr . @ih,32,32 vmap @tunmap-pre;\n"
"add rule inet %s post meta mark vmap @tunmap-post;\n",
table_name, priority_pre,
table_name, priority_post,
table_name,
table_name,
table_name, PORT_GTP1_U,
table_name);
}
static int upf_nft_run(const char *ruleset)
{
int rc;
@ -82,13 +106,19 @@ int upf_nft_init()
return -EIO;
}
rc = upf_nft_run(upf_nft_ruleset_table_create(OTC_SELECT, g_upf->nft.table_name));
rc = upf_nft_run(upf_nft_tunmap_get_table_init_str(OTC_SELECT));
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));
rc = upf_nft_run(upf_nft_tunmap_get_vmap_init_str(OTC_SELECT));
if (rc) {
LOGP(DNFT, LOGL_ERROR, "Failed to initialize nft verdict map in table %s\n", g_upf->nft.table_name);
return rc;
}
return 0;
}
@ -110,53 +140,112 @@ struct upf_nft_args_peer {
const struct osmo_sockaddr *addr_local;
/* The TEID that the peer sends to us in GTP packets. */
uint32_t teid_local;
/* The nft chain id that forwards packets received on addr_local,teid_local. Also used for the 'mark' id in
* the verdict map ruleset. */
uint32_t chain_id;
};
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)
static int tunmap_add_single_direction(char *buf, size_t buflen,
const struct upf_nft_args *args,
bool dir_a2b)
{
struct osmo_strbuf sb = { .buf = buf, .len = buflen };
const struct upf_nft_args_peer *from_peer;
const struct upf_nft_args_peer *to_peer;
OSMO_STRBUF_PRINTF(sb, "add rule inet %s " NFT_CHAIN_NAME_PREFIX_TUNMAP "%u", args->table_name, args->chain_id);
if (dir_a2b) {
from_peer = &args->peer_a;
to_peer = &args->peer_b;
} else {
from_peer = &args->peer_b;
to_peer = &args->peer_a;
}
/* Match only UDP packets */
OSMO_STRBUF_PRINTF(sb, " meta l4proto udp");
/* # add chain for verdict map in prerouting
* add chain inet osmo-upf tunmap-pre-123
* # mangle destination address at prerouting
* add rule inet osmo-upf tunmap-pre-123 ip daddr set 1.1.1.1 meta mark set 123 counter accept
*
* # add chain for verdict map in postrouting
* add chain inet osmo-upf tunmap-post-123
* # mangle source address and GTP TID at postrouting
* add rule inet osmo-upf tunmap-post-123 ip saddr set 2.2.2.1 @ih,32,32 set 0x00000102 counter accept
*
* # add elements to verdict map, jump to chain
* add element inet osmo-upf tunmap-pre { 2.2.2.3 . 0x00000203 : jump tunmap-pre-123 }
* add element inet osmo-upf tunmap-post { 123 : jump tunmap-post-123 }
*/
/* Match on packets coming in at specific local IP */
OSMO_STRBUF_PRINTF(sb, " ip daddr ");
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, from_peer->addr_local);
OSMO_STRBUF_PRINTF(sb, "add chain inet %s tunmap-pre-%u;\n",
args->table_name, from_peer->chain_id);
/* Match on the TEID in the header */
OSMO_STRBUF_PRINTF(sb, " @ih,32,32 0x%08x", from_peer->teid_local);
/* Change outgoing address to local IP on outgoing interface */
OSMO_STRBUF_PRINTF(sb, " ip saddr set ");
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, to_peer->addr_local);
/* Change destination address to to_peer */
OSMO_STRBUF_PRINTF(sb, "add rule inet %s tunmap-pre-%u",
args->table_name, from_peer->chain_id);
OSMO_STRBUF_PRINTF(sb, " ip daddr set ");
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, to_peer->addr_remote);
OSMO_STRBUF_PRINTF(sb, " meta mark set %u counter accept;\n", from_peer->chain_id);
/* 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, "add chain inet %s tunmap-post-%u;\n",
args->table_name, from_peer->chain_id);
OSMO_STRBUF_PRINTF(sb, " counter");
OSMO_STRBUF_PRINTF(sb, "add rule inet %s tunmap-post-%u",
args->table_name, from_peer->chain_id);
OSMO_STRBUF_PRINTF(sb, " ip saddr set ");
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, to_peer->addr_local);
OSMO_STRBUF_PRINTF(sb, " @ih,32,32 set 0x%x", to_peer->teid_remote);
OSMO_STRBUF_PRINTF(sb, " counter accept;\n");
OSMO_STRBUF_PRINTF(sb, " accept");
OSMO_STRBUF_PRINTF(sb, ";\n");
OSMO_STRBUF_PRINTF(sb, "add element inet %s tunmap-pre { ",
args->table_name);
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, from_peer->addr_local);
OSMO_STRBUF_PRINTF(sb, " . 0x%x : jump tunmap-pre-%u };\n",
from_peer->teid_local, from_peer->chain_id);
OSMO_STRBUF_PRINTF(sb, "add element inet %s tunmap-post { %u : jump tunmap-post-%u };\n",
args->table_name, from_peer->chain_id, from_peer->chain_id);
return sb.chars_needed;
}
static int tunmap_del_single_direction(char *buf, size_t buflen,
const struct upf_nft_args *args,
bool dir_a2b)
{
struct osmo_strbuf sb = { .buf = buf, .len = buflen };
const struct upf_nft_args_peer *from_peer;
if (dir_a2b)
from_peer = &args->peer_a;
else
from_peer = &args->peer_b;
/* delete element inet osmo-upf tunmap-pre { 2.2.2.3 . 0x203 }
* delete element inet osmo-upf tunmap-post { 123 }
* delete chain inet osmo-upf tunmap-pre-123
* delete chain inet osmo-upf tunmap-post-123
*/
OSMO_STRBUF_PRINTF(sb, "delete element inet %s tunmap-pre { ",
args->table_name);
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, from_peer->addr_local);
OSMO_STRBUF_PRINTF(sb, " . 0x%x };\n", from_peer->teid_local);
OSMO_STRBUF_PRINTF(sb, "delete element inet %s tunmap-post { %u };\n",
args->table_name, from_peer->chain_id);
OSMO_STRBUF_PRINTF(sb, "delete chain inet %s tunmap-pre-%u;\n",
args->table_name, from_peer->chain_id);
OSMO_STRBUF_PRINTF(sb, "delete chain inet %s tunmap-post-%u;\n",
args->table_name, from_peer->chain_id);
return sb.chars_needed;
}
@ -165,34 +254,56 @@ static int upf_nft_ruleset_tunmap_create_buf(char *buf, size_t buflen, const str
{
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);
OSMO_STRBUF_APPEND(sb, tunmap_add_single_direction, args, true);
/* And from peer_b to peer_a */
OSMO_STRBUF_APPEND(sb, tunmap_single_direction, args, &args->peer_b, &args->peer_a);
OSMO_STRBUF_APPEND(sb, tunmap_add_single_direction, args, false);
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)
OSMO_NAME_C_IMPL(ctx, 1024, "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);
/* Forwarding from peer_a to peer_b */
OSMO_STRBUF_APPEND(sb, tunmap_del_single_direction, args, true);
/* And from peer_b to peer_a */
OSMO_STRBUF_APPEND(sb, tunmap_del_single_direction, args, false);
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)
OSMO_NAME_C_IMPL(ctx, 512, "ERROR", upf_nft_ruleset_tunmap_delete_buf, args)
}
int upf_nft_tunmap_to_str_buf(char *buf, size_t buflen, const struct upf_nft_tunmap_desc *tunmap)
{
struct osmo_strbuf sb = { .buf = buf, .len = buflen };
/* ACCESS 1.1.1.2:0x102 <---> 2.2.2.1:0x201 UPF 2.2.2.3:0x203 <---> 3.3.3.2:0x302 CORE */
OSMO_STRBUF_PRINTF(sb, "ACCESS ");
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &tunmap->access.gtp_remote_addr);
OSMO_STRBUF_PRINTF(sb, ":0x%x <---> ", tunmap->access.remote_teid);
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &tunmap->access.gtp_local_addr);
OSMO_STRBUF_PRINTF(sb, ":0x%x UPF ", tunmap->access.local_teid);
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &tunmap->core.gtp_local_addr);
OSMO_STRBUF_PRINTF(sb, ":0x%x <---> ", tunmap->core.local_teid);
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &tunmap->core.gtp_remote_addr);
OSMO_STRBUF_PRINTF(sb, ":0x%x CORE", tunmap->core.remote_teid);
return sb.chars_needed;
}
char *upf_nft_tunmap_to_str_c(void *ctx, const struct upf_nft_tunmap_desc *tunmap)
{
OSMO_NAME_C_IMPL(ctx, 128, "ERROR", upf_nft_tunmap_to_str_buf, tunmap)
}
static void upf_nft_args_from_tunmap_desc(struct upf_nft_args *args, const struct upf_nft_tunmap_desc *tunmap)
@ -204,39 +315,62 @@ static void upf_nft_args_from_tunmap_desc(struct upf_nft_args *args, const struc
*args = (struct upf_nft_args){
.table_name = g_upf->nft.table_name,
.chain_id = tunmap->id,
.priority = g_upf->nft.priority,
.peer_a = {
.addr_remote = &tunmap->access.gtp_remote_addr,
.teid_remote = tunmap->access.remote_teid,
.addr_local = &tunmap->access.gtp_local_addr,
.teid_local = tunmap->access.local_teid,
.chain_id = tunmap->access.chain_id,
},
.peer_b = {
.addr_remote = &tunmap->core.gtp_remote_addr,
.teid_remote = tunmap->core.remote_teid,
.addr_local = &tunmap->core.gtp_local_addr,
.teid_local = tunmap->core.local_teid,
.chain_id = tunmap->core.chain_id,
},
};
}
char *upf_nft_tunmap_get_table_init_str(void *ctx)
{
return upf_nft_ruleset_table_create(ctx, g_upf->nft.table_name);
}
char *upf_nft_tunmap_get_vmap_init_str(void *ctx)
{
return upf_nft_ruleset_vmap_init(ctx, g_upf->nft.table_name, g_upf->nft.priority_pre,
g_upf->nft.priority_post);
}
static uint32_t chain_id_next(void)
{
g_upf->nft.next_chain_id_state++;
if (!g_upf->nft.next_chain_id_state)
g_upf->nft.next_chain_id_state++;
return g_upf->nft.next_chain_id_state;
}
char *upf_nft_tunmap_get_ruleset_str(void *ctx, 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 */
if (!tunmap->id) {
g_upf->nft.next_id_state++;
if (!g_upf->nft.next_id_state)
g_upf->nft.next_id_state++;
tunmap->id = g_upf->nft.next_id_state;
}
if (!tunmap->access.chain_id)
tunmap->access.chain_id = chain_id_next();
if (!tunmap->core.chain_id)
tunmap->core.chain_id = chain_id_next();
upf_nft_args_from_tunmap_desc(&args, tunmap);
return upf_nft_ruleset_tunmap_create_c(ctx, &args);
}
char *upf_nft_tunmap_get_ruleset_del_str(void *ctx, struct upf_nft_tunmap_desc *tunmap)
{
struct upf_nft_args args;
upf_nft_args_from_tunmap_desc(&args, tunmap);
return upf_nft_ruleset_tunmap_delete_c(ctx, &args);
}
int upf_nft_tunmap_create(struct upf_nft_tunmap_desc *tunmap)
{
return upf_nft_run(upf_nft_tunmap_get_ruleset_str(OTC_SELECT, tunmap));
@ -244,7 +378,5 @@ int upf_nft_tunmap_create(struct upf_nft_tunmap_desc *tunmap)
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));
return upf_nft_run(upf_nft_tunmap_get_ruleset_del_str(OTC_SELECT, tunmap));
}

View File

@ -300,12 +300,13 @@ DEFUN(show_nft_rule_tunmap_example, show_nft_rule_tunmap_example_cmd,
.access = {
.local_teid = 0x201,
.remote_teid = 0x102,
.chain_id = 123,
},
.core = {
.local_teid = 0x203,
.remote_teid = 0x302,
.chain_id = 321,
},
.id = 123,
};
osmo_sockaddr_str_from_str2(&str, "1.1.1.1");
@ -320,7 +321,14 @@ DEFUN(show_nft_rule_tunmap_example, show_nft_rule_tunmap_example_cmd,
osmo_sockaddr_str_from_str2(&str, "3.3.3.3");
osmo_sockaddr_str_to_sockaddr(&str, &d.core.gtp_remote_addr.u.sas);
vty_out(vty, "%% init verdict map:%s", VTY_NEWLINE);
vty_out(vty, "%s%s", upf_nft_tunmap_get_table_init_str(OTC_SELECT), VTY_NEWLINE);
vty_out(vty, "%s%s", upf_nft_tunmap_get_vmap_init_str(OTC_SELECT), VTY_NEWLINE);
vty_out(vty, "%% add tunmap:%s", VTY_NEWLINE);
vty_out(vty, "%% %s%s", upf_nft_tunmap_to_str_c(OTC_SELECT, &d), VTY_NEWLINE);
vty_out(vty, "%s%s", upf_nft_tunmap_get_ruleset_str(OTC_SELECT, &d), VTY_NEWLINE);
vty_out(vty, "%% delete tunmap:%s", VTY_NEWLINE);
vty_out(vty, "%s%s", upf_nft_tunmap_get_ruleset_del_str(OTC_SELECT, &d), VTY_NEWLINE);
return CMD_SUCCESS;
}

View File

@ -3,9 +3,40 @@ OsmoUPF# configure terminal
OsmoUPF(config)# tunmap
OsmoUPF(config-tunmap)# show nft-rule tunmap example
add chain inet osmo-upf tunmap123 { type filter hook prerouting priority -300; }
add rule inet osmo-upf tunmap123 meta l4proto udp ip daddr 2.2.2.1 @ih,32,32 0x00000201 ip saddr set 2.2.2.3 ip daddr set 3.3.3.3 @ih,32,32 set 0x00000302 counter accept;
add rule inet osmo-upf tunmap123 meta l4proto udp ip daddr 2.2.2.3 @ih,32,32 0x00000203 ip saddr set 2.2.2.1 ip daddr set 1.1.1.1 @ih,32,32 set 0x00000102 counter accept;
% init verdict map:
add table inet osmo-upf
add chain inet osmo-upf pre { type filter hook prerouting priority -300; policy accept; };
add chain inet osmo-upf post { type filter hook postrouting priority 400; policy accept; };
add map inet osmo-upf tunmap-pre { typeof ip daddr . @ih,32,32 : verdict; };
add map inet osmo-upf tunmap-post { typeof meta mark : verdict; };
add rule inet osmo-upf pre udp dport 2152 ip daddr . @ih,32,32 vmap @tunmap-pre;
add rule inet osmo-upf post meta mark vmap @tunmap-post;
% add tunmap:
% ACCESS 1.1.1.1:0x102 <---> 2.2.2.1:0x201 UPF 2.2.2.3:0x203 <---> 3.3.3.3:0x302 CORE
add chain inet osmo-upf tunmap-pre-123;
add rule inet osmo-upf tunmap-pre-123 ip daddr set 3.3.3.3 meta mark set 123 counter accept;
add chain inet osmo-upf tunmap-post-123;
add rule inet osmo-upf tunmap-post-123 ip saddr set 2.2.2.3 @ih,32,32 set 0x302 counter accept;
add element inet osmo-upf tunmap-pre { 2.2.2.1 . 0x201 : jump tunmap-pre-123 };
add element inet osmo-upf tunmap-post { 123 : jump tunmap-post-123 };
add chain inet osmo-upf tunmap-pre-321;
add rule inet osmo-upf tunmap-pre-321 ip daddr set 1.1.1.1 meta mark set 321 counter accept;
add chain inet osmo-upf tunmap-post-321;
add rule inet osmo-upf tunmap-post-321 ip saddr set 2.2.2.1 @ih,32,32 set 0x102 counter accept;
add element inet osmo-upf tunmap-pre { 2.2.2.3 . 0x203 : jump tunmap-pre-321 };
add element inet osmo-upf tunmap-post { 321 : jump tunmap-post-321 };
% delete tunmap:
delete element inet osmo-upf tunmap-pre { 2.2.2.1 . 0x201 };
delete element inet osmo-upf tunmap-post { 123 };
delete chain inet osmo-upf tunmap-pre-123;
delete chain inet osmo-upf tunmap-post-123;
delete element inet osmo-upf tunmap-pre { 2.2.2.3 . 0x203 };
delete element inet osmo-upf tunmap-post { 321 };
delete chain inet osmo-upf tunmap-pre-321;
delete chain inet osmo-upf tunmap-post-321;
OsmoUPF(config-tunmap)# show nft-rule tunmap append
% deprecated config option: 'show nft-rule tunmap append'