From patchwork Mon Feb 12 23:08:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tiago Lam X-Patchwork-Id: 872513 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; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="amg1wNNm"; dkim-atps=neutral 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 3zgLz81Bwnz9sRm for ; Tue, 13 Feb 2018 10:12:04 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 5D31810AC; Mon, 12 Feb 2018 23:09:16 +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 4032C1095 for ; Mon, 12 Feb 2018 23:09:14 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-wr0-f195.google.com (mail-wr0-f195.google.com [209.85.128.195]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id B83F6165 for ; Mon, 12 Feb 2018 23:09:11 +0000 (UTC) Received: by mail-wr0-f195.google.com with SMTP id k9so3066696wre.9 for ; Mon, 12 Feb 2018 15:09:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=TAWQxnk1A1yjxgad7vYfhMxQ2X65jNPGJIRnAToAp5Q=; b=amg1wNNmD0wCnKKJFvNpGrAMegLgZy3SciSew8ryNrSIwPlaWjXVM8ufmPO1TH7xMF J6o44xj6yxyevFvE2j/9gaTNwk9rc5cnj0VzgRhCxHCSLlfjJ59Lc9AnHizo3HH6+Dsz oykvXZOhjTmBDdv/FInV3BTAcgq+38ErmPLvrrl09apEEbledl/0yMZPd2muqyxWRzUT LlKHUZkg43+0NOz6y5xkq/tKVWldtKAHkriJfmUioLODaJmwDpmObWFUr24mWqvTe4o2 sNclCH3G+fCWgjh13yW5G2ujtIwHs3DdyqzxWd4mtC5NI77V8qb3AaET/ZzutJXEXMNg WO9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=TAWQxnk1A1yjxgad7vYfhMxQ2X65jNPGJIRnAToAp5Q=; b=dHkJer8x+34Ia4NXWBlZQ3eUgzt9I5a67xnqeRqAwK3Uv/d1FLCaTkgI24NNTZ/ghi EHI6thKvSepIvt6mZmsQ9aWEiU0E4B390zWrMrPEh253P1b2Io+0IKUsG4foMYTzPew8 Mi0tCkzRbcMIasfv+04uB05ieHUs93/Ncw6PxRjbK+iQf4BS6gH7BK21KBNAvxMwT4/V 7iLL7zcUOEAEf7ctbIsJojAJ6pGB02+OeDiGKJp2qRQmXDIz1HJxZrUNqAv/jyovTdv4 BLiUawZqciKBW56zIb7jyvHl4BFODZPf9KZSjlMGB0NgFRVQN50tWagV7tIJhYF9e7yg hBrA== X-Gm-Message-State: APf1xPAISMGL/NoFDMKpEDlfcfQzMKwHHvdpfT5nhlRe1YlEaNONL3BC tgKRxfU6pmehfuk95hanp/2yklQ= X-Google-Smtp-Source: AH8x227GFVAUUKOHCcbv8/Sh1tt/iWOeiaPYj39BCw0xiFTbBfjg6MOAHByR9QSxzdRxIph0hERYfw== X-Received: by 10.223.134.236 with SMTP id 41mr10748599wry.87.1518476949309; Mon, 12 Feb 2018 15:09:09 -0800 (PST) Received: from elche.localdomain (79-66-214-20.dynamic.dsl.as9105.com. [79.66.214.20]) by smtp.googlemail.com with ESMTPSA id z73sm16285673wrb.50.2018.02.12.15.09.07 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 12 Feb 2018 15:09:08 -0800 (PST) From: Tiago Lam To: dev@openvswitch.org Date: Mon, 12 Feb 2018 23:08:28 +0000 Message-Id: <20180212230829.31624-6-tiagolam@gmail.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180212230829.31624-1-tiagolam@gmail.com> References: <20180212230829.31624-1-tiagolam@gmail.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [RFC PATCH v2 5/6] Conntrack: Add SIP end-to-end and unit tests. 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 End-to-end tests have been added to system-traffic.at. They set up a NS1 that acts as a UAS and another NS2 that acts as a UAC, set up the appropriate flows in each direction and finally verify if the traffic between the two NS' is as expected. These tests make use of the SIPp tool and the scenarios needed by SIPp have been added to the new sipp/ folder under tests/. Unit tests have also been added to test-sip.c, and are being called from conntrack-sip.at. These tests call functions like sip_parse_sdp, sip_parse_strt_line and sip_parse_tcp, passing both valid and invalid inputs, then comparing with the expected results. This includes tests for validating the supported TCP framing. Signed-off-by: Tiago Lam --- tests/atlocal.in | 3 + tests/automake.mk | 8 + tests/conntrack-sip.at | 7 + tests/sipp/uac_happy_case_scenario.xml | 126 +++++++++++++ tests/sipp/uas_happy_case_scenario.xml | 125 +++++++++++++ tests/system-traffic.at | 71 +++++++ tests/test-sip.c | 327 +++++++++++++++++++++++++++++++++ tests/testsuite.at | 1 + 8 files changed, 668 insertions(+) create mode 100644 tests/conntrack-sip.at create mode 100644 tests/sipp/uac_happy_case_scenario.xml create mode 100644 tests/sipp/uas_happy_case_scenario.xml create mode 100644 tests/test-sip.c diff --git a/tests/atlocal.in b/tests/atlocal.in index 55f9333ee..023337b5c 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -168,6 +168,9 @@ fi # Set HAVE_TCPDUMP find_command tcpdump +# Set HAVE_SIPP +find_command sipp + CURL_OPT="-g -v --max-time 1 --retry 2 --retry-delay 1 --connect-timeout 1" # Turn off proxies. diff --git a/tests/automake.mk b/tests/automake.mk index 18698ebc3..fc2efe255 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -94,6 +94,7 @@ TESTSUITE_AT = \ tests/vlog.at \ tests/vtep-ctl.at \ tests/auto-attach.at \ + tests/conntrack-sip.at \ tests/ovn.at \ tests/ovn-northd.at \ tests/ovn-nbctl.at \ @@ -335,6 +336,7 @@ tests_ovstest_SOURCES = \ tests/test-ccmap.c \ tests/test-cmap.c \ tests/test-conntrack.c \ + tests/test-sip.c \ tests/test-csum.c \ tests/test-flows.c \ tests/test-hash.c \ @@ -405,6 +407,11 @@ PYCOV_CLEAN_FILES += $(CHECK_PYFILES:.py=.py,cover) .coverage FLAKE8_PYFILES += $(CHECK_PYFILES) +# SIPP scenarios +EXTRA_DIST += \ + tests/sipp/uac_happy_case_scenario.xml \ + tests/sipp/uas_happy_case_scenario.xml + if HAVE_OPENSSL TESTPKI_FILES = \ tests/testpki-cacert.pem \ @@ -446,4 +453,5 @@ CLEAN_LOCAL += clean-pki clean-pki: rm -f tests/pki/stamp rm -rf tests/pki + endif diff --git a/tests/conntrack-sip.at b/tests/conntrack-sip.at new file mode 100644 index 000000000..17eff915c --- /dev/null +++ b/tests/conntrack-sip.at @@ -0,0 +1,7 @@ +AT_BANNER([conntrack-sip unit tests]) + +AT_SETUP([conntrack-sip]) +AT_KEYWORDS([conntrack-sip]) +AT_CHECK(ovstest test-sip, [], [ignore], [ignore]) + +AT_CLEANUP diff --git a/tests/sipp/uac_happy_case_scenario.xml b/tests/sipp/uac_happy_case_scenario.xml new file mode 100644 index 000000000..ee728dfc1 --- /dev/null +++ b/tests/sipp/uac_happy_case_scenario.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: sut + Call-ID: [call_id] + CSeq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[media_ip_type] [media_ip] + t=0 0 + m=audio [rtpstream_audio_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + + ]]> + + + + + + + + + + + + + + + + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 1 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 2 BYE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + + + + diff --git a/tests/sipp/uas_happy_case_scenario.xml b/tests/sipp/uas_happy_case_scenario.xml new file mode 100644 index 000000000..beb2110c2 --- /dev/null +++ b/tests/sipp/uas_happy_case_scenario.xml @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[media_ip_type] [media_ip] + t=0 0 + m=audio [rtpstream_audio_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + + ]]> + + + + + + + + + + + + + + + + + + + + + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + diff --git a/tests/system-traffic.at b/tests/system-traffic.at index dbd56405d..e8dba721a 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -2870,6 +2870,77 @@ udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=,dport=),reply=(src= OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP +dnl Setups two namespaces, at_ns0 and at_ns1, connected to a bridge, br0, and +dnl runs sipp in both in the following form: +dnl - at_ns0 loads an UAS scenario and waits for requests; +dnl - at_ns1 loads an UAC scenario, which will connect to at_ns0. +dnl +dnl Aside from RTP (which is over UDP), this tests sends SIP over TCP over +dnl IPv4 and no NAT is performed. +AT_SETUP([conntrack - SIP over TCP over IPv4]) +AT_SKIP_IF([test $HAVE_SIPP = no]) +CHECK_CONNTRACK() +CHECK_CONNTRACK_ALG() + +OVS_TRAFFIC_VSWITCHD_START() + +ADD_NAMESPACES(at_ns0, at_ns1) + +ADD_VETH(p0, at_ns0, br0, "10.0.1.10/24") +NS_CHECK_EXEC([at_ns0], [ip link set dev p0 address 00:00:00:00:01:10]) +ADD_VETH(p1, at_ns1, br0, "10.0.2.10/24") +NS_CHECK_EXEC([at_ns1], [ip link set dev p1 address 00:00:00:00:02:10]) +NS_CHECK_EXEC([at_ns0], [ip route add 10.0.2.0/24 via 10.0.1.10 dev p0]) +NS_CHECK_EXEC([at_ns1], [ip route add 10.0.1.0/24 via 10.0.2.10 dev p1]) + +dnl Allow any traffic from at_ns1->at_ns0. +dnl Only allow return traffic from at_ns0->at_ns1 (and arp, icmp). +AT_DATA([flows.txt], [dnl +dnl Track all IPv4 traffic +table=0,priority=1,action=drop +table=0,priority=10,arp,action=normal +table=0,priority=10,icmp,action=normal +table=0,priority=100,in_port=2,tcp,action=ct(alg=sip,commit),1 +table=0,priority=100,in_port=1,tcp,action=ct(table=1) +table=0,priority=100,in_port=2,udp,action=ct(table=2) +table=0,priority=100,in_port=1,udp,action=ct(table=2) +dnl +dnl Table 1 +dnl +dnl Allow new TCPv4 TCP connections. +table=1,in_port=1,tcp,ct_state=+trk+est,action=2 +table=1,in_port=1,tcp,ct_state=+trk+rel,action=2 +dnl +dnl Table 2 +dnl +dnl Allow RTP (UDP) connections through. +table=2,in_port=1,udp,ct_state=+rel,action=2 +table=2,in_port=2,udp,ct_state=+rel,action=1 +]) + +AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt]) + +NETNS_DAEMONIZE([at_ns0], [sipp -t t1 -mi 10.0.1.10 -m 1 -d 20000 -sf $srcdir/sipp/uas_happy_case_scenario.xml], [sipp_uas.pid]) +OVS_WAIT_UNTIL([ip netns exec at_ns0 netstat -l | grep sip]) + +dnl Traffic between at_ns1<->at_ns0 should now start flowing. +NS_CHECK_EXEC([at_ns1], [sipp 10.0.1.10 -t t1 -rp 1s -m 1 -d 30000 -mi 10.0.2.10 -sf $srcdir/sipp/uac_happy_case_scenario.xml +], [0], [stdout], [stderr]) + +dnl Wait until uas in at_ns0 is done processing all calls +dnl sipp in at_ns1 (running as uac) is finished with the calls, and sipp in +dnl at_ns0 (running as uas) should be finished as well. If not, then something +dnl is not right and the test should fail. +OVS_WAIT_WHILE([ip netns exec at_ns0 netstat -l | grep sip]) + +dnl Discards CLOSE_WAIT and CLOSING +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.0.1.10)], [0], [dnl +tcp,orig=(src=10.0.2.10,dst=10.0.1.10,sport=,dport=),reply=(src=10.0.1.10,dst=10.0.2.10,sport=,dport=),protoinfo=(state=),helper=sip +]) + +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP + AT_BANNER([conntrack - NAT]) AT_SETUP([conntrack - simple SNAT]) diff --git a/tests/test-sip.c b/tests/test-sip.c new file mode 100644 index 000000000..602f52671 --- /dev/null +++ b/tests/test-sip.c @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2017 Avaya, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#undef NDEBUG +#include +#include +#include +#include +#include "ovstest.h" +#include "openvswitch/ofp-actions.h" +#include "conntrack-sip.h" + +/* Count of tests run */ +static int num_tests = 0; + +static const struct eth_addr DUMMY_ETH_ADDR = ETH_ADDR_C(00,00,00,00,00,01); +static const ovs_be32 DUMMY_IP_ADDR = 0x0a00020a; + +static char *valid_sdp = + "v=0\r\n" + "o=user1 53655765 2353687637 IN IP4 10.0.2.10\r\n" + "s=-\r\n" + "c=IN IP4 10.0.2.10\r\n" + "t=0 0\r\n" + "m=audio 8192 RTP/AVP 0\r\n" + "a=rtpmap:0 PCMU/8000\r\n"; + +static char *invalid_sdp = "invalid sdp"; + +static char *sip_invite = + "INVITE sip:service@10.0.1.10:5060 SIP/2.0\r\n" + "Via: SIP/2.0/TCP 10.0.2.10:5060;branch=z9hG4bK-26201-1-0\r\n" + "From: sipp ;tag=26201SIPpTag001\r\n" + "To: sut \r\n" + "Call-ID: 1-26201@10.0.2.10\r\n" + "CSeq: 1 INVITE\r\n" + "Contact: sip:sipp@10.0.2.10:5060\r\n" + "Max-Forwards: 70\r\n" + "Content-Length: 0\r\n" + "\r\n"; + +static char *sip_invite_with_sdp = + "INVITE sip:service@10.0.1.10:5060 SIP/2.0\r\n" + "Via: SIP/2.0/TCP 10.0.2.10:5060;branch=z9hG4bK-26201-1-0\r\n" + "From: sipp ;tag=26201SIPpTag001\r\n" + "To: sut \r\n" + "Call-ID: 1-26201@10.0.2.10\r\n" + "CSeq: 1 INVITE\r\n" + "Contact: sip:sipp@10.0.2.10:5060\r\n" + "Max-Forwards: 70\r\n" + "Content-Type: application/sdp\r\n" + "Content-Length: 129\r\n" + "\r\n"; + +static char *sip_invite_missing_cr = + "INVITE sip:service@10.0.1.10:5060 SIP/2.0\r\n" + "Via: SIP/2.0/TCP 10.0.2.10:5060;branch=z9hG4bK-26201-1-0\r\n" + "From: sipp ;tag=26201SIPpTag001\r\n" + "To: sut \n" + "Call-ID: 1-26201@10.0.2.10\r\n" + "CSeq: 1 INVITE\r\n" + "Contact: sip:sipp@10.0.2.10:5060\r\n" + "Max-Forwards: 70\n" + "Content-Length: 0\r\n" + "\r\n"; + +static void +test_valid_sdp(void) +{ + struct sip_sdp *sdp; + sdp = sip_parse_sdp(valid_sdp, strlen(valid_sdp)); + + ovs_assert(sdp != NULL); + ovs_assert(sdp->orig == 0x0a02000a); + ovs_assert(sdp->conn == 0x0a02000a); + ovs_assert(sdp->port == 0x2000); + + free(sdp); +} + +static void +test_invalid_sdp(void) +{ + struct sip_sdp *sdp; + sdp = sip_parse_sdp(invalid_sdp, strlen(invalid_sdp)); + + ovs_assert(sdp == NULL); + + free(sdp); +} + +static void +test_parse_strt_ln(void) +{ + struct sip_strt_ln *strt_ln; + strt_ln = sip_parse_strt_ln(sip_invite, strlen(sip_invite)); + + ovs_assert(strt_ln != NULL); + + ovs_assert(strt_ln->type == REQUEST_LINE); + ovs_assert(strt_ln->reqs_ln->mthd == INVITE); +} + +static void +test_parse_strt_ln_missing_cr(void) +{ + struct sip_strt_ln *strt_ln; + strt_ln = sip_parse_strt_ln(sip_invite_missing_cr, + strlen(sip_invite_missing_cr)); + + ovs_assert(strt_ln != NULL); + + ovs_assert(strt_ln->type == REQUEST_LINE); + ovs_assert(strt_ln->reqs_ln->mthd == INVITE); +} + +static void * +compose_dummy_ipv4(struct dp_packet *packet, uint8_t proto, + ovs_be32 ipv4_src, ovs_be32 ipv4_dst, + uint8_t tos, uint8_t ttl, int proto_hdr_len, + int proto_len) +{ + struct ip_header *l3_hdr; + void *data; + + l3_hdr = dp_packet_l3(packet); + l3_hdr->ip_proto = proto; + l3_hdr->ip_ihl_ver = IP_HEADER_LEN / 4; + l3_hdr->ip_tot_len = htons(IP_HEADER_LEN + proto_hdr_len + proto_len); + packet_set_ipv4(packet, ipv4_src, ipv4_dst, tos, ttl); + data = dp_packet_put_zeros(packet, proto_hdr_len); + dp_packet_set_l4(packet, data); + return data; +} + +static void * +compose_dummy_tcp(struct dp_packet *pkt, const struct eth_addr eth_src, + const struct eth_addr eth_dst, ovs_be32 ipv4_src, + ovs_be32 ipv4_dst, ovs_be16 port_src, ovs_be16 port_dst, + int size) +{ + struct tcp_header *th; + + eth_compose(pkt, eth_dst, eth_src, ETH_TYPE_IP, IP_HEADER_LEN); + th = compose_dummy_ipv4(pkt, IPPROTO_TCP, ipv4_src, ipv4_dst, 0, 1, + TCP_HEADER_LEN, size); + + packet_set_tcp_port(pkt, port_src, port_dst); + th->tcp_ctl = htons((TCP_HEADER_LEN / 4) << 12); + + return th + TCP_HEADER_LEN; +} + +/* Test sip_parse_tcp function against multiple cases, including: + * - A single TCP packet transporting a single SIP message; + * - A single TCP packet transporting multiple SIP messages; + * - A SIP message being carried across multiple TCP packets, i.e., a first + * TCP packet arrives transporting an incomplete SIP message, followed by + * another TCP packet wich carries the rest of the SIP message. */ + +static void +test_handle_single_tcp_single_sip(void) +{ + uint32_t stub[128 / 4]; + struct dp_packet packet; + + dp_packet_use_stub(&packet, stub, sizeof stub); + dp_packet_clear(&packet); + + compose_dummy_tcp(&packet, DUMMY_ETH_ADDR, DUMMY_ETH_ADDR, + htonl(DUMMY_IP_ADDR),htonl(DUMMY_IP_ADDR), + htons(IPPORT_SIP), htons(IPPORT_SIP), + strlen(sip_invite_with_sdp) + strlen(valid_sdp)); + /* Compose an SIP message. */ + dp_packet_put(&packet, sip_invite_with_sdp, strlen(sip_invite_with_sdp)); + dp_packet_put(&packet, valid_sdp, strlen(valid_sdp)); + + struct ip_header *l3_hdr = dp_packet_l3(&packet); + struct tcp_header *th = dp_packet_l4(&packet); + size_t tcp_hdr_len = TCP_OFFSET(th->tcp_ctl) * 4; + size_t ip_hdr_len = (IP_IHL(l3_hdr->ip_ihl_ver) * 4); + size_t tcp_len = ntohs(l3_hdr->ip_tot_len) - ip_hdr_len - tcp_hdr_len; + /* Move to beginning of TCP payload, where the SIP payload is */ + char *sip = ((char *) th) + tcp_hdr_len; + size_t sip_len = tcp_len; + struct ovs_list *out_msgs = NULL; + + out_msgs = sip_parse_tcp(sip, sip_len); + + ovs_assert(ovs_list_size(out_msgs) == 1); + + struct sip_msg *out_msg; + struct sip_msg *next; + LIST_FOR_EACH_SAFE (out_msg, next, node, out_msgs) { + struct sip_strt_ln *strt_ln = out_msg->strt_ln; + sip_len = out_msg->bdy_len; + + ovs_assert(strt_ln != NULL); + ovs_assert(strt_ln->type == REQUEST_LINE); + ovs_assert(strt_ln->reqs_ln->mthd == INVITE); + ovs_assert(sip_len == strlen(valid_sdp)); + + free_sip_msg(out_msg); + } + free(out_msgs); + dp_packet_uninit(&packet); +} + +static void +test_handle_single_tcp_multiple_sip(void) +{ + uint32_t stub[128 / 4]; + struct dp_packet packet; + + dp_packet_use_stub(&packet, stub, sizeof stub); + dp_packet_clear(&packet); + + compose_dummy_tcp(&packet, DUMMY_ETH_ADDR, DUMMY_ETH_ADDR, + htonl(DUMMY_IP_ADDR),htonl(DUMMY_IP_ADDR), + htons(IPPORT_SIP), htons(IPPORT_SIP), + 2 * (strlen(sip_invite_with_sdp) + strlen(valid_sdp))); + /* Insert a first SIP message */ + dp_packet_put(&packet, sip_invite_with_sdp, strlen(sip_invite_with_sdp)); + dp_packet_put(&packet, valid_sdp, strlen(valid_sdp)); + /* Insert a second SIP message */ + dp_packet_put(&packet, sip_invite_with_sdp, strlen(sip_invite_with_sdp)); + dp_packet_put(&packet, valid_sdp, strlen(valid_sdp)); + + struct ip_header *l3_hdr = dp_packet_l3(&packet); + struct tcp_header *th = dp_packet_l4(&packet); + size_t tcp_hdr_len = TCP_OFFSET(th->tcp_ctl) * 4; + size_t ip_hdr_len = (IP_IHL(l3_hdr->ip_ihl_ver) * 4); + size_t tcp_len = ntohs(l3_hdr->ip_tot_len) - ip_hdr_len - tcp_hdr_len; + /* Move to beginning of TCP payload, where the SIP payload is */ + char *sip = ((char *) th) + tcp_hdr_len; + size_t sip_len = tcp_len; + struct ovs_list *out_msgs = NULL; + + out_msgs = sip_parse_tcp(sip, sip_len); + + ovs_assert(ovs_list_size(out_msgs) == 2); + + struct sip_msg *out_msg; + struct sip_msg *next; + LIST_FOR_EACH_SAFE (out_msg, next, node, out_msgs) { + struct sip_strt_ln *strt_ln = out_msg->strt_ln; + sip_len = out_msg->bdy_len; + + ovs_assert(strt_ln != NULL); + ovs_assert(strt_ln->type == REQUEST_LINE); + ovs_assert(strt_ln->reqs_ln->mthd == INVITE); + ovs_assert(sip_len == strlen(valid_sdp)); + free_sip_msg(out_msg); + } + free(out_msgs); + dp_packet_uninit(&packet); +} + +static void +test_handle_single_tcp_incomplete_sip(void) +{ + uint32_t stub[128 / 4]; + struct dp_packet packet; + + dp_packet_use_stub(&packet, stub, sizeof stub); + dp_packet_clear(&packet); + + compose_dummy_tcp(&packet, DUMMY_ETH_ADDR, DUMMY_ETH_ADDR, + htonl(DUMMY_IP_ADDR),htonl(DUMMY_IP_ADDR), + htons(IPPORT_SIP), htons(IPPORT_SIP), + strlen(sip_invite_with_sdp)); + dp_packet_put(&packet, sip_invite_with_sdp, strlen(sip_invite_with_sdp)); + + struct ip_header *l3_hdr = dp_packet_l3(&packet); + struct tcp_header *th = dp_packet_l4(&packet); + size_t tcp_hdr_len = TCP_OFFSET(th->tcp_ctl) * 4; + size_t ip_hdr_len = (IP_IHL(l3_hdr->ip_ihl_ver) * 4); + size_t tcp_len = ntohs(l3_hdr->ip_tot_len) - ip_hdr_len - tcp_hdr_len; + /* Move to beginning of TCP payload, where the SIP payload is */ + char *sip = ((char *) th) + tcp_hdr_len; + size_t sip_len = tcp_len; + struct ovs_list *out_msgs = NULL; + + out_msgs = sip_parse_tcp(sip, sip_len); + + ovs_assert(ovs_list_size(out_msgs) == 0); + + free(out_msgs); + dp_packet_uninit(&packet); +} + +static void +run_test(void (*function)(void)) +{ + function(); + num_tests++; + printf("."); +} + +static void +test_sip_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) +{ + run_test(test_valid_sdp); + run_test(test_invalid_sdp); + run_test(test_parse_strt_ln); + run_test(test_parse_strt_ln_missing_cr); + run_test(test_handle_single_tcp_single_sip); + run_test(test_handle_single_tcp_multiple_sip); + run_test(test_handle_single_tcp_incomplete_sip); + + printf("executed %d tests\n", num_tests); +} +OVSTEST_REGISTER("test-sip", test_sip_main); diff --git a/tests/testsuite.at b/tests/testsuite.at index 15c385e2c..05297e7a7 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -71,6 +71,7 @@ m4_include([tests/rstp.at]) m4_include([tests/vlog.at]) m4_include([tests/vtep-ctl.at]) m4_include([tests/auto-attach.at]) +m4_include([tests/conntrack-sip.at]) m4_include([tests/ovn.at]) m4_include([tests/ovn-northd.at]) m4_include([tests/ovn-nbctl.at])