aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/gtpu/gtpu.h
diff options
context:
space:
mode:
authorRune E. Jensen <runeerle@wgtwo.com>2022-11-22 10:35:03 +0100
committerOle Tr�an <otroan@employees.org>2023-11-10 14:39:39 +0000
commitf9ab6985d44651b3f92490829e8fad5bac0ceec2 (patch)
tree3c4c556d6fe52cebb79251f82b16f572e086a9b1 /src/plugins/gtpu/gtpu.h
parent5cc67aacf01e8c010ec64a56930f854bcd5d7669 (diff)
gtpu: support non-G-PDU packets and PDU Session
Updated the gtpu plugin code to support the PDU Session user plane protocol, required for 5G, as specified in 3GPP TS 38.415 version 17.0.0. This enables some initial support of 5G gNodeB's with the gtpu plugin. New features: - Basic support for the GTP-U Extension Header Flag. Packets with one extension can now be decapsulated. This enables basic support of the PDU Session user plane protocol (3GPP TS 38.415 version 17.0.0). New tunnels can be created with a PDU enable flag and a 6-bit QoS Flow Identifier (QFI). With this, encapsulated packets will have the PDU Session extension header, and the QFI set. - Ability to forward GTP-U packets that are not handled by the plugin directly. Only GTP-U packets with a message type of 255 (G-PDU) are handled directly. However, 3GPP TS 29.281 defines several other message types like echo and error indication. A new feature is added to optionally forward unknown or unsupported packets to a new IP address. This works separately for unknown GTP-U message types, unknown TEIDs, and packets with an unknown GTP-U header. This allows both echo and error indications from a 5G gNodeB to be handled by a different system outside VPP. - Simple way to get metrics for active tunnels and on tunnel close. In 5G session/tunnel lifetime is often short and created frequently. The normal API becomes too slow and inaccurate when too many tunnels are created and deleted every second. Improvements: - A clean ground structure to handle multiple message type in the future. The code path for G-PDU packets is optimized for performance, representing the typical case. Unsupported GTP-U packets enter a slow path that decodes the nature of the error. This presents a easy hook to handle other message types in the future. - Improved error reporting When using traces there is more details in the tunnel descriptions. - Updated the API with several enums. Fixes: - gtpu0->length field in IPv6 was computed with IPv4 header lengths in the encapsulation code. - vec_set_len (t->rewrite, ...) size was computed with the IPv4 header size also for IPv6 tunnels. Issues: - This PR does not enable full support of the 3GPP specification. In particular it only supports a single QoS/QFI flow for each tunnel. It ignores all incoming extension header flags. - API functions might change again when/if more support of the 3GPP TS 38.415 spec is added. Note that I have bumped the API version to 2.1.0 as it seems to be the correct approach based on my API changes. Type: feature Signed-off-by: Rune E. Jensen <runeerle@wgtwo.com> Change-Id: I91cd2b31f2561f1b3fb1e46c4c34a5a3c71b4625
Diffstat (limited to 'src/plugins/gtpu/gtpu.h')
-rw-r--r--src/plugins/gtpu/gtpu.h108
1 files changed, 103 insertions, 5 deletions
diff --git a/src/plugins/gtpu/gtpu.h b/src/plugins/gtpu/gtpu.h
index 72d09232001..0c224ebbfe3 100644
--- a/src/plugins/gtpu/gtpu.h
+++ b/src/plugins/gtpu/gtpu.h
@@ -53,21 +53,56 @@
* 12 Next Extension Header Type3) 4)
**/
-typedef struct
-{
+typedef CLIB_PACKED (struct {
u8 ver_flags;
u8 type;
u16 length; /* length in octets of the data following the fixed part of the header */
u32 teid;
+ /* The following fields exists if and only if one or more of E, S or PN
+ * are 1. */
u16 sequence;
u8 pdu_number;
u8 next_ext_type;
-} gtpu_header_t;
+}) gtpu_header_t;
-#define GTPU_V1_HDR_LEN 8
+typedef CLIB_PACKED (struct {
+ u8 type;
+ u8 len;
+ u16 pad;
+}) gtpu_ext_header_t;
+
+/**
+ * DL PDU SESSION INFORMATION (PDU Type 0):
+ * (3GPP TS 38.415)
+ * Bits
+ * Octets 8 7 6 5 4 3 2 1
+ * 1 type qmp snp spare
+ * 2 ppp rqi qos_fi
+ *
+ * UL PDU SESSION INFORMATION (PDU Type 1):
+ * Bits
+ * Octets 8 7 6 5 4 3 2 1
+ * 1 type qmp DL d. UL d. snp
+ * 2 n3/n9 delay new IE qos_fi
+ **/
+typedef CLIB_PACKED (struct {
+ u8 oct0;
+ u8 oct1;
+ // Extensions are supported
+}) pdu_session_container_t;
+
+STATIC_ASSERT_SIZEOF (pdu_session_container_t, 2);
+typedef CLIB_PACKED (struct {
+ u8 len;
+ pdu_session_container_t pdu;
+ u8 next_header;
+}) gtpu_ext_with_pdu_session_header_t;
+
+#define GTPU_V1_HDR_LEN 8
#define GTPU_VER_MASK (7<<5)
#define GTPU_PT_BIT (1<<4)
+#define GTPU_RES_BIT (1 << 3)
#define GTPU_E_BIT (1<<2)
#define GTPU_S_BIT (1<<1)
#define GTPU_PN_BIT (1<<0)
@@ -78,12 +113,42 @@ typedef struct
#define GTPU_PT_GTP (1<<4)
#define GTPU_TYPE_GTPU 255
+#define GTPU_EXT_HDR_PDU_SESSION_CONTAINER 133
+#define GTPU_NO_MORE_EXT_HDR 0
+#define GTPU_PDU_DL_SESSION_TYPE 0
+#define GTPU_PDU_UL_SESSION_TYPE (1 << 4)
+
+#define GTPU_FORWARD_BAD_HEADER (1 << 0)
+#define GTPU_FORWARD_UNKNOWN_TEID (1 << 1)
+#define GTPU_FORWARD_UNKNOWN_TYPE (1 << 2)
+
+/* the ipv4 addresses used for the forwarding tunnels. 127.0.0.127 - .129. */
+#define GTPU_FORWARD_BAD_HEADER_ADDRESS_IPV4 0x7f00007fu
+#define GTPU_FORWARD_UNKNOWN_TEID_ADDRESS_IPV4 0x8000007fu
+#define GTPU_FORWARD_UNKNOWN_TYPE_ADDRESS_IPV4 0x8100007fu
+
+/* the ipv6 addresses used for the forwarding tunnels.
+ * 2001:db8:ffff:ffff:ffff:ffff:ffff:fffd -
+ * 2001:db8:ffff:ffff:ffff:ffff:ffff:ffff*/
+#define GTPU_FORWARD_BAD_HEADER_ADDRESS_IPV6 \
+ { \
+ .as_u64[0] = 0xffffffffb80d0120ull, .as_u64[1] = 0xfdffffffffffffffull \
+ }
+#define GTPU_FORWARD_UNKNOWN_TEID_ADDRESS_IPV6 \
+ { \
+ .as_u64[0] = 0xffffffffb80d0120ull, .as_u64[1] = 0xfeffffffffffffffull \
+ }
+#define GTPU_FORWARD_UNKNOWN_TYPE_ADDRESS_IPV6 \
+ { \
+ .as_u64[0] = 0xffffffffb80d0120ull, .as_u64[1] = 0xffffffffffffffffull \
+ }
/* *INDENT-OFF* */
typedef CLIB_PACKED(struct
{
ip4_header_t ip4; /* 20 bytes */
udp_header_t udp; /* 8 bytes */
gtpu_header_t gtpu; /* 12 bytes */
+ gtpu_ext_with_pdu_session_header_t gtpu_ext; /* 4 bytes */
}) ip4_gtpu_header_t;
/* *INDENT-ON* */
@@ -92,7 +157,8 @@ typedef CLIB_PACKED(struct
{
ip6_header_t ip6; /* 40 bytes */
udp_header_t udp; /* 8 bytes */
- gtpu_header_t gtpu; /* 8 bytes */
+ gtpu_header_t gtpu; /* 12 bytes */
+ gtpu_ext_with_pdu_session_header_t gtpu_ext; /* 4 bytes */
}) ip6_gtpu_header_t;
/* *INDENT-ON* */
@@ -157,6 +223,14 @@ typedef struct
u32 sw_if_index;
u32 hw_if_index;
+ /* PDU session container extension enable/disable */
+ u8 pdu_extension;
+ u8 qfi;
+
+ /* The tunnel is used for forwarding */
+ u8 is_forwarding;
+ u8 forwarding_type;
+
/**
* Linkage into the FIB object graph
*/
@@ -232,6 +306,19 @@ typedef struct
/* API message ID base */
u16 msg_id_base;
+ /* Handle GTP packets of unknown type like echo and error indication,
+ * unknown teid or bad version/header.
+ * All packets will be forwarded to a new IP address,
+ * so that they can be processes outside vpp.
+ * If not set then packets are dropped.
+ * One of more indexes can be unused (~0). */
+ u32 bad_header_forward_tunnel_index_ipv4;
+ u32 unknown_teid_forward_tunnel_index_ipv4;
+ u32 unknown_type_forward_tunnel_index_ipv4;
+ u32 bad_header_forward_tunnel_index_ipv6;
+ u32 unknown_teid_forward_tunnel_index_ipv6;
+ u32 unknown_type_forward_tunnel_index_ipv6;
+
/* convenience */
vlib_main_t *vlib_main;
vnet_main_t *vnet_main;
@@ -263,8 +350,15 @@ typedef struct
u32 decap_next_index;
u32 teid; /* local or rx teid */
u32 tteid; /* remote or tx teid */
+ u8 pdu_extension;
+ u8 qfi;
+ u8 is_forwarding;
+ u8 forwarding_type;
} vnet_gtpu_add_mod_del_tunnel_args_t;
+int vnet_gtpu_add_del_forwarding (vnet_gtpu_add_mod_del_tunnel_args_t *a,
+ u32 *sw_if_indexp);
+
int vnet_gtpu_add_mod_del_tunnel
(vnet_gtpu_add_mod_del_tunnel_args_t * a, u32 * sw_if_indexp);
@@ -272,11 +366,15 @@ typedef struct
{
u32 tunnel_index;
u32 tteid;
+ u8 pdu_extension;
+ u8 qfi;
} gtpu_encap_trace_t;
void vnet_int_gtpu_bypass_mode (u32 sw_if_index, u8 is_ip6, u8 is_enable);
u32 vnet_gtpu_get_tunnel_index (u32 sw_if_index);
int vnet_gtpu_add_del_rx_flow (u32 hw_if_index, u32 t_imdex, int is_add);
+int get_combined_counters (u32 sw_if_index, vlib_counter_t *result_rx,
+ vlib_counter_t *result_tx);
#endif /* included_vnet_gtpu_h */