diff --git a/include/osmocom/upf/Makefile.am b/include/osmocom/upf/Makefile.am index f418cb1..e8eda55 100644 --- a/include/osmocom/upf/Makefile.am +++ b/include/osmocom/upf/Makefile.am @@ -7,5 +7,6 @@ noinst_HEADERS = \ upf_gtp.h \ upf_gtpu_echo.h \ upf_nft.h \ + upf_tun.h \ up_gtp_action.h \ $(NULL) diff --git a/include/osmocom/upf/upf_gtp.h b/include/osmocom/upf/upf_gtp.h index 695aead..b4cd3df 100644 --- a/include/osmocom/upf/upf_gtp.h +++ b/include/osmocom/upf/upf_gtp.h @@ -27,6 +27,8 @@ #include #include +#include + #define LOG_GTP_DEV(DEV, LEVEL, FMT, ARGS...) \ LOGP(DGTP, LEVEL, "%s: " FMT, upf_gtp_dev_to_str_c(OTC_SELECT, (DEV)), ##ARGS) @@ -58,12 +60,7 @@ struct upf_gtp_dev { /* Description of a GTP encapsulation / decapsulation. * The active state to operate the GTP kernel module accordingly is kept in struct upf_gtp_tunend. */ struct upf_tunend { - struct { - struct osmo_sockaddr gtp_local_addr; - uint32_t local_teid; - struct osmo_sockaddr gtp_remote_addr; - uint32_t remote_teid; - } access; + struct upf_tun access; struct { struct osmo_sockaddr ue_local_addr; } core; diff --git a/include/osmocom/upf/upf_nft.h b/include/osmocom/upf/upf_nft.h index 8f0cccd..be2ec0d 100644 --- a/include/osmocom/upf/upf_nft.h +++ b/include/osmocom/upf/upf_nft.h @@ -25,23 +25,16 @@ #include -#include +#include + +struct upf_nft_tun { + struct upf_tun tun; + uint32_t chain_id; +}; struct upf_tunmap { - 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; + struct upf_nft_tun access; + struct upf_nft_tun core; }; int upf_nft_tunmap_to_str_buf(char *buf, size_t buflen, const struct upf_tunmap *tunmap); diff --git a/include/osmocom/upf/upf_tun.h b/include/osmocom/upf/upf_tun.h new file mode 100644 index 0000000..e14b036 --- /dev/null +++ b/include/osmocom/upf/upf_tun.h @@ -0,0 +1,38 @@ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH + * All Rights Reserved. + * + * Author: Neels Janosch Hofmeyr + * + * 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 . + * + */ + +#pragma once + +#include + +#include + +struct upf_tun_ep { + struct osmo_sockaddr addr; + uint32_t teid; +}; + +struct upf_tun { + struct upf_tun_ep local; + struct upf_tun_ep remote; +}; diff --git a/src/osmo-upf/up_gtp_action.c b/src/osmo-upf/up_gtp_action.c index b331260..e7616ac 100644 --- a/src/osmo-upf/up_gtp_action.c +++ b/src/osmo-upf/up_gtp_action.c @@ -48,11 +48,11 @@ int up_gtp_action_cmp(const struct up_gtp_action *a, const struct up_gtp_action switch (a->kind) { case UP_GTP_U_TUNEND: - if ((cmp = CMP_MEMB(tunend.access.local_teid))) + if ((cmp = CMP_MEMB(tunend.access.local.teid))) return cmp; - if ((cmp = CMP_MEMB(tunend.access.remote_teid))) + if ((cmp = CMP_MEMB(tunend.access.remote.teid))) return cmp; - cmp = osmo_sockaddr_cmp(&a->tunend.access.gtp_remote_addr, &b->tunend.access.gtp_remote_addr); + cmp = osmo_sockaddr_cmp(&a->tunend.access.remote.addr, &b->tunend.access.remote.addr); if (cmp) return cmp; cmp = osmo_sockaddr_cmp(&a->tunend.core.ue_local_addr, &b->tunend.core.ue_local_addr); @@ -61,13 +61,13 @@ int up_gtp_action_cmp(const struct up_gtp_action *a, const struct up_gtp_action break; case UP_GTP_U_TUNMAP: - if ((cmp = CMP_MEMB(tunmap.access.local_teid))) + if ((cmp = CMP_MEMB(tunmap.access.tun.local.teid))) return cmp; - if ((cmp = CMP_MEMB(tunmap.access.remote_teid))) + if ((cmp = CMP_MEMB(tunmap.access.tun.remote.teid))) return cmp; - if ((cmp = CMP_MEMB(tunmap.core.local_teid))) + if ((cmp = CMP_MEMB(tunmap.core.tun.local.teid))) return cmp; - if ((cmp = CMP_MEMB(tunmap.core.remote_teid))) + if ((cmp = CMP_MEMB(tunmap.core.tun.remote.teid))) return cmp; break; default: @@ -91,7 +91,7 @@ static int up_gtp_action_enable_disable(struct up_gtp_action *a, bool enable) } /* Pick GTP device matching the local F-TEID set up for the GTP tunnel (it is on the Access side) */ - gtp_addr = &a->tunend.access.gtp_local_addr; + gtp_addr = &a->tunend.access.local.addr; gtp_dev = upf_gtp_dev_find_by_local_addr(gtp_addr); if (!gtp_dev) { LOG_UP_GTP_ACTION(a, LOGL_ERROR, "No GTP device open for local address %s, cannot %s" @@ -158,26 +158,26 @@ int up_gtp_action_to_str_buf(char *buf, size_t buflen, const struct up_gtp_actio switch (a->kind) { case UP_GTP_U_TUNEND: OSMO_STRBUF_PRINTF(sb, "GTP:tunend GTP-access-r:"); - OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &a->tunend.access.gtp_remote_addr); - OSMO_STRBUF_PRINTF(sb, " TEID-access-r:0x%"PRIx32, a->tunend.access.remote_teid); + OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &a->tunend.access.remote.addr); + OSMO_STRBUF_PRINTF(sb, " TEID-access-r:0x%"PRIx32, a->tunend.access.remote.teid); OSMO_STRBUF_PRINTF(sb, " GTP-access-l:"); - OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &a->tunend.access.gtp_local_addr); - OSMO_STRBUF_PRINTF(sb, " TEID-access-l:0x%"PRIx32" IP-core-l:", a->tunend.access.local_teid); + OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &a->tunend.access.local.addr); + OSMO_STRBUF_PRINTF(sb, " TEID-access-l:0x%"PRIx32" IP-core-l:", a->tunend.access.local.teid); OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &a->tunend.core.ue_local_addr); break; case UP_GTP_U_TUNMAP: OSMO_STRBUF_PRINTF(sb, "GTP:tunmap GTP-access-r:"); - OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &a->tunmap.access.gtp_remote_addr); - OSMO_STRBUF_PRINTF(sb, " TEID-access-r:0x%"PRIx32, a->tunmap.access.remote_teid); + OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &a->tunmap.access.tun.remote.addr); + OSMO_STRBUF_PRINTF(sb, " TEID-access-r:0x%"PRIx32, a->tunmap.access.tun.remote.teid); OSMO_STRBUF_PRINTF(sb, " GTP-access-l:"); - OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &a->tunmap.access.gtp_local_addr); - OSMO_STRBUF_PRINTF(sb, " TEID-access-l:0x%"PRIx32, a->tunmap.access.local_teid); + OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &a->tunmap.access.tun.local.addr); + OSMO_STRBUF_PRINTF(sb, " TEID-access-l:0x%"PRIx32, a->tunmap.access.tun.local.teid); OSMO_STRBUF_PRINTF(sb, " GTP-core-r:"); - OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &a->tunmap.core.gtp_remote_addr); - OSMO_STRBUF_PRINTF(sb, " TEID-core-r:0x%"PRIx32, a->tunmap.core.remote_teid); + OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &a->tunmap.core.tun.remote.addr); + OSMO_STRBUF_PRINTF(sb, " TEID-core-r:0x%"PRIx32, a->tunmap.core.tun.remote.teid); OSMO_STRBUF_PRINTF(sb, " GTP-core-l:"); - OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &a->tunmap.core.gtp_local_addr); - OSMO_STRBUF_PRINTF(sb, " TEID-core-l:0x%"PRIx32, a->tunmap.core.local_teid); + OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &a->tunmap.core.tun.local.addr); + OSMO_STRBUF_PRINTF(sb, " TEID-core-l:0x%"PRIx32, a->tunmap.core.tun.local.teid); break; case UP_GTP_DROP: OSMO_STRBUF_PRINTF(sb, "GTP:drop"); diff --git a/src/osmo-upf/up_session.c b/src/osmo-upf/up_session.c index 59d45c0..38f4d2b 100644 --- a/src/osmo-upf/up_session.c +++ b/src/osmo-upf/up_session.c @@ -1227,10 +1227,14 @@ static void add_gtp_action_tunend(void *ctx, struct llist_head *dst, struct pdr .kind = UP_GTP_U_TUNEND, .tunend = { .access = { - .gtp_local_addr = pdr->local_f_teid->fixed.ip_addr.v4, - .local_teid = pdr->local_f_teid->fixed.teid, - .gtp_remote_addr = rfar_forw->outer_header_creation.ip_addr.v4, - .remote_teid = rfar_forw->outer_header_creation.teid, + .local = { + .addr = pdr->local_f_teid->fixed.ip_addr.v4, + .teid = pdr->local_f_teid->fixed.teid, + }, + .remote = { + .addr = rfar_forw->outer_header_creation.ip_addr.v4, + .teid = rfar_forw->outer_header_creation.teid, + }, }, .core = { .ue_local_addr = rpdr->desc.pdi.ue_ip_address.ip_addr.v4, @@ -1336,17 +1340,25 @@ static void add_gtp_action_tunmap(void *ctx, struct llist_head *dst, struct pdr .pdr_core = rpdr->desc.pdr_id, .kind = UP_GTP_U_TUNMAP, .tunmap = { - .access = { - .gtp_local_addr = pdr->local_f_teid->fixed.ip_addr.v4, - .local_teid = pdr->local_f_teid->fixed.teid, - .gtp_remote_addr = rfar_forw->outer_header_creation.ip_addr.v4, - .remote_teid = rfar_forw->outer_header_creation.teid, + .access.tun = { + .local = { + .addr = pdr->local_f_teid->fixed.ip_addr.v4, + .teid = pdr->local_f_teid->fixed.teid, + }, + .remote = { + .addr = rfar_forw->outer_header_creation.ip_addr.v4, + .teid = rfar_forw->outer_header_creation.teid, + }, }, - .core = { - .gtp_local_addr = rpdr->local_f_teid->fixed.ip_addr.v4, - .local_teid = rpdr->local_f_teid->fixed.teid, - .gtp_remote_addr = far_forw->outer_header_creation.ip_addr.v4, - .remote_teid = far_forw->outer_header_creation.teid, + .core.tun = { + .local = { + .addr = rpdr->local_f_teid->fixed.ip_addr.v4, + .teid = rpdr->local_f_teid->fixed.teid, + }, + .remote = { + .addr = far_forw->outer_header_creation.ip_addr.v4, + .teid = far_forw->outer_header_creation.teid, + }, }, }, }; diff --git a/src/osmo-upf/upf_gtp.c b/src/osmo-upf/upf_gtp.c index 54dcf11..cbca882 100644 --- a/src/osmo-upf/upf_gtp.c +++ b/src/osmo-upf/upf_gtp.c @@ -320,9 +320,9 @@ static int upf_gtp_tunend_to_str_buf(char *buf, size_t buflen, const struct upf_ struct osmo_strbuf sb = { .buf = buf, .len = buflen }; /* "tunend{dev=apn0 access(GTP-r=1.2.3.4 TEID:l=0x1234,r=0x5678) core(UE-l=10.9.8.7)}" */ OSMO_STRBUF_PRINTF(sb, "tunend{dev=%s access(GTP-r=", tun->dev->name); - OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &tun->desc.access.gtp_remote_addr); + OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &tun->desc.access.remote.addr); OSMO_STRBUF_PRINTF(sb, " TEID:l=0x%x,r=0x%x) core(UE-l=", - tun->desc.access.local_teid, tun->desc.access.remote_teid); + tun->desc.access.local.teid, tun->desc.access.remote.teid); OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &tun->desc.core.ue_local_addr); OSMO_STRBUF_PRINTF(sb, ")}"); return sb.chars_needed; @@ -345,8 +345,8 @@ static int upf_gtp_tunend_destruct(struct upf_gtp_tunend *tun) #define tunend_validate(TUNEND) \ do { \ - OSMO_ASSERT(osmo_sockaddr_port(&(TUNEND)->access.gtp_local_addr.u.sa) == 0); \ - OSMO_ASSERT(osmo_sockaddr_port(&(TUNEND)->access.gtp_remote_addr.u.sa) == 0); \ + OSMO_ASSERT(osmo_sockaddr_port(&(TUNEND)->access.local.addr.u.sa) == 0); \ + OSMO_ASSERT(osmo_sockaddr_port(&(TUNEND)->access.remote.addr.u.sa) == 0); \ OSMO_ASSERT(osmo_sockaddr_port(&(TUNEND)->core.ue_local_addr.u.sa) == 0); \ } while (0) @@ -369,7 +369,7 @@ static struct gtp_tunnel *upf_gtp_tunend_to_gtp_tunnel(struct upf_gtp_tunend *tu struct gtp_tunnel *t; if (tun->desc.core.ue_local_addr.u.sas.ss_family != AF_INET - || tun->desc.access.gtp_remote_addr.u.sas.ss_family != AF_INET) { + || tun->desc.access.remote.addr.u.sas.ss_family != AF_INET) { LOG_GTP_TUN(tun, LOGL_ERROR, "Only capabale of IPv4\n"); return NULL; } @@ -378,9 +378,9 @@ static struct gtp_tunnel *upf_gtp_tunend_to_gtp_tunnel(struct upf_gtp_tunend *tu OSMO_ASSERT(t); gtp_tunnel_set_ifidx(t, tun->dev->ifidx); gtp_tunnel_set_version(t, GTP_V1); - gtp_tunnel_set_i_tei(t, tun->desc.access.local_teid); - gtp_tunnel_set_o_tei(t, tun->desc.access.remote_teid); - gtp_tunnel_set_sgsn_ip4(t, &tun->desc.access.gtp_remote_addr.u.sin.sin_addr); + gtp_tunnel_set_i_tei(t, tun->desc.access.local.teid); + gtp_tunnel_set_o_tei(t, tun->desc.access.remote.teid); + gtp_tunnel_set_sgsn_ip4(t, &tun->desc.access.remote.addr.u.sin.sin_addr); gtp_tunnel_set_ms_ip4(t, &tun->desc.core.ue_local_addr.u.sin.sin_addr); return t; } @@ -503,9 +503,9 @@ int upf_gtp_tunend_cmp(const struct upf_tunend *a, const struct upf_tunend *b) return 1; #define CMP_MEMB(MEMB) OSMO_CMP(a->MEMB, b->MEMB) - if ((r = CMP_MEMB(access.local_teid))) + if ((r = CMP_MEMB(access.local.teid))) return r; - if ((r = CMP_MEMB(access.remote_teid))) + if ((r = CMP_MEMB(access.remote.teid))) return r; - return osmo_sockaddr_cmp(&a->access.gtp_remote_addr, &b->access.gtp_remote_addr); + return osmo_sockaddr_cmp(&a->access.remote.addr, &b->access.remote.addr); } diff --git a/src/osmo-upf/upf_nft.c b/src/osmo-upf/upf_nft.c index 37a4730..4b5cb43 100644 --- a/src/osmo-upf/upf_nft.c +++ b/src/osmo-upf/upf_nft.c @@ -290,14 +290,14 @@ int upf_nft_tunmap_to_str_buf(char *buf, size_t buflen, const struct upf_tunmap /* 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); + OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &tunmap->access.tun.remote.addr); + OSMO_STRBUF_PRINTF(sb, ":0x%x <---> ", tunmap->access.tun.remote.teid); + OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &tunmap->access.tun.local.addr); + OSMO_STRBUF_PRINTF(sb, ":0x%x UPF ", tunmap->access.tun.local.teid); + OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &tunmap->core.tun.local.addr); + OSMO_STRBUF_PRINTF(sb, ":0x%x <---> ", tunmap->core.tun.local.teid); + OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &tunmap->core.tun.remote.addr); + OSMO_STRBUF_PRINTF(sb, ":0x%x CORE", tunmap->core.tun.remote.teid); return sb.chars_needed; } @@ -308,25 +308,25 @@ char *upf_nft_tunmap_to_str_c(void *ctx, const struct upf_tunmap *tunmap) static void upf_nft_args_from_tunmap(struct upf_nft_args *args, const struct upf_tunmap *tunmap) { - OSMO_ASSERT(osmo_sockaddr_port(&tunmap->access.gtp_remote_addr.u.sa) == 0); - OSMO_ASSERT(osmo_sockaddr_port(&tunmap->access.gtp_local_addr.u.sa) == 0); - OSMO_ASSERT(osmo_sockaddr_port(&tunmap->core.gtp_remote_addr.u.sa) == 0); - OSMO_ASSERT(osmo_sockaddr_port(&tunmap->core.gtp_local_addr.u.sa) == 0); + OSMO_ASSERT(osmo_sockaddr_port(&tunmap->access.tun.remote.addr.u.sa) == 0); + OSMO_ASSERT(osmo_sockaddr_port(&tunmap->access.tun.local.addr.u.sa) == 0); + OSMO_ASSERT(osmo_sockaddr_port(&tunmap->core.tun.remote.addr.u.sa) == 0); + OSMO_ASSERT(osmo_sockaddr_port(&tunmap->core.tun.local.addr.u.sa) == 0); *args = (struct upf_nft_args){ .table_name = g_upf->nft.table_name, .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, + .addr_remote = &tunmap->access.tun.remote.addr, + .teid_remote = tunmap->access.tun.remote.teid, + .addr_local = &tunmap->access.tun.local.addr, + .teid_local = tunmap->access.tun.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, + .addr_remote = &tunmap->core.tun.remote.addr, + .teid_remote = tunmap->core.tun.remote.teid, + .addr_local = &tunmap->core.tun.local.addr, + .teid_local = tunmap->core.tun.local.teid, .chain_id = tunmap->core.chain_id, }, }; diff --git a/src/osmo-upf/upf_vty.c b/src/osmo-upf/upf_vty.c index 3fe297a..51bf002 100644 --- a/src/osmo-upf/upf_vty.c +++ b/src/osmo-upf/upf_vty.c @@ -298,28 +298,32 @@ DEFUN(show_nft_rule_tunmap_example, show_nft_rule_tunmap_example_cmd, struct osmo_sockaddr_str str = {}; struct upf_tunmap tunmap = { .access = { - .local_teid = 0x201, - .remote_teid = 0x102, + .tun = { + .local.teid = 0x201, + .remote.teid = 0x102, + }, .chain_id = 123, }, .core = { - .local_teid = 0x203, - .remote_teid = 0x302, + .tun = { + .local.teid = 0x203, + .remote.teid = 0x302, + }, .chain_id = 321, }, }; osmo_sockaddr_str_from_str2(&str, "1.1.1.1"); - osmo_sockaddr_str_to_sockaddr(&str, &tunmap.access.gtp_remote_addr.u.sas); + osmo_sockaddr_str_to_sockaddr(&str, &tunmap.access.tun.remote.addr.u.sas); osmo_sockaddr_str_from_str2(&str, "2.2.2.1"); - osmo_sockaddr_str_to_sockaddr(&str, &tunmap.access.gtp_local_addr.u.sas); + osmo_sockaddr_str_to_sockaddr(&str, &tunmap.access.tun.local.addr.u.sas); osmo_sockaddr_str_from_str2(&str, "2.2.2.3"); - osmo_sockaddr_str_to_sockaddr(&str, &tunmap.core.gtp_local_addr.u.sas); + osmo_sockaddr_str_to_sockaddr(&str, &tunmap.core.tun.local.addr.u.sas); osmo_sockaddr_str_from_str2(&str, "3.3.3.3"); - osmo_sockaddr_str_to_sockaddr(&str, &tunmap.core.gtp_remote_addr.u.sas); + osmo_sockaddr_str_to_sockaddr(&str, &tunmap.core.tun.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);