2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 06:15:47 +00:00

userspace: Add GTP-U support.

GTP, GPRS Tunneling Protocol, is a group of IP-based communications
protocols used to carry general packet radio service (GPRS) within
GSM, UMTS and LTE networks.  GTP protocol has two parts: Signalling
(GTP-Control, GTP-C) and User data (GTP-User, GTP-U). GTP-C is used
for setting up GTP-U protocol, which is an IP-in-UDP tunneling
protocol. Usually GTP is used in connecting between base station for
radio, Serving Gateway (S-GW), and PDN Gateway (P-GW).

This patch implements GTP-U protocol for userspace datapath,
supporting only required header fields and G-PDU message type.
See spec in:
https://tools.ietf.org/html/draft-hmm-dmm-5g-uplane-analysis-00

Tested-at: https://travis-ci.org/github/williamtu/ovs-travis/builds/666518784
Signed-off-by: Feng Yang <yangfengee04@gmail.com>
Co-authored-by: Feng Yang <yangfengee04@gmail.com>
Signed-off-by: Yi Yang <yangyi01@inspur.com>
Co-authored-by: Yi Yang <yangyi01@inspur.com>
Signed-off-by: William Tu <u9012063@gmail.com>
Acked-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
William Tu
2019-11-25 11:19:23 -08:00
parent f598f46212
commit 3c6d05a02e
30 changed files with 752 additions and 40 deletions

View File

@@ -129,7 +129,7 @@ struct mf_ctx {
* away. Some GCC versions gave warnings on ALWAYS_INLINE, so these are
* defined as macros. */
#if (FLOW_WC_SEQ != 41)
#if (FLOW_WC_SEQ != 42)
#define MINIFLOW_ASSERT(X) ovs_assert(X)
BUILD_MESSAGE("FLOW_WC_SEQ changed: miniflow_extract() will have runtime "
"assertions enabled. Consider updating FLOW_WC_SEQ after "
@@ -731,7 +731,7 @@ void
miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
{
/* Add code to this function (or its callees) to extract new fields. */
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
const struct pkt_metadata *md = &packet->md;
const void *data = dp_packet_data(packet);
@@ -1187,7 +1187,7 @@ flow_get_metadata(const struct flow *flow, struct match *flow_metadata)
{
int i;
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
match_init_catchall(flow_metadata);
if (flow->tunnel.tun_id != htonll(0)) {
@@ -1227,6 +1227,12 @@ flow_get_metadata(const struct flow *flow, struct match *flow_metadata)
if (flow->tunnel.erspan_hwid) {
match_set_tun_erspan_hwid(flow_metadata, flow->tunnel.erspan_hwid);
}
if (flow->tunnel.gtpu_flags) {
match_set_tun_gtpu_flags(flow_metadata, flow->tunnel.gtpu_flags);
}
if (flow->tunnel.gtpu_msgtype) {
match_set_tun_gtpu_msgtype(flow_metadata, flow->tunnel.gtpu_msgtype);
}
tun_metadata_get_fmd(&flow->tunnel, flow_metadata);
if (flow->metadata != htonll(0)) {
match_set_metadata(flow_metadata, flow->metadata);
@@ -1767,7 +1773,7 @@ flow_wildcards_init_for_packet(struct flow_wildcards *wc,
memset(&wc->masks, 0x0, sizeof wc->masks);
/* Update this function whenever struct flow changes. */
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
if (flow_tnl_dst_is_set(&flow->tunnel)) {
if (flow->tunnel.flags & FLOW_TNL_F_KEY) {
@@ -1788,6 +1794,8 @@ flow_wildcards_init_for_packet(struct flow_wildcards *wc,
WC_MASK_FIELD(wc, tunnel.erspan_idx);
WC_MASK_FIELD(wc, tunnel.erspan_dir);
WC_MASK_FIELD(wc, tunnel.erspan_hwid);
WC_MASK_FIELD(wc, tunnel.gtpu_flags);
WC_MASK_FIELD(wc, tunnel.gtpu_msgtype);
if (!(flow->tunnel.flags & FLOW_TNL_F_UDPIF)) {
if (flow->tunnel.metadata.present.map) {
@@ -1918,7 +1926,7 @@ void
flow_wc_map(const struct flow *flow, struct flowmap *map)
{
/* Update this function whenever struct flow changes. */
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
flowmap_init(map);
@@ -2021,7 +2029,7 @@ void
flow_wildcards_clear_non_packet_fields(struct flow_wildcards *wc)
{
/* Update this function whenever struct flow changes. */
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
memset(&wc->masks.metadata, 0, sizeof wc->masks.metadata);
memset(&wc->masks.regs, 0, sizeof wc->masks.regs);
@@ -2165,7 +2173,7 @@ flow_wildcards_set_xxreg_mask(struct flow_wildcards *wc, int idx,
uint32_t
miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis)
{
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
uint32_t hash = basis;
if (flow) {
@@ -2212,7 +2220,7 @@ ASSERT_SEQUENTIAL(ipv6_src, ipv6_dst);
uint32_t
flow_hash_5tuple(const struct flow *flow, uint32_t basis)
{
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
uint32_t hash = basis;
if (flow) {
@@ -2890,7 +2898,7 @@ flow_push_mpls(struct flow *flow, int n, ovs_be16 mpls_eth_type,
if (clear_flow_L3) {
/* Clear all L3 and L4 fields and dp_hash. */
BUILD_ASSERT(FLOW_WC_SEQ == 41);
BUILD_ASSERT(FLOW_WC_SEQ == 42);
memset((char *) flow + FLOW_SEGMENT_2_ENDS_AT, 0,
sizeof(struct flow) - FLOW_SEGMENT_2_ENDS_AT);
flow->dp_hash = 0;
@@ -3188,7 +3196,7 @@ flow_compose(struct dp_packet *p, const struct flow *flow,
/* Add code to this function (or its callees) for emitting new fields or
* protocols. (This isn't essential, so it can be skipped for initial
* testing.) */
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
uint32_t pseudo_hdr_csum;
size_t l4_len;