Initial test suite for osmo-pcap-client
Change-Id: If4a1072e75cb64f785d660e4c828c0f521d84b16
This commit is contained in:
parent
79ed4b1685
commit
c4ac9e0fe3
1
Makefile
1
Makefile
|
@ -28,6 +28,7 @@ SUBDIRS= \
|
||||||
mme \
|
mme \
|
||||||
msc \
|
msc \
|
||||||
ns \
|
ns \
|
||||||
|
pcap-client \
|
||||||
pcu \
|
pcu \
|
||||||
pgw \
|
pgw \
|
||||||
remsim \
|
remsim \
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
module OPCAP_Adapter {
|
||||||
|
|
||||||
|
/* OPCAP Adapter layer, sitting on top of OPCAP_CodecPort.
|
||||||
|
* test suites can 'inherit' in order to have a OPCAP connection to the IUT which they're testing
|
||||||
|
*
|
||||||
|
* (C) 2021 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Released under the terms of GNU General Public License, Version 2 or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import from Osmocom_Types all;
|
||||||
|
import from General_Types all;
|
||||||
|
import from OPCAP_Types all;
|
||||||
|
import from OPCAP_Templates all;
|
||||||
|
import from OPCAP_CodecPort all;
|
||||||
|
import from OPCAP_CodecPort_CtrlFunct all;
|
||||||
|
import from IPL4asp_Types all;
|
||||||
|
import from IPL4asp_PortType all;
|
||||||
|
import from Socket_API_Definitions all;
|
||||||
|
|
||||||
|
const integer NUM_OPCAP := 3;
|
||||||
|
|
||||||
|
type component OPCAP_Adapter_CT {
|
||||||
|
/* down-facing port to OPCAP Codec port */
|
||||||
|
port OPCAP_CODEC_PT OPCAP[NUM_OPCAP];
|
||||||
|
var IPL4asp_Types.ConnectionId g_opcap_conn_id[NUM_OPCAP] := { -1, -1, -1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
private function f_set_tcp_segmentation(integer idx) runs on OPCAP_Adapter_CT {
|
||||||
|
/* Set function for dissecting the binary stream into packets */
|
||||||
|
var f_IPL4_getMsgLen vl_f := refers(f_IPL4_fixedMsgLen);
|
||||||
|
/* Offset: 2, size of length: 2, delta: 4, multiplier: 1, big-endian */
|
||||||
|
OPCAP_CodecPort_CtrlFunct.f_IPL4_setGetMsgLen(OPCAP[idx], g_opcap_conn_id[idx], vl_f, {2, 2, 4, 1, 0});
|
||||||
|
}
|
||||||
|
|
||||||
|
function f_connect(charstring remote_host, IPL4asp_Types.PortNumber remote_port,
|
||||||
|
charstring local_host, IPL4asp_Types.PortNumber local_port, integer idx := 0)
|
||||||
|
runs on OPCAP_Adapter_CT {
|
||||||
|
var IPL4asp_Types.Result res;
|
||||||
|
map(self:OPCAP[idx], system:OPCAP);
|
||||||
|
if (g_opcap_conn_id[idx] != -1) {
|
||||||
|
OPCAP_CodecPort_CtrlFunct.f_IPL4_close(OPCAP[idx], g_opcap_conn_id[idx], {tcp := {}});
|
||||||
|
g_opcap_conn_id[idx] := -1;
|
||||||
|
}
|
||||||
|
res := OPCAP_CodecPort_CtrlFunct.f_IPL4_connect(OPCAP[idx], remote_host, remote_port,
|
||||||
|
local_host, local_port, 0, { tcp :={} });
|
||||||
|
if (not ispresent(res.connId)) {
|
||||||
|
setverdict(fail, "Could not connect to OPCAP port, check your configuration ",
|
||||||
|
"{remote ", remote_host, ":", remote_port, " local ", local_host, ":", local_port, "}");
|
||||||
|
mtc.stop;
|
||||||
|
}
|
||||||
|
g_opcap_conn_id[idx] := res.connId;
|
||||||
|
|
||||||
|
f_set_tcp_segmentation(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function to use to bind to a local port as IPA server, accepting remote clients */
|
||||||
|
function f_bind(charstring local_host, IPL4asp_Types.PortNumber local_port, integer idx := 0)
|
||||||
|
runs on OPCAP_Adapter_CT {
|
||||||
|
var IPL4asp_Types.Result res;
|
||||||
|
map(self:OPCAP[idx], system:OPCAP);
|
||||||
|
if (g_opcap_conn_id[idx] != -1) {
|
||||||
|
OPCAP_CodecPort_CtrlFunct.f_IPL4_close(OPCAP[idx], g_opcap_conn_id[idx], {tcp := {}});
|
||||||
|
g_opcap_conn_id[idx] := -1;
|
||||||
|
}
|
||||||
|
res := OPCAP_CodecPort_CtrlFunct.f_IPL4_listen(OPCAP[idx], local_host, local_port, { tcp:={} });
|
||||||
|
if (not ispresent(res.connId)) {
|
||||||
|
setverdict(fail, "Could not bind to OPCAP port, check your configuration ",
|
||||||
|
"{local ", local_host, ":", local_port, "}");
|
||||||
|
mtc.stop;
|
||||||
|
}
|
||||||
|
g_opcap_conn_id[idx] := res.connId;
|
||||||
|
|
||||||
|
f_set_tcp_segmentation(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f_wait_client_connect(integer idx) runs on OPCAP_Adapter_CT {
|
||||||
|
var IPL4asp_Types.PortEvent rx_event;
|
||||||
|
OPCAP[idx].receive(IPL4asp_Types.PortEvent:{connOpened:=?}) -> value rx_event {
|
||||||
|
log("Connection from ", rx_event.connOpened.remName, ":", rx_event.connOpened.remPort);
|
||||||
|
/* we want to store the client's connId, not the 'bind socket' one */
|
||||||
|
g_opcap_conn_id[idx] := rx_event.connOpened.connId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function f_disconnect(integer idx) runs on OPCAP_Adapter_CT {
|
||||||
|
OPCAP_CodecPort_CtrlFunct.f_IPL4_close(OPCAP[idx], g_opcap_conn_id[idx], {tcp := {}});
|
||||||
|
OPCAP[idx].clear;
|
||||||
|
};
|
||||||
|
|
||||||
|
function f_opcap_send(template (value) OPCAP_PDU pdu, integer idx := 0) runs on OPCAP_Adapter_CT {
|
||||||
|
OPCAP[idx].send(ts_OPCAP_Send(g_opcap_conn_id[idx], pdu));
|
||||||
|
}
|
||||||
|
|
||||||
|
function f_opcap_exp(template OPCAP_PDU exp, integer idx := 0) runs on OPCAP_Adapter_CT return OPCAP_PDU {
|
||||||
|
var OPCAP_RecvFrom rf;
|
||||||
|
OPCAP[idx].receive(tr_OPCAP_Recv(g_opcap_conn_id[idx], exp)) -> value rf;
|
||||||
|
return rf.msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
module OPCAP_CodecPort {
|
||||||
|
|
||||||
|
/* Simple OPCAP Codec Port, translating between raw TCP octetstring payload
|
||||||
|
* towards the IPL4asp port provider, and OPCAP primitives
|
||||||
|
* which carry the decoded OPCAP data types as payload.
|
||||||
|
*
|
||||||
|
* (C) 2021 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Released under the terms of GNU General Public License, Version 2 or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import from IPL4asp_PortType all;
|
||||||
|
import from IPL4asp_Types all;
|
||||||
|
import from OPCAP_Types all;
|
||||||
|
|
||||||
|
type record OPCAP_RecvFrom {
|
||||||
|
ConnectionId connId,
|
||||||
|
OPCAP_PDU msg
|
||||||
|
}
|
||||||
|
|
||||||
|
type record OPCAP_Send {
|
||||||
|
ConnectionId connId,
|
||||||
|
OPCAP_PDU msg
|
||||||
|
}
|
||||||
|
|
||||||
|
template (value) OPCAP_Send ts_OPCAP_Send(ConnectionId conn_id, template (value) OPCAP_PDU msg) := {
|
||||||
|
connId := conn_id,
|
||||||
|
msg := msg
|
||||||
|
}
|
||||||
|
|
||||||
|
template OPCAP_RecvFrom tr_OPCAP_Recv(template ConnectionId conn_id, template OPCAP_PDU msg) := {
|
||||||
|
connId := conn_id,
|
||||||
|
msg := msg
|
||||||
|
}
|
||||||
|
|
||||||
|
private function IPL4_to_OPCAP_RecvFrom(in ASP_RecvFrom pin, out OPCAP_RecvFrom pout) {
|
||||||
|
pout.connId := pin.connId;
|
||||||
|
pout.msg := dec_OPCAP_PDU(pin.msg);
|
||||||
|
} with { extension "prototype(fast)" }
|
||||||
|
|
||||||
|
private function OPCAP_to_IPL4_Send(in OPCAP_Send pin, out ASP_Send pout) {
|
||||||
|
pout.connId := pin.connId;
|
||||||
|
pout.proto := { tcp := {} };
|
||||||
|
pout.msg := enc_OPCAP_PDU(pin.msg);
|
||||||
|
} with { extension "prototype(fast)" }
|
||||||
|
|
||||||
|
type port OPCAP_CODEC_PT message {
|
||||||
|
out OPCAP_Send;
|
||||||
|
in OPCAP_RecvFrom,
|
||||||
|
ASP_ConnId_ReadyToRelease,
|
||||||
|
ASP_Event;
|
||||||
|
} with { extension "user IPL4asp_PT
|
||||||
|
out(OPCAP_Send -> ASP_Send: function(OPCAP_to_IPL4_Send))
|
||||||
|
in(ASP_RecvFrom -> OPCAP_RecvFrom: function(IPL4_to_OPCAP_RecvFrom);
|
||||||
|
ASP_ConnId_ReadyToRelease -> ASP_ConnId_ReadyToRelease: simple;
|
||||||
|
ASP_Event -> ASP_Event: simple)"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
module OPCAP_CodecPort_CtrlFunct {
|
||||||
|
|
||||||
|
import from OPCAP_CodecPort all;
|
||||||
|
import from IPL4asp_Types all;
|
||||||
|
|
||||||
|
external function f_IPL4_listen(
|
||||||
|
inout OPCAP_CODEC_PT portRef,
|
||||||
|
in HostName locName,
|
||||||
|
in PortNumber locPort,
|
||||||
|
in ProtoTuple proto,
|
||||||
|
in OptionList options := {}
|
||||||
|
) return Result;
|
||||||
|
|
||||||
|
external function f_IPL4_connect(
|
||||||
|
inout OPCAP_CODEC_PT portRef,
|
||||||
|
in HostName remName,
|
||||||
|
in PortNumber remPort,
|
||||||
|
in HostName locName,
|
||||||
|
in PortNumber locPort,
|
||||||
|
in ConnectionId connId,
|
||||||
|
in ProtoTuple proto,
|
||||||
|
in OptionList options := {}
|
||||||
|
) return Result;
|
||||||
|
|
||||||
|
external function f_IPL4_close(
|
||||||
|
inout OPCAP_CODEC_PT portRef,
|
||||||
|
in ConnectionId id,
|
||||||
|
in ProtoTuple proto := { unspecified := {} }
|
||||||
|
) return Result;
|
||||||
|
|
||||||
|
external function f_IPL4_setUserData(
|
||||||
|
inout OPCAP_CODEC_PT portRef,
|
||||||
|
in ConnectionId id,
|
||||||
|
in UserData userData
|
||||||
|
) return Result;
|
||||||
|
|
||||||
|
external function f_IPL4_getUserData(
|
||||||
|
inout OPCAP_CODEC_PT portRef,
|
||||||
|
in ConnectionId id,
|
||||||
|
out UserData userData
|
||||||
|
) return Result;
|
||||||
|
|
||||||
|
external function f_IPL4_setGetMsgLen(
|
||||||
|
inout OPCAP_CODEC_PT portRef,
|
||||||
|
in ConnectionId id,
|
||||||
|
inout f_IPL4_getMsgLen f,
|
||||||
|
in ro_integer msgLenArgs
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
#include "IPL4asp_PortType.hh"
|
||||||
|
#include "OPCAP_CodecPort.hh"
|
||||||
|
#include "IPL4asp_PT.hh"
|
||||||
|
|
||||||
|
namespace OPCAP__CodecPort__CtrlFunct {
|
||||||
|
|
||||||
|
IPL4asp__Types::Result f__IPL4__listen(
|
||||||
|
OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
|
||||||
|
const IPL4asp__Types::HostName& locName,
|
||||||
|
const IPL4asp__Types::PortNumber& locPort,
|
||||||
|
const IPL4asp__Types::ProtoTuple& proto,
|
||||||
|
const IPL4asp__Types::OptionList& options)
|
||||||
|
{
|
||||||
|
return f__IPL4__PROVIDER__listen(portRef, locName, locPort, proto, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPL4asp__Types::Result f__IPL4__connect(
|
||||||
|
OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
|
||||||
|
const IPL4asp__Types::HostName& remName,
|
||||||
|
const IPL4asp__Types::PortNumber& remPort,
|
||||||
|
const IPL4asp__Types::HostName& locName,
|
||||||
|
const IPL4asp__Types::PortNumber& locPort,
|
||||||
|
const IPL4asp__Types::ConnectionId& connId,
|
||||||
|
const IPL4asp__Types::ProtoTuple& proto,
|
||||||
|
const IPL4asp__Types::OptionList& options)
|
||||||
|
{
|
||||||
|
return f__IPL4__PROVIDER__connect(portRef, remName, remPort,
|
||||||
|
locName, locPort, connId, proto, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPL4asp__Types::Result f__IPL4__close(
|
||||||
|
OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
|
||||||
|
const IPL4asp__Types::ConnectionId& connId,
|
||||||
|
const IPL4asp__Types::ProtoTuple& proto)
|
||||||
|
{
|
||||||
|
return f__IPL4__PROVIDER__close(portRef, connId, proto);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPL4asp__Types::Result f__IPL4__setUserData(
|
||||||
|
OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
|
||||||
|
const IPL4asp__Types::ConnectionId& connId,
|
||||||
|
const IPL4asp__Types::UserData& userData)
|
||||||
|
{
|
||||||
|
return f__IPL4__PROVIDER__setUserData(portRef, connId, userData);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPL4asp__Types::Result f__IPL4__getUserData(
|
||||||
|
OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
|
||||||
|
const IPL4asp__Types::ConnectionId& connId,
|
||||||
|
IPL4asp__Types::UserData& userData)
|
||||||
|
{
|
||||||
|
return f__IPL4__PROVIDER__getUserData(portRef, connId, userData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void f__IPL4__setGetMsgLen(
|
||||||
|
OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
|
||||||
|
const IPL4asp__Types::ConnectionId& connId,
|
||||||
|
Socket__API__Definitions::f__getMsgLen& f,
|
||||||
|
const Socket__API__Definitions::ro__integer& msgLenArgs)
|
||||||
|
{
|
||||||
|
return f__IPL4__PROVIDER__setGetMsgLen(portRef, connId, f, msgLenArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
module OPCAP_Templates {
|
||||||
|
|
||||||
|
/* OPCAP_Templates, defining TTCN-3 templates for the osmo-pcap protocol.
|
||||||
|
*
|
||||||
|
* OPCAP is a non-standard protocol used between osmo-pcap-client and osmo-pcap-server.
|
||||||
|
*
|
||||||
|
* (C) 2021 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Released under the terms of GNU General Public License, Version 2 or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import from General_Types all;
|
||||||
|
import from Osmocom_Types all;
|
||||||
|
import from OPCAP_Types all;
|
||||||
|
|
||||||
|
|
||||||
|
template (present) OPCAP_PDU tr_OPCAP_FILE_HDR(template (present) uint32_t linktype := ?) := {
|
||||||
|
msg_type := PKT_LINK_HDR,
|
||||||
|
spare := ?,
|
||||||
|
len := 24,
|
||||||
|
u := {
|
||||||
|
file := {
|
||||||
|
magic := PCAP_MAGIC,
|
||||||
|
version_major := PCAP_VERSION_MAJOR,
|
||||||
|
version_minor := PCAP_VERSION_MINOR,
|
||||||
|
thiszone := 0,
|
||||||
|
sigfigs := 0,
|
||||||
|
snaplen := 9000,
|
||||||
|
linktype := linktype
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template (present) OPCAP_PDU tr_OPCAP_PKT(template (present) octetstring payload,
|
||||||
|
template (present) uint32_t caplen := ?,
|
||||||
|
template (present) uint32_t len := ?) := {
|
||||||
|
msg_type := PKT_LINK_DATA,
|
||||||
|
spare := ?,
|
||||||
|
len := ?,
|
||||||
|
u := {
|
||||||
|
packet := {
|
||||||
|
ts_sec := ?,
|
||||||
|
ts_usec := ?,
|
||||||
|
caplen := caplen,
|
||||||
|
len := len,
|
||||||
|
payload := payload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,78 @@
|
||||||
|
module OPCAP_Types {
|
||||||
|
|
||||||
|
/* OPCAP_Types, defining abstract TTCN-3 data types for the osmo-pcap protocol.
|
||||||
|
*
|
||||||
|
* OPCAP is a non-standard protocol used between osmo-pcap-client and osmo-pcap-server.
|
||||||
|
*
|
||||||
|
* (C) 2021 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Released under the terms of GNU General Public License, Version 2 or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import from General_Types all;
|
||||||
|
import from Osmocom_Types all;
|
||||||
|
|
||||||
|
type enumerated OpcapMsgType {
|
||||||
|
PKT_LINK_HDR (0),
|
||||||
|
PKT_LINK_DATA (1)
|
||||||
|
} with { variant "FIELDLENGTH(8)" };
|
||||||
|
|
||||||
|
type record OPCAP_PDU {
|
||||||
|
OpcapMsgType msg_type,
|
||||||
|
uint8_t spare,
|
||||||
|
uint16_t len,
|
||||||
|
OpcapBodyUnion u
|
||||||
|
} with {
|
||||||
|
variant (len) "LENGTHTO(u)"
|
||||||
|
variant (len) "BYTEORDER(last)"
|
||||||
|
variant (u) "CROSSTAG(
|
||||||
|
file, msg_type = PKT_LINK_HDR;
|
||||||
|
packet, msg_type = PKT_LINK_DATA;
|
||||||
|
)"
|
||||||
|
};
|
||||||
|
|
||||||
|
type union OpcapBodyUnion {
|
||||||
|
PcapFileHeader file,
|
||||||
|
OpcapPacket packet
|
||||||
|
};
|
||||||
|
|
||||||
|
/* header in front of a PKT_LINK_DATA */
|
||||||
|
type record OpcapPacket {
|
||||||
|
uint32_t ts_sec,
|
||||||
|
uint32_t ts_usec,
|
||||||
|
uint32_t caplen,
|
||||||
|
uint32_t len,
|
||||||
|
octetstring payload
|
||||||
|
} with {
|
||||||
|
variant (caplen) "LENGTHTO(payload)"
|
||||||
|
};
|
||||||
|
|
||||||
|
/* below definitions are from pcap/pcap.h */
|
||||||
|
const uint16_t PCAP_VERSION_MAJOR := 2;
|
||||||
|
const uint16_t PCAP_VERSION_MINOR := 4;
|
||||||
|
const uint32_t PCAP_MAGIC := 2712847316; //0xA1B2C3D4;
|
||||||
|
|
||||||
|
type record PcapFileHeader {
|
||||||
|
uint32_t magic,
|
||||||
|
uint16_t version_major,
|
||||||
|
uint16_t version_minor,
|
||||||
|
uint32_t thiszone,
|
||||||
|
uint32_t sigfigs,
|
||||||
|
uint32_t snaplen,
|
||||||
|
uint32_t linktype
|
||||||
|
};
|
||||||
|
|
||||||
|
/* below definitions are from pcap/dlt.h */
|
||||||
|
const uint32_t DLT_LINUX_SLL := 113;
|
||||||
|
const uint32_t DLT_EN10MB := 1;
|
||||||
|
|
||||||
|
|
||||||
|
external function enc_OPCAP_PDU(in OPCAP_PDU msg) return octetstring
|
||||||
|
with { extension "prototype(convert) encode(RAW)" };
|
||||||
|
|
||||||
|
external function dec_OPCAP_PDU(in octetstring msg) return OPCAP_PDU
|
||||||
|
with { extension "prototype(convert) decode(RAW)" };
|
||||||
|
|
||||||
|
} with { encode "RAW"; variant "FIELDORDER(msb)"; variant "BYTEORDER(first)" };
|
|
@ -0,0 +1,18 @@
|
||||||
|
[ORDERED_INCLUDE]
|
||||||
|
# Common configuration, shared between test suites
|
||||||
|
"../Common.cfg"
|
||||||
|
# testsuite specific configuration, not expected to change
|
||||||
|
"./OPCAP_CLIENT_Tests.default"
|
||||||
|
|
||||||
|
# Local configuration below
|
||||||
|
|
||||||
|
[LOGGING]
|
||||||
|
|
||||||
|
[TESTPORT_PARAMETERS]
|
||||||
|
|
||||||
|
[MODULE_PARAMETERS]
|
||||||
|
|
||||||
|
[MAIN_CONTROLLER]
|
||||||
|
|
||||||
|
[EXECUTE]
|
||||||
|
OPCAP_CLIENT_Tests.control
|
|
@ -0,0 +1,19 @@
|
||||||
|
[LOGGING]
|
||||||
|
mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
|
||||||
|
|
||||||
|
[TESTPORT_PARAMETERS]
|
||||||
|
*.VTY.CTRL_MODE := "client"
|
||||||
|
*.VTY.CTRL_HOSTNAME := "127.0.0.1"
|
||||||
|
*.VTY.CTRL_PORTNUM := "4237"
|
||||||
|
*.VTY.CTRL_LOGIN_SKIPPED := "yes"
|
||||||
|
*.VTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
|
||||||
|
*.VTY.CTRL_READMODE := "buffered"
|
||||||
|
*.VTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
|
||||||
|
*.VTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
|
||||||
|
*.VTY.PROMPT1 := "OsmoPCAPClient> "
|
||||||
|
*.TCP.noDelay := "yes" // turn off nagle
|
||||||
|
|
||||||
|
[MODULE_PARAMETERS]
|
||||||
|
Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoPCAPClient"
|
||||||
|
|
||||||
|
[EXECUTE]
|
|
@ -0,0 +1,212 @@
|
||||||
|
module OPCAP_CLIENT_Tests {
|
||||||
|
|
||||||
|
import from OPCAP_Adapter all;
|
||||||
|
import from OPCAP_Types all;
|
||||||
|
import from OPCAP_Templates all;
|
||||||
|
|
||||||
|
import from IPL4asp_Types all;
|
||||||
|
import from IPL4asp_PortType all;
|
||||||
|
import from Osmocom_Types all;
|
||||||
|
import from Osmocom_VTY_Functions all;
|
||||||
|
import from TELNETasp_PortType all;
|
||||||
|
import from Socket_API_Definitions all;
|
||||||
|
|
||||||
|
type record IpPort {
|
||||||
|
charstring ip,
|
||||||
|
integer udp_port
|
||||||
|
};
|
||||||
|
|
||||||
|
modulepar {
|
||||||
|
/* local IP address listening for OPCAP connections */
|
||||||
|
charstring mp_local_opcap_ip := "127.0.0.1";
|
||||||
|
/* local TCP base port for inbound OPCAP connections */
|
||||||
|
integer mp_local_opcap_port := 5000;
|
||||||
|
|
||||||
|
/* IP + port for simulating user traffic */
|
||||||
|
IpPort mp_traffic_a := { "127.0.0.23", 44423 };
|
||||||
|
IpPort mp_traffic_b := { "127.0.0.42", 44442 };
|
||||||
|
};
|
||||||
|
|
||||||
|
type component test_CT extends OPCAP_Adapter_CT {
|
||||||
|
timer g_Tguard := 30.0;
|
||||||
|
|
||||||
|
port TELNETasp_PT VTY;
|
||||||
|
|
||||||
|
/* port to generate IP traffic that may or may not be captured */
|
||||||
|
port IPL4asp_PT IP;
|
||||||
|
var integer g_traffic_conn_id[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
private altstep as_Tguard() runs on test_CT {
|
||||||
|
[] g_Tguard.timeout {
|
||||||
|
setverdict(fail, "global guard timeout");
|
||||||
|
mtc.stop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize one of the OPCAP servers, wait for client to connect */
|
||||||
|
private function f_init_one_srv(integer idx, template (present) uint32_t linktype) runs on test_CT {
|
||||||
|
/* start guard timer */
|
||||||
|
activate(as_Tguard());
|
||||||
|
g_Tguard.start;
|
||||||
|
log("Waiting for client-", idx, " connection...");
|
||||||
|
/* wait for connection */
|
||||||
|
f_bind(mp_local_opcap_ip, mp_local_opcap_port+idx, idx);
|
||||||
|
f_wait_client_connect(idx);
|
||||||
|
/* wait for file header */
|
||||||
|
f_opcap_exp(tr_OPCAP_FILE_HDR(linktype), idx);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* global initialization */
|
||||||
|
private function f_init() runs on test_CT {
|
||||||
|
map(self:VTY, system:VTY);
|
||||||
|
f_vty_set_prompts(VTY);
|
||||||
|
f_vty_transceive(VTY, "enable");
|
||||||
|
|
||||||
|
map(self:IP, system:IP);
|
||||||
|
var IPL4asp_Types.Result res
|
||||||
|
|
||||||
|
/* 0 -> 1 */
|
||||||
|
res := f_IPL4_connect(IP, mp_traffic_b.ip, mp_traffic_b.udp_port,
|
||||||
|
mp_traffic_a.ip, mp_traffic_a.udp_port, -1, { udp:={} });
|
||||||
|
g_traffic_conn_id[0] := res.connId;
|
||||||
|
|
||||||
|
/* 1 -> 0 */
|
||||||
|
res := f_IPL4_connect(IP, mp_traffic_a.ip, mp_traffic_a.udp_port,
|
||||||
|
mp_traffic_b.ip, mp_traffic_b.udp_port, -1, { udp:={} });
|
||||||
|
g_traffic_conn_id[1] := res.connId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* generate user traffic from A -> B */
|
||||||
|
function f_trafic_pkt_ab(octetstring payload) runs on test_CT {
|
||||||
|
IP.send(ASP_Send:{g_traffic_conn_id[0], omit, payload})
|
||||||
|
IP.receive(ASP_RecvFrom:{g_traffic_conn_id[1], ?, ?, ?, ?, { udp:={} }, ?, payload});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* generate user traffic from B -> A */
|
||||||
|
function f_trafic_pkt_ba(octetstring payload) runs on test_CT {
|
||||||
|
IP.send(ASP_Send:{g_traffic_conn_id[1], omit, payload})
|
||||||
|
IP.receive(ASP_RecvFrom:{g_traffic_conn_id[0], ?, ?, ?, ?, { udp:={} }, ?, payload});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* expect a specified UDP payload on the OPCAP connection 'idx' */
|
||||||
|
function f_opcap_exp_udp(octetstring udp_payload, integer idx) runs on test_CT {
|
||||||
|
var octetstring rx_tail;
|
||||||
|
var integer udp_payload_len, rx_pdu_len;
|
||||||
|
var OPCAP_PDU rx_pdu;
|
||||||
|
|
||||||
|
udp_payload_len := lengthof(udp_payload);
|
||||||
|
|
||||||
|
/* sadly I couldn't figure out how to create an octetstring template
|
||||||
|
* for 'match an octetstring ending in 'udp_payload' */
|
||||||
|
rx_pdu := f_opcap_exp(tr_OPCAP_PKT(?), idx);
|
||||||
|
rx_pdu_len := lengthof(rx_pdu.u.packet.payload);
|
||||||
|
rx_tail := substr(rx_pdu.u.packet.payload, rx_pdu_len - udp_payload_len, udp_payload_len);
|
||||||
|
if (rx_tail != udp_payload) {
|
||||||
|
log("captured UDP payload: ", rx_tail, " but expected: ", udp_payload);
|
||||||
|
setverdict(fail);
|
||||||
|
} else {
|
||||||
|
setverdict(pass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create an additional pcap-store-connection via the VTY */
|
||||||
|
function f_vty_create_addl_connection(integer idx) runs on test_CT
|
||||||
|
{
|
||||||
|
f_vty_config3(VTY, { "client", "pcap-store-connectio second-" & int2str(idx) },
|
||||||
|
{ "server ip " & mp_local_opcap_ip,
|
||||||
|
"server port " & int2str(mp_local_opcap_port + idx),
|
||||||
|
"connect" }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* wait for inbound client connection and reception of link header */
|
||||||
|
testcase TC_connect_rx_hdr() runs on test_CT
|
||||||
|
{
|
||||||
|
f_init();
|
||||||
|
f_init_one_srv(0, ?);
|
||||||
|
setverdict(pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if client connection is re-started after a close */
|
||||||
|
testcase TC_reconnect(integer idx := 0) runs on test_CT
|
||||||
|
{
|
||||||
|
f_init();
|
||||||
|
f_init_one_srv(idx, ?);
|
||||||
|
f_sleep(2.0);
|
||||||
|
|
||||||
|
log("Disconnecting client-", idx);
|
||||||
|
f_disconnect(idx);
|
||||||
|
|
||||||
|
f_wait_client_connect(idx);
|
||||||
|
f_opcap_exp(tr_OPCAP_FILE_HDR(?), idx);
|
||||||
|
setverdict(pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* capture a packet that's within the filter */
|
||||||
|
testcase TC_capture() runs on test_CT
|
||||||
|
{
|
||||||
|
f_init();
|
||||||
|
f_init_one_srv(0, ?);
|
||||||
|
|
||||||
|
for (var integer i := 0; i < 10; i := i + 1) {
|
||||||
|
var octetstring udp_payload;
|
||||||
|
|
||||||
|
/* we assume 1400 is low enough to avoid IP fragmentation */
|
||||||
|
udp_payload := f_rnd_octstring(f_rnd_int(1400));
|
||||||
|
f_trafic_pkt_ab(udp_payload);
|
||||||
|
|
||||||
|
f_opcap_exp_udp(udp_payload, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait for inbound client connections and reception of link header */
|
||||||
|
testcase TC_multi_connect_rx_hdr() runs on test_CT
|
||||||
|
{
|
||||||
|
f_init();
|
||||||
|
f_init_one_srv(0, ?);
|
||||||
|
f_vty_create_addl_connection(1);
|
||||||
|
f_init_one_srv(1, ?);
|
||||||
|
setverdict(pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ensure a packet that's within the filter is sent to secondary clients */
|
||||||
|
testcase TC_multi_capture() runs on test_CT
|
||||||
|
{
|
||||||
|
f_init();
|
||||||
|
f_init_one_srv(0, ?);
|
||||||
|
f_vty_create_addl_connection(1);
|
||||||
|
f_init_one_srv(1, ?);
|
||||||
|
|
||||||
|
for (var integer i := 0; i < 10; i := i + 1) {
|
||||||
|
var octetstring udp_payload;
|
||||||
|
|
||||||
|
/* we assume 1400 is low enough to avoid IP fragmentation */
|
||||||
|
udp_payload := f_rnd_octstring(f_rnd_int(1400));
|
||||||
|
f_trafic_pkt_ab(udp_payload);
|
||||||
|
|
||||||
|
/* expect packet to arrive on both simulated servers */
|
||||||
|
f_opcap_exp_udp(udp_payload, 0);
|
||||||
|
f_opcap_exp_udp(udp_payload, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: ensure a packet outside the filter is dropped */
|
||||||
|
/* TODO: capture of truncated packet */
|
||||||
|
/* TODO: stall the receive window */
|
||||||
|
/* TODO: different link type (ethernet, not SLL) */
|
||||||
|
|
||||||
|
|
||||||
|
control {
|
||||||
|
execute( TC_connect_rx_hdr() );
|
||||||
|
execute( TC_reconnect() );
|
||||||
|
execute( TC_capture() );
|
||||||
|
execute( TC_multi_connect_rx_hdr() );
|
||||||
|
execute( TC_multi_capture() );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BASEDIR=../deps
|
||||||
|
|
||||||
|
. ../gen_links.sh.inc
|
||||||
|
|
||||||
|
DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
|
||||||
|
FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
|
||||||
|
FILES+=" TCCEncoding_Functions.ttcn TCCEncoding.cc " # GSM 7-bit coding
|
||||||
|
gen_links $DIR $FILES
|
||||||
|
|
||||||
|
DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
|
||||||
|
FILES="Socket_API_Definitions.ttcn"
|
||||||
|
gen_links $DIR $FILES
|
||||||
|
|
||||||
|
DIR=$BASEDIR/titan.TestPorts.IPL4asp/src
|
||||||
|
FILES="IPL4asp_Functions.ttcn IPL4asp_PT.cc IPL4asp_PT.hh IPL4asp_PortType.ttcn IPL4asp_Types.ttcn IPL4asp_discovery.cc IPL4asp_protocol_L234.hh"
|
||||||
|
gen_links $DIR $FILES
|
||||||
|
|
||||||
|
DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
|
||||||
|
FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
|
||||||
|
gen_links $DIR $FILES
|
||||||
|
|
||||||
|
DIR=../library
|
||||||
|
FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn Native_Functions.ttcn Native_FunctionDefs.cc "
|
||||||
|
FILES+="Osmocom_VTY_Functions.ttcn "
|
||||||
|
FILES+="OPCAP_Types.ttcn OPCAP_Templates.ttcn "
|
||||||
|
FILES+="OPCAP_CodecPort.ttcn OPCAP_CodecPort_CtrlFunct.ttcn OPCAP_CodecPort_CtrlFunctdef.cc OPCAP_Adapter.ttcn "
|
||||||
|
gen_links $DIR $FILES
|
||||||
|
|
||||||
|
ignore_pp_results
|
|
@ -0,0 +1,14 @@
|
||||||
|
!
|
||||||
|
! OsmoPCAPClient (UNKNOWN-dirty) configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
client
|
||||||
|
pcap device lo
|
||||||
|
pcap filter udp port 44423
|
||||||
|
pcap detect-loop 0
|
||||||
|
server ip 127.0.0.1
|
||||||
|
server port 5000
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
FILES="*.ttcn TCCConversion.cc TCCInterface.cc TCCEncoding.cc IPL4asp_PT.cc IPL4asp_discovery.cc TELNETasp_PT.cc Native_FunctionDefs.cc OPCAP_CodecPort_CtrlFunctdef.cc "
|
||||||
|
#FILES+="*.ttcnpp "
|
||||||
|
#FILES+="*.asn"
|
||||||
|
|
||||||
|
export CPPFLAGS_TTCN3=""
|
||||||
|
|
||||||
|
../regen-makefile.sh OPCAP_CLIENT_Tests.ttcn $FILES
|
||||||
|
|
||||||
|
#sed -i -e 's/^LINUX_LIBS = -lxml2/LINUX_LIBS = -lxml2 -lfftranscode/' Makefile
|
Loading…
Reference in New Issue