An open source implementation of the Simple Two-Way Active Measurement Protocol (RFC 8762).
Note well: Compilation has only been testing on Linux-based systems (specifically Fedora Core 39+). Your mileage may vary, and patches are definitely welcome!
After cloning the repository, make sure to initialize the git submodules:
$ git submodule update --init --recursive
After that, it should be as easy as
$ cargo build
teaparty
has both a reflector and a sender mode. The sender mode is developed/maintained for the purposes of testing interoperability.
Because the Reflector listens on a privileged port by default, it requires root privileges to run (see below for ways to customize the teaparty
startup).
$ sudo teaparty reflector
is the fastest way to get started. After that, take a look at the following start options documented using the --help
CLI flag:
Usage: teaparty reflector [OPTIONS]
Options:
--stateless Run teaparty in stateless mode.
--heartbeat <HEARTBEAT> Specify hearbeat message target and interval (in seconds) as [IP]@[Seconds]
--link-layer Run teaparty in link-layer mode.
-h, --help Print help
Some TLVs (see below) need access to link-layer information about the test packet. Capturing such information is not possible using traditional BSD-socket-like methods. When the Reflector runs in link-layer mode, it will listen for test packets by acting as a packet capturing system. While this feature will allow the Reflector to handle more TLVs, it may also cause additional overhead.
Monitoring
By default, the Reflector will launch a RESTful API on the localhost on port 8080. It supports the following endpoints:
/heartbeats
Will return information about the configured heartbeat targets:
$ curl http://127.0.0.1:8000/heartbeats
Sample output:
[
{
"target": "8.8.8.8:8620",
"interval": {
"secs": 5,
"nanos": 0
}
}
]
/sessions
Will return information about the currently active sessions:
$ curl 127.0.0.1:8000/sessions
Sample output:
[
{
"id": {
"src": "0.0.0.0:862",
"dst": "127.0.0.1:4567",
"ssid": {
"Ssid": 61183
}
},
"data": {
"sequence": 1,
"last": {
"secs_since_epoch": 1733193824,
"nanos_since_epoch": 695132749
}
}
},
{
"id": {
"src": "0.0.0.0:862",
"dst": "127.0.0.1:5001",
"ssid": {
"Ssid": 61183
}
},
"data": {
"sequence": 0,
"last": {
"secs_since_epoch": 1733193827,
"nanos_since_epoch": 926120800
}
}
}
]
More endpoints are planned. Endpoints that control and not just monitor the Reflector are planned, too.
Configuring
/session
Will add a new active session, if possible. A request to create a new session (a session request) requires
- a source of test packets:
src_ip
: a string;src_port
: a number - a destination of test packets (i.e., the reflector):
src_ip
: a string;src_port
: a number - a key used for validating authenticated test packets:
key
: a string - a session ID:
ssid
: a number
Upon POST
ing a JSON object with the fields above, the server will respond with:
- 500: The session could not be created (most likely because a session with the requested parameters exists)
- 200: The sesion was created (and the body of the response will be the
POST
ed JSON for confirmation)
The Sender has a variety of options that are useful for testing implementations of a STAMP-compliant Reflector:
Usage: teaparty sender [OPTIONS] [COMMAND]
Commands:
tlvs
help Print this message or the help of the given subcommand(s)
Options:
--ssid <SSID>
--malformed <MALFORMED> Include a malformed Tlv in the test packet [possible values: bad-flags, bad-length]
--ecn <ECN> Enable a non-default ECN for testing [possible values: not-ect, ect1, ect0, ce]
--dscp <DSCP> Enable a non-default DSCP for testing [possible values: cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef, voiceadmit]
--src-port <SRC_PORT> [default: 0]
--authenticated <AUTHENTICATED>
-h, --help Print help
The --src-port
option is useful for testing the statefulness of the Reflector. The --malformed
option is useful
for testing the Reflector's error handling. The --ecn
and --dscp
will set the TOS fields of the IP packet of the test packet with the values specified.
-- useful for testing the Reflector's implementation of the TLVs related to quality of service. Omitting either of those options means that the test packet
will have neither DSCP nor ECN values set in the IP header. Setting the --authenticated
flag will cause the sender to operate in
Authenticated Mode and use <AUTHENTICATED>
as the key for generating the test packet's HMAC.
The tlvs
subcommand will put TLVs into the test packet.
Usage: teaparty sender tlvs [COMMAND]
Commands:
dscp-ecn
time
destination-port
class-of-service
location
unrecognized
padding
access-report
history
followup
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
Name | TLV | Defaults/Notes |
---|---|---|
class-of-service | Class of Service | The DSCP value requested to be set in the reflected IP packet can be specified with the --dscp . By default, the requested value is CS1 . |
dscp-ecn | DSCP ECN | The values requested to be set in the reflected IP packet for the DSCP and ECN values can be specified with the --dscp and --ecn flags, respectively. By default, the requested values are CS1 and ECT0 , respectively. |
time | Timestamp | All fields empty (see RFC 8972) |
destination-port | Destination Port | 983 |
location | Location | A Source IP Address sub-TLV |
unrecognized | Special | Will include a TLV whose type is unrecognized |
padding | Padding | Will pad out a STAMP packet with 64 bytes (by default); customize with the -s option |
history | History | Will include a TLV that requests information about the previous N reflected packets in the current session (defaults to 3; customize with --length ) |
Example:
$ teaparty 127.0.0.1 sender --dscp ef tlvs class-of-service
will send a STAMP test packet to a Reflector running on localhost that contains a Class of Service TLV (with the requested value of the reflected packet's IP headerDSCP
field set to CS1
) with the test IP packet's DSCP value set to EF
.
It is possible to put more than one TLV into a test packet by separating multiple instances of the tlvs
subcommand with the --
.
Example:
$ 127.0.0.1 sender --ecn ect1 --dscp af11 tlvs time -- dscp-ecn --ecn ect0 --dscp af21
will send a STAMP test packet to a Reflector running on localhost that contains a Timestamp TLV, a DSCP ECN TLV (requesting that the reflected IP packet's headers have DSCP and ECN fields set to AF21
and ECT0
, respectively), and with the test IP packet's ECN and DSCP values set to ECT1
and AF11
, respectively.
We would love to have you contribute. We love contributors, big and small and everywhere in between. If you would like to learn more about how to work with us, just open an issue!
Feature | Supported |
---|---|
Unauthenticated STAMP messages (reflector) | ✅ |
Unauthenticated STAMP messages (sender) | ✅ |
Authenticated STAMP messages (reflector) | ✅ |
Authenticated STAMP messages (sender) | ✅ |
Stateful (reflector) | ✅ |
TLV | Supported |
---|---|
Extra Padding (reflector) | ❌ |
Extra Padding (sender) | ✅ |
Location (reflector) | ✅ |
Location (sender) | ✅ |
Timestamp (reflector) | ✅ |
Timestamp (sender) | ✅ |
Class of service (reflector) | ✅ |
Class of service (sender) | ✅ |
Direct measurement (reflector) | ❌ |
Direct measurement (sender) | ❌ |
Access report (reflector) | ✅ |
Access report (sender) | ✅ |
Follow-up Telemetry (reflector) | ✅ |
Follow-up Telemetry (sender) | ✅ |
HMAC (reflector) | ❌ |
HMAC (sender) | ❌ |
TLV | Supported |
---|---|
DSCP ECN (reflector) | ✅ |
DSCP ECN (sender) | ✅ |
Heartbeat (reflector) | ✅ |
Heartbeat (sender) | ❌ |
Destination port (reflector) | ✅ |
Destination port (sender) | ✅ |
History (reflector) | ✅ |
History (sender) | ✅ |
In addition to unit tests, there are tools for end-to-end tests in the testing_data
directory. See testing_data/README.md
for more information.