Showing preview only (814K chars total). Download the full file or copy to clipboard to get everything.
Repository: open-traffic-generator/ixia-c
Branch: main
Commit: 9d707acbce23
Files: 94
Total size: 776.8 KB
Directory structure:
gitextract_2ocvabri/
├── .github/
│ └── workflows/
│ ├── ci.yml
│ └── publish.yml
├── .gitignore
├── .gitmodules
├── .markdownlint.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── deployments/
│ ├── docker/
│ │ ├── deployment.sh
│ │ ├── readme.md
│ │ └── versions.yaml
│ ├── k8s/
│ │ ├── bases/
│ │ │ ├── namespace/
│ │ │ │ ├── kustomization.yaml
│ │ │ │ └── namespace.yaml
│ │ │ ├── otg-controller/
│ │ │ │ ├── kustomization.yaml
│ │ │ │ ├── pod.yaml
│ │ │ │ └── service.yaml
│ │ │ └── otg-traffic-port/
│ │ │ ├── kustomization.yaml
│ │ │ ├── pod.yaml
│ │ │ └── service.yaml
│ │ ├── components/
│ │ │ └── images/
│ │ │ └── kustomization.yaml
│ │ ├── kind.yaml
│ │ ├── network-emulation/
│ │ │ ├── go.mod
│ │ │ ├── go.sum
│ │ │ ├── ipfwd.go
│ │ │ ├── kind.yaml
│ │ │ ├── links.yaml
│ │ │ ├── namespace.yaml
│ │ │ ├── pods.yaml
│ │ │ ├── readme.md
│ │ │ └── services.yaml
│ │ ├── overlays/
│ │ │ ├── one-traffic-port-eth0/
│ │ │ │ ├── config-map.yaml
│ │ │ │ ├── kustomization.yaml
│ │ │ │ └── port1/
│ │ │ │ ├── kustomization.yaml
│ │ │ │ ├── pod-patch.yaml
│ │ │ │ └── service-patch.yaml
│ │ │ └── two-traffic-ports-eth0/
│ │ │ ├── config-map.yaml
│ │ │ ├── gen-test-config.sh
│ │ │ ├── init-container.yaml
│ │ │ ├── kustomization.yaml
│ │ │ ├── port1/
│ │ │ │ ├── kustomization.yaml
│ │ │ │ ├── pod-patch.yaml
│ │ │ │ └── service-patch.yaml
│ │ │ └── port2/
│ │ │ ├── kustomization.yaml
│ │ │ ├── pod-patch.yaml
│ │ │ └── service-patch.yaml
│ │ └── readme.md
│ ├── raw-one-arm.yml
│ ├── raw-three-arm-mesh.yml
│ └── raw-two-arm.yml
├── docs/
│ ├── CNAME
│ ├── architecture.md
│ ├── contribute.md
│ ├── deployments-containerlab.md
│ ├── deployments-docker-compose.md
│ ├── deployments-kne.md
│ ├── deployments.md
│ ├── developer/
│ │ ├── hello-snappi.md
│ │ ├── introduction.md
│ │ ├── snappi-constructs.md
│ │ └── snappi-install.md
│ ├── eula.md
│ ├── faq.md
│ ├── features.md
│ ├── index.md
│ ├── integrated-environments.md
│ ├── licensing.md
│ ├── limitations.md
│ ├── news.md
│ ├── prerequisites.md
│ ├── quick-start/
│ │ ├── deployment.md
│ │ ├── introduction.md
│ │ └── sample-test.md
│ ├── reference/
│ │ ├── capabilities.md
│ │ ├── licensing.md
│ │ └── resource-requirements.md
│ ├── releases.md
│ ├── res/
│ │ ├── hw-server.drawio
│ │ └── system_with_UHD400T.drawio
│ ├── resources.md
│ ├── roadmap.md
│ ├── sample-scripts.md
│ ├── stylesheets/
│ │ └── extra.css
│ ├── support.md
│ ├── tests-chassis-app.md
│ ├── tests-ixia-c.md
│ ├── tests-uhd400.md
│ ├── troubleshooting.md
│ ├── usecases.md
│ └── user-guide-introduction.md
├── license
├── mkdocs.md
├── mkdocs.yml
├── notes.md
├── readme.md
└── requirements.txt
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
env:
PYTHON_VERSION: "3.8"
GO_VERSION: "1.23"
on:
push:
jobs:
examples_curl:
runs-on: ubuntu-22.04
steps:
- name: Checkout source
uses: actions/checkout@v3
with:
submodules: true
- name: Setup docker
uses: docker/setup-buildx-action@v3
- name: Deploy Ixia-C
run: |
sed -n '58,61p' readme.md > deploy.sh
sh deploy.sh
- name: Setup and run tests
run: |
sed -n '90,97p' readme.md > test.sh
sh test.sh
- name: Get container logs
if: always()
run: |
cd conformance && ./do.sh topo logs
- name: Archive logs
if: always()
uses: actions/upload-artifact@v4
with:
name: examples_curl
path: |
conformance/logs
examples_go_py:
runs-on: ubuntu-22.04
steps:
- name: Checkout source
uses: actions/checkout@v3
with:
submodules: true
- name: Setup docker
uses: docker/setup-buildx-action@v3
- name: Deploy Ixia-C
run: |
sed -n '58,61p' readme.md > deploy.sh
sh deploy.sh
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Setup Go
uses: actions/setup-go@v3
with:
go-version: ${{ env.GO_VERSION }}
- name: Setup and run tests
run: |
sed -n '67,78p' readme.md > test.sh
sh test.sh
- name: Get container logs
if: always()
run: |
cd conformance && ./do.sh topo logs
- name: Archive logs
if: always()
uses: actions/upload-artifact@v4
with:
name: examples_go_py
path: |
conformance/logs
deployments_k8s:
runs-on: ubuntu-22.04
steps:
- name: Checkout source
uses: actions/checkout@v3
with:
submodules: true
- name: Setup docker
uses: docker/setup-buildx-action@v3
- name: Setup Go
uses: actions/setup-go@v3
with:
go-version: ${{ env.GO_VERSION }}
- name: Setup Cluster
run: |
cd deployments/k8s
sed -n '26,34p' readme.md > setup-cluster.sh
sh setup-cluster.sh
- name: Download images
run: |
cd deployments/k8s
sed -n '42,49p' readme.md > download-images.sh
sh download-images.sh
- name: Setup Pods and Services
run: |
cd deployments/k8s
sed -n '61,64p' readme.md > setup-pods-services.sh
sh setup-pods-services.sh
- name: Setup tests
run: |
cd deployments/k8s
sed -n '75,77p' readme.md > setup-tests.sh
sh setup-tests.sh
- name: Run tests
run: |
cd deployments/k8s
sed -n '85,86p' readme.md > run-tests.sh
sh run-tests.sh
deployments_k8s_network_emulation:
runs-on: ubuntu-22.04
steps:
- name: Checkout source
uses: actions/checkout@v3
with:
submodules: true
- name: Setup docker
uses: docker/setup-buildx-action@v3
- name: Setup Go
uses: actions/setup-go@v3
with:
go-version: ${{ env.GO_VERSION }}
- name: Setup Cluster
run: |
sed -n '49,60p' deployments/k8s/network-emulation/readme.md > setup-cluster.sh
sh setup-cluster.sh
- name: Download images
run: |
sed -n '66,91p' deployments/k8s/network-emulation/readme.md > download-images.sh
sh download-images.sh
- name: Setup Meshnet
run: |
sed -n '97,105p' deployments/k8s/network-emulation/readme.md > setup-meshnet.sh
sh setup-meshnet.sh
- name: Setup Interfaces
run: |
sed -n '113,118p' deployments/k8s/network-emulation/readme.md > setup-interfaces.sh
sh setup-interfaces.sh
- name: Setup Pods and Services
run: |
sed -n '124,131p' deployments/k8s/network-emulation/readme.md > setup-pods-services.sh
sh setup-pods-services.sh
- name: Setup and run tests
run: |
sed -n '141,143p' deployments/k8s/network-emulation/readme.md > test.sh
sh test.sh
- name: Cleanup
run: |
sed -n '153,157p' deployments/k8s/network-emulation/readme.md > cleanup.sh
sh cleanup.sh
================================================
FILE: .github/workflows/publish.yml
================================================
name: publish
on:
push:
branches:
- main
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- uses: actions/setup-python@v4
with:
python-version: 3.x
- run: pip install mkdocs-material
- run: mkdocs gh-deploy --force
================================================
FILE: .gitignore
================================================
scratch
env
*.pcap
*.log
venv
site
.DS_Store
*.bkp
================================================
FILE: .gitmodules
================================================
[submodule "conformance"]
path = conformance
url = https://github.com/open-traffic-generator/conformance.git
================================================
FILE: .markdownlint.json
================================================
{
"default": true,
"MD013" : false,
"MD033": false
}
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
open-traffic-generator@googlegroups.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
When contributing to this repository, please first discuss the change you wish to make, via issue or email (open-traffic-generator@googlegroups.com), with the owners of this repository.
Please note we have a [code of conduct](CODE_OF_CONDUCT.md), please follow it in all your interactions with the project.
## Steps to Contribute
This repo uses GitHub to manage reviews of [pull requests](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests).
Should you wish to work on an issue, please claim it first by commenting on the GitHub issue that you want to work on it. This is to prevent duplicated efforts from contributors on the same issue.
If you have a trivial fix or improvement, go ahead and create a pull request, and submit it for review.
## Pull Request Checklist
* Branch from the main branch and, if needed, rebase to the current main branch before submitting your pull request. If it doesn't merge cleanly with main you may be asked to rebase your changes.
* Commits should be as small as possible, while ensuring that each commit is correct independently (i.e., each commit should compile and pass tests).
* If your patch is not getting reviewed or you need a specific person to review it, you can @-reply a reviewer asking for a review in the pull request or a comment. You can also send a message to open-traffic-generator@googlegroups.com.
* Add tests relevant to the fixed bug or new feature.
================================================
FILE: deployments/docker/deployment.sh
================================================
#!/bin/bash
VERSIONS_YAML_LOC="https://github.com/open-traffic-generator/ixia-c/releases/download/v1.53.0-1/versions.yaml"
VERSIONS_YAML="versions.yaml"
CTRL_IMAGE="ghcr.io/open-traffic-generator/keng-controller"
TE_IMAGE="ghcr.io/open-traffic-generator/ixia-c-traffic-engine"
PE_IMAGE="ghcr.io/open-traffic-generator/ixia-c-protocol-engine"
if [ -n "$AUTH_TOKEN" ]; then
curl -lO -H "Authorization: Bearer $AUTH_TOKEN" $VERSIONS_YAML_LOC
else
curl -kLO $VERSIONS_YAML_LOC
fi
TIMEOUT_SECONDS=300
# --- Argument parsing for ETH_A and ETH_Z ---
if [ -z "$1" ] || [ -z "$2" ]; then
echo "usage: $0 <eth_A> <eth_Z> <function> [args...]"
exit 1
fi
ETH_A=$1
ETH_Z=$2
shift 2
set_docker_permission() {
if ! groups $USER | grep -q '\bdocker\b'; then
echo "Adding $USER to docker group (relogin required to take effect)."
sudo usermod -aG docker $USER
fi
docker ps -a
}
set_docker_permission
configq() {
# echo is needed to further evaluate the
# contents extracted from configuration
eval echo $(yq "${@}" versions.yaml)
}
push_ifc_to_container() {
# It takes a host NIC (say eth1) and injects it into a container’s
# network namespace so the container can directly use that NIC (bypassing Docker’s default bridge).
# It symlinks the container’s netns into /var/run/netns,
# then moves and configures the interface inside that namespace.
if [ -z "${1}" ] || [ -z "${2}" ]
then
echo "usage: ${0} push_ifc_to_container <ifc-name> <container-name>"
exit 1
fi
# Resolve container metadata
cid=$(container_id ${2})
cpid=$(container_pid ${2})
echo "Changing namespace of ifc ${1} to container ID ${cid} pid ${cpid}"
# Prepare namespace paths
orgPath=/proc/${cpid}/ns/net
newPath=/var/run/netns/${cid}
# Make namespace accessible to ip netns
# Move interface into the container’s netns
# Rename and configure inside the container
sudo mkdir -p /var/run/netns
echo "Creating symlink ${orgPath} -> ${newPath}"
sudo ln -s ${orgPath} ${newPath} \
&& sudo ip link set ${1} netns ${cid} \
&& sudo ip netns exec ${cid} ip link set ${1} name ${1} \
&& sudo ip netns exec ${cid} ip -4 addr add 0/0 dev ${1} \
&& sudo ip netns exec ${cid} ip -4 link set ${1} up \
&& echo "Successfully changed namespace of ifc ${1}"
sudo rm -rf ${newPath}
}
container_id() {
docker inspect --format="{{json .Id}}" ${1} | cut -d\" -f 2
}
container_pid() {
docker inspect --format="{{json .State.Pid}}" ${1} | cut -d\" -f 2
}
container_ip() {
docker inspect --format="{{json .NetworkSettings.IPAddress}}" ${1} | cut -d\" -f 2
}
ixia_c_img_tag() {
tag=$(grep ${1} ${VERSIONS_YAML} | cut -d: -f2 | cut -d\ -f2)
echo "${tag}"
}
ixia_c_traffic_engine_img() {
echo "${TE_IMAGE}:$(ixia_c_img_tag ixia-c-traffic-engine)"
}
ixia_c_protocol_engine_img() {
echo "${PE_IMAGE}:$(ixia_c_img_tag ixia-c-protocol-engine)"
}
keng_controller_img() {
echo "${CTRL_IMAGE}:$(ixia_c_img_tag keng-controller)"
}
gen_controller_config_b2b_cpdp() {
configdir=/home/ixia-c/controller/config
OTG_PORTA=$(container_ip ixia-c-traffic-engine-${ETH_A})
OTG_PORTZ=$(container_ip ixia-c-traffic-engine-${ETH_Z})
wait_for_sock ${OTG_PORTA} 5555
wait_for_sock ${OTG_PORTA} 50071
wait_for_sock ${OTG_PORTZ} 5555
wait_for_sock ${OTG_PORTZ} 50071
yml="location_map:
- location: ${ETH_A}
endpoint: \"${OTG_PORTA}:5555+${OTG_PORTA}:50071\"
- location: ${ETH_Z}
endpoint: \"${OTG_PORTZ}:5555+${OTG_PORTZ}:50071\"
"
echo -n "$yml" | sed "s/^ //g" | tee ./config.yaml > /dev/null \
&& docker exec keng-controller mkdir -p ${configdir} \
&& docker cp ./config.yaml keng-controller:${configdir}/ \
&& rm -rf ./config.yaml
}
gen_controller_config_b2b_dp() {
configdir=/home/ixia-c/controller/config
OTG_PORTA=$(container_ip ixia-c-traffic-engine-${ETH_A})
OTG_PORTZ=$(container_ip ixia-c-traffic-engine-${ETH_Z})
wait_for_sock ${OTG_PORTA} 5555
wait_for_sock ${OTG_PORTZ} 5555
yml="location_map:
- location: ${ETH_A}
endpoint: \"${OTG_PORTA}:5555\"
- location: ${ETH_Z}
endpoint: \"${OTG_PORTZ}:5555\"
"
echo -n "$yml" | sed "s/^ //g" | tee ./config.yaml > /dev/null \
&& docker exec keng-controller mkdir -p ${configdir} \
&& docker cp ./config.yaml keng-controller:${configdir}/ \
&& rm -rf ./config.yaml
}
wait_for_sock() {
TIMEOUT_SECONDS=30
if [ ! -z "${3}" ]
then
TIMEOUT_SECONDS=${3}
fi
echo "Waiting for ${1}:${2} to be ready (timeout=${TIMEOUT_SECONDS}s)..."
elapsed=0
TIMEOUT_SECONDS=$(($TIMEOUT_SECONDS * 10))
while true
do
nc -z -v ${1} ${2} && return 0
elapsed=$(($elapsed+1))
# echo "Timeout: $TIMEOUT_SECONDS"
# echo "elapsed time: $elapsed"
if [ $elapsed -gt ${TIMEOUT_SECONDS} ]
then
echo "${1}:${2} to be ready after ${TIMEOUT_SECONDS}"
exit 1
fi
sleep 0.1
done
}
prepare_eth_pair() {
if [ -z "${1}" ] || [ -z "${2}" ]
then
echo "usage: ${0} create_veth_pair <name1> <name2>"
exit 1
fi
sudo ip link set ${1} up \
&& sudo ip link set ${1} promisc on \
&& sudo ip link set ${2} up \
&& sudo ip link set ${2} promisc on
}
create_ixia_c_b2b_cpdp() {
docker ps -a
echo "Setting up back-to-back with CP/DP distribution of ixia-c ..."
docker run -d \
--name=keng-controller \
--publish 0.0.0.0:8443:8443 \
--publish 0.0.0.0:40051:40051 \
$(keng_controller_img) \
--accept-eula \
--trace \
--disable-app-usage-reporter
docker run --privileged -d \
--name=ixia-c-traffic-engine-${ETH_A} \
-e OPT_LISTEN_PORT="5555" \
-e ARG_IFACE_LIST="virtual@af_packet,${ETH_A}" \
-e OPT_NO_HUGEPAGES="Yes" \
-e OPT_NO_PINNING="Yes" \
-e WAIT_FOR_IFACE="Yes" \
-e OPT_ADAPTIVE_CPU_USAGE="Yes" \
$(ixia_c_traffic_engine_img)
if [ -z "${DATA_PLANE_ONLY}" ]
then
docker run --privileged -d \
--net=container:ixia-c-traffic-engine-${ETH_A} \
--name=ixia-c-protocol-engine-${ETH_A} \
-e INTF_LIST="${ETH_A}" \
$(ixia_c_protocol_engine_img)
fi
docker run --privileged -d \
--name=ixia-c-traffic-engine-${ETH_Z} \
-e OPT_LISTEN_PORT="5555" \
-e ARG_IFACE_LIST="virtual@af_packet,${ETH_Z}" \
-e OPT_NO_HUGEPAGES="Yes" \
-e OPT_NO_PINNING="Yes" \
-e WAIT_FOR_IFACE="Yes" \
-e OPT_ADAPTIVE_CPU_USAGE="Yes" \
$(ixia_c_traffic_engine_img)
if [ -z "${DATA_PLANE_ONLY}" ]
then
docker run --privileged -d \
--net=container:ixia-c-traffic-engine-${ETH_Z} \
--name=ixia-c-protocol-engine-${ETH_Z} \
-e INTF_LIST="${ETH_Z}" \
$(ixia_c_protocol_engine_img)
fi
docker ps -a \
&& prepare_eth_pair ${ETH_A} ${ETH_Z} \
&& push_ifc_to_container ${ETH_A} ixia-c-traffic-engine-${ETH_A} \
&& push_ifc_to_container ${ETH_Z} ixia-c-traffic-engine-${ETH_Z}
if [ -z "${DATA_PLANE_ONLY}" ]
then
gen_controller_config_b2b_cpdp $1
else
gen_controller_config_b2b_dp $1
fi
docker ps -a
echo "Successfully deployed !"
}
rm_ixia_c_b2b_cpdp() {
docker ps -a
echo "Tearing down back-to-back with CP/DP distribution of ixia-c ..."
docker stop keng-controller && docker rm keng-controller
docker stop ixia-c-traffic-engine-${ETH_A}
docker rm ixia-c-traffic-engine-${ETH_A}
docker stop ixia-c-traffic-engine-${ETH_Z}
docker rm ixia-c-traffic-engine-${ETH_Z}
if [ -z "${DATA_PLANE_ONLY}" ]
then
docker stop ixia-c-protocol-engine-${ETH_A}
docker rm ixia-c-protocol-engine-${ETH_A}
docker stop ixia-c-protocol-engine-${ETH_Z}
docker rm ixia-c-protocol-engine-${ETH_Z}
fi
docker ps -a
}
create() {
sudo ip link add $ETH_A type veth peer name $ETH_Z
sudo ip link set $ETH_A up
sudo ip link set $ETH_Z up
}
topo() {
case $1 in
new )
create_ixia_c_b2b_cpdp
;;
rm )
rm_ixia_c_b2b_cpdp
;;
* )
exit 1
;;
esac
}
help() {
grep "() {" ${0} | cut -d\ -f1
}
usage() {
echo "usage: $0 [name of any function in script]"
exit 1
}
case $1 in
* )
cmd=${1}
echo "Hi"
shift 1
${cmd} "$@" || usage
;;
esac
================================================
FILE: deployments/docker/readme.md
================================================
# Ixia-C Docker Deployment over Raw Socket
## Manual Steps
1. (Optional) Cleanup all existing containers and images.
```sh
docker stop $(docker ps -aq) && docker rm $(docker ps -aq)
docker rmi $(docker images -q)
```
2. Start an instance of `controller`.
```sh
# implicitly listens on TCP port 8443 and 40051
# --accept-eula option is confirmation that user has accepted the Ixia-C End-User License Agreement (EULA)
# located at https://github.com/open-traffic-generator/ixia-c/blob/main/docs/eula.md
docker run -d \
--name=keng-controller \
--publish 0.0.0.0:8443:8443 \
--publish 0.0.0.0:40051:40051 \
ghcr.io/open-traffic-generator/keng-controller:1.53.0-1 \
--accept-eula \
--trace \
--disable-app-usage-reporter
```
3. Start one or more instances of `traffic-engine`.
- For `traffic-engine` over raw socket:
```sh
# for network interface eth1
docker run --privileged -d \
--name=ixia-c-traffic-engine-eth1 \
-e OPT_LISTEN_PORT="5555" \
-e ARG_IFACE_LIST="virtual@af_packet,eth1" \
-e OPT_NO_HUGEPAGES="Yes" \
-e OPT_NO_PINNING="Yes" \
-e WAIT_FOR_IFACE="Yes" \
-e OPT_ADAPTIVE_CPU_USAGE="Yes" \
ghcr.io/open-traffic-generator/ixia-c-traffic-engine:1.8.0.245
# for network interface eth2
docker run --privileged -d \
--name=ixia-c-traffic-engine-eth2 \
-e OPT_LISTEN_PORT="5555" \
-e ARG_IFACE_LIST="virtual@af_packet,eth2" \
-e OPT_NO_HUGEPAGES="Yes" \
-e OPT_NO_PINNING="Yes" \
-e WAIT_FOR_IFACE="Yes" \
-e OPT_ADAPTIVE_CPU_USAGE="Yes" \
ghcr.io/open-traffic-generator/ixia-c-traffic-engine:1.8.0.245
```
4. Start one or more instances of `protocol-engine`.
- For `protocol-engine` over raw socket:
```sh
# for network interface eth1
docker run --privileged -d \
--net=container:ixia-c-traffic-engine-eth1 \
--name=ixia-c-protocol-engine-eth1 \
-e INTF_LIST="eth1" \
ghcr.io/open-traffic-generator/ixia-c-protocol-engine:1.00.0.522 \
# for network interface eth2
docker run --privileged -d \
--net=container:ixia-c-traffic-engine-eth2 \
--name=ixia-c-protocol-engine-eth2 \
-e INTF_LIST="eth2" \
ghcr.io/open-traffic-generator/ixia-c-protocol-engine:1.00.0.522
```
5. Ensure existing network interfaces are `Up` and have `Promiscuous` mode enabled.
```sh
# check interface details
sudo ip addr
# configure as required
sudo ip link set eth1 up
sudo ip link set eth1 promisc on
sudo ip link set eth2 up
sudo ip link set eth2 promisc on
```
6. Push interface to the containers.
- It takes a host NIC (say eth1) and injects it into a container’s network namespace so the container can directly use that NIC (bypassing Docker’s default bridge).
It symlinks the container’s netns into /var/run/netns, then moves and configures the interface inside that namespace.
```sh
# For Traffic Engine 1
# Resolve container metadata
cid=$(docker inspect --format="{{json .Id}}" ixia-c-traffic-engine-eth1 | cut -d\" -f 2)
cpid=$(docker inspect --format="{{json .State.Pid}}" ixia-c-traffic-engine-eth1 | cut -d\" -f 2)
# Prepare namespace paths
orgPath=/proc/${cpid}/ns/net
newPath=/var/run/netns/${cid}
# Make namespace accessible to ip netns
sudo mkdir -p /var/run/netns
sudo ln -s ${orgPath} ${newPath}
# Move interface into the container’s netns
sudo ip link set eth1 netns ${cid}
# Rename and configure inside the container
sudo ip netns exec ${cid} ip link set eth1 name eth1
sudo ip netns exec ${cid} ip -4 addr add 0/0 dev eth1
sudo ip netns exec ${cid} ip -4 link set eth1 up
# For Traffic Engine 2
# Resolve container metadata
cid=$(docker inspect --format="{{json .Id}}" ixia-c-traffic-engine-eth2 | cut -d\" -f 2)
cpid=$(docker inspect --format="{{json .State.Pid}}" ixia-c-traffic-engine-eth2 | cut -d\" -f 2)
# Prepare namespace paths
orgPath=/proc/${cpid}/ns/net
newPath=/var/run/netns/${cid}
# Make namespace accessible to ip netns
sudo mkdir -p /var/run/netns
sudo ln -s ${orgPath} ${newPath}
# Move interface into the container’s netns
sudo ip link set eth2 netns ${cid}
# Rename and configure inside the container
sudo ip netns exec ${cid} ip link set eth2 name eth2
sudo ip netns exec ${cid} ip -4 addr add 0/0 dev eth2
sudo ip netns exec ${cid} ip -4 link set eth2 up
```
6. Create interface-port config-map inside `keng-controller`.
```sh
configDir=/home/ixia-c/controller/config
OTG_PORTA=$(docker inspect --format="{{json .NetworkSettings.IPAddress}}" ixia-c-traffic-engine-eth1 | cut -d\" -f 2)
OTG_PORTZ=$(docker inspect --format="{{json .NetworkSettings.IPAddress}}" ixia-c-traffic-engine-eth2 | cut -d\" -f 2)
yml="location_map:
- location: ${ETH_A}
endpoint: \"${OTG_PORTA}:5555+${OTG_PORTA}:50071\"
- location: ${ETH_Z}
endpoint: \"${OTG_PORTZ}:5555+${OTG_PORTZ}:50071\"
"
echo -n "$yml" | sed "s/^ //g" | tee ./config.yaml > /dev/null \
&& docker exec keng-controller mkdir -p ${configDir} \
&& docker cp ./config.yaml keng-controller:${configDir}/ \
&& rm -rf ./config.yaml
```
## Automated Steps
```sh
git clone --recurse-submodule https://github.com/open-traffic-generator/ixia-c.git
cd ixia-c/deployments/docker
chmod u+x ./deployment.sh
# deploy control & data plane
./deployment.sh eth1 eth2 topo new
# teardown control & data plane
./deployment.sh eth1 eth2 topo rm
# deploy data plane only
DATA_PLANE_ONLY=true ./deployment.sh eth1 eth2 topo new
# teardown data plane only
DATA_PLANE_ONLY=true ./deployment.sh eth1 eth2 topo rm
#create veth pair [ if needed ]
./deployment.sh veth1 veth2 create
```
## Note:
- If the source and destination NICs have IPv4 addresses configured and the traffic flow is configured such that the `flows[i].packet.ipv4.src/dst` are matching the configured NICs IPv4 addresses, it is a known issue that due to ICMP protocol/port unreachable replies from the host linux kernel, the flow Rx can become greater than the flow Tx value.
- To avoid this, for eth/ipv4 flows install the filter `iptables -I INPUT -p 61 -j DROP` on destination host to prevent the flow traffic from reaching the host linux kernel. Also Note that the filter might have to be changed accordingly for eth/ipv4/udp or eth/ipv4/tcp to be filtered by udp/tcp port numbers.
- It is advisable to follow the similar steps if similar issue occurs for eth/ipv6 flows as well.
## Sample go snippet to use after deployment for testing
```go
// Create a new API handle to make API calls against OTG
api := gosnappi.NewApi()
// Set the transport protocol to HTTP
api.NewHttpTransport().SetLocation("https://localhost:8443")
// Create a new traffic configuration that will be set on OTG
config := gosnappi.NewConfig()
// Add a test port to the configuration
ptx := config.Ports().Add().SetName("ptx").SetLocation("eth1")
prx := config.Ports().Add().SetName("prx").SetLocation("eth2")
```
## Example Go test
- Setup
```bash
git clone --recurse-submodule https://github.com/open-traffic-generator/conformance.git
cd conformance
go mod tidy
go mod download
```
- Test for control & data plane
```bash
go test -tags=all ./examples -run TestQuickstartB2BCpDp -args -portA=eth1 -portZ=eth2
```
- Test for data plane only
```bash
go test -tags=all ./examples -run TestQuickstartB2BDp -args -portA=eth1 -portZ=eth2
```
================================================
FILE: deployments/docker/versions.yaml
================================================
release: 1.53.0-1
open-traffic-generator: 1.53.0
snappi: 1.53.0
gosnappi: 1.53.0
keng-controller: 1.53.0-1
ixia-c-traffic-engine: 1.8.0.245
ixia-c-protocol-engine: 1.00.0.522
otg-gnmi-server: 1.53.0
keng-operator: 0.4.0
keng-layer23-hw-server: 1.53.0-3
keng-app-usage-reporter: 0.0.1-52
ixia-c-one: 1.53.0-1
uhd400: 1.5.10
================================================
FILE: deployments/k8s/bases/namespace/kustomization.yaml
================================================
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
================================================
FILE: deployments/k8s/bases/namespace/namespace.yaml
================================================
apiVersion: v1
kind: Namespace
metadata:
labels:
app: ixia-c
name: ixia-c
================================================
FILE: deployments/k8s/bases/otg-controller/kustomization.yaml
================================================
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- pod.yaml
- service.yaml
================================================
FILE: deployments/k8s/bases/otg-controller/pod.yaml
================================================
apiVersion: v1
kind: Pod
metadata:
labels:
app: ixia-c
role: otg-controller
name: otg-controller
namespace: ixia-c
spec:
containers:
- args:
- --accept-eula
- --debug
image: keng-controller:latest
imagePullPolicy: IfNotPresent
name: keng-controller
ports:
- containerPort: 8443
name: https-port
protocol: TCP
- containerPort: 40051
name: grpc-port
protocol: TCP
livenessProbe:
tcpSocket:
port: https-port
periodSeconds: 5
startupProbe:
tcpSocket:
port: https-port
periodSeconds: 5
failureThreshold: 12
volumeMounts:
- mountPath: /home/ixia-c/controller/config
name: config
readOnly: true
- args:
- -http-server
- https://localhost:8443
- --debug
image: otg-gnmi-server:latest
imagePullPolicy: IfNotPresent
name: otg-gnmi-server
ports:
- containerPort: 50051
name: gnmi-port
protocol: TCP
livenessProbe:
tcpSocket:
port: gnmi-port
periodSeconds: 5
startupProbe:
tcpSocket:
port: gnmi-port
periodSeconds: 5
failureThreshold: 12
restartPolicy: Always
volumes:
- configMap:
defaultMode: 420
name: controller-config
name: config
================================================
FILE: deployments/k8s/bases/otg-controller/service.yaml
================================================
apiVersion: v1
kind: Service
metadata:
name: service-otg-controller
namespace: ixia-c
spec:
type: NodePort
ports:
- name: https
port: 8443
protocol: TCP
targetPort: https-port
nodePort: 30443
- name: grpc
port: 40051
protocol: TCP
targetPort: grpc-port
nodePort: 30451
- name: gnmi
port: 50051
protocol: TCP
targetPort: gnmi-port
nodePort: 30551
selector:
role: otg-controller
================================================
FILE: deployments/k8s/bases/otg-traffic-port/kustomization.yaml
================================================
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- pod.yaml
- service.yaml
================================================
FILE: deployments/k8s/bases/otg-traffic-port/pod.yaml
================================================
apiVersion: v1
kind: Pod
metadata:
labels:
app: ixia-c
role: otg-port
name: otg-port
namespace: ixia-c
spec:
containers:
- env:
- name: OPT_LISTEN_PORT
value: "5555"
- name: OPT_NO_PINNING
value: "Yes"
- name: ARG_IFACE_LIST
value: virtual@af_packet,eth0
- name: OPT_NO_HUGEPAGES
value: "Yes"
- name: WAIT_FOR_IFACE
value: "Yes"
image: ixia-c-traffic-engine:latest
imagePullPolicy: IfNotPresent
name: ixia-c-traffic-engine
ports:
- containerPort: 5555
name: zeromq-port
protocol: TCP
livenessProbe:
tcpSocket:
port: zeromq-port
periodSeconds: 5
startupProbe:
tcpSocket:
port: zeromq-port
periodSeconds: 5
failureThreshold: 12
securityContext:
privileged: true
restartPolicy: Always
================================================
FILE: deployments/k8s/bases/otg-traffic-port/service.yaml
================================================
apiVersion: v1
kind: Service
metadata:
name: otg-port
namespace: ixia-c
spec:
ports:
- name: zeromq
port: 5555
protocol: TCP
targetPort: zeromq-port
selector:
role: otg-port
================================================
FILE: deployments/k8s/components/images/kustomization.yaml
================================================
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
# Release: https://github.com/open-traffic-generator/ixia-c/releases/tag/v1.53.0-1
images:
- name: keng-controller
newName: ghcr.io/open-traffic-generator/keng-controller
newTag: "1.53.0-1"
- name: otg-gnmi-server
newName: ghcr.io/open-traffic-generator/otg-gnmi-server
newTag: "1.53.0"
- name: ixia-c-traffic-engine
newName: ghcr.io/open-traffic-generator/ixia-c-traffic-engine
newTag: "1.8.0.245"
================================================
FILE: deployments/k8s/kind.yaml
================================================
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
# WARNING: It is _strongly_ recommended that you keep this the default
# (127.0.0.1) for security reasons. However it is possible to change this.
# Change to 0.0.0.0 to access kind cluster from outside
apiServerAddress: 127.0.0.1
# By default the API server listens on a random open port.
# You may choose a specific port but probably don't need to in most cases.
# Using a random port makes it easier to spin up multiple clusters.
apiServerPort: 6443
nodes:
# configure single-node cluster
- role: control-plane
# map TCP ports exposed by pods to host
extraPortMappings:
- containerPort: 30443
hostPort: 8443
- containerPort: 30451
hostPort: 40051
- containerPort: 30551
hostPort: 50051
# replicate following for multi-node cluster with intended number of worker nodes
# - role: workers
================================================
FILE: deployments/k8s/network-emulation/go.mod
================================================
module ipfwd
go 1.25.0
require github.com/open-traffic-generator/snappi/gosnappi v1.53.0
require (
github.com/Masterminds/semver/v3 v3.4.0 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect
go.opentelemetry.io/otel v1.43.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 // indirect
go.opentelemetry.io/otel/metric v1.43.0 // indirect
go.opentelemetry.io/otel/sdk v1.43.0 // indirect
go.opentelemetry.io/otel/trace v1.43.0 // indirect
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
golang.org/x/net v0.52.0 // indirect
golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d // indirect
google.golang.org/grpc v1.80.0 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
================================================
FILE: deployments/k8s/network-emulation/go.sum
================================================
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/open-traffic-generator/snappi/gosnappi v1.53.0 h1:3W/0kgdWhb8PIq8K+zUKLoayeHPcy4/X4zj3FFt5Clk=
github.com/open-traffic-generator/snappi/gosnappi v1.53.0/go.mod h1:me43y2L6WheIkx9G7htMmaW+y0TlMS1RRLCEzEW27uA=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo=
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak=
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g=
go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA=
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM=
google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
================================================
FILE: deployments/k8s/network-emulation/ipfwd.go
================================================
package main
import (
"log"
"time"
"github.com/open-traffic-generator/snappi/gosnappi"
)
func main() {
// This test configures one IPv4 interface on tx and rx test port each
// and sends IPv4 packets with src IP address of interface on tx port
// and dst IP address of interface on rx port. The packets are sent only
// after ARP entries have been learned from corresponding DUT interfaces
// and flow metrics is used to validate tx and rx counters.
testConst := map[string]interface{}{
"apiLocation": "https://localhost:8443",
"txPortLocation": "eth1",
"rxPortLocation": "eth2",
"speed": "speed_1_gbps",
"pktRate": uint64(50),
"pktCount": uint32(100),
"pktSize": uint32(128),
"txMac": "00:00:01:01:01:01",
"txIp": "1.1.1.1",
"txGateway": "1.1.1.2",
"txPrefix": uint32(24),
"rxMac": "00:00:01:01:01:02",
"rxIp": "2.2.2.1",
"rxGateway": "2.2.2.2",
"rxPrefix": uint32(24),
}
api := gosnappi.NewApi()
api.NewHttpTransport().SetLocation(testConst["apiLocation"].(string)).SetVerify(false)
log.Println("Constructing OTG configuration ...")
c := otgConfig(testConst)
log.Println("Pushing OTG configuration ...")
if wrn, err := api.SetConfig(c); err != nil {
log.Fatal(err)
} else {
for _, w := range wrn.Warnings() {
log.Println("WARNING:", w)
}
}
log.Println("Waiting for ARP entries for configured interfaces ...")
for start := time.Now(); !ipNeighborsOk(api, testConst); time.Sleep(time.Millisecond * 500) {
if time.Second*30 < time.Until(start) {
log.Fatal("Timed out waiting for ARP entries")
}
}
log.Println("Starting flow transmission ...")
cs := gosnappi.NewControlState()
cs.Traffic().FlowTransmit().SetState(gosnappi.StateTrafficFlowTransmitState.START)
if wrn, err := api.SetControlState(cs); err != nil {
log.Fatal(err)
} else {
for _, w := range wrn.Warnings() {
log.Println("WARNING:", w)
}
}
log.Println("Waiting for flow metrics ...")
for start := time.Now(); !flowMetricsOk(api, testConst); time.Sleep(time.Millisecond * 500) {
if time.Second*30 < time.Until(start) {
log.Fatal("Timed out waiting for ARP entries")
}
}
}
func otgConfig(tc map[string]interface{}) gosnappi.Config {
c := gosnappi.NewConfig()
ptx := c.Ports().Add().SetName("ptx").SetLocation(tc["txPortLocation"].(string))
prx := c.Ports().Add().SetName("prx").SetLocation(tc["rxPortLocation"].(string))
c.Layer1().Add().
SetName("ly").
SetPortNames([]string{ptx.Name(), prx.Name()}).
SetSpeed(gosnappi.Layer1SpeedEnum(tc["speed"].(string)))
dtx := c.Devices().Add().SetName("dtx")
drx := c.Devices().Add().SetName("drx")
dtxEth := dtx.Ethernets().
Add().
SetName("dtxEth").
SetMac(tc["txMac"].(string)).
SetMtu(1500)
dtxEth.Connection().SetPortName(ptx.Name())
dtxIp := dtxEth.
Ipv4Addresses().
Add().
SetName("dtxIp").
SetAddress(tc["txIp"].(string)).
SetGateway(tc["txGateway"].(string)).
SetPrefix(tc["txPrefix"].(uint32))
drxEth := drx.Ethernets().
Add().
SetName("drxEth").
SetMac(tc["rxMac"].(string)).
SetMtu(1500)
drxEth.Connection().SetPortName(prx.Name())
drxIp := drxEth.
Ipv4Addresses().
Add().
SetName("drxIp").
SetAddress(tc["rxIp"].(string)).
SetGateway(tc["rxGateway"].(string)).
SetPrefix(tc["rxPrefix"].(uint32))
flow := c.Flows().Add()
flow.SetName("ftxV4")
flow.Duration().FixedPackets().SetPackets(tc["pktCount"].(uint32))
flow.Rate().SetPps(tc["pktRate"].(uint64))
flow.Size().SetFixed(tc["pktSize"].(uint32))
flow.Metrics().SetEnable(true)
flow.TxRx().Device().
SetTxNames([]string{dtxIp.Name()}).
SetRxNames([]string{drxIp.Name()})
ftxV4Eth := flow.Packet().Add().Ethernet()
ftxV4Eth.Src().SetValue(dtxEth.Mac())
ftxV4Ip := flow.Packet().Add().Ipv4()
ftxV4Ip.Src().SetValue(tc["txIp"].(string))
ftxV4Ip.Dst().SetValue(tc["rxIp"].(string))
log.Printf("Config:\n%v\n", c)
return c
}
func ipNeighborsOk(api gosnappi.Api, tc map[string]interface{}) bool {
count := 0
log.Println("Getting IPv4 neighbors ...")
req := gosnappi.NewStatesRequest()
// query to fetch states for all configured IPv4 interfaces
req.Ipv4Neighbors()
states, err := api.GetStates(req)
if err != nil {
log.Fatal(err)
}
log.Printf("IPv4 Neighbors Metrics:\n%v\n", states)
for _, n := range states.Ipv4Neighbors().Items() {
if n.HasLinkLayerAddress() {
for _, key := range []string{"txGateway", "rxGateway"} {
if n.Ipv4Address() == tc[key].(string) {
count += 1
}
}
}
}
return count == 2
}
func flowMetricsOk(api gosnappi.Api, tc map[string]interface{}) bool {
pktCount := uint64(tc["pktCount"].(uint32))
log.Println("Getting flow metrics ...")
req := gosnappi.NewMetricsRequest()
// query to fetch metrics for all configured flows
req.Flow()
metrics, err := api.GetMetrics(req)
if err != nil {
log.Fatal(err)
}
log.Printf("Flow Metrics:\n%v\n", metrics)
for _, m := range metrics.FlowMetrics().Items() {
if m.Transmit() != gosnappi.FlowMetricTransmit.STOPPED ||
m.FramesTx() != pktCount ||
m.FramesRx() != pktCount {
return false
}
}
return true
}
================================================
FILE: deployments/k8s/network-emulation/kind.yaml
================================================
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
# WARNING: It is _strongly_ recommended that you keep this the default
# (127.0.0.1) for security reasons. However it is possible to change this.
# Change to 0.0.0.0 to access kind cluster from outside
apiServerAddress: 127.0.0.1
# By default the API server listens on a random open port.
# You may choose a specific port but probably don't need to in most cases.
# Using a random port makes it easier to spin up multiple clusters.
apiServerPort: 6443
nodes:
# configure single-node cluster
- role: control-plane
# map TCP ports exposed by pods to host
extraPortMappings:
- containerPort: 30443
hostPort: 8443
- containerPort: 30451
hostPort: 40051
- containerPort: 30551
hostPort: 50051
# replicate following for multi-node cluster with intended number of worker nodes
# - role: workers
================================================
FILE: deployments/k8s/network-emulation/links.yaml
================================================
apiVersion: networkop.co.uk/v1beta1
kind: Topology
metadata:
name: ixia-c-port1
namespace: ixia-c
spec:
links:
- uid: 1
peer_pod: dut
local_intf: eth1
local_ip: 1.1.1.1/24
peer_intf: eth1
peer_ip: 1.1.1.2/24
---
apiVersion: networkop.co.uk/v1beta1
kind: Topology
metadata:
name: ixia-c-port2
namespace: ixia-c
spec:
links:
- uid: 1
peer_pod: dut
local_intf: eth2
local_ip: 2.2.2.1/24
peer_intf: eth2
peer_ip: 2.2.2.2/24
---
apiVersion: networkop.co.uk/v1beta1
kind: Topology
metadata:
name: dut
namespace: ixia-c
spec:
links:
- uid: 1
peer_pod: ixia-c-port1
local_intf: eth1
local_ip: 1.1.1.2/24
peer_intf: eth1
peer_ip: 1.1.1.1/24
- uid: 2
peer_pod: ixia-c-port2
local_intf: eth2
local_ip: 2.2.2.2/24
peer_intf: eth2
peer_ip: 2.2.2.1/24
================================================
FILE: deployments/k8s/network-emulation/namespace.yaml
================================================
apiVersion: v1
kind: Namespace
metadata:
labels:
app: ixia-c
name: ixia-c
================================================
FILE: deployments/k8s/network-emulation/pods.yaml
================================================
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app: ixia-c
name: controller-config
namespace: ixia-c
data:
config.yaml: |
location_map:
- location: eth1
endpoint: service-ixia-c-port1.ixia-c.svc.cluster.local:5555+service-ixia-c-port1.ixia-c.svc.cluster.local:50071
- location: eth2
endpoint: service-ixia-c-port2.ixia-c.svc.cluster.local:5555+service-ixia-c-port2.ixia-c.svc.cluster.local:50071
---
apiVersion: v1
kind: Pod
metadata:
labels:
app: ixia-c
role: controller
name: keng-controller
namespace: ixia-c
spec:
containers:
- args:
- --accept-eula
- --debug
image: ghcr.io/open-traffic-generator/keng-controller:1.53.0-1
imagePullPolicy: IfNotPresent
name: keng-controller
volumeMounts:
- mountPath: /home/ixia-c/controller/config
name: config
readOnly: true
restartPolicy: Always
volumes:
- configMap:
defaultMode: 420
name: controller-config
name: config
---
apiVersion: v1
kind: Pod
metadata:
labels:
app: ixia-c
role: port1
name: ixia-c-port1
namespace: ixia-c
spec:
containers:
- env:
- name: ARG_IFACE_LIST
value: virtual@af_packet,eth1
- name: OPT_NO_HUGEPAGES
value: "Yes"
- name: OPT_LISTEN_PORT
value: "5555"
- name: ARG_CORE_LIST
value: 1 1 1
image: ghcr.io/open-traffic-generator/ixia-c-traffic-engine:1.8.0.245
imagePullPolicy: IfNotPresent
name: ixia-c-port1-traffic-engine
securityContext:
privileged: true
- env:
- name: INTF_LIST
value: eth1
image: ghcr.io/open-traffic-generator/ixia-c-protocol-engine:1.00.0.522
imagePullPolicy: IfNotPresent
name: ixia-c-port1-protocol-engine
securityContext:
privileged: true
restartPolicy: Always
---
apiVersion: v1
kind: Pod
metadata:
labels:
app: ixia-c
role: port2
name: ixia-c-port2
namespace: ixia-c
spec:
containers:
- env:
- name: ARG_IFACE_LIST
value: virtual@af_packet,eth2
- name: OPT_NO_HUGEPAGES
value: "Yes"
- name: OPT_LISTEN_PORT
value: "5555"
- name: ARG_CORE_LIST
value: 1 1 1
image: ghcr.io/open-traffic-generator/ixia-c-traffic-engine:1.8.0.245
imagePullPolicy: IfNotPresent
name: ixia-c-port2-traffic-engine
securityContext:
privileged: true
- env:
- name: INTF_LIST
value: eth2
image: ghcr.io/open-traffic-generator/ixia-c-protocol-engine:1.00.0.522
imagePullPolicy: IfNotPresent
name: ixia-c-port2-protocol-engine
securityContext:
privileged: true
restartPolicy: Always
---
apiVersion: v1
kind: Pod
metadata:
labels:
app: ixia-c
role: dut
name: dut
namespace: ixia-c
spec:
containers:
- image: ubuntu:22.04
imagePullPolicy: IfNotPresent
name: dut-ubuntu
command:
- "sleep"
- "infinity"
restartPolicy: Always
================================================
FILE: deployments/k8s/network-emulation/readme.md
================================================
# Ixia-C Kubernetes Deployment For Emulating Network Topology
Ixia-C is a pure software-based solution for facilitating protocol emulation and traffic generation against containerized DUTs (Device Under Test).
<p align="center">
<img src="ixia-c-k8s.drawio.svg" alt="Ixia-C K8S Deployment For Emulating Network Topology">
</p>
For deployment, K8S (Kubernetes) as a platform can be exercised using one of following approaches:
- Manually construct K8S deployment files for any given topology
- Use [KNE](https://github.com/openconfig/kne) to automate deployment using an abstract topology definition
This document discusses the first approach using a minimal Ubuntu container as DUT.
### Overview
Ixia-C is distributed as a multi-container application with following as core components:
1. `keng-controller`: API Server driving operation on one or more test port based on API requests
2. `ixia-c-traffic-engine`: Drives data plane operations on test port
3. `ixia-c-protocol-engine`: Drives control plane operations on test port
Upon deployment, `ixia-c-traffic-engine` and `ixia-c-protocol-engine` need to share same network namespace and hence constitute an Ixia-C Test Port Pod. A typical deployment consists of one `controller pod` and one or more `test port pod`s.
To establish any meaningful interaction between Ixia-C test ports and DUT interfaces, following needs to be done:
- A pair of virtual interfaces need to be created, each on an Ixia-C test port pod and DUT pod
- The interface pair then needs to have a P2P (point-to-point) link established among themselves
To achieve this, we'll be using [Meshnet CNI](https://github.com/networkop/meshnet-cni).
### Prerequisites
- At least **2 x86 CPU cores**, **7GB RAM** and **30GB Free Hard Disk Space**
- Recommended OS is **Ubuntu 22.04 LTS** release.
- Go **1.20+**
- **Docker Engine** (Community Edition) - Needed when using kind for setting up K8S cluster
### Steps
1. Clone this repository
```bash
git clone --recurse-submodules https://github.com/open-traffic-generator/ixia-c.git && cd ixia-c
```
2. (Optional) Setup a Kubernetes Cluster using [kind](https://kind.sigs.k8s.io/)
```bash
# install kind
go install sigs.k8s.io/kind@v0.20.0
# create a single-node cluster
kind create cluster --config=deployments/k8s/network-emulation/kind.yaml --wait 30s
# get compatible kubectl
sudo docker cp kind-control-plane:/usr/bin/kubectl /usr/local/bin/kubectl
sudo chmod 0755 /usr/local/bin/kubectl
# ensure all pods are ready
kubectl wait --for=condition=Ready pods --all --all-namespaces
```
3. (Optional) If cluster does not have access to ghcr.io, manually download container images and push them to all nodes in the cluster
```bash
# Enter Github user ID and PAT when asked for credentials
docker login ghcr.io
# download ixia-c images
docker pull ghcr.io/open-traffic-generator/keng-controller:1.53.0-1
docker pull ghcr.io/open-traffic-generator/ixia-c-traffic-engine:1.8.0.245
docker pull ghcr.io/open-traffic-generator/ixia-c-protocol-engine:1.00.0.522
# download DUT image
docker pull ubuntu:22.04
# download meshnet image
docker pull networkop/meshnet:latest
# download init image
docker pull networkop/init-wait:latest
# push images to nodes
kind load docker-image ghcr.io/open-traffic-generator/keng-controller:1.53.0-1
kind load docker-image ghcr.io/open-traffic-generator/ixia-c-traffic-engine:1.8.0.245
kind load docker-image ghcr.io/open-traffic-generator/ixia-c-protocol-engine:1.00.0.522
kind load docker-image ubuntu:22.04
kind load docker-image networkop/meshnet:latest
kind load docker-image networkop/init-wait:latest
# make sure all intended images have been pushed correctly
docker exec kind-control-plane crictl images
```
4. Setup meshnet
```bash
# Clone and checkout tested version of meshnet
git clone https://github.com/networkop/meshnet-cni
cd meshnet-cni && git checkout f26c193 && cd -
# Deploy meshnet
kubectl apply -k meshnet-cni/manifests/base
# wait for meshnet pods
kubectl wait --for=condition=Ready pods -n meshnet --all
```
5. Create virtual interfaces and P2P link using meshnet
The deployment file to be applied specifies name of test port pods and dut pod, interfaces to be created inside each of them and corresponding peer interface to create P2P link with.
```bash
# create meshnet CRD
kubectl apply -f deployments/k8s/network-emulation/namespace.yaml
kubectl apply -f deployments/k8s/network-emulation/links.yaml
# ensure meshnet CRD is successfully created (should list three entries)
kubectl get topologies -A
```
6. Create Ixia-C / DUT pods and services
```bash
# Create pods and services
kubectl apply -f deployments/k8s/network-emulation/pods.yaml
kubectl apply -f deployments/k8s/network-emulation/services.yaml
# Wait for pods and list pods / services
kubectl wait --for=condition=Ready pods -n ixia-c --all
kubectl get pods -n ixia-c
kubectl get services -n ixia-c
```
7. Run IPv4 forwarding test using [snappi](https://github.com/open-traffic-generator/snappi/tree/main/gosnappi) which is an auto-generated SDK based on [Open Traffic Generator API](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/master/artifacts/openapi.yaml&nocors)
The test parameters, e.g. location of KENG controller, name of interfaces, etc. can be modified inside `testConst` map in `ipfwd.go`.
Check the file for more details on the test.
```bash
cd deployments/k8s/network-emulation/
go run ipfwd.go
cd -
```
8. (Optional) Cleanup
```bash
# remove cluster if deployed using kind
kind delete cluster
sudo rm -rf /usr/local/bin/kubectl
# remove pods / services / CRDs
kubectl delete -f deployments/k8s/network-emulation/services.yaml
kubectl delete -f deployments/k8s/network-emulation/pods.yaml
kubectl delete -f deployments/k8s/network-emulation/links.yaml
kubectl delete -f deployments/k8s/network-emulation/namespace.yaml
```
### What's Next ?
- Checkout Ixia-C Release Page to get compatible client and server builds.
* [All Releases](https://github.com/open-traffic-generator/ixia-c/releases)
* [Latest Release](https://github.com/open-traffic-generator/ixia-c/releases/latest)
- Checkout [OTG Conformance Tests](https://github.com/open-traffic-generator/conformance) for examples on various OTG features written in Go and Python.
- Checkout [OTG Examples](https://github.com/open-traffic-generator/otg-examples) for more comprehensive examples / labs.
================================================
FILE: deployments/k8s/network-emulation/services.yaml
================================================
apiVersion: v1
kind: Service
metadata:
name: service-keng-controller
namespace: ixia-c
spec:
ports:
- name: https
port: 8443
protocol: TCP
targetPort: 8443
nodePort: 30443
- name: grpc
port: 40051
protocol: TCP
targetPort: 40051
nodePort: 30451
selector:
role: controller
type: NodePort
---
apiVersion: v1
kind: Service
metadata:
name: service-ixia-c-port1
namespace: ixia-c
spec:
ports:
- name: port-5555
port: 5555
protocol: TCP
targetPort: 5555
- name: port-50071
port: 50071
protocol: TCP
targetPort: 50071
selector:
role: port1
---
apiVersion: v1
kind: Service
metadata:
name: service-ixia-c-port2
namespace: ixia-c
spec:
ports:
- name: port-5555
port: 5555
protocol: TCP
targetPort: 5555
- name: port-50071
port: 50071
protocol: TCP
targetPort: 50071
selector:
role: port2
================================================
FILE: deployments/k8s/overlays/one-traffic-port-eth0/config-map.yaml
================================================
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app: ixia-c
name: controller-config
namespace: ixia-c
data:
config.yaml: |
location_map:
- location: port1
endpoint: otg-port1.ixia-c.svc.cluster.local:5555
================================================
FILE: deployments/k8s/overlays/one-traffic-port-eth0/kustomization.yaml
================================================
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../bases/namespace
- ../../bases/otg-controller
- port1
- config-map.yaml
components:
- ../../components/images
================================================
FILE: deployments/k8s/overlays/one-traffic-port-eth0/port1/kustomization.yaml
================================================
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../bases/otg-traffic-port
patches:
- target:
version: v1
kind: Pod
name: otg-port
path: pod-patch.yaml
- target:
version: v1
kind: Service
name: otg-port
path: service-patch.yaml
================================================
FILE: deployments/k8s/overlays/one-traffic-port-eth0/port1/pod-patch.yaml
================================================
- op: replace
path: /metadata/labels/role
value: otg-port1
- op: replace
path: /metadata/name
value: otg-port1
================================================
FILE: deployments/k8s/overlays/one-traffic-port-eth0/port1/service-patch.yaml
================================================
- op: replace
path: /metadata/name
value: otg-port1
- op: replace
path: /spec/selector/role
value: otg-port1
================================================
FILE: deployments/k8s/overlays/two-traffic-ports-eth0/config-map.yaml
================================================
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app: ixia-c
name: controller-config
namespace: ixia-c
data:
config.yaml: |
location_map:
- location: port1
endpoint: otg-port1.ixia-c.svc.cluster.local:5555
- location: port2
endpoint: otg-port2.ixia-c.svc.cluster.local:5555
================================================
FILE: deployments/k8s/overlays/two-traffic-ports-eth0/gen-test-config.sh
================================================
#!/bin/sh
TEST_CONFIG_PATH=test-config.yaml
if [ ! -z ${1} ]
then
TEST_CONFIG_PATH=${1}
fi
gen_test_const() {
# get pod IPs to be used as source and destination IP in packets
txIp=$(kubectl get pod -n ixia-c otg-port1 -o 'jsonpath={.status.podIP}')
rxIp=$(kubectl get pod -n ixia-c otg-port2 -o 'jsonpath={.status.podIP}')
# send ping to flood arp table and extract gateway MAC
kubectl exec -n ixia-c otg-port1 -c ixia-c-traffic-engine -- ping -c 1 ${rxIp}
gatewayMac=$(kubectl exec -n ixia-c otg-port1 -c ixia-c-traffic-engine -- arp -a | head -n 1 | cut -d\ -f4)
txMac=$(kubectl exec -n ixia-c otg-port1 -c ixia-c-traffic-engine -- ifconfig eth0 | grep ether | sed 's/ */_/g' | cut -d_ -f3)
rxMac=$(kubectl exec -n ixia-c otg-port2 -c ixia-c-traffic-engine -- ifconfig eth0 | grep ether | sed 's/ */_/g' | cut -d_ -f3)
yml="otg_test_const:
txMac: ${txMac}
rxMac: ${rxMac}
gatewayMac: ${gatewayMac}
txIp: ${txIp}
rxIp: ${rxIp}
"
echo -n "$yml" | sed "s/^ //g" | tee -a ${TEST_CONFIG_PATH} > /dev/null
}
gen_config_common() {
yml="otg_speed: speed_1_gbps
otg_capture_check: true
otg_iterations: 100
otg_grpc_transport: false
"
echo -n "$yml" | sed "s/^ //g" | tee -a ${TEST_CONFIG_PATH} > /dev/null
}
gen_test_config() {
yml="otg_host: https://localhost:8443
otg_ports:
- port1
- port2
"
echo -n "$yml" | sed "s/^ //g" | tee ${TEST_CONFIG_PATH} > /dev/null
gen_config_common
gen_test_const
}
gen_test_config
================================================
FILE: deployments/k8s/overlays/two-traffic-ports-eth0/init-container.yaml
================================================
apiVersion: v1
kind: Pod
metadata:
name: _
spec:
initContainers:
- name: init-setup
image: ubuntu:22.04
command:
- bash
- -c
- apt-get update && apt-get install -y iptables && iptables -A INPUT -p udp --destination-port 7000:8000 -j DROP && iptables -A INPUT -p tcp --destination-port 7000:8000 -j DROP
securityContext:
privileged: true
================================================
FILE: deployments/k8s/overlays/two-traffic-ports-eth0/kustomization.yaml
================================================
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../bases/namespace
- ../../bases/otg-controller
- port1
- port2
- config-map.yaml
components:
- ../../components/images
patches:
- path: init-container.yaml
target:
kind: Pod
name: otg-port1
- path: init-container.yaml
target:
kind: Pod
name: otg-port2
================================================
FILE: deployments/k8s/overlays/two-traffic-ports-eth0/port1/kustomization.yaml
================================================
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../bases/otg-traffic-port
patches:
- target:
version: v1
kind: Pod
name: otg-port
path: pod-patch.yaml
- target:
version: v1
kind: Service
name: otg-port
path: service-patch.yaml
================================================
FILE: deployments/k8s/overlays/two-traffic-ports-eth0/port1/pod-patch.yaml
================================================
- op: replace
path: /metadata/labels/role
value: otg-port1
- op: replace
path: /metadata/name
value: otg-port1
================================================
FILE: deployments/k8s/overlays/two-traffic-ports-eth0/port1/service-patch.yaml
================================================
- op: replace
path: /metadata/name
value: otg-port1
- op: replace
path: /spec/selector/role
value: otg-port1
================================================
FILE: deployments/k8s/overlays/two-traffic-ports-eth0/port2/kustomization.yaml
================================================
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../bases/otg-traffic-port
patches:
- target:
version: v1
kind: Pod
name: otg-port
path: pod-patch.yaml
- target:
version: v1
kind: Service
name: otg-port
path: service-patch.yaml
================================================
FILE: deployments/k8s/overlays/two-traffic-ports-eth0/port2/pod-patch.yaml
================================================
- op: replace
path: /metadata/labels/role
value: otg-port2
- op: replace
path: /metadata/name
value: otg-port2
================================================
FILE: deployments/k8s/overlays/two-traffic-ports-eth0/port2/service-patch.yaml
================================================
- op: replace
path: /metadata/name
value: otg-port2
- op: replace
path: /spec/selector/role
value: otg-port2
================================================
FILE: deployments/k8s/readme.md
================================================
# Deploy Ixia-C in Kubernetes
This section hosts [kustomize](https://kustomize.io/) manifests for deploying various Ixia-C topologies in Kubernetes cluster.
### Prerequisites
- At least **2 x86 CPU cores**, **7GB RAM** and **30GB Free Hard Disk Space**
- Recommended OS is **Ubuntu 22.04 LTS** release.
- Go **1.20+**
- **Docker Engine** (Community Edition) - Needed when using kind for setting up K8S cluster
> Please make sure that current working directory is `deployments/k8s`.
### Initial Steps
1. Clone repository
```bash
git clone --recurse-submodules https://github.com/open-traffic-generator/ixia-c.git
cd ixia-c/deployments/k8s
```
2. Setup a Kubernetes cluster using [kind](https://kind.sigs.k8s.io/)
```bash
# install kind
go install sigs.k8s.io/kind@v0.20.0
# create cluster with custom configuration
kind create cluster --config=kind.yaml --wait 30s
# install compatible kubectl
sudo docker cp kind-control-plane:/usr/bin/kubectl /usr/local/bin/kubectl
sudo chmod 0755 /usr/local/bin/kubectl
# ensure all pods are ready
kubectl wait --for=condition=Ready pods --all --all-namespaces
```
3. (Optional) Load container images to cluster if offline images are preferred
Images to be used are specified in `components/images/kustomization.yaml`.
```bash
yml=components/images/kustomization.yaml
for i in $(seq $(grep -c newName ${yml}))
do
cap=$(grep -A1 -m${i} newName ${yml} | tail -n 2)
img=$(grep -A1 -m${i} newName ${yml} | tail -n 2 | grep newName | cut -d: -f2 | cut -d\ -f2)
img=${img}:$(grep -A1 -m${i} newName ${yml} | tail -n 2 | grep newTag | cut -d\" -f2)
docker pull "${img}" && kind load docker-image "${img}"
done
```
### Deploy Topology and Run Tests (Stateless traffic on eth0)
1. Deploy topology consisting of two Ixia-c port pods and one KENG controller pod
Topology manifests are kept inside `overlays/two-traffic-ports-eth0` which specifies `port1` and `port2`.
* iptables rule is configured on both ports to drop UDP/TCP packets destined for ports 7000-8000
* number of ports can be increased by adding new port dirs similar to `port1` and using it in rest of the files
```bash
# deploy Ixia-c with two ports that only support stateless traffic over eth0
kubectl apply -k overlays/two-traffic-ports-eth0
# ensure all Ixia-c pods are ready
kubectl wait --for=condition=Ready pods --all -n ixia-c
```
2. Generate test pre-requisites
The sample test requires `conformance/test-config.yaml` which is auto-generated:
* KENG controller / port endpoints
* common port / flow properties
* values like port pod IPs, gateway MAC on tx port, etc.
```bash
overlays/two-traffic-ports-eth0/gen-test-config.sh ../../conformance/test-config.yaml
# check contents
cat ../../conformance/test-config.yaml
```
3. Run sample test
The test being run for this specific topology is `conformance/feature/b2b/packet/udp/udp_port_value_eth0_test.go`
```bash
cd ../../conformance
CGO_ENABLED=0 go test -v -count=1 -p=1 -timeout 3600s -tags="all" -run="^TestUdpPortValueEth0$" ./...
```
================================================
FILE: deployments/raw-one-arm.yml
================================================
version: '3.9'
services:
controller:
image: ghcr.io/open-traffic-generator/keng-controller:${CONTROLLER_VERSION:-latest}
command: --accept-eula
network_mode: "host"
restart: always
traffic_engine:
image: ghcr.io/open-traffic-generator/ixia-c-traffic-engine:${TRAFFIC_ENGINE_VERSION:-latest}
network_mode: "host"
restart: always
privileged: true
cpuset: ${CPU_CORES_IFC1:-"0,1,2"}
environment:
- OPT_LISTEN_PORT=${TCP_PORT_IFC1:-5555}
- ARG_IFACE_LIST=virtual@af_packet,${IFC1}
- OPT_NO_HUGEPAGES=Yes
aur:
image: ghcr.io/open-traffic-generator/keng-app-usage-reporter:${AUR_VERSION:-latest}
network_mode: "host"
restart: always
================================================
FILE: deployments/raw-three-arm-mesh.yml
================================================
version: '3.9'
services:
controller:
image: ghcr.io/open-traffic-generator/keng-controller:${CONTROLLER_VERSION:-latest}
command: --accept-eula
network_mode: "host"
restart: always
traffic_engine_1:
image: ghcr.io/open-traffic-generator/ixia-c-traffic-engine:${TRAFFIC_ENGINE_VERSION:-latest}
restart: always
privileged: true
ports:
- "${TCP_PORT_IFC1:-5555}:5555"
cpuset: ${CPU_CORES_IFC1:-"0,1,2"}
environment:
- OPT_LISTEN_PORT=5555
- ARG_IFACE_LIST=virtual@af_packet,eth0
- OPT_NO_HUGEPAGES=Yes
traffic_engine_2:
image: ghcr.io/open-traffic-generator/ixia-c-traffic-engine:${TRAFFIC_ENGINE_VERSION:-latest}
restart: always
privileged: true
ports:
- "${TCP_PORT_IFC2:-5556}:5555"
cpuset: ${CPU_CORES_IFC2:-"0,3,4"}
environment:
- OPT_LISTEN_PORT=5555
- ARG_IFACE_LIST=virtual@af_packet,eth0
- OPT_NO_HUGEPAGES=Yes
traffic_engine_3:
image: ghcr.io/open-traffic-generator/ixia-c-traffic-engine:${TRAFFIC_ENGINE_VERSION:-latest}
restart: always
privileged: true
ports:
- "${TCP_PORT_IFC3:-5557}:5555"
cpuset: ${CPU_CORES_IFC3:-"0,5,6"}
environment:
- OPT_LISTEN_PORT=5555
- ARG_IFACE_LIST=virtual@af_packet,eth0
- OPT_NO_HUGEPAGES=Yes
aur:
image: ghcr.io/open-traffic-generator/keng-app-usage-reporter:${AUR_VERSION:-latest}
network_mode: "host"
restart: always
================================================
FILE: deployments/raw-two-arm.yml
================================================
version: '3.9'
services:
controller:
image: ghcr.io/open-traffic-generator/keng-controller:${CONTROLLER_VERSION:-latest}
command: --accept-eula
network_mode: "host"
restart: always
traffic_engine_1:
image: ghcr.io/open-traffic-generator/ixia-c-traffic-engine:${TRAFFIC_ENGINE_VERSION:-latest}
network_mode: "host"
restart: always
privileged: true
cpuset: ${CPU_CORES_IFC1:-"0,1,2"}
environment:
- OPT_LISTEN_PORT=${TCP_PORT_IFC1:-5555}
- ARG_IFACE_LIST=virtual@af_packet,${IFC1}
- OPT_NO_HUGEPAGES=Yes
traffic_engine_2:
image: ghcr.io/open-traffic-generator/ixia-c-traffic-engine:${TRAFFIC_ENGINE_VERSION:-latest}
network_mode: "host"
restart: always
privileged: true
cpuset: ${CPU_CORES_IFC2:-"0,3,4"}
environment:
- OPT_LISTEN_PORT=${TCP_PORT_IFC2:-5556}
- ARG_IFACE_LIST=virtual@af_packet,${IFC2}
- OPT_NO_HUGEPAGES=Yes
aur:
image: ghcr.io/open-traffic-generator/keng-app-usage-reporter:${AUR_VERSION:-latest}
network_mode: "host"
restart: always
================================================
FILE: docs/CNAME
================================================
ixia-c.dev
================================================
FILE: docs/architecture.md
================================================
================================================
FILE: docs/contribute.md
================================================
# Contribute
We encourage you to contribute to Ixia-c by :
- using it
- reporting issues
- requesting enhancements
- contributing your Ixia-c based use-cases
- reviewing and contributing to [Open Traffic Generator Data Models](https://github.com/open-traffic-generator/models)
You can reach out to us on Slack as noted [here](support.md).
================================================
FILE: docs/deployments-containerlab.md
================================================
# Deploy Ixia-c-one using containerlab
Ixia-c-one is deployed as single-container application by using [containerlab](https://containerlab.dev/quickstart/) that consists of the following services:
* **containerlab**: Containerlab provides a CLI for orchestrating and managing container-based networking labs. It starts the containers, builds a virtual wiring between them to create lab topologies depending on a user's choice, and manages the labs lifecycle.
* **Ixia-c-one**: Keysight Ixia-c-one is a single-container distribution of Ixia-c, which in turn is Keysight's reference implementation of Open Traffic Generator API.
Meet the [keysight_ixia-c-one](https://containerlab.dev/manual/kinds/keysight_ixia-c-one) kind! It is available from containerlab [release 0.26](https://containerlab.dev/rn/0.26/#keysight-ixia-c).
* **srl linux**: Nokia SR Linux is a truly open network operating system (NOS), that makes your data center switching infrastructure more scalable, more flexible, and simpler to operate.

## Install containerlab
```sh
# download and install the latest release (may require sudo)
bash -c "$(curl -sL https://get.containerlab.dev)"
```
## Deploy the topology
* You can find a sample topology definition in <https://containerlab.dev/lab-examples/ixiacone-srl/>, which consists of Nokia SR Linux and Ixia-c-one nodes that are connected to one-another.
* This consists of a Keysight ixia-c-one node with 2 ports connected to 2 ports on an srl linux node via two point-to-point ethernet links. Both nodes are also connected with their management interfaces to the containerlab docker network.
```sh
# After downloading the sample topology file
containerlab deploy --topo ixiac01.clab.yml
```
- After deployment, you are now ready to run a test using the topology.
## Run a test
* Follow this [link](https://containerlab.dev/lab-examples/ixiacone-srl/#execution) to run a test.
## Destroy/Remove the topology
```sh
# delete a particular topology
containerlab destroy --topo ixiac01.clab.yml
```
================================================
FILE: docs/deployments-docker-compose.md
================================================
# Deploy Ixia-c using docker-compose
Deploying multiple services manually (along with the required parameters) is not always applicable in some scenarios. For convenience, the [deployments](../deployments) directory consists of the following `docker-compose` files:
- `*.yml`: Describes the services for a given scenario and the deployment parameters that are required to start them.
- `.env`: Holds the default parameters, that are used across all `*.yml` files. For example, the name of the interface, the version of docker images, and etc.
If a concerned `.yml` file does not include certain variables from `.env`, those can then safely be ignored.
Follwoing is the example of a usual workflow, by using `docker-compose`.
```sh
# change default parameters if needed; e.g. interface name, image version, etc.
vi deployments/.env
# deploy and start services for community users
docker-compose -f deployments/<scenario>.yml up -d
# stop and remove services deployed
docker-compose -f deployments/<scenario>.yml down
```
On most of the systems, `docker-compose` needs to be installed separately even if the docker is already installed. For more information, see [docker prerequisites](prerequisites.md#docker) .
>All the scenarios that are mentioned in the following sections, describe both manual and automated (requiring docker-compose) steps.
## Deployment Parameters
### Controller
| Controller Parameters | Optional | Default | Description |
|-----------------------------|-----------|-------------------------|-----------------------------------------------------------------|
| --debug | Yes | false | Enables high volume logs with debug info for better diagnostics.|
| --disable-app-usage-reporter| Yes | false | Disables sending of usage data to the app-usage-reporter. |
| --http-port | Yes | 8443 | TCP port for HTTP server. |
| --aur-host | Yes | https://localhost:5600 | Overrides the location of the app-usage-reporter. |
| --accept-eula | No | NA | Indicates that the user has accepted EULA, otherwise the controller will not boot up. |
| --license-servers | No | NA | Indicates the ip address of license servers for commercial users. |
Docker Parameters:
- `--net=host`: It is recommended to allow the use of the host network stack, in order to address the traffic-engine containers using `localhost` instead of `container-ip`, when deployed on the same host.
- `-d`: This starts the container in background.
Example:
```bash
# For community users
docker run --net=host -d ghcr.io/open-traffic-generator/keng-controller --accept-eula --debug --http-port 5050
# For commercial users
docker run --net=host -d ghcr.io/open-traffic-generator/keng-controller --accept-eula --debug --http-port 5050 --license-servers="ip/hostname of license server"
```
### Traffic Engine
| Environment Variables | Optional | Default | Description |
|-----------------------------|-----------|-------------------------|-----------------------------------------------------------------|
| ARG_IFACE_LIST | No | NA | Name of the network interface to bind to. It must be visible to the traffic-engine's network namespace. For example, `virtual@af_packet,eth1` where `eth1` is the interface name and `virtual@af_packet` indicates that the interface is managed by the host kernel's network stack.|
| OPT_LISTEN_PORT | Yes | "5555" | TCP port on which the controller can establish connection with the traffic-engine.|
| OPT_NO_HUGEPAGES | Yes | "No" | If set to `Yes`, it disables hugepages in the OS. The hugepages needs to be disabled when the network interfaces are managed by the host kernel's stack.|
Docker Parameters:
- `--net=host`: This is required if the traffic-engine needs to bind to a network interface that is visible in the host network stack but not inside the docker's network.
- `--privileged`: This is required because the traffic-engine needs to exercise capabilities that require elevated privileges.
- `--cpuset-cpus`: The traffic-engine usually requires 1 shared CPU core for management activities and 2 exclusive CPU cores, each for the transmit engine and receive engine. The shared CPU core can be shared across multiple traffic-engines. For example, `--cpuset-cpus="0,1,2"` which indicates that cpu0 is shared, cpu1 is used for transmit and cpu2 is used for receive. If CPU cores are not specified, any arbitrary CPU cores will be chosen.
> If enough CPU cores are not provided, the available CPU cores may be shared among management, transmit, and the receive engines, that can occasionally result in lower performance.
- `-d`: This starts the container in background.
Example:
```bash
docker run --net=host --privileged -d \
-e OPT_LISTEN_PORT="5555" \
-e ARG_IFACE_LIST="virtual@af_packet,eth1" \
-e OPT_NO_HUGEPAGES="Yes" \
--cpuset-cpus="0,1,2" \
ghcr.io/open-traffic-generator/ixia-c-traffic-engine
```
================================================
FILE: docs/deployments-kne.md
================================================
# Deploy Ixia-c using KNE
Ixia-c can be deployed in the k8s environment by using the [Kubernetes Network Emulation](https://github.com/openconfig/kne) that consists of the following services:
* **operator**: Serves API request from the clients and manages workflow across one or more traffic engines.
* **controller**: Serves API request from the clients and manages workflow across one or more traffic engines.
* **traffic-engine**: Generates, captures, and processes the traffic from one or more network interfaces (on linux-based OS).
* **protocol-engine**: Emulates layer3 networks and protocols such as BGP, ISIS, and etc (on linux-based OS).
* **gnmi-server**: Captures statistics from one or more network interfaces (on linux-based OS).
## System Prerequisites
### CPU and RAM
Following are the recommended resources for a basic use-case.
- `keng-operator`: Each instance requires at least 1 CPU core and 2GB RAM.
- `keng-controller`: Each instance requires at least 1 CPU core and 2GB RAM.
- `otg-gnmi-server`: Each instance requires at least 1 CPU core and 2GB RAM.
- `ixia-c-traffic-engine`: Each instance requires 2 dedicated CPU cores and 3GB dedicated RAM.
- `ixia-c-protocol-engine`: Each instance requires 4 dedicated CPU cores and 1GB dedicated RAM per port.
### OS and Software Prerequisites
- x86_64 Linux Distribution (Centos 7+ or Ubuntu 18+ have been tested)
- Docker 19+ (as distributed by https://docs.docker.com/)
- Go 1.17+
- kind 0.18+
## Install KNE
* The main use case we are interested in is the ability to bring up arbitrary topologies to represent a production topology. This would require multiple vendors as well as traffic generation and end hosts.
```sh
go install github.com/openconfig/kne/kne@latest
```
## Deploy keng-operator
* Ixia Operator defines CRD for Ixia network device (IxiaTG) and can be used to build up different network topologies with network devices from other vendors. Network interconnects between the topology nodes can be setup with various container network interface (CNI) plugins for Kubernetes for attaching multiple network interfaces to the nodes.
```sh
kubectl apply -f https://github.com/open-traffic-generator/keng-operator/releases/download/v0.3.5/ixiatg-operator.yaml
```
## Apply configmap
* The various Ixia component versions to be deployed is derived from the Ixia release version as specified in the IxiaTG config. These component mappings are captured in ixia-configmap.yaml for each Ixia release. The configmap, as shown in the snippet below, comprise of the Ixia release version ("release"), and the list of qualified component versions, for that release. Ixia Operator first tries to access these details from Keysight published releases; if unable to so, it tries to locate them in Kubernetes configmap. This allows users to have the operator load images from private repositories, by updating the configmap entries. Thus, for deployment with custom images, the user is expected to download release specific ixia-configmap.yaml from published releases. Then, in the configmap, update the specific container image "path" / "tag" fields and also update the "release" to some custom name. Start the operator first as specified in the deployment section below, before applying the configmap locally. After this the operator can be used to deploy the containers and services.
* For community users,
```json
apiVersion: v1
kind: ConfigMap
metadata:
name: ixiatg-release-config
namespace: ixiatg-op-system
data:
versions: |
{
"release": "1.53.0-1",
"images": [
{
"name": "controller",
"path": "ghcr.io/open-traffic-generator/keng-controller",
"tag": "1.53.0-1"
},
{
"name": "gnmi-server",
"path": "ghcr.io/open-traffic-generator/otg-gnmi-server",
"tag": "1.53.0"
},
{
"name": "traffic-engine",
"path": "ghcr.io/open-traffic-generator/ixia-c-traffic-engine",
"tag": "1.8.0.245"
},
{
"name": "protocol-engine",
"path": "ghcr.io/open-traffic-generator/ixia-c-protocol-engine",
"tag": "1.00.0.522"
},
{
"name": "ixhw-server",
"path": "ghcr.io/open-traffic-generator/keng-layer23-hw-server",
"tag": "1.53.0-3"
}
]
}
```
* For commercial users, `LICENSE_SERVERS` needs to be specified for `keng-controller` deployment.
```json
apiVersion: v1
kind: ConfigMap
metadata:
name: ixiatg-release-config
namespace: ixiatg-op-system
data:
versions: |
{
"release": "1.53.0-1",
"images": [
{
"name": "controller",
"path": "ghcr.io/open-traffic-generator/keng-controller",
"tag": "1.53.0-1",
"env": {
"LICENSE_SERVERS": "ip/hostname of license server"
}
},
{
"name": "gnmi-server",
"path": "ghcr.io/open-traffic-generator/otg-gnmi-server",
"tag": "1.53.0"
},
{
"name": "traffic-engine",
"path": "ghcr.io/open-traffic-generator/ixia-c-traffic-engine",
"tag": "1.8.0.245"
},
{
"name": "protocol-engine",
"path": "ghcr.io/open-traffic-generator/ixia-c-protocol-engine",
"tag": "1.00.0.522"
},
{
"name": "ixhw-server",
"path": "ghcr.io/open-traffic-generator/keng-layer23-hw-server",
"tag": "1.53.0-3"
}
]
}
```
```sh
# After saving the configmap snippet in a yaml file
kubectl apply -f ixiatg-configmap.yaml
```
## Deploy the topology
* The following snippet shows a simple KNE b2b topology.
```yaml
name: ixia-c
nodes:
- name: otg
vendor: KEYSIGHT
version: 1.53.0-1
services:
8443:
name: https
inside: 8443
40051:
name: grpc
inside: 40051
50051:
name: gnmi
inside: 50051
links:
- a_node: otg
a_int: eth1
z_node: otg
z_int: eth2
```
```sh
# After saving the topology snippet in a yaml file
kne create topology.yaml
```
* After deployment, you are now ready to run a test using this topology.
## Destroy/Remove the topology
```sh
# delete a particular topology
kne delete topology.yaml
```
================================================
FILE: docs/deployments.md
================================================
# Deployment
## Overview
Ixia-c is distributed and deployed as a multi-container application that consists of the following services:
* **controller**: Serves API request from the clients and manages workflow across one or more traffic engines.
* **traffic-engine**: Generates, captures, and processes traffic from one or more network interfaces (on linux-based OS).
* **app-usage-reporter**: (Optional) Collects anonymous usage report from the controller and uploads it to the Keysight Cloud, with minimal impact on the host resources.
All these services are available as docker images on the [GitHub Open-Traffic-Generator repository](https://github.com/orgs/open-traffic-generator/packages). To use specific versions of these images, see [Ixia-c Releases](releases.md) .

> Once the services are deployed, [conformance](https://github.com/open-traffic-generator/conformance/tree/main) (a collection of [snappi](https://pypi.org/project/snappi/) & [gosnappi](https://otg.dev/clients/gosnappi/) test scripts and configurations) can be setup to run against Ixia-c.
## Bootstrap
The Ixia-c services can either all be deployed on the same host or each on separate hosts (as long as they are mutually reachable over the network). There is no boot-time dependency between them, which allows **horizontal scalability** without interrupting the existing services.
You can establish a connectivity between the services in two ways. The options are as follows:
- **controller & traffic-engine**: The client pushes a traffic configuration to the controller, containing the `location` of the traffic engine.
- **controller & app-usage-reporter**: The Controller periodically tries to establish connectivity with the `app-usage-reporter` on a `location`, which can be overridden by using the controller's deployment parameters.
>The **location** (network address) of the traffic-engine and the app-usage-reporter must be reachable from the controller, even if they are not reachable from the client scripts.
## Deployment types
* [Using docker-compose](deployments-docker-compose.md)
* [Using containerlab](deployments-containerlab.md)
* [Using KNE](deployments-kne.md)
## Diagnostics
Check and download controller logs:
```sh
docker exec <container-id> cat logs/controller.log
# follow logs
docker exec <container-id> tail -f logs/controller.log
# check stdout output
docker logs <container-id>
# download logs
docker cp <container-id>:$(docker exec <container-id> readlink -f logs/controller.log) ./
```
Check and download traffic-engine logs:
```sh
docker exec <container-id> cat /var/log/usstream/usstream.log
# follow logs
docker exec <container-id> tail -f /var/log/usstream/usstream.log
# check stdout output
docker logs <container-id>
# download logs
docker cp <container-id>:/var/log/usstream/usstream.log ./
```
## Test Suite
## One-arm Scenario
> TODO: diagram
* Automated
```bash
docker-compose -f deployments/raw-one-arm.yml up -d # community users
# optionally stop and remove services deployed
docker-compose -f deployments/raw-one-arm.yml down # community users
```
* Manual
```bash
# start controller and app usage reporter
# community users
docker run --net=host -d ghcr.io/open-traffic-generator/keng-controller --accept-eula
# commercial users
docker run --net=host -d ghcr.io/open-traffic-generator/keng-controller --accept-eula --license-servers="ip/hostname of license server"
docker run --net=host -d ghcr.io/open-traffic-generator/keng-app-usage-reporter
# start traffic engine on network interface eth1, TCP port 5555 and cpu cores 0, 1, 2
docker run --net=host --privileged -d \
-e OPT_LISTEN_PORT="5555" \
-e ARG_IFACE_LIST="virtual@af_packet,eth1" \
-e OPT_NO_HUGEPAGES="Yes" \
--cpuset-cpus="0,1,2" \
ghcr.io/open-traffic-generator/ixia-c-traffic-engine
```
## Two-arm Scenario
> TODO: diagram
* Automated
```bash
docker-compose -f deployments/raw-two-arm.yml up -d # community users
# optionally stop and remove services deployed
docker-compose -f deployments/raw-two-arm.yml down # community users
```
* Manual
```bash
# start controller and app usage reporter
# community users
docker run --net=host -d ghcr.io/open-traffic-generator/keng-controller --accept-eula
# commercial users
docker run --net=host -d ghcr.io/open-traffic-generator/keng-controller --accept-eula --license-servers="ip/hostname of license server"
docker run --net=host -d ghcr.io/open-traffic-generator/keng-app-usage-reporter
# start traffic engine on network interface eth1, TCP port 5555 and cpu cores 0, 1, 2
docker run --net=host --privileged -d \
-e OPT_LISTEN_PORT="5555" \
-e ARG_IFACE_LIST="virtual@af_packet,eth1" \
-e OPT_NO_HUGEPAGES="Yes" \
--cpuset-cpus="0,1,2" \
ghcr.io/open-traffic-generator/ixia-c-traffic-engine
# start traffic engine on network interface eth2, TCP port 5556 and cpu cores 0, 3, 4
docker run --net=host --privileged -d \
-e OPT_LISTEN_PORT="5556" \
-e ARG_IFACE_LIST="virtual@af_packet,eth2" \
-e OPT_NO_HUGEPAGES="Yes" \
--cpuset-cpus="0,3,4" \
ghcr.io/open-traffic-generator/ixia-c-traffic-engine
```
## Three-arm Mesh Scenario
This scenario binds traffic engine to the management network interface, that belongs to the container which in turn is a part of the docker0 network.
> TODO: diagram
* Automated
```bash
docker-compose -f deployments/raw-three-arm-mesh.yml up -d # community users
# optionally stop and remove services deployed
docker-compose -f deployments/raw-three-arm-mesh.yml down # community users
```
* Manual
```bash
# start controller and app usage reporter
# community users
docker run --net=host -d ghcr.io/open-traffic-generator/keng-controller --accept-eula
# commercial users
docker run --net=host -d ghcr.io/open-traffic-generator/keng-controller --accept-eula --license-servers="ip/hostname of license server"
docker run --net=host -d ghcr.io/open-traffic-generator/keng-app-usage-reporter
# start traffic engine on network interface eth0, TCP port 5555 and cpu cores 0, 1, 2
docker run --privileged -d \
-e OPT_LISTEN_PORT="5555" \
-e ARG_IFACE_LIST="virtual@af_packet,eth0" \
-e OPT_NO_HUGEPAGES="Yes" \
-p 5555:5555 \
--cpuset-cpus="0,1,2" \
ghcr.io/open-traffic-generator/ixia-c-traffic-engine
# start traffic engine on network interface eth0, TCP port 5556 and cpu cores 0, 3, 4
docker run --privileged -d \
-e OPT_LISTEN_PORT="5555" \
-e ARG_IFACE_LIST="virtual@af_packet,eth0" \
-e OPT_NO_HUGEPAGES="Yes" \
-p 5556:5555 \
--cpuset-cpus="0,3,4" \
ghcr.io/open-traffic-generator/ixia-c-traffic-engine
# start traffic engine on network interface eth0, TCP port 5557 and cpu cores 0, 5, 6
docker run --privileged -d \
-e OPT_LISTEN_PORT="5555" \
-e ARG_IFACE_LIST="virtual@af_packet,eth0" \
-e OPT_NO_HUGEPAGES="Yes" \
-p 5557:5555 \
--cpuset-cpus="0,5,6" \
ghcr.io/open-traffic-generator/ixia-c-traffic-engine
```
### TODO: Multi-port per TE container
## Tests
Please follow [readme](https://github.com/open-traffic-generator/conformance/blob/main/readme.md) to run sample go/python tests.
================================================
FILE: docs/developer/hello-snappi.md
================================================
## Use Case
This tutorial explains some key elements that are required to write a **snappi script** for exercising the following topology.
* Send 1000 UDP packets back and forth between the interfaces `eth1` & `eth2` at a rate of 1000 packets per second.
* Ensure that the correct number of valid UDP packets are received on both the ends, by using port capture and port metrics.
The [hello_snappi.py](https://github.com/open-traffic-generator/snappi-tests/tree/3ffe20f/scripts/hello_snappi.py) script covers this extensively.

## Setup
You can start by setting up the topology as described above. For more detail, see [deployment steps for two-arm scenario](../deployments.md#two-arm-scenario).
```sh
git clone --recurse-submodules https://github.com/open-traffic-generator/ixia-c && cd ixia-c
docker-compose -f deployments/raw-two-arm.yml up -d
```
After the set up is completed, install the python packages:
* [snappi](https://pypi.org/project/snappi/) - client SDK auto-generated from [Open Traffic Generator API](https://github.com/open-traffic-generator/models).
* [dpkt](https://pypi.org/project/dpkt/) - for processing `.pcap` files.
```sh
python -m pip install --upgrade snappi==1.53.0 dpkt
```
## Create the API Handle
The first step in any snappi script is to import the `snappi` package and instantiate an `api` object, where the `location` parameter takes the HTTPS/gRPC address of the controller and `verify` is used to turn off the insecure certificate warning.
If the controller is deployed with a non-default TCP port by using the [deployment parameters](../deployments.md#deployment-parameters), it must be specified explicitly in the address (default port of HTTPS is 8443 and gRPC is 40051).
```python
import snappi
# HTTPS
api = snappi.api(location='https://localhost', verify=False)
# or with non-default TCP port
api = snappi.api(location='https://localhost:8080', verify=False)
#gRPC
api = snappi.api(location="localhost:40051", transport=snappi.Transport.GRPC)
# or with non-default TCP port
api = snappi.api(location="localhost:50020", transport=snappi.Transport.GRPC)
```
<details>
<summary><b>Expand</b> This section provides the details on an optional parameter <code>ext</code> which specifies the <i>snappi extension</i> to be loaded.</summary><br/>
If a traffic generator does not natively support the [Open Traffic Generator API](https://github.com/open-traffic-generator/models), snappi can be extended to write a translation layer to bridge the gap. For example, [snappi extension for IxNetwork](https://pypi.org/project/snappi-ixnetwork/). This can be installed by using `python -m pip install --upgrade snappi[ixnetwork]`.
```python
import snappi
# location here refers to HTTPS address of IxNetwork API Server
api = snappi.api(location="https://localhost", ext='ixnetwork', verify=False)
```
</details>
## Configuration
You need to construct the traffic configuration to send it to the controller. Use the `api` object that you created previously. It will act as a handle for the following steps:
* Create new objects for API request (or response)
```python
cfg = api.config()
```
> `api.config()` is a factory function for creating an empty `snappi.Config` object, which encapsulates the parameters that the controller needs to configure different aspects of the traffic generator. The next sections discuss about these configuration parameters in details.
* Initiate the API requests (and get back response)
```python
# this pushes object of type `snappi.Config` to controller
api.set_config(cfg)
# this retrieves back object of type `snappi.Config` from controller
cfg = api.get_config()
```
> By default, API requests in snappi are made over HTTPS with payloads as a JSON string. Since each object in snappi inherits `SnappiObject` or `SnappiIter`, they all share a common method called `.serialize()` and `deserialize()`, that are used internally during the API requests, for valid conversion to / from a JSON string. You will find more about such conveniences offered by snappi along the way.
<details>
<summary><b>Expand</b> This section explains how you can effectively navigate through the <a href="https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.11/artifacts/openapi.yaml">snappi API documentation</a>.</summary><br/>
The objects and methods (for API calls) in snappi are auto-generated from an [Open API Generator YAML file](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.11/artifacts/openapi.yaml). This file adheres to the [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification), which can (by design) also be rendered as an interactive API documentation.
[ReDoc](https://redocly.github.io/redoc/) is an open-source tool that provides a similar functionality. It accepts a link to valid OpenAPI YAML file and generates a document where all the methods (for API calls) are mentioned in the left navigation bar and for each selected method, there's a request/response body description in the center of the page. These descriptions lay out the entire object tree that documents each node in detail.
The [snappi API documentation](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.11/artifacts/openapi.yaml) will always point to the API version **v0.11.11**. To use a different version, do the following:
* Identify the API version from [open-traffic-generator releases](https://github.com/open-traffic-generator/snappi/releases/download/v0.11.11/models-release) and replace **v0.11.11** in the URL with the intended snappi version.
* Open the [open-traffic-generator models](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.11/artifacts/openapi.yaml).
</details>
## Ports
Each instance of a **traffic-engine** is usually referred to as a `port`. As the ports are used to send or receive the traffic (as they are directly bound to the network interfaces), provide the following information to the config object, that you created earlier:
* `name`: An unique identifier for each port.
* `location`: A DNS name or TCP socket address of the traffic-engine (format is specific to a given traffic-engine implementations).
>Note: Unlike the config, creating a new port using `p = api.port()` is not required (and hence not supported), as the `snappi.Port` is never used directly as an API request or response.
```python
# config has an attribute called `ports` which holds an iterator of type
# `snappi.PortIter`, where each item is of type `snappi.Port` (p1 and p2)
p1, p2 = cfg.ports.port(name="p1", location="localhost:5555").port(
name="p2", location="localhost:5556"
)
```
> Instead of using `append()`, use factory method `.port()` on `cfg.ports` which instantiates `snappi.Port`, appends it to `cfg.ports`, and returns the entire iterator (so that it can be unpacked or accessed like a simple list). This is applicable to other iterators in snappi, for example, flows, capture, and layer1.
<details>
<summary><b>Expand</b> this section for more examples on snappi iterators.</summary>
```python
p = cfg.ports.port(name='p1').port(name='p2')
assert p[0].name == 'p1'
p = cfg.ports.port(name='p3')
assert p[2].name == 'p3'
# This will remove 3rd index port
cfg.ports.remove(2)
p4 = cfg.ports.port(name='p4')[-1]
assert p4.name == 'p4'
# This will clear all the ports
cfg.ports.clear()
p5 = cfg.ports.port(name='p5')[0]
assert p5.name == 'p5'
p6 = cfg.ports.add(name='p6')
assert p6.name == 'p6'
p7 = p6.clone()
p7.name = 'p7'
cfg.ports.append(p7)
assert p7.name == 'p7'
```
</details>
## Layer1
The `ports` that you configured earlier, may require a set up for `layer1` (physical layer) properties like speed, MTU, promiscuous mode, and etc.
```python
# config has an attribute called `layer1` which holds an iterator of type
# `snappi.Layer1Iter`, where each item is of type `snappi.Layer1` (ly)
ly = cfg.layer1.layer1(name="ly")[-1]
ly.speed = ly.SPEED_1_GBPS
# set same properties on both ports
ly.port_names = [p1.name, p2.name]
```
>Note: You can set an enum value (all uppercase) defined in the `ly`'s namespace, instead of using an arbitrary value to the `ly.speed`. These enum values are available in the [snappi API documentation](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.11/artifacts/openapi.yaml).
## Capture
To start capturing packets on both the ports, enable `capture`.
```python
# config has an attribute called `captures` which holds an iterator of type
# `snappi.CaptureIter`, where each item is of type `snappi.Capture` (cp)
cp = cfg.captures.capture(name="cp")[-1]
cp.port_names = [p1.name, p2.name]
```
### Flows
This section describes how to set up the traffic flows.
Each flow in snappi can be characterized based on the **tx/rx endpoints**, **duration**, **packet contents, packet rate, packet size**, and etc.
You can configure two flows, one that originates from port `p1` and the other from port `p2`.
```python
# config has an attribute called `flows` which holds an iterator of type
# `snappi.FlowIter`, where each item is of type `snappi.Flow` (f1, f2)
f1, f2 = cfg.flows.flow(name="flow p1->p2").flow(name="flow p2->p1")
# and assign source and destination ports for each
f1.tx_rx.port.tx_name, f1.tx_rx.port.rx_name = p1.name, p2.name
f2.tx_rx.port.tx_name, f2.tx_rx.port.rx_name = p2.name, p1.name
# configure packet size, rate and duration for both flows
f1.size.fixed, f2.size.fixed = 128, 256
for f in cfg.flows:
# send 1000 packets and stop
f.duration.fixed_packets.packets = 1000
# send 1000 packets per second
f.rate.pps = 1000
```
Optionally, the flow duration and rate can be configured as follows:
```python
# send packets for 5 seconds and stop (we could also specify duration in terms
# of continuous or bursts)
f.duration.fixed_seconds.seconds = 5
# send packets at 50% of configured speed (we could also specify absolute rates
# in terms of bps, kbps, etc.)
f.rate.percentage = 50
```
>Note: The `f.rate` is **polymorphic** in nature. It can only be used to set either `pps` or `percentage`, but not both. A special attribute `choice` is used in such cases, which holds the name of the attribute that is currently in use.
In snappi, `f.rate.choice` is automatically set based on the attribute that was last accessed. For example,
```python
f.rate.pps = 100
print(f.rate.serialize())
# output
{
"choice": "pps",
"pps": 100
}
```
>You can set (or access) the `f1.rate.pps` without instantiating an object of type `snappi.FlowRate`, which is held by the `f1.rate`. **Accessing an uninitialized attribute** automatically initializes it with the type of object it holds.
## Protocol Headers
Packets sent out in a `flow` needs to be described in terms of the underlying **protocol** and **payload** contents. If no such description is provided, a simple ethernet frame is configured by default.
The following section describes how you can construct a packet by adding Ethernet, IPv4, and UDP headers (strictly in an order, in which it should appear in the TCP/IP stack).
```python
# configure packet with Ethernet, IPv4 and UDP headers for both flows
eth1, ip1, udp1 = f1.packet.ethernet().ipv4().udp()
eth2, ip2, udp2 = f2.packet.ethernet().ipv4().udp()
```
The `f1.packet` is an iterator which holds the items of type `snappi.FlowHeader` (a **polymorphic** type, instead of the **non-polymorphic** types). Hence, snappi automatically does the following under the hood:
```python
eth1, ip1, udp1 = f.packet.header().header().header()
# set enum choice for each header and initialize intended object with empty
# fields just by accessing it
eth1.choice = e.ETHERNET
eth1.ethernet
ip1.choice = i.IPV4
ip1.ipv4
udp1.choice = u.UDP
udp1.udp
```
At this point, the headers still contain the default field values. Now, you can assign specific values to the various header fields.
> The checksum and length fields in the most of the headers are automatically calculated and inserted before the packets are sent.
### Setup Ethernet
For the Ethernet header, assign a static source and the destination MAC address value. The ethernet type field is *automatically* set to `0x800`, since the next header is IPv4.
```python
# set source and destination MAC addresses
eth1.src.value, eth1.dst.value = "00:AA:00:00:04:00", "00:AA:00:00:00:AA"
eth2.src.value, eth2.dst.value = "00:AA:00:00:00:AA", "00:AA:00:00:04:00"
```
### Setup IPv4
For IPv4 header also, assign a static source and the destination IPv4 address value. The IP protocol field is *automatically* set to `0x11`, since the next protocol in the stack is UDP.
```python
# set source and destination IPv4 addresses
ip1.src.value, ip1.dst.value = "10.0.0.1", "10.0.0.2"
ip2.src.value, ip2.dst.value = "10.0.0.2", "10.0.0.1"
```
### Setup UDP
With the UDP header, instead of assigning a single (fixed) value for the header fields, assign multiple values.
You can achieve this in snappi by using `increment`, `decrement`, and `list` patterns.
```python
# set incrementing port numbers as source UDP ports
udp1.src_port.increment.start = 5000
udp1.src_port.increment.step = 2
udp1.src_port.increment.count = 10
udp2.src_port.increment.start = 6000
udp2.src_port.increment.step = 4
udp2.src_port.increment.count = 10
# assign list of port numbers as destination UDP ports
udp1.dst_port.values = [4000, 4044, 4060, 4074]
udp2.dst_port.values = [8000, 8044, 8060, 8074, 8082, 8084]
```
The above snippet will result in a sequence of packets as shown in the figure below.

> The patterns for headers fields in snappi provide a very flexible way to generate millions of unique packets to test the DUT functionalities, like hashing based on 5-tuple. For more information, see [common snappi constructs](snappi-constructs.md) .
## Start Capture and Traffic
After you have added all the intended configuration parameters to the `cfg`, do the following:
* Push it to the controller, so that the connection with the intended traffic-engines can be established and the intended configuration is applied (to each one of them).
* Start capturing packets on the configured ports.
* Start sending packets from the configured ports.
Every time the `api.set_config()` is called, it essentially resets the state of the controller by **tearing down** any previous connections with traffic-engines and **overriding** any previous configuration. If the call fails at some point, `api.get_config()` will return an empty config.
```python
# push configuration to controller
api.set_config(cfg)
# start packet capture on configured ports
cs = api.capture_state()
cs.state = cs.START
api.set_capture_state(cs)
# start transmitting configured flows
ts = api.transmit_state()
ts.state = ts.START
api.set_transmit_state(ts)
```
> The transmit or capture will be started on all configured flows or ports respectively, unless you provide any specific flow or port name. For example, `cs.port_names = ['p1']`, `ts.flow_names = ['f1']`.
## Fetch and Validate Metrics
As you are sending 1000 packets, at a rate of 1000 packets per second, it should take 1 second for the transmit to complete. You can validate the same by using `metrics`.
The API supports different kinds of metrics, but focus on the `port_metrics` which are similar to the linux network interface stats.
```python
# create a port metrics request and filter based on port names
req = api.metrics_request()
req.port.port_names = [p.name for p in cfg.ports]
# include only sent and received packet counts
req.port.column_names = [req.port.FRAMES_TX, req.port.FRAMES_RX]
# fetch port metrics
res = api.get_metrics(req)
# calculate total frames sent and received across all configured ports
total_tx = sum([m.frames_tx for m in res.port_metrics])
total_rx = sum([m.frames_rx for m in res.port_metrics])
expected = sum([f.duration.fixed_packets.packets for f in cfg.flows])
assert expected == total_tx and total_rx >= expected
```
> Note: Usually this snippet needs to be executed multiple times, until the assertion in the end stands true or a timeout occurs. You can use a function called `wait_for()` in the `hello_snappi.py` script to achieve this.
## Fetch and Validate Captures
Validation by using metrics is limited to counters (for example, total transmitted, total received). To really inspect each packet received, you can use the capture API.
This API is a little different from the others, in the following ways:
* It returns a sequence of raw bytes (representing `.pcap` file) instead of a JSON string.
* It needs to be fed to a tool that can inspect `.pcap` files. For example, `dpkt` or `tcpdump`.
This snippet uses `dpkt` to ensure that each packet received is a valid UDP packet.
```python
for p in cfg.ports:
# create capture request and filter based on port name
req = api.capture_request()
req.port_name = p.name
# fetch captured pcap bytes and feed it to pcap parser dpkt
pcap = dpkt.pcap.Reader(api.get_capture(req))
for _, buf in pcap:
# check if current packet is a valid UDP packet
eth = dpkt.ethernet.Ethernet(buf)
assert isinstance(eth.data.data, dpkt.udp.UDP)
```
Optionally, the following snippet can be used in order to do `tcpdump -r cap.pcap` (inspect captures by using tcpdump).
```python
pcap_bytes = api.get_capture(req)
with open('cap.pcap', 'wb') as p:
p.write(pcap_bytes.read())
```
## Putting It All Together
`snappi` provides a fair level of abstraction and ease-of-use while constructing traffic configuration, compared to the [equivalent in JSON](https://github.com/open-traffic-generator/snappi-tests/tree/3ffe20f/configs/hello_snappi.json). More such comparisons can be found in [common snappi constructs](snappi-constructs.md).
For more information on snappi (per-flow metrics, latency measurements, custom payloads, and etc) and examples on the pytest-based test scripts and utilities, see [snappi-tests](https://github.com/open-traffic-generator/snappi-tests/tree/3ffe20f).
================================================
FILE: docs/developer/introduction.md
================================================
# Developer guide introduction
Introduction to snappi
================================================
FILE: docs/developer/snappi-constructs.md
================================================
# Common snappi constructs
## Overview
Every object in snappi can be serialized to or deserialized from a JSON string which conforms to [Open Traffic Generator API](https://github.com/open-traffic-generator/models). This facilitates storing traffic configurations as JSON files and reusing them in API calls with or without further modifications.
* Create a sample config
```python
import snappi
api = snappi.api()
config = api.config()
config.ports.port(name='p1', location='localhost:5555')
config.flows.flow(name='f1')
```
* Serialize to JSON (or python dictionary or YAML)
```python
json_str = config.serialize()
# serialize child of config object to JSON string
json_str = config.ports.serialize()
yaml_str = config.serialize(encoding=config.YAML)
obj_dict = config.serialize(encoding=config.DICT)
```
* Deserialize from JSON (or python dictionary or YAML)
```python
# whether the argument is JSON or YAML or dict is automatically determined
config.deserialize('{"ports": [{"name": "p2", "location": "localhost:5556"}]}')
# deserialize child of config object from JSON string
config.flows.deserialize('[{"name": "f1"}]')
config.deserialize({"ports": [{"name": "p1", "location": "localhost:5555"}]})
config.deserialize('ports:\n- name: p1\n location: localhost:5555\n')
```
* Pass either snappi object or equivalent JSON string as argument to API calls
```python
config = api.config()
config.ports.port(name='p1', location='localhost:5555')
# config will be serialized to JSON string and sent on wire
api.set_config(config)
json_str = '{"ports": [{"name": "p1", "location": "localhost:5555"}]}'
# JSON string will be directly sent on wire
api.set_config(json_str)
```
Following sections discuss most commonly used constructs in snappi comparing each one of them with equivalent JSON snippet.
For brevity, snippet for config creation is not included (since it's the same across all).
## Flows
This section deals with flow configuration and control.
### Unidirectional Flow
<details>
<summary>
A simple unidirectional flow for a **one-arm** test.
</summary>
<table>
<tr>
<th>
snappi
</th>
<th>
json
</th>
</tr>
<tr>
<td>
```python
p1 = config.ports.port(name='p1', \
location='localhost:5555')[-1]
f1 = config.flows.flow(name='f1')[-1]
f1.tx_rx.port.tx_name = p1.name
```
</td>
<td>
```json
{
"ports": [
{
"location": "localhost:5555",
"name": "p1"
}
],
"flows": [
{
"name": "f1",
"tx_rx": {
"port": {
"tx_name": "p1"
},
"choice": "port"
}
}
]
}
```
</td>
</tr>
</table>
</details>
### Bidirectional Flows
<details>
<summary>A bi-directional flow between two ports.</summary>
<table>
<tr><th>snappi</th><th>json</th></tr><tr>
<td>
```python
p1, p2 = ( \
config.ports \
.port(name='p1', location='localhost:5555') \
.port(name='p2', location='localhost:5556')
)
f1, f2 = config.flows.flow(name='flow p1->p2'). \
flow(name='flow p2->p1')
f1.tx_rx.port.tx_name = p1.name
f1.tx_rx.port.rx_name = p2.name
f2.tx_rx.port.tx_name = p2.name
f2.tx_rx.port.rx_name = p1.name
```
</td>
<td>
```json
{
"ports": [
{
"location": "localhost:5555",
"name": "p1"
},
{
"location": "localhost:5556",
"name": "p2"
}
],
"flows": [
{
"name": "flow p1->p2",
"tx_rx": {
"port": {
"tx_name": "p1",
"rx_name": "p2"
},
"choice": "port"
}
},
{
"name": "flow p2->p1",
"tx_rx": {
"port": {
"tx_name": "p2",
"rx_name": "p1"
},
"choice": "port"
}
}
]
}
```
</td>
</tr></table>
</details>
### Meshed Flows
<details>
<summary>Fully meshed flows between four ports. Each port sends flows to all the ports (except itself). This example is for four ports, it can be easily extended to an arbitrary number of ports.</summary>
<table>
<tr><th>snappi</th><th>json</th></tr><tr>
<td>
```python
import itertools
for i in range(1, 4):
config.ports.port(name='p%d' % i, \
location='localhost:%d' % (5554 + i))
for tx, rx in \
itertools.permutations([p.name for \
p in config.ports], 2):
f = config.flows.flow(name='flow %s->%s' \
% (tx, rx))[-1]
f.tx_rx.port.tx_name = tx
f.tx_rx.port.rx_name = rx
```
</td>
<td>
```json
{
"ports": [
{
"location": "localhost:5555",
"name": "p1"
},
{
"location": "localhost:5556",
"name": "p2"
},
{
"location": "localhost:5557",
"name": "p3"
}
],
"flows": [
{
"name": "flow p1->p2",
"tx_rx": {
"port": {
"tx_name": "p1",
"rx_name": "p2"
},
"choice": "port"
}
},
{
"name": "flow p1->p3",
"tx_rx": {
"port": {
"tx_name": "p1",
"rx_name": "p3"
},
"choice": "port"
}
},
{
"name": "flow p2->p1",
"tx_rx": {
"port": {
"tx_name": "p2",
"rx_name": "p1"
},
"choice": "port"
}
},
{
"name": "flow p2->p3",
"tx_rx": {
"port": {
"tx_name": "p2",
"rx_name": "p3"
},
"choice": "port"
}
},
{
"name": "flow p3->p1",
"tx_rx": {
"port": {
"tx_name": "p3",
"rx_name": "p1"
},
"choice": "port"
}
},
{
"name": "flow p3->p2",
"tx_rx": {
"port": {
"tx_name": "p3",
"rx_name": "p2"
},
"choice": "port"
}
}
]
}
```
</td>
</tr></table>
</details>
### Protocol Headers With Fixed Fields
<details>
<summary>Simple flow with Ethernet, IP and TCP protocol headers.</summary>
<table>
<tr><th>snappi</th><th>json</th></tr><tr>
<td>
```python
p1 = config.ports.port(name='p1', \
location='localhost:5555')[-1]
f1 = config.flows.flow(name='f1')[-1]
f1.tx_rx.port.tx_name = p1.name
eth, ip, tcp = f1.packet.ethernet().ipv4().tcp()
eth.dst.value = '00:00:00:00:00:AA'
ip.dst.value = '192.168.1.1'
tcp.dst_port.value = 5000
```
</td>
<td>
```json
{
"ports": [
{
"location": "localhost:5555",
"name": "p1"
}
],
"flows": [
{
"name": "f1",
"tx_rx": {
"port": {
"tx_name": "p1"
},
"choice": "port"
},
"packet": [
{
"ethernet": {
"dst": {
"value": "00:00:00:00:00:AA",
"choice": "value"
}
},
"choice": "ethernet"
},
{
"ipv4": {
"dst": {
"value": "192.168.1.1",
"choice": "value"
}
},
"choice": "ipv4"
},
{
"tcp": {
"dst_port": {
"value": 5000,
"choice": "value"
}
},
"choice": "tcp"
}
]
}
]
}
```
</td>
</tr></table>
</details>
### Protocol Headers With Varying Fields
<details>
<summary>Flow with Ethernet, IP and TCP headers. Ethernet destination MAC address, destination IP address and TCP destination port are varied using patterns.</summary>
<table>
<tr><th>snappi</th><th>json</th></tr><tr>
<td>
```python
p1 = config.ports.port(name='p1', \
location='localhost:5555')[-1]
f1 = config.flows.flow(name='f1')[-1]
f1.tx_rx.port.tx_name = p1.name
eth, ip, tcp = f1.packet.ethernet().ipv4().tcp()
eth.src.value = '00:00:00:00:00:AA'
eth.dst.values = ['00:00:00:00:00:AB', \
'00:00:00:00:00:AC']
ip.src.value = '192.168.1.1'
ip.dst.increment.start = '192.168.1.2'
ip.dst.increment.step = '0.0.0.1'
ip.dst.increment.count = 2
tcp.src_port.value = 5000
tcp.dst_port.decrement.start = 5002
tcp.dst_port.decrement.step = 1
tcp.dst_port.decrement.count = 2
tcp.seq_num.values = [1, 2]
```
</td>
<td>
```json
{
"ports": [
{
"location": "localhost:5555",
"name": "p1"
}
],
"flows": [
{
"name": "f1",
"tx_rx": {
"port": {
"tx_name": "p1"
},
"choice": "port"
},
"packet": [
{
"ethernet": {
"src": {
"value": "00:00:00:00:00:AA",
"choice": "value"
},
"dst": {
"values": [
"00:00:00:00:00:AB",
"00:00:00:00:00:AC"
],
"choice": "values"
}
},
"choice": "ethernet"
},
{
"ipv4": {
"src": {
"value": "192.168.1.1",
"choice": "value"
},
"dst": {
"increment": {
"start": "192.168.1.2",
"step": "0.0.0.1",
"count": 2
},
"choice": "increment"
}
},
"choice": "ipv4"
},
{
"tcp": {
"src_port": {
"value": 5000,
"choice": "value"
},
"dst_port": {
"decrement": {
"start": 5002,
"step": 1,
"count": 2
},
"choice": "decrement"
},
"seq_num": {
"values": [
1,
2
],
"choice": "values"
}
},
"choice": "tcp"
}
]
}
]
}
```
</td>
</tr></table>
</details>
### Start Flow Transmit
<details>
<summary>Start transmit on a certain set of flows.</summary>
<table>
<tr><th>snappi</th><th>json</th></tr><tr>
<td>
```python
ts = api.control_state()
ts.traffic.flow_transmit.state = ts.traffic.flow_transmit.START # noqa
ts.traffic.flow_transmit.flow_names = ['f1', 'f2']
res = api.set_control_state(ts)
```
</td>
<td>
```json
{
"choice": "traffic",
"traffic": {
"choice": "flow_transmit",
"flow_transmit": {
"flow_names": [
"f1",
"f2"
],
"state": "start"
}
}
}
```
</td>
</tr></table>
</details>
## Capture
Capture configuration and control
### Capture Configuration
<details>
<summary>Configure capture prior to starting capture.</summary>
</details>
### Start Capture
<details>
<summary>Start capture on a set of ports.</summary>
<table>
<tr><th>snappi</th><th>json</th></tr><tr>
<td>
```python
cs = api.control_state()
cs.port.capture.state = cs.port.capture.START
cs.port.capture.port_names = ['p1', 'p2']
res = api.set_control_state(cs)
```
</td>
<td>
```json
{
"choice": "port",
"port": {
"capture": {
"port_names": [
"p1",
"p2"
],
"state": "start"
},
"choice": "capture"
}
}
```
</td>
</tr></table>
</details>
### Get Capture
<details>
<summary>Retrieve capture for a given port. Save capture to a .pcap file (python only).</summary><table>
<tr><th>snappi</th><th>json</th></tr><tr>
<td>
```python
req = api.capture_request()
req.port_name = 'p1'
with open('capture.pcap', 'w') as pcap:
pcap.write(api.get_capture(req).read())
```
</td>
<td>
```json
{
"port_name": "p1"
}
```
</td>
</tr></table>
</details>
## Metrics
### Port Metrics
<details>
<summary>Get port statistics for a given set of ports.</summary>
<table>
<tr><th>snappi</th><th>json</th></tr><tr>
<td>
```python
req = api.metrics_request()
req.port.port_names = ['tx', 'rx']
req.port.column_names = [req.port.FRAMES_TX, \
req.port.FRAMES_RX]
res = api.get_metrics(req)
assert res[0].frames_tx == res[1].frames_rx
```
</td>
<td>
```json
{
"port": {
"port_names": [
"p1",
"p2"
],
"column_names": [
"frames_tx",
"frames_rx"
]
},
"choice": "port"
}
```
</td>
</tr></table>
</details>
### Flow Metrics
<details>
<summary>Get flow statistics.</summary>
Blah
</details>
## TBD
* how to create a flow with certain protocol headers
* how to create a flow to test 5-tuple hashing
* how to create flows with changing flow sizes
* how to create stacked vlans
* creating bursty flows
* how to disable timestamps, signature
================================================
FILE: docs/developer/snappi-install.md
================================================
# Installing Snappi
The procedures explained in this section helps to install and configure snappi for an Open Traffic Generator API.
The test scripts written in **gosnappi**, and the auto-generated Go SDK, can be executed against any traffic generator that conforms to [Open Traffic Generator API](https://github.com/open-traffic-generator/models).
[Ixia-c](https://github.com/open-traffic-generator/ixia-c) is one of such reference implementations of the Open Traffic Generator API.
## To install Snappi for the Go language, do the following:
### Setup the client
```sh
go get github.com/open-traffic-generator/snappi/gosnappi
```
### Start Testing
```Go
package examples
import (
"encoding/hex"
"testing"
"time"
"github.com/open-traffic-generator/snappi/gosnappi"
)
func TestQuickstart(t *testing.T) {
// Create a new API handle to make API calls against OTG
api := gosnappi.NewApi()
// Set the transport protocol to HTTP
api.NewHttpTransport().SetLocation("https://localhost:8443")
// Create a new traffic configuration that will be set on OTG
config := gosnappi.NewConfig()
// Add a test port to the configuration
ptx := config.Ports().Add().SetName("ptx").SetLocation("veth-a")
// Configure a flow and set previously created test port as one of endpoints
flow := config.Flows().Add().SetName("f1")
flow.TxRx().Port().SetTxName(ptx.Name())
// and enable tracking flow metrics
flow.Metrics().SetEnable(true)
// Configure number of packets to transmit for previously configured flow
flow.Duration().FixedPackets().SetPackets(100)
// and fixed byte size of all packets in the flow
flow.Size().SetFixed(128)
// Configure protocol headers for all packets in the flow
pkt := flow.Packet()
eth := pkt.Add().Ethernet()
ipv4 := pkt.Add().Ipv4()
udp := pkt.Add().Udp()
cus := pkt.Add().Custom()
eth.Dst().SetValue("00:11:22:33:44:55")
eth.Src().SetValue("00:11:22:33:44:66")
ipv4.Src().SetValue("10.1.1.1")
ipv4.Dst().SetValue("20.1.1.1")
// Configure repeating patterns for source and destination UDP ports
udp.SrcPort().SetValues([]int32{5010, 5015, 5020, 5025, 5030})
udp.DstPort().Increment().SetStart(6010).SetStep(5).SetCount(5)
// Configure custom bytes (hex string) in payload
cus.SetBytes(hex.EncodeToString([]byte("..QUICKSTART SNAPPI..")))
// Optionally, print JSON representation of config
if j, err := config.ToJson(); err != nil {
t.Fatal(err)
} else {
t.Log("Configuration: ", j)
}
// Push traffic configuration constructed so far to OTG
if _, err := api.SetConfig(config); err != nil {
t.Fatal(err)
}
// Start transmitting the packets from configured flow
ts := gosnappi.NewTransmitState()
ts.SetState(gosnappi.TransmitStateState.START)
if _, err := api.SetTransmitState(ts); err != nil {
t.Fatal(err)
}
// Fetch metrics for configured flow
req := gosnappi.NewMetricsRequest()
req.Flow().SetFlowNames([]string{flow.Name()})
// and keep polling until either expectation is met or deadline exceeds
deadline := time.Now().Add(10 * time.Second)
for {
metrics, err := api.GetMetrics(req)
if err != nil || time.Now().After(deadline) {
t.Fatalf("err = %v || deadline exceeded", err)
}
// print YAML representation of flow metrics
t.Log(metrics)
if metrics.FlowMetrics().Items()[0].Transmit() == gosnappi.FlowMetricTransmit.STOPPED {
break
}
time.Sleep(100 * time.Millisecond)
}
}
```
## To install Snappi for the Python language, do the following:
### Setup the Client
```sh
python -m pip install --upgrade snappi
```
### Start Testing
```python
import datetime
import time
import snappi
import pytest
@pytest.mark.example
def test_quickstart():
# Create a new API handle to make API calls against OTG
# with HTTP as default transport protocol
api = snappi.api(location="https://localhost:8443")
# Create a new traffic configuration that will be set on OTG
config = api.config()
# Add a test port to the configuration
ptx = config.ports.add(name="ptx", location="veth-a")
# Configure a flow and set previously created test port as one of endpoints
flow = config.flows.add(name="flow")
flow.tx_rx.port.tx_name = ptx.name
# and enable tracking flow metrics
flow.metrics.enable = True
# Configure number of packets to transmit for previously configured flow
flow.duration.fixed_packets.packets = 100
# and fixed byte size of all packets in the flow
flow.size.fixed = 128
# Configure protocol headers for all packets in the flow
eth, ip, udp, cus = flow.packet.ethernet().ipv4().udp().custom()
eth.src.value = "00:11:22:33:44:55"
eth.dst.value = "00:11:22:33:44:66"
ip.src.value = "10.1.1.1"
ip.dst.value = "20.1.1.1"
# Configure repeating patterns for source and destination UDP ports
udp.src_port.values = [5010, 5015, 5020, 5025, 5030]
udp.dst_port.increment.start = 6010
udp.dst_port.increment.step = 5
udp.dst_port.increment.count = 5
# Configure custom bytes (hex string) in payload
cus.bytes = "".join([hex(c)[2:] for c in b"..QUICKSTART SNAPPI.."])
# Optionally, print JSON representation of config
print("Configuration: ", config.serialize(encoding=config.JSON))
# Push traffic configuration constructed so far to OTG
api.set_config(config)
# Start transmitting the packets from configured flow
ts = api.transmit_state()
ts.state = ts.START
api.set_transmit_state(ts)
# Fetch metrics for configured flow
req = api.metrics_request()
req.flow.flow_names = [flow.name]
# and keep polling until either expectation is met or deadline exceeds
start = datetime.datetime.now()
while True:
metrics = api.get_metrics(req)
if (datetime.datetime.now() - start).seconds > 10:
raise Exception("deadline exceeded")
# print YAML representation of flow metrics
print(metrics)
if metrics.flow_metrics[0].transmit == metrics.flow_metrics[0].STOPPED:
break
time.sleep(0.1)
```
================================================
FILE: docs/eula.md
================================================
# End User License Agreement
By using Keysight Elastic Network Generator and Ixia-c software you accept Keysight Technologies' End User License Agreement (EULA). The agreement can be found at [www.keysight.com/find/sweula](https://www.keysight.com/find/sweula).
The End-User License Agreement must be accepted before the KENG controller can start. The user can accept the EULA by specifying `--accept-eula` command line option while
starting the `keng-controller` container.
## Copyright notice
© Copyright Keysight Technologies, Inc. 2021, 2022, 2023
================================================
FILE: docs/faq.md
================================================
# FAQ
- [Table of Contents](readme.md)
- FAQ
- [Ixia-c, Open Traffic Generator and snappi](#ixia-c-open-traffic-generator-and-snappi)
- [Diagnostics](#diagnostics)
- [Packets](#packets)
- [Application Usage Reporter](#application-usage-reporter)
- [Ixia-c Free Version](#Ixia-c-free-version)
- [Troubleshooting](#troubleshooting)
- [Support](#support)
## Ixia-c, Open Traffic Generator and snappi
<details>
<summary>
What is the relationship between Open Traffic Generator data models, snappi and Ixia-c?
</summary>
<br>
The [Open Traffic Generator](https://github.com/open-traffic-generator/models) data models describe a vendor neutral data models and APIs for test traffic generation. The models are based on OpenAPI v3. Ixia-c is a traffic generator that complies with these APIs. [snappi](https://github.com/open-traffic-generator/snappi) is a *Pythonic* client library that can be used to write tests that run against Ixia-c.
The following two diagrams illustrate this relationship.
<div align="center">
<br>
<img src="res/api-sdk-tests.drawio.svg"></img>
</div>
<br>
<div align="center">
<br>
<img src="res/tests-sdk-ixia-c.drawio.svg"></img>
</div>
<br>
</details>
<details>
<summary>
Where can I find a tutorial on <i>snappi</i>?
</summary>
<br>
The [Hello snappi](hello-snappi.md) tutorial is a good starting point to get familiar with `snappi`.
</details>
<details>
<summary>
How to use other non-Python clients?
</summary>
<br>
TODO: Fill in details here.
</details>
<details>
<summary>
Can I use <i>curl</i> to control Ixia-c?
</summary>
<br>
Yes. Refer to the [Quick Start](../readme.md##quick-start) on the Ixia-c home page.
</details>
## Diagnostics
<details>
<summary>
What version of the Open Traffic Generator spec does Ixia-c implement?
</summary>
<br>
Ixia-c implements version **[v0.12.5](https://github.com/open-traffic-generator/models/releases/tag/v0.12.5)** of the Open Traffic Generator Data Model. You can view the model [here](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.12.5/artifacts/openapi.yaml).
</details>
<details>
<summary>
How to find version of Open Traffic Generator spec implemented by Ixia-c?
</summary>
<br>
Open Traffic Generator Data Model can be accessed from any browser by pointing it to (https://\<controller-host-ip\>/docs/openapi.json). The `info` section contains the `version` of the Open Traffic Generator Data Model implemented by the KENG controller.
</details>
## Packets
<details>
<summary>
What do packets look like?
</summary>
<br>
Ixia packet testers utilize a proprietary flow-tracking technique which involves inserting a special *instrumentation header* into the packet. It is inserted after the last valid protocol header ie, in the payload.
<div align="center">
<br>
<img src="res/packet-instrumentation.png"></img>
</div>
<br>
The fields in this header are:
- a *signature* which servers as marker to indicate start of header
- a *PGID* or *port group id* field to distinguish between different flows
- a 32 bit *sequence number* that can be used to detect packet re-ordering
- a 32 bit timestamp that can be used to measure one-way latency
</details>
<details>
<summary>
How do I disable packet instrumentation?
</summary>
<br>
According to the Open Traffic Generator data model packet instrumentation is enabled by default on all the flows. It is not possible to disable it at the moment. An update to the data model that allows the end user to disable instrumentation is in the process of being merged into the *main* branch and will be submitted in the coming weeks. Ixia-c will implement it at that point.
</details>
<details>
<summary>
Does Ixia-c calculate packet checksums? If so, which ones?
</summary>
<br>
Yes, the Ixia-c traffic-engine automatically calculates the Ethernet FCS, IPv4, TCP and UDP checksums. The traffic-engine is capable of calculating *four* checksums (in each packet). TODO: verify.
</details>
<details>
<summary>
What <i>layer1</i> settings does Ixia-c utilize?
</summary>
<br>
The only `layer1` setting that is used by the Ixia-c traffic engine is `speed`. This setting is used to help convert flow rate specified as *percentage line-rate* into packets/second (pps) and to ensure that proper inter-packet-gaps are used.
</details>
<details>
<summary>
What is the purpose of the <i>layer1</i> setting <i>speed</i>?
</summary>
<br>
To calculate packets/second (pps) when the flow rate is specified as *percentage line-rate* and to ensure proper inter-packet-gaps.
</details>
## Application Usage Reporter
<details>
<summary>
What is <i>Application Usage Reporter</i>?
</summary>
<br>
The `app-usage-reporter` container collects and uploads to the Keysight cloud some basic telemetry information from the KENG controller. This information helps Keysight improve the controller by focusing on the features that are being used by end users.
</details>
<details>
<summary>
What information does <i>Application Usage Reporter</i> collect?
</summary>
<br>
The *Application Usage Reporter* collects configuration related information like the number of ports in a test, number of flows configured, number of values used in a pattern. TODO: Need to give an exhaustive list.
</details>
<details>
<summary>
Does <i>Application Usage Reporter</i> collect any personally identifiable information?
</summary>
<br>
No. The *Application Usage Reporter* does NOT collect any personally identifiable information like username, hostname, email address, etc.
</details>
<details>
<summary>
Does <i>Application Usage Reporter</i> save my IP address?
</summary>
<br>
No.
</details>
<details>
<summary>
Can I disable <i>Application Usage Reporter</i>? If so, how?
</summary>
<br>
Yes, the *Application Usage Reporter* can be disabled. Refer to the [Deployment Parameters](deployments.md#deployment-parameters) section in the Deployment Guide.
</details>
## Ixia-c Free Version
<details>
<summary>
What are the limitations of the free version of Ixia-c?
</summary>
<br>
The free version of KENG controller supports up to 4 ports in one session and the Ixia-c traffic-engine is limited to running over `raw` sockets.
</details>
<details>
<summary>
What are the differences between the commercial and the free version of Ixia-c?
</summary>
<br>
The following table highlights the differences between the commercial and the free version of Ixia-c.
| Capability | Ixia-c Free | Ixia-c Commercial |
-------------| ------------| ------------------|
| # of Ports | 4 | Unlimited |
| Traffic Engine - Raw | Supported | Supported |
| Traffic Engine - DPDK PCI | Not Supported | Supported |
| Support | Slack Channel | Keysight Support |
</details>
<details>
<summary>
How do I purchase the commercial version of Ixia-c?
</summary>
<br>
Contact your Keysight Sales Rep or reach out to us [here](https://www.keysight.com/us/en/contact.html).
</details>
## Troubleshooting
<details>
<summary>
How do I view KENG controller logs?
</summary>
<br>
Use `docker logs` to view the controller log.
</details>
<details>
<summary>
What is the message <i>"App usage reporting service is down"</i> in KENG controller log?
</summary>
<br>
This message indicates that the `app-usage-reporter` container is not reachable from the KENG controller. This does NOT affect KENG controller's normal operation. Refer to [Deployment Parameters](deployments.md#deployment-parameters) for more details on how to override the default location for the app-usage-reporter or how to disable it all together.
</details>
## Support
<details>
<summary>
Where do I get support for the free version of Ixia-c?
</summary>
<br>
Reach out to us on [Slack](support.md) for support.
</details>
================================================
FILE: docs/features.md
================================================
### Feature metrics showcasing free vs commercial usage
================================================
FILE: docs/index.md
================================================
<h1 align="center">Ixia-c & Elastic Network Generator</h1>
<h3 align="center">Agile and composable network test system designed for continuous integration</h3>
<section>
<div class="container">
<div class="column">
<img src="assets/keng-diagram.png">
</div>
<div class="column">
<ul>
<li>Implements <a href="https://otg.dev" target="_blank">Open Traffic Generator API</a></li>
<li>Emulates key <a href="reference/capabilities/#protocol-emulation">control plane protocols</a></li>
<li>Generates complex <a href="reference/capabilities/#traffic-generation">data plane traffic</a></li>
<li>Supports <a href="deployments">software</a>, <a href="tests-uhd400">white-box</a> and <a href="tests-chassis-app">hardware</a> test ports</li>
<li>Reduces time-to-test with fast API response time and <a href="developer/hello-snappi">agile developer experience</a></li>
<li>Deploys using <a href="quick-start/deployment">modular architecture</a> based on containers and microservices</li>
<li>Accelerates network validation by <a href="integrated-environments">integrating</a> with popular network emulation software.</li>
</ul>
</div>
</div>
</section>
## Community Edition
First in its class [Ixia-c Community Edition](quick-start/introduction.md) of the Elastic Network Generator with **BGP emulation and full set traffic capabilities** [limited by scale and performance](licensing.md) is available to anyone without registration and at no cost.
## OTG Examples
Explore [otg-examples](https://otg.dev/examples/otg-examples/) library to get hands-on experience with using Open Traffic Generator and Ixia-c. With a minimum Linux host or VM you can be running your first network data and control plane validation scenarios in minutes.
## Key Features
* Software multi-container application:
* runs on Linux x86 compute,
* includes software traffic generation and protocol emulation capabilities,
* built using DPDK to generate high traffic rates on a single CPU core,
* can control Keysight network test hardware.
* Easily integrates into CI/CD pipelines like GitHub, GitLab, Jenkins.
* Supports test frameworks like Pytest or Golang test.
* Emulates key data center protocols with high scale of sessions and routes:
* capable of leveraging 3rd party libraries to add unsupported packet formats,
* provides patterns to modify common packet header fields to generate millions of unique packets.
* Supports:
* configurable frame sizes,
* rate specification in pps (packets per second) or % line-rate,
* ability to send traffic bursts.
* Statistics:
* per port and per flow,
* tracks flows based on common packet header fields,
* one way latency measurements (min, max, average) on a per flow basis,
* capture packets and write to PCAP or analyze in the test logic.
## Copyright notice
© Copyright Keysight Technologies, Inc. 2021, 2022, 2023
================================================
FILE: docs/integrated-environments.md
================================================
## Network Topology Emulation
Ixia-c supports the following modern network emulation software:
* [Containerlab:](deployments-containerlab.md) Simple yet powerful specialized tool for orchestrating and managing container-based networking labs.
* [OpenConfig KNE:](deployments-kne.md) Kubernetes Network Emulation, which is a Google initiative to develop tooling for quickly setting up topologies of containers running various device OSes.
================================================
FILE: docs/licensing.md
================================================
# Licensing
## License Editions
The following License Editions are available for Keysight Elastic Network Generator:
| Capability | Community | Developer | Team | System |
|-------------------------------------|----------------------|----------------------|--------------------------------|-------------------------------------|
| Ixia-c Traffic Port Capacity | 4 x 1/10GE | 50GE | 400GE | 800GE |
| Test Concurrency | 1 Seat | 1 Seat | 8 Seats | 16 Seats |
| Protocol Scale | Restricted | Limited | Limited | Unlimited |
| Requires a valid license | N | Y | Y | Y |
| Includes Ixia-c Software Test Ports | Y | Y | Y | Y |
| Works with UHD400T Hardware | N | N | Y | Y |
| Works with IxOS Hardware | N | N | N | Y |
The **Ixia-c Traffic Port Capacity** is determined as a sum of the configured Ixia-c software test port speeds with the possible values of: 100GE, 50GE, 40GE, 25GE, 10GE, and 1GE. The Maximum data plane performance of an Ixia-c port may be less than the configured port speed, depending on the capabilities of the underlying hardware and software drivers. Doesn't apply to the UHD400T and IxOS hardware.
The **Test seat concurrency** applies to a number of controller instances that are running with a configuration that exceeds the capabilities of the Community Edition.
The **Restricted** protocol scale supports the maximum of 4 BGP sessions per test.
The Capabilities of the **Limited** protocol scale depend on the protocol. For details, contact [Keysight Support](https://support.ixiacom.com/contact/support).
Keysight Elastic Network Generator can simultaneously consume multiple licenses to increase the capabilities of a test. For example, if the Ixia-c Traffic Port Capacity configured in one test is 100GE, two Developer licenses will be consumed if available.
If you require capabilities beyond those provided by the Community Edition, use [Keysight Elastic Network Generator](https://www.keysight.com/us/en/products/network-test/protocol-load-test/keysight-elastic-network-generator.html) product page to request an evaluation or a quote.
## License Server
In order to use capabilities of Elastic Network Generator that require a valid license, you need to deploy a Keysight License Server. Keysight uses the license server to manage floating or network shared licenses for its software products. The license server enables licenses to float and not be tied to a specific Elastic Network Generator instance. The Elastic Network Generator controllers must be able to reach the License server.
### Deployment
The license server is a virtual machine and it is distributed as OVA and QCOW2 images (you only need one of them depending on your hypervisor, downloading may need credentials for support website.).
* [OVA image](https://downloads.ixiacom.com/support/downloads_and_updates/public/KENG-License-Server-VM/4.4.0/4.4.0-202/slum-4.4.0-202.ova), 5.8GB
* [QCOW2 image](https://downloads.ixiacom.com/support/downloads_and_updates/public/KENG-License-Server-VM/4.4.0/4.4.0-202/slum-4.4.0-202.qcow2), 6GB
To make a decision where to deploy the License Server VM, take into the account the following requirements:
* For VMware ESXi, use the OVA image
* For Linux-based QEMU or KVM, use the QCOW2 image
* 2 vCPU cores
* 8GB RAM for ESXi, 4GB RAM for QEMU/KVM
* 100GB storage
* 1 vNIC for network connectivity. Note that DHCP is the preferred option, and this is also how the VM is configured to obtain its IP address.
Network connectivity requirements for the License Server VM
1. Internet access from the VM over HTTPS is desirable for online license activation, but not strictly required. Offline activation method is available as well.
2. Access from a user over HTTPS (TCP/443) for license operations (activation, deactivation, reservation, sync).
3. Access from any `keng-controller` that needs a license during a test run over gRPC (TCP/7443) for license checkout and check-in.
Here is an example of how different components communicate with the License Server:

### Configuration
If your network doesn't provide DHCP, you can configure a static IP address for the License Server VM. Access the VM console and go through two-step login process:
* First prompt: `console` (no password)
* Second promt: `admin`/`admin`
* Run the following commands to configure a static IP address, where `x.x.x.x` is the IP address, `yy` is the prefix length, `z.z.z.z` is the default gateway, `a.a.a.a` and `b.b.b.b` are DNS servers:
```Shell
kcos networking ip set mgmt0 x.x.x.x/yy z.z.z.z
kcos networking dns-servers add a.a.a.a b.b.b.b
```
### Activation
Now you shall be able to activate licenses and use the License Server with your Elastic Network Generator environments. Go to `https://your-license-server-hostname` to access the application. Enter credentials: `admin`/`admin` to login.
If you have an activation code, to perform an online activation, click "Activate Licenses", enter the code and click "Activate". For offline mode, choose "Offline Operations" instead.
You can also use a command-line session, via console or SSH, to perform license operations. Run `kcos licensing --help` to see the list of available commands.
## Using Licenses
To use the licenses with the Elastic Network Generator, provide the location of the license servers to the controller instances using
```
--license-servers="server1 server2 server3 server4"
```
argument when launching the controller. The argument accepts a space-separated list of hostnames or IP addresses of the License Servers, up to four. The controller will try to connect to the License Servers in the order they are specified in the list. If the first License Server is not available, or doesn't have enough available licenses to run the test, the controller will try to connect to the next one in the list.
An alternative way is to use an environment variable `LICENSE_SERVERS`.
## Additional Information
Please refer to the [Reference Guide](reference/licensing.md) for more information on the license operations.
================================================
FILE: docs/limitations.md
================================================
# Limitations
* Supported protocol headers are `ethernet`, `ipv4`, `ipv6`, `vlan`, `tcp`, `udp`, `gtpv1`, `gtpv2`, `arp`, `icmp` and `custom`.
* `fixed_packets`, `fixed_seconds`,`continuous` and `burst` are supported for flow duration (fixed number of `burst` is not supported).
* Size of the packet must be a value greater than or equal to 64 bytes.
* Setting random frame size is not supported.
* Only `value`, `values`,`increment` and `decrement` patterns are supported for Protocol Header fields.
* A maximum of `4` increment, decrement and values patterns are supported per flow.
* A maximum of `500K` list entries are supported per list pattern, per flow.
* A maximum of `256 flows` for a given tx-rx port pair is supported.
* Statistics based on `ingress_result_name` is not supported.
* Tx statistics for flow results is not supported.
* Starting or stopping transmit on selected flows is not supported. Pausing flows is not supported.
* `lags`, `devices` and `options` in `Config` are not supported.
* Only `speed`, `promiscuous` and `mtu` settings are supported in `Layer1`.
* In Centos 7+, with Python 2.7+, virtualenv creation fails due to a known limitation
(https://github.com/pypa/virtualenv/issues/1609). It can be avoided by upgrading pip and then
================================================
FILE: docs/news.md
================================================
# News
* **21st April, 2026**: Ixia-c version 1.53.0 (build 1) released. This conforms to **[v1.53.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.53.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **1st April, 2026**: Ixia-c version 1.51.0 (build 1) released. This conforms to **[v1.51.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.51.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **11th March, 2026**: Ixia-c version 1.48.0 (build 5) released. This conforms to **[v1.48.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.48.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **20th February, 2026**: Ixia-c version 1.45.0 (build 5) released. This conforms to **[v1.45.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.45.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **9th February, 2026**: Ixia-c version 1.44.0 (build 8) released. This conforms to **[v1.44.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.44.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **29th January, 2026**: Ixia-c version 1.43.0 (build 7) released. This conforms to **[v1.43.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.43.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **22nd December, 2025**: Ixia-c version 1.42.1 (build 4) released. This conforms to **[v1.42.1](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.42.1/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **8th December, 2025**: Ixia-c version 1.42.0 (build 4) released. This conforms to **[v1.42.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.42.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **24th November, 2025**: Ixia-c version 1.41.0 (build 8) released. This conforms to **[v1.41.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.41.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes bug fixes. [Read more](releases.md)
* **11th November, 2025**: Ixia-c version 1.41.0 (build 1) released. This conforms to **[v1.41.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.41.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **24th October, 2025**: Ixia-c version 1.40.0 (build 15) released. This conforms to **[v1.40.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.40.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **26th September, 2025**: Ixia-c version 1.40.0 (build 1) released. This conforms to **[v1.40.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.40.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **12th September, 2025**: Ixia-c version 1.35.0 (build 14) released. This conforms to **[v1.35.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.35.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **1st September, 2025**: Ixia-c version 1.34.0 (build 1) released. This conforms to **[v1.34.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.34.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **20th August, 2025**: Ixia-c version 1.33.0 (build 34) released. This conforms to **[v1.33.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.33.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **18th July, 2025**: Ixia-c version 1.33.0 (build 1) released. This conforms to **[v1.33.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.33.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **1st July, 2025**: Ixia-c version 1.32.0 (build 1) released. This conforms to **[v1.32.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.32.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **14th June, 2025**: Ixia-c version 1.31.0 (build 6) released. This conforms to **[v1.31.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.31.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **2nd June, 2025**: Ixia-c version 1.31.0 (build 3) released. This conforms to **[v1.31.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.31.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **19th May, 2025**: Ixia-c version 1.28.0 (build 45) released. This conforms to **[v1.28.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.28.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **7th May, 2025**: Ixia-c version 1.28.0 (build 33) released. This conforms to **[v1.28.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.28.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **18th April, 2025**: Ixia-c version 1.28.0 (build 6) released. This conforms to **[v1.28.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.28.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **29th March, 2025**: Ixia-c version 1.24.0 (build 15) released. This conforms to **[v1.24.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.24.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **7th March, 2025**: Ixia-c version 1.24.0 (build 4) released. This conforms to **[v1.24.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.24.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **26th February, 2025**: Ixia-c version 1.20.0 (build 8) released. This conforms to **[v1.20.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.20.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new bug fixes. [Read more](releases.md)
* **11th February, 2025**: Ixia-c version 1.20.0 (build 6) released. This conforms to **[v1.20.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.20.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **24th January, 2025**: Ixia-c version 1.19.0 (build 18) released. This conforms to **[v1.19.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.19.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **23rd December, 2024**: Ixia-c version 1.19.0 (build 5) released. This conforms to **[v1.19.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.19.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **29th November, 2024**: Ixia-c version 1.17.0 (build 9) released. This conforms to **[v1.17.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.17.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **18th November, 2024**: Ixia-c version 1.16.0 (build 2) released. This conforms to **[v1.16.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.16.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **25th October, 2024**: Ixia-c version 1.14.0 (build 1) released. This conforms to **[v1.14.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.14.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **4th October, 2024**: Ixia-c version 1.13.0 (build 9) released. This conforms to **[v1.13.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.13.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **13th September, 2024**: Ixia-c version 1.13.0 (build 1) released. This conforms to **[v1.13.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.13.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **2nd September, 2024**: Ixia-c version 1.12.0 (build 1) released. This conforms to **[v1.12.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.12.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **20th August, 2024**: Ixia-c version 1.8.0 (build 1) released. This conforms to **[v1.8.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.8.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **7th August, 2024**: Ixia-c version 1.7.2 (build 1) released. This conforms to **[v1.7.1](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.7.1/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **19th July, 2024**: Ixia-c version 1.6.2 (build 13) released. This conforms to **[v1.6.2](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.6.2/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **28th June, 2024**: Ixia-c version 1.6.2 (build 1) released. This conforms to **[v1.6.2](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.6.2/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **14th June, 2024**: Ixia-c version 1.5.1 (build 11) released. This conforms to **[v1.5.1](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.5.1/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **1st June, 2024**: Ixia-c version 1.5.1 (build 3) released. This conforms to **[v1.5.1](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.5.1/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **23rd May, 2024**: Ixia-c version 1.5.0 (build 1) released. This conforms to **[v1.5.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.5.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes bug fixes. [Read more](releases.md)
* **20th May, 2024**: Ixia-c version 1.4.0 (build 15) released. This conforms to **[v1.4.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.4.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes bug fixes. [Read more](releases.md)
* **7th May, 2024**: Ixia-c version 1.4.0 (build 1) released. This conforms to **[v1.4.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.4.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **19th April, 2024**: Ixia-c version 1.3.0 (build 2) released. This conforms to **[v1.3.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.3.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **29th March, 2024**: Ixia-c version 1.1.0 (build 21) released. This conforms to **[v1.1.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.1.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **22nd March, 2024**: Ixia-c version 1.1.0 (build 12) released. This conforms to **[v1.1.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.1.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **20th March, 2024**: Ixia-c version 1.1.0 (build 10) released. This conforms to **[v1.1.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.1.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **1st March, 2024**: Ixia-c version 1.0.0 (build 104) released. This conforms to **[v1.0.2](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.0.2/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **22nd February, 2024**: Ixia-c version 1.0.0 (build 92) released. This conforms to **[v1.0.1](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.0.1/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **5th February, 2024**: Ixia-c version 1.0.0 (build 7) released. This conforms to **[v1.0.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v1.0.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **19th January, 2024**: Ixia-c version 0.1.0 (build 222) released. This conforms to **[v0.13.7](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.13.7/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **21st December, 2023**: Ixia-c version 0.1.0 (build 158) released. This conforms to **[v0.13.4](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.13.4/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **7th December, 2023**: Ixia-c version 0.1.0 (build 84) released. This conforms to **[v0.13.2](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.13.2/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **24th November, 2023**: Ixia-c version 0.1.0 (build 81) released. This conforms to **[v0.13.2](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.13.2/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **10th November, 2023**: Ixia-c version 0.1.0 (build 53) released. This conforms to **[v0.13.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.13.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features and bug fixes. [Read more](releases.md)
* **3rd November, 2023**: Ixia-c version 0.1.0 (build 26) released. This conforms to **[v0.13.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.13.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes stability fixes. [Read more](releases.md)
* **20th October, 2023**: Ixia-c version 0.1.0 (build 3) released. This conforms to **[v0.13.0](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.13.0/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features, stability and bug fixes. [Read more](releases.md)
* **29th September, 2023**: Ixia-c version 0.0.1 (build 4554) released. This conforms to **[v0.12.5](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.12.5/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes bug fixes. [Read more](releases.md)
* **14th September, 2023**: Ixia-c version 0.0.1 (build 4478) released. This conforms to **[v0.12.3](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.12.3/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes stability fixes. [Read more](releases.md)
* **1st September, 2023**: Ixia-c version 0.0.1 (build 4435) released. This conforms to **[v0.12.2](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.12.2/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes bug fixes. [Read more](releases.md)
* **21st August, 2023**: Ixia-c version 0.0.1 (build 4399) released. This conforms to **[v0.12.1](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.12.1/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **4th August, 2023**: Ixia-c version 0.0.1 (build 4306) released. This conforms to **[v0.11.11](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.11/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes stability fixes. [Read more](releases.md)
* **21st July, 2023**: Ixia-c version 0.0.1 (build 4167) released. This conforms to **[v0.11.10](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.10/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **29th June, 2023**: Ixia-c version 0.0.1 (build 4139) released. This conforms to **[v0.11.10](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.10/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **16th June, 2023**: Ixia-c version 0.0.1 (build 4124) released. This conforms to **[v0.11.9](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.9/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **2nd June, 2023**: Ixia-c version 0.0.1 (build 4080) released. This conforms to **[v0.11.9](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.9/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes stability fixes. [Read more](releases.md)
* **18th May, 2023**: Ixia-c version 0.0.1 (build 4064) released. This conforms to **[v0.11.8](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.8/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes bug fix. [Read more](releases.md)
* **5th May, 2023**: Ixia-c version 0.0.1 (build 4013) released. This conforms to **[v0.11.8](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.8/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **21st April, 2023**: Ixia-c version 0.0.1 (build 3927) released. This conforms to **[v0.11.8](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.8/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **31st March, 2023**: Ixia-c version 0.0.1 (build 3889) released. This conforms to **[v0.11.4](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.4/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **16th March, 2023**: Ixia-c version 0.0.1 (build 3865) released. This conforms to **[v0.11.1](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.11.1/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes new features. [Read more](releases.md)
* **3rd March, 2023**: Ixia-c version 0.0.1 (build 3841) released. This conforms to **[v0.10.12](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.10.12/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
**Announcement**
`ixia-c` container images are hosted on [GitHub Container Registry](https://github.com/orgs/open-traffic-generator/packages), We stopped publishing `ixia-c` container images to [DockerHub](https://hub.docker.com/r/ixiacom).
* This build includes new features. [Read more](releases.md)
* **17th February, 2023**: Ixia-c version 0.0.1 (build 3807) released. This conforms to **[v0.10.9](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.10.9/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
**Announcement**
`ixia-c` container images are hosted on [GitHub Container Registry](https://github.com/orgs/open-traffic-generator/packages), We stopped publishing `ixia-c` container images to [DockerHub](https://hub.docker.com/r/ixiacom).
* This build includes bug fixes. [Read more](releases.md)
* **2nd February, 2023**: Ixia-c version 0.0.1 (build 3768) released. This conforms to **[v0.10.7](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.10.7/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
**Announcement**
`ixia-c` container images are hosted on [GitHub Container Registry](https://github.com/orgs/open-traffic-generator/packages), We stopped publishing `ixia-c` container images to [DockerHub](https://hub.docker.com/r/ixiacom).
* This build includes bug fixes. [Read more](releases.md)
* **20th January, 2023**: Ixia-c version 0.0.1 (build 3724) released. This conforms to **[v0.10.6](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.10.6/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
**Announcement**
`ixia-c` container images are hosted on [GitHub Container Registry](https://github.com/orgs/open-traffic-generator/packages), We stopped publishing `ixia-c` container images to [DockerHub](https://hub.docker.com/r/ixiacom).
* This build includes bug fixes. [Read more](releases.md)
* **15th December, 2022**: Ixia-c version 0.0.1 (build 3698) released. This conforms to **[v0.10.5](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.10.5/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
**Announcement**
`ixia-c` container images are hosted on [GitHub Container Registry](https://github.com/orgs/open-traffic-generator/packages), We stopped publishing `ixia-c` container images to [DockerHub](https://hub.docker.com/r/ixiacom).
* **1st December, 2022**: Ixia-c version 0.0.1 (build 3662) released. This conforms to **[v0.9.10](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.9.10/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
**Announcement**
`ixia-c` container images are hosted on [GitHub Container Registry](https://github.com/orgs/open-traffic-generator/packages). However we will continue publishing `ixia-c` container images to [DockerHub](https://hub.docker.com/r/ixiacom) until 18th November, 2022.
* **10th November, 2022**: Ixia-c version 0.0.1 (build 3619) released. This conforms to **[v0.9.1](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.9.1/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
**Announcement**
`ixia-c` container images are hosted on [GitHub Container Registry](https://github.com/orgs/open-traffic-generator/packages). However we will continue publishing `ixia-c` container images to [DockerHub](https://hub.docker.com/r/ixiacom) until 18th November, 2022.
* This build includes new features along with bugs fixes. [Read more](releases.md)
* **28th October, 2022**: Ixia-c version 0.0.1 (build 3587) released. This conforms to **[v0.9.1](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.9.1/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
**Announcement**
`ixia-c` container images are hosted on [GitHub Container Registry](https://github.com/orgs/open-traffic-generator/packages). However we will continue publishing `ixia-c` container images to [DockerHub](https://hub.docker.com/r/ixiacom) until 18th November, 2022.
* This build includes bug fixes. [Read more](releases.md)
* **29th September, 2022**: Ixia-c version 0.0.1 (build 3423) released. This conforms to **[v0.9.1](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.9.1/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
**Announcement**
`ixia-c` container images are hosted on [GitHub Container Registry](https://github.com/orgs/open-traffic-generator/packages). However we will continue publishing `ixia-c` container images to [DockerHub](https://hub.docker.com/r/ixiacom) until 18th November, 2022.
* This build includes stability fixes. [Read more](releases.md)
* **16th September, 2022**: Ixia-c version 0.0.1 (build 3383) released. This conforms to **[v0.9.1](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.9.1/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
**Announcement**
`ixia-c` container images are hosted on [GitHub Container Registry](https://github.com/orgs/open-traffic-generator/packages). However we will continue publishing `ixia-c` container images to [DockerHub](https://hub.docker.com/r/ixiacom) until 18th November, 2022.
* This build includes new features. [Read more](releases.md)
* **1st September, 2022**: Ixia-c version 0.0.1 (build 3182) released. This conforms to **[v0.9.1](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.9.1/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
**Announcement**
`ixia-c` container images are hosted on [GitHub Container Registry](https://github.com/orgs/open-traffic-generator/packages). However we will continue publishing `ixia-c` container images to [DockerHub](https://hub.docker.com/r/ixiacom) until 18th November, 2022.
* This build includes new features. [Read more](releases.md)
* **18th August, 2022**: Ixia-c version 0.0.1 (build 3113) released. This conforms to **[v0.8.6](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.8.6/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
**Announcement**
From now onwards `ixia-c` container images will be hosted on [GitHub Container Registry](https://github.com/orgs/open-traffic-generator/packages). However we will continue publishing `ixia-c` container images to [DockerHub](https://hub.docker.com/r/ixiacom) as well for the next 3 months. (until 18th November, 2022)
* This build includes new feature along with bug fix. [Read more](releases.md)
* **4th August, 2022**: Ixia-c version 0.0.1 (build 3027) released. This conforms to **[v0.8.6](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.8.6/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* Support added for static `MPLS` packet header in flows. [Read more](releases.md)
* **27th July, 2022**: Ixia-c version 0.0.1 (build 3002) released. This conforms to **[v0.8.5](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.8.5/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes stability fixes. [Read more](releases.md)
* **21st July, 2022**: Ixia-c version 0.0.1 (build 3000) released. This conforms to **[v0.8.5](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.8.5/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes stability fixes. [Read more](releases.md)
* **1st July, 2022**: Ixia-c version 0.0.1 (build 2994) released. This conforms to **[v0.8.1](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.8.1/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes stability fixes. [Read more](releases.md)
* **30th June, 2022**: Ixia-c version 0.0.1 (build 2992) released. This conforms to **[v0.8.1](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/v0.8.1/artifacts/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes stability fixes. [Read more](releases.md)
* **16th June, 2022**: Ixia-c version 0.0.1 (build 2969) released. This conforms to **[v0.7.15](https://redocly.github.io/redoc/?url=https://github.com/open-traffic-generator/models/releases/download/v0.7.15/openapi.yaml)** of the Open Traffic Generator Models specification.
* This build includes stability fixes. [Read more](releases.md)
* **2nd June, 2022**: Ixia-c version 0.0.1 (build 2934) released. This conforms to **[v0.7.13](ht
gitextract_2ocvabri/ ├── .github/ │ └── workflows/ │ ├── ci.yml │ └── publish.yml ├── .gitignore ├── .gitmodules ├── .markdownlint.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── deployments/ │ ├── docker/ │ │ ├── deployment.sh │ │ ├── readme.md │ │ └── versions.yaml │ ├── k8s/ │ │ ├── bases/ │ │ │ ├── namespace/ │ │ │ │ ├── kustomization.yaml │ │ │ │ └── namespace.yaml │ │ │ ├── otg-controller/ │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── pod.yaml │ │ │ │ └── service.yaml │ │ │ └── otg-traffic-port/ │ │ │ ├── kustomization.yaml │ │ │ ├── pod.yaml │ │ │ └── service.yaml │ │ ├── components/ │ │ │ └── images/ │ │ │ └── kustomization.yaml │ │ ├── kind.yaml │ │ ├── network-emulation/ │ │ │ ├── go.mod │ │ │ ├── go.sum │ │ │ ├── ipfwd.go │ │ │ ├── kind.yaml │ │ │ ├── links.yaml │ │ │ ├── namespace.yaml │ │ │ ├── pods.yaml │ │ │ ├── readme.md │ │ │ └── services.yaml │ │ ├── overlays/ │ │ │ ├── one-traffic-port-eth0/ │ │ │ │ ├── config-map.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ └── port1/ │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── pod-patch.yaml │ │ │ │ └── service-patch.yaml │ │ │ └── two-traffic-ports-eth0/ │ │ │ ├── config-map.yaml │ │ │ ├── gen-test-config.sh │ │ │ ├── init-container.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── port1/ │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── pod-patch.yaml │ │ │ │ └── service-patch.yaml │ │ │ └── port2/ │ │ │ ├── kustomization.yaml │ │ │ ├── pod-patch.yaml │ │ │ └── service-patch.yaml │ │ └── readme.md │ ├── raw-one-arm.yml │ ├── raw-three-arm-mesh.yml │ └── raw-two-arm.yml ├── docs/ │ ├── CNAME │ ├── architecture.md │ ├── contribute.md │ ├── deployments-containerlab.md │ ├── deployments-docker-compose.md │ ├── deployments-kne.md │ ├── deployments.md │ ├── developer/ │ │ ├── hello-snappi.md │ │ ├── introduction.md │ │ ├── snappi-constructs.md │ │ └── snappi-install.md │ ├── eula.md │ ├── faq.md │ ├── features.md │ ├── index.md │ ├── integrated-environments.md │ ├── licensing.md │ ├── limitations.md │ ├── news.md │ ├── prerequisites.md │ ├── quick-start/ │ │ ├── deployment.md │ │ ├── introduction.md │ │ └── sample-test.md │ ├── reference/ │ │ ├── capabilities.md │ │ ├── licensing.md │ │ └── resource-requirements.md │ ├── releases.md │ ├── res/ │ │ ├── hw-server.drawio │ │ └── system_with_UHD400T.drawio │ ├── resources.md │ ├── roadmap.md │ ├── sample-scripts.md │ ├── stylesheets/ │ │ └── extra.css │ ├── support.md │ ├── tests-chassis-app.md │ ├── tests-ixia-c.md │ ├── tests-uhd400.md │ ├── troubleshooting.md │ ├── usecases.md │ └── user-guide-introduction.md ├── license ├── mkdocs.md ├── mkdocs.yml ├── notes.md ├── readme.md └── requirements.txt
SYMBOL INDEX (4 symbols across 1 files)
FILE: deployments/k8s/network-emulation/ipfwd.go
function main (line 10) | func main() {
function otgConfig (line 77) | func otgConfig(tc map[string]interface{}) gosnappi.Config {
function ipNeighborsOk (line 145) | func ipNeighborsOk(api gosnappi.Api, tc map[string]interface{}) bool {
function flowMetricsOk (line 171) | func flowMetricsOk(api gosnappi.Api, tc map[string]interface{}) bool {
Condensed preview — 94 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (819K chars).
[
{
"path": ".github/workflows/ci.yml",
"chars": 4501,
"preview": "name: CI\n\nenv:\n PYTHON_VERSION: \"3.8\"\n GO_VERSION: \"1.23\"\n\non:\n push:\n\njobs:\n examples_curl:\n runs-on: ubuntu-22."
},
{
"path": ".github/workflows/publish.yml",
"chars": 369,
"preview": "name: publish\non:\n push:\n branches:\n - main\n workflow_dispatch:\njobs:\n deploy:\n runs-on: ubuntu-latest\n "
},
{
"path": ".gitignore",
"chars": 51,
"preview": "scratch\nenv\n*.pcap\n*.log\nvenv\nsite\n.DS_Store\n*.bkp\n"
},
{
"path": ".gitmodules",
"chars": 111,
"preview": "[submodule \"conformance\"]\n\tpath = conformance\n\turl = https://github.com/open-traffic-generator/conformance.git\n"
},
{
"path": ".markdownlint.json",
"chars": 66,
"preview": "{\n \"default\": true,\n \"MD013\" : false,\n \"MD033\": false\n}\n\n"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 5506,
"preview": "\n# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make particip"
},
{
"path": "CONTRIBUTING.md",
"chars": 1527,
"preview": "# Contributing\n\nWhen contributing to this repository, please first discuss the change you wish to make, via issue or ema"
},
{
"path": "deployments/docker/deployment.sh",
"chars": 9573,
"preview": "#!/bin/bash\n\n\n\nVERSIONS_YAML_LOC=\"https://github.com/open-traffic-generator/ixia-c/releases/download/v1.53.0-1/versions."
},
{
"path": "deployments/docker/readme.md",
"chars": 9149,
"preview": "# Ixia-C Docker Deployment over Raw Socket\n\n## Manual Steps\n\n1. (Optional) Cleanup all existing containers and images.\n\n"
},
{
"path": "deployments/docker/versions.yaml",
"chars": 323,
"preview": "release: 1.53.0-1\nopen-traffic-generator: 1.53.0\nsnappi: 1.53.0\ngosnappi: 1.53.0\nkeng-controller: 1.53.0-1\nixia-c-traffi"
},
{
"path": "deployments/k8s/bases/namespace/kustomization.yaml",
"chars": 95,
"preview": "apiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\nresources:\n - namespace.yaml\n"
},
{
"path": "deployments/k8s/bases/namespace/namespace.yaml",
"chars": 81,
"preview": "apiVersion: v1\nkind: Namespace\nmetadata:\n labels:\n app: ixia-c\n name: ixia-c"
},
{
"path": "deployments/k8s/bases/otg-controller/kustomization.yaml",
"chars": 105,
"preview": "apiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\nresources:\n - pod.yaml\n - service.yaml"
},
{
"path": "deployments/k8s/bases/otg-controller/pod.yaml",
"chars": 1427,
"preview": "apiVersion: v1\nkind: Pod\nmetadata:\n labels:\n app: ixia-c\n role: otg-controller\n name: otg-controller\n namespace"
},
{
"path": "deployments/k8s/bases/otg-controller/service.yaml",
"chars": 475,
"preview": "apiVersion: v1\nkind: Service\nmetadata:\n name: service-otg-controller\n namespace: ixia-c\nspec:\n type: NodePort\n ports"
},
{
"path": "deployments/k8s/bases/otg-traffic-port/kustomization.yaml",
"chars": 105,
"preview": "apiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\nresources:\n - pod.yaml\n - service.yaml"
},
{
"path": "deployments/k8s/bases/otg-traffic-port/pod.yaml",
"chars": 931,
"preview": "apiVersion: v1\nkind: Pod\nmetadata:\n labels:\n app: ixia-c\n role: otg-port\n name: otg-port\n namespace: ixia-c\nspe"
},
{
"path": "deployments/k8s/bases/otg-traffic-port/service.yaml",
"chars": 207,
"preview": "apiVersion: v1\nkind: Service\nmetadata:\n name: otg-port\n namespace: ixia-c\nspec:\n ports:\n - name: zeromq\n port"
},
{
"path": "deployments/k8s/components/images/kustomization.yaml",
"chars": 491,
"preview": "apiVersion: kustomize.config.k8s.io/v1alpha1\nkind: Component\n\n# Release: https://github.com/open-traffic-generator/ixia-"
},
{
"path": "deployments/k8s/kind.yaml",
"chars": 910,
"preview": "kind: Cluster\napiVersion: kind.x-k8s.io/v1alpha4\nnetworking:\n # WARNING: It is _strongly_ recommended that you keep thi"
},
{
"path": "deployments/k8s/network-emulation/go.mod",
"chars": 1744,
"preview": "module ipfwd\n\ngo 1.25.0\n\nrequire github.com/open-traffic-generator/snappi/gosnappi v1.53.0\n\nrequire (\n\tgithub.com/Master"
},
{
"path": "deployments/k8s/network-emulation/go.sum",
"chars": 8430,
"preview": "github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=\ngithub.com/Masterminds/semver/v3"
},
{
"path": "deployments/k8s/network-emulation/ipfwd.go",
"chars": 5175,
"preview": "package main\n\nimport (\n\t\"log\"\n\t\"time\"\n\n\t\"github.com/open-traffic-generator/snappi/gosnappi\"\n)\n\nfunc main() {\n\n\t// This t"
},
{
"path": "deployments/k8s/network-emulation/kind.yaml",
"chars": 910,
"preview": "kind: Cluster\napiVersion: kind.x-k8s.io/v1alpha4\nnetworking:\n # WARNING: It is _strongly_ recommended that you keep thi"
},
{
"path": "deployments/k8s/network-emulation/links.yaml",
"chars": 848,
"preview": "apiVersion: networkop.co.uk/v1beta1\nkind: Topology\nmetadata:\n name: ixia-c-port1\n namespace: ixia-c\nspec:\n links:\n -"
},
{
"path": "deployments/k8s/network-emulation/namespace.yaml",
"chars": 81,
"preview": "apiVersion: v1\nkind: Namespace\nmetadata:\n labels:\n app: ixia-c\n name: ixia-c"
},
{
"path": "deployments/k8s/network-emulation/pods.yaml",
"chars": 3071,
"preview": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n labels:\n app: ixia-c\n name: controller-config\n namespace: ixia-c\ndata:\n "
},
{
"path": "deployments/k8s/network-emulation/readme.md",
"chars": 6772,
"preview": "# Ixia-C Kubernetes Deployment For Emulating Network Topology\n\nIxia-C is a pure software-based solution for facilitating"
},
{
"path": "deployments/k8s/network-emulation/services.yaml",
"chars": 965,
"preview": "apiVersion: v1\nkind: Service\nmetadata:\n name: service-keng-controller\n namespace: ixia-c\nspec:\n ports:\n - name: ht"
},
{
"path": "deployments/k8s/overlays/one-traffic-port-eth0/config-map.yaml",
"chars": 232,
"preview": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n labels:\n app: ixia-c\n name: controller-config\n namespace: ixia-c\ndata:\n "
},
{
"path": "deployments/k8s/overlays/one-traffic-port-eth0/kustomization.yaml",
"chars": 204,
"preview": "apiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\nresources:\n - ../../bases/namespace\n - ../../bases/ot"
},
{
"path": "deployments/k8s/overlays/one-traffic-port-eth0/port1/kustomization.yaml",
"chars": 293,
"preview": "apiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\nresources:\n - ../../../bases/otg-traffic-port\n\npatches"
},
{
"path": "deployments/k8s/overlays/one-traffic-port-eth0/port1/pod-patch.yaml",
"chars": 118,
"preview": "- op: replace\n path: /metadata/labels/role\n value: otg-port1\n- op: replace\n path: /metadata/name\n value: otg-port1"
},
{
"path": "deployments/k8s/overlays/one-traffic-port-eth0/port1/service-patch.yaml",
"chars": 116,
"preview": "- op: replace\n path: /metadata/name\n value: otg-port1\n- op: replace\n path: /spec/selector/role\n value: otg-port1"
},
{
"path": "deployments/k8s/overlays/two-traffic-ports-eth0/config-map.yaml",
"chars": 309,
"preview": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n labels:\n app: ixia-c\n name: controller-config\n namespace: ixia-c\ndata:\n "
},
{
"path": "deployments/k8s/overlays/two-traffic-ports-eth0/gen-test-config.sh",
"chars": 1645,
"preview": "#!/bin/sh\n\nTEST_CONFIG_PATH=test-config.yaml\nif [ ! -z ${1} ]\nthen\n TEST_CONFIG_PATH=${1}\nfi\n\ngen_test_const() {\n "
},
{
"path": "deployments/k8s/overlays/two-traffic-ports-eth0/init-container.yaml",
"chars": 394,
"preview": "apiVersion: v1\nkind: Pod\nmetadata:\n name: _\nspec:\n initContainers:\n - name: init-setup\n image: ubuntu:22.04\n "
},
{
"path": "deployments/k8s/overlays/two-traffic-ports-eth0/kustomization.yaml",
"chars": 367,
"preview": "apiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\nresources:\n - ../../bases/namespace\n - ../../bases/ot"
},
{
"path": "deployments/k8s/overlays/two-traffic-ports-eth0/port1/kustomization.yaml",
"chars": 293,
"preview": "apiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\nresources:\n - ../../../bases/otg-traffic-port\n\npatches"
},
{
"path": "deployments/k8s/overlays/two-traffic-ports-eth0/port1/pod-patch.yaml",
"chars": 118,
"preview": "- op: replace\n path: /metadata/labels/role\n value: otg-port1\n- op: replace\n path: /metadata/name\n value: otg-port1"
},
{
"path": "deployments/k8s/overlays/two-traffic-ports-eth0/port1/service-patch.yaml",
"chars": 116,
"preview": "- op: replace\n path: /metadata/name\n value: otg-port1\n- op: replace\n path: /spec/selector/role\n value: otg-port1"
},
{
"path": "deployments/k8s/overlays/two-traffic-ports-eth0/port2/kustomization.yaml",
"chars": 293,
"preview": "apiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\nresources:\n - ../../../bases/otg-traffic-port\n\npatches"
},
{
"path": "deployments/k8s/overlays/two-traffic-ports-eth0/port2/pod-patch.yaml",
"chars": 118,
"preview": "- op: replace\n path: /metadata/labels/role\n value: otg-port2\n- op: replace\n path: /metadata/name\n value: otg-port2"
},
{
"path": "deployments/k8s/overlays/two-traffic-ports-eth0/port2/service-patch.yaml",
"chars": 116,
"preview": "- op: replace\n path: /metadata/name\n value: otg-port2\n- op: replace\n path: /spec/selector/role\n value: otg-port2"
},
{
"path": "deployments/k8s/readme.md",
"chars": 3225,
"preview": "# Deploy Ixia-C in Kubernetes\n\nThis section hosts [kustomize](https://kustomize.io/) manifests for deploying various Ixi"
},
{
"path": "deployments/raw-one-arm.yml",
"chars": 697,
"preview": "version: '3.9'\nservices:\n controller:\n image: ghcr.io/open-traffic-generator/keng-controller:${CONTROLLER_VERSION:-l"
},
{
"path": "deployments/raw-three-arm-mesh.yml",
"chars": 1420,
"preview": "version: '3.9'\nservices:\n controller:\n image: ghcr.io/open-traffic-generator/keng-controller:${CONTROLLER_VERSION:-l"
},
{
"path": "deployments/raw-two-arm.yml",
"chars": 1058,
"preview": "version: '3.9'\nservices:\n controller:\n image: ghcr.io/open-traffic-generator/keng-controller:${CONTROLLER_VERSION:-l"
},
{
"path": "docs/CNAME",
"chars": 10,
"preview": "ixia-c.dev"
},
{
"path": "docs/architecture.md",
"chars": 0,
"preview": ""
},
{
"path": "docs/contribute.md",
"chars": 342,
"preview": "# Contribute\n\nWe encourage you to contribute to Ixia-c by :\n\n- using it\n- reporting issues\n- requesting enhancements\n- c"
},
{
"path": "docs/deployments-containerlab.md",
"chars": 2101,
"preview": "\n# Deploy Ixia-c-one using containerlab\n\nIxia-c-one is deployed as single-container application by using [containerlab]("
},
{
"path": "docs/deployments-docker-compose.md",
"chars": 5538,
"preview": "# Deploy Ixia-c using docker-compose\n\nDeploying multiple services manually (along with the required parameters) is not a"
},
{
"path": "docs/deployments-kne.md",
"chars": 7440,
"preview": "# Deploy Ixia-c using KNE\n\nIxia-c can be deployed in the k8s environment by using the [Kubernetes Network Emulation](htt"
},
{
"path": "docs/deployments.md",
"chars": 7819,
"preview": "# Deployment\n\n## Overview\n\nIxia-c is distributed and deployed as a multi-container application that consists of the foll"
},
{
"path": "docs/developer/hello-snappi.md",
"chars": 18318,
"preview": "## Use Case\n\nThis tutorial explains some key elements that are required to write a **snappi script** for exercising the "
},
{
"path": "docs/developer/introduction.md",
"chars": 57,
"preview": "# Developer guide introduction \n\nIntroduction to snappi \n"
},
{
"path": "docs/developer/snappi-constructs.md",
"chars": 12326,
"preview": "# Common snappi constructs\n\n## Overview\n\nEvery object in snappi can be serialized to or deserialized from a JSON string "
},
{
"path": "docs/developer/snappi-install.md",
"chars": 6042,
"preview": "# Installing Snappi\n\nThe procedures explained in this section helps to install and configure snappi for an Open Traffic "
},
{
"path": "docs/eula.md",
"chars": 556,
"preview": "# End User License Agreement\n\nBy using Keysight Elastic Network Generator and Ixia-c software you accept Keysight Techno"
},
{
"path": "docs/faq.md",
"chars": 7800,
"preview": "# FAQ\n\n- [Table of Contents](readme.md)\n - FAQ\n - [Ixia-c, Open Traffic Generator and snappi](#ixia-c-open-traffic-g"
},
{
"path": "docs/features.md",
"chars": 55,
"preview": "### Feature metrics showcasing free vs commercial usage"
},
{
"path": "docs/index.md",
"chars": 3073,
"preview": "<h1 align=\"center\">Ixia-c & Elastic Network Generator</h1>\n<h3 align=\"center\">Agile and composable network test system d"
},
{
"path": "docs/integrated-environments.md",
"chars": 440,
"preview": "## Network Topology Emulation\n\nIxia-c supports the following modern network emulation software:\n\n* [Containerlab:](deplo"
},
{
"path": "docs/licensing.md",
"chars": 6927,
"preview": "# Licensing\n\n## License Editions\n\nThe following License Editions are available for Keysight Elastic Network Generator:\n\n"
},
{
"path": "docs/limitations.md",
"chars": 1269,
"preview": "# Limitations\n\n* Supported protocol headers are `ethernet`, `ipv4`, `ipv6`, `vlan`, `tcp`, `udp`, `gtpv1`, `gtpv2`, `arp"
},
{
"path": "docs/news.md",
"chars": 44328,
"preview": "# News\n\n* **21st April, 2026**: Ixia-c version 1.53.0 (build 1) released. This conforms to **[v1.53.0](https://redocly."
},
{
"path": "docs/prerequisites.md",
"chars": 2522,
"preview": "# Ixia-c Prerequisites\n\n## System Prerequisites\n\n### CPU and RAM\n\nThe minimum memory and cpu requirements for a basic us"
},
{
"path": "docs/quick-start/deployment.md",
"chars": 2396,
"preview": "# Deployment\n\nIxia-c is distributed and deployed as a multi-container application that consists of the following service"
},
{
"path": "docs/quick-start/introduction.md",
"chars": 3649,
"preview": "## What is Ixia-c ?\n\n- A modern, powerful and **API-driven** traffic generator designed to cater to the needs of hyper-s"
},
{
"path": "docs/quick-start/sample-test.md",
"chars": 56,
"preview": "# Quick start sample test \n\nHow to run the sample test \n"
},
{
"path": "docs/reference/capabilities.md",
"chars": 2871,
"preview": "# Supported capabilities\n\n## Protocol emulation\n\n| Feature | OTG model specification | Ixia-c software | IxOS hardware "
},
{
"path": "docs/reference/licensing.md",
"chars": 11685,
"preview": "# Licensing\n\n## License consumption mechanism and feature licenses\n\nElastic Network Generator [licenses](../licensing.md"
},
{
"path": "docs/reference/resource-requirements.md",
"chars": 3525,
"preview": "# Resource requirement\n\nThe minimum memory and cpu requirements for each Ixia-c components are captured in the following"
},
{
"path": "docs/releases.md",
"chars": 474378,
"preview": "# Ixia-c Release Notes and Version Compatibility\n\n## Release v1.53.0-1 (Latest)\n> 21st April, 2026\n\n### Build Details\n\n"
},
{
"path": "docs/res/hw-server.drawio",
"chars": 6200,
"preview": "<mxfile host=\"65bd71144e\">\n <diagram name=\"Page-1\" id=\"kdscWATnTdKI_hbdzj3E\">\n <mxGraphModel dx=\"714\" dy=\"571\""
},
{
"path": "docs/res/system_with_UHD400T.drawio",
"chars": 11943,
"preview": "<mxfile host=\"Electron\" modified=\"2023-09-21T16:50:13.027Z\" agent=\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit"
},
{
"path": "docs/resources.md",
"chars": 1262,
"preview": "# Resources\n\n1. [Product page](https://www.keysight.com/us/en/products/network-test/protocol-load-test/keysight-elastic-"
},
{
"path": "docs/roadmap.md",
"chars": 121,
"preview": "# Roadmap\n\nIxia-c is released periodically. This page does NOT list all the minor/bug-fix releases that are planned.\n\n\n"
},
{
"path": "docs/sample-scripts.md",
"chars": 30885,
"preview": "\nThe following text was taken from the UHD400 topic.\n## Sample `gosnappi` scripts\n\nTwo sample `gosnappi` scripts can be "
},
{
"path": "docs/stylesheets/extra.css",
"chars": 5924,
"preview": "[data-md-color-scheme=\"ks-light\"] {\n --ks-color-black: #000000;\n --ks-color-dark-red: "
},
{
"path": "docs/support.md",
"chars": 703,
"preview": "# Support\n\nCommercial customers of the Keysight Elastic Network Generator can obtain support through the [Keysight Suppo"
},
{
"path": "docs/tests-chassis-app.md",
"chars": 4979,
"preview": "# Ixia Chassis/Appliances\n This section describes how to use KENG with Keysight's Ixia hardware chassis.\n\n**Prerequisite"
},
{
"path": "docs/tests-ixia-c.md",
"chars": 47,
"preview": "# Ixia-c tests \n\nHow to run tests with Ixia-c \n"
},
{
"path": "docs/tests-uhd400.md",
"chars": 2285,
"preview": "# Introduction\n\nThe UHD400T is a high performance, ultra-high density, and highly flexible software defined Tester, for "
},
{
"path": "docs/troubleshooting.md",
"chars": 4873,
"preview": "# Troubleshooting\r\n\r\nThis section explains the troubleshooting scenarios for different environments.\r\n\r\n## OTG hardware "
},
{
"path": "docs/usecases.md",
"chars": 718,
"preview": "# Use Cases\n\nThis page has a listing of all use-cases where Ixia-c is being used.\n\n- Chris Sommers' [demo](https://youtu"
},
{
"path": "docs/user-guide-introduction.md",
"chars": 3923,
"preview": "# Introduction\n[Keysight Elastic Network Generator](https://www.keysight.com/us/en/products/network-test/protocol-load-t"
},
{
"path": "license",
"chars": 1100,
"preview": "MIT License\n\nCopyright (c) 2020 Keysight Technologies, Inc. 2021, 2022, 2023\n\nPermission is hereby granted, free of char"
},
{
"path": "mkdocs.md",
"chars": 1634,
"preview": "# MkDocs How To\n\nThis repo contains the content for the [Ixia-c.dev](https://ixia-c.dev/) web-site. It is built using t"
},
{
"path": "mkdocs.yml",
"chars": 3727,
"preview": "site_name: Ixia-c & Elastic Network Generator Documentation\nrepo_url: https://github.com/open-traffic-generator/ixia-c\nr"
},
{
"path": "notes.md",
"chars": 7465,
"preview": "### Build Details\n\n| Component | Version |\n|-------------------------------|---------------|\n|"
},
{
"path": "readme.md",
"chars": 6956,
"preview": "<h1 align=\"center\">\n <br>\n Ixia-C\n <br>\n</h1>\n\n<h4 align=\"center\">\n Ixia-C - A powerful traffic generator based on <"
},
{
"path": "requirements.txt",
"chars": 15,
"preview": "mkdocs-material"
}
]
About this extraction
This page contains the full source code of the open-traffic-generator/ixia-c GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 94 files (776.8 KB), approximately 206.2k tokens, and a symbol index with 4 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.