diff --git a/include/osmocom/upf/upf.h b/include/osmocom/upf/upf.h index ef7aa2b..2e80abe 100644 --- a/include/osmocom/upf/upf.h +++ b/include/osmocom/upf/upf.h @@ -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; diff --git a/include/osmocom/upf/upf_nft.h b/include/osmocom/upf/upf_nft.h index 4cdcb51..cf0f0b9 100644 --- a/include/osmocom/upf/upf_nft.h +++ b/include/osmocom/upf/upf_nft.h @@ -27,28 +27,32 @@ #include -#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'. 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); diff --git a/src/osmo-upf/up_gtp_action.c b/src/osmo-upf/up_gtp_action.c index 68f5fb9..b331260 100644 --- a/src/osmo-upf/up_gtp_action.c +++ b/src/osmo-upf/up_gtp_action.c @@ -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: diff --git a/src/osmo-upf/upf.c b/src/osmo-upf/upf.c index 0a84799..e26d9c7 100644 --- a/src/osmo-upf/upf.c +++ b/src/osmo-upf/upf.c @@ -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. */ diff --git a/src/osmo-upf/upf_nft.c b/src/osmo-upf/upf_nft.c index f30e30c..ddd556b 100644 --- a/src/osmo-upf/upf_nft.c +++ b/src/osmo-upf/upf_nft.c @@ -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)); } diff --git a/src/osmo-upf/upf_vty.c b/src/osmo-upf/upf_vty.c index 436d91f..70e0d69 100644 --- a/src/osmo-upf/upf_vty.c +++ b/src/osmo-upf/upf_vty.c @@ -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; } diff --git a/tests/nft-rule.vty b/tests/nft-rule.vty index ec719ab..c226191 100644 --- a/tests/nft-rule.vty +++ b/tests/nft-rule.vty @@ -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'