From patchwork Tue May 15 06:32:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Yang, Yi" X-Patchwork-Id: 913450 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40lScM3LKBz9s1R for ; Tue, 15 May 2018 16:40:19 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 93171D60; Tue, 15 May 2018 06:39:54 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id CADC6D09 for ; Tue, 15 May 2018 06:39:53 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 379B2A3 for ; Tue, 15 May 2018 06:39:51 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 May 2018 23:39:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,402,1520924400"; d="scan'208";a="199435953" Received: from unknown (HELO localhost.localdomain.bj.intel.com) ([10.240.224.185]) by orsmga004.jf.intel.com with ESMTP; 14 May 2018 23:39:48 -0700 From: Yi Yang To: dev@openvswitch.org Date: Tue, 15 May 2018 14:32:08 +0800 Message-Id: <1526365929-3047-2-git-send-email-yi.y.yang@intel.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1526365929-3047-1-git-send-email-yi.y.yang@intel.com> References: <1526365929-3047-1-git-send-email-yi.y.yang@intel.com> X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Feng Yang Subject: [ovs-dev] [PATCH v2 1/2] userspace datapath: Add GTP-U tunnel support X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Feng Yang GPRS Tunneling Protocol (GTP) is a group of IP-based communications protocols used to carry general packet radio service (GPRS) within GSM, UMTS and LTE networks. GTP can be decomposed into separate protocols, GTP-C, GTP-U and GTP'. GTP-U is used for carrying user data within the GPRS core network and between the radio access network and the core network. The user data transported can be packets in any of IPv4, IPv6, or PPP formats. GTP-U is user plane communication protocol between Serving-Gateway (S-GW) and PDN-Gateway (P-GW) as well as Multi-access Edge Computing (MEC). This patch added a new tunnel type 'gtpu' into userspace datapath and two new match fields tun_gtpu_flags and tun_gtpu_msgtype, tun_id is reused for GTP Tunnel Endpoint ID (TEID). The below are commands for gtpu tunnel add: $ sudo ovs-vsctl add-br br-int -- set bridge br-int datapath_type=netdev protocols=OpenFlow13 $ sudo ovs-vsctl add-port br-int gtpu1 -- set interface gtpu1 type=gtpu options:packet_type=legacy_l3 options:remote_ip=flow options:key=flow options:dst_port=2152 test-flows-gtpu.txt is openflow table for gtpu tunnel test: $ cat test-flows-gtpu.txt table=0,icmp,in_port=4 actions=load:0xc0a83249->NXM_NX_TUN_IPV4_DST[],load:0x9->NXM_NX_TUN_ID[0..31],output:2 table=0,tcp,tp_dst=80,in_port=4 actions=load:0xc0a83249->NXM_NX_TUN_IPV4_DST[],load:0x9->NXM_NX_TUN_ID[0..31],output:2 table=0,in_port=2,tun_id=0x10,tun_gtpu_flags=0x30,tun_gtpu_msgtype=255 actions=set_field:00:00:22:22:22:22->eth_src,set_field:00:00:11:11:11:11->eth_dst,output:4 table=0,actions=NORMAL Signed-off-by: Feng Yang Signed-off-by: Jiannan Ouyang Signed-off-by: Yi Yang --- build-aux/extract-ofp-fields | 1 + datapath/linux/compat/include/linux/openvswitch.h | 3 + include/openvswitch/match.h | 4 + include/openvswitch/meta-flow.h | 28 +++++ include/openvswitch/packets.h | 4 +- lib/dpif-netlink-rtnl.c | 5 + lib/dpif-netlink.c | 5 + lib/flow.c | 7 ++ lib/match.c | 29 +++++ lib/meta-flow.c | 40 ++++++ lib/meta-flow.xml | 76 ++++++++++++ lib/netdev-native-tnl.c | 145 +++++++++++++++++++++- lib/netdev-native-tnl.h | 12 ++ lib/netdev-vport.c | 18 ++- lib/nx-match.c | 4 + lib/odp-util.c | 48 +++++++ lib/packets.h | 19 +++ lib/tnl-ports.c | 3 + ofproto/ofproto-dpif-ipfix.c | 5 + ofproto/ofproto-dpif-sflow.c | 6 +- ofproto/ofproto-dpif-xlate.c | 4 +- ofproto/tunnel.c | 9 +- vswitchd/vswitch.xml | 16 +++ 23 files changed, 485 insertions(+), 6 deletions(-) diff --git a/build-aux/extract-ofp-fields b/build-aux/extract-ofp-fields index 184b75e..944f095 100755 --- a/build-aux/extract-ofp-fields +++ b/build-aux/extract-ofp-fields @@ -68,6 +68,7 @@ PREREQS = {"none": "MFP_NONE", OXM_CLASSES = {"NXM_OF_": (0, 0x0000), "NXM_NX_": (0, 0x0001), "NXOXM_NSH_": (0x005ad650, 0xffff), + "NXOXM_GTPU_": (0x005ad651, 0xffff), "OXM_OF_": (0, 0x8000), "OXM_OF_PKT_REG": (0, 0x8001), "ONFOXM_ET_": (0x4f4e4600, 0xffff), diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h index 84ebcaf..ad6ea64 100644 --- a/datapath/linux/compat/include/linux/openvswitch.h +++ b/datapath/linux/compat/include/linux/openvswitch.h @@ -236,6 +236,7 @@ enum ovs_vport_type { OVS_VPORT_TYPE_GRE, /* GRE tunnel. */ OVS_VPORT_TYPE_VXLAN, /* VXLAN tunnel. */ OVS_VPORT_TYPE_GENEVE, /* Geneve tunnel. */ + OVS_VPORT_TYPE_GTPU, /* GTPU tunnel. */ OVS_VPORT_TYPE_LISP = 105, /* LISP tunnel */ OVS_VPORT_TYPE_STT = 106, /* STT tunnel */ __OVS_VPORT_TYPE_MAX @@ -394,6 +395,8 @@ enum ovs_tunnel_key_attr { OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS, /* Nested OVS_VXLAN_EXT_* */ OVS_TUNNEL_KEY_ATTR_IPV6_SRC, /* struct in6_addr src IPv6 address. */ OVS_TUNNEL_KEY_ATTR_IPV6_DST, /* struct in6_addr dst IPv6 address. */ + OVS_TUNNEL_KEY_ATTR_GTPU_FLAGS, /* u8 GTP-U FLAGS. */ + OVS_TUNNEL_KEY_ATTR_GTPU_MSGTYPE, /* u8 GTP-U MSGTYPE. */ OVS_TUNNEL_KEY_ATTR_PAD, __OVS_TUNNEL_KEY_ATTR_MAX }; diff --git a/include/openvswitch/match.h b/include/openvswitch/match.h index 49333ae..9bcc4f4 100644 --- a/include/openvswitch/match.h +++ b/include/openvswitch/match.h @@ -109,6 +109,10 @@ void match_set_tun_gbp_id_masked(struct match *match, ovs_be16 gbp_id, ovs_be16 void match_set_tun_gbp_id(struct match *match, ovs_be16 gbp_id); void match_set_tun_gbp_flags_masked(struct match *match, uint8_t flags, uint8_t mask); void match_set_tun_gbp_flags(struct match *match, uint8_t flags); +void match_set_tun_gtpu_flags(struct match *match, uint8_t gtpu_flags); +void match_set_tun_gtpu_flags_masked(struct match *match, uint8_t gtpu_flags, + uint8_t mask); +void match_set_tun_gtpu_msgtype(struct match *match, uint8_t gtpu_msgtype); void match_set_in_port(struct match *, ofp_port_t ofp_port); void match_set_pkt_mark(struct match *, uint32_t pkt_mark); void match_set_pkt_mark_masked(struct match *, uint32_t pkt_mark, uint32_t mask); diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h index 98c9e1c..884a2f6 100644 --- a/include/openvswitch/meta-flow.h +++ b/include/openvswitch/meta-flow.h @@ -1848,6 +1848,34 @@ enum OVS_PACKED_ENUM mf_field_id { */ MFF_NSH_TTL, + /* "tun_gtpu_flags". + * + * The flags in a GTP-U tunnel header. + * + * Type: u8. + * Maskable: bitwise. + * Formatting: decimal. + * Prerequisites: none. + * Access: read/write. + * NXM: none. + * OXM: NXOXM_GTPU_FLAGS(1) since OF1.3 and v2.10. + */ + MFF_TUN_GTPU_FLAGS, + + /* "tun_gtpu_msgtype". + * + * The message type in a GTP-U tunnel header. + * + * Type: u8. + * Maskable: no. + * Formatting: decimal. + * Prerequisites: none. + * Access: read/write. + * NXM: none. + * OXM: NXOXM_GTPU_MSGTYPE(2) since OF1.3 and v2.10. + */ + MFF_TUN_GTPU_MSGTYPE, + MFF_N_IDS }; diff --git a/include/openvswitch/packets.h b/include/openvswitch/packets.h index fef756b..1f3b499 100644 --- a/include/openvswitch/packets.h +++ b/include/openvswitch/packets.h @@ -39,7 +39,9 @@ struct flow_tnl { ovs_be16 tp_dst; ovs_be16 gbp_id; uint8_t gbp_flags; - uint8_t pad1[5]; /* Pad to 64 bits. */ + uint8_t gtpu_flags; + uint8_t gtpu_msgtype; + uint8_t pad1[3]; /* Pad to 64 bits. */ struct tun_metadata metadata; }; diff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c index 40c4569..a628b72 100644 --- a/lib/dpif-netlink-rtnl.c +++ b/lib/dpif-netlink-rtnl.c @@ -99,6 +99,8 @@ vport_type_to_kind(enum ovs_vport_type type, } case OVS_VPORT_TYPE_GENEVE: return "geneve"; + case OVS_VPORT_TYPE_GTPU: + return "gtpu"; case OVS_VPORT_TYPE_NETDEV: case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: @@ -262,6 +264,7 @@ dpif_netlink_rtnl_verify(const struct netdev_tunnel_config *tnl_cfg, case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: case OVS_VPORT_TYPE_STT: + case OVS_VPORT_TYPE_GTPU: case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: default: @@ -327,6 +330,7 @@ dpif_netlink_rtnl_create(const struct netdev_tunnel_config *tnl_cfg, case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: case OVS_VPORT_TYPE_STT: + case OVS_VPORT_TYPE_GTPU: case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: default: @@ -438,6 +442,7 @@ dpif_netlink_rtnl_port_destroy(const char *name, const char *type) case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: case OVS_VPORT_TYPE_STT: + case OVS_VPORT_TYPE_GTPU: case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: default: diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index bb9e95d..8b5bd97 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -787,6 +787,9 @@ get_vport_type(const struct dpif_netlink_vport *vport) case OVS_VPORT_TYPE_STT: return "stt"; + case OVS_VPORT_TYPE_GTPU: + return "gtpu"; + case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: break; @@ -814,6 +817,8 @@ netdev_to_ovs_vport_type(const char *type) return OVS_VPORT_TYPE_VXLAN; } else if (!strcmp(type, "lisp")) { return OVS_VPORT_TYPE_LISP; + } else if (strstr(type, "gtpu")) { + return OVS_VPORT_TYPE_GTPU; } else { return OVS_VPORT_TYPE_UNSPEC; } diff --git a/lib/flow.c b/lib/flow.c index 09b66b8..d5af1e8 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -695,6 +695,13 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst) miniflow_push_be32(mf, packet_type, packet_type); } + /* It won't be parsed if the packet contains application layer data only. + * These include, but not limited to GTP-U messages, GTP-C packets. + */ + if (packet_type == htonl(PT_GTPU_MSG)) { + goto out; + } + /* Initialize packet's layer pointer and offsets. */ frame = data; dp_packet_reset_offsets(packet); diff --git a/lib/match.c b/lib/match.c index 2e9a803..e5cc9c6 100644 --- a/lib/match.c +++ b/lib/match.c @@ -320,6 +320,27 @@ match_set_tun_gbp_flags(struct match *match, uint8_t flags) } void +match_set_tun_gtpu_flags(struct match *match, uint8_t gtpu_flags) +{ + match_set_tun_gtpu_flags_masked(match, gtpu_flags, UINT8_MAX); +} + +void +match_set_tun_gtpu_flags_masked(struct match *match, uint8_t gtpu_flags, + uint8_t mask) +{ + match->wc.masks.tunnel.gtpu_flags = mask; + match->flow.tunnel.gtpu_flags = gtpu_flags & mask; +} + +void +match_set_tun_gtpu_msgtype(struct match *match, uint8_t gtpu_msgtype) +{ + match->flow.tunnel.gtpu_msgtype = gtpu_msgtype; + match->wc.masks.tunnel.gtpu_msgtype = UINT8_MAX; +} + +void match_set_in_port(struct match *match, ofp_port_t ofp_port) { match->wc.masks.in_port.ofp_port = u16_to_ofp(UINT16_MAX); @@ -1239,6 +1260,14 @@ format_flow_tunnel(struct ds *s, const struct match *match) FLOW_TNL_F_MASK); ds_put_char(s, ','); } + + if (wc->masks.tunnel.gtpu_flags) { + ds_put_format(s, "tun_gtpu_flags=%"PRIx8",", tnl->gtpu_flags); + } + if (wc->masks.tunnel.gtpu_msgtype) { + ds_put_format(s, "tun_gtpu_msgtype=%"PRIu8",", tnl->gtpu_msgtype); + } + tun_metadata_match_format(s, match); } diff --git a/lib/meta-flow.c b/lib/meta-flow.c index aa2ec01..bde59df 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -231,6 +231,10 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc) return !wc->masks.tunnel.gbp_id; case MFF_TUN_GBP_FLAGS: return !wc->masks.tunnel.gbp_flags; + case MFF_TUN_GTPU_FLAGS: + return !wc->masks.tunnel.gtpu_flags; + case MFF_TUN_GTPU_MSGTYPE: + return !wc->masks.tunnel.gtpu_msgtype; CASE_MFF_TUN_METADATA: return !ULLONG_GET(wc->masks.tunnel.metadata.present.map, mf->id - MFF_TUN_METADATA0); @@ -513,6 +517,7 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value) case MFF_TUN_TTL: case MFF_TUN_GBP_ID: case MFF_TUN_GBP_FLAGS: + case MFF_TUN_GTPU_MSGTYPE: CASE_MFF_TUN_METADATA: case MFF_METADATA: case MFF_IN_PORT: @@ -625,6 +630,9 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value) case MFF_NSH_C4: return true; + case MFF_TUN_GTPU_FLAGS: + return (value->u8 == GTPU_FLAGS_DEFAULT); + case MFF_N_IDS: default: OVS_NOT_REACHED(); @@ -674,6 +682,12 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow, case MFF_TUN_GBP_FLAGS: value->u8 = flow->tunnel.gbp_flags; break; + case MFF_TUN_GTPU_FLAGS: + value->u8 = flow->tunnel.gtpu_flags; + break; + case MFF_TUN_GTPU_MSGTYPE: + value->u8 = flow->tunnel.gtpu_msgtype; + break; case MFF_TUN_TTL: value->u8 = flow->tunnel.ip_ttl; break; @@ -988,6 +1002,12 @@ mf_set_value(const struct mf_field *mf, case MFF_TUN_GBP_FLAGS: match_set_tun_gbp_flags(match, value->u8); break; + case MFF_TUN_GTPU_FLAGS: + match_set_tun_gtpu_flags(match, value->u8); + break; + case MFF_TUN_GTPU_MSGTYPE: + match_set_tun_gtpu_msgtype(match, value->u8); + break; case MFF_TUN_TOS: match_set_tun_tos(match, value->u8); break; @@ -1385,6 +1405,12 @@ mf_set_flow_value(const struct mf_field *mf, case MFF_TUN_GBP_FLAGS: flow->tunnel.gbp_flags = value->u8; break; + case MFF_TUN_GTPU_FLAGS: + flow->tunnel.gtpu_flags = value->u8; + break; + case MFF_TUN_GTPU_MSGTYPE: + flow->tunnel.gtpu_msgtype = value->u8; + break; case MFF_TUN_TOS: flow->tunnel.ip_tos = value->u8; break; @@ -1700,6 +1726,8 @@ mf_is_pipeline_field(const struct mf_field *mf) case MFF_TUN_FLAGS: case MFF_TUN_GBP_ID: case MFF_TUN_GBP_FLAGS: + case MFF_TUN_GTPU_FLAGS: + case MFF_TUN_GTPU_MSGTYPE: CASE_MFF_TUN_METADATA: case MFF_METADATA: case MFF_IN_PORT: @@ -1870,6 +1898,14 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str) case MFF_TUN_GBP_FLAGS: match_set_tun_gbp_flags_masked(match, 0, 0); break; + case MFF_TUN_GTPU_FLAGS: + match->wc.masks.tunnel.gtpu_flags = 0; + match->flow.tunnel.gtpu_flags = 0; + break; + case MFF_TUN_GTPU_MSGTYPE: + match->wc.masks.tunnel.gtpu_msgtype = 0; + match->flow.tunnel.gtpu_msgtype = 0; + break; case MFF_TUN_TOS: match_set_tun_tos_masked(match, 0, 0); break; @@ -2221,6 +2257,7 @@ mf_set(const struct mf_field *mf, case MFF_ICMPV4_CODE: case MFF_ICMPV6_TYPE: case MFF_ICMPV6_CODE: + case MFF_TUN_GTPU_MSGTYPE: return OFPUTIL_P_NONE; case MFF_DP_HASH: @@ -2250,6 +2287,9 @@ mf_set(const struct mf_field *mf, case MFF_TUN_GBP_FLAGS: match_set_tun_gbp_flags_masked(match, value->u8, mask->u8); break; + case MFF_TUN_GTPU_FLAGS: + match_set_tun_gtpu_flags_masked(match, value->u8, mask->u8); + break; case MFF_TUN_TTL: match_set_tun_ttl_masked(match, value->u8, mask->u8); break; diff --git a/lib/meta-flow.xml b/lib/meta-flow.xml index 933d4b8..d169772 100644 --- a/lib/meta-flow.xml +++ b/lib/meta-flow.xml @@ -731,6 +731,12 @@ tcp,tp_src=0x07c0/0xfff0 Used by Open vSwitch for NSH extensions, in the absence of an official ONF-assigned class. (This OUI is randomly generated.) + +
0x005ad651 (NXOXM_GTPU)
+
+ Used by Open vSwitch for GTP-U extensions, in the absence of an official + ONF-assigned class. (This OUI is randomly generated.) +

@@ -1899,6 +1905,68 @@ ovs-ofctl add-flow br0 tun_metadata0=1234,actions=controller

+

GTP-U Fields

+ +

+ The GTP-U (v1) header is defined as follows [3GPP TS 29.281]. +

+ + +
+ + + + + + +
+ +
+ + + + +
+
+ +

+ where +

+
    +
  • V: version fields, used to determine the version of the + GTP-U protocol, which should be set to '1'.
  • +
  • PT: Packet Type, used as a protocol discriminator + between GTP (when PT is '1') and GTP' (when PT is '0').
  • +
  • E: Extension Header flag, indicating the presence of a + meaningful value of the Next Extension Header field.
  • +
  • S: Sequence number flag, indicating the presence of a + meaningful value of the Sequence Number field.
  • +
  • PN: N-PDU Number flag, indicating the presence of a + meaningful value of the N-PDU Number field.
  • +
  • Message Type: indicating the type of GTP-U message. +
  • +
  • Length: indicating the length in octets of the payload. +
  • +
  • TEID: Tunnel Endpoint Identifier,unambiguously + identifying a tunnel endpoint in the receiving GTP-U protocol entity. + Open vSwitch makes TEID availabe via .
  • +
+ +

+ For a packet tunneled over GTP-U, this field indicates the presence of + optional headers. +

+
+ + +

+ For a packet tunneled over GTP-U, this field indicates whether it's a + signalling message used for path management, or a user plane message + which carries the original packet. The complete range of message types + can be referred to [3GPP TS 29.281]. +

+
+ @@ -4662,6 +4730,14 @@ r r c c c. . +
3GPP TS 29.281
+
+ 3GPP, + ``General Packet Radio System (GPRS) Tunnelling Protocol User Plane + (GTPv1-U),'' + . +
+
Srinivasan
V. Srinivasan, S. Suriy, and G. Varghese, ``Packet diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index c3e698d..cace175 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -55,6 +55,9 @@ static struct vlog_rate_limit err_rl = VLOG_RATE_LIMIT_INIT(60, 5); #define GENEVE_BASE_HLEN (sizeof(struct udp_header) + \ sizeof(struct genevehdr)) +#define GTPU_HLEN (sizeof(struct udp_header) + \ + sizeof(struct gtpuhdr)) + uint16_t tnl_udp_port_min = 32768; uint16_t tnl_udp_port_max = 61000; @@ -715,7 +718,147 @@ netdev_geneve_build_header(const struct netdev *netdev, return 0; } - +void +netdev_gtpu_push_header(struct dp_packet *packet, + const struct ovs_action_push_tnl *data) +{ + struct udp_header *udp; + struct gtpuhdr *gtph; + int gtpu_len; + int ip_tot_size; + + gtpu_len = dp_packet_size(packet); + + udp = netdev_tnl_push_ip_header(packet, data->header, data->header_len, + &ip_tot_size); + udp->udp_len = htons(ip_tot_size); + + gtph = (struct gtpuhdr *)(udp + 1); + gtph->len = htons(gtpu_len); + + if (udp->udp_csum) { + uint32_t csum; + if (netdev_tnl_is_header_ipv6(dp_packet_data(packet))) { + csum = packet_csum_pseudoheader6( + netdev_tnl_ipv6_hdr(dp_packet_data(packet))); + } else { + csum = packet_csum_pseudoheader( + netdev_tnl_ip_hdr(dp_packet_data(packet))); + } + + csum = csum_continue(csum, udp, ip_tot_size); + udp->udp_csum = csum_finish(csum); + + if (!udp->udp_csum) { + udp->udp_csum = htons(0xffff); + } + } + + packet->packet_type = htonl(PT_ETH); +} + + +int +netdev_gtpu_build_header(const struct netdev *netdev, + struct ovs_action_push_tnl *data, + const struct netdev_tnl_build_header_params *params) +{ + struct netdev_vport *dev = netdev_vport_cast(netdev); + struct netdev_tunnel_config *tnl_cfg; + struct gtpuhdr *gtph; + struct udp_header *udp; + + /* XXX: RCUfy tnl_cfg. */ + ovs_mutex_lock(&dev->mutex); + + tnl_cfg = &dev->tnl_cfg; + udp = netdev_tnl_ip_build_header(data, params, IPPROTO_UDP); + udp->udp_dst = tnl_cfg->dst_port; + udp->udp_src = htons(GTPU_DST_PORT); + + if (params->is_ipv6 || params->flow->tunnel.flags & FLOW_TNL_F_CSUM) { + /* Write a value in now to mark that we should compute the checksum + * later. 0xffff is handy because it is transparent to the + * calculation. */ + udp->udp_csum = htons(0xffff); + } + + ovs_mutex_unlock(&dev->mutex); + data->header_len += sizeof *udp; + + gtph = (struct gtpuhdr *)(udp + 1); + gtph->flags = params->flow->tunnel.gtpu_flags; + gtph->msgtype = params->flow->tunnel.gtpu_msgtype; + + put_16aligned_be32(>ph->teid, + htonl(ntohll(params->flow->tunnel.tun_id))); + data->header_len += sizeof *gtph; + data->tnl_type = OVS_VPORT_TYPE_GTPU; + return 0; +} + +struct dp_packet * +netdev_gtpu_pop_header(struct dp_packet *packet) +{ + struct pkt_metadata *md = &packet->md; + struct flow_tnl *tnl = &md->tunnel; + struct gtpuhdr *gtph; + unsigned int hlen; + + pkt_metadata_init_tnl(md); + if (GTPU_HLEN > dp_packet_l4_size(packet)) { + VLOG_WARN_RL(&err_rl, "GTP-U packet too small: min header=%u " + "packet size=%"PRIuSIZE"\n", + (unsigned int)GTPU_HLEN, dp_packet_l4_size(packet)); + goto err; + } + + gtph = udp_extract_tnl_md(packet, tnl, &hlen); + if (!gtph) { + goto err; + } + + if (gtph->flags == 0x30) { + /* Only GTP-U v1 packets without optional fileds are processed, i.e. + * 8 7 6 5 4 3 2 1 + * | ver | PT | 0 | E | S | PN | + * 0 0 1 1 0 0 0 0 + */ + tnl->gtpu_flags = gtph->flags; + } else { + goto err; + } + tnl->gtpu_msgtype = gtph->msgtype; + tnl->tun_id = htonll(ntohl(get_16aligned_be32(>ph->teid))); + + /*Figure out whether the inner packet is IPv4, IPv6 or a GTP-U message.*/ + if (tnl->gtpu_msgtype == GTPU_MSGTYPE_GPDU) { + struct ip_header *ip; + + ip = (struct ip_header *)(gtph + 1); + if (IP_VER(ip->ip_ihl_ver) == 4) { + packet->packet_type = htonl(PT_IPV4); + } else if (IP_VER(ip->ip_ihl_ver) == 6) { + packet->packet_type = htonl(PT_IPV6); + } else { + goto err; + } + } else { + /* GTP-U messages, including echo request, end marker, etc. + * OVS will be kicking it to a control-plane entity if properly + * configured. + */ + packet->packet_type = htonl(PT_GTPU_MSG); + } + + dp_packet_reset_packet(packet, hlen + GTPU_HLEN); + + return packet; +err: + dp_packet_delete(packet); + return NULL; +} + void netdev_tnl_egress_port_range(struct unixctl_conn *conn, int argc, const char *argv[], void *aux OVS_UNUSED) diff --git a/lib/netdev-native-tnl.h b/lib/netdev-native-tnl.h index a912ce9..9c4cc66 100644 --- a/lib/netdev-native-tnl.h +++ b/lib/netdev-native-tnl.h @@ -58,6 +58,18 @@ netdev_vxlan_build_header(const struct netdev *netdev, struct dp_packet * netdev_vxlan_pop_header(struct dp_packet *packet); +void +netdev_gtpu_push_header(struct dp_packet *packet, + const struct ovs_action_push_tnl *data); + +int +netdev_gtpu_build_header(const struct netdev *netdev, + struct ovs_action_push_tnl *data, + const struct netdev_tnl_build_header_params *params); + +struct dp_packet * +netdev_gtpu_pop_header(struct dp_packet *packet); + static inline bool netdev_tnl_is_header_ipv6(const void *header) { diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 52aa12d..ee454a1 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -107,7 +107,10 @@ netdev_vport_needs_dst_port(const struct netdev *dev) return (class->get_config == get_tunnel_config && (!strcmp("geneve", type) || !strcmp("vxlan", type) || - !strcmp("lisp", type) || !strcmp("stt", type)) ); + !strcmp("lisp", type) || !strcmp("stt", type) || + !strcmp("gtpu", type) + ) + ); } const char * @@ -199,6 +202,8 @@ netdev_vport_construct(struct netdev *netdev_) dev->tnl_cfg.dst_port = htons(LISP_DST_PORT); } else if (!strcmp(type, "stt")) { dev->tnl_cfg.dst_port = htons(STT_DST_PORT); + } else if (!strcmp(type, "gtpu")) { + dev->tnl_cfg.dst_port = htons(GTPU_DST_PORT); } dev->tnl_cfg.dont_fragment = true; @@ -408,6 +413,8 @@ tunnel_supported_layers(const char *type, return TNL_L3; } else if (!strcmp(type, "gre")) { return TNL_L2 | TNL_L3; + } else if (!strcmp(type, "gtpu")) { + return TNL_L3; } else if (!strcmp(type, "vxlan") && tnl_cfg->exts & (1 << OVS_VXLAN_EXT_GPE)) { return TNL_L2 | TNL_L3; @@ -455,6 +462,10 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp) tnl_cfg.dst_port = htons(STT_DST_PORT); } + if (!strcmp(type, "gtpu")) { + tnl_cfg.dst_port = htons(GTPU_DST_PORT); + } + needs_dst_port = netdev_vport_needs_dst_port(dev_); tnl_cfg.dont_fragment = true; @@ -700,6 +711,7 @@ get_tunnel_config(const struct netdev *dev, struct smap *args) if ((!strcmp("geneve", type) && dst_port != GENEVE_DST_PORT) || (!strcmp("vxlan", type) && dst_port != VXLAN_DST_PORT) || (!strcmp("lisp", type) && dst_port != LISP_DST_PORT) || + (!strcmp("gtpu", type) && dst_port != GTPU_DST_PORT) || (!strcmp("stt", type) && dst_port != STT_DST_PORT)) { smap_add_format(args, "dst_port", "%d", dst_port); } @@ -979,6 +991,10 @@ netdev_vport_tunnel_register(void) NETDEV_VPORT_GET_IFINDEX), TUNNEL_CLASS("lisp", "lisp_sys", NULL, NULL, NULL, NULL), TUNNEL_CLASS("stt", "stt_sys", NULL, NULL, NULL, NULL), + TUNNEL_CLASS("gtpu", "gptu_sys", netdev_gtpu_build_header, + netdev_gtpu_push_header, + netdev_gtpu_pop_header, + NULL), }; static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; diff --git a/lib/nx-match.c b/lib/nx-match.c index a8edb2e..c7f6c27 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -1153,6 +1153,10 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match, flow->tunnel.gbp_id, match->wc.masks.tunnel.gbp_id); nxm_put_8m(&ctx, MFF_TUN_GBP_FLAGS, oxm, flow->tunnel.gbp_flags, match->wc.masks.tunnel.gbp_flags); + nxm_put_8m(&ctx, MFF_TUN_GTPU_FLAGS, oxm, flow->tunnel.gtpu_flags, + match->wc.masks.tunnel.gtpu_flags); + nxm_put_8m(&ctx, MFF_TUN_GTPU_MSGTYPE, oxm, flow->tunnel.gtpu_msgtype, + match->wc.masks.tunnel.gtpu_msgtype); tun_metadata_to_nx_match(b, oxm, match); /* Network Service Header */ diff --git a/lib/odp-util.c b/lib/odp-util.c index 70188b6..2c5a1f1 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -712,6 +712,15 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data) options++; } ds_put_format(ds, ")"); + } else if (data->tnl_type == OVS_VPORT_TYPE_GTPU) { + const struct gtpuhdr *gtph; + + gtph = format_udp_tnl_push_header(ds, udp); + + ds_put_format(ds, "gtpu(flags=0x%"PRIx8 + ",msgtype=0x%"PRIx8",teid=0x%"PRIx32")", + gtph->flags, gtph->msgtype, + ntohl(get_16aligned_be32(>ph->teid))); } ds_put_format(ds, ")"); } @@ -1474,6 +1483,7 @@ ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data) if (ovs_scan_len(s, &n, "udp(src=%"SCNi16",dst=%"SCNi16",csum=0x%"SCNx16"),", &udp_src, &udp_dst, &csum)) { uint32_t vx_flags, vni; + uint8_t gtpu_flags, gtpu_msgtype; udp->udp_src = htons(udp_src); udp->udp_dst = htons(udp_dst); @@ -1528,6 +1538,17 @@ ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data) gnh->proto_type = htons(ETH_TYPE_TEB); put_16aligned_be32(&gnh->vni, htonl(vni << 8)); tnl_type = OVS_VPORT_TYPE_GENEVE; + } else if (ovs_scan_len(s, &n, "gtpu(flags=0x%"SCNx8",msgtype=0x%" + SCNx8",teid=0x%"SCNx32"))", + >pu_flags, >pu_msgtype, &vni)) { + struct gtpuhdr *gtph = (struct gtpuhdr *) (udp + 1); + + gtph->flags = gtpu_flags; + gtph->msgtype = gtpu_msgtype; + put_16aligned_be32(>ph->teid, htonl(vni)); + tnl_type = OVS_VPORT_TYPE_GTPU; + header_len = sizeof *eth + ip_len + + sizeof *udp + sizeof *gtph; } else { return -EINVAL; } @@ -2373,6 +2394,8 @@ static const struct attr_len_tbl ovs_tun_key_attr_lens[OVS_TUNNEL_KEY_ATTR_MAX + [OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS] = { .len = ATTR_LEN_NESTED, .next = ovs_vxlan_ext_attr_lens , .next_max = OVS_VXLAN_EXT_MAX}, + [OVS_TUNNEL_KEY_ATTR_GTPU_FLAGS] = { .len = 1 }, + [OVS_TUNNEL_KEY_ATTR_GTPU_MSGTYPE] = { .len = 1 }, [OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = 16 }, [OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = 16 }, }; @@ -2698,6 +2721,12 @@ odp_tun_key_from_attr__(const struct nlattr *attr, bool is_mask, case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS: tun_metadata_from_geneve_nlattr(a, is_mask, tun); break; + case OVS_TUNNEL_KEY_ATTR_GTPU_FLAGS: + tun->gtpu_flags = nl_attr_get_u8(a); + break; + case OVS_TUNNEL_KEY_ATTR_GTPU_MSGTYPE: + tun->gtpu_msgtype = nl_attr_get_u8(a); + break; default: /* Allow this to show up as unexpected, if there are unknown @@ -2767,6 +2796,13 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key, if (tun_key->flags & FLOW_TNL_F_OAM) { nl_msg_put_flag(a, OVS_TUNNEL_KEY_ATTR_OAM); } + if (tun_key->gtpu_flags) { + nl_msg_put_u8(a, OVS_TUNNEL_KEY_ATTR_GTPU_FLAGS, tun_key->gtpu_flags); + } + if (tun_key->gtpu_msgtype) { + nl_msg_put_u8(a, OVS_TUNNEL_KEY_ATTR_GTPU_MSGTYPE, + tun_key->gtpu_msgtype); + } /* If tnl_type is set to a particular type of output tunnel, * only put its relevant tunnel metadata to the nlattr. @@ -3487,6 +3523,14 @@ format_odp_tun_attr(const struct nlattr *attr, const struct nlattr *mask_attr, format_odp_tun_geneve(a, ma, ds, verbose); ds_put_cstr(ds, "),"); break; + case OVS_TUNNEL_KEY_ATTR_GTPU_FLAGS: + format_u8x(ds, "gtpu_flags", nl_attr_get_u8(a), + ma ? nl_attr_get(ma) : NULL, verbose); + break; + case OVS_TUNNEL_KEY_ATTR_GTPU_MSGTYPE: + format_u8x(ds, "gtpu_msgtype", nl_attr_get_u8(a), + ma ? nl_attr_get(ma) : NULL, verbose); + break; case OVS_TUNNEL_KEY_ATTR_PAD: break; case __OVS_TUNNEL_KEY_ATTR_MAX: @@ -5179,6 +5223,10 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names, SCAN_FIELD_NESTED_FUNC("geneve(", struct geneve_scan, geneve, geneve_to_attr); SCAN_FIELD_NESTED_FUNC("flags(", uint16_t, tun_flags, tun_flags_to_attr); + SCAN_FIELD_NESTED("gtpu_flags=", uint8_t, u8, + OVS_TUNNEL_KEY_ATTR_GTPU_FLAGS); + SCAN_FIELD_NESTED("gtpu_msg_type=", uint8_t, u8, + OVS_TUNNEL_KEY_ATTR_GTPU_MSGTYPE); } SCAN_END_NESTED(); SCAN_SINGLE_PORT("in_port(", uint32_t, OVS_KEY_ATTR_IN_PORT); diff --git a/lib/packets.h b/lib/packets.h index b2bf706..16cb3f3 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -1306,6 +1306,23 @@ BUILD_ASSERT_DECL(sizeof(struct vxlanhdr) == 8); #define VXLAN_F_GPE 0x4000 #define VXLAN_HF_GPE 0x04000000 +/* GTP-U protocol header */ +struct gtpuhdr { + uint8_t flags; + uint8_t msgtype; + ovs_be16 len; + ovs_16aligned_be32 teid; +}; + +/* GTP-U UDP port */ +#define GTPU_DST_PORT 2152 + +/* Default GTP-U flags */ +#define GTPU_FLAGS_DEFAULT 0x30 + +/* GTP-U message type for normal user plane PDU */ +#define GTPU_MSGTYPE_GPDU 255 + /* Input values for PACKET_TYPE macros have to be in host byte order. * The _BE postfix indicates result is in network byte order. Otherwise result * is in host byte order. */ @@ -1342,6 +1359,8 @@ enum packet_type { PT_MPLS = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_MPLS), PT_MPLS_MC = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_MPLS_MCAST), PT_NSH = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_NSH), + /* GTP-U message. */ + PT_GTPU_MSG = PACKET_TYPE(OFPHTN_UDP_TCP_PORT, GTPU_DST_PORT), PT_UNKNOWN = PACKET_TYPE(0xffff, 0xffff), /* Unknown packet type. */ }; diff --git a/lib/tnl-ports.c b/lib/tnl-ports.c index b814f7a..cb8fab8 100644 --- a/lib/tnl-ports.c +++ b/lib/tnl-ports.c @@ -177,6 +177,9 @@ tnl_type_to_nw_proto(const char type[]) if (!strcmp(type, "vxlan")) { return IPPROTO_UDP; } + if (!strcmp(type, "gtpu")) { + return IPPROTO_UDP; + } return 0; } diff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c index 4d9fe78..2951a74 100644 --- a/ofproto/ofproto-dpif-ipfix.c +++ b/ofproto/ofproto-dpif-ipfix.c @@ -88,6 +88,7 @@ enum dpif_ipfix_tunnel_type { DPIF_IPFIX_TUNNEL_LISP = 0x03, DPIF_IPFIX_TUNNEL_STT = 0x04, DPIF_IPFIX_TUNNEL_GENEVE = 0x07, + DPIF_IPFIX_TUNNEL_GTPU = 0x08, NUM_DPIF_IPFIX_TUNNEL }; @@ -389,6 +390,7 @@ static uint8_t tunnel_protocol[NUM_DPIF_IPFIX_TUNNEL] = { IPPROTO_TCP, /* DPIF_IPFIX_TUNNEL_STT*/ 0 , /* reserved */ IPPROTO_UDP, /* DPIF_IPFIX_TUNNEL_GENEVE*/ + IPPROTO_UDP, /* DPIF_IPFIX_TUNNEL_GTPU */ }; OVS_PACKED( @@ -509,6 +511,7 @@ BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_aggregated_tcp) == 48); * support tunnel key for: * VxLAN: 24-bit VIN, * GRE: 32-bit key, + * GTPU: 32-bit key, * LISP: 24-bit instance ID * STT: 64-bit key */ @@ -811,6 +814,8 @@ dpif_ipfix_tunnel_type(const struct ofport *ofport) return DPIF_IPFIX_TUNNEL_GENEVE; } else if (strcmp(type, "stt") == 0) { return DPIF_IPFIX_TUNNEL_STT; + } else if (strcmp(type, "gtpu") == 0) { + return DPIF_IPFIX_TUNNEL_GTPU; } return DPIF_IPFIX_TUNNEL_UNKNOWN; diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c index bbec30e..042c7cf 100644 --- a/ofproto/ofproto-dpif-sflow.c +++ b/ofproto/ofproto-dpif-sflow.c @@ -61,7 +61,8 @@ enum dpif_sflow_tunnel_type { DPIF_SFLOW_TUNNEL_VXLAN, DPIF_SFLOW_TUNNEL_GRE, DPIF_SFLOW_TUNNEL_LISP, - DPIF_SFLOW_TUNNEL_GENEVE + DPIF_SFLOW_TUNNEL_GENEVE, + DPIF_SFLOW_TUNNEL_GTPU }; struct dpif_sflow_port { @@ -621,6 +622,8 @@ dpif_sflow_tunnel_type(struct ofport *ofport) { return DPIF_SFLOW_TUNNEL_VXLAN; } else if (strcmp(type, "lisp") == 0) { return DPIF_SFLOW_TUNNEL_LISP; + } else if (strcmp(type, "gtpu") == 0) { + return DPIF_SFLOW_TUNNEL_GTPU; } else if (strcmp(type, "geneve") == 0) { return DPIF_SFLOW_TUNNEL_GENEVE; } @@ -641,6 +644,7 @@ dpif_sflow_tunnel_proto(enum dpif_sflow_tunnel_type tunnel_type) case DPIF_SFLOW_TUNNEL_VXLAN: case DPIF_SFLOW_TUNNEL_LISP: + case DPIF_SFLOW_TUNNEL_GTPU: case DPIF_SFLOW_TUNNEL_GENEVE: ipproto = IPPROTO_UDP; diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 3cb7b5e..f566e3c 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -3352,6 +3352,7 @@ propagate_tunnel_data_to_flow(struct xlate_ctx *ctx, struct eth_addr dmac, break; case OVS_VPORT_TYPE_VXLAN: case OVS_VPORT_TYPE_GENEVE: + case OVS_VPORT_TYPE_GTPU: nw_proto = IPPROTO_UDP; break; case OVS_VPORT_TYPE_LISP: @@ -7166,7 +7167,8 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) ctx.xin->xport_uuid = in_port->uuid; } - if (flow->packet_type != htonl(PT_ETH) && in_port && + if (flow->packet_type != htonl(PT_GTPU_MSG) && + flow->packet_type != htonl(PT_ETH) && in_port && in_port->pt_mode == NETDEV_PT_LEGACY_L3 && ctx.table_id == 0) { /* Add dummy Ethernet header to non-L2 packet if it's coming from a * L3 port. So all packets will be L2 packets for lookup. diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c index a040b54..7de68c4 100644 --- a/ofproto/tunnel.c +++ b/ofproto/tunnel.c @@ -384,6 +384,12 @@ tnl_wc_init(struct flow *flow, struct flow_wildcards *wc) wc->masks.tunnel.tp_src = 0; wc->masks.tunnel.tp_dst = 0; + /* GTP-U header are set to be always unwildcarded for GTP-U packets*/ + if (flow->tunnel.gtpu_flags || flow->tunnel.gtpu_msgtype) { + wc->masks.tunnel.gtpu_flags = UINT8_MAX; + wc->masks.tunnel.gtpu_msgtype = UINT8_MAX; + } + if (is_ip_any(flow) && IP_ECN_is_ce(flow->tunnel.ip_tos)) { wc->masks.nw_tos |= IP_ECN_MASK; @@ -569,7 +575,8 @@ tnl_find(const struct flow *flow) OVS_REQ_RDLOCK(rwlock) match.ip_src_flow = ip_src == IP_SRC_FLOW; /* Look for a legacy L2 or L3 tunnel port first. */ - if (pt_ns(flow->packet_type) == OFPHTN_ETHERTYPE) { + if (pt_ns(flow->packet_type) == OFPHTN_ETHERTYPE || + flow->packet_type == htonl(PT_GTPU_MSG)) { match.pt_mode = NETDEV_PT_LEGACY_L3; } else { match.pt_mode = NETDEV_PT_LEGACY_L2; diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index 7ab90d5..83f6cbb 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -2283,6 +2283,22 @@

+
gtpu
+
+ GPRS Tunneling Protocol (GTP) is a group of IP-based communications + protocols used to carry general packet radio service (GPRS) within GSM, + UMTS and LTE networks. GTP-U is used for carrying user data within the GPRS + core network and between the radio access network and the core network. + The user data transported can be packets in any of IPv4, IPv6, or PPP + formats. + + The protocol is documented at http://www.3gpp.org/DynaReport/29281.htm + + Open vSwitch uses UDP destination port 2152. The source port used for + GTP traffic varies on a per-flow basis and is in the ephemeral port + range. +
+
stt
The Stateless TCP Tunnel (STT) is particularly useful when tunnel From patchwork Tue May 15 06:32:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Yang, Yi" X-Patchwork-Id: 913451 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40lSd24HZNz9s1R for ; Tue, 15 May 2018 16:40:54 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id E3376DC8; Tue, 15 May 2018 06:39:59 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id EC158D9A for ; Tue, 15 May 2018 06:39:58 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 071556B9 for ; Tue, 15 May 2018 06:39:57 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 May 2018 23:39:57 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,402,1520924400"; d="scan'208";a="199435991" Received: from unknown (HELO localhost.localdomain.bj.intel.com) ([10.240.224.185]) by orsmga004.jf.intel.com with ESMTP; 14 May 2018 23:39:56 -0700 From: Yi Yang To: dev@openvswitch.org Date: Tue, 15 May 2018 14:32:09 +0800 Message-Id: <1526365929-3047-3-git-send-email-yi.y.yang@intel.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1526365929-3047-1-git-send-email-yi.y.yang@intel.com> References: <1526365929-3047-1-git-send-email-yi.y.yang@intel.com> X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Feng Yang Subject: [ovs-dev] [PATCH v2 2/2] Add GTP-U unit test cases X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Feng Yang This patch adds a basic GTP-U test case to tests/tunnel.at, GTP-U pop and push test cases to tests/tunnel-push-pop.at. Signed-off-by: Feng Yang Signed-off-by: Yi Yang --- tests/ofproto.at | 4 +++- tests/tunnel-push-pop.at | 19 +++++++++++++++++++ tests/tunnel.at | 13 +++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/tests/ofproto.at b/tests/ofproto.at index bf4166a..f2d9798 100644 --- a/tests/ofproto.at +++ b/tests/ofproto.at @@ -2396,7 +2396,7 @@ head_table () { actions: output group set_field strip_vlan push_vlan mod_nw_ttl dec_ttl set_mpls_ttl dec_mpls_ttl push_mpls pop_mpls set_queue supported on Set-Field: tun_id tun_src tun_dst tun_ipv6_src tun_ipv6_dst tun_flags tun_gbp_id tun_gbp_flags tun_metadata0 dnl tun_metadata1 tun_metadata2 tun_metadata3 tun_metadata4 tun_metadata5 tun_metadata6 tun_metadata7 tun_metadata8 tun_metadata9 tun_metadata10 tun_metadata11 tun_metadata12 tun_metadata13 tun_metadata14 tun_metadata15 tun_metadata16 tun_metadata17 tun_metadata18 tun_metadata19 tun_metadata20 tun_metadata21 tun_metadata22 tun_metadata23 tun_metadata24 tun_metadata25 tun_metadata26 tun_metadata27 tun_metadata28 tun_metadata29 tun_metadata30 tun_metadata31 tun_metadata32 tun_metadata33 tun_metadata34 tun_metadata35 tun_metadata36 tun_metadata37 tun_metadata38 tun_metadata39 tun_metadata40 tun_metadata41 tun_metadata42 tun_metadata43 tun_metadata44 tun_metadata45 tun_metadata46 tun_metadata47 tun_metadata48 tun_metadata49 tun_metadata50 tun_metadata51 tun_metadata52 tun_metadata53 tun_metadata54 tun_metadata55 tun_metadata56 tun_metadata57 tun_metadata58 tun_metadata59 tun_metadata60 tun_metadata61 tun_metadata62 tun_metadata63 dnl -metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 reg10 reg11 reg12 reg13 reg14 reg15 xreg0 xreg1 xreg2 xreg3 xreg4 xreg5 xreg6 xreg7 xxreg0 xxreg1 xxreg2 xxreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc mpls_ttl ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst icmp_type icmp_code icmpv6_type icmpv6_code nd_target nd_sll nd_tll nsh_flags nsh_spi nsh_si nsh_c1 nsh_c2 nsh_c3 nsh_c4 nsh_ttl +metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 reg10 reg11 reg12 reg13 reg14 reg15 xreg0 xreg1 xreg2 xreg3 xreg4 xreg5 xreg6 xreg7 xxreg0 xxreg1 xxreg2 xxreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc mpls_ttl ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst icmp_type icmp_code icmpv6_type icmpv6_code nd_target nd_sll nd_tll nsh_flags nsh_spi nsh_si nsh_c1 nsh_c2 nsh_c3 nsh_c4 nsh_ttl tun_gtpu_flags tun_gtpu_msgtype matching: dp_hash: arbitrary mask recirc_id: exact match or wildcard @@ -2568,6 +2568,8 @@ metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 nsh_c3: arbitrary mask nsh_c4: arbitrary mask nsh_ttl: exact match or wildcard + tun_gtpu_flags: arbitrary mask + tun_gtpu_msgtype: exact match or wildcard ' "$1" } diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at index 10f98c6..e97d327 100644 --- a/tests/tunnel-push-pop.at +++ b/tests/tunnel-push-pop.at @@ -18,6 +18,8 @@ AT_CHECK([ovs-vsctl add-port int-br t2 -- set Interface t2 type=vxlan \ options:remote_ip=1.1.2.92 options:key=456 options:packet_type=legacy_l3 ofport_request=7\ -- add-port int-br t7 -- set Interface t7 type=vxlan \ options:remote_ip=1.1.2.92 options:key=345 options:exts=gpe ofport_request=8\ + -- add-port int-br t8 -- set Interface t8 type=gtpu \ + options:remote_ip=1.1.2.92 options:key=123 ofport_request=9\ ], [0]) AT_CHECK([ovs-appctl dpif/show], [0], [dnl @@ -34,6 +36,7 @@ dummy@ovs-dummy: hit:0 missed:0 t5 6/6081: (geneve: egress_pkt_mark=1234, out_key=flow, remote_ip=1.1.2.93) t6 7/3: (gre: key=456, packet_type=legacy_l3, remote_ip=1.1.2.92) t7 8/4789: (vxlan: key=345, remote_ip=1.1.2.92) + t8 9/2152: (gtpu: key=123, remote_ip=1.1.2.92) ]) dnl First setup dummy interface IP address, then add the route @@ -143,6 +146,7 @@ AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl Listening ports: genev_sys_6081 (6081) ref_cnt=2 +gptu_sys_2152 (2152) ref_cnt=1 gre_sys (3) ref_cnt=2 vxlan_sys_4789 (4789) ref_cnt=3 ]) @@ -171,6 +175,12 @@ AT_CHECK([tail -1 stdout], [0], [Datapath actions: tnl_pop(6081) ]) +dnl Check GTP-U tunnel pop +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.2.92,dst=1.1.2.88,proto=17,tos=0,ttl=64,frag=no),udp(src=51283,dst=2152)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: tnl_pop(2152) +]) + dnl Check VXLAN tunnel push AT_CHECK([ovs-ofctl add-flow int-br action=2]) AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) @@ -295,16 +305,25 @@ dnl Check tunnel lookup entries after deleting/reconfiguring some ports AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl Listening ports: genev_sys_6081 (6081) ref_cnt=1 +gptu_sys_2152 (2152) ref_cnt=1 gre_sys (3) ref_cnt=1 vxlan_sys_4789 (4789) ref_cnt=2 vxlan_sys_4790 (4790) ref_cnt=1 ]) +dnl Check GTP-U tunnel push +AT_CHECK([ovs-ofctl add-flow int-br "action=set_field:0x30->tun_gtpu_flags,set_field:0xff->tun_gtpu_msgtype,9"]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: pop_eth,clone(tnl_push(tnl_port(2152),header(size=50,type=6,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=2152,dst=2152,csum=0x0),gtpu(flags=0x30,msgtype=0xff,teid=0x7b)),out_port(100)),1) +]) + AT_CHECK([ovs-vsctl del-port int-br t1 \ -- del-port int-br t2 \ -- del-port int-br t4 \ -- del-port int-br t6 \ -- del-port int-br t7 \ + -- del-port int-br t8 \ ], [0]) dnl Check tunnel lookup entries after deleting all remaining tunnel ports diff --git a/tests/tunnel.at b/tests/tunnel.at index eeadb2f..5a55ce3 100644 --- a/tests/tunnel.at +++ b/tests/tunnel.at @@ -406,6 +406,19 @@ AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl OVS_VSWITCHD_STOP AT_CLEANUP + +AT_SETUP([tunnel - GTP-U]) +OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=gtpu \ + options:remote_ip=1.1.1.1 ofport_request=1]) + +AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl + br0 65534/100: (dummy-internal) + p1 1/2152: (gtpu: remote_ip=1.1.1.1) +]) + +OVS_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([tunnel - different VXLAN UDP port]) OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=vxlan \ options:remote_ip=1.1.1.1 ofport_request=1 options:dst_port=4341])