/* Global definitions for osmo-upf-load-gen */ /* * (C) 2021-2022 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 #include #include #include #include #include #include #include struct osmo_tdef; struct ctrl_handle; enum up_gtp_action_kind { UP_GTP_DROP, UP_GTP_U_TUNEND, UP_GTP_U_TUNMAP, }; enum pfcp_tool_vty_node { PEER_NODE = _LAST_OSMOVTY_NODE + 1, SESSION_NODE, GTP_FLOOD_NODE, }; extern struct osmo_tdef g_pfcp_tool_tdefs[]; extern struct osmo_tdef_group g_pfcp_tool_tdef_groups[]; struct pfcp_tool_peer { struct llist_head entry; struct osmo_sockaddr remote_addr; struct osmo_pfcp_msg last_req; struct osmo_pfcp_msg last_resp; uint64_t next_seid_state; struct llist_head sessions; }; struct pfcp_tool_gtp_tun_ep { struct osmo_sockaddr_str addr; uint32_t teid; }; struct pfcp_tool_gtp_tun { struct pfcp_tool_gtp_tun_ep local; struct pfcp_tool_gtp_tun_ep remote; }; struct pfcp_tool_tunend { struct pfcp_tool_gtp_tun access; struct { struct osmo_sockaddr_str ue_local_addr; } core; }; struct pfcp_tool_tunmap { struct pfcp_tool_gtp_tun access; struct pfcp_tool_gtp_tun core; }; struct pfcp_tool_session { struct llist_head entry; struct pfcp_tool_peer *peer; uint64_t cp_seid; struct osmo_pfcp_ie_f_seid up_f_seid; enum up_gtp_action_kind kind; union { /* En-/De-capsulate GTP: add/remove a GTP header and forward the GTP payload from/to plain IP. */ struct pfcp_tool_tunend tunend; /* Tunnel-map GTP: translate from one TEID to another and forward */ struct pfcp_tool_tunmap tunmap; }; }; struct udp_port { struct llist_head entry; /* IP address and UDP port from user input */ struct osmo_sockaddr osa; /* In case this is a locally bound port, this is the fd for the socket. */ struct osmo_fd ofd; }; struct g_pfcp_tool { struct ctrl_handle *ctrl; struct { char *local_ip; uint16_t local_port; } vty_cfg; struct osmo_pfcp_endpoint *ep; struct llist_head peers; uint32_t next_teid_state; struct { struct range ip_range; } ue; struct { /* list of struct udp_port */ struct llist_head gtp_local_addrs; struct udp_port *gtp_local_addrs_next; /* list of struct udp_port */ struct llist_head gtp_core_addrs; void *gtp_core_addrs_next; struct { struct { /* source address is always the UE IP address */ struct range udp_port_range; } source; struct { struct range ip_range; struct range udp_port_range; } target; bool append_info; } payload; struct { struct gtp_flood_cfg cfg; unsigned int flows_per_session; unsigned int packets_per_flow; struct gtp_flood *state; } flood; } gtp; }; extern struct g_pfcp_tool *g_pfcp_tool; void g_pfcp_tool_alloc(void *ctx); void pfcp_tool_vty_init_cfg(); void pfcp_tool_vty_init_cmds(); int pfcp_tool_mainloop(int poll); struct pfcp_tool_peer *pfcp_tool_peer_find_or_create(const struct osmo_sockaddr *remote_addr); struct pfcp_tool_session *pfcp_tool_session_find_or_create(struct pfcp_tool_peer *peer, uint64_t cp_seid, enum up_gtp_action_kind kind); void pfcp_tool_rx_msg(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_msg *m, struct osmo_pfcp_msg *req); int peer_tx(struct pfcp_tool_peer *peer, struct osmo_pfcp_msg *m); uint64_t peer_new_seid(struct pfcp_tool_peer *peer); uint32_t pfcp_tool_new_teid(void); int pfcp_tool_next_ue_addr(struct osmo_sockaddr *dst); struct udp_port *pfcp_tool_have_local_udp_port_by_str(const struct osmo_sockaddr_str *addr, uint16_t fallback_port); struct udp_port *pfcp_tool_have_core_udp_port_by_str(const struct osmo_sockaddr_str *addr, uint16_t fallback_port); void pfcp_tool_gtp_flood_start(void); int pfcp_tool_vty_go_parent(struct vty *vty); static inline struct llist_head *_llist_round_robin(struct llist_head *list, void **state) { struct llist_head *e = *state; if (!e || e->next == list) e = list; e = e->next; if (e == list) e = NULL; *state = e; return e; } #define llist_round_robin(LIST, STATE, STRUCT, ENTRY_NAME) \ llist_entry(_llist_round_robin(LIST, STATE), STRUCT, ENTRY_NAME)